summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElliot Lee <sopwith@src.gnome.org>1997-11-24 22:37:52 +0000
committerElliot Lee <sopwith@src.gnome.org>1997-11-24 22:37:52 +0000
commit9508b76bd2401b6b9e289b5c8ec9fc0e08909283 (patch)
tree53c88a9e5ac09e1a027e56df33bdaa66d670901b
downloadgdk-pixbuf-9508b76bd2401b6b9e289b5c8ec9fc0e08909283.tar.gz
Initial revision
-rw-r--r--.cvsignore10
-rw-r--r--AUTHORS3
-rw-r--r--COPYING481
-rw-r--r--ChangeLog1140
-rw-r--r--ChangeLog.pre-2-01140
-rw-r--r--ChangeLog.pre-2-101140
-rw-r--r--ChangeLog.pre-2-21140
-rw-r--r--ChangeLog.pre-2-41140
-rw-r--r--ChangeLog.pre-2-61140
-rw-r--r--ChangeLog.pre-2-81140
-rw-r--r--INSTALL0
-rw-r--r--Makefile.am30
-rw-r--r--NEWS0
-rw-r--r--README17
-rw-r--r--TODO36
-rw-r--r--acconfig.h47
-rw-r--r--aclocal.m4395
-rwxr-xr-xconfig.guess883
-rw-r--r--config.h.in36
-rwxr-xr-xconfig.sub954
-rw-r--r--configure.in214
-rw-r--r--docs/.cvsignore1
-rw-r--r--docs/Makefile.am10
-rw-r--r--docs/gdk.texi326
-rw-r--r--docs/gtk.texi3285
-rw-r--r--docs/macros.texi18
-rw-r--r--docs/texinfo.tex4692
-rw-r--r--gdk/.cvsignore6
-rw-r--r--gdk/Makefile.am75
-rw-r--r--gdk/gdk.c2897
-rw-r--r--gdk/gdk.h614
-rw-r--r--gdk/gdkcolor.c718
-rw-r--r--gdk/gdkcursor.c52
-rw-r--r--gdk/gdkdraw.c383
-rw-r--r--gdk/gdkfont.c379
-rw-r--r--gdk/gdkgc.c636
-rw-r--r--gdk/gdkglobals.c47
-rw-r--r--gdk/gdkimage.c492
-rw-r--r--gdk/gdkinput.c324
-rw-r--r--gdk/gdkinput.h143
-rw-r--r--gdk/gdkinputcommon.h687
-rw-r--r--gdk/gdkinputgxi.h628
-rw-r--r--gdk/gdkinputnone.h72
-rw-r--r--gdk/gdkinputxfree.h368
-rw-r--r--gdk/gdkpixmap.c657
-rw-r--r--gdk/gdkprivate.h197
-rw-r--r--gdk/gdkproperty.c194
-rw-r--r--gdk/gdkrectangle.c83
-rw-r--r--gdk/gdkselection.c168
-rw-r--r--gdk/gdktypes.h967
-rw-r--r--gdk/gdkvisual.c431
-rw-r--r--gdk/gdkwindow.c1358
-rw-r--r--gdk/gdkx.h48
-rw-r--r--gdk/gdkxid.c74
-rw-r--r--gdk/gxid.c844
-rw-r--r--gdk/gxid_lib.c116
-rw-r--r--gdk/gxid_lib.h6
-rw-r--r--gdk/gxid_proto.h39
-rwxr-xr-xgdk/makecursors5
-rw-r--r--gdk/makecursors.sed3
-rwxr-xr-xgdk/makekeysyms5
-rw-r--r--gdk/makekeysyms.sed3
-rw-r--r--gdk/x11/gdkcolor-x11.c718
-rw-r--r--gdk/x11/gdkcursor-x11.c52
-rw-r--r--gdk/x11/gdkfont-x11.c379
-rw-r--r--gdk/x11/gdkglobals-x11.c47
-rw-r--r--gdk/x11/gdkimage-x11.c492
-rw-r--r--gdk/x11/gdkinput-gxi.c628
-rw-r--r--gdk/x11/gdkinput-none.c72
-rw-r--r--gdk/x11/gdkinput-x11.c687
-rw-r--r--gdk/x11/gdkinput-xfree.c368
-rw-r--r--gdk/x11/gdkinput.c324
-rw-r--r--gdk/x11/gdkmain-x11.c2897
-rw-r--r--gdk/x11/gdkpixmap-x11.c657
-rw-r--r--gdk/x11/gdkproperty-x11.c194
-rw-r--r--gdk/x11/gdkselection-x11.c168
-rw-r--r--gdk/x11/gdkvisual-x11.c431
-rw-r--r--gdk/x11/gdkwindow-x11.c1358
-rw-r--r--gdk/x11/gdkx.h48
-rw-r--r--gdk/x11/gdkxid.c74
-rw-r--r--gdk/x11/gxid.c844
-rw-r--r--gdk/x11/gxid_lib.c116
-rw-r--r--gdk/x11/gxid_lib.h6
-rw-r--r--gdk/x11/gxid_proto.h39
-rw-r--r--glib/.cvsignore11
-rw-r--r--glib/AUTHORS1
-rw-r--r--glib/COPYING0
-rw-r--r--glib/ChangeLog10
-rw-r--r--glib/INSTALL0
-rw-r--r--glib/Makefile.am38
-rw-r--r--glib/NEWS0
-rw-r--r--glib/README0
-rw-r--r--glib/acconfig.h62
-rw-r--r--glib/aclocal.m4395
-rwxr-xr-xglib/config.guess883
-rwxr-xr-xglib/config.sub954
-rwxr-xr-xglib/configure2921
-rw-r--r--glib/configure.in116
-rw-r--r--glib/garray.c142
-rw-r--r--glib/gcache.c211
-rw-r--r--glib/gerror.c256
-rw-r--r--glib/ghash.c418
-rw-r--r--glib/glib.h674
-rw-r--r--glib/glibconfig.h.in67
-rw-r--r--glib/glist.c349
-rw-r--r--glib/gmem.c824
-rw-r--r--glib/gprimes.c61
-rw-r--r--glib/gslist.c324
-rw-r--r--glib/gstring.c487
-rw-r--r--glib/gtimer.c119
-rw-r--r--glib/gtree.c718
-rw-r--r--glib/gutils.c732
-rwxr-xr-xglib/install-sh238
-rwxr-xr-xglib/ltconfig1415
-rw-r--r--glib/ltmain.sh2372
-rwxr-xr-xglib/missing134
-rwxr-xr-xglib/mkinstalldirs36
-rw-r--r--glib/stamp-h.in1
-rw-r--r--glib/testglib.c296
-rw-r--r--gtk+.prj334
-rw-r--r--gtk+.xconfig.in3
-rw-r--r--gtk/.cvsignore9
-rw-r--r--gtk/3DRings.xpm116
-rw-r--r--gtk/FilesQueue.xpm98
-rw-r--r--gtk/Makefile.am248
-rw-r--r--gtk/Modeller.xpm117
-rw-r--r--gtk/fnmatch.c200
-rw-r--r--gtk/fnmatch.h67
-rw-r--r--gtk/gentypeinfo.el137
-rw-r--r--gtk/gtk.defs810
-rw-r--r--gtk/gtk.h106
-rw-r--r--gtk/gtkaccelerator.c352
-rw-r--r--gtk/gtkaccelerator.h73
-rw-r--r--gtk/gtkadjustment.c118
-rw-r--r--gtk/gtkadjustment.h74
-rw-r--r--gtk/gtkalignment.c193
-rw-r--r--gtk/gtkalignment.h72
-rw-r--r--gtk/gtkarrow.c165
-rw-r--r--gtk/gtkarrow.h66
-rw-r--r--gtk/gtkaspectframe.c336
-rw-r--r--gtk/gtkaspectframe.h75
-rw-r--r--gtk/gtkbbox.c228
-rw-r--r--gtk/gtkbbox.h93
-rw-r--r--gtk/gtkbin.c286
-rw-r--r--gtk/gtkbin.h60
-rw-r--r--gtk/gtkbox.c453
-rw-r--r--gtk/gtkbox.h90
-rw-r--r--gtk/gtkbutton.c915
-rw-r--r--gtk/gtkbutton.h76
-rw-r--r--gtk/gtkcheckbutton.c362
-rw-r--r--gtk/gtkcheckbutton.h66
-rw-r--r--gtk/gtkcheckmenuitem.c250
-rw-r--r--gtk/gtkcheckmenuitem.h69
-rw-r--r--gtk/gtkcolorsel.c1463
-rw-r--r--gtk/gtkcolorsel.h152
-rw-r--r--gtk/gtkcontainer.c844
-rw-r--r--gtk/gtkcontainer.h95
-rw-r--r--gtk/gtkcurve.c860
-rw-r--r--gtk/gtkcurve.h96
-rw-r--r--gtk/gtkdata.c73
-rw-r--r--gtk/gtkdata.h60
-rw-r--r--gtk/gtkdialog.c80
-rw-r--r--gtk/gtkdialog.h64
-rw-r--r--gtk/gtkdrawingarea.c146
-rw-r--r--gtk/gtkdrawingarea.h62
-rw-r--r--gtk/gtkentry.c1678
-rw-r--r--gtk/gtkentry.h94
-rw-r--r--gtk/gtkenums.h191
-rw-r--r--gtk/gtkeventbox.c226
-rw-r--r--gtk/gtkeventbox.h57
-rw-r--r--gtk/gtkfilesel.c2161
-rw-r--r--gtk/gtkfilesel.h73
-rw-r--r--gtk/gtkfixed.c525
-rw-r--r--gtk/gtkfixed.h76
-rw-r--r--gtk/gtkframe.c419
-rw-r--r--gtk/gtkframe.h73
-rw-r--r--gtk/gtkgamma.c464
-rw-r--r--gtk/gtkgamma.h71
-rw-r--r--gtk/gtkgc.c382
-rw-r--r--gtk/gtkgc.h42
-rw-r--r--gtk/gtkhbbox.c269
-rw-r--r--gtk/gtkhbbox.h66
-rw-r--r--gtk/gtkhbox.c306
-rw-r--r--gtk/gtkhbox.h60
-rw-r--r--gtk/gtkhpaned.c355
-rw-r--r--gtk/gtkhpaned.h59
-rw-r--r--gtk/gtkhruler.c277
-rw-r--r--gtk/gtkhruler.h59
-rw-r--r--gtk/gtkhscale.c436
-rw-r--r--gtk/gtkhscale.h59
-rw-r--r--gtk/gtkhscrollbar.c383
-rw-r--r--gtk/gtkhscrollbar.h59
-rw-r--r--gtk/gtkhseparator.c90
-rw-r--r--gtk/gtkhseparator.h59
-rw-r--r--gtk/gtkimage.c181
-rw-r--r--gtk/gtkimage.h69
-rw-r--r--gtk/gtkinputdialog.c546
-rw-r--r--gtk/gtkinputdialog.h76
-rw-r--r--gtk/gtkitem.c191
-rw-r--r--gtk/gtkitem.h65
-rw-r--r--gtk/gtklabel.c329
-rw-r--r--gtk/gtklabel.h69
-rw-r--r--gtk/gtklist.c1007
-rw-r--r--gtk/gtklist.h107
-rw-r--r--gtk/gtklistitem.c394
-rw-r--r--gtk/gtklistitem.h62
-rw-r--r--gtk/gtkmain.c1129
-rw-r--r--gtk/gtkmain.h76
-rw-r--r--gtk/gtkmenu.c732
-rw-r--r--gtk/gtkmenu.h94
-rw-r--r--gtk/gtkmenubar.c310
-rw-r--r--gtk/gtkmenubar.h66
-rw-r--r--gtk/gtkmenufactory.c541
-rw-r--r--gtk/gtkmenufactory.h88
-rw-r--r--gtk/gtkmenuitem.c746
-rw-r--r--gtk/gtkmenuitem.h98
-rw-r--r--gtk/gtkmenushell.c633
-rw-r--r--gtk/gtkmenushell.h83
-rw-r--r--gtk/gtkmisc.c181
-rw-r--r--gtk/gtkmisc.h70
-rw-r--r--gtk/gtknotebook.c1303
-rw-r--r--gtk/gtknotebook.h98
-rw-r--r--gtk/gtkobject.c994
-rw-r--r--gtk/gtkobject.h250
-rw-r--r--gtk/gtkoptionmenu.c584
-rw-r--r--gtk/gtkoptionmenu.h71
-rw-r--r--gtk/gtkpaned.c452
-rw-r--r--gtk/gtkpaned.h78
-rw-r--r--gtk/gtkpixmap.c176
-rw-r--r--gtk/gtkpixmap.h69
-rw-r--r--gtk/gtkpreview.c1571
-rw-r--r--gtk/gtkpreview.h144
-rw-r--r--gtk/gtkprogressbar.c259
-rw-r--r--gtk/gtkprogressbar.h64
-rw-r--r--gtk/gtkradiobutton.c321
-rw-r--r--gtk/gtkradiobutton.h69
-rw-r--r--gtk/gtkradiomenuitem.c240
-rw-r--r--gtk/gtkradiomenuitem.h64
-rw-r--r--gtk/gtkrange.c1369
-rw-r--r--gtk/gtkrange.h144
-rw-r--r--gtk/gtkrc.c1489
-rw-r--r--gtk/gtkrc.h45
-rw-r--r--gtk/gtkruler.c305
-rw-r--r--gtk/gtkruler.h91
-rw-r--r--gtk/gtkscale.c229
-rw-r--r--gtk/gtkscale.h75
-rw-r--r--gtk/gtkscrollbar.c54
-rw-r--r--gtk/gtkscrollbar.h58
-rw-r--r--gtk/gtkscrolledwindow.c510
-rw-r--r--gtk/gtkscrolledwindow.h74
-rw-r--r--gtk/gtkselection.c1388
-rw-r--r--gtk/gtkselection.h91
-rw-r--r--gtk/gtkseparator.c57
-rw-r--r--gtk/gtkseparator.h58
-rw-r--r--gtk/gtksignal.c1322
-rw-r--r--gtk/gtksignal.h124
-rw-r--r--gtk/gtkstyle.c1795
-rw-r--r--gtk/gtkstyle.h217
-rw-r--r--gtk/gtktable.c1178
-rw-r--r--gtk/gtktable.h126
-rw-r--r--gtk/gtktext.c3522
-rw-r--r--gtk/gtktext.h204
-rw-r--r--gtk/gtktogglebutton.c372
-rw-r--r--gtk/gtktogglebutton.h70
-rw-r--r--gtk/gtktooltips.c632
-rw-r--r--gtk/gtktooltips.h88
-rw-r--r--gtk/gtktree.c81
-rw-r--r--gtk/gtktree.h68
-rw-r--r--gtk/gtktreeitem.c108
-rw-r--r--gtk/gtktreeitem.h72
-rw-r--r--gtk/gtktypebuiltins.c53
-rw-r--r--gtk/gtktypebuiltins.h54
-rw-r--r--gtk/gtktypeutils.c459
-rw-r--r--gtk/gtktypeutils.h196
-rw-r--r--gtk/gtkvbbox.c272
-rw-r--r--gtk/gtkvbbox.h66
-rw-r--r--gtk/gtkvbox.c306
-rw-r--r--gtk/gtkvbox.h60
-rw-r--r--gtk/gtkviewport.c616
-rw-r--r--gtk/gtkviewport.h75
-rw-r--r--gtk/gtkvpaned.c356
-rw-r--r--gtk/gtkvpaned.h59
-rw-r--r--gtk/gtkvruler.c282
-rw-r--r--gtk/gtkvruler.h59
-rw-r--r--gtk/gtkvscale.c441
-rw-r--r--gtk/gtkvscale.h59
-rw-r--r--gtk/gtkvscrollbar.c387
-rw-r--r--gtk/gtkvscrollbar.h59
-rw-r--r--gtk/gtkvseparator.c90
-rw-r--r--gtk/gtkvseparator.h59
-rw-r--r--gtk/gtkwidget.c3390
-rw-r--r--gtk/gtkwidget.h505
-rw-r--r--gtk/gtkwindow.c1195
-rw-r--r--gtk/gtkwindow.h105
-rw-r--r--gtk/line-arrow.xbm4
-rw-r--r--gtk/line-wrap.xbm4
-rw-r--r--gtk/marble.xpm408
-rw-r--r--gtk/parent10
-rw-r--r--gtk/runelisp6
-rw-r--r--gtk/simple.c39
-rw-r--r--gtk/test.xpm92
-rw-r--r--gtk/testgtk.c3110
-rw-r--r--gtk/testgtkrc69
-rw-r--r--gtk/testinput.c379
-rw-r--r--gtk/testselection.c466
-rwxr-xr-xinstall-sh238
-rwxr-xr-xltconfig1415
-rw-r--r--ltmain.sh2372
-rwxr-xr-xmakecopyright124
-rwxr-xr-xmissing134
-rwxr-xr-xmkinstalldirs36
-rw-r--r--stamp-h.in1
-rw-r--r--tests/3DRings.xpm116
-rw-r--r--tests/FilesQueue.xpm98
-rw-r--r--tests/Modeller.xpm117
-rw-r--r--tests/marble.xpm408
-rw-r--r--tests/simple.c39
-rw-r--r--tests/test.xpm92
-rw-r--r--tests/testgtk.c3110
-rw-r--r--tests/testgtkrc69
-rw-r--r--tests/testinput.c379
-rw-r--r--tests/testselection.c466
322 files changed, 132552 insertions, 0 deletions
diff --git a/.cvsignore b/.cvsignore
new file mode 100644
index 000000000..0858b3946
--- /dev/null
+++ b/.cvsignore
@@ -0,0 +1,10 @@
+*.lo
+config.log
+config.h
+libtool
+config.status
+stamp-h
+Makefile
+gtk+.xconfig
+config.cache
+
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 000000000..f1adbf18a
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,3 @@
+Peter Mattis (petm@xcf.berkeley.edu)
+Spencer Kimball (spencer@xcf.berkeley.edu)
+Josh MacDonald (jmacd@xcf.berkeley.edu)
diff --git a/COPYING b/COPYING
new file mode 100644
index 000000000..eb685a5ec
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,481 @@
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 000000000..a065ebef5
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,1140 @@
+Mon Nov 17 1997 Jay Painter <jpaint@serv.net>
+ * gtkviewport.c: Raph's Mon, 10 Nov 1997 patch to gtk-list
+ to fix some viewport bugs
+
+Mon Nov 17 1997 Jay Painter <jpaint@serv.net>
+ * gtk/gtkwidget.c: gtk-ajaborsk-971016-2
+ A little patch again to prevent user to use gtk_widget_set_events()
+ when a widget is already realized.
+ In this case, the gtk_widget_set_events() doesn't work.
+
+Mon Nov 17 1997 Jay Painter <jpaint@serv.net>
+ * gtk/gtkwindow.c: gtk-ajaborsk-971016-1
+ This small patch correct position for GTK_WIN_POS_CENTER and
+ GTK_WIN_POS_MOUSE GtkWindow positions.
+
+Sat Nov 15 1997 Jay Painter <jpaint@serv.net>
+ * gdk/gdkgc.c: added function gdk_gc_set_clip_rectangle
+ * gdk/gdk.h: header for above
+
+Sat Nov 15 1997 Jay Painter <jpaint@serv.net>
+ * gdk/gdkgc.c: added function gdk_gc_set_clip_rectangle
+ * gdk/gdk.h: header for above
+
+Wed Nov 12 1997 Jay Painter <jpaint@serv.net>
+ * gdk/gdkpixmap.c: Patrice Fortier's patch for transparent pixmaps.
+ * gdk/gdk.h:
+ gdk/gdkdraw.c: Patrice Fortier's patch to add pixel draw function.
+
+Sun Nov 9 1997 Jay Painter <jpaint@serv.net>
+ * Fixed problems with makefiles relating to the bug
+ which required glib to be installed.
+ * Fixed makefiles to incluce the xpm's in gtk+/gtk needed
+ for testgtk.
+ * Updated gtk+ and gtk+/glib to libtool-1.0f
+
+Fri Nov 7 1997 Jay Painter <jpaint@serv.net>
+ * gtk/gtktext.c: return char_widths[ch & 0xff]; in line 2152
+
+Thr Nov 5 1997 Jay Painter <jpaint@serv.net>
+ * gtk/testgtk.c: added drag and drop test, removed the test hack
+ from the button test
+
+Tue Nov 4 08:28:57 1997 Federico Mena <federico@bananoid.nuclecu.unam.mx>
+
+ * gtk/gtkmain.c (gtk_handle_idle): Patch from David Mosberger to
+ avoid crashes when handling idle function (this manifested itself
+ in the Umax and Microtek backends in SANE.
+
+Sun Nov 2 07:34:56 1997 Tim Janik <timj@psynet.net>
+
+ * gtk/gtkfilesel.c: Small fixes about a segmentation viaolation
+ cause by a double click in the directoy list (introduced by my
+ previous changes).
+
+ * gtk/gtklist.c: Small fixes to gtk_list_add() and gtk_list_remove().
+
+ * gtk/testgtk.c (list_add): Applied Stefan Wille's patch to make this
+ function do something ;).
+
+Fri Oct 31 Jay Painter <jpaint@serv.net>
+ *gdk/gdk.c: reformatted DND code for GTK coding standards
+ *gdk/gdkwindow.c: changed memory allocation for DND to q_mem stuff
+
+Thu Oct 30 Jay Painter <jpaint@serv.net>
+ * gdk/gdkwindow.c:
+ * gdk/gdk/gdk.h:
+ * gtk/gtkwidget.h:
+ * gtk/gtkwidget.c: Applied Stephan Willie's shaped window patch
+
+ * gdk/gdkwindow:
+ * gdk/gdk.h:
+ * gtk/gtkwidget.h:
+ * gtk/gtkwidget.c: reformatted the DND code to conform to GTK
+ coding standards
+
+ * gtk/testgtk: massive fixes, SW's shaped window example
+
+Thu Oct 30 07:33:27 1997 Tim Janik <timj@psynet.net>
+
+ * gtk/gtklistitem.c (gtk_real_list_item_toggle): applied Johannes
+ Keukelaar's <johannes@nada.kth.se> patch for keyboard support in
+ GtkList widgets.
+
+ * gtk/gtkfilesel.c: adapted dir and file list selection
+ behaviour to deal with keyboard selections. this is a little
+ bit tricky: in the dir list it just changes the entrys value on a one
+ button press. but on a keyboard selection via gtk_widget_activate() it
+ does a new population (likewise on a double click) as this seems more
+ obvious.
+
+1997-10-25 Marius Vollmer <mvo@zagadka.ping.de>
+
+ * gdk/gdkcolor.c (gdk_colormap_get_system): Initialize
+ private->ref_count.
+
+Wed Oct 22 09:47:43 1997 Tim Janik <timj@psynet.net>
+
+ * gtk/gtkwindow.c (gtk_window_key_release_event): Fixed a stupid
+ bug that caused the key_release_event to be propagated twice.
+
+Sun Oct 12 11:01:43 1997 Tim Janik <timj@psynet.net>
+
+ * acconfig.h:
+ * configure.in:
+ * gdk/gdkimage.c: Added configure check for IPC_RMID_DEFERRED_RELEASE,
+ because shmat() fails after a shmctl(..., IPC_RMID,...) for OSF1 V3.2,
+ SunOS 4.1.1, 5.5, 5.5.1, 5.6, IRIX 5.2 and 6.2.
+
+Mon Oct 6 11:59:07 1997 Federico Mena <federico@bananoid.nuclecu.unam.mx>
+
+ * gdk/gdk.c (gdk_event_translate): In line 1693, fixed typo that
+ would cause motion notify events not to be delivered.
+
+Sun Oct 5 18:15:06 1997 Federico Mena <federico@bananoid.nuclecu.unam.mx>
+
+ * gtk/gtkrc.c (gtk_rc_parse_bg_pixmap): Changed strdup() for
+ g_strdup().
+
+Wed Sep 24 17:16:34 1997 Peter Mattis <pmattis@bjork.inktomi.com>
+
+ * configure.in: Fixed a stupid error in the test for libXext that
+ would cause it to fail if X_EXTRA_LIBS was not empty.
+
+ * gtk/gtkmain.h (gtk-timj-970919.patch):
+ * gtk/gtkmain.c (gtk-timj-970919.patch): new function
+ `gtk_idle_remove_by_data' to remove all idle callbacks that take a
+ specific piece of data as argument. (gtk_get_current_event):
+ remove idles through gtk_idle_remove_by_data.
+
+ * gtk/gtkwidget.c (gtk-timj-970919.patch):
+ (gtk_widget_destroy): remove pending idles for
+ widgets that have GTK_REDRAW_PENDING or GTK_RESIZE_PENDING and
+ GTK_ANCHORED set (only anchored widgets can have a resize queue
+ handler pending). widgets that have GTK_RESIZE_NEEDED will be removed
+ from their anchored toplevels `resize_widgets' list.
+
+ (gtk_widget_queue_draw): let the widget remember the queue handler
+ tag (through `redraw_handler_key') for later call to `gtk_idle_remove'.
+
+ (gtk_widget_queue_resize): let the widget remember the queue handler
+ tag (through `resize_handler_key') for later call to `gtk_idle_remove'.
+ corrected referencing the toplevel widget for which the handler is
+ pending. if a widget is added to the `resize_widgets' list of a
+ toplevel widget, GTK_RESIZE_NEEDED is set and it's referenced.
+
+ (gtk_real_widget_queue_resize): on the deletion of the `resize_widgets'
+ list, unset GTK_RESIZE_NEEDED and unreference the removed widgets.
+
+ * gtk/gtkwindow.c (gtk-timj-970919.patch):
+ (gtk_real_window_move_resize): move `resize_containers = NULL'
+ initialization out of if-statement.
+ while stepping through the `resize_widgets' list, unreference the
+ widgets and clear GTK_RESIZE_NEEDED. if a widget realy needs are
+ resize, they are flagged through GTK_RESIZE_NEEDED now (instead of
+ GTK_RESIZE_PENDING, as this is indicative for a pending handler).
+ added checks to provide segfaulting if a widgets parent pointer
+ is NULL (e.g. on toplevel widgets that have GTK_RESIZE_NEEDED set).
+
+Tue Sep 23 13:23:27 1997 Federico Mena <federico@bananoid.nuclecu.unam.mx>
+
+ * gdk/gdkimage.c: Applied Tim Janik's patch to mark shm segments
+ as IPC_RMID so that they are automatically removed always.
+
+ * gdk/gdkfont.c: Removed casts from lvalues.
+
+ * gtk/gtkmain.c: Removed GTK_RETLOC_*() (which do a cast) from lvalues.
+
+ * gtk/gtkaccelerator.c (gtk_accelerator_table_remove): Added
+ "const" to the accelerator_key param to be consistent with the
+ declaration in gtkaccelerator.h. The const is not useful in this
+ case, anyway.
+
+Tue Sep 16 13:11:06 1997 Peter Mattis <pmattis@bjork.inktomi.com>
+
+ * gtkpreview.c: Andrew Logan Kieschnick's change to eliminate
+ round-off error when gamma is set to 1.0.
+
+ * gtkrange.c:
+ * gtkviewport.c: Jay Painter's changes to modify the way in which
+ viewports resize.
+
+ * gdkinput.c:
+ * gdkinputgxi.h:
+ * gdkinputxfree.h:
+ * gtk/Makefile.am:
+ * gtk.h:
+ * gtkeventbox.c:
+ * gtkeventbox.h: Owen Taylor's event box widget and fixes for X
+ input support (that I had broken).
+
+ * gdk.h:
+ * gdkwindow.c:
+ * gtksignal.h:
+ * gtksignal.c: Elliot Lee's changes to support Objective C. (id is
+ apparently a reserved word in Objective C).
+
+Sun Sep 14 22:33:15 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwidget.c (gtk_widget_queue_resize): If the toplevel container
+ is invisible we simply call "gtk_container_need_resize" on
+ it. This fixes a bug with option menus not redrawing correctly.
+
+ * gtkmenuitem.c (gtk_menu_item_enter): (gtk_menu_item_leave):
+ These functions now simply pass the event on to their parent. This
+ is necessary for menus to work properly due to the change in how
+ grabs are dealts with.
+
+ * gtkwindow.c (gtk_real_window_move_resize): Fixed a bug that
+ caused the GTK_RESIZE_PENDING flag to not be unset in some cases.
+
+Fri Sep 5 20:49:37 1997 Marius Vollmer <mvo@zagadka.ping.de>
+
+ Bug fixes:
+
+ * Makefile.am: Added PATCHES to EXTRA_DIST.
+ * gtk/gtkpixmap.c (gtk_pixmap_new): Move the "pixmap != NULL" test
+ after the allocation of the pixmap.
+
+ To shut up the compiler:
+
+ * gtk/gtkfilesel.c (get_pwdb): Initialize home_dir.
+ * gtk/gtkmain.c (gtk_init): Replace comments around calls to
+ g_set_*_handler with "if (0)".
+ * gtk/gtkrc.c (gtk_rc_get_token): Initialize hex_number and
+ float_number.
+ * gtk/gtkwindow.c (gtk_window_key_press_event): Initialize
+ direction.
+
+ Changes to the type system in gtk/:
+
+ * Makefile.am: Added gtktypebuiltins.h to gtkinclude_HEADERS.
+ Added gtk.defs, runelisp, gentypeinfo.el and gtktypebuiltins.c to
+ EXTRA_DIST. Added rules to generate gtktypebuiltins.* from
+ gtk.defs.
+
+ * runelisp, gentypeinfo.el, gtk.defs: New files.
+
+ * gtkaccelerator.c, gtkaccelerator.h (gtk_accelerator_table_ref):
+ Return the table so that this function can be used as the `copy'
+ function for GTK_TYPE_BOXED values.
+ * gtkstyle.c, gtkstyle.h (gtk_style_ref): Likewise.
+
+ * gtkenums.h: Removed GtkArgType enum.
+
+ * gtkmain.c (gtk_init): Call gtk_type_init to initialize the type
+ system.
+
+ * gtkobject.c (gtk_object_init_type): New function to take over
+ for gtk_object_get_type. (gtk_object_get_type): Just return the
+ constant GTK_TYPE_OBJECT. (gtk_object_collect_args): Do the right
+ thing for the new GTK_TYPE_* types.
+ * gtksignal.c (gtk_params_get): Likewise.
+
+ * gtktypeutils.c: (gtk_type_init_builtin_types): New
+ function. (gtk_type_init): Call it. Also made non-static.
+ (gtk_type_unique): The allocation scheme for numerical ids has
+ changed: The low 8 bits hold the appropriate GtkFundamentalType of
+ a type, the rest is a globally unique sequence number.
+ (gtk_type_hash): Use the sequence number of a key to hash it.
+ (gtk_type_register_builtin): New function.
+
+ * gtktypeutils.h: (GtkFundamentalType): New enumeration of the
+ fundamental types. (GTK_TYPE_MAKE, GTK_FUNDAMENTAL_TYPE,
+ GTK_TYPE_SEQNO): New macros to work with the new id scheme.
+ (GtkArg): Added fields for new types and renamed old ones. GtkArg
+ should now be a mostly opaque structure, except name and type.
+ (GTK_VALUE_*): New macros to access the values of a GtkArg.
+ (GTK_RETLOC_*): New macros to access the location of a return
+ value that is contained in a GtkArg. * gtktypebuiltins.h: New
+ file to access the typeids of the builtin types.
+
+ * gtkwidget.h (GTK_TYPE_WIDGET): New macro to access the type id
+ of the widget class.
+
+ Thru out: Changed GTK_ARG_* to the appropriate GTK_TYPE_*.
+ Changed access to GtkArg structure to the appropriate GTK_VALUE_*
+ or GTK_RETLOC_* macro. Changed GtkArgType to GtkType. Changed
+ some guints to GtkType.
+
+ General changes in gtk/ to support interpreters:
+
+ * gtkradiobutton.c (gtk_radio_button_new_from_widget,
+ gtk_radio_button_new_with_label_from_widget): New functions.
+
+ * gtksignal.c (gtk_signal_connect_no_marshal): New function.
+ (struct _GtkHandler): Added no_marshal and destroy_func fields.
+ (gtk_signal_handler_new): Initialize them.
+ (gtk_signal_connect_by_type): Added no_marshal and destroy_func
+ arguments. Changed all callers.
+ (gtk_signal_destroy): Invoke destroy_func if there is one and the
+ global destroy func does not apply. (gtk_handlers_run): If the
+ handler has no_marshal set, call its function directly without
+ going thru the signal's marshaller.
+
+Wed Sep 3 09:56:22 1997 RHS Linux User <pmattis@bjork.inktomi.com>
+
+ * gtkrange.c: Changed the way the range control focus was drawn so
+ that the range control is drawn correctly when it does not have
+ the focus.
+
+Tue Sep 2 17:41:17 1997 RHS Linux User <pmattis@bjork.inktomi.com>
+
+ * gtkwidget.c: 'gtk_real_widget_queue_resize' should only remove
+ the "resize_widgets" if another resize is not pending.
+
+Mon Sep 1 18:28:08 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmain.c: Changed the way GDK_DELETE events are handled. Only,
+ if 'gtk_widget_event' returns TRUE is the widget destroyed. By
+ default, 'gtk_widget_event' will return FALSE causing the window
+ to not be destroyed. This prevents segfaults in the GIMP and other
+ programs that do not correctly handle GDK_DELETE events.
+
+ * gtkmain.c: Added modal dialog support by allowing events
+ destined for a child of the grab widget to go to the child instead
+ of the grab widget. (Added 'gtk_widget_is_ancestor' to determine
+ the relationship between the grab widget and the event widget).
+
+ * *.[ch]: Incorprated a whole mess of patches. (Started keeping
+ the ChangeLog up to date again).
+
+Thu Jun 5 17:22:21 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenufactory.c:
+ * gtkmenufactory.h: Added 'gtk_menu_factory_remove_*'
+ calls. Removing entries/paths causes the associated widgets to be
+ destroyed.
+
+ * gtkwidget.c:
+ * gtkwidget.h: Calling 'gtk_widget_set_style' is used as an
+ indication that the programmer specifically wants that style to be
+ used. RC-style substitution is disabled for the widget after such
+ a call.
+
+ * gtkpixmap.c:
+ * gtkpixmap.h:
+ * gtkimage.c:
+ * gtkimage.h: Changed to use clip mask and a single pixmap (or
+ image) to deal with transparent areas.
+
+ * gdkpixmap.c: Modified xpm loading routines to optionally return
+ a clip mask.
+
+ * gdkgc.c:
+ * gdkdraw.c:
+ * gdktypes.h: Modifications to allow clip masks to be used with
+ gc's. Clip masks are bitmaps that specify drawable regions.
+
+Thu May 1 03:11:51 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkscrolledwindow.c: Scrolled windows need to have the
+ GTK_NO_WINDOW flag set. Not having it set caused an obscure
+ redrawing bug.
+
+Wed Apr 30 12:38:03 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkhruler.c:
+ * gtkvruler.c: Fixed a small bug that caused the indicator to be
+ positioned slightly off.
+
+Sun Apr 27 14:28:21 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenushell.c:
+ * gtkmenushell.h:
+ * gtkmenu.c:
+ * gtkmenu.h: Changes so that if a menu is popped up there is a
+ timeout period during which a menu item will not be activated and
+ if the mouse button is released in that period the menu will stay
+ popped up.
+
+ * gtkcurve.c:
+ * gtkcurve.h: Included curve widget courtesy of David
+ Mosberger-Tang (davidm@azstarnet.com).
+
+ * gtkentry.c:
+ * gtkentry.h: Changed "insert" and "delete" signals to
+ "insert_text" and "delete_text" respectively. (The symbol "delete"
+ cannot be used since it is a C++ reserved word).
+
+Sat Apr 19 01:43:49 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenufactory.c: A path which ends in "<nothing>" will cause an
+ invisible (hidden) menu entry to be created. This is useful for
+ setting an accelerator key for which a corresponding menu entry is
+ not desired.
+
+ * gtktooltips.c: Fixed some problems with destruction of the
+ active tip widget not properly updating the tooltips data
+ structures.
+
+Fri Apr 18 15:09:45 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkcontainer.c:
+ * gtklist.c:
+ * gtkwidget.c:
+ * gtkwidget.h: Patch from Owen Taylor (owt1@cornell.edu) which
+ fixes problems with destruction of objects and with destruction of
+ objects which hold the focus.
+
+Thu Apr 17 11:29:15 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenushell.c: Incorrect logic in
+ 'gtk_menu_shell_button_release' for deciding when a menu should
+ stay popped up when the mouse button is released.
+
+ * *.c: Miscellaneous fixes from folks on the net.
+
+Tue Apr 15 02:43:17 1997 Peter Mattis <pmattis@localhost>
+
+ * *.c:
+ * gtkwidget.h: Added GTK_BASIC widget flag which when set
+ specifies a widget as "basic". A "basic" widget is one which
+ doesn't take input events. For example, labels, pixmaps, boxes,
+ tables, alignments, etc.
+
+Sat Apr 12 15:23:08 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkcolorsel.c: Add "#include <math.h>" to define M_PI.
+
+ * gtksignal.c: Fixed a bug in 'gtk_signal_emit' which showed up
+ because of the new cast checking macros. The 'object' was being
+ accessed after it had been destroyed.
+
+ * gtkoptionmenu.c: Fixed bug with using 'GTK_BIN' instead of
+ 'GTK_BUTTON' which showed up because of the new cast checking
+ macros.
+
+ * *.h: 'GTK_CHECK_CAST', 'GTK_CHECK_CLASS_CAST' and
+ 'GTK_CHECK_TYPE' used by standard widget macros everywhere.
+
+Wed Apr 9 00:54:17 1997 Peter Mattis <pmattis@localhost>
+
+ * docs/gtk.texi: Started further work on documentation. Major
+ changes and additions are being made.
+
+ * gtkarrow.c:
+ * gtkarrow.h: Removed function 'gtk_arrow_get'.
+
+ * gtkcontainer.c: 'gtk_container_check_resize' no performs
+ additional checking to account for the case where the containers
+ allocation is no longer sufficient because its parent (or its
+ parents parent, etc.) needs to resize its children.
+
+Tue Apr 8 21:15:50 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkstyle.c: Fixed a bug in 'gtk_style_init' in which the font
+ was not ref'd (via 'gdk_font_ref'), but was free'd (via in
+ 'gdk_font_free') in 'gtk_style_destroy'. (David
+ Mosberger-Tang). Also cleaned up 'gtk_style_destroy' while I was
+ at it.
+
+ * gtkmain.c: Fixed a bug in 'gtk_propogate_event' which caused
+ entry widgets (and probably other widgets) not to be destroyed in
+ some instances.
+
+Mon Apr 7 01:20:38 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkentry.c:
+ * gtkentry.h: Changed the "insert_text", "delete_text" and
+ "changed_text" signals to "insert", "delete", and "changed"
+ respectively. They really should have been named this way
+ originally except the previous signal mechanism prevented
+ duplicate signal names. ("changed" is also used by adjustments).
+
+ * gtkradiomenuitem.c:
+ * gtkradiomenuitem.h: New widget.
+
+ * gtkcheckmenuitem.c:
+ * gtkcheckmenuitem.h: New widget.
+
+ * gtksignal.c: Modified 'gtk_signal_lookup' to require an object
+ type to be passed as a parameter. In addition, signals are now
+ only needed to be uniquely defined in their branch of the class
+ hierarchy. This allows the same signal name to be used in two
+ different branches of the class hierarchy. For instance, the
+ "changed" signal is used both by adjustments and entries...in
+ different ways!
+
+ * gtktypeutils.c: Added 'gtk_type_parent' which returns the parent
+ type for a given type.
+
+Sun Apr 6 22:08:35 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwidget.c: If a widget is set insensitive it loses the focus
+ if it had it.
+
+ * gtkcontainer.c: Insensitive widgets no longer participate in tab
+ traversal.
+
+ * gtkscrolledwindow.c: The "viewport" child is now destroyed and a
+ container class "foreach" function was written (which fixes the
+ sensitivity bug).
+
+Sat Apr 5 14:25:38 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkhscrollbar.c:
+ * gtkvscrollbar.c: Fixed trough size allocation bug.
+
+ * gtkhscale.c:
+ * gtkvscale.c: Fixed trough size allocation and position bug that
+ showed up when scales were placed in notebooks.
+
+Thu Mar 27 17:45:54 1997 David Mosberger-Tang <davidm@azstarnet.com>
+
+ * gtk/gtkmain.c (gtk_handle_idle): Fix appending pending_idles to
+ idle_functions so it works even when idle_functions is empty.
+
+Sat Mar 15 14:15:59 1997 Peter Mattis <pmattis@localhost>
+
+ * *.[ch]: Moved '*_class_init' and '*_init' function declarations
+ for widgets into the source file as those functions no longer had
+ to be public.
+
+ * gtkcheckbutton.c: Fixed redrawing of check button.
+
+ * gtkframe.c: Fixed redrawing of frame when the shadow type is
+ changed.
+
+Sat Mar 8 15:19:23 1997 Peter Mattis <pmattis@localhost>
+
+ * gdkimage.c: Fixed a stupid bug with 'gdk_image_new' which
+ potentially added a NULL image to "image_list" and caused problems
+ when 'gdk_image_exit' was called.
+
+Wed Mar 5 00:40:08 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkpreview.c: Massively changed the colormap handling used by
+ the preview widget. Gray previews are now dithered. A single
+ visual and colormap is shared by the color and gray previews. A
+ GTK_PREVIEW_INFO property is installed on the root window in
+ certain cases to allow multiple GTK programs to share the system
+ colormap.
+
+Sun Mar 2 05:43:06 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkcheckbutton.c: 'gtk_checkbutton_size_allocate' was allocating
+ too much space to its children and not leaving the check button
+ room for the focus border.
+
+ * gtknotebook.c: 'gtk_notebook_size_request' wasn't requesting
+ enough space when the notebook tabs are visible.
+
+Sat Mar 1 01:59:35 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkpreview.c: Fixed a problem with 'gtk_preview_put' when the
+ image byte order is GDK_MSB_FIRST.
+
+ * gtksignal.c:
+ * gtksignal.h: Added 'gtk_signal_connect_after' and
+ 'gtk_signal_connect_object_after' functions. These connect signal
+ handlers which will run after the class function associated with
+ the signal.
+
+ * gtkstyle.c: Fixed a stupid bug in 'gtk_style_new_from_key' that
+ was causing twice as many styles to be created as necesary.
+
+ * gtkwidget.c: 'gtk_real_widget_size_allocate' erases the widgets
+ old allocation if it has the GTK_NO_WINDOW flag set.
+
+ * gtkwidget.c: 'gtk_real_widget_unmap' now erases the widget if it
+ has the GTK_NO_WINDOW flag set.
+
+ * gtklabel.c: Removed 'gtk_label_unmap' as similar functionality
+ was added to gtk_real_widget_unmap.
+
+ * gtkbin.c: Modified 'gtk_bin_map' and 'gtk_bin_unmap' so that it
+ erases and draws the widget if it has the GTK_NO_WINDOW flag set.
+
+ * gtkframe.c: Modified 'gtk_frame_size_allocate' so that it erases
+ the old allocation.
+
+Fri Feb 28 03:27:05 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwindow.c: 'gtk_window_set_title' now changes the window title
+ if the window is already realized.
+
+ * gtkentry.c: 'gtk_entry_set_text' was emitting both a
+ "delete_text" and a "changed_text" signal. Modified so that it
+ only emits a "changed_text" signal.
+
+ * gtkpreview.c: Modified to work correctly on systems with MSB
+ byte order. The colormap for TRUE and DIRECT color displays is now
+ created if the default visual is not equal to the visual we are
+ using.
+
+ * gtkstyle.c: 'gtk_style_attach' and 'gtk_style_find' weren't
+ working properly in the presence of multiple colormaps are
+ different depth visuals.
+
+ * gtkcontainer.c: Massively improved focus traversal using tab and
+ arrow keys. It now uses the layout of the widgets to determine
+ where to move the focus to.
+
+Mon Feb 24 03:24:02 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenufactory.c: Set the accelerator table field for menus when
+ they are created.
+
+ * gtkmenu.c:
+ * gtkmenu.h: Added a default accelerator table field to menus so
+ that runtime modification of accelerator keys in menus can work
+ better.
+
+ * gtkrange.c: 'gtk_range_default_{h,v}motion' had faulty logic for
+ deciding what to do when the slider was at the edge of the
+ trough. They previously didn't update the adjustment value event
+ if the value wasn't what it should be when the slider was at the
+ edge of the trough.
+
+ * gtkviewport.c: 'gtk_viewport_size_allocate' and
+ 'gtk_viewport_adjustment_value_changed' both had the potential for
+ performing a divide by 0. Checks are now in place to prevent this.
+
+ * gtkmenu.c: 'gtk_menu_map' now makes sure the menu lies on screen
+ if the position function is NULL.
+
+ * gtkentry.c: Modified selection handling. 'gtk_delete_selection'
+ actually removes the X selection now. 'gtk_entry_destroy' removes
+ the selection as well and relies on the change in "gdk.c" to make
+ sure the selection event will not be sent to a non-existant
+ window.
+
+ * gdk.c: Selection events are only passed on if the selection
+ owner is not NULL.
+
+ * gtkstyle.c: 'gtk_style_detach' and 'gtk_style_destroy' were not
+ destroying the black and white gc's.
+
+Sun Feb 23 19:17:56 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwindow.c: 'gtk_window_size_request' was setting the window
+ hints. This was also being done in 'gtk_window_map', so the
+ instance being done in 'gtk_window_size_request' was removed.
+
+Fri Feb 21 01:04:01 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwidget.c: 'gtk_widget_draw' has to use the widgets allocated
+ position for the drawing rectangle when the widget has the
+ GTK_NO_WINDOW flag set.
+
+ * gtkwidget.c: In 'gtk_widget_init' the visual and colormap were
+ being directly compared against 'default_visual' and
+ 'default_colormap' instead of calling
+ 'gtk_widget_get_default_{visual,colormap}'.
+
+ * gdkrectangle.c: Amazing! There was a bug in the
+ 'gtk_rectangle_intersect' logic. Its been there for near eternity
+ and I never noticed.
+
+ * gtkpreview.c:
+ * gtkpreview.h: Created preview widget which allows drawing to an
+ rgb or grayscale buffer which is automatically displayed on the
+ screen. Performs dithering as necessary.
+
+Thu Feb 20 20:33:21 1997 Peter Mattis <pmattis@localhost>
+
+ * gdkwindow.c: Modified the logic in 'gdk_window_new' which
+ determined when to add a window to the WM_COLORMAP_WINDOWS
+ property.
+
+Wed Feb 19 19:55:29 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkruler.c: 'gtk_ruler_make_pixmap' was always destroying the
+ old backing store and creating a new one even when it would create
+ a new one of exactly the same size as the old one.
+
+Tue Feb 18 18:32:10 1997 Peter Mattis <pmattis@localhost>
+
+ * gmem.c: 'g_mem_chunk_alloc' was incorrectly modifying the mem
+ areas free mem field when reallocating a previously freed
+ atom. This caused a fairly severe memory leak.
+
+ * gtkmenushell.c: 'gtk_menu_shell_button_release' had a bug in the
+ logic for deciding whether to initiate an X pointer grab or not
+ when the mouse button was released. It now only initiates a grab
+ if the mouse is released within an active menu item.
+
+Fri Feb 14 00:57:40 1997 Peter Mattis <pmattis@localhost>
+
+ * gtknotebook.c: Changed the look of notebook tabs slightly.
+
+ * gtkentry.c:
+ * gtkentry.h: Deleting an entry widget which is holding the X
+ selection presents some difficulties. The X selection must be
+ released, but the widget can't be destroyed until the
+ SELECTION_CLEAR event is received that the X server will send in
+ response to clearing the X selection. There are probably still
+ bugs in the current method of entry widget deletion when the X
+ selection is held.
+
+ * gtkmain.c: 'gtk_propagate_event' was not properly destroying the
+ toplevel window when receiving a key press event.
+
+ * gtkwidget.c: Setting a widget insensitive did not cause it to
+ redraw. It now does.
+
+Thu Feb 13 16:59:07 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkviewport.c: 'gtk_viewport_size_allocate' was allocating its
+ child widget an adjusted allocation. Since the actual scrolling
+ has handled by a subwindow this caused the child to be double
+ scrolled. Modified to always set the child allocations origin to
+ (0, 0).
+
+Wed Feb 12 01:06:48 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkentry.c: Text is now centered vertically. Previously it was
+ pushed up against the top. This problem was only evident when the
+ widget was allocated more vertical space than it requested.
+
+ * gtkfilesel.c: 'gtk_file_selection_key_press' was previously only
+ a stub for tab completion. The actual tab completion call had been
+ left out. (Oops!)
+
+Tue Feb 11 01:43:08 1997 Peter Mattis <pmattis@localhost>
+
+ * gtksignal.c: 'gtk_signal_disconnect_by_data' was going into a
+ loop and crashing. Bad logic. Fixed.
+
+ * gtkmain.c: An idle function which returns FALSE will be removed
+ from the list of idle functions. This makes the functioning of
+ idle functions and timeouts more similar.
+
+ * gtkentry.c: 'gtk_entry_get_text' now returns an empty string
+ when the actual text is NULL. This allows "stupid" programs to use
+ the value returned by 'gtk_entry_get_text' blindly (without
+ checking to see if its NULL).
+
+ * gtkradiobutton.c: Modified 'gtk_radio_button_clicked' so that
+ 'gtk_toggle_button_toggled' is called _after_ the widget state is
+ changed.
+
+ * gtksignal.c:
+ * gtksignal.h: Added 'gtk_signal_name' which returns the character
+ string name for a given signal number.
+
+ * gtkwidget.c: 'gtk_widget_set_parent' checks to see if the widget
+ is now "anchored" through the parent chain to a widget which is
+ GTK_ANCHORED. If it is, then it changes the widgets style using
+ 'gtk_rc_get_style' and recursively performs the same operation on
+ the widgets children. This is necessary is 'gtk_rc_get_style' only
+ works properly on "anchored" widgets.
+
+ * gtkwindow.c: Modified GTK_WIN_POS logic so that it is only used
+ immediately after the window has been shown.
+
+ * gtkmenu.c: 'gtk_menu_key_press'. Can now change menu item
+ accelerator keys on the fly. Why? Why not. Cool/useless feature of
+ the day.
+
+ * gtkmenuitem.c: Accelerator key drawing. Somehow that never got
+ finished. (Oops!)
+
+ * gtkdrawingarea.c: 'gtk_drawing_area_size_allocate' was not
+ actually installed during 'gtk_drawing_area_class_init'. (Oops!)
+
+ * gtkframe.c: 'gtk_frame_size_request' fixed size requisition
+ problem caused by unsigned arithmetic.
+
+ * gtkwindow.c: Modified window widget so that it only uses the
+ widget uposition auxiliary information immediately after it has
+ been shown. This prevents the annoying bug which can cause a
+ uposition'ed window to jump back to its original position after
+ the user moves it.
+
+ * gtkwidget.c: Need to ref and unref style in
+ 'gtk_widget_{push,pop}_style' to make sure that a style on the
+ style stack is not destroyed.
+
+ * gtktogglebutton.c: 'gtk_toggle_button_set_state' now calls
+ gtk_button_clicked to actually change the state of the
+ button. In this way, radio buttons can now perform the appropriate
+ actions when the toggle button state is set.
+
+Mon Feb 10 00:27:39 1997 Peter Mattis <pmattis@localhost>
+
+ * gtklist.c: 'gtk_list_select_item' and 'gtk_list_unselect_item'
+ were casting a GList* variable to a a GtkWidget* variable. Bad bad
+ bad. (Tim Janik).
+
+ * gtksignal.c: Modified 'gtk_signal_connect' and
+ 'gtk_signal_connect_object' to warn when a signal type cannot be
+ found.
+
+Sun Feb 9 00:15:30 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkoptionmenu.c:
+ * gtkoptionmenu.h: Changed option menus back to being derived from
+ buttons. This fixes up some screwiness with their user
+ interaction.
+
+ * gtkwindow.c: Modified key press handler to support focus
+ traversal.
+
+ * gtkcontainer.c:
+ * gtkcontainer.h: Added default focus traversal back in.
+
+Sat Feb 8 10:44:38 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkviewport.h:
+ * gtkviewport.c: Massively sped up viewport scrolling. Used to be
+ reallocating child's size (offset) each time a scrollbar
+ moved. Now a subwindow is moved. All the children are moved
+ automatically by moving the subwindow. Much much much faster.
+
+Tue Feb 4 00:20:44 1997 Peter Mattis <pmattis@localhost>
+
+ * gtree.c: Changed 'g_tree_node_search' to use a loop instead of
+ recursion.
+
+Mon Feb 3 11:30:03 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkbutton.c: Removed 'parent_destroy' global and replaced it
+ with 'parent_class' global to reflect style used in other
+ widgets.
+
+ * gtknotebook.c: Tab labels were being allocated less than their
+ requested size.
+
+ * gtkrange.c:
+ * gtkrange.h: Moved the "digits" field of scales into the range
+ type. The adjustment value for scales is truncated to the number
+ of visible digits instead of being left untouched.
+
+ * gtree.c: Fixed a bug in the AVL tree implementation. Single
+ rotations were always being performed during insertion. It is
+ sometimes necessary to perform a double rotation.
+
+ * gtklabel.c: Modified 'gtk_label_expose' to only draw the label
+ when the allocated space is greater than or equal to the requested
+ space.
+
+ * gtklabel.c: Added call to 'gtk_widget_unmap' to
+ 'gtk_label_destroy' in order for the label to redraw correctly
+ (erase itself) when destroyed.
+
+ * gtklabel.c: Added 'gtk_label_unmap' call which erases the labels
+ allocation when it gets unmapped.
+
+ * *.h: Removed a few remaining instances of using "class" as a
+ parameter name. (Causes problems for C++).
+
+Fri Jan 31 12:26:50 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkcontainer.c: 'gtk_container_enable_resize' needs to call
+ 'gtk_container_check_resize' instead of
+ 'gtk_container_need_resize'.
+
+ * gtkwidget.c: 'gtk_real_widget_show' now maps the widget if its
+ parent is mapped.
+
+ * gtkscrolledwindow.c: Fixed size allocation when the scrollbar
+ policy's are GTK_POLICY_AUTOMATIC. Doing it correctly is harder
+ than I originally thought.
+
+ * gtklist.c: Added 'gtk_list_child_position' to determine the
+ integer position in a list of a child. Filled in the
+ 'gtk_list_item_select' and 'gtk_list_item_unselect' stubs.
+
+Thu Jan 30 16:08:06 1997 Peter Mattis <pmattis@localhost>
+
+ * gmem.c: Changed the implementation of G_ALLOC_AND_FREE mem
+ chunks. They used to allocate SIZEOF_VOID_P extra bytes per atom
+ in order to keep track of which mem area they were allocated
+ from. Now the mem area is determined by searching through an AVL
+ tree of the mem areas for a mem chunk and comparing memory
+ locations. A little slower, but makes G_ALLOC_AND_FREE mem chunks
+ much more attractive.
+
+ * gtree.c: Added an AVL tree implementation to glib.
+
+ * gtksignal.c:
+ * gstring.c: va_arg (arg_list, {char, short}) is
+ invalid. Arguments passed in a variable argument list are
+ promoted. ({char, short}->int). Seemed to work ok before under
+ Linux. Crashed under FreeBSD.
+
+Tue Jan 28 02:27:51 1997 Peter Mattis <pmattis@localhost>
+
+ * gdkwindow.c: Fixed a major slowdown apparent in the file
+ selection dialog which was caused by calling
+ 'gtk_window_add_colormap_windows' way way way too often.
+
+ * *.c: Many widgets called 'gtk_container_need_resize' when
+ something internal changed which would cause the widget to grow or
+ shrink. The assumption was made that the widget would change size
+ and an expose event would be generated. This happens "most" of the
+ time. But its possible for certain widgets to change size without
+ generating expose events, or for its internal geometry to change
+ without a change of size which would mean no expose event was
+ generated. So a wrapper function called
+ 'gtk_container_check_resize' was created and
+ 'gtk_container_need_resize' was modified so that it returns FALSE
+ if a resize was actually generated and TRUE if nothing
+ changed. This allows 'gtk_container_check_resize' to initiate a
+ 'gtk_widget_size_allocate' and 'gtk_widget_draw' to emulate the
+ expose event.
+
+Sat Jan 25 14:17:44 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmain.c: Fixed a bug with propogating key press events. The
+ events were sent 2 times to the toplevel windows which caused the
+ focus widget to be activated twice when the space bar was pressed.
+
+ * */configure.in:
+ * */Makefile.am: Added support for libtool and removed the old
+ shared library configuration craziness.
+
+Fri Jan 24 12:59:22 1997 Peter Mattis <pmattis@localhost>
+
+ * gtktext.c:
+ * gtktext.h: Josh's fixes and additions to the text widget.
+
+ * gtkfill.c:
+ * gtkfill.h: Filler widget useful for filling space in a
+ table. Can specify a minimum size. Used by the canvas widget.
+
+ * gtknotebook.c:
+ * gtknotebook.h: Made outline of notebook widget.
+
+ * gtkcanvas.c:
+ * gtkcanvas.h: Started canvas widget. A composite of 2 rulers (w/
+ an origin), 2 scrolllbars. Guides, grids, snap to.
+
+Sun Jan 19 18:26:45 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkdialog.c:
+ * gtkdialog.h: Created dialog widget which creates a standard
+ looking dialog with buttons along the button and a separator.
+
+ * gtkxid.c: Generalized the window table code for looking up a gdk
+ window based on an XID to work for any XID and a piece of
+ data. Can now look up gdk fonts based on their XID.
+
+ * gtkruler.c:
+ * gtkruler.h:
+ * gtkhruler.c:
+ * gtkhruler.h:
+ * gtkvruler.c:
+ * gtkvruler.h: Started conversion of the ruler widget.
+
+ * gtktext.c:
+ * gtktext.h: Started conversion of the text widget. Scrolling
+ doesn't work.
+
+ * gtkmain.c: Fixed a fairly major bug. The event widget needs to
+ be in a call for the entire duration of handling an event. Not
+ just for when the event widget itself is handling the event.
+
+ * gtkfilesel.c: Fixed up some bugs with resizing.
+
+Fri Jan 10 14:18:03 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwidget.c:
+ * gtkwidget.h:
+ * gtkentry.c:
+ * gtkentry.h: Support for selections.
+
+ * gdkselection.c:
+ * gdk.c:
+ * gdktypes.h:
+ * gdk.h: Gdk support for X selections. Currently only text
+ selections are supported.
+
+ * gtksignal.c: Fixed a major bug which occurred when destroying an
+ object. Memory was being written to after it was freed.
+
+ * gtkfilesel.c:
+ * gtkfilesel.h: Hooked up more functionality to the file selection
+ dialog.
+
+Wed Jan 8 18:13:53 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkfilesel.c:
+ * gtkfilesel.h: Mostly converted old file selection dialog
+ widget. The widget is derived from the GtkWindow class and is
+ quite a bit simpler in the widget code.
+
+ * gtkwidget.c: Fixed 'gtk_widget_grab_focus' and
+ 'gtk_widget_grab_default' to check that the toplevel widget is a
+ type of window (which includes classes derived from windows).
+
+Tue Jan 7 01:12:32 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwindow.c: Was calling 'gtk_window_resize' twice in a
+ row...why?
+
+ * gtksignal.c:
+ * gtksignal.h:
+ * *.c: Changed 'gtk_signal_new' so that the class function that is
+ called when the signal is emitted can be called either before,
+ after or both before and after the calling of any signal
+ handlers.
+
+ * gtkobject.c:
+ * gtkobject.h: Added 'object_data' mechanism for storing data
+ associated with a character string key in objects. Removed
+ 'user_data' field of objects and changed
+ 'gtk_object_{get,set}_user_data' to use the object data
+ mechanism. Removed 'handlers' field of objects.
+
+ * gtkwidget.c:
+ * gtkwidget.h:
+ * gtkwindow.c: Modified aux info mechanism to use object data
+ mechanism.
+
+ * gtksignal.c: Modified signal mechanism to use object data
+ mechanism instead of 'handlers' field.
+
+
+Mon Jan 6 15:10:16 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenushell.c: Fixed up button press handling so as to conform
+ more closely to that used by Motif.
+
+Wed Jan 1 21:27:17 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenu.c:
+ * gtkmenu.h:
+ * gtkmenubar.c:
+ * gtkmenubar.h:
+ * gtkmenushell.c:
+ * gtkmenushell.h: Reorganization of menu-ing code so that code
+ duplication is reduced. The menu shell now contains most of the
+ code for menu-ing interaction while menus and menubars simply layout
+ their child menu items in the appropriate place.
+
+Sun Dec 29 17:48:18 1996 Peter Mattis <pmattis@localhost>
+
+ * gtkmenu.c:
+ * gtkmenubar.c:
+ * gtkmenuitem.h:
+ * gtkmenuitem.c: Modifications so that menu item accelerators and
+ the submenu indicator are drawn correctly and the correct amount
+ of space is allocated.
+
+Sat Dec 28 00:32:13 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * gtkmenufactory.h:
+ * gtkmenufactory.c: Started menu factories as an easy method to
+ create and manipulate menus.
+
+Fri Dec 27 13:17:34 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * gtkmenu.c:
+ * gtkmenu.h:
+ * gtkmenubar.c:
+ * gtkmenubar.h:
+ * gtkmenuitem.c:
+ * gtkmenuitem.h:
+ * gtkmenushell.c:
+ * gtkmenushell.h: Implemented basic menu functionality. Menubars
+ and popup menus work. Submenus work. (Much left to be done).
+
+Wed Dec 18 15:27:05 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * gtktypeutils.h:
+ * gtktypeutils.c: Added 'gtk_type_from_name' which returns a type
+ identifier given a type name. Implemented using a second hash
+ table keyed by type names.
+
+ * gtkbutton.c:
+ * gtktogglebutton.c: Fixed very small messed-up drawing bug when a
+ button loses its focus.
+
+ * gtkwidget.h:
+ * gtkwidget.c:
+ * gtkbutton.c:
+ * gtkwindow.c: Added default button handling. Default buttons now
+ draw correctly and pressing return or enter causes the default
+ button (if one exists) to be activated.
+
+Tue Dec 17 19:32:21 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * gtkhscale.c:
+ * gtkvscale.c: Overrode 'draw_slider' method of ranges in order to
+ draw the slider of scales with a line in them so as to be closer
+ to the Motif look-and-feel.
+
+ * gtkwindow.c: Modified 'gtk_window_focus_in_event' so that focus
+ in events are only handled when the window is visible. Fixes a bug
+ where spurious focus in events get sent when a window is being
+ hidden.
+
+ * gtkwidget.h: Added 'activate_signal' field to the GtkWidgetClass
+ structure. Added 'gtk_widget_activate' call to emit the activate
+ signal for a widget if it is non-zero.
+
+Tue Dec 10 15:59:45 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * gtkwidget.c: 'gtk_widget_set_name' oops in strdup'ing the old
+ "widget->name" instead of the new one we are setting.
+
+ * gtkrc.c: 'gtk_rc_widget_path' changed to use
+ 'gtk_widget_get_name' instead of accessing the "widget->name"
+ field directly.
+
+ * gtkwidget.c: Added 'gtk_widget_get_name' function which returns
+ the widgets name if it exists and the widgets type name if it does
+ not.
+
+ * gtkcheckbutton.c: Added 'gtk_check_button_draw'
+ function. Modified 'gtk_check_button_expose' to pass an expose
+ event to child instead of callings its draw function.
+
+ * gtkentry.c: 'gtk_entry_draw_text' why was "+1" being added to
+ the font->ascent to calculate the font position? This was wrong
+ and caused some characters in fonts to be clipped. (Notably "g").
+
+ * gtkentry.c: 'gtk_entry_realize' specify GTK_BUTTON1_MOTION_MASK
+ and GTK_POINTER_MOTION_HINT_MASK for _both_ windows.
+
+ * gtkmain.c: 'gtk_propagate_event' needs to set the GTK_IN_CALL
+ flag for the object before calling 'gtk_widget_event' and needs to
+ destroy the object if necessary after 'gtk_widget_event' returns.
+
+ * gtkradiobutton.c: 'gtk_radio_button_clicked' needs to call
+ 'gtk_toggle_button_toggled' when the currently active button is
+ toggled.
+
+ * gtkwidget.c: 'gtk_real_widget_hide' needs to call
+ 'gtk_widget_unmap' if the widget is currently mapped.
+
+ * gtkwindow.c: Prevent automatic resizing after the user has
+ specified a new window size. Add 'handling_resize' flag to
+ windows.
+
+ * gtkscrolledwindow.c: Implement the GTK_POLICY_AUTOMATIC
+ scrollbar policy. Need to connect to the adjustments 'changed'
+ signal and notice when the scrollbars aren't in use.
+
+ * gtkcontainer.c: 'gtk_container_init' must set 'auto_resize' and
+ 'need_resize' fields to TRUE and FALSE respectively.
+
+ * gtkwidget.c: 'gtk_widget_set_parent' must all set a widgets state
+ to its parents state.
+
+Sun Dec 1 01:31:01 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * Started ChangeLog
diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0
new file mode 100644
index 000000000..a065ebef5
--- /dev/null
+++ b/ChangeLog.pre-2-0
@@ -0,0 +1,1140 @@
+Mon Nov 17 1997 Jay Painter <jpaint@serv.net>
+ * gtkviewport.c: Raph's Mon, 10 Nov 1997 patch to gtk-list
+ to fix some viewport bugs
+
+Mon Nov 17 1997 Jay Painter <jpaint@serv.net>
+ * gtk/gtkwidget.c: gtk-ajaborsk-971016-2
+ A little patch again to prevent user to use gtk_widget_set_events()
+ when a widget is already realized.
+ In this case, the gtk_widget_set_events() doesn't work.
+
+Mon Nov 17 1997 Jay Painter <jpaint@serv.net>
+ * gtk/gtkwindow.c: gtk-ajaborsk-971016-1
+ This small patch correct position for GTK_WIN_POS_CENTER and
+ GTK_WIN_POS_MOUSE GtkWindow positions.
+
+Sat Nov 15 1997 Jay Painter <jpaint@serv.net>
+ * gdk/gdkgc.c: added function gdk_gc_set_clip_rectangle
+ * gdk/gdk.h: header for above
+
+Sat Nov 15 1997 Jay Painter <jpaint@serv.net>
+ * gdk/gdkgc.c: added function gdk_gc_set_clip_rectangle
+ * gdk/gdk.h: header for above
+
+Wed Nov 12 1997 Jay Painter <jpaint@serv.net>
+ * gdk/gdkpixmap.c: Patrice Fortier's patch for transparent pixmaps.
+ * gdk/gdk.h:
+ gdk/gdkdraw.c: Patrice Fortier's patch to add pixel draw function.
+
+Sun Nov 9 1997 Jay Painter <jpaint@serv.net>
+ * Fixed problems with makefiles relating to the bug
+ which required glib to be installed.
+ * Fixed makefiles to incluce the xpm's in gtk+/gtk needed
+ for testgtk.
+ * Updated gtk+ and gtk+/glib to libtool-1.0f
+
+Fri Nov 7 1997 Jay Painter <jpaint@serv.net>
+ * gtk/gtktext.c: return char_widths[ch & 0xff]; in line 2152
+
+Thr Nov 5 1997 Jay Painter <jpaint@serv.net>
+ * gtk/testgtk.c: added drag and drop test, removed the test hack
+ from the button test
+
+Tue Nov 4 08:28:57 1997 Federico Mena <federico@bananoid.nuclecu.unam.mx>
+
+ * gtk/gtkmain.c (gtk_handle_idle): Patch from David Mosberger to
+ avoid crashes when handling idle function (this manifested itself
+ in the Umax and Microtek backends in SANE.
+
+Sun Nov 2 07:34:56 1997 Tim Janik <timj@psynet.net>
+
+ * gtk/gtkfilesel.c: Small fixes about a segmentation viaolation
+ cause by a double click in the directoy list (introduced by my
+ previous changes).
+
+ * gtk/gtklist.c: Small fixes to gtk_list_add() and gtk_list_remove().
+
+ * gtk/testgtk.c (list_add): Applied Stefan Wille's patch to make this
+ function do something ;).
+
+Fri Oct 31 Jay Painter <jpaint@serv.net>
+ *gdk/gdk.c: reformatted DND code for GTK coding standards
+ *gdk/gdkwindow.c: changed memory allocation for DND to q_mem stuff
+
+Thu Oct 30 Jay Painter <jpaint@serv.net>
+ * gdk/gdkwindow.c:
+ * gdk/gdk/gdk.h:
+ * gtk/gtkwidget.h:
+ * gtk/gtkwidget.c: Applied Stephan Willie's shaped window patch
+
+ * gdk/gdkwindow:
+ * gdk/gdk.h:
+ * gtk/gtkwidget.h:
+ * gtk/gtkwidget.c: reformatted the DND code to conform to GTK
+ coding standards
+
+ * gtk/testgtk: massive fixes, SW's shaped window example
+
+Thu Oct 30 07:33:27 1997 Tim Janik <timj@psynet.net>
+
+ * gtk/gtklistitem.c (gtk_real_list_item_toggle): applied Johannes
+ Keukelaar's <johannes@nada.kth.se> patch for keyboard support in
+ GtkList widgets.
+
+ * gtk/gtkfilesel.c: adapted dir and file list selection
+ behaviour to deal with keyboard selections. this is a little
+ bit tricky: in the dir list it just changes the entrys value on a one
+ button press. but on a keyboard selection via gtk_widget_activate() it
+ does a new population (likewise on a double click) as this seems more
+ obvious.
+
+1997-10-25 Marius Vollmer <mvo@zagadka.ping.de>
+
+ * gdk/gdkcolor.c (gdk_colormap_get_system): Initialize
+ private->ref_count.
+
+Wed Oct 22 09:47:43 1997 Tim Janik <timj@psynet.net>
+
+ * gtk/gtkwindow.c (gtk_window_key_release_event): Fixed a stupid
+ bug that caused the key_release_event to be propagated twice.
+
+Sun Oct 12 11:01:43 1997 Tim Janik <timj@psynet.net>
+
+ * acconfig.h:
+ * configure.in:
+ * gdk/gdkimage.c: Added configure check for IPC_RMID_DEFERRED_RELEASE,
+ because shmat() fails after a shmctl(..., IPC_RMID,...) for OSF1 V3.2,
+ SunOS 4.1.1, 5.5, 5.5.1, 5.6, IRIX 5.2 and 6.2.
+
+Mon Oct 6 11:59:07 1997 Federico Mena <federico@bananoid.nuclecu.unam.mx>
+
+ * gdk/gdk.c (gdk_event_translate): In line 1693, fixed typo that
+ would cause motion notify events not to be delivered.
+
+Sun Oct 5 18:15:06 1997 Federico Mena <federico@bananoid.nuclecu.unam.mx>
+
+ * gtk/gtkrc.c (gtk_rc_parse_bg_pixmap): Changed strdup() for
+ g_strdup().
+
+Wed Sep 24 17:16:34 1997 Peter Mattis <pmattis@bjork.inktomi.com>
+
+ * configure.in: Fixed a stupid error in the test for libXext that
+ would cause it to fail if X_EXTRA_LIBS was not empty.
+
+ * gtk/gtkmain.h (gtk-timj-970919.patch):
+ * gtk/gtkmain.c (gtk-timj-970919.patch): new function
+ `gtk_idle_remove_by_data' to remove all idle callbacks that take a
+ specific piece of data as argument. (gtk_get_current_event):
+ remove idles through gtk_idle_remove_by_data.
+
+ * gtk/gtkwidget.c (gtk-timj-970919.patch):
+ (gtk_widget_destroy): remove pending idles for
+ widgets that have GTK_REDRAW_PENDING or GTK_RESIZE_PENDING and
+ GTK_ANCHORED set (only anchored widgets can have a resize queue
+ handler pending). widgets that have GTK_RESIZE_NEEDED will be removed
+ from their anchored toplevels `resize_widgets' list.
+
+ (gtk_widget_queue_draw): let the widget remember the queue handler
+ tag (through `redraw_handler_key') for later call to `gtk_idle_remove'.
+
+ (gtk_widget_queue_resize): let the widget remember the queue handler
+ tag (through `resize_handler_key') for later call to `gtk_idle_remove'.
+ corrected referencing the toplevel widget for which the handler is
+ pending. if a widget is added to the `resize_widgets' list of a
+ toplevel widget, GTK_RESIZE_NEEDED is set and it's referenced.
+
+ (gtk_real_widget_queue_resize): on the deletion of the `resize_widgets'
+ list, unset GTK_RESIZE_NEEDED and unreference the removed widgets.
+
+ * gtk/gtkwindow.c (gtk-timj-970919.patch):
+ (gtk_real_window_move_resize): move `resize_containers = NULL'
+ initialization out of if-statement.
+ while stepping through the `resize_widgets' list, unreference the
+ widgets and clear GTK_RESIZE_NEEDED. if a widget realy needs are
+ resize, they are flagged through GTK_RESIZE_NEEDED now (instead of
+ GTK_RESIZE_PENDING, as this is indicative for a pending handler).
+ added checks to provide segfaulting if a widgets parent pointer
+ is NULL (e.g. on toplevel widgets that have GTK_RESIZE_NEEDED set).
+
+Tue Sep 23 13:23:27 1997 Federico Mena <federico@bananoid.nuclecu.unam.mx>
+
+ * gdk/gdkimage.c: Applied Tim Janik's patch to mark shm segments
+ as IPC_RMID so that they are automatically removed always.
+
+ * gdk/gdkfont.c: Removed casts from lvalues.
+
+ * gtk/gtkmain.c: Removed GTK_RETLOC_*() (which do a cast) from lvalues.
+
+ * gtk/gtkaccelerator.c (gtk_accelerator_table_remove): Added
+ "const" to the accelerator_key param to be consistent with the
+ declaration in gtkaccelerator.h. The const is not useful in this
+ case, anyway.
+
+Tue Sep 16 13:11:06 1997 Peter Mattis <pmattis@bjork.inktomi.com>
+
+ * gtkpreview.c: Andrew Logan Kieschnick's change to eliminate
+ round-off error when gamma is set to 1.0.
+
+ * gtkrange.c:
+ * gtkviewport.c: Jay Painter's changes to modify the way in which
+ viewports resize.
+
+ * gdkinput.c:
+ * gdkinputgxi.h:
+ * gdkinputxfree.h:
+ * gtk/Makefile.am:
+ * gtk.h:
+ * gtkeventbox.c:
+ * gtkeventbox.h: Owen Taylor's event box widget and fixes for X
+ input support (that I had broken).
+
+ * gdk.h:
+ * gdkwindow.c:
+ * gtksignal.h:
+ * gtksignal.c: Elliot Lee's changes to support Objective C. (id is
+ apparently a reserved word in Objective C).
+
+Sun Sep 14 22:33:15 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwidget.c (gtk_widget_queue_resize): If the toplevel container
+ is invisible we simply call "gtk_container_need_resize" on
+ it. This fixes a bug with option menus not redrawing correctly.
+
+ * gtkmenuitem.c (gtk_menu_item_enter): (gtk_menu_item_leave):
+ These functions now simply pass the event on to their parent. This
+ is necessary for menus to work properly due to the change in how
+ grabs are dealts with.
+
+ * gtkwindow.c (gtk_real_window_move_resize): Fixed a bug that
+ caused the GTK_RESIZE_PENDING flag to not be unset in some cases.
+
+Fri Sep 5 20:49:37 1997 Marius Vollmer <mvo@zagadka.ping.de>
+
+ Bug fixes:
+
+ * Makefile.am: Added PATCHES to EXTRA_DIST.
+ * gtk/gtkpixmap.c (gtk_pixmap_new): Move the "pixmap != NULL" test
+ after the allocation of the pixmap.
+
+ To shut up the compiler:
+
+ * gtk/gtkfilesel.c (get_pwdb): Initialize home_dir.
+ * gtk/gtkmain.c (gtk_init): Replace comments around calls to
+ g_set_*_handler with "if (0)".
+ * gtk/gtkrc.c (gtk_rc_get_token): Initialize hex_number and
+ float_number.
+ * gtk/gtkwindow.c (gtk_window_key_press_event): Initialize
+ direction.
+
+ Changes to the type system in gtk/:
+
+ * Makefile.am: Added gtktypebuiltins.h to gtkinclude_HEADERS.
+ Added gtk.defs, runelisp, gentypeinfo.el and gtktypebuiltins.c to
+ EXTRA_DIST. Added rules to generate gtktypebuiltins.* from
+ gtk.defs.
+
+ * runelisp, gentypeinfo.el, gtk.defs: New files.
+
+ * gtkaccelerator.c, gtkaccelerator.h (gtk_accelerator_table_ref):
+ Return the table so that this function can be used as the `copy'
+ function for GTK_TYPE_BOXED values.
+ * gtkstyle.c, gtkstyle.h (gtk_style_ref): Likewise.
+
+ * gtkenums.h: Removed GtkArgType enum.
+
+ * gtkmain.c (gtk_init): Call gtk_type_init to initialize the type
+ system.
+
+ * gtkobject.c (gtk_object_init_type): New function to take over
+ for gtk_object_get_type. (gtk_object_get_type): Just return the
+ constant GTK_TYPE_OBJECT. (gtk_object_collect_args): Do the right
+ thing for the new GTK_TYPE_* types.
+ * gtksignal.c (gtk_params_get): Likewise.
+
+ * gtktypeutils.c: (gtk_type_init_builtin_types): New
+ function. (gtk_type_init): Call it. Also made non-static.
+ (gtk_type_unique): The allocation scheme for numerical ids has
+ changed: The low 8 bits hold the appropriate GtkFundamentalType of
+ a type, the rest is a globally unique sequence number.
+ (gtk_type_hash): Use the sequence number of a key to hash it.
+ (gtk_type_register_builtin): New function.
+
+ * gtktypeutils.h: (GtkFundamentalType): New enumeration of the
+ fundamental types. (GTK_TYPE_MAKE, GTK_FUNDAMENTAL_TYPE,
+ GTK_TYPE_SEQNO): New macros to work with the new id scheme.
+ (GtkArg): Added fields for new types and renamed old ones. GtkArg
+ should now be a mostly opaque structure, except name and type.
+ (GTK_VALUE_*): New macros to access the values of a GtkArg.
+ (GTK_RETLOC_*): New macros to access the location of a return
+ value that is contained in a GtkArg. * gtktypebuiltins.h: New
+ file to access the typeids of the builtin types.
+
+ * gtkwidget.h (GTK_TYPE_WIDGET): New macro to access the type id
+ of the widget class.
+
+ Thru out: Changed GTK_ARG_* to the appropriate GTK_TYPE_*.
+ Changed access to GtkArg structure to the appropriate GTK_VALUE_*
+ or GTK_RETLOC_* macro. Changed GtkArgType to GtkType. Changed
+ some guints to GtkType.
+
+ General changes in gtk/ to support interpreters:
+
+ * gtkradiobutton.c (gtk_radio_button_new_from_widget,
+ gtk_radio_button_new_with_label_from_widget): New functions.
+
+ * gtksignal.c (gtk_signal_connect_no_marshal): New function.
+ (struct _GtkHandler): Added no_marshal and destroy_func fields.
+ (gtk_signal_handler_new): Initialize them.
+ (gtk_signal_connect_by_type): Added no_marshal and destroy_func
+ arguments. Changed all callers.
+ (gtk_signal_destroy): Invoke destroy_func if there is one and the
+ global destroy func does not apply. (gtk_handlers_run): If the
+ handler has no_marshal set, call its function directly without
+ going thru the signal's marshaller.
+
+Wed Sep 3 09:56:22 1997 RHS Linux User <pmattis@bjork.inktomi.com>
+
+ * gtkrange.c: Changed the way the range control focus was drawn so
+ that the range control is drawn correctly when it does not have
+ the focus.
+
+Tue Sep 2 17:41:17 1997 RHS Linux User <pmattis@bjork.inktomi.com>
+
+ * gtkwidget.c: 'gtk_real_widget_queue_resize' should only remove
+ the "resize_widgets" if another resize is not pending.
+
+Mon Sep 1 18:28:08 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmain.c: Changed the way GDK_DELETE events are handled. Only,
+ if 'gtk_widget_event' returns TRUE is the widget destroyed. By
+ default, 'gtk_widget_event' will return FALSE causing the window
+ to not be destroyed. This prevents segfaults in the GIMP and other
+ programs that do not correctly handle GDK_DELETE events.
+
+ * gtkmain.c: Added modal dialog support by allowing events
+ destined for a child of the grab widget to go to the child instead
+ of the grab widget. (Added 'gtk_widget_is_ancestor' to determine
+ the relationship between the grab widget and the event widget).
+
+ * *.[ch]: Incorprated a whole mess of patches. (Started keeping
+ the ChangeLog up to date again).
+
+Thu Jun 5 17:22:21 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenufactory.c:
+ * gtkmenufactory.h: Added 'gtk_menu_factory_remove_*'
+ calls. Removing entries/paths causes the associated widgets to be
+ destroyed.
+
+ * gtkwidget.c:
+ * gtkwidget.h: Calling 'gtk_widget_set_style' is used as an
+ indication that the programmer specifically wants that style to be
+ used. RC-style substitution is disabled for the widget after such
+ a call.
+
+ * gtkpixmap.c:
+ * gtkpixmap.h:
+ * gtkimage.c:
+ * gtkimage.h: Changed to use clip mask and a single pixmap (or
+ image) to deal with transparent areas.
+
+ * gdkpixmap.c: Modified xpm loading routines to optionally return
+ a clip mask.
+
+ * gdkgc.c:
+ * gdkdraw.c:
+ * gdktypes.h: Modifications to allow clip masks to be used with
+ gc's. Clip masks are bitmaps that specify drawable regions.
+
+Thu May 1 03:11:51 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkscrolledwindow.c: Scrolled windows need to have the
+ GTK_NO_WINDOW flag set. Not having it set caused an obscure
+ redrawing bug.
+
+Wed Apr 30 12:38:03 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkhruler.c:
+ * gtkvruler.c: Fixed a small bug that caused the indicator to be
+ positioned slightly off.
+
+Sun Apr 27 14:28:21 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenushell.c:
+ * gtkmenushell.h:
+ * gtkmenu.c:
+ * gtkmenu.h: Changes so that if a menu is popped up there is a
+ timeout period during which a menu item will not be activated and
+ if the mouse button is released in that period the menu will stay
+ popped up.
+
+ * gtkcurve.c:
+ * gtkcurve.h: Included curve widget courtesy of David
+ Mosberger-Tang (davidm@azstarnet.com).
+
+ * gtkentry.c:
+ * gtkentry.h: Changed "insert" and "delete" signals to
+ "insert_text" and "delete_text" respectively. (The symbol "delete"
+ cannot be used since it is a C++ reserved word).
+
+Sat Apr 19 01:43:49 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenufactory.c: A path which ends in "<nothing>" will cause an
+ invisible (hidden) menu entry to be created. This is useful for
+ setting an accelerator key for which a corresponding menu entry is
+ not desired.
+
+ * gtktooltips.c: Fixed some problems with destruction of the
+ active tip widget not properly updating the tooltips data
+ structures.
+
+Fri Apr 18 15:09:45 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkcontainer.c:
+ * gtklist.c:
+ * gtkwidget.c:
+ * gtkwidget.h: Patch from Owen Taylor (owt1@cornell.edu) which
+ fixes problems with destruction of objects and with destruction of
+ objects which hold the focus.
+
+Thu Apr 17 11:29:15 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenushell.c: Incorrect logic in
+ 'gtk_menu_shell_button_release' for deciding when a menu should
+ stay popped up when the mouse button is released.
+
+ * *.c: Miscellaneous fixes from folks on the net.
+
+Tue Apr 15 02:43:17 1997 Peter Mattis <pmattis@localhost>
+
+ * *.c:
+ * gtkwidget.h: Added GTK_BASIC widget flag which when set
+ specifies a widget as "basic". A "basic" widget is one which
+ doesn't take input events. For example, labels, pixmaps, boxes,
+ tables, alignments, etc.
+
+Sat Apr 12 15:23:08 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkcolorsel.c: Add "#include <math.h>" to define M_PI.
+
+ * gtksignal.c: Fixed a bug in 'gtk_signal_emit' which showed up
+ because of the new cast checking macros. The 'object' was being
+ accessed after it had been destroyed.
+
+ * gtkoptionmenu.c: Fixed bug with using 'GTK_BIN' instead of
+ 'GTK_BUTTON' which showed up because of the new cast checking
+ macros.
+
+ * *.h: 'GTK_CHECK_CAST', 'GTK_CHECK_CLASS_CAST' and
+ 'GTK_CHECK_TYPE' used by standard widget macros everywhere.
+
+Wed Apr 9 00:54:17 1997 Peter Mattis <pmattis@localhost>
+
+ * docs/gtk.texi: Started further work on documentation. Major
+ changes and additions are being made.
+
+ * gtkarrow.c:
+ * gtkarrow.h: Removed function 'gtk_arrow_get'.
+
+ * gtkcontainer.c: 'gtk_container_check_resize' no performs
+ additional checking to account for the case where the containers
+ allocation is no longer sufficient because its parent (or its
+ parents parent, etc.) needs to resize its children.
+
+Tue Apr 8 21:15:50 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkstyle.c: Fixed a bug in 'gtk_style_init' in which the font
+ was not ref'd (via 'gdk_font_ref'), but was free'd (via in
+ 'gdk_font_free') in 'gtk_style_destroy'. (David
+ Mosberger-Tang). Also cleaned up 'gtk_style_destroy' while I was
+ at it.
+
+ * gtkmain.c: Fixed a bug in 'gtk_propogate_event' which caused
+ entry widgets (and probably other widgets) not to be destroyed in
+ some instances.
+
+Mon Apr 7 01:20:38 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkentry.c:
+ * gtkentry.h: Changed the "insert_text", "delete_text" and
+ "changed_text" signals to "insert", "delete", and "changed"
+ respectively. They really should have been named this way
+ originally except the previous signal mechanism prevented
+ duplicate signal names. ("changed" is also used by adjustments).
+
+ * gtkradiomenuitem.c:
+ * gtkradiomenuitem.h: New widget.
+
+ * gtkcheckmenuitem.c:
+ * gtkcheckmenuitem.h: New widget.
+
+ * gtksignal.c: Modified 'gtk_signal_lookup' to require an object
+ type to be passed as a parameter. In addition, signals are now
+ only needed to be uniquely defined in their branch of the class
+ hierarchy. This allows the same signal name to be used in two
+ different branches of the class hierarchy. For instance, the
+ "changed" signal is used both by adjustments and entries...in
+ different ways!
+
+ * gtktypeutils.c: Added 'gtk_type_parent' which returns the parent
+ type for a given type.
+
+Sun Apr 6 22:08:35 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwidget.c: If a widget is set insensitive it loses the focus
+ if it had it.
+
+ * gtkcontainer.c: Insensitive widgets no longer participate in tab
+ traversal.
+
+ * gtkscrolledwindow.c: The "viewport" child is now destroyed and a
+ container class "foreach" function was written (which fixes the
+ sensitivity bug).
+
+Sat Apr 5 14:25:38 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkhscrollbar.c:
+ * gtkvscrollbar.c: Fixed trough size allocation bug.
+
+ * gtkhscale.c:
+ * gtkvscale.c: Fixed trough size allocation and position bug that
+ showed up when scales were placed in notebooks.
+
+Thu Mar 27 17:45:54 1997 David Mosberger-Tang <davidm@azstarnet.com>
+
+ * gtk/gtkmain.c (gtk_handle_idle): Fix appending pending_idles to
+ idle_functions so it works even when idle_functions is empty.
+
+Sat Mar 15 14:15:59 1997 Peter Mattis <pmattis@localhost>
+
+ * *.[ch]: Moved '*_class_init' and '*_init' function declarations
+ for widgets into the source file as those functions no longer had
+ to be public.
+
+ * gtkcheckbutton.c: Fixed redrawing of check button.
+
+ * gtkframe.c: Fixed redrawing of frame when the shadow type is
+ changed.
+
+Sat Mar 8 15:19:23 1997 Peter Mattis <pmattis@localhost>
+
+ * gdkimage.c: Fixed a stupid bug with 'gdk_image_new' which
+ potentially added a NULL image to "image_list" and caused problems
+ when 'gdk_image_exit' was called.
+
+Wed Mar 5 00:40:08 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkpreview.c: Massively changed the colormap handling used by
+ the preview widget. Gray previews are now dithered. A single
+ visual and colormap is shared by the color and gray previews. A
+ GTK_PREVIEW_INFO property is installed on the root window in
+ certain cases to allow multiple GTK programs to share the system
+ colormap.
+
+Sun Mar 2 05:43:06 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkcheckbutton.c: 'gtk_checkbutton_size_allocate' was allocating
+ too much space to its children and not leaving the check button
+ room for the focus border.
+
+ * gtknotebook.c: 'gtk_notebook_size_request' wasn't requesting
+ enough space when the notebook tabs are visible.
+
+Sat Mar 1 01:59:35 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkpreview.c: Fixed a problem with 'gtk_preview_put' when the
+ image byte order is GDK_MSB_FIRST.
+
+ * gtksignal.c:
+ * gtksignal.h: Added 'gtk_signal_connect_after' and
+ 'gtk_signal_connect_object_after' functions. These connect signal
+ handlers which will run after the class function associated with
+ the signal.
+
+ * gtkstyle.c: Fixed a stupid bug in 'gtk_style_new_from_key' that
+ was causing twice as many styles to be created as necesary.
+
+ * gtkwidget.c: 'gtk_real_widget_size_allocate' erases the widgets
+ old allocation if it has the GTK_NO_WINDOW flag set.
+
+ * gtkwidget.c: 'gtk_real_widget_unmap' now erases the widget if it
+ has the GTK_NO_WINDOW flag set.
+
+ * gtklabel.c: Removed 'gtk_label_unmap' as similar functionality
+ was added to gtk_real_widget_unmap.
+
+ * gtkbin.c: Modified 'gtk_bin_map' and 'gtk_bin_unmap' so that it
+ erases and draws the widget if it has the GTK_NO_WINDOW flag set.
+
+ * gtkframe.c: Modified 'gtk_frame_size_allocate' so that it erases
+ the old allocation.
+
+Fri Feb 28 03:27:05 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwindow.c: 'gtk_window_set_title' now changes the window title
+ if the window is already realized.
+
+ * gtkentry.c: 'gtk_entry_set_text' was emitting both a
+ "delete_text" and a "changed_text" signal. Modified so that it
+ only emits a "changed_text" signal.
+
+ * gtkpreview.c: Modified to work correctly on systems with MSB
+ byte order. The colormap for TRUE and DIRECT color displays is now
+ created if the default visual is not equal to the visual we are
+ using.
+
+ * gtkstyle.c: 'gtk_style_attach' and 'gtk_style_find' weren't
+ working properly in the presence of multiple colormaps are
+ different depth visuals.
+
+ * gtkcontainer.c: Massively improved focus traversal using tab and
+ arrow keys. It now uses the layout of the widgets to determine
+ where to move the focus to.
+
+Mon Feb 24 03:24:02 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenufactory.c: Set the accelerator table field for menus when
+ they are created.
+
+ * gtkmenu.c:
+ * gtkmenu.h: Added a default accelerator table field to menus so
+ that runtime modification of accelerator keys in menus can work
+ better.
+
+ * gtkrange.c: 'gtk_range_default_{h,v}motion' had faulty logic for
+ deciding what to do when the slider was at the edge of the
+ trough. They previously didn't update the adjustment value event
+ if the value wasn't what it should be when the slider was at the
+ edge of the trough.
+
+ * gtkviewport.c: 'gtk_viewport_size_allocate' and
+ 'gtk_viewport_adjustment_value_changed' both had the potential for
+ performing a divide by 0. Checks are now in place to prevent this.
+
+ * gtkmenu.c: 'gtk_menu_map' now makes sure the menu lies on screen
+ if the position function is NULL.
+
+ * gtkentry.c: Modified selection handling. 'gtk_delete_selection'
+ actually removes the X selection now. 'gtk_entry_destroy' removes
+ the selection as well and relies on the change in "gdk.c" to make
+ sure the selection event will not be sent to a non-existant
+ window.
+
+ * gdk.c: Selection events are only passed on if the selection
+ owner is not NULL.
+
+ * gtkstyle.c: 'gtk_style_detach' and 'gtk_style_destroy' were not
+ destroying the black and white gc's.
+
+Sun Feb 23 19:17:56 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwindow.c: 'gtk_window_size_request' was setting the window
+ hints. This was also being done in 'gtk_window_map', so the
+ instance being done in 'gtk_window_size_request' was removed.
+
+Fri Feb 21 01:04:01 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwidget.c: 'gtk_widget_draw' has to use the widgets allocated
+ position for the drawing rectangle when the widget has the
+ GTK_NO_WINDOW flag set.
+
+ * gtkwidget.c: In 'gtk_widget_init' the visual and colormap were
+ being directly compared against 'default_visual' and
+ 'default_colormap' instead of calling
+ 'gtk_widget_get_default_{visual,colormap}'.
+
+ * gdkrectangle.c: Amazing! There was a bug in the
+ 'gtk_rectangle_intersect' logic. Its been there for near eternity
+ and I never noticed.
+
+ * gtkpreview.c:
+ * gtkpreview.h: Created preview widget which allows drawing to an
+ rgb or grayscale buffer which is automatically displayed on the
+ screen. Performs dithering as necessary.
+
+Thu Feb 20 20:33:21 1997 Peter Mattis <pmattis@localhost>
+
+ * gdkwindow.c: Modified the logic in 'gdk_window_new' which
+ determined when to add a window to the WM_COLORMAP_WINDOWS
+ property.
+
+Wed Feb 19 19:55:29 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkruler.c: 'gtk_ruler_make_pixmap' was always destroying the
+ old backing store and creating a new one even when it would create
+ a new one of exactly the same size as the old one.
+
+Tue Feb 18 18:32:10 1997 Peter Mattis <pmattis@localhost>
+
+ * gmem.c: 'g_mem_chunk_alloc' was incorrectly modifying the mem
+ areas free mem field when reallocating a previously freed
+ atom. This caused a fairly severe memory leak.
+
+ * gtkmenushell.c: 'gtk_menu_shell_button_release' had a bug in the
+ logic for deciding whether to initiate an X pointer grab or not
+ when the mouse button was released. It now only initiates a grab
+ if the mouse is released within an active menu item.
+
+Fri Feb 14 00:57:40 1997 Peter Mattis <pmattis@localhost>
+
+ * gtknotebook.c: Changed the look of notebook tabs slightly.
+
+ * gtkentry.c:
+ * gtkentry.h: Deleting an entry widget which is holding the X
+ selection presents some difficulties. The X selection must be
+ released, but the widget can't be destroyed until the
+ SELECTION_CLEAR event is received that the X server will send in
+ response to clearing the X selection. There are probably still
+ bugs in the current method of entry widget deletion when the X
+ selection is held.
+
+ * gtkmain.c: 'gtk_propagate_event' was not properly destroying the
+ toplevel window when receiving a key press event.
+
+ * gtkwidget.c: Setting a widget insensitive did not cause it to
+ redraw. It now does.
+
+Thu Feb 13 16:59:07 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkviewport.c: 'gtk_viewport_size_allocate' was allocating its
+ child widget an adjusted allocation. Since the actual scrolling
+ has handled by a subwindow this caused the child to be double
+ scrolled. Modified to always set the child allocations origin to
+ (0, 0).
+
+Wed Feb 12 01:06:48 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkentry.c: Text is now centered vertically. Previously it was
+ pushed up against the top. This problem was only evident when the
+ widget was allocated more vertical space than it requested.
+
+ * gtkfilesel.c: 'gtk_file_selection_key_press' was previously only
+ a stub for tab completion. The actual tab completion call had been
+ left out. (Oops!)
+
+Tue Feb 11 01:43:08 1997 Peter Mattis <pmattis@localhost>
+
+ * gtksignal.c: 'gtk_signal_disconnect_by_data' was going into a
+ loop and crashing. Bad logic. Fixed.
+
+ * gtkmain.c: An idle function which returns FALSE will be removed
+ from the list of idle functions. This makes the functioning of
+ idle functions and timeouts more similar.
+
+ * gtkentry.c: 'gtk_entry_get_text' now returns an empty string
+ when the actual text is NULL. This allows "stupid" programs to use
+ the value returned by 'gtk_entry_get_text' blindly (without
+ checking to see if its NULL).
+
+ * gtkradiobutton.c: Modified 'gtk_radio_button_clicked' so that
+ 'gtk_toggle_button_toggled' is called _after_ the widget state is
+ changed.
+
+ * gtksignal.c:
+ * gtksignal.h: Added 'gtk_signal_name' which returns the character
+ string name for a given signal number.
+
+ * gtkwidget.c: 'gtk_widget_set_parent' checks to see if the widget
+ is now "anchored" through the parent chain to a widget which is
+ GTK_ANCHORED. If it is, then it changes the widgets style using
+ 'gtk_rc_get_style' and recursively performs the same operation on
+ the widgets children. This is necessary is 'gtk_rc_get_style' only
+ works properly on "anchored" widgets.
+
+ * gtkwindow.c: Modified GTK_WIN_POS logic so that it is only used
+ immediately after the window has been shown.
+
+ * gtkmenu.c: 'gtk_menu_key_press'. Can now change menu item
+ accelerator keys on the fly. Why? Why not. Cool/useless feature of
+ the day.
+
+ * gtkmenuitem.c: Accelerator key drawing. Somehow that never got
+ finished. (Oops!)
+
+ * gtkdrawingarea.c: 'gtk_drawing_area_size_allocate' was not
+ actually installed during 'gtk_drawing_area_class_init'. (Oops!)
+
+ * gtkframe.c: 'gtk_frame_size_request' fixed size requisition
+ problem caused by unsigned arithmetic.
+
+ * gtkwindow.c: Modified window widget so that it only uses the
+ widget uposition auxiliary information immediately after it has
+ been shown. This prevents the annoying bug which can cause a
+ uposition'ed window to jump back to its original position after
+ the user moves it.
+
+ * gtkwidget.c: Need to ref and unref style in
+ 'gtk_widget_{push,pop}_style' to make sure that a style on the
+ style stack is not destroyed.
+
+ * gtktogglebutton.c: 'gtk_toggle_button_set_state' now calls
+ gtk_button_clicked to actually change the state of the
+ button. In this way, radio buttons can now perform the appropriate
+ actions when the toggle button state is set.
+
+Mon Feb 10 00:27:39 1997 Peter Mattis <pmattis@localhost>
+
+ * gtklist.c: 'gtk_list_select_item' and 'gtk_list_unselect_item'
+ were casting a GList* variable to a a GtkWidget* variable. Bad bad
+ bad. (Tim Janik).
+
+ * gtksignal.c: Modified 'gtk_signal_connect' and
+ 'gtk_signal_connect_object' to warn when a signal type cannot be
+ found.
+
+Sun Feb 9 00:15:30 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkoptionmenu.c:
+ * gtkoptionmenu.h: Changed option menus back to being derived from
+ buttons. This fixes up some screwiness with their user
+ interaction.
+
+ * gtkwindow.c: Modified key press handler to support focus
+ traversal.
+
+ * gtkcontainer.c:
+ * gtkcontainer.h: Added default focus traversal back in.
+
+Sat Feb 8 10:44:38 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkviewport.h:
+ * gtkviewport.c: Massively sped up viewport scrolling. Used to be
+ reallocating child's size (offset) each time a scrollbar
+ moved. Now a subwindow is moved. All the children are moved
+ automatically by moving the subwindow. Much much much faster.
+
+Tue Feb 4 00:20:44 1997 Peter Mattis <pmattis@localhost>
+
+ * gtree.c: Changed 'g_tree_node_search' to use a loop instead of
+ recursion.
+
+Mon Feb 3 11:30:03 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkbutton.c: Removed 'parent_destroy' global and replaced it
+ with 'parent_class' global to reflect style used in other
+ widgets.
+
+ * gtknotebook.c: Tab labels were being allocated less than their
+ requested size.
+
+ * gtkrange.c:
+ * gtkrange.h: Moved the "digits" field of scales into the range
+ type. The adjustment value for scales is truncated to the number
+ of visible digits instead of being left untouched.
+
+ * gtree.c: Fixed a bug in the AVL tree implementation. Single
+ rotations were always being performed during insertion. It is
+ sometimes necessary to perform a double rotation.
+
+ * gtklabel.c: Modified 'gtk_label_expose' to only draw the label
+ when the allocated space is greater than or equal to the requested
+ space.
+
+ * gtklabel.c: Added call to 'gtk_widget_unmap' to
+ 'gtk_label_destroy' in order for the label to redraw correctly
+ (erase itself) when destroyed.
+
+ * gtklabel.c: Added 'gtk_label_unmap' call which erases the labels
+ allocation when it gets unmapped.
+
+ * *.h: Removed a few remaining instances of using "class" as a
+ parameter name. (Causes problems for C++).
+
+Fri Jan 31 12:26:50 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkcontainer.c: 'gtk_container_enable_resize' needs to call
+ 'gtk_container_check_resize' instead of
+ 'gtk_container_need_resize'.
+
+ * gtkwidget.c: 'gtk_real_widget_show' now maps the widget if its
+ parent is mapped.
+
+ * gtkscrolledwindow.c: Fixed size allocation when the scrollbar
+ policy's are GTK_POLICY_AUTOMATIC. Doing it correctly is harder
+ than I originally thought.
+
+ * gtklist.c: Added 'gtk_list_child_position' to determine the
+ integer position in a list of a child. Filled in the
+ 'gtk_list_item_select' and 'gtk_list_item_unselect' stubs.
+
+Thu Jan 30 16:08:06 1997 Peter Mattis <pmattis@localhost>
+
+ * gmem.c: Changed the implementation of G_ALLOC_AND_FREE mem
+ chunks. They used to allocate SIZEOF_VOID_P extra bytes per atom
+ in order to keep track of which mem area they were allocated
+ from. Now the mem area is determined by searching through an AVL
+ tree of the mem areas for a mem chunk and comparing memory
+ locations. A little slower, but makes G_ALLOC_AND_FREE mem chunks
+ much more attractive.
+
+ * gtree.c: Added an AVL tree implementation to glib.
+
+ * gtksignal.c:
+ * gstring.c: va_arg (arg_list, {char, short}) is
+ invalid. Arguments passed in a variable argument list are
+ promoted. ({char, short}->int). Seemed to work ok before under
+ Linux. Crashed under FreeBSD.
+
+Tue Jan 28 02:27:51 1997 Peter Mattis <pmattis@localhost>
+
+ * gdkwindow.c: Fixed a major slowdown apparent in the file
+ selection dialog which was caused by calling
+ 'gtk_window_add_colormap_windows' way way way too often.
+
+ * *.c: Many widgets called 'gtk_container_need_resize' when
+ something internal changed which would cause the widget to grow or
+ shrink. The assumption was made that the widget would change size
+ and an expose event would be generated. This happens "most" of the
+ time. But its possible for certain widgets to change size without
+ generating expose events, or for its internal geometry to change
+ without a change of size which would mean no expose event was
+ generated. So a wrapper function called
+ 'gtk_container_check_resize' was created and
+ 'gtk_container_need_resize' was modified so that it returns FALSE
+ if a resize was actually generated and TRUE if nothing
+ changed. This allows 'gtk_container_check_resize' to initiate a
+ 'gtk_widget_size_allocate' and 'gtk_widget_draw' to emulate the
+ expose event.
+
+Sat Jan 25 14:17:44 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmain.c: Fixed a bug with propogating key press events. The
+ events were sent 2 times to the toplevel windows which caused the
+ focus widget to be activated twice when the space bar was pressed.
+
+ * */configure.in:
+ * */Makefile.am: Added support for libtool and removed the old
+ shared library configuration craziness.
+
+Fri Jan 24 12:59:22 1997 Peter Mattis <pmattis@localhost>
+
+ * gtktext.c:
+ * gtktext.h: Josh's fixes and additions to the text widget.
+
+ * gtkfill.c:
+ * gtkfill.h: Filler widget useful for filling space in a
+ table. Can specify a minimum size. Used by the canvas widget.
+
+ * gtknotebook.c:
+ * gtknotebook.h: Made outline of notebook widget.
+
+ * gtkcanvas.c:
+ * gtkcanvas.h: Started canvas widget. A composite of 2 rulers (w/
+ an origin), 2 scrolllbars. Guides, grids, snap to.
+
+Sun Jan 19 18:26:45 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkdialog.c:
+ * gtkdialog.h: Created dialog widget which creates a standard
+ looking dialog with buttons along the button and a separator.
+
+ * gtkxid.c: Generalized the window table code for looking up a gdk
+ window based on an XID to work for any XID and a piece of
+ data. Can now look up gdk fonts based on their XID.
+
+ * gtkruler.c:
+ * gtkruler.h:
+ * gtkhruler.c:
+ * gtkhruler.h:
+ * gtkvruler.c:
+ * gtkvruler.h: Started conversion of the ruler widget.
+
+ * gtktext.c:
+ * gtktext.h: Started conversion of the text widget. Scrolling
+ doesn't work.
+
+ * gtkmain.c: Fixed a fairly major bug. The event widget needs to
+ be in a call for the entire duration of handling an event. Not
+ just for when the event widget itself is handling the event.
+
+ * gtkfilesel.c: Fixed up some bugs with resizing.
+
+Fri Jan 10 14:18:03 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwidget.c:
+ * gtkwidget.h:
+ * gtkentry.c:
+ * gtkentry.h: Support for selections.
+
+ * gdkselection.c:
+ * gdk.c:
+ * gdktypes.h:
+ * gdk.h: Gdk support for X selections. Currently only text
+ selections are supported.
+
+ * gtksignal.c: Fixed a major bug which occurred when destroying an
+ object. Memory was being written to after it was freed.
+
+ * gtkfilesel.c:
+ * gtkfilesel.h: Hooked up more functionality to the file selection
+ dialog.
+
+Wed Jan 8 18:13:53 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkfilesel.c:
+ * gtkfilesel.h: Mostly converted old file selection dialog
+ widget. The widget is derived from the GtkWindow class and is
+ quite a bit simpler in the widget code.
+
+ * gtkwidget.c: Fixed 'gtk_widget_grab_focus' and
+ 'gtk_widget_grab_default' to check that the toplevel widget is a
+ type of window (which includes classes derived from windows).
+
+Tue Jan 7 01:12:32 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwindow.c: Was calling 'gtk_window_resize' twice in a
+ row...why?
+
+ * gtksignal.c:
+ * gtksignal.h:
+ * *.c: Changed 'gtk_signal_new' so that the class function that is
+ called when the signal is emitted can be called either before,
+ after or both before and after the calling of any signal
+ handlers.
+
+ * gtkobject.c:
+ * gtkobject.h: Added 'object_data' mechanism for storing data
+ associated with a character string key in objects. Removed
+ 'user_data' field of objects and changed
+ 'gtk_object_{get,set}_user_data' to use the object data
+ mechanism. Removed 'handlers' field of objects.
+
+ * gtkwidget.c:
+ * gtkwidget.h:
+ * gtkwindow.c: Modified aux info mechanism to use object data
+ mechanism.
+
+ * gtksignal.c: Modified signal mechanism to use object data
+ mechanism instead of 'handlers' field.
+
+
+Mon Jan 6 15:10:16 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenushell.c: Fixed up button press handling so as to conform
+ more closely to that used by Motif.
+
+Wed Jan 1 21:27:17 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenu.c:
+ * gtkmenu.h:
+ * gtkmenubar.c:
+ * gtkmenubar.h:
+ * gtkmenushell.c:
+ * gtkmenushell.h: Reorganization of menu-ing code so that code
+ duplication is reduced. The menu shell now contains most of the
+ code for menu-ing interaction while menus and menubars simply layout
+ their child menu items in the appropriate place.
+
+Sun Dec 29 17:48:18 1996 Peter Mattis <pmattis@localhost>
+
+ * gtkmenu.c:
+ * gtkmenubar.c:
+ * gtkmenuitem.h:
+ * gtkmenuitem.c: Modifications so that menu item accelerators and
+ the submenu indicator are drawn correctly and the correct amount
+ of space is allocated.
+
+Sat Dec 28 00:32:13 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * gtkmenufactory.h:
+ * gtkmenufactory.c: Started menu factories as an easy method to
+ create and manipulate menus.
+
+Fri Dec 27 13:17:34 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * gtkmenu.c:
+ * gtkmenu.h:
+ * gtkmenubar.c:
+ * gtkmenubar.h:
+ * gtkmenuitem.c:
+ * gtkmenuitem.h:
+ * gtkmenushell.c:
+ * gtkmenushell.h: Implemented basic menu functionality. Menubars
+ and popup menus work. Submenus work. (Much left to be done).
+
+Wed Dec 18 15:27:05 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * gtktypeutils.h:
+ * gtktypeutils.c: Added 'gtk_type_from_name' which returns a type
+ identifier given a type name. Implemented using a second hash
+ table keyed by type names.
+
+ * gtkbutton.c:
+ * gtktogglebutton.c: Fixed very small messed-up drawing bug when a
+ button loses its focus.
+
+ * gtkwidget.h:
+ * gtkwidget.c:
+ * gtkbutton.c:
+ * gtkwindow.c: Added default button handling. Default buttons now
+ draw correctly and pressing return or enter causes the default
+ button (if one exists) to be activated.
+
+Tue Dec 17 19:32:21 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * gtkhscale.c:
+ * gtkvscale.c: Overrode 'draw_slider' method of ranges in order to
+ draw the slider of scales with a line in them so as to be closer
+ to the Motif look-and-feel.
+
+ * gtkwindow.c: Modified 'gtk_window_focus_in_event' so that focus
+ in events are only handled when the window is visible. Fixes a bug
+ where spurious focus in events get sent when a window is being
+ hidden.
+
+ * gtkwidget.h: Added 'activate_signal' field to the GtkWidgetClass
+ structure. Added 'gtk_widget_activate' call to emit the activate
+ signal for a widget if it is non-zero.
+
+Tue Dec 10 15:59:45 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * gtkwidget.c: 'gtk_widget_set_name' oops in strdup'ing the old
+ "widget->name" instead of the new one we are setting.
+
+ * gtkrc.c: 'gtk_rc_widget_path' changed to use
+ 'gtk_widget_get_name' instead of accessing the "widget->name"
+ field directly.
+
+ * gtkwidget.c: Added 'gtk_widget_get_name' function which returns
+ the widgets name if it exists and the widgets type name if it does
+ not.
+
+ * gtkcheckbutton.c: Added 'gtk_check_button_draw'
+ function. Modified 'gtk_check_button_expose' to pass an expose
+ event to child instead of callings its draw function.
+
+ * gtkentry.c: 'gtk_entry_draw_text' why was "+1" being added to
+ the font->ascent to calculate the font position? This was wrong
+ and caused some characters in fonts to be clipped. (Notably "g").
+
+ * gtkentry.c: 'gtk_entry_realize' specify GTK_BUTTON1_MOTION_MASK
+ and GTK_POINTER_MOTION_HINT_MASK for _both_ windows.
+
+ * gtkmain.c: 'gtk_propagate_event' needs to set the GTK_IN_CALL
+ flag for the object before calling 'gtk_widget_event' and needs to
+ destroy the object if necessary after 'gtk_widget_event' returns.
+
+ * gtkradiobutton.c: 'gtk_radio_button_clicked' needs to call
+ 'gtk_toggle_button_toggled' when the currently active button is
+ toggled.
+
+ * gtkwidget.c: 'gtk_real_widget_hide' needs to call
+ 'gtk_widget_unmap' if the widget is currently mapped.
+
+ * gtkwindow.c: Prevent automatic resizing after the user has
+ specified a new window size. Add 'handling_resize' flag to
+ windows.
+
+ * gtkscrolledwindow.c: Implement the GTK_POLICY_AUTOMATIC
+ scrollbar policy. Need to connect to the adjustments 'changed'
+ signal and notice when the scrollbars aren't in use.
+
+ * gtkcontainer.c: 'gtk_container_init' must set 'auto_resize' and
+ 'need_resize' fields to TRUE and FALSE respectively.
+
+ * gtkwidget.c: 'gtk_widget_set_parent' must all set a widgets state
+ to its parents state.
+
+Sun Dec 1 01:31:01 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * Started ChangeLog
diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10
new file mode 100644
index 000000000..a065ebef5
--- /dev/null
+++ b/ChangeLog.pre-2-10
@@ -0,0 +1,1140 @@
+Mon Nov 17 1997 Jay Painter <jpaint@serv.net>
+ * gtkviewport.c: Raph's Mon, 10 Nov 1997 patch to gtk-list
+ to fix some viewport bugs
+
+Mon Nov 17 1997 Jay Painter <jpaint@serv.net>
+ * gtk/gtkwidget.c: gtk-ajaborsk-971016-2
+ A little patch again to prevent user to use gtk_widget_set_events()
+ when a widget is already realized.
+ In this case, the gtk_widget_set_events() doesn't work.
+
+Mon Nov 17 1997 Jay Painter <jpaint@serv.net>
+ * gtk/gtkwindow.c: gtk-ajaborsk-971016-1
+ This small patch correct position for GTK_WIN_POS_CENTER and
+ GTK_WIN_POS_MOUSE GtkWindow positions.
+
+Sat Nov 15 1997 Jay Painter <jpaint@serv.net>
+ * gdk/gdkgc.c: added function gdk_gc_set_clip_rectangle
+ * gdk/gdk.h: header for above
+
+Sat Nov 15 1997 Jay Painter <jpaint@serv.net>
+ * gdk/gdkgc.c: added function gdk_gc_set_clip_rectangle
+ * gdk/gdk.h: header for above
+
+Wed Nov 12 1997 Jay Painter <jpaint@serv.net>
+ * gdk/gdkpixmap.c: Patrice Fortier's patch for transparent pixmaps.
+ * gdk/gdk.h:
+ gdk/gdkdraw.c: Patrice Fortier's patch to add pixel draw function.
+
+Sun Nov 9 1997 Jay Painter <jpaint@serv.net>
+ * Fixed problems with makefiles relating to the bug
+ which required glib to be installed.
+ * Fixed makefiles to incluce the xpm's in gtk+/gtk needed
+ for testgtk.
+ * Updated gtk+ and gtk+/glib to libtool-1.0f
+
+Fri Nov 7 1997 Jay Painter <jpaint@serv.net>
+ * gtk/gtktext.c: return char_widths[ch & 0xff]; in line 2152
+
+Thr Nov 5 1997 Jay Painter <jpaint@serv.net>
+ * gtk/testgtk.c: added drag and drop test, removed the test hack
+ from the button test
+
+Tue Nov 4 08:28:57 1997 Federico Mena <federico@bananoid.nuclecu.unam.mx>
+
+ * gtk/gtkmain.c (gtk_handle_idle): Patch from David Mosberger to
+ avoid crashes when handling idle function (this manifested itself
+ in the Umax and Microtek backends in SANE.
+
+Sun Nov 2 07:34:56 1997 Tim Janik <timj@psynet.net>
+
+ * gtk/gtkfilesel.c: Small fixes about a segmentation viaolation
+ cause by a double click in the directoy list (introduced by my
+ previous changes).
+
+ * gtk/gtklist.c: Small fixes to gtk_list_add() and gtk_list_remove().
+
+ * gtk/testgtk.c (list_add): Applied Stefan Wille's patch to make this
+ function do something ;).
+
+Fri Oct 31 Jay Painter <jpaint@serv.net>
+ *gdk/gdk.c: reformatted DND code for GTK coding standards
+ *gdk/gdkwindow.c: changed memory allocation for DND to q_mem stuff
+
+Thu Oct 30 Jay Painter <jpaint@serv.net>
+ * gdk/gdkwindow.c:
+ * gdk/gdk/gdk.h:
+ * gtk/gtkwidget.h:
+ * gtk/gtkwidget.c: Applied Stephan Willie's shaped window patch
+
+ * gdk/gdkwindow:
+ * gdk/gdk.h:
+ * gtk/gtkwidget.h:
+ * gtk/gtkwidget.c: reformatted the DND code to conform to GTK
+ coding standards
+
+ * gtk/testgtk: massive fixes, SW's shaped window example
+
+Thu Oct 30 07:33:27 1997 Tim Janik <timj@psynet.net>
+
+ * gtk/gtklistitem.c (gtk_real_list_item_toggle): applied Johannes
+ Keukelaar's <johannes@nada.kth.se> patch for keyboard support in
+ GtkList widgets.
+
+ * gtk/gtkfilesel.c: adapted dir and file list selection
+ behaviour to deal with keyboard selections. this is a little
+ bit tricky: in the dir list it just changes the entrys value on a one
+ button press. but on a keyboard selection via gtk_widget_activate() it
+ does a new population (likewise on a double click) as this seems more
+ obvious.
+
+1997-10-25 Marius Vollmer <mvo@zagadka.ping.de>
+
+ * gdk/gdkcolor.c (gdk_colormap_get_system): Initialize
+ private->ref_count.
+
+Wed Oct 22 09:47:43 1997 Tim Janik <timj@psynet.net>
+
+ * gtk/gtkwindow.c (gtk_window_key_release_event): Fixed a stupid
+ bug that caused the key_release_event to be propagated twice.
+
+Sun Oct 12 11:01:43 1997 Tim Janik <timj@psynet.net>
+
+ * acconfig.h:
+ * configure.in:
+ * gdk/gdkimage.c: Added configure check for IPC_RMID_DEFERRED_RELEASE,
+ because shmat() fails after a shmctl(..., IPC_RMID,...) for OSF1 V3.2,
+ SunOS 4.1.1, 5.5, 5.5.1, 5.6, IRIX 5.2 and 6.2.
+
+Mon Oct 6 11:59:07 1997 Federico Mena <federico@bananoid.nuclecu.unam.mx>
+
+ * gdk/gdk.c (gdk_event_translate): In line 1693, fixed typo that
+ would cause motion notify events not to be delivered.
+
+Sun Oct 5 18:15:06 1997 Federico Mena <federico@bananoid.nuclecu.unam.mx>
+
+ * gtk/gtkrc.c (gtk_rc_parse_bg_pixmap): Changed strdup() for
+ g_strdup().
+
+Wed Sep 24 17:16:34 1997 Peter Mattis <pmattis@bjork.inktomi.com>
+
+ * configure.in: Fixed a stupid error in the test for libXext that
+ would cause it to fail if X_EXTRA_LIBS was not empty.
+
+ * gtk/gtkmain.h (gtk-timj-970919.patch):
+ * gtk/gtkmain.c (gtk-timj-970919.patch): new function
+ `gtk_idle_remove_by_data' to remove all idle callbacks that take a
+ specific piece of data as argument. (gtk_get_current_event):
+ remove idles through gtk_idle_remove_by_data.
+
+ * gtk/gtkwidget.c (gtk-timj-970919.patch):
+ (gtk_widget_destroy): remove pending idles for
+ widgets that have GTK_REDRAW_PENDING or GTK_RESIZE_PENDING and
+ GTK_ANCHORED set (only anchored widgets can have a resize queue
+ handler pending). widgets that have GTK_RESIZE_NEEDED will be removed
+ from their anchored toplevels `resize_widgets' list.
+
+ (gtk_widget_queue_draw): let the widget remember the queue handler
+ tag (through `redraw_handler_key') for later call to `gtk_idle_remove'.
+
+ (gtk_widget_queue_resize): let the widget remember the queue handler
+ tag (through `resize_handler_key') for later call to `gtk_idle_remove'.
+ corrected referencing the toplevel widget for which the handler is
+ pending. if a widget is added to the `resize_widgets' list of a
+ toplevel widget, GTK_RESIZE_NEEDED is set and it's referenced.
+
+ (gtk_real_widget_queue_resize): on the deletion of the `resize_widgets'
+ list, unset GTK_RESIZE_NEEDED and unreference the removed widgets.
+
+ * gtk/gtkwindow.c (gtk-timj-970919.patch):
+ (gtk_real_window_move_resize): move `resize_containers = NULL'
+ initialization out of if-statement.
+ while stepping through the `resize_widgets' list, unreference the
+ widgets and clear GTK_RESIZE_NEEDED. if a widget realy needs are
+ resize, they are flagged through GTK_RESIZE_NEEDED now (instead of
+ GTK_RESIZE_PENDING, as this is indicative for a pending handler).
+ added checks to provide segfaulting if a widgets parent pointer
+ is NULL (e.g. on toplevel widgets that have GTK_RESIZE_NEEDED set).
+
+Tue Sep 23 13:23:27 1997 Federico Mena <federico@bananoid.nuclecu.unam.mx>
+
+ * gdk/gdkimage.c: Applied Tim Janik's patch to mark shm segments
+ as IPC_RMID so that they are automatically removed always.
+
+ * gdk/gdkfont.c: Removed casts from lvalues.
+
+ * gtk/gtkmain.c: Removed GTK_RETLOC_*() (which do a cast) from lvalues.
+
+ * gtk/gtkaccelerator.c (gtk_accelerator_table_remove): Added
+ "const" to the accelerator_key param to be consistent with the
+ declaration in gtkaccelerator.h. The const is not useful in this
+ case, anyway.
+
+Tue Sep 16 13:11:06 1997 Peter Mattis <pmattis@bjork.inktomi.com>
+
+ * gtkpreview.c: Andrew Logan Kieschnick's change to eliminate
+ round-off error when gamma is set to 1.0.
+
+ * gtkrange.c:
+ * gtkviewport.c: Jay Painter's changes to modify the way in which
+ viewports resize.
+
+ * gdkinput.c:
+ * gdkinputgxi.h:
+ * gdkinputxfree.h:
+ * gtk/Makefile.am:
+ * gtk.h:
+ * gtkeventbox.c:
+ * gtkeventbox.h: Owen Taylor's event box widget and fixes for X
+ input support (that I had broken).
+
+ * gdk.h:
+ * gdkwindow.c:
+ * gtksignal.h:
+ * gtksignal.c: Elliot Lee's changes to support Objective C. (id is
+ apparently a reserved word in Objective C).
+
+Sun Sep 14 22:33:15 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwidget.c (gtk_widget_queue_resize): If the toplevel container
+ is invisible we simply call "gtk_container_need_resize" on
+ it. This fixes a bug with option menus not redrawing correctly.
+
+ * gtkmenuitem.c (gtk_menu_item_enter): (gtk_menu_item_leave):
+ These functions now simply pass the event on to their parent. This
+ is necessary for menus to work properly due to the change in how
+ grabs are dealts with.
+
+ * gtkwindow.c (gtk_real_window_move_resize): Fixed a bug that
+ caused the GTK_RESIZE_PENDING flag to not be unset in some cases.
+
+Fri Sep 5 20:49:37 1997 Marius Vollmer <mvo@zagadka.ping.de>
+
+ Bug fixes:
+
+ * Makefile.am: Added PATCHES to EXTRA_DIST.
+ * gtk/gtkpixmap.c (gtk_pixmap_new): Move the "pixmap != NULL" test
+ after the allocation of the pixmap.
+
+ To shut up the compiler:
+
+ * gtk/gtkfilesel.c (get_pwdb): Initialize home_dir.
+ * gtk/gtkmain.c (gtk_init): Replace comments around calls to
+ g_set_*_handler with "if (0)".
+ * gtk/gtkrc.c (gtk_rc_get_token): Initialize hex_number and
+ float_number.
+ * gtk/gtkwindow.c (gtk_window_key_press_event): Initialize
+ direction.
+
+ Changes to the type system in gtk/:
+
+ * Makefile.am: Added gtktypebuiltins.h to gtkinclude_HEADERS.
+ Added gtk.defs, runelisp, gentypeinfo.el and gtktypebuiltins.c to
+ EXTRA_DIST. Added rules to generate gtktypebuiltins.* from
+ gtk.defs.
+
+ * runelisp, gentypeinfo.el, gtk.defs: New files.
+
+ * gtkaccelerator.c, gtkaccelerator.h (gtk_accelerator_table_ref):
+ Return the table so that this function can be used as the `copy'
+ function for GTK_TYPE_BOXED values.
+ * gtkstyle.c, gtkstyle.h (gtk_style_ref): Likewise.
+
+ * gtkenums.h: Removed GtkArgType enum.
+
+ * gtkmain.c (gtk_init): Call gtk_type_init to initialize the type
+ system.
+
+ * gtkobject.c (gtk_object_init_type): New function to take over
+ for gtk_object_get_type. (gtk_object_get_type): Just return the
+ constant GTK_TYPE_OBJECT. (gtk_object_collect_args): Do the right
+ thing for the new GTK_TYPE_* types.
+ * gtksignal.c (gtk_params_get): Likewise.
+
+ * gtktypeutils.c: (gtk_type_init_builtin_types): New
+ function. (gtk_type_init): Call it. Also made non-static.
+ (gtk_type_unique): The allocation scheme for numerical ids has
+ changed: The low 8 bits hold the appropriate GtkFundamentalType of
+ a type, the rest is a globally unique sequence number.
+ (gtk_type_hash): Use the sequence number of a key to hash it.
+ (gtk_type_register_builtin): New function.
+
+ * gtktypeutils.h: (GtkFundamentalType): New enumeration of the
+ fundamental types. (GTK_TYPE_MAKE, GTK_FUNDAMENTAL_TYPE,
+ GTK_TYPE_SEQNO): New macros to work with the new id scheme.
+ (GtkArg): Added fields for new types and renamed old ones. GtkArg
+ should now be a mostly opaque structure, except name and type.
+ (GTK_VALUE_*): New macros to access the values of a GtkArg.
+ (GTK_RETLOC_*): New macros to access the location of a return
+ value that is contained in a GtkArg. * gtktypebuiltins.h: New
+ file to access the typeids of the builtin types.
+
+ * gtkwidget.h (GTK_TYPE_WIDGET): New macro to access the type id
+ of the widget class.
+
+ Thru out: Changed GTK_ARG_* to the appropriate GTK_TYPE_*.
+ Changed access to GtkArg structure to the appropriate GTK_VALUE_*
+ or GTK_RETLOC_* macro. Changed GtkArgType to GtkType. Changed
+ some guints to GtkType.
+
+ General changes in gtk/ to support interpreters:
+
+ * gtkradiobutton.c (gtk_radio_button_new_from_widget,
+ gtk_radio_button_new_with_label_from_widget): New functions.
+
+ * gtksignal.c (gtk_signal_connect_no_marshal): New function.
+ (struct _GtkHandler): Added no_marshal and destroy_func fields.
+ (gtk_signal_handler_new): Initialize them.
+ (gtk_signal_connect_by_type): Added no_marshal and destroy_func
+ arguments. Changed all callers.
+ (gtk_signal_destroy): Invoke destroy_func if there is one and the
+ global destroy func does not apply. (gtk_handlers_run): If the
+ handler has no_marshal set, call its function directly without
+ going thru the signal's marshaller.
+
+Wed Sep 3 09:56:22 1997 RHS Linux User <pmattis@bjork.inktomi.com>
+
+ * gtkrange.c: Changed the way the range control focus was drawn so
+ that the range control is drawn correctly when it does not have
+ the focus.
+
+Tue Sep 2 17:41:17 1997 RHS Linux User <pmattis@bjork.inktomi.com>
+
+ * gtkwidget.c: 'gtk_real_widget_queue_resize' should only remove
+ the "resize_widgets" if another resize is not pending.
+
+Mon Sep 1 18:28:08 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmain.c: Changed the way GDK_DELETE events are handled. Only,
+ if 'gtk_widget_event' returns TRUE is the widget destroyed. By
+ default, 'gtk_widget_event' will return FALSE causing the window
+ to not be destroyed. This prevents segfaults in the GIMP and other
+ programs that do not correctly handle GDK_DELETE events.
+
+ * gtkmain.c: Added modal dialog support by allowing events
+ destined for a child of the grab widget to go to the child instead
+ of the grab widget. (Added 'gtk_widget_is_ancestor' to determine
+ the relationship between the grab widget and the event widget).
+
+ * *.[ch]: Incorprated a whole mess of patches. (Started keeping
+ the ChangeLog up to date again).
+
+Thu Jun 5 17:22:21 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenufactory.c:
+ * gtkmenufactory.h: Added 'gtk_menu_factory_remove_*'
+ calls. Removing entries/paths causes the associated widgets to be
+ destroyed.
+
+ * gtkwidget.c:
+ * gtkwidget.h: Calling 'gtk_widget_set_style' is used as an
+ indication that the programmer specifically wants that style to be
+ used. RC-style substitution is disabled for the widget after such
+ a call.
+
+ * gtkpixmap.c:
+ * gtkpixmap.h:
+ * gtkimage.c:
+ * gtkimage.h: Changed to use clip mask and a single pixmap (or
+ image) to deal with transparent areas.
+
+ * gdkpixmap.c: Modified xpm loading routines to optionally return
+ a clip mask.
+
+ * gdkgc.c:
+ * gdkdraw.c:
+ * gdktypes.h: Modifications to allow clip masks to be used with
+ gc's. Clip masks are bitmaps that specify drawable regions.
+
+Thu May 1 03:11:51 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkscrolledwindow.c: Scrolled windows need to have the
+ GTK_NO_WINDOW flag set. Not having it set caused an obscure
+ redrawing bug.
+
+Wed Apr 30 12:38:03 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkhruler.c:
+ * gtkvruler.c: Fixed a small bug that caused the indicator to be
+ positioned slightly off.
+
+Sun Apr 27 14:28:21 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenushell.c:
+ * gtkmenushell.h:
+ * gtkmenu.c:
+ * gtkmenu.h: Changes so that if a menu is popped up there is a
+ timeout period during which a menu item will not be activated and
+ if the mouse button is released in that period the menu will stay
+ popped up.
+
+ * gtkcurve.c:
+ * gtkcurve.h: Included curve widget courtesy of David
+ Mosberger-Tang (davidm@azstarnet.com).
+
+ * gtkentry.c:
+ * gtkentry.h: Changed "insert" and "delete" signals to
+ "insert_text" and "delete_text" respectively. (The symbol "delete"
+ cannot be used since it is a C++ reserved word).
+
+Sat Apr 19 01:43:49 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenufactory.c: A path which ends in "<nothing>" will cause an
+ invisible (hidden) menu entry to be created. This is useful for
+ setting an accelerator key for which a corresponding menu entry is
+ not desired.
+
+ * gtktooltips.c: Fixed some problems with destruction of the
+ active tip widget not properly updating the tooltips data
+ structures.
+
+Fri Apr 18 15:09:45 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkcontainer.c:
+ * gtklist.c:
+ * gtkwidget.c:
+ * gtkwidget.h: Patch from Owen Taylor (owt1@cornell.edu) which
+ fixes problems with destruction of objects and with destruction of
+ objects which hold the focus.
+
+Thu Apr 17 11:29:15 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenushell.c: Incorrect logic in
+ 'gtk_menu_shell_button_release' for deciding when a menu should
+ stay popped up when the mouse button is released.
+
+ * *.c: Miscellaneous fixes from folks on the net.
+
+Tue Apr 15 02:43:17 1997 Peter Mattis <pmattis@localhost>
+
+ * *.c:
+ * gtkwidget.h: Added GTK_BASIC widget flag which when set
+ specifies a widget as "basic". A "basic" widget is one which
+ doesn't take input events. For example, labels, pixmaps, boxes,
+ tables, alignments, etc.
+
+Sat Apr 12 15:23:08 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkcolorsel.c: Add "#include <math.h>" to define M_PI.
+
+ * gtksignal.c: Fixed a bug in 'gtk_signal_emit' which showed up
+ because of the new cast checking macros. The 'object' was being
+ accessed after it had been destroyed.
+
+ * gtkoptionmenu.c: Fixed bug with using 'GTK_BIN' instead of
+ 'GTK_BUTTON' which showed up because of the new cast checking
+ macros.
+
+ * *.h: 'GTK_CHECK_CAST', 'GTK_CHECK_CLASS_CAST' and
+ 'GTK_CHECK_TYPE' used by standard widget macros everywhere.
+
+Wed Apr 9 00:54:17 1997 Peter Mattis <pmattis@localhost>
+
+ * docs/gtk.texi: Started further work on documentation. Major
+ changes and additions are being made.
+
+ * gtkarrow.c:
+ * gtkarrow.h: Removed function 'gtk_arrow_get'.
+
+ * gtkcontainer.c: 'gtk_container_check_resize' no performs
+ additional checking to account for the case where the containers
+ allocation is no longer sufficient because its parent (or its
+ parents parent, etc.) needs to resize its children.
+
+Tue Apr 8 21:15:50 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkstyle.c: Fixed a bug in 'gtk_style_init' in which the font
+ was not ref'd (via 'gdk_font_ref'), but was free'd (via in
+ 'gdk_font_free') in 'gtk_style_destroy'. (David
+ Mosberger-Tang). Also cleaned up 'gtk_style_destroy' while I was
+ at it.
+
+ * gtkmain.c: Fixed a bug in 'gtk_propogate_event' which caused
+ entry widgets (and probably other widgets) not to be destroyed in
+ some instances.
+
+Mon Apr 7 01:20:38 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkentry.c:
+ * gtkentry.h: Changed the "insert_text", "delete_text" and
+ "changed_text" signals to "insert", "delete", and "changed"
+ respectively. They really should have been named this way
+ originally except the previous signal mechanism prevented
+ duplicate signal names. ("changed" is also used by adjustments).
+
+ * gtkradiomenuitem.c:
+ * gtkradiomenuitem.h: New widget.
+
+ * gtkcheckmenuitem.c:
+ * gtkcheckmenuitem.h: New widget.
+
+ * gtksignal.c: Modified 'gtk_signal_lookup' to require an object
+ type to be passed as a parameter. In addition, signals are now
+ only needed to be uniquely defined in their branch of the class
+ hierarchy. This allows the same signal name to be used in two
+ different branches of the class hierarchy. For instance, the
+ "changed" signal is used both by adjustments and entries...in
+ different ways!
+
+ * gtktypeutils.c: Added 'gtk_type_parent' which returns the parent
+ type for a given type.
+
+Sun Apr 6 22:08:35 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwidget.c: If a widget is set insensitive it loses the focus
+ if it had it.
+
+ * gtkcontainer.c: Insensitive widgets no longer participate in tab
+ traversal.
+
+ * gtkscrolledwindow.c: The "viewport" child is now destroyed and a
+ container class "foreach" function was written (which fixes the
+ sensitivity bug).
+
+Sat Apr 5 14:25:38 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkhscrollbar.c:
+ * gtkvscrollbar.c: Fixed trough size allocation bug.
+
+ * gtkhscale.c:
+ * gtkvscale.c: Fixed trough size allocation and position bug that
+ showed up when scales were placed in notebooks.
+
+Thu Mar 27 17:45:54 1997 David Mosberger-Tang <davidm@azstarnet.com>
+
+ * gtk/gtkmain.c (gtk_handle_idle): Fix appending pending_idles to
+ idle_functions so it works even when idle_functions is empty.
+
+Sat Mar 15 14:15:59 1997 Peter Mattis <pmattis@localhost>
+
+ * *.[ch]: Moved '*_class_init' and '*_init' function declarations
+ for widgets into the source file as those functions no longer had
+ to be public.
+
+ * gtkcheckbutton.c: Fixed redrawing of check button.
+
+ * gtkframe.c: Fixed redrawing of frame when the shadow type is
+ changed.
+
+Sat Mar 8 15:19:23 1997 Peter Mattis <pmattis@localhost>
+
+ * gdkimage.c: Fixed a stupid bug with 'gdk_image_new' which
+ potentially added a NULL image to "image_list" and caused problems
+ when 'gdk_image_exit' was called.
+
+Wed Mar 5 00:40:08 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkpreview.c: Massively changed the colormap handling used by
+ the preview widget. Gray previews are now dithered. A single
+ visual and colormap is shared by the color and gray previews. A
+ GTK_PREVIEW_INFO property is installed on the root window in
+ certain cases to allow multiple GTK programs to share the system
+ colormap.
+
+Sun Mar 2 05:43:06 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkcheckbutton.c: 'gtk_checkbutton_size_allocate' was allocating
+ too much space to its children and not leaving the check button
+ room for the focus border.
+
+ * gtknotebook.c: 'gtk_notebook_size_request' wasn't requesting
+ enough space when the notebook tabs are visible.
+
+Sat Mar 1 01:59:35 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkpreview.c: Fixed a problem with 'gtk_preview_put' when the
+ image byte order is GDK_MSB_FIRST.
+
+ * gtksignal.c:
+ * gtksignal.h: Added 'gtk_signal_connect_after' and
+ 'gtk_signal_connect_object_after' functions. These connect signal
+ handlers which will run after the class function associated with
+ the signal.
+
+ * gtkstyle.c: Fixed a stupid bug in 'gtk_style_new_from_key' that
+ was causing twice as many styles to be created as necesary.
+
+ * gtkwidget.c: 'gtk_real_widget_size_allocate' erases the widgets
+ old allocation if it has the GTK_NO_WINDOW flag set.
+
+ * gtkwidget.c: 'gtk_real_widget_unmap' now erases the widget if it
+ has the GTK_NO_WINDOW flag set.
+
+ * gtklabel.c: Removed 'gtk_label_unmap' as similar functionality
+ was added to gtk_real_widget_unmap.
+
+ * gtkbin.c: Modified 'gtk_bin_map' and 'gtk_bin_unmap' so that it
+ erases and draws the widget if it has the GTK_NO_WINDOW flag set.
+
+ * gtkframe.c: Modified 'gtk_frame_size_allocate' so that it erases
+ the old allocation.
+
+Fri Feb 28 03:27:05 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwindow.c: 'gtk_window_set_title' now changes the window title
+ if the window is already realized.
+
+ * gtkentry.c: 'gtk_entry_set_text' was emitting both a
+ "delete_text" and a "changed_text" signal. Modified so that it
+ only emits a "changed_text" signal.
+
+ * gtkpreview.c: Modified to work correctly on systems with MSB
+ byte order. The colormap for TRUE and DIRECT color displays is now
+ created if the default visual is not equal to the visual we are
+ using.
+
+ * gtkstyle.c: 'gtk_style_attach' and 'gtk_style_find' weren't
+ working properly in the presence of multiple colormaps are
+ different depth visuals.
+
+ * gtkcontainer.c: Massively improved focus traversal using tab and
+ arrow keys. It now uses the layout of the widgets to determine
+ where to move the focus to.
+
+Mon Feb 24 03:24:02 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenufactory.c: Set the accelerator table field for menus when
+ they are created.
+
+ * gtkmenu.c:
+ * gtkmenu.h: Added a default accelerator table field to menus so
+ that runtime modification of accelerator keys in menus can work
+ better.
+
+ * gtkrange.c: 'gtk_range_default_{h,v}motion' had faulty logic for
+ deciding what to do when the slider was at the edge of the
+ trough. They previously didn't update the adjustment value event
+ if the value wasn't what it should be when the slider was at the
+ edge of the trough.
+
+ * gtkviewport.c: 'gtk_viewport_size_allocate' and
+ 'gtk_viewport_adjustment_value_changed' both had the potential for
+ performing a divide by 0. Checks are now in place to prevent this.
+
+ * gtkmenu.c: 'gtk_menu_map' now makes sure the menu lies on screen
+ if the position function is NULL.
+
+ * gtkentry.c: Modified selection handling. 'gtk_delete_selection'
+ actually removes the X selection now. 'gtk_entry_destroy' removes
+ the selection as well and relies on the change in "gdk.c" to make
+ sure the selection event will not be sent to a non-existant
+ window.
+
+ * gdk.c: Selection events are only passed on if the selection
+ owner is not NULL.
+
+ * gtkstyle.c: 'gtk_style_detach' and 'gtk_style_destroy' were not
+ destroying the black and white gc's.
+
+Sun Feb 23 19:17:56 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwindow.c: 'gtk_window_size_request' was setting the window
+ hints. This was also being done in 'gtk_window_map', so the
+ instance being done in 'gtk_window_size_request' was removed.
+
+Fri Feb 21 01:04:01 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwidget.c: 'gtk_widget_draw' has to use the widgets allocated
+ position for the drawing rectangle when the widget has the
+ GTK_NO_WINDOW flag set.
+
+ * gtkwidget.c: In 'gtk_widget_init' the visual and colormap were
+ being directly compared against 'default_visual' and
+ 'default_colormap' instead of calling
+ 'gtk_widget_get_default_{visual,colormap}'.
+
+ * gdkrectangle.c: Amazing! There was a bug in the
+ 'gtk_rectangle_intersect' logic. Its been there for near eternity
+ and I never noticed.
+
+ * gtkpreview.c:
+ * gtkpreview.h: Created preview widget which allows drawing to an
+ rgb or grayscale buffer which is automatically displayed on the
+ screen. Performs dithering as necessary.
+
+Thu Feb 20 20:33:21 1997 Peter Mattis <pmattis@localhost>
+
+ * gdkwindow.c: Modified the logic in 'gdk_window_new' which
+ determined when to add a window to the WM_COLORMAP_WINDOWS
+ property.
+
+Wed Feb 19 19:55:29 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkruler.c: 'gtk_ruler_make_pixmap' was always destroying the
+ old backing store and creating a new one even when it would create
+ a new one of exactly the same size as the old one.
+
+Tue Feb 18 18:32:10 1997 Peter Mattis <pmattis@localhost>
+
+ * gmem.c: 'g_mem_chunk_alloc' was incorrectly modifying the mem
+ areas free mem field when reallocating a previously freed
+ atom. This caused a fairly severe memory leak.
+
+ * gtkmenushell.c: 'gtk_menu_shell_button_release' had a bug in the
+ logic for deciding whether to initiate an X pointer grab or not
+ when the mouse button was released. It now only initiates a grab
+ if the mouse is released within an active menu item.
+
+Fri Feb 14 00:57:40 1997 Peter Mattis <pmattis@localhost>
+
+ * gtknotebook.c: Changed the look of notebook tabs slightly.
+
+ * gtkentry.c:
+ * gtkentry.h: Deleting an entry widget which is holding the X
+ selection presents some difficulties. The X selection must be
+ released, but the widget can't be destroyed until the
+ SELECTION_CLEAR event is received that the X server will send in
+ response to clearing the X selection. There are probably still
+ bugs in the current method of entry widget deletion when the X
+ selection is held.
+
+ * gtkmain.c: 'gtk_propagate_event' was not properly destroying the
+ toplevel window when receiving a key press event.
+
+ * gtkwidget.c: Setting a widget insensitive did not cause it to
+ redraw. It now does.
+
+Thu Feb 13 16:59:07 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkviewport.c: 'gtk_viewport_size_allocate' was allocating its
+ child widget an adjusted allocation. Since the actual scrolling
+ has handled by a subwindow this caused the child to be double
+ scrolled. Modified to always set the child allocations origin to
+ (0, 0).
+
+Wed Feb 12 01:06:48 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkentry.c: Text is now centered vertically. Previously it was
+ pushed up against the top. This problem was only evident when the
+ widget was allocated more vertical space than it requested.
+
+ * gtkfilesel.c: 'gtk_file_selection_key_press' was previously only
+ a stub for tab completion. The actual tab completion call had been
+ left out. (Oops!)
+
+Tue Feb 11 01:43:08 1997 Peter Mattis <pmattis@localhost>
+
+ * gtksignal.c: 'gtk_signal_disconnect_by_data' was going into a
+ loop and crashing. Bad logic. Fixed.
+
+ * gtkmain.c: An idle function which returns FALSE will be removed
+ from the list of idle functions. This makes the functioning of
+ idle functions and timeouts more similar.
+
+ * gtkentry.c: 'gtk_entry_get_text' now returns an empty string
+ when the actual text is NULL. This allows "stupid" programs to use
+ the value returned by 'gtk_entry_get_text' blindly (without
+ checking to see if its NULL).
+
+ * gtkradiobutton.c: Modified 'gtk_radio_button_clicked' so that
+ 'gtk_toggle_button_toggled' is called _after_ the widget state is
+ changed.
+
+ * gtksignal.c:
+ * gtksignal.h: Added 'gtk_signal_name' which returns the character
+ string name for a given signal number.
+
+ * gtkwidget.c: 'gtk_widget_set_parent' checks to see if the widget
+ is now "anchored" through the parent chain to a widget which is
+ GTK_ANCHORED. If it is, then it changes the widgets style using
+ 'gtk_rc_get_style' and recursively performs the same operation on
+ the widgets children. This is necessary is 'gtk_rc_get_style' only
+ works properly on "anchored" widgets.
+
+ * gtkwindow.c: Modified GTK_WIN_POS logic so that it is only used
+ immediately after the window has been shown.
+
+ * gtkmenu.c: 'gtk_menu_key_press'. Can now change menu item
+ accelerator keys on the fly. Why? Why not. Cool/useless feature of
+ the day.
+
+ * gtkmenuitem.c: Accelerator key drawing. Somehow that never got
+ finished. (Oops!)
+
+ * gtkdrawingarea.c: 'gtk_drawing_area_size_allocate' was not
+ actually installed during 'gtk_drawing_area_class_init'. (Oops!)
+
+ * gtkframe.c: 'gtk_frame_size_request' fixed size requisition
+ problem caused by unsigned arithmetic.
+
+ * gtkwindow.c: Modified window widget so that it only uses the
+ widget uposition auxiliary information immediately after it has
+ been shown. This prevents the annoying bug which can cause a
+ uposition'ed window to jump back to its original position after
+ the user moves it.
+
+ * gtkwidget.c: Need to ref and unref style in
+ 'gtk_widget_{push,pop}_style' to make sure that a style on the
+ style stack is not destroyed.
+
+ * gtktogglebutton.c: 'gtk_toggle_button_set_state' now calls
+ gtk_button_clicked to actually change the state of the
+ button. In this way, radio buttons can now perform the appropriate
+ actions when the toggle button state is set.
+
+Mon Feb 10 00:27:39 1997 Peter Mattis <pmattis@localhost>
+
+ * gtklist.c: 'gtk_list_select_item' and 'gtk_list_unselect_item'
+ were casting a GList* variable to a a GtkWidget* variable. Bad bad
+ bad. (Tim Janik).
+
+ * gtksignal.c: Modified 'gtk_signal_connect' and
+ 'gtk_signal_connect_object' to warn when a signal type cannot be
+ found.
+
+Sun Feb 9 00:15:30 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkoptionmenu.c:
+ * gtkoptionmenu.h: Changed option menus back to being derived from
+ buttons. This fixes up some screwiness with their user
+ interaction.
+
+ * gtkwindow.c: Modified key press handler to support focus
+ traversal.
+
+ * gtkcontainer.c:
+ * gtkcontainer.h: Added default focus traversal back in.
+
+Sat Feb 8 10:44:38 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkviewport.h:
+ * gtkviewport.c: Massively sped up viewport scrolling. Used to be
+ reallocating child's size (offset) each time a scrollbar
+ moved. Now a subwindow is moved. All the children are moved
+ automatically by moving the subwindow. Much much much faster.
+
+Tue Feb 4 00:20:44 1997 Peter Mattis <pmattis@localhost>
+
+ * gtree.c: Changed 'g_tree_node_search' to use a loop instead of
+ recursion.
+
+Mon Feb 3 11:30:03 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkbutton.c: Removed 'parent_destroy' global and replaced it
+ with 'parent_class' global to reflect style used in other
+ widgets.
+
+ * gtknotebook.c: Tab labels were being allocated less than their
+ requested size.
+
+ * gtkrange.c:
+ * gtkrange.h: Moved the "digits" field of scales into the range
+ type. The adjustment value for scales is truncated to the number
+ of visible digits instead of being left untouched.
+
+ * gtree.c: Fixed a bug in the AVL tree implementation. Single
+ rotations were always being performed during insertion. It is
+ sometimes necessary to perform a double rotation.
+
+ * gtklabel.c: Modified 'gtk_label_expose' to only draw the label
+ when the allocated space is greater than or equal to the requested
+ space.
+
+ * gtklabel.c: Added call to 'gtk_widget_unmap' to
+ 'gtk_label_destroy' in order for the label to redraw correctly
+ (erase itself) when destroyed.
+
+ * gtklabel.c: Added 'gtk_label_unmap' call which erases the labels
+ allocation when it gets unmapped.
+
+ * *.h: Removed a few remaining instances of using "class" as a
+ parameter name. (Causes problems for C++).
+
+Fri Jan 31 12:26:50 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkcontainer.c: 'gtk_container_enable_resize' needs to call
+ 'gtk_container_check_resize' instead of
+ 'gtk_container_need_resize'.
+
+ * gtkwidget.c: 'gtk_real_widget_show' now maps the widget if its
+ parent is mapped.
+
+ * gtkscrolledwindow.c: Fixed size allocation when the scrollbar
+ policy's are GTK_POLICY_AUTOMATIC. Doing it correctly is harder
+ than I originally thought.
+
+ * gtklist.c: Added 'gtk_list_child_position' to determine the
+ integer position in a list of a child. Filled in the
+ 'gtk_list_item_select' and 'gtk_list_item_unselect' stubs.
+
+Thu Jan 30 16:08:06 1997 Peter Mattis <pmattis@localhost>
+
+ * gmem.c: Changed the implementation of G_ALLOC_AND_FREE mem
+ chunks. They used to allocate SIZEOF_VOID_P extra bytes per atom
+ in order to keep track of which mem area they were allocated
+ from. Now the mem area is determined by searching through an AVL
+ tree of the mem areas for a mem chunk and comparing memory
+ locations. A little slower, but makes G_ALLOC_AND_FREE mem chunks
+ much more attractive.
+
+ * gtree.c: Added an AVL tree implementation to glib.
+
+ * gtksignal.c:
+ * gstring.c: va_arg (arg_list, {char, short}) is
+ invalid. Arguments passed in a variable argument list are
+ promoted. ({char, short}->int). Seemed to work ok before under
+ Linux. Crashed under FreeBSD.
+
+Tue Jan 28 02:27:51 1997 Peter Mattis <pmattis@localhost>
+
+ * gdkwindow.c: Fixed a major slowdown apparent in the file
+ selection dialog which was caused by calling
+ 'gtk_window_add_colormap_windows' way way way too often.
+
+ * *.c: Many widgets called 'gtk_container_need_resize' when
+ something internal changed which would cause the widget to grow or
+ shrink. The assumption was made that the widget would change size
+ and an expose event would be generated. This happens "most" of the
+ time. But its possible for certain widgets to change size without
+ generating expose events, or for its internal geometry to change
+ without a change of size which would mean no expose event was
+ generated. So a wrapper function called
+ 'gtk_container_check_resize' was created and
+ 'gtk_container_need_resize' was modified so that it returns FALSE
+ if a resize was actually generated and TRUE if nothing
+ changed. This allows 'gtk_container_check_resize' to initiate a
+ 'gtk_widget_size_allocate' and 'gtk_widget_draw' to emulate the
+ expose event.
+
+Sat Jan 25 14:17:44 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmain.c: Fixed a bug with propogating key press events. The
+ events were sent 2 times to the toplevel windows which caused the
+ focus widget to be activated twice when the space bar was pressed.
+
+ * */configure.in:
+ * */Makefile.am: Added support for libtool and removed the old
+ shared library configuration craziness.
+
+Fri Jan 24 12:59:22 1997 Peter Mattis <pmattis@localhost>
+
+ * gtktext.c:
+ * gtktext.h: Josh's fixes and additions to the text widget.
+
+ * gtkfill.c:
+ * gtkfill.h: Filler widget useful for filling space in a
+ table. Can specify a minimum size. Used by the canvas widget.
+
+ * gtknotebook.c:
+ * gtknotebook.h: Made outline of notebook widget.
+
+ * gtkcanvas.c:
+ * gtkcanvas.h: Started canvas widget. A composite of 2 rulers (w/
+ an origin), 2 scrolllbars. Guides, grids, snap to.
+
+Sun Jan 19 18:26:45 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkdialog.c:
+ * gtkdialog.h: Created dialog widget which creates a standard
+ looking dialog with buttons along the button and a separator.
+
+ * gtkxid.c: Generalized the window table code for looking up a gdk
+ window based on an XID to work for any XID and a piece of
+ data. Can now look up gdk fonts based on their XID.
+
+ * gtkruler.c:
+ * gtkruler.h:
+ * gtkhruler.c:
+ * gtkhruler.h:
+ * gtkvruler.c:
+ * gtkvruler.h: Started conversion of the ruler widget.
+
+ * gtktext.c:
+ * gtktext.h: Started conversion of the text widget. Scrolling
+ doesn't work.
+
+ * gtkmain.c: Fixed a fairly major bug. The event widget needs to
+ be in a call for the entire duration of handling an event. Not
+ just for when the event widget itself is handling the event.
+
+ * gtkfilesel.c: Fixed up some bugs with resizing.
+
+Fri Jan 10 14:18:03 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwidget.c:
+ * gtkwidget.h:
+ * gtkentry.c:
+ * gtkentry.h: Support for selections.
+
+ * gdkselection.c:
+ * gdk.c:
+ * gdktypes.h:
+ * gdk.h: Gdk support for X selections. Currently only text
+ selections are supported.
+
+ * gtksignal.c: Fixed a major bug which occurred when destroying an
+ object. Memory was being written to after it was freed.
+
+ * gtkfilesel.c:
+ * gtkfilesel.h: Hooked up more functionality to the file selection
+ dialog.
+
+Wed Jan 8 18:13:53 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkfilesel.c:
+ * gtkfilesel.h: Mostly converted old file selection dialog
+ widget. The widget is derived from the GtkWindow class and is
+ quite a bit simpler in the widget code.
+
+ * gtkwidget.c: Fixed 'gtk_widget_grab_focus' and
+ 'gtk_widget_grab_default' to check that the toplevel widget is a
+ type of window (which includes classes derived from windows).
+
+Tue Jan 7 01:12:32 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwindow.c: Was calling 'gtk_window_resize' twice in a
+ row...why?
+
+ * gtksignal.c:
+ * gtksignal.h:
+ * *.c: Changed 'gtk_signal_new' so that the class function that is
+ called when the signal is emitted can be called either before,
+ after or both before and after the calling of any signal
+ handlers.
+
+ * gtkobject.c:
+ * gtkobject.h: Added 'object_data' mechanism for storing data
+ associated with a character string key in objects. Removed
+ 'user_data' field of objects and changed
+ 'gtk_object_{get,set}_user_data' to use the object data
+ mechanism. Removed 'handlers' field of objects.
+
+ * gtkwidget.c:
+ * gtkwidget.h:
+ * gtkwindow.c: Modified aux info mechanism to use object data
+ mechanism.
+
+ * gtksignal.c: Modified signal mechanism to use object data
+ mechanism instead of 'handlers' field.
+
+
+Mon Jan 6 15:10:16 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenushell.c: Fixed up button press handling so as to conform
+ more closely to that used by Motif.
+
+Wed Jan 1 21:27:17 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenu.c:
+ * gtkmenu.h:
+ * gtkmenubar.c:
+ * gtkmenubar.h:
+ * gtkmenushell.c:
+ * gtkmenushell.h: Reorganization of menu-ing code so that code
+ duplication is reduced. The menu shell now contains most of the
+ code for menu-ing interaction while menus and menubars simply layout
+ their child menu items in the appropriate place.
+
+Sun Dec 29 17:48:18 1996 Peter Mattis <pmattis@localhost>
+
+ * gtkmenu.c:
+ * gtkmenubar.c:
+ * gtkmenuitem.h:
+ * gtkmenuitem.c: Modifications so that menu item accelerators and
+ the submenu indicator are drawn correctly and the correct amount
+ of space is allocated.
+
+Sat Dec 28 00:32:13 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * gtkmenufactory.h:
+ * gtkmenufactory.c: Started menu factories as an easy method to
+ create and manipulate menus.
+
+Fri Dec 27 13:17:34 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * gtkmenu.c:
+ * gtkmenu.h:
+ * gtkmenubar.c:
+ * gtkmenubar.h:
+ * gtkmenuitem.c:
+ * gtkmenuitem.h:
+ * gtkmenushell.c:
+ * gtkmenushell.h: Implemented basic menu functionality. Menubars
+ and popup menus work. Submenus work. (Much left to be done).
+
+Wed Dec 18 15:27:05 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * gtktypeutils.h:
+ * gtktypeutils.c: Added 'gtk_type_from_name' which returns a type
+ identifier given a type name. Implemented using a second hash
+ table keyed by type names.
+
+ * gtkbutton.c:
+ * gtktogglebutton.c: Fixed very small messed-up drawing bug when a
+ button loses its focus.
+
+ * gtkwidget.h:
+ * gtkwidget.c:
+ * gtkbutton.c:
+ * gtkwindow.c: Added default button handling. Default buttons now
+ draw correctly and pressing return or enter causes the default
+ button (if one exists) to be activated.
+
+Tue Dec 17 19:32:21 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * gtkhscale.c:
+ * gtkvscale.c: Overrode 'draw_slider' method of ranges in order to
+ draw the slider of scales with a line in them so as to be closer
+ to the Motif look-and-feel.
+
+ * gtkwindow.c: Modified 'gtk_window_focus_in_event' so that focus
+ in events are only handled when the window is visible. Fixes a bug
+ where spurious focus in events get sent when a window is being
+ hidden.
+
+ * gtkwidget.h: Added 'activate_signal' field to the GtkWidgetClass
+ structure. Added 'gtk_widget_activate' call to emit the activate
+ signal for a widget if it is non-zero.
+
+Tue Dec 10 15:59:45 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * gtkwidget.c: 'gtk_widget_set_name' oops in strdup'ing the old
+ "widget->name" instead of the new one we are setting.
+
+ * gtkrc.c: 'gtk_rc_widget_path' changed to use
+ 'gtk_widget_get_name' instead of accessing the "widget->name"
+ field directly.
+
+ * gtkwidget.c: Added 'gtk_widget_get_name' function which returns
+ the widgets name if it exists and the widgets type name if it does
+ not.
+
+ * gtkcheckbutton.c: Added 'gtk_check_button_draw'
+ function. Modified 'gtk_check_button_expose' to pass an expose
+ event to child instead of callings its draw function.
+
+ * gtkentry.c: 'gtk_entry_draw_text' why was "+1" being added to
+ the font->ascent to calculate the font position? This was wrong
+ and caused some characters in fonts to be clipped. (Notably "g").
+
+ * gtkentry.c: 'gtk_entry_realize' specify GTK_BUTTON1_MOTION_MASK
+ and GTK_POINTER_MOTION_HINT_MASK for _both_ windows.
+
+ * gtkmain.c: 'gtk_propagate_event' needs to set the GTK_IN_CALL
+ flag for the object before calling 'gtk_widget_event' and needs to
+ destroy the object if necessary after 'gtk_widget_event' returns.
+
+ * gtkradiobutton.c: 'gtk_radio_button_clicked' needs to call
+ 'gtk_toggle_button_toggled' when the currently active button is
+ toggled.
+
+ * gtkwidget.c: 'gtk_real_widget_hide' needs to call
+ 'gtk_widget_unmap' if the widget is currently mapped.
+
+ * gtkwindow.c: Prevent automatic resizing after the user has
+ specified a new window size. Add 'handling_resize' flag to
+ windows.
+
+ * gtkscrolledwindow.c: Implement the GTK_POLICY_AUTOMATIC
+ scrollbar policy. Need to connect to the adjustments 'changed'
+ signal and notice when the scrollbars aren't in use.
+
+ * gtkcontainer.c: 'gtk_container_init' must set 'auto_resize' and
+ 'need_resize' fields to TRUE and FALSE respectively.
+
+ * gtkwidget.c: 'gtk_widget_set_parent' must all set a widgets state
+ to its parents state.
+
+Sun Dec 1 01:31:01 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * Started ChangeLog
diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2
new file mode 100644
index 000000000..a065ebef5
--- /dev/null
+++ b/ChangeLog.pre-2-2
@@ -0,0 +1,1140 @@
+Mon Nov 17 1997 Jay Painter <jpaint@serv.net>
+ * gtkviewport.c: Raph's Mon, 10 Nov 1997 patch to gtk-list
+ to fix some viewport bugs
+
+Mon Nov 17 1997 Jay Painter <jpaint@serv.net>
+ * gtk/gtkwidget.c: gtk-ajaborsk-971016-2
+ A little patch again to prevent user to use gtk_widget_set_events()
+ when a widget is already realized.
+ In this case, the gtk_widget_set_events() doesn't work.
+
+Mon Nov 17 1997 Jay Painter <jpaint@serv.net>
+ * gtk/gtkwindow.c: gtk-ajaborsk-971016-1
+ This small patch correct position for GTK_WIN_POS_CENTER and
+ GTK_WIN_POS_MOUSE GtkWindow positions.
+
+Sat Nov 15 1997 Jay Painter <jpaint@serv.net>
+ * gdk/gdkgc.c: added function gdk_gc_set_clip_rectangle
+ * gdk/gdk.h: header for above
+
+Sat Nov 15 1997 Jay Painter <jpaint@serv.net>
+ * gdk/gdkgc.c: added function gdk_gc_set_clip_rectangle
+ * gdk/gdk.h: header for above
+
+Wed Nov 12 1997 Jay Painter <jpaint@serv.net>
+ * gdk/gdkpixmap.c: Patrice Fortier's patch for transparent pixmaps.
+ * gdk/gdk.h:
+ gdk/gdkdraw.c: Patrice Fortier's patch to add pixel draw function.
+
+Sun Nov 9 1997 Jay Painter <jpaint@serv.net>
+ * Fixed problems with makefiles relating to the bug
+ which required glib to be installed.
+ * Fixed makefiles to incluce the xpm's in gtk+/gtk needed
+ for testgtk.
+ * Updated gtk+ and gtk+/glib to libtool-1.0f
+
+Fri Nov 7 1997 Jay Painter <jpaint@serv.net>
+ * gtk/gtktext.c: return char_widths[ch & 0xff]; in line 2152
+
+Thr Nov 5 1997 Jay Painter <jpaint@serv.net>
+ * gtk/testgtk.c: added drag and drop test, removed the test hack
+ from the button test
+
+Tue Nov 4 08:28:57 1997 Federico Mena <federico@bananoid.nuclecu.unam.mx>
+
+ * gtk/gtkmain.c (gtk_handle_idle): Patch from David Mosberger to
+ avoid crashes when handling idle function (this manifested itself
+ in the Umax and Microtek backends in SANE.
+
+Sun Nov 2 07:34:56 1997 Tim Janik <timj@psynet.net>
+
+ * gtk/gtkfilesel.c: Small fixes about a segmentation viaolation
+ cause by a double click in the directoy list (introduced by my
+ previous changes).
+
+ * gtk/gtklist.c: Small fixes to gtk_list_add() and gtk_list_remove().
+
+ * gtk/testgtk.c (list_add): Applied Stefan Wille's patch to make this
+ function do something ;).
+
+Fri Oct 31 Jay Painter <jpaint@serv.net>
+ *gdk/gdk.c: reformatted DND code for GTK coding standards
+ *gdk/gdkwindow.c: changed memory allocation for DND to q_mem stuff
+
+Thu Oct 30 Jay Painter <jpaint@serv.net>
+ * gdk/gdkwindow.c:
+ * gdk/gdk/gdk.h:
+ * gtk/gtkwidget.h:
+ * gtk/gtkwidget.c: Applied Stephan Willie's shaped window patch
+
+ * gdk/gdkwindow:
+ * gdk/gdk.h:
+ * gtk/gtkwidget.h:
+ * gtk/gtkwidget.c: reformatted the DND code to conform to GTK
+ coding standards
+
+ * gtk/testgtk: massive fixes, SW's shaped window example
+
+Thu Oct 30 07:33:27 1997 Tim Janik <timj@psynet.net>
+
+ * gtk/gtklistitem.c (gtk_real_list_item_toggle): applied Johannes
+ Keukelaar's <johannes@nada.kth.se> patch for keyboard support in
+ GtkList widgets.
+
+ * gtk/gtkfilesel.c: adapted dir and file list selection
+ behaviour to deal with keyboard selections. this is a little
+ bit tricky: in the dir list it just changes the entrys value on a one
+ button press. but on a keyboard selection via gtk_widget_activate() it
+ does a new population (likewise on a double click) as this seems more
+ obvious.
+
+1997-10-25 Marius Vollmer <mvo@zagadka.ping.de>
+
+ * gdk/gdkcolor.c (gdk_colormap_get_system): Initialize
+ private->ref_count.
+
+Wed Oct 22 09:47:43 1997 Tim Janik <timj@psynet.net>
+
+ * gtk/gtkwindow.c (gtk_window_key_release_event): Fixed a stupid
+ bug that caused the key_release_event to be propagated twice.
+
+Sun Oct 12 11:01:43 1997 Tim Janik <timj@psynet.net>
+
+ * acconfig.h:
+ * configure.in:
+ * gdk/gdkimage.c: Added configure check for IPC_RMID_DEFERRED_RELEASE,
+ because shmat() fails after a shmctl(..., IPC_RMID,...) for OSF1 V3.2,
+ SunOS 4.1.1, 5.5, 5.5.1, 5.6, IRIX 5.2 and 6.2.
+
+Mon Oct 6 11:59:07 1997 Federico Mena <federico@bananoid.nuclecu.unam.mx>
+
+ * gdk/gdk.c (gdk_event_translate): In line 1693, fixed typo that
+ would cause motion notify events not to be delivered.
+
+Sun Oct 5 18:15:06 1997 Federico Mena <federico@bananoid.nuclecu.unam.mx>
+
+ * gtk/gtkrc.c (gtk_rc_parse_bg_pixmap): Changed strdup() for
+ g_strdup().
+
+Wed Sep 24 17:16:34 1997 Peter Mattis <pmattis@bjork.inktomi.com>
+
+ * configure.in: Fixed a stupid error in the test for libXext that
+ would cause it to fail if X_EXTRA_LIBS was not empty.
+
+ * gtk/gtkmain.h (gtk-timj-970919.patch):
+ * gtk/gtkmain.c (gtk-timj-970919.patch): new function
+ `gtk_idle_remove_by_data' to remove all idle callbacks that take a
+ specific piece of data as argument. (gtk_get_current_event):
+ remove idles through gtk_idle_remove_by_data.
+
+ * gtk/gtkwidget.c (gtk-timj-970919.patch):
+ (gtk_widget_destroy): remove pending idles for
+ widgets that have GTK_REDRAW_PENDING or GTK_RESIZE_PENDING and
+ GTK_ANCHORED set (only anchored widgets can have a resize queue
+ handler pending). widgets that have GTK_RESIZE_NEEDED will be removed
+ from their anchored toplevels `resize_widgets' list.
+
+ (gtk_widget_queue_draw): let the widget remember the queue handler
+ tag (through `redraw_handler_key') for later call to `gtk_idle_remove'.
+
+ (gtk_widget_queue_resize): let the widget remember the queue handler
+ tag (through `resize_handler_key') for later call to `gtk_idle_remove'.
+ corrected referencing the toplevel widget for which the handler is
+ pending. if a widget is added to the `resize_widgets' list of a
+ toplevel widget, GTK_RESIZE_NEEDED is set and it's referenced.
+
+ (gtk_real_widget_queue_resize): on the deletion of the `resize_widgets'
+ list, unset GTK_RESIZE_NEEDED and unreference the removed widgets.
+
+ * gtk/gtkwindow.c (gtk-timj-970919.patch):
+ (gtk_real_window_move_resize): move `resize_containers = NULL'
+ initialization out of if-statement.
+ while stepping through the `resize_widgets' list, unreference the
+ widgets and clear GTK_RESIZE_NEEDED. if a widget realy needs are
+ resize, they are flagged through GTK_RESIZE_NEEDED now (instead of
+ GTK_RESIZE_PENDING, as this is indicative for a pending handler).
+ added checks to provide segfaulting if a widgets parent pointer
+ is NULL (e.g. on toplevel widgets that have GTK_RESIZE_NEEDED set).
+
+Tue Sep 23 13:23:27 1997 Federico Mena <federico@bananoid.nuclecu.unam.mx>
+
+ * gdk/gdkimage.c: Applied Tim Janik's patch to mark shm segments
+ as IPC_RMID so that they are automatically removed always.
+
+ * gdk/gdkfont.c: Removed casts from lvalues.
+
+ * gtk/gtkmain.c: Removed GTK_RETLOC_*() (which do a cast) from lvalues.
+
+ * gtk/gtkaccelerator.c (gtk_accelerator_table_remove): Added
+ "const" to the accelerator_key param to be consistent with the
+ declaration in gtkaccelerator.h. The const is not useful in this
+ case, anyway.
+
+Tue Sep 16 13:11:06 1997 Peter Mattis <pmattis@bjork.inktomi.com>
+
+ * gtkpreview.c: Andrew Logan Kieschnick's change to eliminate
+ round-off error when gamma is set to 1.0.
+
+ * gtkrange.c:
+ * gtkviewport.c: Jay Painter's changes to modify the way in which
+ viewports resize.
+
+ * gdkinput.c:
+ * gdkinputgxi.h:
+ * gdkinputxfree.h:
+ * gtk/Makefile.am:
+ * gtk.h:
+ * gtkeventbox.c:
+ * gtkeventbox.h: Owen Taylor's event box widget and fixes for X
+ input support (that I had broken).
+
+ * gdk.h:
+ * gdkwindow.c:
+ * gtksignal.h:
+ * gtksignal.c: Elliot Lee's changes to support Objective C. (id is
+ apparently a reserved word in Objective C).
+
+Sun Sep 14 22:33:15 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwidget.c (gtk_widget_queue_resize): If the toplevel container
+ is invisible we simply call "gtk_container_need_resize" on
+ it. This fixes a bug with option menus not redrawing correctly.
+
+ * gtkmenuitem.c (gtk_menu_item_enter): (gtk_menu_item_leave):
+ These functions now simply pass the event on to their parent. This
+ is necessary for menus to work properly due to the change in how
+ grabs are dealts with.
+
+ * gtkwindow.c (gtk_real_window_move_resize): Fixed a bug that
+ caused the GTK_RESIZE_PENDING flag to not be unset in some cases.
+
+Fri Sep 5 20:49:37 1997 Marius Vollmer <mvo@zagadka.ping.de>
+
+ Bug fixes:
+
+ * Makefile.am: Added PATCHES to EXTRA_DIST.
+ * gtk/gtkpixmap.c (gtk_pixmap_new): Move the "pixmap != NULL" test
+ after the allocation of the pixmap.
+
+ To shut up the compiler:
+
+ * gtk/gtkfilesel.c (get_pwdb): Initialize home_dir.
+ * gtk/gtkmain.c (gtk_init): Replace comments around calls to
+ g_set_*_handler with "if (0)".
+ * gtk/gtkrc.c (gtk_rc_get_token): Initialize hex_number and
+ float_number.
+ * gtk/gtkwindow.c (gtk_window_key_press_event): Initialize
+ direction.
+
+ Changes to the type system in gtk/:
+
+ * Makefile.am: Added gtktypebuiltins.h to gtkinclude_HEADERS.
+ Added gtk.defs, runelisp, gentypeinfo.el and gtktypebuiltins.c to
+ EXTRA_DIST. Added rules to generate gtktypebuiltins.* from
+ gtk.defs.
+
+ * runelisp, gentypeinfo.el, gtk.defs: New files.
+
+ * gtkaccelerator.c, gtkaccelerator.h (gtk_accelerator_table_ref):
+ Return the table so that this function can be used as the `copy'
+ function for GTK_TYPE_BOXED values.
+ * gtkstyle.c, gtkstyle.h (gtk_style_ref): Likewise.
+
+ * gtkenums.h: Removed GtkArgType enum.
+
+ * gtkmain.c (gtk_init): Call gtk_type_init to initialize the type
+ system.
+
+ * gtkobject.c (gtk_object_init_type): New function to take over
+ for gtk_object_get_type. (gtk_object_get_type): Just return the
+ constant GTK_TYPE_OBJECT. (gtk_object_collect_args): Do the right
+ thing for the new GTK_TYPE_* types.
+ * gtksignal.c (gtk_params_get): Likewise.
+
+ * gtktypeutils.c: (gtk_type_init_builtin_types): New
+ function. (gtk_type_init): Call it. Also made non-static.
+ (gtk_type_unique): The allocation scheme for numerical ids has
+ changed: The low 8 bits hold the appropriate GtkFundamentalType of
+ a type, the rest is a globally unique sequence number.
+ (gtk_type_hash): Use the sequence number of a key to hash it.
+ (gtk_type_register_builtin): New function.
+
+ * gtktypeutils.h: (GtkFundamentalType): New enumeration of the
+ fundamental types. (GTK_TYPE_MAKE, GTK_FUNDAMENTAL_TYPE,
+ GTK_TYPE_SEQNO): New macros to work with the new id scheme.
+ (GtkArg): Added fields for new types and renamed old ones. GtkArg
+ should now be a mostly opaque structure, except name and type.
+ (GTK_VALUE_*): New macros to access the values of a GtkArg.
+ (GTK_RETLOC_*): New macros to access the location of a return
+ value that is contained in a GtkArg. * gtktypebuiltins.h: New
+ file to access the typeids of the builtin types.
+
+ * gtkwidget.h (GTK_TYPE_WIDGET): New macro to access the type id
+ of the widget class.
+
+ Thru out: Changed GTK_ARG_* to the appropriate GTK_TYPE_*.
+ Changed access to GtkArg structure to the appropriate GTK_VALUE_*
+ or GTK_RETLOC_* macro. Changed GtkArgType to GtkType. Changed
+ some guints to GtkType.
+
+ General changes in gtk/ to support interpreters:
+
+ * gtkradiobutton.c (gtk_radio_button_new_from_widget,
+ gtk_radio_button_new_with_label_from_widget): New functions.
+
+ * gtksignal.c (gtk_signal_connect_no_marshal): New function.
+ (struct _GtkHandler): Added no_marshal and destroy_func fields.
+ (gtk_signal_handler_new): Initialize them.
+ (gtk_signal_connect_by_type): Added no_marshal and destroy_func
+ arguments. Changed all callers.
+ (gtk_signal_destroy): Invoke destroy_func if there is one and the
+ global destroy func does not apply. (gtk_handlers_run): If the
+ handler has no_marshal set, call its function directly without
+ going thru the signal's marshaller.
+
+Wed Sep 3 09:56:22 1997 RHS Linux User <pmattis@bjork.inktomi.com>
+
+ * gtkrange.c: Changed the way the range control focus was drawn so
+ that the range control is drawn correctly when it does not have
+ the focus.
+
+Tue Sep 2 17:41:17 1997 RHS Linux User <pmattis@bjork.inktomi.com>
+
+ * gtkwidget.c: 'gtk_real_widget_queue_resize' should only remove
+ the "resize_widgets" if another resize is not pending.
+
+Mon Sep 1 18:28:08 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmain.c: Changed the way GDK_DELETE events are handled. Only,
+ if 'gtk_widget_event' returns TRUE is the widget destroyed. By
+ default, 'gtk_widget_event' will return FALSE causing the window
+ to not be destroyed. This prevents segfaults in the GIMP and other
+ programs that do not correctly handle GDK_DELETE events.
+
+ * gtkmain.c: Added modal dialog support by allowing events
+ destined for a child of the grab widget to go to the child instead
+ of the grab widget. (Added 'gtk_widget_is_ancestor' to determine
+ the relationship between the grab widget and the event widget).
+
+ * *.[ch]: Incorprated a whole mess of patches. (Started keeping
+ the ChangeLog up to date again).
+
+Thu Jun 5 17:22:21 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenufactory.c:
+ * gtkmenufactory.h: Added 'gtk_menu_factory_remove_*'
+ calls. Removing entries/paths causes the associated widgets to be
+ destroyed.
+
+ * gtkwidget.c:
+ * gtkwidget.h: Calling 'gtk_widget_set_style' is used as an
+ indication that the programmer specifically wants that style to be
+ used. RC-style substitution is disabled for the widget after such
+ a call.
+
+ * gtkpixmap.c:
+ * gtkpixmap.h:
+ * gtkimage.c:
+ * gtkimage.h: Changed to use clip mask and a single pixmap (or
+ image) to deal with transparent areas.
+
+ * gdkpixmap.c: Modified xpm loading routines to optionally return
+ a clip mask.
+
+ * gdkgc.c:
+ * gdkdraw.c:
+ * gdktypes.h: Modifications to allow clip masks to be used with
+ gc's. Clip masks are bitmaps that specify drawable regions.
+
+Thu May 1 03:11:51 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkscrolledwindow.c: Scrolled windows need to have the
+ GTK_NO_WINDOW flag set. Not having it set caused an obscure
+ redrawing bug.
+
+Wed Apr 30 12:38:03 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkhruler.c:
+ * gtkvruler.c: Fixed a small bug that caused the indicator to be
+ positioned slightly off.
+
+Sun Apr 27 14:28:21 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenushell.c:
+ * gtkmenushell.h:
+ * gtkmenu.c:
+ * gtkmenu.h: Changes so that if a menu is popped up there is a
+ timeout period during which a menu item will not be activated and
+ if the mouse button is released in that period the menu will stay
+ popped up.
+
+ * gtkcurve.c:
+ * gtkcurve.h: Included curve widget courtesy of David
+ Mosberger-Tang (davidm@azstarnet.com).
+
+ * gtkentry.c:
+ * gtkentry.h: Changed "insert" and "delete" signals to
+ "insert_text" and "delete_text" respectively. (The symbol "delete"
+ cannot be used since it is a C++ reserved word).
+
+Sat Apr 19 01:43:49 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenufactory.c: A path which ends in "<nothing>" will cause an
+ invisible (hidden) menu entry to be created. This is useful for
+ setting an accelerator key for which a corresponding menu entry is
+ not desired.
+
+ * gtktooltips.c: Fixed some problems with destruction of the
+ active tip widget not properly updating the tooltips data
+ structures.
+
+Fri Apr 18 15:09:45 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkcontainer.c:
+ * gtklist.c:
+ * gtkwidget.c:
+ * gtkwidget.h: Patch from Owen Taylor (owt1@cornell.edu) which
+ fixes problems with destruction of objects and with destruction of
+ objects which hold the focus.
+
+Thu Apr 17 11:29:15 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenushell.c: Incorrect logic in
+ 'gtk_menu_shell_button_release' for deciding when a menu should
+ stay popped up when the mouse button is released.
+
+ * *.c: Miscellaneous fixes from folks on the net.
+
+Tue Apr 15 02:43:17 1997 Peter Mattis <pmattis@localhost>
+
+ * *.c:
+ * gtkwidget.h: Added GTK_BASIC widget flag which when set
+ specifies a widget as "basic". A "basic" widget is one which
+ doesn't take input events. For example, labels, pixmaps, boxes,
+ tables, alignments, etc.
+
+Sat Apr 12 15:23:08 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkcolorsel.c: Add "#include <math.h>" to define M_PI.
+
+ * gtksignal.c: Fixed a bug in 'gtk_signal_emit' which showed up
+ because of the new cast checking macros. The 'object' was being
+ accessed after it had been destroyed.
+
+ * gtkoptionmenu.c: Fixed bug with using 'GTK_BIN' instead of
+ 'GTK_BUTTON' which showed up because of the new cast checking
+ macros.
+
+ * *.h: 'GTK_CHECK_CAST', 'GTK_CHECK_CLASS_CAST' and
+ 'GTK_CHECK_TYPE' used by standard widget macros everywhere.
+
+Wed Apr 9 00:54:17 1997 Peter Mattis <pmattis@localhost>
+
+ * docs/gtk.texi: Started further work on documentation. Major
+ changes and additions are being made.
+
+ * gtkarrow.c:
+ * gtkarrow.h: Removed function 'gtk_arrow_get'.
+
+ * gtkcontainer.c: 'gtk_container_check_resize' no performs
+ additional checking to account for the case where the containers
+ allocation is no longer sufficient because its parent (or its
+ parents parent, etc.) needs to resize its children.
+
+Tue Apr 8 21:15:50 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkstyle.c: Fixed a bug in 'gtk_style_init' in which the font
+ was not ref'd (via 'gdk_font_ref'), but was free'd (via in
+ 'gdk_font_free') in 'gtk_style_destroy'. (David
+ Mosberger-Tang). Also cleaned up 'gtk_style_destroy' while I was
+ at it.
+
+ * gtkmain.c: Fixed a bug in 'gtk_propogate_event' which caused
+ entry widgets (and probably other widgets) not to be destroyed in
+ some instances.
+
+Mon Apr 7 01:20:38 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkentry.c:
+ * gtkentry.h: Changed the "insert_text", "delete_text" and
+ "changed_text" signals to "insert", "delete", and "changed"
+ respectively. They really should have been named this way
+ originally except the previous signal mechanism prevented
+ duplicate signal names. ("changed" is also used by adjustments).
+
+ * gtkradiomenuitem.c:
+ * gtkradiomenuitem.h: New widget.
+
+ * gtkcheckmenuitem.c:
+ * gtkcheckmenuitem.h: New widget.
+
+ * gtksignal.c: Modified 'gtk_signal_lookup' to require an object
+ type to be passed as a parameter. In addition, signals are now
+ only needed to be uniquely defined in their branch of the class
+ hierarchy. This allows the same signal name to be used in two
+ different branches of the class hierarchy. For instance, the
+ "changed" signal is used both by adjustments and entries...in
+ different ways!
+
+ * gtktypeutils.c: Added 'gtk_type_parent' which returns the parent
+ type for a given type.
+
+Sun Apr 6 22:08:35 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwidget.c: If a widget is set insensitive it loses the focus
+ if it had it.
+
+ * gtkcontainer.c: Insensitive widgets no longer participate in tab
+ traversal.
+
+ * gtkscrolledwindow.c: The "viewport" child is now destroyed and a
+ container class "foreach" function was written (which fixes the
+ sensitivity bug).
+
+Sat Apr 5 14:25:38 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkhscrollbar.c:
+ * gtkvscrollbar.c: Fixed trough size allocation bug.
+
+ * gtkhscale.c:
+ * gtkvscale.c: Fixed trough size allocation and position bug that
+ showed up when scales were placed in notebooks.
+
+Thu Mar 27 17:45:54 1997 David Mosberger-Tang <davidm@azstarnet.com>
+
+ * gtk/gtkmain.c (gtk_handle_idle): Fix appending pending_idles to
+ idle_functions so it works even when idle_functions is empty.
+
+Sat Mar 15 14:15:59 1997 Peter Mattis <pmattis@localhost>
+
+ * *.[ch]: Moved '*_class_init' and '*_init' function declarations
+ for widgets into the source file as those functions no longer had
+ to be public.
+
+ * gtkcheckbutton.c: Fixed redrawing of check button.
+
+ * gtkframe.c: Fixed redrawing of frame when the shadow type is
+ changed.
+
+Sat Mar 8 15:19:23 1997 Peter Mattis <pmattis@localhost>
+
+ * gdkimage.c: Fixed a stupid bug with 'gdk_image_new' which
+ potentially added a NULL image to "image_list" and caused problems
+ when 'gdk_image_exit' was called.
+
+Wed Mar 5 00:40:08 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkpreview.c: Massively changed the colormap handling used by
+ the preview widget. Gray previews are now dithered. A single
+ visual and colormap is shared by the color and gray previews. A
+ GTK_PREVIEW_INFO property is installed on the root window in
+ certain cases to allow multiple GTK programs to share the system
+ colormap.
+
+Sun Mar 2 05:43:06 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkcheckbutton.c: 'gtk_checkbutton_size_allocate' was allocating
+ too much space to its children and not leaving the check button
+ room for the focus border.
+
+ * gtknotebook.c: 'gtk_notebook_size_request' wasn't requesting
+ enough space when the notebook tabs are visible.
+
+Sat Mar 1 01:59:35 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkpreview.c: Fixed a problem with 'gtk_preview_put' when the
+ image byte order is GDK_MSB_FIRST.
+
+ * gtksignal.c:
+ * gtksignal.h: Added 'gtk_signal_connect_after' and
+ 'gtk_signal_connect_object_after' functions. These connect signal
+ handlers which will run after the class function associated with
+ the signal.
+
+ * gtkstyle.c: Fixed a stupid bug in 'gtk_style_new_from_key' that
+ was causing twice as many styles to be created as necesary.
+
+ * gtkwidget.c: 'gtk_real_widget_size_allocate' erases the widgets
+ old allocation if it has the GTK_NO_WINDOW flag set.
+
+ * gtkwidget.c: 'gtk_real_widget_unmap' now erases the widget if it
+ has the GTK_NO_WINDOW flag set.
+
+ * gtklabel.c: Removed 'gtk_label_unmap' as similar functionality
+ was added to gtk_real_widget_unmap.
+
+ * gtkbin.c: Modified 'gtk_bin_map' and 'gtk_bin_unmap' so that it
+ erases and draws the widget if it has the GTK_NO_WINDOW flag set.
+
+ * gtkframe.c: Modified 'gtk_frame_size_allocate' so that it erases
+ the old allocation.
+
+Fri Feb 28 03:27:05 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwindow.c: 'gtk_window_set_title' now changes the window title
+ if the window is already realized.
+
+ * gtkentry.c: 'gtk_entry_set_text' was emitting both a
+ "delete_text" and a "changed_text" signal. Modified so that it
+ only emits a "changed_text" signal.
+
+ * gtkpreview.c: Modified to work correctly on systems with MSB
+ byte order. The colormap for TRUE and DIRECT color displays is now
+ created if the default visual is not equal to the visual we are
+ using.
+
+ * gtkstyle.c: 'gtk_style_attach' and 'gtk_style_find' weren't
+ working properly in the presence of multiple colormaps are
+ different depth visuals.
+
+ * gtkcontainer.c: Massively improved focus traversal using tab and
+ arrow keys. It now uses the layout of the widgets to determine
+ where to move the focus to.
+
+Mon Feb 24 03:24:02 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenufactory.c: Set the accelerator table field for menus when
+ they are created.
+
+ * gtkmenu.c:
+ * gtkmenu.h: Added a default accelerator table field to menus so
+ that runtime modification of accelerator keys in menus can work
+ better.
+
+ * gtkrange.c: 'gtk_range_default_{h,v}motion' had faulty logic for
+ deciding what to do when the slider was at the edge of the
+ trough. They previously didn't update the adjustment value event
+ if the value wasn't what it should be when the slider was at the
+ edge of the trough.
+
+ * gtkviewport.c: 'gtk_viewport_size_allocate' and
+ 'gtk_viewport_adjustment_value_changed' both had the potential for
+ performing a divide by 0. Checks are now in place to prevent this.
+
+ * gtkmenu.c: 'gtk_menu_map' now makes sure the menu lies on screen
+ if the position function is NULL.
+
+ * gtkentry.c: Modified selection handling. 'gtk_delete_selection'
+ actually removes the X selection now. 'gtk_entry_destroy' removes
+ the selection as well and relies on the change in "gdk.c" to make
+ sure the selection event will not be sent to a non-existant
+ window.
+
+ * gdk.c: Selection events are only passed on if the selection
+ owner is not NULL.
+
+ * gtkstyle.c: 'gtk_style_detach' and 'gtk_style_destroy' were not
+ destroying the black and white gc's.
+
+Sun Feb 23 19:17:56 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwindow.c: 'gtk_window_size_request' was setting the window
+ hints. This was also being done in 'gtk_window_map', so the
+ instance being done in 'gtk_window_size_request' was removed.
+
+Fri Feb 21 01:04:01 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwidget.c: 'gtk_widget_draw' has to use the widgets allocated
+ position for the drawing rectangle when the widget has the
+ GTK_NO_WINDOW flag set.
+
+ * gtkwidget.c: In 'gtk_widget_init' the visual and colormap were
+ being directly compared against 'default_visual' and
+ 'default_colormap' instead of calling
+ 'gtk_widget_get_default_{visual,colormap}'.
+
+ * gdkrectangle.c: Amazing! There was a bug in the
+ 'gtk_rectangle_intersect' logic. Its been there for near eternity
+ and I never noticed.
+
+ * gtkpreview.c:
+ * gtkpreview.h: Created preview widget which allows drawing to an
+ rgb or grayscale buffer which is automatically displayed on the
+ screen. Performs dithering as necessary.
+
+Thu Feb 20 20:33:21 1997 Peter Mattis <pmattis@localhost>
+
+ * gdkwindow.c: Modified the logic in 'gdk_window_new' which
+ determined when to add a window to the WM_COLORMAP_WINDOWS
+ property.
+
+Wed Feb 19 19:55:29 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkruler.c: 'gtk_ruler_make_pixmap' was always destroying the
+ old backing store and creating a new one even when it would create
+ a new one of exactly the same size as the old one.
+
+Tue Feb 18 18:32:10 1997 Peter Mattis <pmattis@localhost>
+
+ * gmem.c: 'g_mem_chunk_alloc' was incorrectly modifying the mem
+ areas free mem field when reallocating a previously freed
+ atom. This caused a fairly severe memory leak.
+
+ * gtkmenushell.c: 'gtk_menu_shell_button_release' had a bug in the
+ logic for deciding whether to initiate an X pointer grab or not
+ when the mouse button was released. It now only initiates a grab
+ if the mouse is released within an active menu item.
+
+Fri Feb 14 00:57:40 1997 Peter Mattis <pmattis@localhost>
+
+ * gtknotebook.c: Changed the look of notebook tabs slightly.
+
+ * gtkentry.c:
+ * gtkentry.h: Deleting an entry widget which is holding the X
+ selection presents some difficulties. The X selection must be
+ released, but the widget can't be destroyed until the
+ SELECTION_CLEAR event is received that the X server will send in
+ response to clearing the X selection. There are probably still
+ bugs in the current method of entry widget deletion when the X
+ selection is held.
+
+ * gtkmain.c: 'gtk_propagate_event' was not properly destroying the
+ toplevel window when receiving a key press event.
+
+ * gtkwidget.c: Setting a widget insensitive did not cause it to
+ redraw. It now does.
+
+Thu Feb 13 16:59:07 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkviewport.c: 'gtk_viewport_size_allocate' was allocating its
+ child widget an adjusted allocation. Since the actual scrolling
+ has handled by a subwindow this caused the child to be double
+ scrolled. Modified to always set the child allocations origin to
+ (0, 0).
+
+Wed Feb 12 01:06:48 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkentry.c: Text is now centered vertically. Previously it was
+ pushed up against the top. This problem was only evident when the
+ widget was allocated more vertical space than it requested.
+
+ * gtkfilesel.c: 'gtk_file_selection_key_press' was previously only
+ a stub for tab completion. The actual tab completion call had been
+ left out. (Oops!)
+
+Tue Feb 11 01:43:08 1997 Peter Mattis <pmattis@localhost>
+
+ * gtksignal.c: 'gtk_signal_disconnect_by_data' was going into a
+ loop and crashing. Bad logic. Fixed.
+
+ * gtkmain.c: An idle function which returns FALSE will be removed
+ from the list of idle functions. This makes the functioning of
+ idle functions and timeouts more similar.
+
+ * gtkentry.c: 'gtk_entry_get_text' now returns an empty string
+ when the actual text is NULL. This allows "stupid" programs to use
+ the value returned by 'gtk_entry_get_text' blindly (without
+ checking to see if its NULL).
+
+ * gtkradiobutton.c: Modified 'gtk_radio_button_clicked' so that
+ 'gtk_toggle_button_toggled' is called _after_ the widget state is
+ changed.
+
+ * gtksignal.c:
+ * gtksignal.h: Added 'gtk_signal_name' which returns the character
+ string name for a given signal number.
+
+ * gtkwidget.c: 'gtk_widget_set_parent' checks to see if the widget
+ is now "anchored" through the parent chain to a widget which is
+ GTK_ANCHORED. If it is, then it changes the widgets style using
+ 'gtk_rc_get_style' and recursively performs the same operation on
+ the widgets children. This is necessary is 'gtk_rc_get_style' only
+ works properly on "anchored" widgets.
+
+ * gtkwindow.c: Modified GTK_WIN_POS logic so that it is only used
+ immediately after the window has been shown.
+
+ * gtkmenu.c: 'gtk_menu_key_press'. Can now change menu item
+ accelerator keys on the fly. Why? Why not. Cool/useless feature of
+ the day.
+
+ * gtkmenuitem.c: Accelerator key drawing. Somehow that never got
+ finished. (Oops!)
+
+ * gtkdrawingarea.c: 'gtk_drawing_area_size_allocate' was not
+ actually installed during 'gtk_drawing_area_class_init'. (Oops!)
+
+ * gtkframe.c: 'gtk_frame_size_request' fixed size requisition
+ problem caused by unsigned arithmetic.
+
+ * gtkwindow.c: Modified window widget so that it only uses the
+ widget uposition auxiliary information immediately after it has
+ been shown. This prevents the annoying bug which can cause a
+ uposition'ed window to jump back to its original position after
+ the user moves it.
+
+ * gtkwidget.c: Need to ref and unref style in
+ 'gtk_widget_{push,pop}_style' to make sure that a style on the
+ style stack is not destroyed.
+
+ * gtktogglebutton.c: 'gtk_toggle_button_set_state' now calls
+ gtk_button_clicked to actually change the state of the
+ button. In this way, radio buttons can now perform the appropriate
+ actions when the toggle button state is set.
+
+Mon Feb 10 00:27:39 1997 Peter Mattis <pmattis@localhost>
+
+ * gtklist.c: 'gtk_list_select_item' and 'gtk_list_unselect_item'
+ were casting a GList* variable to a a GtkWidget* variable. Bad bad
+ bad. (Tim Janik).
+
+ * gtksignal.c: Modified 'gtk_signal_connect' and
+ 'gtk_signal_connect_object' to warn when a signal type cannot be
+ found.
+
+Sun Feb 9 00:15:30 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkoptionmenu.c:
+ * gtkoptionmenu.h: Changed option menus back to being derived from
+ buttons. This fixes up some screwiness with their user
+ interaction.
+
+ * gtkwindow.c: Modified key press handler to support focus
+ traversal.
+
+ * gtkcontainer.c:
+ * gtkcontainer.h: Added default focus traversal back in.
+
+Sat Feb 8 10:44:38 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkviewport.h:
+ * gtkviewport.c: Massively sped up viewport scrolling. Used to be
+ reallocating child's size (offset) each time a scrollbar
+ moved. Now a subwindow is moved. All the children are moved
+ automatically by moving the subwindow. Much much much faster.
+
+Tue Feb 4 00:20:44 1997 Peter Mattis <pmattis@localhost>
+
+ * gtree.c: Changed 'g_tree_node_search' to use a loop instead of
+ recursion.
+
+Mon Feb 3 11:30:03 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkbutton.c: Removed 'parent_destroy' global and replaced it
+ with 'parent_class' global to reflect style used in other
+ widgets.
+
+ * gtknotebook.c: Tab labels were being allocated less than their
+ requested size.
+
+ * gtkrange.c:
+ * gtkrange.h: Moved the "digits" field of scales into the range
+ type. The adjustment value for scales is truncated to the number
+ of visible digits instead of being left untouched.
+
+ * gtree.c: Fixed a bug in the AVL tree implementation. Single
+ rotations were always being performed during insertion. It is
+ sometimes necessary to perform a double rotation.
+
+ * gtklabel.c: Modified 'gtk_label_expose' to only draw the label
+ when the allocated space is greater than or equal to the requested
+ space.
+
+ * gtklabel.c: Added call to 'gtk_widget_unmap' to
+ 'gtk_label_destroy' in order for the label to redraw correctly
+ (erase itself) when destroyed.
+
+ * gtklabel.c: Added 'gtk_label_unmap' call which erases the labels
+ allocation when it gets unmapped.
+
+ * *.h: Removed a few remaining instances of using "class" as a
+ parameter name. (Causes problems for C++).
+
+Fri Jan 31 12:26:50 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkcontainer.c: 'gtk_container_enable_resize' needs to call
+ 'gtk_container_check_resize' instead of
+ 'gtk_container_need_resize'.
+
+ * gtkwidget.c: 'gtk_real_widget_show' now maps the widget if its
+ parent is mapped.
+
+ * gtkscrolledwindow.c: Fixed size allocation when the scrollbar
+ policy's are GTK_POLICY_AUTOMATIC. Doing it correctly is harder
+ than I originally thought.
+
+ * gtklist.c: Added 'gtk_list_child_position' to determine the
+ integer position in a list of a child. Filled in the
+ 'gtk_list_item_select' and 'gtk_list_item_unselect' stubs.
+
+Thu Jan 30 16:08:06 1997 Peter Mattis <pmattis@localhost>
+
+ * gmem.c: Changed the implementation of G_ALLOC_AND_FREE mem
+ chunks. They used to allocate SIZEOF_VOID_P extra bytes per atom
+ in order to keep track of which mem area they were allocated
+ from. Now the mem area is determined by searching through an AVL
+ tree of the mem areas for a mem chunk and comparing memory
+ locations. A little slower, but makes G_ALLOC_AND_FREE mem chunks
+ much more attractive.
+
+ * gtree.c: Added an AVL tree implementation to glib.
+
+ * gtksignal.c:
+ * gstring.c: va_arg (arg_list, {char, short}) is
+ invalid. Arguments passed in a variable argument list are
+ promoted. ({char, short}->int). Seemed to work ok before under
+ Linux. Crashed under FreeBSD.
+
+Tue Jan 28 02:27:51 1997 Peter Mattis <pmattis@localhost>
+
+ * gdkwindow.c: Fixed a major slowdown apparent in the file
+ selection dialog which was caused by calling
+ 'gtk_window_add_colormap_windows' way way way too often.
+
+ * *.c: Many widgets called 'gtk_container_need_resize' when
+ something internal changed which would cause the widget to grow or
+ shrink. The assumption was made that the widget would change size
+ and an expose event would be generated. This happens "most" of the
+ time. But its possible for certain widgets to change size without
+ generating expose events, or for its internal geometry to change
+ without a change of size which would mean no expose event was
+ generated. So a wrapper function called
+ 'gtk_container_check_resize' was created and
+ 'gtk_container_need_resize' was modified so that it returns FALSE
+ if a resize was actually generated and TRUE if nothing
+ changed. This allows 'gtk_container_check_resize' to initiate a
+ 'gtk_widget_size_allocate' and 'gtk_widget_draw' to emulate the
+ expose event.
+
+Sat Jan 25 14:17:44 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmain.c: Fixed a bug with propogating key press events. The
+ events were sent 2 times to the toplevel windows which caused the
+ focus widget to be activated twice when the space bar was pressed.
+
+ * */configure.in:
+ * */Makefile.am: Added support for libtool and removed the old
+ shared library configuration craziness.
+
+Fri Jan 24 12:59:22 1997 Peter Mattis <pmattis@localhost>
+
+ * gtktext.c:
+ * gtktext.h: Josh's fixes and additions to the text widget.
+
+ * gtkfill.c:
+ * gtkfill.h: Filler widget useful for filling space in a
+ table. Can specify a minimum size. Used by the canvas widget.
+
+ * gtknotebook.c:
+ * gtknotebook.h: Made outline of notebook widget.
+
+ * gtkcanvas.c:
+ * gtkcanvas.h: Started canvas widget. A composite of 2 rulers (w/
+ an origin), 2 scrolllbars. Guides, grids, snap to.
+
+Sun Jan 19 18:26:45 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkdialog.c:
+ * gtkdialog.h: Created dialog widget which creates a standard
+ looking dialog with buttons along the button and a separator.
+
+ * gtkxid.c: Generalized the window table code for looking up a gdk
+ window based on an XID to work for any XID and a piece of
+ data. Can now look up gdk fonts based on their XID.
+
+ * gtkruler.c:
+ * gtkruler.h:
+ * gtkhruler.c:
+ * gtkhruler.h:
+ * gtkvruler.c:
+ * gtkvruler.h: Started conversion of the ruler widget.
+
+ * gtktext.c:
+ * gtktext.h: Started conversion of the text widget. Scrolling
+ doesn't work.
+
+ * gtkmain.c: Fixed a fairly major bug. The event widget needs to
+ be in a call for the entire duration of handling an event. Not
+ just for when the event widget itself is handling the event.
+
+ * gtkfilesel.c: Fixed up some bugs with resizing.
+
+Fri Jan 10 14:18:03 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwidget.c:
+ * gtkwidget.h:
+ * gtkentry.c:
+ * gtkentry.h: Support for selections.
+
+ * gdkselection.c:
+ * gdk.c:
+ * gdktypes.h:
+ * gdk.h: Gdk support for X selections. Currently only text
+ selections are supported.
+
+ * gtksignal.c: Fixed a major bug which occurred when destroying an
+ object. Memory was being written to after it was freed.
+
+ * gtkfilesel.c:
+ * gtkfilesel.h: Hooked up more functionality to the file selection
+ dialog.
+
+Wed Jan 8 18:13:53 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkfilesel.c:
+ * gtkfilesel.h: Mostly converted old file selection dialog
+ widget. The widget is derived from the GtkWindow class and is
+ quite a bit simpler in the widget code.
+
+ * gtkwidget.c: Fixed 'gtk_widget_grab_focus' and
+ 'gtk_widget_grab_default' to check that the toplevel widget is a
+ type of window (which includes classes derived from windows).
+
+Tue Jan 7 01:12:32 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwindow.c: Was calling 'gtk_window_resize' twice in a
+ row...why?
+
+ * gtksignal.c:
+ * gtksignal.h:
+ * *.c: Changed 'gtk_signal_new' so that the class function that is
+ called when the signal is emitted can be called either before,
+ after or both before and after the calling of any signal
+ handlers.
+
+ * gtkobject.c:
+ * gtkobject.h: Added 'object_data' mechanism for storing data
+ associated with a character string key in objects. Removed
+ 'user_data' field of objects and changed
+ 'gtk_object_{get,set}_user_data' to use the object data
+ mechanism. Removed 'handlers' field of objects.
+
+ * gtkwidget.c:
+ * gtkwidget.h:
+ * gtkwindow.c: Modified aux info mechanism to use object data
+ mechanism.
+
+ * gtksignal.c: Modified signal mechanism to use object data
+ mechanism instead of 'handlers' field.
+
+
+Mon Jan 6 15:10:16 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenushell.c: Fixed up button press handling so as to conform
+ more closely to that used by Motif.
+
+Wed Jan 1 21:27:17 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenu.c:
+ * gtkmenu.h:
+ * gtkmenubar.c:
+ * gtkmenubar.h:
+ * gtkmenushell.c:
+ * gtkmenushell.h: Reorganization of menu-ing code so that code
+ duplication is reduced. The menu shell now contains most of the
+ code for menu-ing interaction while menus and menubars simply layout
+ their child menu items in the appropriate place.
+
+Sun Dec 29 17:48:18 1996 Peter Mattis <pmattis@localhost>
+
+ * gtkmenu.c:
+ * gtkmenubar.c:
+ * gtkmenuitem.h:
+ * gtkmenuitem.c: Modifications so that menu item accelerators and
+ the submenu indicator are drawn correctly and the correct amount
+ of space is allocated.
+
+Sat Dec 28 00:32:13 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * gtkmenufactory.h:
+ * gtkmenufactory.c: Started menu factories as an easy method to
+ create and manipulate menus.
+
+Fri Dec 27 13:17:34 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * gtkmenu.c:
+ * gtkmenu.h:
+ * gtkmenubar.c:
+ * gtkmenubar.h:
+ * gtkmenuitem.c:
+ * gtkmenuitem.h:
+ * gtkmenushell.c:
+ * gtkmenushell.h: Implemented basic menu functionality. Menubars
+ and popup menus work. Submenus work. (Much left to be done).
+
+Wed Dec 18 15:27:05 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * gtktypeutils.h:
+ * gtktypeutils.c: Added 'gtk_type_from_name' which returns a type
+ identifier given a type name. Implemented using a second hash
+ table keyed by type names.
+
+ * gtkbutton.c:
+ * gtktogglebutton.c: Fixed very small messed-up drawing bug when a
+ button loses its focus.
+
+ * gtkwidget.h:
+ * gtkwidget.c:
+ * gtkbutton.c:
+ * gtkwindow.c: Added default button handling. Default buttons now
+ draw correctly and pressing return or enter causes the default
+ button (if one exists) to be activated.
+
+Tue Dec 17 19:32:21 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * gtkhscale.c:
+ * gtkvscale.c: Overrode 'draw_slider' method of ranges in order to
+ draw the slider of scales with a line in them so as to be closer
+ to the Motif look-and-feel.
+
+ * gtkwindow.c: Modified 'gtk_window_focus_in_event' so that focus
+ in events are only handled when the window is visible. Fixes a bug
+ where spurious focus in events get sent when a window is being
+ hidden.
+
+ * gtkwidget.h: Added 'activate_signal' field to the GtkWidgetClass
+ structure. Added 'gtk_widget_activate' call to emit the activate
+ signal for a widget if it is non-zero.
+
+Tue Dec 10 15:59:45 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * gtkwidget.c: 'gtk_widget_set_name' oops in strdup'ing the old
+ "widget->name" instead of the new one we are setting.
+
+ * gtkrc.c: 'gtk_rc_widget_path' changed to use
+ 'gtk_widget_get_name' instead of accessing the "widget->name"
+ field directly.
+
+ * gtkwidget.c: Added 'gtk_widget_get_name' function which returns
+ the widgets name if it exists and the widgets type name if it does
+ not.
+
+ * gtkcheckbutton.c: Added 'gtk_check_button_draw'
+ function. Modified 'gtk_check_button_expose' to pass an expose
+ event to child instead of callings its draw function.
+
+ * gtkentry.c: 'gtk_entry_draw_text' why was "+1" being added to
+ the font->ascent to calculate the font position? This was wrong
+ and caused some characters in fonts to be clipped. (Notably "g").
+
+ * gtkentry.c: 'gtk_entry_realize' specify GTK_BUTTON1_MOTION_MASK
+ and GTK_POINTER_MOTION_HINT_MASK for _both_ windows.
+
+ * gtkmain.c: 'gtk_propagate_event' needs to set the GTK_IN_CALL
+ flag for the object before calling 'gtk_widget_event' and needs to
+ destroy the object if necessary after 'gtk_widget_event' returns.
+
+ * gtkradiobutton.c: 'gtk_radio_button_clicked' needs to call
+ 'gtk_toggle_button_toggled' when the currently active button is
+ toggled.
+
+ * gtkwidget.c: 'gtk_real_widget_hide' needs to call
+ 'gtk_widget_unmap' if the widget is currently mapped.
+
+ * gtkwindow.c: Prevent automatic resizing after the user has
+ specified a new window size. Add 'handling_resize' flag to
+ windows.
+
+ * gtkscrolledwindow.c: Implement the GTK_POLICY_AUTOMATIC
+ scrollbar policy. Need to connect to the adjustments 'changed'
+ signal and notice when the scrollbars aren't in use.
+
+ * gtkcontainer.c: 'gtk_container_init' must set 'auto_resize' and
+ 'need_resize' fields to TRUE and FALSE respectively.
+
+ * gtkwidget.c: 'gtk_widget_set_parent' must all set a widgets state
+ to its parents state.
+
+Sun Dec 1 01:31:01 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * Started ChangeLog
diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4
new file mode 100644
index 000000000..a065ebef5
--- /dev/null
+++ b/ChangeLog.pre-2-4
@@ -0,0 +1,1140 @@
+Mon Nov 17 1997 Jay Painter <jpaint@serv.net>
+ * gtkviewport.c: Raph's Mon, 10 Nov 1997 patch to gtk-list
+ to fix some viewport bugs
+
+Mon Nov 17 1997 Jay Painter <jpaint@serv.net>
+ * gtk/gtkwidget.c: gtk-ajaborsk-971016-2
+ A little patch again to prevent user to use gtk_widget_set_events()
+ when a widget is already realized.
+ In this case, the gtk_widget_set_events() doesn't work.
+
+Mon Nov 17 1997 Jay Painter <jpaint@serv.net>
+ * gtk/gtkwindow.c: gtk-ajaborsk-971016-1
+ This small patch correct position for GTK_WIN_POS_CENTER and
+ GTK_WIN_POS_MOUSE GtkWindow positions.
+
+Sat Nov 15 1997 Jay Painter <jpaint@serv.net>
+ * gdk/gdkgc.c: added function gdk_gc_set_clip_rectangle
+ * gdk/gdk.h: header for above
+
+Sat Nov 15 1997 Jay Painter <jpaint@serv.net>
+ * gdk/gdkgc.c: added function gdk_gc_set_clip_rectangle
+ * gdk/gdk.h: header for above
+
+Wed Nov 12 1997 Jay Painter <jpaint@serv.net>
+ * gdk/gdkpixmap.c: Patrice Fortier's patch for transparent pixmaps.
+ * gdk/gdk.h:
+ gdk/gdkdraw.c: Patrice Fortier's patch to add pixel draw function.
+
+Sun Nov 9 1997 Jay Painter <jpaint@serv.net>
+ * Fixed problems with makefiles relating to the bug
+ which required glib to be installed.
+ * Fixed makefiles to incluce the xpm's in gtk+/gtk needed
+ for testgtk.
+ * Updated gtk+ and gtk+/glib to libtool-1.0f
+
+Fri Nov 7 1997 Jay Painter <jpaint@serv.net>
+ * gtk/gtktext.c: return char_widths[ch & 0xff]; in line 2152
+
+Thr Nov 5 1997 Jay Painter <jpaint@serv.net>
+ * gtk/testgtk.c: added drag and drop test, removed the test hack
+ from the button test
+
+Tue Nov 4 08:28:57 1997 Federico Mena <federico@bananoid.nuclecu.unam.mx>
+
+ * gtk/gtkmain.c (gtk_handle_idle): Patch from David Mosberger to
+ avoid crashes when handling idle function (this manifested itself
+ in the Umax and Microtek backends in SANE.
+
+Sun Nov 2 07:34:56 1997 Tim Janik <timj@psynet.net>
+
+ * gtk/gtkfilesel.c: Small fixes about a segmentation viaolation
+ cause by a double click in the directoy list (introduced by my
+ previous changes).
+
+ * gtk/gtklist.c: Small fixes to gtk_list_add() and gtk_list_remove().
+
+ * gtk/testgtk.c (list_add): Applied Stefan Wille's patch to make this
+ function do something ;).
+
+Fri Oct 31 Jay Painter <jpaint@serv.net>
+ *gdk/gdk.c: reformatted DND code for GTK coding standards
+ *gdk/gdkwindow.c: changed memory allocation for DND to q_mem stuff
+
+Thu Oct 30 Jay Painter <jpaint@serv.net>
+ * gdk/gdkwindow.c:
+ * gdk/gdk/gdk.h:
+ * gtk/gtkwidget.h:
+ * gtk/gtkwidget.c: Applied Stephan Willie's shaped window patch
+
+ * gdk/gdkwindow:
+ * gdk/gdk.h:
+ * gtk/gtkwidget.h:
+ * gtk/gtkwidget.c: reformatted the DND code to conform to GTK
+ coding standards
+
+ * gtk/testgtk: massive fixes, SW's shaped window example
+
+Thu Oct 30 07:33:27 1997 Tim Janik <timj@psynet.net>
+
+ * gtk/gtklistitem.c (gtk_real_list_item_toggle): applied Johannes
+ Keukelaar's <johannes@nada.kth.se> patch for keyboard support in
+ GtkList widgets.
+
+ * gtk/gtkfilesel.c: adapted dir and file list selection
+ behaviour to deal with keyboard selections. this is a little
+ bit tricky: in the dir list it just changes the entrys value on a one
+ button press. but on a keyboard selection via gtk_widget_activate() it
+ does a new population (likewise on a double click) as this seems more
+ obvious.
+
+1997-10-25 Marius Vollmer <mvo@zagadka.ping.de>
+
+ * gdk/gdkcolor.c (gdk_colormap_get_system): Initialize
+ private->ref_count.
+
+Wed Oct 22 09:47:43 1997 Tim Janik <timj@psynet.net>
+
+ * gtk/gtkwindow.c (gtk_window_key_release_event): Fixed a stupid
+ bug that caused the key_release_event to be propagated twice.
+
+Sun Oct 12 11:01:43 1997 Tim Janik <timj@psynet.net>
+
+ * acconfig.h:
+ * configure.in:
+ * gdk/gdkimage.c: Added configure check for IPC_RMID_DEFERRED_RELEASE,
+ because shmat() fails after a shmctl(..., IPC_RMID,...) for OSF1 V3.2,
+ SunOS 4.1.1, 5.5, 5.5.1, 5.6, IRIX 5.2 and 6.2.
+
+Mon Oct 6 11:59:07 1997 Federico Mena <federico@bananoid.nuclecu.unam.mx>
+
+ * gdk/gdk.c (gdk_event_translate): In line 1693, fixed typo that
+ would cause motion notify events not to be delivered.
+
+Sun Oct 5 18:15:06 1997 Federico Mena <federico@bananoid.nuclecu.unam.mx>
+
+ * gtk/gtkrc.c (gtk_rc_parse_bg_pixmap): Changed strdup() for
+ g_strdup().
+
+Wed Sep 24 17:16:34 1997 Peter Mattis <pmattis@bjork.inktomi.com>
+
+ * configure.in: Fixed a stupid error in the test for libXext that
+ would cause it to fail if X_EXTRA_LIBS was not empty.
+
+ * gtk/gtkmain.h (gtk-timj-970919.patch):
+ * gtk/gtkmain.c (gtk-timj-970919.patch): new function
+ `gtk_idle_remove_by_data' to remove all idle callbacks that take a
+ specific piece of data as argument. (gtk_get_current_event):
+ remove idles through gtk_idle_remove_by_data.
+
+ * gtk/gtkwidget.c (gtk-timj-970919.patch):
+ (gtk_widget_destroy): remove pending idles for
+ widgets that have GTK_REDRAW_PENDING or GTK_RESIZE_PENDING and
+ GTK_ANCHORED set (only anchored widgets can have a resize queue
+ handler pending). widgets that have GTK_RESIZE_NEEDED will be removed
+ from their anchored toplevels `resize_widgets' list.
+
+ (gtk_widget_queue_draw): let the widget remember the queue handler
+ tag (through `redraw_handler_key') for later call to `gtk_idle_remove'.
+
+ (gtk_widget_queue_resize): let the widget remember the queue handler
+ tag (through `resize_handler_key') for later call to `gtk_idle_remove'.
+ corrected referencing the toplevel widget for which the handler is
+ pending. if a widget is added to the `resize_widgets' list of a
+ toplevel widget, GTK_RESIZE_NEEDED is set and it's referenced.
+
+ (gtk_real_widget_queue_resize): on the deletion of the `resize_widgets'
+ list, unset GTK_RESIZE_NEEDED and unreference the removed widgets.
+
+ * gtk/gtkwindow.c (gtk-timj-970919.patch):
+ (gtk_real_window_move_resize): move `resize_containers = NULL'
+ initialization out of if-statement.
+ while stepping through the `resize_widgets' list, unreference the
+ widgets and clear GTK_RESIZE_NEEDED. if a widget realy needs are
+ resize, they are flagged through GTK_RESIZE_NEEDED now (instead of
+ GTK_RESIZE_PENDING, as this is indicative for a pending handler).
+ added checks to provide segfaulting if a widgets parent pointer
+ is NULL (e.g. on toplevel widgets that have GTK_RESIZE_NEEDED set).
+
+Tue Sep 23 13:23:27 1997 Federico Mena <federico@bananoid.nuclecu.unam.mx>
+
+ * gdk/gdkimage.c: Applied Tim Janik's patch to mark shm segments
+ as IPC_RMID so that they are automatically removed always.
+
+ * gdk/gdkfont.c: Removed casts from lvalues.
+
+ * gtk/gtkmain.c: Removed GTK_RETLOC_*() (which do a cast) from lvalues.
+
+ * gtk/gtkaccelerator.c (gtk_accelerator_table_remove): Added
+ "const" to the accelerator_key param to be consistent with the
+ declaration in gtkaccelerator.h. The const is not useful in this
+ case, anyway.
+
+Tue Sep 16 13:11:06 1997 Peter Mattis <pmattis@bjork.inktomi.com>
+
+ * gtkpreview.c: Andrew Logan Kieschnick's change to eliminate
+ round-off error when gamma is set to 1.0.
+
+ * gtkrange.c:
+ * gtkviewport.c: Jay Painter's changes to modify the way in which
+ viewports resize.
+
+ * gdkinput.c:
+ * gdkinputgxi.h:
+ * gdkinputxfree.h:
+ * gtk/Makefile.am:
+ * gtk.h:
+ * gtkeventbox.c:
+ * gtkeventbox.h: Owen Taylor's event box widget and fixes for X
+ input support (that I had broken).
+
+ * gdk.h:
+ * gdkwindow.c:
+ * gtksignal.h:
+ * gtksignal.c: Elliot Lee's changes to support Objective C. (id is
+ apparently a reserved word in Objective C).
+
+Sun Sep 14 22:33:15 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwidget.c (gtk_widget_queue_resize): If the toplevel container
+ is invisible we simply call "gtk_container_need_resize" on
+ it. This fixes a bug with option menus not redrawing correctly.
+
+ * gtkmenuitem.c (gtk_menu_item_enter): (gtk_menu_item_leave):
+ These functions now simply pass the event on to their parent. This
+ is necessary for menus to work properly due to the change in how
+ grabs are dealts with.
+
+ * gtkwindow.c (gtk_real_window_move_resize): Fixed a bug that
+ caused the GTK_RESIZE_PENDING flag to not be unset in some cases.
+
+Fri Sep 5 20:49:37 1997 Marius Vollmer <mvo@zagadka.ping.de>
+
+ Bug fixes:
+
+ * Makefile.am: Added PATCHES to EXTRA_DIST.
+ * gtk/gtkpixmap.c (gtk_pixmap_new): Move the "pixmap != NULL" test
+ after the allocation of the pixmap.
+
+ To shut up the compiler:
+
+ * gtk/gtkfilesel.c (get_pwdb): Initialize home_dir.
+ * gtk/gtkmain.c (gtk_init): Replace comments around calls to
+ g_set_*_handler with "if (0)".
+ * gtk/gtkrc.c (gtk_rc_get_token): Initialize hex_number and
+ float_number.
+ * gtk/gtkwindow.c (gtk_window_key_press_event): Initialize
+ direction.
+
+ Changes to the type system in gtk/:
+
+ * Makefile.am: Added gtktypebuiltins.h to gtkinclude_HEADERS.
+ Added gtk.defs, runelisp, gentypeinfo.el and gtktypebuiltins.c to
+ EXTRA_DIST. Added rules to generate gtktypebuiltins.* from
+ gtk.defs.
+
+ * runelisp, gentypeinfo.el, gtk.defs: New files.
+
+ * gtkaccelerator.c, gtkaccelerator.h (gtk_accelerator_table_ref):
+ Return the table so that this function can be used as the `copy'
+ function for GTK_TYPE_BOXED values.
+ * gtkstyle.c, gtkstyle.h (gtk_style_ref): Likewise.
+
+ * gtkenums.h: Removed GtkArgType enum.
+
+ * gtkmain.c (gtk_init): Call gtk_type_init to initialize the type
+ system.
+
+ * gtkobject.c (gtk_object_init_type): New function to take over
+ for gtk_object_get_type. (gtk_object_get_type): Just return the
+ constant GTK_TYPE_OBJECT. (gtk_object_collect_args): Do the right
+ thing for the new GTK_TYPE_* types.
+ * gtksignal.c (gtk_params_get): Likewise.
+
+ * gtktypeutils.c: (gtk_type_init_builtin_types): New
+ function. (gtk_type_init): Call it. Also made non-static.
+ (gtk_type_unique): The allocation scheme for numerical ids has
+ changed: The low 8 bits hold the appropriate GtkFundamentalType of
+ a type, the rest is a globally unique sequence number.
+ (gtk_type_hash): Use the sequence number of a key to hash it.
+ (gtk_type_register_builtin): New function.
+
+ * gtktypeutils.h: (GtkFundamentalType): New enumeration of the
+ fundamental types. (GTK_TYPE_MAKE, GTK_FUNDAMENTAL_TYPE,
+ GTK_TYPE_SEQNO): New macros to work with the new id scheme.
+ (GtkArg): Added fields for new types and renamed old ones. GtkArg
+ should now be a mostly opaque structure, except name and type.
+ (GTK_VALUE_*): New macros to access the values of a GtkArg.
+ (GTK_RETLOC_*): New macros to access the location of a return
+ value that is contained in a GtkArg. * gtktypebuiltins.h: New
+ file to access the typeids of the builtin types.
+
+ * gtkwidget.h (GTK_TYPE_WIDGET): New macro to access the type id
+ of the widget class.
+
+ Thru out: Changed GTK_ARG_* to the appropriate GTK_TYPE_*.
+ Changed access to GtkArg structure to the appropriate GTK_VALUE_*
+ or GTK_RETLOC_* macro. Changed GtkArgType to GtkType. Changed
+ some guints to GtkType.
+
+ General changes in gtk/ to support interpreters:
+
+ * gtkradiobutton.c (gtk_radio_button_new_from_widget,
+ gtk_radio_button_new_with_label_from_widget): New functions.
+
+ * gtksignal.c (gtk_signal_connect_no_marshal): New function.
+ (struct _GtkHandler): Added no_marshal and destroy_func fields.
+ (gtk_signal_handler_new): Initialize them.
+ (gtk_signal_connect_by_type): Added no_marshal and destroy_func
+ arguments. Changed all callers.
+ (gtk_signal_destroy): Invoke destroy_func if there is one and the
+ global destroy func does not apply. (gtk_handlers_run): If the
+ handler has no_marshal set, call its function directly without
+ going thru the signal's marshaller.
+
+Wed Sep 3 09:56:22 1997 RHS Linux User <pmattis@bjork.inktomi.com>
+
+ * gtkrange.c: Changed the way the range control focus was drawn so
+ that the range control is drawn correctly when it does not have
+ the focus.
+
+Tue Sep 2 17:41:17 1997 RHS Linux User <pmattis@bjork.inktomi.com>
+
+ * gtkwidget.c: 'gtk_real_widget_queue_resize' should only remove
+ the "resize_widgets" if another resize is not pending.
+
+Mon Sep 1 18:28:08 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmain.c: Changed the way GDK_DELETE events are handled. Only,
+ if 'gtk_widget_event' returns TRUE is the widget destroyed. By
+ default, 'gtk_widget_event' will return FALSE causing the window
+ to not be destroyed. This prevents segfaults in the GIMP and other
+ programs that do not correctly handle GDK_DELETE events.
+
+ * gtkmain.c: Added modal dialog support by allowing events
+ destined for a child of the grab widget to go to the child instead
+ of the grab widget. (Added 'gtk_widget_is_ancestor' to determine
+ the relationship between the grab widget and the event widget).
+
+ * *.[ch]: Incorprated a whole mess of patches. (Started keeping
+ the ChangeLog up to date again).
+
+Thu Jun 5 17:22:21 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenufactory.c:
+ * gtkmenufactory.h: Added 'gtk_menu_factory_remove_*'
+ calls. Removing entries/paths causes the associated widgets to be
+ destroyed.
+
+ * gtkwidget.c:
+ * gtkwidget.h: Calling 'gtk_widget_set_style' is used as an
+ indication that the programmer specifically wants that style to be
+ used. RC-style substitution is disabled for the widget after such
+ a call.
+
+ * gtkpixmap.c:
+ * gtkpixmap.h:
+ * gtkimage.c:
+ * gtkimage.h: Changed to use clip mask and a single pixmap (or
+ image) to deal with transparent areas.
+
+ * gdkpixmap.c: Modified xpm loading routines to optionally return
+ a clip mask.
+
+ * gdkgc.c:
+ * gdkdraw.c:
+ * gdktypes.h: Modifications to allow clip masks to be used with
+ gc's. Clip masks are bitmaps that specify drawable regions.
+
+Thu May 1 03:11:51 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkscrolledwindow.c: Scrolled windows need to have the
+ GTK_NO_WINDOW flag set. Not having it set caused an obscure
+ redrawing bug.
+
+Wed Apr 30 12:38:03 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkhruler.c:
+ * gtkvruler.c: Fixed a small bug that caused the indicator to be
+ positioned slightly off.
+
+Sun Apr 27 14:28:21 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenushell.c:
+ * gtkmenushell.h:
+ * gtkmenu.c:
+ * gtkmenu.h: Changes so that if a menu is popped up there is a
+ timeout period during which a menu item will not be activated and
+ if the mouse button is released in that period the menu will stay
+ popped up.
+
+ * gtkcurve.c:
+ * gtkcurve.h: Included curve widget courtesy of David
+ Mosberger-Tang (davidm@azstarnet.com).
+
+ * gtkentry.c:
+ * gtkentry.h: Changed "insert" and "delete" signals to
+ "insert_text" and "delete_text" respectively. (The symbol "delete"
+ cannot be used since it is a C++ reserved word).
+
+Sat Apr 19 01:43:49 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenufactory.c: A path which ends in "<nothing>" will cause an
+ invisible (hidden) menu entry to be created. This is useful for
+ setting an accelerator key for which a corresponding menu entry is
+ not desired.
+
+ * gtktooltips.c: Fixed some problems with destruction of the
+ active tip widget not properly updating the tooltips data
+ structures.
+
+Fri Apr 18 15:09:45 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkcontainer.c:
+ * gtklist.c:
+ * gtkwidget.c:
+ * gtkwidget.h: Patch from Owen Taylor (owt1@cornell.edu) which
+ fixes problems with destruction of objects and with destruction of
+ objects which hold the focus.
+
+Thu Apr 17 11:29:15 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenushell.c: Incorrect logic in
+ 'gtk_menu_shell_button_release' for deciding when a menu should
+ stay popped up when the mouse button is released.
+
+ * *.c: Miscellaneous fixes from folks on the net.
+
+Tue Apr 15 02:43:17 1997 Peter Mattis <pmattis@localhost>
+
+ * *.c:
+ * gtkwidget.h: Added GTK_BASIC widget flag which when set
+ specifies a widget as "basic". A "basic" widget is one which
+ doesn't take input events. For example, labels, pixmaps, boxes,
+ tables, alignments, etc.
+
+Sat Apr 12 15:23:08 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkcolorsel.c: Add "#include <math.h>" to define M_PI.
+
+ * gtksignal.c: Fixed a bug in 'gtk_signal_emit' which showed up
+ because of the new cast checking macros. The 'object' was being
+ accessed after it had been destroyed.
+
+ * gtkoptionmenu.c: Fixed bug with using 'GTK_BIN' instead of
+ 'GTK_BUTTON' which showed up because of the new cast checking
+ macros.
+
+ * *.h: 'GTK_CHECK_CAST', 'GTK_CHECK_CLASS_CAST' and
+ 'GTK_CHECK_TYPE' used by standard widget macros everywhere.
+
+Wed Apr 9 00:54:17 1997 Peter Mattis <pmattis@localhost>
+
+ * docs/gtk.texi: Started further work on documentation. Major
+ changes and additions are being made.
+
+ * gtkarrow.c:
+ * gtkarrow.h: Removed function 'gtk_arrow_get'.
+
+ * gtkcontainer.c: 'gtk_container_check_resize' no performs
+ additional checking to account for the case where the containers
+ allocation is no longer sufficient because its parent (or its
+ parents parent, etc.) needs to resize its children.
+
+Tue Apr 8 21:15:50 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkstyle.c: Fixed a bug in 'gtk_style_init' in which the font
+ was not ref'd (via 'gdk_font_ref'), but was free'd (via in
+ 'gdk_font_free') in 'gtk_style_destroy'. (David
+ Mosberger-Tang). Also cleaned up 'gtk_style_destroy' while I was
+ at it.
+
+ * gtkmain.c: Fixed a bug in 'gtk_propogate_event' which caused
+ entry widgets (and probably other widgets) not to be destroyed in
+ some instances.
+
+Mon Apr 7 01:20:38 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkentry.c:
+ * gtkentry.h: Changed the "insert_text", "delete_text" and
+ "changed_text" signals to "insert", "delete", and "changed"
+ respectively. They really should have been named this way
+ originally except the previous signal mechanism prevented
+ duplicate signal names. ("changed" is also used by adjustments).
+
+ * gtkradiomenuitem.c:
+ * gtkradiomenuitem.h: New widget.
+
+ * gtkcheckmenuitem.c:
+ * gtkcheckmenuitem.h: New widget.
+
+ * gtksignal.c: Modified 'gtk_signal_lookup' to require an object
+ type to be passed as a parameter. In addition, signals are now
+ only needed to be uniquely defined in their branch of the class
+ hierarchy. This allows the same signal name to be used in two
+ different branches of the class hierarchy. For instance, the
+ "changed" signal is used both by adjustments and entries...in
+ different ways!
+
+ * gtktypeutils.c: Added 'gtk_type_parent' which returns the parent
+ type for a given type.
+
+Sun Apr 6 22:08:35 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwidget.c: If a widget is set insensitive it loses the focus
+ if it had it.
+
+ * gtkcontainer.c: Insensitive widgets no longer participate in tab
+ traversal.
+
+ * gtkscrolledwindow.c: The "viewport" child is now destroyed and a
+ container class "foreach" function was written (which fixes the
+ sensitivity bug).
+
+Sat Apr 5 14:25:38 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkhscrollbar.c:
+ * gtkvscrollbar.c: Fixed trough size allocation bug.
+
+ * gtkhscale.c:
+ * gtkvscale.c: Fixed trough size allocation and position bug that
+ showed up when scales were placed in notebooks.
+
+Thu Mar 27 17:45:54 1997 David Mosberger-Tang <davidm@azstarnet.com>
+
+ * gtk/gtkmain.c (gtk_handle_idle): Fix appending pending_idles to
+ idle_functions so it works even when idle_functions is empty.
+
+Sat Mar 15 14:15:59 1997 Peter Mattis <pmattis@localhost>
+
+ * *.[ch]: Moved '*_class_init' and '*_init' function declarations
+ for widgets into the source file as those functions no longer had
+ to be public.
+
+ * gtkcheckbutton.c: Fixed redrawing of check button.
+
+ * gtkframe.c: Fixed redrawing of frame when the shadow type is
+ changed.
+
+Sat Mar 8 15:19:23 1997 Peter Mattis <pmattis@localhost>
+
+ * gdkimage.c: Fixed a stupid bug with 'gdk_image_new' which
+ potentially added a NULL image to "image_list" and caused problems
+ when 'gdk_image_exit' was called.
+
+Wed Mar 5 00:40:08 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkpreview.c: Massively changed the colormap handling used by
+ the preview widget. Gray previews are now dithered. A single
+ visual and colormap is shared by the color and gray previews. A
+ GTK_PREVIEW_INFO property is installed on the root window in
+ certain cases to allow multiple GTK programs to share the system
+ colormap.
+
+Sun Mar 2 05:43:06 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkcheckbutton.c: 'gtk_checkbutton_size_allocate' was allocating
+ too much space to its children and not leaving the check button
+ room for the focus border.
+
+ * gtknotebook.c: 'gtk_notebook_size_request' wasn't requesting
+ enough space when the notebook tabs are visible.
+
+Sat Mar 1 01:59:35 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkpreview.c: Fixed a problem with 'gtk_preview_put' when the
+ image byte order is GDK_MSB_FIRST.
+
+ * gtksignal.c:
+ * gtksignal.h: Added 'gtk_signal_connect_after' and
+ 'gtk_signal_connect_object_after' functions. These connect signal
+ handlers which will run after the class function associated with
+ the signal.
+
+ * gtkstyle.c: Fixed a stupid bug in 'gtk_style_new_from_key' that
+ was causing twice as many styles to be created as necesary.
+
+ * gtkwidget.c: 'gtk_real_widget_size_allocate' erases the widgets
+ old allocation if it has the GTK_NO_WINDOW flag set.
+
+ * gtkwidget.c: 'gtk_real_widget_unmap' now erases the widget if it
+ has the GTK_NO_WINDOW flag set.
+
+ * gtklabel.c: Removed 'gtk_label_unmap' as similar functionality
+ was added to gtk_real_widget_unmap.
+
+ * gtkbin.c: Modified 'gtk_bin_map' and 'gtk_bin_unmap' so that it
+ erases and draws the widget if it has the GTK_NO_WINDOW flag set.
+
+ * gtkframe.c: Modified 'gtk_frame_size_allocate' so that it erases
+ the old allocation.
+
+Fri Feb 28 03:27:05 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwindow.c: 'gtk_window_set_title' now changes the window title
+ if the window is already realized.
+
+ * gtkentry.c: 'gtk_entry_set_text' was emitting both a
+ "delete_text" and a "changed_text" signal. Modified so that it
+ only emits a "changed_text" signal.
+
+ * gtkpreview.c: Modified to work correctly on systems with MSB
+ byte order. The colormap for TRUE and DIRECT color displays is now
+ created if the default visual is not equal to the visual we are
+ using.
+
+ * gtkstyle.c: 'gtk_style_attach' and 'gtk_style_find' weren't
+ working properly in the presence of multiple colormaps are
+ different depth visuals.
+
+ * gtkcontainer.c: Massively improved focus traversal using tab and
+ arrow keys. It now uses the layout of the widgets to determine
+ where to move the focus to.
+
+Mon Feb 24 03:24:02 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenufactory.c: Set the accelerator table field for menus when
+ they are created.
+
+ * gtkmenu.c:
+ * gtkmenu.h: Added a default accelerator table field to menus so
+ that runtime modification of accelerator keys in menus can work
+ better.
+
+ * gtkrange.c: 'gtk_range_default_{h,v}motion' had faulty logic for
+ deciding what to do when the slider was at the edge of the
+ trough. They previously didn't update the adjustment value event
+ if the value wasn't what it should be when the slider was at the
+ edge of the trough.
+
+ * gtkviewport.c: 'gtk_viewport_size_allocate' and
+ 'gtk_viewport_adjustment_value_changed' both had the potential for
+ performing a divide by 0. Checks are now in place to prevent this.
+
+ * gtkmenu.c: 'gtk_menu_map' now makes sure the menu lies on screen
+ if the position function is NULL.
+
+ * gtkentry.c: Modified selection handling. 'gtk_delete_selection'
+ actually removes the X selection now. 'gtk_entry_destroy' removes
+ the selection as well and relies on the change in "gdk.c" to make
+ sure the selection event will not be sent to a non-existant
+ window.
+
+ * gdk.c: Selection events are only passed on if the selection
+ owner is not NULL.
+
+ * gtkstyle.c: 'gtk_style_detach' and 'gtk_style_destroy' were not
+ destroying the black and white gc's.
+
+Sun Feb 23 19:17:56 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwindow.c: 'gtk_window_size_request' was setting the window
+ hints. This was also being done in 'gtk_window_map', so the
+ instance being done in 'gtk_window_size_request' was removed.
+
+Fri Feb 21 01:04:01 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwidget.c: 'gtk_widget_draw' has to use the widgets allocated
+ position for the drawing rectangle when the widget has the
+ GTK_NO_WINDOW flag set.
+
+ * gtkwidget.c: In 'gtk_widget_init' the visual and colormap were
+ being directly compared against 'default_visual' and
+ 'default_colormap' instead of calling
+ 'gtk_widget_get_default_{visual,colormap}'.
+
+ * gdkrectangle.c: Amazing! There was a bug in the
+ 'gtk_rectangle_intersect' logic. Its been there for near eternity
+ and I never noticed.
+
+ * gtkpreview.c:
+ * gtkpreview.h: Created preview widget which allows drawing to an
+ rgb or grayscale buffer which is automatically displayed on the
+ screen. Performs dithering as necessary.
+
+Thu Feb 20 20:33:21 1997 Peter Mattis <pmattis@localhost>
+
+ * gdkwindow.c: Modified the logic in 'gdk_window_new' which
+ determined when to add a window to the WM_COLORMAP_WINDOWS
+ property.
+
+Wed Feb 19 19:55:29 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkruler.c: 'gtk_ruler_make_pixmap' was always destroying the
+ old backing store and creating a new one even when it would create
+ a new one of exactly the same size as the old one.
+
+Tue Feb 18 18:32:10 1997 Peter Mattis <pmattis@localhost>
+
+ * gmem.c: 'g_mem_chunk_alloc' was incorrectly modifying the mem
+ areas free mem field when reallocating a previously freed
+ atom. This caused a fairly severe memory leak.
+
+ * gtkmenushell.c: 'gtk_menu_shell_button_release' had a bug in the
+ logic for deciding whether to initiate an X pointer grab or not
+ when the mouse button was released. It now only initiates a grab
+ if the mouse is released within an active menu item.
+
+Fri Feb 14 00:57:40 1997 Peter Mattis <pmattis@localhost>
+
+ * gtknotebook.c: Changed the look of notebook tabs slightly.
+
+ * gtkentry.c:
+ * gtkentry.h: Deleting an entry widget which is holding the X
+ selection presents some difficulties. The X selection must be
+ released, but the widget can't be destroyed until the
+ SELECTION_CLEAR event is received that the X server will send in
+ response to clearing the X selection. There are probably still
+ bugs in the current method of entry widget deletion when the X
+ selection is held.
+
+ * gtkmain.c: 'gtk_propagate_event' was not properly destroying the
+ toplevel window when receiving a key press event.
+
+ * gtkwidget.c: Setting a widget insensitive did not cause it to
+ redraw. It now does.
+
+Thu Feb 13 16:59:07 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkviewport.c: 'gtk_viewport_size_allocate' was allocating its
+ child widget an adjusted allocation. Since the actual scrolling
+ has handled by a subwindow this caused the child to be double
+ scrolled. Modified to always set the child allocations origin to
+ (0, 0).
+
+Wed Feb 12 01:06:48 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkentry.c: Text is now centered vertically. Previously it was
+ pushed up against the top. This problem was only evident when the
+ widget was allocated more vertical space than it requested.
+
+ * gtkfilesel.c: 'gtk_file_selection_key_press' was previously only
+ a stub for tab completion. The actual tab completion call had been
+ left out. (Oops!)
+
+Tue Feb 11 01:43:08 1997 Peter Mattis <pmattis@localhost>
+
+ * gtksignal.c: 'gtk_signal_disconnect_by_data' was going into a
+ loop and crashing. Bad logic. Fixed.
+
+ * gtkmain.c: An idle function which returns FALSE will be removed
+ from the list of idle functions. This makes the functioning of
+ idle functions and timeouts more similar.
+
+ * gtkentry.c: 'gtk_entry_get_text' now returns an empty string
+ when the actual text is NULL. This allows "stupid" programs to use
+ the value returned by 'gtk_entry_get_text' blindly (without
+ checking to see if its NULL).
+
+ * gtkradiobutton.c: Modified 'gtk_radio_button_clicked' so that
+ 'gtk_toggle_button_toggled' is called _after_ the widget state is
+ changed.
+
+ * gtksignal.c:
+ * gtksignal.h: Added 'gtk_signal_name' which returns the character
+ string name for a given signal number.
+
+ * gtkwidget.c: 'gtk_widget_set_parent' checks to see if the widget
+ is now "anchored" through the parent chain to a widget which is
+ GTK_ANCHORED. If it is, then it changes the widgets style using
+ 'gtk_rc_get_style' and recursively performs the same operation on
+ the widgets children. This is necessary is 'gtk_rc_get_style' only
+ works properly on "anchored" widgets.
+
+ * gtkwindow.c: Modified GTK_WIN_POS logic so that it is only used
+ immediately after the window has been shown.
+
+ * gtkmenu.c: 'gtk_menu_key_press'. Can now change menu item
+ accelerator keys on the fly. Why? Why not. Cool/useless feature of
+ the day.
+
+ * gtkmenuitem.c: Accelerator key drawing. Somehow that never got
+ finished. (Oops!)
+
+ * gtkdrawingarea.c: 'gtk_drawing_area_size_allocate' was not
+ actually installed during 'gtk_drawing_area_class_init'. (Oops!)
+
+ * gtkframe.c: 'gtk_frame_size_request' fixed size requisition
+ problem caused by unsigned arithmetic.
+
+ * gtkwindow.c: Modified window widget so that it only uses the
+ widget uposition auxiliary information immediately after it has
+ been shown. This prevents the annoying bug which can cause a
+ uposition'ed window to jump back to its original position after
+ the user moves it.
+
+ * gtkwidget.c: Need to ref and unref style in
+ 'gtk_widget_{push,pop}_style' to make sure that a style on the
+ style stack is not destroyed.
+
+ * gtktogglebutton.c: 'gtk_toggle_button_set_state' now calls
+ gtk_button_clicked to actually change the state of the
+ button. In this way, radio buttons can now perform the appropriate
+ actions when the toggle button state is set.
+
+Mon Feb 10 00:27:39 1997 Peter Mattis <pmattis@localhost>
+
+ * gtklist.c: 'gtk_list_select_item' and 'gtk_list_unselect_item'
+ were casting a GList* variable to a a GtkWidget* variable. Bad bad
+ bad. (Tim Janik).
+
+ * gtksignal.c: Modified 'gtk_signal_connect' and
+ 'gtk_signal_connect_object' to warn when a signal type cannot be
+ found.
+
+Sun Feb 9 00:15:30 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkoptionmenu.c:
+ * gtkoptionmenu.h: Changed option menus back to being derived from
+ buttons. This fixes up some screwiness with their user
+ interaction.
+
+ * gtkwindow.c: Modified key press handler to support focus
+ traversal.
+
+ * gtkcontainer.c:
+ * gtkcontainer.h: Added default focus traversal back in.
+
+Sat Feb 8 10:44:38 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkviewport.h:
+ * gtkviewport.c: Massively sped up viewport scrolling. Used to be
+ reallocating child's size (offset) each time a scrollbar
+ moved. Now a subwindow is moved. All the children are moved
+ automatically by moving the subwindow. Much much much faster.
+
+Tue Feb 4 00:20:44 1997 Peter Mattis <pmattis@localhost>
+
+ * gtree.c: Changed 'g_tree_node_search' to use a loop instead of
+ recursion.
+
+Mon Feb 3 11:30:03 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkbutton.c: Removed 'parent_destroy' global and replaced it
+ with 'parent_class' global to reflect style used in other
+ widgets.
+
+ * gtknotebook.c: Tab labels were being allocated less than their
+ requested size.
+
+ * gtkrange.c:
+ * gtkrange.h: Moved the "digits" field of scales into the range
+ type. The adjustment value for scales is truncated to the number
+ of visible digits instead of being left untouched.
+
+ * gtree.c: Fixed a bug in the AVL tree implementation. Single
+ rotations were always being performed during insertion. It is
+ sometimes necessary to perform a double rotation.
+
+ * gtklabel.c: Modified 'gtk_label_expose' to only draw the label
+ when the allocated space is greater than or equal to the requested
+ space.
+
+ * gtklabel.c: Added call to 'gtk_widget_unmap' to
+ 'gtk_label_destroy' in order for the label to redraw correctly
+ (erase itself) when destroyed.
+
+ * gtklabel.c: Added 'gtk_label_unmap' call which erases the labels
+ allocation when it gets unmapped.
+
+ * *.h: Removed a few remaining instances of using "class" as a
+ parameter name. (Causes problems for C++).
+
+Fri Jan 31 12:26:50 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkcontainer.c: 'gtk_container_enable_resize' needs to call
+ 'gtk_container_check_resize' instead of
+ 'gtk_container_need_resize'.
+
+ * gtkwidget.c: 'gtk_real_widget_show' now maps the widget if its
+ parent is mapped.
+
+ * gtkscrolledwindow.c: Fixed size allocation when the scrollbar
+ policy's are GTK_POLICY_AUTOMATIC. Doing it correctly is harder
+ than I originally thought.
+
+ * gtklist.c: Added 'gtk_list_child_position' to determine the
+ integer position in a list of a child. Filled in the
+ 'gtk_list_item_select' and 'gtk_list_item_unselect' stubs.
+
+Thu Jan 30 16:08:06 1997 Peter Mattis <pmattis@localhost>
+
+ * gmem.c: Changed the implementation of G_ALLOC_AND_FREE mem
+ chunks. They used to allocate SIZEOF_VOID_P extra bytes per atom
+ in order to keep track of which mem area they were allocated
+ from. Now the mem area is determined by searching through an AVL
+ tree of the mem areas for a mem chunk and comparing memory
+ locations. A little slower, but makes G_ALLOC_AND_FREE mem chunks
+ much more attractive.
+
+ * gtree.c: Added an AVL tree implementation to glib.
+
+ * gtksignal.c:
+ * gstring.c: va_arg (arg_list, {char, short}) is
+ invalid. Arguments passed in a variable argument list are
+ promoted. ({char, short}->int). Seemed to work ok before under
+ Linux. Crashed under FreeBSD.
+
+Tue Jan 28 02:27:51 1997 Peter Mattis <pmattis@localhost>
+
+ * gdkwindow.c: Fixed a major slowdown apparent in the file
+ selection dialog which was caused by calling
+ 'gtk_window_add_colormap_windows' way way way too often.
+
+ * *.c: Many widgets called 'gtk_container_need_resize' when
+ something internal changed which would cause the widget to grow or
+ shrink. The assumption was made that the widget would change size
+ and an expose event would be generated. This happens "most" of the
+ time. But its possible for certain widgets to change size without
+ generating expose events, or for its internal geometry to change
+ without a change of size which would mean no expose event was
+ generated. So a wrapper function called
+ 'gtk_container_check_resize' was created and
+ 'gtk_container_need_resize' was modified so that it returns FALSE
+ if a resize was actually generated and TRUE if nothing
+ changed. This allows 'gtk_container_check_resize' to initiate a
+ 'gtk_widget_size_allocate' and 'gtk_widget_draw' to emulate the
+ expose event.
+
+Sat Jan 25 14:17:44 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmain.c: Fixed a bug with propogating key press events. The
+ events were sent 2 times to the toplevel windows which caused the
+ focus widget to be activated twice when the space bar was pressed.
+
+ * */configure.in:
+ * */Makefile.am: Added support for libtool and removed the old
+ shared library configuration craziness.
+
+Fri Jan 24 12:59:22 1997 Peter Mattis <pmattis@localhost>
+
+ * gtktext.c:
+ * gtktext.h: Josh's fixes and additions to the text widget.
+
+ * gtkfill.c:
+ * gtkfill.h: Filler widget useful for filling space in a
+ table. Can specify a minimum size. Used by the canvas widget.
+
+ * gtknotebook.c:
+ * gtknotebook.h: Made outline of notebook widget.
+
+ * gtkcanvas.c:
+ * gtkcanvas.h: Started canvas widget. A composite of 2 rulers (w/
+ an origin), 2 scrolllbars. Guides, grids, snap to.
+
+Sun Jan 19 18:26:45 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkdialog.c:
+ * gtkdialog.h: Created dialog widget which creates a standard
+ looking dialog with buttons along the button and a separator.
+
+ * gtkxid.c: Generalized the window table code for looking up a gdk
+ window based on an XID to work for any XID and a piece of
+ data. Can now look up gdk fonts based on their XID.
+
+ * gtkruler.c:
+ * gtkruler.h:
+ * gtkhruler.c:
+ * gtkhruler.h:
+ * gtkvruler.c:
+ * gtkvruler.h: Started conversion of the ruler widget.
+
+ * gtktext.c:
+ * gtktext.h: Started conversion of the text widget. Scrolling
+ doesn't work.
+
+ * gtkmain.c: Fixed a fairly major bug. The event widget needs to
+ be in a call for the entire duration of handling an event. Not
+ just for when the event widget itself is handling the event.
+
+ * gtkfilesel.c: Fixed up some bugs with resizing.
+
+Fri Jan 10 14:18:03 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwidget.c:
+ * gtkwidget.h:
+ * gtkentry.c:
+ * gtkentry.h: Support for selections.
+
+ * gdkselection.c:
+ * gdk.c:
+ * gdktypes.h:
+ * gdk.h: Gdk support for X selections. Currently only text
+ selections are supported.
+
+ * gtksignal.c: Fixed a major bug which occurred when destroying an
+ object. Memory was being written to after it was freed.
+
+ * gtkfilesel.c:
+ * gtkfilesel.h: Hooked up more functionality to the file selection
+ dialog.
+
+Wed Jan 8 18:13:53 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkfilesel.c:
+ * gtkfilesel.h: Mostly converted old file selection dialog
+ widget. The widget is derived from the GtkWindow class and is
+ quite a bit simpler in the widget code.
+
+ * gtkwidget.c: Fixed 'gtk_widget_grab_focus' and
+ 'gtk_widget_grab_default' to check that the toplevel widget is a
+ type of window (which includes classes derived from windows).
+
+Tue Jan 7 01:12:32 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwindow.c: Was calling 'gtk_window_resize' twice in a
+ row...why?
+
+ * gtksignal.c:
+ * gtksignal.h:
+ * *.c: Changed 'gtk_signal_new' so that the class function that is
+ called when the signal is emitted can be called either before,
+ after or both before and after the calling of any signal
+ handlers.
+
+ * gtkobject.c:
+ * gtkobject.h: Added 'object_data' mechanism for storing data
+ associated with a character string key in objects. Removed
+ 'user_data' field of objects and changed
+ 'gtk_object_{get,set}_user_data' to use the object data
+ mechanism. Removed 'handlers' field of objects.
+
+ * gtkwidget.c:
+ * gtkwidget.h:
+ * gtkwindow.c: Modified aux info mechanism to use object data
+ mechanism.
+
+ * gtksignal.c: Modified signal mechanism to use object data
+ mechanism instead of 'handlers' field.
+
+
+Mon Jan 6 15:10:16 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenushell.c: Fixed up button press handling so as to conform
+ more closely to that used by Motif.
+
+Wed Jan 1 21:27:17 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenu.c:
+ * gtkmenu.h:
+ * gtkmenubar.c:
+ * gtkmenubar.h:
+ * gtkmenushell.c:
+ * gtkmenushell.h: Reorganization of menu-ing code so that code
+ duplication is reduced. The menu shell now contains most of the
+ code for menu-ing interaction while menus and menubars simply layout
+ their child menu items in the appropriate place.
+
+Sun Dec 29 17:48:18 1996 Peter Mattis <pmattis@localhost>
+
+ * gtkmenu.c:
+ * gtkmenubar.c:
+ * gtkmenuitem.h:
+ * gtkmenuitem.c: Modifications so that menu item accelerators and
+ the submenu indicator are drawn correctly and the correct amount
+ of space is allocated.
+
+Sat Dec 28 00:32:13 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * gtkmenufactory.h:
+ * gtkmenufactory.c: Started menu factories as an easy method to
+ create and manipulate menus.
+
+Fri Dec 27 13:17:34 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * gtkmenu.c:
+ * gtkmenu.h:
+ * gtkmenubar.c:
+ * gtkmenubar.h:
+ * gtkmenuitem.c:
+ * gtkmenuitem.h:
+ * gtkmenushell.c:
+ * gtkmenushell.h: Implemented basic menu functionality. Menubars
+ and popup menus work. Submenus work. (Much left to be done).
+
+Wed Dec 18 15:27:05 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * gtktypeutils.h:
+ * gtktypeutils.c: Added 'gtk_type_from_name' which returns a type
+ identifier given a type name. Implemented using a second hash
+ table keyed by type names.
+
+ * gtkbutton.c:
+ * gtktogglebutton.c: Fixed very small messed-up drawing bug when a
+ button loses its focus.
+
+ * gtkwidget.h:
+ * gtkwidget.c:
+ * gtkbutton.c:
+ * gtkwindow.c: Added default button handling. Default buttons now
+ draw correctly and pressing return or enter causes the default
+ button (if one exists) to be activated.
+
+Tue Dec 17 19:32:21 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * gtkhscale.c:
+ * gtkvscale.c: Overrode 'draw_slider' method of ranges in order to
+ draw the slider of scales with a line in them so as to be closer
+ to the Motif look-and-feel.
+
+ * gtkwindow.c: Modified 'gtk_window_focus_in_event' so that focus
+ in events are only handled when the window is visible. Fixes a bug
+ where spurious focus in events get sent when a window is being
+ hidden.
+
+ * gtkwidget.h: Added 'activate_signal' field to the GtkWidgetClass
+ structure. Added 'gtk_widget_activate' call to emit the activate
+ signal for a widget if it is non-zero.
+
+Tue Dec 10 15:59:45 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * gtkwidget.c: 'gtk_widget_set_name' oops in strdup'ing the old
+ "widget->name" instead of the new one we are setting.
+
+ * gtkrc.c: 'gtk_rc_widget_path' changed to use
+ 'gtk_widget_get_name' instead of accessing the "widget->name"
+ field directly.
+
+ * gtkwidget.c: Added 'gtk_widget_get_name' function which returns
+ the widgets name if it exists and the widgets type name if it does
+ not.
+
+ * gtkcheckbutton.c: Added 'gtk_check_button_draw'
+ function. Modified 'gtk_check_button_expose' to pass an expose
+ event to child instead of callings its draw function.
+
+ * gtkentry.c: 'gtk_entry_draw_text' why was "+1" being added to
+ the font->ascent to calculate the font position? This was wrong
+ and caused some characters in fonts to be clipped. (Notably "g").
+
+ * gtkentry.c: 'gtk_entry_realize' specify GTK_BUTTON1_MOTION_MASK
+ and GTK_POINTER_MOTION_HINT_MASK for _both_ windows.
+
+ * gtkmain.c: 'gtk_propagate_event' needs to set the GTK_IN_CALL
+ flag for the object before calling 'gtk_widget_event' and needs to
+ destroy the object if necessary after 'gtk_widget_event' returns.
+
+ * gtkradiobutton.c: 'gtk_radio_button_clicked' needs to call
+ 'gtk_toggle_button_toggled' when the currently active button is
+ toggled.
+
+ * gtkwidget.c: 'gtk_real_widget_hide' needs to call
+ 'gtk_widget_unmap' if the widget is currently mapped.
+
+ * gtkwindow.c: Prevent automatic resizing after the user has
+ specified a new window size. Add 'handling_resize' flag to
+ windows.
+
+ * gtkscrolledwindow.c: Implement the GTK_POLICY_AUTOMATIC
+ scrollbar policy. Need to connect to the adjustments 'changed'
+ signal and notice when the scrollbars aren't in use.
+
+ * gtkcontainer.c: 'gtk_container_init' must set 'auto_resize' and
+ 'need_resize' fields to TRUE and FALSE respectively.
+
+ * gtkwidget.c: 'gtk_widget_set_parent' must all set a widgets state
+ to its parents state.
+
+Sun Dec 1 01:31:01 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * Started ChangeLog
diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6
new file mode 100644
index 000000000..a065ebef5
--- /dev/null
+++ b/ChangeLog.pre-2-6
@@ -0,0 +1,1140 @@
+Mon Nov 17 1997 Jay Painter <jpaint@serv.net>
+ * gtkviewport.c: Raph's Mon, 10 Nov 1997 patch to gtk-list
+ to fix some viewport bugs
+
+Mon Nov 17 1997 Jay Painter <jpaint@serv.net>
+ * gtk/gtkwidget.c: gtk-ajaborsk-971016-2
+ A little patch again to prevent user to use gtk_widget_set_events()
+ when a widget is already realized.
+ In this case, the gtk_widget_set_events() doesn't work.
+
+Mon Nov 17 1997 Jay Painter <jpaint@serv.net>
+ * gtk/gtkwindow.c: gtk-ajaborsk-971016-1
+ This small patch correct position for GTK_WIN_POS_CENTER and
+ GTK_WIN_POS_MOUSE GtkWindow positions.
+
+Sat Nov 15 1997 Jay Painter <jpaint@serv.net>
+ * gdk/gdkgc.c: added function gdk_gc_set_clip_rectangle
+ * gdk/gdk.h: header for above
+
+Sat Nov 15 1997 Jay Painter <jpaint@serv.net>
+ * gdk/gdkgc.c: added function gdk_gc_set_clip_rectangle
+ * gdk/gdk.h: header for above
+
+Wed Nov 12 1997 Jay Painter <jpaint@serv.net>
+ * gdk/gdkpixmap.c: Patrice Fortier's patch for transparent pixmaps.
+ * gdk/gdk.h:
+ gdk/gdkdraw.c: Patrice Fortier's patch to add pixel draw function.
+
+Sun Nov 9 1997 Jay Painter <jpaint@serv.net>
+ * Fixed problems with makefiles relating to the bug
+ which required glib to be installed.
+ * Fixed makefiles to incluce the xpm's in gtk+/gtk needed
+ for testgtk.
+ * Updated gtk+ and gtk+/glib to libtool-1.0f
+
+Fri Nov 7 1997 Jay Painter <jpaint@serv.net>
+ * gtk/gtktext.c: return char_widths[ch & 0xff]; in line 2152
+
+Thr Nov 5 1997 Jay Painter <jpaint@serv.net>
+ * gtk/testgtk.c: added drag and drop test, removed the test hack
+ from the button test
+
+Tue Nov 4 08:28:57 1997 Federico Mena <federico@bananoid.nuclecu.unam.mx>
+
+ * gtk/gtkmain.c (gtk_handle_idle): Patch from David Mosberger to
+ avoid crashes when handling idle function (this manifested itself
+ in the Umax and Microtek backends in SANE.
+
+Sun Nov 2 07:34:56 1997 Tim Janik <timj@psynet.net>
+
+ * gtk/gtkfilesel.c: Small fixes about a segmentation viaolation
+ cause by a double click in the directoy list (introduced by my
+ previous changes).
+
+ * gtk/gtklist.c: Small fixes to gtk_list_add() and gtk_list_remove().
+
+ * gtk/testgtk.c (list_add): Applied Stefan Wille's patch to make this
+ function do something ;).
+
+Fri Oct 31 Jay Painter <jpaint@serv.net>
+ *gdk/gdk.c: reformatted DND code for GTK coding standards
+ *gdk/gdkwindow.c: changed memory allocation for DND to q_mem stuff
+
+Thu Oct 30 Jay Painter <jpaint@serv.net>
+ * gdk/gdkwindow.c:
+ * gdk/gdk/gdk.h:
+ * gtk/gtkwidget.h:
+ * gtk/gtkwidget.c: Applied Stephan Willie's shaped window patch
+
+ * gdk/gdkwindow:
+ * gdk/gdk.h:
+ * gtk/gtkwidget.h:
+ * gtk/gtkwidget.c: reformatted the DND code to conform to GTK
+ coding standards
+
+ * gtk/testgtk: massive fixes, SW's shaped window example
+
+Thu Oct 30 07:33:27 1997 Tim Janik <timj@psynet.net>
+
+ * gtk/gtklistitem.c (gtk_real_list_item_toggle): applied Johannes
+ Keukelaar's <johannes@nada.kth.se> patch for keyboard support in
+ GtkList widgets.
+
+ * gtk/gtkfilesel.c: adapted dir and file list selection
+ behaviour to deal with keyboard selections. this is a little
+ bit tricky: in the dir list it just changes the entrys value on a one
+ button press. but on a keyboard selection via gtk_widget_activate() it
+ does a new population (likewise on a double click) as this seems more
+ obvious.
+
+1997-10-25 Marius Vollmer <mvo@zagadka.ping.de>
+
+ * gdk/gdkcolor.c (gdk_colormap_get_system): Initialize
+ private->ref_count.
+
+Wed Oct 22 09:47:43 1997 Tim Janik <timj@psynet.net>
+
+ * gtk/gtkwindow.c (gtk_window_key_release_event): Fixed a stupid
+ bug that caused the key_release_event to be propagated twice.
+
+Sun Oct 12 11:01:43 1997 Tim Janik <timj@psynet.net>
+
+ * acconfig.h:
+ * configure.in:
+ * gdk/gdkimage.c: Added configure check for IPC_RMID_DEFERRED_RELEASE,
+ because shmat() fails after a shmctl(..., IPC_RMID,...) for OSF1 V3.2,
+ SunOS 4.1.1, 5.5, 5.5.1, 5.6, IRIX 5.2 and 6.2.
+
+Mon Oct 6 11:59:07 1997 Federico Mena <federico@bananoid.nuclecu.unam.mx>
+
+ * gdk/gdk.c (gdk_event_translate): In line 1693, fixed typo that
+ would cause motion notify events not to be delivered.
+
+Sun Oct 5 18:15:06 1997 Federico Mena <federico@bananoid.nuclecu.unam.mx>
+
+ * gtk/gtkrc.c (gtk_rc_parse_bg_pixmap): Changed strdup() for
+ g_strdup().
+
+Wed Sep 24 17:16:34 1997 Peter Mattis <pmattis@bjork.inktomi.com>
+
+ * configure.in: Fixed a stupid error in the test for libXext that
+ would cause it to fail if X_EXTRA_LIBS was not empty.
+
+ * gtk/gtkmain.h (gtk-timj-970919.patch):
+ * gtk/gtkmain.c (gtk-timj-970919.patch): new function
+ `gtk_idle_remove_by_data' to remove all idle callbacks that take a
+ specific piece of data as argument. (gtk_get_current_event):
+ remove idles through gtk_idle_remove_by_data.
+
+ * gtk/gtkwidget.c (gtk-timj-970919.patch):
+ (gtk_widget_destroy): remove pending idles for
+ widgets that have GTK_REDRAW_PENDING or GTK_RESIZE_PENDING and
+ GTK_ANCHORED set (only anchored widgets can have a resize queue
+ handler pending). widgets that have GTK_RESIZE_NEEDED will be removed
+ from their anchored toplevels `resize_widgets' list.
+
+ (gtk_widget_queue_draw): let the widget remember the queue handler
+ tag (through `redraw_handler_key') for later call to `gtk_idle_remove'.
+
+ (gtk_widget_queue_resize): let the widget remember the queue handler
+ tag (through `resize_handler_key') for later call to `gtk_idle_remove'.
+ corrected referencing the toplevel widget for which the handler is
+ pending. if a widget is added to the `resize_widgets' list of a
+ toplevel widget, GTK_RESIZE_NEEDED is set and it's referenced.
+
+ (gtk_real_widget_queue_resize): on the deletion of the `resize_widgets'
+ list, unset GTK_RESIZE_NEEDED and unreference the removed widgets.
+
+ * gtk/gtkwindow.c (gtk-timj-970919.patch):
+ (gtk_real_window_move_resize): move `resize_containers = NULL'
+ initialization out of if-statement.
+ while stepping through the `resize_widgets' list, unreference the
+ widgets and clear GTK_RESIZE_NEEDED. if a widget realy needs are
+ resize, they are flagged through GTK_RESIZE_NEEDED now (instead of
+ GTK_RESIZE_PENDING, as this is indicative for a pending handler).
+ added checks to provide segfaulting if a widgets parent pointer
+ is NULL (e.g. on toplevel widgets that have GTK_RESIZE_NEEDED set).
+
+Tue Sep 23 13:23:27 1997 Federico Mena <federico@bananoid.nuclecu.unam.mx>
+
+ * gdk/gdkimage.c: Applied Tim Janik's patch to mark shm segments
+ as IPC_RMID so that they are automatically removed always.
+
+ * gdk/gdkfont.c: Removed casts from lvalues.
+
+ * gtk/gtkmain.c: Removed GTK_RETLOC_*() (which do a cast) from lvalues.
+
+ * gtk/gtkaccelerator.c (gtk_accelerator_table_remove): Added
+ "const" to the accelerator_key param to be consistent with the
+ declaration in gtkaccelerator.h. The const is not useful in this
+ case, anyway.
+
+Tue Sep 16 13:11:06 1997 Peter Mattis <pmattis@bjork.inktomi.com>
+
+ * gtkpreview.c: Andrew Logan Kieschnick's change to eliminate
+ round-off error when gamma is set to 1.0.
+
+ * gtkrange.c:
+ * gtkviewport.c: Jay Painter's changes to modify the way in which
+ viewports resize.
+
+ * gdkinput.c:
+ * gdkinputgxi.h:
+ * gdkinputxfree.h:
+ * gtk/Makefile.am:
+ * gtk.h:
+ * gtkeventbox.c:
+ * gtkeventbox.h: Owen Taylor's event box widget and fixes for X
+ input support (that I had broken).
+
+ * gdk.h:
+ * gdkwindow.c:
+ * gtksignal.h:
+ * gtksignal.c: Elliot Lee's changes to support Objective C. (id is
+ apparently a reserved word in Objective C).
+
+Sun Sep 14 22:33:15 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwidget.c (gtk_widget_queue_resize): If the toplevel container
+ is invisible we simply call "gtk_container_need_resize" on
+ it. This fixes a bug with option menus not redrawing correctly.
+
+ * gtkmenuitem.c (gtk_menu_item_enter): (gtk_menu_item_leave):
+ These functions now simply pass the event on to their parent. This
+ is necessary for menus to work properly due to the change in how
+ grabs are dealts with.
+
+ * gtkwindow.c (gtk_real_window_move_resize): Fixed a bug that
+ caused the GTK_RESIZE_PENDING flag to not be unset in some cases.
+
+Fri Sep 5 20:49:37 1997 Marius Vollmer <mvo@zagadka.ping.de>
+
+ Bug fixes:
+
+ * Makefile.am: Added PATCHES to EXTRA_DIST.
+ * gtk/gtkpixmap.c (gtk_pixmap_new): Move the "pixmap != NULL" test
+ after the allocation of the pixmap.
+
+ To shut up the compiler:
+
+ * gtk/gtkfilesel.c (get_pwdb): Initialize home_dir.
+ * gtk/gtkmain.c (gtk_init): Replace comments around calls to
+ g_set_*_handler with "if (0)".
+ * gtk/gtkrc.c (gtk_rc_get_token): Initialize hex_number and
+ float_number.
+ * gtk/gtkwindow.c (gtk_window_key_press_event): Initialize
+ direction.
+
+ Changes to the type system in gtk/:
+
+ * Makefile.am: Added gtktypebuiltins.h to gtkinclude_HEADERS.
+ Added gtk.defs, runelisp, gentypeinfo.el and gtktypebuiltins.c to
+ EXTRA_DIST. Added rules to generate gtktypebuiltins.* from
+ gtk.defs.
+
+ * runelisp, gentypeinfo.el, gtk.defs: New files.
+
+ * gtkaccelerator.c, gtkaccelerator.h (gtk_accelerator_table_ref):
+ Return the table so that this function can be used as the `copy'
+ function for GTK_TYPE_BOXED values.
+ * gtkstyle.c, gtkstyle.h (gtk_style_ref): Likewise.
+
+ * gtkenums.h: Removed GtkArgType enum.
+
+ * gtkmain.c (gtk_init): Call gtk_type_init to initialize the type
+ system.
+
+ * gtkobject.c (gtk_object_init_type): New function to take over
+ for gtk_object_get_type. (gtk_object_get_type): Just return the
+ constant GTK_TYPE_OBJECT. (gtk_object_collect_args): Do the right
+ thing for the new GTK_TYPE_* types.
+ * gtksignal.c (gtk_params_get): Likewise.
+
+ * gtktypeutils.c: (gtk_type_init_builtin_types): New
+ function. (gtk_type_init): Call it. Also made non-static.
+ (gtk_type_unique): The allocation scheme for numerical ids has
+ changed: The low 8 bits hold the appropriate GtkFundamentalType of
+ a type, the rest is a globally unique sequence number.
+ (gtk_type_hash): Use the sequence number of a key to hash it.
+ (gtk_type_register_builtin): New function.
+
+ * gtktypeutils.h: (GtkFundamentalType): New enumeration of the
+ fundamental types. (GTK_TYPE_MAKE, GTK_FUNDAMENTAL_TYPE,
+ GTK_TYPE_SEQNO): New macros to work with the new id scheme.
+ (GtkArg): Added fields for new types and renamed old ones. GtkArg
+ should now be a mostly opaque structure, except name and type.
+ (GTK_VALUE_*): New macros to access the values of a GtkArg.
+ (GTK_RETLOC_*): New macros to access the location of a return
+ value that is contained in a GtkArg. * gtktypebuiltins.h: New
+ file to access the typeids of the builtin types.
+
+ * gtkwidget.h (GTK_TYPE_WIDGET): New macro to access the type id
+ of the widget class.
+
+ Thru out: Changed GTK_ARG_* to the appropriate GTK_TYPE_*.
+ Changed access to GtkArg structure to the appropriate GTK_VALUE_*
+ or GTK_RETLOC_* macro. Changed GtkArgType to GtkType. Changed
+ some guints to GtkType.
+
+ General changes in gtk/ to support interpreters:
+
+ * gtkradiobutton.c (gtk_radio_button_new_from_widget,
+ gtk_radio_button_new_with_label_from_widget): New functions.
+
+ * gtksignal.c (gtk_signal_connect_no_marshal): New function.
+ (struct _GtkHandler): Added no_marshal and destroy_func fields.
+ (gtk_signal_handler_new): Initialize them.
+ (gtk_signal_connect_by_type): Added no_marshal and destroy_func
+ arguments. Changed all callers.
+ (gtk_signal_destroy): Invoke destroy_func if there is one and the
+ global destroy func does not apply. (gtk_handlers_run): If the
+ handler has no_marshal set, call its function directly without
+ going thru the signal's marshaller.
+
+Wed Sep 3 09:56:22 1997 RHS Linux User <pmattis@bjork.inktomi.com>
+
+ * gtkrange.c: Changed the way the range control focus was drawn so
+ that the range control is drawn correctly when it does not have
+ the focus.
+
+Tue Sep 2 17:41:17 1997 RHS Linux User <pmattis@bjork.inktomi.com>
+
+ * gtkwidget.c: 'gtk_real_widget_queue_resize' should only remove
+ the "resize_widgets" if another resize is not pending.
+
+Mon Sep 1 18:28:08 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmain.c: Changed the way GDK_DELETE events are handled. Only,
+ if 'gtk_widget_event' returns TRUE is the widget destroyed. By
+ default, 'gtk_widget_event' will return FALSE causing the window
+ to not be destroyed. This prevents segfaults in the GIMP and other
+ programs that do not correctly handle GDK_DELETE events.
+
+ * gtkmain.c: Added modal dialog support by allowing events
+ destined for a child of the grab widget to go to the child instead
+ of the grab widget. (Added 'gtk_widget_is_ancestor' to determine
+ the relationship between the grab widget and the event widget).
+
+ * *.[ch]: Incorprated a whole mess of patches. (Started keeping
+ the ChangeLog up to date again).
+
+Thu Jun 5 17:22:21 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenufactory.c:
+ * gtkmenufactory.h: Added 'gtk_menu_factory_remove_*'
+ calls. Removing entries/paths causes the associated widgets to be
+ destroyed.
+
+ * gtkwidget.c:
+ * gtkwidget.h: Calling 'gtk_widget_set_style' is used as an
+ indication that the programmer specifically wants that style to be
+ used. RC-style substitution is disabled for the widget after such
+ a call.
+
+ * gtkpixmap.c:
+ * gtkpixmap.h:
+ * gtkimage.c:
+ * gtkimage.h: Changed to use clip mask and a single pixmap (or
+ image) to deal with transparent areas.
+
+ * gdkpixmap.c: Modified xpm loading routines to optionally return
+ a clip mask.
+
+ * gdkgc.c:
+ * gdkdraw.c:
+ * gdktypes.h: Modifications to allow clip masks to be used with
+ gc's. Clip masks are bitmaps that specify drawable regions.
+
+Thu May 1 03:11:51 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkscrolledwindow.c: Scrolled windows need to have the
+ GTK_NO_WINDOW flag set. Not having it set caused an obscure
+ redrawing bug.
+
+Wed Apr 30 12:38:03 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkhruler.c:
+ * gtkvruler.c: Fixed a small bug that caused the indicator to be
+ positioned slightly off.
+
+Sun Apr 27 14:28:21 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenushell.c:
+ * gtkmenushell.h:
+ * gtkmenu.c:
+ * gtkmenu.h: Changes so that if a menu is popped up there is a
+ timeout period during which a menu item will not be activated and
+ if the mouse button is released in that period the menu will stay
+ popped up.
+
+ * gtkcurve.c:
+ * gtkcurve.h: Included curve widget courtesy of David
+ Mosberger-Tang (davidm@azstarnet.com).
+
+ * gtkentry.c:
+ * gtkentry.h: Changed "insert" and "delete" signals to
+ "insert_text" and "delete_text" respectively. (The symbol "delete"
+ cannot be used since it is a C++ reserved word).
+
+Sat Apr 19 01:43:49 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenufactory.c: A path which ends in "<nothing>" will cause an
+ invisible (hidden) menu entry to be created. This is useful for
+ setting an accelerator key for which a corresponding menu entry is
+ not desired.
+
+ * gtktooltips.c: Fixed some problems with destruction of the
+ active tip widget not properly updating the tooltips data
+ structures.
+
+Fri Apr 18 15:09:45 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkcontainer.c:
+ * gtklist.c:
+ * gtkwidget.c:
+ * gtkwidget.h: Patch from Owen Taylor (owt1@cornell.edu) which
+ fixes problems with destruction of objects and with destruction of
+ objects which hold the focus.
+
+Thu Apr 17 11:29:15 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenushell.c: Incorrect logic in
+ 'gtk_menu_shell_button_release' for deciding when a menu should
+ stay popped up when the mouse button is released.
+
+ * *.c: Miscellaneous fixes from folks on the net.
+
+Tue Apr 15 02:43:17 1997 Peter Mattis <pmattis@localhost>
+
+ * *.c:
+ * gtkwidget.h: Added GTK_BASIC widget flag which when set
+ specifies a widget as "basic". A "basic" widget is one which
+ doesn't take input events. For example, labels, pixmaps, boxes,
+ tables, alignments, etc.
+
+Sat Apr 12 15:23:08 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkcolorsel.c: Add "#include <math.h>" to define M_PI.
+
+ * gtksignal.c: Fixed a bug in 'gtk_signal_emit' which showed up
+ because of the new cast checking macros. The 'object' was being
+ accessed after it had been destroyed.
+
+ * gtkoptionmenu.c: Fixed bug with using 'GTK_BIN' instead of
+ 'GTK_BUTTON' which showed up because of the new cast checking
+ macros.
+
+ * *.h: 'GTK_CHECK_CAST', 'GTK_CHECK_CLASS_CAST' and
+ 'GTK_CHECK_TYPE' used by standard widget macros everywhere.
+
+Wed Apr 9 00:54:17 1997 Peter Mattis <pmattis@localhost>
+
+ * docs/gtk.texi: Started further work on documentation. Major
+ changes and additions are being made.
+
+ * gtkarrow.c:
+ * gtkarrow.h: Removed function 'gtk_arrow_get'.
+
+ * gtkcontainer.c: 'gtk_container_check_resize' no performs
+ additional checking to account for the case where the containers
+ allocation is no longer sufficient because its parent (or its
+ parents parent, etc.) needs to resize its children.
+
+Tue Apr 8 21:15:50 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkstyle.c: Fixed a bug in 'gtk_style_init' in which the font
+ was not ref'd (via 'gdk_font_ref'), but was free'd (via in
+ 'gdk_font_free') in 'gtk_style_destroy'. (David
+ Mosberger-Tang). Also cleaned up 'gtk_style_destroy' while I was
+ at it.
+
+ * gtkmain.c: Fixed a bug in 'gtk_propogate_event' which caused
+ entry widgets (and probably other widgets) not to be destroyed in
+ some instances.
+
+Mon Apr 7 01:20:38 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkentry.c:
+ * gtkentry.h: Changed the "insert_text", "delete_text" and
+ "changed_text" signals to "insert", "delete", and "changed"
+ respectively. They really should have been named this way
+ originally except the previous signal mechanism prevented
+ duplicate signal names. ("changed" is also used by adjustments).
+
+ * gtkradiomenuitem.c:
+ * gtkradiomenuitem.h: New widget.
+
+ * gtkcheckmenuitem.c:
+ * gtkcheckmenuitem.h: New widget.
+
+ * gtksignal.c: Modified 'gtk_signal_lookup' to require an object
+ type to be passed as a parameter. In addition, signals are now
+ only needed to be uniquely defined in their branch of the class
+ hierarchy. This allows the same signal name to be used in two
+ different branches of the class hierarchy. For instance, the
+ "changed" signal is used both by adjustments and entries...in
+ different ways!
+
+ * gtktypeutils.c: Added 'gtk_type_parent' which returns the parent
+ type for a given type.
+
+Sun Apr 6 22:08:35 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwidget.c: If a widget is set insensitive it loses the focus
+ if it had it.
+
+ * gtkcontainer.c: Insensitive widgets no longer participate in tab
+ traversal.
+
+ * gtkscrolledwindow.c: The "viewport" child is now destroyed and a
+ container class "foreach" function was written (which fixes the
+ sensitivity bug).
+
+Sat Apr 5 14:25:38 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkhscrollbar.c:
+ * gtkvscrollbar.c: Fixed trough size allocation bug.
+
+ * gtkhscale.c:
+ * gtkvscale.c: Fixed trough size allocation and position bug that
+ showed up when scales were placed in notebooks.
+
+Thu Mar 27 17:45:54 1997 David Mosberger-Tang <davidm@azstarnet.com>
+
+ * gtk/gtkmain.c (gtk_handle_idle): Fix appending pending_idles to
+ idle_functions so it works even when idle_functions is empty.
+
+Sat Mar 15 14:15:59 1997 Peter Mattis <pmattis@localhost>
+
+ * *.[ch]: Moved '*_class_init' and '*_init' function declarations
+ for widgets into the source file as those functions no longer had
+ to be public.
+
+ * gtkcheckbutton.c: Fixed redrawing of check button.
+
+ * gtkframe.c: Fixed redrawing of frame when the shadow type is
+ changed.
+
+Sat Mar 8 15:19:23 1997 Peter Mattis <pmattis@localhost>
+
+ * gdkimage.c: Fixed a stupid bug with 'gdk_image_new' which
+ potentially added a NULL image to "image_list" and caused problems
+ when 'gdk_image_exit' was called.
+
+Wed Mar 5 00:40:08 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkpreview.c: Massively changed the colormap handling used by
+ the preview widget. Gray previews are now dithered. A single
+ visual and colormap is shared by the color and gray previews. A
+ GTK_PREVIEW_INFO property is installed on the root window in
+ certain cases to allow multiple GTK programs to share the system
+ colormap.
+
+Sun Mar 2 05:43:06 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkcheckbutton.c: 'gtk_checkbutton_size_allocate' was allocating
+ too much space to its children and not leaving the check button
+ room for the focus border.
+
+ * gtknotebook.c: 'gtk_notebook_size_request' wasn't requesting
+ enough space when the notebook tabs are visible.
+
+Sat Mar 1 01:59:35 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkpreview.c: Fixed a problem with 'gtk_preview_put' when the
+ image byte order is GDK_MSB_FIRST.
+
+ * gtksignal.c:
+ * gtksignal.h: Added 'gtk_signal_connect_after' and
+ 'gtk_signal_connect_object_after' functions. These connect signal
+ handlers which will run after the class function associated with
+ the signal.
+
+ * gtkstyle.c: Fixed a stupid bug in 'gtk_style_new_from_key' that
+ was causing twice as many styles to be created as necesary.
+
+ * gtkwidget.c: 'gtk_real_widget_size_allocate' erases the widgets
+ old allocation if it has the GTK_NO_WINDOW flag set.
+
+ * gtkwidget.c: 'gtk_real_widget_unmap' now erases the widget if it
+ has the GTK_NO_WINDOW flag set.
+
+ * gtklabel.c: Removed 'gtk_label_unmap' as similar functionality
+ was added to gtk_real_widget_unmap.
+
+ * gtkbin.c: Modified 'gtk_bin_map' and 'gtk_bin_unmap' so that it
+ erases and draws the widget if it has the GTK_NO_WINDOW flag set.
+
+ * gtkframe.c: Modified 'gtk_frame_size_allocate' so that it erases
+ the old allocation.
+
+Fri Feb 28 03:27:05 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwindow.c: 'gtk_window_set_title' now changes the window title
+ if the window is already realized.
+
+ * gtkentry.c: 'gtk_entry_set_text' was emitting both a
+ "delete_text" and a "changed_text" signal. Modified so that it
+ only emits a "changed_text" signal.
+
+ * gtkpreview.c: Modified to work correctly on systems with MSB
+ byte order. The colormap for TRUE and DIRECT color displays is now
+ created if the default visual is not equal to the visual we are
+ using.
+
+ * gtkstyle.c: 'gtk_style_attach' and 'gtk_style_find' weren't
+ working properly in the presence of multiple colormaps are
+ different depth visuals.
+
+ * gtkcontainer.c: Massively improved focus traversal using tab and
+ arrow keys. It now uses the layout of the widgets to determine
+ where to move the focus to.
+
+Mon Feb 24 03:24:02 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenufactory.c: Set the accelerator table field for menus when
+ they are created.
+
+ * gtkmenu.c:
+ * gtkmenu.h: Added a default accelerator table field to menus so
+ that runtime modification of accelerator keys in menus can work
+ better.
+
+ * gtkrange.c: 'gtk_range_default_{h,v}motion' had faulty logic for
+ deciding what to do when the slider was at the edge of the
+ trough. They previously didn't update the adjustment value event
+ if the value wasn't what it should be when the slider was at the
+ edge of the trough.
+
+ * gtkviewport.c: 'gtk_viewport_size_allocate' and
+ 'gtk_viewport_adjustment_value_changed' both had the potential for
+ performing a divide by 0. Checks are now in place to prevent this.
+
+ * gtkmenu.c: 'gtk_menu_map' now makes sure the menu lies on screen
+ if the position function is NULL.
+
+ * gtkentry.c: Modified selection handling. 'gtk_delete_selection'
+ actually removes the X selection now. 'gtk_entry_destroy' removes
+ the selection as well and relies on the change in "gdk.c" to make
+ sure the selection event will not be sent to a non-existant
+ window.
+
+ * gdk.c: Selection events are only passed on if the selection
+ owner is not NULL.
+
+ * gtkstyle.c: 'gtk_style_detach' and 'gtk_style_destroy' were not
+ destroying the black and white gc's.
+
+Sun Feb 23 19:17:56 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwindow.c: 'gtk_window_size_request' was setting the window
+ hints. This was also being done in 'gtk_window_map', so the
+ instance being done in 'gtk_window_size_request' was removed.
+
+Fri Feb 21 01:04:01 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwidget.c: 'gtk_widget_draw' has to use the widgets allocated
+ position for the drawing rectangle when the widget has the
+ GTK_NO_WINDOW flag set.
+
+ * gtkwidget.c: In 'gtk_widget_init' the visual and colormap were
+ being directly compared against 'default_visual' and
+ 'default_colormap' instead of calling
+ 'gtk_widget_get_default_{visual,colormap}'.
+
+ * gdkrectangle.c: Amazing! There was a bug in the
+ 'gtk_rectangle_intersect' logic. Its been there for near eternity
+ and I never noticed.
+
+ * gtkpreview.c:
+ * gtkpreview.h: Created preview widget which allows drawing to an
+ rgb or grayscale buffer which is automatically displayed on the
+ screen. Performs dithering as necessary.
+
+Thu Feb 20 20:33:21 1997 Peter Mattis <pmattis@localhost>
+
+ * gdkwindow.c: Modified the logic in 'gdk_window_new' which
+ determined when to add a window to the WM_COLORMAP_WINDOWS
+ property.
+
+Wed Feb 19 19:55:29 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkruler.c: 'gtk_ruler_make_pixmap' was always destroying the
+ old backing store and creating a new one even when it would create
+ a new one of exactly the same size as the old one.
+
+Tue Feb 18 18:32:10 1997 Peter Mattis <pmattis@localhost>
+
+ * gmem.c: 'g_mem_chunk_alloc' was incorrectly modifying the mem
+ areas free mem field when reallocating a previously freed
+ atom. This caused a fairly severe memory leak.
+
+ * gtkmenushell.c: 'gtk_menu_shell_button_release' had a bug in the
+ logic for deciding whether to initiate an X pointer grab or not
+ when the mouse button was released. It now only initiates a grab
+ if the mouse is released within an active menu item.
+
+Fri Feb 14 00:57:40 1997 Peter Mattis <pmattis@localhost>
+
+ * gtknotebook.c: Changed the look of notebook tabs slightly.
+
+ * gtkentry.c:
+ * gtkentry.h: Deleting an entry widget which is holding the X
+ selection presents some difficulties. The X selection must be
+ released, but the widget can't be destroyed until the
+ SELECTION_CLEAR event is received that the X server will send in
+ response to clearing the X selection. There are probably still
+ bugs in the current method of entry widget deletion when the X
+ selection is held.
+
+ * gtkmain.c: 'gtk_propagate_event' was not properly destroying the
+ toplevel window when receiving a key press event.
+
+ * gtkwidget.c: Setting a widget insensitive did not cause it to
+ redraw. It now does.
+
+Thu Feb 13 16:59:07 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkviewport.c: 'gtk_viewport_size_allocate' was allocating its
+ child widget an adjusted allocation. Since the actual scrolling
+ has handled by a subwindow this caused the child to be double
+ scrolled. Modified to always set the child allocations origin to
+ (0, 0).
+
+Wed Feb 12 01:06:48 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkentry.c: Text is now centered vertically. Previously it was
+ pushed up against the top. This problem was only evident when the
+ widget was allocated more vertical space than it requested.
+
+ * gtkfilesel.c: 'gtk_file_selection_key_press' was previously only
+ a stub for tab completion. The actual tab completion call had been
+ left out. (Oops!)
+
+Tue Feb 11 01:43:08 1997 Peter Mattis <pmattis@localhost>
+
+ * gtksignal.c: 'gtk_signal_disconnect_by_data' was going into a
+ loop and crashing. Bad logic. Fixed.
+
+ * gtkmain.c: An idle function which returns FALSE will be removed
+ from the list of idle functions. This makes the functioning of
+ idle functions and timeouts more similar.
+
+ * gtkentry.c: 'gtk_entry_get_text' now returns an empty string
+ when the actual text is NULL. This allows "stupid" programs to use
+ the value returned by 'gtk_entry_get_text' blindly (without
+ checking to see if its NULL).
+
+ * gtkradiobutton.c: Modified 'gtk_radio_button_clicked' so that
+ 'gtk_toggle_button_toggled' is called _after_ the widget state is
+ changed.
+
+ * gtksignal.c:
+ * gtksignal.h: Added 'gtk_signal_name' which returns the character
+ string name for a given signal number.
+
+ * gtkwidget.c: 'gtk_widget_set_parent' checks to see if the widget
+ is now "anchored" through the parent chain to a widget which is
+ GTK_ANCHORED. If it is, then it changes the widgets style using
+ 'gtk_rc_get_style' and recursively performs the same operation on
+ the widgets children. This is necessary is 'gtk_rc_get_style' only
+ works properly on "anchored" widgets.
+
+ * gtkwindow.c: Modified GTK_WIN_POS logic so that it is only used
+ immediately after the window has been shown.
+
+ * gtkmenu.c: 'gtk_menu_key_press'. Can now change menu item
+ accelerator keys on the fly. Why? Why not. Cool/useless feature of
+ the day.
+
+ * gtkmenuitem.c: Accelerator key drawing. Somehow that never got
+ finished. (Oops!)
+
+ * gtkdrawingarea.c: 'gtk_drawing_area_size_allocate' was not
+ actually installed during 'gtk_drawing_area_class_init'. (Oops!)
+
+ * gtkframe.c: 'gtk_frame_size_request' fixed size requisition
+ problem caused by unsigned arithmetic.
+
+ * gtkwindow.c: Modified window widget so that it only uses the
+ widget uposition auxiliary information immediately after it has
+ been shown. This prevents the annoying bug which can cause a
+ uposition'ed window to jump back to its original position after
+ the user moves it.
+
+ * gtkwidget.c: Need to ref and unref style in
+ 'gtk_widget_{push,pop}_style' to make sure that a style on the
+ style stack is not destroyed.
+
+ * gtktogglebutton.c: 'gtk_toggle_button_set_state' now calls
+ gtk_button_clicked to actually change the state of the
+ button. In this way, radio buttons can now perform the appropriate
+ actions when the toggle button state is set.
+
+Mon Feb 10 00:27:39 1997 Peter Mattis <pmattis@localhost>
+
+ * gtklist.c: 'gtk_list_select_item' and 'gtk_list_unselect_item'
+ were casting a GList* variable to a a GtkWidget* variable. Bad bad
+ bad. (Tim Janik).
+
+ * gtksignal.c: Modified 'gtk_signal_connect' and
+ 'gtk_signal_connect_object' to warn when a signal type cannot be
+ found.
+
+Sun Feb 9 00:15:30 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkoptionmenu.c:
+ * gtkoptionmenu.h: Changed option menus back to being derived from
+ buttons. This fixes up some screwiness with their user
+ interaction.
+
+ * gtkwindow.c: Modified key press handler to support focus
+ traversal.
+
+ * gtkcontainer.c:
+ * gtkcontainer.h: Added default focus traversal back in.
+
+Sat Feb 8 10:44:38 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkviewport.h:
+ * gtkviewport.c: Massively sped up viewport scrolling. Used to be
+ reallocating child's size (offset) each time a scrollbar
+ moved. Now a subwindow is moved. All the children are moved
+ automatically by moving the subwindow. Much much much faster.
+
+Tue Feb 4 00:20:44 1997 Peter Mattis <pmattis@localhost>
+
+ * gtree.c: Changed 'g_tree_node_search' to use a loop instead of
+ recursion.
+
+Mon Feb 3 11:30:03 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkbutton.c: Removed 'parent_destroy' global and replaced it
+ with 'parent_class' global to reflect style used in other
+ widgets.
+
+ * gtknotebook.c: Tab labels were being allocated less than their
+ requested size.
+
+ * gtkrange.c:
+ * gtkrange.h: Moved the "digits" field of scales into the range
+ type. The adjustment value for scales is truncated to the number
+ of visible digits instead of being left untouched.
+
+ * gtree.c: Fixed a bug in the AVL tree implementation. Single
+ rotations were always being performed during insertion. It is
+ sometimes necessary to perform a double rotation.
+
+ * gtklabel.c: Modified 'gtk_label_expose' to only draw the label
+ when the allocated space is greater than or equal to the requested
+ space.
+
+ * gtklabel.c: Added call to 'gtk_widget_unmap' to
+ 'gtk_label_destroy' in order for the label to redraw correctly
+ (erase itself) when destroyed.
+
+ * gtklabel.c: Added 'gtk_label_unmap' call which erases the labels
+ allocation when it gets unmapped.
+
+ * *.h: Removed a few remaining instances of using "class" as a
+ parameter name. (Causes problems for C++).
+
+Fri Jan 31 12:26:50 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkcontainer.c: 'gtk_container_enable_resize' needs to call
+ 'gtk_container_check_resize' instead of
+ 'gtk_container_need_resize'.
+
+ * gtkwidget.c: 'gtk_real_widget_show' now maps the widget if its
+ parent is mapped.
+
+ * gtkscrolledwindow.c: Fixed size allocation when the scrollbar
+ policy's are GTK_POLICY_AUTOMATIC. Doing it correctly is harder
+ than I originally thought.
+
+ * gtklist.c: Added 'gtk_list_child_position' to determine the
+ integer position in a list of a child. Filled in the
+ 'gtk_list_item_select' and 'gtk_list_item_unselect' stubs.
+
+Thu Jan 30 16:08:06 1997 Peter Mattis <pmattis@localhost>
+
+ * gmem.c: Changed the implementation of G_ALLOC_AND_FREE mem
+ chunks. They used to allocate SIZEOF_VOID_P extra bytes per atom
+ in order to keep track of which mem area they were allocated
+ from. Now the mem area is determined by searching through an AVL
+ tree of the mem areas for a mem chunk and comparing memory
+ locations. A little slower, but makes G_ALLOC_AND_FREE mem chunks
+ much more attractive.
+
+ * gtree.c: Added an AVL tree implementation to glib.
+
+ * gtksignal.c:
+ * gstring.c: va_arg (arg_list, {char, short}) is
+ invalid. Arguments passed in a variable argument list are
+ promoted. ({char, short}->int). Seemed to work ok before under
+ Linux. Crashed under FreeBSD.
+
+Tue Jan 28 02:27:51 1997 Peter Mattis <pmattis@localhost>
+
+ * gdkwindow.c: Fixed a major slowdown apparent in the file
+ selection dialog which was caused by calling
+ 'gtk_window_add_colormap_windows' way way way too often.
+
+ * *.c: Many widgets called 'gtk_container_need_resize' when
+ something internal changed which would cause the widget to grow or
+ shrink. The assumption was made that the widget would change size
+ and an expose event would be generated. This happens "most" of the
+ time. But its possible for certain widgets to change size without
+ generating expose events, or for its internal geometry to change
+ without a change of size which would mean no expose event was
+ generated. So a wrapper function called
+ 'gtk_container_check_resize' was created and
+ 'gtk_container_need_resize' was modified so that it returns FALSE
+ if a resize was actually generated and TRUE if nothing
+ changed. This allows 'gtk_container_check_resize' to initiate a
+ 'gtk_widget_size_allocate' and 'gtk_widget_draw' to emulate the
+ expose event.
+
+Sat Jan 25 14:17:44 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmain.c: Fixed a bug with propogating key press events. The
+ events were sent 2 times to the toplevel windows which caused the
+ focus widget to be activated twice when the space bar was pressed.
+
+ * */configure.in:
+ * */Makefile.am: Added support for libtool and removed the old
+ shared library configuration craziness.
+
+Fri Jan 24 12:59:22 1997 Peter Mattis <pmattis@localhost>
+
+ * gtktext.c:
+ * gtktext.h: Josh's fixes and additions to the text widget.
+
+ * gtkfill.c:
+ * gtkfill.h: Filler widget useful for filling space in a
+ table. Can specify a minimum size. Used by the canvas widget.
+
+ * gtknotebook.c:
+ * gtknotebook.h: Made outline of notebook widget.
+
+ * gtkcanvas.c:
+ * gtkcanvas.h: Started canvas widget. A composite of 2 rulers (w/
+ an origin), 2 scrolllbars. Guides, grids, snap to.
+
+Sun Jan 19 18:26:45 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkdialog.c:
+ * gtkdialog.h: Created dialog widget which creates a standard
+ looking dialog with buttons along the button and a separator.
+
+ * gtkxid.c: Generalized the window table code for looking up a gdk
+ window based on an XID to work for any XID and a piece of
+ data. Can now look up gdk fonts based on their XID.
+
+ * gtkruler.c:
+ * gtkruler.h:
+ * gtkhruler.c:
+ * gtkhruler.h:
+ * gtkvruler.c:
+ * gtkvruler.h: Started conversion of the ruler widget.
+
+ * gtktext.c:
+ * gtktext.h: Started conversion of the text widget. Scrolling
+ doesn't work.
+
+ * gtkmain.c: Fixed a fairly major bug. The event widget needs to
+ be in a call for the entire duration of handling an event. Not
+ just for when the event widget itself is handling the event.
+
+ * gtkfilesel.c: Fixed up some bugs with resizing.
+
+Fri Jan 10 14:18:03 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwidget.c:
+ * gtkwidget.h:
+ * gtkentry.c:
+ * gtkentry.h: Support for selections.
+
+ * gdkselection.c:
+ * gdk.c:
+ * gdktypes.h:
+ * gdk.h: Gdk support for X selections. Currently only text
+ selections are supported.
+
+ * gtksignal.c: Fixed a major bug which occurred when destroying an
+ object. Memory was being written to after it was freed.
+
+ * gtkfilesel.c:
+ * gtkfilesel.h: Hooked up more functionality to the file selection
+ dialog.
+
+Wed Jan 8 18:13:53 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkfilesel.c:
+ * gtkfilesel.h: Mostly converted old file selection dialog
+ widget. The widget is derived from the GtkWindow class and is
+ quite a bit simpler in the widget code.
+
+ * gtkwidget.c: Fixed 'gtk_widget_grab_focus' and
+ 'gtk_widget_grab_default' to check that the toplevel widget is a
+ type of window (which includes classes derived from windows).
+
+Tue Jan 7 01:12:32 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwindow.c: Was calling 'gtk_window_resize' twice in a
+ row...why?
+
+ * gtksignal.c:
+ * gtksignal.h:
+ * *.c: Changed 'gtk_signal_new' so that the class function that is
+ called when the signal is emitted can be called either before,
+ after or both before and after the calling of any signal
+ handlers.
+
+ * gtkobject.c:
+ * gtkobject.h: Added 'object_data' mechanism for storing data
+ associated with a character string key in objects. Removed
+ 'user_data' field of objects and changed
+ 'gtk_object_{get,set}_user_data' to use the object data
+ mechanism. Removed 'handlers' field of objects.
+
+ * gtkwidget.c:
+ * gtkwidget.h:
+ * gtkwindow.c: Modified aux info mechanism to use object data
+ mechanism.
+
+ * gtksignal.c: Modified signal mechanism to use object data
+ mechanism instead of 'handlers' field.
+
+
+Mon Jan 6 15:10:16 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenushell.c: Fixed up button press handling so as to conform
+ more closely to that used by Motif.
+
+Wed Jan 1 21:27:17 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenu.c:
+ * gtkmenu.h:
+ * gtkmenubar.c:
+ * gtkmenubar.h:
+ * gtkmenushell.c:
+ * gtkmenushell.h: Reorganization of menu-ing code so that code
+ duplication is reduced. The menu shell now contains most of the
+ code for menu-ing interaction while menus and menubars simply layout
+ their child menu items in the appropriate place.
+
+Sun Dec 29 17:48:18 1996 Peter Mattis <pmattis@localhost>
+
+ * gtkmenu.c:
+ * gtkmenubar.c:
+ * gtkmenuitem.h:
+ * gtkmenuitem.c: Modifications so that menu item accelerators and
+ the submenu indicator are drawn correctly and the correct amount
+ of space is allocated.
+
+Sat Dec 28 00:32:13 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * gtkmenufactory.h:
+ * gtkmenufactory.c: Started menu factories as an easy method to
+ create and manipulate menus.
+
+Fri Dec 27 13:17:34 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * gtkmenu.c:
+ * gtkmenu.h:
+ * gtkmenubar.c:
+ * gtkmenubar.h:
+ * gtkmenuitem.c:
+ * gtkmenuitem.h:
+ * gtkmenushell.c:
+ * gtkmenushell.h: Implemented basic menu functionality. Menubars
+ and popup menus work. Submenus work. (Much left to be done).
+
+Wed Dec 18 15:27:05 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * gtktypeutils.h:
+ * gtktypeutils.c: Added 'gtk_type_from_name' which returns a type
+ identifier given a type name. Implemented using a second hash
+ table keyed by type names.
+
+ * gtkbutton.c:
+ * gtktogglebutton.c: Fixed very small messed-up drawing bug when a
+ button loses its focus.
+
+ * gtkwidget.h:
+ * gtkwidget.c:
+ * gtkbutton.c:
+ * gtkwindow.c: Added default button handling. Default buttons now
+ draw correctly and pressing return or enter causes the default
+ button (if one exists) to be activated.
+
+Tue Dec 17 19:32:21 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * gtkhscale.c:
+ * gtkvscale.c: Overrode 'draw_slider' method of ranges in order to
+ draw the slider of scales with a line in them so as to be closer
+ to the Motif look-and-feel.
+
+ * gtkwindow.c: Modified 'gtk_window_focus_in_event' so that focus
+ in events are only handled when the window is visible. Fixes a bug
+ where spurious focus in events get sent when a window is being
+ hidden.
+
+ * gtkwidget.h: Added 'activate_signal' field to the GtkWidgetClass
+ structure. Added 'gtk_widget_activate' call to emit the activate
+ signal for a widget if it is non-zero.
+
+Tue Dec 10 15:59:45 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * gtkwidget.c: 'gtk_widget_set_name' oops in strdup'ing the old
+ "widget->name" instead of the new one we are setting.
+
+ * gtkrc.c: 'gtk_rc_widget_path' changed to use
+ 'gtk_widget_get_name' instead of accessing the "widget->name"
+ field directly.
+
+ * gtkwidget.c: Added 'gtk_widget_get_name' function which returns
+ the widgets name if it exists and the widgets type name if it does
+ not.
+
+ * gtkcheckbutton.c: Added 'gtk_check_button_draw'
+ function. Modified 'gtk_check_button_expose' to pass an expose
+ event to child instead of callings its draw function.
+
+ * gtkentry.c: 'gtk_entry_draw_text' why was "+1" being added to
+ the font->ascent to calculate the font position? This was wrong
+ and caused some characters in fonts to be clipped. (Notably "g").
+
+ * gtkentry.c: 'gtk_entry_realize' specify GTK_BUTTON1_MOTION_MASK
+ and GTK_POINTER_MOTION_HINT_MASK for _both_ windows.
+
+ * gtkmain.c: 'gtk_propagate_event' needs to set the GTK_IN_CALL
+ flag for the object before calling 'gtk_widget_event' and needs to
+ destroy the object if necessary after 'gtk_widget_event' returns.
+
+ * gtkradiobutton.c: 'gtk_radio_button_clicked' needs to call
+ 'gtk_toggle_button_toggled' when the currently active button is
+ toggled.
+
+ * gtkwidget.c: 'gtk_real_widget_hide' needs to call
+ 'gtk_widget_unmap' if the widget is currently mapped.
+
+ * gtkwindow.c: Prevent automatic resizing after the user has
+ specified a new window size. Add 'handling_resize' flag to
+ windows.
+
+ * gtkscrolledwindow.c: Implement the GTK_POLICY_AUTOMATIC
+ scrollbar policy. Need to connect to the adjustments 'changed'
+ signal and notice when the scrollbars aren't in use.
+
+ * gtkcontainer.c: 'gtk_container_init' must set 'auto_resize' and
+ 'need_resize' fields to TRUE and FALSE respectively.
+
+ * gtkwidget.c: 'gtk_widget_set_parent' must all set a widgets state
+ to its parents state.
+
+Sun Dec 1 01:31:01 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * Started ChangeLog
diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8
new file mode 100644
index 000000000..a065ebef5
--- /dev/null
+++ b/ChangeLog.pre-2-8
@@ -0,0 +1,1140 @@
+Mon Nov 17 1997 Jay Painter <jpaint@serv.net>
+ * gtkviewport.c: Raph's Mon, 10 Nov 1997 patch to gtk-list
+ to fix some viewport bugs
+
+Mon Nov 17 1997 Jay Painter <jpaint@serv.net>
+ * gtk/gtkwidget.c: gtk-ajaborsk-971016-2
+ A little patch again to prevent user to use gtk_widget_set_events()
+ when a widget is already realized.
+ In this case, the gtk_widget_set_events() doesn't work.
+
+Mon Nov 17 1997 Jay Painter <jpaint@serv.net>
+ * gtk/gtkwindow.c: gtk-ajaborsk-971016-1
+ This small patch correct position for GTK_WIN_POS_CENTER and
+ GTK_WIN_POS_MOUSE GtkWindow positions.
+
+Sat Nov 15 1997 Jay Painter <jpaint@serv.net>
+ * gdk/gdkgc.c: added function gdk_gc_set_clip_rectangle
+ * gdk/gdk.h: header for above
+
+Sat Nov 15 1997 Jay Painter <jpaint@serv.net>
+ * gdk/gdkgc.c: added function gdk_gc_set_clip_rectangle
+ * gdk/gdk.h: header for above
+
+Wed Nov 12 1997 Jay Painter <jpaint@serv.net>
+ * gdk/gdkpixmap.c: Patrice Fortier's patch for transparent pixmaps.
+ * gdk/gdk.h:
+ gdk/gdkdraw.c: Patrice Fortier's patch to add pixel draw function.
+
+Sun Nov 9 1997 Jay Painter <jpaint@serv.net>
+ * Fixed problems with makefiles relating to the bug
+ which required glib to be installed.
+ * Fixed makefiles to incluce the xpm's in gtk+/gtk needed
+ for testgtk.
+ * Updated gtk+ and gtk+/glib to libtool-1.0f
+
+Fri Nov 7 1997 Jay Painter <jpaint@serv.net>
+ * gtk/gtktext.c: return char_widths[ch & 0xff]; in line 2152
+
+Thr Nov 5 1997 Jay Painter <jpaint@serv.net>
+ * gtk/testgtk.c: added drag and drop test, removed the test hack
+ from the button test
+
+Tue Nov 4 08:28:57 1997 Federico Mena <federico@bananoid.nuclecu.unam.mx>
+
+ * gtk/gtkmain.c (gtk_handle_idle): Patch from David Mosberger to
+ avoid crashes when handling idle function (this manifested itself
+ in the Umax and Microtek backends in SANE.
+
+Sun Nov 2 07:34:56 1997 Tim Janik <timj@psynet.net>
+
+ * gtk/gtkfilesel.c: Small fixes about a segmentation viaolation
+ cause by a double click in the directoy list (introduced by my
+ previous changes).
+
+ * gtk/gtklist.c: Small fixes to gtk_list_add() and gtk_list_remove().
+
+ * gtk/testgtk.c (list_add): Applied Stefan Wille's patch to make this
+ function do something ;).
+
+Fri Oct 31 Jay Painter <jpaint@serv.net>
+ *gdk/gdk.c: reformatted DND code for GTK coding standards
+ *gdk/gdkwindow.c: changed memory allocation for DND to q_mem stuff
+
+Thu Oct 30 Jay Painter <jpaint@serv.net>
+ * gdk/gdkwindow.c:
+ * gdk/gdk/gdk.h:
+ * gtk/gtkwidget.h:
+ * gtk/gtkwidget.c: Applied Stephan Willie's shaped window patch
+
+ * gdk/gdkwindow:
+ * gdk/gdk.h:
+ * gtk/gtkwidget.h:
+ * gtk/gtkwidget.c: reformatted the DND code to conform to GTK
+ coding standards
+
+ * gtk/testgtk: massive fixes, SW's shaped window example
+
+Thu Oct 30 07:33:27 1997 Tim Janik <timj@psynet.net>
+
+ * gtk/gtklistitem.c (gtk_real_list_item_toggle): applied Johannes
+ Keukelaar's <johannes@nada.kth.se> patch for keyboard support in
+ GtkList widgets.
+
+ * gtk/gtkfilesel.c: adapted dir and file list selection
+ behaviour to deal with keyboard selections. this is a little
+ bit tricky: in the dir list it just changes the entrys value on a one
+ button press. but on a keyboard selection via gtk_widget_activate() it
+ does a new population (likewise on a double click) as this seems more
+ obvious.
+
+1997-10-25 Marius Vollmer <mvo@zagadka.ping.de>
+
+ * gdk/gdkcolor.c (gdk_colormap_get_system): Initialize
+ private->ref_count.
+
+Wed Oct 22 09:47:43 1997 Tim Janik <timj@psynet.net>
+
+ * gtk/gtkwindow.c (gtk_window_key_release_event): Fixed a stupid
+ bug that caused the key_release_event to be propagated twice.
+
+Sun Oct 12 11:01:43 1997 Tim Janik <timj@psynet.net>
+
+ * acconfig.h:
+ * configure.in:
+ * gdk/gdkimage.c: Added configure check for IPC_RMID_DEFERRED_RELEASE,
+ because shmat() fails after a shmctl(..., IPC_RMID,...) for OSF1 V3.2,
+ SunOS 4.1.1, 5.5, 5.5.1, 5.6, IRIX 5.2 and 6.2.
+
+Mon Oct 6 11:59:07 1997 Federico Mena <federico@bananoid.nuclecu.unam.mx>
+
+ * gdk/gdk.c (gdk_event_translate): In line 1693, fixed typo that
+ would cause motion notify events not to be delivered.
+
+Sun Oct 5 18:15:06 1997 Federico Mena <federico@bananoid.nuclecu.unam.mx>
+
+ * gtk/gtkrc.c (gtk_rc_parse_bg_pixmap): Changed strdup() for
+ g_strdup().
+
+Wed Sep 24 17:16:34 1997 Peter Mattis <pmattis@bjork.inktomi.com>
+
+ * configure.in: Fixed a stupid error in the test for libXext that
+ would cause it to fail if X_EXTRA_LIBS was not empty.
+
+ * gtk/gtkmain.h (gtk-timj-970919.patch):
+ * gtk/gtkmain.c (gtk-timj-970919.patch): new function
+ `gtk_idle_remove_by_data' to remove all idle callbacks that take a
+ specific piece of data as argument. (gtk_get_current_event):
+ remove idles through gtk_idle_remove_by_data.
+
+ * gtk/gtkwidget.c (gtk-timj-970919.patch):
+ (gtk_widget_destroy): remove pending idles for
+ widgets that have GTK_REDRAW_PENDING or GTK_RESIZE_PENDING and
+ GTK_ANCHORED set (only anchored widgets can have a resize queue
+ handler pending). widgets that have GTK_RESIZE_NEEDED will be removed
+ from their anchored toplevels `resize_widgets' list.
+
+ (gtk_widget_queue_draw): let the widget remember the queue handler
+ tag (through `redraw_handler_key') for later call to `gtk_idle_remove'.
+
+ (gtk_widget_queue_resize): let the widget remember the queue handler
+ tag (through `resize_handler_key') for later call to `gtk_idle_remove'.
+ corrected referencing the toplevel widget for which the handler is
+ pending. if a widget is added to the `resize_widgets' list of a
+ toplevel widget, GTK_RESIZE_NEEDED is set and it's referenced.
+
+ (gtk_real_widget_queue_resize): on the deletion of the `resize_widgets'
+ list, unset GTK_RESIZE_NEEDED and unreference the removed widgets.
+
+ * gtk/gtkwindow.c (gtk-timj-970919.patch):
+ (gtk_real_window_move_resize): move `resize_containers = NULL'
+ initialization out of if-statement.
+ while stepping through the `resize_widgets' list, unreference the
+ widgets and clear GTK_RESIZE_NEEDED. if a widget realy needs are
+ resize, they are flagged through GTK_RESIZE_NEEDED now (instead of
+ GTK_RESIZE_PENDING, as this is indicative for a pending handler).
+ added checks to provide segfaulting if a widgets parent pointer
+ is NULL (e.g. on toplevel widgets that have GTK_RESIZE_NEEDED set).
+
+Tue Sep 23 13:23:27 1997 Federico Mena <federico@bananoid.nuclecu.unam.mx>
+
+ * gdk/gdkimage.c: Applied Tim Janik's patch to mark shm segments
+ as IPC_RMID so that they are automatically removed always.
+
+ * gdk/gdkfont.c: Removed casts from lvalues.
+
+ * gtk/gtkmain.c: Removed GTK_RETLOC_*() (which do a cast) from lvalues.
+
+ * gtk/gtkaccelerator.c (gtk_accelerator_table_remove): Added
+ "const" to the accelerator_key param to be consistent with the
+ declaration in gtkaccelerator.h. The const is not useful in this
+ case, anyway.
+
+Tue Sep 16 13:11:06 1997 Peter Mattis <pmattis@bjork.inktomi.com>
+
+ * gtkpreview.c: Andrew Logan Kieschnick's change to eliminate
+ round-off error when gamma is set to 1.0.
+
+ * gtkrange.c:
+ * gtkviewport.c: Jay Painter's changes to modify the way in which
+ viewports resize.
+
+ * gdkinput.c:
+ * gdkinputgxi.h:
+ * gdkinputxfree.h:
+ * gtk/Makefile.am:
+ * gtk.h:
+ * gtkeventbox.c:
+ * gtkeventbox.h: Owen Taylor's event box widget and fixes for X
+ input support (that I had broken).
+
+ * gdk.h:
+ * gdkwindow.c:
+ * gtksignal.h:
+ * gtksignal.c: Elliot Lee's changes to support Objective C. (id is
+ apparently a reserved word in Objective C).
+
+Sun Sep 14 22:33:15 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwidget.c (gtk_widget_queue_resize): If the toplevel container
+ is invisible we simply call "gtk_container_need_resize" on
+ it. This fixes a bug with option menus not redrawing correctly.
+
+ * gtkmenuitem.c (gtk_menu_item_enter): (gtk_menu_item_leave):
+ These functions now simply pass the event on to their parent. This
+ is necessary for menus to work properly due to the change in how
+ grabs are dealts with.
+
+ * gtkwindow.c (gtk_real_window_move_resize): Fixed a bug that
+ caused the GTK_RESIZE_PENDING flag to not be unset in some cases.
+
+Fri Sep 5 20:49:37 1997 Marius Vollmer <mvo@zagadka.ping.de>
+
+ Bug fixes:
+
+ * Makefile.am: Added PATCHES to EXTRA_DIST.
+ * gtk/gtkpixmap.c (gtk_pixmap_new): Move the "pixmap != NULL" test
+ after the allocation of the pixmap.
+
+ To shut up the compiler:
+
+ * gtk/gtkfilesel.c (get_pwdb): Initialize home_dir.
+ * gtk/gtkmain.c (gtk_init): Replace comments around calls to
+ g_set_*_handler with "if (0)".
+ * gtk/gtkrc.c (gtk_rc_get_token): Initialize hex_number and
+ float_number.
+ * gtk/gtkwindow.c (gtk_window_key_press_event): Initialize
+ direction.
+
+ Changes to the type system in gtk/:
+
+ * Makefile.am: Added gtktypebuiltins.h to gtkinclude_HEADERS.
+ Added gtk.defs, runelisp, gentypeinfo.el and gtktypebuiltins.c to
+ EXTRA_DIST. Added rules to generate gtktypebuiltins.* from
+ gtk.defs.
+
+ * runelisp, gentypeinfo.el, gtk.defs: New files.
+
+ * gtkaccelerator.c, gtkaccelerator.h (gtk_accelerator_table_ref):
+ Return the table so that this function can be used as the `copy'
+ function for GTK_TYPE_BOXED values.
+ * gtkstyle.c, gtkstyle.h (gtk_style_ref): Likewise.
+
+ * gtkenums.h: Removed GtkArgType enum.
+
+ * gtkmain.c (gtk_init): Call gtk_type_init to initialize the type
+ system.
+
+ * gtkobject.c (gtk_object_init_type): New function to take over
+ for gtk_object_get_type. (gtk_object_get_type): Just return the
+ constant GTK_TYPE_OBJECT. (gtk_object_collect_args): Do the right
+ thing for the new GTK_TYPE_* types.
+ * gtksignal.c (gtk_params_get): Likewise.
+
+ * gtktypeutils.c: (gtk_type_init_builtin_types): New
+ function. (gtk_type_init): Call it. Also made non-static.
+ (gtk_type_unique): The allocation scheme for numerical ids has
+ changed: The low 8 bits hold the appropriate GtkFundamentalType of
+ a type, the rest is a globally unique sequence number.
+ (gtk_type_hash): Use the sequence number of a key to hash it.
+ (gtk_type_register_builtin): New function.
+
+ * gtktypeutils.h: (GtkFundamentalType): New enumeration of the
+ fundamental types. (GTK_TYPE_MAKE, GTK_FUNDAMENTAL_TYPE,
+ GTK_TYPE_SEQNO): New macros to work with the new id scheme.
+ (GtkArg): Added fields for new types and renamed old ones. GtkArg
+ should now be a mostly opaque structure, except name and type.
+ (GTK_VALUE_*): New macros to access the values of a GtkArg.
+ (GTK_RETLOC_*): New macros to access the location of a return
+ value that is contained in a GtkArg. * gtktypebuiltins.h: New
+ file to access the typeids of the builtin types.
+
+ * gtkwidget.h (GTK_TYPE_WIDGET): New macro to access the type id
+ of the widget class.
+
+ Thru out: Changed GTK_ARG_* to the appropriate GTK_TYPE_*.
+ Changed access to GtkArg structure to the appropriate GTK_VALUE_*
+ or GTK_RETLOC_* macro. Changed GtkArgType to GtkType. Changed
+ some guints to GtkType.
+
+ General changes in gtk/ to support interpreters:
+
+ * gtkradiobutton.c (gtk_radio_button_new_from_widget,
+ gtk_radio_button_new_with_label_from_widget): New functions.
+
+ * gtksignal.c (gtk_signal_connect_no_marshal): New function.
+ (struct _GtkHandler): Added no_marshal and destroy_func fields.
+ (gtk_signal_handler_new): Initialize them.
+ (gtk_signal_connect_by_type): Added no_marshal and destroy_func
+ arguments. Changed all callers.
+ (gtk_signal_destroy): Invoke destroy_func if there is one and the
+ global destroy func does not apply. (gtk_handlers_run): If the
+ handler has no_marshal set, call its function directly without
+ going thru the signal's marshaller.
+
+Wed Sep 3 09:56:22 1997 RHS Linux User <pmattis@bjork.inktomi.com>
+
+ * gtkrange.c: Changed the way the range control focus was drawn so
+ that the range control is drawn correctly when it does not have
+ the focus.
+
+Tue Sep 2 17:41:17 1997 RHS Linux User <pmattis@bjork.inktomi.com>
+
+ * gtkwidget.c: 'gtk_real_widget_queue_resize' should only remove
+ the "resize_widgets" if another resize is not pending.
+
+Mon Sep 1 18:28:08 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmain.c: Changed the way GDK_DELETE events are handled. Only,
+ if 'gtk_widget_event' returns TRUE is the widget destroyed. By
+ default, 'gtk_widget_event' will return FALSE causing the window
+ to not be destroyed. This prevents segfaults in the GIMP and other
+ programs that do not correctly handle GDK_DELETE events.
+
+ * gtkmain.c: Added modal dialog support by allowing events
+ destined for a child of the grab widget to go to the child instead
+ of the grab widget. (Added 'gtk_widget_is_ancestor' to determine
+ the relationship between the grab widget and the event widget).
+
+ * *.[ch]: Incorprated a whole mess of patches. (Started keeping
+ the ChangeLog up to date again).
+
+Thu Jun 5 17:22:21 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenufactory.c:
+ * gtkmenufactory.h: Added 'gtk_menu_factory_remove_*'
+ calls. Removing entries/paths causes the associated widgets to be
+ destroyed.
+
+ * gtkwidget.c:
+ * gtkwidget.h: Calling 'gtk_widget_set_style' is used as an
+ indication that the programmer specifically wants that style to be
+ used. RC-style substitution is disabled for the widget after such
+ a call.
+
+ * gtkpixmap.c:
+ * gtkpixmap.h:
+ * gtkimage.c:
+ * gtkimage.h: Changed to use clip mask and a single pixmap (or
+ image) to deal with transparent areas.
+
+ * gdkpixmap.c: Modified xpm loading routines to optionally return
+ a clip mask.
+
+ * gdkgc.c:
+ * gdkdraw.c:
+ * gdktypes.h: Modifications to allow clip masks to be used with
+ gc's. Clip masks are bitmaps that specify drawable regions.
+
+Thu May 1 03:11:51 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkscrolledwindow.c: Scrolled windows need to have the
+ GTK_NO_WINDOW flag set. Not having it set caused an obscure
+ redrawing bug.
+
+Wed Apr 30 12:38:03 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkhruler.c:
+ * gtkvruler.c: Fixed a small bug that caused the indicator to be
+ positioned slightly off.
+
+Sun Apr 27 14:28:21 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenushell.c:
+ * gtkmenushell.h:
+ * gtkmenu.c:
+ * gtkmenu.h: Changes so that if a menu is popped up there is a
+ timeout period during which a menu item will not be activated and
+ if the mouse button is released in that period the menu will stay
+ popped up.
+
+ * gtkcurve.c:
+ * gtkcurve.h: Included curve widget courtesy of David
+ Mosberger-Tang (davidm@azstarnet.com).
+
+ * gtkentry.c:
+ * gtkentry.h: Changed "insert" and "delete" signals to
+ "insert_text" and "delete_text" respectively. (The symbol "delete"
+ cannot be used since it is a C++ reserved word).
+
+Sat Apr 19 01:43:49 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenufactory.c: A path which ends in "<nothing>" will cause an
+ invisible (hidden) menu entry to be created. This is useful for
+ setting an accelerator key for which a corresponding menu entry is
+ not desired.
+
+ * gtktooltips.c: Fixed some problems with destruction of the
+ active tip widget not properly updating the tooltips data
+ structures.
+
+Fri Apr 18 15:09:45 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkcontainer.c:
+ * gtklist.c:
+ * gtkwidget.c:
+ * gtkwidget.h: Patch from Owen Taylor (owt1@cornell.edu) which
+ fixes problems with destruction of objects and with destruction of
+ objects which hold the focus.
+
+Thu Apr 17 11:29:15 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenushell.c: Incorrect logic in
+ 'gtk_menu_shell_button_release' for deciding when a menu should
+ stay popped up when the mouse button is released.
+
+ * *.c: Miscellaneous fixes from folks on the net.
+
+Tue Apr 15 02:43:17 1997 Peter Mattis <pmattis@localhost>
+
+ * *.c:
+ * gtkwidget.h: Added GTK_BASIC widget flag which when set
+ specifies a widget as "basic". A "basic" widget is one which
+ doesn't take input events. For example, labels, pixmaps, boxes,
+ tables, alignments, etc.
+
+Sat Apr 12 15:23:08 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkcolorsel.c: Add "#include <math.h>" to define M_PI.
+
+ * gtksignal.c: Fixed a bug in 'gtk_signal_emit' which showed up
+ because of the new cast checking macros. The 'object' was being
+ accessed after it had been destroyed.
+
+ * gtkoptionmenu.c: Fixed bug with using 'GTK_BIN' instead of
+ 'GTK_BUTTON' which showed up because of the new cast checking
+ macros.
+
+ * *.h: 'GTK_CHECK_CAST', 'GTK_CHECK_CLASS_CAST' and
+ 'GTK_CHECK_TYPE' used by standard widget macros everywhere.
+
+Wed Apr 9 00:54:17 1997 Peter Mattis <pmattis@localhost>
+
+ * docs/gtk.texi: Started further work on documentation. Major
+ changes and additions are being made.
+
+ * gtkarrow.c:
+ * gtkarrow.h: Removed function 'gtk_arrow_get'.
+
+ * gtkcontainer.c: 'gtk_container_check_resize' no performs
+ additional checking to account for the case where the containers
+ allocation is no longer sufficient because its parent (or its
+ parents parent, etc.) needs to resize its children.
+
+Tue Apr 8 21:15:50 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkstyle.c: Fixed a bug in 'gtk_style_init' in which the font
+ was not ref'd (via 'gdk_font_ref'), but was free'd (via in
+ 'gdk_font_free') in 'gtk_style_destroy'. (David
+ Mosberger-Tang). Also cleaned up 'gtk_style_destroy' while I was
+ at it.
+
+ * gtkmain.c: Fixed a bug in 'gtk_propogate_event' which caused
+ entry widgets (and probably other widgets) not to be destroyed in
+ some instances.
+
+Mon Apr 7 01:20:38 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkentry.c:
+ * gtkentry.h: Changed the "insert_text", "delete_text" and
+ "changed_text" signals to "insert", "delete", and "changed"
+ respectively. They really should have been named this way
+ originally except the previous signal mechanism prevented
+ duplicate signal names. ("changed" is also used by adjustments).
+
+ * gtkradiomenuitem.c:
+ * gtkradiomenuitem.h: New widget.
+
+ * gtkcheckmenuitem.c:
+ * gtkcheckmenuitem.h: New widget.
+
+ * gtksignal.c: Modified 'gtk_signal_lookup' to require an object
+ type to be passed as a parameter. In addition, signals are now
+ only needed to be uniquely defined in their branch of the class
+ hierarchy. This allows the same signal name to be used in two
+ different branches of the class hierarchy. For instance, the
+ "changed" signal is used both by adjustments and entries...in
+ different ways!
+
+ * gtktypeutils.c: Added 'gtk_type_parent' which returns the parent
+ type for a given type.
+
+Sun Apr 6 22:08:35 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwidget.c: If a widget is set insensitive it loses the focus
+ if it had it.
+
+ * gtkcontainer.c: Insensitive widgets no longer participate in tab
+ traversal.
+
+ * gtkscrolledwindow.c: The "viewport" child is now destroyed and a
+ container class "foreach" function was written (which fixes the
+ sensitivity bug).
+
+Sat Apr 5 14:25:38 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkhscrollbar.c:
+ * gtkvscrollbar.c: Fixed trough size allocation bug.
+
+ * gtkhscale.c:
+ * gtkvscale.c: Fixed trough size allocation and position bug that
+ showed up when scales were placed in notebooks.
+
+Thu Mar 27 17:45:54 1997 David Mosberger-Tang <davidm@azstarnet.com>
+
+ * gtk/gtkmain.c (gtk_handle_idle): Fix appending pending_idles to
+ idle_functions so it works even when idle_functions is empty.
+
+Sat Mar 15 14:15:59 1997 Peter Mattis <pmattis@localhost>
+
+ * *.[ch]: Moved '*_class_init' and '*_init' function declarations
+ for widgets into the source file as those functions no longer had
+ to be public.
+
+ * gtkcheckbutton.c: Fixed redrawing of check button.
+
+ * gtkframe.c: Fixed redrawing of frame when the shadow type is
+ changed.
+
+Sat Mar 8 15:19:23 1997 Peter Mattis <pmattis@localhost>
+
+ * gdkimage.c: Fixed a stupid bug with 'gdk_image_new' which
+ potentially added a NULL image to "image_list" and caused problems
+ when 'gdk_image_exit' was called.
+
+Wed Mar 5 00:40:08 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkpreview.c: Massively changed the colormap handling used by
+ the preview widget. Gray previews are now dithered. A single
+ visual and colormap is shared by the color and gray previews. A
+ GTK_PREVIEW_INFO property is installed on the root window in
+ certain cases to allow multiple GTK programs to share the system
+ colormap.
+
+Sun Mar 2 05:43:06 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkcheckbutton.c: 'gtk_checkbutton_size_allocate' was allocating
+ too much space to its children and not leaving the check button
+ room for the focus border.
+
+ * gtknotebook.c: 'gtk_notebook_size_request' wasn't requesting
+ enough space when the notebook tabs are visible.
+
+Sat Mar 1 01:59:35 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkpreview.c: Fixed a problem with 'gtk_preview_put' when the
+ image byte order is GDK_MSB_FIRST.
+
+ * gtksignal.c:
+ * gtksignal.h: Added 'gtk_signal_connect_after' and
+ 'gtk_signal_connect_object_after' functions. These connect signal
+ handlers which will run after the class function associated with
+ the signal.
+
+ * gtkstyle.c: Fixed a stupid bug in 'gtk_style_new_from_key' that
+ was causing twice as many styles to be created as necesary.
+
+ * gtkwidget.c: 'gtk_real_widget_size_allocate' erases the widgets
+ old allocation if it has the GTK_NO_WINDOW flag set.
+
+ * gtkwidget.c: 'gtk_real_widget_unmap' now erases the widget if it
+ has the GTK_NO_WINDOW flag set.
+
+ * gtklabel.c: Removed 'gtk_label_unmap' as similar functionality
+ was added to gtk_real_widget_unmap.
+
+ * gtkbin.c: Modified 'gtk_bin_map' and 'gtk_bin_unmap' so that it
+ erases and draws the widget if it has the GTK_NO_WINDOW flag set.
+
+ * gtkframe.c: Modified 'gtk_frame_size_allocate' so that it erases
+ the old allocation.
+
+Fri Feb 28 03:27:05 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwindow.c: 'gtk_window_set_title' now changes the window title
+ if the window is already realized.
+
+ * gtkentry.c: 'gtk_entry_set_text' was emitting both a
+ "delete_text" and a "changed_text" signal. Modified so that it
+ only emits a "changed_text" signal.
+
+ * gtkpreview.c: Modified to work correctly on systems with MSB
+ byte order. The colormap for TRUE and DIRECT color displays is now
+ created if the default visual is not equal to the visual we are
+ using.
+
+ * gtkstyle.c: 'gtk_style_attach' and 'gtk_style_find' weren't
+ working properly in the presence of multiple colormaps are
+ different depth visuals.
+
+ * gtkcontainer.c: Massively improved focus traversal using tab and
+ arrow keys. It now uses the layout of the widgets to determine
+ where to move the focus to.
+
+Mon Feb 24 03:24:02 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenufactory.c: Set the accelerator table field for menus when
+ they are created.
+
+ * gtkmenu.c:
+ * gtkmenu.h: Added a default accelerator table field to menus so
+ that runtime modification of accelerator keys in menus can work
+ better.
+
+ * gtkrange.c: 'gtk_range_default_{h,v}motion' had faulty logic for
+ deciding what to do when the slider was at the edge of the
+ trough. They previously didn't update the adjustment value event
+ if the value wasn't what it should be when the slider was at the
+ edge of the trough.
+
+ * gtkviewport.c: 'gtk_viewport_size_allocate' and
+ 'gtk_viewport_adjustment_value_changed' both had the potential for
+ performing a divide by 0. Checks are now in place to prevent this.
+
+ * gtkmenu.c: 'gtk_menu_map' now makes sure the menu lies on screen
+ if the position function is NULL.
+
+ * gtkentry.c: Modified selection handling. 'gtk_delete_selection'
+ actually removes the X selection now. 'gtk_entry_destroy' removes
+ the selection as well and relies on the change in "gdk.c" to make
+ sure the selection event will not be sent to a non-existant
+ window.
+
+ * gdk.c: Selection events are only passed on if the selection
+ owner is not NULL.
+
+ * gtkstyle.c: 'gtk_style_detach' and 'gtk_style_destroy' were not
+ destroying the black and white gc's.
+
+Sun Feb 23 19:17:56 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwindow.c: 'gtk_window_size_request' was setting the window
+ hints. This was also being done in 'gtk_window_map', so the
+ instance being done in 'gtk_window_size_request' was removed.
+
+Fri Feb 21 01:04:01 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwidget.c: 'gtk_widget_draw' has to use the widgets allocated
+ position for the drawing rectangle when the widget has the
+ GTK_NO_WINDOW flag set.
+
+ * gtkwidget.c: In 'gtk_widget_init' the visual and colormap were
+ being directly compared against 'default_visual' and
+ 'default_colormap' instead of calling
+ 'gtk_widget_get_default_{visual,colormap}'.
+
+ * gdkrectangle.c: Amazing! There was a bug in the
+ 'gtk_rectangle_intersect' logic. Its been there for near eternity
+ and I never noticed.
+
+ * gtkpreview.c:
+ * gtkpreview.h: Created preview widget which allows drawing to an
+ rgb or grayscale buffer which is automatically displayed on the
+ screen. Performs dithering as necessary.
+
+Thu Feb 20 20:33:21 1997 Peter Mattis <pmattis@localhost>
+
+ * gdkwindow.c: Modified the logic in 'gdk_window_new' which
+ determined when to add a window to the WM_COLORMAP_WINDOWS
+ property.
+
+Wed Feb 19 19:55:29 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkruler.c: 'gtk_ruler_make_pixmap' was always destroying the
+ old backing store and creating a new one even when it would create
+ a new one of exactly the same size as the old one.
+
+Tue Feb 18 18:32:10 1997 Peter Mattis <pmattis@localhost>
+
+ * gmem.c: 'g_mem_chunk_alloc' was incorrectly modifying the mem
+ areas free mem field when reallocating a previously freed
+ atom. This caused a fairly severe memory leak.
+
+ * gtkmenushell.c: 'gtk_menu_shell_button_release' had a bug in the
+ logic for deciding whether to initiate an X pointer grab or not
+ when the mouse button was released. It now only initiates a grab
+ if the mouse is released within an active menu item.
+
+Fri Feb 14 00:57:40 1997 Peter Mattis <pmattis@localhost>
+
+ * gtknotebook.c: Changed the look of notebook tabs slightly.
+
+ * gtkentry.c:
+ * gtkentry.h: Deleting an entry widget which is holding the X
+ selection presents some difficulties. The X selection must be
+ released, but the widget can't be destroyed until the
+ SELECTION_CLEAR event is received that the X server will send in
+ response to clearing the X selection. There are probably still
+ bugs in the current method of entry widget deletion when the X
+ selection is held.
+
+ * gtkmain.c: 'gtk_propagate_event' was not properly destroying the
+ toplevel window when receiving a key press event.
+
+ * gtkwidget.c: Setting a widget insensitive did not cause it to
+ redraw. It now does.
+
+Thu Feb 13 16:59:07 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkviewport.c: 'gtk_viewport_size_allocate' was allocating its
+ child widget an adjusted allocation. Since the actual scrolling
+ has handled by a subwindow this caused the child to be double
+ scrolled. Modified to always set the child allocations origin to
+ (0, 0).
+
+Wed Feb 12 01:06:48 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkentry.c: Text is now centered vertically. Previously it was
+ pushed up against the top. This problem was only evident when the
+ widget was allocated more vertical space than it requested.
+
+ * gtkfilesel.c: 'gtk_file_selection_key_press' was previously only
+ a stub for tab completion. The actual tab completion call had been
+ left out. (Oops!)
+
+Tue Feb 11 01:43:08 1997 Peter Mattis <pmattis@localhost>
+
+ * gtksignal.c: 'gtk_signal_disconnect_by_data' was going into a
+ loop and crashing. Bad logic. Fixed.
+
+ * gtkmain.c: An idle function which returns FALSE will be removed
+ from the list of idle functions. This makes the functioning of
+ idle functions and timeouts more similar.
+
+ * gtkentry.c: 'gtk_entry_get_text' now returns an empty string
+ when the actual text is NULL. This allows "stupid" programs to use
+ the value returned by 'gtk_entry_get_text' blindly (without
+ checking to see if its NULL).
+
+ * gtkradiobutton.c: Modified 'gtk_radio_button_clicked' so that
+ 'gtk_toggle_button_toggled' is called _after_ the widget state is
+ changed.
+
+ * gtksignal.c:
+ * gtksignal.h: Added 'gtk_signal_name' which returns the character
+ string name for a given signal number.
+
+ * gtkwidget.c: 'gtk_widget_set_parent' checks to see if the widget
+ is now "anchored" through the parent chain to a widget which is
+ GTK_ANCHORED. If it is, then it changes the widgets style using
+ 'gtk_rc_get_style' and recursively performs the same operation on
+ the widgets children. This is necessary is 'gtk_rc_get_style' only
+ works properly on "anchored" widgets.
+
+ * gtkwindow.c: Modified GTK_WIN_POS logic so that it is only used
+ immediately after the window has been shown.
+
+ * gtkmenu.c: 'gtk_menu_key_press'. Can now change menu item
+ accelerator keys on the fly. Why? Why not. Cool/useless feature of
+ the day.
+
+ * gtkmenuitem.c: Accelerator key drawing. Somehow that never got
+ finished. (Oops!)
+
+ * gtkdrawingarea.c: 'gtk_drawing_area_size_allocate' was not
+ actually installed during 'gtk_drawing_area_class_init'. (Oops!)
+
+ * gtkframe.c: 'gtk_frame_size_request' fixed size requisition
+ problem caused by unsigned arithmetic.
+
+ * gtkwindow.c: Modified window widget so that it only uses the
+ widget uposition auxiliary information immediately after it has
+ been shown. This prevents the annoying bug which can cause a
+ uposition'ed window to jump back to its original position after
+ the user moves it.
+
+ * gtkwidget.c: Need to ref and unref style in
+ 'gtk_widget_{push,pop}_style' to make sure that a style on the
+ style stack is not destroyed.
+
+ * gtktogglebutton.c: 'gtk_toggle_button_set_state' now calls
+ gtk_button_clicked to actually change the state of the
+ button. In this way, radio buttons can now perform the appropriate
+ actions when the toggle button state is set.
+
+Mon Feb 10 00:27:39 1997 Peter Mattis <pmattis@localhost>
+
+ * gtklist.c: 'gtk_list_select_item' and 'gtk_list_unselect_item'
+ were casting a GList* variable to a a GtkWidget* variable. Bad bad
+ bad. (Tim Janik).
+
+ * gtksignal.c: Modified 'gtk_signal_connect' and
+ 'gtk_signal_connect_object' to warn when a signal type cannot be
+ found.
+
+Sun Feb 9 00:15:30 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkoptionmenu.c:
+ * gtkoptionmenu.h: Changed option menus back to being derived from
+ buttons. This fixes up some screwiness with their user
+ interaction.
+
+ * gtkwindow.c: Modified key press handler to support focus
+ traversal.
+
+ * gtkcontainer.c:
+ * gtkcontainer.h: Added default focus traversal back in.
+
+Sat Feb 8 10:44:38 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkviewport.h:
+ * gtkviewport.c: Massively sped up viewport scrolling. Used to be
+ reallocating child's size (offset) each time a scrollbar
+ moved. Now a subwindow is moved. All the children are moved
+ automatically by moving the subwindow. Much much much faster.
+
+Tue Feb 4 00:20:44 1997 Peter Mattis <pmattis@localhost>
+
+ * gtree.c: Changed 'g_tree_node_search' to use a loop instead of
+ recursion.
+
+Mon Feb 3 11:30:03 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkbutton.c: Removed 'parent_destroy' global and replaced it
+ with 'parent_class' global to reflect style used in other
+ widgets.
+
+ * gtknotebook.c: Tab labels were being allocated less than their
+ requested size.
+
+ * gtkrange.c:
+ * gtkrange.h: Moved the "digits" field of scales into the range
+ type. The adjustment value for scales is truncated to the number
+ of visible digits instead of being left untouched.
+
+ * gtree.c: Fixed a bug in the AVL tree implementation. Single
+ rotations were always being performed during insertion. It is
+ sometimes necessary to perform a double rotation.
+
+ * gtklabel.c: Modified 'gtk_label_expose' to only draw the label
+ when the allocated space is greater than or equal to the requested
+ space.
+
+ * gtklabel.c: Added call to 'gtk_widget_unmap' to
+ 'gtk_label_destroy' in order for the label to redraw correctly
+ (erase itself) when destroyed.
+
+ * gtklabel.c: Added 'gtk_label_unmap' call which erases the labels
+ allocation when it gets unmapped.
+
+ * *.h: Removed a few remaining instances of using "class" as a
+ parameter name. (Causes problems for C++).
+
+Fri Jan 31 12:26:50 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkcontainer.c: 'gtk_container_enable_resize' needs to call
+ 'gtk_container_check_resize' instead of
+ 'gtk_container_need_resize'.
+
+ * gtkwidget.c: 'gtk_real_widget_show' now maps the widget if its
+ parent is mapped.
+
+ * gtkscrolledwindow.c: Fixed size allocation when the scrollbar
+ policy's are GTK_POLICY_AUTOMATIC. Doing it correctly is harder
+ than I originally thought.
+
+ * gtklist.c: Added 'gtk_list_child_position' to determine the
+ integer position in a list of a child. Filled in the
+ 'gtk_list_item_select' and 'gtk_list_item_unselect' stubs.
+
+Thu Jan 30 16:08:06 1997 Peter Mattis <pmattis@localhost>
+
+ * gmem.c: Changed the implementation of G_ALLOC_AND_FREE mem
+ chunks. They used to allocate SIZEOF_VOID_P extra bytes per atom
+ in order to keep track of which mem area they were allocated
+ from. Now the mem area is determined by searching through an AVL
+ tree of the mem areas for a mem chunk and comparing memory
+ locations. A little slower, but makes G_ALLOC_AND_FREE mem chunks
+ much more attractive.
+
+ * gtree.c: Added an AVL tree implementation to glib.
+
+ * gtksignal.c:
+ * gstring.c: va_arg (arg_list, {char, short}) is
+ invalid. Arguments passed in a variable argument list are
+ promoted. ({char, short}->int). Seemed to work ok before under
+ Linux. Crashed under FreeBSD.
+
+Tue Jan 28 02:27:51 1997 Peter Mattis <pmattis@localhost>
+
+ * gdkwindow.c: Fixed a major slowdown apparent in the file
+ selection dialog which was caused by calling
+ 'gtk_window_add_colormap_windows' way way way too often.
+
+ * *.c: Many widgets called 'gtk_container_need_resize' when
+ something internal changed which would cause the widget to grow or
+ shrink. The assumption was made that the widget would change size
+ and an expose event would be generated. This happens "most" of the
+ time. But its possible for certain widgets to change size without
+ generating expose events, or for its internal geometry to change
+ without a change of size which would mean no expose event was
+ generated. So a wrapper function called
+ 'gtk_container_check_resize' was created and
+ 'gtk_container_need_resize' was modified so that it returns FALSE
+ if a resize was actually generated and TRUE if nothing
+ changed. This allows 'gtk_container_check_resize' to initiate a
+ 'gtk_widget_size_allocate' and 'gtk_widget_draw' to emulate the
+ expose event.
+
+Sat Jan 25 14:17:44 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmain.c: Fixed a bug with propogating key press events. The
+ events were sent 2 times to the toplevel windows which caused the
+ focus widget to be activated twice when the space bar was pressed.
+
+ * */configure.in:
+ * */Makefile.am: Added support for libtool and removed the old
+ shared library configuration craziness.
+
+Fri Jan 24 12:59:22 1997 Peter Mattis <pmattis@localhost>
+
+ * gtktext.c:
+ * gtktext.h: Josh's fixes and additions to the text widget.
+
+ * gtkfill.c:
+ * gtkfill.h: Filler widget useful for filling space in a
+ table. Can specify a minimum size. Used by the canvas widget.
+
+ * gtknotebook.c:
+ * gtknotebook.h: Made outline of notebook widget.
+
+ * gtkcanvas.c:
+ * gtkcanvas.h: Started canvas widget. A composite of 2 rulers (w/
+ an origin), 2 scrolllbars. Guides, grids, snap to.
+
+Sun Jan 19 18:26:45 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkdialog.c:
+ * gtkdialog.h: Created dialog widget which creates a standard
+ looking dialog with buttons along the button and a separator.
+
+ * gtkxid.c: Generalized the window table code for looking up a gdk
+ window based on an XID to work for any XID and a piece of
+ data. Can now look up gdk fonts based on their XID.
+
+ * gtkruler.c:
+ * gtkruler.h:
+ * gtkhruler.c:
+ * gtkhruler.h:
+ * gtkvruler.c:
+ * gtkvruler.h: Started conversion of the ruler widget.
+
+ * gtktext.c:
+ * gtktext.h: Started conversion of the text widget. Scrolling
+ doesn't work.
+
+ * gtkmain.c: Fixed a fairly major bug. The event widget needs to
+ be in a call for the entire duration of handling an event. Not
+ just for when the event widget itself is handling the event.
+
+ * gtkfilesel.c: Fixed up some bugs with resizing.
+
+Fri Jan 10 14:18:03 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwidget.c:
+ * gtkwidget.h:
+ * gtkentry.c:
+ * gtkentry.h: Support for selections.
+
+ * gdkselection.c:
+ * gdk.c:
+ * gdktypes.h:
+ * gdk.h: Gdk support for X selections. Currently only text
+ selections are supported.
+
+ * gtksignal.c: Fixed a major bug which occurred when destroying an
+ object. Memory was being written to after it was freed.
+
+ * gtkfilesel.c:
+ * gtkfilesel.h: Hooked up more functionality to the file selection
+ dialog.
+
+Wed Jan 8 18:13:53 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkfilesel.c:
+ * gtkfilesel.h: Mostly converted old file selection dialog
+ widget. The widget is derived from the GtkWindow class and is
+ quite a bit simpler in the widget code.
+
+ * gtkwidget.c: Fixed 'gtk_widget_grab_focus' and
+ 'gtk_widget_grab_default' to check that the toplevel widget is a
+ type of window (which includes classes derived from windows).
+
+Tue Jan 7 01:12:32 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkwindow.c: Was calling 'gtk_window_resize' twice in a
+ row...why?
+
+ * gtksignal.c:
+ * gtksignal.h:
+ * *.c: Changed 'gtk_signal_new' so that the class function that is
+ called when the signal is emitted can be called either before,
+ after or both before and after the calling of any signal
+ handlers.
+
+ * gtkobject.c:
+ * gtkobject.h: Added 'object_data' mechanism for storing data
+ associated with a character string key in objects. Removed
+ 'user_data' field of objects and changed
+ 'gtk_object_{get,set}_user_data' to use the object data
+ mechanism. Removed 'handlers' field of objects.
+
+ * gtkwidget.c:
+ * gtkwidget.h:
+ * gtkwindow.c: Modified aux info mechanism to use object data
+ mechanism.
+
+ * gtksignal.c: Modified signal mechanism to use object data
+ mechanism instead of 'handlers' field.
+
+
+Mon Jan 6 15:10:16 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenushell.c: Fixed up button press handling so as to conform
+ more closely to that used by Motif.
+
+Wed Jan 1 21:27:17 1997 Peter Mattis <pmattis@localhost>
+
+ * gtkmenu.c:
+ * gtkmenu.h:
+ * gtkmenubar.c:
+ * gtkmenubar.h:
+ * gtkmenushell.c:
+ * gtkmenushell.h: Reorganization of menu-ing code so that code
+ duplication is reduced. The menu shell now contains most of the
+ code for menu-ing interaction while menus and menubars simply layout
+ their child menu items in the appropriate place.
+
+Sun Dec 29 17:48:18 1996 Peter Mattis <pmattis@localhost>
+
+ * gtkmenu.c:
+ * gtkmenubar.c:
+ * gtkmenuitem.h:
+ * gtkmenuitem.c: Modifications so that menu item accelerators and
+ the submenu indicator are drawn correctly and the correct amount
+ of space is allocated.
+
+Sat Dec 28 00:32:13 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * gtkmenufactory.h:
+ * gtkmenufactory.c: Started menu factories as an easy method to
+ create and manipulate menus.
+
+Fri Dec 27 13:17:34 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * gtkmenu.c:
+ * gtkmenu.h:
+ * gtkmenubar.c:
+ * gtkmenubar.h:
+ * gtkmenuitem.c:
+ * gtkmenuitem.h:
+ * gtkmenushell.c:
+ * gtkmenushell.h: Implemented basic menu functionality. Menubars
+ and popup menus work. Submenus work. (Much left to be done).
+
+Wed Dec 18 15:27:05 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * gtktypeutils.h:
+ * gtktypeutils.c: Added 'gtk_type_from_name' which returns a type
+ identifier given a type name. Implemented using a second hash
+ table keyed by type names.
+
+ * gtkbutton.c:
+ * gtktogglebutton.c: Fixed very small messed-up drawing bug when a
+ button loses its focus.
+
+ * gtkwidget.h:
+ * gtkwidget.c:
+ * gtkbutton.c:
+ * gtkwindow.c: Added default button handling. Default buttons now
+ draw correctly and pressing return or enter causes the default
+ button (if one exists) to be activated.
+
+Tue Dec 17 19:32:21 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * gtkhscale.c:
+ * gtkvscale.c: Overrode 'draw_slider' method of ranges in order to
+ draw the slider of scales with a line in them so as to be closer
+ to the Motif look-and-feel.
+
+ * gtkwindow.c: Modified 'gtk_window_focus_in_event' so that focus
+ in events are only handled when the window is visible. Fixes a bug
+ where spurious focus in events get sent when a window is being
+ hidden.
+
+ * gtkwidget.h: Added 'activate_signal' field to the GtkWidgetClass
+ structure. Added 'gtk_widget_activate' call to emit the activate
+ signal for a widget if it is non-zero.
+
+Tue Dec 10 15:59:45 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * gtkwidget.c: 'gtk_widget_set_name' oops in strdup'ing the old
+ "widget->name" instead of the new one we are setting.
+
+ * gtkrc.c: 'gtk_rc_widget_path' changed to use
+ 'gtk_widget_get_name' instead of accessing the "widget->name"
+ field directly.
+
+ * gtkwidget.c: Added 'gtk_widget_get_name' function which returns
+ the widgets name if it exists and the widgets type name if it does
+ not.
+
+ * gtkcheckbutton.c: Added 'gtk_check_button_draw'
+ function. Modified 'gtk_check_button_expose' to pass an expose
+ event to child instead of callings its draw function.
+
+ * gtkentry.c: 'gtk_entry_draw_text' why was "+1" being added to
+ the font->ascent to calculate the font position? This was wrong
+ and caused some characters in fonts to be clipped. (Notably "g").
+
+ * gtkentry.c: 'gtk_entry_realize' specify GTK_BUTTON1_MOTION_MASK
+ and GTK_POINTER_MOTION_HINT_MASK for _both_ windows.
+
+ * gtkmain.c: 'gtk_propagate_event' needs to set the GTK_IN_CALL
+ flag for the object before calling 'gtk_widget_event' and needs to
+ destroy the object if necessary after 'gtk_widget_event' returns.
+
+ * gtkradiobutton.c: 'gtk_radio_button_clicked' needs to call
+ 'gtk_toggle_button_toggled' when the currently active button is
+ toggled.
+
+ * gtkwidget.c: 'gtk_real_widget_hide' needs to call
+ 'gtk_widget_unmap' if the widget is currently mapped.
+
+ * gtkwindow.c: Prevent automatic resizing after the user has
+ specified a new window size. Add 'handling_resize' flag to
+ windows.
+
+ * gtkscrolledwindow.c: Implement the GTK_POLICY_AUTOMATIC
+ scrollbar policy. Need to connect to the adjustments 'changed'
+ signal and notice when the scrollbars aren't in use.
+
+ * gtkcontainer.c: 'gtk_container_init' must set 'auto_resize' and
+ 'need_resize' fields to TRUE and FALSE respectively.
+
+ * gtkwidget.c: 'gtk_widget_set_parent' must all set a widgets state
+ to its parents state.
+
+Sun Dec 1 01:31:01 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * Started ChangeLog
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/INSTALL
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 000000000..8f24c51eb
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,30 @@
+## Process this file with automake to produce Makefile.in
+
+SRC_SUBDIRS = glib gdk gtk
+SUBDIRS = $(SRC_SUBDIRS) docs
+
+EXTRA_DIST = gtk+.prj makecopyright TODO
+
+.PHONY: files populate checkin release
+
+files:
+ @files=`ls $(DISTFILES) 2> /dev/null `; for p in $$files; do \
+ echo $$p; \
+ done
+ @for subdir in $(SUBDIRS); do \
+ files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \
+ for file in $$files; do \
+ echo $$subdir/$$file; \
+ done; \
+ done
+
+populate:
+ @echo "populating project"
+ @files=`$(MAKE) files | grep -v "make\[[1-9]\]"`; prcs populate -d gtk+.prj $$files
+
+checkin: populate
+ @echo "checking in project"
+ @prcs checkin
+
+release:
+ $(MAKE) dist distdir=$(PACKAGE)`date +"%y%m%d"`
diff --git a/NEWS b/NEWS
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/NEWS
diff --git a/README b/README
new file mode 100644
index 000000000..728cf38a5
--- /dev/null
+++ b/README
@@ -0,0 +1,17 @@
+
+The official ftp site is:
+ ftp://ftp.gimp.org/pub/gtk
+
+Patches can be uploaded to:
+ ftp://ftp.gimp.org/incoming
+
+Anonymous CVS access for gtk+ (as well as 'gimp', 'gimp-data', and
+'gnome') is available via
+ CVSROOT=:pserver:anonymous@cvs.gnome.org:/home/cvs
+with an empty password.
+
+A mailing list is located at:
+ gtk-list@redhat.com
+
+To subscribe: mail -s subscribe gtk-list-request@redhat.com < /dev/null
+(Send mail to gtk-list-request@redhat.com with the subject "subscribe")
diff --git a/TODO b/TODO
new file mode 100644
index 000000000..8c1af4d12
--- /dev/null
+++ b/TODO
@@ -0,0 +1,36 @@
+Now
+---
+
+3. Fix focus activation of list items. Does list item activation have to be
+ completely reorganized?
+
+4. Lists should scroll to center the recently selected item if it isn't
+ visible.
+
+
+The Future
+----------
+
+-Documentation
+
+-Tree widget
+
+-Text widget (needs to be finished)
+
+-Widget redrawing when the window resizes sometimes messes up.
+
+-Make sure a widget added to a list is a list item and a widget added
+ to a menu is a menu item, etc...
+
+-More dialogs? Print, font, etc?
+
+-Multiple document interface (MDI)?
+
+-Support another widget style? Should be possible using GtkStyle's, but
+ there may be some work needed to remove any style dependencies in widget
+ code. Maybe GtkStyle's should have 'draw_push_button', 'draw_check_button',
+ etc, functions to draw the various widgets.
+
+-OffiX drag and drop support
+
+-Make all widget attributes configurable after the widget is created.
diff --git a/acconfig.h b/acconfig.h
new file mode 100644
index 000000000..be2cb542c
--- /dev/null
+++ b/acconfig.h
@@ -0,0 +1,47 @@
+/* acconfig.h
+ This file is in the public domain.
+
+ Descriptive text for the C preprocessor macros that
+ the distributed Autoconf macros can define.
+ No software package will use all of them; autoheader copies the ones
+ your configure.in uses into your configuration header file templates.
+
+ The entries are in sort -df order: alphabetical, case insensitive,
+ ignoring punctuation (such as underscores). Although this order
+ can split up related entries, it makes it easier to check whether
+ a given entry is in the file.
+
+ Leave the following blank line there!! Autoheader needs it. */
+
+
+/* Other stuff */
+#undef HAVE_IPC_H
+#undef HAVE_SHM_H
+#undef HAVE_XPM
+#undef HAVE_XSHM_H
+#undef HAVE_SYS_SELECT_H
+
+#undef IPC_RMID_DEFERRED_RELEASE
+
+#undef NO_FD_SET
+
+#undef RESOURCE_BASE
+
+#undef XINPUT_NONE
+#undef XINPUT_GXI
+#undef XINPUT_XFREE
+
+/* Define as the return type of signal handlers (int or void). */
+#undef RETSIGTYPE
+
+/* Most machines will be happy with int or void. IRIX requires '...' */
+#undef SIGNAL_ARG_TYPE
+
+/* #undef PACKAGE */
+/* #undef VERSION */
+
+
+/* Leave that blank line there!! Autoheader needs it.
+ If you're adding to this file, keep in mind:
+ The entries are in sort -df order: alphabetical, case insensitive,
+ ignoring punctuation (such as underscores). */
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100644
index 000000000..9f99ab8e7
--- /dev/null
+++ b/aclocal.m4
@@ -0,0 +1,395 @@
+dnl aclocal.m4 generated automatically by aclocal 1.2
+
+# Do all the work for Automake. This macro actually does too much --
+# some checks are only needed if your package does certain things.
+# But this isn't really a big deal.
+
+# serial 1
+
+dnl Usage:
+dnl AM_INIT_AUTOMAKE(package,version, [no-define])
+
+AC_DEFUN(AM_INIT_AUTOMAKE,
+[AC_REQUIRE([AM_PROG_INSTALL])
+PACKAGE=[$1]
+AC_SUBST(PACKAGE)
+VERSION=[$2]
+AC_SUBST(VERSION)
+dnl test to see if srcdir already configured
+if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
+ AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+fi
+ifelse([$3],,
+AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE")
+AC_DEFINE_UNQUOTED(VERSION, "$VERSION"))
+AM_SANITY_CHECK
+AC_ARG_PROGRAM
+dnl FIXME This is truly gross.
+missing_dir=`cd $ac_aux_dir && pwd`
+AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir)
+AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir)
+AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir)
+AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir)
+AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
+AC_PROG_MAKE_SET])
+
+
+# serial 1
+
+AC_DEFUN(AM_PROG_INSTALL,
+[AC_REQUIRE([AC_PROG_INSTALL])
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
+AC_SUBST(INSTALL_SCRIPT)dnl
+])
+
+#
+# Check to make sure that the build environment is sane.
+#
+
+AC_DEFUN(AM_SANITY_CHECK,
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftestfile
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
+ if test "$@" = "X"; then
+ # -L didn't work.
+ set X `ls -t $srcdir/configure conftestfile`
+ fi
+ test "[$]2" = conftestfile
+ )
+then
+ # Ok.
+ :
+else
+ AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+rm -f conftest*
+AC_MSG_RESULT(yes)])
+
+dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY)
+dnl The program must properly implement --version.
+AC_DEFUN(AM_MISSING_PROG,
+[AC_MSG_CHECKING(for working $2)
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf. Sigh.
+if ($2 --version) < /dev/null > /dev/null 2>&1; then
+ $1=$2
+ AC_MSG_RESULT(found)
+else
+ $1="$3/missing $2"
+ AC_MSG_RESULT(missing)
+fi
+AC_SUBST($1)])
+
+# Like AC_CONFIG_HEADER, but automatically create stamp file.
+
+AC_DEFUN(AM_CONFIG_HEADER,
+[AC_PREREQ([2.12])
+AC_CONFIG_HEADER([$1])
+dnl When config.status generates a header, we must update the stamp-h file.
+dnl This file resides in the same directory as the config header
+dnl that is generated. We must strip everything past the first ":",
+dnl and everything past the last "/".
+AC_OUTPUT_COMMANDS(changequote(<<,>>)dnl
+ifelse(patsubst(<<$1>>, <<[^ ]>>, <<>>), <<>>,
+<<test -z "<<$>>CONFIG_HEADERS" || echo timestamp > patsubst(<<$1>>, <<^\([^:]*/\)?.*>>, <<\1>>)stamp-h<<>>dnl>>,
+<<am_indx=1
+for am_file in <<$1>>; do
+ case " <<$>>CONFIG_HEADERS " in
+ *" <<$>>am_file "*<<)>>
+ echo timestamp > `echo <<$>>am_file | sed -e 's%:.*%%' -e 's%[^/]*$%%'`stamp-h$am_indx
+ ;;
+ esac
+ am_indx=`expr "<<$>>am_indx" + 1`
+done<<>>dnl>>)
+changequote([,]))])
+
+
+# serial 17 AM_PROG_LIBTOOL
+AC_DEFUN(AM_PROG_LIBTOOL,
+[AC_REQUIRE([AC_CANONICAL_HOST])
+AC_REQUIRE([AC_PROG_RANLIB])
+AC_REQUIRE([AC_PROG_CC])
+AC_REQUIRE([AM_PROG_LD])
+AC_REQUIRE([AM_PROG_NM])
+AC_REQUIRE([AC_PROG_LN_S])
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+AC_SUBST(LIBTOOL)
+
+dnl Allow the --disable-shared flag to stop us from building shared libs.
+AC_ARG_ENABLE(shared,
+[ --enable-shared build shared libraries [default=yes]],
+[if test "$enableval" = no; then
+ libtool_enable_shared=no
+else
+ libtool_enable_shared=yes
+fi])
+test -n "$libtool_enable_shared" && enable_shared="$libtool_enable_shared"
+libtool_shared=
+test "$enable_shared" = no && libtool_shared=" --disable-shared"
+
+dnl Allow the --disable-static flag to stop us from building static libs.
+AC_ARG_ENABLE(static,
+[ --enable-static build static libraries [default=yes]],
+[if test "$enableval" = no; then
+ libtool_enable_static=no
+else
+ libtool_enable_static=yes
+fi])
+test -n "$libtool_enable_static" && enable_static="$libtool_enable_static"
+libtool_static=
+test "$enable_static" = no && libtool_static=" --disable-static"
+
+libtool_flags="$libtool_shared$libtool_static"
+test "$silent" = yes && libtool_flags="$libtool_flags --silent"
+test "$ac_cv_prog_gcc" = yes && libtool_flags="$libtool_flags --with-gcc"
+test "$ac_cv_prog_gnu_ld" = yes && libtool_flags="$libtool_flags --with-gnu-ld"
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+[case "$host" in
+*-*-irix6*)
+ ac_save_CFLAGS="$CFLAGS"
+ flag_passed=no
+ for f in -32 -64 -n32 ABI -cckr -mips1 -mips2 -mips3 -mips4; do
+ case "$f" in
+ ABI)
+ test -n "$SGI_ABI" && flag_passed=yes
+ if test "$flag_passed" = no && test "$ac_cv_prog_gcc" = yes; then
+ # Choose the ABI flag according to GCC's specs.
+ if $CC -dumpspecs 2>&1 | sed '/^\*link:$/,/^$/!d' | egrep -e '[ ]-32' >/dev/null; then
+ LD="${LD-ld} -32"
+ else
+ LD="${LD-ld} -n32"
+ fi
+ fi
+ ;;
+
+ *)
+ if echo " $CC $CFLAGS " | egrep -e "[ ]$f[ ]" > /dev/null; then
+ flag_passed=yes
+ LD="${LD-ld} $f"
+ fi
+ ;;
+ esac
+ done
+ CFLAGS="$ac_save_CFLAGS"
+ ;;
+
+*-*-sco3.2v5*)
+ # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+ CFLAGS="$CFLAGS -belf"
+ ;;
+esac]
+
+# Actually configure libtool. ac_aux_dir is where install-sh is found.
+CC="$CC" CFLAGS="$CFLAGS" CPPFLAGS="$CPPFLAGS" \
+LD="$LD" NM="$NM" RANLIB="$RANLIB" LN_S="$LN_S" \
+${CONFIG_SHELL-/bin/sh} $ac_aux_dir/ltconfig \
+$libtool_flags --no-verify $ac_aux_dir/ltmain.sh $host \
+|| AC_MSG_ERROR([libtool configure failed])
+])
+
+# AM_PROG_LD - find the path to the GNU or non-GNU linker
+AC_DEFUN(AM_PROG_LD,
+[AC_ARG_WITH(gnu-ld,
+[ --with-gnu-ld assume the C compiler uses GNU ld [default=no]],
+test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no)
+AC_REQUIRE([AC_PROG_CC])
+ac_prog=ld
+if test "$ac_cv_prog_gcc" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ AC_MSG_CHECKING([for ld used by GCC])
+ ac_prog=`($CC -print-prog-name=ld) 2>&5`
+ case "$ac_prog" in
+ # Accept absolute paths.
+ /*)
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ AC_MSG_CHECKING([for GNU ld])
+else
+ AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(ac_cv_path_LD,
+[if test -z "$LD"; then
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog"; then
+ ac_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some GNU ld's only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ if "$ac_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
+ test "$with_gnu_ld" != no && break
+ else
+ test "$with_gnu_ld" != yes && break
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+else
+ ac_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$ac_cv_path_LD"
+if test -n "$LD"; then
+ AC_MSG_RESULT($LD)
+else
+ AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+AC_SUBST(LD)
+AM_PROG_LD_GNU
+])
+
+AC_DEFUN(AM_PROG_LD_GNU,
+[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], ac_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU ld's only accept -v.
+if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+ ac_cv_prog_gnu_ld=yes
+else
+ ac_cv_prog_gnu_ld=no
+fi])
+])
+
+# AM_PROG_NM - find the path to a BSD-compatible name lister
+AC_DEFUN(AM_PROG_NM,
+[AC_MSG_CHECKING([for BSD-compatible nm])
+AC_CACHE_VAL(ac_cv_path_NM,
+[case "$NM" in
+/*)
+ ac_cv_path_NM="$NM" # Let the user override the test with a path.
+ ;;
+*)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in /usr/ucb $PATH /bin; do
+ test -z "$ac_dir" && dir=.
+ if test -f $ac_dir/nm; then
+ # Check to see if the nm accepts a BSD-compat flag.
+ if ($ac_dir/nm -B /dev/null 2>&1; exit 0) | grep /dev/null >/dev/null; then
+ ac_cv_path_NM="$ac_dir/nm -B"
+ elif ($ac_dir/nm -p /dev/null 2>&1; exit 0) | grep /dev/null >/dev/null; then
+ ac_cv_path_NM="$ac_dir/nm -p"
+ else
+ ac_cv_path_NM="$ac_dir/nm"
+ fi
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_NM" && ac_cv_path_NM=nm
+ ;;
+esac])
+NM="$ac_cv_path_NM"
+AC_MSG_RESULT([$NM])
+AC_SUBST(NM)
+])
+
+# Add --enable-maintainer-mode option to configure.
+# From Jim Meyering
+
+# serial 1
+
+AC_DEFUN(AM_MAINTAINER_MODE,
+[AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
+ dnl maintainer-mode is disabled by default
+ AC_ARG_ENABLE(maintainer-mode,
+[ --enable-maintainer-mode enable make rules and dependencies not useful
+ (and sometimes confusing) to the casual installer],
+ USE_MAINTAINER_MODE=$enableval,
+ USE_MAINTAINER_MODE=no)
+ AC_MSG_RESULT($USE_MAINTAINER_MODE)
+ if test $USE_MAINTAINER_MODE = yes; then
+ MAINT=
+ else
+ MAINT='#M#'
+ fi
+ AC_SUBST(MAINT)dnl
+]
+)
+
+
+# serial 1
+
+# @defmac AC_PROG_CC_STDC
+# @maindex PROG_CC_STDC
+# @ovindex CC
+# If the C compiler in not in ANSI C mode by default, try to add an option
+# to output variable @code{CC} to make it so. This macro tries various
+# options that select ANSI C on some system or another. It considers the
+# compiler to be in ANSI C mode if it defines @code{__STDC__} to 1 and
+# handles function prototypes correctly.
+#
+# If you use this macro, you should check after calling it whether the C
+# compiler has been set to accept ANSI C; if not, the shell variable
+# @code{am_cv_prog_cc_stdc} is set to @samp{no}. If you wrote your source
+# code in ANSI C, you can make an un-ANSIfied copy of it by using the
+# program @code{ansi2knr}, which comes with Ghostscript.
+# @end defmac
+
+AC_DEFUN(AM_PROG_CC_STDC,
+[AC_REQUIRE([AC_PROG_CC])
+AC_BEFORE([$0], [AC_C_INLINE])
+AC_BEFORE([$0], [AC_C_CONST])
+AC_MSG_CHECKING(for ${CC-cc} option to accept ANSI C)
+AC_CACHE_VAL(am_cv_prog_cc_stdc,
+[am_cv_prog_cc_stdc=no
+ac_save_CC="$CC"
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX -qlanglvl=ansi
+# Ultrix and OSF/1 -std1
+# HP-UX -Aa -D_HPUX_SOURCE
+# SVR4 -Xc -D__EXTENSIONS__
+for ac_arg in "" -qlanglvl=ansi -std1 "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ AC_TRY_COMPILE(
+[#if !defined(__STDC__) || __STDC__ != 1
+choke me
+#endif
+/* DYNIX/ptx V4.1.3 can't compile sys/stat.h with -Xc -D__EXTENSIONS__. */
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/stat.h>
+#endif
+], [
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};],
+[am_cv_prog_cc_stdc="$ac_arg"; break])
+done
+CC="$ac_save_CC"
+])
+if test -z "$am_cv_prog_cc_stdc"; then
+ AC_MSG_RESULT([none needed])
+else
+ AC_MSG_RESULT($am_cv_prog_cc_stdc)
+fi
+case "x$am_cv_prog_cc_stdc" in
+ x|xno) ;;
+ *) CC="$CC $am_cv_prog_cc_stdc" ;;
+esac
+])
+
diff --git a/config.guess b/config.guess
new file mode 100755
index 000000000..413ed41c0
--- /dev/null
+++ b/config.guess
@@ -0,0 +1,883 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Written by Per Bothner <bothner@cygnus.com>.
+# The master version of this file is at the FSF in /home/gd/gnu/lib.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit system type (host/target name).
+#
+# Only a few systems have been added to this list; please add others
+# (but try to keep the structure clean).
+#
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 8/24/94.)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+trap 'rm -f dummy.c dummy.o dummy; exit 1' 1 2 15
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ alpha:OSF1:*:*)
+ if test $UNAME_RELEASE = "V4.0"; then
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ fi
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ cat <<EOF >dummy.s
+ .globl main
+ .ent main
+main:
+ .frame \$30,0,\$26,0
+ .prologue 0
+ .long 0x47e03d80 # implver $0
+ lda \$2,259
+ .long 0x47e20c21 # amask $2,$1
+ srl \$1,8,\$2
+ sll \$2,2,\$2
+ sll \$0,3,\$0
+ addl \$1,\$0,\$0
+ addl \$2,\$0,\$0
+ ret \$31,(\$26),1
+ .end main
+EOF
+ ${CC-cc} dummy.s -o dummy 2>/dev/null
+ if test "$?" = 0 ; then
+ ./dummy
+ case "$?" in
+ 7)
+ UNAME_MACHINE="alpha"
+ ;;
+ 15)
+ UNAME_MACHINE="alphaev5"
+ ;;
+ 14)
+ UNAME_MACHINE="alphaev56"
+ ;;
+ 10)
+ UNAME_MACHINE="alphapca56"
+ ;;
+ 16)
+ UNAME_MACHINE="alphaev6"
+ ;;
+ esac
+ fi
+ rm -f dummy.s dummy
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr [[A-Z]] [[a-z]]`
+ exit 0 ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit 0 ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-cbm-sysv4
+ exit 0;;
+ amiga:NetBSD:*:*)
+ echo m68k-cbm-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ amiga:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ arc64:OpenBSD:*:*)
+ echo mips64el-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ arc:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ hkmips:OpenBSD:*:*)
+ echo mips-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ pmax:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sgi:OpenBSD:*:*)
+ echo mips-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ wgrisc:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit 0;;
+ arm32:NetBSD:*:*)
+ echo arm-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ exit 0 ;;
+ SR2?01:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit 0;;
+ Pyramid*:OSx*:*:*|MIS*:OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit 0 ;;
+ NILE:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit 0 ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ i86pc:SunOS:5.*:*)
+ echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit 0 ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit 0 ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ atari*:NetBSD:*:*)
+ echo m68k-atari-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ atari*:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sun3*:NetBSD:*:*)
+ echo m68k-sun-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sun3*:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mac68k:NetBSD:*:*)
+ echo m68k-apple-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mac68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme88k:OpenBSD:*:*)
+ echo m88k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit 0 ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit 0 ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ 2020:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit 0 ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ sed 's/^ //' << EOF >dummy.c
+ int main (argc, argv) int argc; char **argv; {
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ ${CC-cc} dummy.c -o dummy \
+ && ./dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+ && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit 0 ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit 0 ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit 0 ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit 0 ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 -o $UNAME_PROCESSOR = mc88110 ] ; then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \
+ -o ${TARGET_BINARY_INTERFACE}x = x ] ; then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit 0 ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit 0 ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit 0 ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit 0 ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i?86:AIX:*:*)
+ echo i386-ibm-aix
+ exit 0 ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ sed 's/^ //' << EOF >dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ echo rs6000-ibm-aix3.2.5
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit 0 ;;
+ *:AIX:*:4)
+ if /usr/sbin/lsattr -EHl proc0 | grep POWER >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=4.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit 0 ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit 0 ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit 0 ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC NetBSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit 0 ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit 0 ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit 0 ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit 0 ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit 0 ;;
+ 9000/[3478]??:HP-UX:*:*)
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/7?? | 9000/8?[1679] ) HP_ARCH=hppa1.1 ;;
+ 9000/8?? ) HP_ARCH=hppa1.0 ;;
+ esac
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ 3050*:HI-UX:*:*)
+ sed 's/^ //' << EOF >dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ echo unknown-hitachi-hiuxwe2
+ exit 0 ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit 0 ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit 0 ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit 0 ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit 0 ;;
+ i?86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit 0 ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit 0 ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ CRAY*X-MP:*:*:*)
+ echo xmp-cray-unicos
+ exit 0 ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE}
+ exit 0 ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
+ exit 0 ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE}
+ exit 0 ;;
+ CRAY-2:*:*:*)
+ echo cray2-cray-unicos
+ exit 0 ;;
+ F300:UNIX_System_V:*:*)
+ FUJITSU_SYS=`uname -p | tr [A-Z] [a-z] | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit 0 ;;
+ F301:UNIX_System_V:*:*)
+ echo f301-fujitsu-uxpv`echo $UNAME_RELEASE | sed 's/ .*//'`
+ exit 0 ;;
+ hp3[0-9][05]:NetBSD:*:*)
+ echo m68k-hp-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ hp300:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ i?86:BSD/386:*:* | *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:FreeBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit 0 ;;
+ *:NetBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ exit 0 ;;
+ *:OpenBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ exit 0 ;;
+ i*:CYGWIN*:*)
+ echo i386-pc-cygwin32
+ exit 0 ;;
+ i*:MINGW*:*)
+ echo i386-pc-mingw32
+ exit 0 ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin32
+ exit 0 ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ *:GNU:*:*)
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit 0 ;;
+ *:Linux:*:*)
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us.
+ ld_help_string=`ld --help 2>&1`
+ ld_supported_emulations=`echo $ld_help_string \
+ | sed -ne '/supported emulations:/!d
+ s/[ ][ ]*/ /g
+ s/.*supported emulations: *//
+ s/ .*//
+ p'`
+ case "$ld_supported_emulations" in
+ i?86linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" ; exit 0 ;;
+ i?86coff) echo "${UNAME_MACHINE}-pc-linux-gnucoff" ; exit 0 ;;
+ sparclinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
+ m68klinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
+ elf32ppc) echo "powerpc-unknown-linux-gnu" ; exit 0 ;;
+ esac
+
+ if test "${UNAME_MACHINE}" = "alpha" ; then
+ sed 's/^ //' <<EOF >dummy.s
+ .globl main
+ .ent main
+ main:
+ .frame \$30,0,\$26,0
+ .prologue 0
+ .long 0x47e03d80 # implver $0
+ lda \$2,259
+ .long 0x47e20c21 # amask $2,$1
+ srl \$1,8,\$2
+ sll \$2,2,\$2
+ sll \$0,3,\$0
+ addl \$1,\$0,\$0
+ addl \$2,\$0,\$0
+ ret \$31,(\$26),1
+ .end main
+EOF
+ LIBC=""
+ ${CC-cc} dummy.s -o dummy 2>/dev/null
+ if test "$?" = 0 ; then
+ ./dummy
+ case "$?" in
+ 7)
+ UNAME_MACHINE="alpha"
+ ;;
+ 15)
+ UNAME_MACHINE="alphaev5"
+ ;;
+ 14)
+ UNAME_MACHINE="alphaev56"
+ ;;
+ 10)
+ UNAME_MACHINE="alphapca56"
+ ;;
+ 16)
+ UNAME_MACHINE="alphaev6"
+ ;;
+ esac
+
+ objdump --private-headers dummy | \
+ grep ld.so.1 > /dev/null
+ if test "$?" = 0 ; then
+ LIBC="libc1"
+ fi
+ fi
+ rm -f dummy.s dummy
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} ; exit 0
+ elif test "${UNAME_MACHINE}" = "mips" ; then
+ cat >dummy.c <<EOF
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+#ifdef __MIPSEB__
+ printf ("%s-unknown-linux-gnu\n", argv[1]);
+#endif
+#ifdef __MIPSEL__
+ printf ("%sel-unknown-linux-gnu\n", argv[1]);
+#endif
+ return 0;
+}
+EOF
+ ${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ else
+ # Either a pre-BFD a.out linker (linux-gnuoldld)
+ # or one that does not give us useful --help.
+ # GCC wants to distinguish between linux-gnuoldld and linux-gnuaout.
+ # If ld does not provide *any* "supported emulations:"
+ # that means it is gnuoldld.
+ echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations:"
+ test $? != 0 && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0
+
+ case "${UNAME_MACHINE}" in
+ i?86)
+ VENDOR=pc;
+ ;;
+ *)
+ VENDOR=unknown;
+ ;;
+ esac
+ # Determine whether the default compiler is a.out or elf
+ cat >dummy.c <<EOF
+#include <features.h>
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+#ifdef __ELF__
+# ifdef __GLIBC__
+# if __GLIBC__ >= 2
+ printf ("%s-${VENDOR}-linux-gnu\n", argv[1]);
+# else
+ printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]);
+# endif
+# else
+ printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]);
+# endif
+#else
+ printf ("%s-${VENDOR}-linux-gnuaout\n", argv[1]);
+#endif
+ return 0;
+}
+EOF
+ ${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ fi ;;
+# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions
+# are messed up and put the nodename in both sysname and nodename.
+ i?86:DYNIX/ptx:4*:*)
+ echo i386-sequent-sysv4
+ exit 0 ;;
+ i?86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit 0 ;;
+ i?86:*:4.*:* | i?86:SYSTEM_V:4.*:*)
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ i?86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit 0 ;;
+ pc:*:*:*)
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i386.
+ echo i386-pc-msdosdjgpp
+ exit 0 ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit 0 ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit 0 ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit 0 ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit 0 ;;
+ M68*:*:R3V[567]*:*)
+ test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+ 3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4.3${OS_REL} && exit 0
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4 && exit 0 ;;
+ m68*:LynxOS:2.*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit 0 ;;
+ i?86:LynxOS:2.*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ rs6000:LynxOS:2.*:* | PowerPC:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit 0 ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit 0 ;;
+ PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit 0 ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit 0 ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit 0 ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit 0 ;;
+ news*:NEWS-OS:*:6*)
+ echo mips-sony-newsos6
+ exit 0 ;;
+ R3000:*System_V*:*:* | R4000:UNIX_SYSV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+cat >dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+#if !defined (ultrix)
+ printf ("vax-dec-bsd\n"); exit (0);
+#else
+ printf ("vax-dec-ultrix\n"); exit (0);
+#endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy && rm dummy.c dummy && exit 0
+rm -f dummy.c dummy
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ c34*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ c38*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ c4*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ esac
+fi
+
+#echo '(Unable to guess system type)' 1>&2
+
+exit 1
diff --git a/config.h.in b/config.h.in
new file mode 100644
index 000000000..d190ec4fe
--- /dev/null
+++ b/config.h.in
@@ -0,0 +1,36 @@
+/* config.h.in. Generated automatically from configure.in by autoheader. */
+
+/* Define to empty if the keyword does not work. */
+#undef const
+
+/* Define as the return type of signal handlers (int or void). */
+#undef RETSIGTYPE
+
+/* Define if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define if the X Window System is missing or not being used. */
+#undef X_DISPLAY_MISSING
+
+/* Other stuff */
+#undef HAVE_IPC_H
+#undef HAVE_SHM_H
+#undef HAVE_XPM
+#undef HAVE_XSHM_H
+#undef HAVE_SYS_SELECT_H
+
+#undef IPC_RMID_DEFERRED_RELEASE
+
+#undef NO_FD_SET
+
+#undef RESOURCE_BASE
+
+#undef XINPUT_NONE
+#undef XINPUT_GXI
+#undef XINPUT_XFREE
+
+/* Define as the return type of signal handlers (int or void). */
+#undef RETSIGTYPE
+
+/* #undef PACKAGE */
+/* #undef VERSION */
diff --git a/config.sub b/config.sub
new file mode 100755
index 000000000..213a6d47d
--- /dev/null
+++ b/config.sub
@@ -0,0 +1,954 @@
+#! /bin/sh
+# Configuration validation subroutine script, version 1.1.
+# Copyright (C) 1991, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+if [ x$1 = x ]
+then
+ echo Configuration name missing. 1>&2
+ echo "Usage: $0 CPU-MFR-OPSYS" 1>&2
+ echo "or $0 ALIAS" 1>&2
+ echo where ALIAS is a recognized configuration type. 1>&2
+ exit 1
+fi
+
+# First pass through any local machine types.
+case $1 in
+ *local*)
+ echo $1
+ exit 0
+ ;;
+ *)
+ ;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ linux-gnu*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple)
+ os=
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco5)
+ os=sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ tahoe | i860 | m32r | m68k | m68000 | m88k | ns32k | arc | arm \
+ | arme[lb] | pyramid | mn10200 | mn10300 \
+ | tron | a29k | 580 | i960 | h8300 | hppa | hppa1.0 | hppa1.1 \
+ | alpha | alphaev5 | alphaev56 | we32k | ns16k | clipper \
+ | i370 | sh | powerpc | powerpcle | 1750a | dsp16xx | pdp11 \
+ | mips64 | mipsel | mips64el | mips64orion | mips64orionel \
+ | mipstx39 | mipstx39el \
+ | sparc | sparclet | sparclite | sparc64 | v850)
+ basic_machine=$basic_machine-unknown
+ ;;
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i[3456]86)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ vax-* | tahoe-* | i[3456]86-* | i860-* | m32r-* | m68k-* | m68000-* \
+ | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | arm-* | c[123]* \
+ | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \
+ | power-* | none-* | 580-* | cray2-* | h8300-* | i960-* \
+ | xmp-* | ymp-* | hppa-* | hppa1.0-* | hppa1.1-* \
+ | alpha-* | alphaev5-* | alphaev56-* | we32k-* | cydra-* \
+ | ns16k-* | pn-* | np1-* | xps100-* | clipper-* | orion-* \
+ | sparclite-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \
+ | sparc64-* | mips64-* | mipsel-* \
+ | mips64el-* | mips64orion-* | mips64orionel-* \
+ | mipstx39-* | mipstx39el-* \
+ | f301-*)
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-cbm
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-cbm
+ os=-amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-cbm
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ cray2)
+ basic_machine=cray2-cray
+ os=-unicos
+ ;;
+ [ctj]90-cray)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k7[0-9][0-9] | hp7[0-9][0-9] | hp9k8[0-9]7 | hp8[0-9]7)
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i[3456]86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i[3456]86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i[3456]86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i[3456]86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ mipsel*-linux*)
+ basic_machine=mipsel-unknown
+ os=-linux-gnu
+ ;;
+ mips*-linux*)
+ basic_machine=mips-unknown
+ os=-linux-gnu
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pentium | p5)
+ basic_machine=i586-intel
+ ;;
+ pentiumpro | p6)
+ basic_machine=i686-intel
+ ;;
+ pentium-* | p5-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ k5)
+ # We don't have specific support for AMD's K5 yet, so just call it a Pentium
+ basic_machine=i586-amd
+ ;;
+ nexen)
+ # We don't have specific support for Nexgen yet, so just call it a Pentium
+ basic_machine=i586-nexgen
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=rs6000-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ xmp)
+ basic_machine=xmp-cray
+ os=-unicos
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ mips)
+ if [ x$os = x-linux-gnu ]; then
+ basic_machine=mips-unknown
+ else
+ basic_machine=mips-mips
+ fi
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sparc)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
+ | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -cygwin32* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux-gnu* | -uxpv*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigaos
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f301-fujitsu)
+ os=-uxpv
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -aix*)
+ vendor=ibm
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -vxsim* | -vxworks*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
diff --git a/configure.in b/configure.in
new file mode 100644
index 000000000..faa57edc8
--- /dev/null
+++ b/configure.in
@@ -0,0 +1,214 @@
+# Process this file with autoconf to produce a configure script.
+AC_INIT(gdk/gdktypes.h)
+
+# Configure glib
+AC_CONFIG_SUBDIRS(glib)
+
+dnl Initialize automake stuff
+AM_INIT_AUTOMAKE(gtk+, 971109)
+
+# Specify a configuration file
+AM_CONFIG_HEADER(config.h)
+
+dnl Initialize libtool
+AM_PROG_LIBTOOL
+
+dnl Initialize maintainer mode
+AM_MAINTAINER_MODE
+
+AC_CANONICAL_HOST
+
+AC_ARG_ENABLE(shm, [ --enable-shm support shared memory if available [default=yes]],
+ echo $enable_shm, enable_shm="yes")
+AC_ARG_ENABLE(debug, [ --enable-debug turn on debugging [default=no]],
+if eval "test x$enable_debug = xyes"; then
+ DEBUGFLAG="-g"
+fi)
+AC_ARG_ENABLE(ansi, [ --enable-ansi turn on strict ansi [default=no]],
+ , enable_ansi=no)
+
+AC_ARG_WITH(xinput, [ --with-xinput[=no/gxi/xfree] support XInput ])
+
+if test -n "$DEBUGFLAG"; then
+ CFLAGS="$DEBUGFLAG"
+else
+ CFLAGS="$CFLAGS -DNDEBUG"
+fi
+
+# Build time sanity check...
+AM_SANITY_CHECK
+
+# Checks for programs.
+AC_PROG_CC
+AM_PROG_CC_STDC
+AC_PROG_INSTALL
+AC_PROG_MAKE_SET
+
+if eval "test x$GCC = xyes"; then
+ test `echo "$CFLAGS" | grep "\-Wall" > /dev/null 2> /dev/null`
+ if test ! $?; then
+ CFLAGS="$CFLAGS -Wall"
+ fi
+
+ if eval "test x$enable_ansi = xyes"; then
+ test `echo "$CFLAGS" | grep "\-ansi" > /dev/null 2> /dev/null`
+ if test ! $?; then
+ CFLAGS="$CFLAGS -ansi"
+ fi
+
+ test `echo "$CFLAGS" | grep "\-pedantic" > /dev/null 2> /dev/null`
+ if test ! $?; then
+ CFLAGS="$CFLAGS -pedantic"
+ fi
+ fi
+fi
+
+# Find the X11 include and library directories
+AC_PATH_X
+AC_PATH_XTRA
+
+if test "x$x_includes" = "x"; then
+ x_includes="/usr/include"
+fi
+
+saved_cflags="$CFLAGS"
+saved_ldflags="$LDFLAGS"
+
+CFLAGS="$X_CFLAGS"
+LDFLAGS="$X_LDFLAGS $X_LIBS"
+
+# Checks for libraries.
+# Check for the X11 library
+AC_CHECK_LIB(X11, XOpenDisplay, x_libs="-lX11 $X_EXTRA_LIBS", no_x11_lib=yes, $X_EXTRA_LIBS)
+
+if eval "test x$enable_shm = xyes"; then
+ # Check for the Xext library (needed for XShm extention)
+ AC_CHECK_LIB(Xext, XShmAttach, x_libs="-lXext $x_libs", no_xext_lib=yes, $x_libs)
+fi
+
+x_cflags="$X_CFLAGS"
+x_ldflags="$X_LDFLAGS $X_LIBS"
+
+# set up things for XInput
+
+if eval "test x$with_xinput = xgxi -o x$with_xinput = xyes"; then
+ AC_DEFINE(XINPUT_GXI)
+ xinput_progs=gxid
+ x_libs="-lXi $x_libs"
+elif eval "test x$with_xinput = xxfree"; then
+ AC_DEFINE(XINPUT_XFREE)
+ x_libs="-lXi $x_libs"
+else
+ AC_DEFINE(XINPUT_NONE)
+fi
+
+
+AC_SUBST(x_cflags)
+AC_SUBST(x_includes)
+AC_SUBST(x_ldflags)
+AC_SUBST(x_libs)
+AC_SUBST(xinput_progs)
+
+CFLAGS="$saved_cflags"
+LDFLAGS="$saved_ldflags"
+
+if eval "test x$enable_shm = xyes"; then
+ # Check for shared memory
+ AC_CHECK_HEADER(sys/ipc.h, AC_DEFINE(HAVE_IPC_H), no_sys_ipc=yes)
+ AC_CHECK_HEADER(sys/shm.h, AC_DEFINE(HAVE_SHM_H), no_sys_shm=yes)
+
+ # Check whether shmctl IPC_RMID allowes subsequent attaches
+ if test "$ac_cv_header_sys_shm_h" = "yes"; then
+ AC_MSG_CHECKING(whether shmctl IPC_RMID allowes subsequent attaches)
+ AC_TRY_RUN([
+ #include <sys/types.h>
+ #include <sys/ipc.h>
+ #include <sys/shm.h>
+ int main()
+ {
+ int id;
+ char *shmaddr;
+ id = shmget (IPC_PRIVATE, 4, IPC_CREAT | 0777);
+ if (id == -1)
+ exit (2);
+ shmaddr = shmat (id, 0, 0);
+ shmctl (id, IPC_RMID, 0);
+ if ((char*) shmat (id, 0, 0) == (char*) -1)
+ {
+ shmdt (shmaddr);
+ exit (1);
+ }
+ shmdt (shmaddr);
+ shmdt (shmaddr);
+ exit (0);
+ }
+ ],
+ AC_DEFINE(IPC_RMID_DEFERRED_RELEASE)
+ AC_MSG_RESULT(yes),
+ AC_MSG_RESULT(no),
+ AC_MSG_RESULT(assuming no))
+ fi
+
+ # Check for the X shared memory extension header file
+ AC_MSG_CHECKING(X11/extensions/XShm.h)
+ if eval "test x$no_ext_lib = xyes"; then
+ AC_MSG_RESULT(no)
+ no_xshm=yes
+ else
+ if eval "test -f $x_includes/X11/extensions/XShm.h"; then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_XSHM_H)
+ else
+ AC_MSG_RESULT(no)
+ no_xshm=yes
+ fi
+ fi
+fi
+
+# Check for private display resource base variable
+AC_MSG_CHECKING(resource base field in XDisplay)
+AC_CACHE_VAL(gtk_cv_display_resource_base,
+[AC_TRY_RUN([
+#define XLIB_ILLEGAL_ACCESS
+#include <X11/Xlib.h>
+
+int
+main ()
+{
+ Display *display;
+
+ return 0;
+
+ display->resource_base;
+}],
+gtk_cv_display_resource_base="resource_base",
+gtk_cv_display_resource_base="private3")])
+AC_MSG_RESULT($gtk_cv_display_resource_base)
+AC_DEFINE_UNQUOTED(RESOURCE_BASE, gdk_display->$gtk_cv_display_resource_base)
+
+# Checks for header files.
+AC_HEADER_STDC
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+
+# Checks for library functions.
+AC_TYPE_SIGNAL
+
+# Check for sys/select.h
+
+AC_MSG_CHECKING([fd_set and sys/select])
+AC_TRY_COMPILE([#include <sys/types.h>],
+ [fd_set readMask, writeMask;], gtk_ok=yes, gtk_ok=no)
+if test $gtk_ok = no; then
+ AC_HEADER_EGREP(fd_mask, sys/select.h, gtk_ok=yes)
+ if test $gtk_ok = yes; then
+ AC_DEFINE(HAVE_SYS_SELECT_H)
+ fi
+fi
+AC_MSG_RESULT($gtk_ok)
+if test $gtk_ok = no; then
+ AC_DEFINE(NO_FD_SET)
+fi
+
+AC_OUTPUT(Makefile gtk+.xconfig docs/Makefile gdk/Makefile gtk/Makefile)
diff --git a/docs/.cvsignore b/docs/.cvsignore
new file mode 100644
index 000000000..f3c7a7c5d
--- /dev/null
+++ b/docs/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/docs/Makefile.am b/docs/Makefile.am
new file mode 100644
index 000000000..f4df2f3e3
--- /dev/null
+++ b/docs/Makefile.am
@@ -0,0 +1,10 @@
+## Process this file with automake to produce Makefile.in
+
+info_TEXINFOS = gdk.texi gtk.texi
+
+EXTRA_DIST = texinfo.tex macros.texi
+
+files:
+ @files=`ls $(DISTFILES) 2> /dev/null `; for p in $$files; do \
+ echo $$p; \
+ done
diff --git a/docs/gdk.texi b/docs/gdk.texi
new file mode 100644
index 000000000..4942fe29b
--- /dev/null
+++ b/docs/gdk.texi
@@ -0,0 +1,326 @@
+\input texinfo @c -*-texinfo-*-
+@c %**start of header
+@setfilename gdk.info
+@settitle GDK
+@setchapternewpage odd
+@c %**end of header
+
+@set edition 1.0
+@set update-date 16 May 1996
+@set update-month May 1996
+
+@ifinfo
+This file documents GDK, the General Drawing Kit
+
+Copyright (C) 1996 Peter Mattis
+
+Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies
+
+@ignore
+Permission is granted to process this file throught TeX and print the
+results, provided the printed document carries copying permission notice
+identical to this one except for the removal of this paragraph (this
+paragraph not being relevant to the printed manual).
+
+@end ignore
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation
+approved by Peter Mattis.
+@end ifinfo
+
+@titlepage
+@title The General Drawing Kit
+@subtitle Version 1.0
+@subtitle @value{update-month}
+@author by Peter Mattis
+
+@page
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1996 Peter Mattis
+
+Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation
+approved by Peter Mattis.
+@end titlepage
+
+@dircategory User Interface Toolkit
+@direntry
+* GDK: (gdk). The General Drawing Kit
+@end direntry
+
+@node Top, Copying, (dir), (dir)
+@top The General Drawing Kit
+@ifinfo
+This is edition @value{edition} of the GDK documentation,
+@w{@value{update-date}}.
+@end ifinfo
+
+@menu
+* Copying:: Your rights.
+* Overview:: What is GDK?
+* Initialization:: Initialization and exit.
+* Events:: Event handling.
+* Visuals:: Understanding and using visuals.
+* Windows:: Creating and using windows.
+* Graphics Contexts:: Creating and modifying GCs.
+* Pixmaps:: Creating pixmaps.
+* Images:: Creating images.
+* Color:: Specifying color.
+* Fonts:: Creating fonts.
+* Drawing:: Drawing commands.
+* XInput Support:: Using extended devices.
+* Miscellany:: Other stuff.
+* Examples:: Using GDK.
+* Function Index:: Index of functions
+* Concept Index:: Index of concepts
+@end menu
+
+@node Copying, Overview, Top, Top
+@comment node-name, next, previous, up
+@chapter Copying
+
+GDK is @dfn{free}; this means that everyone is free to use it and free
+to redestribute it on a free basis. GDK is not in the public domain; it
+is copyrighted and there are restrictions on its distribution, but these
+restrictions are designed to permit everything that a good cooperating
+citizen would want to do. What is not allowed is to try to prevent
+others from further sharing any version of GDK that they might get from
+you.
+
+Specifically, we want to make sure that you have the right to give away
+copies of GDK, that you receive source code or else can get it if you
+want it, that you can change GDK or use pieces of it in new free
+programs, and that you know you can do these things.
+
+To make sure that everyone has such rights, we have to forbid you to
+deprive anyone else of these rights. For example, if you distribute
+copies of GDK, you must give the recipients all the rights that you
+have. You must make sure that they, too, receive or can get the source
+code. And you must tell them their rights.
+
+Also, for my own protection, we must make certain that everyone finds
+out that there is no warranty for GDK. If GDK is modified by someone
+else and passed on, we want their recipients to know that what they have
+is not what we distributed, so that any problems introduced by others
+will no reflect on our reputation.
+
+The precise conditions of the licenses for GDK are found in the General
+Public Licenses that accompanies it.
+
+
+@node Overview, Initialization, Copying, Top
+@comment node-name, next, previous, up
+@chapter What is GDK?
+@cindex Overview
+
+GDK is designed as a wrapper library that lies on top of Xlib. It
+performs many common and desired operations for a programmer instead
+of the programmer having to explicitly ask for such functionality from
+Xlib directly. For example, GDK provides a common interface to both
+regular and shared memory XImage types. By doing so, an application
+can nearly transparently use the fastest image type available. GDK
+also provides routines for determining the best available color depth
+and the best available visual which is not always the default visual
+for a screen.
+
+@node Initialization, Events, Overview, Top
+@comment node-name, next, previous, up
+@chapter Initialization and exit
+@cindex Initialization
+@cindex Exit
+
+Initializing GDK is easy. Simply call @code{gdk_init} passing in the
+@var{argc} and @var{argv} parameters. Exit is similarly easy. Just
+call @code{gdk_exit}.
+
+@deftypefun void gdk_init (int *@var{argc}, char ***@var{argv})
+Initializes the GDK library. The arguments @var{argc} and @var{argv}
+are scanned and any arguments that GDK recognizes are handled and
+removed. The @var{argc} and @var{argv} parameters are the values
+passed to @code{main} upon program invocation.
+@end deftypefun
+
+@deftypefun void gdk_exit (int @var{errorcode})
+Exit GDK and perform any necessary cleanup. @code{gdk_exit} will call
+the systems @code{exit} function passing @var{errorcode} as the
+parameter.
+@end deftypefun
+
+@example
+int
+main (int argc, char *argv[])
+@{
+ /* Initialize GDK. */
+ gdk_init (&argc, &argv);
+
+ /* Exit from GDK...this call will never return. */
+ gdk_exit (0);
+
+ /* Keep compiler from issuing a warning */
+ return 0;
+@}
+@end example
+
+
+@node Events, Visuals, Initialization, Top
+@comment node-name, next, previous, up
+@chapter Event handling
+@cindex Events
+
+Events are the means by which GDK lets the programmer know of user
+interaction. An event is normally a button or key press or some other
+indirect user action, such as a the mouse cursor entering or leaving a
+window.
+
+There exist only a few functions for getting events and event
+information. These are @code{gdk_events_pending},
+@code{gdk_event_get}, @code{gdk_events_record} and
+@code{gdk_events_playback}. The latter two functions are useful for
+automatic testing of a software package and should normally not be
+needed in a program.
+
+@deftypefun gint gdk_events_pending (void)
+Returns the number of events pending on the event queue.
+@end deftypefun
+
+@deftypefun gint gdk_event_get (GdkEvent *@var{event})
+Return the next available event in the @var{event}
+structure. @code{gdk_event_get} will return @code{TRUE} on success and
+@code{FALSE} on failure. Success and failure is determined by whether
+an event arrived before the timeout period expired.
+@end deftypefun
+
+@deftypefun void gdk_events_record (char *@var{filename})
+Turn on recording of events. User events and certain system events will
+be saved in the file named by the variable @var{filename}. This stream
+of events can later be played back and ``should'' produce the same
+results as when the original events were handled. However, the
+programmer does need to be careful in that the state of the program must
+be the same when @code{gdk_events_record} is called and when
+@code{gdk_events_playback} is called. For this reason,
+@code{gdk_events_record} is normally not called directly, but is instead
+invoked indirectly by specifying the ``-record'' command line option.
+@end deftypefun
+
+@deftypefun void gdk_events_playback (char *@var{filename})
+Start playback of events from a file. (See the above description of
+@code{gdk_events_record}). Normally this function is not called directly
+but is invoked by the ``-playback'' command line option.
+@end deftypefun
+
+@deftypefun void gdk_events_stop (void)
+Stop recording and playback of events.
+@end deftypefun
+
+@example
+void
+handle_event ()
+@{
+ GdkEvent event;
+
+ if (gdk_event_get (&event))
+ @{
+ switch (event.type)
+ @{
+ @dots{}
+ @}
+ @}
+@}
+@end example
+
+
+@node Visuals, Windows, Events, Top
+@comment node-name, next, previous, up
+@chapter Understanding and using visuals
+@cindex Visuals
+
+@node Windows, Graphics Contexts, Visuals, Top
+@comment node-name, next, previous, up
+@chapter Creating and using windows
+@cindex Windows
+
+@node Graphics Contexts, Pixmaps, Windows, Top
+@comment node-name, next, previous, up
+@chapter Creating and modifying GCs
+@cindex Graphics Contexts
+@cindex GC
+
+@node Pixmaps, Images, Graphics Contexts, Top
+@comment node-name, next, previous, up
+@chapter Creating pixmaps
+@cindex Pixmaps
+
+@node Images, Color, Pixmaps, Top
+@comment node-name, next, previous, up
+@chapter Creating images
+@cindex Images
+
+@node Color, Fonts, Images, Top
+@comment node-name, next, previous, up
+@chapter Specifying color
+@cindex Color
+
+@node Fonts, Drawing, Color, Top
+@comment node-name, next, previous, up
+@chapter Creating Fonts
+@cindex Fonts
+
+@node Drawing, XInput Support, Fonts, Top
+@comment node-name, next, previous, up
+@chapter Drawing Commands
+@cindex Drawing
+
+@node XInput Support, Miscellany, Drawing, Top
+@comment node-name, next, previous, up
+@chapter Using extended devices
+@cindex Overview
+@cindex Using extended device capabilities
+@cindex Controlling extended devices
+
+@node Miscellany, Examples, XInput Support, Top
+@comment node-name, next, previous, up
+@chapter Other stuff
+@cindex Timers
+@cindex Debugging
+@cindex Miscellaneous
+
+
+@node Examples, Function Index, Miscellany, Top
+@comment node-name, next, previous, up
+@chapter Using GDK
+@cindex Examples
+
+
+@node Function Index, Concept Index, Examples, Top
+@comment node-name, next, previous, up
+@unnumbered Variable Index
+
+@printindex fn
+
+@node Concept Index, , Function Index, Top
+@comment node-name, next, previous, up
+@unnumbered Concept Index
+
+@printindex cp
+
+@summarycontents
+@contents
+@bye
diff --git a/docs/gtk.texi b/docs/gtk.texi
new file mode 100644
index 000000000..93daf5b83
--- /dev/null
+++ b/docs/gtk.texi
@@ -0,0 +1,3285 @@
+\input texinfo @c -*-texinfo-*-
+@c Copyright (C) 1996 by Peter Mattis. All rights reserved.
+@c
+@c %**start of header
+@setfilename gtk.info
+@settitle GTK
+@setchapternewpage odd
+@include macros.texi
+@c %**end of header
+
+@set edition 1.0
+@set update-date 9 April 1997
+@set update-month April 1997
+
+@ifinfo
+This file documents GTK, the General Toolkit
+
+Copyright (C) 1996 Peter Mattis
+Copyright (C) 1997 Peter Mattis
+
+Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies
+
+@ignore
+Permission is granted to process this file throught TeX and print the
+results, provided the printed document carries copying permission notice
+identical to this one except for the removal of this paragraph (this
+paragraph not being relevant to the printed manual).
+
+@end ignore
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation
+approved by Peter Mattis.
+@end ifinfo
+
+@titlepage
+@title The General Toolkit
+@subtitle Version @value{edition}
+@subtitle @value{update-month}
+@author by Peter Mattis
+
+@page
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1996 Peter Mattis
+Copyright @copyright{} 1997 Peter Mattis
+
+Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation
+approved by Peter Mattis.
+@end titlepage
+
+@dircategory User Interface Toolkit
+@direntry
+* GTK: (gtk). The General Toolkit
+@end direntry
+
+@node Top, Copying, (dir), (dir)
+@top The General Toolkit
+@ifinfo
+This is edition @value{edition} of the GTK documentation,
+@w{@value{update-date}}.
+@end ifinfo
+
+@menu
+* Copying:: Your rights.
+* Overview:: What is GTK?
+* Objects:: Object overview.
+* Signals:: Signals overview.
+* Widgets:: Widget overview.
+* Other Objects:: Utility objects.
+* Miscellaneous:: Initialization, exit and other features.
+* Examples:: Using GTK.
+* Object Implementation:: Object internals.
+* Signal Implementation:: Signal internals.
+* Widget Implementation:: Widget internals.
+* Function Index:: Index of functions.
+* Concept Index:: Index of concepts.
+@end menu
+
+@node Copying, Overview, Top, Top
+@comment node-name, next, previous, up
+@chapter Copying
+
+GTK is @dfn{free}; this means that everyone is free to use it and free
+to redestribute it on a free basis. GTK is not in the public domain; it
+is copyrighted and there are restrictions on its distribution, but
+these restrictions are designed to permit everything that a good
+cooperating citizen would want to do. What is not allowed is to try to
+prevent others from further sharing any version of GTK that they might
+get from you.
+
+Specifically, we want to make sure that you have the right to give away
+copies of GTK, that you receive source code or else can get it if you
+want it, that you can change GTK or use pieces of it in new free
+programs, and that you know you can do these things.
+
+To make sure that everyone has such rights, we have to forbid you to
+deprive anyone else of these rights. For example, if you distribute
+copies of GTK, you must give the recipients all the rights that you
+have. You must make sure that they, too, receive or can get the source
+code. And you must tell them their rights.
+
+Also, for my own protection, we must make certain that everyone finds
+out that there is no warranty for GTK. If GTK is modified by someone
+else and passed on, we want their recipients to know that what they have
+is not what we distributed, so that any problems introduced by others
+will no reflect on our reputation.
+
+The precise conditions of the licenses for GTK are found in the General
+Public Licenses that accompanies it.
+
+
+@node Overview, Objects, Copying, Top
+@comment node-name, next, previous, up
+@chapter What is GTK?
+@cindex Overview
+
+GTK is a library for creating graphical user interfaces similar to the
+Motif ``look and feel''. It is designed to be small and efficient, but
+still flexible enough to allow the programmer freedom in the interfaces
+created. GTK allows the programmer to use a variety of standard user
+interface widgets (@pxref{Widgets}) such as push, radio and check
+buttons, menus, lists and frames. It also provides several ``container''
+widgets which can be used to control the layout of the user interface
+elements.
+
+GTK provides some unique features. (At least, I know of no other widget
+library which provides them). For example, a button does not contain a
+label, it contains a child widget, which in most instances will be a
+label. However, the child widget can also be a pixmap, image or any
+combination possible the programmer desires. This flexibility is adhered
+to throughout the library.
+
+
+@node Objects, Signals, Overview, Top
+@comment node-name, next, previous, up
+@chapter Object Overview
+@cindex Objects
+
+GTK implements a semi-simple class mechanism and an associated class
+hierarchy for widgets and several other useful objects. The GtkObject
+type is the root of the class hierarchy. It provides a few items needed
+by all classes, the foundation for the signal (@pxref{Signals})
+mechanism and the ``destroy'' method.
+
+The class hierarchy is defined by a type hierarchy. This hierarchy
+allows queries to be made in regards to a type. The basic query that can
+be performed is asking whether a given type has an ``is a'' relation
+with another type. For instance, it is common to ask whether a general
+widget pointer is a type of specific widget so that runtime sanity
+checks can be made.
+
+@section Type utility functions
+
+The @code{GtkTypeInfo} structure is used to communicate information to
+@code{gtk_type_unique} as opposed to passing in large numbers of
+parameters.
+
+@example
+typedef struct _GtkTypeInfo GtkTypeInfo;
+
+struct _GtkTypeInfo
+@{
+ gchar *type_name;
+ guint object_size;
+ guint class_size;
+ GtkClassInitFunc class_init_func;
+ GtkObjectInitFunc object_init_func;
+ GtkValueInitFunc value_init_func;
+@}
+@end example
+
+@itemize @bullet
+@item
+The @code{type_name} field refers to the name of the type. It is
+convention for the type name to be the same as the C structure type. For
+example, the type name of the @code{GtkObject} structure is
+``GtkObject''.
+
+@item
+The @code{object_size} field refers to the size in bytes of the C
+structure. The easiest (and portable) means of computing this size is by
+using the C @code{sizeof} operator. For instance, the sizeof of the
+@code{GtkObject} structure is computed by doing @code{sizeof
+(GtkObject)}.
+
+@item
+The @code{class_size} field refers to the size in bytes of the C
+structure for the class. Again, the @code{sizeof} operator should be
+used to compute this value.
+
+@item
+The @code{class_init_func} field is a callback which is used by the type
+mechanism to initialize class specific fields. The single argument this
+function takes is a pointer to a class structure.
+
+@item
+The @code{object_init_func} field is a callback which is used by the
+type mechanism to initialize object specific fields. The single argument
+this functions takes is a pointer to an object structure.
+
+@item
+The @code{value_init_func} field is a callback which is used by the type
+mechanism to initialize object stack value types. (FIXME: unfinished).
+@end itemize
+
+@deftypefun guint gtk_type_unique (guint @var{parent_type}, GtkTypeInfo *@var{type_info})
+The @var{parent_type} is simply the value of the new types parent
+type. If @var{parent_type} is 0, then the new type is the root of the
+type hierarchy. @var{type_info} is a pointer to a structure which
+contains necessary information for construction of the new
+type. Specifically, the @code{type_name}, @code{object_size} and
+@code{class_size} fields are required. The @code{class_init_func},
+@code{object_init_func} and @code{value_init_func} fields may be NULL.
+@end deftypefun
+
+@deftypefun gchar* gtk_type_name (guint @var{type})
+The returned string is the name of @var{type} as specified to
+@code{gtk_type_unique}.
+@end deftypefun
+
+@deftypefun guint gtk_type_from_name (guchar *@var{name})
+Return the type associated with @var{name}. If there is no type
+associated with @var{name}, then 0 will be returned.
+@end deftypefun
+
+@deftypefun guint gtk_type_parent (guint @var{type})
+Returns the parent type of @var{type} or 0 if @var{type} is the root of
+the type hierarchy.
+@end deftypefun
+
+@deftypefun gpointer gtk_type_class (guint @var{type})
+Returns the initialized class structure for @var{type}. The class
+structure is actually created and initialized the first time it is
+needed. If creation and initialization occurs, the @code{class_size}
+field of the @code{GtkTypeInfo} structure used to initialize this type
+is used to determine how large the class structure is. The
+@code{class_init_func} field from the @code{GtkTypeInfo} structure is
+called for all the members in the types ancestry, including the
+type. The order of this invocation proceeds from the root on down. For
+example, the @code{GtkWidgetClass} is first initialized as an
+@code{GtkObjectClass} by the object class initialization routine and
+then by the widget class initialization routine. This allows the widget
+class initialization routine to override values set by the object class
+initialization routine. The returned structure is shared by all objects
+of @var{type} and, as such, should not be modified.
+@end deftypefun
+
+@deftypefun gpointer gtk_type_new (guint @var{type})
+Returns a new instance of an @var{type} object. The object structure is
+created and initialized similarly to the class structure (as described
+above). The @code{object_size} and @code{object_init_func} fields of the
+@code{GtkTypeInfo} structure are used to determine the objects allocated
+size and the object specific initialization routine. Similarly to the
+class initialization, all the object initialization routines from the
+root on down to the particular type being created are invoked.
+@end deftypefun
+
+@deftypefun void gtk_type_describe_heritage (guint @var{type})
+Prints the type heritage for @var{type}. The heritage for a type
+includes the type and all its parent types up the type tree.
+@end deftypefun
+
+@deftypefun void gtk_type_describe_tree (guint @var{type}, gint @var{show_size})
+Prints the type tree which starts at @var{type}. @var{show_size} is a
+boolean which determines whether type sizes are printed.
+@end deftypefun
+
+@deftypefun gint gtk_type_is_a (guint @var{type}, guint @var{is_a_type})
+A predicate function which determines whether the relation @var{type}
+is_a @var{is_a_type} is true.
+@end deftypefun
+
+@section Object functions
+
+The GtkObject type is the root of the type hierarchy used by GTK. It
+provides a minimal set of fields used to implement the actual
+object, class and signal mechanisms, as well as several utility routines
+which make dealing with objects easier.
+
+For the adventurous, see @ref{Object Implementation}.
+
+@deftypefun guint gtk_object_get_type (void)
+Returns the @code{GtkObject} type identifier.
+@end deftypefun
+
+@deftypefun void gtk_object_class_add_signals (GtkObjectClass *@var{class}, gint *@var{signals}, gint @var{nsignals})
+Adds @var{signals} to the @code{signals} field in the GtkObjectClass
+structure @var{class}. @xref{Signals}.
+@end deftypefun
+
+@deftypefun void gtk_object_destroy (GtkObject *@var{object})
+Performs checks to make sure it is alright to destroy @var{object} and
+then emits the @code{destroy} signal. The check which is performed is to
+make sure @var{object} is not already processing another signal. If this
+were the case then destroying the object immediately would undoubtedly
+cause problems as the other signal would not be able to tell the object
+was destroyed. The solution is that if @var{object} is processing another
+signal we mark @var{object} is needing to be destroyed. When we finish
+processing of the other signal we check whether the object needs to be
+destroyed.
+@end deftypefun
+
+The GtkObject type provides a mechanism for associating arbitrary
+amounts of data with an object. The data is associated with the object
+using a character string key. The functions @code{gtk_object_set_data},
+@code{gtk_object_get_data}, and @code{gtk_object_remove_data} are the
+interface to this mechanism. Two other routines,
+@code{gtk_object_set_user_data} and @code{gtk_object_get_user_data},
+exist as convenience functions which simply use the same mechanism.
+
+@deftypefun void gtk_object_set_data (GtkObject *@var{object}, const char *@var{key}, gpointer @var{data})
+Associate @var{data} with @var{key} in the data list of @var{object}.
+@end deftypefun
+
+@deftypefun gpointer gtk_object_get_data (GtkObject *@var{object}, const char *@var{key})
+Retrieve the data associated with @var{key} in the data list of @var{object}.
+@end deftypefun
+
+@deftypefun void gtk_object_remove_data (GtkObject *@var{object}, const char *@var{key})
+Remove the data associated with @var{key} in the data list of @var{object}.
+@end deftypefun
+
+@deftypefun void gtk_object_set_user_data (GtkObject *@var{object}, gpointer @var{data})
+Sets @var{data} into the @code{user_data} field of @var{object}.
+@end deftypefun
+
+@deftypefun gpointer gtk_object_get_user_data (GtkObject *@var{object})
+Returns the @code{user_data} field of @var{object}.
+@end deftypefun
+
+The GtkObject type also provides a mechanism for specifying
+initialization values for fields. This general mechanism is called
+object value stacks. The reason for using value stacks is that they can
+simplify the life of the programmer. For instance, by default widgets
+are non-visible when created. However, the ``visible'' value for widgets
+may be specified so that widgets are made visible when created. (FIXME:
+unfinished).
+
+@deftypefun void gtk_object_value_stack_new (guint @var{object_type}, const gchar *@var{value_id}, GtkParamType @var{value_type})
+@end deftypefun
+
+@deftypefun void gtk_object_push_value (guint @var{object_type}, const gchar *@var{value_id}, @dots{})
+Push a value on the value stack specified by @var{object_type} and
+@var{value_id}. The type of value is implicitly given in the context of
+@var{object_type} and @var{value_id}. (That is, it is not specified
+explicitly in the function call). Only a single extra argument is
+expected which is the data which is to be placed on the stack.
+@end deftypefun
+
+@deftypefun void gtk_object_pop_value (guint @var{object_type}, const gchar *@var{value_id})
+Pop a value of the value stack specified by @var{object_type} and
+@var{value_id}.
+@end deftypefun
+
+@deftypefun gint gtk_object_peek_value (guint @var{object_type}, const gchar *@var{value_id}, gpointer @var{data})
+Peek at the value on the top of the value stack specified by
+@var{object_type} and @var{value_id}. The @var{data} argument is
+interpreted as the location of where to place the ``peeked'' data. For
+instance, if the peeked data is of type @code{GTK_PARAM_POINTER}, then
+@var{data} will be a pointer to a pointer. If the value stack is empty
+or does not exist or an error occurs, @code{gtk_object_peek_value} will
+return @code{FALSE}. On success it will return @code{TRUE}.
+@end deftypefun
+
+
+@node Signals, Widgets, Objects, Top
+@comment node-name, next, previous, up
+@chapter Signals Overview
+@cindex Signals
+
+Signals are GTK's method for objects to perform callbacks. A signal is
+an event which occurs upon an object. The programmer can connect to a
+signal of an object which involves specifying a function to be called
+when that signal is emitted in the specified object.
+
+When a signal is emitted, both the class function associated with the
+signal (when it was defined) and all signal handlers installed for that
+signal on the particular object emitting the signal are called. The
+widget programmer can specify whether the class function is to be called
+before after or both before and after the signal handlers installed by
+the widget user. The widget user can, however, specify that their signal
+handler is to be run after the class function (using the ``_after''
+signal connection routines). Any signal handling function can emit the
+same signal on the same object while it is running causing that signal
+emittion to either restart or to run recursively. Additionally, signal
+emittion can be terminated prematurely. While both such abilities are
+rarely used, they do allow for greater flexibility in regards to
+signals. For instance, a programmer can attach to the key press event
+signal and intercept all tab key presses from a widget. This particular
+example is used in the file selection dialog to implement tab completion
+of filenames and prevent the entry widget from inserting the tab into
+its buffer.
+
+Signals are selected using either an integer identifier or a character
+string name. It is convention to name the signal the same as the class
+function which is associated with it. There are two versions of most of
+the signal functions, one which takes an integer identifier and one
+which takes a character string name for the signal.
+
+@deftypefun gint gtk_signal_new (gchar *@var{name}, GtkSignalRunType @var{run_type}, gint @var{object_type}, gint @var{function_offset}, GtkSignalMarsahller @var{marshaller}, GtkParamType @var{return_val}, gint @var{nparams}, @dots{})
+Create a new signal and give it the character string identifier
+@var{name}. @var{name} needs to be unique in the context of
+@var{object_type}'s branch of the class hierarchy. That is,
+@var{object_type} cannot create a signal type with the same name as a
+signal type created by one of its parent types.
+
+@var{run_type} specifies whether the class function should be run before
+(@code{GTK_RUN_FIRST}), after (@code{GTK_RUN_LAST}) or both before and
+after normal signal handlers (@code{GTK_RUN_BOTH}). Additionally, the
+@code{GTK_RUN_NO_RECURSE} value can be or'ed with any of those values to
+specify that the signal should not be recursive. By default, emitting
+the same signal on the same widget will cause the signal to be emitted
+twice. However, if the @code{GTK_RUN_NO_RECURSE} flag is specified,
+emitting the same signal on the same widget will cause the current
+signal emittion to be restarted. This allows the widget programmer to
+specify the semantics of signal emittion on a per signal
+basis. (The @code{GTK_RUN_NO_RECURSE} flag is used by the GtkAdjustment
+widget).
+
+The @var{function_offset} is the byte offset from the start of the class
+structure to the class function field within the class structure. The
+easiest means to compute this offset is by using the
+@code{GTK_SIGNAL_OFFSET} macro which takes the class structure type as
+the first argument and the field as the second argument. For example,
+@code{GTK_SIGNAL_OFFSET (GtkObjectClass, destroy)} will give the offset
+of the @code{destroy} class function within the
+@code{GtkObjectClass}. Note: An offset is specified instead of an
+absolute location since there will be multiple instances of a class
+structure being referenced. (The @code{GtkWidgetClass} structure ``is
+a'' @code{GtkObjectClass} structure, etc.)
+
+The @var{marshaller} function is used to invoke a signal handler. Since
+signal handlers may take different parameters and return values and a
+general mechanism for invoking them is not apparent, the approach of
+making the signal creator responsible for invoking the signal handler
+was taken. (FIXME: unfinished).
+
+The @var{return_val} and @var{nparams} and the remaining arguments
+specify the return value and the arguments to the signal handler
+respectively. Note: There is an implicit first argument to every signal
+handler which is the widget the signal has been emitted from. The
+variable argument list (@var{@dots{}}) specifies the types of the
+arguments. These can be one of @code{GTK_PARAM_CHAR},
+@code{GTK_PARAM_SHORT}, @code{GTK_PARAM_INT}, @code{GTK_PARAM_LONG},
+@code{GTK_PARAM_POINTER} or @code{GTK_PARAM_FUNCTION}. It is undefined
+to specify @code{GTK_PARAM_NONE} as an argument type, however it is ok
+to use @code{GTK_PARAM_NONE} for @var{return_val}. (This corresponds to
+returning a @code{void}).
+
+@code{gtk_signal_new} returns the integer identifier of the newly
+created signal. Signal identifiers start numbering at 1 and increase
+upwards. A value of -1 will be returned if an error occurs.
+
+@strong{Note:} @code{gtk_signal_new} is only needed by widget writers. A
+normal user of GTK will never needed to invoke this function.
+@end deftypefun
+
+@deftypefun gint gtk_signal_lookup (gchar *@var{name}, gint @var{object_type})
+Returns the integer identifier for the signal referenced by @var{name}
+and @var{object_type}. If @var{object_type} does not define the signal
+@var{name}, then the signal is looked for in @var{object_type}'s parent
+type recursively.
+@end deftypefun
+
+@deftypefun gint gtk_signal_emit (GtkObject *@var{object}, gint @var{signal_type}, @dots{})
+Emit the signal specified by the integer identifier @var{signal_type}
+from @var{object}. If an error occurs, @code{gtk_signal_emit} will
+return @code{FALSE} and will return @code{TRUE} on success. The signal
+definition determines the parameters passed in the variable argument
+list (@code{@dots{}}). For example, if the signal is defined as:
+
+@example
+ gint (* event) (GtkWidget *widget, GdkEvent *event);
+@end example
+
+Then a call to emit the ``event'' signal would look like:
+
+@example
+ GdkEvent event;
+ gint return_val;
+ @dots{}
+ gtk_signal_emit (some_object,
+ gtk_signal_lookup ("event",
+ GTK_OBJECT_TYPE (some_object)),
+ &event, &return_val);
+@end example
+
+Notice that the @code{widget} argument is implicit in that the first
+argument to every signal is a type derived from @code{GtkObject}. The
+@var{return_val} argument is actually a pointer to the return value type
+since the signal mechanism needs to be able to place the return value in
+an actual location. And lastly, the @code{gtk_signal_lookup} call is
+normally avoided by using the @code{gtk_signal_emit_by_name} function
+instead. @code{gtk_signal_emit} is normally used internally by widgets
+which know the signal identifier (since they defined the signal) and can
+therefore side-step the cost of calling @code{gtk_signal_lookup}.
+@end deftypefun
+
+@deftypefun gint gtk_signal_emit_by_name (GtkObject *@var{object}, gchar *@var{name}, @dots{})
+Similar to @code{gtk_signal_emit} except that the signal is referenced
+by @var{name} instead of by its integer identifier.
+@end deftypefun
+
+@deftypefun void gtk_signal_emit_stop (GtkObject *@var{object}, gint @var{signal_type})
+Stop the emission of the signal @var{signal_type} on
+@var{object}. @var{signal_type} is the integer identifier for the signal
+and can be determined using the function
+@code{gtk_signal_lookup}. Alternatively, the function
+@code{gtk_signal_emit_stop_by_name} can be used to refer to the signal
+by name. Attempting to stop the emission of a signal that isn't being
+emitted does nothing.
+@end deftypefun
+
+@deftypefun void gtk_signal_emit_stop_by_name (GtkObject *@var{object}, gchar *@var{name})
+Similar to @code{gtk_signal_emit_stop} except that the signal is
+referenced by @var{name} instead of by its integer identifier.
+@end deftypefun
+
+@deftypefun gint gtk_signal_connect (GtkObject *@var{object}, gchar *@var{name}, GtkSignalFunc @var{func}, gpointer @var{func_data})
+Connects a signal handling function to a signal emitting
+object. @var{func} is connected to the signal @var{name} emitted by
+@var{object}. The arguments and returns type of @var{func} should match
+the arguments and return type of the signal @var{name}. However,
+@var{func} may take the extra argument of @var{func_data}. Due to the C
+calling convention it is ok to ignore the extra argument. (It is ok to
+ignore all the arguments in fact).
+
+@code{gtk_signal_connect} returns an integer identifier for the
+connection which can be used to refer to it in the future. Specifically
+it is useful for removing the connection and/or blocking it from being
+used.
+@end deftypefun
+
+@deftypefun gint gtk_signal_connect_after (GtkObject *@var{object}, gchar *@var{name}, GtkSignalFunc @var{func}, gpointer @var{func_data})
+Similar to @code{gtk_signal_connect} except the signal handler is
+connected in the ``after'' slot. This allows a signal handler to be
+guaranteed to run after other signal handlers connected to the same
+signal on the same object and after the class function associated with
+the signal.
+
+Like @code{gtk_signal_connect}, @code{gtk_signal_connect_after} returns
+an integer identifier which can be used to refer to the connection.
+@end deftypefun
+
+@deftypefun gint gtk_signal_connect_object (GtkObject *@var{object}, gchar *@var{name}, GtkSignalFunc @var{func}, GtkObject *@var{slot_object})
+Connects @var{func} to the signal @var{name} emitted by
+@var{object}. Similar to @code{gtk_signal_connect} with the difference
+that @var{slot_object} is passed as the first parameter to @var{func}
+instead of the signal emitting object. This can be useful for connecting
+a signal emitted by one object to a signal in another object. A common
+usage is to connect the ``destroy'' signal of dialog to the ``clicked''
+signal emitted by a ``close'' button in the dialog. That is, the
+``clicked'' signal emitted by the button will caused the ``destroy''
+signal to be emitted for the dialog. This is also the ``right'' way to
+handle closing of a dialog since the ``destroy'' signal will be sent if
+the dialog is deleted using a window manager function and this enables
+the two methods of closing the window to be handled by the same
+mechanism. Returns an integer identifier which can be used to refer to
+the connection.
+@end deftypefun
+
+@deftypefun gint gtk_signal_connect_object_after (GtkObject *@var{object}, gchar *@var{name}, GtkSignalFunc @var{func}, GtkObject *@var{slot_object})
+Similar to @code{gtk_signal_connect_object} except the signal handler is
+connected in the ``after'' slot. This allows a signal handler to be
+guaranteed to run after other signal handlers connected to the same
+signal on the same object and after the class function associated with
+the signal. Returns an integer identifier which can be used to refer to
+the connection.
+@end deftypefun
+
+@deftypefun void gtk_signal_disconnect (GtkObject *@var{object}, gint @var{id})
+Disconnects a signal handler from an object. The signal handler is
+identified by the integer @var{id} which is returned by the
+@code{gtk_signal_connect*} family of functions.
+@end deftypefun
+
+@deftypefun void gtk_signal_disconnect_by_data (GtkObject *@var{object}, gpointer @var{data})
+Disconnects a signal handler from an object. The signal handler is
+identified by the @var{data} argument specified as the @var{func_data}
+argument to the @code{gtk_signal_connect*} family of functions. For the
+@code{gtk_signal_connect_object*} functions, @var{data} refers to the
+@var{slot_object}.
+
+@strong{Note:} This will remove all signal handlers connected to
+@var{object} which were connected using @var{data} as their
+@var{func_data} argument. Multiple signal handlers may be disconnected
+with this call.
+@end deftypefun
+
+@deftypefun void gtk_signal_handler_block (GtkObject *@var{object}, gint @var{id})
+Blocks calling of a signal handler during signal emission. The signal
+handler is identified by the integer @var{id} which is returned by the
+@code{gtk_signal_connect*} family of functions. If the signal is already
+blocked no change is made.
+@end deftypefun
+
+@deftypefun void gtk_signal_handler_block_by_data (GtkObject *@var{object}, gint @var{data})
+Blocks calling of a signal handler during signal emission. The signal
+handler is identified by the @var{data} argument specified as the
+@var{func_data} argument to the @code{gtk_signal_connect*} family of
+functions. For the @code{gtk_signal_connect_object*} functions,
+@var{data} refers to the @var{slot_object}. If the signal is already
+blocked no change is made.
+
+@strong{Note:} This will block all signal handlers connected to
+@var{object} which were connected using @var{data} as their
+@var{func_data} argument. Multiple signal handlers may be blocked
+with this call.
+@end deftypefun
+
+@deftypefun void gtk_signal_handler_unblock (GtkObject *@var{object}, gint @var{id})
+Unblocks calling of a signal handler during signal emission. The signal
+handler is identified by the integer @var{id} which is returned by the
+@code{gtk_signal_connect*} family of functions. If the signal is already
+unblocked no change is made.
+@end deftypefun
+
+@deftypefun void gtk_signal_handler_unblock_by_data (GtkObject *@var{object}, gint @var{data})
+Unblocks calling of a signal handler during signal emission. The signal
+handler is identified by the @var{data} argument specified as the
+@var{func_data} argument to the @code{gtk_signal_connect*} family of
+functions. For the @code{gtk_signal_connect_object*} functions,
+@var{data} refers to the @var{slot_object}. If the signal is already
+unblocked no change is made.
+
+@strong{Note:} This will unblock all signal handlers connected to
+@var{object} which were connected using @var{data} as their
+@var{func_data} argument. Multiple signal handlers may be unblocked
+with this call.
+@end deftypefun
+
+@deftypefun void gtk_signal_handlers_destroy (GtkObject *@var{object})
+Destroy all of the signal handlers connected to @var{object}. There
+should normally never be reason to call this function as it is called
+automatically when @var{object} is destroyed.
+@end deftypefun
+
+@deftypefun void gtk_signal_default_marshaller (GtkObject *@var{object}, GtkSignalFunc @var{func}, gpointer @var{func_data}, GtkSignalParam *@var{params})
+@code{gtk_signal_new} requires a callback in order to actually call a
+signal handler for a particular signal. The vast majority of signals are
+of the particular form:
+
+@example
+ (* std_signal) (gpointer std_arg);
+@end example
+
+@code{gtk_signal_default_marshaller} is a signal marshaller which
+marshals arguments for a signal of that form.
+@end deftypefun
+
+
+@node Widgets, Other Objects, Signals, Top
+@comment node-name, next, previous, up
+@chapter Widget Overview
+@cindex Widgets
+
+
+Widgets are the general term used to describe user interface objects. A
+widget defines a class interface that all user interface objects conform
+to. This interface allows a uniform method for dealing with operations
+common to all objects such as hiding and showing, size requisition and
+allocation and events.
+
+The common interface that widgets must adhere to is described by the
+GtkWidget and GtkWidgetClass structure. For the purposes of using GTK
+these structures can be considered read-only and, for the most part,
+opaque.
+
+All widget creation routines in GTK return pointers to GtkWidget
+structures. In reality, all widget creation routines create structures
+that can be viewed as equivalent to the GtkWidget structure, but often
+have contain additional information. @xref{Object Implementation}
+
+The widgets available for use are implemented in a hierarchy. Several
+widgets exist solely as common bases for more specific widgets. For
+example, it is not possible to create a ruler widget itself, but the
+ruler widget provides a base and functionality common to the horizontal
+and vertical rulers.
+
+The available widgets (in alphabetical order):
+
+@menu
+* GtkAlignment:: The alignment widget.
+* GtkArrow:: The arrow widget.
+* GtkBin:: The bin widget.
+* GtkBox:: The box widget.
+* GtkButton:: The button widget.
+* GtkCheckButton:: The check button widget.
+* GtkCheckMenuItem:: The check menu item widget.
+* GtkContainer:: The container widget.
+* GtkDialog:: The dialog widget.
+* GtkDrawingArea:: The drawing area widget.
+* GtkEntry:: The entry widget.
+* GtkFileSelection:: The file selection dialog widget.
+* GtkFrame:: The frame widget.
+* GtkHBox:: The horizontal box widget.
+* GtkHRuler:: The horizontal ruler widget.
+* GtkHScale:: The horizontal scale widget.
+* GtkHScrollbar:: The horizontal scrollbar widget.
+* GtkHSeparator:: The horizontal separator widget.
+* GtkImage:: The image widget.
+* GtkItem:: The item widget.
+* GtkLabel:: The label widget.
+* GtkList:: The list widget.
+* GtkListItem:: The list item widget.
+* GtkMenu:: The menu widget.
+* GtkMenuBar:: The menu bar widget.
+* GtkMenuItem:: The menu item widget.
+* GtkMenuShell:: The menu shell widget.
+* GtkMisc:: The misc widget.
+* GtkNotebook:: The notebook widget.
+* GtkOptionMenu:: The option menu widget.
+* GtkPixmap:: The pixmap widget.
+* GtkPreview:: The preview widget.
+* GtkProgressBar:: The progress bar widget.
+* GtkRadioButton:: The radio button widget.
+* GtkRadioMenuItem:: The radio menu item widget.
+* GtkRange:: The range widget.
+* GtkRuler:: The ruler widget.
+* GtkScale:: The scale widget.
+* GtkScrollbar:: The scrollbar widget.
+* GtkScrolledWindow:: The scrolled window widget.
+* GtkSeparator:: The separator widget.
+* GtkTable:: The table widget.
+* GtkText:: The text widget.
+* GtkToggleButton:: The toggle button widget.
+* GtkTree:: The tree widget.
+* GtkTreeItem:: The tree item widget.
+* GtkVBox:: The vertical box widget.
+* GtkViewport:: The viewport widget.
+* GtkVRuler:: The vertical ruler widget.
+* GtkVScale:: The vertical scale widget.
+* GtkVScrollbar:: The vertical scrollbar widget.
+* GtkVSeparator:: The vertical separator widget.
+* GtkWidget:: The base widget type.
+* GtkWindow:: The window widget.
+@end menu
+
+
+@node GtkAlignment, GtkArrow, Widgets, Widgets
+@comment node-name, next, previous, up
+@section The alignment widget
+
+
+@subsection Description
+
+The alignment widget is a container (@pxref{GtkContainer}) derived from
+the bin widget (@pxref{GtkBin}). Its entire purpose is to give the
+programmer flexibility in how the child it manages is positioned when a
+window is resized.
+
+Normally, a widget is allocated at least as much size as it
+requests. (@pxref{GtkContainer} for a discussion of geometry
+management). When a widget is allocated more size than it requests there
+is a question of how the widget should expand. By convention, most GTK
+widgets expand to fill their allocated space. Sometimes this behavior is
+not desired. The alignment widget allows the programmer to specify how a
+widget should expand and position itself to fill the area it is
+allocated.
+
+@subsection Options
+
+@defopt xscale
+@defoptx yscale
+The @var{xscale} and @var{yscale} options specify how to scale the child
+widget. If the scale value is 0.0, the child widget is allocated exactly
+the size it requested in that dimension. If the scale value is 1.0, the
+child widget is allocated all of the space in a dimension. A scale value
+of 1.0 for both x and y is equivalent to not using an alignment widget.
+@end defopt
+
+@defopt xalign
+@defoptx yalign
+The @var{xalign} and @var{yalign} options specify how to position the
+child widget when it is not allocated all the space available to it
+(because the @var{xscale} and/or @var{yscale} options are less than
+1.0). If an alignment value is 0.0 the widget is positioned to the left
+(or top) of its allocated space. An alignment value of 1.0 positions the
+widget to the right (or bottom) of its allocated space. A common usage
+is to specify @var{xalign} and @var{yalign} to be 0.5 which causes the
+widget to be centered within its allocated area.
+@end defopt
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_alignment_get_type (void)
+Returns the @code{GtkAlignment} type identifier.
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_alignment_new (gfloat @var{xalign}, gfloat @var{yalign}, gfloat @var{xscale}, gfloat @var{yscale})
+Create a new @code{GtkAlignment} object and initialize it with the
+values @var{xalign}, @var{yalign}, @var{xscale} and @var{yscale}. The
+new widget is returned as a pointer to a @code{GtkWidget}
+object. @code{NULL} is returned on failure.
+@end deftypefun
+
+@deftypefun void gtk_alignment_set (GtkAlignment *@var{alignment}, gfloat @var{xalign}, gfloat @var{yalign}, gfloat @var{xscale}, gfloat @var{yscale})
+Set the @var{xalign}, @var{yalign}, @var{xscale} and @var{yscale} options
+of an alignment widget. It is important to not set the fields of the
+@code{GtkAlignment} structure directly (or, for that matter, any type
+derived from @code{GtkObject}).
+@end deftypefun
+
+@gtkstdmacros{Alignment, ALIGNMENT}
+
+
+@page
+@node GtkArrow, GtkBin, GtkAlignment, Widgets
+@comment node-name, next, previous, up
+@section The arrow widget
+
+@subsection Description
+
+The arrow widget is derived from the misc widget (@pxref{GtkMisc}) and
+is intended for use where a directional arrow (in one of the four
+cardinal directions) is desired. As such, it has very limited
+functionality and basically only draws itself in a particular direction
+and with a particular shadow type. The arrow widget will expand to fill
+all the space it is allocated.
+
+@subsection Options
+
+@defopt arrow_type
+The @var{arrow_type} option specifies which direction the arrow will
+point. It can be one of @code{GTK_ARROW_UP}, @code{GTK_ARROW_DOWN},
+@code{GTK_ARROW_LEFT} or @code{GTK_ARROW_RIGHT}.
+@end defopt
+
+@defopt shadow_type
+The @var{shadow_type} option specifies how to draw the shadow for the
+arrow. Currently, only the @code{GTK_SHADOW_IN} and
+@code{GTK_SHADOW_OUT} shadow types are supported for drawing
+arrows. Other shadow types will cause nothing to be drawn.
+@end defopt
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_arrow_get_type (void)
+Returns the @code{GtkArrow} type identifier.
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_arrow_new (GtkArrowType @var{arrow_type}, GtkShadowType @var{shadow_type})
+Create a new @code{GtkArrow} object and initialize it with the values
+@var{arrow_type} and @var{shadow_type}. The new widget is returned as a
+pointer to a @code{GtkWidget} object. @code{NULL} is returned on
+failure.
+@end deftypefun
+
+@deftypefun void gtk_arrow_set (GtkArrow *@var{arrow}, GtkArrowType @var{arrow_type}, GtkShadowType @var{shadow_type})
+Set the @var{arrow_type} and @var{shadow_type} options of an arrow
+widget. It is important to not set the fields of the @code{GtkArrow}
+structure directly (or, for that matter, any type derived from
+@code{GtkObject}).
+@end deftypefun
+
+@gtkstdmacros{Arrow, ARROW}
+
+
+@page
+@node GtkBin, GtkBox, GtkArrow, Widgets
+@comment node-name, next, previous, up
+@section The bin widget
+
+@subsection Description
+
+The bin widget is a container (@pxref{GtkContainer}) derived from the
+container widget. It is an abstract base class. That is, it is not
+possible to create an actual bin widget. It exists only to provide a
+base of functionality for other widgets. Specifically, the bin widget
+provides a base for several other widgets that contain only a single
+child. These widgets include alignments (@pxref{GtkAlignment}), frames
+(@pxref{GtkFrame}), items (@pxref{GtkItem}), viewports
+(@pxref{GtkViewport}) and windows (@pxref{GtkWindow})
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_bin_get_type (void)
+Returns the @code{GtkBin} type identifier.
+@end deftypefun
+
+@gtkstdmacros{Bin, BIN}
+
+
+@page
+@node GtkBox, GtkButton, GtkBin, Widgets
+@comment node-name, next, previous, up
+@section The box widget
+
+
+@subsection Description
+
+The box widget is a container (@pxref{GtkContainer}) derived from the
+container widget. It is an abstract base class used by the horizontal
+box (@pxref{GtkHBox}) and vertical box (@pxref{GtkVBox}) widgets to
+provide a base of common functionality.
+
+A box provides an abstraction for organizing the position and size of
+widgets. Widgets in a box are layed out horizontally or vertically. By
+using a box widget appropriately, a programmer can control how widgets
+are positioned and how they will be allocated space when a window gets
+resized.
+
+The key attribute of boxes is that they position their children in a
+single row (horizontal boxes) or column (vertical boxes). In the case of
+horizontal boxes, all children are stretched vertically. The vertical
+size of the box is determined by the largest vertical requisition of all
+of its children. Similarly, a vertical box streches all of its children
+horizontally. The horizontal size (of the vertical box) is determined by
+the largest horizontal requisition of all of its children. An alignment
+widget (@pxref{GtkAlignment}) can be used to control child allocation
+more precisely on a per child basis.
+
+The second attribute of boxes is how they expand children. In the case
+of a horizontal box, the main control is over how children are expanded
+horizontally to fill the allocated area. (The rest of this discussion
+will focus on horizontal boxes but it applies to vertical boxes as
+well).
+
+There are two flags which can be set controlling how a widget is
+expanded horizontally in a horizontal box. These are the @code{expand}
+and @code{fill}. There operation is fairly simple. If @code{expand} is
+set, the childs potentially allocated area will expand to fill available
+space. If @code{fill} is set, the childs actual allocated area will be
+its potentially allocated area. There is a difference between
+the potentially area (which is the area the box widget sets aside for
+the child) and the actual allocated area (which is the area the box
+widget actual allocates for the widget via
+@code{gtk_widget_size_allocate}).
+
+The allocation of space to children occurs as follows (for horizontal
+boxes):
+@enumerate
+@item
+All children are allocated at least their requested size horizontally
+and the maximum requested child size vertically.
+
+@item
+Any child with the @code{expand} flag set is allocated @code{extra_width
+/ nexpand_children} extra pixels horizontally. If the @code{homogeneous}
+flag was set, all children are considered to have the @code{expand} flag
+set. That is, all children will be allocated the same area.The
+horizontal box is a fair widget and, as such, divides up any extra
+allocated space evenly among the ``expand'' children. (Those children
+which have the @code{expand} flag set). The exception occurs when
+@code{extra_width / nexpand_children} does not divide cleanly. The extra
+space is given to the last widget.
+
+@item
+@code{spacing} number of pixels separate each child. Note: The
+separation is between the potentially allocated area for each child and
+not the actual allocated area. The @code{padding} value associated with
+each child causes that many pixels to be left empty to each side of the
+child.
+
+@item
+If a child has the @code{fill} flag set it is allocated its potentially
+allocated area. If it does not, it is allocated its requested size
+horizontally and centered within its potentially allocated area. Its
+vertical allocation is still the maximum requested size of any child.
+
+@item
+Children placed at the start of the box are placed in order of addition
+to the box from left to right in the boxes allocated area.. Children
+placed at the end of the box are placed in order of addition from right
+to left in the boxes allocated area.
+@end enumerate
+
+@xref{GtkHBox}, and @ref{GtkVBox}, for code examples of using horizontal
+and vertical boxes.
+
+@subsection Options
+
+@c FIXME: options for GtkBox
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_box_get_type (void)
+Returns the @code{GtkBox} type identifier.
+@end deftypefun
+
+@deftypefun void gtk_box_pack_start (GtkBox *@var{box}, GtkWidget *@var{child}, gint @var{expand}, gint @var{fill}, gint @var{padding})
+Add @var{child} to the front of @var{box}. The flags @var{expand} and
+@var{fill} and the padding value of @var{padding} are associated with
+@var{child}.
+@end deftypefun
+
+@deftypefun void gtk_box_pack_end (GtkBox *@var{box}, GtkWidget *@var{child}, gint @var{expand}, gint @var{fill}, gint @var{padding})
+Add @var{child} to the end of @var{box}. The flags @var{expand} and
+@var{fill} and the padding value of @var{padding} are associated with
+@var{child}.
+@end deftypefun
+
+@deftypefun void gtk_box_pack_start_defaults (GtkBox *@var{box}, GtkWidget *@var{widget})
+A convenience function which is equivalent to the following:
+
+@example
+ gtk_box_pack_start (@var{box}, @var{widget}, TRUE, TRUE, 0);
+@end example
+@end deftypefun
+
+@deftypefun void gtk_box_pack_end_defaults (GtkBox *@var{box}, GtkWidget *@var{widget})
+A convenience function which is equivalent to the following:
+
+@example
+ gtk_box_pack_start (@var{box}, @var{widget}, TRUE, TRUE, 0);
+@end example
+@end deftypefun
+
+@gtkstdmacros{Box, BOX}
+
+
+@page
+@node GtkButton, GtkCheckButton, GtkBox, Widgets
+@comment node-name, next, previous, up
+@section The button widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@deftypefn Signal void GtkButton::pressed (GtkButton *@var{button})
+@end deftypefn
+
+@deftypefn Signal void GtkButton::released (GtkButton *@var{button})
+@end deftypefn
+
+@deftypefn Signal void GtkButton::clicked (GtkButton *@var{button})
+@end deftypefn
+
+@deftypefn Signal void GtkButton::enter (GtkButton *@var{button})
+@end deftypefn
+
+@deftypefn Signal void GtkButton::leave (GtkButton *@var{button})
+@end deftypefn
+
+@subsection Functions
+
+@deftypefun guint gtk_button_get_type (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_button_new (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_button_new_with_label (gchar *@var{label})
+@end deftypefun
+
+@deftypefun void gtk_button_pressed (GtkButton *@var{button})
+@end deftypefun
+
+@deftypefun void gtk_button_released (GtkButton *@var{button})
+@end deftypefun
+
+@deftypefun void gtk_button_clicked (GtkButton *@var{button})
+@end deftypefun
+
+@deftypefun void gtk_button_enter (GtkButton *@var{button})
+@end deftypefun
+
+@deftypefun void gtk_button_leave (GtkButton *@var{button})
+@end deftypefun
+
+@gtkstdmacros{Button, BUTTON}
+
+
+@page
+@node GtkCheckButton, GtkCheckMenuItem, GtkButton, Widgets
+@comment node-name, next, previous, up
+@section The check button widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_check_button_get_type (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_check_button_new (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_check_button_new_with_label (gchar *@var{label})
+@end deftypefun
+
+@deftypefun GtkCheckButton* GTK_CHECK_BUTTON (gpointer @var{obj})
+@end deftypefun
+
+@deftypefun GtkCheckButtonClass* GTK_CHECK_BUTTON_CLASS (gpointer @var{class})
+@end deftypefun
+
+@deftypefun gint GTK_IS_CHECK_BUTTON (gpointer @var{obj})
+@end deftypefun
+
+@gtkstdmacros{CheckButton, CHECK_BUTTON}
+
+
+@page
+@node GtkCheckMenuItem, GtkContainer, GtkCheckButton, Widgets,
+@comment node-name, next, previous, up
+@section The check menu item widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@deftypefn Signal void GtkCheckMenuItem::toggled (GtkCheckMenuItem *@var{check_menu_item})
+@end deftypefn
+
+@subsection Functions
+
+@deftypefun guint gtk_check_menu_item_get_type (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_check_menu_item_new (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_check_menu_item_new_with_label (gchar *@var{label})
+@end deftypefun
+
+@deftypefun void gtk_check_menu_item_set_state (GtkCheckMenuItem *@var{check_menu_item}, gint @var{state})
+@end deftypefun
+
+@deftypefun void gtk_check_menu_item_toggled (GtkCheckMenuItem *@var{check_menu_item})
+@end deftypefun
+
+@gtkstdmacros{CheckMenuItem, CHECK_MENU_ITEM}
+
+
+@page
+@node GtkContainer, GtkDialog, GtkCheckMenuItem, Widgets
+@comment node-name, next, previous, up
+@section The container widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@deftypefn Signal void GtkContainer::add (GtkContainer *@var{container}, GtkWidget *@var{widget})
+@end deftypefn
+
+@deftypefn Signal void GtkContainer::remove (GtkContainer *@var{container}, GtkWidget *@var{widget})
+@end deftypefn
+
+@deftypefn Signal void GtkContainer::need_resize (GtkContainer *@var{container}, GtkWidget *@var{widget})
+@end deftypefn
+
+@deftypefn Signal void GtkContainer::foreach (GtkContainer *@var{container}, GtkCallback @var{callback}, gpointer @var{callback_data})
+@end deftypefn
+
+@deftypefn Signal gint GtkContainer::focus (GtkContainer *@var{container}, GtkDirectionType @var{direction})
+@end deftypefn
+
+@subsection Functions
+
+@deftypefun guint gtk_container_get_type (void)
+@end deftypefun
+
+@deftypefun void gtk_container_border_width (GtkContainer *@var{container}, gint @var{border_width})
+@end deftypefun
+
+@deftypefun void gtk_container_add (GtkContainer *@var{container}, GtkWidget *@var{widget})
+@end deftypefun
+
+@deftypefun void gtk_container_remove (GtkContainer *@var{container}, GtkWidget *@var{widget})
+@end deftypefun
+
+@deftypefun void gtk_container_disable_resize (GtkContainer *@var{container})
+@end deftypefun
+
+@deftypefun void gtk_container_enable_resize (GtkContainer *@var{container})
+@end deftypefun
+
+@deftypefun void gtk_container_block_resize (GtkContainer *@var{container})
+@end deftypefun
+
+@deftypefun void gtk_container_unblock_resize (GtkContainer *@var{container})
+@end deftypefun
+
+@deftypefun gint gtk_container_need_resize (GtkContainer *@var{container}, GtkWidget *@var{widget})
+@end deftypefun
+
+@deftypefun void gtk_container_check_resize (GtkContainer *@var{container}, GtkWidget *@var{widget})
+@end deftypefun
+
+@deftypefun void gtk_container_foreach (GtkContainer *@var{container}, GtkCallback @var{callback}, gpointer @var{callback_data})
+@end deftypefun
+
+@deftypefun void gtk_container_focus (GtkContainer *@var{container}, GtkDirectionType @var{direction})
+@end deftypefun
+
+@deftypefun GList* gtk_container_children (GtkContainer @var{container})
+@end deftypefun
+
+@gtkstdmacros{Container, CONTAINER}
+
+
+@page
+@node GtkDialog, GtkDrawingArea, GtkContainer, Widgets
+@comment node-name, next, previous, up
+@section The dialog widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_dialog_get_type (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_dialog_new (void)
+@end deftypefun
+
+@gtkstdmacros{Dialog, DIALOG}
+
+
+@page
+@node GtkDrawingArea, GtkEntry, GtkDialog, Widgets
+@comment node-name, next, previous, up
+@section The drawing area widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_drawing_area_get_type (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_drawing_area_new (void)
+@end deftypefun
+
+@deftypefun void gtk_drawing_area_size (GtkDrawingArea *@var{darea}, gint @var{width}, gint @var{height})
+@end deftypefun
+
+@gtkstdmacros{DrawingArea, DRAWING_AREA}
+
+
+@page
+@node GtkEntry, GtkFileSelection, GtkDrawingArea, Widgets
+@comment node-name, next, previous, up
+@section The entry widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@deftypefn Signal void GtkEntry::insert (GtkEntry *@var{entry}, gchar *@var{text}, gint @var{length}, gint *@var{position})
+@end deftypefn
+
+@deftypefn Signal void GtkEntry::delete (GtkEntry *@var{entry}, gint @var{start_pos}, gint @var{end_pos})
+@end deftypefn
+
+@deftypefn Signal void GtkEntry::changed (GtkEntry *@var{entry})
+@end deftypefn
+
+@subsection Functions
+
+@deftypefun guint gtk_entry_get_type (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_entry_new (void)
+@end deftypefun
+
+@deftypefun void gtk_entry_set_text (GtkEntry *@var{entry}, gchar *@var{text})
+@end deftypefun
+
+@deftypefun void gtk_entry_append_text (GtkEntry *@var{entry}, gchar *@var{text})
+@end deftypefun
+
+@deftypefun void gtk_entry_prepend_text (GtkEntry *@var{entry}, gchar *@var{text})
+@end deftypefun
+
+@deftypefun void gtk_entry_set_position (GtkEntry *@var{entry}, gint @var{position})
+@end deftypefun
+
+@deftypefun gchar* gtk_entry_get_text (GtkEntry *@var{entry})
+@end deftypefun
+
+@gtkstdmacros{Entry, ENTRY}
+
+
+@page
+@node GtkFileSelection, GtkFrame, GtkEntry, Widgets
+@comment node-name, next, previous, up
+@section The file selection dialog widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_file_selection_get_Type (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_file_selection_new (gchar *@var{title})
+@end deftypefun
+
+@deftypefun void gtk_file_selection_set_filename (GtkFileSelection *@var{filesel}, gchar *@var{filename})
+@end deftypefun
+
+@deftypefun gchar* gtk_file_selection_get_filename (GtkFileSelection *@var{filesel})
+@end deftypefun
+
+@gtkstdmacros{FileSelection, FILE_SELECTION}
+
+
+@page
+@node GtkFrame, GtkHBox, GtkFileSelection, Widgets
+@comment node-name, next, previous, up
+@section The frame widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_frame_get_type (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_frame_new (gchar *@var{label})
+@end deftypefun
+
+@deftypefun void gtk_frame_set_label (GtkFrame *@var{frame}, gchar *@var{label})
+@end deftypefun
+
+@deftypefun void gtk_frame_set_label_align (GtkFrame *@var{frame}, gfloat @var{xalign}, gfloat @var{yalign})
+@end deftypefun
+
+@deftypefun void gtk_frame_set_shadow_type (GtkFrame *@var{frame}, GtkShadowType @var{type})
+@end deftypefun
+
+@gtkstdmacros{Frame, FRAME}
+
+
+@page
+@node GtkHBox, GtkHRuler, GtkFrame, Widgets
+@comment node-name, next, previous, up
+@section The horizontal box widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_hbox_get_type (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_hbox_new (gint @var{homogeneous}, gint @var{spacing})
+@end deftypefun
+
+@gtkstdmacros{HBox, HBOX}
+
+
+@page
+@node GtkHRuler, GtkHScale, GtkHBox, Widgets
+@comment node-name, next, previous, up
+@section The horizontal ruler widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_hruler_get_type (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_hruler_new (void)
+@end deftypefun
+
+@gtkstdmacros{HRuler, HRULER}
+
+
+@page
+@node GtkHScale, GtkHScrollbar, GtkHRuler, Widgets
+@comment node-name, next, previous, up
+@section The horizontal scale widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_hscale_get_type (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_hscale_new (GtkAdjustment *@var{adjustment})
+@end deftypefun
+
+@gtkstdmacros{HScale, HSCALE}
+
+
+@page
+@node GtkHScrollbar, GtkHSeparator, GtkHScale, Widgets
+@comment node-name, next, previous, up
+@section The horizontal scrollbar widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_hscrollbar_get_type (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_hscrollbar_new (GtkAdjustment *@var{adjustment})
+@end deftypefun
+
+@gtkstdmacros{HScrollbar, HSCROLLBAR}
+
+
+@page
+@node GtkHSeparator, GtkImage, GtkHScrollbar, Widgets
+@comment node-name, next, previous, up
+@section The horizontal separator widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_hseparator_get_type (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_hseparator_new (void)
+@end deftypefun
+
+@gtkstdmacros{HSeparator, HSEPARATOR}
+
+
+@page
+@node GtkImage, GtkItem, GtkHSeparator, Widgets
+@comment node-name, next, previous, up
+@section The image widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_image_get_type (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_image_new (GdkImage *@var{val})
+@end deftypefun
+
+@deftypefun void gtk_image_set (GtkImage *@var{image}, GdkImage *@var{val})
+@end deftypefun
+
+@deftypefun void gtk_image_get (GtkImage *@var{image}, GdkImage **@var{val})
+@end deftypefun
+
+@gtkstdmacros{Image, IMAGE}
+
+
+@page
+@node GtkItem, GtkLabel, GtkImage, Widgets
+@comment node-name, next, previous, up
+@section The item widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@deftypefn Signal void GtkItem::select (GtkItem *@var{item})
+@end deftypefn
+
+@deftypefn Signal void GtkItem::deselect (GtkItem *@var{item})
+@end deftypefn
+
+@deftypefn Signal void GtkItem::toggle (GtkItem *@var{toggle})
+@end deftypefn
+
+@subsection Functions
+
+@deftypefun guint gtk_item_get_type (void)
+@end deftypefun
+
+@deftypefun void gtk_item_select (GtkItem *@var{item})
+@end deftypefun
+
+@deftypefun void gtk_item_deselect (GtkItem *@var{item})
+@end deftypefun
+
+@deftypefun void gtk_item_toggle (GtkItem *@var{item})
+@end deftypefun
+
+@gtkstdmacros{Item, ITEM}
+
+
+@page
+@node GtkLabel, GtkList, GtkItem, Widgets
+@comment node-name, next, previous, up
+@section The label widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_label_get_type (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_label_new (GtkLabel *@var{label}, gchar *@var{str})
+@end deftypefun
+
+@deftypefun void gtk_label_set (GtkLabel *@var{label}, gchar *@var{str})
+@end deftypefun
+
+@deftypefun void gtk_label_get (GtkLabel *@var{label}, gchar **@var{str})
+@end deftypefun
+
+@gtkstdmacros{Label, LABEL}
+
+
+@page
+@node GtkList, GtkListItem, GtkLabel, Widgets
+@comment node-name, next, previous, up
+@section The list widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@deftypefn Signal void GtkList::selection_changed (GtkList *@var{list})
+@end deftypefn
+
+@deftypefn Signal void GtkList::select_child (GtkList *@var{list}, GtkWidget *@var{child})
+@end deftypefn
+
+@deftypefn Signal void GtkList::unselect_child (GtkList *@var{list}, GtkWidget *@var{child})
+@end deftypefn
+
+@subsection Functions
+
+@deftypefun guint gtk_list_get_type (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_list_new (void)
+@end deftypefun
+
+@deftypefun void gtk_list_insert_items (GtkList *@var{list}, GList *@var{items}, gint @var{position})
+@end deftypefun
+
+@deftypefun void gtk_list_append_items (GtkList *@var{list}, GList *@var{items})
+@end deftypefun
+
+@deftypefun void gtk_list_prepend_items (GtkList *@var{list}, GList *@var{items})
+@end deftypefun
+
+@deftypefun void gtk_list_remove_items (GtkList *@var{list}, GList *@var{items})
+@end deftypefun
+
+@deftypefun void gtk_list_clear_items (GtkList *@var{list}, gint @var{start}, gint @var{end})
+@end deftypefun
+
+@deftypefun void gtk_list_select_item (GtkList *@var{list}, gint @var{item})
+@end deftypefun
+
+@deftypefun void gtk_list_unselect_item (GtkList *@var{list}, gint @var{item})
+@end deftypefun
+
+@deftypefun void gtk_list_select_child (GtkList *@var{list}, GtkWidget *@var{child})
+@end deftypefun
+
+@deftypefun void gtk_list_unselect_child (GtkList *@var{list}, GtkWidget *@var{child})
+@end deftypefun
+
+@deftypefun gint gtk_list_child_position (GtkList *@var{list}, GtkWidget *@var{child})
+@end deftypefun
+
+@deftypefun void gtk_list_set_selection_mode (GtkList *@var{list}, GtkSelectionMode @var{mode})
+@end deftypefun
+
+@gtkstdmacros{List, LIST}
+
+
+@page
+@node GtkListItem, GtkMenu, GtkList, Widgets
+@comment node-name, next, previous, up
+@section The list item widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_list_item_get_type (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_list_item_new (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_list_item_new_with_label (gchar *@var{label})
+@end deftypefun
+
+@deftypefun void gtk_list_item_select (GtkListItem *@var{list_item})
+@end deftypefun
+
+@deftypefun void gtk_list_item_deselect (GtkListItem *@var{list_item})
+@end deftypefun
+
+@gtkstdmacros{ListItem, LIST_ITEM}
+
+
+@page
+@node GtkMenu, GtkMenuBar, GtkListItem, Widgets
+@comment node-name, next, previous, up
+@section The menu widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_menu_get_type (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_menu_new (void)
+@end deftypefun
+
+@deftypefun void gtk_menu_append (GtkMenu *@var{menu}, GtkWidget *@var{child})
+@end deftypefun
+
+@deftypefun void gtk_menu_prepend (GtkMenu *@var{menu}, GtkWidget *@var{child})
+@end deftypefun
+
+@deftypefun void gtk_menu_insert (GtkMenu *@var{menu}, GtkWidget *@var{child}, gint @var{position})
+@end deftypefun
+
+@deftypefun void gtk_menu_popup (GtkMenu *@var{menu}, GtkWidget *@var{parent_menu_shell}, GtkWidget *@var{parent_menu_item}, GtkMenuPositionFunc @var{func}, gpointer @var{data}, gint @var{button})
+@end deftypefun
+
+@deftypefun void gtk_menu_popdown (GtkMenu *@var{menu})
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_menu_get_active (GtkMenu *@var{menu})
+@end deftypefun
+
+@deftypefun void gtk_menu_set_active (GtkMenu *@var{menu})
+@end deftypefun
+
+@deftypefun void gtk_menu_set_accelerator_table (GtkMenu *@var{menu}, GtkAcceleratorTable *@var{table})
+@end deftypefun
+
+@gtkstdmacros{Menu, MENU}
+
+
+@page
+@node GtkMenuBar, GtkMenuItem, GtkMenu, Widgets
+@comment node-name, next, previous, up
+@section The menu bar widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_menu_bar_get_type (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_menu_bar_new (void)
+@end deftypefun
+
+@deftypefun void gtk_menu_bar_append (GtkMenuBar *@var{menu_bar}, GtkWidget *@var{child})
+@end deftypefun
+
+@deftypefun void gtk_menu_bar_prepend (GtkMenuBar *@var{menu_bar}, GtkWidget *@var{child})
+@end deftypefun
+
+@deftypefun void gtk_menu_bar_insert (GtkMenuBar *@var{menu_bar}, GtkWidget *@var{child}, gint @var{position})
+@end deftypefun
+
+@gtkstdmacros{MenuBar, MENU_BAR}
+
+
+@page
+@node GtkMenuItem, GtkMenuShell, GtkMenuBar, Widgets
+@comment node-name, next, previous, up
+@section The menu item widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@deftypefn Signal void GtkMenuItem::activate (GtkMenuItem *@var{menu_item})
+@end deftypefn
+
+@subsection Functions
+
+@deftypefun guint gtk_menu_item_get_type (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_menu_item_new (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_menu_item_new_with_label (gchar *@var{label})
+@end deftypefun
+
+@deftypefun void gtk_menu_item_set_submenu (GtkMenuItem *@var{menu_item}, GtkWidget *@var{submenu})
+@end deftypefun
+
+@deftypefun void gtk_menu_item_set_placement (GtkMenuItem *@var{menu_item}, GtkSubmenuPlacement @var{placement})
+@end deftypefun
+
+@deftypefun void gtk_menu_item_accelerator_size (GtkMenuItem *@var{menu_item})
+@end deftypefun
+
+@deftypefun void gtk_menu_item_accelerator_text (GtkMenuItem *@var{menu_item}, gchar *@var{buffer})
+@end deftypefun
+
+@deftypefun void gtk_menu_item_configure (GtkMenuItem *@var{menu_item}, gint @var{show_toggle_indicator}, gint @var{show_submenu_indicator})
+@end deftypefun
+
+@deftypefun void gtk_menu_item_select (GtkMenuItem *@var{menu_item})
+@end deftypefun
+
+@deftypefun void gtk_menu_item_deselect (GtkMenuItem *@var{menu_item})
+@end deftypefun
+
+@deftypefun void gtk_menu_item_activate (GtkMenuItem *@var{menu_item})
+@end deftypefun
+
+@gtkstdmacros{MenuItem, MENU_ITEM}
+
+
+@page
+@node GtkMenuShell, GtkMisc, GtkMenuItem, Widgets
+@comment node-name, next, previous, up
+@section The menu shell widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@deftypefn Signal void GtkMenuShell::deactivate (GtkMenuShell *@var{menu_shell})
+@end deftypefn
+
+@subsection Functions
+
+@deftypefun guint gtk_menu_shell_get_type (void)
+@end deftypefun
+
+@deftypefun void gtk_menu_shell_append (GtkMenuShell *@var{menu_shell}, GtkWidget *@var{child})
+@end deftypefun
+
+@deftypefun void gtk_menu_shell_prepend (GtkMenuShell *@var{menu_shell}, GtkWidget *@var{child})
+@end deftypefun
+
+@deftypefun void gtk_menu_shell_insert (GtkMenuShell *@var{menu_shell}, GtkWidget *@var{child}, gint @var{position})
+@end deftypefun
+
+@deftypefun void gtk_menu_shell_deactivate (GtkMenuShell *@var{menu_shell})
+@end deftypefun
+
+@gtkstdmacros{MenuShell, MENU_SHELL}
+
+
+@page
+@node GtkMisc, GtkNotebook, GtkMenuShell, Widgets
+@comment node-name, next, previous, up
+@section The misc widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_misc_get_type (void)
+@end deftypefun
+
+@deftypefun void gtk_misc_set_alignment (GtkMisc *@var{misc}, gfloat @var{xalign}, gfloat @var{yalign})
+@end deftypefun
+
+@deftypefun void gtk_misc_set_padding (GtkMisc *@var{misc}, gint @var{xpad}, gint @var{ypad})
+@end deftypefun
+
+@gtkstdmacros{Misc, MISC}
+
+
+@page
+@node GtkNotebook, GtkOptionMenu, GtkMisc, Widgets
+@comment node-name, next, previous, up
+@section The notebook widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_notebook_get_type (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_notebook_new (void)
+@end deftypefun
+
+@deftypefun void gtk_notebook_append_page (GtkNotebook *@var{notebook}, GtkWidget *@var{child}, GtkWidget *@var{tab_label})
+@end deftypefun
+
+@deftypefun void gtk_notebook_prepend_page (GtkNotebook *@var{notebook}, GtkWidget *@var{child}, GtkWidget *@var{tab_label})
+@end deftypefun
+
+@deftypefun void gtk_notebook_insert_page (GtkNotebook *@var{notebook}, GtkWidget *@var{child}, GtkWidget *@var{tab_label}, gint @var{position})
+@end deftypefun
+
+@deftypefun void gtk_notebook_remove_page (GtkNotebook *@var{notebook}, gint @var{page_num})
+@end deftypefun
+
+@deftypefun void gtk_notebook_set_page (GtkNotebook *@var{notebook}, gint @var{page_num})
+@end deftypefun
+
+@deftypefun void gtk_notebook_next_page (GtkNotebook *@var{notebook})
+@end deftypefun
+
+@deftypefun void gtk_notebook_prev_page (GtkNotebook *@var{notebook})
+@end deftypefun
+
+@deftypefun void gtk_notebook_set_tab_pos (GtkNotebook *@var{notebook}, GtkPositionType @var{pos})
+@end deftypefun
+
+@deftypefun void gtk_notebook_set_show_tabs (GtkNotebook *@var{notebook}, gint @var{show_tabs})
+@end deftypefun
+
+@deftypefun void gtk_notebook_set_show_border (GtkNotebook *@var{notebook}, gint @var{show_border})
+@end deftypefun
+
+@gtkstdmacros{Notebook, NOTEBOOK}
+
+
+@page
+@node GtkOptionMenu, GtkPixmap, GtkNotebook, Widgets
+@comment node-name, next, previous, up
+@section The option menu widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_option_menu_get_type (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_option_menu_new (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_option_menu_get_menu (GtkOptionMenu *@var{option_menu})
+@end deftypefun
+
+@deftypefun void gtk_option_menu_set_menu (GtkOptionMenu *@var{option_menu}, GtkWidget *@var{menu})
+@end deftypefun
+
+@deftypefun void gtk_option_menu_remove_menu (GtkOptionMenu *@var{option_menu})
+@end deftypefun
+
+@deftypefun void gtk_option_menu_set_history (GtkOptionMenu *@var{option_menu}, gint @var{index})
+@end deftypefun
+
+@gtkstdmacros{OptionMenu, OPTION_MENU}
+
+
+@page
+@node GtkPixmap, GtkPreview, GtkOptionMenu, Widgets
+@comment node-name, next, previous, up
+@section The pixmap widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_pixmap_get_type (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_pixmap_new (GdkPixmap *@var{normal}, GdkPixmap *@var{active}, GdkPixmap *@var{prelight}, GdkPixmap *@var{selected}, GdkPixmap *@var{insensitive})
+@end deftypefun
+
+@deftypefun void gtk_pixmap_set (GtkPixmap *@var{pixmap}, GdkPixmap *@var{val}, GtkStateType @var{state})
+@end deftypefun
+
+@deftypefun void gtk_pixmap_get (GtkPixmap *@var{pixmap}, GdkPixmap **@var{val}, GtkStateType @var{state})
+@end deftypefun
+
+@gtkstdmacros{Pixmap, PIXMAP}
+
+
+@page
+@node GtkPreview, GtkProgressBar, GtkPixmap, Widgets
+@comment node-name, next, previous, up
+@section The preview widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_preview_get_type (void)
+@end deftypefun
+
+@deftypefun void gtk_preview_uninit (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_preview_new (GtkPreviewType @var{type})
+@end deftypefun
+
+@deftypefun void gtk_preview_size (GtkPreview *@var{preview}, gint @var{width}, gint @var{height})
+@end deftypefun
+
+@deftypefun void gtk_preview_put (GtkPreview *@var{preview}, GdkWindow *@var{window}, GdkGC *@var{gc}, gint @var{srcx}, gint @var{srcy}, gint @var{destx}, gint @var{desty}, gint @var{width}, gint @var{height})
+@end deftypefun
+
+@deftypefun void gtk_preview_put_row (GtkPreview *@var{preview}, guchar *@var{src}, guchar *@var{dest}, gint @var{x}, gint @var{y}, gint @var{w})
+@end deftypefun
+
+@deftypefun void gtk_preview_draw_row (GtkPreview *@var{preview}, guchar @var{data}, gint @var{x}, gint @var{y}, gint @var{w})
+@end deftypefun
+
+@deftypefun void gtk_preview_set_expand (GtkPreview *@var{preview}, gint @var{expand})
+@end deftypefun
+
+@deftypefun void gtk_preview_set_gamma (double @var{gamma})
+@end deftypefun
+
+@deftypefun void gtk_preview_set_color_cube (guint @var{nred_shades}, guint @var{ngreen_shades}, guint @var{nblue_shades}, guint @var{ngray_shades})
+@end deftypefun
+
+@deftypefun void gtk_preview_set_install_cmap (gint @var{install_cmap})
+@end deftypefun
+
+@deftypefun void gtk_preview_set_reserved (gint @var{nreserved})
+@end deftypefun
+
+@deftypefun GdkVisual* gtk_preview_get_visual (void)
+@end deftypefun
+
+@deftypefun GdkColormap* gtk_preview_get_cmap (void)
+@end deftypefun
+
+@deftypefun GtkPreviewInfo* gtk_preview_get_info (void)
+@end deftypefun
+
+@gtkstdmacros{Preview, PREVIEW}
+
+
+@page
+@node GtkProgressBar, GtkRadioButton, GtkPreview, Widgets
+@comment node-name, next, previous, up
+@section The progress bar widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_progress_bar_get_type (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_progress_bar_new (void)
+@end deftypefun
+
+@deftypefun void gtk_progress_bar_update (GtkProgressBar *@var{pbar}, gfloat @var{percentage})
+@end deftypefun
+
+@gtkstdmacros{ProgressBar, PROGRESS_BAR}
+
+
+@page
+@node GtkRadioButton, GtkRadioMenuItem, GtkProgressBar, Widgets
+@comment node-name, next, previous, up
+@section The radio button widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_radio_button_get_type (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_radio_button_new (GSList *@var{group})
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_radio_button_new_with_label (GSList *@var{group}, gchar *@var{label})
+@end deftypefun
+
+@deftypefun GSList* gtk_radio_button_group (GtkRadioButton *@var{radio_button})
+@end deftypefun
+
+@gtkstdmacros{RadioButton, RADIO_BUTTON}
+
+
+@page
+@node GtkRadioMenuItem, GtkRange, GtkRadioButton, Widgets
+@comment node-name, next, previous, up
+@section The radio button widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_radio_menu_item_get_type (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_radio_menu_item_new (GSList *@var{group})
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_radio_menu_item_new_with_label (GSList *@var{group}, gchar *@var{label})
+@end deftypefun
+
+@deftypefun GSList* gtk_radio_menu_item_group (GtkRadioMenuItem *@var{radio_menu_item})
+@end deftypefun
+
+@gtkstdmacros{RadioMenuItem, RADIO_MENU_ITEM}
+
+
+@page
+@node GtkRange, GtkRuler, GtkRadioMenuItem, Widgets
+@comment node-name, next, previous, up
+@section The range widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_range_get_type (void)
+@end deftypefun
+
+@deftypefun GtkAdjustment* gtk_range_get_adjustment (GtkRange *@var{range})
+@end deftypefun
+
+@deftypefun void gtk_range_set_update_policy (GtkRange *@var{range}, GtkUpdatePolicy @var{policy})
+@end deftypefun
+
+@deftypefun void gtk_range_set_adjustment (GtkRange *@var{range}, GtkAdjustment *@var{adjustment})
+@end deftypefun
+
+@deftypefun void gtk_range_draw_background (GtkRange *@var{range})
+@end deftypefun
+
+@deftypefun void gtk_range_draw_trough (GtkRange *@var{range})
+@end deftypefun
+
+@deftypefun void gtk_range_draw_slider (GtkRange *@var{range})
+@end deftypefun
+
+@deftypefun void gtk_range_draw_step_forw (GtkRange *@var{range})
+@end deftypefun
+
+@deftypefun void gtk_range_draw_step_back (GtkRange *@var{range})
+@end deftypefun
+
+@deftypefun void gtk_range_slider_update (GtkRange *@var{range})
+@end deftypefun
+
+@deftypefun gint gtk_range_trough_click (GtkRange *@var{range}, gint @var{x}, gint @var{y})
+@end deftypefun
+
+@deftypefun void gtk_range_default_hslider_update (GtkRange *@var{range})
+@end deftypefun
+
+@deftypefun void gtk_range_default_vslider_update (GtkRange *@var{range})
+@end deftypefun
+
+@deftypefun gint gtk_range_default_htrough_click (GtkRange *@var{range}, gint @var{x}, gint @var{y})
+@end deftypefun
+
+@deftypefun gint gtk_range_default_vtrough_click (GtkRange *@var{range}, gint @var{x}, gint @var{y})
+@end deftypefun
+
+@deftypefun void gtk_range_default_hmotion (GtkRange *@var{range}, gint @var{xdelta}, gint @var{ydelta})
+@end deftypefun
+
+@deftypefun void gtk_range_default_vmotion (GtkRange *@var{range}, gint @var{xdelta}, gint @var{ydelta})
+@end deftypefun
+
+@deftypefun gfloat gtk_range_calc_value (GtkRange *@var{ragne}, gint @var{position})
+@end deftypefun
+
+@gtkstdmacros{Range, RANGE}
+
+
+@page
+@node GtkRuler, GtkScale, GtkRange, Widgets
+@comment node-name, next, previous, up
+@section The ruler widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_ruler_get_type (void)
+@end deftypefun
+
+@deftypefun void gtk_ruler_set_metric (GtkRuler *@var{ruler}, GtkMetricType @var{metric})
+@end deftypefun
+
+@deftypefun void gtk_ruler_set_range (GtkRuler *@var{ruler}, gfloat @var{lower}, gfloat @var{upper}, gfloat @var{position}, gfloat @var{max_size})
+@end deftypefun
+
+@deftypefun void gtk_ruler_draw_ticks (GtkRuler *@var{ruler})
+@end deftypefun
+
+@deftypefun void gtk_ruler_draw_pos (GtkRuler *@var{ruler})
+@end deftypefun
+
+@gtkstdmacros{Ruler, RULER}
+
+
+@page
+@node GtkScale, GtkScrollbar, GtkRuler, Widgets
+@comment node-name, next, previous, up
+@section The scale widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_scale_get_type (void)
+@end deftypefun
+
+@deftypefun void gtk_scale_set_digits (GtkScale *@var{scale}, gint @var{digits})
+@end deftypefun
+
+@deftypefun void gtk_scale_set_draw_value (GtkScale *@var{scale}, gint @var{draw_value})
+@end deftypefun
+
+@deftypefun void gtk_scale_set_value_pos (GtkScale *@var{scale}, gint @var{pos})
+@end deftypefun
+
+@deftypefun gint gtk_scale_value_width (GtkScale *@var{scale})
+@end deftypefun
+
+@deftypefun void gtk_scale_draw_value (GtkScale *@var{scale})
+@end deftypefun
+
+@gtkstdmacros{Scale, SCALE}
+
+
+@page
+@node GtkScrollbar, GtkScrolledWindow, GtkScale, Widgets
+@comment node-name, next, previous, up
+@section The scrollbar widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_scrollbar_get_type (void)
+@end deftypefun
+
+@gtkstdmacros{Scrollbar, SCROLLBAR}
+
+
+@page
+@node GtkScrolledWindow, GtkSeparator, GtkScrollbar, Widgets
+@comment node-name, next, previous, up
+@section The scrolled window widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_scrolled_window_get_type (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_scrolled_window_new (GtkAdjustment *@var{hadjustment}, GtkAdjustment *@var{vadjustment})
+@end deftypefun
+
+@deftypefun GtkAdjustment* gtk_scrolled_window_get_hadjustment (GtkScrolledWindow *@var{scrolled_window})
+@end deftypefun
+
+@deftypefun GtkAdjustment* gtk_scrolled_window_get_vadjustment (GtkScrolledWindow *@var{scrolled_window})
+@end deftypefun
+
+@deftypefun void gtk_scrolled_window_set_policy (GtkScrolledWindow *@var{scrolled_window}, GtkPolicyType @var{hscrollbar_policy}, GtkPolicyType @var{vscrollbar_policy})
+@end deftypefun
+
+@gtkstdmacros{ScrolledWindow, SCROLLED_WINDOW}
+
+
+@page
+@node GtkSeparator, GtkTable, GtkScrolledWindow, Widgets
+@comment node-name, next, previous, up
+@section The separator widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_separator_get_type (void)
+@end deftypefun
+
+@gtkstdmacros{Separator, SEPARATOR}
+
+
+@page
+@node GtkTable, GtkText, GtkSeparator, Widgets
+@comment node-name, next, previous, up
+@section The table widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_table_get_type (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_table_new (gint @var{rows}, gint @var{columns}, gint @var{homogeneous})
+@end deftypefun
+
+@deftypefun void gtk_table_attach (GtkTable *@var{table}, GtkWidget *@var{child}, gint @var{left_attach}, gint @var{right_attach}, gint @var{top_attach}, gint @var{bottom_attach}, gint @var{xoptions}, gint @var{yoptions}, gint @var{xpadding}, gint @var{ypadding})
+@end deftypefun
+
+@deftypefun void gtk_table_attach_defaults (GtkTable *@var{table}, GtkWidget *@var{widget}, gint @var{left_attach}, gint @var{right_attach}, gint @var{top_attach}, gint @var{bottom_attach})
+@end deftypefun
+
+@deftypefun void gtk_table_set_row_spacing (GtkTable *@var{table}, gint @var{row}, gint @var{spacing})
+@end deftypefun
+
+@deftypefun void gtk_table_set_col_spacing (GtkTable *@var{table}, gint @var{col}, gint @var{spacing})
+@end deftypefun
+
+@deftypefun void gtk_table_set_row_spacings (GtkTable *@var{table}, gint @var{spacing})
+@end deftypefun
+
+@deftypefun void gtk_table_set_col_spacings (GtkTable *@var{table}, gint @var{spacing})
+@end deftypefun
+
+@gtkstdmacros{Table, TABLE}
+
+
+@page
+@node GtkText, GtkToggleButton, GtkTable, Widgets
+@comment node-name, next, previous, up
+@section The text widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_text_get_type (void)
+@end deftypefun
+
+@gtkstdmacros{Text, TEXT}
+
+
+@page
+@node GtkToggleButton, GtkTree, GtkText, Widgets
+@comment node-name, next, previous, up
+@section The toggle button widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@deftypefn Signal void GtkToggleButton::toggled (GtkToggleButton *@var{toggle_button})
+@end deftypefn
+
+@subsection Functions
+
+@deftypefun guint gtk_toggle_button_get_type (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_toggle_button_new (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_toggle_button_new_with_label (gchar *@var{label})
+@end deftypefun
+
+@deftypefun void gtk_toggle_button_set_mode (GtkToggleButton *@var{toggle_button}, gint @var{draw_indicator})
+@end deftypefun
+
+@deftypefun void gtk_toggle_button_set_state (GtkToggleButton *@var{toggle_button}, gint @var{state})
+@end deftypefun
+
+@deftypefun void gtk_toggle_button_toggled (GtkToggleButotn *@var{toggle_button})
+@end deftypefun
+
+@gtkstdmacros{ToggleButton, TOGGLE_BUTTON}
+
+
+@page
+@node GtkTree, GtkTreeItem, GtkToggleButton, Widgets
+@comment node-name, next, previous, up
+@section The tree widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_tree_get_type (void)
+@end deftypefun
+
+@gtkstdmacros{Tree, TREE}
+
+
+@page
+@node GtkTreeItem, GtkVBox, GtkTree, Widgets
+@comment node-name, next, previous, up
+@section The tree item widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_tree_item_get_type (void)
+@end deftypefun
+
+@gtkstdmacros{TreeItem, TREE_ITEM}
+
+
+@page
+@node GtkVBox, GtkViewport, GtkTreeItem, Widgets
+@comment node-name, next, previous, up
+@section The vertical box widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_vbox_get_type (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_vbox_new (gint @var{homogeneous}, gint @var{spacing})
+@end deftypefun
+
+@gtkstdmacros{VBox, VBOX}
+
+
+@page
+@node GtkViewport, GtkVRuler, GtkVBox, Widgets
+@comment node-name, next, previous, up
+@section The viewport widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_viewport_get_type (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_viewport_new (GtkAdjustment *@var{hadjustment}, GtkAdjustment *@var{vadjustment})
+@end deftypefun
+
+@deftypefun GtkAdjustment* gtk_viewport_get_hadjustment (GtkViewport *@var{viewport})
+@end deftypefun
+
+@deftypefun GtkAdjustment* gtk_viewport_get_vadjustment (GtkViewport *@var{viewport})
+@end deftypefun
+
+@deftypefun void gtk_viewport_set_hadjustment (GtkViewport *@var{viewport}, GtkAdjustment *@var{adjustment})
+@end deftypefun
+
+@deftypefun void gtk_viewport_set_vadjustment (GtkViewport *@var{viewport}, GtkAdjustment *@var{adjustment})
+@end deftypefun
+
+@deftypefun void gtk_viewport_set_shadow_type (GtkViewport *@var{viewport}, GtkShadowType @var{type})
+@end deftypefun
+
+@gtkstdmacros{Viewport, VIEWPORT}
+
+
+@page
+@node GtkVRuler, GtkVScale, GtkViewport, Widgets
+@comment node-name, next, previous, up
+@section The vertical ruler widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_vruler_get_type (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_vruler_new (void)
+@end deftypefun
+
+@gtkstdmacros{VRuler, VRULER}
+
+
+@page
+@node GtkVScale, GtkVScrollbar, GtkVRuler, Widgets
+@comment node-name, next, previous, up
+@section The vertical ruler widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_vscale_get_type (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_vscale_new (GtkAdjustment *@var{adjustment})
+@end deftypefun
+
+@gtkstdmacros{VScale, VSCALE}
+
+
+@page
+@node GtkVScrollbar, GtkVSeparator, GtkVScale, Widgets
+@comment node-name, next, previous, up
+@section The vertical scrollbar widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_vscrollbar_get_type (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_vscrollbar_new (GtkAdjustment *@var{adjustment})
+@end deftypefun
+
+@gtkstdmacros{VScrollbar, VSCROLLBAR}
+
+
+@page
+@node GtkVSeparator, GtkWidget, GtkVScrollbar, Widgets
+@comment node-name, next, previous, up
+@section The vertical separator widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@subsection Functions
+
+@deftypefun guint gtk_vseparator_get_type (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_vseparator_new (void)
+@end deftypefun
+
+@gtkstdmacros{VSeparator, VSEPARATOR}
+
+
+@page
+@node GtkWidget, GtkWindow, GtkVSeparator, Widgets
+@comment node-name, next, previous, up
+@section The base widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@deftypefn Signal void GtkWidget::show (GtkWidget *@var{widget})
+@end deftypefn
+
+@deftypefn Signal void GtkWidget::hide (GtkWidget *@var{widget})
+@end deftypefn
+
+@deftypefn Signal void GtkWidget::map (GtkWidget *@var{widget})
+@end deftypefn
+
+@deftypefn Signal void GtkWidget::unmap (GtkWidget *@var{widget})
+@end deftypefn
+
+@deftypefn Signal void GtkWidget::realize (GtkWidget *@var{widget})
+@end deftypefn
+
+@deftypefn Signal void GtkWidget::unrealize (GtkWidget *@var{widget})
+@end deftypefn
+
+@deftypefn Signal void GtkWidget::draw (GtkWidget *@var{widget}, GdkRectangle *@var{area})
+@end deftypefn
+
+@deftypefn Signal void GtkWidget::draw_focus (GtkWidget *@var{widget})
+@end deftypefn
+
+@deftypefn Signal void GtkWidget::draw_default (GtkWidget *@var{widget})
+@end deftypefn
+
+@deftypefn Signal void GtkWidget::size_request (GtkWidget *@var{widget}, GtkRequisition *@var{requisition})
+@end deftypefn
+
+@deftypefn Signal void GtkWidget::size_allocate (GtkWidget *@var{widget}, GtkAllocation *@var{allocation})
+@end deftypefn
+
+@deftypefn Signal void GtkWidget::state_changed (GtkWidget *@var{widget})
+@end deftypefn
+
+@deftypefn Signal gint GtkWidget::install_accelerator (GtkWidget *@var{widget}, gchar *@var{signal_name}, gchar @var{key}, guint8 @var{modifiers})
+@end deftypefn
+
+@deftypefn Signal void GtkWidget::remove_accelerator (GtkWidget *@var{widget}, gchar *@var{signal_name})
+@end deftypefn
+
+@deftypefn Signal gint GtkWidget::event (GtkWidget *@var{widget}, GdkEvent *@var{event})
+@end deftypefn
+
+@deftypefn Signal gint GtkWidget::button_press_event (GtkWidget *@var{widget}, GdkEventButton *@var{event})
+@end deftypefn
+
+@deftypefn Signal gint GtkWidget::button_release_event (GtkWidget *@var{widget}, GdkEventButton *@var{event})
+@end deftypefn
+
+@deftypefn Signal gint GtkWidget::motion_notify_event (GtkWidget *@var{widget}, GdkEventMotion *@var{event})
+@end deftypefn
+
+@deftypefn Signal gint GtkWidget::delete_event (GtkWidget *@var{widget}, GdkEventAny *@var{event})
+@end deftypefn
+
+@deftypefn Signal gint GtkWidget::destroy_event (GtkWidget *@var{widget}, GdkEventAny *@var{event})
+@end deftypefn
+
+@deftypefn Signal gint GtkWidget::expose_event (GtkWidget *@var{widget}, GdkEventExpose *@var{event})
+@end deftypefn
+
+@deftypefn Signal gint GtkWidget::key_press_event (GtkWidget *@var{widget}, GdkEventKey *@var{event})
+@end deftypefn
+
+@deftypefn Signal gint GtkWidget::key_release_event (GtkWidget *@var{widget}, GdkEventKey *@var{event})
+@end deftypefn
+
+@deftypefn Signal gint GtkWidget::enter_notify_event (GtkWidget *@var{widget}, GdkEventCrossing *@var{event})
+@end deftypefn
+
+@deftypefn Signal gint GtkWidget::leave_notify_event (GtkWidget *@var{widget}, GdkEventCrossing *@var{event})
+@end deftypefn
+
+@deftypefn Signal gint GtkWidget::configure_event (GtkWidget *@var{widget}, GdkEventConfigure *@var{event})
+@end deftypefn
+
+@deftypefn Signal gint GtkWidget::focus_in_event (GtkWidget *@var{widget}, GdkEventFocus *@var{event})
+@end deftypefn
+
+@deftypefn Signal gint GtkWidget::focus_out_event (GtkWidget *@var{widget}, GdkEventFocus *@var{event})
+@end deftypefn
+
+@deftypefn Signal gint GtkWidget::map_event (GtkWidget *@var{widget}, GdkEventAny *@var{event})
+@end deftypefn
+
+@deftypefn Signal gint GtkWidget::unmap_event (GtkWidget *@var{widget}, GdkEventAny *@var{event})
+@end deftypefn
+
+@deftypefn Signal gint GtkWidget::property_notify_event (GtkWidget *@var{widget}, GdkEventProperty *@var{event})
+@end deftypefn
+
+@deftypefn Signal gint GtkWidget::selection_clear_event (GtkWidget *@var{widget}, GdkEventSelection *@var{event})
+@end deftypefn
+
+@deftypefn Signal gint GtkWidget::selection_request_event (GtkWidget *@var{widget}, GdkEventSelection *@var{event})
+@end deftypefn
+
+@deftypefn Signal gint GtkWidget::selection_notify_event (GtkWidget *@var{widget}, GdkEventSelection *@var{event})
+@end deftypefn
+
+@deftypefn Signal gint GtkWidget::drop_event (GtkWidget *@var{widget}, GdkEventDrop *@var{event})
+@end deftypefn
+
+@deftypefn Signal gint GtkWidget::drag_begin_event (GtkWidget *@var{widget}, GdkEventDragBegin *@var{event})
+@end deftypefn
+
+@deftypefn Signal gint GtkWidget::other_event (GtkWidget *@var{widget}, GdkEventOther *@var{event})
+@end deftypefn
+
+@subsection Functions
+
+@deftypefun guint gtk_widget_get_type (void)
+@end deftypefun
+
+@deftypefun void gtk_widget_class_init (GtkWidgetClass *@var{class})
+@end deftypefun
+
+@deftypefun void gtk_widget_init (GtkWidget *@var{widget})
+@end deftypefun
+
+@deftypefun void gtk_widget_destroy (GtkWidget *@var{widget})
+@end deftypefun
+
+@deftypefun void gtk_widget_show (GtkWidget *@var{widget})
+@end deftypefun
+
+@deftypefun void gtk_widget_hide (GtkWidget *@var{widget})
+@end deftypefun
+
+@deftypefun void gtk_widget_map (GtkWidget *@var{widget})
+@end deftypefun
+
+@deftypefun void gtk_widget_unmap (GtkWidget *@var{widget})
+@end deftypefun
+
+@deftypefun void gtk_widget_realize (GtkWidget *@var{widget})
+@end deftypefun
+
+@deftypefun void gtk_widget_unrealize (GtkWidget *@var{widget})
+@end deftypefun
+
+@deftypefun void gtk_widget_draw (GtkWidget *@var{widget}, GdkRectangle *@var{area})
+@end deftypefun
+
+@deftypefun void gtk_widget_draw_focus (GtkWidget *@var{widget})
+@end deftypefun
+
+@deftypefun void gtk_widget_draw_children (GtkWidget *@var{widget})
+@end deftypefun
+
+@deftypefun void gtk_widget_size_request (GtkWidget *@var{widget}, GtkRequisition *@var{requisition})
+@end deftypefun
+
+@deftypefun void gtk_widget_size_allocate (GtkWidget *@var{widget}, GtkAllocation *@var{allocation})
+@end deftypefun
+
+@deftypefun void gtk_widget_install_accelerator (GtkWidget *@var{widget}, GtkAcceleratorTable *@var{table}, gchar *@var{signal_name}, gchar @var{key}, guint8 @var{modifiers})
+@end deftypefun
+
+@deftypefun void gtk_widget_remove_accelerator (GtkWidget *@var{widget}, GtkAcceleratorTable *@var{table}, gchar *@var{signal_name})
+@end deftypefun
+
+@deftypefun gint gtk_widget_event (GtkWidget *@var{widget}, GdkEvent *@var{event})
+@end deftypefun
+
+@deftypefun void gtk_widget_reparent (GtkWidget *@var{widget}, GtkWidget *@var{new_parent})
+@end deftypefun
+
+@deftypefun void gtk_widget_popup (GtkWidget *@var{widget}, gint @var{x}, gint @var{y})
+@end deftypefun
+
+@deftypefun gint gtk_widget_intersect (GtkWidget *@var{widget}, GdkRectangle *@var{area}, GdkRectangle *@var{intersection})
+@end deftypefun
+
+@deftypefun void gtk_widget_grab_focus (GtkWidget *@var{widget})
+@end deftypefun
+
+@deftypefun void gtk_widget_grab_default (GtkWidget *@var{widget})
+@end deftypefun
+
+@deftypefun void gtk_widget_restore_state (GtkWidget *@var{widget})
+@end deftypefun
+
+@deftypefun void gtk_widget_set_name (GtkWidget *@var{widget}, gchar *@var{name})
+@end deftypefun
+
+@deftypefun void gtk_widget_set_state (GtkWidget *@var{widget}, GtkStateType @var{state})
+@end deftypefun
+
+@deftypefun void gtk_widget_set_sensitive (GtkWidget *@var{widget}, gint sensitive)
+@end deftypefun
+
+@deftypefun void gtk_widget_set_parent (GtkWidget *@var{widget}, GtkWidget *@var{parent})
+@end deftypefun
+
+@deftypefun void gtk_widget_set_style (GtkWidget *@var{widget}, GtkStyle *@var{style})
+@end deftypefun
+
+@deftypefun void gtk_widget_set_uposition (GtkWidget *@var{widget}, gint @var{x}, gint @var{y})
+@end deftypefun
+
+@deftypefun void gtk_widget_set_usize (GtkWidget *@var{widget}, gint @var{width}, gint @var{height})
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_widget_get_toplevel (GtkWidget *@var{widget})
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_widget_get_ancestor (GtkWidget *@var{widget}, gint @var{type})
+@end deftypefun
+
+@deftypefun GdkColormap* gtk_widget_get_colormap (GtkWidget *@var{widget})
+@end deftypefun
+
+@deftypefun GdkVisual* gtk_widget_get_visual (GtkWidget *@var{visual})
+@end deftypefun
+
+@deftypefun GtkStyle* gtk_widget_get_style (GtkWidget *@var{style})
+@end deftypefun
+
+@gtkstdmacros{Widget, WIDGET}
+
+
+@page
+@node GtkWindow, , GtkWidget, Widgets
+@comment node-name, next, previous, up
+@section The window widget
+
+
+@subsection Description
+
+@subsection Signals
+
+@deftypefn Signal void GtkWindow::move_resize (GtkWindow *@var{window}, gint *@var{x}, gint *@var{y}, gint @var{width}, gint @var{height})
+@end deftypefn
+
+@subsection Functions
+
+@deftypefun guint gtk_window_get_type (void)
+@end deftypefun
+
+@deftypefun GtkWidget* gtk_window_new (GtkWindowType @var{type})
+@end deftypefun
+
+@deftypefun void gtk_window_set_title (GtkWindow *@var{window}, gchar *@var{title})
+@end deftypefun
+
+@deftypefun void gtk_window_set_focus (GtkWindow *@var{window}, GtkWidget *@var{focus})
+@end deftypefun
+
+@deftypefun void gtk_window_set_default (GtkWindow *@var{window}, GtkWidget *@var{defaultw})
+@end deftypefun
+
+@deftypefun void gtk_window_set_policy (GtkWindow *@var{window}, gint @var{allow_shrink}, gint @var{allow_grow}, gint @var{auto_shrink})
+@end deftypefun
+
+@deftypefun void gtk_window_add_accelerator_table (GtkWindow *@var{window}, GtkAcceleratorTable *@var{table})
+@end deftypefun
+
+@deftypefun void gtk_window_remove_accelerator_table (GtkWindow *@var{window}, GtkAcceleratorTable *@var{table})
+@end deftypefun
+
+@deftypefun void gtk_window_position (GtkWindow *@var{window}, GtkWindowPosition @var{position})
+@end deftypefun
+
+@gtkstdmacros{Window, WINDOW}
+
+
+@node Other Objects, Miscellaneous, Widgets, Top
+@comment node-name, next, previous, up
+@chapter Utility objects
+
+
+@menu
+* GtkAdjustment:: The adjustment object.
+* GtkData:: The data object.
+@end menu
+
+
+@node GtkAdjustment, GtkData, Other Objects, Other Objects
+@comment node-name, next, previous, up
+@section The adjustment object
+
+
+@node GtkData, , GtkAdjustment, Other Objects
+@comment node-name, next, previous, up
+@section The data object
+
+
+@node Miscellaneous, Examples, Other Objects, Top
+@comment node-name, next, previous, up
+@chapter Initialization, exit and other features
+
+
+@menu
+* Initialization and exit:: Initializing and exiting GTK.
+* Menu Factories:: Simplified menu creation.
+* Tree Factories:: Simplified tree creation.
+* Tool Tips:: Pop up help mechanism.
+* Resource Files:: Resource files.
+* Standard Macros:: Macros defined by all objects.
+@end menu
+
+
+@node Initialization and exit, Menu Factories, Miscellaneous, Miscellaneous
+@comment node-name, next, previous, up
+@section Initializing and exiting GTK
+
+
+@node Menu Factories, Tree Factories, Initialization and exit, Miscellaneous
+@comment node-name, next, previous, up
+@section Simplified menu creation
+
+
+@node Tree Factories, Tool Tips, Menu Factories, Miscellaneous
+@comment node-name, next, previous, up
+@section Simplified tree creation
+
+
+@node Tool Tips, Resource Files, Tree Factories, Miscellaneous
+@comment node-name, next, previous, up
+@section Pop up help mechanism
+
+
+@node Resource Files, Standard Macros, Tool Tips, Miscellaneous
+@comment node-name, next, previous, up
+@section Pop up help mechanism
+
+
+@node Standard Macros, , Resource Files, Miscellaneous
+@comment node-name, next, previous, up
+@section Macros defined by all objects
+
+There are three macros that are defined by all object types. The first
+two are used for performing casts and the last is for querying whether
+an object is of a particular type. These macros are both conveniences
+and debugging tools. If the GTK library was compiled with @code{NDEBUG}
+defined as a preprocessor symbol (via the -DNDEBUG to cc), then the
+macros check the object type and emit a warning if the cast is
+invalid. Doing such checking is fairly expensive since the cast macros
+are used everywhere in GTK and would normally be turned off in a public
+release of a product. Note: The functions below are indeed macros, but
+they may be considered functions for most purposes.
+
+@deftypefun Gtk<ObjectType>* GTK_<OBJECT_TYPE> (gpointer @var{obj})
+Cast a generic pointer to @code{Gtk<ObjectType>*}. This function is
+provided in order to be able to provide checking during development
+stages of code development since it is possible to examine the actual
+type of object (using @code{gtk_type_is_a}) before performing the cast.
+@end deftypefun
+
+@deftypefun Gtk<ObjectType>Class* GTK_<OBJECT_TYPE>_CLASS (gpointer @var{class})
+Cast a generic pointer to @code{Gtk<ObjectType>Class*}. Like
+@code{GTK_<ObjectType>}, this function is, in reality, a macro.
+@end deftypefun
+
+@deftypefun gint GTK_IS_<ObjectType> (gpointer @var{obj})
+Determine if a generic pointer refers to a @code{Gtk<ObjectType>}
+object. This function is, in reality, a macro wrapper around the
+@code{gtk_type_is_a} function (@pxref{Objects}).
+@end deftypefun
+
+
+@node Examples, Object Implementation, Miscellaneous, Top
+@comment node-name, next, previous, up
+@chapter Using GTK
+
+
+@menu
+* Simple:: The simplest GTK program.
+* Hello World:: Hello world in GTK.
+* Hello World II:: An enhanced hello world.
+* Hello World III:: Making Hello World II robust.
+@end menu
+
+
+@node Simple, Hello World, Examples, Examples
+@comment node-name, next, previous, up
+@section The simplest GTK program
+
+
+The 16 line GTK program shown below is just about the simplest possible
+program which uses GTK. (Well, technically, you don't have to create the
+window and it would still be a program which uses GTK). The program,
+when compiled and run, will create a single window 200x200 pixels in
+size. The program does not exit until its is explicitly killed using the
+shell or a window manager function.
+
+@example
+#include <gtk/gtk.h>
+
+int
+main (int argc, char *argv[])
+@{
+ GtkWidget *window;
+
+ gtk_init (&argc, &argv);
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_widget_show (window);
+
+ gtk_main ();
+
+ return 0;
+@}
+@end example
+
+The first point of interest in this program is the standard
+initialization line.
+
+@example
+ gtk_init (&argc, &argv);
+@end example
+
+Almost every GTK program will contain such a line. GTK will initialize
+itself and GDK and remove any command line arguments it recognizes from
+@var{argc} and @var{argv}.
+
+The next two lines of code create and display a window.
+
+@example
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_widget_show (window);
+@end example
+
+The @code{GTK_WINDOW_TOPLEVEL} argument specifies that we want the
+window to undergo window manager decoration and placement. One might be
+lead to think that the window, since it has no children, would be 0x0
+pixels in size. But, this is not the case because a window that has no
+children defaults to 200x200 pixels in size. Mainly because 0x0 windows
+are annoying to manipulate or even see in some cases.
+
+The last line enters the GTK main processing loop.
+
+@example
+ gtk_main ();
+@end example
+
+Normally, @code{gtk_main} is called once and the program should exit
+when it returns. @xref{Initialization and exit}.
+
+
+@node Hello World, Hello World II, Simple, Examples
+@comment node-name, next, previous, up
+@section Hello world in GTK
+
+
+@example
+#include <gtk/gtk.h>
+
+int
+main (int argc, char *argv[])
+@{
+ GtkWidget *window;
+ GtkWidget *label;
+
+ gtk_init (&argc, &argv);
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_container_border_width (GTK_CONTAINER (window), 10);
+
+ label = gtk_label_new ("Hello World");
+ gtk_container_add (GTK_CONTAINER (window), label);
+ gtk_widget_show (label);
+
+ gtk_widget_show (window);
+
+ gtk_main ();
+
+ return 0;
+@}
+@end example
+
+
+@node Hello World II, Hello World III, Hello World, Examples
+@comment node-name, next, previous, up
+@section An enhanced hello world
+
+
+@example
+#include "gtk.h"
+
+void
+hello (void)
+@{
+ g_print ("Hello World\n");
+ gtk_exit (0);
+@}
+
+int
+main (int argc, char *argv[])
+@{
+ GtkWidget *window;
+ GtkWidget *button;
+
+ gtk_init (&argc, &argv);
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_container_border_width (GTK_CONTAINER (window), 10);
+
+ button = gtk_button_new_with_label ("Hello World");
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ GTK_SIGNAL_FUNC (hello), NULL);
+ gtk_container_add (GTK_CONTAINER (window), button);
+ gtk_widget_show (button);
+
+ gtk_widget_show (window);
+
+ gtk_main ();
+
+ return 0;
+@}
+@end example
+
+
+@node Hello World III, , Hello World II, Examples
+@comment node-name, next, previous, up
+@section Making Hello World II robust
+
+
+@example
+#include "gtk.h"
+
+void
+hello (void)
+@{
+ g_print ("Hello World\n");
+ gtk_exit (0);
+@}
+
+void
+destroy (void)
+@{
+ gtk_exit (0);
+@}
+
+int
+main (int argc, char *argv[])
+@{
+ GtkWidget *window;
+ GtkWidget *button;
+
+ gtk_init (&argc, &argv);
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ GTK_SIGNAL_FUNC (destroy), NULL);
+ gtk_container_border_width (GTK_CONTAINER (window), 10);
+
+ button = gtk_button_new_with_label ("Hello World");
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ GTK_SIGNAL_FUNC (hello), NULL);
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ GTK_SIGNAL_FUNC (gtk_widget_destroy),
+ GTK_OBJECT (window));
+ gtk_container_add (GTK_CONTAINER (window), button);
+ gtk_widget_show (button);
+
+ gtk_widget_show (window);
+
+ gtk_main ();
+
+ return 0;
+@}
+@end example
+
+
+@node Object Implementation, Signal Implementation, Examples, Top
+@comment node-name, next, previous, up
+@chapter Object internals
+@cindex Object Implementaton
+
+Objects (or the @code{GtkObject} type) and the class hierarchy in
+general is implemented via a hierarchy of structs and type casting. Be
+aware that when classes are mentioned it is the conceptual idea of
+classes that is being referred to. GTK is written entirely in C which
+provides no direct support for classes.
+
+The first part to the class mechanism is the object fields. These are
+fields that will be used on a per object basis. For example, the widget
+type contains a field for the widgets parent. Every derived type needs a
+reference to its parent type. A descendant class of @code{GtkObject}
+would define itself like:
+
+@example
+struct Descendant
+@{
+ GtkObject object;
+
+ @dots{}
+@};
+@end example
+
+It is important to note that the @code{GtkObject} field needs to appear
+first in the descendant type structure. This allows pointers to objects
+of type @code{Descendant} to be cast to pointers to @code{GtkObjects}'s
+and vice-versa.
+
+The second part to the class mechanism is the class fields. These fields
+are defined on a per class basis. In the case of widgets, the class
+fields are all the ``virtual'' functions for widgets. The
+@code{GtkObject} class defines the @code{destroy} virtual function and
+the necessary fields for the signal mechanism as well as a field for
+determining the runtime type of an object. A virtual function is
+semantically the same as it is in C++. That is, the actual function that
+is called is determined based on the type of the object. Or, more
+specifically, the actual function call depends on the class structure
+that is pointed to by the @code{klass} field of the @code{GtkObject}
+structure.
+
+To see how the class fields work it is necessary to see the object
+fields for a @code{GtkObject}. The @code{GtkObject} type is defined as
+follows:
+
+@example
+typedef struct _GtkObject GtkObject;
+
+struct _GtkObject
+@{
+ guint32 flags;
+ GtkObjectClass *klass;
+ gpointer object_data;
+@};
+@end example
+
+The @code{class} field actually points to a class structure derived from
+@code{GtkObjectClass}. By convention, each new type defines its own
+class structure even if it is unnecessary. As an example, the
+hypothetical @code{Descendant} class would define its class structure
+as:
+
+@example
+struct DescendantClass
+@{
+ GtkObjectClass parent_class;
+
+ @dots{}
+@};
+@end example
+
+It is convention to name the parent class field (@code{GtkObjectClass}
+in this case), @code{parent_class}. For the same reason as stated above
+for the object structure, the parent class field must be the first field
+in the class structure.
+
+@strong{Note:} GTK assumes that the first field in a structure will be
+placed by the compiler at the start of the structure. This is certainly
+true for gcc, however, from my precursory reading of the C standard I
+was unable to come to a definite conclusion as to whether this was
+required or simply done for simplicity. I'm not too worried about this
+assumption, though, as every C compiler I've ever encountered would work
+with GTK.
+
+The @code{flags} field of the @code{GtkObject} structure is used to keep
+track of a relatively few object flags and is also used by the
+@code{GtkWidget} type to store additional flags. At this time, the upper
+16 bits of the flags field are reserved but unused.
+
+The @code{object_data} field of the @code{GtkObject} structure is an
+opaque pointer used by the object data mechanism. In truth, it is a
+pointer to the beginning of the data list which is composed of the
+following structures.
+
+@example
+typedef struct _GtkObjectData GtkObjectData;
+
+struct _GtkObjectData
+@{
+ guint id;
+ gpointer data;
+ GtkObjectData *next;
+@};
+@end example
+
+The data mechanism allows arbitrary data to be associated with a
+character string key in any object. A hash table is used to transform
+the character string key into the data id and then a search through the
+list is made to see if the data exists. The assumption being that the
+data list will usually be short and therefore a linear search is
+ok. Future work on the data mechanism might make use of a resizable
+array instead of a linked list. This would shrink the overhead of the
+@code{GtkObjectData} structure by 4 bytes on 32 bit architectures.
+
+
+@node Signal Implementation, Widget Implementation, Object Implementation, Top
+@comment node-name, next, previous, up
+@chapter Signal internals
+@cindex Signal Implementation
+
+
+@node Widget Implementation, Function Index, Signal Implementation, Top
+@comment node-name, next, previous, up
+@chapter Widget internals
+@cindex Widget Implementation
+
+
+@node Function Index, Concept Index, Widget Implementation, Top
+@comment node-name, next, previous, up
+@unnumbered Function Index
+
+@printindex fn
+
+
+@node Concept Index, , Function Index, Top
+@comment node-name, next, previous, up
+@unnumbered Concept Index
+
+@printindex cp
+
+
+@summarycontents
+@contents
+@bye
diff --git a/docs/macros.texi b/docs/macros.texi
new file mode 100644
index 000000000..f8df89a46
--- /dev/null
+++ b/docs/macros.texi
@@ -0,0 +1,18 @@
+@macro gtkstdmacros {p, q}
+
+@deftypefun Gtk\p\* GTK_\q\ (gpointer @var{obj})
+Cast a generic pointer to @code{Gtk\p\*}. @xref{Standard Macros}, for
+more info.
+@end deftypefun
+
+@deftypefun Gtk\p\Class* GTK_\q\_CLASS (gpointer @var{class})
+Cast a generic pointer to @code{Gtk\p\Class*}. @xref{Standard Macros},
+for more info.
+@end deftypefun
+
+@deftypefun gint GTK_IS_\q\ (gpointer @var{obj})
+Determine if a generic pointer refers to a @code{Gtk\p\}
+object. @xref{Standard Macros}, for more info.
+@end deftypefun
+
+@end macro
diff --git a/docs/texinfo.tex b/docs/texinfo.tex
new file mode 100644
index 000000000..7d62f26f7
--- /dev/null
+++ b/docs/texinfo.tex
@@ -0,0 +1,4692 @@
+%% TeX macros to handle texinfo files
+
+% Copyright (C) 1985, 86, 88, 90, 91, 92, 93,
+% 94, 95, 1996 Free Software Foundation, Inc.
+
+%This texinfo.tex file is free software; you can redistribute it and/or
+%modify it under the terms of the GNU General Public License as
+%published by the Free Software Foundation; either version 2, or (at
+%your option) any later version.
+
+%This texinfo.tex file 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
+%General Public License for more details.
+
+%You should have received a copy of the GNU General Public License
+%along with this texinfo.tex file; see the file COPYING. If not, write
+%to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+%Boston, MA 02111-1307, USA.
+
+
+%In other words, you are welcome to use, share and improve this program.
+%You are forbidden to forbid anyone else to use, share and improve
+%what you give them. Help stamp out software-hoarding!
+
+
+% Send bug reports to bug-texinfo@prep.ai.mit.edu.
+% Please include a *precise* test case in each bug report.
+
+
+% Make it possible to create a .fmt file just by loading this file:
+% if the underlying format is not loaded, start by loading it now.
+% Added by gildea November 1993.
+\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi
+
+% This automatically updates the version number based on RCS.
+\def\deftexinfoversion$#1: #2 ${\def\texinfoversion{#2}}
+\deftexinfoversion$Revision$
+\message{Loading texinfo package [Version \texinfoversion]:}
+
+% If in a .fmt file, print the version number
+% and turn on active characters that we couldn't do earlier because
+% they might have appeared in the input file name.
+\everyjob{\message{[Texinfo version \texinfoversion]}\message{}
+ \catcode`+=\active \catcode`\_=\active}
+
+% Save some parts of plain tex whose names we will redefine.
+
+\let\ptexb=\b
+\let\ptexbullet=\bullet
+\let\ptexc=\c
+\let\ptexcomma=\,
+\let\ptexdot=\.
+\let\ptexdots=\dots
+\let\ptexend=\end
+\let\ptexequiv = \equiv
+\let\ptexi=\i
+\let\ptexlbrace=\{
+\let\ptexrbrace=\}
+\let\ptexstar=\*
+\let\ptext=\t
+\let\ptextilde=\~
+
+% Be sure we're in horizontal mode when doing a tie, since we make space
+% equivalent to this in @example-like environments. Otherwise, a space
+% at the beginning of a line will start with \penalty -- and
+% since \penalty is valid in vertical mode, we'd end up putting the
+% penalty on the vertical list instead of in the new paragraph.
+{\catcode`@ = 11
+ % Avoid using \@M directly, because that causes trouble
+ % if the definition is written into an index file.
+ \global\let\tiepenalty = \@M
+ \gdef\tie{\leavevmode\penalty\tiepenalty\ }
+}
+\let\~ = \tie % And make it available as @~.
+
+
+\message{Basics,}
+\chardef\other=12
+
+% If this character appears in an error message or help string, it
+% starts a new line in the output.
+\newlinechar = `^^J
+
+% Set up fixed words for English.
+\ifx\putwordChapter\undefined{\gdef\putwordChapter{Chapter}}\fi%
+\def\putwordInfo{Info}%
+\ifx\putwordSee\undefined{\gdef\putwordSee{See}}\fi%
+\ifx\putwordsee\undefined{\gdef\putwordsee{see}}\fi%
+\ifx\putwordfile\undefined{\gdef\putwordfile{file}}\fi%
+\ifx\putwordpage\undefined{\gdef\putwordpage{page}}\fi%
+\ifx\putwordsection\undefined{\gdef\putwordsection{section}}\fi%
+\ifx\putwordSection\undefined{\gdef\putwordSection{Section}}\fi%
+\ifx\putwordTableofContents\undefined{\gdef\putwordTableofContents{Table of Contents}}\fi%
+\ifx\putwordShortContents\undefined{\gdef\putwordShortContents{Short Contents}}\fi%
+\ifx\putwordAppendix\undefined{\gdef\putwordAppendix{Appendix}}\fi%
+
+% Ignore a token.
+%
+\def\gobble#1{}
+
+\hyphenation{ap-pen-dix}
+\hyphenation{mini-buf-fer mini-buf-fers}
+\hyphenation{eshell}
+
+% Margin to add to right of even pages, to left of odd pages.
+\newdimen \bindingoffset
+\newdimen \normaloffset
+\newdimen\pagewidth \newdimen\pageheight
+
+% Sometimes it is convenient to have everything in the transcript file
+% and nothing on the terminal. We don't just call \tracingall here,
+% since that produces some useless output on the terminal.
+%
+\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}%
+\def\loggingall{\tracingcommands2 \tracingstats2
+ \tracingpages1 \tracingoutput1 \tracinglostchars1
+ \tracingmacros2 \tracingparagraphs1 \tracingrestores1
+ \showboxbreadth\maxdimen\showboxdepth\maxdimen
+}%
+
+%---------------------Begin change-----------------------
+%
+%%%% For @cropmarks command.
+% Dimensions to add cropmarks at corners Added by P. A. MacKay, 12 Nov. 1986
+%
+\newdimen\cornerlong \newdimen\cornerthick
+\newdimen \topandbottommargin
+\newdimen \outerhsize \newdimen \outervsize
+\cornerlong=1pc\cornerthick=.3pt % These set size of cropmarks
+\outerhsize=7in
+%\outervsize=9.5in
+% Alternative @smallbook page size is 9.25in
+\outervsize=9.25in
+\topandbottommargin=.75in
+%
+%---------------------End change-----------------------
+
+% \onepageout takes a vbox as an argument. Note that \pagecontents
+% does insertions, but you have to call it yourself.
+\chardef\PAGE=255 \output={\onepageout{\pagecontents\PAGE}}
+\def\onepageout#1{%
+ \hoffset=\normaloffset
+ \ifodd\pageno \advance\hoffset by \bindingoffset
+ \else \advance\hoffset by -\bindingoffset\fi
+ {%
+ \escapechar = `\\ % use backslash in output files.
+ \indexdummies
+ \shipout\vbox{%
+ {\let\hsize=\pagewidth \makeheadline}%
+ \pagebody{#1}%
+ {\let\hsize=\pagewidth \makefootline}%
+ }%
+ }%
+ \advancepageno
+ \ifnum\outputpenalty>-20000 \else\dosupereject\fi
+}
+
+%%%% For @cropmarks command %%%%
+
+% Here is a modification of the main output routine for Near East Publications
+% This provides right-angle cropmarks at all four corners.
+% The contents of the page are centerlined into the cropmarks,
+% and any desired binding offset is added as an \hskip on either
+% site of the centerlined box. (P. A. MacKay, 12 November, 1986)
+%
+\def\croppageout#1{\hoffset=0pt % make sure this doesn't mess things up
+{\escapechar=`\\\relax % makes sure backslash is used in output files.
+ \shipout
+ \vbox to \outervsize{\hsize=\outerhsize
+ \vbox{\line{\ewtop\hfill\ewtop}}
+ \nointerlineskip
+ \line{\vbox{\moveleft\cornerthick\nstop}
+ \hfill
+ \vbox{\moveright\cornerthick\nstop}}
+ \vskip \topandbottommargin
+ \centerline{\ifodd\pageno\hskip\bindingoffset\fi
+ \vbox{
+ {\let\hsize=\pagewidth \makeheadline}
+ \pagebody{#1}
+ {\let\hsize=\pagewidth \makefootline}}
+ \ifodd\pageno\else\hskip\bindingoffset\fi}
+ \vskip \topandbottommargin plus1fill minus1fill
+ \boxmaxdepth\cornerthick
+ \line{\vbox{\moveleft\cornerthick\nsbot}
+ \hfill
+ \vbox{\moveright\cornerthick\nsbot}}
+ \nointerlineskip
+ \vbox{\line{\ewbot\hfill\ewbot}}
+ }}
+ \advancepageno
+ \ifnum\outputpenalty>-20000 \else\dosupereject\fi}
+%
+% Do @cropmarks to get crop marks
+\def\cropmarks{\let\onepageout=\croppageout }
+
+\newinsert\margin \dimen\margin=\maxdimen
+
+\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}}
+{\catcode`\@ =11
+\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi
+% marginal hacks, juha@viisa.uucp (Juha Takala)
+\ifvoid\margin\else % marginal info is present
+ \rlap{\kern\hsize\vbox to\z@{\kern1pt\box\margin \vss}}\fi
+\dimen@=\dp#1 \unvbox#1
+\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi
+\ifr@ggedbottom \kern-\dimen@ \vfil \fi}
+}
+
+%
+% Here are the rules for the cropmarks. Note that they are
+% offset so that the space between them is truly \outerhsize or \outervsize
+% (P. A. MacKay, 12 November, 1986)
+%
+\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong}
+\def\nstop{\vbox
+ {\hrule height\cornerthick depth\cornerlong width\cornerthick}}
+\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong}
+\def\nsbot{\vbox
+ {\hrule height\cornerlong depth\cornerthick width\cornerthick}}
+
+% Parse an argument, then pass it to #1. The argument is the rest of
+% the input line (except we remove a trailing comment). #1 should be a
+% macro which expects an ordinary undelimited TeX argument.
+%
+\def\parsearg#1{%
+ \let\next = #1%
+ \begingroup
+ \obeylines
+ \futurelet\temp\parseargx
+}
+
+% If the next token is an obeyed space (from an @example environment or
+% the like), remove it and recurse. Otherwise, we're done.
+\def\parseargx{%
+ % \obeyedspace is defined far below, after the definition of \sepspaces.
+ \ifx\obeyedspace\temp
+ \expandafter\parseargdiscardspace
+ \else
+ \expandafter\parseargline
+ \fi
+}
+
+% Remove a single space (as the delimiter token to the macro call).
+{\obeyspaces %
+ \gdef\parseargdiscardspace {\futurelet\temp\parseargx}}
+
+{\obeylines %
+ \gdef\parseargline#1^^M{%
+ \endgroup % End of the group started in \parsearg.
+ %
+ % First remove any @c comment, then any @comment.
+ % Result of each macro is put in \toks0.
+ \argremovec #1\c\relax %
+ \expandafter\argremovecomment \the\toks0 \comment\relax %
+ %
+ % Call the caller's macro, saved as \next in \parsearg.
+ \expandafter\next\expandafter{\the\toks0}%
+ }%
+}
+
+% Since all \c{,omment} does is throw away the argument, we can let TeX
+% do that for us. The \relax here is matched by the \relax in the call
+% in \parseargline; it could be more or less anything, its purpose is
+% just to delimit the argument to the \c.
+\def\argremovec#1\c#2\relax{\toks0 = {#1}}
+\def\argremovecomment#1\comment#2\relax{\toks0 = {#1}}
+
+% \argremovec{,omment} might leave us with trailing spaces, though; e.g.,
+% @end itemize @c foo
+% will have two active spaces as part of the argument with the
+% `itemize'. Here we remove all active spaces from #1, and assign the
+% result to \toks0.
+%
+% This loses if there are any *other* active characters besides spaces
+% in the argument -- _ ^ +, for example -- since they get expanded.
+% Fortunately, Texinfo does not define any such commands. (If it ever
+% does, the catcode of the characters in questionwill have to be changed
+% here.) But this means we cannot call \removeactivespaces as part of
+% \argremovec{,omment}, since @c uses \parsearg, and thus the argument
+% that \parsearg gets might well have any character at all in it.
+%
+\def\removeactivespaces#1{%
+ \begingroup
+ \ignoreactivespaces
+ \edef\temp{#1}%
+ \global\toks0 = \expandafter{\temp}%
+ \endgroup
+}
+
+% Change the active space to expand to nothing.
+%
+\begingroup
+ \obeyspaces
+ \gdef\ignoreactivespaces{\obeyspaces\let =\empty}
+\endgroup
+
+
+\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next}
+
+%% These are used to keep @begin/@end levels from running away
+%% Call \inENV within environments (after a \begingroup)
+\newif\ifENV \ENVfalse \def\inENV{\ifENV\relax\else\ENVtrue\fi}
+\def\ENVcheck{%
+\ifENV\errmessage{Still within an environment. Type Return to continue.}
+\endgroup\fi} % This is not perfect, but it should reduce lossage
+
+% @begin foo is the same as @foo, for now.
+\newhelp\EMsimple{Type <Return> to continue.}
+
+\outer\def\begin{\parsearg\beginxxx}
+
+\def\beginxxx #1{%
+\expandafter\ifx\csname #1\endcsname\relax
+{\errhelp=\EMsimple \errmessage{Undefined command @begin #1}}\else
+\csname #1\endcsname\fi}
+
+% @end foo executes the definition of \Efoo.
+%
+\def\end{\parsearg\endxxx}
+\def\endxxx #1{%
+ \removeactivespaces{#1}%
+ \edef\endthing{\the\toks0}%
+ %
+ \expandafter\ifx\csname E\endthing\endcsname\relax
+ \expandafter\ifx\csname \endthing\endcsname\relax
+ % There's no \foo, i.e., no ``environment'' foo.
+ \errhelp = \EMsimple
+ \errmessage{Undefined command `@end \endthing'}%
+ \else
+ \unmatchedenderror\endthing
+ \fi
+ \else
+ % Everything's ok; the right environment has been started.
+ \csname E\endthing\endcsname
+ \fi
+}
+
+% There is an environment #1, but it hasn't been started. Give an error.
+%
+\def\unmatchedenderror#1{%
+ \errhelp = \EMsimple
+ \errmessage{This `@end #1' doesn't have a matching `@#1'}%
+}
+
+% Define the control sequence \E#1 to give an unmatched @end error.
+%
+\def\defineunmatchedend#1{%
+ \expandafter\def\csname E#1\endcsname{\unmatchedenderror{#1}}%
+}
+
+
+% Single-spacing is done by various environments (specifically, in
+% \nonfillstart and \quotations).
+\newskip\singlespaceskip \singlespaceskip = 12.5pt
+\def\singlespace{%
+ % Why was this kern here? It messes up equalizing space above and below
+ % environments. --karl, 6may93
+ %{\advance \baselineskip by -\singlespaceskip
+ %\kern \baselineskip}%
+ \setleading \singlespaceskip
+}
+
+%% Simple single-character @ commands
+
+% @@ prints an @
+% Kludge this until the fonts are right (grr).
+\def\@{{\tt \char '100}}
+
+% This is turned off because it was never documented
+% and you can use @w{...} around a quote to suppress ligatures.
+%% Define @` and @' to be the same as ` and '
+%% but suppressing ligatures.
+%\def\`{{`}}
+%\def\'{{'}}
+
+% Used to generate quoted braces.
+\def\mylbrace {{\tt \char '173}}
+\def\myrbrace {{\tt \char '175}}
+\let\{=\mylbrace
+\let\}=\myrbrace
+\begingroup
+ % Definitions to produce actual \{ & \} command in an index.
+ \catcode`\{ = 12 \catcode`\} = 12
+ \catcode`\[ = 1 \catcode`\] = 2
+ \catcode`\@ = 0 \catcode`\\ = 12
+ @gdef@lbracecmd[\{]%
+ @gdef@rbracecmd[\}]%
+@endgroup
+
+% Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent
+% Others are defined by plain TeX: @` @' @" @^ @~ @= @v @H.
+\let\, = \c
+\let\dotaccent = \.
+\def\ringaccent#1{{\accent23 #1}}
+\let\tieaccent = \t
+\let\ubaraccent = \b
+\let\udotaccent = \d
+
+% Other special characters: @questiondown @exclamdown
+% Plain TeX defines: @AA @AE @O @OE @L (and lowercase versions) @ss.
+\def\questiondown{?`}
+\def\exclamdown{!`}
+
+% Dotless i and dotless j, used for accents.
+\def\imacro{i}
+\def\jmacro{j}
+\def\dotless#1{%
+ \def\temp{#1}%
+ \ifx\temp\imacro \ptexi
+ \else\ifx\temp\jmacro \j
+ \else \errmessage{@dotless can be used only with i or j}%
+ \fi\fi
+}
+
+% @: forces normal size whitespace following.
+\def\:{\spacefactor=1000 }
+
+% @* forces a line break.
+\def\*{\hfil\break\hbox{}\ignorespaces}
+
+% @. is an end-of-sentence period.
+\def\.{.\spacefactor=3000 }
+
+% @enddots{} is an end-of-sentence ellipsis.
+\gdef\enddots{$\mathinner{\ldotp\ldotp\ldotp\ldotp}$\spacefactor=3000}
+
+% @! is an end-of-sentence bang.
+\gdef\!{!\spacefactor=3000 }
+
+% @? is an end-of-sentence query.
+\gdef\?{?\spacefactor=3000 }
+
+% @w prevents a word break. Without the \leavevmode, @w at the
+% beginning of a paragraph, when TeX is still in vertical mode, would
+% produce a whole line of output instead of starting the paragraph.
+\def\w#1{\leavevmode\hbox{#1}}
+
+% @group ... @end group forces ... to be all on one page, by enclosing
+% it in a TeX vbox. We use \vtop instead of \vbox to construct the box
+% to keep its height that of a normal line. According to the rules for
+% \topskip (p.114 of the TeXbook), the glue inserted is
+% max (\topskip - \ht (first item), 0). If that height is large,
+% therefore, no glue is inserted, and the space between the headline and
+% the text is small, which looks bad.
+%
+\def\group{\begingroup
+ \ifnum\catcode13=\active \else
+ \errhelp = \groupinvalidhelp
+ \errmessage{@group invalid in context where filling is enabled}%
+ \fi
+ %
+ % The \vtop we start below produces a box with normal height and large
+ % depth; thus, TeX puts \baselineskip glue before it, and (when the
+ % next line of text is done) \lineskip glue after it. (See p.82 of
+ % the TeXbook.) Thus, space below is not quite equal to space
+ % above. But it's pretty close.
+ \def\Egroup{%
+ \egroup % End the \vtop.
+ \endgroup % End the \group.
+ }%
+ %
+ \vtop\bgroup
+ % We have to put a strut on the last line in case the @group is in
+ % the midst of an example, rather than completely enclosing it.
+ % Otherwise, the interline space between the last line of the group
+ % and the first line afterwards is too small. But we can't put the
+ % strut in \Egroup, since there it would be on a line by itself.
+ % Hence this just inserts a strut at the beginning of each line.
+ \everypar = {\strut}%
+ %
+ % Since we have a strut on every line, we don't need any of TeX's
+ % normal interline spacing.
+ \offinterlineskip
+ %
+ % OK, but now we have to do something about blank
+ % lines in the input in @example-like environments, which normally
+ % just turn into \lisppar, which will insert no space now that we've
+ % turned off the interline space. Simplest is to make them be an
+ % empty paragraph.
+ \ifx\par\lisppar
+ \edef\par{\leavevmode \par}%
+ %
+ % Reset ^^M's definition to new definition of \par.
+ \obeylines
+ \fi
+ %
+ % Do @comment since we are called inside an environment such as
+ % @example, where each end-of-line in the input causes an
+ % end-of-line in the output. We don't want the end-of-line after
+ % the `@group' to put extra space in the output. Since @group
+ % should appear on a line by itself (according to the Texinfo
+ % manual), we don't worry about eating any user text.
+ \comment
+}
+%
+% TeX puts in an \escapechar (i.e., `@') at the beginning of the help
+% message, so this ends up printing `@group can only ...'.
+%
+\newhelp\groupinvalidhelp{%
+group can only be used in environments such as @example,^^J%
+where each line of input produces a line of output.}
+
+% @need space-in-mils
+% forces a page break if there is not space-in-mils remaining.
+
+\newdimen\mil \mil=0.001in
+
+\def\need{\parsearg\needx}
+
+% Old definition--didn't work.
+%\def\needx #1{\par %
+%% This method tries to make TeX break the page naturally
+%% if the depth of the box does not fit.
+%{\baselineskip=0pt%
+%\vtop to #1\mil{\vfil}\kern -#1\mil\penalty 10000
+%\prevdepth=-1000pt
+%}}
+
+\def\needx#1{%
+ % Go into vertical mode, so we don't make a big box in the middle of a
+ % paragraph.
+ \par
+ %
+ % Don't add any leading before our big empty box, but allow a page
+ % break, since the best break might be right here.
+ \allowbreak
+ \nointerlineskip
+ \vtop to #1\mil{\vfil}%
+ %
+ % TeX does not even consider page breaks if a penalty added to the
+ % main vertical list is 10000 or more. But in order to see if the
+ % empty box we just added fits on the page, we must make it consider
+ % page breaks. On the other hand, we don't want to actually break the
+ % page after the empty box. So we use a penalty of 9999.
+ %
+ % There is an extremely small chance that TeX will actually break the
+ % page at this \penalty, if there are no other feasible breakpoints in
+ % sight. (If the user is using lots of big @group commands, which
+ % almost-but-not-quite fill up a page, TeX will have a hard time doing
+ % good page breaking, for example.) However, I could not construct an
+ % example where a page broke at this \penalty; if it happens in a real
+ % document, then we can reconsider our strategy.
+ \penalty9999
+ %
+ % Back up by the size of the box, whether we did a page break or not.
+ \kern -#1\mil
+ %
+ % Do not allow a page break right after this kern.
+ \nobreak
+}
+
+% @br forces paragraph break
+
+\let\br = \par
+
+% @dots{} output some dots
+
+\def\dots{$\ldots$}
+
+% @page forces the start of a new page
+
+\def\page{\par\vfill\supereject}
+
+% @exdent text....
+% outputs text on separate line in roman font, starting at standard page margin
+
+% This records the amount of indent in the innermost environment.
+% That's how much \exdent should take out.
+\newskip\exdentamount
+
+% This defn is used inside fill environments such as @defun.
+\def\exdent{\parsearg\exdentyyy}
+\def\exdentyyy #1{{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break}}
+
+% This defn is used inside nofill environments such as @example.
+\def\nofillexdent{\parsearg\nofillexdentyyy}
+\def\nofillexdentyyy #1{{\advance \leftskip by -\exdentamount
+\leftline{\hskip\leftskip{\rm#1}}}}
+
+% @inmargin{TEXT} puts TEXT in the margin next to the current paragraph.
+
+\def\inmargin#1{%
+\strut\vadjust{\nobreak\kern-\strutdepth
+ \vtop to \strutdepth{\baselineskip\strutdepth\vss
+ \llap{\rightskip=\inmarginspacing \vbox{\noindent #1}}\null}}}
+\newskip\inmarginspacing \inmarginspacing=1cm
+\def\strutdepth{\dp\strutbox}
+
+%\hbox{{\rm#1}}\hfil\break}}
+
+% @include file insert text of that file as input.
+% Allow normal characters that we make active in the argument (a file name).
+\def\include{\begingroup
+ \catcode`\\=12
+ \catcode`~=12
+ \catcode`^=12
+ \catcode`_=12
+ \catcode`|=12
+ \catcode`<=12
+ \catcode`>=12
+ \catcode`+=12
+ \parsearg\includezzz}
+% Restore active chars for included file.
+\def\includezzz#1{\endgroup\begingroup
+ % Read the included file in a group so nested @include's work.
+ \def\thisfile{#1}%
+ \input\thisfile
+\endgroup}
+
+\def\thisfile{}
+
+% @center line outputs that line, centered
+
+\def\center{\parsearg\centerzzz}
+\def\centerzzz #1{{\advance\hsize by -\leftskip
+\advance\hsize by -\rightskip
+\centerline{#1}}}
+
+% @sp n outputs n lines of vertical space
+
+\def\sp{\parsearg\spxxx}
+\def\spxxx #1{\vskip #1\baselineskip}
+
+% @comment ...line which is ignored...
+% @c is the same as @comment
+% @ignore ... @end ignore is another way to write a comment
+
+\def\comment{\catcode 64=\other \catcode 123=\other \catcode 125=\other%
+\parsearg \commentxxx}
+
+\def\commentxxx #1{\catcode 64=0 \catcode 123=1 \catcode 125=2 }
+
+\let\c=\comment
+
+% @paragraphindent is defined for the Info formatting commands only.
+\let\paragraphindent=\comment
+
+% Prevent errors for section commands.
+% Used in @ignore and in failing conditionals.
+\def\ignoresections{%
+\let\chapter=\relax
+\let\unnumbered=\relax
+\let\top=\relax
+\let\unnumberedsec=\relax
+\let\unnumberedsection=\relax
+\let\unnumberedsubsec=\relax
+\let\unnumberedsubsection=\relax
+\let\unnumberedsubsubsec=\relax
+\let\unnumberedsubsubsection=\relax
+\let\section=\relax
+\let\subsec=\relax
+\let\subsubsec=\relax
+\let\subsection=\relax
+\let\subsubsection=\relax
+\let\appendix=\relax
+\let\appendixsec=\relax
+\let\appendixsection=\relax
+\let\appendixsubsec=\relax
+\let\appendixsubsection=\relax
+\let\appendixsubsubsec=\relax
+\let\appendixsubsubsection=\relax
+\let\contents=\relax
+\let\smallbook=\relax
+\let\titlepage=\relax
+}
+
+% Used in nested conditionals, where we have to parse the Texinfo source
+% and so want to turn off most commands, in case they are used
+% incorrectly.
+%
+\def\ignoremorecommands{%
+ \let\defcodeindex = \relax
+ \let\defcv = \relax
+ \let\deffn = \relax
+ \let\deffnx = \relax
+ \let\defindex = \relax
+ \let\defivar = \relax
+ \let\defmac = \relax
+ \let\defmethod = \relax
+ \let\defop = \relax
+ \let\defopt = \relax
+ \let\defspec = \relax
+ \let\deftp = \relax
+ \let\deftypefn = \relax
+ \let\deftypefun = \relax
+ \let\deftypevar = \relax
+ \let\deftypevr = \relax
+ \let\defun = \relax
+ \let\defvar = \relax
+ \let\defvr = \relax
+ \let\ref = \relax
+ \let\xref = \relax
+ \let\printindex = \relax
+ \let\pxref = \relax
+ \let\settitle = \relax
+ \let\setchapternewpage = \relax
+ \let\setchapterstyle = \relax
+ \let\everyheading = \relax
+ \let\evenheading = \relax
+ \let\oddheading = \relax
+ \let\everyfooting = \relax
+ \let\evenfooting = \relax
+ \let\oddfooting = \relax
+ \let\headings = \relax
+ \let\include = \relax
+ \let\lowersections = \relax
+ \let\down = \relax
+ \let\raisesections = \relax
+ \let\up = \relax
+ \let\set = \relax
+ \let\clear = \relax
+ \let\item = \relax
+}
+
+% Ignore @ignore ... @end ignore.
+%
+\def\ignore{\doignore{ignore}}
+
+% Also ignore @ifinfo, @ifhtml, @html, @menu, and @direntry text.
+%
+\def\ifinfo{\doignore{ifinfo}}
+\def\ifhtml{\doignore{ifhtml}}
+\def\html{\doignore{html}}
+\def\menu{\doignore{menu}}
+\def\direntry{\doignore{direntry}}
+
+% Also ignore @macro ... @end macro. The user must run texi2dvi,
+% which runs makeinfo to do macro expansion. Ignore @unmacro, too.
+\def\macro{\doignore{macro}}
+\let\unmacro = \comment
+
+
+% @dircategory CATEGORY -- specify a category of the dir file
+% which this file should belong to. Ignore this in TeX.
+\let\dircategory = \comment
+
+% Ignore text until a line `@end #1'.
+%
+\def\doignore#1{\begingroup
+ % Don't complain about control sequences we have declared \outer.
+ \ignoresections
+ %
+ % Define a command to swallow text until we reach `@end #1'.
+ \long\def\doignoretext##1\end #1{\enddoignore}%
+ %
+ % Make sure that spaces turn into tokens that match what \doignoretext wants.
+ \catcode32 = 10
+ %
+ % And now expand that command.
+ \doignoretext
+}
+
+% What we do to finish off ignored text.
+%
+\def\enddoignore{\endgroup\ignorespaces}%
+
+\newif\ifwarnedobs\warnedobsfalse
+\def\obstexwarn{%
+ \ifwarnedobs\relax\else
+ % We need to warn folks that they may have trouble with TeX 3.0.
+ % This uses \immediate\write16 rather than \message to get newlines.
+ \immediate\write16{}
+ \immediate\write16{***WARNING*** for users of Unix TeX 3.0!}
+ \immediate\write16{This manual trips a bug in TeX version 3.0 (tex hangs).}
+ \immediate\write16{If you are running another version of TeX, relax.}
+ \immediate\write16{If you are running Unix TeX 3.0, kill this TeX process.}
+ \immediate\write16{ Then upgrade your TeX installation if you can.}
+ \immediate\write16{ (See ftp://ftp.gnu.ai.mit.edu/pub/gnu/TeX.README.)}
+ \immediate\write16{If you are stuck with version 3.0, run the}
+ \immediate\write16{ script ``tex3patch'' from the Texinfo distribution}
+ \immediate\write16{ to use a workaround.}
+ \immediate\write16{}
+ \global\warnedobstrue
+ \fi
+}
+
+% **In TeX 3.0, setting text in \nullfont hangs tex. For a
+% workaround (which requires the file ``dummy.tfm'' to be installed),
+% uncomment the following line:
+%%%%%\font\nullfont=dummy\let\obstexwarn=\relax
+
+% Ignore text, except that we keep track of conditional commands for
+% purposes of nesting, up to an `@end #1' command.
+%
+\def\nestedignore#1{%
+ \obstexwarn
+ % We must actually expand the ignored text to look for the @end
+ % command, so that nested ignore constructs work. Thus, we put the
+ % text into a \vbox and then do nothing with the result. To minimize
+ % the change of memory overflow, we follow the approach outlined on
+ % page 401 of the TeXbook: make the current font be a dummy font.
+ %
+ \setbox0 = \vbox\bgroup
+ % Don't complain about control sequences we have declared \outer.
+ \ignoresections
+ %
+ % Define `@end #1' to end the box, which will in turn undefine the
+ % @end command again.
+ \expandafter\def\csname E#1\endcsname{\egroup\ignorespaces}%
+ %
+ % We are going to be parsing Texinfo commands. Most cause no
+ % trouble when they are used incorrectly, but some commands do
+ % complicated argument parsing or otherwise get confused, so we
+ % undefine them.
+ %
+ % We can't do anything about stray @-signs, unfortunately;
+ % they'll produce `undefined control sequence' errors.
+ \ignoremorecommands
+ %
+ % Set the current font to be \nullfont, a TeX primitive, and define
+ % all the font commands to also use \nullfont. We don't use
+ % dummy.tfm, as suggested in the TeXbook, because not all sites
+ % might have that installed. Therefore, math mode will still
+ % produce output, but that should be an extremely small amount of
+ % stuff compared to the main input.
+ %
+ \nullfont
+ \let\tenrm = \nullfont \let\tenit = \nullfont \let\tensl = \nullfont
+ \let\tenbf = \nullfont \let\tentt = \nullfont \let\smallcaps = \nullfont
+ \let\tensf = \nullfont
+ % Similarly for index fonts (mostly for their use in
+ % smallexample)
+ \let\indrm = \nullfont \let\indit = \nullfont \let\indsl = \nullfont
+ \let\indbf = \nullfont \let\indtt = \nullfont \let\indsc = \nullfont
+ \let\indsf = \nullfont
+ %
+ % Don't complain when characters are missing from the fonts.
+ \tracinglostchars = 0
+ %
+ % Don't bother to do space factor calculations.
+ \frenchspacing
+ %
+ % Don't report underfull hboxes.
+ \hbadness = 10000
+ %
+ % Do minimal line-breaking.
+ \pretolerance = 10000
+ %
+ % Do not execute instructions in @tex
+ \def\tex{\doignore{tex}}
+}
+
+% @set VAR sets the variable VAR to an empty value.
+% @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE.
+%
+% Since we want to separate VAR from REST-OF-LINE (which might be
+% empty), we can't just use \parsearg; we have to insert a space of our
+% own to delimit the rest of the line, and then take it out again if we
+% didn't need it. Make sure the catcode of space is correct to avoid
+% losing inside @example, for instance.
+%
+\def\set{\begingroup\catcode` =10 \parsearg\setxxx}
+\def\setxxx#1{\setyyy#1 \endsetyyy}
+\def\setyyy#1 #2\endsetyyy{%
+ \def\temp{#2}%
+ \ifx\temp\empty \global\expandafter\let\csname SET#1\endcsname = \empty
+ \else \setzzz{#1}#2\endsetzzz % Remove the trailing space \setxxx inserted.
+ \fi
+ \endgroup
+}
+% Can't use \xdef to pre-expand #2 and save some time, since \temp or
+% \next or other control sequences that we've defined might get us into
+% an infinite loop. Consider `@set foo @cite{bar}'.
+\def\setzzz#1#2 \endsetzzz{\expandafter\gdef\csname SET#1\endcsname{#2}}
+
+% @clear VAR clears (i.e., unsets) the variable VAR.
+%
+\def\clear{\parsearg\clearxxx}
+\def\clearxxx#1{\global\expandafter\let\csname SET#1\endcsname=\relax}
+
+% @value{foo} gets the text saved in variable foo.
+%
+\def\value#1{\expandafter
+ \ifx\csname SET#1\endcsname\relax
+ {\{No value for ``#1''\}}
+ \else \csname SET#1\endcsname \fi}
+
+% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined
+% with @set.
+%
+\def\ifset{\parsearg\ifsetxxx}
+\def\ifsetxxx #1{%
+ \expandafter\ifx\csname SET#1\endcsname\relax
+ \expandafter\ifsetfail
+ \else
+ \expandafter\ifsetsucceed
+ \fi
+}
+\def\ifsetsucceed{\conditionalsucceed{ifset}}
+\def\ifsetfail{\nestedignore{ifset}}
+\defineunmatchedend{ifset}
+
+% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been
+% defined with @set, or has been undefined with @clear.
+%
+\def\ifclear{\parsearg\ifclearxxx}
+\def\ifclearxxx #1{%
+ \expandafter\ifx\csname SET#1\endcsname\relax
+ \expandafter\ifclearsucceed
+ \else
+ \expandafter\ifclearfail
+ \fi
+}
+\def\ifclearsucceed{\conditionalsucceed{ifclear}}
+\def\ifclearfail{\nestedignore{ifclear}}
+\defineunmatchedend{ifclear}
+
+% @iftex always succeeds; we read the text following, through @end
+% iftex). But `@end iftex' should be valid only after an @iftex.
+%
+\def\iftex{\conditionalsucceed{iftex}}
+\defineunmatchedend{iftex}
+
+% We can't just want to start a group at @iftex (for example) and end it
+% at @end iftex, since then @set commands inside the conditional have no
+% effect (they'd get reverted at the end of the group). So we must
+% define \Eiftex to redefine itself to be its previous value. (We can't
+% just define it to fail again with an ``unmatched end'' error, since
+% the @ifset might be nested.)
+%
+\def\conditionalsucceed#1{%
+ \edef\temp{%
+ % Remember the current value of \E#1.
+ \let\nece{prevE#1} = \nece{E#1}%
+ %
+ % At the `@end #1', redefine \E#1 to be its previous value.
+ \def\nece{E#1}{\let\nece{E#1} = \nece{prevE#1}}%
+ }%
+ \temp
+}
+
+% We need to expand lots of \csname's, but we don't want to expand the
+% control sequences after we've constructed them.
+%
+\def\nece#1{\expandafter\noexpand\csname#1\endcsname}
+
+% @asis just yields its argument. Used with @table, for example.
+%
+\def\asis#1{#1}
+
+% @math means output in math mode.
+% We don't use $'s directly in the definition of \math because control
+% sequences like \math are expanded when the toc file is written. Then,
+% we read the toc file back, the $'s will be normal characters (as they
+% should be, according to the definition of Texinfo). So we must use a
+% control sequence to switch into and out of math mode.
+%
+% This isn't quite enough for @math to work properly in indices, but it
+% seems unlikely it will ever be needed there.
+%
+\let\implicitmath = $
+\def\math#1{\implicitmath #1\implicitmath}
+
+% @bullet and @minus need the same treatment as @math, just above.
+\def\bullet{\implicitmath\ptexbullet\implicitmath}
+\def\minus{\implicitmath-\implicitmath}
+
+\def\node{\ENVcheck\parsearg\nodezzz}
+\def\nodezzz#1{\nodexxx [#1,]}
+\def\nodexxx[#1,#2]{\gdef\lastnode{#1}}
+\let\nwnode=\node
+\let\lastnode=\relax
+
+\def\donoderef{\ifx\lastnode\relax\else
+\expandafter\expandafter\expandafter\setref{\lastnode}\fi
+\global\let\lastnode=\relax}
+
+\def\unnumbnoderef{\ifx\lastnode\relax\else
+\expandafter\expandafter\expandafter\unnumbsetref{\lastnode}\fi
+\global\let\lastnode=\relax}
+
+\def\appendixnoderef{\ifx\lastnode\relax\else
+\expandafter\expandafter\expandafter\appendixsetref{\lastnode}\fi
+\global\let\lastnode=\relax}
+
+% @refill is a no-op.
+\let\refill=\relax
+
+% @setfilename is done at the beginning of every texinfo file.
+% So open here the files we need to have open while reading the input.
+% This makes it possible to make a .fmt file for texinfo.
+\def\setfilename{%
+ \readauxfile
+ \opencontents
+ \openindices
+ \fixbackslash % Turn off hack to swallow `\input texinfo'.
+ \global\let\setfilename=\comment % Ignore extra @setfilename cmds.
+ \comment % Ignore the actual filename.
+}
+
+% @bye.
+\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend}
+
+% \def\macro#1{\begingroup\ignoresections\catcode`\#=6\def\macrotemp{#1}\parsearg\macroxxx}
+% \def\macroxxx#1#2 \end macro{%
+% \expandafter\gdef\macrotemp#1{#2}%
+% \endgroup}
+
+%\def\linemacro#1{\begingroup\ignoresections\catcode`\#=6\def\macrotemp{#1}\parsearg\linemacroxxx}
+%\def\linemacroxxx#1#2 \end linemacro{%
+%\let\parsearg=\relax
+%\edef\macrotempx{\csname M\butfirst\expandafter\string\macrotemp\endcsname}%
+%\expandafter\xdef\macrotemp{\parsearg\macrotempx}%
+%\expandafter\gdef\macrotempx#1{#2}%
+%\endgroup}
+
+%\def\butfirst#1{}
+
+
+\message{fonts,}
+
+% Font-change commands.
+
+% Texinfo supports the sans serif font style, which plain TeX does not.
+% So we set up a \sf analogous to plain's \rm, etc.
+\newfam\sffam
+\def\sf{\fam=\sffam \tensf}
+\let\li = \sf % Sometimes we call it \li, not \sf.
+
+% We don't need math for this one.
+\def\ttsl{\tenttsl}
+
+%% Try out Computer Modern fonts at \magstephalf
+\let\mainmagstep=\magstephalf
+
+% Set the font macro #1 to the font named #2, adding on the
+% specified font prefix (normally `cm').
+% #3 is the font's design size, #4 is a scale factor
+\def\setfont#1#2#3#4{\font#1=\fontprefix#2#3 scaled #4}
+
+% Use cm as the default font prefix.
+% To specify the font prefix, you must define \fontprefix
+% before you read in texinfo.tex.
+\ifx\fontprefix\undefined
+\def\fontprefix{cm}
+\fi
+% Support font families that don't use the same naming scheme as CM.
+\def\rmshape{r}
+\def\rmbshape{bx} %where the normal face is bold
+\def\bfshape{b}
+\def\bxshape{bx}
+\def\ttshape{tt}
+\def\ttbshape{tt}
+\def\ttslshape{sltt}
+\def\itshape{ti}
+\def\itbshape{bxti}
+\def\slshape{sl}
+\def\slbshape{bxsl}
+\def\sfshape{ss}
+\def\sfbshape{ss}
+\def\scshape{csc}
+\def\scbshape{csc}
+
+\ifx\bigger\relax
+\let\mainmagstep=\magstep1
+\setfont\textrm\rmshape{12}{1000}
+\setfont\texttt\ttshape{12}{1000}
+\else
+\setfont\textrm\rmshape{10}{\mainmagstep}
+\setfont\texttt\ttshape{10}{\mainmagstep}
+\fi
+% Instead of cmb10, you many want to use cmbx10.
+% cmbx10 is a prettier font on its own, but cmb10
+% looks better when embedded in a line with cmr10.
+\setfont\textbf\bfshape{10}{\mainmagstep}
+\setfont\textit\itshape{10}{\mainmagstep}
+\setfont\textsl\slshape{10}{\mainmagstep}
+\setfont\textsf\sfshape{10}{\mainmagstep}
+\setfont\textsc\scshape{10}{\mainmagstep}
+\setfont\textttsl\ttslshape{10}{\mainmagstep}
+\font\texti=cmmi10 scaled \mainmagstep
+\font\textsy=cmsy10 scaled \mainmagstep
+
+% A few fonts for @defun, etc.
+\setfont\defbf\bxshape{10}{\magstep1} %was 1314
+\setfont\deftt\ttshape{10}{\magstep1}
+\def\df{\let\tentt=\deftt \let\tenbf = \defbf \bf}
+
+% Fonts for indices and small examples (9pt).
+% We actually use the slanted font rather than the italic,
+% because texinfo normally uses the slanted fonts for that.
+% Do not make many font distinctions in general in the index, since they
+% aren't very useful.
+\setfont\ninett\ttshape{9}{1000}
+\setfont\indrm\rmshape{9}{1000}
+\setfont\indit\slshape{9}{1000}
+\let\indsl=\indit
+\let\indtt=\ninett
+\let\indttsl=\ninett
+\let\indsf=\indrm
+\let\indbf=\indrm
+\setfont\indsc\scshape{10}{900}
+\font\indi=cmmi9
+\font\indsy=cmsy9
+
+% Chapter (and unnumbered) fonts (17.28pt).
+\setfont\chaprm\rmbshape{12}{\magstep2}
+\setfont\chapit\itbshape{10}{\magstep3}
+\setfont\chapsl\slbshape{10}{\magstep3}
+\setfont\chaptt\ttbshape{12}{\magstep2}
+\setfont\chapttsl\ttslshape{10}{\magstep3}
+\setfont\chapsf\sfbshape{12}{\magstep2}
+\let\chapbf=\chaprm
+\setfont\chapsc\scbshape{10}{\magstep3}
+\font\chapi=cmmi12 scaled \magstep2
+\font\chapsy=cmsy10 scaled \magstep3
+
+% Section fonts (14.4pt).
+\setfont\secrm\rmbshape{12}{\magstep1}
+\setfont\secit\itbshape{10}{\magstep2}
+\setfont\secsl\slbshape{10}{\magstep2}
+\setfont\sectt\ttbshape{12}{\magstep1}
+\setfont\secttsl\ttslshape{10}{\magstep2}
+\setfont\secsf\sfbshape{12}{\magstep1}
+\let\secbf\secrm
+\setfont\secsc\scbshape{10}{\magstep2}
+\font\seci=cmmi12 scaled \magstep1
+\font\secsy=cmsy10 scaled \magstep2
+
+% \setfont\ssecrm\bxshape{10}{\magstep1} % This size an font looked bad.
+% \setfont\ssecit\itshape{10}{\magstep1} % The letters were too crowded.
+% \setfont\ssecsl\slshape{10}{\magstep1}
+% \setfont\ssectt\ttshape{10}{\magstep1}
+% \setfont\ssecsf\sfshape{10}{\magstep1}
+
+%\setfont\ssecrm\bfshape{10}{1315} % Note the use of cmb rather than cmbx.
+%\setfont\ssecit\itshape{10}{1315} % Also, the size is a little larger than
+%\setfont\ssecsl\slshape{10}{1315} % being scaled magstep1.
+%\setfont\ssectt\ttshape{10}{1315}
+%\setfont\ssecsf\sfshape{10}{1315}
+
+%\let\ssecbf=\ssecrm
+
+% Subsection fonts (13.15pt).
+\setfont\ssecrm\rmbshape{12}{\magstephalf}
+\setfont\ssecit\itbshape{10}{1315}
+\setfont\ssecsl\slbshape{10}{1315}
+\setfont\ssectt\ttbshape{12}{\magstephalf}
+\setfont\ssecttsl\ttslshape{10}{\magstep1}
+\setfont\ssecsf\sfbshape{12}{\magstephalf}
+\let\ssecbf\ssecrm
+\setfont\ssecsc\scbshape{10}{\magstep1}
+\font\sseci=cmmi12 scaled \magstephalf
+\font\ssecsy=cmsy10 scaled \magstep1
+% The smallcaps and symbol fonts should actually be scaled \magstep1.5,
+% but that is not a standard magnification.
+
+% Fonts for title page:
+\setfont\titlerm\rmbshape{12}{\magstep3}
+\let\authorrm = \secrm
+
+% In order for the font changes to affect most math symbols and letters,
+% we have to define the \textfont of the standard families. Since
+% texinfo doesn't allow for producing subscripts and superscripts, we
+% don't bother to reset \scriptfont and \scriptscriptfont (which would
+% also require loading a lot more fonts).
+%
+\def\resetmathfonts{%
+ \textfont0 = \tenrm \textfont1 = \teni \textfont2 = \tensy
+ \textfont\itfam = \tenit \textfont\slfam = \tensl \textfont\bffam = \tenbf
+ \textfont\ttfam = \tentt \textfont\sffam = \tensf
+}
+
+
+% The font-changing commands redefine the meanings of \tenSTYLE, instead
+% of just \STYLE. We do this so that font changes will continue to work
+% in math mode, where it is the current \fam that is relevant in most
+% cases, not the current font. Plain TeX does \def\bf{\fam=\bffam
+% \tenbf}, for example. By redefining \tenbf, we obviate the need to
+% redefine \bf itself.
+\def\textfonts{%
+ \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl
+ \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc
+ \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy \let\tenttsl=\textttsl
+ \resetmathfonts}
+\def\chapfonts{%
+ \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl
+ \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc
+ \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy \let\tenttsl=\chapttsl
+ \resetmathfonts \setleading{19pt}}
+\def\secfonts{%
+ \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl
+ \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc
+ \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy \let\tenttsl=\secttsl
+ \resetmathfonts \setleading{16pt}}
+\def\subsecfonts{%
+ \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl
+ \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc
+ \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy \let\tenttsl=\ssecttsl
+ \resetmathfonts \setleading{15pt}}
+\let\subsubsecfonts = \subsecfonts % Maybe make sssec fonts scaled magstephalf?
+\def\indexfonts{%
+ \let\tenrm=\indrm \let\tenit=\indit \let\tensl=\indsl
+ \let\tenbf=\indbf \let\tentt=\indtt \let\smallcaps=\indsc
+ \let\tensf=\indsf \let\teni=\indi \let\tensy=\indsy \let\tenttsl=\indttsl
+ \resetmathfonts \setleading{12pt}}
+
+% Set up the default fonts, so we can use them for creating boxes.
+%
+\textfonts
+
+% Count depth in font-changes, for error checks
+\newcount\fontdepth \fontdepth=0
+
+% Fonts for short table of contents.
+\setfont\shortcontrm\rmshape{12}{1000}
+\setfont\shortcontbf\bxshape{12}{1000}
+\setfont\shortcontsl\slshape{12}{1000}
+
+%% Add scribe-like font environments, plus @l for inline lisp (usually sans
+%% serif) and @ii for TeX italic
+
+% \smartitalic{ARG} outputs arg in italics, followed by an italic correction
+% unless the following character is such as not to need one.
+\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else\/\fi\fi\fi}
+\def\smartitalic#1{{\sl #1}\futurelet\next\smartitalicx}
+
+\let\i=\smartitalic
+\let\var=\smartitalic
+\let\dfn=\smartitalic
+\let\emph=\smartitalic
+\let\cite=\smartitalic
+
+\def\b#1{{\bf #1}}
+\let\strong=\b
+
+% We can't just use \exhyphenpenalty, because that only has effect at
+% the end of a paragraph. Restore normal hyphenation at the end of the
+% group within which \nohyphenation is presumably called.
+%
+\def\nohyphenation{\hyphenchar\font = -1 \aftergroup\restorehyphenation}
+\def\restorehyphenation{\hyphenchar\font = `- }
+
+\def\t#1{%
+ {\tt \rawbackslash \frenchspacing #1}%
+ \null
+}
+\let\ttfont=\t
+\def\samp #1{`\tclose{#1}'\null}
+\setfont\smallrm\rmshape{8}{1000}
+\font\smallsy=cmsy9
+\def\key#1{{\smallrm\textfont2=\smallsy \leavevmode\hbox{%
+ \raise0.4pt\hbox{$\langle$}\kern-.08em\vtop{%
+ \vbox{\hrule\kern-0.4pt
+ \hbox{\raise0.4pt\hbox{\vphantom{$\langle$}}#1}}%
+ \kern-0.4pt\hrule}%
+ \kern-.06em\raise0.4pt\hbox{$\rangle$}}}}
+% The old definition, with no lozenge:
+%\def\key #1{{\ttsl \nohyphenation \uppercase{#1}}\null}
+\def\ctrl #1{{\tt \rawbackslash \hat}#1}
+
+\let\file=\samp
+\let\url=\samp % perhaps include a hypertex \special eventually
+\def\email#1{$\langle${\tt #1}$\rangle$}
+
+% @code is a modification of @t,
+% which makes spaces the same size as normal in the surrounding text.
+\def\tclose#1{%
+ {%
+ % Change normal interword space to be same as for the current font.
+ \spaceskip = \fontdimen2\font
+ %
+ % Switch to typewriter.
+ \tt
+ %
+ % But `\ ' produces the large typewriter interword space.
+ \def\ {{\spaceskip = 0pt{} }}%
+ %
+ % Turn off hyphenation.
+ \nohyphenation
+ %
+ \rawbackslash
+ \frenchspacing
+ #1%
+ }%
+ \null
+}
+
+% We *must* turn on hyphenation at `-' and `_' in \code.
+% Otherwise, it is too hard to avoid overfull hboxes
+% in the Emacs manual, the Library manual, etc.
+
+% Unfortunately, TeX uses one parameter (\hyphenchar) to control
+% both hyphenation at - and hyphenation within words.
+% We must therefore turn them both off (\tclose does that)
+% and arrange explicitly to hyphenate at a dash.
+% -- rms.
+{
+\catcode`\-=\active
+\catcode`\_=\active
+\global\def\code{\begingroup \catcode`\-=\active \let-\codedash \catcode`\_=\active \let_\codeunder \codex}
+% The following is used by \doprintindex to insure that long function names
+% wrap around. It is necessary for - and _ to be active before the index is
+% read from the file, as \entry parses the arguments long before \code is
+% ever called. -- mycroft
+\global\def\indexbreaks{\catcode`\-=\active \let-\realdash \catcode`\_=\active \let_\realunder}
+}
+
+\def\realdash{-}
+\def\realunder{_}
+\def\codedash{-\discretionary{}{}{}}
+\def\codeunder{\normalunderscore\discretionary{}{}{}}
+\def\codex #1{\tclose{#1}\endgroup}
+
+%\let\exp=\tclose %Was temporary
+
+% @kbd is like @code, except that if the argument is just one @key command,
+% then @kbd has no effect.
+%
+\def\xkey{\key}
+\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}%
+\ifx\one\xkey\ifx\threex\three \key{#2}%
+\else{\tclose{\ttsl\look}}\fi
+\else{\tclose{\ttsl\look}}\fi}
+
+% Check if we are currently using a typewriter font. Since all the
+% Computer Modern typewriter fonts have zero interword stretch (and
+% shrink), and it is reasonable to expect all typewriter fonts to have
+% this property, we can check that font parameter.
+%
+\def\ifmonospace{\ifdim\fontdimen3\font=0pt }
+
+% Typeset a dimension, e.g., `in' or `pt'. The only reason for the
+% argument is to make the input look right: @dmn{pt} instead of
+% @dmn{}pt.
+%
+\def\dmn#1{\thinspace #1}
+
+\def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par}
+
+% @l was never documented to mean ``switch to the Lisp font'',
+% and it is not used as such in any manual I can find. We need it for
+% Polish suppressed-l. --karl, 22sep96.
+%\def\l#1{{\li #1}\null}
+
+\def\r#1{{\rm #1}} % roman font
+% Use of \lowercase was suggested.
+\def\sc#1{{\smallcaps#1}} % smallcaps font
+\def\ii#1{{\it #1}} % italic font
+
+% @pounds{} is a sterling sign.
+\def\pounds{{\it\$}}
+
+
+\message{page headings,}
+
+\newskip\titlepagetopglue \titlepagetopglue = 1.5in
+\newskip\titlepagebottomglue \titlepagebottomglue = 2pc
+
+% First the title page. Must do @settitle before @titlepage.
+\def\titlefont#1{{\titlerm #1}}
+
+\newif\ifseenauthor
+\newif\iffinishedtitlepage
+
+\def\shorttitlepage{\parsearg\shorttitlepagezzz}
+\def\shorttitlepagezzz #1{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}%
+ \endgroup\page\hbox{}\page}
+
+\def\titlepage{\begingroup \parindent=0pt \textfonts
+ \let\subtitlerm=\tenrm
+% I deinstalled the following change because \cmr12 is undefined.
+% This change was not in the ChangeLog anyway. --rms.
+% \let\subtitlerm=\cmr12
+ \def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines}%
+ %
+ \def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines}%
+ %
+ % Leave some space at the very top of the page.
+ \vglue\titlepagetopglue
+ %
+ % Now you can print the title using @title.
+ \def\title{\parsearg\titlezzz}%
+ \def\titlezzz##1{\leftline{\titlefont{##1}}
+ % print a rule at the page bottom also.
+ \finishedtitlepagefalse
+ \vskip4pt \hrule height 4pt width \hsize \vskip4pt}%
+ % No rule at page bottom unless we print one at the top with @title.
+ \finishedtitlepagetrue
+ %
+ % Now you can put text using @subtitle.
+ \def\subtitle{\parsearg\subtitlezzz}%
+ \def\subtitlezzz##1{{\subtitlefont \rightline{##1}}}%
+ %
+ % @author should come last, but may come many times.
+ \def\author{\parsearg\authorzzz}%
+ \def\authorzzz##1{\ifseenauthor\else\vskip 0pt plus 1filll\seenauthortrue\fi
+ {\authorfont \leftline{##1}}}%
+ %
+ % Most title ``pages'' are actually two pages long, with space
+ % at the top of the second. We don't want the ragged left on the second.
+ \let\oldpage = \page
+ \def\page{%
+ \iffinishedtitlepage\else
+ \finishtitlepage
+ \fi
+ \oldpage
+ \let\page = \oldpage
+ \hbox{}}%
+% \def\page{\oldpage \hbox{}}
+}
+
+\def\Etitlepage{%
+ \iffinishedtitlepage\else
+ \finishtitlepage
+ \fi
+ % It is important to do the page break before ending the group,
+ % because the headline and footline are only empty inside the group.
+ % If we use the new definition of \page, we always get a blank page
+ % after the title page, which we certainly don't want.
+ \oldpage
+ \endgroup
+ \HEADINGSon
+}
+
+\def\finishtitlepage{%
+ \vskip4pt \hrule height 2pt width \hsize
+ \vskip\titlepagebottomglue
+ \finishedtitlepagetrue
+}
+
+%%% Set up page headings and footings.
+
+\let\thispage=\folio
+
+\newtoks \evenheadline % Token sequence for heading line of even pages
+\newtoks \oddheadline % Token sequence for heading line of odd pages
+\newtoks \evenfootline % Token sequence for footing line of even pages
+\newtoks \oddfootline % Token sequence for footing line of odd pages
+
+% Now make Tex use those variables
+\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline
+ \else \the\evenheadline \fi}}
+\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline
+ \else \the\evenfootline \fi}\HEADINGShook}
+\let\HEADINGShook=\relax
+
+% Commands to set those variables.
+% For example, this is what @headings on does
+% @evenheading @thistitle|@thispage|@thischapter
+% @oddheading @thischapter|@thispage|@thistitle
+% @evenfooting @thisfile||
+% @oddfooting ||@thisfile
+
+\def\evenheading{\parsearg\evenheadingxxx}
+\def\oddheading{\parsearg\oddheadingxxx}
+\def\everyheading{\parsearg\everyheadingxxx}
+
+\def\evenfooting{\parsearg\evenfootingxxx}
+\def\oddfooting{\parsearg\oddfootingxxx}
+\def\everyfooting{\parsearg\everyfootingxxx}
+
+{\catcode`\@=0 %
+
+\gdef\evenheadingxxx #1{\evenheadingyyy #1@|@|@|@|\finish}
+\gdef\evenheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\oddheadingxxx #1{\oddheadingyyy #1@|@|@|@|\finish}
+\gdef\oddheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\everyheadingxxx #1{\everyheadingyyy #1@|@|@|@|\finish}
+\gdef\everyheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}
+\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\evenfootingxxx #1{\evenfootingyyy #1@|@|@|@|\finish}
+\gdef\evenfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\oddfootingxxx #1{\oddfootingyyy #1@|@|@|@|\finish}
+\gdef\oddfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\everyfootingxxx #1{\everyfootingyyy #1@|@|@|@|\finish}
+\gdef\everyfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}
+\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+%
+}% unbind the catcode of @.
+
+% @headings double turns headings on for double-sided printing.
+% @headings single turns headings on for single-sided printing.
+% @headings off turns them off.
+% @headings on same as @headings double, retained for compatibility.
+% @headings after turns on double-sided headings after this page.
+% @headings doubleafter turns on double-sided headings after this page.
+% @headings singleafter turns on single-sided headings after this page.
+% By default, they are off at the start of a document,
+% and turned `on' after @end titlepage.
+
+\def\headings #1 {\csname HEADINGS#1\endcsname}
+
+\def\HEADINGSoff{
+\global\evenheadline={\hfil} \global\evenfootline={\hfil}
+\global\oddheadline={\hfil} \global\oddfootline={\hfil}}
+\HEADINGSoff
+% When we turn headings on, set the page number to 1.
+% For double-sided printing, put current file name in lower left corner,
+% chapter name on inside top of right hand pages, document
+% title on inside top of left hand pages, and page numbers on outside top
+% edge of all pages.
+\def\HEADINGSdouble{
+\global\pageno=1
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\folio\hfil\thistitle}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+\global\let\contentsalignmacro = \chapoddpage
+}
+\let\contentsalignmacro = \chappager
+
+% For single-sided printing, chapter title goes across top left of page,
+% page number on top right.
+\def\HEADINGSsingle{
+\global\pageno=1
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\thischapter\hfil\folio}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+\global\let\contentsalignmacro = \chappager
+}
+\def\HEADINGSon{\HEADINGSdouble}
+
+\def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex}
+\let\HEADINGSdoubleafter=\HEADINGSafter
+\def\HEADINGSdoublex{%
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\folio\hfil\thistitle}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+\global\let\contentsalignmacro = \chapoddpage
+}
+
+\def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex}
+\def\HEADINGSsinglex{%
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\thischapter\hfil\folio}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+\global\let\contentsalignmacro = \chappager
+}
+
+% Subroutines used in generating headings
+% Produces Day Month Year style of output.
+\def\today{\number\day\space
+\ifcase\month\or
+January\or February\or March\or April\or May\or June\or
+July\or August\or September\or October\or November\or December\fi
+\space\number\year}
+
+% Use this if you want the Month Day, Year style of output.
+%\def\today{\ifcase\month\or
+%January\or February\or March\or April\or May\or June\or
+%July\or August\or September\or October\or November\or December\fi
+%\space\number\day, \number\year}
+
+% @settitle line... specifies the title of the document, for headings
+% It generates no output of its own
+
+\def\thistitle{No Title}
+\def\settitle{\parsearg\settitlezzz}
+\def\settitlezzz #1{\gdef\thistitle{#1}}
+
+
+\message{tables,}
+
+% @tabs -- simple alignment
+
+% These don't work. For one thing, \+ is defined as outer.
+% So these macros cannot even be defined.
+
+%\def\tabs{\parsearg\tabszzz}
+%\def\tabszzz #1{\settabs\+#1\cr}
+%\def\tabline{\parsearg\tablinezzz}
+%\def\tablinezzz #1{\+#1\cr}
+%\def\&{&}
+
+% Tables -- @table, @ftable, @vtable, @item(x), @kitem(x), @xitem(x).
+
+% default indentation of table text
+\newdimen\tableindent \tableindent=.8in
+% default indentation of @itemize and @enumerate text
+\newdimen\itemindent \itemindent=.3in
+% margin between end of table item and start of table text.
+\newdimen\itemmargin \itemmargin=.1in
+
+% used internally for \itemindent minus \itemmargin
+\newdimen\itemmax
+
+% Note @table, @vtable, and @vtable define @item, @itemx, etc., with
+% these defs.
+% They also define \itemindex
+% to index the item name in whatever manner is desired (perhaps none).
+
+\newif\ifitemxneedsnegativevskip
+
+\def\itemxpar{\par\ifitemxneedsnegativevskip\nobreak\vskip-\parskip\nobreak\fi}
+
+\def\internalBitem{\smallbreak \parsearg\itemzzz}
+\def\internalBitemx{\itemxpar \parsearg\itemzzz}
+
+\def\internalBxitem "#1"{\def\xitemsubtopix{#1} \smallbreak \parsearg\xitemzzz}
+\def\internalBxitemx "#1"{\def\xitemsubtopix{#1} \itemxpar \parsearg\xitemzzz}
+
+\def\internalBkitem{\smallbreak \parsearg\kitemzzz}
+\def\internalBkitemx{\itemxpar \parsearg\kitemzzz}
+
+\def\kitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \lastfunction}}%
+ \itemzzz {#1}}
+
+\def\xitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \xitemsubtopic}}%
+ \itemzzz {#1}}
+
+\def\itemzzz #1{\begingroup %
+ \advance\hsize by -\rightskip
+ \advance\hsize by -\tableindent
+ \setbox0=\hbox{\itemfont{#1}}%
+ \itemindex{#1}%
+ \nobreak % This prevents a break before @itemx.
+ %
+ % Be sure we are not still in the middle of a paragraph.
+ %{\parskip = 0in
+ %\par
+ %}%
+ %
+ % If the item text does not fit in the space we have, put it on a line
+ % by itself, and do not allow a page break either before or after that
+ % line. We do not start a paragraph here because then if the next
+ % command is, e.g., @kindex, the whatsit would get put into the
+ % horizontal list on a line by itself, resulting in extra blank space.
+ \ifdim \wd0>\itemmax
+ %
+ % Make this a paragraph so we get the \parskip glue and wrapping,
+ % but leave it ragged-right.
+ \begingroup
+ \advance\leftskip by-\tableindent
+ \advance\hsize by\tableindent
+ \advance\rightskip by0pt plus1fil
+ \leavevmode\unhbox0\par
+ \endgroup
+ %
+ % We're going to be starting a paragraph, but we don't want the
+ % \parskip glue -- logically it's part of the @item we just started.
+ \nobreak \vskip-\parskip
+ %
+ % Stop a page break at the \parskip glue coming up. Unfortunately
+ % we can't prevent a possible page break at the following
+ % \baselineskip glue.
+ \nobreak
+ \endgroup
+ \itemxneedsnegativevskipfalse
+ \else
+ % The item text fits into the space. Start a paragraph, so that the
+ % following text (if any) will end up on the same line. Since that
+ % text will be indented by \tableindent, we make the item text be in
+ % a zero-width box.
+ \noindent
+ \rlap{\hskip -\tableindent\box0}\ignorespaces%
+ \endgroup%
+ \itemxneedsnegativevskiptrue%
+ \fi
+}
+
+\def\item{\errmessage{@item while not in a table}}
+\def\itemx{\errmessage{@itemx while not in a table}}
+\def\kitem{\errmessage{@kitem while not in a table}}
+\def\kitemx{\errmessage{@kitemx while not in a table}}
+\def\xitem{\errmessage{@xitem while not in a table}}
+\def\xitemx{\errmessage{@xitemx while not in a table}}
+
+%% Contains a kludge to get @end[description] to work
+\def\description{\tablez{\dontindex}{1}{}{}{}{}}
+
+\def\table{\begingroup\inENV\obeylines\obeyspaces\tablex}
+{\obeylines\obeyspaces%
+\gdef\tablex #1^^M{%
+\tabley\dontindex#1 \endtabley}}
+
+\def\ftable{\begingroup\inENV\obeylines\obeyspaces\ftablex}
+{\obeylines\obeyspaces%
+\gdef\ftablex #1^^M{%
+\tabley\fnitemindex#1 \endtabley
+\def\Eftable{\endgraf\afterenvbreak\endgroup}%
+\let\Etable=\relax}}
+
+\def\vtable{\begingroup\inENV\obeylines\obeyspaces\vtablex}
+{\obeylines\obeyspaces%
+\gdef\vtablex #1^^M{%
+\tabley\vritemindex#1 \endtabley
+\def\Evtable{\endgraf\afterenvbreak\endgroup}%
+\let\Etable=\relax}}
+
+\def\dontindex #1{}
+\def\fnitemindex #1{\doind {fn}{\code{#1}}}%
+\def\vritemindex #1{\doind {vr}{\code{#1}}}%
+
+{\obeyspaces %
+\gdef\tabley#1#2 #3 #4 #5 #6 #7\endtabley{\endgroup%
+\tablez{#1}{#2}{#3}{#4}{#5}{#6}}}
+
+\def\tablez #1#2#3#4#5#6{%
+\aboveenvbreak %
+\begingroup %
+\def\Edescription{\Etable}% Necessary kludge.
+\let\itemindex=#1%
+\ifnum 0#3>0 \advance \leftskip by #3\mil \fi %
+\ifnum 0#4>0 \tableindent=#4\mil \fi %
+\ifnum 0#5>0 \advance \rightskip by #5\mil \fi %
+\def\itemfont{#2}%
+\itemmax=\tableindent %
+\advance \itemmax by -\itemmargin %
+\advance \leftskip by \tableindent %
+\exdentamount=\tableindent
+\parindent = 0pt
+\parskip = \smallskipamount
+\ifdim \parskip=0pt \parskip=2pt \fi%
+\def\Etable{\endgraf\afterenvbreak\endgroup}%
+\let\item = \internalBitem %
+\let\itemx = \internalBitemx %
+\let\kitem = \internalBkitem %
+\let\kitemx = \internalBkitemx %
+\let\xitem = \internalBxitem %
+\let\xitemx = \internalBxitemx %
+}
+
+% This is the counter used by @enumerate, which is really @itemize
+
+\newcount \itemno
+
+\def\itemize{\parsearg\itemizezzz}
+
+\def\itemizezzz #1{%
+ \begingroup % ended by the @end itemsize
+ \itemizey {#1}{\Eitemize}
+}
+
+\def\itemizey #1#2{%
+\aboveenvbreak %
+\itemmax=\itemindent %
+\advance \itemmax by -\itemmargin %
+\advance \leftskip by \itemindent %
+\exdentamount=\itemindent
+\parindent = 0pt %
+\parskip = \smallskipamount %
+\ifdim \parskip=0pt \parskip=2pt \fi%
+\def#2{\endgraf\afterenvbreak\endgroup}%
+\def\itemcontents{#1}%
+\let\item=\itemizeitem}
+
+% Set sfcode to normal for the chars that usually have another value.
+% These are `.?!:;,'
+\def\frenchspacing{\sfcode46=1000 \sfcode63=1000 \sfcode33=1000
+ \sfcode58=1000 \sfcode59=1000 \sfcode44=1000 }
+
+% \splitoff TOKENS\endmark defines \first to be the first token in
+% TOKENS, and \rest to be the remainder.
+%
+\def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}%
+
+% Allow an optional argument of an uppercase letter, lowercase letter,
+% or number, to specify the first label in the enumerated list. No
+% argument is the same as `1'.
+%
+\def\enumerate{\parsearg\enumeratezzz}
+\def\enumeratezzz #1{\enumeratey #1 \endenumeratey}
+\def\enumeratey #1 #2\endenumeratey{%
+ \begingroup % ended by the @end enumerate
+ %
+ % If we were given no argument, pretend we were given `1'.
+ \def\thearg{#1}%
+ \ifx\thearg\empty \def\thearg{1}\fi
+ %
+ % Detect if the argument is a single token. If so, it might be a
+ % letter. Otherwise, the only valid thing it can be is a number.
+ % (We will always have one token, because of the test we just made.
+ % This is a good thing, since \splitoff doesn't work given nothing at
+ % all -- the first parameter is undelimited.)
+ \expandafter\splitoff\thearg\endmark
+ \ifx\rest\empty
+ % Only one token in the argument. It could still be anything.
+ % A ``lowercase letter'' is one whose \lccode is nonzero.
+ % An ``uppercase letter'' is one whose \lccode is both nonzero, and
+ % not equal to itself.
+ % Otherwise, we assume it's a number.
+ %
+ % We need the \relax at the end of the \ifnum lines to stop TeX from
+ % continuing to look for a <number>.
+ %
+ \ifnum\lccode\expandafter`\thearg=0\relax
+ \numericenumerate % a number (we hope)
+ \else
+ % It's a letter.
+ \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax
+ \lowercaseenumerate % lowercase letter
+ \else
+ \uppercaseenumerate % uppercase letter
+ \fi
+ \fi
+ \else
+ % Multiple tokens in the argument. We hope it's a number.
+ \numericenumerate
+ \fi
+}
+
+% An @enumerate whose labels are integers. The starting integer is
+% given in \thearg.
+%
+\def\numericenumerate{%
+ \itemno = \thearg
+ \startenumeration{\the\itemno}%
+}
+
+% The starting (lowercase) letter is in \thearg.
+\def\lowercaseenumerate{%
+ \itemno = \expandafter`\thearg
+ \startenumeration{%
+ % Be sure we're not beyond the end of the alphabet.
+ \ifnum\itemno=0
+ \errmessage{No more lowercase letters in @enumerate; get a bigger
+ alphabet}%
+ \fi
+ \char\lccode\itemno
+ }%
+}
+
+% The starting (uppercase) letter is in \thearg.
+\def\uppercaseenumerate{%
+ \itemno = \expandafter`\thearg
+ \startenumeration{%
+ % Be sure we're not beyond the end of the alphabet.
+ \ifnum\itemno=0
+ \errmessage{No more uppercase letters in @enumerate; get a bigger
+ alphabet}
+ \fi
+ \char\uccode\itemno
+ }%
+}
+
+% Call itemizey, adding a period to the first argument and supplying the
+% common last two arguments. Also subtract one from the initial value in
+% \itemno, since @item increments \itemno.
+%
+\def\startenumeration#1{%
+ \advance\itemno by -1
+ \itemizey{#1.}\Eenumerate\flushcr
+}
+
+% @alphaenumerate and @capsenumerate are abbreviations for giving an arg
+% to @enumerate.
+%
+\def\alphaenumerate{\enumerate{a}}
+\def\capsenumerate{\enumerate{A}}
+\def\Ealphaenumerate{\Eenumerate}
+\def\Ecapsenumerate{\Eenumerate}
+
+% Definition of @item while inside @itemize.
+
+\def\itemizeitem{%
+\advance\itemno by 1
+{\let\par=\endgraf \smallbreak}%
+\ifhmode \errmessage{\in hmode at itemizeitem}\fi
+{\parskip=0in \hskip 0pt
+\hbox to 0pt{\hss \itemcontents\hskip \itemmargin}%
+\vadjust{\penalty 1200}}%
+\flushcr}
+
+% @multitable macros
+% Amy Hendrickson, 8/18/94, 3/6/96
+%
+% @multitable ... @end multitable will make as many columns as desired.
+% Contents of each column will wrap at width given in preamble. Width
+% can be specified either with sample text given in a template line,
+% or in percent of \hsize, the current width of text on page.
+
+% Table can continue over pages but will only break between lines.
+
+% To make preamble:
+%
+% Either define widths of columns in terms of percent of \hsize:
+% @multitable @columnfractions .25 .3 .45
+% @item ...
+%
+% Numbers following @columnfractions are the percent of the total
+% current hsize to be used for each column. You may use as many
+% columns as desired.
+
+
+% Or use a template:
+% @multitable {Column 1 template} {Column 2 template} {Column 3 template}
+% @item ...
+% using the widest term desired in each column.
+%
+% For those who want to use more than one line's worth of words in
+% the preamble, break the line within one argument and it
+% will parse correctly, i.e.,
+%
+% @multitable {Column 1 template} {Column 2 template} {Column 3
+% template}
+% Not:
+% @multitable {Column 1 template} {Column 2 template}
+% {Column 3 template}
+
+% Each new table line starts with @item, each subsequent new column
+% starts with @tab. Empty columns may be produced by supplying @tab's
+% with nothing between them for as many times as empty columns are needed,
+% ie, @tab@tab@tab will produce two empty columns.
+
+% @item, @tab, @multitable or @end multitable do not need to be on their
+% own lines, but it will not hurt if they are.
+
+% Sample multitable:
+
+% @multitable {Column 1 template} {Column 2 template} {Column 3 template}
+% @item first col stuff @tab second col stuff @tab third col
+% @item
+% first col stuff
+% @tab
+% second col stuff
+% @tab
+% third col
+% @item first col stuff @tab second col stuff
+% @tab Many paragraphs of text may be used in any column.
+%
+% They will wrap at the width determined by the template.
+% @item@tab@tab This will be in third column.
+% @end multitable
+
+% Default dimensions may be reset by user.
+% @multitableparskip is vertical space between paragraphs in table.
+% @multitableparindent is paragraph indent in table.
+% @multitablecolmargin is horizontal space to be left between columns.
+% @multitablelinespace is space to leave between table items, baseline
+% to baseline.
+% 0pt means it depends on current normal line spacing.
+
+%%%%
+% Dimensions
+
+\newskip\multitableparskip
+\newskip\multitableparindent
+\newdimen\multitablecolspace
+\newskip\multitablelinespace
+\multitableparskip=0pt
+\multitableparindent=6pt
+\multitablecolspace=12pt
+\multitablelinespace=0pt
+
+%%%%
+% Macros used to set up halign preamble:
+\let\endsetuptable\relax
+\def\xendsetuptable{\endsetuptable}
+\let\columnfractions\relax
+\def\xcolumnfractions{\columnfractions}
+\newif\ifsetpercent
+
+%% 2/1/96, to allow fractions to be given with more than one digit.
+\def\pickupwholefraction#1 {\global\advance\colcount by1 %
+\expandafter\xdef\csname col\the\colcount\endcsname{.#1\hsize}%
+\setuptable}
+
+\newcount\colcount
+\def\setuptable#1{\def\firstarg{#1}%
+\ifx\firstarg\xendsetuptable\let\go\relax%
+\else
+ \ifx\firstarg\xcolumnfractions\global\setpercenttrue%
+ \else
+ \ifsetpercent
+ \let\go\pickupwholefraction % In this case arg of setuptable
+ % is the decimal point before the
+ % number given in percent of hsize.
+ % We don't need this so we don't use it.
+ \else
+ \global\advance\colcount by1
+ \setbox0=\hbox{#1 }% Add a normal word space as a separator;
+ % typically that is always in the input, anyway.
+ \expandafter\xdef\csname col\the\colcount\endcsname{\the\wd0}%
+ \fi%
+ \fi%
+\ifx\go\pickupwholefraction\else\let\go\setuptable\fi%
+\fi\go}
+
+%%%%
+% multitable syntax
+\def\tab{&\hskip1sp\relax} % 2/2/96
+ % tiny skip here makes sure this column space is
+ % maintained, even if it is never used.
+
+
+%%%%
+% @multitable ... @end multitable definitions:
+
+\def\multitable{\parsearg\dotable}
+
+\def\dotable#1{\bgroup
+\let\item\cr
+\tolerance=9500
+\hbadness=9500
+\setmultitablespacing
+\parskip=\multitableparskip
+\parindent=\multitableparindent
+\overfullrule=0pt
+\global\colcount=0\relax%
+\def\Emultitable{\global\setpercentfalse\global\everycr{}\cr\egroup\egroup}%
+ % To parse everything between @multitable and @item :
+\setuptable#1 \endsetuptable
+ % Need to reset this to 0 after \setuptable.
+\global\colcount=0\relax%
+ %
+ % This preamble sets up a generic column definition, which will
+ % be used as many times as user calls for columns.
+ % \vtop will set a single line and will also let text wrap and
+ % continue for many paragraphs if desired.
+\halign\bgroup&\global\advance\colcount by 1\relax%
+\multistrut\vtop{\hsize=\expandafter\csname col\the\colcount\endcsname
+ % In order to keep entries from bumping into each other
+ % we will add a \leftskip of \multitablecolspace to all columns after
+ % the first one.
+ % If a template has been used, we will add \multitablecolspace
+ % to the width of each template entry.
+ % If user has set preamble in terms of percent of \hsize
+ % we will use that dimension as the width of the column, and
+ % the \leftskip will keep entries from bumping into each other.
+ % Table will start at left margin and final column will justify at
+ % right margin.
+\ifnum\colcount=1
+\else
+ \ifsetpercent
+ \else
+ % If user has <not> set preamble in terms of percent of \hsize
+ % we will advance \hsize by \multitablecolspace
+ \advance\hsize by \multitablecolspace
+ \fi
+ % In either case we will make \leftskip=\multitablecolspace:
+\leftskip=\multitablecolspace
+\fi
+\noindent##\multistrut}\cr%
+ % \everycr will reset column counter, \colcount, at the end of
+ % each line. Every column entry will cause \colcount to advance by one.
+ % The table preamble
+ % looks at the current \colcount to find the correct column width.
+\global\everycr{\noalign{%
+\filbreak%% keeps underfull box messages off when table breaks over pages.
+\global\colcount=0\relax}}
+}
+
+\def\setmultitablespacing{% test to see if user has set \multitablelinespace.
+% If so, do nothing. If not, give it an appropriate dimension based on
+% current baselineskip.
+\ifdim\multitablelinespace=0pt
+%% strut to put in table in case some entry doesn't have descenders,
+%% to keep lines equally spaced
+\let\multistrut = \strut
+%% Test to see if parskip is larger than space between lines of
+%% table. If not, do nothing.
+%% If so, set to same dimension as multitablelinespace.
+\else
+\gdef\multistrut{\vrule height\multitablelinespace depth\dp0
+width0pt\relax} \fi
+\ifdim\multitableparskip>\multitablelinespace
+\global\multitableparskip=\multitablelinespace
+\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller
+ %% than skip between lines in the table.
+\fi%
+\ifdim\multitableparskip=0pt
+\global\multitableparskip=\multitablelinespace
+\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller
+ %% than skip between lines in the table.
+\fi}
+
+
+\message{indexing,}
+% Index generation facilities
+
+% Define \newwrite to be identical to plain tex's \newwrite
+% except not \outer, so it can be used within \newindex.
+{\catcode`\@=11
+\gdef\newwrite{\alloc@7\write\chardef\sixt@@n}}
+
+% \newindex {foo} defines an index named foo.
+% It automatically defines \fooindex such that
+% \fooindex ...rest of line... puts an entry in the index foo.
+% It also defines \fooindfile to be the number of the output channel for
+% the file that accumulates this index. The file's extension is foo.
+% The name of an index should be no more than 2 characters long
+% for the sake of vms.
+
+\def\newindex #1{
+\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file
+\openout \csname#1indfile\endcsname \jobname.#1 % Open the file
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\doindex {#1}}
+}
+
+% @defindex foo == \newindex{foo}
+
+\def\defindex{\parsearg\newindex}
+
+% Define @defcodeindex, like @defindex except put all entries in @code.
+
+\def\newcodeindex #1{
+\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file
+\openout \csname#1indfile\endcsname \jobname.#1 % Open the file
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\docodeindex {#1}}
+}
+
+\def\defcodeindex{\parsearg\newcodeindex}
+
+% @synindex foo bar makes index foo feed into index bar.
+% Do this instead of @defindex foo if you don't want it as a separate index.
+\def\synindex #1 #2 {%
+\expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname
+\expandafter\let\csname#1indfile\endcsname=\synindexfoo
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\doindex {#2}}%
+}
+
+% @syncodeindex foo bar similar, but put all entries made for index foo
+% inside @code.
+\def\syncodeindex #1 #2 {%
+\expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname
+\expandafter\let\csname#1indfile\endcsname=\synindexfoo
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\docodeindex {#2}}%
+}
+
+% Define \doindex, the driver for all \fooindex macros.
+% Argument #1 is generated by the calling \fooindex macro,
+% and it is "foo", the name of the index.
+
+% \doindex just uses \parsearg; it calls \doind for the actual work.
+% This is because \doind is more useful to call from other macros.
+
+% There is also \dosubind {index}{topic}{subtopic}
+% which makes an entry in a two-level index such as the operation index.
+
+\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer}
+\def\singleindexer #1{\doind{\indexname}{#1}}
+
+% like the previous two, but they put @code around the argument.
+\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer}
+\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}}
+
+\def\indexdummies{%
+% Take care of the plain tex accent commands.
+\def\"{\realbackslash "}%
+\def\`{\realbackslash `}%
+\def\'{\realbackslash '}%
+\def\^{\realbackslash ^}%
+\def\~{\realbackslash ~}%
+\def\={\realbackslash =}%
+\def\b{\realbackslash b}%
+\def\c{\realbackslash c}%
+\def\d{\realbackslash d}%
+\def\u{\realbackslash u}%
+\def\v{\realbackslash v}%
+\def\H{\realbackslash H}%
+% Take care of the plain tex special European modified letters.
+\def\oe{\realbackslash oe}%
+\def\ae{\realbackslash ae}%
+\def\aa{\realbackslash aa}%
+\def\OE{\realbackslash OE}%
+\def\AE{\realbackslash AE}%
+\def\AA{\realbackslash AA}%
+\def\o{\realbackslash o}%
+\def\O{\realbackslash O}%
+\def\l{\realbackslash l}%
+\def\L{\realbackslash L}%
+\def\ss{\realbackslash ss}%
+% Take care of texinfo commands likely to appear in an index entry.
+% (Must be a way to avoid doing expansion at all, and thus not have to
+% laboriously list every single command here.)
+\def\@{@}% will be @@ when we switch to @ as escape char.
+%\let\{ = \lbracecmd
+%\let\} = \rbracecmd
+\def\_{{\realbackslash _}}%
+\def\w{\realbackslash w }%
+\def\bf{\realbackslash bf }%
+%\def\rm{\realbackslash rm }%
+\def\sl{\realbackslash sl }%
+\def\sf{\realbackslash sf}%
+\def\tt{\realbackslash tt}%
+\def\gtr{\realbackslash gtr}%
+\def\less{\realbackslash less}%
+\def\hat{\realbackslash hat}%
+%\def\char{\realbackslash char}%
+\def\TeX{\realbackslash TeX}%
+\def\dots{\realbackslash dots }%
+\def\copyright{\realbackslash copyright }%
+\def\tclose##1{\realbackslash tclose {##1}}%
+\def\code##1{\realbackslash code {##1}}%
+\def\dotless##1{\realbackslash dotless {##1}}%
+\def\samp##1{\realbackslash samp {##1}}%
+\def\,##1{\realbackslash ,{##1}}%
+\def\t##1{\realbackslash t {##1}}%
+\def\r##1{\realbackslash r {##1}}%
+\def\i##1{\realbackslash i {##1}}%
+\def\b##1{\realbackslash b {##1}}%
+\def\cite##1{\realbackslash cite {##1}}%
+\def\key##1{\realbackslash key {##1}}%
+\def\file##1{\realbackslash file {##1}}%
+\def\var##1{\realbackslash var {##1}}%
+\def\kbd##1{\realbackslash kbd {##1}}%
+\def\dfn##1{\realbackslash dfn {##1}}%
+\def\emph##1{\realbackslash emph {##1}}%
+\unsepspaces
+}
+
+% If an index command is used in an @example environment, any spaces
+% therein should become regular spaces in the raw index file, not the
+% expansion of \tie (\\leavevmode \penalty \@M \ ).
+{\obeyspaces
+ \gdef\unsepspaces{\obeyspaces\let =\space}}
+
+% \indexnofonts no-ops all font-change commands.
+% This is used when outputting the strings to sort the index by.
+\def\indexdummyfont#1{#1}
+\def\indexdummytex{TeX}
+\def\indexdummydots{...}
+
+\def\indexnofonts{%
+% Just ignore accents.
+\let\,=\indexdummyfont
+\let\"=\indexdummyfont
+\let\`=\indexdummyfont
+\let\'=\indexdummyfont
+\let\^=\indexdummyfont
+\let\~=\indexdummyfont
+\let\==\indexdummyfont
+\let\b=\indexdummyfont
+\let\c=\indexdummyfont
+\let\d=\indexdummyfont
+\let\u=\indexdummyfont
+\let\v=\indexdummyfont
+\let\H=\indexdummyfont
+\let\dotless=\indexdummyfont
+% Take care of the plain tex special European modified letters.
+\def\oe{oe}%
+\def\ae{ae}%
+\def\aa{aa}%
+\def\OE{OE}%
+\def\AE{AE}%
+\def\AA{AA}%
+\def\o{o}%
+\def\O{O}%
+\def\l{l}%
+\def\L{L}%
+\def\ss{ss}%
+\let\w=\indexdummyfont
+\let\t=\indexdummyfont
+\let\r=\indexdummyfont
+\let\i=\indexdummyfont
+\let\b=\indexdummyfont
+\let\emph=\indexdummyfont
+\let\strong=\indexdummyfont
+\let\cite=\indexdummyfont
+\let\sc=\indexdummyfont
+%Don't no-op \tt, since it isn't a user-level command
+% and is used in the definitions of the active chars like <, >, |...
+%\let\tt=\indexdummyfont
+\let\tclose=\indexdummyfont
+\let\code=\indexdummyfont
+\let\file=\indexdummyfont
+\let\samp=\indexdummyfont
+\let\kbd=\indexdummyfont
+\let\key=\indexdummyfont
+\let\var=\indexdummyfont
+\let\TeX=\indexdummytex
+\let\dots=\indexdummydots
+\def\@{@}%
+}
+
+% To define \realbackslash, we must make \ not be an escape.
+% We must first make another character (@) an escape
+% so we do not become unable to do a definition.
+
+{\catcode`\@=0 \catcode`\\=\other
+@gdef@realbackslash{\}}
+
+\let\indexbackslash=0 %overridden during \printindex.
+
+\let\SETmarginindex=\relax %initialize!
+% workhorse for all \fooindexes
+% #1 is name of index, #2 is stuff to put there
+\def\doind #1#2{%
+ % Put the index entry in the margin if desired.
+ \ifx\SETmarginindex\relax\else
+ \insert\margin{\hbox{\vrule height8pt depth3pt width0pt #2}}%
+ \fi
+ {%
+ \count255=\lastpenalty
+ {%
+ \indexdummies % Must do this here, since \bf, etc expand at this stage
+ \escapechar=`\\
+ {%
+ \let\folio=0 % We will expand all macros now EXCEPT \folio.
+ \def\rawbackslashxx{\indexbackslash}% \indexbackslash isn't defined now
+ % so it will be output as is; and it will print as backslash.
+ %
+ % First process the index-string with all font commands turned off
+ % to get the string to sort by.
+ {\indexnofonts \xdef\indexsorttmp{#2}}%
+ %
+ % Now produce the complete index entry, with both the sort key and the
+ % original text, including any font commands.
+ \toks0 = {#2}%
+ \edef\temp{%
+ \write\csname#1indfile\endcsname{%
+ \realbackslash entry{\indexsorttmp}{\folio}{\the\toks0}}%
+ }%
+ \temp
+ }%
+ }%
+ \penalty\count255
+ }%
+}
+
+\def\dosubind #1#2#3{%
+{\count10=\lastpenalty %
+{\indexdummies % Must do this here, since \bf, etc expand at this stage
+\escapechar=`\\%
+{\let\folio=0%
+\def\rawbackslashxx{\indexbackslash}%
+%
+% Now process the index-string once, with all font commands turned off,
+% to get the string to sort the index by.
+{\indexnofonts
+\xdef\temp1{#2 #3}%
+}%
+% Now produce the complete index entry. We process the index-string again,
+% this time with font commands expanded, to get what to print in the index.
+\edef\temp{%
+\write \csname#1indfile\endcsname{%
+\realbackslash entry {\temp1}{\folio}{#2}{#3}}}%
+\temp }%
+}\penalty\count10}}
+
+% The index entry written in the file actually looks like
+% \entry {sortstring}{page}{topic}
+% or
+% \entry {sortstring}{page}{topic}{subtopic}
+% The texindex program reads in these files and writes files
+% containing these kinds of lines:
+% \initial {c}
+% before the first topic whose initial is c
+% \entry {topic}{pagelist}
+% for a topic that is used without subtopics
+% \primary {topic}
+% for the beginning of a topic that is used with subtopics
+% \secondary {subtopic}{pagelist}
+% for each subtopic.
+
+% Define the user-accessible indexing commands
+% @findex, @vindex, @kindex, @cindex.
+
+\def\findex {\fnindex}
+\def\kindex {\kyindex}
+\def\cindex {\cpindex}
+\def\vindex {\vrindex}
+\def\tindex {\tpindex}
+\def\pindex {\pgindex}
+
+\def\cindexsub {\begingroup\obeylines\cindexsub}
+{\obeylines %
+\gdef\cindexsub "#1" #2^^M{\endgroup %
+\dosubind{cp}{#2}{#1}}}
+
+% Define the macros used in formatting output of the sorted index material.
+
+% This is what you call to cause a particular index to get printed.
+% Write
+% @unnumbered Function Index
+% @printindex fn
+
+\def\printindex{\parsearg\doprintindex}
+
+\def\doprintindex#1{\begingroup
+ \dobreak \chapheadingskip{10000}%
+ %
+ \indexfonts \rm
+ \tolerance = 9500
+ \indexbreaks
+ \def\indexbackslash{\rawbackslashxx}%
+ % Index files are almost Texinfo source, but we use \ as the escape
+ % character. It would be better to use @, but that's too big a change
+ % to make right now.
+ \catcode`\\ = 0
+ \catcode`\@ = 11
+ \escapechar = `\\
+ \begindoublecolumns
+ %
+ % See if the index file exists and is nonempty.
+ \openin 1 \jobname.#1s
+ \ifeof 1
+ % \enddoublecolumns gets confused if there is no text in the index,
+ % and it loses the chapter title and the aux file entries for the
+ % index. The easiest way to prevent this problem is to make sure
+ % there is some text.
+ (Index is nonexistent)
+ \else
+ %
+ % If the index file exists but is empty, then \openin leaves \ifeof
+ % false. We have to make TeX try to read something from the file, so
+ % it can discover if there is anything in it.
+ \read 1 to \temp
+ \ifeof 1
+ (Index is empty)
+ \else
+ \input \jobname.#1s
+ \fi
+ \fi
+ \closein 1
+ \enddoublecolumns
+\endgroup}
+
+% These macros are used by the sorted index file itself.
+% Change them to control the appearance of the index.
+
+% Same as \bigskipamount except no shrink.
+% \balancecolumns gets confused if there is any shrink.
+\newskip\initialskipamount \initialskipamount 12pt plus4pt
+
+\def\initial #1{%
+{\let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt
+\ifdim\lastskip<\initialskipamount
+\removelastskip \penalty-200 \vskip \initialskipamount\fi
+\line{\secbf#1\hfill}\kern 2pt\penalty10000}}
+
+% This typesets a paragraph consisting of #1, dot leaders, and then #2
+% flush to the right margin. It is used for index and table of contents
+% entries. The paragraph is indented by \leftskip.
+%
+\def\entry #1#2{\begingroup
+ %
+ % Start a new paragraph if necessary, so our assignments below can't
+ % affect previous text.
+ \par
+ %
+ % Do not fill out the last line with white space.
+ \parfillskip = 0in
+ %
+ % No extra space above this paragraph.
+ \parskip = 0in
+ %
+ % Do not prefer a separate line ending with a hyphen to fewer lines.
+ \finalhyphendemerits = 0
+ %
+ % \hangindent is only relevant when the entry text and page number
+ % don't both fit on one line. In that case, bob suggests starting the
+ % dots pretty far over on the line. Unfortunately, a large
+ % indentation looks wrong when the entry text itself is broken across
+ % lines. So we use a small indentation and put up with long leaders.
+ %
+ % \hangafter is reset to 1 (which is the value we want) at the start
+ % of each paragraph, so we need not do anything with that.
+ \hangindent=2em
+ %
+ % When the entry text needs to be broken, just fill out the first line
+ % with blank space.
+ \rightskip = 0pt plus1fil
+ %
+ % Start a ``paragraph'' for the index entry so the line breaking
+ % parameters we've set above will have an effect.
+ \noindent
+ %
+ % Insert the text of the index entry. TeX will do line-breaking on it.
+ #1%
+ % The following is kludged to not output a line of dots in the index if
+ % there are no page numbers. The next person who breaks this will be
+ % cursed by a Unix daemon.
+ \def\tempa{{\rm }}%
+ \def\tempb{#2}%
+ \edef\tempc{\tempa}%
+ \edef\tempd{\tempb}%
+ \ifx\tempc\tempd\ \else%
+ %
+ % If we must, put the page number on a line of its own, and fill out
+ % this line with blank space. (The \hfil is overwhelmed with the
+ % fill leaders glue in \indexdotfill if the page number does fit.)
+ \hfil\penalty50
+ \null\nobreak\indexdotfill % Have leaders before the page number.
+ %
+ % The `\ ' here is removed by the implicit \unskip that TeX does as
+ % part of (the primitive) \par. Without it, a spurious underfull
+ % \hbox ensues.
+ \ #2% The page number ends the paragraph.
+ \fi%
+ \par
+\endgroup}
+
+% Like \dotfill except takes at least 1 em.
+\def\indexdotfill{\cleaders
+ \hbox{$\mathsurround=0pt \mkern1.5mu ${\it .}$ \mkern1.5mu$}\hskip 1em plus 1fill}
+
+\def\primary #1{\line{#1\hfil}}
+
+\newskip\secondaryindent \secondaryindent=0.5cm
+
+\def\secondary #1#2{
+{\parfillskip=0in \parskip=0in
+\hangindent =1in \hangafter=1
+\noindent\hskip\secondaryindent\hbox{#1}\indexdotfill #2\par
+}}
+
+% Define two-column mode, which we use to typeset indexes.
+% Adapted from the TeXbook, page 416, which is to say,
+% the manmac.tex format used to print the TeXbook itself.
+\catcode`\@=11
+
+\newbox\partialpage
+\newdimen\doublecolumnhsize
+
+\def\begindoublecolumns{\begingroup % ended by \enddoublecolumns
+ % Grab any single-column material above us.
+ \output = {\global\setbox\partialpage
+ =\vbox{\unvbox255\kern -\topskip \kern \baselineskip}}%
+ \eject
+ %
+ % Now switch to the double-column output routine.
+ \output={\doublecolumnout}%
+ %
+ % Change the page size parameters. We could do this once outside this
+ % routine, in each of @smallbook, @afourpaper, and the default 8.5x11
+ % format, but then we repeat the same computation. Repeating a couple
+ % of assignments once per index is clearly meaningless for the
+ % execution time, so we may as well do it once.
+ %
+ % First we halve the line length, less a little for the gutter between
+ % the columns. We compute the gutter based on the line length, so it
+ % changes automatically with the paper format. The magic constant
+ % below is chosen so that the gutter has the same value (well, +- <
+ % 1pt) as it did when we hard-coded it.
+ %
+ % We put the result in a separate register, \doublecolumhsize, so we
+ % can restore it in \pagesofar, after \hsize itself has (potentially)
+ % been clobbered.
+ %
+ \doublecolumnhsize = \hsize
+ \advance\doublecolumnhsize by -.04154\hsize
+ \divide\doublecolumnhsize by 2
+ \hsize = \doublecolumnhsize
+ %
+ % Double the \vsize as well. (We don't need a separate register here,
+ % since nobody clobbers \vsize.)
+ \vsize = 2\vsize
+}
+\def\doublecolumnout{%
+ \splittopskip=\topskip \splitmaxdepth=\maxdepth
+ % Get the available space for the double columns -- the normal
+ % (undoubled) page height minus any material left over from the
+ % previous page.
+ \dimen@=\pageheight \advance\dimen@ by-\ht\partialpage
+ % box0 will be the left-hand column, box1 the right.
+ \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@
+ \onepageout\pagesofar
+ \unvbox255 \penalty\outputpenalty
+}
+\def\pagesofar{%
+ % The contents of the output page -- any previous material,
+ % followed by the two boxes we just split.
+ \unvbox\partialpage
+ \hsize = \doublecolumnhsize
+ \wd0=\hsize \wd2=\hsize \hbox to\pagewidth{\box0\hfil\box2}%
+}
+\def\enddoublecolumns{%
+ \output={\balancecolumns}\eject % split what we have
+ \endgroup
+ % Back to normal single-column typesetting, but take account of the
+ % fact that we just accumulated some stuff on the output page.
+ \pagegoal=\vsize
+}
+\def\balancecolumns{%
+ % Called on the last page of the double column material.
+ \setbox0=\vbox{\unvbox255}%
+ \dimen@ = \ht0
+ \advance\dimen@ by \topskip
+ \advance\dimen@ by-\baselineskip
+ \divide\dimen@ by 2
+ \splittopskip = \topskip
+ % Loop until we get a decent breakpoint.
+ {\vbadness=10000 \loop \global\setbox3=\copy0
+ \global\setbox1=\vsplit3 to\dimen@
+ \ifdim\ht3>\dimen@ \global\advance\dimen@ by1pt \repeat}%
+ \setbox0=\vbox to\dimen@{\unvbox1}%
+ \setbox2=\vbox to\dimen@{\unvbox3}%
+ \pagesofar
+}
+\catcode `\@=\other
+
+
+\message{sectioning,}
+% Define chapters, sections, etc.
+
+\newcount \chapno
+\newcount \secno \secno=0
+\newcount \subsecno \subsecno=0
+\newcount \subsubsecno \subsubsecno=0
+
+% This counter is funny since it counts through charcodes of letters A, B, ...
+\newcount \appendixno \appendixno = `\@
+\def\appendixletter{\char\the\appendixno}
+
+\newwrite \contentsfile
+% This is called from \setfilename.
+\def\opencontents{\openout \contentsfile = \jobname.toc}
+
+% Each @chapter defines this as the name of the chapter.
+% page headings and footings can use it. @section does likewise
+
+\def\thischapter{} \def\thissection{}
+\def\seccheck#1{\if \pageno<0 %
+\errmessage{@#1 not allowed after generating table of contents}\fi
+%
+}
+
+\def\chapternofonts{%
+\let\rawbackslash=\relax%
+\let\frenchspacing=\relax%
+\def\result{\realbackslash result}
+\def\equiv{\realbackslash equiv}
+\def\expansion{\realbackslash expansion}
+\def\print{\realbackslash print}
+\def\TeX{\realbackslash TeX}
+\def\dots{\realbackslash dots}
+\def\copyright{\realbackslash copyright}
+\def\tt{\realbackslash tt}
+\def\bf{\realbackslash bf }
+\def\w{\realbackslash w}
+\def\less{\realbackslash less}
+\def\gtr{\realbackslash gtr}
+\def\hat{\realbackslash hat}
+\def\char{\realbackslash char}
+\def\tclose##1{\realbackslash tclose {##1}}
+\def\code##1{\realbackslash code {##1}}
+\def\samp##1{\realbackslash samp {##1}}
+\def\r##1{\realbackslash r {##1}}
+\def\b##1{\realbackslash b {##1}}
+\def\key##1{\realbackslash key {##1}}
+\def\file##1{\realbackslash file {##1}}
+\def\kbd##1{\realbackslash kbd {##1}}
+% These are redefined because @smartitalic wouldn't work inside xdef.
+\def\i##1{\realbackslash i {##1}}
+\def\cite##1{\realbackslash cite {##1}}
+\def\var##1{\realbackslash var {##1}}
+\def\emph##1{\realbackslash emph {##1}}
+\def\dfn##1{\realbackslash dfn {##1}}
+}
+
+\newcount\absseclevel % used to calculate proper heading level
+\newcount\secbase\secbase=0 % @raise/lowersections modify this count
+
+% @raisesections: treat @section as chapter, @subsection as section, etc.
+\def\raisesections{\global\advance\secbase by -1}
+\let\up=\raisesections % original BFox name
+
+% @lowersections: treat @chapter as section, @section as subsection, etc.
+\def\lowersections{\global\advance\secbase by 1}
+\let\down=\lowersections % original BFox name
+
+% Choose a numbered-heading macro
+% #1 is heading level if unmodified by @raisesections or @lowersections
+% #2 is text for heading
+\def\numhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+\ifcase\absseclevel
+ \chapterzzz{#2}
+\or
+ \seczzz{#2}
+\or
+ \numberedsubseczzz{#2}
+\or
+ \numberedsubsubseczzz{#2}
+\else
+ \ifnum \absseclevel<0
+ \chapterzzz{#2}
+ \else
+ \numberedsubsubseczzz{#2}
+ \fi
+\fi
+}
+
+% like \numhead, but chooses appendix heading levels
+\def\apphead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+\ifcase\absseclevel
+ \appendixzzz{#2}
+\or
+ \appendixsectionzzz{#2}
+\or
+ \appendixsubseczzz{#2}
+\or
+ \appendixsubsubseczzz{#2}
+\else
+ \ifnum \absseclevel<0
+ \appendixzzz{#2}
+ \else
+ \appendixsubsubseczzz{#2}
+ \fi
+\fi
+}
+
+% like \numhead, but chooses numberless heading levels
+\def\unnmhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+\ifcase\absseclevel
+ \unnumberedzzz{#2}
+\or
+ \unnumberedseczzz{#2}
+\or
+ \unnumberedsubseczzz{#2}
+\or
+ \unnumberedsubsubseczzz{#2}
+\else
+ \ifnum \absseclevel<0
+ \unnumberedzzz{#2}
+ \else
+ \unnumberedsubsubseczzz{#2}
+ \fi
+\fi
+}
+
+
+\def\thischaptername{No Chapter Title}
+\outer\def\chapter{\parsearg\chapteryyy}
+\def\chapteryyy #1{\numhead0{#1}} % normally numhead0 calls chapterzzz
+\def\chapterzzz #1{\seccheck{chapter}%
+\secno=0 \subsecno=0 \subsubsecno=0
+\global\advance \chapno by 1 \message{\putwordChapter \the\chapno}%
+\chapmacro {#1}{\the\chapno}%
+\gdef\thissection{#1}%
+\gdef\thischaptername{#1}%
+% We don't substitute the actual chapter name into \thischapter
+% because we don't want its macros evaluated now.
+\xdef\thischapter{\putwordChapter{} \the\chapno: \noexpand\thischaptername}%
+{\chapternofonts%
+\edef\temp{{\realbackslash chapentry {#1}{\the\chapno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\global\let\section = \numberedsec
+\global\let\subsection = \numberedsubsec
+\global\let\subsubsection = \numberedsubsubsec
+}}
+
+\outer\def\appendix{\parsearg\appendixyyy}
+\def\appendixyyy #1{\apphead0{#1}} % normally apphead0 calls appendixzzz
+\def\appendixzzz #1{\seccheck{appendix}%
+\secno=0 \subsecno=0 \subsubsecno=0
+\global\advance \appendixno by 1 \message{Appendix \appendixletter}%
+\chapmacro {#1}{\putwordAppendix{} \appendixletter}%
+\gdef\thissection{#1}%
+\gdef\thischaptername{#1}%
+\xdef\thischapter{\putwordAppendix{} \appendixletter: \noexpand\thischaptername}%
+{\chapternofonts%
+\edef\temp{{\realbackslash chapentry
+ {#1}{\putwordAppendix{} \appendixletter}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\global\let\section = \appendixsec
+\global\let\subsection = \appendixsubsec
+\global\let\subsubsection = \appendixsubsubsec
+}}
+
+% @centerchap is like @unnumbered, but the heading is centered.
+\outer\def\centerchap{\parsearg\centerchapyyy}
+\def\centerchapyyy #1{{\let\unnumbchapmacro=\centerchapmacro \unnumberedyyy{#1}}}
+
+\outer\def\top{\parsearg\unnumberedyyy}
+\outer\def\unnumbered{\parsearg\unnumberedyyy}
+\def\unnumberedyyy #1{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz
+\def\unnumberedzzz #1{\seccheck{unnumbered}%
+\secno=0 \subsecno=0 \subsubsecno=0
+%
+% This used to be simply \message{#1}, but TeX fully expands the
+% argument to \message. Therefore, if #1 contained @-commands, TeX
+% expanded them. For example, in `@unnumbered The @cite{Book}', TeX
+% expanded @cite (which turns out to cause errors because \cite is meant
+% to be executed, not expanded).
+%
+% Anyway, we don't want the fully-expanded definition of @cite to appear
+% as a result of the \message, we just want `@cite' itself. We use
+% \the<toks register> to achieve this: TeX expands \the<toks> only once,
+% simply yielding the contents of the <toks register>.
+\toks0 = {#1}\message{(\the\toks0)}%
+%
+\unnumbchapmacro {#1}%
+\gdef\thischapter{#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbchapentry {#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\global\let\section = \unnumberedsec
+\global\let\subsection = \unnumberedsubsec
+\global\let\subsubsection = \unnumberedsubsubsec
+}}
+
+\outer\def\numberedsec{\parsearg\secyyy}
+\def\secyyy #1{\numhead1{#1}} % normally calls seczzz
+\def\seczzz #1{\seccheck{section}%
+\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 %
+\gdef\thissection{#1}\secheading {#1}{\the\chapno}{\the\secno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash secentry %
+{#1}{\the\chapno}{\the\secno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}}
+
+\outer\def\appendixsection{\parsearg\appendixsecyyy}
+\outer\def\appendixsec{\parsearg\appendixsecyyy}
+\def\appendixsecyyy #1{\apphead1{#1}} % normally calls appendixsectionzzz
+\def\appendixsectionzzz #1{\seccheck{appendixsection}%
+\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 %
+\gdef\thissection{#1}\secheading {#1}{\appendixletter}{\the\secno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash secentry %
+{#1}{\appendixletter}{\the\secno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\unnumberedsec{\parsearg\unnumberedsecyyy}
+\def\unnumberedsecyyy #1{\unnmhead1{#1}} % normally calls unnumberedseczzz
+\def\unnumberedseczzz #1{\seccheck{unnumberedsec}%
+\plainsecheading {#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\numberedsubsec{\parsearg\numberedsubsecyyy}
+\def\numberedsubsecyyy #1{\numhead2{#1}} % normally calls numberedsubseczzz
+\def\numberedsubseczzz #1{\seccheck{subsection}%
+\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 %
+\subsecheading {#1}{\the\chapno}{\the\secno}{\the\subsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsecentry %
+{#1}{\the\chapno}{\the\secno}{\the\subsecno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}}
+
+\outer\def\appendixsubsec{\parsearg\appendixsubsecyyy}
+\def\appendixsubsecyyy #1{\apphead2{#1}} % normally calls appendixsubseczzz
+\def\appendixsubseczzz #1{\seccheck{appendixsubsec}%
+\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 %
+\subsecheading {#1}{\appendixletter}{\the\secno}{\the\subsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsecentry %
+{#1}{\appendixletter}{\the\secno}{\the\subsecno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\unnumberedsubsec{\parsearg\unnumberedsubsecyyy}
+\def\unnumberedsubsecyyy #1{\unnmhead2{#1}} %normally calls unnumberedsubseczzz
+\def\unnumberedsubseczzz #1{\seccheck{unnumberedsubsec}%
+\plainsubsecheading {#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbsubsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\numberedsubsubsec{\parsearg\numberedsubsubsecyyy}
+\def\numberedsubsubsecyyy #1{\numhead3{#1}} % normally numberedsubsubseczzz
+\def\numberedsubsubseczzz #1{\seccheck{subsubsection}%
+\gdef\thissection{#1}\global\advance \subsubsecno by 1 %
+\subsubsecheading {#1}
+ {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsubsecentry %
+ {#1}
+ {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}
+ {\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}}
+
+\outer\def\appendixsubsubsec{\parsearg\appendixsubsubsecyyy}
+\def\appendixsubsubsecyyy #1{\apphead3{#1}} % normally appendixsubsubseczzz
+\def\appendixsubsubseczzz #1{\seccheck{appendixsubsubsec}%
+\gdef\thissection{#1}\global\advance \subsubsecno by 1 %
+\subsubsecheading {#1}
+ {\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsubsecentry{#1}%
+ {\appendixletter}
+ {\the\secno}{\the\subsecno}{\the\subsubsecno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\unnumberedsubsubsec{\parsearg\unnumberedsubsubsecyyy}
+\def\unnumberedsubsubsecyyy #1{\unnmhead3{#1}} %normally unnumberedsubsubseczzz
+\def\unnumberedsubsubseczzz #1{\seccheck{unnumberedsubsubsec}%
+\plainsubsubsecheading {#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbsubsubsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}}
+
+% These are variants which are not "outer", so they can appear in @ifinfo.
+% Actually, they should now be obsolete; ordinary section commands should work.
+\def\infotop{\parsearg\unnumberedzzz}
+\def\infounnumbered{\parsearg\unnumberedzzz}
+\def\infounnumberedsec{\parsearg\unnumberedseczzz}
+\def\infounnumberedsubsec{\parsearg\unnumberedsubseczzz}
+\def\infounnumberedsubsubsec{\parsearg\unnumberedsubsubseczzz}
+
+\def\infoappendix{\parsearg\appendixzzz}
+\def\infoappendixsec{\parsearg\appendixseczzz}
+\def\infoappendixsubsec{\parsearg\appendixsubseczzz}
+\def\infoappendixsubsubsec{\parsearg\appendixsubsubseczzz}
+
+\def\infochapter{\parsearg\chapterzzz}
+\def\infosection{\parsearg\sectionzzz}
+\def\infosubsection{\parsearg\subsectionzzz}
+\def\infosubsubsection{\parsearg\subsubsectionzzz}
+
+% These macros control what the section commands do, according
+% to what kind of chapter we are in (ordinary, appendix, or unnumbered).
+% Define them by default for a numbered chapter.
+\global\let\section = \numberedsec
+\global\let\subsection = \numberedsubsec
+\global\let\subsubsection = \numberedsubsubsec
+
+% Define @majorheading, @heading and @subheading
+
+% NOTE on use of \vbox for chapter headings, section headings, and
+% such:
+% 1) We use \vbox rather than the earlier \line to permit
+% overlong headings to fold.
+% 2) \hyphenpenalty is set to 10000 because hyphenation in a
+% heading is obnoxious; this forbids it.
+% 3) Likewise, headings look best if no \parindent is used, and
+% if justification is not attempted. Hence \raggedright.
+
+
+\def\majorheading{\parsearg\majorheadingzzz}
+\def\majorheadingzzz #1{%
+{\advance\chapheadingskip by 10pt \chapbreak }%
+{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\penalty 200}
+
+\def\chapheading{\parsearg\chapheadingzzz}
+\def\chapheadingzzz #1{\chapbreak %
+{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\penalty 200}
+
+% @heading, @subheading, @subsubheading.
+\def\heading{\parsearg\plainsecheading}
+\def\subheading{\parsearg\plainsubsecheading}
+\def\subsubheading{\parsearg\plainsubsubsecheading}
+
+% These macros generate a chapter, section, etc. heading only
+% (including whitespace, linebreaking, etc. around it),
+% given all the information in convenient, parsed form.
+
+%%% Args are the skip and penalty (usually negative)
+\def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi}
+
+\def\setchapterstyle #1 {\csname CHAPF#1\endcsname}
+
+%%% Define plain chapter starts, and page on/off switching for it
+% Parameter controlling skip before chapter headings (if needed)
+
+\newskip\chapheadingskip
+
+\def\chapbreak{\dobreak \chapheadingskip {-4000}}
+\def\chappager{\par\vfill\supereject}
+\def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi}
+
+\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname}
+
+\def\CHAPPAGoff{
+\global\let\contentsalignmacro = \chappager
+\global\let\pchapsepmacro=\chapbreak
+\global\let\pagealignmacro=\chappager}
+
+\def\CHAPPAGon{
+\global\let\contentsalignmacro = \chappager
+\global\let\pchapsepmacro=\chappager
+\global\let\pagealignmacro=\chappager
+\global\def\HEADINGSon{\HEADINGSsingle}}
+
+\def\CHAPPAGodd{
+\global\let\contentsalignmacro = \chapoddpage
+\global\let\pchapsepmacro=\chapoddpage
+\global\let\pagealignmacro=\chapoddpage
+\global\def\HEADINGSon{\HEADINGSdouble}}
+
+\CHAPPAGon
+
+\def\CHAPFplain{
+\global\let\chapmacro=\chfplain
+\global\let\unnumbchapmacro=\unnchfplain
+\global\let\centerchapmacro=\centerchfplain}
+
+% Plain chapter opening.
+% #1 is the text, #2 the chapter number or empty if unnumbered.
+\def\chfplain#1#2{%
+ \pchapsepmacro
+ {%
+ \chapfonts \rm
+ \def\chapnum{#2}%
+ \setbox0 = \hbox{#2\ifx\chapnum\empty\else\enspace\fi}%
+ \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright
+ \hangindent = \wd0 \centerparametersmaybe
+ \unhbox0 #1\par}%
+ }%
+ \nobreak\bigskip % no page break after a chapter title
+ \nobreak
+}
+
+% Plain opening for unnumbered.
+\def\unnchfplain#1{\chfplain{#1}{}}
+
+% @centerchap -- centered and unnumbered.
+\let\centerparametersmaybe = \relax
+\def\centerchfplain#1{{%
+ \def\centerparametersmaybe{%
+ \advance\rightskip by 3\rightskip
+ \leftskip = \rightskip
+ \parfillskip = 0pt
+ }%
+ \chfplain{#1}{}%
+}}
+
+\CHAPFplain % The default
+
+\def\unnchfopen #1{%
+\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\penalty 10000 %
+}
+
+\def\chfopen #1#2{\chapoddpage {\chapfonts
+\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}%
+\par\penalty 5000 %
+}
+
+\def\centerchfopen #1{%
+\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt
+ \hfill {\rm #1}\hfill}}\bigskip \par\penalty 10000 %
+}
+
+\def\CHAPFopen{
+\global\let\chapmacro=\chfopen
+\global\let\unnumbchapmacro=\unnchfopen
+\global\let\centerchapmacro=\centerchfopen}
+
+
+% Section titles.
+\newskip\secheadingskip
+\def\secheadingbreak{\dobreak \secheadingskip {-1000}}
+\def\secheading#1#2#3{\sectionheading{sec}{#2.#3}{#1}}
+\def\plainsecheading#1{\sectionheading{sec}{}{#1}}
+
+% Subsection titles.
+\newskip \subsecheadingskip
+\def\subsecheadingbreak{\dobreak \subsecheadingskip {-500}}
+\def\subsecheading#1#2#3#4{\sectionheading{subsec}{#2.#3.#4}{#1}}
+\def\plainsubsecheading#1{\sectionheading{subsec}{}{#1}}
+
+% Subsubsection titles.
+\let\subsubsecheadingskip = \subsecheadingskip
+\let\subsubsecheadingbreak = \subsecheadingbreak
+\def\subsubsecheading#1#2#3#4#5{\sectionheading{subsubsec}{#2.#3.#4.#5}{#1}}
+\def\plainsubsubsecheading#1{\sectionheading{subsubsec}{}{#1}}
+
+
+% Print any size section title.
+%
+% #1 is the section type (sec/subsec/subsubsec), #2 is the section
+% number (maybe empty), #3 the text.
+\def\sectionheading#1#2#3{%
+ {%
+ \expandafter\advance\csname #1headingskip\endcsname by \parskip
+ \csname #1headingbreak\endcsname
+ }%
+ {%
+ % Switch to the right set of fonts.
+ \csname #1fonts\endcsname \rm
+ %
+ % Only insert the separating space if we have a section number.
+ \def\secnum{#2}%
+ \setbox0 = \hbox{#2\ifx\secnum\empty\else\enspace\fi}%
+ %
+ \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright
+ \hangindent = \wd0 % zero if no section number
+ \unhbox0 #3}%
+ }%
+ \ifdim\parskip<10pt \nobreak\kern10pt\nobreak\kern-\parskip\fi \nobreak
+}
+
+
+\message{toc printing,}
+% Finish up the main text and prepare to read what we've written
+% to \contentsfile.
+
+\newskip\contentsrightmargin \contentsrightmargin=1in
+\def\startcontents#1{%
+ % If @setchapternewpage on, and @headings double, the contents should
+ % start on an odd page, unlike chapters. Thus, we maintain
+ % \contentsalignmacro in parallel with \pagealignmacro.
+ % From: Torbjorn Granlund <tege@matematik.su.se>
+ \contentsalignmacro
+ \immediate\closeout \contentsfile
+ \ifnum \pageno>0
+ \pageno = -1 % Request roman numbered pages.
+ \fi
+ % Don't need to put `Contents' or `Short Contents' in the headline.
+ % It is abundantly clear what they are.
+ \unnumbchapmacro{#1}\def\thischapter{}%
+ \begingroup % Set up to handle contents files properly.
+ \catcode`\\=0 \catcode`\{=1 \catcode`\}=2 \catcode`\@=11
+ \catcode`\^=7 % to see ^^e4 as \"a etc. juha@piuha.ydi.vtt.fi
+ \raggedbottom % Worry more about breakpoints than the bottom.
+ \advance\hsize by -\contentsrightmargin % Don't use the full line length.
+}
+
+
+% Normal (long) toc.
+\outer\def\contents{%
+ \startcontents{\putwordTableofContents}%
+ \input \jobname.toc
+ \endgroup
+ \vfill \eject
+}
+
+% And just the chapters.
+\outer\def\summarycontents{%
+ \startcontents{\putwordShortContents}%
+ %
+ \let\chapentry = \shortchapentry
+ \let\unnumbchapentry = \shortunnumberedentry
+ % We want a true roman here for the page numbers.
+ \secfonts
+ \let\rm=\shortcontrm \let\bf=\shortcontbf \let\sl=\shortcontsl
+ \rm
+ \hyphenpenalty = 10000
+ \advance\baselineskip by 1pt % Open it up a little.
+ \def\secentry ##1##2##3##4{}
+ \def\unnumbsecentry ##1##2{}
+ \def\subsecentry ##1##2##3##4##5{}
+ \def\unnumbsubsecentry ##1##2{}
+ \def\subsubsecentry ##1##2##3##4##5##6{}
+ \def\unnumbsubsubsecentry ##1##2{}
+ \input \jobname.toc
+ \endgroup
+ \vfill \eject
+}
+\let\shortcontents = \summarycontents
+
+% These macros generate individual entries in the table of contents.
+% The first argument is the chapter or section name.
+% The last argument is the page number.
+% The arguments in between are the chapter number, section number, ...
+
+% Chapter-level things, for both the long and short contents.
+\def\chapentry#1#2#3{\dochapentry{#2\labelspace#1}{#3}}
+
+% See comments in \dochapentry re vbox and related settings
+\def\shortchapentry#1#2#3{%
+ \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno{#3}}%
+}
+
+% Typeset the label for a chapter or appendix for the short contents.
+% The arg is, e.g. `Appendix A' for an appendix, or `3' for a chapter.
+% We could simplify the code here by writing out an \appendixentry
+% command in the toc file for appendices, instead of using \chapentry
+% for both, but it doesn't seem worth it.
+\setbox0 = \hbox{\shortcontrm \putwordAppendix }
+\newdimen\shortappendixwidth \shortappendixwidth = \wd0
+
+\def\shortchaplabel#1{%
+ % We typeset #1 in a box of constant width, regardless of the text of
+ % #1, so the chapter titles will come out aligned.
+ \setbox0 = \hbox{#1}%
+ \dimen0 = \ifdim\wd0 > \shortappendixwidth \shortappendixwidth \else 0pt \fi
+ %
+ % This space should be plenty, since a single number is .5em, and the
+ % widest letter (M) is 1em, at least in the Computer Modern fonts.
+ % (This space doesn't include the extra space that gets added after
+ % the label; that gets put in by \shortchapentry above.)
+ \advance\dimen0 by 1.1em
+ \hbox to \dimen0{#1\hfil}%
+}
+
+\def\unnumbchapentry#1#2{\dochapentry{#1}{#2}}
+\def\shortunnumberedentry#1#2{\tocentry{#1}{\doshortpageno{#2}}}
+
+% Sections.
+\def\secentry#1#2#3#4{\dosecentry{#2.#3\labelspace#1}{#4}}
+\def\unnumbsecentry#1#2{\dosecentry{#1}{#2}}
+
+% Subsections.
+\def\subsecentry#1#2#3#4#5{\dosubsecentry{#2.#3.#4\labelspace#1}{#5}}
+\def\unnumbsubsecentry#1#2{\dosubsecentry{#1}{#2}}
+
+% And subsubsections.
+\def\subsubsecentry#1#2#3#4#5#6{%
+ \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}{#6}}
+\def\unnumbsubsubsecentry#1#2{\dosubsubsecentry{#1}{#2}}
+
+% This parameter controls the indentation of the various levels.
+\newdimen\tocindent \tocindent = 3pc
+
+% Now for the actual typesetting. In all these, #1 is the text and #2 is the
+% page number.
+%
+% If the toc has to be broken over pages, we want it to be at chapters
+% if at all possible; hence the \penalty.
+\def\dochapentry#1#2{%
+ \penalty-300 \vskip1\baselineskip plus.33\baselineskip minus.25\baselineskip
+ \begingroup
+ \chapentryfonts
+ \tocentry{#1}{\dopageno{#2}}%
+ \endgroup
+ \nobreak\vskip .25\baselineskip plus.1\baselineskip
+}
+
+\def\dosecentry#1#2{\begingroup
+ \secentryfonts \leftskip=\tocindent
+ \tocentry{#1}{\dopageno{#2}}%
+\endgroup}
+
+\def\dosubsecentry#1#2{\begingroup
+ \subsecentryfonts \leftskip=2\tocindent
+ \tocentry{#1}{\dopageno{#2}}%
+\endgroup}
+
+\def\dosubsubsecentry#1#2{\begingroup
+ \subsubsecentryfonts \leftskip=3\tocindent
+ \tocentry{#1}{\dopageno{#2}}%
+\endgroup}
+
+% Final typesetting of a toc entry; we use the same \entry macro as for
+% the index entries, but we want to suppress hyphenation here. (We
+% can't do that in the \entry macro, since index entries might consist
+% of hyphenated-identifiers-that-do-not-fit-on-a-line-and-nothing-else.)
+%
+% \turnoffactive is for the sake of @" used for umlauts.
+\def\tocentry#1#2{\begingroup
+ \vskip 0pt plus1pt % allow a little stretch for the sake of nice page breaks
+ \entry{\turnoffactive #1}{\turnoffactive #2}%
+\endgroup}
+
+% Space between chapter (or whatever) number and the title.
+\def\labelspace{\hskip1em \relax}
+
+\def\dopageno#1{{\rm #1}}
+\def\doshortpageno#1{{\rm #1}}
+
+\def\chapentryfonts{\secfonts \rm}
+\def\secentryfonts{\textfonts}
+\let\subsecentryfonts = \textfonts
+\let\subsubsecentryfonts = \textfonts
+
+
+\message{environments,}
+
+% Since these characters are used in examples, it should be an even number of
+% \tt widths. Each \tt character is 1en, so two makes it 1em.
+% Furthermore, these definitions must come after we define our fonts.
+\newbox\dblarrowbox \newbox\longdblarrowbox
+\newbox\pushcharbox \newbox\bullbox
+\newbox\equivbox \newbox\errorbox
+
+%{\tentt
+%\global\setbox\dblarrowbox = \hbox to 1em{\hfil$\Rightarrow$\hfil}
+%\global\setbox\longdblarrowbox = \hbox to 1em{\hfil$\mapsto$\hfil}
+%\global\setbox\pushcharbox = \hbox to 1em{\hfil$\dashv$\hfil}
+%\global\setbox\equivbox = \hbox to 1em{\hfil$\ptexequiv$\hfil}
+% Adapted from the manmac format (p.420 of TeXbook)
+%\global\setbox\bullbox = \hbox to 1em{\kern.15em\vrule height .75ex width .85ex
+% depth .1ex\hfil}
+%}
+
+% @point{}, @result{}, @expansion{}, @print{}, @equiv{}.
+\def\point{$\star$}
+\def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}}
+\def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}}
+\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}}
+\def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}}
+
+% Adapted from the TeXbook's \boxit.
+{\tentt \global\dimen0 = 3em}% Width of the box.
+\dimen2 = .55pt % Thickness of rules
+% The text. (`r' is open on the right, `e' somewhat less so on the left.)
+\setbox0 = \hbox{\kern-.75pt \tensf error\kern-1.5pt}
+
+\global\setbox\errorbox=\hbox to \dimen0{\hfil
+ \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right.
+ \advance\hsize by -2\dimen2 % Rules.
+ \vbox{
+ \hrule height\dimen2
+ \hbox{\vrule width\dimen2 \kern3pt % Space to left of text.
+ \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below.
+ \kern3pt\vrule width\dimen2}% Space to right.
+ \hrule height\dimen2}
+ \hfil}
+
+% The @error{} command.
+\def\error{\leavevmode\lower.7ex\copy\errorbox}
+
+% @tex ... @end tex escapes into raw Tex temporarily.
+% One exception: @ is still an escape character, so that @end tex works.
+% But \@ or @@ will get a plain tex @ character.
+
+\def\tex{\begingroup
+\catcode `\\=0 \catcode `\{=1 \catcode `\}=2
+\catcode `\$=3 \catcode `\&=4 \catcode `\#=6
+\catcode `\^=7 \catcode `\_=8 \catcode `\~=13 \let~=\tie
+\catcode `\%=14
+\catcode 43=12 % plus
+\catcode`\"=12
+\catcode`\==12
+\catcode`\|=12
+\catcode`\<=12
+\catcode`\>=12
+\escapechar=`\\
+%
+\let\,=\ptexcomma
+\let\~=\ptextilde
+\let\{=\ptexlbrace
+\let\}=\ptexrbrace
+\let\.=\ptexdot
+\let\*=\ptexstar
+\let\dots=\ptexdots
+\def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}
+\def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi}
+\def\@{@}%
+\let\bullet=\ptexbullet
+\let\b=\ptexb \let\c=\ptexc \let\i=\ptexi \let\t=\ptext
+%
+\let\Etex=\endgroup}
+
+% Define @lisp ... @endlisp.
+% @lisp does a \begingroup so it can rebind things,
+% including the definition of @endlisp (which normally is erroneous).
+
+% Amount to narrow the margins by for @lisp.
+\newskip\lispnarrowing \lispnarrowing=0.4in
+
+% This is the definition that ^^M gets inside @lisp, @example, and other
+% such environments. \null is better than a space, since it doesn't
+% have any width.
+\def\lisppar{\null\endgraf}
+
+% Make each space character in the input produce a normal interword
+% space in the output. Don't allow a line break at this space, as this
+% is used only in environments like @example, where each line of input
+% should produce a line of output anyway.
+%
+{\obeyspaces %
+\gdef\sepspaces{\obeyspaces\let =\tie}}
+
+% Define \obeyedspace to be our active space, whatever it is. This is
+% for use in \parsearg.
+{\sepspaces%
+\global\let\obeyedspace= }
+
+% This space is always present above and below environments.
+\newskip\envskipamount \envskipamount = 0pt
+
+% Make spacing and below environment symmetrical. We use \parskip here
+% to help in doing that, since in @example-like environments \parskip
+% is reset to zero; thus the \afterenvbreak inserts no space -- but the
+% start of the next paragraph will insert \parskip
+%
+\def\aboveenvbreak{{\advance\envskipamount by \parskip
+\endgraf \ifdim\lastskip<\envskipamount
+\removelastskip \penalty-50 \vskip\envskipamount \fi}}
+
+\let\afterenvbreak = \aboveenvbreak
+
+% \nonarrowing is a flag. If "set", @lisp etc don't narrow margins.
+\let\nonarrowing=\relax
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \cartouche: draw rectangle w/rounded corners around argument
+\font\circle=lcircle10
+\newdimen\circthick
+\newdimen\cartouter\newdimen\cartinner
+\newskip\normbskip\newskip\normpskip\newskip\normlskip
+\circthick=\fontdimen8\circle
+%
+\def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth
+\def\ctr{{\hskip 6pt\circle\char'010}}
+\def\cbl{{\circle\char'012\hskip -6pt}}
+\def\cbr{{\hskip 6pt\circle\char'011}}
+\def\carttop{\hbox to \cartouter{\hskip\lskip
+ \ctl\leaders\hrule height\circthick\hfil\ctr
+ \hskip\rskip}}
+\def\cartbot{\hbox to \cartouter{\hskip\lskip
+ \cbl\leaders\hrule height\circthick\hfil\cbr
+ \hskip\rskip}}
+%
+\newskip\lskip\newskip\rskip
+
+\long\def\cartouche{%
+\begingroup
+ \lskip=\leftskip \rskip=\rightskip
+ \leftskip=0pt\rightskip=0pt %we want these *outside*.
+ \cartinner=\hsize \advance\cartinner by-\lskip
+ \advance\cartinner by-\rskip
+ \cartouter=\hsize
+ \advance\cartouter by 18pt % allow for 3pt kerns on either
+% side, and for 6pt waste from
+% each corner char
+ \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip
+ % Flag to tell @lisp, etc., not to narrow margin.
+ \let\nonarrowing=\comment
+ \vbox\bgroup
+ \baselineskip=0pt\parskip=0pt\lineskip=0pt
+ \carttop
+ \hbox\bgroup
+ \hskip\lskip
+ \vrule\kern3pt
+ \vbox\bgroup
+ \hsize=\cartinner
+ \kern3pt
+ \begingroup
+ \baselineskip=\normbskip
+ \lineskip=\normlskip
+ \parskip=\normpskip
+ \vskip -\parskip
+\def\Ecartouche{%
+ \endgroup
+ \kern3pt
+ \egroup
+ \kern3pt\vrule
+ \hskip\rskip
+ \egroup
+ \cartbot
+ \egroup
+\endgroup
+}}
+
+
+% This macro is called at the beginning of all the @example variants,
+% inside a group.
+\def\nonfillstart{%
+ \aboveenvbreak
+ \inENV % This group ends at the end of the body
+ \hfuzz = 12pt % Don't be fussy
+ \sepspaces % Make spaces be word-separators rather than space tokens.
+ \singlespace
+ \let\par = \lisppar % don't ignore blank lines
+ \obeylines % each line of input is a line of output
+ \parskip = 0pt
+ \parindent = 0pt
+ \emergencystretch = 0pt % don't try to avoid overfull boxes
+ % @cartouche defines \nonarrowing to inhibit narrowing
+ % at next level down.
+ \ifx\nonarrowing\relax
+ \advance \leftskip by \lispnarrowing
+ \exdentamount=\lispnarrowing
+ \let\exdent=\nofillexdent
+ \let\nonarrowing=\relax
+ \fi
+}
+
+% To ending an @example-like environment, we first end the paragraph
+% (via \afterenvbreak's vertical glue), and then the group. That way we
+% keep the zero \parskip that the environments set -- \parskip glue
+% will be inserted at the beginning of the next paragraph in the
+% document, after the environment.
+%
+\def\nonfillfinish{\afterenvbreak\endgroup}%
+
+% This macro is
+\def\lisp{\begingroup
+ \nonfillstart
+ \let\Elisp = \nonfillfinish
+ \tt
+ \rawbackslash % have \ input char produce \ char from current font
+ \gobble
+}
+
+% Define the \E... control sequence only if we are inside the
+% environment, so the error checking in \end will work.
+%
+% We must call \lisp last in the definition, since it reads the
+% return following the @example (or whatever) command.
+%
+\def\example{\begingroup \def\Eexample{\nonfillfinish\endgroup}\lisp}
+\def\smallexample{\begingroup \def\Esmallexample{\nonfillfinish\endgroup}\lisp}
+\def\smalllisp{\begingroup \def\Esmalllisp{\nonfillfinish\endgroup}\lisp}
+
+% @smallexample and @smalllisp. This is not used unless the @smallbook
+% command is given. Originally contributed by Pavel@xerox.
+%
+\def\smalllispx{\begingroup
+ \nonfillstart
+ \let\Esmalllisp = \nonfillfinish
+ \let\Esmallexample = \nonfillfinish
+ %
+ % Smaller fonts for small examples.
+ \indexfonts \tt
+ \rawbackslash % make \ output the \ character from the current font (tt)
+ \gobble
+}
+
+% This is @display; same as @lisp except use roman font.
+%
+\def\display{\begingroup
+ \nonfillstart
+ \let\Edisplay = \nonfillfinish
+ \gobble
+}
+
+% This is @format; same as @display except don't narrow margins.
+%
+\def\format{\begingroup
+ \let\nonarrowing = t
+ \nonfillstart
+ \let\Eformat = \nonfillfinish
+ \gobble
+}
+
+% @flushleft (same as @format) and @flushright.
+%
+\def\flushleft{\begingroup
+ \let\nonarrowing = t
+ \nonfillstart
+ \let\Eflushleft = \nonfillfinish
+ \gobble
+}
+\def\flushright{\begingroup
+ \let\nonarrowing = t
+ \nonfillstart
+ \let\Eflushright = \nonfillfinish
+ \advance\leftskip by 0pt plus 1fill
+ \gobble}
+
+% @quotation does normal linebreaking (hence we can't use \nonfillstart)
+% and narrows the margins.
+%
+\def\quotation{%
+ \begingroup\inENV %This group ends at the end of the @quotation body
+ {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip
+ \singlespace
+ \parindent=0pt
+ % We have retained a nonzero parskip for the environment, since we're
+ % doing normal filling. So to avoid extra space below the environment...
+ \def\Equotation{\parskip = 0pt \nonfillfinish}%
+ %
+ % @cartouche defines \nonarrowing to inhibit narrowing at next level down.
+ \ifx\nonarrowing\relax
+ \advance\leftskip by \lispnarrowing
+ \advance\rightskip by \lispnarrowing
+ \exdentamount = \lispnarrowing
+ \let\nonarrowing = \relax
+ \fi
+}
+
+\message{defuns,}
+% Define formatter for defuns
+% First, allow user to change definition object font (\df) internally
+\def\setdeffont #1 {\csname DEF#1\endcsname}
+
+\newskip\defbodyindent \defbodyindent=.4in
+\newskip\defargsindent \defargsindent=50pt
+\newskip\deftypemargin \deftypemargin=12pt
+\newskip\deflastargmargin \deflastargmargin=18pt
+
+\newcount\parencount
+% define \functionparens, which makes ( and ) and & do special things.
+% \functionparens affects the group it is contained in.
+\def\activeparens{%
+\catcode`\(=\active \catcode`\)=\active \catcode`\&=\active
+\catcode`\[=\active \catcode`\]=\active}
+
+% Make control sequences which act like normal parenthesis chars.
+\let\lparen = ( \let\rparen = )
+
+{\activeparens % Now, smart parens don't turn on until &foo (see \amprm)
+
+% Be sure that we always have a definition for `(', etc. For example,
+% if the fn name has parens in it, \boldbrax will not be in effect yet,
+% so TeX would otherwise complain about undefined control sequence.
+\global\let(=\lparen \global\let)=\rparen
+\global\let[=\lbrack \global\let]=\rbrack
+
+\gdef\functionparens{\boldbrax\let&=\amprm\parencount=0 }
+\gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb}
+% This is used to turn on special parens
+% but make & act ordinary (given that it's active).
+\gdef\boldbraxnoamp{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb\let&=\ampnr}
+
+% Definitions of (, ) and & used in args for functions.
+% This is the definition of ( outside of all parentheses.
+\gdef\oprm#1 {{\rm\char`\(}#1 \bf \let(=\opnested %
+\global\advance\parencount by 1 }
+%
+% This is the definition of ( when already inside a level of parens.
+\gdef\opnested{\char`\(\global\advance\parencount by 1 }
+%
+\gdef\clrm{% Print a paren in roman if it is taking us back to depth of 0.
+% also in that case restore the outer-level definition of (.
+\ifnum \parencount=1 {\rm \char `\)}\sl \let(=\oprm \else \char `\) \fi
+\global\advance \parencount by -1 }
+% If we encounter &foo, then turn on ()-hacking afterwards
+\gdef\amprm#1 {{\rm\&#1}\let(=\oprm \let)=\clrm\ }
+%
+\gdef\normalparens{\boldbrax\let&=\ampnr}
+} % End of definition inside \activeparens
+%% These parens (in \boldbrax) actually are a little bolder than the
+%% contained text. This is especially needed for [ and ]
+\def\opnr{{\sf\char`\(}} \def\clnr{{\sf\char`\)}} \def\ampnr{\&}
+\def\lbrb{{\bf\char`\[}} \def\rbrb{{\bf\char`\]}}
+
+% First, defname, which formats the header line itself.
+% #1 should be the function name.
+% #2 should be the type of definition, such as "Function".
+
+\def\defname #1#2{%
+% Get the values of \leftskip and \rightskip as they were
+% outside the @def...
+\dimen2=\leftskip
+\advance\dimen2 by -\defbodyindent
+\dimen3=\rightskip
+\advance\dimen3 by -\defbodyindent
+\noindent %
+\setbox0=\hbox{\hskip \deflastargmargin{\rm #2}\hskip \deftypemargin}%
+\dimen0=\hsize \advance \dimen0 by -\wd0 % compute size for first line
+\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuations
+\parshape 2 0in \dimen0 \defargsindent \dimen1 %
+% Now output arg 2 ("Function" or some such)
+% ending at \deftypemargin from the right margin,
+% but stuck inside a box of width 0 so it does not interfere with linebreaking
+{% Adjust \hsize to exclude the ambient margins,
+% so that \rightline will obey them.
+\advance \hsize by -\dimen2 \advance \hsize by -\dimen3
+\rlap{\rightline{{\rm #2}\hskip \deftypemargin}}}%
+% Make all lines underfull and no complaints:
+\tolerance=10000 \hbadness=10000
+\advance\leftskip by -\defbodyindent
+\exdentamount=\defbodyindent
+{\df #1}\enskip % Generate function name
+}
+
+% Actually process the body of a definition
+% #1 should be the terminating control sequence, such as \Edefun.
+% #2 should be the "another name" control sequence, such as \defunx.
+% #3 should be the control sequence that actually processes the header,
+% such as \defunheader.
+
+\def\defparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2{\begingroup\obeylines\activeparens\spacesplit#3}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup %
+\catcode 61=\active % 61 is `='
+\obeylines\activeparens\spacesplit#3}
+
+\def\defmethparsebody #1#2#3#4 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\activeparens\spacesplit{#3{#4}}}
+
+\def\defopparsebody #1#2#3#4#5 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 ##2 {\def#4{##1}%
+\begingroup\obeylines\activeparens\spacesplit{#3{##2}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\activeparens\spacesplit{#3{#5}}}
+
+% These parsing functions are similar to the preceding ones
+% except that they do not make parens into active characters.
+% These are used for "variables" since they have no arguments.
+
+\def\defvarparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2{\begingroup\obeylines\spacesplit#3}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup %
+\catcode 61=\active %
+\obeylines\spacesplit#3}
+
+% This is used for \def{tp,vr}parsebody. It could probably be used for
+% some of the others, too, with some judicious conditionals.
+%
+\def\parsebodycommon#1#2#3{%
+ \begingroup\inENV %
+ \medbreak %
+ % Define the end token that this defining construct specifies
+ % so that it will exit this group.
+ \def#1{\endgraf\endgroup\medbreak}%
+ \def#2##1 {\begingroup\obeylines\spacesplit{#3{##1}}}%
+ \parindent=0in
+ \advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+ \exdentamount=\defbodyindent
+ \begingroup\obeylines
+}
+
+\def\defvrparsebody#1#2#3#4 {%
+ \parsebodycommon{#1}{#2}{#3}%
+ \spacesplit{#3{#4}}%
+}
+
+% This loses on `@deftp {Data Type} {struct termios}' -- it thinks the
+% type is just `struct', because we lose the braces in `{struct
+% termios}' when \spacesplit reads its undelimited argument. Sigh.
+% \let\deftpparsebody=\defvrparsebody
+%
+% So, to get around this, we put \empty in with the type name. That
+% way, TeX won't find exactly `{...}' as an undelimited argument, and
+% won't strip off the braces.
+%
+\def\deftpparsebody #1#2#3#4 {%
+ \parsebodycommon{#1}{#2}{#3}%
+ \spacesplit{\parsetpheaderline{#3{#4}}}\empty
+}
+
+% Fine, but then we have to eventually remove the \empty *and* the
+% braces (if any). That's what this does, putting the result in \tptemp.
+%
+\def\removeemptybraces\empty#1\relax{\def\tptemp{#1}}%
+
+% After \spacesplit has done its work, this is called -- #1 is the final
+% thing to call, #2 the type name (which starts with \empty), and #3
+% (which might be empty) the arguments.
+%
+\def\parsetpheaderline#1#2#3{%
+ \removeemptybraces#2\relax
+ #1{\tptemp}{#3}%
+}%
+
+\def\defopvarparsebody #1#2#3#4#5 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 ##2 {\def#4{##1}%
+\begingroup\obeylines\spacesplit{#3{##2}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\spacesplit{#3{#5}}}
+
+% Split up #2 at the first space token.
+% call #1 with two arguments:
+% the first is all of #2 before the space token,
+% the second is all of #2 after that space token.
+% If #2 contains no space token, all of it is passed as the first arg
+% and the second is passed as empty.
+
+{\obeylines
+\gdef\spacesplit#1#2^^M{\endgroup\spacesplitfoo{#1}#2 \relax\spacesplitfoo}%
+\long\gdef\spacesplitfoo#1#2 #3#4\spacesplitfoo{%
+\ifx\relax #3%
+#1{#2}{}\else #1{#2}{#3#4}\fi}}
+
+% So much for the things common to all kinds of definitions.
+
+% Define @defun.
+
+% First, define the processing that is wanted for arguments of \defun
+% Use this to expand the args and terminate the paragraph they make up
+
+\def\defunargs #1{\functionparens \sl
+% Expand, preventing hyphenation at `-' chars.
+% Note that groups don't affect changes in \hyphenchar.
+\hyphenchar\tensl=0
+#1%
+\hyphenchar\tensl=45
+\ifnum\parencount=0 \else \errmessage{unbalanced parens in @def arguments}\fi%
+\interlinepenalty=10000
+\advance\rightskip by 0pt plus 1fil
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000%
+}
+
+\def\deftypefunargs #1{%
+% Expand, preventing hyphenation at `-' chars.
+% Note that groups don't affect changes in \hyphenchar.
+% Use \boldbraxnoamp, not \functionparens, so that & is not special.
+\boldbraxnoamp
+\tclose{#1}% avoid \code because of side effects on active chars
+\interlinepenalty=10000
+\advance\rightskip by 0pt plus 1fil
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000%
+}
+
+% Do complete processing of one @defun or @defunx line already parsed.
+
+% @deffn Command forward-char nchars
+
+\def\deffn{\defmethparsebody\Edeffn\deffnx\deffnheader}
+
+\def\deffnheader #1#2#3{\doind {fn}{\code{#2}}%
+\begingroup\defname {#2}{#1}\defunargs{#3}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defun == @deffn Function
+
+\def\defun{\defparsebody\Edefun\defunx\defunheader}
+
+\def\defunheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Function}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @deftypefun int foobar (int @var{foo}, float @var{bar})
+
+\def\deftypefun{\defparsebody\Edeftypefun\deftypefunx\deftypefunheader}
+
+% #1 is the data type. #2 is the name and args.
+\def\deftypefunheader #1#2{\deftypefunheaderx{#1}#2 \relax}
+% #1 is the data type, #2 the name, #3 the args.
+\def\deftypefunheaderx #1#2 #3\relax{%
+\doind {fn}{\code{#2}}% Make entry in function index
+\begingroup\defname {\defheaderxcond#1\relax$$$#2}{Function}%
+\deftypefunargs {#3}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @deftypefn {Library Function} int foobar (int @var{foo}, float @var{bar})
+
+\def\deftypefn{\defmethparsebody\Edeftypefn\deftypefnx\deftypefnheader}
+
+% \defheaderxcond#1\relax$$$
+% puts #1 in @code, followed by a space, but does nothing if #1 is null.
+\def\defheaderxcond#1#2$$${\ifx#1\relax\else\code{#1#2} \fi}
+
+% #1 is the classification. #2 is the data type. #3 is the name and args.
+\def\deftypefnheader #1#2#3{\deftypefnheaderx{#1}{#2}#3 \relax}
+% #1 is the classification, #2 the data type, #3 the name, #4 the args.
+\def\deftypefnheaderx #1#2#3 #4\relax{%
+\doind {fn}{\code{#3}}% Make entry in function index
+\begingroup
+\normalparens % notably, turn off `&' magic, which prevents
+% at least some C++ text from working
+\defname {\defheaderxcond#2\relax$$$#3}{#1}%
+\deftypefunargs {#4}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defmac == @deffn Macro
+
+\def\defmac{\defparsebody\Edefmac\defmacx\defmacheader}
+
+\def\defmacheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Macro}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defspec == @deffn Special Form
+
+\def\defspec{\defparsebody\Edefspec\defspecx\defspecheader}
+
+\def\defspecheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Special Form}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% This definition is run if you use @defunx
+% anywhere other than immediately after a @defun or @defunx.
+
+\def\deffnx #1 {\errmessage{@deffnx in invalid context}}
+\def\defunx #1 {\errmessage{@defunx in invalid context}}
+\def\defmacx #1 {\errmessage{@defmacx in invalid context}}
+\def\defspecx #1 {\errmessage{@defspecx in invalid context}}
+\def\deftypefnx #1 {\errmessage{@deftypefnx in invalid context}}
+\def\deftypeunx #1 {\errmessage{@deftypeunx in invalid context}}
+
+% @defmethod, and so on
+
+% @defop {Funny Method} foo-class frobnicate argument
+
+\def\defop #1 {\def\defoptype{#1}%
+\defopparsebody\Edefop\defopx\defopheader\defoptype}
+
+\def\defopheader #1#2#3{%
+\dosubind {fn}{\code{#2}}{on #1}% Make entry in function index
+\begingroup\defname {#2}{\defoptype{} on #1}%
+\defunargs {#3}\endgroup %
+}
+
+% @defmethod == @defop Method
+
+\def\defmethod{\defmethparsebody\Edefmethod\defmethodx\defmethodheader}
+
+\def\defmethodheader #1#2#3{%
+\dosubind {fn}{\code{#2}}{on #1}% entry in function index
+\begingroup\defname {#2}{Method on #1}%
+\defunargs {#3}\endgroup %
+}
+
+% @defcv {Class Option} foo-class foo-flag
+
+\def\defcv #1 {\def\defcvtype{#1}%
+\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype}
+
+\def\defcvarheader #1#2#3{%
+\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index
+\begingroup\defname {#2}{\defcvtype{} of #1}%
+\defvarargs {#3}\endgroup %
+}
+
+% @defivar == @defcv {Instance Variable}
+
+\def\defivar{\defvrparsebody\Edefivar\defivarx\defivarheader}
+
+\def\defivarheader #1#2#3{%
+\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index
+\begingroup\defname {#2}{Instance Variable of #1}%
+\defvarargs {#3}\endgroup %
+}
+
+% These definitions are run if you use @defmethodx, etc.,
+% anywhere other than immediately after a @defmethod, etc.
+
+\def\defopx #1 {\errmessage{@defopx in invalid context}}
+\def\defmethodx #1 {\errmessage{@defmethodx in invalid context}}
+\def\defcvx #1 {\errmessage{@defcvx in invalid context}}
+\def\defivarx #1 {\errmessage{@defivarx in invalid context}}
+
+% Now @defvar
+
+% First, define the processing that is wanted for arguments of @defvar.
+% This is actually simple: just print them in roman.
+% This must expand the args and terminate the paragraph they make up
+\def\defvarargs #1{\normalparens #1%
+\interlinepenalty=10000
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000}
+
+% @defvr Counter foo-count
+
+\def\defvr{\defvrparsebody\Edefvr\defvrx\defvrheader}
+
+\def\defvrheader #1#2#3{\doind {vr}{\code{#2}}%
+\begingroup\defname {#2}{#1}\defvarargs{#3}\endgroup}
+
+% @defvar == @defvr Variable
+
+\def\defvar{\defvarparsebody\Edefvar\defvarx\defvarheader}
+
+\def\defvarheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
+\begingroup\defname {#1}{Variable}%
+\defvarargs {#2}\endgroup %
+}
+
+% @defopt == @defvr {User Option}
+
+\def\defopt{\defvarparsebody\Edefopt\defoptx\defoptheader}
+
+\def\defoptheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
+\begingroup\defname {#1}{User Option}%
+\defvarargs {#2}\endgroup %
+}
+
+% @deftypevar int foobar
+
+\def\deftypevar{\defvarparsebody\Edeftypevar\deftypevarx\deftypevarheader}
+
+% #1 is the data type. #2 is the name.
+\def\deftypevarheader #1#2{%
+\doind {vr}{\code{#2}}% Make entry in variables index
+\begingroup\defname {\defheaderxcond#1\relax$$$#2}{Variable}%
+\interlinepenalty=10000
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000
+\endgroup}
+
+% @deftypevr {Global Flag} int enable
+
+\def\deftypevr{\defvrparsebody\Edeftypevr\deftypevrx\deftypevrheader}
+
+\def\deftypevrheader #1#2#3{\doind {vr}{\code{#3}}%
+\begingroup\defname {\defheaderxcond#2\relax$$$#3}{#1}
+\interlinepenalty=10000
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000
+\endgroup}
+
+% This definition is run if you use @defvarx
+% anywhere other than immediately after a @defvar or @defvarx.
+
+\def\defvrx #1 {\errmessage{@defvrx in invalid context}}
+\def\defvarx #1 {\errmessage{@defvarx in invalid context}}
+\def\defoptx #1 {\errmessage{@defoptx in invalid context}}
+\def\deftypevarx #1 {\errmessage{@deftypevarx in invalid context}}
+\def\deftypevrx #1 {\errmessage{@deftypevrx in invalid context}}
+
+% Now define @deftp
+% Args are printed in bold, a slight difference from @defvar.
+
+\def\deftpargs #1{\bf \defvarargs{#1}}
+
+% @deftp Class window height width ...
+
+\def\deftp{\deftpparsebody\Edeftp\deftpx\deftpheader}
+
+\def\deftpheader #1#2#3{\doind {tp}{\code{#2}}%
+\begingroup\defname {#2}{#1}\deftpargs{#3}\endgroup}
+
+% This definition is run if you use @deftpx, etc
+% anywhere other than immediately after a @deftp, etc.
+
+\def\deftpx #1 {\errmessage{@deftpx in invalid context}}
+
+
+\message{cross reference,}
+% Define cross-reference macros
+\newwrite \auxfile
+
+\newif\ifhavexrefs % True if xref values are known.
+\newif\ifwarnedxrefs % True if we warned once that they aren't known.
+
+% @inforef is simple.
+\def\inforef #1{\inforefzzz #1,,,,**}
+\def\inforefzzz #1,#2,#3,#4**{\putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}},
+ node \samp{\ignorespaces#1{}}}
+
+% \setref{foo} defines a cross-reference point named foo.
+
+\def\setref#1{%
+\dosetq{#1-title}{Ytitle}%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Ysectionnumberandtype}}
+
+\def\unnumbsetref#1{%
+\dosetq{#1-title}{Ytitle}%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Ynothing}}
+
+\def\appendixsetref#1{%
+\dosetq{#1-title}{Ytitle}%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Yappendixletterandtype}}
+
+% \xref, \pxref, and \ref generate cross-references to specified points.
+% For \xrefX, #1 is the node name, #2 the name of the Info
+% cross-reference, #3 the printed node name, #4 the name of the Info
+% file, #5 the name of the printed manual. All but the node name can be
+% omitted.
+%
+\def\pxref#1{\putwordsee{} \xrefX[#1,,,,,,,]}
+\def\xref#1{\putwordSee{} \xrefX[#1,,,,,,,]}
+\def\ref#1{\xrefX[#1,,,,,,,]}
+\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup
+ \def\printedmanual{\ignorespaces #5}%
+ \def\printednodename{\ignorespaces #3}%
+ \setbox1=\hbox{\printedmanual}%
+ \setbox0=\hbox{\printednodename}%
+ \ifdim \wd0 = 0pt
+ % No printed node name was explicitly given.
+ \expandafter\ifx\csname SETxref-automatic-section-title\endcsname\relax
+ % Use the node name inside the square brackets.
+ \def\printednodename{\ignorespaces #1}%
+ \else
+ % Use the actual chapter/section title appear inside
+ % the square brackets. Use the real section title if we have it.
+ \ifdim \wd1>0pt%
+ % It is in another manual, so we don't have it.
+ \def\printednodename{\ignorespaces #1}%
+ \else
+ \ifhavexrefs
+ % We know the real title if we have the xref values.
+ \def\printednodename{\refx{#1-title}{}}%
+ \else
+ % Otherwise just copy the Info node name.
+ \def\printednodename{\ignorespaces #1}%
+ \fi%
+ \fi
+ \fi
+ \fi
+ %
+ % If we use \unhbox0 and \unhbox1 to print the node names, TeX does not
+ % insert empty discretionaries after hyphens, which means that it will
+ % not find a line break at a hyphen in a node names. Since some manuals
+ % are best written with fairly long node names, containing hyphens, this
+ % is a loss. Therefore, we give the text of the node name again, so it
+ % is as if TeX is seeing it for the first time.
+ \ifdim \wd1 > 0pt
+ \putwordsection{} ``\printednodename'' in \cite{\printedmanual}%
+ \else
+ % _ (for example) has to be the character _ for the purposes of the
+ % control sequence corresponding to the node, but it has to expand
+ % into the usual \leavevmode...\vrule stuff for purposes of
+ % printing. So we \turnoffactive for the \refx-snt, back on for the
+ % printing, back off for the \refx-pg.
+ {\turnoffactive \refx{#1-snt}{}}%
+ \space [\printednodename],\space
+ \turnoffactive \putwordpage\tie\refx{#1-pg}{}%
+ \fi
+\endgroup}
+
+% \dosetq is the interface for calls from other macros
+
+% Use \turnoffactive so that punctuation chars such as underscore
+% work in node names.
+\def\dosetq #1#2{{\let\folio=0 \turnoffactive \auxhat%
+\edef\next{\write\auxfile{\internalsetq {#1}{#2}}}%
+\next}}
+
+% \internalsetq {foo}{page} expands into
+% CHARACTERS 'xrdef {foo}{...expansion of \Ypage...}
+% When the aux file is read, ' is the escape character
+
+\def\internalsetq #1#2{'xrdef {#1}{\csname #2\endcsname}}
+
+% Things to be expanded by \internalsetq
+
+\def\Ypagenumber{\folio}
+
+\def\Ytitle{\thissection}
+
+\def\Ynothing{}
+
+\def\Ysectionnumberandtype{%
+\ifnum\secno=0 \putwordChapter\xreftie\the\chapno %
+\else \ifnum \subsecno=0 \putwordSection\xreftie\the\chapno.\the\secno %
+\else \ifnum \subsubsecno=0 %
+\putwordSection\xreftie\the\chapno.\the\secno.\the\subsecno %
+\else %
+\putwordSection\xreftie\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno %
+\fi \fi \fi }
+
+\def\Yappendixletterandtype{%
+\ifnum\secno=0 \putwordAppendix\xreftie'char\the\appendixno{}%
+\else \ifnum \subsecno=0 \putwordSection\xreftie'char\the\appendixno.\the\secno %
+\else \ifnum \subsubsecno=0 %
+\putwordSection\xreftie'char\the\appendixno.\the\secno.\the\subsecno %
+\else %
+\putwordSection\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno %
+\fi \fi \fi }
+
+\gdef\xreftie{'tie}
+
+% Use TeX 3.0's \inputlineno to get the line number, for better error
+% messages, but if we're using an old version of TeX, don't do anything.
+%
+\ifx\inputlineno\thisisundefined
+ \let\linenumber = \empty % Non-3.0.
+\else
+ \def\linenumber{\the\inputlineno:\space}
+\fi
+
+% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME.
+% If its value is nonempty, SUFFIX is output afterward.
+
+\def\refx#1#2{%
+ \expandafter\ifx\csname X#1\endcsname\relax
+ % If not defined, say something at least.
+ $\langle$un\-de\-fined$\rangle$%
+ \ifhavexrefs
+ \message{\linenumber Undefined cross reference `#1'.}%
+ \else
+ \ifwarnedxrefs\else
+ \global\warnedxrefstrue
+ \message{Cross reference values unknown; you must run TeX again.}%
+ \fi
+ \fi
+ \else
+ % It's defined, so just use it.
+ \csname X#1\endcsname
+ \fi
+ #2% Output the suffix in any case.
+}
+
+% Read the last existing aux file, if any. No error if none exists.
+
+% This is the macro invoked by entries in the aux file.
+\def\xrdef #1#2{
+{\catcode`\'=\other\expandafter \gdef \csname X#1\endcsname {#2}}}
+
+\def\readauxfile{%
+\begingroup
+\catcode `\^^@=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\^^C=\other
+\catcode `\^^D=\other
+\catcode `\^^E=\other
+\catcode `\^^F=\other
+\catcode `\^^G=\other
+\catcode `\^^H=\other
+\catcode `\ =\other
+\catcode `\^^L=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode 26=\other
+\catcode `\^^[=\other
+\catcode `\^^\=\other
+\catcode `\^^]=\other
+\catcode `\^^^=\other
+\catcode `\^^_=\other
+\catcode `\@=\other
+\catcode `\^=\other
+\catcode `\~=\other
+\catcode `\[=\other
+\catcode `\]=\other
+\catcode`\"=\other
+\catcode`\_=\other
+\catcode`\|=\other
+\catcode`\<=\other
+\catcode`\>=\other
+\catcode `\$=\other
+\catcode `\#=\other
+\catcode `\&=\other
+% `\+ does not work, so use 43.
+\catcode 43=\other
+% Make the characters 128-255 be printing characters
+{%
+ \count 1=128
+ \def\loop{%
+ \catcode\count 1=\other
+ \advance\count 1 by 1
+ \ifnum \count 1<256 \loop \fi
+ }%
+}%
+% the aux file uses ' as the escape.
+% Turn off \ as an escape so we do not lose on
+% entries which were dumped with control sequences in their names.
+% For example, 'xrdef {$\leq $-fun}{page ...} made by @defun ^^
+% Reference to such entries still does not work the way one would wish,
+% but at least they do not bomb out when the aux file is read in.
+\catcode `\{=1 \catcode `\}=2
+\catcode `\%=\other
+\catcode `\'=0
+\catcode`\^=7 % to make ^^e4 etc usable in xref tags
+\catcode `\\=\other
+\openin 1 \jobname.aux
+\ifeof 1 \else \closein 1 \input \jobname.aux \global\havexrefstrue
+\global\warnedobstrue
+\fi
+% Open the new aux file. Tex will close it automatically at exit.
+\openout \auxfile=\jobname.aux
+\endgroup}
+
+
+% Footnotes.
+
+\newcount \footnoteno
+
+% The trailing space in the following definition for supereject is
+% vital for proper filling; pages come out unaligned when you do a
+% pagealignmacro call if that space before the closing brace is
+% removed. (Generally, numeric constants should always be followed by a
+% space to prevent strange expansion errors.)
+\def\supereject{\par\penalty -20000\footnoteno =0 }
+
+% @footnotestyle is meaningful for info output only..
+\let\footnotestyle=\comment
+
+\let\ptexfootnote=\footnote
+
+{\catcode `\@=11
+%
+% Auto-number footnotes. Otherwise like plain.
+\gdef\footnote{%
+ \global\advance\footnoteno by \@ne
+ \edef\thisfootno{$^{\the\footnoteno}$}%
+ %
+ % In case the footnote comes at the end of a sentence, preserve the
+ % extra spacing after we do the footnote number.
+ \let\@sf\empty
+ \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\/\fi
+ %
+ % Remove inadvertent blank space before typesetting the footnote number.
+ \unskip
+ \thisfootno\@sf
+ \footnotezzz
+}%
+
+% Don't bother with the trickery in plain.tex to not require the
+% footnote text as a parameter. Our footnotes don't need to be so general.
+%
+\long\gdef\footnotezzz#1{\insert\footins{%
+ % We want to typeset this text as a normal paragraph, even if the
+ % footnote reference occurs in (for example) a display environment.
+ % So reset some parameters.
+ \interlinepenalty\interfootnotelinepenalty
+ \splittopskip\ht\strutbox % top baseline for broken footnotes
+ \splitmaxdepth\dp\strutbox
+ \floatingpenalty\@MM
+ \leftskip\z@skip
+ \rightskip\z@skip
+ \spaceskip\z@skip
+ \xspaceskip\z@skip
+ \parindent\defaultparindent
+ %
+ % Hang the footnote text off the number.
+ \hang
+ \textindent{\thisfootno}%
+ %
+ % Don't crash into the line above the footnote text. Since this
+ % expands into a box, it must come within the paragraph, lest it
+ % provide a place where TeX can split the footnote.
+ \footstrut
+ #1\strut}%
+}
+
+}%end \catcode `\@=11
+
+% Set the baselineskip to #1, and the lineskip and strut size
+% correspondingly. There is no deep meaning behind these magic numbers
+% used as factors; they just match (closely enough) what Knuth defined.
+%
+\def\lineskipfactor{.08333}
+\def\strutheightpercent{.70833}
+\def\strutdepthpercent {.29167}
+%
+\def\setleading#1{%
+ \normalbaselineskip = #1\relax
+ \normallineskip = \lineskipfactor\normalbaselineskip
+ \normalbaselines
+ \setbox\strutbox =\hbox{%
+ \vrule width0pt height\strutheightpercent\baselineskip
+ depth \strutdepthpercent \baselineskip
+ }%
+}
+
+% @| inserts a changebar to the left of the current line. It should
+% surround any changed text. This approach does *not* work if the
+% change spans more than two lines of output. To handle that, we would
+% have adopt a much more difficult approach (putting marks into the main
+% vertical list for the beginning and end of each change).
+%
+\def\|{%
+ % \vadjust can only be used in horizontal mode.
+ \leavevmode
+ %
+ % Append this vertical mode material after the current line in the output.
+ \vadjust{%
+ % We want to insert a rule with the height and depth of the current
+ % leading; that is exactly what \strutbox is supposed to record.
+ \vskip-\baselineskip
+ %
+ % \vadjust-items are inserted at the left edge of the type. So
+ % the \llap here moves out into the left-hand margin.
+ \llap{%
+ %
+ % For a thicker or thinner bar, change the `1pt'.
+ \vrule height\baselineskip width1pt
+ %
+ % This is the space between the bar and the text.
+ \hskip 12pt
+ }%
+ }%
+}
+
+% For a final copy, take out the rectangles
+% that mark overfull boxes (in case you have decided
+% that the text looks ok even though it passes the margin).
+%
+\def\finalout{\overfullrule=0pt}
+
+
+% End of control word definitions.
+
+\message{and turning on texinfo input format.}
+
+\def\openindices{%
+ \newindex{cp}%
+ \newcodeindex{fn}%
+ \newcodeindex{vr}%
+ \newcodeindex{tp}%
+ \newcodeindex{ky}%
+ \newcodeindex{pg}%
+}
+
+% Set some numeric style parameters, for 8.5 x 11 format.
+
+\hsize = 6in
+\hoffset = .25in
+\newdimen\defaultparindent \defaultparindent = 15pt
+\parindent = \defaultparindent
+\parskip 3pt plus 2pt minus 1pt
+\setleading{13.2pt}
+\advance\topskip by 1.2cm
+
+\chapheadingskip = 15pt plus 4pt minus 2pt
+\secheadingskip = 12pt plus 3pt minus 2pt
+\subsecheadingskip = 9pt plus 2pt minus 2pt
+
+% Prevent underfull vbox error messages.
+\vbadness=10000
+
+% Following George Bush, just get rid of widows and orphans.
+\widowpenalty=10000
+\clubpenalty=10000
+
+% Use TeX 3.0's \emergencystretch to help line breaking, but if we're
+% using an old version of TeX, don't do anything. We want the amount of
+% stretch added to depend on the line length, hence the dependence on
+% \hsize. This makes it come to about 9pt for the 8.5x11 format.
+%
+\ifx\emergencystretch\thisisundefined
+ % Allow us to assign to \emergencystretch anyway.
+ \def\emergencystretch{\dimen0}%
+\else
+ \emergencystretch = \hsize
+ \divide\emergencystretch by 45
+\fi
+
+% Use @smallbook to reset parameters for 7x9.5 format (or else 7x9.25)
+\def\smallbook{
+ \global\chapheadingskip = 15pt plus 4pt minus 2pt
+ \global\secheadingskip = 12pt plus 3pt minus 2pt
+ \global\subsecheadingskip = 9pt plus 2pt minus 2pt
+ %
+ \global\lispnarrowing = 0.3in
+ \setleading{12pt}
+ \advance\topskip by -1cm
+ \global\parskip 2pt plus 1pt
+ \global\hsize = 5in
+ \global\vsize=7.5in
+ \global\tolerance=700
+ \global\hfuzz=1pt
+ \global\contentsrightmargin=0pt
+ \global\deftypemargin=0pt
+ \global\defbodyindent=.5cm
+ %
+ \global\pagewidth=\hsize
+ \global\pageheight=\vsize
+ %
+ \global\let\smalllisp=\smalllispx
+ \global\let\smallexample=\smalllispx
+ \global\def\Esmallexample{\Esmalllisp}
+}
+
+% Use @afourpaper to print on European A4 paper.
+\def\afourpaper{
+\global\tolerance=700
+\global\hfuzz=1pt
+\setleading{12pt}
+\global\parskip 15pt plus 1pt
+
+\global\vsize= 53\baselineskip
+\advance\vsize by \topskip
+%\global\hsize= 5.85in % A4 wide 10pt
+\global\hsize= 6.5in
+\global\outerhsize=\hsize
+\global\advance\outerhsize by 0.5in
+\global\outervsize=\vsize
+\global\advance\outervsize by 0.6in
+
+\global\pagewidth=\hsize
+\global\pageheight=\vsize
+}
+
+\bindingoffset=0pt
+\normaloffset=\hoffset
+\pagewidth=\hsize
+\pageheight=\vsize
+
+% Allow control of the text dimensions. Parameters in order: textheight;
+% textwidth; voffset; hoffset; binding offset; topskip.
+% All require a dimension;
+% header is additional; added length extends the bottom of the page.
+
+\def\changepagesizes#1#2#3#4#5#6{
+ \global\vsize= #1
+ \global\topskip= #6
+ \advance\vsize by \topskip
+ \global\voffset= #3
+ \global\hsize= #2
+ \global\outerhsize=\hsize
+ \global\advance\outerhsize by 0.5in
+ \global\outervsize=\vsize
+ \global\advance\outervsize by 0.6in
+ \global\pagewidth=\hsize
+ \global\pageheight=\vsize
+ \global\normaloffset= #4
+ \global\bindingoffset= #5}
+
+% A specific text layout, 24x15cm overall, intended for A4 paper. Top margin
+% 29mm, hence bottom margin 28mm, nominal side margin 3cm.
+\def\afourlatex
+ {\global\tolerance=700
+ \global\hfuzz=1pt
+ \setleading{12pt}
+ \global\parskip 15pt plus 1pt
+ \advance\baselineskip by 1.6pt
+ \changepagesizes{237mm}{150mm}{3.6mm}{3.6mm}{3mm}{7mm}
+ }
+
+% Use @afourwide to print on European A4 paper in wide format.
+\def\afourwide{\afourpaper
+\changepagesizes{9.5in}{6.5in}{\hoffset}{\normaloffset}{\bindingoffset}{7mm}}
+
+% Define macros to output various characters with catcode for normal text.
+\catcode`\"=\other
+\catcode`\~=\other
+\catcode`\^=\other
+\catcode`\_=\other
+\catcode`\|=\other
+\catcode`\<=\other
+\catcode`\>=\other
+\catcode`\+=\other
+\def\normaldoublequote{"}
+\def\normaltilde{~}
+\def\normalcaret{^}
+\def\normalunderscore{_}
+\def\normalverticalbar{|}
+\def\normalless{<}
+\def\normalgreater{>}
+\def\normalplus{+}
+
+% This macro is used to make a character print one way in ttfont
+% where it can probably just be output, and another way in other fonts,
+% where something hairier probably needs to be done.
+%
+% #1 is what to print if we are indeed using \tt; #2 is what to print
+% otherwise. Since all the Computer Modern typewriter fonts have zero
+% interword stretch (and shrink), and it is reasonable to expect all
+% typewriter fonts to have this, we can check that font parameter.
+%
+\def\ifusingtt#1#2{\ifdim \fontdimen3\the\font=0pt #1\else #2\fi}
+
+% Turn off all special characters except @
+% (and those which the user can use as if they were ordinary).
+% Most of these we simply print from the \tt font, but for some, we can
+% use math or other variants that look better in normal text.
+
+\catcode`\"=\active
+\def\activedoublequote{{\tt \char '042}}
+\let"=\activedoublequote
+\catcode`\~=\active
+\def~{{\tt \char '176}}
+\chardef\hat=`\^
+\catcode`\^=\active
+\def\auxhat{\def^{'hat}}
+\def^{{\tt \hat}}
+
+\catcode`\_=\active
+\def_{\ifusingtt\normalunderscore\_}
+% Subroutine for the previous macro.
+\def\_{\leavevmode \kern.06em \vbox{\hrule width.3em height.1ex}}
+
+\catcode`\|=\active
+\def|{{\tt \char '174}}
+\chardef \less=`\<
+\catcode`\<=\active
+\def<{{\tt \less}}
+\chardef \gtr=`\>
+\catcode`\>=\active
+\def>{{\tt \gtr}}
+\catcode`\+=\active
+\def+{{\tt \char 43}}
+%\catcode 27=\active
+%\def^^[{$\diamondsuit$}
+
+% Set up an active definition for =, but don't enable it most of the time.
+{\catcode`\==\active
+\global\def={{\tt \char 61}}}
+
+\catcode`+=\active
+\catcode`\_=\active
+
+% If a .fmt file is being used, characters that might appear in a file
+% name cannot be active until we have parsed the command line.
+% So turn them off again, and have \everyjob (or @setfilename) turn them on.
+% \otherifyactive is called near the end of this file.
+\def\otherifyactive{\catcode`+=\other \catcode`\_=\other}
+
+\catcode`\@=0
+
+% \rawbackslashxx output one backslash character in current font
+\global\chardef\rawbackslashxx=`\\
+%{\catcode`\\=\other
+%@gdef@rawbackslashxx{\}}
+
+% \rawbackslash redefines \ as input to do \rawbackslashxx.
+{\catcode`\\=\active
+@gdef@rawbackslash{@let\=@rawbackslashxx }}
+
+% \normalbackslash outputs one backslash in fixed width font.
+\def\normalbackslash{{\tt\rawbackslashxx}}
+
+% Say @foo, not \foo, in error messages.
+\escapechar=`\@
+
+% \catcode 17=0 % Define control-q
+\catcode`\\=\active
+
+% Used sometimes to turn off (effectively) the active characters
+% even after parsing them.
+@def@turnoffactive{@let"=@normaldoublequote
+@let\=@realbackslash
+@let~=@normaltilde
+@let^=@normalcaret
+@let_=@normalunderscore
+@let|=@normalverticalbar
+@let<=@normalless
+@let>=@normalgreater
+@let+=@normalplus}
+
+@def@normalturnoffactive{@let"=@normaldoublequote
+@let\=@normalbackslash
+@let~=@normaltilde
+@let^=@normalcaret
+@let_=@normalunderscore
+@let|=@normalverticalbar
+@let<=@normalless
+@let>=@normalgreater
+@let+=@normalplus}
+
+% Make _ and + \other characters, temporarily.
+% This is canceled by @fixbackslash.
+@otherifyactive
+
+% If a .fmt file is being used, we don't want the `\input texinfo' to show up.
+% That is what \eatinput is for; after that, the `\' should revert to printing
+% a backslash.
+%
+@gdef@eatinput input texinfo{@fixbackslash}
+@global@let\ = @eatinput
+
+% On the other hand, perhaps the file did not have a `\input texinfo'. Then
+% the first `\{ in the file would cause an error. This macro tries to fix
+% that, assuming it is called before the first `\' could plausibly occur.
+% Also back turn on active characters that might appear in the input
+% file name, in case not using a pre-dumped format.
+%
+@gdef@fixbackslash{@ifx\@eatinput @let\ = @normalbackslash @fi
+ @catcode`+=@active @catcode`@_=@active}
+
+%% These look ok in all fonts, so just make them not special. The @rm below
+%% makes sure that the current font starts out as the newly loaded cmr10
+@catcode`@$=@other @catcode`@%=@other @catcode`@&=@other @catcode`@#=@other
+
+@textfonts
+@rm
+
+@c Local variables:
+@c page-delimiter: "^\\\\message"
+@c End:
diff --git a/gdk/.cvsignore b/gdk/.cvsignore
new file mode 100644
index 000000000..79680c82c
--- /dev/null
+++ b/gdk/.cvsignore
@@ -0,0 +1,6 @@
+*.lo
+Makefile
+.deps
+_libs
+libgdk.la
+
diff --git a/gdk/Makefile.am b/gdk/Makefile.am
new file mode 100644
index 000000000..f298e2c3a
--- /dev/null
+++ b/gdk/Makefile.am
@@ -0,0 +1,75 @@
+## Process this file with automake to produce Makefile.in
+
+gdkincludedir = $(includedir)/gdk
+
+lib_LTLIBRARIES = libgdk.la
+
+libgdk_la_SOURCES = \
+ gdk.c \
+ gdkcolor.c \
+ gdkcursor.c \
+ gdkdraw.c \
+ gdkfont.c \
+ gdkgc.c \
+ gdkglobals.c \
+ gdkimage.c \
+ gdkinput.c \
+ gdkpixmap.c \
+ gdkproperty.c \
+ gdkrectangle.c \
+ gdkselection.c \
+ gdkvisual.c \
+ gdkwindow.c \
+ gdkxid.c \
+ gxid_lib.c
+## this last one is ifdef'd out unless XINPUT_GXI is defined
+## It's easier than trying to get automake to handle compiling
+## it conditionally
+
+gdkinclude_HEADERS = \
+ gdk.h \
+ gdkcursors.h \
+ gdkkeysyms.h \
+ gdkprivate.h \
+ gdktypes.h \
+ gdkinput.h \
+ gdkinputnone.h \
+ gdkinputcommon.h\
+ gdkinputgxi.h \
+ gdkinputxfree.h \
+ gxid_lib.h \
+ gxid_proto.h \
+ gdkx.h
+
+libgdk_la_LDFLAGS = -version-info 1:0:0 \
+ @x_ldflags@ @x_libs@
+
+INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/glib @x_cflags@
+
+EXTRA_PROGRAMS = gxid
+
+bin_PROGRAMS = @xinput_progs@
+
+gxid_SOURCES = gxid.c
+
+gxid_LDADD = \
+ @x_ldflags@ \
+ @x_libs@ \
+ -lm
+
+BUILT_SOURCES = gdkcursors.h gdkkeysyms.h
+
+EXTRA_DIST = makecursors makecursors.sed makekeysyms makekeysyms.sed
+
+gdkcursors.h:
+ $(srcdir)/makecursors @x_includes@/X11/cursorfont.h > $@
+
+gdkkeysyms.h:
+ $(srcdir)/makekeysyms @x_includes@/X11/keysymdef.h > $@
+
+.PHONY: files
+
+files:
+ @files=`ls $(DISTFILES) 2> /dev/null `; for p in $$files; do \
+ echo $$p; \
+ done
diff --git a/gdk/gdk.c b/gdk/gdk.c
new file mode 100644
index 000000000..d5f85dd1e
--- /dev/null
+++ b/gdk/gdk.c
@@ -0,0 +1,2897 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "../config.h"
+
+#include <ctype.h>
+#include <locale.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif /* HAVE_SYS_SELECT_H_ */
+
+#define XLIB_ILLEGAL_ACCESS
+#include <X11/Xatom.h>
+#include <X11/Xlib.h>
+#include <X11/Xos.h>
+#include <X11/Xutil.h>
+#include <X11/Xmu/WinUtil.h>
+#include <X11/cursorfont.h>
+#include "gdk.h"
+#include "gdkprivate.h"
+#include "gdkinput.h"
+
+
+#ifndef X_GETTIMEOFDAY
+#define X_GETTIMEOFDAY(tv) gettimeofday (tv, NULL)
+#endif /* X_GETTIMEOFDAY */
+
+
+#define DOUBLE_CLICK_TIME 250
+#define TRIPLE_CLICK_TIME 500
+#define DOUBLE_CLICK_DIST 5
+#define TRIPLE_CLICK_DIST 5
+
+
+#ifndef NO_FD_SET
+# define SELECT_MASK fd_set
+#else
+# ifndef _AIX
+ typedef long fd_mask;
+# endif
+# if defined(_IBMR2)
+# define SELECT_MASK void
+# else
+# define SELECT_MASK int
+# endif
+#endif
+
+
+typedef struct _GdkInput GdkInput;
+typedef struct _GdkPredicate GdkPredicate;
+
+struct _GdkInput
+{
+ gint tag;
+ gint source;
+ GdkInputCondition condition;
+ GdkInputFunction function;
+ gpointer data;
+};
+
+struct _GdkPredicate
+{
+ GdkEventFunc func;
+ gpointer data;
+};
+
+/*
+ * Private function declarations
+ */
+static gint gdk_event_wait (void);
+static gint gdk_event_translate (GdkEvent *event,
+ XEvent *xevent);
+static Bool gdk_event_get_type (Display *display,
+ XEvent *xevent,
+ XPointer arg);
+static void gdk_synthesize_click (GdkEvent *event,
+ gint nclicks);
+
+static void gdk_dnd_drag_begin (GdkWindow *initial_window);
+static void gdk_dnd_drag_enter (Window dest);
+static void gdk_dnd_drag_leave (Window dest);
+static void gdk_dnd_drag_end (Window dest,
+ GdkPoint coords);
+static GdkAtom gdk_dnd_check_types (GdkWindow *window,
+ XEvent *xevent);
+static void gdk_print_atom (GdkAtom anatom);
+
+/*
+ * old junk from offix, we might use it though so leave it
+ */
+static Window gdk_drop_get_client_window (Display *dpy,
+ Window win);
+static GdkWindow * gdk_drop_get_real_window (GdkWindow *w,
+ guint16 *x,
+ guint16 *y);
+static void gdk_exit_func (void);
+static int gdk_x_error (Display *display,
+ XErrorEvent *error);
+static int gdk_x_io_error (Display *display);
+static RETSIGTYPE gdk_signal (int signum);
+
+
+/* Private variable declarations
+ */
+static int initialized = 0; /* 1 if the library is initialized,
+ * 0 otherwise.
+ */
+static int connection_number = 0; /* The file descriptor number of our
+ * connection to the X server. This
+ * is used so that we may determine
+ * when events are pending by using
+ * the "select" system call.
+ */
+
+static gint received_destroy_notify = FALSE; /* Did we just receive a destroy notify
+ * event? If so, we need to actually
+ * destroy the window which received
+ * it now.
+ */
+static GdkWindow *window_to_destroy = NULL; /* If we previously received a destroy
+ * notify event then this is the window
+ * which received that event.
+ */
+
+static struct timeval start; /* The time at which the library was
+ * last initialized.
+ */
+static struct timeval timer; /* Timeout interval to use in the call
+ * to "select". This is used in
+ * conjunction with "timerp" to create
+ * a maximum time to wait for an event
+ * to arrive.
+ */
+static struct timeval *timerp; /* The actual timer passed to "select"
+ * This may be NULL, in which case
+ * "select" will block until an event
+ * arrives.
+ */
+static guint32 timer_val; /* The timeout length as specified by
+ * the user in milliseconds.
+ */
+static GList *inputs; /* A list of the input file descriptors
+ * that we care about. Each list node
+ * contains a GdkInput struct that describes
+ * when we are interested in the specified
+ * file descriptor. That is, when it is
+ * available for read, write or has an
+ * exception pending.
+ */
+static guint32 button_click_time[2]; /* The last 2 button click times. Used
+ * to determine if the latest button click
+ * is part of a double or triple click.
+ */
+static GdkWindow *button_window[2]; /* The last 2 windows to receive button presses.
+ * Also used to determine if the latest button
+ * click is part of a double or triple click.
+ */
+static guint button_number[2]; /* The last 2 buttons to be pressed.
+ */
+
+#define OTHER_XEVENT_BUFSIZE 4
+static XEvent other_xevent[OTHER_XEVENT_BUFSIZE]; /* XEvents passed along to user */
+static int other_xevent_i = 0;
+static GList *putback_events = NULL;
+
+static gulong base_id;
+static gint autorepeat;
+
+
+/*
+ *--------------------------------------------------------------
+ * gdk_init
+ *
+ * Initialize the library for use.
+ *
+ * Arguments:
+ * "argc" is the number of arguments.
+ * "argv" is an array of strings.
+ *
+ * Results:
+ * "argc" and "argv" are modified to reflect any arguments
+ * which were not handled. (Such arguments should either
+ * be handled by the application or dismissed).
+ *
+ * Side effects:
+ * The library is initialized.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+gdk_init (int *argc,
+ char ***argv)
+{
+ XKeyboardState keyboard_state;
+ int synchronize;
+ int i, j, k;
+ XClassHint *class_hint;
+ int argc_orig = *argc;
+ char **argv_orig;
+
+ argv_orig = malloc ((argc_orig + 1) * sizeof (char*));
+ for (i = 0; i < argc_orig; i++)
+ argv_orig[i] = g_strdup ((*argv)[i]);
+ argv_orig[argc_orig] = NULL;
+
+ X_GETTIMEOFDAY (&start);
+
+ signal (SIGHUP, gdk_signal);
+ signal (SIGINT, gdk_signal);
+ signal (SIGQUIT, gdk_signal);
+ signal (SIGBUS, gdk_signal);
+ signal (SIGSEGV, gdk_signal);
+ signal (SIGPIPE, gdk_signal);
+ signal (SIGTERM, gdk_signal);
+
+ gdk_display_name = NULL;
+
+ XSetErrorHandler (gdk_x_error);
+ XSetIOErrorHandler (gdk_x_io_error);
+
+ synchronize = FALSE;
+
+ if (argc && argv)
+ {
+ if (*argc > 0)
+ gdk_progname = (*argv)[0];
+
+ for (i = 1; i < *argc;)
+ {
+ if (strcmp ("--display", (*argv)[i]) == 0)
+ {
+ (*argv)[i] = NULL;
+
+ if ((i + 1) < *argc)
+ {
+ gdk_display_name = g_strdup ((*argv)[i + 1]);
+ (*argv)[i + 1] = NULL;
+ i += 1;
+ }
+ }
+ else if (strcmp ("--sync", (*argv)[i]) == 0)
+ {
+ (*argv)[i] = NULL;
+ synchronize = TRUE;
+ }
+ else if (strcmp ("--show-events", (*argv)[i]) == 0)
+ {
+ (*argv)[i] = NULL;
+ gdk_show_events = TRUE;
+ }
+ else if (strcmp ("--no-show-events", (*argv)[i]) == 0)
+ {
+ (*argv)[i] = NULL;
+ gdk_show_events = FALSE;
+ }
+ else if (strcmp ("--no-xshm", (*argv)[i]) == 0)
+ {
+ (*argv)[i] = NULL;
+ gdk_use_xshm = FALSE;
+ }
+ else if (strcmp ("--debug-level", (*argv)[i]) == 0)
+ {
+ if ((i + 1) < *argc)
+ {
+ (*argv)[i++] = NULL;
+ gdk_debug_level = atoi ((*argv)[i]);
+ (*argv)[i] = NULL;
+ }
+ }
+ else if (strcmp ("-name", (*argv)[i]) == 0)
+ {
+ if ((i + 1) < *argc)
+ {
+ (*argv)[i++] = NULL;
+ gdk_progname = (*argv)[i];
+ (*argv)[i] = NULL;
+ }
+ }
+ else if (strcmp ("-class", (*argv)[i]) == 0)
+ {
+ if ((i + 1) < *argc)
+ {
+ (*argv)[i++] = NULL;
+ gdk_progclass = (*argv)[i];
+ (*argv)[i] = NULL;
+ }
+ }
+#ifdef XINPUT_GXI
+ else if (strcmp ("--gxid_host", (*argv)[i]) == 0)
+ {
+ if ((i + 1) < *argc)
+ {
+ (*argv)[i++] = NULL;
+ gdk_input_gxid_host = ((*argv)[i]);
+ (*argv)[i] = NULL;
+ }
+ }
+ else if (strcmp ("--gxid_port", (*argv)[i]) == 0)
+ {
+ if ((i + 1) < *argc)
+ {
+ (*argv)[i++] = NULL;
+ gdk_input_gxid_port = atoi ((*argv)[i]);
+ (*argv)[i] = NULL;
+ }
+ }
+#endif
+ i += 1;
+ }
+
+ for (i = 1; i < *argc; i++)
+ {
+ for (k = i; k < *argc; k++)
+ if ((*argv)[k] != NULL)
+ break;
+
+ if (k > i)
+ {
+ k -= i;
+ for (j = i + k; j < *argc; j++)
+ (*argv)[j-k] = (*argv)[j];
+ *argc -= k;
+ }
+ }
+ }
+ else
+ {
+ gdk_progname = "<unknown>";
+ }
+
+ gdk_display = XOpenDisplay (gdk_display_name);
+ if (!gdk_display)
+ g_error ("cannot open display: %s", XDisplayName (gdk_display_name));
+
+ /* This is really crappy. We have to look into the display structure
+ * to find the base resource id. This is only needed for recording
+ * and playback of events.
+ */
+ /* base_id = RESOURCE_BASE; */
+ base_id = 0;
+ if (gdk_show_events)
+ g_print ("base id: %lu\n", base_id);
+
+ connection_number = ConnectionNumber (gdk_display);
+ if (gdk_debug_level >= 1)
+ g_print ("connection number: %d\n", connection_number);
+
+ if (synchronize)
+ XSynchronize (gdk_display, True);
+
+ gdk_screen = DefaultScreen (gdk_display);
+ gdk_root_window = RootWindow (gdk_display, gdk_screen);
+
+ gdk_leader_window = XCreateSimpleWindow(gdk_display, gdk_root_window,
+ 10, 10, 10, 10, 0, 0 , 0);
+ class_hint = XAllocClassHint();
+ class_hint->res_name = gdk_progname;
+ class_hint->res_class = gdk_progclass;
+ XSetClassHint(gdk_display, gdk_leader_window, class_hint);
+ XSetCommand(gdk_display, gdk_leader_window, argv_orig, argc_orig);
+ XFree (class_hint);
+
+ gdk_wm_delete_window = XInternAtom (gdk_display, "WM_DELETE_WINDOW", True);
+ gdk_wm_take_focus = XInternAtom (gdk_display, "WM_TAKE_FOCUS", True);
+ gdk_wm_protocols = XInternAtom (gdk_display, "WM_PROTOCOLS", True);
+ gdk_wm_window_protocols[0] = gdk_wm_delete_window;
+ gdk_wm_window_protocols[1] = gdk_wm_take_focus;
+ gdk_selection_property = XInternAtom (gdk_display, "GDK_SELECTION", False);
+
+ gdk_dnd.gdk_XdeEnter = gdk_atom_intern("_XDE_ENTER", FALSE);
+ gdk_dnd.gdk_XdeLeave = gdk_atom_intern("_XDE_LEAVE", FALSE);
+ gdk_dnd.gdk_XdeRequest = gdk_atom_intern("_XDE_REQUEST", FALSE);
+ gdk_dnd.gdk_XdeDataAvailable = gdk_atom_intern("_XDE_DATA_AVAILABLE", FALSE);
+ gdk_dnd.gdk_XdeTypelist = gdk_atom_intern("_XDE_TYPELIST", FALSE);
+ gdk_dnd.gdk_cursor_dragdefault = XCreateFontCursor(gdk_display, XC_bogosity);
+ gdk_dnd.gdk_cursor_dragok = XCreateFontCursor(gdk_display, XC_heart);
+
+ XGetKeyboardControl (gdk_display, &keyboard_state);
+ autorepeat = keyboard_state.global_auto_repeat;
+
+ timer.tv_sec = 0;
+ timer.tv_usec = 0;
+ timerp = NULL;
+
+ button_click_time[0] = 0;
+ button_click_time[1] = 0;
+ button_window[0] = NULL;
+ button_window[1] = NULL;
+ button_number[0] = -1;
+ button_number[1] = -1;
+
+ if (ATEXIT (gdk_exit_func))
+ g_warning ("unable to register exit function");
+
+ gdk_visual_init ();
+ gdk_window_init ();
+ gdk_image_init ();
+ gdk_input_init ();
+
+ initialized = 1;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_exit
+ *
+ * Restores the library to an un-itialized state and exits
+ * the program using the "exit" system call.
+ *
+ * Arguments:
+ * "errorcode" is the error value to pass to "exit".
+ *
+ * Results:
+ * Allocated structures are freed and the program exits
+ * cleanly.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+gdk_exit (int errorcode)
+{
+ /* de-initialisation is done by the gdk_exit_funct(),
+ no need to do this here (Alex J.) */
+ exit (errorcode);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_set_locale
+ *
+ * Arguments:
+ *
+ * Results:
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+gchar*
+gdk_set_locale ()
+{
+ if (!setlocale (LC_ALL,""))
+ g_print ("locale not supported by C library\n");
+
+ if (!XSupportsLocale ())
+ {
+ g_print ("locale not supported by Xlib, locale set to C\n");
+ setlocale (LC_ALL, "C");
+ }
+
+ if (!XSetLocaleModifiers (""))
+ {
+ g_print ("can not set locale modifiers\n");
+ }
+
+ return setlocale (LC_ALL,NULL);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_events_pending
+ *
+ * Returns the number of events pending on the queue.
+ * These events have already been read from the server
+ * connection.
+ *
+ * Arguments:
+ *
+ * Results:
+ * Returns the number of events on XLib's event queue.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+gint
+gdk_events_pending ()
+{
+ return XPending (gdk_display);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_event_get
+ *
+ * Gets the next event.
+ *
+ * Arguments:
+ * "event" is used to hold the received event.
+ * If "event" is NULL an event is received as normal
+ * however it is not placed in "event" (and thus no
+ * error occurs).
+ *
+ * Results:
+ * Returns TRUE if an event was received that we care about
+ * and FALSE otherwise. This function will also return
+ * before an event is received if the timeout interval
+ * runs out.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+gint
+gdk_event_get (GdkEvent *event,
+ GdkEventFunc pred,
+ gpointer data)
+{
+ GdkEvent *temp_event;
+ GdkPredicate event_pred;
+ GList *temp_list;
+ XEvent xevent;
+
+ /* If the last event we received was a destroy notify
+ * event then we will actually destroy the "gdk" data
+ * structures now. We don't want to destroy them at the
+ * time of receiving the event since the main program
+ * may try to access them and may need to destroy user
+ * data that has been attached to the window
+ */
+ if (received_destroy_notify)
+ {
+ if (gdk_show_events)
+ g_print ("destroying window:\twindow: %ld\n",
+ ((GdkWindowPrivate*) window_to_destroy)->xwindow - base_id);
+
+ gdk_window_real_destroy (window_to_destroy);
+ received_destroy_notify = FALSE;
+ window_to_destroy = NULL;
+ }
+
+ /* Initially we haven't received an event and want to
+ * return FALSE. If "event" is non-NULL, then initialize
+ * it to the nothing event.
+ */
+ if (event)
+ {
+ event->any.type = GDK_NOTHING;
+ event->any.window = NULL;
+ event->any.send_event = FALSE;
+ }
+
+ if (pred)
+ {
+ temp_list = putback_events;
+ while (temp_list)
+ {
+ temp_event = temp_list->data;
+
+ if ((* pred) (temp_event, data))
+ {
+ if (event)
+ *event = *temp_event;
+ putback_events = g_list_remove_link (putback_events, temp_list);
+ g_list_free (temp_list);
+ return TRUE;
+ }
+
+ temp_list = temp_list->next;
+ }
+
+ event_pred.func = pred;
+ event_pred.data = data;
+
+ if (XCheckIfEvent (gdk_display, &xevent, gdk_event_get_type, (XPointer) &event_pred))
+ if (event)
+ return gdk_event_translate (event, &xevent);
+ }
+ else
+ {
+ if (putback_events)
+ {
+ temp_event = putback_events->data;
+ *event = *temp_event;
+
+ temp_list = putback_events;
+ putback_events = putback_events->next;
+ if (putback_events)
+ putback_events->prev = NULL;
+
+ temp_list->next = NULL;
+ temp_list->prev = NULL;
+ g_list_free (temp_list);
+ g_free (temp_event);
+
+ return TRUE;
+ }
+
+ /* Wait for an event to occur or the timeout to elapse.
+ * If an event occurs "gdk_event_wait" will return TRUE.
+ * If the timeout elapses "gdk_event_wait" will return
+ * FALSE.
+ */
+ if (gdk_event_wait ())
+ {
+ /* If we get here we can rest assurred that an event
+ * has occurred. Read it.
+ */
+ XNextEvent (gdk_display, &xevent);
+
+ event->any.send_event = xevent.xany.send_event;
+
+ /* If "event" non-NULL.
+ */
+ if (event)
+ return gdk_event_translate (event, &xevent);
+ }
+ }
+
+ return FALSE;
+}
+
+void
+gdk_event_put (GdkEvent *event)
+{
+ GdkEvent *new_event;
+
+ g_return_if_fail (event != NULL);
+
+ new_event = g_new (GdkEvent, 1);
+ *new_event = *event;
+
+ putback_events = g_list_prepend (putback_events, new_event);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_event_copy
+ *
+ * Copy a event structure into new storage.
+ *
+ * Arguments:
+ * "event" is the event struct to copy.
+ *
+ * Results:
+ * A new event structure. Free it with gdk_event_free.
+ *
+ * Side effects:
+ * The reference count of the window in the event is increased.
+ *
+ *--------------------------------------------------------------
+ */
+
+static GMemChunk *event_chunk;
+
+GdkEvent*
+gdk_event_copy (GdkEvent *event)
+{
+ GdkEvent *new_event;
+
+ g_return_val_if_fail (event != NULL, NULL);
+
+ if (event_chunk == NULL)
+ event_chunk = g_mem_chunk_new ("events",
+ sizeof (GdkEvent),
+ 4096,
+ G_ALLOC_AND_FREE);
+
+ new_event = g_chunk_new (GdkEvent, event_chunk);
+ *new_event = *event;
+ gdk_window_ref (new_event->any.window);
+ return new_event;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_event_free
+ *
+ * Free a event structure obtained from gdk_event_copy. Do not use
+ * with other event structures.
+ *
+ * Arguments:
+ * "event" is the event struct to free.
+ *
+ * Results:
+ *
+ * Side effects:
+ * The reference count of the window in the event is decreased and
+ * might be freed, too.
+ *
+ *-------------------------------------------------------------- */
+
+void
+gdk_event_free (GdkEvent *event)
+{
+ g_assert (event_chunk != NULL);
+ g_return_if_fail (event != NULL);
+
+ gdk_window_unref (event->any.window);
+ g_mem_chunk_free (event_chunk, event);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_set_debug_level
+ *
+ * Sets the debugging level.
+ *
+ * Arguments:
+ * "level" is the new debugging level.
+ *
+ * Results:
+ *
+ * Side effects:
+ * Other function calls to "gdk" use the debugging
+ * level to determine what kind of debugging information
+ * to print out.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+gdk_set_debug_level (int level)
+{
+ gdk_debug_level = level;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_set_show_events
+ *
+ * Turns on/off the showing of events.
+ *
+ * Arguments:
+ * "show_events" is a boolean describing whether or
+ * not to show the events gdk receives.
+ *
+ * Results:
+ *
+ * Side effects:
+ * When "show_events" is TRUE, calls to "gdk_event_get"
+ * will output debugging informatin regarding the event
+ * received to stdout.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+gdk_set_show_events (int show_events)
+{
+ gdk_show_events = show_events;
+}
+
+void
+gdk_set_use_xshm (gint use_xshm)
+{
+ gdk_use_xshm = use_xshm;
+}
+
+gint
+gdk_get_debug_level ()
+{
+ return gdk_debug_level;
+}
+
+gint
+gdk_get_show_events ()
+{
+ return gdk_show_events;
+}
+
+gint
+gdk_get_use_xshm ()
+{
+ return gdk_use_xshm;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_time_get
+ *
+ * Get the number of milliseconds since the library was
+ * initialized.
+ *
+ * Arguments:
+ *
+ * Results:
+ * The time since the library was initialized is returned.
+ * This time value is accurate to milliseconds even though
+ * a more accurate time down to the microsecond could be
+ * returned.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+guint32
+gdk_time_get ()
+{
+ struct timeval end;
+ struct timeval elapsed;
+ guint32 milliseconds;
+
+ X_GETTIMEOFDAY (&end);
+
+ if (start.tv_usec > end.tv_usec)
+ {
+ end.tv_usec += 1000000;
+ end.tv_sec--;
+ }
+ elapsed.tv_sec = end.tv_sec - start.tv_sec;
+ elapsed.tv_usec = end.tv_usec - start.tv_usec;
+
+ milliseconds = (elapsed.tv_sec * 1000) + (elapsed.tv_usec / 1000);
+
+ return milliseconds;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_timer_get
+ *
+ * Returns the current timer.
+ *
+ * Arguments:
+ *
+ * Results:
+ * Returns the current timer interval. This interval is
+ * in units of milliseconds.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+guint32
+gdk_timer_get ()
+{
+ return timer_val;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_timer_set
+ *
+ * Sets the timer interval.
+ *
+ * Arguments:
+ * "milliseconds" is the new value for the timer.
+ *
+ * Results:
+ *
+ * Side effects:
+ * Calls to "gdk_event_get" will last for a maximum
+ * of time of "milliseconds". However, a value of 0
+ * milliseconds will cause "gdk_event_get" to block
+ * indefinately until an event is received.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+gdk_timer_set (guint32 milliseconds)
+{
+ timer_val = milliseconds;
+ timer.tv_sec = milliseconds / 1000;
+ timer.tv_usec = (milliseconds % 1000) * 1000;
+
+}
+
+void
+gdk_timer_enable ()
+{
+ timerp = &timer;
+}
+
+void
+gdk_timer_disable ()
+{
+ timerp = NULL;
+}
+
+gint
+gdk_input_add (gint source,
+ GdkInputCondition condition,
+ GdkInputFunction function,
+ gpointer data)
+{
+ static gint next_tag = 1;
+ GList *list;
+ GdkInput *input;
+ gint tag;
+
+ tag = 0;
+ list = inputs;
+
+ while (list)
+ {
+ input = list->data;
+ list = list->next;
+
+ if ((input->source == source) && (input->condition == condition))
+ {
+ input->function = function;
+ input->data = data;
+ tag = input->tag;
+ }
+ }
+
+ if (!tag)
+ {
+ input = g_new (GdkInput, 1);
+ input->tag = next_tag++;
+ input->source = source;
+ input->condition = condition;
+ input->function = function;
+ input->data = data;
+ tag = input->tag;
+
+ inputs = g_list_prepend (inputs, input);
+ }
+
+ return tag;
+}
+
+void
+gdk_input_remove (gint tag)
+{
+ GList *list;
+ GList *temp_list;
+ GdkInput *input;
+
+ list = inputs;
+ while (list)
+ {
+ input = list->data;
+
+ if (input->tag == tag)
+ {
+ temp_list = list;
+
+ if (list->next)
+ list->next->prev = list->prev;
+ if (list->prev)
+ list->prev->next = list->next;
+ if (inputs == list)
+ inputs = list->next;
+
+ temp_list->next = NULL;
+ temp_list->prev = NULL;
+
+ g_free (temp_list->data);
+ g_list_free (temp_list);
+ break;
+ }
+
+ list = list->next;
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_pointer_grab
+ *
+ * Grabs the pointer to a specific window
+ *
+ * Arguments:
+ * "window" is the window which will receive the grab
+ * "owner_events" specifies whether events will be reported as is,
+ * or relative to "window"
+ * "event_mask" masks only interesting events
+ * "confine_to" limits the cursor movement to the specified window
+ * "cursor" changes the cursor for the duration of the grab
+ * "time" specifies the time
+ *
+ * Results:
+ *
+ * Side effects:
+ * requires a corresponding call to gdk_pointer_ungrab
+ *
+ *--------------------------------------------------------------
+ */
+
+gint
+gdk_pointer_grab (GdkWindow * window,
+ gint owner_events,
+ GdkEventMask event_mask,
+ GdkWindow * confine_to,
+ GdkCursor * cursor,
+ guint32 time)
+{
+ /* From gdkwindow.c */
+ extern int nevent_masks;
+ extern int event_mask_table[];
+
+ gint return_val;
+ GdkWindowPrivate *window_private;
+ GdkWindowPrivate *confine_to_private;
+ GdkCursorPrivate *cursor_private;
+ guint xevent_mask;
+ Window xwindow;
+ Window xconfine_to;
+ Cursor xcursor;
+ int i;
+
+ g_return_val_if_fail (window != NULL, 0);
+
+ window_private = (GdkWindowPrivate*) window;
+ confine_to_private = (GdkWindowPrivate*) confine_to;
+ cursor_private = (GdkCursorPrivate*) cursor;
+
+ xwindow = window_private->xwindow;
+
+ if (!confine_to)
+ xconfine_to = None;
+ else
+ xconfine_to = confine_to_private->xwindow;
+
+ if (!cursor)
+ xcursor = None;
+ else
+ xcursor = cursor_private->xcursor;
+
+
+ xevent_mask = 0;
+ for (i = 0; i < nevent_masks; i++)
+ {
+ if (event_mask & (1 << (i + 1)))
+ xevent_mask |= event_mask_table[i];
+ }
+
+ if (((GdkWindowPrivate *)window)->extension_events &&
+ gdk_input_vtable.grab_pointer)
+ return_val = gdk_input_vtable.grab_pointer (window,
+ owner_events,
+ event_mask,
+ confine_to,
+ time);
+ else
+ return_val = Success;;
+
+ if (return_val == Success)
+ return_val = XGrabPointer (window_private->xdisplay,
+ xwindow,
+ owner_events,
+ xevent_mask,
+ GrabModeAsync, GrabModeAsync,
+ xconfine_to,
+ xcursor,
+ time);
+
+ return return_val;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_pointer_ungrab
+ *
+ * Releases any pointer grab
+ *
+ * Arguments:
+ *
+ * Results:
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+gdk_pointer_ungrab (guint32 time)
+{
+ if (gdk_input_vtable.ungrab_pointer)
+ gdk_input_vtable.ungrab_pointer (time);
+
+ XUngrabPointer (gdk_display, time);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_keyboard_grab
+ *
+ * Grabs the keyboard to a specific window
+ *
+ * Arguments:
+ * "window" is the window which will receive the grab
+ * "owner_events" specifies whether events will be reported as is,
+ * or relative to "window"
+ * "time" specifies the time
+ *
+ * Results:
+ *
+ * Side effects:
+ * requires a corresponding call to gdk_keyboard_ungrab
+ *
+ *--------------------------------------------------------------
+ */
+
+gint
+gdk_keyboard_grab (GdkWindow * window,
+ gint owner_events,
+ guint32 time)
+{
+ GdkWindowPrivate *window_private;
+ Window xwindow;
+
+ g_return_val_if_fail (window != NULL, 0);
+
+ window_private = (GdkWindowPrivate*) window;
+ xwindow = window_private->xwindow;
+
+ return XGrabKeyboard (window_private->xdisplay,
+ xwindow,
+ owner_events,
+ GrabModeAsync, GrabModeAsync,
+ time);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_keyboard_ungrab
+ *
+ * Releases any keyboard grab
+ *
+ * Arguments:
+ *
+ * Results:
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+gdk_keyboard_ungrab (guint32 time)
+{
+ XUngrabKeyboard (gdk_display, time);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_screen_width
+ *
+ * Return the width of the screen.
+ *
+ * Arguments:
+ *
+ * Results:
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+gint
+gdk_screen_width ()
+{
+ gint return_val;
+
+ return_val = DisplayWidth (gdk_display, gdk_screen);
+
+ return return_val;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_screen_height
+ *
+ * Return the height of the screen.
+ *
+ * Arguments:
+ *
+ * Results:
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+gint
+gdk_screen_height ()
+{
+ gint return_val;
+
+ return_val = DisplayHeight (gdk_display, gdk_screen);
+
+ return return_val;
+}
+
+void
+gdk_key_repeat_disable ()
+{
+ XAutoRepeatOff (gdk_display);
+}
+
+void
+gdk_key_repeat_restore ()
+{
+ if (autorepeat)
+ XAutoRepeatOn (gdk_display);
+ else
+ XAutoRepeatOff (gdk_display);
+}
+
+
+/*
+ *--------------------------------------------------------------
+ * gdk_flush
+ *
+ * Flushes the Xlib output buffer and then waits
+ * until all requests have been received and processed
+ * by the X server. The only real use for this function
+ * is in dealing with XShm.
+ *
+ * Arguments:
+ *
+ * Results:
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+void gdk_flush ()
+{
+ XSync (gdk_display, False);
+}
+
+
+void
+gdk_beep ()
+{
+ XBell(gdk_display, 100);
+}
+
+
+/*
+ *--------------------------------------------------------------
+ * gdk_event_wait
+ *
+ * Waits until an event occurs or the timer runs out.
+ *
+ * Arguments:
+ *
+ * Results:
+ * Returns TRUE if an event is ready to be read and FALSE
+ * if the timer ran out.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+static gint
+gdk_event_wait ()
+{
+ GList *list;
+ GdkInput *input;
+ GdkInputCondition condition;
+ SELECT_MASK readfds;
+ SELECT_MASK writefds;
+ SELECT_MASK exceptfds;
+ int max_input;
+ int nfd;
+
+ /* If there are no events pending we will wait for an event.
+ * The time we wait is dependant on the "timer". If no timer
+ * has been specified then we'll block until an event arrives.
+ * If a timer has been specified we'll block until an event
+ * arrives or the timer expires. (This is all done using the
+ * "select" system call).
+ */
+
+ if (XPending (gdk_display) == 0)
+ {
+ FD_ZERO (&readfds);
+ FD_ZERO (&writefds);
+ FD_ZERO (&exceptfds);
+
+ FD_SET (connection_number, &readfds);
+ max_input = connection_number;
+
+ list = inputs;
+ while (list)
+ {
+ input = list->data;
+ list = list->next;
+
+ if (input->condition & GDK_INPUT_READ)
+ FD_SET (input->source, &readfds);
+ if (input->condition & GDK_INPUT_WRITE)
+ FD_SET (input->source, &writefds);
+ if (input->condition & GDK_INPUT_EXCEPTION)
+ FD_SET (input->source, &exceptfds);
+
+ max_input = MAX (max_input, input->source);
+ }
+
+ nfd = select (max_input+1, &readfds, &writefds, &exceptfds, timerp);
+
+ timerp = NULL;
+ timer_val = 0;
+
+ if (nfd > 0)
+ {
+ if (FD_ISSET (connection_number, &readfds))
+ {
+ if (XPending (gdk_display) == 0)
+ {
+ if (nfd == 1)
+ {
+ XNoOp (gdk_display);
+ XFlush (gdk_display);
+ }
+ return FALSE;
+ }
+ else
+ return TRUE;
+ }
+
+ list = inputs;
+ while (list)
+ {
+ input = list->data;
+ list = list->next;
+
+ condition = 0;
+ if (FD_ISSET (input->source, &readfds))
+ condition |= GDK_INPUT_READ;
+ if (FD_ISSET (input->source, &writefds))
+ condition |= GDK_INPUT_WRITE;
+ if (FD_ISSET (input->source, &exceptfds))
+ condition |= GDK_INPUT_EXCEPTION;
+
+ if (condition && input->function)
+ (* input->function) (input->data, input->source, condition);
+ }
+ }
+ }
+ else
+ return TRUE;
+
+ return FALSE;
+}
+
+static gint
+gdk_event_translate (GdkEvent *event,
+ XEvent *xevent)
+{
+
+ GdkWindow *window;
+ GdkWindowPrivate *window_private;
+ XComposeStatus compose;
+ int charcount;
+ char buf[16];
+ gint return_val;
+
+ /* Are static variables used for this purpose thread-safe? */
+ static GdkPoint dnd_drag_start = {0,0},
+ dnd_drag_oldpos = {0,0};
+ static GdkRectangle dnd_drag_dropzone = {0,0,0,0};
+ static gint dnd_drag_perhaps = 0;
+ static GdkWindowPrivate *real_sw = NULL;
+ static Window dnd_drag_curwin = None, dnd_drag_target = None;
+
+ return_val = FALSE;
+
+ /* Find the GdkWindow that this event occurred in.
+ * All events occur in some GdkWindow (otherwise, why
+ * would we be receiving them). It really is an error
+ * to receive an event for which we cannot find the
+ * corresponding GdkWindow. We handle events with window=None
+ * specially - they are generated by XFree86's XInput under
+ * some circumstances.
+ */
+
+ if ((xevent->xany.window == None) &&
+ gdk_input_vtable.window_none_event)
+ {
+ return_val = gdk_input_vtable.window_none_event (event,xevent);
+
+ if (return_val >= 0) /* was handled */
+ return return_val;
+ else
+ return_val = FALSE;
+ }
+
+ window = gdk_window_lookup (xevent->xany.window);
+ window_private = (GdkWindowPrivate *) window;
+
+ /* We do a "manual" conversion of the XEvent to a
+ * GdkEvent. The structures are mostly the same so
+ * the conversion is fairly straightforward. We also
+ * optionally print debugging info regarding events
+ * received.
+ */
+ /* Addendum:
+ * During drag & drop you get events where the pointer is
+ * in other windows. Need to just do finer-grained checking
+ */
+ switch (xevent->type)
+ {
+ case KeyPress:
+ /* Lookup the string corresponding to the given keysym.
+ */
+ charcount = XLookupString (&xevent->xkey, buf, 16,
+ (KeySym*) &event->key.keyval,
+ &compose);
+
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("key press:\t\twindow: %ld key: %12s %d\n",
+ xevent->xkey.window - base_id,
+ XKeysymToString (event->key.keyval),
+ event->key.keyval);
+
+ event->key.type = GDK_KEY_PRESS;
+ event->key.window = window;
+ event->key.time = xevent->xkey.time;
+ event->key.state = (GdkModifierType) xevent->xkey.state;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case KeyRelease:
+ /* Lookup the string corresponding to the given keysym.
+ */
+ charcount = XLookupString (&xevent->xkey, buf, 16,
+ (KeySym*) &event->key.keyval,
+ &compose);
+
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("key release:\t\twindow: %ld key: %12s %d\n",
+ xevent->xkey.window - base_id,
+ XKeysymToString (event->key.keyval),
+ event->key.keyval);
+
+ event->key.type = GDK_KEY_RELEASE;
+ event->key.window = window;
+ event->key.time = xevent->xkey.time;
+ event->key.state = (GdkModifierType) xevent->xkey.state;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case ButtonPress:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("button press[%d]:\t\twindow: %ld x,y: %d %d button: %d\n",
+ window_private?window_private->dnd_drag_enabled:0,
+ xevent->xbutton.window - base_id,
+ xevent->xbutton.x, xevent->xbutton.y,
+ xevent->xbutton.button);
+
+ if (window_private &&
+ (window_private->extension_events != 0) &&
+ gdk_input_ignore_core)
+ break;
+
+ event->button.type = GDK_BUTTON_PRESS;
+ event->button.window = window;
+ event->button.time = xevent->xbutton.time;
+ event->button.x = xevent->xbutton.x;
+ event->button.y = xevent->xbutton.y;
+ event->button.pressure = 0.5;
+ event->button.xtilt = 0;
+ event->button.ytilt = 0;
+ event->button.state = (GdkModifierType) xevent->xbutton.state;
+ event->button.button = xevent->xbutton.button;
+ event->button.source = GDK_SOURCE_MOUSE;
+ event->button.deviceid = GDK_CORE_POINTER;
+
+ if ((event->button.time < (button_click_time[1] + TRIPLE_CLICK_TIME)) &&
+ (event->button.window == button_window[1]) &&
+ (event->button.button == button_number[1]))
+ {
+ gdk_synthesize_click (event, 3);
+
+ button_click_time[1] = 0;
+ button_click_time[0] = 0;
+ button_window[1] = NULL;
+ button_window[0] = 0;
+ button_number[1] = -1;
+ button_number[0] = -1;
+ }
+ else if ((event->button.time < (button_click_time[0] + DOUBLE_CLICK_TIME)) &&
+ (event->button.window == button_window[0]) &&
+ (event->button.button == button_number[0]))
+ {
+ gdk_synthesize_click (event, 2);
+
+ button_click_time[1] = button_click_time[0];
+ button_click_time[0] = event->button.time;
+ button_window[1] = button_window[0];
+ button_window[0] = event->button.window;
+ button_number[1] = button_number[0];
+ button_number[0] = event->button.button;
+ }
+ else
+ {
+ button_click_time[1] = 0;
+ button_click_time[0] = event->button.time;
+ button_window[1] = NULL;
+ button_window[0] = event->button.window;
+ button_number[1] = -1;
+ button_number[0] = event->button.button;
+ }
+ if(window_private
+ && window_private->dnd_drag_enabled
+ && !dnd_drag_perhaps
+ && !gdk_dnd.drag_really)
+ {
+ dnd_drag_perhaps = 1;
+ dnd_drag_start.x = xevent->xbutton.x_root;
+ dnd_drag_start.y = xevent->xbutton.y_root;
+ real_sw = window_private;
+
+ if(gdk_dnd.drag_startwindows)
+ {
+ g_free(gdk_dnd.drag_startwindows);
+ gdk_dnd.drag_startwindows = NULL;
+ }
+ gdk_dnd.drag_numwindows = gdk_dnd.drag_really = 0;
+
+ {
+ /* Set motion mask for first DnD'd window, since it
+ will be the one that is actually dragged */
+ XWindowAttributes dnd_winattr;
+ XSetWindowAttributes dnd_setwinattr;
+ Status rv;
+
+ /* We need to get motion events while the button is down, so
+ we can know whether to really start dragging or not... */
+ XGetWindowAttributes(gdk_display, (Window)window_private->xwindow,
+ &dnd_winattr);
+
+ window_private->dnd_drag_savedeventmask = dnd_winattr.your_event_mask;
+ dnd_setwinattr.event_mask =
+ window_private->dnd_drag_eventmask = ButtonMotionMask;
+ XChangeWindowAttributes(gdk_display, window_private->xwindow,
+ CWEventMask, &dnd_setwinattr);
+ }
+ }
+ return_val = window_private?(!window_private->destroyed):FALSE;
+ break;
+
+ case ButtonRelease:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("button release[%d]:\twindow: %ld x,y: %d %d button: %d\n",
+ window_private?window_private->dnd_drag_enabled:0,
+ xevent->xbutton.window - base_id,
+ xevent->xbutton.x, xevent->xbutton.y,
+ xevent->xbutton.button);
+
+ if (window_private &&
+ (window_private->extension_events != 0) &&
+ gdk_input_ignore_core)
+ break;
+
+ event->button.type = GDK_BUTTON_RELEASE;
+ event->button.window = window;
+ event->button.time = xevent->xbutton.time;
+ event->button.x = xevent->xbutton.x;
+ event->button.y = xevent->xbutton.y;
+ event->button.pressure = 0.5;
+ event->button.xtilt = 0;
+ event->button.ytilt = 0;
+ event->button.state = (GdkModifierType) xevent->xbutton.state;
+ event->button.button = xevent->xbutton.button;
+ event->button.source = GDK_SOURCE_MOUSE;
+ event->button.deviceid = GDK_CORE_POINTER;
+
+ if(dnd_drag_perhaps)
+ {
+ if(gdk_dnd.drag_really)
+ {
+ GdkPoint foo = {xevent->xbutton.x_root,
+ xevent->xbutton.y_root};
+ XUngrabPointer(gdk_display, CurrentTime);
+
+ if(dnd_drag_target != None)
+ gdk_dnd_drag_end(dnd_drag_target, foo);
+ gdk_dnd.drag_really = 0;
+
+ if(gdk_dnd.drag_numwindows)
+ {
+ XSetWindowAttributes attrs;
+ /* Reset event mask to pre-drag value, assuming event_mask
+ doesn't change during drag */
+ attrs.event_mask = real_sw->dnd_drag_savedeventmask;
+ XChangeWindowAttributes(gdk_display, real_sw->xwindow,
+ CWEventMask, &attrs);
+ }
+
+ gdk_dnd.drag_numwindows = 0;
+ if(gdk_dnd.drag_startwindows)
+ {
+ g_free(gdk_dnd.drag_startwindows);
+ gdk_dnd.drag_startwindows = NULL;
+ }
+
+ real_sw = NULL;
+ }
+
+ dnd_drag_perhaps = 0;
+ dnd_drag_start.x = dnd_drag_start.y = 0;
+ dnd_drag_dropzone.x = dnd_drag_dropzone.y = 0;
+ dnd_drag_dropzone.width = dnd_drag_dropzone.height = 0;
+ dnd_drag_curwin = None;
+ }
+ return_val = window ? (!window_private->destroyed) : FALSE;
+ break;
+
+ case MotionNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("motion notify:\t\twindow: %ld x,y: %d %d hint: %s d:%d r%d\n",
+ xevent->xmotion.window - base_id,
+ xevent->xmotion.x, xevent->xmotion.y,
+ (xevent->xmotion.is_hint) ? "true" : "false",
+ dnd_drag_perhaps, gdk_dnd.drag_really);
+
+ if (window_private &&
+ (window_private->extension_events != 0) &&
+ gdk_input_ignore_core)
+ break;
+
+ event->motion.type = GDK_MOTION_NOTIFY;
+ event->motion.window = window;
+ event->motion.time = xevent->xmotion.time;
+ event->motion.x = xevent->xmotion.x;
+ event->motion.y = xevent->xmotion.y;
+ event->motion.pressure = 0.5;
+ event->motion.xtilt = 0;
+ event->motion.ytilt = 0;
+ event->motion.state = (GdkModifierType) xevent->xmotion.state;
+ event->motion.is_hint = xevent->xmotion.is_hint;
+ event->motion.source = GDK_SOURCE_MOUSE;
+ event->motion.deviceid = GDK_CORE_POINTER;
+
+#define IS_IN_ZONE(cx, cy) (cx >= dnd_drag_dropzone.x \
+ && cy >= dnd_drag_dropzone.y \
+ && cx < (dnd_drag_dropzone.x + dnd_drag_dropzone.width) \
+ && cy < (dnd_drag_dropzone.y + dnd_drag_dropzone.height))
+
+ if(dnd_drag_perhaps && gdk_dnd.drag_really)
+ {
+ /* First, we have to find what window the motion was in... */
+ /* XXX there has to be a better way to do this, perhaps with
+ XTranslateCoordinates or XQueryTree - I don't know how,
+ and this sort of works */
+ Window curwin, childwin = gdk_root_window, rootwinret;
+ int x, y;
+ unsigned int mask;
+ while(childwin != None)
+ {
+ curwin = childwin;
+ XQueryPointer(gdk_display, curwin, &rootwinret, &childwin,
+ &x, &y, &x, &y, &mask);
+ }
+ if(curwin != dnd_drag_curwin)
+ {
+ /* We have left one window and entered another
+ (do leave & enter bits) */
+ if(dnd_drag_curwin != real_sw->xwindow && dnd_drag_curwin != None)
+ gdk_dnd_drag_leave(dnd_drag_curwin);
+ dnd_drag_curwin = curwin;
+ gdk_dnd_drag_enter(dnd_drag_curwin);
+ dnd_drag_dropzone.x = dnd_drag_dropzone.y = 0;
+ dnd_drag_dropzone.width = dnd_drag_dropzone.height = 0;
+ dnd_drag_target = None;
+ XChangeActivePointerGrab(gdk_display,
+ ButtonMotionMask |
+ ButtonPressMask | ButtonReleaseMask |
+ EnterWindowMask | LeaveWindowMask,
+ gdk_dnd.gdk_cursor_dragdefault,
+ CurrentTime);
+ }
+ else if(dnd_drag_dropzone.width > 0
+ && dnd_drag_dropzone.height > 0)
+ {
+ /* Handle all that dropzone stuff - thanks John ;-) */
+ if(dnd_drag_target != None
+ && IS_IN_ZONE(dnd_drag_oldpos.x, dnd_drag_oldpos.y)
+ && !IS_IN_ZONE(xevent->xmotion.x_root,
+ xevent->xmotion.y_root))
+ {
+ /* We were in the drop zone and moved out */
+ dnd_drag_target = None;
+ gdk_dnd_drag_leave(curwin);
+ }
+ else
+ {
+ /* We were outside drop zone but in the window
+ - have to send enter events */
+ gdk_dnd_drag_enter(curwin);
+ dnd_drag_curwin = curwin;
+ dnd_drag_dropzone.x = dnd_drag_dropzone.y = 0;
+ dnd_drag_target = None;
+ }
+ } else
+ dnd_drag_curwin = None;
+ return_val = FALSE;
+ }
+ else
+ return_val = window?(!window_private->destroyed):FALSE;
+ break;
+
+ case EnterNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("enter notify:\t\twindow: %ld detail: %d subwin: %ld\n",
+ xevent->xcrossing.window - base_id,
+ xevent->xcrossing.detail,
+ xevent->xcrossing.subwindow - base_id);
+
+ /* Tell XInput stuff about it if appropriate */
+ if (window_private &&
+ (window_private->extension_events != 0) &&
+ gdk_input_vtable.enter_event)
+ gdk_input_vtable.enter_event (&xevent->xcrossing, window);
+
+ event->crossing.type = GDK_ENTER_NOTIFY;
+ event->crossing.window = window;
+
+ /* If the subwindow field of the XEvent is non-NULL, then
+ * lookup the corresponding GdkWindow.
+ */
+ if (xevent->xcrossing.subwindow != None)
+ event->crossing.subwindow = gdk_window_lookup (xevent->xcrossing.subwindow);
+ else
+ event->crossing.subwindow = NULL;
+
+ /* Translate the crossing detail into Gdk terms.
+ */
+ switch (xevent->xcrossing.detail)
+ {
+ case NotifyInferior:
+ event->crossing.detail = GDK_NOTIFY_INFERIOR;
+ break;
+ case NotifyAncestor:
+ event->crossing.detail = GDK_NOTIFY_ANCESTOR;
+ break;
+ case NotifyVirtual:
+ event->crossing.detail = GDK_NOTIFY_VIRTUAL;
+ break;
+ case NotifyNonlinear:
+ event->crossing.detail = GDK_NOTIFY_NONLINEAR;
+ break;
+ case NotifyNonlinearVirtual:
+ event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
+ break;
+ default:
+ event->crossing.detail = GDK_NOTIFY_UNKNOWN;
+ break;
+ }
+
+ if(dnd_drag_perhaps
+ && gdk_dnd.drag_really
+ && xevent->xcrossing.window == real_sw->xwindow)
+ {
+ gdk_dnd.drag_really = 0;
+ XUngrabPointer(gdk_display, CurrentTime);
+ }
+
+ return_val = (window ? !window_private->destroyed : FALSE);
+ break;
+
+ case LeaveNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("leave notify:\t\twindow: %ld detail: %d subwin: %ld\n",
+ xevent->xcrossing.window - base_id,
+ xevent->xcrossing.detail, xevent->xcrossing.subwindow - base_id);
+
+ event->crossing.type = GDK_LEAVE_NOTIFY;
+ event->crossing.window = window;
+
+ /* Translate the crossing detail into Gdk terms.
+ */
+ switch (xevent->xcrossing.detail)
+ {
+ case NotifyInferior:
+ event->crossing.detail = GDK_NOTIFY_INFERIOR;
+ break;
+ case NotifyAncestor:
+ event->crossing.detail = GDK_NOTIFY_ANCESTOR;
+ break;
+ case NotifyVirtual:
+ event->crossing.detail = GDK_NOTIFY_VIRTUAL;
+ break;
+ case NotifyNonlinear:
+ event->crossing.detail = GDK_NOTIFY_NONLINEAR;
+ break;
+ case NotifyNonlinearVirtual:
+ event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
+ break;
+ default:
+ event->crossing.detail = GDK_NOTIFY_UNKNOWN;
+ break;
+ }
+ if(dnd_drag_perhaps
+ && !gdk_dnd.drag_really)
+ {
+ gdk_dnd_drag_addwindow((GdkWindow *) real_sw);
+ gdk_dnd_drag_begin((GdkWindow *) real_sw);
+ XGrabPointer(gdk_display, real_sw->xwindow, False,
+ ButtonMotionMask |
+ ButtonPressMask | ButtonReleaseMask |
+ EnterWindowMask | LeaveWindowMask,
+ GrabModeAsync, GrabModeAsync, gdk_root_window,
+ gdk_dnd.gdk_cursor_dragdefault, CurrentTime);
+ gdk_dnd.drag_really = 1;
+ }
+ return_val = window ? (!window_private->destroyed) : FALSE;
+ break;
+
+ case FocusIn:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("focus in:\t\twindow: %ld\n",
+ xevent->xfocus.window - base_id);
+
+ event->focus_change.type = GDK_FOCUS_CHANGE;
+ event->focus_change.window = window;
+ event->focus_change.in = TRUE;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case FocusOut:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("focus out:\t\twindow: %ld\n",
+ xevent->xfocus.window - base_id);
+
+ event->focus_change.type = GDK_FOCUS_CHANGE;
+ event->focus_change.window = window;
+ event->focus_change.in = FALSE;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case KeymapNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("keymap notify\n");
+
+ /* Not currently handled */
+ break;
+
+ case Expose:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("expose:\t\twindow: %ld %d x,y: %d %d w,h: %d %d\n",
+ xevent->xexpose.window - base_id, xevent->xexpose.count,
+ xevent->xexpose.x, xevent->xexpose.y,
+ xevent->xexpose.width, xevent->xexpose.height);
+
+ event->expose.type = GDK_EXPOSE;
+ event->expose.window = window;
+ event->expose.area.x = xevent->xexpose.x;
+ event->expose.area.y = xevent->xexpose.y;
+ event->expose.area.width = xevent->xexpose.width;
+ event->expose.area.height = xevent->xexpose.height;
+ event->expose.count = xevent->xexpose.count;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case GraphicsExpose:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("graphics expose:\tdrawable: %ld\n",
+ xevent->xgraphicsexpose.drawable - base_id);
+
+ event->expose.type = GDK_EXPOSE;
+ event->expose.window = window;
+ event->expose.area.x = xevent->xgraphicsexpose.x;
+ event->expose.area.y = xevent->xgraphicsexpose.y;
+ event->expose.area.width = xevent->xgraphicsexpose.width;
+ event->expose.area.height = xevent->xgraphicsexpose.height;
+ event->expose.count = xevent->xexpose.count;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case NoExpose:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("no expose:\t\tdrawable: %ld\n",
+ xevent->xnoexpose.drawable - base_id);
+
+ /* Not currently handled */
+ break;
+
+ case VisibilityNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ switch (xevent->xvisibility.state)
+ {
+ case VisibilityFullyObscured:
+ g_print ("visibility notify:\twindow: %ld none\n",
+ xevent->xvisibility.window - base_id);
+ break;
+ case VisibilityPartiallyObscured:
+ g_print ("visibility notify:\twindow: %ld partial\n",
+ xevent->xvisibility.window - base_id);
+ break;
+ case VisibilityUnobscured:
+ g_print ("visibility notify:\twindow: %ld full\n",
+ xevent->xvisibility.window - base_id);
+ break;
+ }
+
+ /* Not currently handled */
+ break;
+
+ case CreateNotify:
+ /* Not currently handled */
+ break;
+
+ case DestroyNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("destroy notify:\twindow: %ld\n",
+ xevent->xdestroywindow.window - base_id);
+
+ event->any.type = GDK_DESTROY;
+ event->any.window = window;
+
+ /* Remeber which window received the destroy notify
+ * event so that we can destroy our associated
+ * data structures the next time the user asks
+ * us for an event.
+ */
+ received_destroy_notify = TRUE;
+ window_to_destroy = window;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case UnmapNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("unmap notify:\t\twindow: %ld\n",
+ xevent->xmap.window - base_id);
+
+ event->any.type = GDK_UNMAP;
+ event->any.window = window;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case MapNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("map notify:\t\twindow: %ld\n",
+ xevent->xmap.window - base_id);
+
+ event->any.type = GDK_MAP;
+ event->any.window = window;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case ReparentNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("reparent notify:\twindow: %ld\n",
+ xevent->xreparent.window - base_id);
+
+ /* Not currently handled */
+ break;
+
+ case ConfigureNotify:
+ /* Print debugging info.
+ */
+ while ((XPending(gdk_display) > 0) &&
+ XCheckTypedWindowEvent(gdk_display, xevent->xany.window,
+ ConfigureNotify, xevent))
+ /*XSync(gdk_display, 0)*/;
+
+ if (gdk_show_events)
+ g_print ("configure notify:\twindow: %ld x,y: %d %d w,h: %d %d\n",
+ xevent->xconfigure.window - base_id,
+ xevent->xconfigure.x, xevent->xconfigure.y,
+ xevent->xconfigure.width, xevent->xconfigure.height);
+
+ if (window_private &&
+ (window_private->extension_events != 0) &&
+ gdk_input_vtable.configure_event)
+ gdk_input_vtable.configure_event (&xevent->xconfigure, window);
+
+ if ((window_private->window_type != GDK_WINDOW_CHILD) &&
+ ((window_private->width != xevent->xconfigure.width) ||
+ (window_private->height != xevent->xconfigure.height)))
+ {
+ event->configure.type = GDK_CONFIGURE;
+ event->configure.window = window;
+ event->configure.x = xevent->xconfigure.x;
+ event->configure.y = xevent->xconfigure.y;
+ event->configure.width = xevent->xconfigure.width;
+ event->configure.height = xevent->xconfigure.height;
+
+ window_private->x = xevent->xconfigure.x;
+ window_private->y = xevent->xconfigure.y;
+ window_private->width = xevent->xconfigure.width;
+ window_private->height = xevent->xconfigure.height;
+ if (window_private->resize_count > 1)
+ window_private->resize_count -= 1;
+
+ return_val = !window_private->destroyed;
+ }
+ break;
+
+ case PropertyNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("property notify:\twindow: %ld\n",
+ xevent->xproperty.window - base_id);
+
+ event->property.type = GDK_PROPERTY_NOTIFY;
+ event->property.window = window;
+ event->property.atom = xevent->xproperty.atom;
+ event->property.time = xevent->xproperty.time;
+ event->property.state = xevent->xproperty.state;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case SelectionClear:
+ if (gdk_show_events)
+ g_print ("selection clear:\twindow: %ld\n",
+ xevent->xproperty.window - base_id);
+
+ event->selection.type = GDK_SELECTION_CLEAR;
+ event->selection.window = window;
+ event->selection.selection = xevent->xselectionclear.selection;
+ event->selection.time = xevent->xselectionclear.time;
+
+ return_val = !((GdkWindowPrivate*) window)->destroyed;
+ break;
+
+ case SelectionRequest:
+ if (gdk_show_events)
+ g_print ("selection request:\twindow: %ld\n",
+ xevent->xproperty.window - base_id);
+
+ event->selection.type = GDK_SELECTION_REQUEST;
+ event->selection.window = window;
+ event->selection.selection = xevent->xselectionrequest.selection;
+ event->selection.target = xevent->xselectionrequest.target;
+ event->selection.property = xevent->xselectionrequest.property;
+ event->selection.requestor = xevent->xselectionrequest.requestor;
+ event->selection.time = xevent->xselectionrequest.time;
+
+ return_val = !((GdkWindowPrivate*) window)->destroyed;
+ break;
+
+ case SelectionNotify:
+ if (gdk_show_events)
+ g_print ("selection notify:\twindow: %ld\n",
+ xevent->xproperty.window - base_id);
+
+
+ event->selection.type = GDK_SELECTION_NOTIFY;
+ event->selection.window = window;
+ event->selection.selection = xevent->xselection.selection;
+ event->selection.target = xevent->xselection.target;
+ event->selection.property = xevent->xselection.property;
+ event->selection.time = xevent->xselection.time;
+
+ return_val = !((GdkWindowPrivate*) window)->destroyed;
+ break;
+
+ case ColormapNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("colormap notify:\twindow: %ld\n",
+ xevent->xcolormap.window - base_id);
+
+ /* Not currently handled */
+ break;
+
+ case ClientMessage:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("client message:\twindow: %ld\n",
+ xevent->xclient.window - base_id);
+
+ /* Client messages are the means of the window manager
+ * communicating with a program. We'll first check to
+ * see if this is really the window manager talking
+ * to us.
+ */
+ if (xevent->xclient.message_type == gdk_wm_protocols)
+ {
+ if ((Atom) xevent->xclient.data.l[0] == gdk_wm_delete_window)
+ {
+ /* The delete window request specifies a window
+ * to delete. We don't actually destroy the
+ * window because "it is only a request". (The
+ * window might contain vital data that the
+ * program does not want destroyed). Instead
+ * the event is passed along to the program,
+ * which should then destroy the window.
+ */
+
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("delete window:\t\twindow: %ld\n",
+ xevent->xclient.window - base_id);
+
+ event->any.type = GDK_DELETE;
+ event->any.window = window;
+
+ return_val = !window_private->destroyed;
+ }
+ else if ((Atom) xevent->xclient.data.l[0] == gdk_wm_take_focus)
+ {
+ }
+ }
+ else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeEnter)
+ {
+ Atom reptype = 0;
+
+ event->dropenter.u.allflags = xevent->xclient.data.l[1];
+ if (gdk_show_events)
+ g_print ("GDK_DROP_ENTER\n");
+ return_val = FALSE;
+
+ /* Now figure out if we really want this drop...
+ * If someone is trying funky clipboard stuff, ignore
+ */
+ if (window_private
+ && window_private->dnd_drop_enabled
+ && event->dropenter.u.flags.sendreply
+ && (reptype = gdk_dnd_check_types (window, xevent)))
+ {
+ XEvent replyev;
+
+ replyev.xclient.type = ClientMessage;
+ replyev.xclient.window = xevent->xclient.data.l[0];
+ replyev.xclient.format = 32;
+ replyev.xclient.message_type = gdk_dnd.gdk_XdeRequest;
+ replyev.xclient.data.l[0] = window_private->xwindow;
+
+ event->dragrequest.u.allflags = 0;
+ event->dragrequest.u.flags.protocol_version =
+ DND_PROTOCOL_VERSION;
+ event->dragrequest.u.flags.willaccept = 1;
+ event->dragrequest.u.flags.delete_data =
+ (window_private->dnd_drop_destructive_op) ? 1 : 0;
+
+ replyev.xclient.data.l[1] = event->dragrequest.u.allflags;
+ replyev.xclient.data.l[2] = replyev.xclient.data.l[3] = 0;
+ replyev.xclient.data.l[4] = reptype;
+
+ XSendEvent (gdk_display, replyev.xclient.window,
+ False, NoEventMask, &replyev);
+
+ event->any.type = GDK_DROP_ENTER;
+ event->dropenter.requestor = replyev.xclient.window;
+ event->dropenter.u.allflags = xevent->xclient.data.l[1];
+ }
+ }
+ else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeLeave)
+ {
+ if (gdk_show_events)
+ g_print ("GDK_DROP_LEAVE\n");
+ if (window_private && window_private->dnd_drop_enabled)
+ {
+ event->dropleave.type = GDK_DROP_LEAVE;
+ event->dropleave.window = window;
+ event->dropleave.requestor = xevent->xclient.data.l[0];
+ event->dropleave.u.allflags = xevent->xclient.data.l[1];
+ return_val = TRUE;
+ }
+ else
+ return_val = FALSE;
+ }
+ else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeRequest)
+ {
+ /*
+ * make sure to only handle requests from the window the cursor is
+ * over
+ */
+ if (gdk_show_events)
+ g_print ("GDK_DRAG_REQUEST\n");
+ event->dragrequest.u.allflags = xevent->xclient.data.l[1];
+ return_val = FALSE;
+
+ if (window && gdk_dnd.drag_really &&
+ xevent->xclient.data.l[0] == dnd_drag_curwin &&
+ event->dragrequest.u.flags.sendreply == 0)
+ {
+ /* Got request - do we need to ask user? */
+ if (!event->dragrequest.u.flags.willaccept
+ && event->dragrequest.u.flags.senddata)
+ {
+ /* Yes we do :) */
+ event->dragrequest.type = GDK_DRAG_REQUEST;
+ event->dragrequest.window = window;
+ event->dragrequest.requestor = xevent->xclient.data.l[0];
+ event->dragrequest.isdrop = 0;
+ event->dragrequest.drop_coords.x =
+ event->dragrequest.drop_coords.y = 0;
+ return_val = TRUE;
+ }
+ else if (event->dragrequest.u.flags.willaccept)
+ {
+ window_private->dnd_drag_destructive_op =
+ event->dragrequest.u.flags.delete_data;
+ window_private->dnd_drag_accepted = 1;
+ window_private->dnd_drag_data_type =
+ xevent->xclient.data.l[4];
+
+ dnd_drag_target = dnd_drag_curwin;
+ XChangeActivePointerGrab (gdk_display,
+ ButtonMotionMask |
+ ButtonPressMask |
+ ButtonReleaseMask |
+ EnterWindowMask | LeaveWindowMask,
+ gdk_dnd.gdk_cursor_dragok,
+ CurrentTime);
+ }
+ dnd_drag_dropzone.x = xevent->xclient.data.l[2] & 65535;
+ dnd_drag_dropzone.y =
+ (xevent->xclient.data.l[2] >> 16) & 65535;
+ dnd_drag_dropzone.width = xevent->xclient.data.l[3] & 65535;
+ dnd_drag_dropzone.height =
+ (xevent->xclient.data.l[3] >> 16) & 65535;
+ }
+ }
+ else if(xevent->xclient.message_type == gdk_dnd.gdk_XdeDataAvailable)
+ {
+ gint tmp_int; Atom tmp_atom;
+ gulong tmp_long;
+ guchar *tmp_charptr;
+ gpointer tmp_ptr;
+
+ if(gdk_show_events)
+ g_print("GDK_DROP_DATA_AVAIL\n");
+ event->dropdataavailable.u.allflags = xevent->xclient.data.l[1];
+ if(window
+ /* No preview of data ATM */
+ && event->dropdataavailable.u.flags.isdrop)
+ {
+ event->dropdataavailable.type = GDK_DROP_DATA_AVAIL;
+ event->dropdataavailable.window = window;
+ event->dropdataavailable.requestor = xevent->xclient.data.l[0];
+ event->dropdataavailable.data_type =
+ gdk_atom_name(xevent->xclient.data.l[2]);
+ if(XGetWindowProperty (gdk_display,
+ event->dropdataavailable.requestor,
+ xevent->xclient.data.l[2],
+ 0, LONG_MAX - 1,
+ False, XA_PRIMARY, &tmp_atom,
+ &tmp_int,
+ &event->dropdataavailable.data_numbytes,
+ &tmp_long,
+ &tmp_charptr)
+ != Success)
+ {
+ g_warning("XGetWindowProperty on %#x may have failed\n",
+ event->dropdataavailable.requestor);
+ event->dropdataavailable.data = NULL;
+ }
+ else
+ {
+ g_print("XGetWindowProperty got us %d bytes\n",
+ event->dropdataavailable.data_numbytes);
+ event->dropdataavailable.data =
+ g_malloc(event->dropdataavailable.data_numbytes);
+ memcpy(event->dropdataavailable.data,
+ tmp_charptr, event->dropdataavailable.data_numbytes);
+ XFree(tmp_charptr);
+ return_val = TRUE;
+ }
+ return_val = TRUE;
+ }
+ } else {
+ /* Send unknown ClientMessage's on to Gtk for it to use */
+ event->client.type = GDK_CLIENT_EVENT;
+ event->client.window = window;
+ event->client.message_type = xevent->xclient.message_type;
+ event->client.data_format = xevent->xclient.format;
+ memcpy(&event->client.data, &xevent->xclient.data,
+ sizeof(event->client.data));
+ return_val = TRUE;
+ }
+ return_val = return_val && !window_private->destroyed;
+ break;
+
+ case MappingNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("mapping notify\n");
+
+ /* Let XLib know that there is a new keyboard mapping.
+ */
+ XRefreshKeyboardMapping (&xevent->xmapping);
+ break;
+
+ default:
+ /* something else - (e.g., a Xinput event) */
+
+ if (window_private &&
+ (window_private->extension_events != 0) &&
+ gdk_input_vtable.other_event)
+ return_val = gdk_input_vtable.other_event(event, xevent, window);
+
+ if (return_val < 0) /* not an XInput event, convert */
+ {
+ event->other.type = GDK_OTHER_EVENT;
+ event->other.window = window;
+ event->other.xevent = &other_xevent[other_xevent_i];
+ memcpy (&other_xevent[other_xevent_i], xevent, sizeof (XEvent));
+ other_xevent_i = (other_xevent_i+1) % OTHER_XEVENT_BUFSIZE;
+ return_val = TRUE;
+ }
+
+ return_val = return_val && !window_private->destroyed;
+ break;
+ }
+
+ return return_val;
+}
+
+static Bool
+gdk_event_get_type (Display *display,
+ XEvent *xevent,
+ XPointer arg)
+{
+ GdkEvent event;
+ GdkPredicate *pred;
+
+ if (gdk_event_translate (&event, xevent))
+ {
+ pred = (GdkPredicate*) arg;
+ return (* pred->func) (&event, pred->data);
+ }
+
+ return FALSE;
+}
+
+static void
+gdk_synthesize_click (GdkEvent *event,
+ gint nclicks)
+{
+ GdkEvent temp_event;
+
+ g_return_if_fail (event != NULL);
+
+ temp_event = *event;
+ temp_event.type = (nclicks == 2) ? GDK_2BUTTON_PRESS : GDK_3BUTTON_PRESS;
+
+ gdk_event_put (&temp_event);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_exit_func
+ *
+ * This is the "atexit" function that makes sure the
+ * library gets a chance to cleanup.
+ *
+ * Arguments:
+ *
+ * Results:
+ *
+ * Side effects:
+ * The library is un-initialized and the program exits.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+gdk_exit_func ()
+{
+ if (initialized)
+ {
+ gdk_image_exit ();
+ gdk_input_exit ();
+ gdk_key_repeat_restore ();
+
+ XCloseDisplay (gdk_display);
+ initialized = 0;
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_x_error
+ *
+ * The X error handling routine.
+ *
+ * Arguments:
+ * "display" is the X display the error orignated from.
+ * "error" is the XErrorEvent that we are handling.
+ *
+ * Results:
+ * Either we were expecting some sort of error to occur,
+ * in which case we set the "gdk_error_code" flag, or this
+ * error was unexpected, in which case we will print an
+ * error message and exit. (Since trying to continue will
+ * most likely simply lead to more errors).
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+gdk_x_error (Display *display,
+ XErrorEvent *error)
+{
+ char buf[64];
+
+ if (gdk_error_warnings)
+ {
+ XGetErrorText (display, error->error_code, buf, 63);
+ g_error ("%s", buf);
+ }
+
+ gdk_error_code = -1;
+ return 0;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_x_io_error
+ *
+ * The X I/O error handling routine.
+ *
+ * Arguments:
+ * "display" is the X display the error orignated from.
+ *
+ * Results:
+ * An X I/O error basically means we lost our connection
+ * to the X server. There is not much we can do to
+ * continue, so simply print an error message and exit.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+gdk_x_io_error (Display *display)
+{
+ g_error ("an x io error occurred");
+ return 0;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_signal
+ *
+ * The signal handler.
+ *
+ * Arguments:
+ * "sig_num" is the number of the signal we received.
+ *
+ * Results:
+ * The signals we catch are all fatal. So we simply build
+ * up a nice little error message and print it and exit.
+ * If in the process of doing so another signal is received
+ * we notice that we are already exiting and simply kill
+ * our process.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+static RETSIGTYPE
+gdk_signal (int sig_num)
+{
+ static int caught_fatal_sig = 0;
+ char *sig;
+
+ if (caught_fatal_sig)
+ kill (getpid (), sig_num);
+ caught_fatal_sig = 1;
+
+ switch (sig_num)
+ {
+ case SIGHUP:
+ sig = "sighup";
+ break;
+ case SIGINT:
+ sig = "sigint";
+ break;
+ case SIGQUIT:
+ sig = "sigquit";
+ break;
+ case SIGBUS:
+ sig = "sigbus";
+ break;
+ case SIGSEGV:
+ sig = "sigsegv";
+ break;
+ case SIGPIPE:
+ sig = "sigpipe";
+ break;
+ case SIGTERM:
+ sig = "sigterm";
+ break;
+ default:
+ sig = "unknown signal";
+ break;
+ }
+
+ g_print ("\n** ERROR **: %s caught\n", sig);
+ gdk_exit (1);
+}
+
+static void
+gdk_dnd_drag_begin (GdkWindow *initial_window)
+{
+ GdkEventDragBegin tev;
+ tev.type = GDK_DRAG_BEGIN;
+ tev.window = initial_window;
+ tev.u.allflags = 0;
+ tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
+
+ gdk_event_put ((GdkEvent *) &tev);
+}
+
+static void
+gdk_dnd_drag_enter (Window dest)
+{
+ XEvent sev;
+ GdkEventDropEnter tev;
+ int i;
+ GdkWindowPrivate *wp;
+
+ sev.xclient.type = ClientMessage;
+ sev.xclient.format = 32;
+ sev.xclient.message_type = gdk_dnd.gdk_XdeEnter;
+ sev.xclient.window = dest;
+
+ tev.u.allflags = 0;
+ tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
+ tev.u.flags.sendreply = 1;
+ for (i = 0; i < gdk_dnd.drag_numwindows; i++)
+ {
+ wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
+ if (wp->dnd_drag_data_numtypesavail)
+ {
+ sev.xclient.data.l[0] = wp->xwindow;
+ tev.u.flags.extended_typelist = (wp->dnd_drag_data_numtypesavail > 3)?1:0;
+ sev.xclient.data.l[1] = tev.u.allflags;
+ sev.xclient.data.l[2] = wp->dnd_drag_data_typesavail[0];
+ if (wp->dnd_drag_data_numtypesavail > 1)
+ {
+ sev.xclient.data.l[3] = wp->dnd_drag_data_typesavail[1];
+ if (wp->dnd_drag_data_numtypesavail > 2)
+ {
+ sev.xclient.data.l[4] = wp->dnd_drag_data_typesavail[2];
+ }
+ else
+ sev.xclient.data.l[4] = None;
+ }
+ else
+ sev.xclient.data.l[3] = sev.xclient.data.l[4] = None;
+ XSendEvent (gdk_display, dest, False, NoEventMask, &sev);
+ }
+
+ }
+}
+
+static void
+gdk_dnd_drag_leave (Window dest)
+{
+ XEvent sev;
+ GdkEventDropLeave tev;
+ int i;
+ GdkWindowPrivate *wp;
+
+ tev.u.allflags = 0;
+
+ tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
+ sev.xclient.type = ClientMessage;
+ sev.xclient.window = dest;
+ sev.xclient.format = 32;
+ sev.xclient.message_type = gdk_dnd.gdk_XdeLeave;
+ sev.xclient.data.l[1] = tev.u.allflags;
+ for (i = 0; i < gdk_dnd.drag_numwindows; i++)
+ {
+ wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
+ sev.xclient.data.l[0] = wp->xwindow;
+ XSendEvent(gdk_display, dest, False, NoEventMask, &sev);
+ wp->dnd_drag_accepted = 0;
+ }
+}
+
+/*
+ * when a drop occurs, we go through the list of windows being dragged and
+ * tell them that it has occurred, so that they can set things up and reply
+ * to 'dest' window
+ */
+static void
+gdk_dnd_drag_end (Window dest,
+ GdkPoint coords)
+{
+ GdkWindowPrivate *wp;
+ GdkEventDragRequest tev;
+ gchar *tmp_cptr;
+ int i;
+
+ tev.type = GDK_DRAG_REQUEST;
+ tev.drop_coords = coords;
+ tev.requestor = dest;
+ tev.u.allflags = 0;
+ tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
+ tev.isdrop = 1;
+
+ for (i = 0; i < gdk_dnd.drag_numwindows; i++)
+ {
+ wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
+ if (wp->dnd_drag_accepted)
+ {
+ tev.window = (GdkWindow *) wp;
+ tev.u.flags.delete_data = wp->dnd_drag_destructive_op;
+ tev.data_type =
+ gdk_atom_name(wp->dnd_drag_data_type);
+
+ gdk_event_put((GdkEvent *) &tev);
+ }
+ }
+}
+
+static GdkAtom
+gdk_dnd_check_types (GdkWindow *window,
+ XEvent *xevent)
+{
+ GdkWindowPrivate *wp = (GdkWindowPrivate *) window;
+ int i, j;
+ GdkEventDropEnter event;
+
+ g_return_val_if_fail(window != NULL, 0);
+ g_return_val_if_fail(xevent != NULL, 0);
+ g_return_val_if_fail(xevent->type == ClientMessage, 0);
+ g_return_val_if_fail(xevent->xclient.message_type == gdk_dnd.gdk_XdeEnter, 0);
+
+ if(wp->dnd_drop_data_numtypesavail <= 0 ||
+ !wp->dnd_drop_data_typesavail)
+ return 0;
+
+ for (i = 2; i <= 4; i++)
+ {
+ for (j = 0; j < wp->dnd_drop_data_numtypesavail; j++)
+ {
+ if (xevent->xclient.data.l[i] == wp->dnd_drop_data_typesavail[j])
+ return xevent->xclient.data.l[i];
+ }
+ }
+
+ /* Now we get the extended type list if it's available */
+ event.u.allflags = xevent->xclient.data.l[1];
+ if (event.u.flags.extended_typelist)
+ {
+ Atom *exttypes, realtype;
+ gulong nitems, nbar;
+ gint realfmt;
+
+ if (XGetWindowProperty(gdk_display, xevent->xclient.data.l[0],
+ gdk_dnd.gdk_XdeTypelist, 0L, LONG_MAX - 1,
+ False, AnyPropertyType, &realtype, &realfmt,
+ &nitems, &nbar, (unsigned char **) &exttypes)
+ != Success)
+ return 0;
+
+ if (realfmt != (sizeof(Atom) * 8))
+ {
+ g_warning("XdeTypelist property had format of %d instead of the expected %d, on window %#lx\n",
+ realfmt, sizeof(Atom) * 8, xevent->xclient.data.l[0]);
+ return 0;
+ }
+
+ for (i = 0; i <= nitems; i++)
+ {
+ for (j = 0; j < wp->dnd_drop_data_numtypesavail; j++)
+ {
+ if (exttypes[i] == wp->dnd_drop_data_typesavail[j])
+ {
+ XFree (exttypes);
+ return exttypes[i];
+ }
+ }
+ }
+ XFree (exttypes);
+ }
+ return 0;
+}
+
+/*
+ * used for debugging only
+ */
+static void
+gdk_print_atom (GdkAtom anatom)
+{
+ gchar *tmpstr = NULL;
+ tmpstr = (anatom!=None)?gdk_atom_name(anatom):"(none)";
+ g_print("Atom %lu has name %s\n", anatom, tmpstr);
+ if(tmpstr)
+ g_free(tmpstr);
+}
+
+/*
+ * used only by below routine and itself
+ */
+static Window
+getchildren (Display *dpy,
+ Window win,
+ Atom WM_STATE)
+{
+ Window root, parent, *children, inf = 0;
+ Atom type = None;
+ unsigned int nchildren, i;
+ int format;
+ unsigned long nitems, after;
+ unsigned char *data;
+
+ if (XQueryTree(dpy, win, &root, &parent, &children, &nchildren) == 0)
+ return 0;
+
+ for (i = 0; !inf && (i < nchildren); i++)
+ {
+ XGetWindowProperty (dpy, children[i], WM_STATE, 0, 0, False,
+ AnyPropertyType, &type, &format, &nitems,
+ &after, &data);
+ if (type != 0)
+ inf = children[i];
+ }
+
+ for (i = 0; !inf && (i < nchildren); i++)
+ inf = getchildren (dpy, children[i], WM_STATE);
+
+ if (children != 0)
+ XFree ((char *) children);
+
+ return inf;
+}
+
+/*
+ * find a window with WM_STATE, else return win itself, as per ICCCM
+ *
+ * modification of the XmuClientWindow() routine from X11R6.3
+ */
+Window
+gdk_get_client_window (Display *dpy,
+ Window win)
+{
+ Atom WM_STATE;
+ Atom type = None;
+ int format;
+ unsigned long nitems, after;
+ unsigned char *data;
+ Window inf;
+
+ if (win == 0)
+ return DefaultRootWindow(dpy);
+
+ if ((WM_STATE = XInternAtom (dpy, "WM_STATE", True)) == 0)
+ return win;
+
+ XGetWindowProperty (dpy, win, WM_STATE, 0, 0, False, AnyPropertyType,
+ &type, &format, &nitems, &after, &data);
+ if (type)
+ return win;
+
+ inf = getchildren (dpy, win, WM_STATE);
+
+ if (inf == 0)
+ return win;
+ else
+ return inf;
+}
+
+static GdkWindow *
+gdk_drop_get_real_window (GdkWindow *w,
+ guint16 *x,
+ guint16 *y)
+{
+ GdkWindow *retval = w;
+ GdkWindowPrivate *awin;
+ GList *children;
+ gint16 myx = *x, myy = *y;
+
+ g_return_val_if_fail(w != NULL && x != NULL && y != NULL, NULL);
+
+ myx = *x;
+ myy = *y;
+
+descend:
+ for (children = gdk_window_get_children(retval);
+ children && children->next;
+ children = children->next)
+ {
+ awin = (GdkWindowPrivate *) children->data;
+ if ((myx >= awin->x) && (myy >= awin->y)
+ && (myx < (awin->x + awin->width))
+ && (myy < (awin->y + awin->height)))
+ {
+ retval = (GdkWindow *) awin;
+ myx -= awin->x;
+ myy -= awin->y;
+ goto descend;
+ }
+ }
+
+ *x = myx;
+ *y = myy;
+
+ return retval;
+}
+
+/* Sends a ClientMessage to all toplevel client windows */
+void
+gdk_event_send_clientmessage_toall(GdkEvent *event)
+{
+ XEvent sev;
+ Window *ret_children, ret_root, ret_parent, curwin;
+ unsigned int ret_nchildren;
+ int i;
+
+ g_return_if_fail(event != NULL);
+
+ /* Set up our event to send, with the exception of its target window */
+ sev.xclient.type = ClientMessage;
+ sev.xclient.display = gdk_display;
+ sev.xclient.format = event->client.data_format;
+ sev.xclient.serial = CurrentTime;
+ memcpy(&sev.xclient.data, &event->client.data, sizeof(sev.xclient.data));
+ sev.xclient.message_type = event->client.message_type;
+
+ /* OK, we're all set, now let's find some windows to send this to */
+ if(XQueryTree(gdk_display, gdk_root_window, &ret_root, &ret_parent,
+ &ret_children, &ret_nchildren) != True)
+ return;
+
+ /* foreach true child window of the root window, send an event to it */
+ for(i = 0; i < ret_nchildren; i++) {
+ curwin = gdk_get_client_window(gdk_display, ret_children[i]);
+ sev.xclient.window = curwin;
+ XSendEvent(gdk_display, curwin, False, NoEventMask, &sev);
+ }
+
+ XFree(ret_children);
+}
diff --git a/gdk/gdk.h b/gdk/gdk.h
new file mode 100644
index 000000000..ac341b206
--- /dev/null
+++ b/gdk/gdk.h
@@ -0,0 +1,614 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GDK_H__
+#define __GDK_H__
+
+
+#include <gdk/gdktypes.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* Initialization, exit and events
+ */
+void gdk_init (int *argc,
+ char ***argv);
+void gdk_exit (int error_code);
+gchar* gdk_set_locale (void);
+
+gint gdk_events_pending (void);
+gint gdk_event_get (GdkEvent *event,
+ GdkEventFunc pred,
+ gpointer data);
+void gdk_event_put (GdkEvent *event);
+
+GdkEvent *gdk_event_copy (GdkEvent *event);
+void gdk_event_free (GdkEvent *event);
+
+void gdk_set_debug_level (gint level);
+void gdk_set_show_events (gint show_events);
+void gdk_set_use_xshm (gint use_xshm);
+
+gint gdk_get_debug_level (void);
+gint gdk_get_show_events (void);
+gint gdk_get_use_xshm (void);
+
+guint32 gdk_time_get (void);
+guint32 gdk_timer_get (void);
+void gdk_timer_set (guint32 milliseconds);
+void gdk_timer_enable (void);
+void gdk_timer_disable (void);
+
+gint gdk_input_add (gint source,
+ GdkInputCondition condition,
+ GdkInputFunction function,
+ gpointer data);
+void gdk_input_remove (gint tag);
+
+gint gdk_pointer_grab (GdkWindow * window,
+ gint owner_events,
+ GdkEventMask event_mask,
+ GdkWindow * confine_to,
+ GdkCursor * cursor,
+ guint32 time);
+void gdk_pointer_ungrab (guint32 time);
+
+gint gdk_keyboard_grab (GdkWindow * window,
+ gint owner_events,
+ guint32 time);
+void gdk_keyboard_ungrab (guint32 time);
+
+gint gdk_screen_width (void);
+gint gdk_screen_height (void);
+
+void gdk_flush (void);
+void gdk_beep (void);
+
+void gdk_key_repeat_disable (void);
+void gdk_key_repeat_restore (void);
+
+
+/* Visuals
+ */
+gint gdk_visual_get_best_depth (void);
+GdkVisualType gdk_visual_get_best_type (void);
+GdkVisual* gdk_visual_get_system (void);
+GdkVisual* gdk_visual_get_best (void);
+GdkVisual* gdk_visual_get_best_with_depth (gint depth);
+GdkVisual* gdk_visual_get_best_with_type (GdkVisualType visual_type);
+GdkVisual* gdk_visual_get_best_with_both (gint depth,
+ GdkVisualType visual_type);
+
+/* Actually, these are no-ops... */
+GdkVisual* gdk_visual_ref (GdkVisual *visual);
+void gdk_visual_unref (GdkVisual *visual);
+
+void gdk_query_depths (gint **depths,
+ gint *count);
+void gdk_query_visual_types (GdkVisualType **visual_types,
+ gint *count);
+void gdk_query_visuals (GdkVisual **visuals,
+ gint *count);
+
+
+/* Windows
+ */
+GdkWindow* gdk_window_new (GdkWindow *parent,
+ GdkWindowAttr *attributes,
+ gint attributes_mask);
+
+GdkWindow * gdk_window_foreign_new (guint32 anid);
+void gdk_window_destroy (GdkWindow *window);
+GdkWindow* gdk_window_ref (GdkWindow *window);
+void gdk_window_unref (GdkWindow *window);
+
+void gdk_window_show (GdkWindow *window);
+void gdk_window_hide (GdkWindow *window);
+void gdk_window_move (GdkWindow *window,
+ gint x,
+ gint y);
+void gdk_window_resize (GdkWindow *window,
+ gint width,
+ gint height);
+void gdk_window_move_resize (GdkWindow *window,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
+void gdk_window_reparent (GdkWindow *window,
+ GdkWindow *new_parent,
+ gint x,
+ gint y);
+void gdk_window_clear (GdkWindow *window);
+void gdk_window_clear_area (GdkWindow *window,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
+void gdk_window_clear_area_e(GdkWindow *window,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
+void gdk_window_copy_area (GdkWindow *window,
+ GdkGC *gc,
+ gint x,
+ gint y,
+ GdkWindow *source_window,
+ gint source_x,
+ gint source_y,
+ gint width,
+ gint height);
+void gdk_window_raise (GdkWindow *window);
+void gdk_window_lower (GdkWindow *window);
+
+void gdk_window_set_user_data (GdkWindow *window,
+ gpointer user_data);
+
+
+/*
+ * This allows for making shaped (partially transparent) windows
+ * - cool feature, needed for Drag and Drag for example.
+ * The shape_mask can be the mask
+ * from gdk_pixmap_create_from_xpm. Stefan Wille
+ */
+void gdk_window_shape_combine_mask (GdkWindow *window,
+ GdkBitmap *shape_mask,
+ gint offset_x,
+ gint offset_y);
+
+/*
+ * Drag & Drop
+ * Algorithm (drop source):
+ * A window being dragged will be sent a GDK_DRAG_BEGIN message.
+ * It will then do gdk_dnd_drag_addwindow() for any other windows that are to be
+ * dragged.
+ * When we get a DROP_ENTER incoming, we send it on to the window in question.
+ * That window needs to use gdk_dnd_drop_enter_reply() to indicate the state of
+ * things (it must call that even if it's not going to accept the drop)
+ *
+ * These two turn on/off drag or drop, and if enabling it also
+ * sets the list of types supported. The list of types passed in
+ * should be in order of decreasing preference.
+ */
+void gdk_window_dnd_drag_set (GdkWindow *window,
+ guint8 drag_enable,
+ gchar **typelist,
+ guint numtypes);
+
+/*
+ *XXX todo: add a GDK_DROP_ENTER which can look at actual data
+ */
+void gdk_window_dnd_drop_set (GdkWindow *window,
+ guint8 drop_enable,
+ gchar **typelist,
+ guint numtypes,
+ guint8 destructive_op);
+
+/*
+ * This is used by the GDK_DRAG_BEGIN handler. An example of usage would be a
+ * file manager where multiple icons were selected and the drag began.
+ * The icon that the drag actually began on would gdk_dnd_drag_addwindow
+ * for all the other icons that were being dragged...
+ */
+void gdk_dnd_drag_addwindow (GdkWindow *window);
+void gdk_window_dnd_data_set (GdkWindow *window,
+ GdkEvent *event,
+ gpointer data,
+ gulong data_numbytes);
+
+
+void gdk_window_set_hints (GdkWindow *window,
+ gint x,
+ gint y,
+ gint min_width,
+ gint min_height,
+ gint max_width,
+ gint max_height,
+ gint flags);
+void gdk_window_set_title (GdkWindow *window,
+ const gchar *title);
+void gdk_window_set_background (GdkWindow *window,
+ GdkColor *color);
+void gdk_window_set_back_pixmap (GdkWindow *window,
+ GdkPixmap *pixmap,
+ gint parent_relative);
+void gdk_window_set_cursor (GdkWindow *window,
+ GdkCursor *cursor);
+void gdk_window_set_colormap (GdkWindow *window,
+ GdkColormap *colormap);
+void gdk_window_get_user_data (GdkWindow *window,
+ gpointer *data);
+void gdk_window_get_geometry (GdkWindow *window,
+ gint *x,
+ gint *y,
+ gint *width,
+ gint *height,
+ gint *depth);
+void gdk_window_get_position (GdkWindow *window,
+ gint *x,
+ gint *y);
+void gdk_window_get_size (GdkWindow *window,
+ gint *width,
+ gint *height);
+GdkVisual* gdk_window_get_visual (GdkWindow *window);
+GdkColormap* gdk_window_get_colormap (GdkWindow *window);
+GdkWindowType gdk_window_get_type (GdkWindow *window);
+gint gdk_window_get_origin (GdkWindow *window,
+ gint *x,
+ gint *y);
+GdkWindow* gdk_window_get_pointer (GdkWindow *window,
+ gint *x,
+ gint *y,
+ GdkModifierType *mask);
+GdkWindow* gdk_window_get_parent (GdkWindow *window);
+GdkWindow* gdk_window_get_toplevel (GdkWindow *window);
+GList* gdk_window_get_children (GdkWindow *window);
+GdkEventMask gdk_window_get_events (GdkWindow *window);
+void gdk_window_set_events (GdkWindow *window,
+ GdkEventMask event_mask);
+
+/* Cursors
+ */
+GdkCursor* gdk_cursor_new (GdkCursorType cursor_type);
+void gdk_cursor_destroy (GdkCursor *cursor);
+
+
+/* GCs
+ */
+GdkGC* gdk_gc_new (GdkWindow *window);
+GdkGC* gdk_gc_new_with_values (GdkWindow *window,
+ GdkGCValues *values,
+ GdkGCValuesMask values_mask);
+void gdk_gc_destroy (GdkGC *gc);
+void gdk_gc_get_values (GdkGC *gc,
+ GdkGCValues *values);
+void gdk_gc_set_foreground (GdkGC *gc,
+ GdkColor *color);
+void gdk_gc_set_background (GdkGC *gc,
+ GdkColor *color);
+void gdk_gc_set_font (GdkGC *gc,
+ GdkFont *font);
+void gdk_gc_set_function (GdkGC *gc,
+ GdkFunction function);
+void gdk_gc_set_fill (GdkGC *gc,
+ GdkFill fill);
+void gdk_gc_set_tile (GdkGC *gc,
+ GdkPixmap *tile);
+void gdk_gc_set_stipple (GdkGC *gc,
+ GdkPixmap *stipple);
+void gdk_gc_set_ts_origin (GdkGC *gc,
+ gint x,
+ gint y);
+void gdk_gc_set_clip_origin (GdkGC *gc,
+ gint x,
+ gint y);
+void gdk_gc_set_clip_mask (GdkGC *gc,
+ GdkBitmap *mask);
+void gdk_gc_set_clip_rectangle (GdkGC *gc,
+ GdkRectangle *rectangle);
+void gdk_gc_set_subwindow (GdkGC *gc,
+ GdkSubwindowMode mode);
+void gdk_gc_set_exposures (GdkGC *gc,
+ gint exposures);
+void gdk_gc_set_line_attributes (GdkGC *gc,
+ gint line_width,
+ GdkLineStyle line_style,
+ GdkCapStyle cap_style,
+ GdkJoinStyle join_style);
+
+
+/* Pixmaps
+ */
+GdkPixmap* gdk_pixmap_new (GdkWindow *window,
+ gint width,
+ gint height,
+ gint depth);
+GdkBitmap* gdk_bitmap_create_from_data (GdkWindow *window,
+ gchar *data,
+ gint width,
+ gint height);
+GdkPixmap* gdk_pixmap_create_from_data (GdkWindow *window,
+ gchar *data,
+ gint width,
+ gint height,
+ gint depth,
+ GdkColor *fg,
+ GdkColor *bg);
+GdkPixmap* gdk_pixmap_create_from_xpm (GdkWindow *window,
+ GdkBitmap **mask,
+ GdkColor *transparent_color,
+ const gchar *filename);
+GdkPixmap* gdk_pixmap_create_from_xpm_d (GdkWindow *window,
+ GdkBitmap **mask,
+ GdkColor *transparent_color,
+ gchar **data);
+void gdk_pixmap_destroy (GdkPixmap *pixmap);
+
+
+
+/* Images
+ */
+GdkImage* gdk_image_new_bitmap(GdkVisual *,
+ gpointer,
+ gint,
+ gint);
+GdkImage* gdk_image_new (GdkImageType type,
+ GdkVisual *visual,
+ gint width,
+ gint height);
+GdkImage* gdk_image_get (GdkWindow *window,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
+void gdk_image_put_pixel (GdkImage *image,
+ gint x,
+ gint y,
+ guint32 pixel);
+guint32 gdk_image_get_pixel (GdkImage *image,
+ gint x,
+ gint y);
+void gdk_image_destroy (GdkImage *image);
+
+
+/* Color
+ */
+GdkColormap* gdk_colormap_new (GdkVisual *visual,
+ gint allocate);
+void gdk_colormap_destroy (GdkColormap *colormap);
+
+GdkColormap* gdk_colormap_ref (GdkColormap *cmap);
+void gdk_colormap_unref (GdkColormap *cmap);
+
+GdkColormap* gdk_colormap_get_system (void);
+gint gdk_colormap_get_system_size (void);
+
+void gdk_colormap_change (GdkColormap *colormap,
+ gint ncolors);
+void gdk_colors_store (GdkColormap *colormap,
+ GdkColor *colors,
+ gint ncolors);
+gint gdk_colors_alloc (GdkColormap *colormap,
+ gint contiguous,
+ gulong *planes,
+ gint nplanes,
+ gulong *pixels,
+ gint npixels);
+void gdk_colors_free (GdkColormap *colormap,
+ gulong *pixels,
+ gint npixels,
+ gulong planes);
+gint gdk_color_white (GdkColormap *colormap,
+ GdkColor *color);
+gint gdk_color_black (GdkColormap *colormap,
+ GdkColor *color);
+gint gdk_color_parse (const gchar *spec,
+ GdkColor *color);
+gint gdk_color_alloc (GdkColormap *colormap,
+ GdkColor *color);
+gint gdk_color_change (GdkColormap *colormap,
+ GdkColor *color);
+gint gdk_color_equal (GdkColor *colora,
+ GdkColor *colorb);
+
+
+/* Fonts
+ */
+GdkFont* gdk_font_load (const gchar *font_name);
+GdkFont* gdk_fontset_load (gchar *fontset_name);
+void gdk_font_free (GdkFont *font);
+void gdk_fontset_free (GdkFont *font);
+GdkFont* gdk_font_ref (GdkFont *font);
+gint gdk_font_id (GdkFont *font);
+gint gdk_font_equal (GdkFont *fonta,
+ GdkFont *fontb);
+gint gdk_string_width (GdkFont *font,
+ const gchar *string);
+gint gdk_text_width (GdkFont *font,
+ const gchar *text,
+ gint text_length);
+gint gdk_char_width (GdkFont *font,
+ gchar character);
+gint gdk_string_measure (GdkFont *font,
+ const gchar *string);
+gint gdk_text_measure (GdkFont *font,
+ const gchar *text,
+ gint text_length);
+gint gdk_char_measure (GdkFont *font,
+ gchar character);
+
+
+/* Drawing
+ */
+void gdk_draw_point (GdkDrawable *drawable,
+ GdkGC *gc,
+ gint x,
+ gint y);
+void gdk_draw_line (GdkDrawable *drawable,
+ GdkGC *gc,
+ gint x1,
+ gint y1,
+ gint x2,
+ gint y2);
+void gdk_draw_rectangle (GdkDrawable *drawable,
+ GdkGC *gc,
+ gint filled,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
+void gdk_draw_arc (GdkDrawable *drawable,
+ GdkGC *gc,
+ gint filled,
+ gint x,
+ gint y,
+ gint width,
+ gint height,
+ gint angle1,
+ gint angle2);
+void gdk_draw_polygon (GdkDrawable *drawable,
+ GdkGC *gc,
+ gint filled,
+ GdkPoint *points,
+ gint npoints);
+void gdk_draw_string (GdkDrawable *drawable,
+ GdkFont *font,
+ GdkGC *gc,
+ gint x,
+ gint y,
+ const gchar *string);
+void gdk_draw_text (GdkDrawable *drawable,
+ GdkFont *font,
+ GdkGC *gc,
+ gint x,
+ gint y,
+ const gchar *text,
+ gint text_length);
+void gdk_draw_pixmap (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkDrawable *src,
+ gint xsrc,
+ gint ysrc,
+ gint xdest,
+ gint ydest,
+ gint width,
+ gint height);
+void gdk_draw_bitmap (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkDrawable *src,
+ gint xsrc,
+ gint ysrc,
+ gint xdest,
+ gint ydest,
+ gint width,
+ gint height);
+void gdk_draw_image (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkImage *image,
+ gint xsrc,
+ gint ysrc,
+ gint xdest,
+ gint ydest,
+ gint width,
+ gint height);
+void gdk_draw_points (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkPoint *points,
+ gint npoints);
+void gdk_draw_segments (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkSegment *segs,
+ gint nsegs);
+
+
+/* Selections
+ */
+gint gdk_selection_owner_set (GdkWindow *owner,
+ GdkAtom selection,
+ guint32 time,
+ gint send_event);
+GdkWindow* gdk_selection_owner_get (GdkAtom selection);
+void gdk_selection_convert (GdkWindow *requestor,
+ GdkAtom selection,
+ GdkAtom target,
+ guint32 time);
+gint gdk_selection_property_get (GdkWindow *requestor,
+ guchar **data,
+ GdkAtom *prop_type,
+ gint *prop_format);
+void gdk_selection_send_notify (guint32 requestor,
+ GdkAtom selection,
+ GdkAtom target,
+ GdkAtom property,
+ guint32 time);
+
+/* Properties
+ */
+GdkAtom gdk_atom_intern (const gchar *atom_name,
+ gint only_if_exists);
+gchar* gdk_atom_name (GdkAtom atom);
+gint gdk_property_get (GdkWindow *window,
+ GdkAtom property,
+ GdkAtom type,
+ gulong offset,
+ gulong length,
+ gint pdelete,
+ GdkAtom *actual_property_type,
+ gint *actual_format,
+ gint *actual_length,
+ guchar **data);
+
+void gdk_property_change (GdkWindow *window,
+ GdkAtom property,
+ GdkAtom type,
+ gint format,
+ GdkPropMode mode,
+ guchar *data,
+ gint nelements);
+void gdk_property_delete (GdkWindow *window,
+ GdkAtom property);
+
+
+/* Rectangle utilities
+ */
+gint gdk_rectangle_intersect (GdkRectangle *src1,
+ GdkRectangle *src2,
+ GdkRectangle *dest);
+
+/* XInput support
+ */
+
+void gdk_input_init (void);
+void gdk_input_exit (void);
+GList *gdk_input_list_devices (void);
+void gdk_input_set_extension_events (GdkWindow *window,
+ gint mask,
+ GdkExtensionMode mode);
+void gdk_input_set_source (guint32 deviceid,
+ GdkInputSource source);
+gint gdk_input_set_mode (guint32 deviceid,
+ GdkInputMode mode);
+void gdk_input_set_axes (guint32 deviceid,
+ GdkAxisUse *axes);
+void gdk_input_window_get_pointer (GdkWindow *window,
+ guint32 deviceid,
+ gdouble *x,
+ gdouble *y,
+ gdouble *pressure,
+ gdouble *xtilt,
+ gdouble *ytilt,
+ GdkModifierType *mask);
+
+GdkTimeCoord *gdk_input_motion_events (GdkWindow *window,
+ guint32 deviceid,
+ guint32 start,
+ guint32 stop,
+ gint *nevents_return);
+
+/* Miscellaneous */
+void gdk_event_send_clientmessage_toall(GdkEvent *event);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GDK_H__ */
diff --git a/gdk/gdkcolor.c b/gdk/gdkcolor.c
new file mode 100644
index 000000000..5e66f089b
--- /dev/null
+++ b/gdk/gdkcolor.c
@@ -0,0 +1,718 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <X11/Xlib.h>
+#include "gdk.h"
+#include "gdkprivate.h"
+
+
+static gint gdk_colormap_match_color (GdkColormap *cmap,
+ GdkColor *color,
+ const gchar *available);
+static void gdk_colormap_add (GdkColormap *cmap);
+static void gdk_colormap_remove (GdkColormap *cmap);
+static guint gdk_colormap_hash (Colormap *cmap);
+static gint gdk_colormap_cmp (Colormap *a,
+ Colormap *b);
+
+static GHashTable *colormap_hash = NULL;
+
+
+GdkColormap*
+gdk_colormap_new (GdkVisual *visual,
+ gint private_cmap)
+{
+ GdkColormap *colormap;
+ GdkColormapPrivate *private;
+ Visual *xvisual;
+ XColor default_colors[256];
+ int size;
+ int i;
+
+ g_return_val_if_fail (visual != NULL, NULL);
+
+ private = g_new (GdkColormapPrivate, 1);
+ colormap = (GdkColormap*) private;
+
+ private->xdisplay = gdk_display;
+ private->visual = visual;
+ private->next_color = 0;
+ private->ref_count = 1;
+ xvisual = ((GdkVisualPrivate*) visual)->xvisual;
+
+ switch (visual->type)
+ {
+ case GDK_VISUAL_GRAYSCALE:
+ case GDK_VISUAL_PSEUDO_COLOR:
+ private->private_val = private_cmap;
+ private->xcolormap = XCreateColormap (private->xdisplay, gdk_root_window,
+ xvisual, (private_cmap) ? (AllocAll) : (AllocNone));
+
+ if (private_cmap)
+ {
+ for (i = 0; i < 256; i++)
+ default_colors[i].pixel = i;
+
+ XQueryColors (private->xdisplay,
+ DefaultColormap (private->xdisplay, gdk_screen),
+ default_colors, visual->colormap_size);
+
+ for (i = 0; i < visual->colormap_size; i++)
+ {
+ colormap->colors[i].pixel = default_colors[i].pixel;
+ colormap->colors[i].red = default_colors[i].red;
+ colormap->colors[i].green = default_colors[i].green;
+ colormap->colors[i].blue = default_colors[i].blue;
+ }
+
+ gdk_colormap_change (colormap, visual->colormap_size);
+ }
+ break;
+
+ case GDK_VISUAL_DIRECT_COLOR:
+ private->private_val = TRUE;
+ private->xcolormap = XCreateColormap (private->xdisplay, gdk_root_window,
+ xvisual, AllocAll);
+
+ size = 1 << visual->red_prec;
+ for (i = 0; i < size; i++)
+ colormap->colors[i].red = i * 65535 / (size - 1);
+
+ size = 1 << visual->green_prec;
+ for (i = 0; i < size; i++)
+ colormap->colors[i].green = i * 65535 / (size - 1);
+
+ size = 1 << visual->blue_prec;
+ for (i = 0; i < size; i++)
+ colormap->colors[i].blue = i * 65535 / (size - 1);
+
+ gdk_colormap_change (colormap, visual->colormap_size);
+ break;
+
+ case GDK_VISUAL_STATIC_GRAY:
+ case GDK_VISUAL_STATIC_COLOR:
+ case GDK_VISUAL_TRUE_COLOR:
+ private->private_val = FALSE;
+ private->xcolormap = XCreateColormap (private->xdisplay, gdk_root_window,
+ xvisual, AllocNone);
+ break;
+ }
+
+ gdk_colormap_add (colormap);
+
+ return colormap;
+}
+
+void
+gdk_colormap_real_destroy (GdkColormap *colormap)
+{
+ GdkColormapPrivate *private = (GdkColormapPrivate*) colormap;
+
+ g_return_if_fail (colormap != NULL);
+
+ if (private->ref_count > 0)
+ return;
+
+ gdk_colormap_remove (colormap);
+ XFreeColormap (private->xdisplay, private->xcolormap);
+ g_free (colormap);
+}
+
+void
+gdk_colormap_destroy (GdkColormap *colormap)
+{
+ gdk_colormap_unref (colormap);
+}
+
+GdkColormap*
+gdk_colormap_ref (GdkColormap *cmap)
+{
+ GdkColormapPrivate *private = (GdkColormapPrivate *)cmap;
+ g_return_val_if_fail (cmap != NULL, NULL);
+
+ private->ref_count += 1;
+ return cmap;
+}
+
+void
+gdk_colormap_unref (GdkColormap *cmap)
+{
+ GdkColormapPrivate *private = (GdkColormapPrivate *)cmap;
+ g_return_if_fail (cmap != NULL);
+
+ private->ref_count -= 1;
+ if (private->ref_count == 0)
+ gdk_colormap_real_destroy (cmap);
+}
+
+GdkColormap*
+gdk_colormap_get_system (void)
+{
+ static GdkColormap *colormap = NULL;
+ GdkColormapPrivate *private;
+ XColor xpalette[256];
+ gint i;
+
+ if (!colormap)
+ {
+ private = g_new (GdkColormapPrivate, 1);
+ colormap = (GdkColormap*) private;
+
+ private->xdisplay = gdk_display;
+ private->xcolormap = DefaultColormap (gdk_display, gdk_screen);
+ private->visual = gdk_visual_get_system ();
+ private->private_val = FALSE;
+ private->next_color = 0;
+ private->ref_count = 1;
+
+ for (i = 0; i < 256; i++)
+ {
+ xpalette[i].pixel = i;
+ xpalette[i].red = 0;
+ xpalette[i].green = 0;
+ xpalette[i].blue = 0;
+ }
+
+ XQueryColors (gdk_display, private->xcolormap, xpalette, 256);
+
+ for (i = 0; i < 256; i++)
+ {
+ colormap->colors[i].pixel = xpalette[i].pixel;
+ colormap->colors[i].red = xpalette[i].red;
+ colormap->colors[i].green = xpalette[i].green;
+ colormap->colors[i].blue = xpalette[i].blue;
+ }
+
+ gdk_colormap_add (colormap);
+ }
+
+ return colormap;
+}
+
+gint
+gdk_colormap_get_system_size (void)
+{
+ return DisplayCells (gdk_display, gdk_screen);
+}
+
+void
+gdk_colormap_change (GdkColormap *colormap,
+ gint ncolors)
+{
+ GdkColormapPrivate *private;
+ GdkVisual *visual;
+ XColor palette[256];
+ gint shift;
+ int max_colors;
+ int size;
+ int i;
+
+ g_return_if_fail (colormap != NULL);
+
+ private = (GdkColormapPrivate*) colormap;
+ switch (private->visual->type)
+ {
+ case GDK_VISUAL_GRAYSCALE:
+ case GDK_VISUAL_PSEUDO_COLOR:
+ for (i = 0; i < ncolors; i++)
+ {
+ palette[i].pixel = colormap->colors[i].pixel;
+ palette[i].red = colormap->colors[i].red;
+ palette[i].green = colormap->colors[i].green;
+ palette[i].blue = colormap->colors[i].blue;
+ palette[i].flags = DoRed | DoGreen | DoBlue;
+ }
+
+ XStoreColors (private->xdisplay, private->xcolormap, palette, ncolors);
+ private->next_color = MAX (private->next_color, ncolors);
+ break;
+
+ case GDK_VISUAL_DIRECT_COLOR:
+ visual = private->visual;
+
+ shift = visual->red_shift;
+ max_colors = 1 << visual->red_prec;
+ size = (ncolors < max_colors) ? (ncolors) : (max_colors);
+
+ for (i = 0; i < size; i++)
+ {
+ palette[i].pixel = i << shift;
+ palette[i].red = colormap->colors[i].red;
+ palette[i].flags = DoRed;
+ }
+
+ XStoreColors (private->xdisplay, private->xcolormap, palette, size);
+
+ shift = visual->green_shift;
+ max_colors = 1 << visual->green_prec;
+ size = (ncolors < max_colors) ? (ncolors) : (max_colors);
+
+ for (i = 0; i < size; i++)
+ {
+ palette[i].pixel = i << shift;
+ palette[i].green = colormap->colors[i].green;
+ palette[i].flags = DoGreen;
+ }
+
+ XStoreColors (private->xdisplay, private->xcolormap, palette, size);
+
+ shift = visual->blue_shift;
+ max_colors = 1 << visual->blue_prec;
+ size = (ncolors < max_colors) ? (ncolors) : (max_colors);
+
+ for (i = 0; i < size; i++)
+ {
+ palette[i].pixel = i << shift;
+ palette[i].blue = colormap->colors[i].blue;
+ palette[i].flags = DoBlue;
+ }
+
+ XStoreColors (private->xdisplay, private->xcolormap, palette, size);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void
+gdk_colors_store (GdkColormap *colormap,
+ GdkColor *colors,
+ gint ncolors)
+{
+ gint i;
+
+ for (i = 0; i < ncolors; i++)
+ {
+ colormap->colors[i].pixel = colors[i].pixel;
+ colormap->colors[i].red = colors[i].red;
+ colormap->colors[i].green = colors[i].green;
+ colormap->colors[i].blue = colors[i].blue;
+ }
+
+ gdk_colormap_change (colormap, ncolors);
+}
+
+gint
+gdk_colors_alloc (GdkColormap *colormap,
+ gint contiguous,
+ gulong *planes,
+ gint nplanes,
+ gulong *pixels,
+ gint npixels)
+{
+ GdkColormapPrivate *private;
+ gint return_val;
+
+ g_return_val_if_fail (colormap != NULL, 0);
+
+ private = (GdkColormapPrivate*) colormap;
+
+ return_val = XAllocColorCells (private->xdisplay, private->xcolormap,
+ contiguous, planes, nplanes, pixels, npixels);
+
+ return return_val;
+}
+
+void
+gdk_colors_free (GdkColormap *colormap,
+ gulong *pixels,
+ gint npixels,
+ gulong planes)
+{
+ GdkColormapPrivate *private;
+
+ g_return_if_fail (colormap != NULL);
+
+ private = (GdkColormapPrivate*) colormap;
+
+ XFreeColors (private->xdisplay, private->xcolormap,
+ pixels, npixels, planes);
+}
+
+gint
+gdk_color_white (GdkColormap *colormap,
+ GdkColor *color)
+{
+ gint return_val;
+
+ g_return_val_if_fail (colormap != NULL, FALSE);
+
+ if (color)
+ {
+ color->pixel = WhitePixel (gdk_display, gdk_screen);
+ color->red = 65535;
+ color->green = 65535;
+ color->blue = 65535;
+
+ return_val = gdk_color_alloc (colormap, color);
+ }
+ else
+ return_val = FALSE;
+
+ return return_val;
+}
+
+gint
+gdk_color_black (GdkColormap *colormap,
+ GdkColor *color)
+{
+ gint return_val;
+
+ g_return_val_if_fail (colormap != NULL, FALSE);
+
+ if (color)
+ {
+ color->pixel = BlackPixel (gdk_display, gdk_screen);
+ color->red = 0;
+ color->green = 0;
+ color->blue = 0;
+
+ return_val = gdk_color_alloc (colormap, color);
+ }
+ else
+ return_val = FALSE;
+
+ return return_val;
+}
+
+gint
+gdk_color_parse (const gchar *spec,
+ GdkColor *color)
+{
+ Colormap xcolormap;
+ XColor xcolor;
+ gint return_val;
+
+ g_return_val_if_fail (spec != NULL, FALSE);
+ g_return_val_if_fail (color != NULL, FALSE);
+
+ xcolormap = DefaultColormap (gdk_display, gdk_screen);
+
+ if (XParseColor (gdk_display, xcolormap, spec, &xcolor))
+ {
+ return_val = TRUE;
+ color->red = xcolor.red;
+ color->green = xcolor.green;
+ color->blue = xcolor.blue;
+ }
+ else
+ return_val = FALSE;
+
+ return return_val;
+}
+
+gint
+gdk_color_alloc (GdkColormap *colormap,
+ GdkColor *color)
+{
+ GdkColormapPrivate *private;
+ GdkVisual *visual;
+ XColor xcolor;
+ gchar available[256];
+ gint available_init;
+ gint return_val;
+ gint i, index;
+
+ g_return_val_if_fail (colormap != NULL, FALSE);
+ g_return_val_if_fail (color != NULL, FALSE);
+
+ xcolor.red = color->red;
+ xcolor.green = color->green;
+ xcolor.blue = color->blue;
+ xcolor.pixel = color->pixel;
+ xcolor.flags = DoRed | DoGreen | DoBlue;
+
+ return_val = FALSE;
+ private = (GdkColormapPrivate*) colormap;
+
+ switch (private->visual->type)
+ {
+ case GDK_VISUAL_GRAYSCALE:
+ case GDK_VISUAL_PSEUDO_COLOR:
+ if (private->private_val)
+ {
+ if (private->next_color > 255)
+ {
+ for (i = 0; i < 256; i++)
+ available[i] = TRUE;
+
+ index = gdk_colormap_match_color (colormap, color, available);
+ if (index != -1)
+ {
+ available[index] = FALSE;
+ *color = colormap->colors[index];
+ return_val = TRUE;
+ }
+ else
+ {
+ return_val = FALSE;
+ }
+ }
+ else
+ {
+ xcolor.pixel = 255 - private->next_color;
+ color->pixel = xcolor.pixel;
+ private->next_color += 1;
+
+ XStoreColor (private->xdisplay, private->xcolormap, &xcolor);
+ return_val = TRUE;
+ }
+ }
+ else
+ {
+ available_init = 1;
+
+ while (1)
+ {
+ if (XAllocColor (private->xdisplay, private->xcolormap, &xcolor))
+ {
+ color->pixel = xcolor.pixel;
+ color->red = xcolor.red;
+ color->green = xcolor.green;
+ color->blue = xcolor.blue;
+
+ colormap->colors[color->pixel] = *color;
+
+ return_val = TRUE;
+ break;
+ }
+ else
+ {
+ if (available_init)
+ {
+ available_init = 0;
+ for (i = 0; i < 256; i++)
+ available[i] = TRUE;
+ }
+
+ index = gdk_colormap_match_color (colormap, color, available);
+ if (index != -1)
+ {
+ available[index] = FALSE;
+ xcolor.red = colormap->colors[index].red;
+ xcolor.green = colormap->colors[index].green;
+ xcolor.blue = colormap->colors[index].blue;
+ }
+ else
+ {
+ return_val = FALSE;
+ break;
+ }
+ }
+ }
+ }
+ break;
+
+ case GDK_VISUAL_DIRECT_COLOR:
+ visual = private->visual;
+ xcolor.pixel = (((xcolor.red >> (16 - visual->red_prec)) << visual->red_shift) +
+ ((xcolor.green >> (16 - visual->green_prec)) << visual->green_shift) +
+ ((xcolor.blue >> (16 - visual->blue_prec)) << visual->blue_shift));
+ color->pixel = xcolor.pixel;
+ return_val = TRUE;
+ break;
+
+ case GDK_VISUAL_STATIC_GRAY:
+ case GDK_VISUAL_STATIC_COLOR:
+ case GDK_VISUAL_TRUE_COLOR:
+ if (XAllocColor (private->xdisplay, private->xcolormap, &xcolor))
+ {
+ color->pixel = xcolor.pixel;
+ return_val = TRUE;
+ }
+ else
+ return_val = FALSE;
+ break;
+ }
+
+ return return_val;
+}
+
+gint
+gdk_color_change (GdkColormap *colormap,
+ GdkColor *color)
+{
+ GdkColormapPrivate *private;
+ XColor xcolor;
+
+ g_return_val_if_fail (colormap != NULL, FALSE);
+ g_return_val_if_fail (color != NULL, FALSE);
+
+ xcolor.pixel = color->pixel;
+ xcolor.red = color->red;
+ xcolor.green = color->green;
+ xcolor.blue = color->blue;
+ xcolor.flags = DoRed | DoGreen | DoBlue;
+
+ private = (GdkColormapPrivate*) colormap;
+ XStoreColor (private->xdisplay, private->xcolormap, &xcolor);
+
+ return TRUE;
+}
+
+gint
+gdk_color_equal (GdkColor *colora,
+ GdkColor *colorb)
+{
+ g_return_val_if_fail (colora != NULL, FALSE);
+ g_return_val_if_fail (colorb != NULL, FALSE);
+
+ return ((colora->red == colorb->red) &&
+ (colora->green == colorb->green) &&
+ (colora->blue == colorb->blue));
+}
+
+GdkColormap*
+gdkx_colormap_get (Colormap xcolormap)
+{
+ GdkColormap *colormap;
+ GdkColormapPrivate *private;
+ XColor xpalette[256];
+ gint i;
+
+ colormap = gdk_colormap_lookup (xcolormap);
+ if (colormap)
+ return colormap;
+
+ if (xcolormap == DefaultColormap (gdk_display, gdk_screen))
+ return gdk_colormap_get_system ();
+
+ private = g_new (GdkColormapPrivate, 1);
+ colormap = (GdkColormap*) private;
+
+ private->xdisplay = gdk_display;
+ private->xcolormap = xcolormap;
+ private->visual = NULL;
+ private->private_val = TRUE;
+ private->next_color = 0;
+
+ for (i = 0; i < 256; i++)
+ {
+ xpalette[i].pixel = i;
+ xpalette[i].red = 0;
+ xpalette[i].green = 0;
+ xpalette[i].blue = 0;
+ }
+
+ XQueryColors (gdk_display, private->xcolormap, xpalette, 256);
+
+ for (i = 0; i < 256; i++)
+ {
+ colormap->colors[i].pixel = xpalette[i].pixel;
+ colormap->colors[i].red = xpalette[i].red;
+ colormap->colors[i].green = xpalette[i].green;
+ colormap->colors[i].blue = xpalette[i].blue;
+ }
+
+ gdk_colormap_add (colormap);
+
+ return colormap;
+}
+
+
+static gint
+gdk_colormap_match_color (GdkColormap *cmap,
+ GdkColor *color,
+ const gchar *available)
+{
+ GdkColor *colors;
+ guint sum, max;
+ gint rdiff, gdiff, bdiff;
+ gint i, index;
+
+ g_return_val_if_fail (cmap != NULL, 0);
+ g_return_val_if_fail (color != NULL, 0);
+
+ colors = cmap->colors;
+ max = 3 * (65536);
+ index = -1;
+
+ for (i = 0; i < 256; i++)
+ {
+ if ((!available) || (available && available[i]))
+ {
+ rdiff = (color->red - colors[i].red);
+ gdiff = (color->green - colors[i].green);
+ bdiff = (color->blue - colors[i].blue);
+
+ sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
+
+ if (sum < max)
+ {
+ index = i;
+ max = sum;
+ }
+ }
+ }
+
+ return index;
+}
+
+
+GdkColormap*
+gdk_colormap_lookup (Colormap xcolormap)
+{
+ GdkColormap *cmap;
+
+ if (!colormap_hash)
+ return NULL;
+
+ cmap = g_hash_table_lookup (colormap_hash, &xcolormap);
+ return cmap;
+}
+
+static void
+gdk_colormap_add (GdkColormap *cmap)
+{
+ GdkColormapPrivate *private;
+
+ if (!colormap_hash)
+ colormap_hash = g_hash_table_new ((GHashFunc) gdk_colormap_hash,
+ (GCompareFunc) gdk_colormap_cmp);
+
+ private = (GdkColormapPrivate*) cmap;
+
+ g_hash_table_insert (colormap_hash, &private->xcolormap, cmap);
+}
+
+static void
+gdk_colormap_remove (GdkColormap *cmap)
+{
+ GdkColormapPrivate *private;
+
+ if (!colormap_hash)
+ colormap_hash = g_hash_table_new ((GHashFunc) gdk_colormap_hash,
+ (GCompareFunc) gdk_colormap_cmp);
+
+ private = (GdkColormapPrivate*) cmap;
+
+ g_hash_table_remove (colormap_hash, &private->xcolormap);
+}
+
+static guint
+gdk_colormap_hash (Colormap *cmap)
+{
+ return *cmap;
+}
+
+static gint
+gdk_colormap_cmp (Colormap *a,
+ Colormap *b)
+{
+ return (*a == *b);
+}
diff --git a/gdk/gdkcursor.c b/gdk/gdkcursor.c
new file mode 100644
index 000000000..22bfd250b
--- /dev/null
+++ b/gdk/gdkcursor.c
@@ -0,0 +1,52 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <X11/Xlib.h>
+#include <X11/cursorfont.h>
+#include "gdk.h"
+#include "gdkprivate.h"
+
+
+GdkCursor*
+gdk_cursor_new (GdkCursorType cursor_type)
+{
+ GdkCursorPrivate *private;
+ GdkCursor *cursor;
+ Cursor xcursor;
+
+ xcursor = XCreateFontCursor (gdk_display, cursor_type);
+ private = g_new (GdkCursorPrivate, 1);
+ private->xdisplay = gdk_display;
+ private->xcursor = xcursor;
+ cursor = (GdkCursor*) private;
+ cursor->type = cursor_type;
+
+ return cursor;
+}
+
+void
+gdk_cursor_destroy (GdkCursor *cursor)
+{
+ GdkCursorPrivate *private;
+
+ g_return_if_fail (cursor != NULL);
+
+ private = (GdkCursorPrivate *) cursor;
+ XFreeCursor (private->xdisplay, private->xcursor);
+
+ g_free (private);
+}
diff --git a/gdk/gdkdraw.c b/gdk/gdkdraw.c
new file mode 100644
index 000000000..47482f72e
--- /dev/null
+++ b/gdk/gdkdraw.c
@@ -0,0 +1,383 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <X11/Xlib.h>
+#include <X11/Xos.h>
+#include "gdk.h"
+#include "gdkprivate.h"
+
+
+void
+gdk_draw_point (GdkDrawable *drawable,
+ GdkGC *gc,
+ gint x,
+ gint y)
+{
+ GdkWindowPrivate *drawable_private;
+ GdkGCPrivate *gc_private;
+
+ g_return_if_fail (drawable != NULL);
+ g_return_if_fail (gc != NULL);
+
+ drawable_private = (GdkWindowPrivate*) drawable;
+ gc_private = (GdkGCPrivate*) gc;
+
+ XDrawPoint (drawable_private->xdisplay, drawable_private->xwindow,
+ gc_private->xgc, x, y);
+}
+
+void
+gdk_draw_line (GdkDrawable *drawable,
+ GdkGC *gc,
+ gint x1,
+ gint y1,
+ gint x2,
+ gint y2)
+{
+ GdkWindowPrivate *drawable_private;
+ GdkGCPrivate *gc_private;
+
+ g_return_if_fail (drawable != NULL);
+ g_return_if_fail (gc != NULL);
+
+ drawable_private = (GdkWindowPrivate*) drawable;
+ gc_private = (GdkGCPrivate*) gc;
+
+ XDrawLine (drawable_private->xdisplay, drawable_private->xwindow,
+ gc_private->xgc, x1, y1, x2, y2);
+}
+
+void
+gdk_draw_rectangle (GdkDrawable *drawable,
+ GdkGC *gc,
+ gint filled,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ GdkWindowPrivate *drawable_private;
+ GdkGCPrivate *gc_private;
+
+ g_return_if_fail (drawable != NULL);
+ g_return_if_fail (gc != NULL);
+
+ drawable_private = (GdkWindowPrivate*) drawable;
+ gc_private = (GdkGCPrivate*) gc;
+
+ if (width == -1)
+ width = drawable_private->width;
+ if (height == -1)
+ height = drawable_private->height;
+
+ if (filled)
+ XFillRectangle (drawable_private->xdisplay, drawable_private->xwindow,
+ gc_private->xgc, x, y, width, height);
+ else
+ XDrawRectangle (drawable_private->xdisplay, drawable_private->xwindow,
+ gc_private->xgc, x, y, width, height);
+}
+
+void
+gdk_draw_arc (GdkDrawable *drawable,
+ GdkGC *gc,
+ gint filled,
+ gint x,
+ gint y,
+ gint width,
+ gint height,
+ gint angle1,
+ gint angle2)
+{
+ GdkWindowPrivate *drawable_private;
+ GdkGCPrivate *gc_private;
+
+ g_return_if_fail (drawable != NULL);
+ g_return_if_fail (gc != NULL);
+
+ drawable_private = (GdkWindowPrivate*) drawable;
+ gc_private = (GdkGCPrivate*) gc;
+
+ if (width == -1)
+ width = drawable_private->width;
+ if (height == -1)
+ height = drawable_private->height;
+
+ if (filled)
+ XFillArc (drawable_private->xdisplay, drawable_private->xwindow,
+ gc_private->xgc, x, y, width, height, angle1, angle2);
+ else
+ XDrawArc (drawable_private->xdisplay, drawable_private->xwindow,
+ gc_private->xgc, x, y, width, height, angle1, angle2);
+}
+
+void
+gdk_draw_polygon (GdkDrawable *drawable,
+ GdkGC *gc,
+ gint filled,
+ GdkPoint *points,
+ gint npoints)
+{
+ GdkWindowPrivate *drawable_private;
+ GdkGCPrivate *gc_private;
+
+ g_return_if_fail (drawable != NULL);
+ g_return_if_fail (gc != NULL);
+
+ drawable_private = (GdkWindowPrivate*) drawable;
+ gc_private = (GdkGCPrivate*) gc;
+
+ if (filled)
+ {
+ XFillPolygon (drawable_private->xdisplay, drawable_private->xwindow,
+ gc_private->xgc, (XPoint*) points, npoints, Complex, CoordModeOrigin);
+ }
+ else
+ {
+ XDrawLines (drawable_private->xdisplay, drawable_private->xwindow,
+ gc_private->xgc, (XPoint*) points, npoints, CoordModeOrigin);
+
+ if ((points[0].x != points[npoints-1].x) ||
+ (points[0].y != points[npoints-1].y))
+ XDrawLine (drawable_private->xdisplay, drawable_private->xwindow,
+ gc_private->xgc, points[npoints-1].x, points[npoints-1].y,
+ points[0].x, points[0].y);
+ }
+}
+
+/* gdk_draw_string
+ *
+ * Modified by Li-Da Lho to draw 16 bits and Multibyte strings
+ *
+ * Interface changed: add "GdkFont *font" to specify font or fontset explicitely
+ */
+void
+gdk_draw_string (GdkDrawable *drawable,
+ GdkFont *font,
+ GdkGC *gc,
+ gint x,
+ gint y,
+ const gchar *string)
+{
+ GdkWindowPrivate *drawable_private;
+ GdkFontPrivate *font_private;
+ GdkGCPrivate *gc_private;
+
+ g_return_if_fail (drawable != NULL);
+ g_return_if_fail (font != NULL);
+ g_return_if_fail (gc != NULL);
+ g_return_if_fail (string != NULL);
+
+ drawable_private = (GdkWindowPrivate*) drawable;
+ gc_private = (GdkGCPrivate*) gc;
+ font_private = (GdkFontPrivate*) font;
+
+ if (font->type == GDK_FONT_FONT)
+ {
+ XFontStruct *xfont = (XFontStruct *) font_private->xfont;
+ XSetFont(drawable_private->xdisplay, gc_private->xgc, xfont->fid);
+ if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
+ {
+ XDrawString (drawable_private->xdisplay, drawable_private->xwindow,
+ gc_private->xgc, x, y, string, strlen (string));
+ }
+ else
+ {
+ XDrawString16 (drawable_private->xdisplay, drawable_private->xwindow,
+ gc_private->xgc, x, y, (XChar2b *) string,
+ strlen (string) / 2);
+ }
+ }
+ else if (font->type == GDK_FONT_FONTSET)
+ {
+ XFontSet fontset = (XFontSet) font_private->xfont;
+ XmbDrawString (drawable_private->xdisplay, drawable_private->xwindow,
+ fontset, gc_private->xgc, x, y, string, strlen (string));
+ }
+ else
+ g_error("undefined font type\n");
+}
+
+/* gdk_draw_text
+ *
+ * Modified by Li-Da Lho to draw 16 bits and Multibyte strings
+ *
+ * Interface changed: add "GdkFont *font" to specify font or fontset explicitely
+ */
+void
+gdk_draw_text (GdkDrawable *drawable,
+ GdkFont *font,
+ GdkGC *gc,
+ gint x,
+ gint y,
+ const gchar *text,
+ gint text_length)
+{
+ GdkWindowPrivate *drawable_private;
+ GdkFontPrivate *font_private;
+ GdkGCPrivate *gc_private;
+
+ g_return_if_fail (drawable != NULL);
+ g_return_if_fail (font != NULL);
+ g_return_if_fail (gc != NULL);
+ g_return_if_fail (text != NULL);
+
+ drawable_private = (GdkWindowPrivate*) drawable;
+ gc_private = (GdkGCPrivate*) gc;
+ font_private = (GdkFontPrivate*) font;
+
+ if (font->type == GDK_FONT_FONT)
+ {
+ XFontStruct *xfont = (XFontStruct *) font_private->xfont;
+ XSetFont(drawable_private->xdisplay, gc_private->xgc, xfont->fid);
+ if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
+ {
+ XDrawString (drawable_private->xdisplay, drawable_private->xwindow,
+ gc_private->xgc, x, y, text, text_length);
+ }
+ else
+ {
+ XDrawString16 (drawable_private->xdisplay, drawable_private->xwindow,
+ gc_private->xgc, x, y, (XChar2b *) text, text_length / 2);
+ }
+ }
+ else if (font->type == GDK_FONT_FONTSET)
+ {
+ XFontSet fontset = (XFontSet) font_private->xfont;
+ XmbDrawString (drawable_private->xdisplay, drawable_private->xwindow,
+ fontset, gc_private->xgc, x, y, text, text_length);
+ }
+ else
+ g_error("undefined font type\n");
+}
+
+void
+gdk_draw_pixmap (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkPixmap *src,
+ gint xsrc,
+ gint ysrc,
+ gint xdest,
+ gint ydest,
+ gint width,
+ gint height)
+{
+ GdkWindowPrivate *drawable_private;
+ GdkWindowPrivate *src_private;
+ GdkGCPrivate *gc_private;
+
+ g_return_if_fail (drawable != NULL);
+ g_return_if_fail (src != NULL);
+ g_return_if_fail (gc != NULL);
+
+ drawable_private = (GdkWindowPrivate*) drawable;
+ src_private = (GdkWindowPrivate*) src;
+ gc_private = (GdkGCPrivate*) gc;
+
+ if (width == -1)
+ width = src_private->width;
+ if (height == -1)
+ height = src_private->height;
+
+ XCopyArea (drawable_private->xdisplay,
+ src_private->xwindow,
+ drawable_private->xwindow,
+ gc_private->xgc,
+ xsrc, ysrc,
+ width, height,
+ xdest, ydest);
+}
+
+void
+gdk_draw_image (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkImage *image,
+ gint xsrc,
+ gint ysrc,
+ gint xdest,
+ gint ydest,
+ gint width,
+ gint height)
+{
+ GdkImagePrivate *image_private;
+
+ g_return_if_fail (drawable != NULL);
+ g_return_if_fail (image != NULL);
+ g_return_if_fail (gc != NULL);
+
+ image_private = (GdkImagePrivate*) image;
+
+ g_return_if_fail (image_private->image_put != NULL);
+
+ if (width == -1)
+ width = image->width;
+ if (height == -1)
+ height = image->height;
+
+ (* image_private->image_put) (drawable, gc, image, xsrc, ysrc,
+ xdest, ydest, width, height);
+}
+
+void
+gdk_draw_points (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkPoint *points,
+ gint npoints)
+{
+ GdkWindowPrivate *drawable_private;
+ GdkGCPrivate *gc_private;
+
+ g_return_if_fail (drawable != NULL);
+ g_return_if_fail ((points != NULL) && (npoints > 0));
+ g_return_if_fail (gc != NULL);
+
+ drawable_private = (GdkWindowPrivate*) drawable;
+ gc_private = (GdkGCPrivate*) gc;
+
+ XDrawPoints (drawable_private->xdisplay,
+ drawable_private->xwindow,
+ gc_private->xgc,
+ (XPoint *) points,
+ npoints,
+ CoordModeOrigin);
+}
+
+void
+gdk_draw_segments (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkSegment *segs,
+ gint nsegs)
+{
+ GdkWindowPrivate *drawable_private;
+ GdkGCPrivate *gc_private;
+
+ if (nsegs <= 0)
+ return;
+
+ g_return_if_fail (drawable != NULL);
+ g_return_if_fail (segs != NULL);
+ g_return_if_fail (gc != NULL);
+
+ drawable_private = (GdkWindowPrivate*) drawable;
+ gc_private = (GdkGCPrivate*) gc;
+
+ XDrawSegments (drawable_private->xdisplay,
+ drawable_private->xwindow,
+ gc_private->xgc,
+ (XSegment *) segs,
+ nsegs);
+}
diff --git a/gdk/gdkfont.c b/gdk/gdkfont.c
new file mode 100644
index 000000000..e1b1e7254
--- /dev/null
+++ b/gdk/gdkfont.c
@@ -0,0 +1,379 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <X11/Xlib.h>
+#include <X11/Xos.h>
+#include "gdk.h"
+#include "gdkprivate.h"
+
+GdkFont*
+gdk_font_load (const gchar *font_name)
+{
+ GdkFont *font;
+ GdkFontPrivate *private;
+
+ private = g_new (GdkFontPrivate, 1);
+ font = (GdkFont*) private;
+
+ private->xdisplay = gdk_display;
+ private->xfont = XLoadQueryFont (private->xdisplay, font_name);
+ private->ref_count = 1;
+
+ if (!private->xfont)
+ {
+ g_free (font);
+ return NULL;
+ }
+ else
+ {
+ font->type = GDK_FONT_FONT;
+ font->ascent = ((XFontStruct *) private->xfont)->ascent;
+ font->descent = ((XFontStruct *) private->xfont)->descent;
+ }
+
+ gdk_xid_table_insert (&((XFontStruct *) private->xfont)->fid, font);
+
+ return font;
+}
+
+GdkFont*
+gdk_fontset_load(gchar *fontset_name)
+{
+ GdkFont *font;
+ GdkFontPrivate *private;
+ XFontSet fontset;
+ gint missing_charset_count;
+ gchar **missing_charset_list;
+ gchar *def_string;
+
+ private = g_new (GdkFontPrivate, 1);
+ font = (GdkFont*) private;
+
+ private->xdisplay = gdk_display;
+ fontset = XCreateFontSet (gdk_display, fontset_name,
+ &missing_charset_list, &missing_charset_count,
+ &def_string);
+
+ if (missing_charset_count)
+ {
+ g_print ("Missing charsets in FontSet creation");
+ XFreeStringList (missing_charset_list);
+ }
+
+ private->ref_count = 1;
+
+ if (!fontset)
+ {
+ g_free (font);
+ return NULL;
+ }
+ else
+ {
+ XFontSetExtents *extent = XExtentsOfFontSet(fontset);
+
+ private->xfont = fontset;
+ font->type = GDK_FONT_FONTSET;
+ /* how to define ascent and descent for fontset ??? */
+ font->ascent = extent->max_logical_extent.height;
+ font->descent = font->ascent / 4 ;
+ }
+ return font;
+}
+void
+gdk_font_free (GdkFont *font)
+{
+ GdkFontPrivate *private;
+
+ g_return_if_fail (font != NULL);
+
+ private = (GdkFontPrivate*) font;
+
+ private->ref_count -= 1;
+ if (private->ref_count == 0)
+ {
+ gdk_xid_table_remove (((XFontStruct *) private->xfont)->fid);
+ XFreeFont (private->xdisplay, (XFontStruct *) private->xfont);
+ g_free (font);
+ }
+}
+
+void
+gdk_fontset_free (GdkFont *font)
+{
+ GdkFontPrivate *private;
+
+ g_return_if_fail (font != NULL);
+
+ private = (GdkFontPrivate*) font;
+
+ private->ref_count -= 1;
+ if (private->ref_count == 0)
+ {
+ XFreeFontSet (private->xdisplay, (XFontSet) private->xfont);
+ g_free (font);
+ }
+}
+
+GdkFont*
+gdk_font_ref (GdkFont *font)
+{
+ GdkFontPrivate *private;
+
+ g_return_val_if_fail (font != NULL, NULL);
+
+ private = (GdkFontPrivate*) font;
+ private->ref_count += 1;
+ return font;
+}
+
+gint
+gdk_font_id (GdkFont *font)
+{
+ GdkFontPrivate *font_private;
+
+ g_return_val_if_fail (font != NULL, 0);
+
+ font_private = (GdkFontPrivate*) font;
+
+ if (font->type == GDK_FONT_FONT)
+ {
+ return ((XFontStruct *) font_private->xfont)->fid;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+gint
+gdk_font_equal (GdkFont *fonta,
+ GdkFont *fontb)
+{
+ GdkFontPrivate *privatea;
+ GdkFontPrivate *privateb;
+
+ g_return_val_if_fail (fonta != NULL, FALSE);
+ g_return_val_if_fail (fontb != NULL, FALSE);
+
+ privatea = (GdkFontPrivate*) fonta;
+ privateb = (GdkFontPrivate*) fontb;
+
+ if (fonta->type == GDK_FONT_FONT && fontb->type == GDK_FONT_FONT)
+ {
+ return (((XFontStruct *) privatea->xfont)->fid ==
+ ((XFontStruct *) privateb->xfont)->fid);
+ }
+ else if (fonta->type == GDK_FONT_FONTSET && fontb->type == GDK_FONT_FONTSET)
+ {
+ /* how to compare two fontsets ?? by basename or XFontSet ?? */
+ return (((XFontSet) privatea->xfont) == ((XFontSet) privateb->xfont));
+ }
+ else
+ /* fontset != font */
+ return 0;
+}
+
+gint
+gdk_string_width (GdkFont *font,
+ const gchar *string)
+{
+ GdkFontPrivate *font_private;
+ gint width;
+ XFontStruct *xfont;
+ XFontSet fontset;
+
+ g_return_val_if_fail (font != NULL, -1);
+ g_return_val_if_fail (string != NULL, -1);
+
+ font_private = (GdkFontPrivate*) font;
+
+ switch (font->type)
+ {
+ case GDK_FONT_FONT:
+ xfont = (XFontStruct *) font_private->xfont;
+ if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
+ {
+ width = XTextWidth (xfont, string, strlen (string));
+ }
+ else
+ {
+ width = XTextWidth16 (xfont, (XChar2b *) string, strlen (string) / 2);
+ }
+ break;
+ case GDK_FONT_FONTSET:
+ fontset = (XFontSet) font_private->xfont;
+ width = XmbTextEscapement (fontset, string, strlen(string));
+ break;
+ default:
+ width = 0;
+ }
+
+ return width;
+}
+
+gint
+gdk_text_width (GdkFont *font,
+ const gchar *text,
+ gint text_length)
+{
+ GdkFontPrivate *private;
+ gint width;
+ XFontStruct *xfont;
+ XFontSet fontset;
+
+ g_return_val_if_fail (font != NULL, -1);
+ g_return_val_if_fail (text != NULL, -1);
+
+ private = (GdkFontPrivate*) font;
+
+ switch (font->type)
+ {
+ case GDK_FONT_FONT:
+ xfont = (XFontStruct *) private->xfont;
+ if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
+ {
+ width = XTextWidth (xfont, text, text_length);
+ }
+ else
+ {
+ width = XTextWidth16 (xfont, (XChar2b *) text, text_length / 2);
+ }
+ break;
+ case GDK_FONT_FONTSET:
+ fontset = (XFontSet) private->xfont;
+ width = XmbTextEscapement (fontset, text, text_length);
+ break;
+ default:
+ width = 0;
+ }
+ return width;
+}
+
+/* Problem: What if a character is a 16 bits character ?? */
+gint
+gdk_char_width (GdkFont *font,
+ gchar character)
+{
+ GdkFontPrivate *private;
+ XCharStruct *chars;
+ gint width;
+ guint ch = character & 0xff; /* get rid of sign-extension */
+ XFontStruct *xfont;
+ XFontSet fontset;
+
+ g_return_val_if_fail (font != NULL, -1);
+
+ private = (GdkFontPrivate*) font;
+
+ switch (font->type)
+ {
+ case GDK_FONT_FONT:
+ /* only 8 bits characters are considered here */
+ xfont = (XFontStruct *) private->xfont;
+ if ((xfont->min_byte1 == 0) &&
+ (xfont->max_byte1 == 0) &&
+ (ch >= xfont->min_char_or_byte2) &&
+ (ch <= xfont->max_char_or_byte2))
+ {
+ chars = xfont->per_char;
+ if (chars)
+ width = chars[ch - xfont->min_char_or_byte2].width;
+ else
+ width = xfont->min_bounds.width;
+ }
+ else
+ {
+ width = XTextWidth (xfont, &character, 1);
+ }
+ break;
+ case GDK_FONT_FONTSET:
+ fontset = (XFontSet) private->xfont;
+ width = XmbTextEscapement (fontset, &character, 1) ;
+ break;
+ default:
+ width = 0;
+ }
+ return width;
+}
+
+gint
+gdk_string_measure (GdkFont *font,
+ const gchar *string)
+{
+ g_return_val_if_fail (font != NULL, -1);
+ g_return_val_if_fail (string != NULL, -1);
+
+ return gdk_text_measure (font, string, strlen (string));
+}
+
+gint
+gdk_text_measure (GdkFont *font,
+ const gchar *text,
+ gint text_length)
+{
+ GdkFontPrivate *private;
+ XCharStruct overall;
+ XFontStruct *xfont;
+ XFontSet fontset;
+ XRectangle ink, log;
+ int direction;
+ int font_ascent;
+ int font_descent;
+ gint width;
+
+ g_return_val_if_fail (font != NULL, -1);
+ g_return_val_if_fail (text != NULL, -1);
+
+ private = (GdkFontPrivate*) font;
+
+ switch (font->type)
+ {
+ case GDK_FONT_FONT:
+ xfont = (XFontStruct *) private->xfont;
+ if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
+ {
+ XTextExtents (xfont, text, text_length,
+ &direction, &font_ascent, &font_descent,
+ &overall);
+ }
+ else
+ {
+ XTextExtents16 (xfont, (XChar2b *) text, text_length / 2,
+ &direction, &font_ascent, &font_descent,
+ &overall);
+ }
+ width = overall.rbearing;
+ break;
+ case GDK_FONT_FONTSET:
+ fontset = (XFontSet) private->xfont;
+ XmbTextExtents (fontset, text, text_length, &ink, &log);
+ width = log.width;
+ break;
+ default:
+ width = 0;
+ }
+ return width;
+}
+
+gint
+gdk_char_measure (GdkFont *font,
+ gchar character)
+{
+ g_return_val_if_fail (font != NULL, -1);
+
+ return gdk_text_measure (font, &character, 1);
+}
diff --git a/gdk/gdkgc.c b/gdk/gdkgc.c
new file mode 100644
index 000000000..3dc11ce6c
--- /dev/null
+++ b/gdk/gdkgc.c
@@ -0,0 +1,636 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <string.h>
+#include <X11/Xlib.h>
+#include "gdk.h"
+#include "gdkprivate.h"
+
+
+GdkGC*
+gdk_gc_new (GdkWindow *window)
+{
+ return gdk_gc_new_with_values (window, NULL, 0);
+}
+
+GdkGC*
+gdk_gc_new_with_values (GdkWindow *window,
+ GdkGCValues *values,
+ GdkGCValuesMask values_mask)
+{
+ GdkGC *gc;
+ GdkGCPrivate *private;
+ Window xwindow;
+ XGCValues xvalues;
+ unsigned long xvalues_mask;
+
+ private = g_new (GdkGCPrivate, 1);
+ gc = (GdkGC*) private;
+
+ xwindow = ((GdkWindowPrivate*) window)->xwindow;
+ private->xdisplay = ((GdkWindowPrivate*) window)->xdisplay;
+
+ xvalues.function = GXcopy;
+ xvalues.fill_style = FillSolid;
+ xvalues.arc_mode = ArcPieSlice;
+ xvalues.subwindow_mode = ClipByChildren;
+ xvalues.graphics_exposures = True;
+ xvalues_mask = GCFunction | GCFillStyle | GCArcMode | GCSubwindowMode | GCGraphicsExposures;
+
+ if (values_mask & GDK_GC_FOREGROUND)
+ {
+ xvalues.foreground = values->foreground.pixel;
+ xvalues_mask |= GCForeground;
+ }
+ if (values_mask & GDK_GC_BACKGROUND)
+ {
+ xvalues.background = values->background.pixel;
+ xvalues_mask |= GCBackground;
+ }
+ if ((values_mask & GDK_GC_FONT) && (values->font->type == GDK_FONT_FONT))
+ {
+ xvalues.font = ((XFontStruct *) ((GdkFontPrivate*) values->font)->xfont)->fid;
+ xvalues_mask |= GCFont;
+ }
+ if (values_mask & GDK_GC_FUNCTION)
+ {
+ switch (values->function)
+ {
+ case GDK_COPY:
+ xvalues.function = GXcopy;
+ break;
+ case GDK_INVERT:
+ xvalues.function = GXinvert;
+ break;
+ case GDK_XOR:
+ xvalues.function = GXxor;
+ break;
+ }
+ xvalues_mask |= GCFunction;
+ }
+ if (values_mask & GDK_GC_FILL)
+ {
+ switch (values->fill)
+ {
+ case GDK_SOLID:
+ xvalues.fill_style = FillSolid;
+ break;
+ case GDK_TILED:
+ xvalues.fill_style = FillTiled;
+ break;
+ case GDK_STIPPLED:
+ xvalues.fill_style = FillStippled;
+ break;
+ case GDK_OPAQUE_STIPPLED:
+ xvalues.fill_style = FillOpaqueStippled;
+ break;
+ }
+ xvalues_mask |= GCFillStyle;
+ }
+ if (values_mask & GDK_GC_TILE)
+ {
+ xvalues.tile = ((GdkPixmapPrivate*) values->tile)->xwindow;
+ xvalues_mask |= GCTile;
+ }
+ if (values_mask & GDK_GC_STIPPLE)
+ {
+ xvalues.stipple = ((GdkPixmapPrivate*) values->stipple)->xwindow;
+ xvalues_mask |= GCStipple;
+ }
+ if (values_mask & GDK_GC_CLIP_MASK)
+ {
+ xvalues.clip_mask = ((GdkPixmapPrivate*) values->clip_mask)->xwindow;
+ xvalues_mask |= GCClipMask;
+ }
+ if (values_mask & GDK_GC_SUBWINDOW)
+ {
+ xvalues.subwindow_mode = values->subwindow_mode;
+ xvalues_mask |= GCSubwindowMode;
+ }
+ if (values_mask & GDK_GC_TS_X_ORIGIN)
+ {
+ xvalues.ts_x_origin = values->ts_x_origin;
+ xvalues_mask |= GCTileStipXOrigin;
+ }
+ if (values_mask & GDK_GC_TS_Y_ORIGIN)
+ {
+ xvalues.ts_y_origin = values->ts_y_origin;
+ xvalues_mask |= GCTileStipYOrigin;
+ }
+ if (values_mask & GDK_GC_CLIP_X_ORIGIN)
+ {
+ xvalues.clip_x_origin = values->clip_x_origin;
+ xvalues_mask |= GCClipXOrigin;
+ }
+ if (values_mask & GDK_GC_CLIP_Y_ORIGIN)
+ {
+ xvalues.clip_y_origin = values->clip_y_origin;
+ xvalues_mask |= GCClipYOrigin;
+ }
+ if (values_mask & GDK_GC_EXPOSURES)
+ {
+ xvalues.graphics_exposures = values->graphics_exposures;
+ xvalues_mask |= GCGraphicsExposures;
+ }
+ if (values_mask & GDK_GC_LINE_WIDTH)
+ {
+ xvalues.line_width = values->line_width;
+ xvalues_mask |= GCLineWidth;
+ }
+ if (values_mask & GDK_GC_LINE_STYLE)
+ {
+ switch (values->line_style)
+ {
+ case GDK_LINE_SOLID:
+ xvalues.line_style = LineSolid;
+ break;
+ case GDK_LINE_ON_OFF_DASH:
+ xvalues.line_style = LineOnOffDash;
+ break;
+ case GDK_LINE_DOUBLE_DASH:
+ xvalues.line_style = LineDoubleDash;
+ break;
+ }
+ xvalues_mask |= GCLineStyle;
+ }
+ if (values_mask & GDK_GC_CAP_STYLE)
+ {
+ switch (values->cap_style)
+ {
+ case GDK_CAP_NOT_LAST:
+ xvalues.cap_style = CapNotLast;
+ break;
+ case GDK_CAP_BUTT:
+ xvalues.cap_style = CapButt;
+ break;
+ case GDK_CAP_ROUND:
+ xvalues.cap_style = CapRound;
+ break;
+ case GDK_CAP_PROJECTING:
+ xvalues.cap_style = CapProjecting;
+ break;
+ }
+ xvalues_mask |= GCCapStyle;
+ }
+ if (values_mask & GDK_GC_JOIN_STYLE)
+ {
+ switch (values->join_style)
+ {
+ case GDK_JOIN_MITER:
+ xvalues.join_style = JoinMiter;
+ break;
+ case GDK_JOIN_ROUND:
+ xvalues.join_style = JoinRound;
+ break;
+ case GDK_JOIN_BEVEL:
+ xvalues.join_style = JoinBevel;
+ break;
+ }
+ xvalues_mask |= GCJoinStyle;
+ }
+
+ private->xgc = XCreateGC (private->xdisplay, xwindow, xvalues_mask, &xvalues);
+
+ return gc;
+}
+
+void
+gdk_gc_destroy (GdkGC *gc)
+{
+ GdkGCPrivate *private;
+
+ g_return_if_fail (gc != NULL);
+
+ private = (GdkGCPrivate*) gc;
+ XFreeGC (private->xdisplay, private->xgc);
+
+ memset (gc, 0, sizeof (GdkGCPrivate));
+ g_free (gc);
+}
+
+void
+gdk_gc_get_values (GdkGC *gc,
+ GdkGCValues *values)
+{
+ GdkGCPrivate *private;
+ XGCValues xvalues;
+
+ g_return_if_fail (gc != NULL);
+ g_return_if_fail (values != NULL);
+
+ private = (GdkGCPrivate*) gc;
+
+ if (XGetGCValues (private->xdisplay, private->xgc,
+ GCForeground | GCBackground | GCFont |
+ GCFunction | GCTile | GCStipple | /* GCClipMask | */
+ GCSubwindowMode | GCGraphicsExposures |
+ GCTileStipXOrigin | GCTileStipYOrigin |
+ GCClipXOrigin | GCClipYOrigin |
+ GCLineWidth | GCLineStyle | GCCapStyle |
+ GCFillStyle | GCJoinStyle, &xvalues))
+ {
+ values->foreground.pixel = xvalues.foreground;
+ values->background.pixel = xvalues.background;
+ values->font = gdk_font_lookup (xvalues.font);
+
+ switch (xvalues.function)
+ {
+ case GXcopy:
+ values->function = GDK_COPY;
+ break;
+ case GXinvert:
+ values->function = GDK_INVERT;
+ break;
+ case GXxor:
+ values->function = GDK_XOR;
+ break;
+ }
+
+ switch (xvalues.fill_style)
+ {
+ case FillSolid:
+ values->fill = GDK_SOLID;
+ break;
+ case FillTiled:
+ values->fill = GDK_TILED;
+ break;
+ case FillStippled:
+ values->fill = GDK_STIPPLED;
+ break;
+ case FillOpaqueStippled:
+ values->fill = GDK_OPAQUE_STIPPLED;
+ break;
+ }
+
+ values->tile = gdk_pixmap_lookup (xvalues.tile);
+ values->stipple = gdk_pixmap_lookup (xvalues.stipple);
+ values->clip_mask = NULL;
+ values->subwindow_mode = xvalues.subwindow_mode;
+ values->ts_x_origin = xvalues.ts_x_origin;
+ values->ts_y_origin = xvalues.ts_y_origin;
+ values->clip_x_origin = xvalues.clip_x_origin;
+ values->clip_y_origin = xvalues.clip_y_origin;
+ values->graphics_exposures = xvalues.graphics_exposures;
+ values->line_width = xvalues.line_width;
+
+ switch (xvalues.line_style)
+ {
+ case LineSolid:
+ values->line_style = GDK_LINE_SOLID;
+ break;
+ case LineOnOffDash:
+ values->line_style = GDK_LINE_ON_OFF_DASH;
+ break;
+ case LineDoubleDash:
+ values->line_style = GDK_LINE_DOUBLE_DASH;
+ break;
+ }
+
+ switch (xvalues.cap_style)
+ {
+ case CapNotLast:
+ values->cap_style = GDK_CAP_NOT_LAST;
+ break;
+ case CapButt:
+ values->cap_style = GDK_CAP_BUTT;
+ break;
+ case CapRound:
+ values->cap_style = GDK_CAP_ROUND;
+ break;
+ case CapProjecting:
+ values->cap_style = GDK_CAP_PROJECTING;
+ break;
+ }
+
+ switch (xvalues.join_style)
+ {
+ case JoinMiter:
+ values->join_style = GDK_JOIN_MITER;
+ break;
+ case JoinRound:
+ values->join_style = GDK_JOIN_ROUND;
+ break;
+ case JoinBevel:
+ values->join_style = GDK_JOIN_BEVEL;
+ break;
+ }
+ }
+ else
+ {
+ memset (values, 0, sizeof (GdkGCValues));
+ }
+}
+
+void
+gdk_gc_set_foreground (GdkGC *gc,
+ GdkColor *color)
+{
+ GdkGCPrivate *private;
+
+ g_return_if_fail (gc != NULL);
+ g_return_if_fail (color != NULL);
+
+ private = (GdkGCPrivate*) gc;
+ XSetForeground (private->xdisplay, private->xgc, color->pixel);
+}
+
+void
+gdk_gc_set_background (GdkGC *gc,
+ GdkColor *color)
+{
+ GdkGCPrivate *private;
+
+ g_return_if_fail (gc != NULL);
+ g_return_if_fail (color != NULL);
+
+ private = (GdkGCPrivate*) gc;
+ XSetBackground (private->xdisplay, private->xgc, color->pixel);
+}
+
+void
+gdk_gc_set_font (GdkGC *gc,
+ GdkFont *font)
+{
+ GdkGCPrivate *gc_private;
+ GdkFontPrivate *font_private;
+
+ g_return_if_fail (gc != NULL);
+ g_return_if_fail (font != NULL);
+
+ gc_private = (GdkGCPrivate*) gc;
+ font_private = (GdkFontPrivate*) font;
+
+ XSetFont (gc_private->xdisplay, gc_private->xgc,
+ ((XFontStruct *) font_private->xfont)->fid);
+}
+
+void
+gdk_gc_set_function (GdkGC *gc,
+ GdkFunction function)
+{
+ GdkGCPrivate *private;
+
+ g_return_if_fail (gc != NULL);
+
+ private = (GdkGCPrivate*) gc;
+
+ switch (function)
+ {
+ case GDK_COPY:
+ XSetFunction (private->xdisplay, private->xgc, GXcopy);
+ break;
+ case GDK_INVERT:
+ XSetFunction (private->xdisplay, private->xgc, GXinvert);
+ break;
+ case GDK_XOR:
+ XSetFunction (private->xdisplay, private->xgc, GXor);
+ break;
+ }
+}
+
+void
+gdk_gc_set_fill (GdkGC *gc,
+ GdkFill fill)
+{
+ GdkGCPrivate *private;
+
+ g_return_if_fail (gc != NULL);
+
+ private = (GdkGCPrivate*) gc;
+
+ switch (fill)
+ {
+ case GDK_SOLID:
+ XSetFillStyle (private->xdisplay, private->xgc, FillSolid);
+ break;
+ case GDK_TILED:
+ XSetFillStyle (private->xdisplay, private->xgc, FillTiled);
+ break;
+ case GDK_STIPPLED:
+ XSetFillStyle (private->xdisplay, private->xgc, FillStippled);
+ break;
+ case GDK_OPAQUE_STIPPLED:
+ XSetFillStyle (private->xdisplay, private->xgc, FillOpaqueStippled);
+ break;
+ }
+}
+
+void
+gdk_gc_set_tile (GdkGC *gc,
+ GdkPixmap *tile)
+{
+ GdkGCPrivate *private;
+ GdkPixmapPrivate *pixmap_private;
+ Pixmap pixmap;
+
+ g_return_if_fail (gc != NULL);
+
+ private = (GdkGCPrivate*) gc;
+
+ pixmap = None;
+ if (tile)
+ {
+ pixmap_private = (GdkPixmapPrivate*) tile;
+ pixmap = pixmap_private->xwindow;
+ }
+
+ XSetTile (private->xdisplay, private->xgc, pixmap);
+}
+
+void
+gdk_gc_set_stipple (GdkGC *gc,
+ GdkPixmap *stipple)
+{
+ GdkGCPrivate *private;
+ GdkPixmapPrivate *pixmap_private;
+ Pixmap pixmap;
+
+ g_return_if_fail (gc != NULL);
+
+ private = (GdkGCPrivate*) gc;
+
+ pixmap = None;
+ if (stipple)
+ {
+ pixmap_private = (GdkPixmapPrivate*) stipple;
+ pixmap = pixmap_private->xwindow;
+ }
+
+ XSetStipple (private->xdisplay, private->xgc, pixmap);
+}
+
+void
+gdk_gc_set_ts_origin (GdkGC *gc,
+ gint x,
+ gint y)
+{
+ GdkGCPrivate *private;
+
+ g_return_if_fail (gc != NULL);
+
+ private = (GdkGCPrivate*) gc;
+
+ XSetTSOrigin (private->xdisplay, private->xgc, x, y);
+}
+
+void
+gdk_gc_set_clip_origin (GdkGC *gc,
+ gint x,
+ gint y)
+{
+ GdkGCPrivate *private;
+
+ g_return_if_fail (gc != NULL);
+
+ private = (GdkGCPrivate*) gc;
+
+ XSetClipOrigin (private->xdisplay, private->xgc, x, y);
+}
+
+void
+gdk_gc_set_clip_mask (GdkGC *gc,
+ GdkBitmap *mask)
+{
+ GdkGCPrivate *private;
+ Pixmap xmask;
+
+ g_return_if_fail (gc != NULL);
+
+ private = (GdkGCPrivate*) gc;
+
+ if (mask)
+ xmask = ((GdkWindowPrivate*) mask)->xwindow;
+ else
+ xmask = None;
+
+ XSetClipMask (private->xdisplay, private->xgc, xmask);
+}
+
+
+void
+gdk_gc_set_clip_rectangle (GdkGC *gc,
+ GdkRectangle *rectangle)
+{
+ GdkGCPrivate *private;
+ XRectangle xrectangle;
+
+ g_return_if_fail (gc != NULL);
+
+ private = (GdkGCPrivate*) gc;
+
+ xrectangle.x = rectangle->x;
+ xrectangle.y = rectangle->y;
+ xrectangle.width = rectangle->width;
+ xrectangle.height = rectangle->height;
+
+ XSetClipRectangles (private->xdisplay, private->xgc, 0, 0,
+ &xrectangle, 1, Unsorted);
+}
+
+void
+gdk_gc_set_subwindow (GdkGC *gc,
+ GdkSubwindowMode mode)
+{
+ GdkGCPrivate *private;
+
+ g_return_if_fail (gc != NULL);
+
+ private = (GdkGCPrivate*) gc;
+
+ XSetSubwindowMode (private->xdisplay, private->xgc, mode);
+}
+
+void
+gdk_gc_set_exposures (GdkGC *gc,
+ gint exposures)
+{
+ GdkGCPrivate *private;
+
+ g_return_if_fail (gc != NULL);
+
+ private = (GdkGCPrivate*) gc;
+
+ XSetGraphicsExposures (private->xdisplay, private->xgc, exposures);
+}
+
+void
+gdk_gc_set_line_attributes (GdkGC *gc,
+ gint line_width,
+ GdkLineStyle line_style,
+ GdkCapStyle cap_style,
+ GdkJoinStyle join_style)
+{
+ GdkGCPrivate *private;
+ int xline_style;
+ int xcap_style;
+ int xjoin_style;
+
+ g_return_if_fail (gc != NULL);
+
+ private = (GdkGCPrivate*) gc;
+
+ switch (line_style)
+ {
+ case GDK_LINE_SOLID:
+ xline_style = LineSolid;
+ break;
+ case GDK_LINE_ON_OFF_DASH:
+ xline_style = LineOnOffDash;
+ break;
+ case GDK_LINE_DOUBLE_DASH:
+ xline_style = LineDoubleDash;
+ break;
+ default:
+ xline_style = None;
+ }
+
+ switch (cap_style)
+ {
+ case GDK_CAP_NOT_LAST:
+ xcap_style = CapNotLast;
+ break;
+ case GDK_CAP_BUTT:
+ xcap_style = CapButt;
+ break;
+ case GDK_CAP_ROUND:
+ xcap_style = CapRound;
+ break;
+ case GDK_CAP_PROJECTING:
+ xcap_style = CapProjecting;
+ break;
+ default:
+ xcap_style = None;
+ }
+
+ switch (join_style)
+ {
+ case GDK_JOIN_MITER:
+ xjoin_style = JoinMiter;
+ break;
+ case GDK_JOIN_ROUND:
+ xjoin_style = JoinRound;
+ break;
+ case GDK_JOIN_BEVEL:
+ xjoin_style = JoinBevel;
+ break;
+ default:
+ xjoin_style = None;
+ }
+
+ XSetLineAttributes (private->xdisplay, private->xgc, line_width,
+ xline_style, xcap_style, xjoin_style);
+}
diff --git a/gdk/gdkglobals.c b/gdk/gdkglobals.c
new file mode 100644
index 000000000..58f7bf844
--- /dev/null
+++ b/gdk/gdkglobals.c
@@ -0,0 +1,47 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include "gdktypes.h"
+#include "gdkprivate.h"
+
+gint gdk_debug_level = 0;
+gint gdk_show_events = FALSE;
+gint gdk_use_xshm = TRUE;
+gchar *gdk_display_name = NULL;
+Display *gdk_display = NULL;
+gint gdk_screen;
+Window gdk_root_window;
+Window gdk_leader_window;
+GdkWindowPrivate gdk_root_parent;
+Atom gdk_wm_delete_window;
+Atom gdk_wm_take_focus;
+Atom gdk_wm_protocols;
+Atom gdk_wm_window_protocols[2];
+Atom gdk_selection_property;
+GdkDndGlobals gdk_dnd = {None,None,None,
+ None,None,None,
+ None,
+ None,None,
+ NULL,
+ 0, 0,
+ {0,0}};
+gchar *gdk_progname = NULL;
+gchar *gdk_progclass = NULL;
+gint gdk_error_code;
+gint gdk_error_warnings = TRUE;
diff --git a/gdk/gdkimage.c b/gdk/gdkimage.c
new file mode 100644
index 000000000..bcda3119f
--- /dev/null
+++ b/gdk/gdkimage.c
@@ -0,0 +1,492 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "../config.h"
+
+#include <sys/types.h>
+
+#if defined (HAVE_IPC_H) && defined (HAVE_SHM_H) && defined (HAVE_XSHM_H)
+#define USE_SHM
+#endif
+
+#ifdef USE_SHM
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#endif /* USE_SHM */
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#ifdef USE_SHM
+#include <X11/extensions/XShm.h>
+#endif /* USE_SHM */
+
+#include "gdk.h"
+#include "gdkprivate.h"
+
+
+static void gdk_image_put_normal (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkImage *image,
+ gint xsrc,
+ gint ysrc,
+ gint xdest,
+ gint ydest,
+ gint width,
+ gint height);
+static void gdk_image_put_shared (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkImage *image,
+ gint xsrc,
+ gint ysrc,
+ gint xdest,
+ gint ydest,
+ gint width,
+ gint height);
+
+
+static GList *image_list = NULL;
+
+
+void
+gdk_image_exit ()
+{
+ GdkImage *image;
+
+ while (image_list)
+ {
+ image = image_list->data;
+ gdk_image_destroy (image);
+ }
+}
+
+GdkImage *
+gdk_image_new_bitmap(GdkVisual *visual, gpointer data, gint w, gint h)
+/*
+ * Desc: create a new bitmap image
+ */
+{
+ Visual *xvisual;
+ GdkImage *image;
+ GdkImagePrivate *private;
+ private = g_new(GdkImagePrivate, 1);
+ image = (GdkImage *) private;
+ private->xdisplay = gdk_display;
+ private->image_put = gdk_image_put_normal;
+ image->type = GDK_IMAGE_NORMAL;
+ image->visual = visual;
+ image->width = w;
+ image->height = h;
+ image->depth = 1;
+ xvisual = ((GdkVisualPrivate*) visual)->xvisual;
+ private->ximage = XCreateImage(private->xdisplay, xvisual, 1, XYBitmap,
+ 0, 0, w ,h, 8, 0);
+ private->ximage->data = data;
+ private->ximage->bitmap_bit_order = MSBFirst;
+ private->ximage->byte_order = MSBFirst;
+ image->byte_order = MSBFirst;
+ image->mem = private->ximage->data;
+ image->bpl = private->ximage->bytes_per_line;
+ image->bpp = 1;
+ return(image);
+} /* gdk_image_new_bitmap() */
+
+static int
+gdk_image_check_xshm(Display *display)
+/*
+ * Desc: query the server for support for the MIT_SHM extension
+ * Return: 0 = not available
+ * 1 = shared XImage support available
+ * 2 = shared Pixmap support available also
+ */
+{
+#ifdef USE_SHM
+ int major, minor, ignore;
+ Bool pixmaps;
+
+ if (XQueryExtension(display, "MIT-SHM", &ignore, &ignore, &ignore))
+ {
+ if (XShmQueryVersion(display, &major, &minor, &pixmaps )==True)
+ {
+ return (pixmaps==True) ? 2 : 1;
+ }
+ }
+#endif /* USE_SHM */
+ return 0;
+}
+
+void
+gdk_image_init ()
+{
+ if (gdk_use_xshm)
+ {
+ if (!gdk_image_check_xshm (gdk_display))
+ {
+ g_warning ("MIT-SHM Extension not availible on server");
+ gdk_use_xshm = False;
+ }
+ }
+}
+
+GdkImage*
+gdk_image_new (GdkImageType type,
+ GdkVisual *visual,
+ gint width,
+ gint height)
+{
+ GdkImage *image;
+ GdkImagePrivate *private;
+#ifdef USE_SHM
+ XShmSegmentInfo *x_shm_info;
+#endif /* USE_SHM */
+ Visual *xvisual;
+
+ switch (type)
+ {
+ case GDK_IMAGE_FASTEST:
+ image = gdk_image_new (GDK_IMAGE_SHARED, visual, width, height);
+
+ if (!image)
+ image = gdk_image_new (GDK_IMAGE_NORMAL, visual, width, height);
+ break;
+
+ default:
+ private = g_new (GdkImagePrivate, 1);
+ image = (GdkImage*) private;
+
+ private->xdisplay = gdk_display;
+ private->image_put = NULL;
+
+ image->type = type;
+ image->visual = visual;
+ image->width = width;
+ image->height = height;
+ image->depth = visual->depth;
+
+ xvisual = ((GdkVisualPrivate*) visual)->xvisual;
+
+ switch (type)
+ {
+ case GDK_IMAGE_SHARED:
+#ifdef USE_SHM
+ if (gdk_use_xshm)
+ {
+ private->image_put = gdk_image_put_shared;
+
+ private->x_shm_info = g_new (XShmSegmentInfo, 1);
+ x_shm_info = private->x_shm_info;
+
+ private->ximage = XShmCreateImage (private->xdisplay, xvisual, visual->depth,
+ ZPixmap, NULL, x_shm_info, width, height);
+ if (private->ximage == NULL)
+ {
+ g_warning ("XShmCreateImage failed");
+
+ g_free (image);
+ gdk_use_xshm = False;
+ return NULL;
+ }
+
+ x_shm_info->shmid = shmget (IPC_PRIVATE,
+ private->ximage->bytes_per_line * private->ximage->height,
+ IPC_CREAT | 0777);
+
+ if (x_shm_info->shmid == -1)
+ {
+ g_warning ("shmget failed!");
+
+ XDestroyImage (private->ximage);
+ g_free (private->x_shm_info);
+ g_free (image);
+
+ gdk_use_xshm = False;
+ gdk_use_xshm = False;
+ return NULL;
+ }
+
+ x_shm_info->readOnly = False;
+ x_shm_info->shmaddr = shmat (x_shm_info->shmid, 0, 0);
+ private->ximage->data = x_shm_info->shmaddr;
+
+ if (x_shm_info->shmaddr == (char*) -1)
+ {
+ g_warning ("shmat failed!");
+
+ XDestroyImage (private->ximage);
+ shmctl (x_shm_info->shmid, IPC_RMID, 0);
+
+ g_free (private->x_shm_info);
+ g_free (image);
+
+ return NULL;
+ }
+
+#ifdef IPC_RMID_DEFERRED_RELEASE
+ if (x_shm_info->shmaddr != (char*) -1)
+ shmctl (x_shm_info->shmid, IPC_RMID, 0);
+#endif
+
+ gdk_error_code = 0;
+ gdk_error_warnings = 0;
+
+ XShmAttach (private->xdisplay, x_shm_info);
+ XSync (private->xdisplay, False);
+
+ gdk_error_warnings = 1;
+ if (gdk_error_code == -1)
+ {
+ g_warning ("XShmAttach failed!");
+
+ XDestroyImage (private->ximage);
+ shmdt (x_shm_info->shmaddr);
+ shmctl (x_shm_info->shmid, IPC_RMID, 0);
+
+ g_free (private->x_shm_info);
+ g_free (image);
+
+ gdk_use_xshm = False;
+ return NULL;
+ }
+
+ if (image)
+ image_list = g_list_prepend (image_list, image);
+ }
+ else
+ {
+ g_free (image);
+ return NULL;
+ }
+ break;
+#else /* USE_SHM */
+ g_free (image);
+ return NULL;
+#endif /* USE_SHM */
+ case GDK_IMAGE_NORMAL:
+ private->image_put = gdk_image_put_normal;
+
+ private->ximage = XCreateImage (private->xdisplay, xvisual, visual->depth,
+ ZPixmap, 0, 0, width, height, 32, 0);
+
+ private->ximage->data = g_new (char, private->ximage->bytes_per_line *
+ private->ximage->height);
+ break;
+
+ case GDK_IMAGE_FASTEST:
+ g_assert_not_reached ();
+ }
+
+ if (image)
+ {
+ image->byte_order = private->ximage->byte_order;
+ image->mem = private->ximage->data;
+ image->bpl = private->ximage->bytes_per_line;
+
+ switch (private->ximage->bits_per_pixel)
+ {
+ case 8:
+ image->bpp = 1;
+ break;
+ case 16:
+ image->bpp = 2;
+ break;
+ case 24:
+ image->bpp = 3;
+ break;
+ case 32:
+ image->bpp = 4;
+ break;
+ }
+ }
+ }
+
+ return image;
+}
+
+GdkImage*
+gdk_image_get (GdkWindow *window,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ GdkImage *image;
+ GdkImagePrivate *private;
+ GdkWindowPrivate *win_private;
+
+ g_return_val_if_fail (window != NULL, NULL);
+
+ win_private = (GdkWindowPrivate *) window;
+
+ private = g_new (GdkImagePrivate, 1);
+ image = (GdkImage*) private;
+
+ private->xdisplay = gdk_display;
+ private->image_put = gdk_image_put_normal;
+ private->ximage = XGetImage (private->xdisplay,
+ win_private->xwindow,
+ x, y, width, height,
+ AllPlanes, ZPixmap);
+
+ image->type = GDK_IMAGE_NORMAL;
+ image->visual = gdk_window_get_visual (window);
+ image->width = width;
+ image->height = height;
+ image->depth = private->ximage->depth;
+
+ image->mem = private->ximage->data;
+ image->bpl = private->ximage->bytes_per_line;
+ image->bpp = 1;
+
+ return image;
+}
+
+guint32
+gdk_image_get_pixel (GdkImage *image,
+ gint x,
+ gint y)
+{
+ guint32 pixel;
+ GdkImagePrivate *private;
+
+ g_return_val_if_fail (image != NULL, 0);
+
+ private = (GdkImagePrivate *) image;
+
+ pixel = XGetPixel (private->ximage, x, y);
+
+ return pixel;
+}
+
+void
+gdk_image_put_pixel (GdkImage *image,
+ gint x,
+ gint y,
+ guint32 pixel)
+{
+ GdkImagePrivate *private;
+
+ g_return_if_fail (image != NULL);
+
+ private = (GdkImagePrivate *) image;
+
+ pixel = XPutPixel (private->ximage, x, y, pixel);
+}
+
+void
+gdk_image_destroy (GdkImage *image)
+{
+ GdkImagePrivate *private;
+#ifdef USE_SHM
+ XShmSegmentInfo *x_shm_info;
+#endif /* USE_SHM */
+
+ g_return_if_fail (image != NULL);
+
+ private = (GdkImagePrivate*) image;
+ switch (image->type)
+ {
+ case GDK_IMAGE_NORMAL:
+ XDestroyImage (private->ximage);
+ break;
+
+ case GDK_IMAGE_SHARED:
+#ifdef USE_SHM
+ XShmDetach (private->xdisplay, private->x_shm_info);
+ XDestroyImage (private->ximage);
+
+ x_shm_info = private->x_shm_info;
+ shmdt (x_shm_info->shmaddr);
+ shmctl (x_shm_info->shmid, IPC_RMID, 0);
+
+ g_free (private->x_shm_info);
+
+ image_list = g_list_remove (image_list, image);
+#else /* USE_SHM */
+ g_error ("trying to destroy shared memory image when gdk was compiled without shared memory support");
+#endif /* USE_SHM */
+ break;
+
+ case GDK_IMAGE_FASTEST:
+ g_assert_not_reached ();
+ }
+
+ g_free (image);
+}
+
+static void
+gdk_image_put_normal (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkImage *image,
+ gint xsrc,
+ gint ysrc,
+ gint xdest,
+ gint ydest,
+ gint width,
+ gint height)
+{
+ GdkWindowPrivate *drawable_private;
+ GdkImagePrivate *image_private;
+ GdkGCPrivate *gc_private;
+
+ g_return_if_fail (drawable != NULL);
+ g_return_if_fail (image != NULL);
+ g_return_if_fail (gc != NULL);
+
+ drawable_private = (GdkWindowPrivate*) drawable;
+ image_private = (GdkImagePrivate*) image;
+ gc_private = (GdkGCPrivate*) gc;
+
+ g_return_if_fail (image->type == GDK_IMAGE_NORMAL);
+
+ XPutImage (drawable_private->xdisplay, drawable_private->xwindow,
+ gc_private->xgc, image_private->ximage,
+ xsrc, ysrc, xdest, ydest, width, height);
+}
+
+static void
+gdk_image_put_shared (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkImage *image,
+ gint xsrc,
+ gint ysrc,
+ gint xdest,
+ gint ydest,
+ gint width,
+ gint height)
+{
+#ifdef USE_SHM
+ GdkWindowPrivate *drawable_private;
+ GdkImagePrivate *image_private;
+ GdkGCPrivate *gc_private;
+
+ g_return_if_fail (drawable != NULL);
+ g_return_if_fail (image != NULL);
+ g_return_if_fail (gc != NULL);
+
+ drawable_private = (GdkWindowPrivate*) drawable;
+ image_private = (GdkImagePrivate*) image;
+ gc_private = (GdkGCPrivate*) gc;
+
+ g_return_if_fail (image->type == GDK_IMAGE_SHARED);
+
+ XShmPutImage (drawable_private->xdisplay, drawable_private->xwindow,
+ gc_private->xgc, image_private->ximage,
+ xsrc, ysrc, xdest, ydest, width, height, False);
+#else /* USE_SHM */
+ g_error ("trying to draw shared memory image when gdk was compiled without shared memory support");
+#endif /* USE_SHM */
+}
diff --git a/gdk/gdkinput.c b/gdk/gdkinput.c
new file mode 100644
index 000000000..ad4b1fcc9
--- /dev/null
+++ b/gdk/gdkinput.c
@@ -0,0 +1,324 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include "../config.h"
+#include "gdk.h"
+#include "gdkx.h"
+#include "gdkprivate.h"
+#include "gdkinput.h"
+
+
+/* Forward declarations */
+
+static gint gdk_input_enable_window (GdkWindow *window,
+ GdkDevicePrivate *gdkdev);
+static gint gdk_input_disable_window (GdkWindow *window,
+ GdkDevicePrivate *gdkdev);
+static GdkInputWindow *gdk_input_window_find (GdkWindow *window);
+static GdkDevicePrivate *gdk_input_find_device (guint32 id);
+
+
+/* Incorporate the specific routines depending on compilation options */
+
+static GdkAxisUse gdk_input_core_axes[] = { GDK_AXIS_X, GDK_AXIS_Y };
+
+static GdkDeviceInfo gdk_input_core_info =
+{
+ GDK_CORE_POINTER,
+ "Core Pointer",
+ GDK_SOURCE_MOUSE,
+ GDK_MODE_SCREEN,
+ TRUE,
+ 2,
+ gdk_input_core_axes
+};
+
+/* Global variables */
+
+GdkInputVTable gdk_input_vtable;
+/* information about network port and host for gxid daemon */
+gchar *gdk_input_gxid_host;
+gint gdk_input_gxid_port;
+gint gdk_input_ignore_core;
+
+/* Local variables */
+
+static GList *gdk_input_devices;
+static GList *gdk_input_windows;
+
+#include "gdkinputnone.h"
+#include "gdkinputcommon.h"
+#include "gdkinputxfree.h"
+#include "gdkinputgxi.h"
+
+GList *
+gdk_input_list_devices ()
+{
+ return gdk_input_devices;
+}
+
+void
+gdk_input_set_source (guint32 deviceid, GdkInputSource source)
+{
+ GdkDevicePrivate *gdkdev = gdk_input_find_device(deviceid);
+ g_return_if_fail (gdkdev != NULL);
+
+ gdkdev->info.source = source;
+}
+
+gint
+gdk_input_set_mode (guint32 deviceid, GdkInputMode mode)
+{
+ if (deviceid == GDK_CORE_POINTER)
+ return FALSE;
+
+ if (gdk_input_vtable.set_mode)
+ return gdk_input_vtable.set_mode(deviceid,mode);
+ else
+ return FALSE;
+}
+
+void
+gdk_input_set_axes (guint32 deviceid, GdkAxisUse *axes)
+{
+ if (deviceid != GDK_CORE_POINTER && gdk_input_vtable.set_axes)
+ gdk_input_vtable.set_axes (deviceid, axes);
+}
+
+GdkTimeCoord *
+gdk_input_motion_events (GdkWindow *window,
+ guint32 deviceid,
+ guint32 start,
+ guint32 stop,
+ gint *nevents_return)
+{
+ XTimeCoord *xcoords;
+ GdkTimeCoord *coords;
+ int i;
+
+ if (deviceid == GDK_CORE_POINTER)
+ {
+ xcoords = XGetMotionEvents (gdk_display,
+ ((GdkWindowPrivate *)window)->xwindow,
+ start, stop, nevents_return);
+ if (xcoords)
+ {
+ coords = g_new (GdkTimeCoord, *nevents_return);
+ for (i=0; i<*nevents_return; i++)
+ {
+ coords[i].time = xcoords[i].time;
+ coords[i].x = xcoords[i].x;
+ coords[i].y = xcoords[i].y;
+ coords[i].pressure = 0.5;
+ coords[i].xtilt = 0.0;
+ coords[i].ytilt = 0.0;
+ }
+
+ XFree(xcoords);
+
+ return coords;
+ }
+ else
+ return NULL;
+ }
+ else
+ {
+ if (gdk_input_vtable.motion_events)
+ {
+ return gdk_input_vtable.motion_events(window,
+ deviceid, start, stop,
+ nevents_return);
+ }
+ else
+ {
+ *nevents_return = 0;
+ return NULL;
+ }
+ }
+}
+
+static gint
+gdk_input_enable_window (GdkWindow *window, GdkDevicePrivate *gdkdev)
+{
+ if (gdk_input_vtable.enable_window)
+ return gdk_input_vtable.enable_window (window, gdkdev);
+ else
+ return TRUE;
+}
+
+static gint
+gdk_input_disable_window (GdkWindow *window, GdkDevicePrivate *gdkdev)
+{
+ if (gdk_input_vtable.disable_window)
+ return gdk_input_vtable.disable_window(window,gdkdev);
+ else
+ return TRUE;
+}
+
+
+static GdkInputWindow *
+gdk_input_window_find(GdkWindow *window)
+{
+ GList *tmp_list;
+
+ for (tmp_list=gdk_input_windows; tmp_list; tmp_list=tmp_list->next)
+ if (((GdkInputWindow *)(tmp_list->data))->window == window)
+ return (GdkInputWindow *)(tmp_list->data);
+
+ return NULL; /* Not found */
+}
+
+/* FIXME: this routine currently needs to be called between creation
+ and the corresponding configure event (because it doesn't get the
+ root_relative_geometry). This should work with
+ gtk_window_set_extension_events, but will likely fail in other
+ cases */
+
+void
+gdk_input_set_extension_events (GdkWindow *window, gint mask,
+ GdkExtensionMode mode)
+{
+ GList *tmp_list;
+ GdkInputWindow *iw;
+
+ g_return_if_fail (window != NULL);
+
+ if (mode == GDK_EXTENSION_EVENTS_NONE)
+ mask = 0;
+
+ if (mask != 0)
+ {
+ iw = g_new(GdkInputWindow,1);
+
+ iw->window = window;
+ iw->mode = mode;
+
+ iw->obscuring = NULL;
+ iw->num_obscuring = 0;
+ iw->grabbed = FALSE;
+
+ gdk_input_windows = g_list_append(gdk_input_windows,iw);
+ ((GdkWindowPrivate *)window)->extension_events = mask;
+
+ /* Add enter window events to the event mask */
+ /* FIXME, this is not needed for XINPUT_NONE */
+ gdk_window_set_events (window,
+ gdk_window_get_events (window) |
+ GDK_ENTER_NOTIFY_MASK);
+ }
+ else
+ {
+ iw = gdk_input_window_find (window);
+ if (iw)
+ {
+ gdk_input_windows = g_list_remove(gdk_input_windows,iw);
+ g_free(iw);
+ }
+
+ ((GdkWindowPrivate *)window)->extension_events = 0;
+ }
+
+ for (tmp_list = gdk_input_devices; tmp_list; tmp_list = tmp_list->next)
+ {
+ GdkDevicePrivate *gdkdev = (GdkDevicePrivate *)(tmp_list->data);
+
+ if (gdkdev->info.deviceid != GDK_CORE_POINTER)
+ {
+ if (mask != 0 && gdkdev->info.mode != GDK_MODE_DISABLED
+ && (gdkdev->info.has_cursor || mode == GDK_EXTENSION_EVENTS_ALL))
+ gdk_input_enable_window(window,gdkdev);
+ else
+ gdk_input_disable_window(window,gdkdev);
+ }
+ }
+}
+
+void
+gdk_input_window_destroy (GdkWindow *window)
+{
+ GdkInputWindow *input_window;
+
+ input_window = gdk_input_window_find (window);
+ g_return_if_fail (input_window != NULL);
+
+ gdk_input_windows = g_list_remove(gdk_input_windows,input_window);
+ g_free(input_window);
+}
+
+void
+gdk_input_exit (void)
+{
+ GList *tmp_list;
+ GdkDevicePrivate *gdkdev;
+
+ for (tmp_list = gdk_input_devices; tmp_list; tmp_list = tmp_list->next)
+ {
+ gdkdev = (GdkDevicePrivate *)(tmp_list->data);
+ if (gdkdev->info.deviceid != GDK_CORE_POINTER)
+ {
+ gdk_input_set_mode(gdkdev->info.deviceid,GDK_MODE_DISABLED);
+
+ g_free(gdkdev->info.name);
+#ifndef XINPUT_NONE
+ g_free(gdkdev->axes);
+#endif
+ g_free(gdkdev->info.axes);
+ g_free(gdkdev);
+ }
+ }
+
+ g_list_free(gdk_input_devices);
+
+ for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
+ {
+ g_free(tmp_list->data);
+ }
+ g_list_free(gdk_input_windows);
+}
+
+static GdkDevicePrivate *
+gdk_input_find_device(guint32 id)
+{
+ GList *tmp_list = gdk_input_devices;
+ GdkDevicePrivate *gdkdev;
+ while (tmp_list)
+ {
+ gdkdev = (GdkDevicePrivate *)(tmp_list->data);
+ if (gdkdev->info.deviceid == id)
+ return gdkdev;
+ tmp_list = tmp_list->next;
+ }
+ return NULL;
+}
+
+void
+gdk_input_window_get_pointer (GdkWindow *window,
+ guint32 deviceid,
+ gdouble *x,
+ gdouble *y,
+ gdouble *pressure,
+ gdouble *xtilt,
+ gdouble *ytilt,
+ GdkModifierType *mask)
+{
+ if (gdk_input_vtable.get_pointer)
+ gdk_input_vtable.get_pointer (window, deviceid, x, y, pressure,
+ xtilt, ytilt, mask);
+}
diff --git a/gdk/gdkinput.h b/gdk/gdkinput.h
new file mode 100644
index 000000000..21aee6000
--- /dev/null
+++ b/gdk/gdkinput.h
@@ -0,0 +1,143 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __GDK_INPUT_H__
+#define __GDK_INPUT_H__
+
+#ifndef XINPUT_NONE
+#include <X11/extensions/XInput.h>
+#endif
+
+typedef struct _GdkAxisInfo GdkAxisInfo;
+typedef struct _GdkInputVTable GdkInputVTable;
+typedef struct _GdkDevicePrivate GdkDevicePrivate;
+typedef struct _GdkInputWindow GdkInputWindow;
+
+struct _GdkInputVTable {
+ gint (*set_mode) (guint32 deviceid, GdkInputMode mode);
+ void (*set_axes) (guint32 deviceid, GdkAxisUse *axes);
+ GdkTimeCoord* (*motion_events) (GdkWindow *window,
+ guint32 deviceid,
+ guint32 start,
+ guint32 stop,
+ gint *nevents_return);
+ void (*get_pointer) (GdkWindow *window,
+ guint32 deviceid,
+ gdouble *x,
+ gdouble *y,
+ gdouble *pressure,
+ gdouble *xtilt,
+ gdouble *ytilt,
+ GdkModifierType *mask);
+ gint (*grab_pointer) (GdkWindow * window,
+ gint owner_events,
+ GdkEventMask event_mask,
+ GdkWindow * confine_to,
+ guint32 time);
+ void (*ungrab_pointer) (guint32 time);
+
+ void (*configure_event) (XConfigureEvent *xevent, GdkWindow *window);
+ void (*enter_event) (XCrossingEvent *xevent, GdkWindow *window);
+ gint (*other_event) (GdkEvent *event, XEvent *xevent, GdkWindow *window);
+ /* Handle an unidentified event. Returns TRUE if handled, FALSE
+ otherwise */
+ gint (*window_none_event) (GdkEvent *event, XEvent *xevent);
+ gint (*enable_window) (GdkWindow *window, GdkDevicePrivate *gdkdev);
+ gint (*disable_window) (GdkWindow *window, GdkDevicePrivate *gdkdev);
+};
+
+/* information about a device axis */
+struct _GdkAxisInfo
+{
+ /* reported x resolution */
+ gint xresolution;
+
+ /* reported x minimum/maximum values */
+ gint xmin_value, xmax_value;
+
+ /* calibrated resolution (for aspect ration) - only relative values
+ between axes used */
+ gint resolution;
+
+ /* calibrated minimum/maximum values */
+ gint min_value, max_value;
+};
+
+#define GDK_INPUT_NUM_EVENTC 6
+
+struct _GdkDevicePrivate {
+ GdkDeviceInfo info;
+
+#ifndef XINPUT_NONE
+ /* information about the axes */
+ GdkAxisInfo *axes;
+
+ /* reverse lookup on axis use type */
+ gint axis_for_use[GDK_AXIS_LAST];
+
+ /* Information about XInput device */
+ XDevice *xdevice;
+
+ int buttonpress_type, buttonrelease_type, motionnotify_type,
+ proximityin_type, proximityout_type, changenotify_type;
+
+ /* true if we need to select a different set of events, but
+ can't because this is the core pointer */
+ gint needs_update;
+
+ /* Mask of buttons (used for button grabs) */
+ gint button_state;
+
+ /* true if we've claimed the device as active. (used only for XINPUT_GXI) */
+ gint claimed;
+#endif /* !XINPUT_NONE */
+};
+
+struct _GdkInputWindow
+{
+ /* gdk window */
+ GdkWindow *window;
+
+ /* Extension mode (GDK_EXTENSION_EVENTS_ALL/CURSOR) */
+ GdkExtensionMode mode;
+
+ /* position relative to root window */
+ gint16 root_x;
+ gint16 root_y;
+
+ /* rectangles relative to window of windows obscuring this one */
+ GdkRectangle *obscuring;
+ gint num_obscuring;
+
+ /* Is there a pointer grab for this window ? */
+ gint grabbed;
+};
+
+/* Global data */
+
+extern GdkInputVTable gdk_input_vtable;
+/* information about network port and host for gxid daemon */
+extern gchar *gdk_input_gxid_host;
+extern gint gdk_input_gxid_port;
+extern gint gdk_input_ignore_core;
+
+/* Function declarations */
+
+void gdk_input_window_destroy (GdkWindow *window);
+
+#endif __GDK_INPUT_H__
diff --git a/gdk/gdkinputcommon.h b/gdk/gdkinputcommon.h
new file mode 100644
index 000000000..5e457e0aa
--- /dev/null
+++ b/gdk/gdkinputcommon.h
@@ -0,0 +1,687 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#if defined(XINPUT_GXI) || defined(XINPUT_XFREE)
+
+/* Forward declarations */
+static void gdk_input_get_root_relative_geometry (Display *dpy, Window w,
+ int *x_ret, int *y_ret,
+ int *width_ret,
+ int *height_ret);
+static GdkDevicePrivate *gdk_input_device_new(XDeviceInfo *device,
+ gint include_core);
+static void gdk_input_common_find_events(GdkWindow *window,
+ GdkDevicePrivate *gdkdev,
+ gint mask,
+ XEventClass *classes,
+ int *num_classes);
+static void gdk_input_common_select_events(GdkWindow *window,
+ GdkDevicePrivate *gdkdev);
+static void gdk_input_translate_coordinates(GdkDevicePrivate *gdkdev,
+ GdkInputWindow *input_window,
+ gint *axis_data,
+ gdouble *x, gdouble *y,
+ gdouble *pressure,
+ gdouble *xtilt, gdouble *ytilt);
+static guint gdk_input_translate_state(guint state, guint device_state);
+static gint gdk_input_common_init(gint include_core);
+static gint gdk_input_common_other_event (GdkEvent *event,
+ XEvent *xevent,
+ GdkInputWindow *input_window,
+ GdkDevicePrivate *gdkdev);
+static void gdk_input_common_set_axes (guint32 deviceid, GdkAxisUse *axes);
+static GdkTimeCoord * gdk_input_common_motion_events (GdkWindow *window,
+ guint32 deviceid,
+ guint32 start,
+ guint32 stop,
+ gint *nevents_return);
+static void gdk_input_common_get_pointer (GdkWindow *window,
+ guint32 deviceid,
+ gdouble *x,
+ gdouble *y,
+ gdouble *pressure,
+ gdouble *xtilt,
+ gdouble *ytilt,
+ GdkModifierType *mask);
+
+/* Global variables */
+
+static gint gdk_input_root_width;
+static gint gdk_input_root_height;
+
+static void
+gdk_input_get_root_relative_geometry(Display *dpy, Window w, int *x_ret, int *y_ret,
+ int *width_ret, int *height_ret)
+{
+ Window root,parent;
+ Window *children;
+ int nchildren;
+ int x,y,width,height;
+ int xc,yc,widthc,heightc,border_widthc,depthc;
+
+ XQueryTree(dpy,w,&root,&parent,&children,&nchildren);
+ if (children) XFree(children);
+ XGetGeometry(dpy,w,&root,&x,&y,&width,&height,&border_widthc,
+ &depthc);
+ x += border_widthc;
+ y += border_widthc;
+
+ while (root != parent)
+ {
+ w = parent;
+ XQueryTree(dpy,w,&root,&parent,&children,&nchildren);
+ if (children) XFree(children);
+ XGetGeometry(dpy,w,&root,&xc,&yc,&widthc,&heightc,
+ &border_widthc,&depthc);
+ x += xc + border_widthc;
+ y += yc + border_widthc;
+ }
+
+ if (x_ret)
+ *x_ret = x;
+ if (y_ret)
+ *y_ret = y;
+ if (width_ret)
+ *width_ret = width;
+ if (height_ret)
+ *height_ret = height;
+}
+
+static GdkDevicePrivate *
+gdk_input_device_new(XDeviceInfo *device, gint include_core)
+{
+ GdkDevicePrivate *gdkdev;
+ gchar *tmp_name, *p;
+ XAnyClassPtr class;
+ gint i,j;
+
+ gdkdev = g_new(GdkDevicePrivate,1);
+
+ gdkdev->info.deviceid = device->id;
+ if (device->name[0]) {
+ gdkdev->info.name = g_new(char, strlen(device->name)+1);
+ strcpy(gdkdev->info.name,device->name);
+ } else {
+ /* XFree86 3.2 gives an empty name to the default core devices,
+ (fixed in 3.2A) */
+ gdkdev->info.name = g_strdup("pointer");
+ strcpy(gdkdev->info.name,"pointer");
+ gdkdev->info.source = GDK_SOURCE_MOUSE;
+ }
+
+ gdkdev->info.mode = GDK_MODE_DISABLED;
+
+ /* Try to figure out what kind of device this is by its name -
+ could invite a very, very, long list... Lowercase name
+ for comparison purposes */
+
+ tmp_name = g_strdup(gdkdev->info.name);
+ for (p = tmp_name; *p; p++)
+ {
+ if (*p >= 'A' && *p <= 'Z')
+ *p += 'a' - 'A';
+ }
+
+ if (!strcmp (tmp_name, "pointer"))
+ gdkdev->info.source = GDK_SOURCE_MOUSE;
+ else if (!strcmp (tmp_name, "wacom") ||
+ !strcmp (tmp_name, "pen"))
+ gdkdev->info.source = GDK_SOURCE_PEN;
+ else if (!strcmp (tmp_name, "eraser"))
+ gdkdev->info.source = GDK_SOURCE_ERASER;
+ else if (!strcmp (tmp_name, "cursor"))
+ gdkdev->info.source = GDK_SOURCE_CURSOR;
+ else
+ gdkdev->info.source = GDK_SOURCE_PEN;
+
+ g_free(tmp_name);
+
+ gdkdev->xdevice = NULL;
+
+ /* step through the classes */
+
+ gdkdev->info.num_axes = 0;
+ gdkdev->axes = 0;
+ gdkdev->info.has_cursor = 0;
+ gdkdev->needs_update = FALSE;
+ gdkdev->claimed = FALSE;
+ gdkdev->button_state = 0;
+
+ class = device->inputclassinfo;
+ for (i=0;i<device->num_classes;i++)
+ {
+ switch (class->class) {
+ case ButtonClass:
+ {
+ break;
+ }
+ case ValuatorClass:
+ {
+ XValuatorInfo *xvi = (XValuatorInfo *)class;
+ gdkdev->info.num_axes = xvi->num_axes;
+ gdkdev->axes = g_new(GdkAxisInfo, xvi->num_axes);
+ gdkdev->info.axes = g_new(GdkAxisUse, xvi->num_axes);
+ for (j=0;j<xvi->num_axes;j++)
+ {
+ gdkdev->axes[j].resolution =
+ gdkdev->axes[j].xresolution = xvi->axes[j].resolution;
+ gdkdev->axes[j].min_value =
+ gdkdev->axes[j].xmin_value = xvi->axes[j].min_value;
+ gdkdev->axes[j].max_value =
+ gdkdev->axes[j].xmax_value = xvi->axes[j].max_value;
+ gdkdev->info.axes[j] = GDK_AXIS_IGNORE;
+ }
+ j=0;
+ if (j<xvi->num_axes)
+ gdkdev->info.axes[j++] = GDK_AXIS_X;
+ if (j<xvi->num_axes)
+ gdkdev->info.axes[j++] = GDK_AXIS_Y;
+ if (j<xvi->num_axes)
+ gdkdev->info.axes[j++] = GDK_AXIS_PRESSURE;
+ if (j<xvi->num_axes)
+ gdkdev->info.axes[j++] = GDK_AXIS_XTILT;
+ if (j<xvi->num_axes)
+ gdkdev->info.axes[j++] = GDK_AXIS_YTILT;
+
+ /* set up reverse lookup on axis use */
+ for (j=GDK_AXIS_IGNORE;j<GDK_AXIS_LAST;j++)
+ gdkdev->axis_for_use[j] = -1;
+
+ for (j=0;j<xvi->num_axes;j++)
+ if (gdkdev->info.axes[j] != GDK_AXIS_IGNORE)
+ gdkdev->axis_for_use[gdkdev->info.axes[j]] = j;
+
+ break;
+ }
+ }
+ class = (XAnyClassPtr)(((char *)class) + class->length);
+ }
+ /* return NULL if no axes */
+ if (!gdkdev->info.num_axes || !gdkdev->axes ||
+ (!include_core && device->use == IsXPointer))
+ {
+ g_free(gdkdev->info.name);
+ if (gdkdev->axes)
+ g_free(gdkdev->axes);
+ g_free(gdkdev);
+ return NULL;
+ }
+
+ if (device->use != IsXPointer)
+ gdkdev->xdevice = XOpenDevice(gdk_display, gdkdev->info.deviceid);
+
+ return gdkdev;
+}
+
+static void
+gdk_input_common_find_events(GdkWindow *window,
+ GdkDevicePrivate *gdkdev,
+ gint mask,
+ XEventClass *classes,
+ int *num_classes)
+{
+ gint i;
+ XEventClass class;
+
+ i = 0;
+ /* We have to track press and release events in pairs to keep
+ track of button state correctly and implement grabbing */
+ if (mask & GDK_BUTTON_PRESS_MASK || mask & GDK_BUTTON_RELEASE_MASK)
+ {
+ DeviceButtonPress (gdkdev->xdevice, gdkdev->buttonpress_type,
+ class);
+ if (class != 0)
+ classes[i++] = class;
+ DeviceButtonRelease (gdkdev->xdevice, gdkdev->buttonrelease_type,
+ class);
+ if (class != 0)
+ classes[i++] = class;
+ }
+ if (mask & GDK_POINTER_MOTION_MASK)
+ {
+ DeviceMotionNotify (gdkdev->xdevice, gdkdev->motionnotify_type, class);
+ if (class != 0)
+ classes[i++] = class;
+ }
+ if (mask & GDK_POINTER_MOTION_HINT_MASK)
+ {
+ /* We'll get into trouble if the macros change, but at least we'll
+ know about it, and we avoid warnings now */
+ DevicePointerMotionHint (gdkdev->xdevice, 0, class);
+ if (class != 0)
+ classes[i++] = class;
+ }
+ if (mask & GDK_PROXIMITY_IN_MASK)
+ {
+ ProximityIn (gdkdev->xdevice, gdkdev->proximityin_type, class);
+ if (class != 0)
+ classes[i++] = class;
+ }
+ if (mask & GDK_PROXIMITY_OUT_MASK)
+ {
+ ProximityOut (gdkdev->xdevice, gdkdev->proximityout_type, class);
+ if (class != 0)
+ classes[i++] = class;
+ }
+
+ *num_classes = i;
+}
+
+static void
+gdk_input_common_select_events(GdkWindow *window,
+ GdkDevicePrivate *gdkdev)
+{
+ XEventClass classes[6];
+ gint num_classes;
+
+ if (gdkdev->info.mode == GDK_MODE_DISABLED)
+ gdk_input_common_find_events(window, gdkdev, 0, classes, &num_classes);
+ else
+ gdk_input_common_find_events(window, gdkdev,
+ ((GdkWindowPrivate *)window)->extension_events,
+ classes, &num_classes);
+
+ XSelectExtensionEvent (gdk_display,
+ GDK_WINDOW_XWINDOW(window),
+ classes, num_classes);
+}
+
+gint
+gdk_input_common_init(gint include_core)
+{
+ char **extensions;
+ XDeviceInfo *devices;
+ int num_devices;
+ int num_extensions, loop;
+ Display *display = gdk_display;
+
+ /* Init global vars */
+ gdk_window_get_geometry(NULL, /* use root window */
+ NULL,NULL,
+ &gdk_input_root_width,&gdk_input_root_height,
+ NULL);
+
+ /* Init XInput extension */
+
+ extensions = XListExtensions(display, &num_extensions);
+ for (loop = 0; loop < num_extensions &&
+ (strcmp(extensions[loop], "XInputExtension") != 0); loop++);
+ XFreeExtensionList(extensions);
+ if (loop == num_extensions) /* XInput extension not found */
+ return FALSE;
+
+ gdk_input_devices = 0;
+ devices = XListInputDevices(display, &num_devices);
+
+ for(loop=0; loop<num_devices; loop++)
+ {
+ GdkDevicePrivate *gdkdev = gdk_input_device_new(&devices[loop],
+ include_core);
+ if (gdkdev)
+ gdk_input_devices = g_list_append(gdk_input_devices, gdkdev);
+ }
+ XFreeDeviceList(devices);
+
+ gdk_input_devices = g_list_append (gdk_input_devices, &gdk_input_core_info);
+
+ return TRUE;
+}
+
+static void
+gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
+ GdkInputWindow *input_window,
+ gint *axis_data,
+ gdouble *x, gdouble *y, gdouble *pressure,
+ gdouble *xtilt, gdouble *ytilt)
+{
+ GdkWindowPrivate *win_priv;
+
+ int x_axis, y_axis, pressure_axis, xtilt_axis, ytilt_axis;
+
+ double device_width, device_height;
+ double x_offset, y_offset, x_scale, y_scale;
+
+ win_priv = (GdkWindowPrivate *) input_window->window;
+
+ x_axis = gdkdev->axis_for_use[GDK_AXIS_X];
+ y_axis = gdkdev->axis_for_use[GDK_AXIS_Y];
+ pressure_axis = gdkdev->axis_for_use[GDK_AXIS_PRESSURE];
+ xtilt_axis = gdkdev->axis_for_use[GDK_AXIS_XTILT];
+ ytilt_axis = gdkdev->axis_for_use[GDK_AXIS_YTILT];
+
+ device_width = gdkdev->axes[x_axis].max_value -
+ gdkdev->axes[x_axis].min_value;
+ device_height = gdkdev->axes[y_axis].max_value -
+ gdkdev->axes[y_axis].min_value;
+
+ if (gdkdev->info.mode == GDK_MODE_SCREEN)
+ {
+ x_scale = gdk_input_root_width / device_width;
+ y_scale = gdk_input_root_height / device_height;
+
+ x_offset = - input_window->root_x;
+ y_offset = - input_window->root_y;
+ }
+ else /* GDK_MODE_WINDOW */
+ {
+ double device_aspect = (device_height*gdkdev->axes[y_axis].resolution) /
+ (device_width*gdkdev->axes[x_axis].resolution);
+
+ if (device_aspect * win_priv->width >= win_priv->height)
+ {
+ /* device taller than window */
+ x_scale = win_priv->width / device_width;
+ y_scale = (x_scale * gdkdev->axes[x_axis].resolution)
+ / gdkdev->axes[y_axis].resolution;
+
+ x_offset = 0;
+ y_offset = -(device_height * y_scale -
+ win_priv->height)/2;
+ }
+ else
+ {
+ /* window taller than device */
+ y_scale = win_priv->height / device_height;
+ x_scale = (y_scale * gdkdev->axes[y_axis].resolution)
+ / gdkdev->axes[x_axis].resolution;
+
+ y_offset = 0;
+ x_offset = - (device_width * x_scale - win_priv->width)/2;
+ }
+ }
+
+ if (x) *x = x_offset + x_scale*axis_data[x_axis];
+ if (y) *y = y_offset + y_scale*axis_data[y_axis];
+
+ if (pressure)
+ {
+ if (pressure_axis != -1)
+ *pressure = ((double)axis_data[pressure_axis]
+ - gdkdev->axes[pressure_axis].min_value)
+ / (gdkdev->axes[pressure_axis].max_value
+ - gdkdev->axes[pressure_axis].min_value);
+ else
+ *pressure = 0.5;
+ }
+
+ if (xtilt)
+ {
+ if (xtilt_axis != -1)
+ {
+ *xtilt = 2. * (double)(axis_data[xtilt_axis] -
+ (gdkdev->axes[xtilt_axis].min_value +
+ gdkdev->axes[xtilt_axis].max_value)/2) /
+ (gdkdev->axes[xtilt_axis].max_value -
+ gdkdev->axes[xtilt_axis].min_value);
+ }
+ else *xtilt = 0;
+ }
+
+ if (ytilt)
+ {
+ if (ytilt_axis != -1)
+ {
+ *ytilt = 2. * (double)(axis_data[ytilt_axis] -
+ (gdkdev->axes[ytilt_axis].min_value +
+ gdkdev->axes[ytilt_axis].max_value)/2) /
+ (gdkdev->axes[ytilt_axis].max_value -
+ gdkdev->axes[ytilt_axis].min_value);
+ }
+ else
+ *ytilt = 0;
+ }
+}
+
+/* combine the state of the core device and the device state
+ into one - for now we do this in a simple-minded manner -
+ we just take the keyboard portion of the core device and
+ the button portion (all of?) the device state.
+ Any button remapping should go on here. */
+static guint
+gdk_input_translate_state(guint state, guint device_state)
+{
+ return device_state | (state & 0xFF);
+}
+
+static gint
+gdk_input_common_other_event (GdkEvent *event,
+ XEvent *xevent,
+ GdkInputWindow *input_window,
+ GdkDevicePrivate *gdkdev)
+{
+ if ((xevent->type == gdkdev->buttonpress_type) ||
+ (xevent->type == gdkdev->buttonrelease_type))
+ {
+ XDeviceButtonEvent *xdbe = (XDeviceButtonEvent *)(xevent);
+
+ if (xdbe->type == gdkdev->buttonpress_type)
+ {
+ event->button.type = GDK_BUTTON_PRESS;
+ gdkdev->button_state |= 1 << xdbe->button;
+ }
+ else
+ {
+ event->button.type = GDK_BUTTON_RELEASE;
+ gdkdev->button_state &= ~(1 << xdbe->button);
+ }
+ event->button.window = input_window->window;
+ event->button.time = xdbe->time;
+ event->button.source = gdkdev->info.source;
+ event->button.deviceid = xdbe->deviceid;
+
+ gdk_input_translate_coordinates (gdkdev,input_window, xdbe->axis_data,
+ &event->button.x,&event->button.y,
+ &event->button.pressure,
+ &event->button.xtilt,
+ &event->button.ytilt);
+ event->button.state = gdk_input_translate_state(xdbe->state,xdbe->device_state);
+ event->button.button = xdbe->button;
+
+ return TRUE;
+ }
+
+ if (xevent->type == gdkdev->motionnotify_type)
+ {
+ XDeviceMotionEvent *xdme = (XDeviceMotionEvent *)(xevent);
+
+ gdk_input_translate_coordinates(gdkdev,input_window,xdme->axis_data,
+ &event->motion.x,&event->motion.y,
+ &event->motion.pressure,
+ &event->motion.xtilt,
+ &event->motion.ytilt);
+
+ event->motion.type = GDK_MOTION_NOTIFY;
+ event->motion.window = input_window->window;
+ event->motion.time = xdme->time;
+ event->motion.deviceid = xdme->deviceid;
+ event->motion.state = gdk_input_translate_state(xdme->state,
+ xdme->device_state);
+ event->motion.source = gdkdev->info.source;
+ event->motion.deviceid = xdme->deviceid;
+
+ if (gdk_show_events)
+ g_print ("motion notify:\t\twindow: %ld device: %ld x,y: %f %f hint: %s\n",
+ xdme->window,
+ xdme->deviceid,
+ event->motion.x, event->motion.y,
+ (xevent->xmotion.is_hint) ? "true" : "false");
+
+
+ return TRUE;
+ }
+
+ if (xevent->type == gdkdev->proximityin_type ||
+ xevent->type == gdkdev->proximityout_type)
+ {
+ XProximityNotifyEvent *xpne = (XProximityNotifyEvent *)(xevent);
+
+ event->proximity.type = (xevent->type == gdkdev->proximityin_type)?
+ GDK_PROXIMITY_IN:GDK_PROXIMITY_OUT;
+ event->proximity.window = input_window->window;
+ event->proximity.time = xpne->time;
+ event->proximity.source = gdkdev->info.source;
+ event->proximity.deviceid = xpne->deviceid;
+
+ return TRUE;
+ }
+
+ return -1; /* wasn't one of our event types */
+}
+
+static void
+gdk_input_common_set_axes (guint32 deviceid, GdkAxisUse *axes)
+{
+ int i;
+ GdkDevicePrivate *gdkdev = gdk_input_find_device(deviceid);
+ g_return_if_fail (gdkdev != NULL);
+
+ for (i=GDK_AXIS_IGNORE;i<GDK_AXIS_LAST;i++)
+ {
+ gdkdev->axis_for_use[i] = -1;
+ }
+
+ for (i=0;i<gdkdev->info.num_axes;i++)
+ {
+ gdkdev->info.axes[i] = axes[i];
+ gdkdev->axis_for_use[axes[i]] = i;
+ }
+}
+
+static GdkTimeCoord *
+gdk_input_common_motion_events (GdkWindow *window,
+ guint32 deviceid,
+ guint32 start,
+ guint32 stop,
+ gint *nevents_return)
+{
+ GdkTimeCoord *coords;
+ XDeviceTimeCoord *device_coords;
+ GdkInputWindow *input_window;
+ GdkDevicePrivate *gdkdev;
+
+ int mode_return;
+ int axis_count_return;
+ int i;
+
+ gdkdev = gdk_input_find_device (deviceid);
+ input_window = gdk_input_window_find (window);
+
+ g_return_val_if_fail (gdkdev != NULL, NULL);
+ g_return_val_if_fail (gdkdev->xdevice != NULL, NULL);
+ g_return_val_if_fail (input_window != NULL, NULL);
+
+ device_coords = XGetDeviceMotionEvents (gdk_display,
+ gdkdev->xdevice,
+ start, stop,
+ nevents_return, &mode_return,
+ &axis_count_return);
+
+ if (device_coords)
+ {
+ coords = g_new (GdkTimeCoord, *nevents_return);
+
+ for (i=0; i<*nevents_return; i++)
+ {
+ gdk_input_translate_coordinates (gdkdev, input_window,
+ device_coords[i].data,
+ &coords[i].x, &coords[i].y,
+ &coords[i].pressure,
+ &coords[i].xtilt, &coords[i].ytilt);
+ }
+ XFreeDeviceMotionEvents (device_coords);
+
+ return coords;
+ }
+ else
+ return NULL;
+}
+
+static void
+gdk_input_common_get_pointer (GdkWindow *window,
+ guint32 deviceid,
+ gdouble *x,
+ gdouble *y,
+ gdouble *pressure,
+ gdouble *xtilt,
+ gdouble *ytilt,
+ GdkModifierType *mask)
+{
+ GdkDevicePrivate *gdkdev;
+ GdkInputWindow *input_window;
+ XDeviceState *state;
+ XInputClass *input_class;
+ gint x_int, y_int;
+ gint i;
+
+ /* we probably need to get the mask in any case */
+
+ if (deviceid == GDK_CORE_POINTER)
+ {
+ gdk_window_get_pointer (window, &x_int, &y_int, mask);
+ if (x) *x = x_int;
+ if (y) *y = y_int;
+ if (pressure) *pressure = 0.5;
+ if (xtilt) *xtilt = 0;
+ if (ytilt) *ytilt = 0;
+ }
+ else
+ {
+ if (mask)
+ gdk_window_get_pointer (window, NULL, NULL, mask);
+
+ gdkdev = gdk_input_find_device (deviceid);
+ input_window = gdk_input_window_find (window);
+
+ g_return_if_fail (gdkdev != NULL);
+ g_return_if_fail (gdkdev->xdevice != NULL);
+ g_return_if_fail (input_window != NULL);
+
+ state = XQueryDeviceState (gdk_display, gdkdev->xdevice);
+ input_class = state->data;
+ for (i=0; i<state->num_classes; i++)
+ {
+ switch (input_class->class)
+ {
+ case ValuatorClass:
+ gdk_input_translate_coordinates(gdkdev, input_window,
+ ((XValuatorState *)input_class)->valuators,
+ x, y, pressure,
+ xtilt, ytilt);
+
+
+ break;
+ case ButtonClass:
+ if (mask)
+ {
+ *mask &= ~(GDK_BUTTON1_MASK | GDK_BUTTON2_MASK |
+ GDK_BUTTON3_MASK | GDK_BUTTON4_MASK |
+ GDK_BUTTON5_MASK);
+ for (i=0; i < ((XButtonState *)input_class)->num_buttons; i++)
+ {
+ if (((XButtonState *)input_class)->buttons[i])
+ *mask |= GDK_BUTTON1_MASK << i;
+ }
+ }
+ break;
+ }
+ input_class = (XInputClass *)(((char *)input_class)+input_class->length);
+ }
+ }
+}
+
+#endif
diff --git a/gdk/gdkinputgxi.h b/gdk/gdkinputgxi.h
new file mode 100644
index 000000000..a30e05f95
--- /dev/null
+++ b/gdk/gdkinputgxi.h
@@ -0,0 +1,628 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef XINPUT_GXI
+
+/* #define DEBUG_SWITCHING */
+
+#include <gxid_lib.h>
+
+/* Forward declarations */
+static void gdk_input_gxi_select_notify (GdkDevicePrivate *gdkdev);
+static gint gdk_input_gxi_set_mode (guint32 deviceid, GdkInputMode mode);
+static gint gdk_input_is_extension_device (guint32 deviceid);
+static void gdk_input_gxi_configure_event (XConfigureEvent *xevent,
+ GdkWindow *window);
+static void gdk_input_gxi_enter_event (XCrossingEvent *xevent,
+ GdkWindow *window);
+static gint gdk_input_gxi_other_event (GdkEvent *event,
+ XEvent *xevent,
+ GdkWindow *window);
+static void gdk_input_gxi_update_device (GdkDevicePrivate *gdkdev);
+
+static gint gdk_input_gxi_window_none_event (GdkEvent *event, XEvent *xevent);
+static gint gdk_input_gxi_enable_window (GdkWindow *window,
+ GdkDevicePrivate *gdkdev);
+static gint gdk_input_gxi_disable_window (GdkWindow *window,
+ GdkDevicePrivate *gdkdev);
+static Window gdk_input_find_root_child(Display *dpy, Window w);
+static void gdk_input_compute_obscuring(GdkInputWindow *input_window);
+static gint gdk_input_is_obscured(GdkInputWindow *input_window, gdouble x,
+ gdouble y);
+static GdkTimeCoord *gdk_input_gxi_motion_events (GdkWindow *window,
+ guint32 deviceid,
+ guint32 start,
+ guint32 stop,
+ gint *nevents_return);
+static void gdk_input_gxi_get_pointer (GdkWindow *window,
+ guint32 deviceid,
+ gdouble *x,
+ gdouble *y,
+ gdouble *pressure,
+ gdouble *xtilt,
+ gdouble *ytilt,
+ GdkModifierType *mask);
+static gint gdk_input_gxi_grab_pointer (GdkWindow * window,
+ gint owner_events,
+ GdkEventMask event_mask,
+ GdkWindow * confine_to,
+ guint32 time);
+static void gdk_input_gxi_ungrab_pointer (guint32 time);
+
+/* Local variables */
+
+static GdkDevicePrivate *gdk_input_current_device;
+static GdkDevicePrivate *gdk_input_core_pointer;
+
+void
+gdk_input_init(void)
+{
+ GList *tmp_list;
+
+ gdk_input_vtable.set_mode = gdk_input_gxi_set_mode;
+ gdk_input_vtable.set_axes = gdk_input_common_set_axes;
+ gdk_input_vtable.motion_events = gdk_input_gxi_motion_events;
+ gdk_input_vtable.get_pointer = gdk_input_gxi_get_pointer;
+ gdk_input_vtable.grab_pointer = gdk_input_gxi_grab_pointer;
+ gdk_input_vtable.ungrab_pointer = gdk_input_gxi_ungrab_pointer;
+ gdk_input_vtable.configure_event = gdk_input_gxi_configure_event;
+ gdk_input_vtable.enter_event = gdk_input_gxi_enter_event;
+ gdk_input_vtable.other_event = gdk_input_gxi_other_event;
+ gdk_input_vtable.window_none_event = gdk_input_gxi_window_none_event;
+ gdk_input_vtable.enable_window = gdk_input_gxi_enable_window;
+ gdk_input_vtable.disable_window = gdk_input_gxi_disable_window;
+
+ gdk_input_ignore_core = FALSE;
+ gdk_input_core_pointer = NULL;
+
+ if (!gdk_input_gxid_host)
+ {
+ gdk_input_gxid_host = getenv("GXID_HOST");
+ }
+ if (!gdk_input_gxid_port)
+ {
+ char *t = getenv("GXID_PORT");
+ if (t)
+ gdk_input_gxid_port = atoi(t);
+ }
+
+ gdk_input_common_init(TRUE);
+
+ /* find initial core pointer */
+
+ for (tmp_list = gdk_input_devices; tmp_list; tmp_list = tmp_list->next)
+ {
+ GdkDevicePrivate *gdkdev = (GdkDevicePrivate *)tmp_list->data;
+ if (gdk_input_is_extension_device(gdkdev->info.deviceid))
+ {
+ gdk_input_gxi_select_notify (gdkdev);
+ }
+ else
+ {
+ if (gdkdev->info.deviceid != GDK_CORE_POINTER)
+ gdk_input_core_pointer = gdkdev;
+ }
+ }
+}
+
+static void
+gdk_input_gxi_select_notify (GdkDevicePrivate *gdkdev)
+{
+ XEventClass class;
+
+ ChangeDeviceNotify (gdkdev->xdevice, gdkdev->changenotify_type, class);
+
+ XSelectExtensionEvent (gdk_display, gdk_root_window, &class, 1);
+}
+
+/* Set the core pointer. Device should already be enabled. */
+static gint
+gdk_input_gxi_set_core_pointer(GdkDevicePrivate *gdkdev)
+{
+ int x_axis,y_axis;
+
+ g_return_val_if_fail(gdkdev->xdevice,FALSE);
+
+ x_axis = gdkdev->axis_for_use[GDK_AXIS_X];
+ y_axis = gdkdev->axis_for_use[GDK_AXIS_Y];
+
+ g_return_val_if_fail(x_axis != -1 && y_axis != -1,FALSE);
+
+ /* core_pointer might not be up to date so we check with the server
+ before change the pointer */
+
+ if ( !gdk_input_is_extension_device(gdkdev->info.deviceid) )
+ {
+#if 0
+ if (gdkdev != gdk_input_core_pointer)
+ g_warning("core pointer inconsistency");
+#endif
+ return TRUE;
+ }
+
+ if ( XChangePointerDevice(gdk_display,gdkdev->xdevice, x_axis, y_axis)
+ != Success )
+ {
+ return FALSE;
+ }
+ else
+ {
+ gdk_input_gxi_update_device (gdk_input_core_pointer);
+ gdk_input_core_pointer = gdkdev;
+ return TRUE;
+ }
+}
+
+
+/* FIXME, merge with gdk_input_xfree_set_mode */
+
+static gint
+gdk_input_gxi_set_mode (guint32 deviceid, GdkInputMode mode)
+{
+ GList *tmp_list;
+ GdkDevicePrivate *gdkdev;
+ GdkInputMode old_mode;
+ GdkInputWindow *input_window;
+
+ gdkdev = gdk_input_find_device(deviceid);
+ g_return_val_if_fail (gdkdev != NULL,FALSE);
+ old_mode = gdkdev->info.mode;
+
+ if (gdkdev->info.mode == mode)
+ return TRUE;
+
+ gdkdev->info.mode = mode;
+
+ if (old_mode != GDK_MODE_DISABLED)
+ {
+ for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
+ {
+ input_window = (GdkInputWindow *)tmp_list->data;
+ if (input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
+ gdk_input_disable_window (input_window->window, gdkdev);
+ }
+ }
+
+ if (mode != GDK_MODE_DISABLED)
+ {
+ for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
+ {
+ input_window = (GdkInputWindow *)tmp_list->data;
+ if (input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
+ if (!gdk_input_enable_window(input_window->window, gdkdev))
+ {
+ gdk_input_set_mode(deviceid, old_mode);
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+
+}
+
+gint
+gdk_input_is_extension_device (guint32 deviceid)
+{
+ XDeviceInfo *devices;
+ int num_devices, loop;
+
+ if (deviceid == GDK_CORE_POINTER)
+ return FALSE;
+
+ devices = XListInputDevices(gdk_display, &num_devices);
+ for(loop=0; loop<num_devices; loop++)
+ {
+ if ((devices[loop].id == deviceid) && (devices[loop].use == IsXExtensionDevice))
+ {
+ XFreeDeviceList(devices);
+ return TRUE;
+ }
+ }
+
+ XFreeDeviceList(devices);
+ return FALSE;
+}
+
+static void
+gdk_input_gxi_configure_event (XConfigureEvent *xevent, GdkWindow *window)
+{
+ GdkInputWindow *input_window;
+ gint root_x, root_y;
+
+ input_window = gdk_input_window_find(window);
+ g_return_if_fail (input_window != NULL);
+
+ gdk_input_get_root_relative_geometry(gdk_display,GDK_WINDOW_XWINDOW(window),
+ &root_x, &root_y, NULL, NULL);
+ input_window->root_x = root_x;
+ input_window->root_y = root_y;
+ gdk_input_compute_obscuring(input_window);
+}
+
+static void
+gdk_input_gxi_enter_event (XCrossingEvent *xevent, GdkWindow *window)
+{
+ GdkInputWindow *input_window;
+
+ input_window = gdk_input_window_find(window);
+ g_return_if_fail (input_window != NULL);
+
+ gdk_input_compute_obscuring(input_window);
+}
+
+static gint
+gdk_input_gxi_other_event (GdkEvent *event,
+ XEvent *xevent,
+ GdkWindow *window)
+{
+ GdkInputWindow *input_window;
+
+ GdkDevicePrivate *gdkdev;
+ gint return_val;
+
+ input_window = gdk_input_window_find(window);
+ g_return_val_if_fail (window != NULL, -1);
+
+ /* This is a sort of a hack, as there isn't any XDeviceAnyEvent -
+ but it's potentially faster than scanning through the types of
+ every device. If we were deceived, then it won't match any of
+ the types for the device anyways */
+ gdkdev = gdk_input_find_device(((XDeviceButtonEvent *)xevent)->deviceid);
+
+ if (!gdkdev) {
+ return -1; /* we don't handle it - not an XInput event */
+ }
+
+ if (gdkdev->info.mode == GDK_MODE_DISABLED ||
+ input_window->mode == GDK_EXTENSION_EVENTS_CURSOR)
+ return FALSE;
+
+ if (gdkdev != gdk_input_current_device &&
+ xevent->type != gdkdev->changenotify_type)
+ {
+ gdk_input_current_device = gdkdev;
+ }
+
+ return_val = gdk_input_common_other_event (event, xevent,
+ input_window, gdkdev);
+
+ if (return_val > 0 && event->type == GDK_MOTION_NOTIFY &&
+ (!gdkdev->button_state) && (!input_window->grabbed) &&
+ ((event->motion.x < 0) || (event->motion.y < 0) ||
+ (event->motion.x > ((GdkWindowPrivate *)window)->width) ||
+ (event->motion.y > ((GdkWindowPrivate *)window)->height) ||
+ gdk_input_is_obscured(input_window,event->motion.x,event->motion.y)))
+ {
+#ifdef DEBUG_SWITCHING
+ g_print("gdkinput: Setting core pointer to %d on motion at (%f,%f)\n",
+ gdkdev->info.deviceid,event->motion.x,event->motion.y);
+ g_print(" window geometry is: %dx%d\n",
+ ((GdkWindowPrivate *)window)->width,
+ ((GdkWindowPrivate *)window)->height);
+#endif
+ gdk_input_gxi_set_core_pointer(gdkdev);
+ return FALSE;
+ }
+ else
+ return return_val;
+
+}
+
+static void
+gdk_input_gxi_update_device (GdkDevicePrivate *gdkdev)
+{
+ GList *t;
+
+ if (gdk_input_is_extension_device (gdkdev->info.deviceid))
+ {
+ if (!gdkdev->xdevice)
+ {
+ gdkdev->xdevice = XOpenDevice(gdk_display, gdkdev->info.deviceid);
+ gdk_input_gxi_select_notify (gdkdev);
+ gdkdev->needs_update = 1;
+ }
+ if (gdkdev->needs_update && gdkdev->xdevice)
+ {
+ for (t = gdk_input_windows; t; t = t->next)
+ gdk_input_common_select_events (((GdkInputWindow *)t->data)->window,
+ gdkdev);
+ gdkdev->needs_update = 0;
+ }
+ }
+}
+
+static gint
+gdk_input_gxi_window_none_event (GdkEvent *event, XEvent *xevent)
+{
+ GdkDevicePrivate *gdkdev =
+ gdk_input_find_device(((XDeviceButtonEvent *)xevent)->deviceid);
+
+ if (!gdkdev) {
+ return -1; /* we don't handle it - not an XInput event */
+ }
+
+ if (xevent->type == gdkdev->changenotify_type)
+ {
+ if (gdk_input_core_pointer != gdkdev)
+ {
+#ifdef DEBUG_SWITCHING
+ g_print("ChangeNotify from %d to %d:\n",
+ gdk_input_core_pointer->info.deviceid,
+ gdkdev->info.deviceid);
+#endif
+ gdk_input_gxi_update_device (gdk_input_core_pointer);
+ gdk_input_core_pointer = gdkdev;
+ }
+ }
+
+ return FALSE;
+}
+
+static gint
+gdk_input_gxi_enable_window (GdkWindow *window, GdkDevicePrivate *gdkdev)
+{
+ GdkInputWindow *input_window;
+
+ input_window = gdk_input_window_find (window);
+ g_return_val_if_fail (input_window != NULL, FALSE);
+
+ if (!gdkdev->claimed)
+ {
+ if (gxid_claim_device(gdk_input_gxid_host, gdk_input_gxid_port,
+ gdkdev->info.deviceid,
+ GDK_WINDOW_XWINDOW(window), FALSE) !=
+ GXID_RETURN_OK)
+ {
+ g_warning("Could not get device (is gxid running?)\n");
+ return FALSE;
+ }
+ gdkdev->claimed = TRUE;
+ }
+
+ if (gdkdev->xdevice && gdkdev != gdk_input_core_pointer)
+ gdk_input_common_select_events(window, gdkdev);
+ else
+ gdkdev->needs_update = TRUE;
+
+ return TRUE;
+}
+
+static gint
+gdk_input_gxi_disable_window(GdkWindow *window, GdkDevicePrivate *gdkdev)
+{
+ GdkInputWindow *input_window;
+
+ input_window = gdk_input_window_find (window);
+ g_return_val_if_fail (input_window != NULL, FALSE);
+
+ if (gdkdev->claimed)
+ {
+ gxid_release_device(gdk_input_gxid_host, gdk_input_gxid_port,
+ gdkdev->info.deviceid,
+ GDK_WINDOW_XWINDOW(window));
+
+ gdkdev->claimed = FALSE;
+ }
+
+ if (gdkdev->xdevice && gdkdev != gdk_input_core_pointer)
+ gdk_input_common_select_events(window, gdkdev);
+ else
+ gdkdev->needs_update = TRUE;
+
+ return TRUE;
+}
+
+static gint
+gdk_input_is_obscured(GdkInputWindow *input_window, gdouble x, gdouble y)
+{
+ int i;
+ for (i=0;i<input_window->num_obscuring;i++)
+ {
+ GdkRectangle *rect = &input_window->obscuring[i];
+ if ((x >= rect->x) &&
+ (y >= rect->y) &&
+ (x < rect->x + rect->width) &&
+ (y < rect->y + rect->height))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* If this routine needs fixing, the corresponding routine
+ in gxid.c will need it too. */
+
+static Window
+gdk_input_find_root_child(Display *dpy, Window w)
+{
+ Window root,parent;
+ Window *children;
+ int nchildren;
+
+ parent = w;
+ do
+ {
+ w = parent;
+ XQueryTree(dpy,w,&root,&parent,&children,&nchildren);
+ if (children) XFree(children);
+ }
+ while (parent != root);
+
+ return w;
+}
+
+void
+gdk_input_compute_obscuring(GdkInputWindow *input_window)
+{
+ int i;
+ int x,y,width,height;
+ int xc,yc,widthc,heightc,border_widthc,depthc;
+
+ Window root,parent;
+ Window *children;
+ int nchildren;
+
+ Window w = GDK_WINDOW_XWINDOW(input_window->window);
+ Window root_child = gdk_input_find_root_child(gdk_display,w);
+ gdk_input_get_root_relative_geometry(gdk_display,w,&x,&y,&width,&height);
+
+ input_window->root_x = x;
+ input_window->root_y = y;
+
+ XQueryTree(gdk_display,GDK_ROOT_WINDOW(),
+ &root,&parent,&children,&nchildren);
+
+
+ if (input_window->obscuring)
+ g_free(input_window->obscuring);
+ input_window->obscuring = 0;
+ input_window->num_obscuring = 0;
+
+ for (i=0;i<nchildren;i++)
+ if (children[i] == root_child)
+ break;
+
+ if (i>=nchildren-1)
+ {
+ if (nchildren)
+ XFree(children);
+ return;
+ }
+
+ input_window->obscuring = g_new(GdkRectangle,(nchildren-i-1));
+
+ for (i=i+1;i<nchildren;i++)
+ {
+ int xmin, xmax, ymin, ymax;
+ XGetGeometry(gdk_display,children[i],&root,&xc,&yc,&widthc,&heightc,
+ &border_widthc, &depthc);
+ xmin = xc>x ? xc : x;
+ xmax = (xc+widthc)<(x+width) ? xc+widthc : x+width;
+ ymin = yc>y ? yc : y;
+ ymax = (yc+heightc)<(y+height) ? yc+heightc : y+height;
+ if ((xmin < xmax) && (ymin < ymax))
+ {
+ XWindowAttributes attributes;
+ XGetWindowAttributes(gdk_display,children[i],&attributes);
+ if (attributes.map_state == IsViewable)
+ {
+ GdkRectangle *rect = &input_window->obscuring[input_window->num_obscuring];
+
+ /* we store the whole window, not just the obscuring part */
+ rect->x = xc - x;
+ rect->y = yc - y;
+ rect->width = widthc;
+ rect->height = heightc;
+ input_window->num_obscuring++;
+ }
+ }
+ }
+
+ if (nchildren)
+ XFree(children);
+}
+
+static void
+gdk_input_gxi_get_pointer (GdkWindow *window,
+ guint32 deviceid,
+ gdouble *x,
+ gdouble *y,
+ gdouble *pressure,
+ gdouble *xtilt,
+ gdouble *ytilt,
+ GdkModifierType *mask)
+{
+ GdkDevicePrivate *gdkdev;
+
+ gdkdev = gdk_input_find_device (deviceid);
+ g_return_if_fail (gdkdev != NULL);
+
+ if (gdkdev == gdk_input_core_pointer)
+ gdk_input_common_get_pointer (window, GDK_CORE_POINTER, x, y,
+ pressure, xtilt, ytilt, mask);
+ else
+ gdk_input_common_get_pointer (window, deviceid, x, y,
+ pressure, xtilt, ytilt, mask);
+}
+
+static GdkTimeCoord *
+gdk_input_gxi_motion_events (GdkWindow *window,
+ guint32 deviceid,
+ guint32 start,
+ guint32 stop,
+ gint *nevents_return)
+{
+ GdkDevicePrivate *gdkdev;
+
+ gdkdev = gdk_input_find_device (deviceid);
+ g_return_val_if_fail (gdkdev != NULL, NULL);
+
+
+ if (gdkdev == gdk_input_core_pointer)
+ return gdk_input_motion_events (window, GDK_CORE_POINTER, start, stop,
+ nevents_return);
+ else
+ return gdk_input_common_motion_events (window, deviceid, start, stop,
+ nevents_return);
+
+}
+
+static gint
+gdk_input_gxi_grab_pointer (GdkWindow * window,
+ gint owner_events,
+ GdkEventMask event_mask,
+ GdkWindow * confine_to,
+ guint32 time)
+{
+ GdkInputWindow *input_window, *new_window;
+ GList *tmp_list;
+
+ tmp_list = gdk_input_windows;
+ while (tmp_list)
+ {
+ input_window = (GdkInputWindow *)tmp_list->data;
+ if (input_window->grabbed)
+ return AlreadyGrabbed;
+
+ if (input_window->window == window)
+ new_window = input_window;
+
+ tmp_list = tmp_list->next;
+ }
+
+ new_window->grabbed = TRUE;
+ return Success;
+}
+
+static void
+gdk_input_gxi_ungrab_pointer (guint32 time)
+{
+ GdkInputWindow *input_window;
+ GList *tmp_list;
+
+ tmp_list = gdk_input_windows;
+ while (tmp_list)
+ {
+ input_window = (GdkInputWindow *)tmp_list->data;
+ if (input_window->grabbed)
+ input_window->grabbed = FALSE;
+ tmp_list = tmp_list->next;
+ }
+}
+
+#endif /* XINPUT_GXI */
diff --git a/gdk/gdkinputnone.h b/gdk/gdkinputnone.h
new file mode 100644
index 000000000..8ae8c4189
--- /dev/null
+++ b/gdk/gdkinputnone.h
@@ -0,0 +1,72 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef XINPUT_NONE
+
+static void gdk_input_none_get_pointer (GdkWindow *window,
+ guint32 deviceid,
+ gdouble *x,
+ gdouble *y,
+ gdouble *pressure,
+ gdouble *xtilt,
+ gdouble *ytilt,
+ GdkModifierType *mask);
+
+void
+gdk_input_init ()
+{
+ gdk_input_vtable.set_mode = NULL;
+ gdk_input_vtable.set_axes = NULL;
+ gdk_input_vtable.motion_events = NULL;
+ gdk_input_vtable.get_pointer = gdk_input_none_get_pointer;
+ gdk_input_vtable.grab_pointer = NULL;
+ gdk_input_vtable.ungrab_pointer = NULL;
+ gdk_input_vtable.configure_event = NULL;
+ gdk_input_vtable.enter_event = NULL;
+ gdk_input_vtable.other_event = NULL;
+ gdk_input_vtable.window_none_event = NULL;
+ gdk_input_vtable.enable_window = NULL;
+ gdk_input_vtable.disable_window = NULL;
+
+ gdk_input_devices = g_list_append (NULL, &gdk_input_core_info);
+
+ gdk_input_ignore_core = FALSE;
+}
+
+static void
+gdk_input_none_get_pointer (GdkWindow *window,
+ guint32 deviceid,
+ gdouble *x,
+ gdouble *y,
+ gdouble *pressure,
+ gdouble *xtilt,
+ gdouble *ytilt,
+ GdkModifierType *mask)
+{
+ gint x_int, y_int;
+
+ gdk_window_get_pointer (window, &x_int, &y_int, mask);
+
+ if (x) *x = x_int;
+ if (y) *y = y_int;
+ if (pressure) *pressure = 0.5;
+ if (xtilt) *xtilt = 0;
+ if (ytilt) *ytilt = 0;
+}
+
+#endif /* XINPUT_NONE */
diff --git a/gdk/gdkinputxfree.h b/gdk/gdkinputxfree.h
new file mode 100644
index 000000000..f74249008
--- /dev/null
+++ b/gdk/gdkinputxfree.h
@@ -0,0 +1,368 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef XINPUT_XFREE
+
+/* forward declarations */
+
+static gint gdk_input_xfree_set_mode (guint32 deviceid, GdkInputMode mode);
+static void gdk_input_check_proximity();
+static void gdk_input_xfree_configure_event (XConfigureEvent *xevent,
+ GdkWindow *window);
+static void gdk_input_xfree_enter_event (XCrossingEvent *xevent,
+ GdkWindow *window);
+static gint gdk_input_xfree_other_event (GdkEvent *event,
+ XEvent *xevent,
+ GdkWindow *window);
+static gint gdk_input_xfree_enable_window(GdkWindow *window,
+ GdkDevicePrivate *gdkdev);
+static gint gdk_input_xfree_disable_window(GdkWindow *window,
+ GdkDevicePrivate *gdkdev);
+static gint gdk_input_xfree_grab_pointer (GdkWindow * window,
+ gint owner_events,
+ GdkEventMask event_mask,
+ GdkWindow * confine_to,
+ guint32 time);
+static void gdk_input_xfree_ungrab_pointer (guint32 time);
+
+void
+gdk_input_init(void)
+{
+ gdk_input_vtable.set_mode = gdk_input_xfree_set_mode;
+ gdk_input_vtable.set_axes = gdk_input_common_set_axes;
+ gdk_input_vtable.motion_events = gdk_input_common_motion_events;
+ gdk_input_vtable.get_pointer = gdk_input_common_get_pointer;
+ gdk_input_vtable.grab_pointer = gdk_input_xfree_grab_pointer;
+ gdk_input_vtable.ungrab_pointer = gdk_input_xfree_ungrab_pointer;
+ gdk_input_vtable.configure_event = gdk_input_xfree_configure_event;
+ gdk_input_vtable.enter_event = gdk_input_xfree_enter_event;
+ gdk_input_vtable.other_event = gdk_input_xfree_other_event;
+ gdk_input_vtable.window_none_event = NULL;
+ gdk_input_vtable.enable_window = gdk_input_xfree_enable_window;
+ gdk_input_vtable.disable_window = gdk_input_xfree_disable_window;
+
+ gdk_input_ignore_core = FALSE;
+ gdk_input_common_init(FALSE);
+}
+
+static gint
+gdk_input_xfree_set_mode (guint32 deviceid, GdkInputMode mode)
+{
+ GList *tmp_list;
+ GdkDevicePrivate *gdkdev;
+ GdkInputMode old_mode;
+ GdkInputWindow *input_window;
+
+ gdkdev = gdk_input_find_device(deviceid);
+ g_return_val_if_fail (gdkdev != NULL,FALSE);
+ old_mode = gdkdev->info.mode;
+
+ if (gdkdev->info.mode == mode)
+ return TRUE;
+
+ gdkdev->info.mode = mode;
+
+ if (mode == GDK_MODE_WINDOW)
+ {
+ gdkdev->info.has_cursor = FALSE;
+ for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
+ {
+ input_window = (GdkInputWindow *)tmp_list->data;
+ if (input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
+ gdk_input_enable_window (input_window->window, gdkdev);
+ else
+ if (old_mode != GDK_MODE_DISABLED)
+ gdk_input_disable_window (input_window->window, gdkdev);
+ }
+ }
+ else if (mode == GDK_MODE_SCREEN)
+ {
+ gdkdev->info.has_cursor = TRUE;
+ for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
+ gdk_input_enable_window (((GdkInputWindow *)tmp_list->data)->window,
+ gdkdev);
+ }
+ else /* mode == GDK_MODE_DISABLED */
+ {
+ for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
+ {
+ input_window = (GdkInputWindow *)tmp_list->data;
+ if (old_mode != GDK_MODE_WINDOW ||
+ input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
+ gdk_input_disable_window (input_window->window, gdkdev);
+ }
+ }
+
+ return TRUE;
+
+}
+
+static void
+gdk_input_check_proximity()
+{
+ gint new_proximity = 0;
+ GList *tmp_list = gdk_input_devices;
+
+ while (tmp_list && !new_proximity)
+ {
+ GdkDevicePrivate *gdkdev = (GdkDevicePrivate *)(tmp_list->data);
+
+ if (gdkdev->info.mode != GDK_MODE_DISABLED
+ && gdkdev->info.deviceid != GDK_CORE_POINTER
+ && gdkdev->xdevice)
+ {
+ XDeviceState *state = XQueryDeviceState(GDK_DISPLAY(),
+ gdkdev->xdevice);
+ XInputClass *xic;
+ int i;
+
+ xic = state->data;
+ for (i=0; i<state->num_classes; i++)
+ {
+ if (xic->class == ValuatorClass)
+ {
+ XValuatorState *xvs = (XValuatorState *)xic;
+ if ((xvs->mode & ProximityState) == InProximity)
+ {
+ new_proximity = TRUE;
+ }
+ break;
+ }
+ xic = (XInputClass *)((char *)xic + xic->length);
+ }
+ }
+ tmp_list = tmp_list->next;
+ }
+
+ gdk_input_ignore_core = new_proximity;
+}
+
+static void
+gdk_input_xfree_configure_event (XConfigureEvent *xevent, GdkWindow *window)
+{
+ GdkInputWindow *input_window;
+ gint root_x, root_y;
+
+ input_window = gdk_input_window_find(window);
+ g_return_if_fail (window != NULL);
+
+ gdk_input_get_root_relative_geometry(GDK_DISPLAY(),GDK_WINDOW_XWINDOW(window),
+ &root_x,
+ &root_y, NULL, NULL);
+
+ input_window->root_x = root_x;
+ input_window->root_y = root_y;
+}
+
+static void
+gdk_input_xfree_enter_event (XCrossingEvent *xevent,
+ GdkWindow *window)
+{
+ GdkInputWindow *input_window;
+ gint root_x, root_y;
+
+ input_window = gdk_input_window_find(window);
+ g_return_if_fail (window != NULL);
+
+ gdk_input_check_proximity();
+
+ gdk_input_get_root_relative_geometry(GDK_DISPLAY(),GDK_WINDOW_XWINDOW(window),
+ &root_x,
+ &root_y, NULL, NULL);
+
+ input_window->root_x = root_x;
+ input_window->root_y = root_y;
+}
+
+static gint
+gdk_input_xfree_other_event (GdkEvent *event,
+ XEvent *xevent,
+ GdkWindow *window)
+{
+ GdkInputWindow *input_window;
+
+ GdkDevicePrivate *gdkdev;
+ gint return_val;
+
+ input_window = gdk_input_window_find(window);
+ g_return_val_if_fail (window != NULL, -1);
+
+ /* This is a sort of a hack, as there isn't any XDeviceAnyEvent -
+ but it's potentially faster than scanning through the types of
+ every device. If we were deceived, then it won't match any of
+ the types for the device anyways */
+ gdkdev = gdk_input_find_device(((XDeviceButtonEvent *)xevent)->deviceid);
+
+ if (!gdkdev) {
+ return -1; /* we don't handle it - not an XInput event */
+ }
+
+ /* FIXME: It would be nice if we could just get rid of the events
+ entirely, instead of having to ignore them */
+ if (gdkdev->info.mode == GDK_MODE_DISABLED ||
+ (gdkdev->info.mode == GDK_MODE_WINDOW
+ && input_window->mode == GDK_EXTENSION_EVENTS_CURSOR))
+ return FALSE;
+
+ if (!gdk_input_ignore_core)
+ gdk_input_check_proximity();
+
+ return_val = gdk_input_common_other_event (event, xevent,
+ input_window, gdkdev);
+
+ if (return_val > 0 && event->type == GDK_PROXIMITY_OUT &&
+ gdk_input_ignore_core)
+ gdk_input_check_proximity();
+
+ /* Do a passive button grab. We have to be careful not to release
+ an explicit grab, if any. Doubling the grab should be harmless,
+ but we check anyways. */
+
+ /* FIXME, finding the proper events here is going to be SLOW - but
+ we might have different sets for each window/device combination */
+
+ if (return_val> 0 && !input_window->grabbed)
+ {
+ if (event->type == GDK_BUTTON_PRESS)
+ {
+ XEventClass event_classes[6];
+ gint num_classes;
+
+ gdk_input_common_find_events (window, gdkdev,
+ ((GdkWindowPrivate *)window)->extension_events,
+ event_classes, &num_classes);
+
+ XGrabDevice( GDK_DISPLAY(), gdkdev->xdevice,
+ GDK_WINDOW_XWINDOW (window),
+ TRUE, num_classes, event_classes,
+ GrabModeAsync, GrabModeAsync, event->button.time);
+ }
+ else if (event->type == GDK_BUTTON_RELEASE)
+ XUngrabDevice( GDK_DISPLAY(), gdkdev->xdevice, event->button.time);
+ }
+
+ return return_val;
+}
+
+static gint
+gdk_input_xfree_enable_window(GdkWindow *window, GdkDevicePrivate *gdkdev)
+{
+ /* FIXME: watchout, gdkdev might be core pointer, never opened */
+ gdk_input_common_select_events (window, gdkdev);
+ return TRUE;
+}
+
+static gint
+gdk_input_xfree_disable_window(GdkWindow *window, GdkDevicePrivate *gdkdev)
+{
+ gdk_input_common_select_events (window, gdkdev);
+ return TRUE;
+}
+
+static gint
+gdk_input_xfree_grab_pointer (GdkWindow * window,
+ gint owner_events,
+ GdkEventMask event_mask,
+ GdkWindow * confine_to,
+ guint32 time)
+{
+ GdkInputWindow *input_window, *new_window;
+ GdkDevicePrivate *gdkdev;
+ GList *tmp_list;
+ XEventClass event_classes[6];
+ gint num_classes;
+
+ tmp_list = gdk_input_windows;
+ new_window = NULL;
+ while (tmp_list)
+ {
+ input_window = (GdkInputWindow *)tmp_list->data;
+ if (input_window->grabbed)
+ return AlreadyGrabbed;
+
+ if (input_window->window == window)
+ {
+ new_window = input_window;
+ break;
+ }
+
+ tmp_list = tmp_list->next;
+ }
+
+ g_return_if_fail (new_window == NULL);
+
+ new_window->grabbed = TRUE;
+
+ tmp_list = gdk_input_devices;
+ while (tmp_list)
+ {
+ gdkdev = (GdkDevicePrivate *)tmp_list->data;
+ if (gdkdev->info.deviceid != GDK_CORE_POINTER &&
+ gdkdev->xdevice && !gdkdev->button_state)
+ {
+ gdk_input_common_find_events (window, gdkdev,
+ ((GdkWindowPrivate *)window)->extension_events,
+ event_classes, &num_classes);
+
+ /* FIXME: we should do something on failure */
+ XGrabDevice( GDK_DISPLAY(), gdkdev->xdevice,
+ GDK_WINDOW_XWINDOW (window),
+ TRUE, num_classes, event_classes,
+ GrabModeAsync, GrabModeAsync, time);
+ }
+ tmp_list = tmp_list->next;
+ }
+
+ return Success;
+}
+
+static void
+gdk_input_xfree_ungrab_pointer (guint32 time)
+{
+ GdkInputWindow *input_window;
+ GdkDevicePrivate *gdkdev;
+ GList *tmp_list;
+
+ tmp_list = gdk_input_windows;
+ while (tmp_list)
+ {
+ input_window = (GdkInputWindow *)tmp_list->data;
+ if (input_window->grabbed)
+ break;
+ tmp_list = tmp_list->next;
+ }
+
+ if (tmp_list) /* we found a grabbed window */
+ {
+ input_window->grabbed = FALSE;
+
+ tmp_list = gdk_input_devices;
+ while (tmp_list)
+ {
+ gdkdev = (GdkDevicePrivate *)tmp_list->data;
+ if (gdkdev->info.deviceid != GDK_CORE_POINTER &&
+ gdkdev->xdevice && !gdkdev->button_state)
+ {
+ XUngrabDevice( gdk_display, gdkdev->xdevice, time);
+ }
+ tmp_list = tmp_list->next;
+ }
+ }
+}
+
+#endif /* XINPUT_XFREE */
diff --git a/gdk/gdkpixmap.c b/gdk/gdkpixmap.c
new file mode 100644
index 000000000..d2d96b6da
--- /dev/null
+++ b/gdk/gdkpixmap.c
@@ -0,0 +1,657 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "../config.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <X11/Xlib.h>
+
+#include "gdk.h"
+#include "gdkprivate.h"
+
+typedef struct
+{
+ gchar *color_string;
+ GdkColor color;
+ gint transparent;
+} _GdkPixmapColor;
+
+GdkPixmap*
+gdk_pixmap_new (GdkWindow *window,
+ gint width,
+ gint height,
+ gint depth)
+{
+ GdkPixmap *pixmap;
+ GdkWindowPrivate *private;
+ GdkWindowPrivate *window_private;
+
+ if (!window)
+ window = (GdkWindow*) &gdk_root_parent;
+
+ if (depth == -1)
+ gdk_window_get_geometry (window, NULL, NULL, NULL, NULL, &depth);
+
+ private = g_new (GdkWindowPrivate, 1);
+ pixmap = (GdkPixmap*) private;
+
+ window_private = (GdkWindowPrivate*) window;
+
+ private->xdisplay = window_private->xdisplay;
+ private->window_type = GDK_WINDOW_PIXMAP;
+ private->xwindow = XCreatePixmap (private->xdisplay, window_private->xwindow,
+ width, height, depth);
+ private->parent = NULL;
+ private->x = 0;
+ private->y = 0;
+ private->width = width;
+ private->height = height;
+ private->resize_count = 0;
+ private->ref_count = 1;
+ private->destroyed = 0;
+
+ gdk_xid_table_insert (&private->xwindow, pixmap);
+
+ return pixmap;
+}
+
+GdkPixmap *
+gdk_bitmap_create_from_data (GdkWindow *window,
+ gchar *data,
+ gint width,
+ gint height)
+{
+ GdkPixmap *pixmap;
+ GdkWindowPrivate *private;
+ GdkWindowPrivate *window_private;
+
+ g_return_val_if_fail (data != NULL, NULL);
+
+ if (!window)
+ window = (GdkWindow*) &gdk_root_parent;
+
+ private = g_new (GdkWindowPrivate, 1);
+ pixmap = (GdkPixmap*) private;
+
+ window_private = (GdkWindowPrivate*) window;
+
+ private->parent = NULL;
+ private->xdisplay = window_private->xdisplay;
+ private->window_type = GDK_WINDOW_PIXMAP;
+ private->x = 0;
+ private->y = 0;
+ private->width = width;
+ private->height = height;
+ private->resize_count = 0;
+ private->ref_count = 1;
+ private->destroyed = FALSE;
+
+ private->xwindow = XCreateBitmapFromData (private->xdisplay,
+ window_private->xwindow,
+ data, width, height);
+
+ gdk_xid_table_insert (&private->xwindow, pixmap);
+
+ return pixmap;
+}
+
+GdkPixmap*
+gdk_pixmap_create_from_data (GdkWindow *window,
+ gchar *data,
+ gint width,
+ gint height,
+ gint depth,
+ GdkColor *fg,
+ GdkColor *bg)
+{
+ GdkPixmap *pixmap;
+ GdkWindowPrivate *private;
+ GdkWindowPrivate *window_private;
+
+ g_return_val_if_fail (data != NULL, NULL);
+ g_return_val_if_fail (fg != NULL, NULL);
+ g_return_val_if_fail (bg != NULL, NULL);
+
+ if (!window)
+ window = (GdkWindow*) &gdk_root_parent;
+
+ if (depth == -1)
+ gdk_window_get_geometry (window, NULL, NULL, NULL, NULL, &depth);
+
+ private = g_new (GdkWindowPrivate, 1);
+ pixmap = (GdkPixmap*) private;
+
+ window_private = (GdkWindowPrivate*) window;
+
+ private->parent = NULL;
+ private->xdisplay = window_private->xdisplay;
+ private->window_type = GDK_WINDOW_PIXMAP;
+ private->x = 0;
+ private->y = 0;
+ private->width = width;
+ private->height = height;
+ private->resize_count = 0;
+ private->ref_count = 1;
+ private->destroyed = FALSE;
+
+ private->xwindow = XCreatePixmapFromBitmapData (private->xdisplay,
+ window_private->xwindow,
+ data, width, height,
+ fg->pixel, bg->pixel, depth);
+
+ gdk_xid_table_insert (&private->xwindow, pixmap);
+
+ return pixmap;
+}
+
+gint
+gdk_pixmap_seek_string (FILE *infile,
+ const gchar *str,
+ gint skip_comments)
+{
+ char instr[1024];
+
+ while (!feof (infile))
+ {
+ fscanf (infile, "%s", instr);
+ if (skip_comments == TRUE && strcmp (instr, "/*") == 0)
+ {
+ fscanf (infile, "%s", instr);
+ while (!feof (infile) && strcmp (instr, "*/") != 0)
+ fscanf (infile, "%s", instr);
+ fscanf(infile, "%s", instr);
+ }
+ if (strcmp (instr, str)==0)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+gint
+gdk_pixmap_seek_char (FILE *infile,
+ gchar c)
+{
+ gchar b, oldb;
+
+ while (!feof (infile))
+ {
+ fscanf(infile, "%c", &b);
+ if (c != b && b == '/')
+ {
+ fscanf (infile, "%c", &b);
+ if (b == '*')
+ {
+ oldb = b;
+ while (!feof (infile) && !(oldb == '*' && b == '/'))
+ {
+ oldb = b;
+ fscanf (infile, "%c", &b);
+ }
+ fscanf (infile, "%c", &b);
+ }
+ }
+ if (c == b)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+gint
+gdk_pixmap_read_string (FILE *infile,
+ gchar **buffer,
+ int *buffer_size)
+{
+ gchar c;
+ gint cnt = 0;
+
+ if ((*buffer) == NULL)
+ {
+ (*buffer_size) = 10 * sizeof (gchar);
+ (*buffer) = (gchar *) malloc (*buffer_size);
+ }
+
+ do
+ fscanf (infile, "%c", &c);
+ while (!feof (infile) && c != '"');
+
+ if (c != '"')
+ return FALSE;
+
+ while (!feof (infile))
+ {
+ fscanf (infile, "%c", &c);
+
+ if (cnt == (*buffer_size))
+ {
+ (*buffer_size) *= 2;
+ (*buffer) = (gchar *) realloc ((*buffer), *buffer_size);
+ }
+
+ if (c != '"')
+ (*buffer)[cnt++] = c;
+ else
+ {
+ (*buffer)[cnt++] = 0;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+gchar*
+gdk_pixmap_skip_whitespaces (gchar *buffer)
+{
+ gint32 index = 0;
+
+ while (buffer[index] != 0 && (buffer[index] == 0x20 || buffer[index] == 0x09))
+ index++;
+
+ return &buffer[index];
+}
+
+gchar*
+gdk_pixmap_skip_string (gchar *buffer)
+{
+ gint32 index = 0;
+
+ while (buffer[index] != 0 && buffer[index] != 0x20 && buffer[index] != 0x09)
+ index++;
+
+ return &buffer[index];
+}
+
+gchar*
+gdk_pixmap_extract_color (gchar *buffer)
+{
+ gint counter, finished = FALSE, numnames;
+ gchar *ptr = NULL, ch, temp[128];
+ gchar color[128], *retcol;
+
+ counter = 0;
+ while (ptr == NULL)
+ {
+ if (buffer[counter] == 'c')
+ {
+ ch = buffer[counter + 1];
+ if (ch == 0x20 || ch == 0x09)
+ ptr = &buffer[counter + 1];
+ }
+ else if (buffer[counter] == 0)
+ return NULL;
+
+ counter++;
+ }
+
+ if (ptr == NULL)
+ return NULL;
+
+ ptr = gdk_pixmap_skip_whitespaces (ptr);
+
+ if (ptr[0] == 0)
+ return NULL;
+ else if (ptr[0] == '#')
+ {
+ retcol = g_new(gchar, strlen (ptr) + 1);
+ strcpy (retcol, ptr);
+ return retcol;
+ }
+
+ color[0] = 0;
+ numnames = 0;
+
+ while (finished == FALSE)
+ {
+ sscanf (ptr, "%s", temp);
+
+ if ((gint)ptr[0] == 0 || strcmp ("s", temp) == 0 || strcmp ("m", temp) == 0 ||
+ strcmp ("g", temp) == 0 || strcmp ("g4", temp) == 0)
+ finished = TRUE;
+ else
+ {
+ if (numnames > 0)
+ strcat (color, " ");
+ strcat (color, temp);
+ ptr = gdk_pixmap_skip_string (ptr);
+ ptr = gdk_pixmap_skip_whitespaces (ptr);
+ numnames++;
+ }
+ }
+
+ retcol = g_new(gchar, strlen (color) + 1);
+ strcpy (retcol, color);
+ return retcol;
+}
+
+
+GdkPixmap*
+gdk_pixmap_create_from_xpm (GdkWindow *window,
+ GdkBitmap **mask,
+ GdkColor *transparent_color,
+ const gchar *filename)
+{
+ FILE *infile = NULL;
+ GdkPixmap *pixmap = NULL;
+ GdkImage *image = NULL;
+ GdkColormap *colormap;
+ GdkVisual *visual;
+ GdkGC *gc;
+ GdkColor tmp_color;
+ gint width, height, num_cols, cpp, cnt, n, ns, xcnt, ycnt;
+ gchar *buffer = NULL, *color_name = NULL, pixel_str[32];
+ guint buffer_size = 0;
+ _GdkPixmapColor *colors = NULL, *color = NULL;
+ gulong index;
+
+ if (!window)
+ window = (GdkWindow*) &gdk_root_parent;
+
+ infile = fopen (filename, "rb");
+ if (infile != NULL)
+ {
+ if (gdk_pixmap_seek_string (infile, "XPM", FALSE) == TRUE)
+ {
+ if (gdk_pixmap_seek_char (infile,'{') == TRUE)
+ {
+ gdk_pixmap_seek_char (infile, '"');
+ fseek (infile, -1, SEEK_CUR);
+ gdk_pixmap_read_string (infile, &buffer, &buffer_size);
+
+ sscanf (buffer,"%d %d %d %d", &width, &height, &num_cols, &cpp);
+
+ colors = g_new(_GdkPixmapColor, num_cols);
+
+ colormap = gdk_window_get_colormap (window);
+ visual = gdk_window_get_visual (window);
+
+ if (transparent_color == NULL)
+ {
+ gdk_color_white (colormap, &tmp_color);
+ transparent_color = &tmp_color;
+ }
+
+ for (cnt = 0; cnt < num_cols; cnt++)
+ {
+ gdk_pixmap_seek_char (infile, '"');
+ fseek (infile, -1, SEEK_CUR);
+ gdk_pixmap_read_string (infile, &buffer, &buffer_size);
+
+ colors[cnt].color_string = g_new(gchar, cpp + 1);
+ for (n = 0; n < cpp; n++)
+ colors[cnt].color_string[n] = buffer[n];
+ colors[cnt].color_string[n] = 0;
+ colors[cnt].transparent = FALSE;
+
+ if (color_name != NULL)
+ g_free (color_name);
+
+ color_name = gdk_pixmap_extract_color (&buffer[cpp]);
+
+ if (color_name != NULL)
+ {
+ if (gdk_color_parse (color_name, &colors[cnt].color) == FALSE)
+ {
+ colors[cnt].color = *transparent_color;
+ colors[cnt].transparent = TRUE;
+ }
+ }
+ else
+ {
+ colors[cnt].color = *transparent_color;
+ colors[cnt].transparent = TRUE;
+ }
+
+ gdk_color_alloc (colormap, &colors[cnt].color);
+ }
+
+ index = 0;
+ image = gdk_image_new (GDK_IMAGE_FASTEST, visual, width, height);
+
+ gc = NULL;
+ if (mask)
+ {
+ *mask = gdk_pixmap_new (window, width, height, 1);
+ gc = gdk_gc_new (*mask);
+
+ gdk_color_black (colormap, &tmp_color);
+ gdk_gc_set_foreground (gc, &tmp_color);
+ gdk_draw_rectangle (*mask, gc, TRUE, 0, 0, -1, -1);
+
+ gdk_color_white (colormap, &tmp_color);
+ gdk_gc_set_foreground (gc, &tmp_color);
+ }
+
+ for (ycnt = 0; ycnt < height; ycnt++)
+ {
+ gdk_pixmap_read_string (infile, &buffer, &buffer_size);
+
+ for (n = 0, cnt = 0, xcnt = 0; n < (width * cpp); n += cpp, xcnt++)
+ {
+ strncpy (pixel_str, &buffer[n], cpp);
+ pixel_str[cpp] = 0;
+ color = NULL;
+ ns = 0;
+
+ while (color == NULL)
+ {
+ if (strcmp (pixel_str, colors[ns].color_string) == 0)
+ color = &colors[ns];
+ else
+ ns++;
+ }
+
+ gdk_image_put_pixel (image, xcnt, ycnt, color->color.pixel);
+
+ if (mask && color->transparent)
+ {
+ if (cnt < xcnt)
+ gdk_draw_line (*mask, gc, cnt, ycnt, xcnt - 1, ycnt);
+ cnt = xcnt + 1;
+ }
+ }
+
+ if (mask && (cnt < xcnt))
+ gdk_draw_line (*mask, gc, cnt, ycnt, xcnt - 1, ycnt);
+ }
+
+ if (mask)
+ gdk_gc_destroy (gc);
+
+ pixmap = gdk_pixmap_new (window, width, height, visual->depth);
+
+ gc = gdk_gc_new (pixmap);
+ gdk_gc_set_foreground (gc, transparent_color);
+ gdk_draw_image (pixmap, gc, image, 0, 0, 0, 0, image->width, image->height);
+ gdk_gc_destroy (gc);
+ gdk_image_destroy (image);
+ }
+ }
+
+ fclose (infile);
+ free (buffer);
+
+ if (colors != NULL)
+ {
+ for (cnt = 0; cnt < num_cols; cnt++)
+ g_free (colors[cnt].color_string);
+ g_free (colors);
+ }
+ }
+
+ return pixmap;
+}
+
+GdkPixmap*
+gdk_pixmap_create_from_xpm_d (GdkWindow *window,
+ GdkBitmap **mask,
+ GdkColor *transparent_color,
+ gchar **data)
+{
+ GdkPixmap *pixmap = NULL;
+ GdkImage *image = NULL;
+ GdkColormap *colormap;
+ GdkVisual *visual;
+ GdkGC *gc;
+ GdkColor tmp_color;
+ gint width, height, num_cols, cpp, cnt, n, ns, xcnt, ycnt, i;
+ gchar *buffer, *color_name = NULL, pixel_str[32];
+ _GdkPixmapColor *colors = NULL, *color = NULL;
+ gulong index;
+
+ if (!window)
+ window = (GdkWindow*) &gdk_root_parent;
+
+ i = 0;
+ buffer = data[i++];
+ sscanf (buffer,"%d %d %d %d", &width, &height, &num_cols, &cpp);
+
+ colors = g_new(_GdkPixmapColor, num_cols);
+
+ colormap = gdk_window_get_colormap (window);
+ visual = gdk_window_get_visual (window);
+
+ if (transparent_color == NULL)
+ {
+ gdk_color_white (colormap, &tmp_color);
+ transparent_color = &tmp_color;
+ }
+
+ for (cnt = 0; cnt < num_cols; cnt++)
+ {
+ buffer = data[i++];
+
+ colors[cnt].color_string = g_new(gchar, cpp + 1);
+ for (n = 0; n < cpp; n++)
+ colors[cnt].color_string[n] = buffer[n];
+ colors[cnt].color_string[n] = 0;
+ colors[cnt].transparent = FALSE;
+
+ if (color_name != NULL)
+ g_free (color_name);
+
+ color_name = gdk_pixmap_extract_color (&buffer[cpp]);
+
+ if (color_name != NULL)
+ {
+ if (gdk_color_parse (color_name, &colors[cnt].color) == FALSE)
+ {
+ colors[cnt].color = *transparent_color;
+ colors[cnt].transparent = TRUE;
+ }
+ }
+ else
+ {
+ colors[cnt].color = *transparent_color;
+ colors[cnt].transparent = TRUE;
+ }
+
+ gdk_color_alloc (colormap, &colors[cnt].color);
+ }
+
+ index = 0;
+ image = gdk_image_new (GDK_IMAGE_FASTEST, visual, width, height);
+
+ gc = NULL;
+ if (mask)
+ {
+ *mask = gdk_pixmap_new (window, width, height, 1);
+ gc = gdk_gc_new (*mask);
+
+ gdk_color_black (colormap, &tmp_color);
+ gdk_gc_set_foreground (gc, &tmp_color);
+ gdk_draw_rectangle (*mask, gc, TRUE, 0, 0, -1, -1);
+
+ gdk_color_white (colormap, &tmp_color);
+ gdk_gc_set_foreground (gc, &tmp_color);
+ }
+
+ for (ycnt = 0; ycnt < height; ycnt++)
+ {
+ buffer = data[i++];
+
+ for (n = 0, cnt = 0, xcnt = 0; n < (width * cpp); n += cpp, xcnt++)
+ {
+ strncpy (pixel_str, &buffer[n], cpp);
+ pixel_str[cpp] = 0;
+ color = NULL;
+ ns = 0;
+
+ while (color == NULL)
+ {
+ if (strcmp (pixel_str, colors[ns].color_string) == 0)
+ color = &colors[ns];
+ else
+ ns++;
+ }
+
+ gdk_image_put_pixel (image, xcnt, ycnt, color->color.pixel);
+
+ if (mask && color->transparent)
+ {
+ if (cnt < xcnt)
+ gdk_draw_line (*mask, gc, cnt, ycnt, xcnt - 1, ycnt);
+ cnt = xcnt + 1;
+ }
+ }
+
+ if (mask && (cnt < xcnt))
+ gdk_draw_line (*mask, gc, cnt, ycnt, xcnt - 1, ycnt);
+ }
+
+ if (mask)
+ gdk_gc_destroy (gc);
+
+ pixmap = gdk_pixmap_new (window, width, height, visual->depth);
+
+ gc = gdk_gc_new (pixmap);
+ gdk_gc_set_foreground (gc, transparent_color);
+ gdk_draw_image (pixmap, gc, image, 0, 0, 0, 0, image->width, image->height);
+ gdk_gc_destroy (gc);
+ gdk_image_destroy (image);
+
+ if (colors != NULL)
+ {
+ for (cnt = 0; cnt < num_cols; cnt++)
+ g_free (colors[cnt].color_string);
+ g_free (colors);
+ }
+
+ return pixmap;
+}
+
+void
+gdk_pixmap_destroy (GdkPixmap *pixmap)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (pixmap != NULL);
+
+ private = (GdkPixmapPrivate*) pixmap;
+ if (private->ref_count <= 0)
+ {
+ XFreePixmap (private->xdisplay, private->xwindow);
+ gdk_xid_table_remove (private->xwindow);
+ g_free (pixmap);
+ }
+ else
+ {
+ private->ref_count -= 1;
+ }
+}
diff --git a/gdk/gdkprivate.h b/gdk/gdkprivate.h
new file mode 100644
index 000000000..3c1677e41
--- /dev/null
+++ b/gdk/gdkprivate.h
@@ -0,0 +1,197 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GDK_PRIVATE_H__
+#define __GDK_PRIVATE_H__
+
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <gdk/gdktypes.h>
+
+#define DND_PROTOCOL_VERSION 0
+
+#define gdk_window_lookup(xid) ((GdkWindow*) gdk_xid_table_lookup (xid))
+#define gdk_pixmap_lookup(xid) ((GdkPixmap*) gdk_xid_table_lookup (xid))
+#define gdk_font_lookup(xid) ((GdkFont*) gdk_xid_table_lookup (xid))
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+typedef struct _GdkWindowPrivate GdkWindowPrivate;
+typedef struct _GdkWindowPrivate GdkPixmapPrivate;
+typedef struct _GdkImagePrivate GdkImagePrivate;
+typedef struct _GdkGCPrivate GdkGCPrivate;
+typedef struct _GdkColormapPrivate GdkColormapPrivate;
+typedef struct _GdkVisualPrivate GdkVisualPrivate;
+typedef struct _GdkFontPrivate GdkFontPrivate;
+typedef struct _GdkCursorPrivate GdkCursorPrivate;
+
+
+struct _GdkWindowPrivate
+{
+ GdkWindow window;
+ GdkWindow *parent;
+ Window xwindow;
+ Display *xdisplay;
+ gint16 x;
+ gint16 y;
+ guint16 width;
+ guint16 height;
+ guint8 resize_count;
+ guint8 ref_count;
+ guint8 window_type;
+ guint8 destroyed : 2;
+ guint8 dnd_drag_enabled : 1,
+ dnd_drag_datashow : 1,
+ dnd_drag_destructive_op : 1,
+ dnd_drag_accepted : 1,
+ dnd_drop_enabled : 1,
+ dnd_drop_destructive_op : 1;
+ GdkAtom dnd_drag_data_type, *dnd_drag_data_typesavail;
+ guint dnd_drag_data_numtypesavail;
+ /* We have to turn on MotionMask/EnterWindowMask/LeaveWindowMask
+ during drags, then set it back to what it was after */
+ glong dnd_drag_savedeventmask, dnd_drag_eventmask;
+ GdkAtom *dnd_drop_data_typesavail;
+ guint dnd_drop_data_numtypesavail;
+ /* need to allow custom drag/drop cursors */
+
+ gint extension_events;
+};
+
+struct _GdkImagePrivate
+{
+ GdkImage image;
+ XImage *ximage;
+ Display *xdisplay;
+ gpointer x_shm_info;
+
+ void (*image_put) (GdkDrawable *window,
+ GdkGC *gc,
+ GdkImage *image,
+ gint xsrc,
+ gint ysrc,
+ gint xdest,
+ gint ydest,
+ gint width,
+ gint height);
+};
+
+struct _GdkGCPrivate
+{
+ GdkGC gc;
+ GC xgc;
+ Display *xdisplay;
+};
+
+struct _GdkColormapPrivate
+{
+ GdkColormap colormap;
+ Colormap xcolormap;
+ Display *xdisplay;
+ GdkVisual *visual;
+ gint private_val;
+ gint next_color;
+ gint ref_count;
+};
+
+struct _GdkVisualPrivate
+{
+ GdkVisual visual;
+ Visual *xvisual;
+};
+
+struct _GdkFontPrivate
+{
+ GdkFont font;
+ /* XFontStruct *xfont; */
+ /* generic pointer point to XFontStruct or XFontSet */
+ gpointer xfont;
+ Display *xdisplay;
+ gint ref_count;
+};
+
+struct _GdkCursorPrivate
+{
+ GdkCursor cursor;
+ Cursor xcursor;
+ Display *xdisplay;
+};
+
+struct _GdkDndGlobals {
+ GdkAtom gdk_XdeEnter, gdk_XdeLeave, gdk_XdeRequest;
+ GdkAtom gdk_XdeDataAvailable, gdk_XdeDataShow, gdk_XdeCancel;
+ GdkAtom gdk_XdeTypelist;
+ Cursor gdk_cursor_dragdefault, gdk_cursor_dragok;
+ GdkWindow **drag_startwindows;
+ guint drag_numwindows;
+ guint8 drag_really;
+ GdkPoint drag_dropcoords;
+};
+typedef struct _GdkDndGlobals GdkDndGlobals;
+
+void gdk_window_init (void);
+void gdk_visual_init (void);
+
+void gdk_image_init (void);
+void gdk_image_exit (void);
+
+GdkColormap* gdk_colormap_lookup (Colormap xcolormap);
+GdkVisual* gdk_visual_lookup (Visual *xvisual);
+
+void gdk_window_real_destroy (GdkWindow *window);
+void gdk_window_add_colormap_windows (GdkWindow *window);
+
+void gdk_xid_table_insert (XID *xid,
+ gpointer data);
+void gdk_xid_table_remove (XID xid);
+gpointer gdk_xid_table_lookup (XID xid);
+
+
+extern gint gdk_debug_level;
+extern gint gdk_show_events;
+extern gint gdk_use_xshm;
+extern gint gdk_stack_trace;
+extern gchar *gdk_display_name;
+extern Display *gdk_display;
+extern gint gdk_screen;
+extern Window gdk_root_window;
+extern Window gdk_leader_window;
+extern GdkWindowPrivate gdk_root_parent;
+extern Atom gdk_wm_delete_window;
+extern Atom gdk_wm_take_focus;
+extern Atom gdk_wm_protocols;
+extern Atom gdk_wm_window_protocols[];
+extern Atom gdk_selection_property;
+extern GdkDndGlobals gdk_dnd;
+extern GdkWindow *selection_owner[];
+extern gchar *gdk_progname;
+extern gchar *gdk_progclass;
+extern gint gdk_error_code;
+extern gint gdk_error_warnings;
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GDK_PRIVATE_H__ */
diff --git a/gdk/gdkproperty.c b/gdk/gdkproperty.c
new file mode 100644
index 000000000..35d8a50cf
--- /dev/null
+++ b/gdk/gdkproperty.c
@@ -0,0 +1,194 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <string.h>
+#include "gdk.h"
+#include "gdkprivate.h"
+
+
+GdkAtom
+gdk_atom_intern (const gchar *atom_name,
+ gint only_if_exists)
+{
+ return XInternAtom (gdk_display, atom_name, only_if_exists);
+}
+
+gchar *
+gdk_atom_name (GdkAtom atom)
+{
+ gchar *t;
+ gchar *name;
+
+ /* If this atom doesn't exist, we'll die with an X error unless
+ we take precautions */
+
+ gdk_error_warnings = 0;
+ t = XGetAtomName (gdk_display, atom);
+ gdk_error_warnings = 1;
+
+ if (gdk_error_code == -1)
+ {
+ return NULL;
+ }
+ else
+ {
+ name = g_strdup (t);
+ XFree (t);
+
+ return name;
+ }
+}
+
+gint
+gdk_property_get (GdkWindow *window,
+ GdkAtom property,
+ GdkAtom type,
+ gulong offset,
+ gulong length,
+ gint pdelete,
+ GdkAtom *actual_property_type,
+ gint *actual_format_type,
+ gint *actual_length,
+ guchar **data)
+{
+ GdkWindowPrivate *private;
+ Display *xdisplay;
+ Window xwindow;
+ Atom ret_prop_type;
+ gint ret_format;
+ gulong ret_nitems;
+ gulong ret_bytes_after;
+ gulong ret_length;
+ guchar *ret_data;
+
+ if (window)
+ {
+ private = (GdkWindowPrivate*) window;
+ xdisplay = private->xdisplay;
+ xwindow = private->xwindow;
+ }
+ else
+ {
+ xdisplay = gdk_display;
+ xwindow = gdk_root_window;
+ }
+
+ XGetWindowProperty (xdisplay, xwindow, property,
+ offset, (length + 3) / 4, pdelete,
+ type, &ret_prop_type, &ret_format,
+ &ret_nitems, &ret_bytes_after,
+ &ret_data);
+
+ if ((ret_prop_type == None) && (ret_format == 0))
+ return FALSE;
+
+ if (actual_property_type)
+ *actual_property_type = ret_prop_type;
+ if (actual_format_type)
+ *actual_format_type = ret_format;
+
+ if (ret_prop_type != property)
+ {
+ XFree (ret_data);
+ return FALSE;
+ }
+
+ /* FIXME: ignoring bytes_after could have very bad effects */
+
+ if (data)
+ {
+ switch (ret_format)
+ {
+ case 8:
+ ret_length = ret_nitems;
+ break;
+ case 16:
+ ret_length = 2 * ret_nitems;
+ break;
+ case 32:
+ ret_length = 4 * ret_nitems;
+ break;
+ default:
+ g_warning ("unknown property return format: %d", ret_format);
+ XFree (ret_data);
+ return FALSE;
+ }
+
+ *data = g_new (guchar, ret_length);
+ memcpy (*data, ret_data, ret_length);
+ if (actual_length)
+ *actual_length = ret_length;
+ }
+
+ XFree (ret_data);
+
+ return TRUE;
+}
+
+void
+gdk_property_change (GdkWindow *window,
+ GdkAtom property,
+ GdkAtom type,
+ gint format,
+ GdkPropMode mode,
+ guchar *data,
+ gint nelements)
+{
+ GdkWindowPrivate *private;
+ Display *xdisplay;
+ Window xwindow;
+
+ if (window)
+ {
+ private = (GdkWindowPrivate*) window;
+ xdisplay = private->xdisplay;
+ xwindow = private->xwindow;
+ }
+ else
+ {
+ xdisplay = gdk_display;
+ xwindow = gdk_root_window;
+ }
+
+ XChangeProperty (xdisplay, xwindow, property, type,
+ format, mode, data, nelements);
+}
+
+void
+gdk_property_delete (GdkWindow *window,
+ GdkAtom property)
+{
+ GdkWindowPrivate *private;
+ Display *xdisplay;
+ Window xwindow;
+
+ if (window)
+ {
+ private = (GdkWindowPrivate*) window;
+ xdisplay = private->xdisplay;
+ xwindow = private->xwindow;
+ }
+ else
+ {
+ xdisplay = gdk_display;
+ xwindow = gdk_root_window;
+ }
+
+ XDeleteProperty (xdisplay, xwindow, property);
+}
diff --git a/gdk/gdkrectangle.c b/gdk/gdkrectangle.c
new file mode 100644
index 000000000..dbb35b664
--- /dev/null
+++ b/gdk/gdkrectangle.c
@@ -0,0 +1,83 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gdk.h"
+
+
+gint
+gdk_rectangle_intersect (GdkRectangle *src1,
+ GdkRectangle *src2,
+ GdkRectangle *dest)
+{
+ GdkRectangle *temp;
+ gint src1_x2, src1_y2;
+ gint src2_x2, src2_y2;
+ gint return_val;
+
+ g_return_val_if_fail (src1 != NULL, FALSE);
+ g_return_val_if_fail (src2 != NULL, FALSE);
+ g_return_val_if_fail (dest != NULL, FALSE);
+
+ return_val = FALSE;
+
+ if (src2->x < src1->x)
+ {
+ temp = src1;
+ src1 = src2;
+ src2 = temp;
+ }
+ dest->x = src2->x;
+
+ src1_x2 = src1->x + src1->width;
+ src2_x2 = src2->x + src2->width;
+
+ if (src2->x < src1_x2)
+ {
+ if (src1_x2 < src2_x2)
+ dest->width = src1_x2 - dest->x;
+ else
+ dest->width = src2_x2 - dest->x;
+
+ if (src2->y < src1->y)
+ {
+ temp = src1;
+ src1 = src2;
+ src2 = temp;
+ }
+ dest->y = src2->y;
+
+ src1_y2 = src1->y + src1->height;
+ src2_y2 = src2->y + src2->height;
+
+ if (src2->y < src1_y2)
+ {
+ return_val = TRUE;
+
+ if (src1_y2 < src2_y2)
+ dest->height = src1_y2 - dest->y;
+ else
+ dest->height = src2_y2 - dest->y;
+
+ if (dest->height == 0)
+ return_val = FALSE;
+ if (dest->width == 0)
+ return_val = FALSE;
+ }
+ }
+
+ return return_val;
+}
diff --git a/gdk/gdkselection.c b/gdk/gdkselection.c
new file mode 100644
index 000000000..6bd425110
--- /dev/null
+++ b/gdk/gdkselection.c
@@ -0,0 +1,168 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <string.h>
+#include "gdk.h"
+#include "gdkprivate.h"
+
+
+gint
+gdk_selection_owner_set (GdkWindow *owner,
+ GdkAtom selection,
+ guint32 time,
+ gint send_event)
+{
+ GdkWindowPrivate *private;
+ Display *xdisplay;
+ Window xwindow;
+
+ if (owner)
+ {
+ private = (GdkWindowPrivate*) owner;
+ xdisplay = private->xdisplay;
+ xwindow = private->xwindow;
+ }
+ else
+ {
+ xdisplay = gdk_display;
+ xwindow = None;
+ }
+
+ XSetSelectionOwner (xdisplay, selection, xwindow, time);
+
+ return (XGetSelectionOwner (xdisplay, selection) == xwindow);
+}
+
+GdkWindow*
+gdk_selection_owner_get (GdkAtom selection)
+{
+ Window xwindow;
+
+ xwindow = XGetSelectionOwner (gdk_display, selection);
+ if (xwindow == None)
+ return NULL;
+
+ return gdk_window_lookup (xwindow);
+}
+
+void
+gdk_selection_convert (GdkWindow *requestor,
+ GdkAtom selection,
+ GdkAtom target,
+ guint32 time)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (requestor != NULL);
+
+ private = (GdkWindowPrivate*) requestor;
+
+ XConvertSelection (private->xdisplay, selection, target,
+ gdk_selection_property, private->xwindow, time);
+}
+
+gint
+gdk_selection_property_get (GdkWindow *requestor,
+ guchar **data,
+ GdkAtom *ret_type,
+ gint *ret_format)
+{
+ GdkWindowPrivate *private;
+ gulong nitems;
+ gulong nbytes;
+ gulong length;
+ GdkAtom prop_type;
+ gint prop_format;
+ guchar *t;
+
+ g_return_val_if_fail (requestor != NULL, 0);
+
+ /* If retrieved chunks are typically small, (and the ICCM says the
+ should be) it would be a win to try first with a buffer of
+ moderate length, to avoid two round trips to the server */
+
+ private = (GdkWindowPrivate*) requestor;
+
+ XGetWindowProperty (private->xdisplay, private->xwindow,
+ gdk_selection_property, 0, 0, False,
+ AnyPropertyType, &prop_type, &prop_format,
+ &nitems, &nbytes, &t);
+
+ if (ret_type)
+ *ret_type = prop_type;
+ if (ret_format)
+ *ret_format = prop_format;
+
+ if (prop_type == None)
+ {
+ *data = NULL;
+ return 0;
+ }
+
+ XFree (t);
+
+ /* Add on an extra byte to handle null termination. X guarantees
+ that t will be 1 longer than nbytes and null terminated */
+ length = nbytes + 1;
+
+ /* We can't delete the selection here, because it might be the INCR
+ protocol, in which case the client has to make sure they'll be
+ notified of PropertyChange events _before_ the property is deleted.
+ Otherwise there's no guarantee we'll win the race ... */
+ XGetWindowProperty (private->xdisplay, private->xwindow,
+ gdk_selection_property, 0, (nbytes + 3) / 4, False,
+ AnyPropertyType, &prop_type, &prop_format,
+ &nitems, &nbytes, &t);
+
+ if (prop_type != None)
+ {
+ *data = g_new (guchar, length);
+ memcpy (*data, t, length);
+ XFree (t);
+ return length-1;
+ }
+ else
+ {
+ *data = NULL;
+ return 0;
+ }
+}
+
+
+void
+gdk_selection_send_notify (guint32 requestor,
+ GdkAtom selection,
+ GdkAtom target,
+ GdkAtom property,
+ guint32 time)
+{
+ XSelectionEvent xevent;
+
+ xevent.type = SelectionNotify;
+ xevent.serial = 0;
+ xevent.send_event = True;
+ xevent.display = gdk_display;
+ xevent.requestor = requestor;
+ xevent.selection = selection;
+ xevent.target = target;
+ xevent.property = property;
+ xevent.time = time;
+
+ XSendEvent (gdk_display, requestor, False, NoEventMask, (XEvent*) &xevent);
+}
diff --git a/gdk/gdktypes.h b/gdk/gdktypes.h
new file mode 100644
index 000000000..7fc7434ac
--- /dev/null
+++ b/gdk/gdktypes.h
@@ -0,0 +1,967 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GDK_TYPES_H__
+#define __GDK_TYPES_H__
+
+
+/* GDK uses "glib". (And so does GTK).
+ */
+#include <glib.h>
+
+
+#define GDK_NONE 0L
+#define GDK_CURRENT_TIME 0L
+#define GDK_PARENT_RELATIVE 1L
+
+/* special deviceid for core pointer events */
+#define GDK_CORE_POINTER 0xfedc
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* Type definitions for the basic structures.
+ */
+
+typedef gulong GdkAtom;
+typedef struct _GdkColor GdkColor;
+typedef struct _GdkColormap GdkColormap;
+typedef struct _GdkVisual GdkVisual;
+typedef struct _GdkWindowAttr GdkWindowAttr;
+typedef struct _GdkWindow GdkWindow;
+typedef struct _GdkWindow GdkPixmap;
+typedef struct _GdkWindow GdkBitmap;
+typedef struct _GdkWindow GdkDrawable;
+typedef struct _GdkImage GdkImage;
+typedef struct _GdkGCValues GdkGCValues;
+typedef struct _GdkGC GdkGC;
+typedef struct _GdkPoint GdkPoint;
+typedef struct _GdkRectangle GdkRectangle;
+typedef struct _GdkSegment GdkSegment;
+typedef struct _GdkFont GdkFont;
+typedef struct _GdkCursor GdkCursor;
+
+typedef struct _GdkEventAny GdkEventAny;
+typedef struct _GdkEventExpose GdkEventExpose;
+typedef struct _GdkEventMotion GdkEventMotion;
+typedef struct _GdkEventButton GdkEventButton;
+typedef struct _GdkEventKey GdkEventKey;
+typedef struct _GdkEventFocus GdkEventFocus;
+typedef struct _GdkEventCrossing GdkEventCrossing;
+typedef struct _GdkEventConfigure GdkEventConfigure;
+typedef struct _GdkEventProperty GdkEventProperty;
+typedef struct _GdkEventSelection GdkEventSelection;
+typedef struct _GdkEventProximity GdkEventProximity;
+typedef struct _GdkEventOther GdkEventOther;
+typedef struct _GdkEventDragBegin GdkEventDragBegin;
+typedef struct _GdkEventDragRequest GdkEventDragRequest;
+typedef struct _GdkEventDropEnter GdkEventDropEnter;
+typedef struct _GdkEventDropDataAvailable GdkEventDropDataAvailable;
+typedef struct _GdkEventDropLeave GdkEventDropLeave;
+typedef struct _GdkEventClient GdkEventClient;
+typedef union _GdkEvent GdkEvent;
+typedef struct _GdkDeviceInfo GdkDeviceInfo;
+typedef struct _GdkTimeCoord GdkTimeCoord;
+typedef gint (*GdkEventFunc) (GdkEvent *event,
+ gpointer data);
+
+
+/* Types of windows.
+ * Root: There is only 1 root window and it is initialized
+ * at startup. Creating a window of type GDK_WINDOW_ROOT
+ * is an error.
+ * Toplevel: Windows which interact with the window manager.
+ * Child: Windows which are children of some other type of window.
+ * (Any other type of window). Most windows are child windows.
+ * Dialog: A special kind of toplevel window which interacts with
+ * the window manager slightly differently than a regular
+ * toplevel window. Dialog windows should be used for any
+ * transient window.
+ * Pixmap: Pixmaps are really just another kind of window which
+ * doesn't actually appear on the screen. It can't have
+ * children, either and is really just a convenience so
+ * that the drawing functions can work on both windows
+ * and pixmaps transparently. (ie. You shouldn't pass a
+ * pixmap to any procedure which accepts a window with the
+ * exception of the drawing functions).
+ */
+typedef enum
+{
+ GDK_WINDOW_ROOT,
+ GDK_WINDOW_TOPLEVEL,
+ GDK_WINDOW_CHILD,
+ GDK_WINDOW_DIALOG,
+ GDK_WINDOW_TEMP,
+ GDK_WINDOW_PIXMAP
+} GdkWindowType;
+
+/* Classes of windows.
+ * InputOutput: Almost every window should be of this type. Such windows
+ * receive events and are also displayed on screen.
+ * InputOnly: Used only in special circumstances when events need to be
+ * stolen from another window or windows. Input only windows
+ * have no visible output, so they are handy for placing over
+ * top of a group of windows in order to grab the events (or
+ * filter the events) from those windows.
+ */
+typedef enum
+{
+ GDK_INPUT_OUTPUT,
+ GDK_INPUT_ONLY
+} GdkWindowClass;
+
+/* Types of images.
+ * Normal: Normal X image type. These are slow as they involve passing
+ * the entire image through the X connection each time a draw
+ * request is required.
+ * Shared: Shared memory X image type. These are fast as the X server
+ * and the program actually use the same piece of memory. They
+ * should be used with care though as there is the possibility
+ * for both the X server and the program to be reading/writing
+ * the image simultaneously and producing undesired results.
+ */
+typedef enum
+{
+ GDK_IMAGE_NORMAL,
+ GDK_IMAGE_SHARED,
+ GDK_IMAGE_FASTEST
+} GdkImageType;
+
+/* Types of visuals.
+ * StaticGray:
+ * Grayscale:
+ * StaticColor:
+ * PseudoColor:
+ * TrueColor:
+ * DirectColor:
+ */
+typedef enum
+{
+ GDK_VISUAL_STATIC_GRAY,
+ GDK_VISUAL_GRAYSCALE,
+ GDK_VISUAL_STATIC_COLOR,
+ GDK_VISUAL_PSEUDO_COLOR,
+ GDK_VISUAL_TRUE_COLOR,
+ GDK_VISUAL_DIRECT_COLOR
+} GdkVisualType;
+
+/* Types of font.
+ * GDK_FONT_FONT: the font is an XFontStruct.
+ * GDK_FONT_FONTSET: the font is an XFontSet used for I18N.
+ */
+typedef enum
+{
+ GDK_FONT_FONT,
+ GDK_FONT_FONTSET
+} GdkFontType;
+
+/* Window attribute mask values.
+ * GDK_WA_TITLE: The "title" field is valid.
+ * GDK_WA_X: The "x" field is valid.
+ * GDK_WA_Y: The "y" field is valid.
+ * GDK_WA_CURSOR: The "cursor" field is valid.
+ * GDK_WA_COLORMAP: The "colormap" field is valid.
+ * GDK_WA_VISUAL: The "visual" field is valid.
+ */
+typedef enum
+{
+ GDK_WA_TITLE = 1 << 1,
+ GDK_WA_X = 1 << 2,
+ GDK_WA_Y = 1 << 3,
+ GDK_WA_CURSOR = 1 << 4,
+ GDK_WA_COLORMAP = 1 << 5,
+ GDK_WA_VISUAL = 1 << 6,
+ GDK_WA_WMCLASS = 1 << 7
+} GdkWindowAttributesType;
+
+/* Size restriction enumeration.
+ */
+typedef enum
+{
+ GDK_HINT_POS = 1 << 0,
+ GDK_HINT_MIN_SIZE = 1 << 1,
+ GDK_HINT_MAX_SIZE = 1 << 2
+} GdkWindowHints;
+
+/* GC function types.
+ * Copy: Overwrites destination pixels with the source pixels.
+ * Invert: Inverts the destination pixels.
+ * Xor: Xor's the destination pixels with the source pixels.
+ */
+typedef enum
+{
+ GDK_COPY,
+ GDK_INVERT,
+ GDK_XOR
+} GdkFunction;
+
+/* GC fill types.
+ * Solid:
+ * Tiled:
+ * Stippled:
+ * OpaqueStippled:
+ */
+typedef enum
+{
+ GDK_SOLID,
+ GDK_TILED,
+ GDK_STIPPLED,
+ GDK_OPAQUE_STIPPLED
+} GdkFill;
+
+/* GC line styles
+ * Solid:
+ * OnOffDash:
+ * DoubleDash:
+ */
+typedef enum
+{
+ GDK_LINE_SOLID,
+ GDK_LINE_ON_OFF_DASH,
+ GDK_LINE_DOUBLE_DASH
+} GdkLineStyle;
+
+/* GC cap styles
+ * CapNotLast:
+ * CapButt:
+ * CapRound:
+ * CapProjecting:
+ */
+typedef enum
+{
+ GDK_CAP_NOT_LAST,
+ GDK_CAP_BUTT,
+ GDK_CAP_ROUND,
+ GDK_CAP_PROJECTING
+} GdkCapStyle;
+
+/* GC join styles
+ * JoinMiter:
+ * JoinRound:
+ * JoinBevel:
+ */
+typedef enum
+{
+ GDK_JOIN_MITER,
+ GDK_JOIN_ROUND,
+ GDK_JOIN_BEVEL
+} GdkJoinStyle;
+
+/* Cursor types.
+ */
+typedef enum
+{
+#include <gdk/gdkcursors.h>
+ GDK_LAST_CURSOR
+} GdkCursorType;
+
+/* Event types.
+ * Nothing: No event occurred.
+ * Delete: A window delete event was sent by the window manager.
+ * The specified window should be deleted.
+ * Destroy: A window has been destroyed.
+ * Expose: Part of a window has been uncovered.
+ * MotionNotify: The mouse has moved.
+ * ButtonPress: A mouse button was pressed.
+ * ButtonRelease: A mouse button was release.
+ * KeyPress: A key was pressed.
+ * KeyRelease: A key was released.
+ * EnterNotify: A window was entered.
+ * LeaveNotify: A window was exited.
+ * FocusChange: The focus window has changed. (The focus window gets
+ * keyboard events).
+ * Resize: A window has been resized.
+ * Map: A window has been mapped. (It is now visible on the screen).
+ * Unmap: A window has been unmapped. (It is no longer visible on
+ * the screen).
+ */
+typedef enum
+{
+ GDK_NOTHING = -1,
+ GDK_DELETE = 0,
+ GDK_DESTROY = 1,
+ GDK_EXPOSE = 2,
+ GDK_MOTION_NOTIFY = 3,
+ GDK_BUTTON_PRESS = 4,
+ GDK_2BUTTON_PRESS = 5,
+ GDK_3BUTTON_PRESS = 6,
+ GDK_BUTTON_RELEASE = 7,
+ GDK_KEY_PRESS = 8,
+ GDK_KEY_RELEASE = 9,
+ GDK_ENTER_NOTIFY = 10,
+ GDK_LEAVE_NOTIFY = 11,
+ GDK_FOCUS_CHANGE = 12,
+ GDK_CONFIGURE = 13,
+ GDK_MAP = 14,
+ GDK_UNMAP = 15,
+ GDK_PROPERTY_NOTIFY = 16,
+ GDK_SELECTION_CLEAR = 17,
+ GDK_SELECTION_REQUEST = 18,
+ GDK_SELECTION_NOTIFY = 19,
+ GDK_PROXIMITY_IN = 20,
+ GDK_PROXIMITY_OUT = 21,
+ GDK_DRAG_BEGIN = 22,
+ GDK_DRAG_REQUEST = 23,
+ GDK_DROP_ENTER = 24,
+ GDK_DROP_LEAVE = 25,
+ GDK_DROP_DATA_AVAIL = 26,
+ GDK_CLIENT_EVENT = 27,
+ GDK_OTHER_EVENT = 9999
+} GdkEventType;
+
+/* Event masks. (Used to select what types of events a window
+ * will receive).
+ */
+typedef enum
+{
+ GDK_EXPOSURE_MASK = 1 << 1,
+ GDK_POINTER_MOTION_MASK = 1 << 2,
+ GDK_POINTER_MOTION_HINT_MASK = 1 << 3,
+ GDK_BUTTON_MOTION_MASK = 1 << 4,
+ GDK_BUTTON1_MOTION_MASK = 1 << 5,
+ GDK_BUTTON2_MOTION_MASK = 1 << 6,
+ GDK_BUTTON3_MOTION_MASK = 1 << 7,
+ GDK_BUTTON_PRESS_MASK = 1 << 8,
+ GDK_BUTTON_RELEASE_MASK = 1 << 9,
+ GDK_KEY_PRESS_MASK = 1 << 10,
+ GDK_KEY_RELEASE_MASK = 1 << 11,
+ GDK_ENTER_NOTIFY_MASK = 1 << 12,
+ GDK_LEAVE_NOTIFY_MASK = 1 << 13,
+ GDK_FOCUS_CHANGE_MASK = 1 << 14,
+ GDK_STRUCTURE_MASK = 1 << 15,
+ GDK_PROPERTY_CHANGE_MASK = 1 << 16,
+ GDK_PROXIMITY_IN_MASK = 1 << 17,
+ GDK_PROXIMITY_OUT_MASK = 1 << 18,
+ GDK_ALL_EVENTS_MASK = 0x07FFFF
+} GdkEventMask;
+
+/* Types of enter/leave notifications.
+ * Ancestor:
+ * Virtual:
+ * Inferior:
+ * Nonlinear:
+ * NonlinearVirtual:
+ * Unknown: An unknown type of enter/leave event occurred.
+ */
+typedef enum
+{
+ GDK_NOTIFY_ANCESTOR = 0,
+ GDK_NOTIFY_VIRTUAL = 1,
+ GDK_NOTIFY_INFERIOR = 2,
+ GDK_NOTIFY_NONLINEAR = 3,
+ GDK_NOTIFY_NONLINEAR_VIRTUAL = 4,
+ GDK_NOTIFY_UNKNOWN = 5
+} GdkNotifyType;
+
+/* Types of modifiers.
+ */
+typedef enum
+{
+ GDK_SHIFT_MASK = 1 << 0,
+ GDK_LOCK_MASK = 1 << 1,
+ GDK_CONTROL_MASK = 1 << 2,
+ GDK_MOD1_MASK = 1 << 3,
+ GDK_MOD2_MASK = 1 << 4,
+ GDK_MOD3_MASK = 1 << 5,
+ GDK_MOD4_MASK = 1 << 6,
+ GDK_MOD5_MASK = 1 << 7,
+ GDK_BUTTON1_MASK = 1 << 8,
+ GDK_BUTTON2_MASK = 1 << 9,
+ GDK_BUTTON3_MASK = 1 << 10,
+ GDK_BUTTON4_MASK = 1 << 11,
+ GDK_BUTTON5_MASK = 1 << 12
+} GdkModifierType;
+
+typedef enum
+{
+ GDK_CLIP_BY_CHILDREN = 0,
+ GDK_INCLUDE_INFERIORS = 1
+} GdkSubwindowMode;
+
+typedef enum
+{
+ GDK_INPUT_READ = 1 << 0,
+ GDK_INPUT_WRITE = 1 << 1,
+ GDK_INPUT_EXCEPTION = 1 << 2
+} GdkInputCondition;
+
+typedef enum
+{
+ GDK_OK = 0,
+ GDK_ERROR = -1,
+ GDK_ERROR_PARAM = -2,
+ GDK_ERROR_FILE = -3,
+ GDK_ERROR_MEM = -4
+} GdkStatus;
+
+typedef enum
+{
+ GDK_LSB_FIRST,
+ GDK_MSB_FIRST
+} GdkByteOrder;
+
+typedef enum
+{
+ GDK_GC_FOREGROUND = 1 << 0,
+ GDK_GC_BACKGROUND = 1 << 1,
+ GDK_GC_FONT = 1 << 2,
+ GDK_GC_FUNCTION = 1 << 3,
+ GDK_GC_FILL = 1 << 4,
+ GDK_GC_TILE = 1 << 5,
+ GDK_GC_STIPPLE = 1 << 6,
+ GDK_GC_CLIP_MASK = 1 << 7,
+ GDK_GC_SUBWINDOW = 1 << 8,
+ GDK_GC_TS_X_ORIGIN = 1 << 9,
+ GDK_GC_TS_Y_ORIGIN = 1 << 10,
+ GDK_GC_CLIP_X_ORIGIN = 1 << 11,
+ GDK_GC_CLIP_Y_ORIGIN = 1 << 12,
+ GDK_GC_EXPOSURES = 1 << 13,
+ GDK_GC_LINE_WIDTH = 1 << 14,
+ GDK_GC_LINE_STYLE = 1 << 15,
+ GDK_GC_CAP_STYLE = 1 << 16,
+ GDK_GC_JOIN_STYLE = 1 << 17
+} GdkGCValuesMask;
+
+typedef enum
+{
+ GDK_SELECTION_PRIMARY = 1,
+ GDK_SELECTION_SECONDARY = 2
+} GdkSelection;
+
+typedef enum
+{
+ GDK_PROPERTY_NEW_VALUE,
+ GDK_PROPERTY_DELETE
+} GdkPropertyState;
+
+typedef enum
+{
+ GDK_PROP_MODE_REPLACE,
+ GDK_PROP_MODE_PREPEND,
+ GDK_PROP_MODE_APPEND
+} GdkPropMode;
+
+/* These definitions are for version 1 of the OffiX D&D protocol,
+ taken from <OffiX/DragAndDropTypes.h> */
+typedef enum
+{
+ GDK_DNDTYPE_NOTDND = -1,
+ GDK_DNDTYPE_UNKNOWN = 0,
+ GDK_DNDTYPE_RAWDATA = 1,
+ GDK_DNDTYPE_FILE = 2,
+ GDK_DNDTYPE_FILES = 3,
+ GDK_DNDTYPE_TEXT = 4,
+ GDK_DNDTYPE_DIR = 5,
+ GDK_DNDTYPE_LINK = 6,
+ GDK_DNDTYPE_EXE = 7,
+ GDK_DNDTYPE_URL = 8,
+ GDK_DNDTYPE_MIME = 9,
+ GDK_DNDTYPE_END = 10
+} GdkDndType;
+
+/* Enums for XInput support */
+
+typedef enum
+{
+ GDK_SOURCE_MOUSE,
+ GDK_SOURCE_PEN,
+ GDK_SOURCE_ERASER,
+ GDK_SOURCE_CURSOR
+} GdkInputSource;
+
+typedef enum
+{
+ GDK_MODE_DISABLED,
+ GDK_MODE_SCREEN,
+ GDK_MODE_WINDOW
+} GdkInputMode;
+
+typedef enum
+{
+ GDK_AXIS_IGNORE,
+ GDK_AXIS_X,
+ GDK_AXIS_Y,
+ GDK_AXIS_PRESSURE,
+ GDK_AXIS_XTILT,
+ GDK_AXIS_YTILT,
+ GDK_AXIS_LAST
+} GdkAxisUse;
+
+/* The next two types define enums for predefined atoms relating
+ to selections. In general, one will need to use gdk_intern_atom */
+
+typedef enum
+{
+ GDK_TARGET_BITMAP = 5,
+ GDK_TARGET_COLORMAP = 7,
+ GDK_TARGET_DRAWABLE = 17,
+ GDK_TARGET_PIXMAP = 20,
+ GDK_TARGET_STRING = 31
+} GdkTarget;
+
+typedef enum
+{
+ GDK_SELECTION_TYPE_ATOM = 4,
+ GDK_SELECTION_TYPE_BITMAP = 5,
+ GDK_SELECTION_TYPE_COLORMAP = 7,
+ GDK_SELECTION_TYPE_DRAWABLE = 17,
+ GDK_SELECTION_TYPE_INTEGER = 19,
+ GDK_SELECTION_TYPE_PIXMAP = 20,
+ GDK_SELECTION_TYPE_WINDOW = 33,
+ GDK_SELECTION_TYPE_STRING = 31
+} GdkSelectionType;
+
+typedef enum
+{
+ GDK_EXTENSION_EVENTS_NONE,
+ GDK_EXTENSION_EVENTS_ALL,
+ GDK_EXTENSION_EVENTS_CURSOR
+} GdkExtensionMode;
+
+typedef void (*GdkInputFunction) (gpointer data,
+ gint source,
+ GdkInputCondition condition);
+
+/* The color type.
+ * A color consists of red, green and blue values in the
+ * range 0-65535 and a pixel value. The pixel value is highly
+ * dependent on the depth and colormap which this color will
+ * be used to draw into. Therefore, sharing colors between
+ * colormaps is a bad idea.
+ */
+struct _GdkColor
+{
+ gulong pixel;
+ gushort red;
+ gushort green;
+ gushort blue;
+};
+
+/* The colormap type.
+ * Colormaps consist of 256 colors.
+ */
+struct _GdkColormap
+{
+ GdkColor colors[256];
+};
+
+/* The visual type.
+ * "type" is the type of visual this is (PseudoColor, TrueColor, etc).
+ * "depth" is the bit depth of this visual.
+ * "colormap_size" is the size of a colormap for this visual.
+ * "bits_per_rgb" is the number of significant bits per red, green and blue.
+ * The red, green and blue masks, shifts and precisions refer
+ * to value needed to calculate pixel values in TrueColor and DirectColor
+ * visuals. The "mask" is the significant bits within the pixel. The
+ * "shift" is the number of bits left we must shift a primary for it
+ * to be in position (according to the "mask"). "prec" refers to how
+ * much precision the pixel value contains for a particular primary.
+ */
+struct _GdkVisual
+{
+ GdkVisualType type;
+ gint depth;
+ GdkByteOrder byte_order;
+ gint colormap_size;
+ gint bits_per_rgb;
+
+ guint32 red_mask;
+ gint red_shift;
+ gint red_prec;
+
+ guint32 green_mask;
+ gint green_shift;
+ gint green_prec;
+
+ guint32 blue_mask;
+ gint blue_shift;
+ gint blue_prec;
+};
+
+struct _GdkWindowAttr
+{
+ gchar *title;
+ gint event_mask;
+ gint16 x, y;
+ gint16 width;
+ gint16 height;
+ GdkWindowClass wclass;
+ GdkVisual *visual;
+ GdkColormap *colormap;
+ GdkWindowType window_type;
+ GdkCursor *cursor;
+ gchar *wmclass_name;
+ gchar *wmclass_class;
+};
+
+struct _GdkWindow
+{
+ gpointer user_data;
+};
+
+struct _GdkImage
+{
+ GdkImageType type;
+ GdkVisual *visual; /* visual used to create the image */
+ GdkByteOrder byte_order;
+ guint16 width;
+ guint16 height;
+ guint16 depth;
+ guint16 bpp; /* bytes per pixel */
+ guint16 bpl; /* bytes per line */
+ gpointer mem;
+};
+
+struct _GdkGCValues
+{
+ GdkColor foreground;
+ GdkColor background;
+ GdkFont *font;
+ GdkFunction function;
+ GdkFill fill;
+ GdkPixmap *tile;
+ GdkPixmap *stipple;
+ GdkPixmap *clip_mask;
+ GdkSubwindowMode subwindow_mode;
+ gint ts_x_origin;
+ gint ts_y_origin;
+ gint clip_x_origin;
+ gint clip_y_origin;
+ gint graphics_exposures;
+ gint line_width;
+ GdkLineStyle line_style;
+ GdkCapStyle cap_style;
+ GdkJoinStyle join_style;
+};
+
+struct _GdkGC
+{
+ gint dummy_var;
+};
+
+struct _GdkPoint
+{
+ gint16 x;
+ gint16 y;
+};
+
+struct _GdkRectangle
+{
+ gint16 x;
+ gint16 y;
+ guint16 width;
+ guint16 height;
+};
+
+struct _GdkSegment
+{
+ gint16 x1;
+ gint16 y1;
+ gint16 x2;
+ gint16 y2;
+};
+
+struct _GdkFont
+{
+ GdkFontType type;
+ gint ascent;
+ gint descent;
+};
+
+struct _GdkCursor
+{
+ GdkCursorType type;
+};
+
+/* Types for XInput support */
+
+struct _GdkDeviceInfo
+{
+ guint32 deviceid;
+ gchar *name;
+ GdkInputSource source;
+ GdkInputMode mode;
+ gint has_cursor; /* TRUE if the X pointer follows device motion */
+ gint num_axes;
+ GdkAxisUse *axes; /* Specifies use for each axis */
+};
+
+struct _GdkTimeCoord
+{
+ guint32 time;
+ gdouble x;
+ gdouble y;
+ gdouble pressure;
+ gdouble xtilt;
+ gdouble ytilt;
+};
+
+struct _GdkEventAny
+{
+ GdkEventType type;
+ GdkWindow *window;
+ gint8 send_event;
+};
+
+struct _GdkEventExpose
+{
+ GdkEventType type;
+ GdkWindow *window;
+ GdkRectangle area;
+ gint count; /* If non-zero, how many more events follow. */
+};
+
+struct _GdkEventMotion
+{
+ GdkEventType type;
+ GdkWindow *window;
+ guint32 time;
+ gdouble x;
+ gdouble y;
+ gdouble pressure;
+ gdouble xtilt;
+ gdouble ytilt;
+ guint state;
+ gint16 is_hint;
+ GdkInputSource source;
+ guint32 deviceid;
+};
+
+struct _GdkEventButton
+{
+ GdkEventType type;
+ GdkWindow *window;
+ guint32 time;
+ gdouble x;
+ gdouble y;
+ gdouble pressure;
+ gdouble xtilt;
+ gdouble ytilt;
+ guint state;
+ guint button;
+ GdkInputSource source;
+ guint32 deviceid;
+};
+
+struct _GdkEventKey
+{
+ GdkEventType type;
+ GdkWindow *window;
+ guint32 time;
+ guint state;
+ guint keyval;
+};
+
+struct _GdkEventCrossing
+{
+ GdkEventType type;
+ GdkWindow *window;
+ GdkWindow *subwindow;
+ GdkNotifyType detail;
+};
+
+struct _GdkEventFocus
+{
+ GdkEventType type;
+ GdkWindow *window;
+ gint16 in;
+};
+
+struct _GdkEventConfigure
+{
+ GdkEventType type;
+ GdkWindow *window;
+ gint16 x, y;
+ gint16 width;
+ gint16 height;
+};
+
+struct _GdkEventProperty
+{
+ GdkEventType type;
+ GdkWindow *window;
+ GdkAtom atom;
+ guint32 time;
+ guint state;
+};
+
+struct _GdkEventSelection
+{
+ GdkEventType type;
+ GdkWindow *window;
+ GdkAtom selection;
+ GdkAtom target;
+ GdkAtom property;
+ guint32 requestor;
+ guint32 time;
+};
+
+/* This event type will be used pretty rarely. It only is important
+ for XInput aware programs that are drawing their own cursor */
+
+struct _GdkEventProximity
+{
+ GdkEventType type;
+ GdkWindow *window;
+ guint32 time;
+ GdkInputSource source;
+ guint32 deviceid;
+};
+
+struct _GdkEventDragRequest
+{
+ GdkEventType type;
+ GdkWindow *window;
+ guint32 requestor;
+ union {
+ struct {
+ guint protocol_version:4;
+ guint sendreply:1;
+ guint willaccept:1;
+ guint delete_data:1; /* Do *not* delete if link is sent, only
+ if data is sent */
+ guint senddata:1;
+ guint reserved:22;
+ } flags;
+ glong allflags;
+ } u;
+ guint8 isdrop; /* This gdk event can be generated by a couple of
+ X events - this lets the app know whether the
+ drop really occurred or we just set the data */
+
+ GdkPoint drop_coords;
+ gchar *data_type;
+};
+
+struct _GdkEventDragBegin
+{
+ GdkEventType type;
+ GdkWindow *window;
+ union {
+ struct {
+ guint protocol_version:4;
+ guint reserved:28;
+ } flags;
+ glong allflags;
+ } u;
+};
+
+struct _GdkEventDropEnter
+{
+ GdkEventType type;
+ GdkWindow *window;
+ guint32 requestor;
+ union {
+ struct {
+ guint protocol_version:4;
+ guint sendreply:1;
+ guint extended_typelist:1;
+ guint reserved:26;
+ } flags;
+ glong allflags;
+ } u;
+};
+
+struct _GdkEventDropLeave
+{
+ GdkEventType type;
+ GdkWindow *window;
+ guint32 requestor;
+ union {
+ struct {
+ guint protocol_version:4;
+ guint reserved:28;
+ } flags;
+ glong allflags;
+ } u;
+};
+
+struct _GdkEventDropDataAvailable
+{
+ GdkEventType type;
+ GdkWindow *window;
+ guint32 requestor;
+ union {
+ struct {
+ guint protocol_version:4;
+ guint isdrop:1;
+ guint reserved:25;
+ } flags;
+ glong allflags;
+ } u;
+ gchar *data_type; /* MIME type */
+ gulong data_numbytes;
+ gpointer data;
+};
+
+struct _GdkEventClient
+{
+ GdkEventType type;
+ GdkWindow *window;
+ GdkAtom message_type;
+ gushort data_format;
+ union {
+ char b[20];
+ short s[10];
+ long l[5];
+ } data;
+};
+
+#ifndef _XLIB_H_
+#define XEvent void
+#endif
+
+struct _GdkEventOther
+{
+ GdkEventType type;
+ GdkWindow *window;
+ XEvent *xevent;
+};
+
+union _GdkEvent
+{
+ GdkEventType type;
+ GdkEventAny any;
+ GdkEventExpose expose;
+ GdkEventMotion motion;
+ GdkEventButton button;
+ GdkEventKey key;
+ GdkEventCrossing crossing;
+ GdkEventFocus focus_change;
+ GdkEventConfigure configure;
+ GdkEventProperty property;
+ GdkEventSelection selection;
+ GdkEventProximity proximity;
+ GdkEventDragBegin dragbegin;
+ GdkEventDragRequest dragrequest;
+ GdkEventDropEnter dropenter;
+ GdkEventDropLeave dropleave;
+ GdkEventDropDataAvailable dropdataavailable;
+ GdkEventClient client;
+ GdkEventOther other;
+};
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GDK_TYPES_H__ */
diff --git a/gdk/gdkvisual.c b/gdk/gdkvisual.c
new file mode 100644
index 000000000..22acee6f1
--- /dev/null
+++ b/gdk/gdkvisual.c
@@ -0,0 +1,431 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include "gdk.h"
+#include "gdkprivate.h"
+
+
+static void gdk_visual_add (GdkVisual *visual);
+static void gdk_visual_decompose_mask (gulong mask,
+ gint *shift,
+ gint *prec);
+static guint gdk_visual_hash (Visual *key);
+static gint gdk_visual_compare (Visual *a,
+ Visual *b);
+
+
+static GdkVisualPrivate *system_visual;
+static GdkVisualPrivate *visuals;
+static gint nvisuals;
+
+static gint available_depths[4];
+static gint navailable_depths;
+
+static GdkVisualType available_types[6];
+static gint navailable_types;
+
+static char* visual_names[] =
+{
+ "static gray",
+ "grayscale",
+ "static color",
+ "pseudo color",
+ "true color",
+ "direct color",
+};
+
+static GHashTable *visual_hash = NULL;
+
+void
+gdk_visual_init ()
+{
+ static gint possible_depths[5] = { 32, 24, 16, 15, 8 };
+ static GdkVisualType possible_types[6] =
+ {
+ GDK_VISUAL_DIRECT_COLOR,
+ GDK_VISUAL_TRUE_COLOR,
+ GDK_VISUAL_PSEUDO_COLOR,
+ GDK_VISUAL_STATIC_COLOR,
+ GDK_VISUAL_GRAYSCALE,
+ GDK_VISUAL_STATIC_GRAY
+ };
+
+ static gint npossible_depths = 5;
+ static gint npossible_types = 6;
+
+ XVisualInfo *visual_list;
+ XVisualInfo visual_template;
+ GdkVisualPrivate temp_visual;
+ Visual *default_xvisual;
+ int nxvisuals;
+ int i, j;
+
+ visual_template.screen = gdk_screen;
+ visual_list = XGetVisualInfo (gdk_display, VisualScreenMask, &visual_template, &nxvisuals);
+ visuals = g_new (GdkVisualPrivate, nxvisuals);
+
+ default_xvisual = DefaultVisual (gdk_display, gdk_screen);
+
+ nvisuals = 0;
+ for (i = 0; i < nxvisuals; i++)
+ {
+ if (visual_list[i].depth >= 8)
+ {
+#ifdef __cplusplus
+ switch (visual_list[i].c_class)
+#else /* __cplusplus */
+ switch (visual_list[i].class)
+#endif /* __cplusplus */
+ {
+ case StaticGray:
+ visuals[nvisuals].visual.type = GDK_VISUAL_STATIC_GRAY;
+ break;
+ case GrayScale:
+ visuals[nvisuals].visual.type = GDK_VISUAL_GRAYSCALE;
+ break;
+ case StaticColor:
+ visuals[nvisuals].visual.type = GDK_VISUAL_STATIC_COLOR;
+ break;
+ case PseudoColor:
+ visuals[nvisuals].visual.type = GDK_VISUAL_PSEUDO_COLOR;
+ break;
+ case TrueColor:
+ visuals[nvisuals].visual.type = GDK_VISUAL_TRUE_COLOR;
+ break;
+ case DirectColor:
+ visuals[nvisuals].visual.type = GDK_VISUAL_DIRECT_COLOR;
+ break;
+ }
+
+ visuals[nvisuals].visual.depth = visual_list[i].depth;
+ visuals[nvisuals].visual.byte_order =
+ (ImageByteOrder(gdk_display) == LSBFirst) ?
+ GDK_LSB_FIRST : GDK_MSB_FIRST;
+ visuals[nvisuals].visual.red_mask = visual_list[i].red_mask;
+ visuals[nvisuals].visual.green_mask = visual_list[i].green_mask;
+ visuals[nvisuals].visual.blue_mask = visual_list[i].blue_mask;
+ visuals[nvisuals].visual.colormap_size = visual_list[i].colormap_size;
+ visuals[nvisuals].visual.bits_per_rgb = visual_list[i].bits_per_rgb;
+ visuals[nvisuals].xvisual = visual_list[i].visual;
+
+ if ((visuals[nvisuals].visual.type == GDK_VISUAL_TRUE_COLOR) ||
+ (visuals[nvisuals].visual.type == GDK_VISUAL_DIRECT_COLOR))
+ {
+ gdk_visual_decompose_mask (visuals[nvisuals].visual.red_mask,
+ &visuals[nvisuals].visual.red_shift,
+ &visuals[nvisuals].visual.red_prec);
+
+ gdk_visual_decompose_mask (visuals[nvisuals].visual.green_mask,
+ &visuals[nvisuals].visual.green_shift,
+ &visuals[nvisuals].visual.green_prec);
+
+ gdk_visual_decompose_mask (visuals[nvisuals].visual.blue_mask,
+ &visuals[nvisuals].visual.blue_shift,
+ &visuals[nvisuals].visual.blue_prec);
+ }
+ else
+ {
+ visuals[nvisuals].visual.red_mask = 0;
+ visuals[nvisuals].visual.red_shift = 0;
+ visuals[nvisuals].visual.red_prec = 0;
+
+ visuals[nvisuals].visual.green_mask = 0;
+ visuals[nvisuals].visual.green_shift = 0;
+ visuals[nvisuals].visual.green_prec = 0;
+
+ visuals[nvisuals].visual.blue_mask = 0;
+ visuals[nvisuals].visual.blue_shift = 0;
+ visuals[nvisuals].visual.blue_prec = 0;
+ }
+
+ nvisuals += 1;
+ }
+ }
+
+ XFree (visual_list);
+
+ for (i = 0; i < nvisuals; i++)
+ {
+ for (j = i+1; j < nvisuals; j++)
+ {
+ if (visuals[j].visual.depth >= visuals[i].visual.depth)
+ {
+ if ((visuals[j].visual.depth == 8) && (visuals[i].visual.depth == 8))
+ {
+ if (visuals[j].visual.type == GDK_VISUAL_PSEUDO_COLOR)
+ {
+ temp_visual = visuals[j];
+ visuals[j] = visuals[i];
+ visuals[i] = temp_visual;
+ }
+ else if ((visuals[i].visual.type != GDK_VISUAL_PSEUDO_COLOR) &&
+ visuals[j].visual.type > visuals[i].visual.type)
+ {
+ temp_visual = visuals[j];
+ visuals[j] = visuals[i];
+ visuals[i] = temp_visual;
+ }
+ }
+ else if ((visuals[j].visual.depth > visuals[i].visual.depth) ||
+ ((visuals[j].visual.depth == visuals[i].visual.depth) &&
+ (visuals[j].visual.type > visuals[i].visual.type)))
+ {
+ temp_visual = visuals[j];
+ visuals[j] = visuals[i];
+ visuals[i] = temp_visual;
+ }
+ }
+ }
+ }
+
+ for (i = 0; i < nvisuals; i++)
+ if (default_xvisual->visualid == visuals[i].xvisual->visualid)
+ {
+ system_visual = &visuals[i];
+ break;
+ }
+
+ if (gdk_debug_level >= 1)
+ for (i = 0; i < nvisuals; i++)
+ g_print ("visual: %s: %d\n",
+ visual_names[visuals[i].visual.type],
+ visuals[i].visual.depth);
+
+ navailable_depths = 0;
+ for (i = 0; i < npossible_depths; i++)
+ {
+ for (j = 0; j < nvisuals; j++)
+ {
+ if (visuals[j].visual.depth == possible_depths[i])
+ {
+ available_depths[navailable_depths++] = visuals[j].visual.depth;
+ break;
+ }
+ }
+ }
+
+ if (navailable_depths == 0)
+ g_error ("unable to find a usable depth");
+
+ navailable_types = 0;
+ for (i = 0; i < npossible_types; i++)
+ {
+ for (j = 0; j < nvisuals; j++)
+ {
+ if (visuals[j].visual.type == possible_types[i])
+ {
+ available_types[navailable_types++] = visuals[j].visual.type;
+ break;
+ }
+ }
+ }
+
+ for (i = 0; i < nvisuals; i++)
+ gdk_visual_add ((GdkVisual*) &visuals[i]);
+
+ if (npossible_types == 0)
+ g_error ("unable to find a usable visual type");
+}
+
+GdkVisual*
+gdk_visual_ref (GdkVisual *visual)
+{
+ return visual;
+}
+
+void
+gdk_visual_unref (GdkVisual *visual)
+{
+ return;
+}
+
+gint
+gdk_visual_get_best_depth ()
+{
+ return available_depths[0];
+}
+
+GdkVisualType
+gdk_visual_get_best_type ()
+{
+ return available_types[0];
+}
+
+GdkVisual*
+gdk_visual_get_system ()
+{
+ return ((GdkVisual*) system_visual);
+}
+
+GdkVisual*
+gdk_visual_get_best ()
+{
+ return ((GdkVisual*) &(visuals[0]));
+}
+
+GdkVisual*
+gdk_visual_get_best_with_depth (gint depth)
+{
+ GdkVisual *return_val;
+ int i;
+
+ return_val = NULL;
+ for (i = 0; i < nvisuals; i++)
+ if (depth == visuals[i].visual.depth)
+ {
+ return_val = (GdkVisual*) &(visuals[i]);
+ break;
+ }
+
+ return return_val;
+}
+
+GdkVisual*
+gdk_visual_get_best_with_type (GdkVisualType visual_type)
+{
+ GdkVisual *return_val;
+ int i;
+
+ return_val = NULL;
+ for (i = 0; i < nvisuals; i++)
+ if (visual_type == visuals[i].visual.type)
+ {
+ return_val = (GdkVisual*) &(visuals[i]);
+ break;
+ }
+
+ return return_val;
+}
+
+GdkVisual*
+gdk_visual_get_best_with_both (gint depth,
+ GdkVisualType visual_type)
+{
+ GdkVisual *return_val;
+ int i;
+
+ return_val = NULL;
+ for (i = 0; i < nvisuals; i++)
+ if ((depth == visuals[i].visual.depth) &&
+ (visual_type == visuals[i].visual.type))
+ {
+ return_val = (GdkVisual*) &(visuals[i]);
+ break;
+ }
+
+ return return_val;
+}
+
+void
+gdk_query_depths (gint **depths,
+ gint *count)
+{
+ *count = navailable_depths;
+ *depths = available_depths;
+}
+
+void
+gdk_query_visual_types (GdkVisualType **visual_types,
+ gint *count)
+{
+ *count = navailable_types;
+ *visual_types = available_types;
+}
+
+void
+gdk_query_visuals (GdkVisual **visual_return,
+ gint *count)
+{
+ *count = nvisuals;
+ *visual_return = (GdkVisual*) visuals;
+}
+
+
+GdkVisual*
+gdk_visual_lookup (Visual *xvisual)
+{
+ GdkVisual *visual;
+
+ if (!visual_hash)
+ return NULL;
+
+ visual = g_hash_table_lookup (visual_hash, xvisual);
+ return visual;
+}
+
+GdkVisual*
+gdkx_visual_get (VisualID xvisualid)
+{
+ int i;
+
+ for (i = 0; i < nvisuals; i++)
+ if (xvisualid == visuals[i].xvisual->visualid)
+ return (GdkVisual*) &visuals[i];
+
+ return NULL;
+}
+
+
+static void
+gdk_visual_add (GdkVisual *visual)
+{
+ GdkVisualPrivate *private;
+
+ if (!visual_hash)
+ visual_hash = g_hash_table_new ((GHashFunc) gdk_visual_hash,
+ (GCompareFunc) gdk_visual_compare);
+
+ private = (GdkVisualPrivate*) visual;
+
+ g_hash_table_insert (visual_hash, private->xvisual, visual);
+}
+
+static void
+gdk_visual_decompose_mask (gulong mask,
+ gint *shift,
+ gint *prec)
+{
+ *shift = 0;
+ *prec = 0;
+
+ while (!(mask & 0x1))
+ {
+ (*shift)++;
+ mask >>= 1;
+ }
+
+ while (mask & 0x1)
+ {
+ (*prec)++;
+ mask >>= 1;
+ }
+}
+
+static guint
+gdk_visual_hash (Visual *key)
+{
+ return key->visualid;
+}
+
+static gint
+gdk_visual_compare (Visual *a,
+ Visual *b)
+{
+ return (a->visualid == b->visualid);
+}
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
new file mode 100644
index 000000000..aef1367d9
--- /dev/null
+++ b/gdk/gdkwindow.c
@@ -0,0 +1,1358 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/shape.h>
+#include <netinet/in.h>
+#include "gdk.h"
+#include "gdkinput.h"
+#include "gdkprivate.h"
+#include <stdlib.h>
+
+int nevent_masks = 16;
+int event_mask_table[18] =
+{
+ ExposureMask,
+ PointerMotionMask,
+ PointerMotionHintMask,
+ ButtonMotionMask,
+ Button1MotionMask,
+ Button2MotionMask,
+ Button3MotionMask,
+ ButtonPressMask | OwnerGrabButtonMask,
+ ButtonReleaseMask | OwnerGrabButtonMask,
+ KeyPressMask,
+ KeyReleaseMask,
+ EnterWindowMask,
+ LeaveWindowMask,
+ FocusChangeMask,
+ StructureNotifyMask,
+ PropertyChangeMask,
+ 0, /* PROXIMITY_IN */
+ 0 /* PROXIMTY_OUT */
+};
+
+
+void
+gdk_window_init ()
+{
+ XWindowAttributes xattributes;
+ unsigned int width;
+ unsigned int height;
+ unsigned int border_width;
+ unsigned int depth;
+ int x, y;
+
+ XGetGeometry (gdk_display, gdk_root_window, &gdk_root_window,
+ &x, &y, &width, &height, &border_width, &depth);
+ XGetWindowAttributes (gdk_display, gdk_root_window, &xattributes);
+
+ gdk_root_parent.xdisplay = gdk_display;
+ gdk_root_parent.xwindow = gdk_root_window;
+ gdk_root_parent.window_type = GDK_WINDOW_ROOT;
+ gdk_root_parent.window.user_data = NULL;
+}
+
+GdkWindow*
+gdk_window_new (GdkWindow *parent,
+ GdkWindowAttr *attributes,
+ gint attributes_mask)
+{
+ GdkWindow *window;
+ GdkWindowPrivate *private;
+ GdkWindowPrivate *parent_private;
+ GdkVisual *visual;
+ GdkColormap *colormap;
+ Display *parent_display;
+ Window xparent;
+ Visual *xvisual;
+ XSetWindowAttributes xattributes;
+ long xattributes_mask;
+ XSizeHints size_hints;
+ XWMHints wm_hints;
+ XTextProperty text_property;
+ XClassHint *class_hint;
+ int x, y, depth;
+ unsigned int class;
+ char *title;
+ int i;
+
+ g_return_val_if_fail (attributes != NULL, NULL);
+
+ if (!parent)
+ parent = (GdkWindow*) &gdk_root_parent;
+
+ parent_private = (GdkWindowPrivate*) parent;
+ xparent = parent_private->xwindow;
+ parent_display = parent_private->xdisplay;
+
+ private = g_new (GdkWindowPrivate, 1);
+ window = (GdkWindow*) private;
+
+ private->parent = parent;
+ private->xdisplay = parent_display;
+ private->destroyed = FALSE;
+ private->resize_count = 0;
+ private->ref_count = 1;
+ xattributes_mask = 0;
+
+ if (attributes_mask & GDK_WA_X)
+ x = attributes->x;
+ else
+ x = 0;
+
+ if (attributes_mask & GDK_WA_Y)
+ y = attributes->y;
+ else
+ y = 0;
+
+ private->x = x;
+ private->y = y;
+ private->width = (attributes->width > 1) ? (attributes->width) : (1);
+ private->height = (attributes->height > 1) ? (attributes->height) : (1);
+ private->window_type = attributes->window_type;
+ private->extension_events = FALSE;
+ private->dnd_drag_data_type = None;
+ private->dnd_drag_data_typesavail =
+ private->dnd_drop_data_typesavail = NULL;
+ private->dnd_drop_enabled = private->dnd_drag_enabled =
+ private->dnd_drag_accepted = private->dnd_drag_datashow =
+ private->dnd_drop_data_numtypesavail =
+ private->dnd_drag_data_numtypesavail = 0;
+ private->dnd_drag_eventmask = private->dnd_drag_savedeventmask = 0;
+
+ window->user_data = NULL;
+
+ if (attributes_mask & GDK_WA_VISUAL)
+ visual = attributes->visual;
+ else
+ visual = gdk_visual_get_system ();
+ xvisual = ((GdkVisualPrivate*) visual)->xvisual;
+
+ xattributes.event_mask = StructureNotifyMask;
+ for (i = 0; i < nevent_masks; i++)
+ {
+ if (attributes->event_mask & (1 << (i + 1)))
+ xattributes.event_mask |= event_mask_table[i];
+ }
+
+ if (xattributes.event_mask)
+ xattributes_mask |= CWEventMask;
+
+ if (attributes->wclass == GDK_INPUT_OUTPUT)
+ {
+ class = InputOutput;
+ depth = visual->depth;
+
+ if (attributes_mask & GDK_WA_COLORMAP)
+ colormap = attributes->colormap;
+ else
+ colormap = gdk_colormap_get_system ();
+
+ xattributes.background_pixel = BlackPixel (gdk_display, gdk_screen);
+ xattributes.border_pixel = BlackPixel (gdk_display, gdk_screen);
+ xattributes_mask |= CWBorderPixel | CWBackPixel;
+
+ switch (private->window_type)
+ {
+ case GDK_WINDOW_TOPLEVEL:
+ xattributes.colormap = ((GdkColormapPrivate*) colormap)->xcolormap;
+ xattributes_mask |= CWColormap;
+
+ xparent = gdk_root_window;
+ break;
+
+ case GDK_WINDOW_CHILD:
+ xattributes.colormap = ((GdkColormapPrivate*) colormap)->xcolormap;
+ xattributes_mask |= CWColormap;
+ break;
+
+ case GDK_WINDOW_DIALOG:
+ xattributes.colormap = ((GdkColormapPrivate*) colormap)->xcolormap;
+ xattributes_mask |= CWColormap;
+
+ xparent = gdk_root_window;
+ break;
+
+ case GDK_WINDOW_TEMP:
+ xattributes.colormap = ((GdkColormapPrivate*) colormap)->xcolormap;
+ xattributes_mask |= CWColormap;
+
+ xparent = gdk_root_window;
+
+ xattributes.save_under = True;
+ xattributes.override_redirect = True;
+ xattributes.cursor = None;
+ xattributes_mask |= CWSaveUnder | CWOverrideRedirect;
+ break;
+ case GDK_WINDOW_ROOT:
+ g_error ("cannot make windows of type GDK_WINDOW_ROOT");
+ break;
+ case GDK_WINDOW_PIXMAP:
+ g_error ("cannot make windows of type GDK_WINDOW_PIXMAP (use gdk_pixmap_new)");
+ break;
+ }
+ }
+ else
+ {
+ depth = 1;
+ class = InputOnly;
+ colormap = NULL;
+ }
+
+ private->xwindow = XCreateWindow (private->xdisplay, xparent,
+ x, y, private->width, private->height,
+ 0, depth, class, xvisual,
+ xattributes_mask, &xattributes);
+ gdk_xid_table_insert (&private->xwindow, window);
+
+ switch (private->window_type)
+ {
+ case GDK_WINDOW_DIALOG:
+ XSetTransientForHint (private->xdisplay, private->xwindow, xparent);
+ case GDK_WINDOW_TOPLEVEL:
+ case GDK_WINDOW_TEMP:
+ XSetWMProtocols (private->xdisplay, private->xwindow, gdk_wm_window_protocols, 2);
+ break;
+ case GDK_WINDOW_CHILD:
+ if ((attributes->wclass == GDK_INPUT_OUTPUT) &&
+ (colormap != gdk_colormap_get_system ()) &&
+ (colormap != gdk_window_get_colormap (gdk_window_get_toplevel (window))))
+ {
+ g_print ("adding colormap window\n");
+ gdk_window_add_colormap_windows (window);
+ }
+ break;
+ default:
+ break;
+ }
+
+ size_hints.flags = PSize | PBaseSize;
+ size_hints.width = private->width;
+ size_hints.height = private->height;
+ size_hints.base_width = private->width;
+ size_hints.base_height = private->height;
+
+ wm_hints.flags = InputHint | StateHint | WindowGroupHint;
+ wm_hints.window_group = gdk_leader_window;
+ wm_hints.input = True;
+ wm_hints.initial_state = NormalState;
+
+ XSetWMNormalHints (private->xdisplay, private->xwindow, &size_hints);
+ XSetWMHints (private->xdisplay, private->xwindow, &wm_hints);
+
+ if (attributes_mask & GDK_WA_TITLE)
+ title = attributes->title;
+ else
+ title = gdk_progname;
+
+ if (XStringListToTextProperty (&title, 1, &text_property))
+ {
+ XSetWMName (private->xdisplay, private->xwindow, &text_property);
+ XSetWMIconName (private->xdisplay, private->xwindow, &text_property);
+ XFree (text_property.value);
+ }
+
+ if (attributes_mask & GDK_WA_WMCLASS)
+ {
+ class_hint = XAllocClassHint ();
+ class_hint->res_name = attributes->wmclass_name;
+ class_hint->res_class = attributes->wmclass_class;
+ XSetClassHint (private->xdisplay, private->xwindow, class_hint);
+ XFree (class_hint);
+ }
+
+ gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
+ (attributes->cursor) :
+ NULL));
+
+ return window;
+}
+
+GdkWindow *
+gdk_window_foreign_new (guint32 anid)
+{
+ GdkWindow *window;
+ GdkWindowPrivate *private;
+ XWindowAttributes attrs;
+
+ private = g_new (GdkWindowPrivate, 1);
+ window = (GdkWindow*) private;
+
+ XGetWindowAttributes (gdk_display, anid, &attrs);
+
+ private->parent = NULL;
+ private->xwindow = anid;
+ private->xdisplay = gdk_display;
+ private->x = attrs.x;
+ private->y = attrs.y;
+ private->width = attrs.width;
+ private->height = attrs.height;
+ private->resize_count = 0;
+ private->ref_count = 1;
+ if (anid == attrs.root)
+ private->window_type = GDK_WINDOW_ROOT;
+ else
+ private->window_type = GDK_WINDOW_TOPLEVEL;
+ /* the above is probably wrong, but it may not be worth the extra
+ X call to get it right */
+
+ private->destroyed = FALSE;
+ private->extension_events = 0;
+
+ window->user_data = NULL;
+
+ gdk_xid_table_insert (&private->xwindow, window);
+
+ return window;
+}
+
+void
+gdk_window_destroy (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+ GdkWindowPrivate *temp_private;
+ GdkWindow *temp_window;
+ GList *children;
+ GList *tmp;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+ if(private->dnd_drag_data_numtypesavail > 0)
+ {
+ free(private->dnd_drag_data_typesavail);
+ private->dnd_drag_data_typesavail = NULL;
+ }
+ if(private->dnd_drop_data_numtypesavail > 0)
+ {
+ free(private->dnd_drop_data_typesavail);
+ private->dnd_drop_data_typesavail = NULL;
+ }
+
+ switch (private->window_type)
+ {
+ case GDK_WINDOW_TOPLEVEL:
+ case GDK_WINDOW_CHILD:
+ case GDK_WINDOW_DIALOG:
+ case GDK_WINDOW_TEMP:
+ if (private->ref_count >= 1)
+ private->ref_count -= 1;
+
+ if (!private->destroyed || (private->destroyed == 2))
+ {
+ children = gdk_window_get_children (window);
+ tmp = children;
+
+ while (tmp)
+ {
+ temp_window = tmp->data;
+ tmp = tmp->next;
+
+ temp_private = (GdkWindowPrivate*) temp_window;
+ if (temp_private && !temp_private->destroyed)
+ /* Removes some nice coredumps... /David */
+ {
+ temp_private->destroyed = 2;
+ temp_private->ref_count += 1;
+ gdk_window_destroy (temp_window);
+ }
+ }
+
+ g_list_free (children);
+
+ if (!private->destroyed)
+ XDestroyWindow (private->xdisplay, private->xwindow);
+ private->destroyed = TRUE;
+ }
+ break;
+
+ case GDK_WINDOW_ROOT:
+ g_error ("attempted to destroy root window");
+ break;
+
+ case GDK_WINDOW_PIXMAP:
+ g_warning ("called gdk_window_destroy on a pixmap (use gdk_pixmap_destroy)");
+ gdk_pixmap_destroy (window);
+ break;
+ }
+}
+
+void
+gdk_window_real_destroy (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+
+ if (private->extension_events != 0)
+ gdk_input_window_destroy (window);
+
+ if (private->ref_count == 0)
+ {
+ gdk_xid_table_remove (private->xwindow);
+ g_free (window);
+ }
+}
+
+GdkWindow*
+gdk_window_ref (GdkWindow *window)
+{
+ GdkWindowPrivate *private = (GdkWindowPrivate *)window;
+ g_return_if_fail (window != NULL);
+
+ private->ref_count += 1;
+ return window;
+}
+
+void
+gdk_window_unref (GdkWindow *window)
+{
+ GdkWindowPrivate *private = (GdkWindowPrivate *)window;
+ g_return_if_fail (window != NULL);
+
+ private->ref_count -= 1;
+ if (private->ref_count == 0)
+ gdk_window_real_destroy (window);
+}
+
+void
+gdk_window_show (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+ if (!private->destroyed)
+ {
+ XRaiseWindow (private->xdisplay, private->xwindow);
+ XMapWindow (private->xdisplay, private->xwindow);
+ }
+}
+
+void
+gdk_window_hide (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+ if (!private->destroyed)
+ XUnmapWindow (private->xdisplay, private->xwindow);
+}
+
+void
+gdk_window_move (GdkWindow *window,
+ gint x,
+ gint y)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+ XMoveWindow (private->xdisplay, private->xwindow, x, y);
+
+ if (private->window_type == GDK_WINDOW_CHILD)
+ {
+ private->x = x;
+ private->y = y;
+ }
+}
+
+void
+gdk_window_resize (GdkWindow *window,
+ gint width,
+ gint height)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ if (width < 1)
+ width = 1;
+ if (height < 1)
+ height = 1;
+
+ private = (GdkWindowPrivate*) window;
+
+ if (!private->destroyed &&
+ ((private->resize_count > 0) ||
+ (private->width != (guint16) width) ||
+ (private->height != (guint16) height)))
+ {
+ XResizeWindow (private->xdisplay, private->xwindow, width, height);
+ private->resize_count += 1;
+
+ if (private->window_type == GDK_WINDOW_CHILD)
+ {
+ private->width = width;
+ private->height = height;
+ }
+ }
+}
+
+void
+gdk_window_move_resize (GdkWindow *window,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ if (width < 1)
+ width = 1;
+ if (height < 1)
+ height = 1;
+
+ private = (GdkWindowPrivate*) window;
+ XMoveResizeWindow (private->xdisplay, private->xwindow, x, y, width, height);
+
+ if (!private->destroyed &&
+ (private->window_type == GDK_WINDOW_CHILD))
+ {
+ private->x = x;
+ private->y = y;
+ private->width = width;
+ private->height = height;
+ }
+}
+
+void
+gdk_window_reparent (GdkWindow *window,
+ GdkWindow *new_parent,
+ gint x,
+ gint y)
+{
+ GdkWindowPrivate *window_private;
+ GdkWindowPrivate *parent_private;
+
+ g_return_if_fail (window != NULL);
+
+ if (!new_parent)
+ new_parent = (GdkWindow*) &gdk_root_parent;
+
+ window_private = (GdkWindowPrivate*) window;
+ parent_private = (GdkWindowPrivate*) new_parent;
+
+ XReparentWindow (window_private->xdisplay,
+ window_private->xwindow,
+ parent_private->xwindow,
+ x, y);
+}
+
+void
+gdk_window_clear (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+
+ XClearWindow (private->xdisplay, private->xwindow);
+}
+
+void
+gdk_window_clear_area (GdkWindow *window,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+
+ if (!private->destroyed)
+ XClearArea (private->xdisplay, private->xwindow,
+ x, y, width, height, False);
+}
+
+void
+gdk_window_clear_area_e (GdkWindow *window,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+
+ if (!private->destroyed)
+ XClearArea (private->xdisplay, private->xwindow,
+ x, y, width, height, True);
+}
+
+void
+gdk_window_copy_area (GdkWindow *window,
+ GdkGC *gc,
+ gint x,
+ gint y,
+ GdkWindow *source_window,
+ gint source_x,
+ gint source_y,
+ gint width,
+ gint height)
+{
+ GdkWindowPrivate *src_private;
+ GdkWindowPrivate *dest_private;
+ GdkGCPrivate *gc_private;
+
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (gc != NULL);
+
+ if (source_window == NULL)
+ source_window = window;
+
+ src_private = (GdkWindowPrivate*) source_window;
+ dest_private = (GdkWindowPrivate*) window;
+ gc_private = (GdkGCPrivate*) gc;
+
+ if (!src_private->destroyed && !dest_private->destroyed)
+ {
+ XCopyArea (dest_private->xdisplay, src_private->xwindow, dest_private->xwindow,
+ gc_private->xgc,
+ source_x, source_y,
+ width, height,
+ x, y);
+ }
+}
+
+void
+gdk_window_raise (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+
+ if (!private->destroyed)
+ XRaiseWindow (private->xdisplay, private->xwindow);
+}
+
+void
+gdk_window_lower (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+
+ if (!private->destroyed)
+ XLowerWindow (private->xdisplay, private->xwindow);
+}
+
+void
+gdk_window_set_user_data (GdkWindow *window,
+ gpointer user_data)
+{
+ g_return_if_fail (window != NULL);
+
+ window->user_data = user_data;
+}
+
+void
+gdk_window_set_hints (GdkWindow *window,
+ gint x,
+ gint y,
+ gint min_width,
+ gint min_height,
+ gint max_width,
+ gint max_height,
+ gint flags)
+{
+ GdkWindowPrivate *private;
+ XSizeHints size_hints;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+ size_hints.flags = 0;
+
+ if (flags & GDK_HINT_POS)
+ {
+ size_hints.flags |= PPosition;
+ size_hints.x = x;
+ size_hints.y = y;
+ }
+
+ if (flags & GDK_HINT_MIN_SIZE)
+ {
+ size_hints.flags |= PMinSize;
+ size_hints.min_width = min_width;
+ size_hints.min_height = min_height;
+ }
+
+ if (flags & GDK_HINT_MAX_SIZE)
+ {
+ size_hints.flags |= PMaxSize;
+ size_hints.max_width = max_width;
+ size_hints.max_height = max_height;
+ }
+
+ if (flags)
+ XSetWMNormalHints (private->xdisplay, private->xwindow, &size_hints);
+}
+
+void
+gdk_window_set_title (GdkWindow *window,
+ const gchar *title)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+ XStoreName (private->xdisplay, private->xwindow, title);
+ XSetIconName (private->xdisplay, private->xwindow, title);
+}
+
+void
+gdk_window_set_background (GdkWindow *window,
+ GdkColor *color)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+ XSetWindowBackground (private->xdisplay, private->xwindow, color->pixel);
+}
+
+void
+gdk_window_set_back_pixmap (GdkWindow *window,
+ GdkPixmap *pixmap,
+ gint parent_relative)
+{
+ GdkWindowPrivate *window_private;
+ GdkPixmapPrivate *pixmap_private;
+ Pixmap xpixmap;
+
+ g_return_if_fail (window != NULL);
+
+ window_private = (GdkWindowPrivate*) window;
+ pixmap_private = (GdkPixmapPrivate*) pixmap;
+
+ if (pixmap)
+ xpixmap = pixmap_private->xwindow;
+ else
+ xpixmap = None;
+
+ if (parent_relative)
+ xpixmap = ParentRelative;
+
+ XSetWindowBackgroundPixmap (window_private->xdisplay, window_private->xwindow, xpixmap);
+}
+
+void
+gdk_window_set_cursor (GdkWindow *window,
+ GdkCursor *cursor)
+{
+ GdkWindowPrivate *window_private;
+ GdkCursorPrivate *cursor_private;
+ Cursor xcursor;
+
+ g_return_if_fail (window != NULL);
+
+ window_private = (GdkWindowPrivate*) window;
+ cursor_private = (GdkCursorPrivate*) cursor;
+
+ if (!cursor)
+ xcursor = None;
+ else
+ xcursor = cursor_private->xcursor;
+
+ XDefineCursor (window_private->xdisplay, window_private->xwindow, xcursor);
+}
+
+void
+gdk_window_set_colormap (GdkWindow *window,
+ GdkColormap *colormap)
+{
+ GdkWindowPrivate *window_private;
+ GdkColormapPrivate *colormap_private;
+
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (colormap != NULL);
+
+ window_private = (GdkWindowPrivate*) window;
+ colormap_private = (GdkColormapPrivate*) colormap;
+
+ XSetWindowColormap (window_private->xdisplay,
+ window_private->xwindow,
+ colormap_private->xcolormap);
+
+ if (window_private->window_type != GDK_WINDOW_TOPLEVEL)
+ gdk_window_add_colormap_windows (window);
+}
+
+void
+gdk_window_get_user_data (GdkWindow *window,
+ gpointer *data)
+{
+ g_return_if_fail (window != NULL);
+
+ *data = window->user_data;
+}
+
+void
+gdk_window_get_geometry (GdkWindow *window,
+ gint *x,
+ gint *y,
+ gint *width,
+ gint *height,
+ gint *depth)
+{
+ GdkWindowPrivate *window_private;
+ Window root;
+ gint tx;
+ gint ty;
+ guint twidth;
+ guint theight;
+ guint tborder_width;
+ guint tdepth;
+
+ if (!window)
+ window = (GdkWindow*) &gdk_root_parent;
+
+ window_private = (GdkWindowPrivate*) window;
+
+ XGetGeometry (window_private->xdisplay, window_private->xwindow,
+ &root, &tx, &ty, &twidth, &theight, &tborder_width, &tdepth);
+
+ if (x)
+ *x = tx;
+ if (y)
+ *y = ty;
+ if (width)
+ *width = twidth;
+ if (height)
+ *height = theight;
+ if (depth)
+ *depth = tdepth;
+}
+
+void
+gdk_window_get_position (GdkWindow *window,
+ gint *x,
+ gint *y)
+{
+ GdkWindowPrivate *window_private;
+
+ g_return_if_fail (window != NULL);
+
+ window_private = (GdkWindowPrivate*) window;
+
+ if (x)
+ *x = window_private->x;
+ if (y)
+ *y = window_private->y;
+}
+
+void
+gdk_window_get_size (GdkWindow *window,
+ gint *width,
+ gint *height)
+{
+ GdkWindowPrivate *window_private;
+
+ g_return_if_fail (window != NULL);
+
+ window_private = (GdkWindowPrivate*) window;
+
+ if (width)
+ *width = window_private->width;
+ if (height)
+ *height = window_private->height;
+}
+
+
+GdkVisual*
+gdk_window_get_visual (GdkWindow *window)
+{
+ GdkWindowPrivate *window_private;
+ XWindowAttributes window_attributes;
+
+ g_return_val_if_fail (window != NULL, NULL);
+
+ window_private = (GdkWindowPrivate*) window;
+ while (window_private && (window_private->window_type == GDK_WINDOW_PIXMAP))
+ window_private = (GdkWindowPrivate*) window_private->parent;
+
+ if (window_private)
+ {
+ XGetWindowAttributes (window_private->xdisplay,
+ window_private->xwindow,
+ &window_attributes);
+
+ return gdk_visual_lookup (window_attributes.visual);
+ }
+
+ return NULL;
+}
+
+GdkColormap*
+gdk_window_get_colormap (GdkWindow *window)
+{
+ GdkWindowPrivate *window_private;
+ XWindowAttributes window_attributes;
+
+ g_return_val_if_fail (window != NULL, NULL);
+
+ window_private = (GdkWindowPrivate*) window;
+
+ XGetWindowAttributes (window_private->xdisplay,
+ window_private->xwindow,
+ &window_attributes);
+
+ return gdk_colormap_lookup (window_attributes.colormap);
+}
+
+GdkWindowType
+gdk_window_get_type (GdkWindow *window)
+{
+ GdkWindowPrivate *window_private;
+
+ g_return_val_if_fail (window != NULL, (GdkWindowType) -1);
+
+ window_private = (GdkWindowPrivate*) window;
+ return window_private->window_type;
+}
+
+gint
+gdk_window_get_origin (GdkWindow *window,
+ gint *x,
+ gint *y)
+{
+ GdkWindowPrivate *private;
+ gint return_val;
+ Window child;
+ gint tx, ty;
+
+ g_return_val_if_fail (window != NULL, 0);
+
+ private = (GdkWindowPrivate*) window;
+
+ return_val = XTranslateCoordinates (private->xdisplay,
+ private->xwindow,
+ gdk_root_window,
+ 0, 0, &tx, &ty,
+ &child);
+
+ if (x)
+ *x = tx;
+ if (y)
+ *y = ty;
+
+ return return_val;
+}
+
+GdkWindow*
+gdk_window_get_pointer (GdkWindow *window,
+ gint *x,
+ gint *y,
+ GdkModifierType *mask)
+{
+ GdkWindowPrivate *private;
+ GdkWindow *return_val;
+ Window root;
+ Window child;
+ int rootx, rooty;
+ int winx, winy;
+ unsigned int xmask;
+
+ if (!window)
+ window = (GdkWindow*) &gdk_root_parent;
+
+ private = (GdkWindowPrivate*) window;
+
+ return_val = NULL;
+ if (XQueryPointer (private->xdisplay, private->xwindow, &root, &child,
+ &rootx, &rooty, &winx, &winy, &xmask))
+ {
+ if (x) *x = winx;
+ if (y) *y = winy;
+ if (mask) *mask = xmask;
+
+ if (child)
+ return_val = gdk_window_lookup (child);
+ }
+
+ return return_val;
+}
+
+GdkWindow*
+gdk_window_get_parent (GdkWindow *window)
+{
+ g_return_val_if_fail (window != NULL, NULL);
+
+ return ((GdkWindowPrivate*) window)->parent;
+}
+
+GdkWindow*
+gdk_window_get_toplevel (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+
+ g_return_val_if_fail (window != NULL, NULL);
+
+ private = (GdkWindowPrivate*) window;
+
+ while (private->window_type == GDK_WINDOW_CHILD)
+ {
+ window = ((GdkWindowPrivate*) window)->parent;
+ private = (GdkWindowPrivate*) window;
+ }
+
+ return window;
+}
+
+GList*
+gdk_window_get_children (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+ GdkWindow *child;
+ GList *children;
+ Window root;
+ Window parent;
+ Window *xchildren;
+ unsigned int nchildren;
+ unsigned int i;
+
+ g_return_val_if_fail (window != NULL, NULL);
+
+ private = (GdkWindowPrivate*) window;
+
+ XQueryTree (private->xdisplay, private->xwindow,
+ &root, &parent, &xchildren, &nchildren);
+
+ children = NULL;
+
+ if (nchildren > 0)
+ {
+ for (i = 0; i < nchildren; i++)
+ {
+ child = gdk_window_lookup (xchildren[i]);
+ if (child)
+ children = g_list_prepend (children, child);
+ }
+
+ XFree (xchildren);
+ }
+
+ return children;
+}
+
+GdkEventMask
+gdk_window_get_events (GdkWindow *window)
+{
+ XWindowAttributes attrs;
+ GdkEventMask event_mask;
+ int i;
+
+ XGetWindowAttributes (gdk_display, ((GdkWindowPrivate *)window)->xwindow,
+ &attrs);
+
+ event_mask = 0;
+ for (i = 0; i < nevent_masks; i++)
+ {
+ if (attrs.your_event_mask & event_mask_table[i])
+ event_mask |= 1 << (i + 1);
+ }
+
+ return event_mask;
+}
+
+void
+gdk_window_set_events (GdkWindow *window,
+ GdkEventMask event_mask)
+{
+ long xevent_mask;
+ int i;
+
+ xevent_mask = StructureNotifyMask;
+ for (i = 0; i < nevent_masks; i++)
+ {
+ if (event_mask & (1 << (i + 1)))
+ xevent_mask |= event_mask_table[i];
+ }
+
+ XSelectInput (gdk_display, ((GdkWindowPrivate *)window)->xwindow,
+ xevent_mask);
+}
+
+void
+gdk_window_add_colormap_windows (GdkWindow *window)
+{
+ GdkWindow *toplevel;
+ GdkWindowPrivate *toplevel_private;
+ GdkWindowPrivate *window_private;
+ Window *old_windows;
+ Window *new_windows;
+ int i, count;
+
+ g_return_if_fail (window != NULL);
+
+ toplevel = gdk_window_get_toplevel (window);
+ toplevel_private = (GdkWindowPrivate*) toplevel;
+ window_private = (GdkWindowPrivate*) window;
+
+ if (!XGetWMColormapWindows (toplevel_private->xdisplay,
+ toplevel_private->xwindow,
+ &old_windows, &count))
+ {
+ old_windows = NULL;
+ count = 0;
+ }
+
+ for (i = 0; i < count; i++)
+ if (old_windows[i] == window_private->xwindow)
+ return;
+
+ new_windows = g_new (Window, count + 1);
+
+ for (i = 0; i < count; i++)
+ new_windows[i] = old_windows[i];
+ new_windows[count] = window_private->xwindow;
+
+ XSetWMColormapWindows (toplevel_private->xdisplay,
+ toplevel_private->xwindow,
+ new_windows, count + 1);
+
+ g_free (new_windows);
+ if (old_windows)
+ XFree (old_windows);
+}
+
+/*
+ * This needs the X11 shape extension.
+ * If not available, simply remove the call to
+ * XShapeCombineMask. Shaped windows will look
+ * ugly, but programs still work. Stefan Wille
+ */
+void
+gdk_window_shape_combine_mask (GdkWindow *window,
+ GdkBitmap *mask,
+ gint x, gint y)
+{
+ GdkWindowPrivate *window_private;
+ GdkWindowPrivate *pixmap_private;
+
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (mask != NULL);
+
+ window_private = (GdkWindowPrivate*) window;
+ pixmap_private = (GdkWindowPrivate*) mask;
+
+ XShapeCombineMask (window_private->xdisplay,
+ window_private->xwindow,
+ ShapeBounding,
+ x, y, /* offset */
+ (Pixmap)pixmap_private->xwindow,
+ ShapeSet);
+}
+
+void
+gdk_dnd_drag_addwindow (GdkWindow *window)
+{
+ GdkWindowPrivate *window_private;
+
+ g_return_if_fail (window != NULL);
+
+ window_private = (GdkWindowPrivate *) window;
+
+ if (window_private->dnd_drag_enabled == 1 && gdk_dnd.drag_really == 0)
+ {
+ gdk_dnd.drag_numwindows++;
+ gdk_dnd.drag_startwindows = g_realloc (gdk_dnd.drag_startwindows,
+ gdk_dnd.drag_numwindows
+ * sizeof(GdkWindow *));
+ gdk_dnd.drag_startwindows[gdk_dnd.drag_numwindows - 1] = window;
+ window_private->dnd_drag_accepted = 0;
+ }
+ else
+ g_warning ("dnd_really is 1 or drag is not enabled! can't addwindow\n");
+}
+
+void
+gdk_window_dnd_drag_set (GdkWindow *window,
+ guint8 drag_enable,
+ gchar **typelist,
+ guint numtypes)
+{
+ GdkWindowPrivate *window_private;
+ int i, wasset = 0;
+
+ g_return_if_fail (window != NULL);
+ window_private = (GdkWindowPrivate *) window;
+
+ window_private->dnd_drag_enabled = drag_enable ? 1 : 0;
+
+ if (drag_enable)
+ {
+ g_return_if_fail(typelist != NULL);
+
+ if (window_private->dnd_drag_data_numtypesavail > 3)
+ wasset = 1;
+ window_private->dnd_drag_data_numtypesavail = numtypes;
+
+ window_private->dnd_drag_data_typesavail =
+ g_realloc (window_private->dnd_drag_data_typesavail,
+ (numtypes + 1) * sizeof (GdkAtom));
+
+ for (i = 0; i < numtypes; i++)
+ {
+ /* Allow blanket use of ALL to get anything... */
+ if (strcmp (typelist[i], "ALL"))
+ window_private->dnd_drag_data_typesavail[i] =
+ gdk_atom_intern (typelist[i], FALSE);
+ else
+ window_private->dnd_drag_data_typesavail[i] = None;
+ }
+
+ /*
+ * set our extended type list if we need to
+ */
+ if (numtypes > 3)
+ gdk_property_change(window, gdk_dnd.gdk_XdeTypelist,
+ XA_PRIMARY, 32, GDK_PROP_MODE_REPLACE,
+ (guchar *)(window_private->dnd_drag_data_typesavail
+ + (sizeof(GdkAtom) * 3)),
+ (numtypes - 3) * sizeof(GdkAtom));
+ else if (wasset)
+ gdk_property_delete (window, gdk_dnd.gdk_XdeTypelist);
+ }
+ else
+ {
+ free (window_private->dnd_drag_data_typesavail);
+ window_private->dnd_drag_data_typesavail = NULL;
+ window_private->dnd_drag_data_numtypesavail = 0;
+ }
+}
+
+void
+gdk_window_dnd_drop_set (GdkWindow *window,
+ guint8 drop_enable,
+ gchar **typelist,
+ guint numtypes,
+ guint8 destructive_op)
+{
+ GdkWindowPrivate *window_private;
+ int i;
+
+ g_return_if_fail (window != NULL);
+
+ window_private = (GdkWindowPrivate *) window;
+
+ window_private->dnd_drop_enabled = drop_enable ? 1 : 0;
+ if (drop_enable)
+ {
+ g_return_if_fail(typelist != NULL);
+
+ window_private->dnd_drop_data_numtypesavail = numtypes;
+
+ window_private->dnd_drop_data_typesavail =
+ g_realloc (window_private->dnd_drop_data_typesavail,
+ (numtypes + 1) * sizeof (GdkAtom));
+
+ for (i = 0; i < numtypes; i++)
+ window_private->dnd_drop_data_typesavail[i] =
+ gdk_atom_intern (typelist[i], FALSE);
+
+ window_private->dnd_drop_destructive_op = destructive_op;
+ }
+}
+
+/*
+ * This is used to reply to a GDK_DRAG_REQUEST event
+ * (which may be generated by XdeRequest or a confirmed drop...
+ */
+void
+gdk_window_dnd_data_set (GdkWindow *window,
+ GdkEvent *event,
+ gpointer data,
+ gulong data_numbytes)
+{
+ GdkWindowPrivate *window_private;
+ XEvent sev;
+ GdkEventDropDataAvailable tmp_ev;
+ gchar *tmp;
+
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (event != NULL);
+ g_return_if_fail (data != NULL);
+ g_return_if_fail (data_numbytes > 0);
+ g_return_if_fail (event->type == GDK_DRAG_REQUEST);
+
+ g_free (event->dragrequest.data_type);
+ event->dragrequest.data_type = NULL;
+
+ window_private = (GdkWindowPrivate *) window;
+ g_return_if_fail (window_private->dnd_drag_accepted != 0);
+
+ /* We set the property on our window... */
+ gdk_property_change (window, window_private->dnd_drag_data_type,
+ XA_PRIMARY, 8, GDK_PROP_MODE_REPLACE, data,
+ data_numbytes);
+ tmp = gdk_atom_name(window_private->dnd_drag_data_type);
+ g_print("DnD type %s on window %ld\n", tmp, window_private->xwindow);
+ g_free(tmp);
+
+ /*
+ * Then we send the event to tell the receiving window that the
+ * drop has happened
+ */
+ tmp_ev.u.allflags = 0;
+ tmp_ev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
+ tmp_ev.u.flags.isdrop = event->dragrequest.isdrop;
+
+ sev.xclient.type = ClientMessage;
+ sev.xclient.format = 32;
+ sev.xclient.window = event->dragrequest.requestor;
+ sev.xclient.message_type = gdk_dnd.gdk_XdeDataAvailable;
+ sev.xclient.data.l[0] = window_private->xwindow;
+ sev.xclient.data.l[1] = tmp_ev.u.allflags;
+ sev.xclient.data.l[2] = window_private->dnd_drag_data_type;
+
+ if (event->dragrequest.isdrop)
+ sev.xclient.data.l[3] = event->dragrequest.drop_coords.x +
+ (event->dragrequest.drop_coords.y << 16);
+ else
+ sev.xclient.data.l[3] = 0;
+
+ sev.xclient.data.l[4] = 0;
+
+ XSendEvent (gdk_display, event->dragrequest.requestor, False,
+ NoEventMask, &sev);
+}
diff --git a/gdk/gdkx.h b/gdk/gdkx.h
new file mode 100644
index 000000000..cb8e33b44
--- /dev/null
+++ b/gdk/gdkx.h
@@ -0,0 +1,48 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GDK_X_H__
+#define __GDK_X_H__
+
+#include <gdk/gdkprivate.h>
+
+
+#define GDK_ROOT_WINDOW() gdk_root_window
+#define GDK_ROOT_PARENT() &gdk_root_parent
+#define GDK_DISPLAY() gdk_display
+#define GDK_WINDOW_XDISPLAY(win) (((GdkWindowPrivate*) win)->xdisplay)
+#define GDK_WINDOW_XWINDOW(win) (((GdkWindowPrivate*) win)->xwindow)
+#define GDK_IMAGE_XDISPLAY(image) (((GdkImagePrivate*) image)->xdisplay)
+#define GDK_IMAGE_XIMAGE(image) (((GdkImagePrivate*) image)->ximage)
+#define GDK_GC_XDISPLAY(gc) (((GdkGCPrivate*) gc)->xdisplay)
+#define GDK_GC_XGC(gc) (((GdkGCPrivate*) gc)->xgc)
+#define GDK_COLORMAP_XDISPLAY(cmap) (((GdkColormapPrivate*) cmap)->xdisplay)
+#define GDK_COLORMAP_XCOLORMAP(cmap) (((GdkColormapPrivate*) cmap)->xcolormap)
+#define GDK_VISUAL_XVISUAL(vis) (((GdkVisualPrivate*) vis)->xvisual)
+#define GDK_FONT_XDISPLAY(font) (((GdkFontPrivate*) font)->xdisplay)
+#define GDK_FONT_XFONT(font) (((GdkFontPrivate*) font)->xfont)
+
+
+GdkVisual* gdkx_visual_get (VisualID xvisualid);
+GdkColormap* gdkx_colormap_get (Colormap xcolormap);
+/* Utility function in gdk.c - not sure where it belongs, but it's
+ needed in more than one place, so make it public */
+Window gdk_get_client_window (Display *dpy,
+ Window win);
+
+
+#endif /* __GDK_X_H__ */
diff --git a/gdk/gdkxid.c b/gdk/gdkxid.c
new file mode 100644
index 000000000..7ee6075c5
--- /dev/null
+++ b/gdk/gdkxid.c
@@ -0,0 +1,74 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gdkprivate.h"
+
+
+static guint gdk_xid_hash (XID *xid);
+static gint gdk_xid_compare (XID *a,
+ XID *b);
+
+
+GHashTable *xid_ht = NULL;
+
+
+void
+gdk_xid_table_insert (XID *xid,
+ gpointer data)
+{
+ g_return_if_fail (xid != NULL);
+
+ if (!xid_ht)
+ xid_ht = g_hash_table_new ((GHashFunc) gdk_xid_hash,
+ (GCompareFunc) gdk_xid_compare);
+
+ g_hash_table_insert (xid_ht, xid, data);
+}
+
+void
+gdk_xid_table_remove (XID xid)
+{
+ if (!xid_ht)
+ xid_ht = g_hash_table_new ((GHashFunc) gdk_xid_hash,
+ (GCompareFunc) gdk_xid_compare);
+
+ g_hash_table_remove (xid_ht, &xid);
+}
+
+gpointer
+gdk_xid_table_lookup (XID xid)
+{
+ gpointer data;
+
+ data = g_hash_table_lookup (xid_ht, &xid);
+
+ return data;
+}
+
+
+static guint
+gdk_xid_hash (XID *xid)
+{
+ return *xid;
+}
+
+static gint
+gdk_xid_compare (XID *a,
+ XID *b)
+{
+ return (*a == *b);
+}
diff --git a/gdk/gxid.c b/gdk/gxid.c
new file mode 100644
index 000000000..219c08bfe
--- /dev/null
+++ b/gdk/gxid.c
@@ -0,0 +1,844 @@
+/*
+ * gxid version 0.3
+ *
+ * Copyright 1997 Owen Taylor <owt1@cornell.edu>
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/XInput.h>
+
+#include "gxid_proto.h"
+
+/* #define DEBUG_CLIENTS */
+/* #define DEBUG_EVENTS */
+
+char *program_name;
+Display *dpy;
+Window root_window; /* default root window of dpy */
+int port = 0; /* port to listen on */
+int socket_fd = 0; /* file descriptor of socket */
+typedef struct GxidWindow_ GxidWindow;
+
+typedef struct GxidDevice_ GxidDevice;
+struct GxidDevice_ {
+ XID id;
+ int exclusive;
+ int ispointer;
+
+ XDevice *xdevice;
+ int motionnotify_type;
+ int changenotify_type;
+};
+
+struct GxidWindow_ {
+ Window xwindow;
+ /* Immediate child of root that is ancestor of window */
+ Window root_child;
+ int num_devices;
+ GxidDevice **devices;
+};
+
+GxidDevice **devices = NULL;
+int num_devices = 0;
+GxidWindow **windows = NULL;
+int num_windows = 0;
+
+void
+handler(int signal)
+{
+ fprintf(stderr,"%s: dying on signal %d\n",program_name,signal);
+ if (socket_fd)
+ close(socket_fd);
+ exit(1);
+}
+
+void
+init_socket()
+{
+ struct sockaddr_in sin;
+
+ socket_fd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
+ if (socket_fd < 0)
+ {
+ fprintf (stderr, "%s: error getting socket\n",
+ program_name);
+ exit(1);
+ }
+
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(port);
+ sin.sin_addr.s_addr = INADDR_ANY;
+
+ if (bind(socket_fd,(struct sockaddr *)(&sin),
+ sizeof(struct sockaddr_in)) < 0)
+ {
+ fprintf (stderr,"%s: cannot bind to port %d\n",
+ program_name,port);
+ exit(1);
+ }
+
+ if (listen(socket_fd,5) < 0)
+ {
+ fprintf (stderr,"%s: error listening on socket\n",
+ program_name);
+ exit(1);
+ };
+}
+
+#define NUM_EVENTC 2
+static void
+enable_device(GxidDevice *dev)
+{
+ XEventClass xevc[NUM_EVENTC];
+ int num_eventc = NUM_EVENTC;
+ int i,j;
+
+ if (!dev->xdevice)
+ {
+ if (dev->ispointer) return;
+
+ dev->xdevice = XOpenDevice(dpy, dev->id);
+ if (!dev->xdevice) return;
+
+ DeviceMotionNotify (dev->xdevice, dev->motionnotify_type,
+ xevc[0]);
+ ChangeDeviceNotify (dev->xdevice, dev->changenotify_type,
+ xevc[1]);
+
+ /* compress out zero event classes */
+ for (i=0,j=0;i<NUM_EVENTC;i++)
+ {
+ if (xevc[i]) {
+ xevc[j] = xevc[i];
+ j++;
+ }
+ }
+ num_eventc = j;
+
+ XSelectExtensionEvent (dpy, root_window, xevc, num_eventc);
+ }
+}
+
+/* switch the core pointer from whatever it is now to something else,
+ return true on success, false otherwise */
+static int
+switch_core_pointer()
+{
+ GxidDevice *old_pointer = 0;
+ GxidDevice *new_pointer = 0;
+ int result;
+ int i;
+
+ for (i=0;i<num_devices;i++)
+ {
+ if (devices[i]->ispointer)
+ old_pointer = devices[i];
+ else
+ if (!new_pointer && !devices[i]->exclusive)
+ new_pointer = devices[i];
+ }
+
+ if (!old_pointer || !new_pointer)
+ return 0;
+
+#ifdef DEBUG_EVENTS
+ fprintf(stderr,"gxid: Switching core from %ld to %ld\n",
+ old_pointer->id,new_pointer->id);
+#endif
+ result = XChangePointerDevice(dpy,new_pointer->xdevice, 0, 1);
+ if (result != Success)
+ {
+ fprintf(stderr,"gxid: Error %d switching core from %ld to %ld\n",
+ result, old_pointer->id, new_pointer->id);
+ }
+ else
+ {
+ new_pointer->ispointer = 1;
+ old_pointer->ispointer = 0;
+ if (!old_pointer->xdevice)
+ enable_device(old_pointer);
+ }
+
+ return 1;
+}
+
+void
+disable_device(GxidDevice *dev)
+{
+ if (dev->xdevice)
+ {
+ if (dev->ispointer)
+ return;
+ XCloseDevice(dpy,dev->xdevice);
+ dev->xdevice = 0;
+ }
+}
+
+GxidDevice *
+init_device(XDeviceInfo *xdevice)
+{
+ GxidDevice *dev = (GxidDevice *)malloc(sizeof(GxidDevice));
+ XAnyClassPtr class;
+ int num_axes, i;
+
+ dev->id = xdevice->id;
+ dev->exclusive = 0;
+ dev->xdevice = NULL;
+
+ dev->ispointer = (xdevice->use == IsXPointer);
+
+ /* step through the classes */
+
+ num_axes = 0;
+ class = xdevice->inputclassinfo;
+ for (i=0;i<xdevice->num_classes;i++)
+ {
+ if (class->class == ValuatorClass)
+ {
+ XValuatorInfo *xvi = (XValuatorInfo *)class;
+ num_axes = xvi->num_axes;
+ }
+ class = (XAnyClassPtr)(((char *)class) + class->length);
+ }
+
+ /* return NULL if insufficient axes */
+ if (num_axes < 2)
+ {
+ free((void *)dev);
+ return NULL;
+ }
+
+ if (!dev->ispointer)
+ enable_device(dev);
+ return dev;
+}
+
+void
+init_xinput()
+{
+ char **extensions;
+ XDeviceInfo *xdevices;
+ int num_xdevices;
+ int num_extensions;
+ int i;
+
+ extensions = XListExtensions(dpy, &num_extensions);
+ for (i = 0; i < num_extensions &&
+ (strcmp(extensions[i], "XInputExtension") != 0); i++);
+ XFreeExtensionList(extensions);
+ if (i == num_extensions) /* XInput extension not found */
+ {
+ fprintf(stderr,"XInput extension not found\n");
+ exit(1);
+ }
+
+ xdevices = XListInputDevices(dpy, &num_xdevices);
+ devices = (GxidDevice **)malloc(num_xdevices * sizeof(GxidDevice *));
+
+ num_devices = 0;
+ for(i=0; i<num_xdevices; i++)
+ {
+ GxidDevice *dev = init_device(&xdevices[i]);
+ if (dev)
+ devices[num_devices++] = dev;
+ }
+ XFreeDeviceList(xdevices);
+}
+
+/* If this routine needs fixing, the corresponding routine
+ in gdkinputgxi.h will need it too. */
+
+Window
+gxi_find_root_child(Display *dpy, Window w)
+{
+ Window root,parent;
+ Window *children;
+ int nchildren;
+
+ parent = w;
+ do
+ {
+ w = parent;
+ XQueryTree(dpy,w,&root,&parent,&children,&nchildren);
+ if (children) XFree(children);
+ }
+ while (parent != root);
+
+ return w;
+}
+
+int
+handle_claim_device(GxidClaimDevice *msg)
+{
+ int i,j;
+ XID devid = ntohl(msg->device);
+ XID winid = ntohl(msg->window);
+ int exclusive = ntohl(msg->exclusive);
+ GxidDevice *device = NULL;
+ GxidWindow *window = NULL;
+
+#ifdef DEBUG_CLIENTS
+ fprintf(stderr,"device %ld claimed (window 0x%lx)\n",devid,winid);
+#endif
+
+ for (i=0;i<num_devices;i++)
+ {
+ if (devices[i]->id == devid)
+ {
+ device = devices[i];
+ break;
+ }
+ }
+ if (!device)
+ {
+ fprintf(stderr,"%s: Unknown device id %ld\n",program_name,devid);
+ return GXID_RETURN_ERROR;
+ }
+
+ if (device->exclusive)
+ {
+ /* already in use */
+ fprintf(stderr,
+ "%s: Device %ld already claimed in exclusive mode\n",
+ program_name,devid);
+ return GXID_RETURN_ERROR;
+ }
+
+ if (exclusive)
+ {
+ for (i=0;i<num_windows;i++)
+ {
+ for (j=0;j<windows[i]->num_devices;j++)
+ if (windows[i]->devices[j]->id == devid)
+ {
+ /* already in use */
+ fprintf(stderr,
+ "%s: Can't establish exclusive use of device %ld\n",
+ program_name,devid);
+ return GXID_RETURN_ERROR;
+ }
+ }
+ if (device->ispointer)
+ if (!switch_core_pointer())
+ {
+ fprintf(stderr,
+ "%s: Can't free up core pointer %ld\n",
+ program_name,devid);
+ return GXID_RETURN_ERROR;
+ }
+
+ device->exclusive = 1;
+ disable_device(device);
+ XSelectInput(dpy,winid,StructureNotifyMask);
+ }
+ else /* !exclusive */
+ {
+ /* FIXME: this is a bit improper. We probably should do this only
+ when a window is first claimed. But we might be fooled if
+ an old client died without releasing it's windows. So until
+ we look for client-window closings, do it here
+
+ (We do look for closings now...)
+ */
+
+ XSelectInput(dpy,winid,EnterWindowMask|StructureNotifyMask);
+ }
+
+ for (i=0;i<num_windows;i++)
+ {
+ if (windows[i]->xwindow == winid)
+ {
+ window = windows[i];
+ break;
+ }
+ }
+
+ /* Create window structure if no devices have been previously
+ claimed on it */
+ if (!window)
+ {
+ num_windows++;
+ windows = (GxidWindow **)realloc(windows,
+ sizeof(GxidWindow*)*num_windows);
+ window = (GxidWindow *)malloc(sizeof(GxidWindow));
+ windows[num_windows-1] = window;
+
+ window->xwindow = winid;
+ window->root_child = gxi_find_root_child(dpy,winid);
+ window->num_devices = 0;
+ window->devices = 0;
+ }
+
+
+ for (i=0;i<window->num_devices;i++)
+ {
+ if (window->devices[i] == device)
+ return GXID_RETURN_OK;
+ }
+
+ window->num_devices++;
+ window->devices = (GxidDevice **)realloc(window->devices,
+ sizeof(GxidDevice*)*num_devices);
+ /* we need add the device to the window */
+ window->devices[i] = device;
+
+ return GXID_RETURN_OK;
+}
+
+int
+handle_release_device(GxidReleaseDevice *msg)
+{
+ int i,j;
+ XID devid = ntohl(msg->device);
+ XID winid = ntohl(msg->window);
+
+ GxidDevice *device = NULL;
+
+#ifdef DEBUG_CLIENTS
+ fprintf(stderr,"device %ld released (window 0x%lx)\n",devid,winid);
+#endif
+
+ for (i=0;i<num_devices;i++)
+ {
+ if (devices[i]->id == devid)
+ {
+ device = devices[i];
+ break;
+ }
+ }
+ if (!device)
+ {
+ fprintf(stderr,"%s: Unknown device id %ld\n",program_name,devid);
+ return GXID_RETURN_ERROR;
+ }
+
+ for (i=0;i<num_windows;i++)
+ {
+ GxidWindow *w = windows[i];
+
+ if (w->xwindow == winid)
+ for (j=0;j<w->num_devices;j++)
+ if (w->devices[j]->id == devid)
+ {
+ if (j<w->num_devices-1)
+ w->devices[j] = w->devices[w->num_devices-1];
+ w->num_devices--;
+
+ if (w->num_devices == 0)
+ {
+ if (i<num_windows-1)
+ windows[i] = windows[num_windows-1];
+ num_windows--;
+
+ free((void *)w);
+ /* FIXME: should we deselect input? But what
+ what if window is already destroyed */
+ }
+
+ if (device->exclusive)
+ {
+ device->exclusive = 0;
+ enable_device(device);
+ }
+ return GXID_RETURN_OK;
+ }
+ }
+
+ /* device/window combination not found */
+ fprintf(stderr,
+ "%s: Device %ld not claimed for window 0x%lx\n",
+ program_name,devid,winid);
+ return GXID_RETURN_ERROR;
+}
+
+void
+handle_connection()
+{
+ GxidMessage msg;
+ GxidU32 type;
+ int length;
+ GxidI32 retval;
+
+ int conn_fd;
+ struct sockaddr_in sin;
+ int sin_length;
+ int count;
+
+ sin_length = sizeof(struct sockaddr_in);
+ conn_fd = accept(socket_fd,(struct sockaddr *)&sin,&sin_length);
+ if (conn_fd < 0)
+ {
+ fprintf(stderr,"%s: Error accepting connection\n",
+ program_name);
+ exit(1);
+ }
+
+ /* read type and length of message */
+
+ count = read(conn_fd,(char *)&msg,2*sizeof(GxidU32));
+ if (count != 2*sizeof(GxidU32))
+ {
+ fprintf(stderr,"%s: Error reading message header\n",
+ program_name);
+ close(conn_fd);
+ return;
+ }
+ type = ntohl(msg.any.type);
+ length = ntohl(msg.any.length);
+
+ /* read rest of message */
+
+ if (length > sizeof(GxidMessage))
+ {
+ fprintf(stderr,"%s: Bad message length\n",
+ program_name);
+ close(conn_fd);
+ return;
+ }
+
+ count = read(conn_fd,2*sizeof(GxidU32) + (char *)&msg,
+ length - 2*sizeof(GxidU32));
+ if (count != length - 2*sizeof(GxidU32))
+ {
+ fprintf(stderr,"%s: Error reading message body\n",
+ program_name);
+ close(conn_fd);
+ return;
+ }
+
+ switch (type)
+ {
+ case GXID_CLAIM_DEVICE:
+ retval = handle_claim_device((GxidClaimDevice *)&msg);
+ break;
+ case GXID_RELEASE_DEVICE:
+ retval = handle_release_device((GxidReleaseDevice *)&msg);
+ break;
+ default:
+ fprintf(stderr,"%s: Unknown message type: %ld (ignoring)\n",
+ program_name,type);
+ close(conn_fd);
+ return;
+ }
+
+ count = write(conn_fd,&retval,sizeof(GxidI32));
+ if (count != sizeof(GxidI32))
+ {
+ fprintf(stderr,"%s: Error writing return code\n",
+ program_name);
+ }
+
+ close(conn_fd);
+}
+
+void
+handle_motion_notify(XDeviceMotionEvent *event)
+{
+ int i,j;
+ GxidDevice *old_device = NULL;
+ GxidDevice *new_device = NULL;
+ Window w, root, child;
+ int root_x, root_y, x, y, mask;
+
+ for (j=0;j<num_devices;j++)
+ {
+ if (devices[j]->ispointer)
+ old_device = devices[j];
+ if (devices[j]->id == event->deviceid)
+ new_device = devices[j];
+ }
+
+ if (new_device && !new_device->exclusive && !new_device->ispointer)
+ {
+ /* make sure we aren't stealing the pointer back from a slow
+ client */
+ child = root_window;
+ do
+ {
+ w = child;
+ /* FIXME: this fails disasterously if child vanishes between
+ calls. (Which is prone to happening since we get events
+ on root just as the client exits) */
+
+ XQueryPointer(dpy,w,&root,&child,&root_x,&root_y,
+ &x,&y,&mask);
+ }
+ while (child != None);
+
+ for (i=0;i<num_windows;i++)
+ if (windows[i]->xwindow == w)
+ for (j=0;j<windows[i]->num_devices;j++)
+ if (windows[i]->devices[j] == new_device)
+ return;
+
+ /* FIXME: do something smarter with axes */
+ XChangePointerDevice(dpy,new_device->xdevice, 0, 1);
+ new_device->ispointer = 1;
+
+ old_device->ispointer = 0;
+ if (!old_device->xdevice)
+ enable_device(old_device);
+ }
+}
+
+void
+handle_change_notify(XChangeDeviceNotifyEvent *event)
+{
+ int j;
+ GxidDevice *old_device = NULL;
+ GxidDevice *new_device = NULL;
+
+
+ for (j=0;j<num_devices;j++)
+ {
+ if (devices[j]->ispointer)
+ old_device = devices[j];
+ if (devices[j]->id == event->deviceid)
+ new_device = devices[j];
+ }
+
+#ifdef DEBUG_EVENTS
+ fprintf(stderr,"gxid: ChangeNotify event; old = %ld; new = %ld\n",
+ old_device->id, new_device->id);
+#endif
+
+ if (old_device != new_device)
+ {
+ new_device->ispointer = 1;
+
+ old_device->ispointer = 0;
+ if (!old_device->xdevice)
+ enable_device(old_device);
+ }
+}
+
+void
+handle_enter_notify(XEnterWindowEvent *event, GxidWindow *window)
+{
+ int i;
+ GxidDevice *old_pointer = NULL;
+ for (i=0;i<num_devices;i++)
+ {
+ if (devices[i]->ispointer)
+ {
+ old_pointer = devices[i];
+ break;
+ }
+ }
+
+#ifdef DEBUG_EVENTS
+ fprintf(stderr,"gxid: Enter event; oldpointer = %ld\n",
+ old_pointer->id);
+#endif
+
+ if (old_pointer)
+ for (i=0;i<window->num_devices;i++)
+ {
+ if (window->devices[i] == old_pointer)
+ {
+ switch_core_pointer();
+ break;
+ }
+ }
+}
+
+void
+handle_destroy_notify(XDestroyWindowEvent *event)
+{
+ int i,j;
+
+ for (i=0;i<num_windows;i++)
+ if (windows[i]->xwindow == event->window)
+ {
+ GxidWindow *w = windows[i];
+
+ for (j=0;j<w->num_devices;j++)
+ {
+#ifdef DEBUG_CLIENTS
+ fprintf(stderr,"device %ld released on destruction of window 0x%lx.\n",
+ w->devices[j]->id,w->xwindow);
+#endif
+
+ if (w->devices[j]->exclusive)
+ {
+ w->devices[j]->exclusive = 0;
+ enable_device(devices[j]);
+ }
+ }
+
+ if (i<num_windows-1)
+ windows[i] = windows[num_windows-1];
+ num_windows--;
+
+ if (w->devices)
+ free((void *)w->devices);
+ free((void *)w);
+ /* FIXME: should we deselect input? But what
+ what if window is already destroyed */
+
+ return;
+ }
+}
+
+void
+handle_xevent()
+{
+ int i;
+ XEvent event;
+
+ XNextEvent (dpy, &event);
+
+#ifdef DEBUG_EVENTS
+ fprintf(stderr,"Event - type = %d; window = 0x%lx\n",
+ event.type,event.xany.window);
+#endif
+
+ if (event.type == ConfigureNotify)
+ {
+#ifdef DEBUG_EVENTS
+ XConfigureEvent *xce = (XConfigureEvent *)&event;
+ fprintf(stderr," configureNotify: window = 0x%lx\n",xce->window);
+#endif
+ }
+ else if (event.type == EnterNotify)
+ {
+ /* pointer entered a claimed window */
+ for (i=0;i<num_windows;i++)
+ {
+ if (event.xany.window == windows[i]->xwindow)
+ handle_enter_notify((XEnterWindowEvent *)&event,windows[i]);
+ }
+ }
+ else if (event.type == DestroyNotify)
+ {
+ /* A claimed window was destroyed */
+ for (i=0;i<num_windows;i++)
+ {
+ if (event.xany.window == windows[i]->xwindow)
+ handle_destroy_notify((XDestroyWindowEvent *)&event);
+ }
+ }
+ else
+ for (i=0;i<num_devices;i++)
+ {
+ if (event.type == devices[i]->motionnotify_type)
+ {
+ handle_motion_notify((XDeviceMotionEvent *)&event);
+ break;
+ }
+ else if (event.type == devices[i]->changenotify_type)
+ {
+ handle_change_notify((XChangeDeviceNotifyEvent *)&event);
+ break;
+ }
+ }
+}
+
+void
+usage()
+{
+ fprintf(stderr,"Usage: %s [-d display] [-p --gxid-port port]\n",
+ program_name);
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ int i;
+ char *display_name = NULL;
+ fd_set readfds;
+
+ program_name = argv[0];
+
+ for (i=1;i<argc;i++)
+ {
+ if (!strcmp(argv[i],"-d"))
+ {
+ if (++i >= argc) usage();
+ display_name = argv[i];
+ }
+ else if (!strcmp(argv[i],"--gxid-port") ||
+ !strcmp(argv[i],"-p"))
+ {
+ if (++i >= argc) usage();
+ port = atoi(argv[i]);
+ break;
+ }
+ else
+ usage();
+ }
+
+ if (!port)
+ {
+ char *t = getenv("GXID_PORT");
+ if (t)
+ port = atoi(t);
+ else
+ port = 6951;
+ }
+ /* set up a signal handler so we can clean up if killed */
+
+ signal(SIGTERM,handler);
+ signal(SIGINT,handler);
+
+ /* initialize the X connection */
+
+ dpy = XOpenDisplay (display_name);
+ if (!dpy)
+ {
+ fprintf (stderr, "%s: unable to open display '%s'\n",
+ program_name, XDisplayName (display_name));
+ exit (1);
+ }
+
+ root_window = DefaultRootWindow(dpy);
+
+ /* We'll want to do this in the future if we are to support
+ gxid monitoring visibility information for clients */
+#if 0
+ XSelectInput(dpy,root_window,SubstructureNotifyMask);
+#endif
+ init_xinput();
+
+ /* set up our server connection */
+
+ init_socket();
+
+ /* main loop */
+
+ if (XPending(dpy)) /* this seems necessary to get things
+ in sync */
+ handle_xevent();
+ while (1)
+ {
+
+ FD_ZERO(&readfds);
+ FD_SET(ConnectionNumber(dpy),&readfds);
+ FD_SET(socket_fd,&readfds);
+
+ if (select(8*sizeof(readfds),&readfds,
+ (fd_set *)0,(fd_set *)0, (struct timeval *)0) < 0)
+ {
+ fprintf(stderr,"Error in select\n");
+ exit(1);
+ }
+
+ if (FD_ISSET(socket_fd,&readfds))
+ handle_connection(socket_fd);
+
+ while (XPending(dpy))
+ handle_xevent();
+ }
+
+ XCloseDisplay (dpy);
+ exit (0);
+}
diff --git a/gdk/gxid_lib.c b/gdk/gxid_lib.c
new file mode 100644
index 000000000..357b76451
--- /dev/null
+++ b/gdk/gxid_lib.c
@@ -0,0 +1,116 @@
+/*
+ * gxid version 0.3
+ *
+ * Copyright 1997 Owen Taylor <owt1@cornell.edu>
+*/
+
+#include "../config.h"
+
+#ifdef XINPUT_GXI
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include "gxid_lib.h"
+
+/* handles mechanics of communicating with a client */
+static int
+gxid_send_message(char *host, int port, GxidMessage *msg)
+{
+ int socket_fd;
+ struct sockaddr_in sin;
+ int count;
+ GxidI32 retval;
+ struct hostent *he;
+
+ if (!port) port = 6951;
+
+ if (!host || strcmp(host,"localhost") )
+ {
+ /* looking it up as localhost can be _SLOW_ on ppp systems */
+ /* FIXME: Could localhost be anything other than loopback? */
+ host = "127.0.0.1";
+ }
+
+ he = gethostbyname(host);
+ if (!he)
+ {
+ fprintf(stderr,"gxid_lib: error looking up %s\n",host);
+ return GXID_RETURN_ERROR;
+ }
+
+ sin.sin_family = he->h_addrtype;
+ sin.sin_port = htons(port);
+ memcpy(&sin.sin_addr,he->h_addr_list[0],he->h_length);
+
+ socket_fd = socket(AF_INET,SOCK_STREAM,0);
+ if (socket_fd < 0)
+ {
+ fprintf(stderr,"gxid_lib: can't get socket");
+ return GXID_RETURN_ERROR;
+ }
+
+ if (connect(socket_fd, (struct sockaddr *)&sin,
+ sizeof sin) < 0)
+ {
+ fprintf(stderr,"gxid_lib: can't connect to %s:%d\n",host,port);
+ close(socket_fd);
+ return GXID_RETURN_ERROR;
+ }
+
+ count = write(socket_fd,(char *)msg,ntohl(msg->any.length));
+ if (count != ntohl(msg->any.length))
+ {
+ fprintf(stderr,"gxid_lib: error writing");
+ close(socket_fd);
+ return GXID_RETURN_ERROR;
+ }
+
+ /* now read the return code */
+ count = read(socket_fd,(char *)&retval,sizeof(GxidI32));
+ if (count != sizeof(GxidI32))
+ {
+ fprintf(stderr,"gxid_lib: error reading return code");
+ close(socket_fd);
+ return GXID_RETURN_ERROR;
+ }
+
+ close (socket_fd);
+ return ntohl(retval);
+}
+
+/* claim a device. If exclusive, device is claimed exclusively */
+int
+gxid_claim_device(char *host, int port, GxidU32 device, GxidU32 window,
+ int exclusive)
+{
+ GxidClaimDevice msg;
+ msg.type = htonl(GXID_CLAIM_DEVICE);
+ msg.length = htonl(sizeof(GxidClaimDevice));
+ msg.device = htonl(device);
+ msg.window = htonl(window);
+ msg.exclusive = htonl(exclusive);
+
+ return gxid_send_message(host,port,(GxidMessage *)&msg);
+}
+
+/* release a device/window pair */
+int
+gxid_release_device(char *host, int port, GxidU32 device, GxidU32 window)
+{
+ GxidReleaseDevice msg;
+ msg.type = htonl(GXID_RELEASE_DEVICE);
+ msg.length = htonl(sizeof(GxidReleaseDevice));
+ msg.device = htonl(device);
+ msg.window = htonl(window);
+
+ return gxid_send_message(host,port,(GxidMessage *)&msg);
+}
+
+#endif /* XINPUT_GXI */
+
diff --git a/gdk/gxid_lib.h b/gdk/gxid_lib.h
new file mode 100644
index 000000000..6a7103bbe
--- /dev/null
+++ b/gdk/gxid_lib.h
@@ -0,0 +1,6 @@
+#include "gxid_proto.h"
+
+int gxid_claim_device(char *host, int port,
+ GxidU32 device, GxidU32 window, int exclusive);
+int gxid_release_device(char *host, int port, GxidU32 device,
+ GxidU32 window);
diff --git a/gdk/gxid_proto.h b/gdk/gxid_proto.h
new file mode 100644
index 000000000..24959b806
--- /dev/null
+++ b/gdk/gxid_proto.h
@@ -0,0 +1,39 @@
+#define GXID_CLAIM_DEVICE 1
+#define GXID_RELEASE_DEVICE 2
+
+#define GXID_RETURN_OK 0
+#define GXID_RETURN_ERROR -1
+
+typedef struct GxidClaimDevice_ GxidClaimDevice;
+typedef struct GxidReleaseDevice_ GxidReleaseDevice;
+typedef struct GxidMessageAny_ GxidMessageAny;
+typedef union GxidMessage_ GxidMessage;
+
+typedef unsigned long GxidU32;
+typedef long GxidI32;
+
+struct GxidClaimDevice_ {
+ GxidU32 type;
+ GxidU32 length;
+ GxidU32 device;
+ GxidU32 window;
+ GxidU32 exclusive;
+};
+
+struct GxidReleaseDevice_ {
+ GxidU32 type;
+ GxidU32 length;
+ GxidU32 device;
+ GxidU32 window;
+};
+
+struct GxidMessageAny_ {
+ GxidU32 type;
+ GxidU32 length;
+};
+
+union GxidMessage_ {
+ GxidMessageAny any;
+ GxidClaimDevice claim;
+ GxidReleaseDevice release;
+};
diff --git a/gdk/makecursors b/gdk/makecursors
new file mode 100755
index 000000000..664776a2b
--- /dev/null
+++ b/gdk/makecursors
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+sed -f makecursors.sed $1 > .makecursors.tmp
+awk '{printf "%s = %s,\n", $1, $2}' .makecursors.tmp
+rm .makecursors.tmp
diff --git a/gdk/makecursors.sed b/gdk/makecursors.sed
new file mode 100644
index 000000000..107d13f8d
--- /dev/null
+++ b/gdk/makecursors.sed
@@ -0,0 +1,3 @@
+/define/ ! d
+/define/ y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
+s/^.*XC_/GDK_/g
diff --git a/gdk/makekeysyms b/gdk/makekeysyms
new file mode 100755
index 000000000..40b49d4e8
--- /dev/null
+++ b/gdk/makekeysyms
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+sed -f makekeysyms.sed $1 > .makekeysms.tmp
+awk '{printf "#define %s %s\n", $1, $2}' .makekeysms.tmp
+rm .makekeysms.tmp
diff --git a/gdk/makekeysyms.sed b/gdk/makekeysyms.sed
new file mode 100644
index 000000000..bafbf76c0
--- /dev/null
+++ b/gdk/makekeysyms.sed
@@ -0,0 +1,3 @@
+/define/ ! d
+s/^.*XK_/GDK_/g
+s/0X/0x/g
diff --git a/gdk/x11/gdkcolor-x11.c b/gdk/x11/gdkcolor-x11.c
new file mode 100644
index 000000000..5e66f089b
--- /dev/null
+++ b/gdk/x11/gdkcolor-x11.c
@@ -0,0 +1,718 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <X11/Xlib.h>
+#include "gdk.h"
+#include "gdkprivate.h"
+
+
+static gint gdk_colormap_match_color (GdkColormap *cmap,
+ GdkColor *color,
+ const gchar *available);
+static void gdk_colormap_add (GdkColormap *cmap);
+static void gdk_colormap_remove (GdkColormap *cmap);
+static guint gdk_colormap_hash (Colormap *cmap);
+static gint gdk_colormap_cmp (Colormap *a,
+ Colormap *b);
+
+static GHashTable *colormap_hash = NULL;
+
+
+GdkColormap*
+gdk_colormap_new (GdkVisual *visual,
+ gint private_cmap)
+{
+ GdkColormap *colormap;
+ GdkColormapPrivate *private;
+ Visual *xvisual;
+ XColor default_colors[256];
+ int size;
+ int i;
+
+ g_return_val_if_fail (visual != NULL, NULL);
+
+ private = g_new (GdkColormapPrivate, 1);
+ colormap = (GdkColormap*) private;
+
+ private->xdisplay = gdk_display;
+ private->visual = visual;
+ private->next_color = 0;
+ private->ref_count = 1;
+ xvisual = ((GdkVisualPrivate*) visual)->xvisual;
+
+ switch (visual->type)
+ {
+ case GDK_VISUAL_GRAYSCALE:
+ case GDK_VISUAL_PSEUDO_COLOR:
+ private->private_val = private_cmap;
+ private->xcolormap = XCreateColormap (private->xdisplay, gdk_root_window,
+ xvisual, (private_cmap) ? (AllocAll) : (AllocNone));
+
+ if (private_cmap)
+ {
+ for (i = 0; i < 256; i++)
+ default_colors[i].pixel = i;
+
+ XQueryColors (private->xdisplay,
+ DefaultColormap (private->xdisplay, gdk_screen),
+ default_colors, visual->colormap_size);
+
+ for (i = 0; i < visual->colormap_size; i++)
+ {
+ colormap->colors[i].pixel = default_colors[i].pixel;
+ colormap->colors[i].red = default_colors[i].red;
+ colormap->colors[i].green = default_colors[i].green;
+ colormap->colors[i].blue = default_colors[i].blue;
+ }
+
+ gdk_colormap_change (colormap, visual->colormap_size);
+ }
+ break;
+
+ case GDK_VISUAL_DIRECT_COLOR:
+ private->private_val = TRUE;
+ private->xcolormap = XCreateColormap (private->xdisplay, gdk_root_window,
+ xvisual, AllocAll);
+
+ size = 1 << visual->red_prec;
+ for (i = 0; i < size; i++)
+ colormap->colors[i].red = i * 65535 / (size - 1);
+
+ size = 1 << visual->green_prec;
+ for (i = 0; i < size; i++)
+ colormap->colors[i].green = i * 65535 / (size - 1);
+
+ size = 1 << visual->blue_prec;
+ for (i = 0; i < size; i++)
+ colormap->colors[i].blue = i * 65535 / (size - 1);
+
+ gdk_colormap_change (colormap, visual->colormap_size);
+ break;
+
+ case GDK_VISUAL_STATIC_GRAY:
+ case GDK_VISUAL_STATIC_COLOR:
+ case GDK_VISUAL_TRUE_COLOR:
+ private->private_val = FALSE;
+ private->xcolormap = XCreateColormap (private->xdisplay, gdk_root_window,
+ xvisual, AllocNone);
+ break;
+ }
+
+ gdk_colormap_add (colormap);
+
+ return colormap;
+}
+
+void
+gdk_colormap_real_destroy (GdkColormap *colormap)
+{
+ GdkColormapPrivate *private = (GdkColormapPrivate*) colormap;
+
+ g_return_if_fail (colormap != NULL);
+
+ if (private->ref_count > 0)
+ return;
+
+ gdk_colormap_remove (colormap);
+ XFreeColormap (private->xdisplay, private->xcolormap);
+ g_free (colormap);
+}
+
+void
+gdk_colormap_destroy (GdkColormap *colormap)
+{
+ gdk_colormap_unref (colormap);
+}
+
+GdkColormap*
+gdk_colormap_ref (GdkColormap *cmap)
+{
+ GdkColormapPrivate *private = (GdkColormapPrivate *)cmap;
+ g_return_val_if_fail (cmap != NULL, NULL);
+
+ private->ref_count += 1;
+ return cmap;
+}
+
+void
+gdk_colormap_unref (GdkColormap *cmap)
+{
+ GdkColormapPrivate *private = (GdkColormapPrivate *)cmap;
+ g_return_if_fail (cmap != NULL);
+
+ private->ref_count -= 1;
+ if (private->ref_count == 0)
+ gdk_colormap_real_destroy (cmap);
+}
+
+GdkColormap*
+gdk_colormap_get_system (void)
+{
+ static GdkColormap *colormap = NULL;
+ GdkColormapPrivate *private;
+ XColor xpalette[256];
+ gint i;
+
+ if (!colormap)
+ {
+ private = g_new (GdkColormapPrivate, 1);
+ colormap = (GdkColormap*) private;
+
+ private->xdisplay = gdk_display;
+ private->xcolormap = DefaultColormap (gdk_display, gdk_screen);
+ private->visual = gdk_visual_get_system ();
+ private->private_val = FALSE;
+ private->next_color = 0;
+ private->ref_count = 1;
+
+ for (i = 0; i < 256; i++)
+ {
+ xpalette[i].pixel = i;
+ xpalette[i].red = 0;
+ xpalette[i].green = 0;
+ xpalette[i].blue = 0;
+ }
+
+ XQueryColors (gdk_display, private->xcolormap, xpalette, 256);
+
+ for (i = 0; i < 256; i++)
+ {
+ colormap->colors[i].pixel = xpalette[i].pixel;
+ colormap->colors[i].red = xpalette[i].red;
+ colormap->colors[i].green = xpalette[i].green;
+ colormap->colors[i].blue = xpalette[i].blue;
+ }
+
+ gdk_colormap_add (colormap);
+ }
+
+ return colormap;
+}
+
+gint
+gdk_colormap_get_system_size (void)
+{
+ return DisplayCells (gdk_display, gdk_screen);
+}
+
+void
+gdk_colormap_change (GdkColormap *colormap,
+ gint ncolors)
+{
+ GdkColormapPrivate *private;
+ GdkVisual *visual;
+ XColor palette[256];
+ gint shift;
+ int max_colors;
+ int size;
+ int i;
+
+ g_return_if_fail (colormap != NULL);
+
+ private = (GdkColormapPrivate*) colormap;
+ switch (private->visual->type)
+ {
+ case GDK_VISUAL_GRAYSCALE:
+ case GDK_VISUAL_PSEUDO_COLOR:
+ for (i = 0; i < ncolors; i++)
+ {
+ palette[i].pixel = colormap->colors[i].pixel;
+ palette[i].red = colormap->colors[i].red;
+ palette[i].green = colormap->colors[i].green;
+ palette[i].blue = colormap->colors[i].blue;
+ palette[i].flags = DoRed | DoGreen | DoBlue;
+ }
+
+ XStoreColors (private->xdisplay, private->xcolormap, palette, ncolors);
+ private->next_color = MAX (private->next_color, ncolors);
+ break;
+
+ case GDK_VISUAL_DIRECT_COLOR:
+ visual = private->visual;
+
+ shift = visual->red_shift;
+ max_colors = 1 << visual->red_prec;
+ size = (ncolors < max_colors) ? (ncolors) : (max_colors);
+
+ for (i = 0; i < size; i++)
+ {
+ palette[i].pixel = i << shift;
+ palette[i].red = colormap->colors[i].red;
+ palette[i].flags = DoRed;
+ }
+
+ XStoreColors (private->xdisplay, private->xcolormap, palette, size);
+
+ shift = visual->green_shift;
+ max_colors = 1 << visual->green_prec;
+ size = (ncolors < max_colors) ? (ncolors) : (max_colors);
+
+ for (i = 0; i < size; i++)
+ {
+ palette[i].pixel = i << shift;
+ palette[i].green = colormap->colors[i].green;
+ palette[i].flags = DoGreen;
+ }
+
+ XStoreColors (private->xdisplay, private->xcolormap, palette, size);
+
+ shift = visual->blue_shift;
+ max_colors = 1 << visual->blue_prec;
+ size = (ncolors < max_colors) ? (ncolors) : (max_colors);
+
+ for (i = 0; i < size; i++)
+ {
+ palette[i].pixel = i << shift;
+ palette[i].blue = colormap->colors[i].blue;
+ palette[i].flags = DoBlue;
+ }
+
+ XStoreColors (private->xdisplay, private->xcolormap, palette, size);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void
+gdk_colors_store (GdkColormap *colormap,
+ GdkColor *colors,
+ gint ncolors)
+{
+ gint i;
+
+ for (i = 0; i < ncolors; i++)
+ {
+ colormap->colors[i].pixel = colors[i].pixel;
+ colormap->colors[i].red = colors[i].red;
+ colormap->colors[i].green = colors[i].green;
+ colormap->colors[i].blue = colors[i].blue;
+ }
+
+ gdk_colormap_change (colormap, ncolors);
+}
+
+gint
+gdk_colors_alloc (GdkColormap *colormap,
+ gint contiguous,
+ gulong *planes,
+ gint nplanes,
+ gulong *pixels,
+ gint npixels)
+{
+ GdkColormapPrivate *private;
+ gint return_val;
+
+ g_return_val_if_fail (colormap != NULL, 0);
+
+ private = (GdkColormapPrivate*) colormap;
+
+ return_val = XAllocColorCells (private->xdisplay, private->xcolormap,
+ contiguous, planes, nplanes, pixels, npixels);
+
+ return return_val;
+}
+
+void
+gdk_colors_free (GdkColormap *colormap,
+ gulong *pixels,
+ gint npixels,
+ gulong planes)
+{
+ GdkColormapPrivate *private;
+
+ g_return_if_fail (colormap != NULL);
+
+ private = (GdkColormapPrivate*) colormap;
+
+ XFreeColors (private->xdisplay, private->xcolormap,
+ pixels, npixels, planes);
+}
+
+gint
+gdk_color_white (GdkColormap *colormap,
+ GdkColor *color)
+{
+ gint return_val;
+
+ g_return_val_if_fail (colormap != NULL, FALSE);
+
+ if (color)
+ {
+ color->pixel = WhitePixel (gdk_display, gdk_screen);
+ color->red = 65535;
+ color->green = 65535;
+ color->blue = 65535;
+
+ return_val = gdk_color_alloc (colormap, color);
+ }
+ else
+ return_val = FALSE;
+
+ return return_val;
+}
+
+gint
+gdk_color_black (GdkColormap *colormap,
+ GdkColor *color)
+{
+ gint return_val;
+
+ g_return_val_if_fail (colormap != NULL, FALSE);
+
+ if (color)
+ {
+ color->pixel = BlackPixel (gdk_display, gdk_screen);
+ color->red = 0;
+ color->green = 0;
+ color->blue = 0;
+
+ return_val = gdk_color_alloc (colormap, color);
+ }
+ else
+ return_val = FALSE;
+
+ return return_val;
+}
+
+gint
+gdk_color_parse (const gchar *spec,
+ GdkColor *color)
+{
+ Colormap xcolormap;
+ XColor xcolor;
+ gint return_val;
+
+ g_return_val_if_fail (spec != NULL, FALSE);
+ g_return_val_if_fail (color != NULL, FALSE);
+
+ xcolormap = DefaultColormap (gdk_display, gdk_screen);
+
+ if (XParseColor (gdk_display, xcolormap, spec, &xcolor))
+ {
+ return_val = TRUE;
+ color->red = xcolor.red;
+ color->green = xcolor.green;
+ color->blue = xcolor.blue;
+ }
+ else
+ return_val = FALSE;
+
+ return return_val;
+}
+
+gint
+gdk_color_alloc (GdkColormap *colormap,
+ GdkColor *color)
+{
+ GdkColormapPrivate *private;
+ GdkVisual *visual;
+ XColor xcolor;
+ gchar available[256];
+ gint available_init;
+ gint return_val;
+ gint i, index;
+
+ g_return_val_if_fail (colormap != NULL, FALSE);
+ g_return_val_if_fail (color != NULL, FALSE);
+
+ xcolor.red = color->red;
+ xcolor.green = color->green;
+ xcolor.blue = color->blue;
+ xcolor.pixel = color->pixel;
+ xcolor.flags = DoRed | DoGreen | DoBlue;
+
+ return_val = FALSE;
+ private = (GdkColormapPrivate*) colormap;
+
+ switch (private->visual->type)
+ {
+ case GDK_VISUAL_GRAYSCALE:
+ case GDK_VISUAL_PSEUDO_COLOR:
+ if (private->private_val)
+ {
+ if (private->next_color > 255)
+ {
+ for (i = 0; i < 256; i++)
+ available[i] = TRUE;
+
+ index = gdk_colormap_match_color (colormap, color, available);
+ if (index != -1)
+ {
+ available[index] = FALSE;
+ *color = colormap->colors[index];
+ return_val = TRUE;
+ }
+ else
+ {
+ return_val = FALSE;
+ }
+ }
+ else
+ {
+ xcolor.pixel = 255 - private->next_color;
+ color->pixel = xcolor.pixel;
+ private->next_color += 1;
+
+ XStoreColor (private->xdisplay, private->xcolormap, &xcolor);
+ return_val = TRUE;
+ }
+ }
+ else
+ {
+ available_init = 1;
+
+ while (1)
+ {
+ if (XAllocColor (private->xdisplay, private->xcolormap, &xcolor))
+ {
+ color->pixel = xcolor.pixel;
+ color->red = xcolor.red;
+ color->green = xcolor.green;
+ color->blue = xcolor.blue;
+
+ colormap->colors[color->pixel] = *color;
+
+ return_val = TRUE;
+ break;
+ }
+ else
+ {
+ if (available_init)
+ {
+ available_init = 0;
+ for (i = 0; i < 256; i++)
+ available[i] = TRUE;
+ }
+
+ index = gdk_colormap_match_color (colormap, color, available);
+ if (index != -1)
+ {
+ available[index] = FALSE;
+ xcolor.red = colormap->colors[index].red;
+ xcolor.green = colormap->colors[index].green;
+ xcolor.blue = colormap->colors[index].blue;
+ }
+ else
+ {
+ return_val = FALSE;
+ break;
+ }
+ }
+ }
+ }
+ break;
+
+ case GDK_VISUAL_DIRECT_COLOR:
+ visual = private->visual;
+ xcolor.pixel = (((xcolor.red >> (16 - visual->red_prec)) << visual->red_shift) +
+ ((xcolor.green >> (16 - visual->green_prec)) << visual->green_shift) +
+ ((xcolor.blue >> (16 - visual->blue_prec)) << visual->blue_shift));
+ color->pixel = xcolor.pixel;
+ return_val = TRUE;
+ break;
+
+ case GDK_VISUAL_STATIC_GRAY:
+ case GDK_VISUAL_STATIC_COLOR:
+ case GDK_VISUAL_TRUE_COLOR:
+ if (XAllocColor (private->xdisplay, private->xcolormap, &xcolor))
+ {
+ color->pixel = xcolor.pixel;
+ return_val = TRUE;
+ }
+ else
+ return_val = FALSE;
+ break;
+ }
+
+ return return_val;
+}
+
+gint
+gdk_color_change (GdkColormap *colormap,
+ GdkColor *color)
+{
+ GdkColormapPrivate *private;
+ XColor xcolor;
+
+ g_return_val_if_fail (colormap != NULL, FALSE);
+ g_return_val_if_fail (color != NULL, FALSE);
+
+ xcolor.pixel = color->pixel;
+ xcolor.red = color->red;
+ xcolor.green = color->green;
+ xcolor.blue = color->blue;
+ xcolor.flags = DoRed | DoGreen | DoBlue;
+
+ private = (GdkColormapPrivate*) colormap;
+ XStoreColor (private->xdisplay, private->xcolormap, &xcolor);
+
+ return TRUE;
+}
+
+gint
+gdk_color_equal (GdkColor *colora,
+ GdkColor *colorb)
+{
+ g_return_val_if_fail (colora != NULL, FALSE);
+ g_return_val_if_fail (colorb != NULL, FALSE);
+
+ return ((colora->red == colorb->red) &&
+ (colora->green == colorb->green) &&
+ (colora->blue == colorb->blue));
+}
+
+GdkColormap*
+gdkx_colormap_get (Colormap xcolormap)
+{
+ GdkColormap *colormap;
+ GdkColormapPrivate *private;
+ XColor xpalette[256];
+ gint i;
+
+ colormap = gdk_colormap_lookup (xcolormap);
+ if (colormap)
+ return colormap;
+
+ if (xcolormap == DefaultColormap (gdk_display, gdk_screen))
+ return gdk_colormap_get_system ();
+
+ private = g_new (GdkColormapPrivate, 1);
+ colormap = (GdkColormap*) private;
+
+ private->xdisplay = gdk_display;
+ private->xcolormap = xcolormap;
+ private->visual = NULL;
+ private->private_val = TRUE;
+ private->next_color = 0;
+
+ for (i = 0; i < 256; i++)
+ {
+ xpalette[i].pixel = i;
+ xpalette[i].red = 0;
+ xpalette[i].green = 0;
+ xpalette[i].blue = 0;
+ }
+
+ XQueryColors (gdk_display, private->xcolormap, xpalette, 256);
+
+ for (i = 0; i < 256; i++)
+ {
+ colormap->colors[i].pixel = xpalette[i].pixel;
+ colormap->colors[i].red = xpalette[i].red;
+ colormap->colors[i].green = xpalette[i].green;
+ colormap->colors[i].blue = xpalette[i].blue;
+ }
+
+ gdk_colormap_add (colormap);
+
+ return colormap;
+}
+
+
+static gint
+gdk_colormap_match_color (GdkColormap *cmap,
+ GdkColor *color,
+ const gchar *available)
+{
+ GdkColor *colors;
+ guint sum, max;
+ gint rdiff, gdiff, bdiff;
+ gint i, index;
+
+ g_return_val_if_fail (cmap != NULL, 0);
+ g_return_val_if_fail (color != NULL, 0);
+
+ colors = cmap->colors;
+ max = 3 * (65536);
+ index = -1;
+
+ for (i = 0; i < 256; i++)
+ {
+ if ((!available) || (available && available[i]))
+ {
+ rdiff = (color->red - colors[i].red);
+ gdiff = (color->green - colors[i].green);
+ bdiff = (color->blue - colors[i].blue);
+
+ sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
+
+ if (sum < max)
+ {
+ index = i;
+ max = sum;
+ }
+ }
+ }
+
+ return index;
+}
+
+
+GdkColormap*
+gdk_colormap_lookup (Colormap xcolormap)
+{
+ GdkColormap *cmap;
+
+ if (!colormap_hash)
+ return NULL;
+
+ cmap = g_hash_table_lookup (colormap_hash, &xcolormap);
+ return cmap;
+}
+
+static void
+gdk_colormap_add (GdkColormap *cmap)
+{
+ GdkColormapPrivate *private;
+
+ if (!colormap_hash)
+ colormap_hash = g_hash_table_new ((GHashFunc) gdk_colormap_hash,
+ (GCompareFunc) gdk_colormap_cmp);
+
+ private = (GdkColormapPrivate*) cmap;
+
+ g_hash_table_insert (colormap_hash, &private->xcolormap, cmap);
+}
+
+static void
+gdk_colormap_remove (GdkColormap *cmap)
+{
+ GdkColormapPrivate *private;
+
+ if (!colormap_hash)
+ colormap_hash = g_hash_table_new ((GHashFunc) gdk_colormap_hash,
+ (GCompareFunc) gdk_colormap_cmp);
+
+ private = (GdkColormapPrivate*) cmap;
+
+ g_hash_table_remove (colormap_hash, &private->xcolormap);
+}
+
+static guint
+gdk_colormap_hash (Colormap *cmap)
+{
+ return *cmap;
+}
+
+static gint
+gdk_colormap_cmp (Colormap *a,
+ Colormap *b)
+{
+ return (*a == *b);
+}
diff --git a/gdk/x11/gdkcursor-x11.c b/gdk/x11/gdkcursor-x11.c
new file mode 100644
index 000000000..22bfd250b
--- /dev/null
+++ b/gdk/x11/gdkcursor-x11.c
@@ -0,0 +1,52 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <X11/Xlib.h>
+#include <X11/cursorfont.h>
+#include "gdk.h"
+#include "gdkprivate.h"
+
+
+GdkCursor*
+gdk_cursor_new (GdkCursorType cursor_type)
+{
+ GdkCursorPrivate *private;
+ GdkCursor *cursor;
+ Cursor xcursor;
+
+ xcursor = XCreateFontCursor (gdk_display, cursor_type);
+ private = g_new (GdkCursorPrivate, 1);
+ private->xdisplay = gdk_display;
+ private->xcursor = xcursor;
+ cursor = (GdkCursor*) private;
+ cursor->type = cursor_type;
+
+ return cursor;
+}
+
+void
+gdk_cursor_destroy (GdkCursor *cursor)
+{
+ GdkCursorPrivate *private;
+
+ g_return_if_fail (cursor != NULL);
+
+ private = (GdkCursorPrivate *) cursor;
+ XFreeCursor (private->xdisplay, private->xcursor);
+
+ g_free (private);
+}
diff --git a/gdk/x11/gdkfont-x11.c b/gdk/x11/gdkfont-x11.c
new file mode 100644
index 000000000..e1b1e7254
--- /dev/null
+++ b/gdk/x11/gdkfont-x11.c
@@ -0,0 +1,379 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <X11/Xlib.h>
+#include <X11/Xos.h>
+#include "gdk.h"
+#include "gdkprivate.h"
+
+GdkFont*
+gdk_font_load (const gchar *font_name)
+{
+ GdkFont *font;
+ GdkFontPrivate *private;
+
+ private = g_new (GdkFontPrivate, 1);
+ font = (GdkFont*) private;
+
+ private->xdisplay = gdk_display;
+ private->xfont = XLoadQueryFont (private->xdisplay, font_name);
+ private->ref_count = 1;
+
+ if (!private->xfont)
+ {
+ g_free (font);
+ return NULL;
+ }
+ else
+ {
+ font->type = GDK_FONT_FONT;
+ font->ascent = ((XFontStruct *) private->xfont)->ascent;
+ font->descent = ((XFontStruct *) private->xfont)->descent;
+ }
+
+ gdk_xid_table_insert (&((XFontStruct *) private->xfont)->fid, font);
+
+ return font;
+}
+
+GdkFont*
+gdk_fontset_load(gchar *fontset_name)
+{
+ GdkFont *font;
+ GdkFontPrivate *private;
+ XFontSet fontset;
+ gint missing_charset_count;
+ gchar **missing_charset_list;
+ gchar *def_string;
+
+ private = g_new (GdkFontPrivate, 1);
+ font = (GdkFont*) private;
+
+ private->xdisplay = gdk_display;
+ fontset = XCreateFontSet (gdk_display, fontset_name,
+ &missing_charset_list, &missing_charset_count,
+ &def_string);
+
+ if (missing_charset_count)
+ {
+ g_print ("Missing charsets in FontSet creation");
+ XFreeStringList (missing_charset_list);
+ }
+
+ private->ref_count = 1;
+
+ if (!fontset)
+ {
+ g_free (font);
+ return NULL;
+ }
+ else
+ {
+ XFontSetExtents *extent = XExtentsOfFontSet(fontset);
+
+ private->xfont = fontset;
+ font->type = GDK_FONT_FONTSET;
+ /* how to define ascent and descent for fontset ??? */
+ font->ascent = extent->max_logical_extent.height;
+ font->descent = font->ascent / 4 ;
+ }
+ return font;
+}
+void
+gdk_font_free (GdkFont *font)
+{
+ GdkFontPrivate *private;
+
+ g_return_if_fail (font != NULL);
+
+ private = (GdkFontPrivate*) font;
+
+ private->ref_count -= 1;
+ if (private->ref_count == 0)
+ {
+ gdk_xid_table_remove (((XFontStruct *) private->xfont)->fid);
+ XFreeFont (private->xdisplay, (XFontStruct *) private->xfont);
+ g_free (font);
+ }
+}
+
+void
+gdk_fontset_free (GdkFont *font)
+{
+ GdkFontPrivate *private;
+
+ g_return_if_fail (font != NULL);
+
+ private = (GdkFontPrivate*) font;
+
+ private->ref_count -= 1;
+ if (private->ref_count == 0)
+ {
+ XFreeFontSet (private->xdisplay, (XFontSet) private->xfont);
+ g_free (font);
+ }
+}
+
+GdkFont*
+gdk_font_ref (GdkFont *font)
+{
+ GdkFontPrivate *private;
+
+ g_return_val_if_fail (font != NULL, NULL);
+
+ private = (GdkFontPrivate*) font;
+ private->ref_count += 1;
+ return font;
+}
+
+gint
+gdk_font_id (GdkFont *font)
+{
+ GdkFontPrivate *font_private;
+
+ g_return_val_if_fail (font != NULL, 0);
+
+ font_private = (GdkFontPrivate*) font;
+
+ if (font->type == GDK_FONT_FONT)
+ {
+ return ((XFontStruct *) font_private->xfont)->fid;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+gint
+gdk_font_equal (GdkFont *fonta,
+ GdkFont *fontb)
+{
+ GdkFontPrivate *privatea;
+ GdkFontPrivate *privateb;
+
+ g_return_val_if_fail (fonta != NULL, FALSE);
+ g_return_val_if_fail (fontb != NULL, FALSE);
+
+ privatea = (GdkFontPrivate*) fonta;
+ privateb = (GdkFontPrivate*) fontb;
+
+ if (fonta->type == GDK_FONT_FONT && fontb->type == GDK_FONT_FONT)
+ {
+ return (((XFontStruct *) privatea->xfont)->fid ==
+ ((XFontStruct *) privateb->xfont)->fid);
+ }
+ else if (fonta->type == GDK_FONT_FONTSET && fontb->type == GDK_FONT_FONTSET)
+ {
+ /* how to compare two fontsets ?? by basename or XFontSet ?? */
+ return (((XFontSet) privatea->xfont) == ((XFontSet) privateb->xfont));
+ }
+ else
+ /* fontset != font */
+ return 0;
+}
+
+gint
+gdk_string_width (GdkFont *font,
+ const gchar *string)
+{
+ GdkFontPrivate *font_private;
+ gint width;
+ XFontStruct *xfont;
+ XFontSet fontset;
+
+ g_return_val_if_fail (font != NULL, -1);
+ g_return_val_if_fail (string != NULL, -1);
+
+ font_private = (GdkFontPrivate*) font;
+
+ switch (font->type)
+ {
+ case GDK_FONT_FONT:
+ xfont = (XFontStruct *) font_private->xfont;
+ if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
+ {
+ width = XTextWidth (xfont, string, strlen (string));
+ }
+ else
+ {
+ width = XTextWidth16 (xfont, (XChar2b *) string, strlen (string) / 2);
+ }
+ break;
+ case GDK_FONT_FONTSET:
+ fontset = (XFontSet) font_private->xfont;
+ width = XmbTextEscapement (fontset, string, strlen(string));
+ break;
+ default:
+ width = 0;
+ }
+
+ return width;
+}
+
+gint
+gdk_text_width (GdkFont *font,
+ const gchar *text,
+ gint text_length)
+{
+ GdkFontPrivate *private;
+ gint width;
+ XFontStruct *xfont;
+ XFontSet fontset;
+
+ g_return_val_if_fail (font != NULL, -1);
+ g_return_val_if_fail (text != NULL, -1);
+
+ private = (GdkFontPrivate*) font;
+
+ switch (font->type)
+ {
+ case GDK_FONT_FONT:
+ xfont = (XFontStruct *) private->xfont;
+ if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
+ {
+ width = XTextWidth (xfont, text, text_length);
+ }
+ else
+ {
+ width = XTextWidth16 (xfont, (XChar2b *) text, text_length / 2);
+ }
+ break;
+ case GDK_FONT_FONTSET:
+ fontset = (XFontSet) private->xfont;
+ width = XmbTextEscapement (fontset, text, text_length);
+ break;
+ default:
+ width = 0;
+ }
+ return width;
+}
+
+/* Problem: What if a character is a 16 bits character ?? */
+gint
+gdk_char_width (GdkFont *font,
+ gchar character)
+{
+ GdkFontPrivate *private;
+ XCharStruct *chars;
+ gint width;
+ guint ch = character & 0xff; /* get rid of sign-extension */
+ XFontStruct *xfont;
+ XFontSet fontset;
+
+ g_return_val_if_fail (font != NULL, -1);
+
+ private = (GdkFontPrivate*) font;
+
+ switch (font->type)
+ {
+ case GDK_FONT_FONT:
+ /* only 8 bits characters are considered here */
+ xfont = (XFontStruct *) private->xfont;
+ if ((xfont->min_byte1 == 0) &&
+ (xfont->max_byte1 == 0) &&
+ (ch >= xfont->min_char_or_byte2) &&
+ (ch <= xfont->max_char_or_byte2))
+ {
+ chars = xfont->per_char;
+ if (chars)
+ width = chars[ch - xfont->min_char_or_byte2].width;
+ else
+ width = xfont->min_bounds.width;
+ }
+ else
+ {
+ width = XTextWidth (xfont, &character, 1);
+ }
+ break;
+ case GDK_FONT_FONTSET:
+ fontset = (XFontSet) private->xfont;
+ width = XmbTextEscapement (fontset, &character, 1) ;
+ break;
+ default:
+ width = 0;
+ }
+ return width;
+}
+
+gint
+gdk_string_measure (GdkFont *font,
+ const gchar *string)
+{
+ g_return_val_if_fail (font != NULL, -1);
+ g_return_val_if_fail (string != NULL, -1);
+
+ return gdk_text_measure (font, string, strlen (string));
+}
+
+gint
+gdk_text_measure (GdkFont *font,
+ const gchar *text,
+ gint text_length)
+{
+ GdkFontPrivate *private;
+ XCharStruct overall;
+ XFontStruct *xfont;
+ XFontSet fontset;
+ XRectangle ink, log;
+ int direction;
+ int font_ascent;
+ int font_descent;
+ gint width;
+
+ g_return_val_if_fail (font != NULL, -1);
+ g_return_val_if_fail (text != NULL, -1);
+
+ private = (GdkFontPrivate*) font;
+
+ switch (font->type)
+ {
+ case GDK_FONT_FONT:
+ xfont = (XFontStruct *) private->xfont;
+ if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
+ {
+ XTextExtents (xfont, text, text_length,
+ &direction, &font_ascent, &font_descent,
+ &overall);
+ }
+ else
+ {
+ XTextExtents16 (xfont, (XChar2b *) text, text_length / 2,
+ &direction, &font_ascent, &font_descent,
+ &overall);
+ }
+ width = overall.rbearing;
+ break;
+ case GDK_FONT_FONTSET:
+ fontset = (XFontSet) private->xfont;
+ XmbTextExtents (fontset, text, text_length, &ink, &log);
+ width = log.width;
+ break;
+ default:
+ width = 0;
+ }
+ return width;
+}
+
+gint
+gdk_char_measure (GdkFont *font,
+ gchar character)
+{
+ g_return_val_if_fail (font != NULL, -1);
+
+ return gdk_text_measure (font, &character, 1);
+}
diff --git a/gdk/x11/gdkglobals-x11.c b/gdk/x11/gdkglobals-x11.c
new file mode 100644
index 000000000..58f7bf844
--- /dev/null
+++ b/gdk/x11/gdkglobals-x11.c
@@ -0,0 +1,47 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include "gdktypes.h"
+#include "gdkprivate.h"
+
+gint gdk_debug_level = 0;
+gint gdk_show_events = FALSE;
+gint gdk_use_xshm = TRUE;
+gchar *gdk_display_name = NULL;
+Display *gdk_display = NULL;
+gint gdk_screen;
+Window gdk_root_window;
+Window gdk_leader_window;
+GdkWindowPrivate gdk_root_parent;
+Atom gdk_wm_delete_window;
+Atom gdk_wm_take_focus;
+Atom gdk_wm_protocols;
+Atom gdk_wm_window_protocols[2];
+Atom gdk_selection_property;
+GdkDndGlobals gdk_dnd = {None,None,None,
+ None,None,None,
+ None,
+ None,None,
+ NULL,
+ 0, 0,
+ {0,0}};
+gchar *gdk_progname = NULL;
+gchar *gdk_progclass = NULL;
+gint gdk_error_code;
+gint gdk_error_warnings = TRUE;
diff --git a/gdk/x11/gdkimage-x11.c b/gdk/x11/gdkimage-x11.c
new file mode 100644
index 000000000..bcda3119f
--- /dev/null
+++ b/gdk/x11/gdkimage-x11.c
@@ -0,0 +1,492 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "../config.h"
+
+#include <sys/types.h>
+
+#if defined (HAVE_IPC_H) && defined (HAVE_SHM_H) && defined (HAVE_XSHM_H)
+#define USE_SHM
+#endif
+
+#ifdef USE_SHM
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#endif /* USE_SHM */
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#ifdef USE_SHM
+#include <X11/extensions/XShm.h>
+#endif /* USE_SHM */
+
+#include "gdk.h"
+#include "gdkprivate.h"
+
+
+static void gdk_image_put_normal (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkImage *image,
+ gint xsrc,
+ gint ysrc,
+ gint xdest,
+ gint ydest,
+ gint width,
+ gint height);
+static void gdk_image_put_shared (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkImage *image,
+ gint xsrc,
+ gint ysrc,
+ gint xdest,
+ gint ydest,
+ gint width,
+ gint height);
+
+
+static GList *image_list = NULL;
+
+
+void
+gdk_image_exit ()
+{
+ GdkImage *image;
+
+ while (image_list)
+ {
+ image = image_list->data;
+ gdk_image_destroy (image);
+ }
+}
+
+GdkImage *
+gdk_image_new_bitmap(GdkVisual *visual, gpointer data, gint w, gint h)
+/*
+ * Desc: create a new bitmap image
+ */
+{
+ Visual *xvisual;
+ GdkImage *image;
+ GdkImagePrivate *private;
+ private = g_new(GdkImagePrivate, 1);
+ image = (GdkImage *) private;
+ private->xdisplay = gdk_display;
+ private->image_put = gdk_image_put_normal;
+ image->type = GDK_IMAGE_NORMAL;
+ image->visual = visual;
+ image->width = w;
+ image->height = h;
+ image->depth = 1;
+ xvisual = ((GdkVisualPrivate*) visual)->xvisual;
+ private->ximage = XCreateImage(private->xdisplay, xvisual, 1, XYBitmap,
+ 0, 0, w ,h, 8, 0);
+ private->ximage->data = data;
+ private->ximage->bitmap_bit_order = MSBFirst;
+ private->ximage->byte_order = MSBFirst;
+ image->byte_order = MSBFirst;
+ image->mem = private->ximage->data;
+ image->bpl = private->ximage->bytes_per_line;
+ image->bpp = 1;
+ return(image);
+} /* gdk_image_new_bitmap() */
+
+static int
+gdk_image_check_xshm(Display *display)
+/*
+ * Desc: query the server for support for the MIT_SHM extension
+ * Return: 0 = not available
+ * 1 = shared XImage support available
+ * 2 = shared Pixmap support available also
+ */
+{
+#ifdef USE_SHM
+ int major, minor, ignore;
+ Bool pixmaps;
+
+ if (XQueryExtension(display, "MIT-SHM", &ignore, &ignore, &ignore))
+ {
+ if (XShmQueryVersion(display, &major, &minor, &pixmaps )==True)
+ {
+ return (pixmaps==True) ? 2 : 1;
+ }
+ }
+#endif /* USE_SHM */
+ return 0;
+}
+
+void
+gdk_image_init ()
+{
+ if (gdk_use_xshm)
+ {
+ if (!gdk_image_check_xshm (gdk_display))
+ {
+ g_warning ("MIT-SHM Extension not availible on server");
+ gdk_use_xshm = False;
+ }
+ }
+}
+
+GdkImage*
+gdk_image_new (GdkImageType type,
+ GdkVisual *visual,
+ gint width,
+ gint height)
+{
+ GdkImage *image;
+ GdkImagePrivate *private;
+#ifdef USE_SHM
+ XShmSegmentInfo *x_shm_info;
+#endif /* USE_SHM */
+ Visual *xvisual;
+
+ switch (type)
+ {
+ case GDK_IMAGE_FASTEST:
+ image = gdk_image_new (GDK_IMAGE_SHARED, visual, width, height);
+
+ if (!image)
+ image = gdk_image_new (GDK_IMAGE_NORMAL, visual, width, height);
+ break;
+
+ default:
+ private = g_new (GdkImagePrivate, 1);
+ image = (GdkImage*) private;
+
+ private->xdisplay = gdk_display;
+ private->image_put = NULL;
+
+ image->type = type;
+ image->visual = visual;
+ image->width = width;
+ image->height = height;
+ image->depth = visual->depth;
+
+ xvisual = ((GdkVisualPrivate*) visual)->xvisual;
+
+ switch (type)
+ {
+ case GDK_IMAGE_SHARED:
+#ifdef USE_SHM
+ if (gdk_use_xshm)
+ {
+ private->image_put = gdk_image_put_shared;
+
+ private->x_shm_info = g_new (XShmSegmentInfo, 1);
+ x_shm_info = private->x_shm_info;
+
+ private->ximage = XShmCreateImage (private->xdisplay, xvisual, visual->depth,
+ ZPixmap, NULL, x_shm_info, width, height);
+ if (private->ximage == NULL)
+ {
+ g_warning ("XShmCreateImage failed");
+
+ g_free (image);
+ gdk_use_xshm = False;
+ return NULL;
+ }
+
+ x_shm_info->shmid = shmget (IPC_PRIVATE,
+ private->ximage->bytes_per_line * private->ximage->height,
+ IPC_CREAT | 0777);
+
+ if (x_shm_info->shmid == -1)
+ {
+ g_warning ("shmget failed!");
+
+ XDestroyImage (private->ximage);
+ g_free (private->x_shm_info);
+ g_free (image);
+
+ gdk_use_xshm = False;
+ gdk_use_xshm = False;
+ return NULL;
+ }
+
+ x_shm_info->readOnly = False;
+ x_shm_info->shmaddr = shmat (x_shm_info->shmid, 0, 0);
+ private->ximage->data = x_shm_info->shmaddr;
+
+ if (x_shm_info->shmaddr == (char*) -1)
+ {
+ g_warning ("shmat failed!");
+
+ XDestroyImage (private->ximage);
+ shmctl (x_shm_info->shmid, IPC_RMID, 0);
+
+ g_free (private->x_shm_info);
+ g_free (image);
+
+ return NULL;
+ }
+
+#ifdef IPC_RMID_DEFERRED_RELEASE
+ if (x_shm_info->shmaddr != (char*) -1)
+ shmctl (x_shm_info->shmid, IPC_RMID, 0);
+#endif
+
+ gdk_error_code = 0;
+ gdk_error_warnings = 0;
+
+ XShmAttach (private->xdisplay, x_shm_info);
+ XSync (private->xdisplay, False);
+
+ gdk_error_warnings = 1;
+ if (gdk_error_code == -1)
+ {
+ g_warning ("XShmAttach failed!");
+
+ XDestroyImage (private->ximage);
+ shmdt (x_shm_info->shmaddr);
+ shmctl (x_shm_info->shmid, IPC_RMID, 0);
+
+ g_free (private->x_shm_info);
+ g_free (image);
+
+ gdk_use_xshm = False;
+ return NULL;
+ }
+
+ if (image)
+ image_list = g_list_prepend (image_list, image);
+ }
+ else
+ {
+ g_free (image);
+ return NULL;
+ }
+ break;
+#else /* USE_SHM */
+ g_free (image);
+ return NULL;
+#endif /* USE_SHM */
+ case GDK_IMAGE_NORMAL:
+ private->image_put = gdk_image_put_normal;
+
+ private->ximage = XCreateImage (private->xdisplay, xvisual, visual->depth,
+ ZPixmap, 0, 0, width, height, 32, 0);
+
+ private->ximage->data = g_new (char, private->ximage->bytes_per_line *
+ private->ximage->height);
+ break;
+
+ case GDK_IMAGE_FASTEST:
+ g_assert_not_reached ();
+ }
+
+ if (image)
+ {
+ image->byte_order = private->ximage->byte_order;
+ image->mem = private->ximage->data;
+ image->bpl = private->ximage->bytes_per_line;
+
+ switch (private->ximage->bits_per_pixel)
+ {
+ case 8:
+ image->bpp = 1;
+ break;
+ case 16:
+ image->bpp = 2;
+ break;
+ case 24:
+ image->bpp = 3;
+ break;
+ case 32:
+ image->bpp = 4;
+ break;
+ }
+ }
+ }
+
+ return image;
+}
+
+GdkImage*
+gdk_image_get (GdkWindow *window,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ GdkImage *image;
+ GdkImagePrivate *private;
+ GdkWindowPrivate *win_private;
+
+ g_return_val_if_fail (window != NULL, NULL);
+
+ win_private = (GdkWindowPrivate *) window;
+
+ private = g_new (GdkImagePrivate, 1);
+ image = (GdkImage*) private;
+
+ private->xdisplay = gdk_display;
+ private->image_put = gdk_image_put_normal;
+ private->ximage = XGetImage (private->xdisplay,
+ win_private->xwindow,
+ x, y, width, height,
+ AllPlanes, ZPixmap);
+
+ image->type = GDK_IMAGE_NORMAL;
+ image->visual = gdk_window_get_visual (window);
+ image->width = width;
+ image->height = height;
+ image->depth = private->ximage->depth;
+
+ image->mem = private->ximage->data;
+ image->bpl = private->ximage->bytes_per_line;
+ image->bpp = 1;
+
+ return image;
+}
+
+guint32
+gdk_image_get_pixel (GdkImage *image,
+ gint x,
+ gint y)
+{
+ guint32 pixel;
+ GdkImagePrivate *private;
+
+ g_return_val_if_fail (image != NULL, 0);
+
+ private = (GdkImagePrivate *) image;
+
+ pixel = XGetPixel (private->ximage, x, y);
+
+ return pixel;
+}
+
+void
+gdk_image_put_pixel (GdkImage *image,
+ gint x,
+ gint y,
+ guint32 pixel)
+{
+ GdkImagePrivate *private;
+
+ g_return_if_fail (image != NULL);
+
+ private = (GdkImagePrivate *) image;
+
+ pixel = XPutPixel (private->ximage, x, y, pixel);
+}
+
+void
+gdk_image_destroy (GdkImage *image)
+{
+ GdkImagePrivate *private;
+#ifdef USE_SHM
+ XShmSegmentInfo *x_shm_info;
+#endif /* USE_SHM */
+
+ g_return_if_fail (image != NULL);
+
+ private = (GdkImagePrivate*) image;
+ switch (image->type)
+ {
+ case GDK_IMAGE_NORMAL:
+ XDestroyImage (private->ximage);
+ break;
+
+ case GDK_IMAGE_SHARED:
+#ifdef USE_SHM
+ XShmDetach (private->xdisplay, private->x_shm_info);
+ XDestroyImage (private->ximage);
+
+ x_shm_info = private->x_shm_info;
+ shmdt (x_shm_info->shmaddr);
+ shmctl (x_shm_info->shmid, IPC_RMID, 0);
+
+ g_free (private->x_shm_info);
+
+ image_list = g_list_remove (image_list, image);
+#else /* USE_SHM */
+ g_error ("trying to destroy shared memory image when gdk was compiled without shared memory support");
+#endif /* USE_SHM */
+ break;
+
+ case GDK_IMAGE_FASTEST:
+ g_assert_not_reached ();
+ }
+
+ g_free (image);
+}
+
+static void
+gdk_image_put_normal (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkImage *image,
+ gint xsrc,
+ gint ysrc,
+ gint xdest,
+ gint ydest,
+ gint width,
+ gint height)
+{
+ GdkWindowPrivate *drawable_private;
+ GdkImagePrivate *image_private;
+ GdkGCPrivate *gc_private;
+
+ g_return_if_fail (drawable != NULL);
+ g_return_if_fail (image != NULL);
+ g_return_if_fail (gc != NULL);
+
+ drawable_private = (GdkWindowPrivate*) drawable;
+ image_private = (GdkImagePrivate*) image;
+ gc_private = (GdkGCPrivate*) gc;
+
+ g_return_if_fail (image->type == GDK_IMAGE_NORMAL);
+
+ XPutImage (drawable_private->xdisplay, drawable_private->xwindow,
+ gc_private->xgc, image_private->ximage,
+ xsrc, ysrc, xdest, ydest, width, height);
+}
+
+static void
+gdk_image_put_shared (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkImage *image,
+ gint xsrc,
+ gint ysrc,
+ gint xdest,
+ gint ydest,
+ gint width,
+ gint height)
+{
+#ifdef USE_SHM
+ GdkWindowPrivate *drawable_private;
+ GdkImagePrivate *image_private;
+ GdkGCPrivate *gc_private;
+
+ g_return_if_fail (drawable != NULL);
+ g_return_if_fail (image != NULL);
+ g_return_if_fail (gc != NULL);
+
+ drawable_private = (GdkWindowPrivate*) drawable;
+ image_private = (GdkImagePrivate*) image;
+ gc_private = (GdkGCPrivate*) gc;
+
+ g_return_if_fail (image->type == GDK_IMAGE_SHARED);
+
+ XShmPutImage (drawable_private->xdisplay, drawable_private->xwindow,
+ gc_private->xgc, image_private->ximage,
+ xsrc, ysrc, xdest, ydest, width, height, False);
+#else /* USE_SHM */
+ g_error ("trying to draw shared memory image when gdk was compiled without shared memory support");
+#endif /* USE_SHM */
+}
diff --git a/gdk/x11/gdkinput-gxi.c b/gdk/x11/gdkinput-gxi.c
new file mode 100644
index 000000000..a30e05f95
--- /dev/null
+++ b/gdk/x11/gdkinput-gxi.c
@@ -0,0 +1,628 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef XINPUT_GXI
+
+/* #define DEBUG_SWITCHING */
+
+#include <gxid_lib.h>
+
+/* Forward declarations */
+static void gdk_input_gxi_select_notify (GdkDevicePrivate *gdkdev);
+static gint gdk_input_gxi_set_mode (guint32 deviceid, GdkInputMode mode);
+static gint gdk_input_is_extension_device (guint32 deviceid);
+static void gdk_input_gxi_configure_event (XConfigureEvent *xevent,
+ GdkWindow *window);
+static void gdk_input_gxi_enter_event (XCrossingEvent *xevent,
+ GdkWindow *window);
+static gint gdk_input_gxi_other_event (GdkEvent *event,
+ XEvent *xevent,
+ GdkWindow *window);
+static void gdk_input_gxi_update_device (GdkDevicePrivate *gdkdev);
+
+static gint gdk_input_gxi_window_none_event (GdkEvent *event, XEvent *xevent);
+static gint gdk_input_gxi_enable_window (GdkWindow *window,
+ GdkDevicePrivate *gdkdev);
+static gint gdk_input_gxi_disable_window (GdkWindow *window,
+ GdkDevicePrivate *gdkdev);
+static Window gdk_input_find_root_child(Display *dpy, Window w);
+static void gdk_input_compute_obscuring(GdkInputWindow *input_window);
+static gint gdk_input_is_obscured(GdkInputWindow *input_window, gdouble x,
+ gdouble y);
+static GdkTimeCoord *gdk_input_gxi_motion_events (GdkWindow *window,
+ guint32 deviceid,
+ guint32 start,
+ guint32 stop,
+ gint *nevents_return);
+static void gdk_input_gxi_get_pointer (GdkWindow *window,
+ guint32 deviceid,
+ gdouble *x,
+ gdouble *y,
+ gdouble *pressure,
+ gdouble *xtilt,
+ gdouble *ytilt,
+ GdkModifierType *mask);
+static gint gdk_input_gxi_grab_pointer (GdkWindow * window,
+ gint owner_events,
+ GdkEventMask event_mask,
+ GdkWindow * confine_to,
+ guint32 time);
+static void gdk_input_gxi_ungrab_pointer (guint32 time);
+
+/* Local variables */
+
+static GdkDevicePrivate *gdk_input_current_device;
+static GdkDevicePrivate *gdk_input_core_pointer;
+
+void
+gdk_input_init(void)
+{
+ GList *tmp_list;
+
+ gdk_input_vtable.set_mode = gdk_input_gxi_set_mode;
+ gdk_input_vtable.set_axes = gdk_input_common_set_axes;
+ gdk_input_vtable.motion_events = gdk_input_gxi_motion_events;
+ gdk_input_vtable.get_pointer = gdk_input_gxi_get_pointer;
+ gdk_input_vtable.grab_pointer = gdk_input_gxi_grab_pointer;
+ gdk_input_vtable.ungrab_pointer = gdk_input_gxi_ungrab_pointer;
+ gdk_input_vtable.configure_event = gdk_input_gxi_configure_event;
+ gdk_input_vtable.enter_event = gdk_input_gxi_enter_event;
+ gdk_input_vtable.other_event = gdk_input_gxi_other_event;
+ gdk_input_vtable.window_none_event = gdk_input_gxi_window_none_event;
+ gdk_input_vtable.enable_window = gdk_input_gxi_enable_window;
+ gdk_input_vtable.disable_window = gdk_input_gxi_disable_window;
+
+ gdk_input_ignore_core = FALSE;
+ gdk_input_core_pointer = NULL;
+
+ if (!gdk_input_gxid_host)
+ {
+ gdk_input_gxid_host = getenv("GXID_HOST");
+ }
+ if (!gdk_input_gxid_port)
+ {
+ char *t = getenv("GXID_PORT");
+ if (t)
+ gdk_input_gxid_port = atoi(t);
+ }
+
+ gdk_input_common_init(TRUE);
+
+ /* find initial core pointer */
+
+ for (tmp_list = gdk_input_devices; tmp_list; tmp_list = tmp_list->next)
+ {
+ GdkDevicePrivate *gdkdev = (GdkDevicePrivate *)tmp_list->data;
+ if (gdk_input_is_extension_device(gdkdev->info.deviceid))
+ {
+ gdk_input_gxi_select_notify (gdkdev);
+ }
+ else
+ {
+ if (gdkdev->info.deviceid != GDK_CORE_POINTER)
+ gdk_input_core_pointer = gdkdev;
+ }
+ }
+}
+
+static void
+gdk_input_gxi_select_notify (GdkDevicePrivate *gdkdev)
+{
+ XEventClass class;
+
+ ChangeDeviceNotify (gdkdev->xdevice, gdkdev->changenotify_type, class);
+
+ XSelectExtensionEvent (gdk_display, gdk_root_window, &class, 1);
+}
+
+/* Set the core pointer. Device should already be enabled. */
+static gint
+gdk_input_gxi_set_core_pointer(GdkDevicePrivate *gdkdev)
+{
+ int x_axis,y_axis;
+
+ g_return_val_if_fail(gdkdev->xdevice,FALSE);
+
+ x_axis = gdkdev->axis_for_use[GDK_AXIS_X];
+ y_axis = gdkdev->axis_for_use[GDK_AXIS_Y];
+
+ g_return_val_if_fail(x_axis != -1 && y_axis != -1,FALSE);
+
+ /* core_pointer might not be up to date so we check with the server
+ before change the pointer */
+
+ if ( !gdk_input_is_extension_device(gdkdev->info.deviceid) )
+ {
+#if 0
+ if (gdkdev != gdk_input_core_pointer)
+ g_warning("core pointer inconsistency");
+#endif
+ return TRUE;
+ }
+
+ if ( XChangePointerDevice(gdk_display,gdkdev->xdevice, x_axis, y_axis)
+ != Success )
+ {
+ return FALSE;
+ }
+ else
+ {
+ gdk_input_gxi_update_device (gdk_input_core_pointer);
+ gdk_input_core_pointer = gdkdev;
+ return TRUE;
+ }
+}
+
+
+/* FIXME, merge with gdk_input_xfree_set_mode */
+
+static gint
+gdk_input_gxi_set_mode (guint32 deviceid, GdkInputMode mode)
+{
+ GList *tmp_list;
+ GdkDevicePrivate *gdkdev;
+ GdkInputMode old_mode;
+ GdkInputWindow *input_window;
+
+ gdkdev = gdk_input_find_device(deviceid);
+ g_return_val_if_fail (gdkdev != NULL,FALSE);
+ old_mode = gdkdev->info.mode;
+
+ if (gdkdev->info.mode == mode)
+ return TRUE;
+
+ gdkdev->info.mode = mode;
+
+ if (old_mode != GDK_MODE_DISABLED)
+ {
+ for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
+ {
+ input_window = (GdkInputWindow *)tmp_list->data;
+ if (input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
+ gdk_input_disable_window (input_window->window, gdkdev);
+ }
+ }
+
+ if (mode != GDK_MODE_DISABLED)
+ {
+ for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
+ {
+ input_window = (GdkInputWindow *)tmp_list->data;
+ if (input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
+ if (!gdk_input_enable_window(input_window->window, gdkdev))
+ {
+ gdk_input_set_mode(deviceid, old_mode);
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+
+}
+
+gint
+gdk_input_is_extension_device (guint32 deviceid)
+{
+ XDeviceInfo *devices;
+ int num_devices, loop;
+
+ if (deviceid == GDK_CORE_POINTER)
+ return FALSE;
+
+ devices = XListInputDevices(gdk_display, &num_devices);
+ for(loop=0; loop<num_devices; loop++)
+ {
+ if ((devices[loop].id == deviceid) && (devices[loop].use == IsXExtensionDevice))
+ {
+ XFreeDeviceList(devices);
+ return TRUE;
+ }
+ }
+
+ XFreeDeviceList(devices);
+ return FALSE;
+}
+
+static void
+gdk_input_gxi_configure_event (XConfigureEvent *xevent, GdkWindow *window)
+{
+ GdkInputWindow *input_window;
+ gint root_x, root_y;
+
+ input_window = gdk_input_window_find(window);
+ g_return_if_fail (input_window != NULL);
+
+ gdk_input_get_root_relative_geometry(gdk_display,GDK_WINDOW_XWINDOW(window),
+ &root_x, &root_y, NULL, NULL);
+ input_window->root_x = root_x;
+ input_window->root_y = root_y;
+ gdk_input_compute_obscuring(input_window);
+}
+
+static void
+gdk_input_gxi_enter_event (XCrossingEvent *xevent, GdkWindow *window)
+{
+ GdkInputWindow *input_window;
+
+ input_window = gdk_input_window_find(window);
+ g_return_if_fail (input_window != NULL);
+
+ gdk_input_compute_obscuring(input_window);
+}
+
+static gint
+gdk_input_gxi_other_event (GdkEvent *event,
+ XEvent *xevent,
+ GdkWindow *window)
+{
+ GdkInputWindow *input_window;
+
+ GdkDevicePrivate *gdkdev;
+ gint return_val;
+
+ input_window = gdk_input_window_find(window);
+ g_return_val_if_fail (window != NULL, -1);
+
+ /* This is a sort of a hack, as there isn't any XDeviceAnyEvent -
+ but it's potentially faster than scanning through the types of
+ every device. If we were deceived, then it won't match any of
+ the types for the device anyways */
+ gdkdev = gdk_input_find_device(((XDeviceButtonEvent *)xevent)->deviceid);
+
+ if (!gdkdev) {
+ return -1; /* we don't handle it - not an XInput event */
+ }
+
+ if (gdkdev->info.mode == GDK_MODE_DISABLED ||
+ input_window->mode == GDK_EXTENSION_EVENTS_CURSOR)
+ return FALSE;
+
+ if (gdkdev != gdk_input_current_device &&
+ xevent->type != gdkdev->changenotify_type)
+ {
+ gdk_input_current_device = gdkdev;
+ }
+
+ return_val = gdk_input_common_other_event (event, xevent,
+ input_window, gdkdev);
+
+ if (return_val > 0 && event->type == GDK_MOTION_NOTIFY &&
+ (!gdkdev->button_state) && (!input_window->grabbed) &&
+ ((event->motion.x < 0) || (event->motion.y < 0) ||
+ (event->motion.x > ((GdkWindowPrivate *)window)->width) ||
+ (event->motion.y > ((GdkWindowPrivate *)window)->height) ||
+ gdk_input_is_obscured(input_window,event->motion.x,event->motion.y)))
+ {
+#ifdef DEBUG_SWITCHING
+ g_print("gdkinput: Setting core pointer to %d on motion at (%f,%f)\n",
+ gdkdev->info.deviceid,event->motion.x,event->motion.y);
+ g_print(" window geometry is: %dx%d\n",
+ ((GdkWindowPrivate *)window)->width,
+ ((GdkWindowPrivate *)window)->height);
+#endif
+ gdk_input_gxi_set_core_pointer(gdkdev);
+ return FALSE;
+ }
+ else
+ return return_val;
+
+}
+
+static void
+gdk_input_gxi_update_device (GdkDevicePrivate *gdkdev)
+{
+ GList *t;
+
+ if (gdk_input_is_extension_device (gdkdev->info.deviceid))
+ {
+ if (!gdkdev->xdevice)
+ {
+ gdkdev->xdevice = XOpenDevice(gdk_display, gdkdev->info.deviceid);
+ gdk_input_gxi_select_notify (gdkdev);
+ gdkdev->needs_update = 1;
+ }
+ if (gdkdev->needs_update && gdkdev->xdevice)
+ {
+ for (t = gdk_input_windows; t; t = t->next)
+ gdk_input_common_select_events (((GdkInputWindow *)t->data)->window,
+ gdkdev);
+ gdkdev->needs_update = 0;
+ }
+ }
+}
+
+static gint
+gdk_input_gxi_window_none_event (GdkEvent *event, XEvent *xevent)
+{
+ GdkDevicePrivate *gdkdev =
+ gdk_input_find_device(((XDeviceButtonEvent *)xevent)->deviceid);
+
+ if (!gdkdev) {
+ return -1; /* we don't handle it - not an XInput event */
+ }
+
+ if (xevent->type == gdkdev->changenotify_type)
+ {
+ if (gdk_input_core_pointer != gdkdev)
+ {
+#ifdef DEBUG_SWITCHING
+ g_print("ChangeNotify from %d to %d:\n",
+ gdk_input_core_pointer->info.deviceid,
+ gdkdev->info.deviceid);
+#endif
+ gdk_input_gxi_update_device (gdk_input_core_pointer);
+ gdk_input_core_pointer = gdkdev;
+ }
+ }
+
+ return FALSE;
+}
+
+static gint
+gdk_input_gxi_enable_window (GdkWindow *window, GdkDevicePrivate *gdkdev)
+{
+ GdkInputWindow *input_window;
+
+ input_window = gdk_input_window_find (window);
+ g_return_val_if_fail (input_window != NULL, FALSE);
+
+ if (!gdkdev->claimed)
+ {
+ if (gxid_claim_device(gdk_input_gxid_host, gdk_input_gxid_port,
+ gdkdev->info.deviceid,
+ GDK_WINDOW_XWINDOW(window), FALSE) !=
+ GXID_RETURN_OK)
+ {
+ g_warning("Could not get device (is gxid running?)\n");
+ return FALSE;
+ }
+ gdkdev->claimed = TRUE;
+ }
+
+ if (gdkdev->xdevice && gdkdev != gdk_input_core_pointer)
+ gdk_input_common_select_events(window, gdkdev);
+ else
+ gdkdev->needs_update = TRUE;
+
+ return TRUE;
+}
+
+static gint
+gdk_input_gxi_disable_window(GdkWindow *window, GdkDevicePrivate *gdkdev)
+{
+ GdkInputWindow *input_window;
+
+ input_window = gdk_input_window_find (window);
+ g_return_val_if_fail (input_window != NULL, FALSE);
+
+ if (gdkdev->claimed)
+ {
+ gxid_release_device(gdk_input_gxid_host, gdk_input_gxid_port,
+ gdkdev->info.deviceid,
+ GDK_WINDOW_XWINDOW(window));
+
+ gdkdev->claimed = FALSE;
+ }
+
+ if (gdkdev->xdevice && gdkdev != gdk_input_core_pointer)
+ gdk_input_common_select_events(window, gdkdev);
+ else
+ gdkdev->needs_update = TRUE;
+
+ return TRUE;
+}
+
+static gint
+gdk_input_is_obscured(GdkInputWindow *input_window, gdouble x, gdouble y)
+{
+ int i;
+ for (i=0;i<input_window->num_obscuring;i++)
+ {
+ GdkRectangle *rect = &input_window->obscuring[i];
+ if ((x >= rect->x) &&
+ (y >= rect->y) &&
+ (x < rect->x + rect->width) &&
+ (y < rect->y + rect->height))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* If this routine needs fixing, the corresponding routine
+ in gxid.c will need it too. */
+
+static Window
+gdk_input_find_root_child(Display *dpy, Window w)
+{
+ Window root,parent;
+ Window *children;
+ int nchildren;
+
+ parent = w;
+ do
+ {
+ w = parent;
+ XQueryTree(dpy,w,&root,&parent,&children,&nchildren);
+ if (children) XFree(children);
+ }
+ while (parent != root);
+
+ return w;
+}
+
+void
+gdk_input_compute_obscuring(GdkInputWindow *input_window)
+{
+ int i;
+ int x,y,width,height;
+ int xc,yc,widthc,heightc,border_widthc,depthc;
+
+ Window root,parent;
+ Window *children;
+ int nchildren;
+
+ Window w = GDK_WINDOW_XWINDOW(input_window->window);
+ Window root_child = gdk_input_find_root_child(gdk_display,w);
+ gdk_input_get_root_relative_geometry(gdk_display,w,&x,&y,&width,&height);
+
+ input_window->root_x = x;
+ input_window->root_y = y;
+
+ XQueryTree(gdk_display,GDK_ROOT_WINDOW(),
+ &root,&parent,&children,&nchildren);
+
+
+ if (input_window->obscuring)
+ g_free(input_window->obscuring);
+ input_window->obscuring = 0;
+ input_window->num_obscuring = 0;
+
+ for (i=0;i<nchildren;i++)
+ if (children[i] == root_child)
+ break;
+
+ if (i>=nchildren-1)
+ {
+ if (nchildren)
+ XFree(children);
+ return;
+ }
+
+ input_window->obscuring = g_new(GdkRectangle,(nchildren-i-1));
+
+ for (i=i+1;i<nchildren;i++)
+ {
+ int xmin, xmax, ymin, ymax;
+ XGetGeometry(gdk_display,children[i],&root,&xc,&yc,&widthc,&heightc,
+ &border_widthc, &depthc);
+ xmin = xc>x ? xc : x;
+ xmax = (xc+widthc)<(x+width) ? xc+widthc : x+width;
+ ymin = yc>y ? yc : y;
+ ymax = (yc+heightc)<(y+height) ? yc+heightc : y+height;
+ if ((xmin < xmax) && (ymin < ymax))
+ {
+ XWindowAttributes attributes;
+ XGetWindowAttributes(gdk_display,children[i],&attributes);
+ if (attributes.map_state == IsViewable)
+ {
+ GdkRectangle *rect = &input_window->obscuring[input_window->num_obscuring];
+
+ /* we store the whole window, not just the obscuring part */
+ rect->x = xc - x;
+ rect->y = yc - y;
+ rect->width = widthc;
+ rect->height = heightc;
+ input_window->num_obscuring++;
+ }
+ }
+ }
+
+ if (nchildren)
+ XFree(children);
+}
+
+static void
+gdk_input_gxi_get_pointer (GdkWindow *window,
+ guint32 deviceid,
+ gdouble *x,
+ gdouble *y,
+ gdouble *pressure,
+ gdouble *xtilt,
+ gdouble *ytilt,
+ GdkModifierType *mask)
+{
+ GdkDevicePrivate *gdkdev;
+
+ gdkdev = gdk_input_find_device (deviceid);
+ g_return_if_fail (gdkdev != NULL);
+
+ if (gdkdev == gdk_input_core_pointer)
+ gdk_input_common_get_pointer (window, GDK_CORE_POINTER, x, y,
+ pressure, xtilt, ytilt, mask);
+ else
+ gdk_input_common_get_pointer (window, deviceid, x, y,
+ pressure, xtilt, ytilt, mask);
+}
+
+static GdkTimeCoord *
+gdk_input_gxi_motion_events (GdkWindow *window,
+ guint32 deviceid,
+ guint32 start,
+ guint32 stop,
+ gint *nevents_return)
+{
+ GdkDevicePrivate *gdkdev;
+
+ gdkdev = gdk_input_find_device (deviceid);
+ g_return_val_if_fail (gdkdev != NULL, NULL);
+
+
+ if (gdkdev == gdk_input_core_pointer)
+ return gdk_input_motion_events (window, GDK_CORE_POINTER, start, stop,
+ nevents_return);
+ else
+ return gdk_input_common_motion_events (window, deviceid, start, stop,
+ nevents_return);
+
+}
+
+static gint
+gdk_input_gxi_grab_pointer (GdkWindow * window,
+ gint owner_events,
+ GdkEventMask event_mask,
+ GdkWindow * confine_to,
+ guint32 time)
+{
+ GdkInputWindow *input_window, *new_window;
+ GList *tmp_list;
+
+ tmp_list = gdk_input_windows;
+ while (tmp_list)
+ {
+ input_window = (GdkInputWindow *)tmp_list->data;
+ if (input_window->grabbed)
+ return AlreadyGrabbed;
+
+ if (input_window->window == window)
+ new_window = input_window;
+
+ tmp_list = tmp_list->next;
+ }
+
+ new_window->grabbed = TRUE;
+ return Success;
+}
+
+static void
+gdk_input_gxi_ungrab_pointer (guint32 time)
+{
+ GdkInputWindow *input_window;
+ GList *tmp_list;
+
+ tmp_list = gdk_input_windows;
+ while (tmp_list)
+ {
+ input_window = (GdkInputWindow *)tmp_list->data;
+ if (input_window->grabbed)
+ input_window->grabbed = FALSE;
+ tmp_list = tmp_list->next;
+ }
+}
+
+#endif /* XINPUT_GXI */
diff --git a/gdk/x11/gdkinput-none.c b/gdk/x11/gdkinput-none.c
new file mode 100644
index 000000000..8ae8c4189
--- /dev/null
+++ b/gdk/x11/gdkinput-none.c
@@ -0,0 +1,72 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef XINPUT_NONE
+
+static void gdk_input_none_get_pointer (GdkWindow *window,
+ guint32 deviceid,
+ gdouble *x,
+ gdouble *y,
+ gdouble *pressure,
+ gdouble *xtilt,
+ gdouble *ytilt,
+ GdkModifierType *mask);
+
+void
+gdk_input_init ()
+{
+ gdk_input_vtable.set_mode = NULL;
+ gdk_input_vtable.set_axes = NULL;
+ gdk_input_vtable.motion_events = NULL;
+ gdk_input_vtable.get_pointer = gdk_input_none_get_pointer;
+ gdk_input_vtable.grab_pointer = NULL;
+ gdk_input_vtable.ungrab_pointer = NULL;
+ gdk_input_vtable.configure_event = NULL;
+ gdk_input_vtable.enter_event = NULL;
+ gdk_input_vtable.other_event = NULL;
+ gdk_input_vtable.window_none_event = NULL;
+ gdk_input_vtable.enable_window = NULL;
+ gdk_input_vtable.disable_window = NULL;
+
+ gdk_input_devices = g_list_append (NULL, &gdk_input_core_info);
+
+ gdk_input_ignore_core = FALSE;
+}
+
+static void
+gdk_input_none_get_pointer (GdkWindow *window,
+ guint32 deviceid,
+ gdouble *x,
+ gdouble *y,
+ gdouble *pressure,
+ gdouble *xtilt,
+ gdouble *ytilt,
+ GdkModifierType *mask)
+{
+ gint x_int, y_int;
+
+ gdk_window_get_pointer (window, &x_int, &y_int, mask);
+
+ if (x) *x = x_int;
+ if (y) *y = y_int;
+ if (pressure) *pressure = 0.5;
+ if (xtilt) *xtilt = 0;
+ if (ytilt) *ytilt = 0;
+}
+
+#endif /* XINPUT_NONE */
diff --git a/gdk/x11/gdkinput-x11.c b/gdk/x11/gdkinput-x11.c
new file mode 100644
index 000000000..5e457e0aa
--- /dev/null
+++ b/gdk/x11/gdkinput-x11.c
@@ -0,0 +1,687 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#if defined(XINPUT_GXI) || defined(XINPUT_XFREE)
+
+/* Forward declarations */
+static void gdk_input_get_root_relative_geometry (Display *dpy, Window w,
+ int *x_ret, int *y_ret,
+ int *width_ret,
+ int *height_ret);
+static GdkDevicePrivate *gdk_input_device_new(XDeviceInfo *device,
+ gint include_core);
+static void gdk_input_common_find_events(GdkWindow *window,
+ GdkDevicePrivate *gdkdev,
+ gint mask,
+ XEventClass *classes,
+ int *num_classes);
+static void gdk_input_common_select_events(GdkWindow *window,
+ GdkDevicePrivate *gdkdev);
+static void gdk_input_translate_coordinates(GdkDevicePrivate *gdkdev,
+ GdkInputWindow *input_window,
+ gint *axis_data,
+ gdouble *x, gdouble *y,
+ gdouble *pressure,
+ gdouble *xtilt, gdouble *ytilt);
+static guint gdk_input_translate_state(guint state, guint device_state);
+static gint gdk_input_common_init(gint include_core);
+static gint gdk_input_common_other_event (GdkEvent *event,
+ XEvent *xevent,
+ GdkInputWindow *input_window,
+ GdkDevicePrivate *gdkdev);
+static void gdk_input_common_set_axes (guint32 deviceid, GdkAxisUse *axes);
+static GdkTimeCoord * gdk_input_common_motion_events (GdkWindow *window,
+ guint32 deviceid,
+ guint32 start,
+ guint32 stop,
+ gint *nevents_return);
+static void gdk_input_common_get_pointer (GdkWindow *window,
+ guint32 deviceid,
+ gdouble *x,
+ gdouble *y,
+ gdouble *pressure,
+ gdouble *xtilt,
+ gdouble *ytilt,
+ GdkModifierType *mask);
+
+/* Global variables */
+
+static gint gdk_input_root_width;
+static gint gdk_input_root_height;
+
+static void
+gdk_input_get_root_relative_geometry(Display *dpy, Window w, int *x_ret, int *y_ret,
+ int *width_ret, int *height_ret)
+{
+ Window root,parent;
+ Window *children;
+ int nchildren;
+ int x,y,width,height;
+ int xc,yc,widthc,heightc,border_widthc,depthc;
+
+ XQueryTree(dpy,w,&root,&parent,&children,&nchildren);
+ if (children) XFree(children);
+ XGetGeometry(dpy,w,&root,&x,&y,&width,&height,&border_widthc,
+ &depthc);
+ x += border_widthc;
+ y += border_widthc;
+
+ while (root != parent)
+ {
+ w = parent;
+ XQueryTree(dpy,w,&root,&parent,&children,&nchildren);
+ if (children) XFree(children);
+ XGetGeometry(dpy,w,&root,&xc,&yc,&widthc,&heightc,
+ &border_widthc,&depthc);
+ x += xc + border_widthc;
+ y += yc + border_widthc;
+ }
+
+ if (x_ret)
+ *x_ret = x;
+ if (y_ret)
+ *y_ret = y;
+ if (width_ret)
+ *width_ret = width;
+ if (height_ret)
+ *height_ret = height;
+}
+
+static GdkDevicePrivate *
+gdk_input_device_new(XDeviceInfo *device, gint include_core)
+{
+ GdkDevicePrivate *gdkdev;
+ gchar *tmp_name, *p;
+ XAnyClassPtr class;
+ gint i,j;
+
+ gdkdev = g_new(GdkDevicePrivate,1);
+
+ gdkdev->info.deviceid = device->id;
+ if (device->name[0]) {
+ gdkdev->info.name = g_new(char, strlen(device->name)+1);
+ strcpy(gdkdev->info.name,device->name);
+ } else {
+ /* XFree86 3.2 gives an empty name to the default core devices,
+ (fixed in 3.2A) */
+ gdkdev->info.name = g_strdup("pointer");
+ strcpy(gdkdev->info.name,"pointer");
+ gdkdev->info.source = GDK_SOURCE_MOUSE;
+ }
+
+ gdkdev->info.mode = GDK_MODE_DISABLED;
+
+ /* Try to figure out what kind of device this is by its name -
+ could invite a very, very, long list... Lowercase name
+ for comparison purposes */
+
+ tmp_name = g_strdup(gdkdev->info.name);
+ for (p = tmp_name; *p; p++)
+ {
+ if (*p >= 'A' && *p <= 'Z')
+ *p += 'a' - 'A';
+ }
+
+ if (!strcmp (tmp_name, "pointer"))
+ gdkdev->info.source = GDK_SOURCE_MOUSE;
+ else if (!strcmp (tmp_name, "wacom") ||
+ !strcmp (tmp_name, "pen"))
+ gdkdev->info.source = GDK_SOURCE_PEN;
+ else if (!strcmp (tmp_name, "eraser"))
+ gdkdev->info.source = GDK_SOURCE_ERASER;
+ else if (!strcmp (tmp_name, "cursor"))
+ gdkdev->info.source = GDK_SOURCE_CURSOR;
+ else
+ gdkdev->info.source = GDK_SOURCE_PEN;
+
+ g_free(tmp_name);
+
+ gdkdev->xdevice = NULL;
+
+ /* step through the classes */
+
+ gdkdev->info.num_axes = 0;
+ gdkdev->axes = 0;
+ gdkdev->info.has_cursor = 0;
+ gdkdev->needs_update = FALSE;
+ gdkdev->claimed = FALSE;
+ gdkdev->button_state = 0;
+
+ class = device->inputclassinfo;
+ for (i=0;i<device->num_classes;i++)
+ {
+ switch (class->class) {
+ case ButtonClass:
+ {
+ break;
+ }
+ case ValuatorClass:
+ {
+ XValuatorInfo *xvi = (XValuatorInfo *)class;
+ gdkdev->info.num_axes = xvi->num_axes;
+ gdkdev->axes = g_new(GdkAxisInfo, xvi->num_axes);
+ gdkdev->info.axes = g_new(GdkAxisUse, xvi->num_axes);
+ for (j=0;j<xvi->num_axes;j++)
+ {
+ gdkdev->axes[j].resolution =
+ gdkdev->axes[j].xresolution = xvi->axes[j].resolution;
+ gdkdev->axes[j].min_value =
+ gdkdev->axes[j].xmin_value = xvi->axes[j].min_value;
+ gdkdev->axes[j].max_value =
+ gdkdev->axes[j].xmax_value = xvi->axes[j].max_value;
+ gdkdev->info.axes[j] = GDK_AXIS_IGNORE;
+ }
+ j=0;
+ if (j<xvi->num_axes)
+ gdkdev->info.axes[j++] = GDK_AXIS_X;
+ if (j<xvi->num_axes)
+ gdkdev->info.axes[j++] = GDK_AXIS_Y;
+ if (j<xvi->num_axes)
+ gdkdev->info.axes[j++] = GDK_AXIS_PRESSURE;
+ if (j<xvi->num_axes)
+ gdkdev->info.axes[j++] = GDK_AXIS_XTILT;
+ if (j<xvi->num_axes)
+ gdkdev->info.axes[j++] = GDK_AXIS_YTILT;
+
+ /* set up reverse lookup on axis use */
+ for (j=GDK_AXIS_IGNORE;j<GDK_AXIS_LAST;j++)
+ gdkdev->axis_for_use[j] = -1;
+
+ for (j=0;j<xvi->num_axes;j++)
+ if (gdkdev->info.axes[j] != GDK_AXIS_IGNORE)
+ gdkdev->axis_for_use[gdkdev->info.axes[j]] = j;
+
+ break;
+ }
+ }
+ class = (XAnyClassPtr)(((char *)class) + class->length);
+ }
+ /* return NULL if no axes */
+ if (!gdkdev->info.num_axes || !gdkdev->axes ||
+ (!include_core && device->use == IsXPointer))
+ {
+ g_free(gdkdev->info.name);
+ if (gdkdev->axes)
+ g_free(gdkdev->axes);
+ g_free(gdkdev);
+ return NULL;
+ }
+
+ if (device->use != IsXPointer)
+ gdkdev->xdevice = XOpenDevice(gdk_display, gdkdev->info.deviceid);
+
+ return gdkdev;
+}
+
+static void
+gdk_input_common_find_events(GdkWindow *window,
+ GdkDevicePrivate *gdkdev,
+ gint mask,
+ XEventClass *classes,
+ int *num_classes)
+{
+ gint i;
+ XEventClass class;
+
+ i = 0;
+ /* We have to track press and release events in pairs to keep
+ track of button state correctly and implement grabbing */
+ if (mask & GDK_BUTTON_PRESS_MASK || mask & GDK_BUTTON_RELEASE_MASK)
+ {
+ DeviceButtonPress (gdkdev->xdevice, gdkdev->buttonpress_type,
+ class);
+ if (class != 0)
+ classes[i++] = class;
+ DeviceButtonRelease (gdkdev->xdevice, gdkdev->buttonrelease_type,
+ class);
+ if (class != 0)
+ classes[i++] = class;
+ }
+ if (mask & GDK_POINTER_MOTION_MASK)
+ {
+ DeviceMotionNotify (gdkdev->xdevice, gdkdev->motionnotify_type, class);
+ if (class != 0)
+ classes[i++] = class;
+ }
+ if (mask & GDK_POINTER_MOTION_HINT_MASK)
+ {
+ /* We'll get into trouble if the macros change, but at least we'll
+ know about it, and we avoid warnings now */
+ DevicePointerMotionHint (gdkdev->xdevice, 0, class);
+ if (class != 0)
+ classes[i++] = class;
+ }
+ if (mask & GDK_PROXIMITY_IN_MASK)
+ {
+ ProximityIn (gdkdev->xdevice, gdkdev->proximityin_type, class);
+ if (class != 0)
+ classes[i++] = class;
+ }
+ if (mask & GDK_PROXIMITY_OUT_MASK)
+ {
+ ProximityOut (gdkdev->xdevice, gdkdev->proximityout_type, class);
+ if (class != 0)
+ classes[i++] = class;
+ }
+
+ *num_classes = i;
+}
+
+static void
+gdk_input_common_select_events(GdkWindow *window,
+ GdkDevicePrivate *gdkdev)
+{
+ XEventClass classes[6];
+ gint num_classes;
+
+ if (gdkdev->info.mode == GDK_MODE_DISABLED)
+ gdk_input_common_find_events(window, gdkdev, 0, classes, &num_classes);
+ else
+ gdk_input_common_find_events(window, gdkdev,
+ ((GdkWindowPrivate *)window)->extension_events,
+ classes, &num_classes);
+
+ XSelectExtensionEvent (gdk_display,
+ GDK_WINDOW_XWINDOW(window),
+ classes, num_classes);
+}
+
+gint
+gdk_input_common_init(gint include_core)
+{
+ char **extensions;
+ XDeviceInfo *devices;
+ int num_devices;
+ int num_extensions, loop;
+ Display *display = gdk_display;
+
+ /* Init global vars */
+ gdk_window_get_geometry(NULL, /* use root window */
+ NULL,NULL,
+ &gdk_input_root_width,&gdk_input_root_height,
+ NULL);
+
+ /* Init XInput extension */
+
+ extensions = XListExtensions(display, &num_extensions);
+ for (loop = 0; loop < num_extensions &&
+ (strcmp(extensions[loop], "XInputExtension") != 0); loop++);
+ XFreeExtensionList(extensions);
+ if (loop == num_extensions) /* XInput extension not found */
+ return FALSE;
+
+ gdk_input_devices = 0;
+ devices = XListInputDevices(display, &num_devices);
+
+ for(loop=0; loop<num_devices; loop++)
+ {
+ GdkDevicePrivate *gdkdev = gdk_input_device_new(&devices[loop],
+ include_core);
+ if (gdkdev)
+ gdk_input_devices = g_list_append(gdk_input_devices, gdkdev);
+ }
+ XFreeDeviceList(devices);
+
+ gdk_input_devices = g_list_append (gdk_input_devices, &gdk_input_core_info);
+
+ return TRUE;
+}
+
+static void
+gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
+ GdkInputWindow *input_window,
+ gint *axis_data,
+ gdouble *x, gdouble *y, gdouble *pressure,
+ gdouble *xtilt, gdouble *ytilt)
+{
+ GdkWindowPrivate *win_priv;
+
+ int x_axis, y_axis, pressure_axis, xtilt_axis, ytilt_axis;
+
+ double device_width, device_height;
+ double x_offset, y_offset, x_scale, y_scale;
+
+ win_priv = (GdkWindowPrivate *) input_window->window;
+
+ x_axis = gdkdev->axis_for_use[GDK_AXIS_X];
+ y_axis = gdkdev->axis_for_use[GDK_AXIS_Y];
+ pressure_axis = gdkdev->axis_for_use[GDK_AXIS_PRESSURE];
+ xtilt_axis = gdkdev->axis_for_use[GDK_AXIS_XTILT];
+ ytilt_axis = gdkdev->axis_for_use[GDK_AXIS_YTILT];
+
+ device_width = gdkdev->axes[x_axis].max_value -
+ gdkdev->axes[x_axis].min_value;
+ device_height = gdkdev->axes[y_axis].max_value -
+ gdkdev->axes[y_axis].min_value;
+
+ if (gdkdev->info.mode == GDK_MODE_SCREEN)
+ {
+ x_scale = gdk_input_root_width / device_width;
+ y_scale = gdk_input_root_height / device_height;
+
+ x_offset = - input_window->root_x;
+ y_offset = - input_window->root_y;
+ }
+ else /* GDK_MODE_WINDOW */
+ {
+ double device_aspect = (device_height*gdkdev->axes[y_axis].resolution) /
+ (device_width*gdkdev->axes[x_axis].resolution);
+
+ if (device_aspect * win_priv->width >= win_priv->height)
+ {
+ /* device taller than window */
+ x_scale = win_priv->width / device_width;
+ y_scale = (x_scale * gdkdev->axes[x_axis].resolution)
+ / gdkdev->axes[y_axis].resolution;
+
+ x_offset = 0;
+ y_offset = -(device_height * y_scale -
+ win_priv->height)/2;
+ }
+ else
+ {
+ /* window taller than device */
+ y_scale = win_priv->height / device_height;
+ x_scale = (y_scale * gdkdev->axes[y_axis].resolution)
+ / gdkdev->axes[x_axis].resolution;
+
+ y_offset = 0;
+ x_offset = - (device_width * x_scale - win_priv->width)/2;
+ }
+ }
+
+ if (x) *x = x_offset + x_scale*axis_data[x_axis];
+ if (y) *y = y_offset + y_scale*axis_data[y_axis];
+
+ if (pressure)
+ {
+ if (pressure_axis != -1)
+ *pressure = ((double)axis_data[pressure_axis]
+ - gdkdev->axes[pressure_axis].min_value)
+ / (gdkdev->axes[pressure_axis].max_value
+ - gdkdev->axes[pressure_axis].min_value);
+ else
+ *pressure = 0.5;
+ }
+
+ if (xtilt)
+ {
+ if (xtilt_axis != -1)
+ {
+ *xtilt = 2. * (double)(axis_data[xtilt_axis] -
+ (gdkdev->axes[xtilt_axis].min_value +
+ gdkdev->axes[xtilt_axis].max_value)/2) /
+ (gdkdev->axes[xtilt_axis].max_value -
+ gdkdev->axes[xtilt_axis].min_value);
+ }
+ else *xtilt = 0;
+ }
+
+ if (ytilt)
+ {
+ if (ytilt_axis != -1)
+ {
+ *ytilt = 2. * (double)(axis_data[ytilt_axis] -
+ (gdkdev->axes[ytilt_axis].min_value +
+ gdkdev->axes[ytilt_axis].max_value)/2) /
+ (gdkdev->axes[ytilt_axis].max_value -
+ gdkdev->axes[ytilt_axis].min_value);
+ }
+ else
+ *ytilt = 0;
+ }
+}
+
+/* combine the state of the core device and the device state
+ into one - for now we do this in a simple-minded manner -
+ we just take the keyboard portion of the core device and
+ the button portion (all of?) the device state.
+ Any button remapping should go on here. */
+static guint
+gdk_input_translate_state(guint state, guint device_state)
+{
+ return device_state | (state & 0xFF);
+}
+
+static gint
+gdk_input_common_other_event (GdkEvent *event,
+ XEvent *xevent,
+ GdkInputWindow *input_window,
+ GdkDevicePrivate *gdkdev)
+{
+ if ((xevent->type == gdkdev->buttonpress_type) ||
+ (xevent->type == gdkdev->buttonrelease_type))
+ {
+ XDeviceButtonEvent *xdbe = (XDeviceButtonEvent *)(xevent);
+
+ if (xdbe->type == gdkdev->buttonpress_type)
+ {
+ event->button.type = GDK_BUTTON_PRESS;
+ gdkdev->button_state |= 1 << xdbe->button;
+ }
+ else
+ {
+ event->button.type = GDK_BUTTON_RELEASE;
+ gdkdev->button_state &= ~(1 << xdbe->button);
+ }
+ event->button.window = input_window->window;
+ event->button.time = xdbe->time;
+ event->button.source = gdkdev->info.source;
+ event->button.deviceid = xdbe->deviceid;
+
+ gdk_input_translate_coordinates (gdkdev,input_window, xdbe->axis_data,
+ &event->button.x,&event->button.y,
+ &event->button.pressure,
+ &event->button.xtilt,
+ &event->button.ytilt);
+ event->button.state = gdk_input_translate_state(xdbe->state,xdbe->device_state);
+ event->button.button = xdbe->button;
+
+ return TRUE;
+ }
+
+ if (xevent->type == gdkdev->motionnotify_type)
+ {
+ XDeviceMotionEvent *xdme = (XDeviceMotionEvent *)(xevent);
+
+ gdk_input_translate_coordinates(gdkdev,input_window,xdme->axis_data,
+ &event->motion.x,&event->motion.y,
+ &event->motion.pressure,
+ &event->motion.xtilt,
+ &event->motion.ytilt);
+
+ event->motion.type = GDK_MOTION_NOTIFY;
+ event->motion.window = input_window->window;
+ event->motion.time = xdme->time;
+ event->motion.deviceid = xdme->deviceid;
+ event->motion.state = gdk_input_translate_state(xdme->state,
+ xdme->device_state);
+ event->motion.source = gdkdev->info.source;
+ event->motion.deviceid = xdme->deviceid;
+
+ if (gdk_show_events)
+ g_print ("motion notify:\t\twindow: %ld device: %ld x,y: %f %f hint: %s\n",
+ xdme->window,
+ xdme->deviceid,
+ event->motion.x, event->motion.y,
+ (xevent->xmotion.is_hint) ? "true" : "false");
+
+
+ return TRUE;
+ }
+
+ if (xevent->type == gdkdev->proximityin_type ||
+ xevent->type == gdkdev->proximityout_type)
+ {
+ XProximityNotifyEvent *xpne = (XProximityNotifyEvent *)(xevent);
+
+ event->proximity.type = (xevent->type == gdkdev->proximityin_type)?
+ GDK_PROXIMITY_IN:GDK_PROXIMITY_OUT;
+ event->proximity.window = input_window->window;
+ event->proximity.time = xpne->time;
+ event->proximity.source = gdkdev->info.source;
+ event->proximity.deviceid = xpne->deviceid;
+
+ return TRUE;
+ }
+
+ return -1; /* wasn't one of our event types */
+}
+
+static void
+gdk_input_common_set_axes (guint32 deviceid, GdkAxisUse *axes)
+{
+ int i;
+ GdkDevicePrivate *gdkdev = gdk_input_find_device(deviceid);
+ g_return_if_fail (gdkdev != NULL);
+
+ for (i=GDK_AXIS_IGNORE;i<GDK_AXIS_LAST;i++)
+ {
+ gdkdev->axis_for_use[i] = -1;
+ }
+
+ for (i=0;i<gdkdev->info.num_axes;i++)
+ {
+ gdkdev->info.axes[i] = axes[i];
+ gdkdev->axis_for_use[axes[i]] = i;
+ }
+}
+
+static GdkTimeCoord *
+gdk_input_common_motion_events (GdkWindow *window,
+ guint32 deviceid,
+ guint32 start,
+ guint32 stop,
+ gint *nevents_return)
+{
+ GdkTimeCoord *coords;
+ XDeviceTimeCoord *device_coords;
+ GdkInputWindow *input_window;
+ GdkDevicePrivate *gdkdev;
+
+ int mode_return;
+ int axis_count_return;
+ int i;
+
+ gdkdev = gdk_input_find_device (deviceid);
+ input_window = gdk_input_window_find (window);
+
+ g_return_val_if_fail (gdkdev != NULL, NULL);
+ g_return_val_if_fail (gdkdev->xdevice != NULL, NULL);
+ g_return_val_if_fail (input_window != NULL, NULL);
+
+ device_coords = XGetDeviceMotionEvents (gdk_display,
+ gdkdev->xdevice,
+ start, stop,
+ nevents_return, &mode_return,
+ &axis_count_return);
+
+ if (device_coords)
+ {
+ coords = g_new (GdkTimeCoord, *nevents_return);
+
+ for (i=0; i<*nevents_return; i++)
+ {
+ gdk_input_translate_coordinates (gdkdev, input_window,
+ device_coords[i].data,
+ &coords[i].x, &coords[i].y,
+ &coords[i].pressure,
+ &coords[i].xtilt, &coords[i].ytilt);
+ }
+ XFreeDeviceMotionEvents (device_coords);
+
+ return coords;
+ }
+ else
+ return NULL;
+}
+
+static void
+gdk_input_common_get_pointer (GdkWindow *window,
+ guint32 deviceid,
+ gdouble *x,
+ gdouble *y,
+ gdouble *pressure,
+ gdouble *xtilt,
+ gdouble *ytilt,
+ GdkModifierType *mask)
+{
+ GdkDevicePrivate *gdkdev;
+ GdkInputWindow *input_window;
+ XDeviceState *state;
+ XInputClass *input_class;
+ gint x_int, y_int;
+ gint i;
+
+ /* we probably need to get the mask in any case */
+
+ if (deviceid == GDK_CORE_POINTER)
+ {
+ gdk_window_get_pointer (window, &x_int, &y_int, mask);
+ if (x) *x = x_int;
+ if (y) *y = y_int;
+ if (pressure) *pressure = 0.5;
+ if (xtilt) *xtilt = 0;
+ if (ytilt) *ytilt = 0;
+ }
+ else
+ {
+ if (mask)
+ gdk_window_get_pointer (window, NULL, NULL, mask);
+
+ gdkdev = gdk_input_find_device (deviceid);
+ input_window = gdk_input_window_find (window);
+
+ g_return_if_fail (gdkdev != NULL);
+ g_return_if_fail (gdkdev->xdevice != NULL);
+ g_return_if_fail (input_window != NULL);
+
+ state = XQueryDeviceState (gdk_display, gdkdev->xdevice);
+ input_class = state->data;
+ for (i=0; i<state->num_classes; i++)
+ {
+ switch (input_class->class)
+ {
+ case ValuatorClass:
+ gdk_input_translate_coordinates(gdkdev, input_window,
+ ((XValuatorState *)input_class)->valuators,
+ x, y, pressure,
+ xtilt, ytilt);
+
+
+ break;
+ case ButtonClass:
+ if (mask)
+ {
+ *mask &= ~(GDK_BUTTON1_MASK | GDK_BUTTON2_MASK |
+ GDK_BUTTON3_MASK | GDK_BUTTON4_MASK |
+ GDK_BUTTON5_MASK);
+ for (i=0; i < ((XButtonState *)input_class)->num_buttons; i++)
+ {
+ if (((XButtonState *)input_class)->buttons[i])
+ *mask |= GDK_BUTTON1_MASK << i;
+ }
+ }
+ break;
+ }
+ input_class = (XInputClass *)(((char *)input_class)+input_class->length);
+ }
+ }
+}
+
+#endif
diff --git a/gdk/x11/gdkinput-xfree.c b/gdk/x11/gdkinput-xfree.c
new file mode 100644
index 000000000..f74249008
--- /dev/null
+++ b/gdk/x11/gdkinput-xfree.c
@@ -0,0 +1,368 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef XINPUT_XFREE
+
+/* forward declarations */
+
+static gint gdk_input_xfree_set_mode (guint32 deviceid, GdkInputMode mode);
+static void gdk_input_check_proximity();
+static void gdk_input_xfree_configure_event (XConfigureEvent *xevent,
+ GdkWindow *window);
+static void gdk_input_xfree_enter_event (XCrossingEvent *xevent,
+ GdkWindow *window);
+static gint gdk_input_xfree_other_event (GdkEvent *event,
+ XEvent *xevent,
+ GdkWindow *window);
+static gint gdk_input_xfree_enable_window(GdkWindow *window,
+ GdkDevicePrivate *gdkdev);
+static gint gdk_input_xfree_disable_window(GdkWindow *window,
+ GdkDevicePrivate *gdkdev);
+static gint gdk_input_xfree_grab_pointer (GdkWindow * window,
+ gint owner_events,
+ GdkEventMask event_mask,
+ GdkWindow * confine_to,
+ guint32 time);
+static void gdk_input_xfree_ungrab_pointer (guint32 time);
+
+void
+gdk_input_init(void)
+{
+ gdk_input_vtable.set_mode = gdk_input_xfree_set_mode;
+ gdk_input_vtable.set_axes = gdk_input_common_set_axes;
+ gdk_input_vtable.motion_events = gdk_input_common_motion_events;
+ gdk_input_vtable.get_pointer = gdk_input_common_get_pointer;
+ gdk_input_vtable.grab_pointer = gdk_input_xfree_grab_pointer;
+ gdk_input_vtable.ungrab_pointer = gdk_input_xfree_ungrab_pointer;
+ gdk_input_vtable.configure_event = gdk_input_xfree_configure_event;
+ gdk_input_vtable.enter_event = gdk_input_xfree_enter_event;
+ gdk_input_vtable.other_event = gdk_input_xfree_other_event;
+ gdk_input_vtable.window_none_event = NULL;
+ gdk_input_vtable.enable_window = gdk_input_xfree_enable_window;
+ gdk_input_vtable.disable_window = gdk_input_xfree_disable_window;
+
+ gdk_input_ignore_core = FALSE;
+ gdk_input_common_init(FALSE);
+}
+
+static gint
+gdk_input_xfree_set_mode (guint32 deviceid, GdkInputMode mode)
+{
+ GList *tmp_list;
+ GdkDevicePrivate *gdkdev;
+ GdkInputMode old_mode;
+ GdkInputWindow *input_window;
+
+ gdkdev = gdk_input_find_device(deviceid);
+ g_return_val_if_fail (gdkdev != NULL,FALSE);
+ old_mode = gdkdev->info.mode;
+
+ if (gdkdev->info.mode == mode)
+ return TRUE;
+
+ gdkdev->info.mode = mode;
+
+ if (mode == GDK_MODE_WINDOW)
+ {
+ gdkdev->info.has_cursor = FALSE;
+ for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
+ {
+ input_window = (GdkInputWindow *)tmp_list->data;
+ if (input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
+ gdk_input_enable_window (input_window->window, gdkdev);
+ else
+ if (old_mode != GDK_MODE_DISABLED)
+ gdk_input_disable_window (input_window->window, gdkdev);
+ }
+ }
+ else if (mode == GDK_MODE_SCREEN)
+ {
+ gdkdev->info.has_cursor = TRUE;
+ for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
+ gdk_input_enable_window (((GdkInputWindow *)tmp_list->data)->window,
+ gdkdev);
+ }
+ else /* mode == GDK_MODE_DISABLED */
+ {
+ for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
+ {
+ input_window = (GdkInputWindow *)tmp_list->data;
+ if (old_mode != GDK_MODE_WINDOW ||
+ input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
+ gdk_input_disable_window (input_window->window, gdkdev);
+ }
+ }
+
+ return TRUE;
+
+}
+
+static void
+gdk_input_check_proximity()
+{
+ gint new_proximity = 0;
+ GList *tmp_list = gdk_input_devices;
+
+ while (tmp_list && !new_proximity)
+ {
+ GdkDevicePrivate *gdkdev = (GdkDevicePrivate *)(tmp_list->data);
+
+ if (gdkdev->info.mode != GDK_MODE_DISABLED
+ && gdkdev->info.deviceid != GDK_CORE_POINTER
+ && gdkdev->xdevice)
+ {
+ XDeviceState *state = XQueryDeviceState(GDK_DISPLAY(),
+ gdkdev->xdevice);
+ XInputClass *xic;
+ int i;
+
+ xic = state->data;
+ for (i=0; i<state->num_classes; i++)
+ {
+ if (xic->class == ValuatorClass)
+ {
+ XValuatorState *xvs = (XValuatorState *)xic;
+ if ((xvs->mode & ProximityState) == InProximity)
+ {
+ new_proximity = TRUE;
+ }
+ break;
+ }
+ xic = (XInputClass *)((char *)xic + xic->length);
+ }
+ }
+ tmp_list = tmp_list->next;
+ }
+
+ gdk_input_ignore_core = new_proximity;
+}
+
+static void
+gdk_input_xfree_configure_event (XConfigureEvent *xevent, GdkWindow *window)
+{
+ GdkInputWindow *input_window;
+ gint root_x, root_y;
+
+ input_window = gdk_input_window_find(window);
+ g_return_if_fail (window != NULL);
+
+ gdk_input_get_root_relative_geometry(GDK_DISPLAY(),GDK_WINDOW_XWINDOW(window),
+ &root_x,
+ &root_y, NULL, NULL);
+
+ input_window->root_x = root_x;
+ input_window->root_y = root_y;
+}
+
+static void
+gdk_input_xfree_enter_event (XCrossingEvent *xevent,
+ GdkWindow *window)
+{
+ GdkInputWindow *input_window;
+ gint root_x, root_y;
+
+ input_window = gdk_input_window_find(window);
+ g_return_if_fail (window != NULL);
+
+ gdk_input_check_proximity();
+
+ gdk_input_get_root_relative_geometry(GDK_DISPLAY(),GDK_WINDOW_XWINDOW(window),
+ &root_x,
+ &root_y, NULL, NULL);
+
+ input_window->root_x = root_x;
+ input_window->root_y = root_y;
+}
+
+static gint
+gdk_input_xfree_other_event (GdkEvent *event,
+ XEvent *xevent,
+ GdkWindow *window)
+{
+ GdkInputWindow *input_window;
+
+ GdkDevicePrivate *gdkdev;
+ gint return_val;
+
+ input_window = gdk_input_window_find(window);
+ g_return_val_if_fail (window != NULL, -1);
+
+ /* This is a sort of a hack, as there isn't any XDeviceAnyEvent -
+ but it's potentially faster than scanning through the types of
+ every device. If we were deceived, then it won't match any of
+ the types for the device anyways */
+ gdkdev = gdk_input_find_device(((XDeviceButtonEvent *)xevent)->deviceid);
+
+ if (!gdkdev) {
+ return -1; /* we don't handle it - not an XInput event */
+ }
+
+ /* FIXME: It would be nice if we could just get rid of the events
+ entirely, instead of having to ignore them */
+ if (gdkdev->info.mode == GDK_MODE_DISABLED ||
+ (gdkdev->info.mode == GDK_MODE_WINDOW
+ && input_window->mode == GDK_EXTENSION_EVENTS_CURSOR))
+ return FALSE;
+
+ if (!gdk_input_ignore_core)
+ gdk_input_check_proximity();
+
+ return_val = gdk_input_common_other_event (event, xevent,
+ input_window, gdkdev);
+
+ if (return_val > 0 && event->type == GDK_PROXIMITY_OUT &&
+ gdk_input_ignore_core)
+ gdk_input_check_proximity();
+
+ /* Do a passive button grab. We have to be careful not to release
+ an explicit grab, if any. Doubling the grab should be harmless,
+ but we check anyways. */
+
+ /* FIXME, finding the proper events here is going to be SLOW - but
+ we might have different sets for each window/device combination */
+
+ if (return_val> 0 && !input_window->grabbed)
+ {
+ if (event->type == GDK_BUTTON_PRESS)
+ {
+ XEventClass event_classes[6];
+ gint num_classes;
+
+ gdk_input_common_find_events (window, gdkdev,
+ ((GdkWindowPrivate *)window)->extension_events,
+ event_classes, &num_classes);
+
+ XGrabDevice( GDK_DISPLAY(), gdkdev->xdevice,
+ GDK_WINDOW_XWINDOW (window),
+ TRUE, num_classes, event_classes,
+ GrabModeAsync, GrabModeAsync, event->button.time);
+ }
+ else if (event->type == GDK_BUTTON_RELEASE)
+ XUngrabDevice( GDK_DISPLAY(), gdkdev->xdevice, event->button.time);
+ }
+
+ return return_val;
+}
+
+static gint
+gdk_input_xfree_enable_window(GdkWindow *window, GdkDevicePrivate *gdkdev)
+{
+ /* FIXME: watchout, gdkdev might be core pointer, never opened */
+ gdk_input_common_select_events (window, gdkdev);
+ return TRUE;
+}
+
+static gint
+gdk_input_xfree_disable_window(GdkWindow *window, GdkDevicePrivate *gdkdev)
+{
+ gdk_input_common_select_events (window, gdkdev);
+ return TRUE;
+}
+
+static gint
+gdk_input_xfree_grab_pointer (GdkWindow * window,
+ gint owner_events,
+ GdkEventMask event_mask,
+ GdkWindow * confine_to,
+ guint32 time)
+{
+ GdkInputWindow *input_window, *new_window;
+ GdkDevicePrivate *gdkdev;
+ GList *tmp_list;
+ XEventClass event_classes[6];
+ gint num_classes;
+
+ tmp_list = gdk_input_windows;
+ new_window = NULL;
+ while (tmp_list)
+ {
+ input_window = (GdkInputWindow *)tmp_list->data;
+ if (input_window->grabbed)
+ return AlreadyGrabbed;
+
+ if (input_window->window == window)
+ {
+ new_window = input_window;
+ break;
+ }
+
+ tmp_list = tmp_list->next;
+ }
+
+ g_return_if_fail (new_window == NULL);
+
+ new_window->grabbed = TRUE;
+
+ tmp_list = gdk_input_devices;
+ while (tmp_list)
+ {
+ gdkdev = (GdkDevicePrivate *)tmp_list->data;
+ if (gdkdev->info.deviceid != GDK_CORE_POINTER &&
+ gdkdev->xdevice && !gdkdev->button_state)
+ {
+ gdk_input_common_find_events (window, gdkdev,
+ ((GdkWindowPrivate *)window)->extension_events,
+ event_classes, &num_classes);
+
+ /* FIXME: we should do something on failure */
+ XGrabDevice( GDK_DISPLAY(), gdkdev->xdevice,
+ GDK_WINDOW_XWINDOW (window),
+ TRUE, num_classes, event_classes,
+ GrabModeAsync, GrabModeAsync, time);
+ }
+ tmp_list = tmp_list->next;
+ }
+
+ return Success;
+}
+
+static void
+gdk_input_xfree_ungrab_pointer (guint32 time)
+{
+ GdkInputWindow *input_window;
+ GdkDevicePrivate *gdkdev;
+ GList *tmp_list;
+
+ tmp_list = gdk_input_windows;
+ while (tmp_list)
+ {
+ input_window = (GdkInputWindow *)tmp_list->data;
+ if (input_window->grabbed)
+ break;
+ tmp_list = tmp_list->next;
+ }
+
+ if (tmp_list) /* we found a grabbed window */
+ {
+ input_window->grabbed = FALSE;
+
+ tmp_list = gdk_input_devices;
+ while (tmp_list)
+ {
+ gdkdev = (GdkDevicePrivate *)tmp_list->data;
+ if (gdkdev->info.deviceid != GDK_CORE_POINTER &&
+ gdkdev->xdevice && !gdkdev->button_state)
+ {
+ XUngrabDevice( gdk_display, gdkdev->xdevice, time);
+ }
+ tmp_list = tmp_list->next;
+ }
+ }
+}
+
+#endif /* XINPUT_XFREE */
diff --git a/gdk/x11/gdkinput.c b/gdk/x11/gdkinput.c
new file mode 100644
index 000000000..ad4b1fcc9
--- /dev/null
+++ b/gdk/x11/gdkinput.c
@@ -0,0 +1,324 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include "../config.h"
+#include "gdk.h"
+#include "gdkx.h"
+#include "gdkprivate.h"
+#include "gdkinput.h"
+
+
+/* Forward declarations */
+
+static gint gdk_input_enable_window (GdkWindow *window,
+ GdkDevicePrivate *gdkdev);
+static gint gdk_input_disable_window (GdkWindow *window,
+ GdkDevicePrivate *gdkdev);
+static GdkInputWindow *gdk_input_window_find (GdkWindow *window);
+static GdkDevicePrivate *gdk_input_find_device (guint32 id);
+
+
+/* Incorporate the specific routines depending on compilation options */
+
+static GdkAxisUse gdk_input_core_axes[] = { GDK_AXIS_X, GDK_AXIS_Y };
+
+static GdkDeviceInfo gdk_input_core_info =
+{
+ GDK_CORE_POINTER,
+ "Core Pointer",
+ GDK_SOURCE_MOUSE,
+ GDK_MODE_SCREEN,
+ TRUE,
+ 2,
+ gdk_input_core_axes
+};
+
+/* Global variables */
+
+GdkInputVTable gdk_input_vtable;
+/* information about network port and host for gxid daemon */
+gchar *gdk_input_gxid_host;
+gint gdk_input_gxid_port;
+gint gdk_input_ignore_core;
+
+/* Local variables */
+
+static GList *gdk_input_devices;
+static GList *gdk_input_windows;
+
+#include "gdkinputnone.h"
+#include "gdkinputcommon.h"
+#include "gdkinputxfree.h"
+#include "gdkinputgxi.h"
+
+GList *
+gdk_input_list_devices ()
+{
+ return gdk_input_devices;
+}
+
+void
+gdk_input_set_source (guint32 deviceid, GdkInputSource source)
+{
+ GdkDevicePrivate *gdkdev = gdk_input_find_device(deviceid);
+ g_return_if_fail (gdkdev != NULL);
+
+ gdkdev->info.source = source;
+}
+
+gint
+gdk_input_set_mode (guint32 deviceid, GdkInputMode mode)
+{
+ if (deviceid == GDK_CORE_POINTER)
+ return FALSE;
+
+ if (gdk_input_vtable.set_mode)
+ return gdk_input_vtable.set_mode(deviceid,mode);
+ else
+ return FALSE;
+}
+
+void
+gdk_input_set_axes (guint32 deviceid, GdkAxisUse *axes)
+{
+ if (deviceid != GDK_CORE_POINTER && gdk_input_vtable.set_axes)
+ gdk_input_vtable.set_axes (deviceid, axes);
+}
+
+GdkTimeCoord *
+gdk_input_motion_events (GdkWindow *window,
+ guint32 deviceid,
+ guint32 start,
+ guint32 stop,
+ gint *nevents_return)
+{
+ XTimeCoord *xcoords;
+ GdkTimeCoord *coords;
+ int i;
+
+ if (deviceid == GDK_CORE_POINTER)
+ {
+ xcoords = XGetMotionEvents (gdk_display,
+ ((GdkWindowPrivate *)window)->xwindow,
+ start, stop, nevents_return);
+ if (xcoords)
+ {
+ coords = g_new (GdkTimeCoord, *nevents_return);
+ for (i=0; i<*nevents_return; i++)
+ {
+ coords[i].time = xcoords[i].time;
+ coords[i].x = xcoords[i].x;
+ coords[i].y = xcoords[i].y;
+ coords[i].pressure = 0.5;
+ coords[i].xtilt = 0.0;
+ coords[i].ytilt = 0.0;
+ }
+
+ XFree(xcoords);
+
+ return coords;
+ }
+ else
+ return NULL;
+ }
+ else
+ {
+ if (gdk_input_vtable.motion_events)
+ {
+ return gdk_input_vtable.motion_events(window,
+ deviceid, start, stop,
+ nevents_return);
+ }
+ else
+ {
+ *nevents_return = 0;
+ return NULL;
+ }
+ }
+}
+
+static gint
+gdk_input_enable_window (GdkWindow *window, GdkDevicePrivate *gdkdev)
+{
+ if (gdk_input_vtable.enable_window)
+ return gdk_input_vtable.enable_window (window, gdkdev);
+ else
+ return TRUE;
+}
+
+static gint
+gdk_input_disable_window (GdkWindow *window, GdkDevicePrivate *gdkdev)
+{
+ if (gdk_input_vtable.disable_window)
+ return gdk_input_vtable.disable_window(window,gdkdev);
+ else
+ return TRUE;
+}
+
+
+static GdkInputWindow *
+gdk_input_window_find(GdkWindow *window)
+{
+ GList *tmp_list;
+
+ for (tmp_list=gdk_input_windows; tmp_list; tmp_list=tmp_list->next)
+ if (((GdkInputWindow *)(tmp_list->data))->window == window)
+ return (GdkInputWindow *)(tmp_list->data);
+
+ return NULL; /* Not found */
+}
+
+/* FIXME: this routine currently needs to be called between creation
+ and the corresponding configure event (because it doesn't get the
+ root_relative_geometry). This should work with
+ gtk_window_set_extension_events, but will likely fail in other
+ cases */
+
+void
+gdk_input_set_extension_events (GdkWindow *window, gint mask,
+ GdkExtensionMode mode)
+{
+ GList *tmp_list;
+ GdkInputWindow *iw;
+
+ g_return_if_fail (window != NULL);
+
+ if (mode == GDK_EXTENSION_EVENTS_NONE)
+ mask = 0;
+
+ if (mask != 0)
+ {
+ iw = g_new(GdkInputWindow,1);
+
+ iw->window = window;
+ iw->mode = mode;
+
+ iw->obscuring = NULL;
+ iw->num_obscuring = 0;
+ iw->grabbed = FALSE;
+
+ gdk_input_windows = g_list_append(gdk_input_windows,iw);
+ ((GdkWindowPrivate *)window)->extension_events = mask;
+
+ /* Add enter window events to the event mask */
+ /* FIXME, this is not needed for XINPUT_NONE */
+ gdk_window_set_events (window,
+ gdk_window_get_events (window) |
+ GDK_ENTER_NOTIFY_MASK);
+ }
+ else
+ {
+ iw = gdk_input_window_find (window);
+ if (iw)
+ {
+ gdk_input_windows = g_list_remove(gdk_input_windows,iw);
+ g_free(iw);
+ }
+
+ ((GdkWindowPrivate *)window)->extension_events = 0;
+ }
+
+ for (tmp_list = gdk_input_devices; tmp_list; tmp_list = tmp_list->next)
+ {
+ GdkDevicePrivate *gdkdev = (GdkDevicePrivate *)(tmp_list->data);
+
+ if (gdkdev->info.deviceid != GDK_CORE_POINTER)
+ {
+ if (mask != 0 && gdkdev->info.mode != GDK_MODE_DISABLED
+ && (gdkdev->info.has_cursor || mode == GDK_EXTENSION_EVENTS_ALL))
+ gdk_input_enable_window(window,gdkdev);
+ else
+ gdk_input_disable_window(window,gdkdev);
+ }
+ }
+}
+
+void
+gdk_input_window_destroy (GdkWindow *window)
+{
+ GdkInputWindow *input_window;
+
+ input_window = gdk_input_window_find (window);
+ g_return_if_fail (input_window != NULL);
+
+ gdk_input_windows = g_list_remove(gdk_input_windows,input_window);
+ g_free(input_window);
+}
+
+void
+gdk_input_exit (void)
+{
+ GList *tmp_list;
+ GdkDevicePrivate *gdkdev;
+
+ for (tmp_list = gdk_input_devices; tmp_list; tmp_list = tmp_list->next)
+ {
+ gdkdev = (GdkDevicePrivate *)(tmp_list->data);
+ if (gdkdev->info.deviceid != GDK_CORE_POINTER)
+ {
+ gdk_input_set_mode(gdkdev->info.deviceid,GDK_MODE_DISABLED);
+
+ g_free(gdkdev->info.name);
+#ifndef XINPUT_NONE
+ g_free(gdkdev->axes);
+#endif
+ g_free(gdkdev->info.axes);
+ g_free(gdkdev);
+ }
+ }
+
+ g_list_free(gdk_input_devices);
+
+ for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
+ {
+ g_free(tmp_list->data);
+ }
+ g_list_free(gdk_input_windows);
+}
+
+static GdkDevicePrivate *
+gdk_input_find_device(guint32 id)
+{
+ GList *tmp_list = gdk_input_devices;
+ GdkDevicePrivate *gdkdev;
+ while (tmp_list)
+ {
+ gdkdev = (GdkDevicePrivate *)(tmp_list->data);
+ if (gdkdev->info.deviceid == id)
+ return gdkdev;
+ tmp_list = tmp_list->next;
+ }
+ return NULL;
+}
+
+void
+gdk_input_window_get_pointer (GdkWindow *window,
+ guint32 deviceid,
+ gdouble *x,
+ gdouble *y,
+ gdouble *pressure,
+ gdouble *xtilt,
+ gdouble *ytilt,
+ GdkModifierType *mask)
+{
+ if (gdk_input_vtable.get_pointer)
+ gdk_input_vtable.get_pointer (window, deviceid, x, y, pressure,
+ xtilt, ytilt, mask);
+}
diff --git a/gdk/x11/gdkmain-x11.c b/gdk/x11/gdkmain-x11.c
new file mode 100644
index 000000000..d5f85dd1e
--- /dev/null
+++ b/gdk/x11/gdkmain-x11.c
@@ -0,0 +1,2897 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "../config.h"
+
+#include <ctype.h>
+#include <locale.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif /* HAVE_SYS_SELECT_H_ */
+
+#define XLIB_ILLEGAL_ACCESS
+#include <X11/Xatom.h>
+#include <X11/Xlib.h>
+#include <X11/Xos.h>
+#include <X11/Xutil.h>
+#include <X11/Xmu/WinUtil.h>
+#include <X11/cursorfont.h>
+#include "gdk.h"
+#include "gdkprivate.h"
+#include "gdkinput.h"
+
+
+#ifndef X_GETTIMEOFDAY
+#define X_GETTIMEOFDAY(tv) gettimeofday (tv, NULL)
+#endif /* X_GETTIMEOFDAY */
+
+
+#define DOUBLE_CLICK_TIME 250
+#define TRIPLE_CLICK_TIME 500
+#define DOUBLE_CLICK_DIST 5
+#define TRIPLE_CLICK_DIST 5
+
+
+#ifndef NO_FD_SET
+# define SELECT_MASK fd_set
+#else
+# ifndef _AIX
+ typedef long fd_mask;
+# endif
+# if defined(_IBMR2)
+# define SELECT_MASK void
+# else
+# define SELECT_MASK int
+# endif
+#endif
+
+
+typedef struct _GdkInput GdkInput;
+typedef struct _GdkPredicate GdkPredicate;
+
+struct _GdkInput
+{
+ gint tag;
+ gint source;
+ GdkInputCondition condition;
+ GdkInputFunction function;
+ gpointer data;
+};
+
+struct _GdkPredicate
+{
+ GdkEventFunc func;
+ gpointer data;
+};
+
+/*
+ * Private function declarations
+ */
+static gint gdk_event_wait (void);
+static gint gdk_event_translate (GdkEvent *event,
+ XEvent *xevent);
+static Bool gdk_event_get_type (Display *display,
+ XEvent *xevent,
+ XPointer arg);
+static void gdk_synthesize_click (GdkEvent *event,
+ gint nclicks);
+
+static void gdk_dnd_drag_begin (GdkWindow *initial_window);
+static void gdk_dnd_drag_enter (Window dest);
+static void gdk_dnd_drag_leave (Window dest);
+static void gdk_dnd_drag_end (Window dest,
+ GdkPoint coords);
+static GdkAtom gdk_dnd_check_types (GdkWindow *window,
+ XEvent *xevent);
+static void gdk_print_atom (GdkAtom anatom);
+
+/*
+ * old junk from offix, we might use it though so leave it
+ */
+static Window gdk_drop_get_client_window (Display *dpy,
+ Window win);
+static GdkWindow * gdk_drop_get_real_window (GdkWindow *w,
+ guint16 *x,
+ guint16 *y);
+static void gdk_exit_func (void);
+static int gdk_x_error (Display *display,
+ XErrorEvent *error);
+static int gdk_x_io_error (Display *display);
+static RETSIGTYPE gdk_signal (int signum);
+
+
+/* Private variable declarations
+ */
+static int initialized = 0; /* 1 if the library is initialized,
+ * 0 otherwise.
+ */
+static int connection_number = 0; /* The file descriptor number of our
+ * connection to the X server. This
+ * is used so that we may determine
+ * when events are pending by using
+ * the "select" system call.
+ */
+
+static gint received_destroy_notify = FALSE; /* Did we just receive a destroy notify
+ * event? If so, we need to actually
+ * destroy the window which received
+ * it now.
+ */
+static GdkWindow *window_to_destroy = NULL; /* If we previously received a destroy
+ * notify event then this is the window
+ * which received that event.
+ */
+
+static struct timeval start; /* The time at which the library was
+ * last initialized.
+ */
+static struct timeval timer; /* Timeout interval to use in the call
+ * to "select". This is used in
+ * conjunction with "timerp" to create
+ * a maximum time to wait for an event
+ * to arrive.
+ */
+static struct timeval *timerp; /* The actual timer passed to "select"
+ * This may be NULL, in which case
+ * "select" will block until an event
+ * arrives.
+ */
+static guint32 timer_val; /* The timeout length as specified by
+ * the user in milliseconds.
+ */
+static GList *inputs; /* A list of the input file descriptors
+ * that we care about. Each list node
+ * contains a GdkInput struct that describes
+ * when we are interested in the specified
+ * file descriptor. That is, when it is
+ * available for read, write or has an
+ * exception pending.
+ */
+static guint32 button_click_time[2]; /* The last 2 button click times. Used
+ * to determine if the latest button click
+ * is part of a double or triple click.
+ */
+static GdkWindow *button_window[2]; /* The last 2 windows to receive button presses.
+ * Also used to determine if the latest button
+ * click is part of a double or triple click.
+ */
+static guint button_number[2]; /* The last 2 buttons to be pressed.
+ */
+
+#define OTHER_XEVENT_BUFSIZE 4
+static XEvent other_xevent[OTHER_XEVENT_BUFSIZE]; /* XEvents passed along to user */
+static int other_xevent_i = 0;
+static GList *putback_events = NULL;
+
+static gulong base_id;
+static gint autorepeat;
+
+
+/*
+ *--------------------------------------------------------------
+ * gdk_init
+ *
+ * Initialize the library for use.
+ *
+ * Arguments:
+ * "argc" is the number of arguments.
+ * "argv" is an array of strings.
+ *
+ * Results:
+ * "argc" and "argv" are modified to reflect any arguments
+ * which were not handled. (Such arguments should either
+ * be handled by the application or dismissed).
+ *
+ * Side effects:
+ * The library is initialized.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+gdk_init (int *argc,
+ char ***argv)
+{
+ XKeyboardState keyboard_state;
+ int synchronize;
+ int i, j, k;
+ XClassHint *class_hint;
+ int argc_orig = *argc;
+ char **argv_orig;
+
+ argv_orig = malloc ((argc_orig + 1) * sizeof (char*));
+ for (i = 0; i < argc_orig; i++)
+ argv_orig[i] = g_strdup ((*argv)[i]);
+ argv_orig[argc_orig] = NULL;
+
+ X_GETTIMEOFDAY (&start);
+
+ signal (SIGHUP, gdk_signal);
+ signal (SIGINT, gdk_signal);
+ signal (SIGQUIT, gdk_signal);
+ signal (SIGBUS, gdk_signal);
+ signal (SIGSEGV, gdk_signal);
+ signal (SIGPIPE, gdk_signal);
+ signal (SIGTERM, gdk_signal);
+
+ gdk_display_name = NULL;
+
+ XSetErrorHandler (gdk_x_error);
+ XSetIOErrorHandler (gdk_x_io_error);
+
+ synchronize = FALSE;
+
+ if (argc && argv)
+ {
+ if (*argc > 0)
+ gdk_progname = (*argv)[0];
+
+ for (i = 1; i < *argc;)
+ {
+ if (strcmp ("--display", (*argv)[i]) == 0)
+ {
+ (*argv)[i] = NULL;
+
+ if ((i + 1) < *argc)
+ {
+ gdk_display_name = g_strdup ((*argv)[i + 1]);
+ (*argv)[i + 1] = NULL;
+ i += 1;
+ }
+ }
+ else if (strcmp ("--sync", (*argv)[i]) == 0)
+ {
+ (*argv)[i] = NULL;
+ synchronize = TRUE;
+ }
+ else if (strcmp ("--show-events", (*argv)[i]) == 0)
+ {
+ (*argv)[i] = NULL;
+ gdk_show_events = TRUE;
+ }
+ else if (strcmp ("--no-show-events", (*argv)[i]) == 0)
+ {
+ (*argv)[i] = NULL;
+ gdk_show_events = FALSE;
+ }
+ else if (strcmp ("--no-xshm", (*argv)[i]) == 0)
+ {
+ (*argv)[i] = NULL;
+ gdk_use_xshm = FALSE;
+ }
+ else if (strcmp ("--debug-level", (*argv)[i]) == 0)
+ {
+ if ((i + 1) < *argc)
+ {
+ (*argv)[i++] = NULL;
+ gdk_debug_level = atoi ((*argv)[i]);
+ (*argv)[i] = NULL;
+ }
+ }
+ else if (strcmp ("-name", (*argv)[i]) == 0)
+ {
+ if ((i + 1) < *argc)
+ {
+ (*argv)[i++] = NULL;
+ gdk_progname = (*argv)[i];
+ (*argv)[i] = NULL;
+ }
+ }
+ else if (strcmp ("-class", (*argv)[i]) == 0)
+ {
+ if ((i + 1) < *argc)
+ {
+ (*argv)[i++] = NULL;
+ gdk_progclass = (*argv)[i];
+ (*argv)[i] = NULL;
+ }
+ }
+#ifdef XINPUT_GXI
+ else if (strcmp ("--gxid_host", (*argv)[i]) == 0)
+ {
+ if ((i + 1) < *argc)
+ {
+ (*argv)[i++] = NULL;
+ gdk_input_gxid_host = ((*argv)[i]);
+ (*argv)[i] = NULL;
+ }
+ }
+ else if (strcmp ("--gxid_port", (*argv)[i]) == 0)
+ {
+ if ((i + 1) < *argc)
+ {
+ (*argv)[i++] = NULL;
+ gdk_input_gxid_port = atoi ((*argv)[i]);
+ (*argv)[i] = NULL;
+ }
+ }
+#endif
+ i += 1;
+ }
+
+ for (i = 1; i < *argc; i++)
+ {
+ for (k = i; k < *argc; k++)
+ if ((*argv)[k] != NULL)
+ break;
+
+ if (k > i)
+ {
+ k -= i;
+ for (j = i + k; j < *argc; j++)
+ (*argv)[j-k] = (*argv)[j];
+ *argc -= k;
+ }
+ }
+ }
+ else
+ {
+ gdk_progname = "<unknown>";
+ }
+
+ gdk_display = XOpenDisplay (gdk_display_name);
+ if (!gdk_display)
+ g_error ("cannot open display: %s", XDisplayName (gdk_display_name));
+
+ /* This is really crappy. We have to look into the display structure
+ * to find the base resource id. This is only needed for recording
+ * and playback of events.
+ */
+ /* base_id = RESOURCE_BASE; */
+ base_id = 0;
+ if (gdk_show_events)
+ g_print ("base id: %lu\n", base_id);
+
+ connection_number = ConnectionNumber (gdk_display);
+ if (gdk_debug_level >= 1)
+ g_print ("connection number: %d\n", connection_number);
+
+ if (synchronize)
+ XSynchronize (gdk_display, True);
+
+ gdk_screen = DefaultScreen (gdk_display);
+ gdk_root_window = RootWindow (gdk_display, gdk_screen);
+
+ gdk_leader_window = XCreateSimpleWindow(gdk_display, gdk_root_window,
+ 10, 10, 10, 10, 0, 0 , 0);
+ class_hint = XAllocClassHint();
+ class_hint->res_name = gdk_progname;
+ class_hint->res_class = gdk_progclass;
+ XSetClassHint(gdk_display, gdk_leader_window, class_hint);
+ XSetCommand(gdk_display, gdk_leader_window, argv_orig, argc_orig);
+ XFree (class_hint);
+
+ gdk_wm_delete_window = XInternAtom (gdk_display, "WM_DELETE_WINDOW", True);
+ gdk_wm_take_focus = XInternAtom (gdk_display, "WM_TAKE_FOCUS", True);
+ gdk_wm_protocols = XInternAtom (gdk_display, "WM_PROTOCOLS", True);
+ gdk_wm_window_protocols[0] = gdk_wm_delete_window;
+ gdk_wm_window_protocols[1] = gdk_wm_take_focus;
+ gdk_selection_property = XInternAtom (gdk_display, "GDK_SELECTION", False);
+
+ gdk_dnd.gdk_XdeEnter = gdk_atom_intern("_XDE_ENTER", FALSE);
+ gdk_dnd.gdk_XdeLeave = gdk_atom_intern("_XDE_LEAVE", FALSE);
+ gdk_dnd.gdk_XdeRequest = gdk_atom_intern("_XDE_REQUEST", FALSE);
+ gdk_dnd.gdk_XdeDataAvailable = gdk_atom_intern("_XDE_DATA_AVAILABLE", FALSE);
+ gdk_dnd.gdk_XdeTypelist = gdk_atom_intern("_XDE_TYPELIST", FALSE);
+ gdk_dnd.gdk_cursor_dragdefault = XCreateFontCursor(gdk_display, XC_bogosity);
+ gdk_dnd.gdk_cursor_dragok = XCreateFontCursor(gdk_display, XC_heart);
+
+ XGetKeyboardControl (gdk_display, &keyboard_state);
+ autorepeat = keyboard_state.global_auto_repeat;
+
+ timer.tv_sec = 0;
+ timer.tv_usec = 0;
+ timerp = NULL;
+
+ button_click_time[0] = 0;
+ button_click_time[1] = 0;
+ button_window[0] = NULL;
+ button_window[1] = NULL;
+ button_number[0] = -1;
+ button_number[1] = -1;
+
+ if (ATEXIT (gdk_exit_func))
+ g_warning ("unable to register exit function");
+
+ gdk_visual_init ();
+ gdk_window_init ();
+ gdk_image_init ();
+ gdk_input_init ();
+
+ initialized = 1;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_exit
+ *
+ * Restores the library to an un-itialized state and exits
+ * the program using the "exit" system call.
+ *
+ * Arguments:
+ * "errorcode" is the error value to pass to "exit".
+ *
+ * Results:
+ * Allocated structures are freed and the program exits
+ * cleanly.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+gdk_exit (int errorcode)
+{
+ /* de-initialisation is done by the gdk_exit_funct(),
+ no need to do this here (Alex J.) */
+ exit (errorcode);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_set_locale
+ *
+ * Arguments:
+ *
+ * Results:
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+gchar*
+gdk_set_locale ()
+{
+ if (!setlocale (LC_ALL,""))
+ g_print ("locale not supported by C library\n");
+
+ if (!XSupportsLocale ())
+ {
+ g_print ("locale not supported by Xlib, locale set to C\n");
+ setlocale (LC_ALL, "C");
+ }
+
+ if (!XSetLocaleModifiers (""))
+ {
+ g_print ("can not set locale modifiers\n");
+ }
+
+ return setlocale (LC_ALL,NULL);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_events_pending
+ *
+ * Returns the number of events pending on the queue.
+ * These events have already been read from the server
+ * connection.
+ *
+ * Arguments:
+ *
+ * Results:
+ * Returns the number of events on XLib's event queue.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+gint
+gdk_events_pending ()
+{
+ return XPending (gdk_display);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_event_get
+ *
+ * Gets the next event.
+ *
+ * Arguments:
+ * "event" is used to hold the received event.
+ * If "event" is NULL an event is received as normal
+ * however it is not placed in "event" (and thus no
+ * error occurs).
+ *
+ * Results:
+ * Returns TRUE if an event was received that we care about
+ * and FALSE otherwise. This function will also return
+ * before an event is received if the timeout interval
+ * runs out.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+gint
+gdk_event_get (GdkEvent *event,
+ GdkEventFunc pred,
+ gpointer data)
+{
+ GdkEvent *temp_event;
+ GdkPredicate event_pred;
+ GList *temp_list;
+ XEvent xevent;
+
+ /* If the last event we received was a destroy notify
+ * event then we will actually destroy the "gdk" data
+ * structures now. We don't want to destroy them at the
+ * time of receiving the event since the main program
+ * may try to access them and may need to destroy user
+ * data that has been attached to the window
+ */
+ if (received_destroy_notify)
+ {
+ if (gdk_show_events)
+ g_print ("destroying window:\twindow: %ld\n",
+ ((GdkWindowPrivate*) window_to_destroy)->xwindow - base_id);
+
+ gdk_window_real_destroy (window_to_destroy);
+ received_destroy_notify = FALSE;
+ window_to_destroy = NULL;
+ }
+
+ /* Initially we haven't received an event and want to
+ * return FALSE. If "event" is non-NULL, then initialize
+ * it to the nothing event.
+ */
+ if (event)
+ {
+ event->any.type = GDK_NOTHING;
+ event->any.window = NULL;
+ event->any.send_event = FALSE;
+ }
+
+ if (pred)
+ {
+ temp_list = putback_events;
+ while (temp_list)
+ {
+ temp_event = temp_list->data;
+
+ if ((* pred) (temp_event, data))
+ {
+ if (event)
+ *event = *temp_event;
+ putback_events = g_list_remove_link (putback_events, temp_list);
+ g_list_free (temp_list);
+ return TRUE;
+ }
+
+ temp_list = temp_list->next;
+ }
+
+ event_pred.func = pred;
+ event_pred.data = data;
+
+ if (XCheckIfEvent (gdk_display, &xevent, gdk_event_get_type, (XPointer) &event_pred))
+ if (event)
+ return gdk_event_translate (event, &xevent);
+ }
+ else
+ {
+ if (putback_events)
+ {
+ temp_event = putback_events->data;
+ *event = *temp_event;
+
+ temp_list = putback_events;
+ putback_events = putback_events->next;
+ if (putback_events)
+ putback_events->prev = NULL;
+
+ temp_list->next = NULL;
+ temp_list->prev = NULL;
+ g_list_free (temp_list);
+ g_free (temp_event);
+
+ return TRUE;
+ }
+
+ /* Wait for an event to occur or the timeout to elapse.
+ * If an event occurs "gdk_event_wait" will return TRUE.
+ * If the timeout elapses "gdk_event_wait" will return
+ * FALSE.
+ */
+ if (gdk_event_wait ())
+ {
+ /* If we get here we can rest assurred that an event
+ * has occurred. Read it.
+ */
+ XNextEvent (gdk_display, &xevent);
+
+ event->any.send_event = xevent.xany.send_event;
+
+ /* If "event" non-NULL.
+ */
+ if (event)
+ return gdk_event_translate (event, &xevent);
+ }
+ }
+
+ return FALSE;
+}
+
+void
+gdk_event_put (GdkEvent *event)
+{
+ GdkEvent *new_event;
+
+ g_return_if_fail (event != NULL);
+
+ new_event = g_new (GdkEvent, 1);
+ *new_event = *event;
+
+ putback_events = g_list_prepend (putback_events, new_event);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_event_copy
+ *
+ * Copy a event structure into new storage.
+ *
+ * Arguments:
+ * "event" is the event struct to copy.
+ *
+ * Results:
+ * A new event structure. Free it with gdk_event_free.
+ *
+ * Side effects:
+ * The reference count of the window in the event is increased.
+ *
+ *--------------------------------------------------------------
+ */
+
+static GMemChunk *event_chunk;
+
+GdkEvent*
+gdk_event_copy (GdkEvent *event)
+{
+ GdkEvent *new_event;
+
+ g_return_val_if_fail (event != NULL, NULL);
+
+ if (event_chunk == NULL)
+ event_chunk = g_mem_chunk_new ("events",
+ sizeof (GdkEvent),
+ 4096,
+ G_ALLOC_AND_FREE);
+
+ new_event = g_chunk_new (GdkEvent, event_chunk);
+ *new_event = *event;
+ gdk_window_ref (new_event->any.window);
+ return new_event;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_event_free
+ *
+ * Free a event structure obtained from gdk_event_copy. Do not use
+ * with other event structures.
+ *
+ * Arguments:
+ * "event" is the event struct to free.
+ *
+ * Results:
+ *
+ * Side effects:
+ * The reference count of the window in the event is decreased and
+ * might be freed, too.
+ *
+ *-------------------------------------------------------------- */
+
+void
+gdk_event_free (GdkEvent *event)
+{
+ g_assert (event_chunk != NULL);
+ g_return_if_fail (event != NULL);
+
+ gdk_window_unref (event->any.window);
+ g_mem_chunk_free (event_chunk, event);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_set_debug_level
+ *
+ * Sets the debugging level.
+ *
+ * Arguments:
+ * "level" is the new debugging level.
+ *
+ * Results:
+ *
+ * Side effects:
+ * Other function calls to "gdk" use the debugging
+ * level to determine what kind of debugging information
+ * to print out.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+gdk_set_debug_level (int level)
+{
+ gdk_debug_level = level;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_set_show_events
+ *
+ * Turns on/off the showing of events.
+ *
+ * Arguments:
+ * "show_events" is a boolean describing whether or
+ * not to show the events gdk receives.
+ *
+ * Results:
+ *
+ * Side effects:
+ * When "show_events" is TRUE, calls to "gdk_event_get"
+ * will output debugging informatin regarding the event
+ * received to stdout.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+gdk_set_show_events (int show_events)
+{
+ gdk_show_events = show_events;
+}
+
+void
+gdk_set_use_xshm (gint use_xshm)
+{
+ gdk_use_xshm = use_xshm;
+}
+
+gint
+gdk_get_debug_level ()
+{
+ return gdk_debug_level;
+}
+
+gint
+gdk_get_show_events ()
+{
+ return gdk_show_events;
+}
+
+gint
+gdk_get_use_xshm ()
+{
+ return gdk_use_xshm;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_time_get
+ *
+ * Get the number of milliseconds since the library was
+ * initialized.
+ *
+ * Arguments:
+ *
+ * Results:
+ * The time since the library was initialized is returned.
+ * This time value is accurate to milliseconds even though
+ * a more accurate time down to the microsecond could be
+ * returned.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+guint32
+gdk_time_get ()
+{
+ struct timeval end;
+ struct timeval elapsed;
+ guint32 milliseconds;
+
+ X_GETTIMEOFDAY (&end);
+
+ if (start.tv_usec > end.tv_usec)
+ {
+ end.tv_usec += 1000000;
+ end.tv_sec--;
+ }
+ elapsed.tv_sec = end.tv_sec - start.tv_sec;
+ elapsed.tv_usec = end.tv_usec - start.tv_usec;
+
+ milliseconds = (elapsed.tv_sec * 1000) + (elapsed.tv_usec / 1000);
+
+ return milliseconds;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_timer_get
+ *
+ * Returns the current timer.
+ *
+ * Arguments:
+ *
+ * Results:
+ * Returns the current timer interval. This interval is
+ * in units of milliseconds.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+guint32
+gdk_timer_get ()
+{
+ return timer_val;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_timer_set
+ *
+ * Sets the timer interval.
+ *
+ * Arguments:
+ * "milliseconds" is the new value for the timer.
+ *
+ * Results:
+ *
+ * Side effects:
+ * Calls to "gdk_event_get" will last for a maximum
+ * of time of "milliseconds". However, a value of 0
+ * milliseconds will cause "gdk_event_get" to block
+ * indefinately until an event is received.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+gdk_timer_set (guint32 milliseconds)
+{
+ timer_val = milliseconds;
+ timer.tv_sec = milliseconds / 1000;
+ timer.tv_usec = (milliseconds % 1000) * 1000;
+
+}
+
+void
+gdk_timer_enable ()
+{
+ timerp = &timer;
+}
+
+void
+gdk_timer_disable ()
+{
+ timerp = NULL;
+}
+
+gint
+gdk_input_add (gint source,
+ GdkInputCondition condition,
+ GdkInputFunction function,
+ gpointer data)
+{
+ static gint next_tag = 1;
+ GList *list;
+ GdkInput *input;
+ gint tag;
+
+ tag = 0;
+ list = inputs;
+
+ while (list)
+ {
+ input = list->data;
+ list = list->next;
+
+ if ((input->source == source) && (input->condition == condition))
+ {
+ input->function = function;
+ input->data = data;
+ tag = input->tag;
+ }
+ }
+
+ if (!tag)
+ {
+ input = g_new (GdkInput, 1);
+ input->tag = next_tag++;
+ input->source = source;
+ input->condition = condition;
+ input->function = function;
+ input->data = data;
+ tag = input->tag;
+
+ inputs = g_list_prepend (inputs, input);
+ }
+
+ return tag;
+}
+
+void
+gdk_input_remove (gint tag)
+{
+ GList *list;
+ GList *temp_list;
+ GdkInput *input;
+
+ list = inputs;
+ while (list)
+ {
+ input = list->data;
+
+ if (input->tag == tag)
+ {
+ temp_list = list;
+
+ if (list->next)
+ list->next->prev = list->prev;
+ if (list->prev)
+ list->prev->next = list->next;
+ if (inputs == list)
+ inputs = list->next;
+
+ temp_list->next = NULL;
+ temp_list->prev = NULL;
+
+ g_free (temp_list->data);
+ g_list_free (temp_list);
+ break;
+ }
+
+ list = list->next;
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_pointer_grab
+ *
+ * Grabs the pointer to a specific window
+ *
+ * Arguments:
+ * "window" is the window which will receive the grab
+ * "owner_events" specifies whether events will be reported as is,
+ * or relative to "window"
+ * "event_mask" masks only interesting events
+ * "confine_to" limits the cursor movement to the specified window
+ * "cursor" changes the cursor for the duration of the grab
+ * "time" specifies the time
+ *
+ * Results:
+ *
+ * Side effects:
+ * requires a corresponding call to gdk_pointer_ungrab
+ *
+ *--------------------------------------------------------------
+ */
+
+gint
+gdk_pointer_grab (GdkWindow * window,
+ gint owner_events,
+ GdkEventMask event_mask,
+ GdkWindow * confine_to,
+ GdkCursor * cursor,
+ guint32 time)
+{
+ /* From gdkwindow.c */
+ extern int nevent_masks;
+ extern int event_mask_table[];
+
+ gint return_val;
+ GdkWindowPrivate *window_private;
+ GdkWindowPrivate *confine_to_private;
+ GdkCursorPrivate *cursor_private;
+ guint xevent_mask;
+ Window xwindow;
+ Window xconfine_to;
+ Cursor xcursor;
+ int i;
+
+ g_return_val_if_fail (window != NULL, 0);
+
+ window_private = (GdkWindowPrivate*) window;
+ confine_to_private = (GdkWindowPrivate*) confine_to;
+ cursor_private = (GdkCursorPrivate*) cursor;
+
+ xwindow = window_private->xwindow;
+
+ if (!confine_to)
+ xconfine_to = None;
+ else
+ xconfine_to = confine_to_private->xwindow;
+
+ if (!cursor)
+ xcursor = None;
+ else
+ xcursor = cursor_private->xcursor;
+
+
+ xevent_mask = 0;
+ for (i = 0; i < nevent_masks; i++)
+ {
+ if (event_mask & (1 << (i + 1)))
+ xevent_mask |= event_mask_table[i];
+ }
+
+ if (((GdkWindowPrivate *)window)->extension_events &&
+ gdk_input_vtable.grab_pointer)
+ return_val = gdk_input_vtable.grab_pointer (window,
+ owner_events,
+ event_mask,
+ confine_to,
+ time);
+ else
+ return_val = Success;;
+
+ if (return_val == Success)
+ return_val = XGrabPointer (window_private->xdisplay,
+ xwindow,
+ owner_events,
+ xevent_mask,
+ GrabModeAsync, GrabModeAsync,
+ xconfine_to,
+ xcursor,
+ time);
+
+ return return_val;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_pointer_ungrab
+ *
+ * Releases any pointer grab
+ *
+ * Arguments:
+ *
+ * Results:
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+gdk_pointer_ungrab (guint32 time)
+{
+ if (gdk_input_vtable.ungrab_pointer)
+ gdk_input_vtable.ungrab_pointer (time);
+
+ XUngrabPointer (gdk_display, time);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_keyboard_grab
+ *
+ * Grabs the keyboard to a specific window
+ *
+ * Arguments:
+ * "window" is the window which will receive the grab
+ * "owner_events" specifies whether events will be reported as is,
+ * or relative to "window"
+ * "time" specifies the time
+ *
+ * Results:
+ *
+ * Side effects:
+ * requires a corresponding call to gdk_keyboard_ungrab
+ *
+ *--------------------------------------------------------------
+ */
+
+gint
+gdk_keyboard_grab (GdkWindow * window,
+ gint owner_events,
+ guint32 time)
+{
+ GdkWindowPrivate *window_private;
+ Window xwindow;
+
+ g_return_val_if_fail (window != NULL, 0);
+
+ window_private = (GdkWindowPrivate*) window;
+ xwindow = window_private->xwindow;
+
+ return XGrabKeyboard (window_private->xdisplay,
+ xwindow,
+ owner_events,
+ GrabModeAsync, GrabModeAsync,
+ time);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_keyboard_ungrab
+ *
+ * Releases any keyboard grab
+ *
+ * Arguments:
+ *
+ * Results:
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+gdk_keyboard_ungrab (guint32 time)
+{
+ XUngrabKeyboard (gdk_display, time);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_screen_width
+ *
+ * Return the width of the screen.
+ *
+ * Arguments:
+ *
+ * Results:
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+gint
+gdk_screen_width ()
+{
+ gint return_val;
+
+ return_val = DisplayWidth (gdk_display, gdk_screen);
+
+ return return_val;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_screen_height
+ *
+ * Return the height of the screen.
+ *
+ * Arguments:
+ *
+ * Results:
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+gint
+gdk_screen_height ()
+{
+ gint return_val;
+
+ return_val = DisplayHeight (gdk_display, gdk_screen);
+
+ return return_val;
+}
+
+void
+gdk_key_repeat_disable ()
+{
+ XAutoRepeatOff (gdk_display);
+}
+
+void
+gdk_key_repeat_restore ()
+{
+ if (autorepeat)
+ XAutoRepeatOn (gdk_display);
+ else
+ XAutoRepeatOff (gdk_display);
+}
+
+
+/*
+ *--------------------------------------------------------------
+ * gdk_flush
+ *
+ * Flushes the Xlib output buffer and then waits
+ * until all requests have been received and processed
+ * by the X server. The only real use for this function
+ * is in dealing with XShm.
+ *
+ * Arguments:
+ *
+ * Results:
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+void gdk_flush ()
+{
+ XSync (gdk_display, False);
+}
+
+
+void
+gdk_beep ()
+{
+ XBell(gdk_display, 100);
+}
+
+
+/*
+ *--------------------------------------------------------------
+ * gdk_event_wait
+ *
+ * Waits until an event occurs or the timer runs out.
+ *
+ * Arguments:
+ *
+ * Results:
+ * Returns TRUE if an event is ready to be read and FALSE
+ * if the timer ran out.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+static gint
+gdk_event_wait ()
+{
+ GList *list;
+ GdkInput *input;
+ GdkInputCondition condition;
+ SELECT_MASK readfds;
+ SELECT_MASK writefds;
+ SELECT_MASK exceptfds;
+ int max_input;
+ int nfd;
+
+ /* If there are no events pending we will wait for an event.
+ * The time we wait is dependant on the "timer". If no timer
+ * has been specified then we'll block until an event arrives.
+ * If a timer has been specified we'll block until an event
+ * arrives or the timer expires. (This is all done using the
+ * "select" system call).
+ */
+
+ if (XPending (gdk_display) == 0)
+ {
+ FD_ZERO (&readfds);
+ FD_ZERO (&writefds);
+ FD_ZERO (&exceptfds);
+
+ FD_SET (connection_number, &readfds);
+ max_input = connection_number;
+
+ list = inputs;
+ while (list)
+ {
+ input = list->data;
+ list = list->next;
+
+ if (input->condition & GDK_INPUT_READ)
+ FD_SET (input->source, &readfds);
+ if (input->condition & GDK_INPUT_WRITE)
+ FD_SET (input->source, &writefds);
+ if (input->condition & GDK_INPUT_EXCEPTION)
+ FD_SET (input->source, &exceptfds);
+
+ max_input = MAX (max_input, input->source);
+ }
+
+ nfd = select (max_input+1, &readfds, &writefds, &exceptfds, timerp);
+
+ timerp = NULL;
+ timer_val = 0;
+
+ if (nfd > 0)
+ {
+ if (FD_ISSET (connection_number, &readfds))
+ {
+ if (XPending (gdk_display) == 0)
+ {
+ if (nfd == 1)
+ {
+ XNoOp (gdk_display);
+ XFlush (gdk_display);
+ }
+ return FALSE;
+ }
+ else
+ return TRUE;
+ }
+
+ list = inputs;
+ while (list)
+ {
+ input = list->data;
+ list = list->next;
+
+ condition = 0;
+ if (FD_ISSET (input->source, &readfds))
+ condition |= GDK_INPUT_READ;
+ if (FD_ISSET (input->source, &writefds))
+ condition |= GDK_INPUT_WRITE;
+ if (FD_ISSET (input->source, &exceptfds))
+ condition |= GDK_INPUT_EXCEPTION;
+
+ if (condition && input->function)
+ (* input->function) (input->data, input->source, condition);
+ }
+ }
+ }
+ else
+ return TRUE;
+
+ return FALSE;
+}
+
+static gint
+gdk_event_translate (GdkEvent *event,
+ XEvent *xevent)
+{
+
+ GdkWindow *window;
+ GdkWindowPrivate *window_private;
+ XComposeStatus compose;
+ int charcount;
+ char buf[16];
+ gint return_val;
+
+ /* Are static variables used for this purpose thread-safe? */
+ static GdkPoint dnd_drag_start = {0,0},
+ dnd_drag_oldpos = {0,0};
+ static GdkRectangle dnd_drag_dropzone = {0,0,0,0};
+ static gint dnd_drag_perhaps = 0;
+ static GdkWindowPrivate *real_sw = NULL;
+ static Window dnd_drag_curwin = None, dnd_drag_target = None;
+
+ return_val = FALSE;
+
+ /* Find the GdkWindow that this event occurred in.
+ * All events occur in some GdkWindow (otherwise, why
+ * would we be receiving them). It really is an error
+ * to receive an event for which we cannot find the
+ * corresponding GdkWindow. We handle events with window=None
+ * specially - they are generated by XFree86's XInput under
+ * some circumstances.
+ */
+
+ if ((xevent->xany.window == None) &&
+ gdk_input_vtable.window_none_event)
+ {
+ return_val = gdk_input_vtable.window_none_event (event,xevent);
+
+ if (return_val >= 0) /* was handled */
+ return return_val;
+ else
+ return_val = FALSE;
+ }
+
+ window = gdk_window_lookup (xevent->xany.window);
+ window_private = (GdkWindowPrivate *) window;
+
+ /* We do a "manual" conversion of the XEvent to a
+ * GdkEvent. The structures are mostly the same so
+ * the conversion is fairly straightforward. We also
+ * optionally print debugging info regarding events
+ * received.
+ */
+ /* Addendum:
+ * During drag & drop you get events where the pointer is
+ * in other windows. Need to just do finer-grained checking
+ */
+ switch (xevent->type)
+ {
+ case KeyPress:
+ /* Lookup the string corresponding to the given keysym.
+ */
+ charcount = XLookupString (&xevent->xkey, buf, 16,
+ (KeySym*) &event->key.keyval,
+ &compose);
+
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("key press:\t\twindow: %ld key: %12s %d\n",
+ xevent->xkey.window - base_id,
+ XKeysymToString (event->key.keyval),
+ event->key.keyval);
+
+ event->key.type = GDK_KEY_PRESS;
+ event->key.window = window;
+ event->key.time = xevent->xkey.time;
+ event->key.state = (GdkModifierType) xevent->xkey.state;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case KeyRelease:
+ /* Lookup the string corresponding to the given keysym.
+ */
+ charcount = XLookupString (&xevent->xkey, buf, 16,
+ (KeySym*) &event->key.keyval,
+ &compose);
+
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("key release:\t\twindow: %ld key: %12s %d\n",
+ xevent->xkey.window - base_id,
+ XKeysymToString (event->key.keyval),
+ event->key.keyval);
+
+ event->key.type = GDK_KEY_RELEASE;
+ event->key.window = window;
+ event->key.time = xevent->xkey.time;
+ event->key.state = (GdkModifierType) xevent->xkey.state;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case ButtonPress:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("button press[%d]:\t\twindow: %ld x,y: %d %d button: %d\n",
+ window_private?window_private->dnd_drag_enabled:0,
+ xevent->xbutton.window - base_id,
+ xevent->xbutton.x, xevent->xbutton.y,
+ xevent->xbutton.button);
+
+ if (window_private &&
+ (window_private->extension_events != 0) &&
+ gdk_input_ignore_core)
+ break;
+
+ event->button.type = GDK_BUTTON_PRESS;
+ event->button.window = window;
+ event->button.time = xevent->xbutton.time;
+ event->button.x = xevent->xbutton.x;
+ event->button.y = xevent->xbutton.y;
+ event->button.pressure = 0.5;
+ event->button.xtilt = 0;
+ event->button.ytilt = 0;
+ event->button.state = (GdkModifierType) xevent->xbutton.state;
+ event->button.button = xevent->xbutton.button;
+ event->button.source = GDK_SOURCE_MOUSE;
+ event->button.deviceid = GDK_CORE_POINTER;
+
+ if ((event->button.time < (button_click_time[1] + TRIPLE_CLICK_TIME)) &&
+ (event->button.window == button_window[1]) &&
+ (event->button.button == button_number[1]))
+ {
+ gdk_synthesize_click (event, 3);
+
+ button_click_time[1] = 0;
+ button_click_time[0] = 0;
+ button_window[1] = NULL;
+ button_window[0] = 0;
+ button_number[1] = -1;
+ button_number[0] = -1;
+ }
+ else if ((event->button.time < (button_click_time[0] + DOUBLE_CLICK_TIME)) &&
+ (event->button.window == button_window[0]) &&
+ (event->button.button == button_number[0]))
+ {
+ gdk_synthesize_click (event, 2);
+
+ button_click_time[1] = button_click_time[0];
+ button_click_time[0] = event->button.time;
+ button_window[1] = button_window[0];
+ button_window[0] = event->button.window;
+ button_number[1] = button_number[0];
+ button_number[0] = event->button.button;
+ }
+ else
+ {
+ button_click_time[1] = 0;
+ button_click_time[0] = event->button.time;
+ button_window[1] = NULL;
+ button_window[0] = event->button.window;
+ button_number[1] = -1;
+ button_number[0] = event->button.button;
+ }
+ if(window_private
+ && window_private->dnd_drag_enabled
+ && !dnd_drag_perhaps
+ && !gdk_dnd.drag_really)
+ {
+ dnd_drag_perhaps = 1;
+ dnd_drag_start.x = xevent->xbutton.x_root;
+ dnd_drag_start.y = xevent->xbutton.y_root;
+ real_sw = window_private;
+
+ if(gdk_dnd.drag_startwindows)
+ {
+ g_free(gdk_dnd.drag_startwindows);
+ gdk_dnd.drag_startwindows = NULL;
+ }
+ gdk_dnd.drag_numwindows = gdk_dnd.drag_really = 0;
+
+ {
+ /* Set motion mask for first DnD'd window, since it
+ will be the one that is actually dragged */
+ XWindowAttributes dnd_winattr;
+ XSetWindowAttributes dnd_setwinattr;
+ Status rv;
+
+ /* We need to get motion events while the button is down, so
+ we can know whether to really start dragging or not... */
+ XGetWindowAttributes(gdk_display, (Window)window_private->xwindow,
+ &dnd_winattr);
+
+ window_private->dnd_drag_savedeventmask = dnd_winattr.your_event_mask;
+ dnd_setwinattr.event_mask =
+ window_private->dnd_drag_eventmask = ButtonMotionMask;
+ XChangeWindowAttributes(gdk_display, window_private->xwindow,
+ CWEventMask, &dnd_setwinattr);
+ }
+ }
+ return_val = window_private?(!window_private->destroyed):FALSE;
+ break;
+
+ case ButtonRelease:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("button release[%d]:\twindow: %ld x,y: %d %d button: %d\n",
+ window_private?window_private->dnd_drag_enabled:0,
+ xevent->xbutton.window - base_id,
+ xevent->xbutton.x, xevent->xbutton.y,
+ xevent->xbutton.button);
+
+ if (window_private &&
+ (window_private->extension_events != 0) &&
+ gdk_input_ignore_core)
+ break;
+
+ event->button.type = GDK_BUTTON_RELEASE;
+ event->button.window = window;
+ event->button.time = xevent->xbutton.time;
+ event->button.x = xevent->xbutton.x;
+ event->button.y = xevent->xbutton.y;
+ event->button.pressure = 0.5;
+ event->button.xtilt = 0;
+ event->button.ytilt = 0;
+ event->button.state = (GdkModifierType) xevent->xbutton.state;
+ event->button.button = xevent->xbutton.button;
+ event->button.source = GDK_SOURCE_MOUSE;
+ event->button.deviceid = GDK_CORE_POINTER;
+
+ if(dnd_drag_perhaps)
+ {
+ if(gdk_dnd.drag_really)
+ {
+ GdkPoint foo = {xevent->xbutton.x_root,
+ xevent->xbutton.y_root};
+ XUngrabPointer(gdk_display, CurrentTime);
+
+ if(dnd_drag_target != None)
+ gdk_dnd_drag_end(dnd_drag_target, foo);
+ gdk_dnd.drag_really = 0;
+
+ if(gdk_dnd.drag_numwindows)
+ {
+ XSetWindowAttributes attrs;
+ /* Reset event mask to pre-drag value, assuming event_mask
+ doesn't change during drag */
+ attrs.event_mask = real_sw->dnd_drag_savedeventmask;
+ XChangeWindowAttributes(gdk_display, real_sw->xwindow,
+ CWEventMask, &attrs);
+ }
+
+ gdk_dnd.drag_numwindows = 0;
+ if(gdk_dnd.drag_startwindows)
+ {
+ g_free(gdk_dnd.drag_startwindows);
+ gdk_dnd.drag_startwindows = NULL;
+ }
+
+ real_sw = NULL;
+ }
+
+ dnd_drag_perhaps = 0;
+ dnd_drag_start.x = dnd_drag_start.y = 0;
+ dnd_drag_dropzone.x = dnd_drag_dropzone.y = 0;
+ dnd_drag_dropzone.width = dnd_drag_dropzone.height = 0;
+ dnd_drag_curwin = None;
+ }
+ return_val = window ? (!window_private->destroyed) : FALSE;
+ break;
+
+ case MotionNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("motion notify:\t\twindow: %ld x,y: %d %d hint: %s d:%d r%d\n",
+ xevent->xmotion.window - base_id,
+ xevent->xmotion.x, xevent->xmotion.y,
+ (xevent->xmotion.is_hint) ? "true" : "false",
+ dnd_drag_perhaps, gdk_dnd.drag_really);
+
+ if (window_private &&
+ (window_private->extension_events != 0) &&
+ gdk_input_ignore_core)
+ break;
+
+ event->motion.type = GDK_MOTION_NOTIFY;
+ event->motion.window = window;
+ event->motion.time = xevent->xmotion.time;
+ event->motion.x = xevent->xmotion.x;
+ event->motion.y = xevent->xmotion.y;
+ event->motion.pressure = 0.5;
+ event->motion.xtilt = 0;
+ event->motion.ytilt = 0;
+ event->motion.state = (GdkModifierType) xevent->xmotion.state;
+ event->motion.is_hint = xevent->xmotion.is_hint;
+ event->motion.source = GDK_SOURCE_MOUSE;
+ event->motion.deviceid = GDK_CORE_POINTER;
+
+#define IS_IN_ZONE(cx, cy) (cx >= dnd_drag_dropzone.x \
+ && cy >= dnd_drag_dropzone.y \
+ && cx < (dnd_drag_dropzone.x + dnd_drag_dropzone.width) \
+ && cy < (dnd_drag_dropzone.y + dnd_drag_dropzone.height))
+
+ if(dnd_drag_perhaps && gdk_dnd.drag_really)
+ {
+ /* First, we have to find what window the motion was in... */
+ /* XXX there has to be a better way to do this, perhaps with
+ XTranslateCoordinates or XQueryTree - I don't know how,
+ and this sort of works */
+ Window curwin, childwin = gdk_root_window, rootwinret;
+ int x, y;
+ unsigned int mask;
+ while(childwin != None)
+ {
+ curwin = childwin;
+ XQueryPointer(gdk_display, curwin, &rootwinret, &childwin,
+ &x, &y, &x, &y, &mask);
+ }
+ if(curwin != dnd_drag_curwin)
+ {
+ /* We have left one window and entered another
+ (do leave & enter bits) */
+ if(dnd_drag_curwin != real_sw->xwindow && dnd_drag_curwin != None)
+ gdk_dnd_drag_leave(dnd_drag_curwin);
+ dnd_drag_curwin = curwin;
+ gdk_dnd_drag_enter(dnd_drag_curwin);
+ dnd_drag_dropzone.x = dnd_drag_dropzone.y = 0;
+ dnd_drag_dropzone.width = dnd_drag_dropzone.height = 0;
+ dnd_drag_target = None;
+ XChangeActivePointerGrab(gdk_display,
+ ButtonMotionMask |
+ ButtonPressMask | ButtonReleaseMask |
+ EnterWindowMask | LeaveWindowMask,
+ gdk_dnd.gdk_cursor_dragdefault,
+ CurrentTime);
+ }
+ else if(dnd_drag_dropzone.width > 0
+ && dnd_drag_dropzone.height > 0)
+ {
+ /* Handle all that dropzone stuff - thanks John ;-) */
+ if(dnd_drag_target != None
+ && IS_IN_ZONE(dnd_drag_oldpos.x, dnd_drag_oldpos.y)
+ && !IS_IN_ZONE(xevent->xmotion.x_root,
+ xevent->xmotion.y_root))
+ {
+ /* We were in the drop zone and moved out */
+ dnd_drag_target = None;
+ gdk_dnd_drag_leave(curwin);
+ }
+ else
+ {
+ /* We were outside drop zone but in the window
+ - have to send enter events */
+ gdk_dnd_drag_enter(curwin);
+ dnd_drag_curwin = curwin;
+ dnd_drag_dropzone.x = dnd_drag_dropzone.y = 0;
+ dnd_drag_target = None;
+ }
+ } else
+ dnd_drag_curwin = None;
+ return_val = FALSE;
+ }
+ else
+ return_val = window?(!window_private->destroyed):FALSE;
+ break;
+
+ case EnterNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("enter notify:\t\twindow: %ld detail: %d subwin: %ld\n",
+ xevent->xcrossing.window - base_id,
+ xevent->xcrossing.detail,
+ xevent->xcrossing.subwindow - base_id);
+
+ /* Tell XInput stuff about it if appropriate */
+ if (window_private &&
+ (window_private->extension_events != 0) &&
+ gdk_input_vtable.enter_event)
+ gdk_input_vtable.enter_event (&xevent->xcrossing, window);
+
+ event->crossing.type = GDK_ENTER_NOTIFY;
+ event->crossing.window = window;
+
+ /* If the subwindow field of the XEvent is non-NULL, then
+ * lookup the corresponding GdkWindow.
+ */
+ if (xevent->xcrossing.subwindow != None)
+ event->crossing.subwindow = gdk_window_lookup (xevent->xcrossing.subwindow);
+ else
+ event->crossing.subwindow = NULL;
+
+ /* Translate the crossing detail into Gdk terms.
+ */
+ switch (xevent->xcrossing.detail)
+ {
+ case NotifyInferior:
+ event->crossing.detail = GDK_NOTIFY_INFERIOR;
+ break;
+ case NotifyAncestor:
+ event->crossing.detail = GDK_NOTIFY_ANCESTOR;
+ break;
+ case NotifyVirtual:
+ event->crossing.detail = GDK_NOTIFY_VIRTUAL;
+ break;
+ case NotifyNonlinear:
+ event->crossing.detail = GDK_NOTIFY_NONLINEAR;
+ break;
+ case NotifyNonlinearVirtual:
+ event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
+ break;
+ default:
+ event->crossing.detail = GDK_NOTIFY_UNKNOWN;
+ break;
+ }
+
+ if(dnd_drag_perhaps
+ && gdk_dnd.drag_really
+ && xevent->xcrossing.window == real_sw->xwindow)
+ {
+ gdk_dnd.drag_really = 0;
+ XUngrabPointer(gdk_display, CurrentTime);
+ }
+
+ return_val = (window ? !window_private->destroyed : FALSE);
+ break;
+
+ case LeaveNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("leave notify:\t\twindow: %ld detail: %d subwin: %ld\n",
+ xevent->xcrossing.window - base_id,
+ xevent->xcrossing.detail, xevent->xcrossing.subwindow - base_id);
+
+ event->crossing.type = GDK_LEAVE_NOTIFY;
+ event->crossing.window = window;
+
+ /* Translate the crossing detail into Gdk terms.
+ */
+ switch (xevent->xcrossing.detail)
+ {
+ case NotifyInferior:
+ event->crossing.detail = GDK_NOTIFY_INFERIOR;
+ break;
+ case NotifyAncestor:
+ event->crossing.detail = GDK_NOTIFY_ANCESTOR;
+ break;
+ case NotifyVirtual:
+ event->crossing.detail = GDK_NOTIFY_VIRTUAL;
+ break;
+ case NotifyNonlinear:
+ event->crossing.detail = GDK_NOTIFY_NONLINEAR;
+ break;
+ case NotifyNonlinearVirtual:
+ event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
+ break;
+ default:
+ event->crossing.detail = GDK_NOTIFY_UNKNOWN;
+ break;
+ }
+ if(dnd_drag_perhaps
+ && !gdk_dnd.drag_really)
+ {
+ gdk_dnd_drag_addwindow((GdkWindow *) real_sw);
+ gdk_dnd_drag_begin((GdkWindow *) real_sw);
+ XGrabPointer(gdk_display, real_sw->xwindow, False,
+ ButtonMotionMask |
+ ButtonPressMask | ButtonReleaseMask |
+ EnterWindowMask | LeaveWindowMask,
+ GrabModeAsync, GrabModeAsync, gdk_root_window,
+ gdk_dnd.gdk_cursor_dragdefault, CurrentTime);
+ gdk_dnd.drag_really = 1;
+ }
+ return_val = window ? (!window_private->destroyed) : FALSE;
+ break;
+
+ case FocusIn:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("focus in:\t\twindow: %ld\n",
+ xevent->xfocus.window - base_id);
+
+ event->focus_change.type = GDK_FOCUS_CHANGE;
+ event->focus_change.window = window;
+ event->focus_change.in = TRUE;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case FocusOut:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("focus out:\t\twindow: %ld\n",
+ xevent->xfocus.window - base_id);
+
+ event->focus_change.type = GDK_FOCUS_CHANGE;
+ event->focus_change.window = window;
+ event->focus_change.in = FALSE;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case KeymapNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("keymap notify\n");
+
+ /* Not currently handled */
+ break;
+
+ case Expose:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("expose:\t\twindow: %ld %d x,y: %d %d w,h: %d %d\n",
+ xevent->xexpose.window - base_id, xevent->xexpose.count,
+ xevent->xexpose.x, xevent->xexpose.y,
+ xevent->xexpose.width, xevent->xexpose.height);
+
+ event->expose.type = GDK_EXPOSE;
+ event->expose.window = window;
+ event->expose.area.x = xevent->xexpose.x;
+ event->expose.area.y = xevent->xexpose.y;
+ event->expose.area.width = xevent->xexpose.width;
+ event->expose.area.height = xevent->xexpose.height;
+ event->expose.count = xevent->xexpose.count;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case GraphicsExpose:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("graphics expose:\tdrawable: %ld\n",
+ xevent->xgraphicsexpose.drawable - base_id);
+
+ event->expose.type = GDK_EXPOSE;
+ event->expose.window = window;
+ event->expose.area.x = xevent->xgraphicsexpose.x;
+ event->expose.area.y = xevent->xgraphicsexpose.y;
+ event->expose.area.width = xevent->xgraphicsexpose.width;
+ event->expose.area.height = xevent->xgraphicsexpose.height;
+ event->expose.count = xevent->xexpose.count;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case NoExpose:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("no expose:\t\tdrawable: %ld\n",
+ xevent->xnoexpose.drawable - base_id);
+
+ /* Not currently handled */
+ break;
+
+ case VisibilityNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ switch (xevent->xvisibility.state)
+ {
+ case VisibilityFullyObscured:
+ g_print ("visibility notify:\twindow: %ld none\n",
+ xevent->xvisibility.window - base_id);
+ break;
+ case VisibilityPartiallyObscured:
+ g_print ("visibility notify:\twindow: %ld partial\n",
+ xevent->xvisibility.window - base_id);
+ break;
+ case VisibilityUnobscured:
+ g_print ("visibility notify:\twindow: %ld full\n",
+ xevent->xvisibility.window - base_id);
+ break;
+ }
+
+ /* Not currently handled */
+ break;
+
+ case CreateNotify:
+ /* Not currently handled */
+ break;
+
+ case DestroyNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("destroy notify:\twindow: %ld\n",
+ xevent->xdestroywindow.window - base_id);
+
+ event->any.type = GDK_DESTROY;
+ event->any.window = window;
+
+ /* Remeber which window received the destroy notify
+ * event so that we can destroy our associated
+ * data structures the next time the user asks
+ * us for an event.
+ */
+ received_destroy_notify = TRUE;
+ window_to_destroy = window;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case UnmapNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("unmap notify:\t\twindow: %ld\n",
+ xevent->xmap.window - base_id);
+
+ event->any.type = GDK_UNMAP;
+ event->any.window = window;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case MapNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("map notify:\t\twindow: %ld\n",
+ xevent->xmap.window - base_id);
+
+ event->any.type = GDK_MAP;
+ event->any.window = window;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case ReparentNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("reparent notify:\twindow: %ld\n",
+ xevent->xreparent.window - base_id);
+
+ /* Not currently handled */
+ break;
+
+ case ConfigureNotify:
+ /* Print debugging info.
+ */
+ while ((XPending(gdk_display) > 0) &&
+ XCheckTypedWindowEvent(gdk_display, xevent->xany.window,
+ ConfigureNotify, xevent))
+ /*XSync(gdk_display, 0)*/;
+
+ if (gdk_show_events)
+ g_print ("configure notify:\twindow: %ld x,y: %d %d w,h: %d %d\n",
+ xevent->xconfigure.window - base_id,
+ xevent->xconfigure.x, xevent->xconfigure.y,
+ xevent->xconfigure.width, xevent->xconfigure.height);
+
+ if (window_private &&
+ (window_private->extension_events != 0) &&
+ gdk_input_vtable.configure_event)
+ gdk_input_vtable.configure_event (&xevent->xconfigure, window);
+
+ if ((window_private->window_type != GDK_WINDOW_CHILD) &&
+ ((window_private->width != xevent->xconfigure.width) ||
+ (window_private->height != xevent->xconfigure.height)))
+ {
+ event->configure.type = GDK_CONFIGURE;
+ event->configure.window = window;
+ event->configure.x = xevent->xconfigure.x;
+ event->configure.y = xevent->xconfigure.y;
+ event->configure.width = xevent->xconfigure.width;
+ event->configure.height = xevent->xconfigure.height;
+
+ window_private->x = xevent->xconfigure.x;
+ window_private->y = xevent->xconfigure.y;
+ window_private->width = xevent->xconfigure.width;
+ window_private->height = xevent->xconfigure.height;
+ if (window_private->resize_count > 1)
+ window_private->resize_count -= 1;
+
+ return_val = !window_private->destroyed;
+ }
+ break;
+
+ case PropertyNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("property notify:\twindow: %ld\n",
+ xevent->xproperty.window - base_id);
+
+ event->property.type = GDK_PROPERTY_NOTIFY;
+ event->property.window = window;
+ event->property.atom = xevent->xproperty.atom;
+ event->property.time = xevent->xproperty.time;
+ event->property.state = xevent->xproperty.state;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case SelectionClear:
+ if (gdk_show_events)
+ g_print ("selection clear:\twindow: %ld\n",
+ xevent->xproperty.window - base_id);
+
+ event->selection.type = GDK_SELECTION_CLEAR;
+ event->selection.window = window;
+ event->selection.selection = xevent->xselectionclear.selection;
+ event->selection.time = xevent->xselectionclear.time;
+
+ return_val = !((GdkWindowPrivate*) window)->destroyed;
+ break;
+
+ case SelectionRequest:
+ if (gdk_show_events)
+ g_print ("selection request:\twindow: %ld\n",
+ xevent->xproperty.window - base_id);
+
+ event->selection.type = GDK_SELECTION_REQUEST;
+ event->selection.window = window;
+ event->selection.selection = xevent->xselectionrequest.selection;
+ event->selection.target = xevent->xselectionrequest.target;
+ event->selection.property = xevent->xselectionrequest.property;
+ event->selection.requestor = xevent->xselectionrequest.requestor;
+ event->selection.time = xevent->xselectionrequest.time;
+
+ return_val = !((GdkWindowPrivate*) window)->destroyed;
+ break;
+
+ case SelectionNotify:
+ if (gdk_show_events)
+ g_print ("selection notify:\twindow: %ld\n",
+ xevent->xproperty.window - base_id);
+
+
+ event->selection.type = GDK_SELECTION_NOTIFY;
+ event->selection.window = window;
+ event->selection.selection = xevent->xselection.selection;
+ event->selection.target = xevent->xselection.target;
+ event->selection.property = xevent->xselection.property;
+ event->selection.time = xevent->xselection.time;
+
+ return_val = !((GdkWindowPrivate*) window)->destroyed;
+ break;
+
+ case ColormapNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("colormap notify:\twindow: %ld\n",
+ xevent->xcolormap.window - base_id);
+
+ /* Not currently handled */
+ break;
+
+ case ClientMessage:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("client message:\twindow: %ld\n",
+ xevent->xclient.window - base_id);
+
+ /* Client messages are the means of the window manager
+ * communicating with a program. We'll first check to
+ * see if this is really the window manager talking
+ * to us.
+ */
+ if (xevent->xclient.message_type == gdk_wm_protocols)
+ {
+ if ((Atom) xevent->xclient.data.l[0] == gdk_wm_delete_window)
+ {
+ /* The delete window request specifies a window
+ * to delete. We don't actually destroy the
+ * window because "it is only a request". (The
+ * window might contain vital data that the
+ * program does not want destroyed). Instead
+ * the event is passed along to the program,
+ * which should then destroy the window.
+ */
+
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("delete window:\t\twindow: %ld\n",
+ xevent->xclient.window - base_id);
+
+ event->any.type = GDK_DELETE;
+ event->any.window = window;
+
+ return_val = !window_private->destroyed;
+ }
+ else if ((Atom) xevent->xclient.data.l[0] == gdk_wm_take_focus)
+ {
+ }
+ }
+ else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeEnter)
+ {
+ Atom reptype = 0;
+
+ event->dropenter.u.allflags = xevent->xclient.data.l[1];
+ if (gdk_show_events)
+ g_print ("GDK_DROP_ENTER\n");
+ return_val = FALSE;
+
+ /* Now figure out if we really want this drop...
+ * If someone is trying funky clipboard stuff, ignore
+ */
+ if (window_private
+ && window_private->dnd_drop_enabled
+ && event->dropenter.u.flags.sendreply
+ && (reptype = gdk_dnd_check_types (window, xevent)))
+ {
+ XEvent replyev;
+
+ replyev.xclient.type = ClientMessage;
+ replyev.xclient.window = xevent->xclient.data.l[0];
+ replyev.xclient.format = 32;
+ replyev.xclient.message_type = gdk_dnd.gdk_XdeRequest;
+ replyev.xclient.data.l[0] = window_private->xwindow;
+
+ event->dragrequest.u.allflags = 0;
+ event->dragrequest.u.flags.protocol_version =
+ DND_PROTOCOL_VERSION;
+ event->dragrequest.u.flags.willaccept = 1;
+ event->dragrequest.u.flags.delete_data =
+ (window_private->dnd_drop_destructive_op) ? 1 : 0;
+
+ replyev.xclient.data.l[1] = event->dragrequest.u.allflags;
+ replyev.xclient.data.l[2] = replyev.xclient.data.l[3] = 0;
+ replyev.xclient.data.l[4] = reptype;
+
+ XSendEvent (gdk_display, replyev.xclient.window,
+ False, NoEventMask, &replyev);
+
+ event->any.type = GDK_DROP_ENTER;
+ event->dropenter.requestor = replyev.xclient.window;
+ event->dropenter.u.allflags = xevent->xclient.data.l[1];
+ }
+ }
+ else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeLeave)
+ {
+ if (gdk_show_events)
+ g_print ("GDK_DROP_LEAVE\n");
+ if (window_private && window_private->dnd_drop_enabled)
+ {
+ event->dropleave.type = GDK_DROP_LEAVE;
+ event->dropleave.window = window;
+ event->dropleave.requestor = xevent->xclient.data.l[0];
+ event->dropleave.u.allflags = xevent->xclient.data.l[1];
+ return_val = TRUE;
+ }
+ else
+ return_val = FALSE;
+ }
+ else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeRequest)
+ {
+ /*
+ * make sure to only handle requests from the window the cursor is
+ * over
+ */
+ if (gdk_show_events)
+ g_print ("GDK_DRAG_REQUEST\n");
+ event->dragrequest.u.allflags = xevent->xclient.data.l[1];
+ return_val = FALSE;
+
+ if (window && gdk_dnd.drag_really &&
+ xevent->xclient.data.l[0] == dnd_drag_curwin &&
+ event->dragrequest.u.flags.sendreply == 0)
+ {
+ /* Got request - do we need to ask user? */
+ if (!event->dragrequest.u.flags.willaccept
+ && event->dragrequest.u.flags.senddata)
+ {
+ /* Yes we do :) */
+ event->dragrequest.type = GDK_DRAG_REQUEST;
+ event->dragrequest.window = window;
+ event->dragrequest.requestor = xevent->xclient.data.l[0];
+ event->dragrequest.isdrop = 0;
+ event->dragrequest.drop_coords.x =
+ event->dragrequest.drop_coords.y = 0;
+ return_val = TRUE;
+ }
+ else if (event->dragrequest.u.flags.willaccept)
+ {
+ window_private->dnd_drag_destructive_op =
+ event->dragrequest.u.flags.delete_data;
+ window_private->dnd_drag_accepted = 1;
+ window_private->dnd_drag_data_type =
+ xevent->xclient.data.l[4];
+
+ dnd_drag_target = dnd_drag_curwin;
+ XChangeActivePointerGrab (gdk_display,
+ ButtonMotionMask |
+ ButtonPressMask |
+ ButtonReleaseMask |
+ EnterWindowMask | LeaveWindowMask,
+ gdk_dnd.gdk_cursor_dragok,
+ CurrentTime);
+ }
+ dnd_drag_dropzone.x = xevent->xclient.data.l[2] & 65535;
+ dnd_drag_dropzone.y =
+ (xevent->xclient.data.l[2] >> 16) & 65535;
+ dnd_drag_dropzone.width = xevent->xclient.data.l[3] & 65535;
+ dnd_drag_dropzone.height =
+ (xevent->xclient.data.l[3] >> 16) & 65535;
+ }
+ }
+ else if(xevent->xclient.message_type == gdk_dnd.gdk_XdeDataAvailable)
+ {
+ gint tmp_int; Atom tmp_atom;
+ gulong tmp_long;
+ guchar *tmp_charptr;
+ gpointer tmp_ptr;
+
+ if(gdk_show_events)
+ g_print("GDK_DROP_DATA_AVAIL\n");
+ event->dropdataavailable.u.allflags = xevent->xclient.data.l[1];
+ if(window
+ /* No preview of data ATM */
+ && event->dropdataavailable.u.flags.isdrop)
+ {
+ event->dropdataavailable.type = GDK_DROP_DATA_AVAIL;
+ event->dropdataavailable.window = window;
+ event->dropdataavailable.requestor = xevent->xclient.data.l[0];
+ event->dropdataavailable.data_type =
+ gdk_atom_name(xevent->xclient.data.l[2]);
+ if(XGetWindowProperty (gdk_display,
+ event->dropdataavailable.requestor,
+ xevent->xclient.data.l[2],
+ 0, LONG_MAX - 1,
+ False, XA_PRIMARY, &tmp_atom,
+ &tmp_int,
+ &event->dropdataavailable.data_numbytes,
+ &tmp_long,
+ &tmp_charptr)
+ != Success)
+ {
+ g_warning("XGetWindowProperty on %#x may have failed\n",
+ event->dropdataavailable.requestor);
+ event->dropdataavailable.data = NULL;
+ }
+ else
+ {
+ g_print("XGetWindowProperty got us %d bytes\n",
+ event->dropdataavailable.data_numbytes);
+ event->dropdataavailable.data =
+ g_malloc(event->dropdataavailable.data_numbytes);
+ memcpy(event->dropdataavailable.data,
+ tmp_charptr, event->dropdataavailable.data_numbytes);
+ XFree(tmp_charptr);
+ return_val = TRUE;
+ }
+ return_val = TRUE;
+ }
+ } else {
+ /* Send unknown ClientMessage's on to Gtk for it to use */
+ event->client.type = GDK_CLIENT_EVENT;
+ event->client.window = window;
+ event->client.message_type = xevent->xclient.message_type;
+ event->client.data_format = xevent->xclient.format;
+ memcpy(&event->client.data, &xevent->xclient.data,
+ sizeof(event->client.data));
+ return_val = TRUE;
+ }
+ return_val = return_val && !window_private->destroyed;
+ break;
+
+ case MappingNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("mapping notify\n");
+
+ /* Let XLib know that there is a new keyboard mapping.
+ */
+ XRefreshKeyboardMapping (&xevent->xmapping);
+ break;
+
+ default:
+ /* something else - (e.g., a Xinput event) */
+
+ if (window_private &&
+ (window_private->extension_events != 0) &&
+ gdk_input_vtable.other_event)
+ return_val = gdk_input_vtable.other_event(event, xevent, window);
+
+ if (return_val < 0) /* not an XInput event, convert */
+ {
+ event->other.type = GDK_OTHER_EVENT;
+ event->other.window = window;
+ event->other.xevent = &other_xevent[other_xevent_i];
+ memcpy (&other_xevent[other_xevent_i], xevent, sizeof (XEvent));
+ other_xevent_i = (other_xevent_i+1) % OTHER_XEVENT_BUFSIZE;
+ return_val = TRUE;
+ }
+
+ return_val = return_val && !window_private->destroyed;
+ break;
+ }
+
+ return return_val;
+}
+
+static Bool
+gdk_event_get_type (Display *display,
+ XEvent *xevent,
+ XPointer arg)
+{
+ GdkEvent event;
+ GdkPredicate *pred;
+
+ if (gdk_event_translate (&event, xevent))
+ {
+ pred = (GdkPredicate*) arg;
+ return (* pred->func) (&event, pred->data);
+ }
+
+ return FALSE;
+}
+
+static void
+gdk_synthesize_click (GdkEvent *event,
+ gint nclicks)
+{
+ GdkEvent temp_event;
+
+ g_return_if_fail (event != NULL);
+
+ temp_event = *event;
+ temp_event.type = (nclicks == 2) ? GDK_2BUTTON_PRESS : GDK_3BUTTON_PRESS;
+
+ gdk_event_put (&temp_event);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_exit_func
+ *
+ * This is the "atexit" function that makes sure the
+ * library gets a chance to cleanup.
+ *
+ * Arguments:
+ *
+ * Results:
+ *
+ * Side effects:
+ * The library is un-initialized and the program exits.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+gdk_exit_func ()
+{
+ if (initialized)
+ {
+ gdk_image_exit ();
+ gdk_input_exit ();
+ gdk_key_repeat_restore ();
+
+ XCloseDisplay (gdk_display);
+ initialized = 0;
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_x_error
+ *
+ * The X error handling routine.
+ *
+ * Arguments:
+ * "display" is the X display the error orignated from.
+ * "error" is the XErrorEvent that we are handling.
+ *
+ * Results:
+ * Either we were expecting some sort of error to occur,
+ * in which case we set the "gdk_error_code" flag, or this
+ * error was unexpected, in which case we will print an
+ * error message and exit. (Since trying to continue will
+ * most likely simply lead to more errors).
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+gdk_x_error (Display *display,
+ XErrorEvent *error)
+{
+ char buf[64];
+
+ if (gdk_error_warnings)
+ {
+ XGetErrorText (display, error->error_code, buf, 63);
+ g_error ("%s", buf);
+ }
+
+ gdk_error_code = -1;
+ return 0;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_x_io_error
+ *
+ * The X I/O error handling routine.
+ *
+ * Arguments:
+ * "display" is the X display the error orignated from.
+ *
+ * Results:
+ * An X I/O error basically means we lost our connection
+ * to the X server. There is not much we can do to
+ * continue, so simply print an error message and exit.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+gdk_x_io_error (Display *display)
+{
+ g_error ("an x io error occurred");
+ return 0;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_signal
+ *
+ * The signal handler.
+ *
+ * Arguments:
+ * "sig_num" is the number of the signal we received.
+ *
+ * Results:
+ * The signals we catch are all fatal. So we simply build
+ * up a nice little error message and print it and exit.
+ * If in the process of doing so another signal is received
+ * we notice that we are already exiting and simply kill
+ * our process.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+static RETSIGTYPE
+gdk_signal (int sig_num)
+{
+ static int caught_fatal_sig = 0;
+ char *sig;
+
+ if (caught_fatal_sig)
+ kill (getpid (), sig_num);
+ caught_fatal_sig = 1;
+
+ switch (sig_num)
+ {
+ case SIGHUP:
+ sig = "sighup";
+ break;
+ case SIGINT:
+ sig = "sigint";
+ break;
+ case SIGQUIT:
+ sig = "sigquit";
+ break;
+ case SIGBUS:
+ sig = "sigbus";
+ break;
+ case SIGSEGV:
+ sig = "sigsegv";
+ break;
+ case SIGPIPE:
+ sig = "sigpipe";
+ break;
+ case SIGTERM:
+ sig = "sigterm";
+ break;
+ default:
+ sig = "unknown signal";
+ break;
+ }
+
+ g_print ("\n** ERROR **: %s caught\n", sig);
+ gdk_exit (1);
+}
+
+static void
+gdk_dnd_drag_begin (GdkWindow *initial_window)
+{
+ GdkEventDragBegin tev;
+ tev.type = GDK_DRAG_BEGIN;
+ tev.window = initial_window;
+ tev.u.allflags = 0;
+ tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
+
+ gdk_event_put ((GdkEvent *) &tev);
+}
+
+static void
+gdk_dnd_drag_enter (Window dest)
+{
+ XEvent sev;
+ GdkEventDropEnter tev;
+ int i;
+ GdkWindowPrivate *wp;
+
+ sev.xclient.type = ClientMessage;
+ sev.xclient.format = 32;
+ sev.xclient.message_type = gdk_dnd.gdk_XdeEnter;
+ sev.xclient.window = dest;
+
+ tev.u.allflags = 0;
+ tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
+ tev.u.flags.sendreply = 1;
+ for (i = 0; i < gdk_dnd.drag_numwindows; i++)
+ {
+ wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
+ if (wp->dnd_drag_data_numtypesavail)
+ {
+ sev.xclient.data.l[0] = wp->xwindow;
+ tev.u.flags.extended_typelist = (wp->dnd_drag_data_numtypesavail > 3)?1:0;
+ sev.xclient.data.l[1] = tev.u.allflags;
+ sev.xclient.data.l[2] = wp->dnd_drag_data_typesavail[0];
+ if (wp->dnd_drag_data_numtypesavail > 1)
+ {
+ sev.xclient.data.l[3] = wp->dnd_drag_data_typesavail[1];
+ if (wp->dnd_drag_data_numtypesavail > 2)
+ {
+ sev.xclient.data.l[4] = wp->dnd_drag_data_typesavail[2];
+ }
+ else
+ sev.xclient.data.l[4] = None;
+ }
+ else
+ sev.xclient.data.l[3] = sev.xclient.data.l[4] = None;
+ XSendEvent (gdk_display, dest, False, NoEventMask, &sev);
+ }
+
+ }
+}
+
+static void
+gdk_dnd_drag_leave (Window dest)
+{
+ XEvent sev;
+ GdkEventDropLeave tev;
+ int i;
+ GdkWindowPrivate *wp;
+
+ tev.u.allflags = 0;
+
+ tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
+ sev.xclient.type = ClientMessage;
+ sev.xclient.window = dest;
+ sev.xclient.format = 32;
+ sev.xclient.message_type = gdk_dnd.gdk_XdeLeave;
+ sev.xclient.data.l[1] = tev.u.allflags;
+ for (i = 0; i < gdk_dnd.drag_numwindows; i++)
+ {
+ wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
+ sev.xclient.data.l[0] = wp->xwindow;
+ XSendEvent(gdk_display, dest, False, NoEventMask, &sev);
+ wp->dnd_drag_accepted = 0;
+ }
+}
+
+/*
+ * when a drop occurs, we go through the list of windows being dragged and
+ * tell them that it has occurred, so that they can set things up and reply
+ * to 'dest' window
+ */
+static void
+gdk_dnd_drag_end (Window dest,
+ GdkPoint coords)
+{
+ GdkWindowPrivate *wp;
+ GdkEventDragRequest tev;
+ gchar *tmp_cptr;
+ int i;
+
+ tev.type = GDK_DRAG_REQUEST;
+ tev.drop_coords = coords;
+ tev.requestor = dest;
+ tev.u.allflags = 0;
+ tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
+ tev.isdrop = 1;
+
+ for (i = 0; i < gdk_dnd.drag_numwindows; i++)
+ {
+ wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
+ if (wp->dnd_drag_accepted)
+ {
+ tev.window = (GdkWindow *) wp;
+ tev.u.flags.delete_data = wp->dnd_drag_destructive_op;
+ tev.data_type =
+ gdk_atom_name(wp->dnd_drag_data_type);
+
+ gdk_event_put((GdkEvent *) &tev);
+ }
+ }
+}
+
+static GdkAtom
+gdk_dnd_check_types (GdkWindow *window,
+ XEvent *xevent)
+{
+ GdkWindowPrivate *wp = (GdkWindowPrivate *) window;
+ int i, j;
+ GdkEventDropEnter event;
+
+ g_return_val_if_fail(window != NULL, 0);
+ g_return_val_if_fail(xevent != NULL, 0);
+ g_return_val_if_fail(xevent->type == ClientMessage, 0);
+ g_return_val_if_fail(xevent->xclient.message_type == gdk_dnd.gdk_XdeEnter, 0);
+
+ if(wp->dnd_drop_data_numtypesavail <= 0 ||
+ !wp->dnd_drop_data_typesavail)
+ return 0;
+
+ for (i = 2; i <= 4; i++)
+ {
+ for (j = 0; j < wp->dnd_drop_data_numtypesavail; j++)
+ {
+ if (xevent->xclient.data.l[i] == wp->dnd_drop_data_typesavail[j])
+ return xevent->xclient.data.l[i];
+ }
+ }
+
+ /* Now we get the extended type list if it's available */
+ event.u.allflags = xevent->xclient.data.l[1];
+ if (event.u.flags.extended_typelist)
+ {
+ Atom *exttypes, realtype;
+ gulong nitems, nbar;
+ gint realfmt;
+
+ if (XGetWindowProperty(gdk_display, xevent->xclient.data.l[0],
+ gdk_dnd.gdk_XdeTypelist, 0L, LONG_MAX - 1,
+ False, AnyPropertyType, &realtype, &realfmt,
+ &nitems, &nbar, (unsigned char **) &exttypes)
+ != Success)
+ return 0;
+
+ if (realfmt != (sizeof(Atom) * 8))
+ {
+ g_warning("XdeTypelist property had format of %d instead of the expected %d, on window %#lx\n",
+ realfmt, sizeof(Atom) * 8, xevent->xclient.data.l[0]);
+ return 0;
+ }
+
+ for (i = 0; i <= nitems; i++)
+ {
+ for (j = 0; j < wp->dnd_drop_data_numtypesavail; j++)
+ {
+ if (exttypes[i] == wp->dnd_drop_data_typesavail[j])
+ {
+ XFree (exttypes);
+ return exttypes[i];
+ }
+ }
+ }
+ XFree (exttypes);
+ }
+ return 0;
+}
+
+/*
+ * used for debugging only
+ */
+static void
+gdk_print_atom (GdkAtom anatom)
+{
+ gchar *tmpstr = NULL;
+ tmpstr = (anatom!=None)?gdk_atom_name(anatom):"(none)";
+ g_print("Atom %lu has name %s\n", anatom, tmpstr);
+ if(tmpstr)
+ g_free(tmpstr);
+}
+
+/*
+ * used only by below routine and itself
+ */
+static Window
+getchildren (Display *dpy,
+ Window win,
+ Atom WM_STATE)
+{
+ Window root, parent, *children, inf = 0;
+ Atom type = None;
+ unsigned int nchildren, i;
+ int format;
+ unsigned long nitems, after;
+ unsigned char *data;
+
+ if (XQueryTree(dpy, win, &root, &parent, &children, &nchildren) == 0)
+ return 0;
+
+ for (i = 0; !inf && (i < nchildren); i++)
+ {
+ XGetWindowProperty (dpy, children[i], WM_STATE, 0, 0, False,
+ AnyPropertyType, &type, &format, &nitems,
+ &after, &data);
+ if (type != 0)
+ inf = children[i];
+ }
+
+ for (i = 0; !inf && (i < nchildren); i++)
+ inf = getchildren (dpy, children[i], WM_STATE);
+
+ if (children != 0)
+ XFree ((char *) children);
+
+ return inf;
+}
+
+/*
+ * find a window with WM_STATE, else return win itself, as per ICCCM
+ *
+ * modification of the XmuClientWindow() routine from X11R6.3
+ */
+Window
+gdk_get_client_window (Display *dpy,
+ Window win)
+{
+ Atom WM_STATE;
+ Atom type = None;
+ int format;
+ unsigned long nitems, after;
+ unsigned char *data;
+ Window inf;
+
+ if (win == 0)
+ return DefaultRootWindow(dpy);
+
+ if ((WM_STATE = XInternAtom (dpy, "WM_STATE", True)) == 0)
+ return win;
+
+ XGetWindowProperty (dpy, win, WM_STATE, 0, 0, False, AnyPropertyType,
+ &type, &format, &nitems, &after, &data);
+ if (type)
+ return win;
+
+ inf = getchildren (dpy, win, WM_STATE);
+
+ if (inf == 0)
+ return win;
+ else
+ return inf;
+}
+
+static GdkWindow *
+gdk_drop_get_real_window (GdkWindow *w,
+ guint16 *x,
+ guint16 *y)
+{
+ GdkWindow *retval = w;
+ GdkWindowPrivate *awin;
+ GList *children;
+ gint16 myx = *x, myy = *y;
+
+ g_return_val_if_fail(w != NULL && x != NULL && y != NULL, NULL);
+
+ myx = *x;
+ myy = *y;
+
+descend:
+ for (children = gdk_window_get_children(retval);
+ children && children->next;
+ children = children->next)
+ {
+ awin = (GdkWindowPrivate *) children->data;
+ if ((myx >= awin->x) && (myy >= awin->y)
+ && (myx < (awin->x + awin->width))
+ && (myy < (awin->y + awin->height)))
+ {
+ retval = (GdkWindow *) awin;
+ myx -= awin->x;
+ myy -= awin->y;
+ goto descend;
+ }
+ }
+
+ *x = myx;
+ *y = myy;
+
+ return retval;
+}
+
+/* Sends a ClientMessage to all toplevel client windows */
+void
+gdk_event_send_clientmessage_toall(GdkEvent *event)
+{
+ XEvent sev;
+ Window *ret_children, ret_root, ret_parent, curwin;
+ unsigned int ret_nchildren;
+ int i;
+
+ g_return_if_fail(event != NULL);
+
+ /* Set up our event to send, with the exception of its target window */
+ sev.xclient.type = ClientMessage;
+ sev.xclient.display = gdk_display;
+ sev.xclient.format = event->client.data_format;
+ sev.xclient.serial = CurrentTime;
+ memcpy(&sev.xclient.data, &event->client.data, sizeof(sev.xclient.data));
+ sev.xclient.message_type = event->client.message_type;
+
+ /* OK, we're all set, now let's find some windows to send this to */
+ if(XQueryTree(gdk_display, gdk_root_window, &ret_root, &ret_parent,
+ &ret_children, &ret_nchildren) != True)
+ return;
+
+ /* foreach true child window of the root window, send an event to it */
+ for(i = 0; i < ret_nchildren; i++) {
+ curwin = gdk_get_client_window(gdk_display, ret_children[i]);
+ sev.xclient.window = curwin;
+ XSendEvent(gdk_display, curwin, False, NoEventMask, &sev);
+ }
+
+ XFree(ret_children);
+}
diff --git a/gdk/x11/gdkpixmap-x11.c b/gdk/x11/gdkpixmap-x11.c
new file mode 100644
index 000000000..d2d96b6da
--- /dev/null
+++ b/gdk/x11/gdkpixmap-x11.c
@@ -0,0 +1,657 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "../config.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <X11/Xlib.h>
+
+#include "gdk.h"
+#include "gdkprivate.h"
+
+typedef struct
+{
+ gchar *color_string;
+ GdkColor color;
+ gint transparent;
+} _GdkPixmapColor;
+
+GdkPixmap*
+gdk_pixmap_new (GdkWindow *window,
+ gint width,
+ gint height,
+ gint depth)
+{
+ GdkPixmap *pixmap;
+ GdkWindowPrivate *private;
+ GdkWindowPrivate *window_private;
+
+ if (!window)
+ window = (GdkWindow*) &gdk_root_parent;
+
+ if (depth == -1)
+ gdk_window_get_geometry (window, NULL, NULL, NULL, NULL, &depth);
+
+ private = g_new (GdkWindowPrivate, 1);
+ pixmap = (GdkPixmap*) private;
+
+ window_private = (GdkWindowPrivate*) window;
+
+ private->xdisplay = window_private->xdisplay;
+ private->window_type = GDK_WINDOW_PIXMAP;
+ private->xwindow = XCreatePixmap (private->xdisplay, window_private->xwindow,
+ width, height, depth);
+ private->parent = NULL;
+ private->x = 0;
+ private->y = 0;
+ private->width = width;
+ private->height = height;
+ private->resize_count = 0;
+ private->ref_count = 1;
+ private->destroyed = 0;
+
+ gdk_xid_table_insert (&private->xwindow, pixmap);
+
+ return pixmap;
+}
+
+GdkPixmap *
+gdk_bitmap_create_from_data (GdkWindow *window,
+ gchar *data,
+ gint width,
+ gint height)
+{
+ GdkPixmap *pixmap;
+ GdkWindowPrivate *private;
+ GdkWindowPrivate *window_private;
+
+ g_return_val_if_fail (data != NULL, NULL);
+
+ if (!window)
+ window = (GdkWindow*) &gdk_root_parent;
+
+ private = g_new (GdkWindowPrivate, 1);
+ pixmap = (GdkPixmap*) private;
+
+ window_private = (GdkWindowPrivate*) window;
+
+ private->parent = NULL;
+ private->xdisplay = window_private->xdisplay;
+ private->window_type = GDK_WINDOW_PIXMAP;
+ private->x = 0;
+ private->y = 0;
+ private->width = width;
+ private->height = height;
+ private->resize_count = 0;
+ private->ref_count = 1;
+ private->destroyed = FALSE;
+
+ private->xwindow = XCreateBitmapFromData (private->xdisplay,
+ window_private->xwindow,
+ data, width, height);
+
+ gdk_xid_table_insert (&private->xwindow, pixmap);
+
+ return pixmap;
+}
+
+GdkPixmap*
+gdk_pixmap_create_from_data (GdkWindow *window,
+ gchar *data,
+ gint width,
+ gint height,
+ gint depth,
+ GdkColor *fg,
+ GdkColor *bg)
+{
+ GdkPixmap *pixmap;
+ GdkWindowPrivate *private;
+ GdkWindowPrivate *window_private;
+
+ g_return_val_if_fail (data != NULL, NULL);
+ g_return_val_if_fail (fg != NULL, NULL);
+ g_return_val_if_fail (bg != NULL, NULL);
+
+ if (!window)
+ window = (GdkWindow*) &gdk_root_parent;
+
+ if (depth == -1)
+ gdk_window_get_geometry (window, NULL, NULL, NULL, NULL, &depth);
+
+ private = g_new (GdkWindowPrivate, 1);
+ pixmap = (GdkPixmap*) private;
+
+ window_private = (GdkWindowPrivate*) window;
+
+ private->parent = NULL;
+ private->xdisplay = window_private->xdisplay;
+ private->window_type = GDK_WINDOW_PIXMAP;
+ private->x = 0;
+ private->y = 0;
+ private->width = width;
+ private->height = height;
+ private->resize_count = 0;
+ private->ref_count = 1;
+ private->destroyed = FALSE;
+
+ private->xwindow = XCreatePixmapFromBitmapData (private->xdisplay,
+ window_private->xwindow,
+ data, width, height,
+ fg->pixel, bg->pixel, depth);
+
+ gdk_xid_table_insert (&private->xwindow, pixmap);
+
+ return pixmap;
+}
+
+gint
+gdk_pixmap_seek_string (FILE *infile,
+ const gchar *str,
+ gint skip_comments)
+{
+ char instr[1024];
+
+ while (!feof (infile))
+ {
+ fscanf (infile, "%s", instr);
+ if (skip_comments == TRUE && strcmp (instr, "/*") == 0)
+ {
+ fscanf (infile, "%s", instr);
+ while (!feof (infile) && strcmp (instr, "*/") != 0)
+ fscanf (infile, "%s", instr);
+ fscanf(infile, "%s", instr);
+ }
+ if (strcmp (instr, str)==0)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+gint
+gdk_pixmap_seek_char (FILE *infile,
+ gchar c)
+{
+ gchar b, oldb;
+
+ while (!feof (infile))
+ {
+ fscanf(infile, "%c", &b);
+ if (c != b && b == '/')
+ {
+ fscanf (infile, "%c", &b);
+ if (b == '*')
+ {
+ oldb = b;
+ while (!feof (infile) && !(oldb == '*' && b == '/'))
+ {
+ oldb = b;
+ fscanf (infile, "%c", &b);
+ }
+ fscanf (infile, "%c", &b);
+ }
+ }
+ if (c == b)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+gint
+gdk_pixmap_read_string (FILE *infile,
+ gchar **buffer,
+ int *buffer_size)
+{
+ gchar c;
+ gint cnt = 0;
+
+ if ((*buffer) == NULL)
+ {
+ (*buffer_size) = 10 * sizeof (gchar);
+ (*buffer) = (gchar *) malloc (*buffer_size);
+ }
+
+ do
+ fscanf (infile, "%c", &c);
+ while (!feof (infile) && c != '"');
+
+ if (c != '"')
+ return FALSE;
+
+ while (!feof (infile))
+ {
+ fscanf (infile, "%c", &c);
+
+ if (cnt == (*buffer_size))
+ {
+ (*buffer_size) *= 2;
+ (*buffer) = (gchar *) realloc ((*buffer), *buffer_size);
+ }
+
+ if (c != '"')
+ (*buffer)[cnt++] = c;
+ else
+ {
+ (*buffer)[cnt++] = 0;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+gchar*
+gdk_pixmap_skip_whitespaces (gchar *buffer)
+{
+ gint32 index = 0;
+
+ while (buffer[index] != 0 && (buffer[index] == 0x20 || buffer[index] == 0x09))
+ index++;
+
+ return &buffer[index];
+}
+
+gchar*
+gdk_pixmap_skip_string (gchar *buffer)
+{
+ gint32 index = 0;
+
+ while (buffer[index] != 0 && buffer[index] != 0x20 && buffer[index] != 0x09)
+ index++;
+
+ return &buffer[index];
+}
+
+gchar*
+gdk_pixmap_extract_color (gchar *buffer)
+{
+ gint counter, finished = FALSE, numnames;
+ gchar *ptr = NULL, ch, temp[128];
+ gchar color[128], *retcol;
+
+ counter = 0;
+ while (ptr == NULL)
+ {
+ if (buffer[counter] == 'c')
+ {
+ ch = buffer[counter + 1];
+ if (ch == 0x20 || ch == 0x09)
+ ptr = &buffer[counter + 1];
+ }
+ else if (buffer[counter] == 0)
+ return NULL;
+
+ counter++;
+ }
+
+ if (ptr == NULL)
+ return NULL;
+
+ ptr = gdk_pixmap_skip_whitespaces (ptr);
+
+ if (ptr[0] == 0)
+ return NULL;
+ else if (ptr[0] == '#')
+ {
+ retcol = g_new(gchar, strlen (ptr) + 1);
+ strcpy (retcol, ptr);
+ return retcol;
+ }
+
+ color[0] = 0;
+ numnames = 0;
+
+ while (finished == FALSE)
+ {
+ sscanf (ptr, "%s", temp);
+
+ if ((gint)ptr[0] == 0 || strcmp ("s", temp) == 0 || strcmp ("m", temp) == 0 ||
+ strcmp ("g", temp) == 0 || strcmp ("g4", temp) == 0)
+ finished = TRUE;
+ else
+ {
+ if (numnames > 0)
+ strcat (color, " ");
+ strcat (color, temp);
+ ptr = gdk_pixmap_skip_string (ptr);
+ ptr = gdk_pixmap_skip_whitespaces (ptr);
+ numnames++;
+ }
+ }
+
+ retcol = g_new(gchar, strlen (color) + 1);
+ strcpy (retcol, color);
+ return retcol;
+}
+
+
+GdkPixmap*
+gdk_pixmap_create_from_xpm (GdkWindow *window,
+ GdkBitmap **mask,
+ GdkColor *transparent_color,
+ const gchar *filename)
+{
+ FILE *infile = NULL;
+ GdkPixmap *pixmap = NULL;
+ GdkImage *image = NULL;
+ GdkColormap *colormap;
+ GdkVisual *visual;
+ GdkGC *gc;
+ GdkColor tmp_color;
+ gint width, height, num_cols, cpp, cnt, n, ns, xcnt, ycnt;
+ gchar *buffer = NULL, *color_name = NULL, pixel_str[32];
+ guint buffer_size = 0;
+ _GdkPixmapColor *colors = NULL, *color = NULL;
+ gulong index;
+
+ if (!window)
+ window = (GdkWindow*) &gdk_root_parent;
+
+ infile = fopen (filename, "rb");
+ if (infile != NULL)
+ {
+ if (gdk_pixmap_seek_string (infile, "XPM", FALSE) == TRUE)
+ {
+ if (gdk_pixmap_seek_char (infile,'{') == TRUE)
+ {
+ gdk_pixmap_seek_char (infile, '"');
+ fseek (infile, -1, SEEK_CUR);
+ gdk_pixmap_read_string (infile, &buffer, &buffer_size);
+
+ sscanf (buffer,"%d %d %d %d", &width, &height, &num_cols, &cpp);
+
+ colors = g_new(_GdkPixmapColor, num_cols);
+
+ colormap = gdk_window_get_colormap (window);
+ visual = gdk_window_get_visual (window);
+
+ if (transparent_color == NULL)
+ {
+ gdk_color_white (colormap, &tmp_color);
+ transparent_color = &tmp_color;
+ }
+
+ for (cnt = 0; cnt < num_cols; cnt++)
+ {
+ gdk_pixmap_seek_char (infile, '"');
+ fseek (infile, -1, SEEK_CUR);
+ gdk_pixmap_read_string (infile, &buffer, &buffer_size);
+
+ colors[cnt].color_string = g_new(gchar, cpp + 1);
+ for (n = 0; n < cpp; n++)
+ colors[cnt].color_string[n] = buffer[n];
+ colors[cnt].color_string[n] = 0;
+ colors[cnt].transparent = FALSE;
+
+ if (color_name != NULL)
+ g_free (color_name);
+
+ color_name = gdk_pixmap_extract_color (&buffer[cpp]);
+
+ if (color_name != NULL)
+ {
+ if (gdk_color_parse (color_name, &colors[cnt].color) == FALSE)
+ {
+ colors[cnt].color = *transparent_color;
+ colors[cnt].transparent = TRUE;
+ }
+ }
+ else
+ {
+ colors[cnt].color = *transparent_color;
+ colors[cnt].transparent = TRUE;
+ }
+
+ gdk_color_alloc (colormap, &colors[cnt].color);
+ }
+
+ index = 0;
+ image = gdk_image_new (GDK_IMAGE_FASTEST, visual, width, height);
+
+ gc = NULL;
+ if (mask)
+ {
+ *mask = gdk_pixmap_new (window, width, height, 1);
+ gc = gdk_gc_new (*mask);
+
+ gdk_color_black (colormap, &tmp_color);
+ gdk_gc_set_foreground (gc, &tmp_color);
+ gdk_draw_rectangle (*mask, gc, TRUE, 0, 0, -1, -1);
+
+ gdk_color_white (colormap, &tmp_color);
+ gdk_gc_set_foreground (gc, &tmp_color);
+ }
+
+ for (ycnt = 0; ycnt < height; ycnt++)
+ {
+ gdk_pixmap_read_string (infile, &buffer, &buffer_size);
+
+ for (n = 0, cnt = 0, xcnt = 0; n < (width * cpp); n += cpp, xcnt++)
+ {
+ strncpy (pixel_str, &buffer[n], cpp);
+ pixel_str[cpp] = 0;
+ color = NULL;
+ ns = 0;
+
+ while (color == NULL)
+ {
+ if (strcmp (pixel_str, colors[ns].color_string) == 0)
+ color = &colors[ns];
+ else
+ ns++;
+ }
+
+ gdk_image_put_pixel (image, xcnt, ycnt, color->color.pixel);
+
+ if (mask && color->transparent)
+ {
+ if (cnt < xcnt)
+ gdk_draw_line (*mask, gc, cnt, ycnt, xcnt - 1, ycnt);
+ cnt = xcnt + 1;
+ }
+ }
+
+ if (mask && (cnt < xcnt))
+ gdk_draw_line (*mask, gc, cnt, ycnt, xcnt - 1, ycnt);
+ }
+
+ if (mask)
+ gdk_gc_destroy (gc);
+
+ pixmap = gdk_pixmap_new (window, width, height, visual->depth);
+
+ gc = gdk_gc_new (pixmap);
+ gdk_gc_set_foreground (gc, transparent_color);
+ gdk_draw_image (pixmap, gc, image, 0, 0, 0, 0, image->width, image->height);
+ gdk_gc_destroy (gc);
+ gdk_image_destroy (image);
+ }
+ }
+
+ fclose (infile);
+ free (buffer);
+
+ if (colors != NULL)
+ {
+ for (cnt = 0; cnt < num_cols; cnt++)
+ g_free (colors[cnt].color_string);
+ g_free (colors);
+ }
+ }
+
+ return pixmap;
+}
+
+GdkPixmap*
+gdk_pixmap_create_from_xpm_d (GdkWindow *window,
+ GdkBitmap **mask,
+ GdkColor *transparent_color,
+ gchar **data)
+{
+ GdkPixmap *pixmap = NULL;
+ GdkImage *image = NULL;
+ GdkColormap *colormap;
+ GdkVisual *visual;
+ GdkGC *gc;
+ GdkColor tmp_color;
+ gint width, height, num_cols, cpp, cnt, n, ns, xcnt, ycnt, i;
+ gchar *buffer, *color_name = NULL, pixel_str[32];
+ _GdkPixmapColor *colors = NULL, *color = NULL;
+ gulong index;
+
+ if (!window)
+ window = (GdkWindow*) &gdk_root_parent;
+
+ i = 0;
+ buffer = data[i++];
+ sscanf (buffer,"%d %d %d %d", &width, &height, &num_cols, &cpp);
+
+ colors = g_new(_GdkPixmapColor, num_cols);
+
+ colormap = gdk_window_get_colormap (window);
+ visual = gdk_window_get_visual (window);
+
+ if (transparent_color == NULL)
+ {
+ gdk_color_white (colormap, &tmp_color);
+ transparent_color = &tmp_color;
+ }
+
+ for (cnt = 0; cnt < num_cols; cnt++)
+ {
+ buffer = data[i++];
+
+ colors[cnt].color_string = g_new(gchar, cpp + 1);
+ for (n = 0; n < cpp; n++)
+ colors[cnt].color_string[n] = buffer[n];
+ colors[cnt].color_string[n] = 0;
+ colors[cnt].transparent = FALSE;
+
+ if (color_name != NULL)
+ g_free (color_name);
+
+ color_name = gdk_pixmap_extract_color (&buffer[cpp]);
+
+ if (color_name != NULL)
+ {
+ if (gdk_color_parse (color_name, &colors[cnt].color) == FALSE)
+ {
+ colors[cnt].color = *transparent_color;
+ colors[cnt].transparent = TRUE;
+ }
+ }
+ else
+ {
+ colors[cnt].color = *transparent_color;
+ colors[cnt].transparent = TRUE;
+ }
+
+ gdk_color_alloc (colormap, &colors[cnt].color);
+ }
+
+ index = 0;
+ image = gdk_image_new (GDK_IMAGE_FASTEST, visual, width, height);
+
+ gc = NULL;
+ if (mask)
+ {
+ *mask = gdk_pixmap_new (window, width, height, 1);
+ gc = gdk_gc_new (*mask);
+
+ gdk_color_black (colormap, &tmp_color);
+ gdk_gc_set_foreground (gc, &tmp_color);
+ gdk_draw_rectangle (*mask, gc, TRUE, 0, 0, -1, -1);
+
+ gdk_color_white (colormap, &tmp_color);
+ gdk_gc_set_foreground (gc, &tmp_color);
+ }
+
+ for (ycnt = 0; ycnt < height; ycnt++)
+ {
+ buffer = data[i++];
+
+ for (n = 0, cnt = 0, xcnt = 0; n < (width * cpp); n += cpp, xcnt++)
+ {
+ strncpy (pixel_str, &buffer[n], cpp);
+ pixel_str[cpp] = 0;
+ color = NULL;
+ ns = 0;
+
+ while (color == NULL)
+ {
+ if (strcmp (pixel_str, colors[ns].color_string) == 0)
+ color = &colors[ns];
+ else
+ ns++;
+ }
+
+ gdk_image_put_pixel (image, xcnt, ycnt, color->color.pixel);
+
+ if (mask && color->transparent)
+ {
+ if (cnt < xcnt)
+ gdk_draw_line (*mask, gc, cnt, ycnt, xcnt - 1, ycnt);
+ cnt = xcnt + 1;
+ }
+ }
+
+ if (mask && (cnt < xcnt))
+ gdk_draw_line (*mask, gc, cnt, ycnt, xcnt - 1, ycnt);
+ }
+
+ if (mask)
+ gdk_gc_destroy (gc);
+
+ pixmap = gdk_pixmap_new (window, width, height, visual->depth);
+
+ gc = gdk_gc_new (pixmap);
+ gdk_gc_set_foreground (gc, transparent_color);
+ gdk_draw_image (pixmap, gc, image, 0, 0, 0, 0, image->width, image->height);
+ gdk_gc_destroy (gc);
+ gdk_image_destroy (image);
+
+ if (colors != NULL)
+ {
+ for (cnt = 0; cnt < num_cols; cnt++)
+ g_free (colors[cnt].color_string);
+ g_free (colors);
+ }
+
+ return pixmap;
+}
+
+void
+gdk_pixmap_destroy (GdkPixmap *pixmap)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (pixmap != NULL);
+
+ private = (GdkPixmapPrivate*) pixmap;
+ if (private->ref_count <= 0)
+ {
+ XFreePixmap (private->xdisplay, private->xwindow);
+ gdk_xid_table_remove (private->xwindow);
+ g_free (pixmap);
+ }
+ else
+ {
+ private->ref_count -= 1;
+ }
+}
diff --git a/gdk/x11/gdkproperty-x11.c b/gdk/x11/gdkproperty-x11.c
new file mode 100644
index 000000000..35d8a50cf
--- /dev/null
+++ b/gdk/x11/gdkproperty-x11.c
@@ -0,0 +1,194 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <string.h>
+#include "gdk.h"
+#include "gdkprivate.h"
+
+
+GdkAtom
+gdk_atom_intern (const gchar *atom_name,
+ gint only_if_exists)
+{
+ return XInternAtom (gdk_display, atom_name, only_if_exists);
+}
+
+gchar *
+gdk_atom_name (GdkAtom atom)
+{
+ gchar *t;
+ gchar *name;
+
+ /* If this atom doesn't exist, we'll die with an X error unless
+ we take precautions */
+
+ gdk_error_warnings = 0;
+ t = XGetAtomName (gdk_display, atom);
+ gdk_error_warnings = 1;
+
+ if (gdk_error_code == -1)
+ {
+ return NULL;
+ }
+ else
+ {
+ name = g_strdup (t);
+ XFree (t);
+
+ return name;
+ }
+}
+
+gint
+gdk_property_get (GdkWindow *window,
+ GdkAtom property,
+ GdkAtom type,
+ gulong offset,
+ gulong length,
+ gint pdelete,
+ GdkAtom *actual_property_type,
+ gint *actual_format_type,
+ gint *actual_length,
+ guchar **data)
+{
+ GdkWindowPrivate *private;
+ Display *xdisplay;
+ Window xwindow;
+ Atom ret_prop_type;
+ gint ret_format;
+ gulong ret_nitems;
+ gulong ret_bytes_after;
+ gulong ret_length;
+ guchar *ret_data;
+
+ if (window)
+ {
+ private = (GdkWindowPrivate*) window;
+ xdisplay = private->xdisplay;
+ xwindow = private->xwindow;
+ }
+ else
+ {
+ xdisplay = gdk_display;
+ xwindow = gdk_root_window;
+ }
+
+ XGetWindowProperty (xdisplay, xwindow, property,
+ offset, (length + 3) / 4, pdelete,
+ type, &ret_prop_type, &ret_format,
+ &ret_nitems, &ret_bytes_after,
+ &ret_data);
+
+ if ((ret_prop_type == None) && (ret_format == 0))
+ return FALSE;
+
+ if (actual_property_type)
+ *actual_property_type = ret_prop_type;
+ if (actual_format_type)
+ *actual_format_type = ret_format;
+
+ if (ret_prop_type != property)
+ {
+ XFree (ret_data);
+ return FALSE;
+ }
+
+ /* FIXME: ignoring bytes_after could have very bad effects */
+
+ if (data)
+ {
+ switch (ret_format)
+ {
+ case 8:
+ ret_length = ret_nitems;
+ break;
+ case 16:
+ ret_length = 2 * ret_nitems;
+ break;
+ case 32:
+ ret_length = 4 * ret_nitems;
+ break;
+ default:
+ g_warning ("unknown property return format: %d", ret_format);
+ XFree (ret_data);
+ return FALSE;
+ }
+
+ *data = g_new (guchar, ret_length);
+ memcpy (*data, ret_data, ret_length);
+ if (actual_length)
+ *actual_length = ret_length;
+ }
+
+ XFree (ret_data);
+
+ return TRUE;
+}
+
+void
+gdk_property_change (GdkWindow *window,
+ GdkAtom property,
+ GdkAtom type,
+ gint format,
+ GdkPropMode mode,
+ guchar *data,
+ gint nelements)
+{
+ GdkWindowPrivate *private;
+ Display *xdisplay;
+ Window xwindow;
+
+ if (window)
+ {
+ private = (GdkWindowPrivate*) window;
+ xdisplay = private->xdisplay;
+ xwindow = private->xwindow;
+ }
+ else
+ {
+ xdisplay = gdk_display;
+ xwindow = gdk_root_window;
+ }
+
+ XChangeProperty (xdisplay, xwindow, property, type,
+ format, mode, data, nelements);
+}
+
+void
+gdk_property_delete (GdkWindow *window,
+ GdkAtom property)
+{
+ GdkWindowPrivate *private;
+ Display *xdisplay;
+ Window xwindow;
+
+ if (window)
+ {
+ private = (GdkWindowPrivate*) window;
+ xdisplay = private->xdisplay;
+ xwindow = private->xwindow;
+ }
+ else
+ {
+ xdisplay = gdk_display;
+ xwindow = gdk_root_window;
+ }
+
+ XDeleteProperty (xdisplay, xwindow, property);
+}
diff --git a/gdk/x11/gdkselection-x11.c b/gdk/x11/gdkselection-x11.c
new file mode 100644
index 000000000..6bd425110
--- /dev/null
+++ b/gdk/x11/gdkselection-x11.c
@@ -0,0 +1,168 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <string.h>
+#include "gdk.h"
+#include "gdkprivate.h"
+
+
+gint
+gdk_selection_owner_set (GdkWindow *owner,
+ GdkAtom selection,
+ guint32 time,
+ gint send_event)
+{
+ GdkWindowPrivate *private;
+ Display *xdisplay;
+ Window xwindow;
+
+ if (owner)
+ {
+ private = (GdkWindowPrivate*) owner;
+ xdisplay = private->xdisplay;
+ xwindow = private->xwindow;
+ }
+ else
+ {
+ xdisplay = gdk_display;
+ xwindow = None;
+ }
+
+ XSetSelectionOwner (xdisplay, selection, xwindow, time);
+
+ return (XGetSelectionOwner (xdisplay, selection) == xwindow);
+}
+
+GdkWindow*
+gdk_selection_owner_get (GdkAtom selection)
+{
+ Window xwindow;
+
+ xwindow = XGetSelectionOwner (gdk_display, selection);
+ if (xwindow == None)
+ return NULL;
+
+ return gdk_window_lookup (xwindow);
+}
+
+void
+gdk_selection_convert (GdkWindow *requestor,
+ GdkAtom selection,
+ GdkAtom target,
+ guint32 time)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (requestor != NULL);
+
+ private = (GdkWindowPrivate*) requestor;
+
+ XConvertSelection (private->xdisplay, selection, target,
+ gdk_selection_property, private->xwindow, time);
+}
+
+gint
+gdk_selection_property_get (GdkWindow *requestor,
+ guchar **data,
+ GdkAtom *ret_type,
+ gint *ret_format)
+{
+ GdkWindowPrivate *private;
+ gulong nitems;
+ gulong nbytes;
+ gulong length;
+ GdkAtom prop_type;
+ gint prop_format;
+ guchar *t;
+
+ g_return_val_if_fail (requestor != NULL, 0);
+
+ /* If retrieved chunks are typically small, (and the ICCM says the
+ should be) it would be a win to try first with a buffer of
+ moderate length, to avoid two round trips to the server */
+
+ private = (GdkWindowPrivate*) requestor;
+
+ XGetWindowProperty (private->xdisplay, private->xwindow,
+ gdk_selection_property, 0, 0, False,
+ AnyPropertyType, &prop_type, &prop_format,
+ &nitems, &nbytes, &t);
+
+ if (ret_type)
+ *ret_type = prop_type;
+ if (ret_format)
+ *ret_format = prop_format;
+
+ if (prop_type == None)
+ {
+ *data = NULL;
+ return 0;
+ }
+
+ XFree (t);
+
+ /* Add on an extra byte to handle null termination. X guarantees
+ that t will be 1 longer than nbytes and null terminated */
+ length = nbytes + 1;
+
+ /* We can't delete the selection here, because it might be the INCR
+ protocol, in which case the client has to make sure they'll be
+ notified of PropertyChange events _before_ the property is deleted.
+ Otherwise there's no guarantee we'll win the race ... */
+ XGetWindowProperty (private->xdisplay, private->xwindow,
+ gdk_selection_property, 0, (nbytes + 3) / 4, False,
+ AnyPropertyType, &prop_type, &prop_format,
+ &nitems, &nbytes, &t);
+
+ if (prop_type != None)
+ {
+ *data = g_new (guchar, length);
+ memcpy (*data, t, length);
+ XFree (t);
+ return length-1;
+ }
+ else
+ {
+ *data = NULL;
+ return 0;
+ }
+}
+
+
+void
+gdk_selection_send_notify (guint32 requestor,
+ GdkAtom selection,
+ GdkAtom target,
+ GdkAtom property,
+ guint32 time)
+{
+ XSelectionEvent xevent;
+
+ xevent.type = SelectionNotify;
+ xevent.serial = 0;
+ xevent.send_event = True;
+ xevent.display = gdk_display;
+ xevent.requestor = requestor;
+ xevent.selection = selection;
+ xevent.target = target;
+ xevent.property = property;
+ xevent.time = time;
+
+ XSendEvent (gdk_display, requestor, False, NoEventMask, (XEvent*) &xevent);
+}
diff --git a/gdk/x11/gdkvisual-x11.c b/gdk/x11/gdkvisual-x11.c
new file mode 100644
index 000000000..22acee6f1
--- /dev/null
+++ b/gdk/x11/gdkvisual-x11.c
@@ -0,0 +1,431 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include "gdk.h"
+#include "gdkprivate.h"
+
+
+static void gdk_visual_add (GdkVisual *visual);
+static void gdk_visual_decompose_mask (gulong mask,
+ gint *shift,
+ gint *prec);
+static guint gdk_visual_hash (Visual *key);
+static gint gdk_visual_compare (Visual *a,
+ Visual *b);
+
+
+static GdkVisualPrivate *system_visual;
+static GdkVisualPrivate *visuals;
+static gint nvisuals;
+
+static gint available_depths[4];
+static gint navailable_depths;
+
+static GdkVisualType available_types[6];
+static gint navailable_types;
+
+static char* visual_names[] =
+{
+ "static gray",
+ "grayscale",
+ "static color",
+ "pseudo color",
+ "true color",
+ "direct color",
+};
+
+static GHashTable *visual_hash = NULL;
+
+void
+gdk_visual_init ()
+{
+ static gint possible_depths[5] = { 32, 24, 16, 15, 8 };
+ static GdkVisualType possible_types[6] =
+ {
+ GDK_VISUAL_DIRECT_COLOR,
+ GDK_VISUAL_TRUE_COLOR,
+ GDK_VISUAL_PSEUDO_COLOR,
+ GDK_VISUAL_STATIC_COLOR,
+ GDK_VISUAL_GRAYSCALE,
+ GDK_VISUAL_STATIC_GRAY
+ };
+
+ static gint npossible_depths = 5;
+ static gint npossible_types = 6;
+
+ XVisualInfo *visual_list;
+ XVisualInfo visual_template;
+ GdkVisualPrivate temp_visual;
+ Visual *default_xvisual;
+ int nxvisuals;
+ int i, j;
+
+ visual_template.screen = gdk_screen;
+ visual_list = XGetVisualInfo (gdk_display, VisualScreenMask, &visual_template, &nxvisuals);
+ visuals = g_new (GdkVisualPrivate, nxvisuals);
+
+ default_xvisual = DefaultVisual (gdk_display, gdk_screen);
+
+ nvisuals = 0;
+ for (i = 0; i < nxvisuals; i++)
+ {
+ if (visual_list[i].depth >= 8)
+ {
+#ifdef __cplusplus
+ switch (visual_list[i].c_class)
+#else /* __cplusplus */
+ switch (visual_list[i].class)
+#endif /* __cplusplus */
+ {
+ case StaticGray:
+ visuals[nvisuals].visual.type = GDK_VISUAL_STATIC_GRAY;
+ break;
+ case GrayScale:
+ visuals[nvisuals].visual.type = GDK_VISUAL_GRAYSCALE;
+ break;
+ case StaticColor:
+ visuals[nvisuals].visual.type = GDK_VISUAL_STATIC_COLOR;
+ break;
+ case PseudoColor:
+ visuals[nvisuals].visual.type = GDK_VISUAL_PSEUDO_COLOR;
+ break;
+ case TrueColor:
+ visuals[nvisuals].visual.type = GDK_VISUAL_TRUE_COLOR;
+ break;
+ case DirectColor:
+ visuals[nvisuals].visual.type = GDK_VISUAL_DIRECT_COLOR;
+ break;
+ }
+
+ visuals[nvisuals].visual.depth = visual_list[i].depth;
+ visuals[nvisuals].visual.byte_order =
+ (ImageByteOrder(gdk_display) == LSBFirst) ?
+ GDK_LSB_FIRST : GDK_MSB_FIRST;
+ visuals[nvisuals].visual.red_mask = visual_list[i].red_mask;
+ visuals[nvisuals].visual.green_mask = visual_list[i].green_mask;
+ visuals[nvisuals].visual.blue_mask = visual_list[i].blue_mask;
+ visuals[nvisuals].visual.colormap_size = visual_list[i].colormap_size;
+ visuals[nvisuals].visual.bits_per_rgb = visual_list[i].bits_per_rgb;
+ visuals[nvisuals].xvisual = visual_list[i].visual;
+
+ if ((visuals[nvisuals].visual.type == GDK_VISUAL_TRUE_COLOR) ||
+ (visuals[nvisuals].visual.type == GDK_VISUAL_DIRECT_COLOR))
+ {
+ gdk_visual_decompose_mask (visuals[nvisuals].visual.red_mask,
+ &visuals[nvisuals].visual.red_shift,
+ &visuals[nvisuals].visual.red_prec);
+
+ gdk_visual_decompose_mask (visuals[nvisuals].visual.green_mask,
+ &visuals[nvisuals].visual.green_shift,
+ &visuals[nvisuals].visual.green_prec);
+
+ gdk_visual_decompose_mask (visuals[nvisuals].visual.blue_mask,
+ &visuals[nvisuals].visual.blue_shift,
+ &visuals[nvisuals].visual.blue_prec);
+ }
+ else
+ {
+ visuals[nvisuals].visual.red_mask = 0;
+ visuals[nvisuals].visual.red_shift = 0;
+ visuals[nvisuals].visual.red_prec = 0;
+
+ visuals[nvisuals].visual.green_mask = 0;
+ visuals[nvisuals].visual.green_shift = 0;
+ visuals[nvisuals].visual.green_prec = 0;
+
+ visuals[nvisuals].visual.blue_mask = 0;
+ visuals[nvisuals].visual.blue_shift = 0;
+ visuals[nvisuals].visual.blue_prec = 0;
+ }
+
+ nvisuals += 1;
+ }
+ }
+
+ XFree (visual_list);
+
+ for (i = 0; i < nvisuals; i++)
+ {
+ for (j = i+1; j < nvisuals; j++)
+ {
+ if (visuals[j].visual.depth >= visuals[i].visual.depth)
+ {
+ if ((visuals[j].visual.depth == 8) && (visuals[i].visual.depth == 8))
+ {
+ if (visuals[j].visual.type == GDK_VISUAL_PSEUDO_COLOR)
+ {
+ temp_visual = visuals[j];
+ visuals[j] = visuals[i];
+ visuals[i] = temp_visual;
+ }
+ else if ((visuals[i].visual.type != GDK_VISUAL_PSEUDO_COLOR) &&
+ visuals[j].visual.type > visuals[i].visual.type)
+ {
+ temp_visual = visuals[j];
+ visuals[j] = visuals[i];
+ visuals[i] = temp_visual;
+ }
+ }
+ else if ((visuals[j].visual.depth > visuals[i].visual.depth) ||
+ ((visuals[j].visual.depth == visuals[i].visual.depth) &&
+ (visuals[j].visual.type > visuals[i].visual.type)))
+ {
+ temp_visual = visuals[j];
+ visuals[j] = visuals[i];
+ visuals[i] = temp_visual;
+ }
+ }
+ }
+ }
+
+ for (i = 0; i < nvisuals; i++)
+ if (default_xvisual->visualid == visuals[i].xvisual->visualid)
+ {
+ system_visual = &visuals[i];
+ break;
+ }
+
+ if (gdk_debug_level >= 1)
+ for (i = 0; i < nvisuals; i++)
+ g_print ("visual: %s: %d\n",
+ visual_names[visuals[i].visual.type],
+ visuals[i].visual.depth);
+
+ navailable_depths = 0;
+ for (i = 0; i < npossible_depths; i++)
+ {
+ for (j = 0; j < nvisuals; j++)
+ {
+ if (visuals[j].visual.depth == possible_depths[i])
+ {
+ available_depths[navailable_depths++] = visuals[j].visual.depth;
+ break;
+ }
+ }
+ }
+
+ if (navailable_depths == 0)
+ g_error ("unable to find a usable depth");
+
+ navailable_types = 0;
+ for (i = 0; i < npossible_types; i++)
+ {
+ for (j = 0; j < nvisuals; j++)
+ {
+ if (visuals[j].visual.type == possible_types[i])
+ {
+ available_types[navailable_types++] = visuals[j].visual.type;
+ break;
+ }
+ }
+ }
+
+ for (i = 0; i < nvisuals; i++)
+ gdk_visual_add ((GdkVisual*) &visuals[i]);
+
+ if (npossible_types == 0)
+ g_error ("unable to find a usable visual type");
+}
+
+GdkVisual*
+gdk_visual_ref (GdkVisual *visual)
+{
+ return visual;
+}
+
+void
+gdk_visual_unref (GdkVisual *visual)
+{
+ return;
+}
+
+gint
+gdk_visual_get_best_depth ()
+{
+ return available_depths[0];
+}
+
+GdkVisualType
+gdk_visual_get_best_type ()
+{
+ return available_types[0];
+}
+
+GdkVisual*
+gdk_visual_get_system ()
+{
+ return ((GdkVisual*) system_visual);
+}
+
+GdkVisual*
+gdk_visual_get_best ()
+{
+ return ((GdkVisual*) &(visuals[0]));
+}
+
+GdkVisual*
+gdk_visual_get_best_with_depth (gint depth)
+{
+ GdkVisual *return_val;
+ int i;
+
+ return_val = NULL;
+ for (i = 0; i < nvisuals; i++)
+ if (depth == visuals[i].visual.depth)
+ {
+ return_val = (GdkVisual*) &(visuals[i]);
+ break;
+ }
+
+ return return_val;
+}
+
+GdkVisual*
+gdk_visual_get_best_with_type (GdkVisualType visual_type)
+{
+ GdkVisual *return_val;
+ int i;
+
+ return_val = NULL;
+ for (i = 0; i < nvisuals; i++)
+ if (visual_type == visuals[i].visual.type)
+ {
+ return_val = (GdkVisual*) &(visuals[i]);
+ break;
+ }
+
+ return return_val;
+}
+
+GdkVisual*
+gdk_visual_get_best_with_both (gint depth,
+ GdkVisualType visual_type)
+{
+ GdkVisual *return_val;
+ int i;
+
+ return_val = NULL;
+ for (i = 0; i < nvisuals; i++)
+ if ((depth == visuals[i].visual.depth) &&
+ (visual_type == visuals[i].visual.type))
+ {
+ return_val = (GdkVisual*) &(visuals[i]);
+ break;
+ }
+
+ return return_val;
+}
+
+void
+gdk_query_depths (gint **depths,
+ gint *count)
+{
+ *count = navailable_depths;
+ *depths = available_depths;
+}
+
+void
+gdk_query_visual_types (GdkVisualType **visual_types,
+ gint *count)
+{
+ *count = navailable_types;
+ *visual_types = available_types;
+}
+
+void
+gdk_query_visuals (GdkVisual **visual_return,
+ gint *count)
+{
+ *count = nvisuals;
+ *visual_return = (GdkVisual*) visuals;
+}
+
+
+GdkVisual*
+gdk_visual_lookup (Visual *xvisual)
+{
+ GdkVisual *visual;
+
+ if (!visual_hash)
+ return NULL;
+
+ visual = g_hash_table_lookup (visual_hash, xvisual);
+ return visual;
+}
+
+GdkVisual*
+gdkx_visual_get (VisualID xvisualid)
+{
+ int i;
+
+ for (i = 0; i < nvisuals; i++)
+ if (xvisualid == visuals[i].xvisual->visualid)
+ return (GdkVisual*) &visuals[i];
+
+ return NULL;
+}
+
+
+static void
+gdk_visual_add (GdkVisual *visual)
+{
+ GdkVisualPrivate *private;
+
+ if (!visual_hash)
+ visual_hash = g_hash_table_new ((GHashFunc) gdk_visual_hash,
+ (GCompareFunc) gdk_visual_compare);
+
+ private = (GdkVisualPrivate*) visual;
+
+ g_hash_table_insert (visual_hash, private->xvisual, visual);
+}
+
+static void
+gdk_visual_decompose_mask (gulong mask,
+ gint *shift,
+ gint *prec)
+{
+ *shift = 0;
+ *prec = 0;
+
+ while (!(mask & 0x1))
+ {
+ (*shift)++;
+ mask >>= 1;
+ }
+
+ while (mask & 0x1)
+ {
+ (*prec)++;
+ mask >>= 1;
+ }
+}
+
+static guint
+gdk_visual_hash (Visual *key)
+{
+ return key->visualid;
+}
+
+static gint
+gdk_visual_compare (Visual *a,
+ Visual *b)
+{
+ return (a->visualid == b->visualid);
+}
diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c
new file mode 100644
index 000000000..aef1367d9
--- /dev/null
+++ b/gdk/x11/gdkwindow-x11.c
@@ -0,0 +1,1358 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/shape.h>
+#include <netinet/in.h>
+#include "gdk.h"
+#include "gdkinput.h"
+#include "gdkprivate.h"
+#include <stdlib.h>
+
+int nevent_masks = 16;
+int event_mask_table[18] =
+{
+ ExposureMask,
+ PointerMotionMask,
+ PointerMotionHintMask,
+ ButtonMotionMask,
+ Button1MotionMask,
+ Button2MotionMask,
+ Button3MotionMask,
+ ButtonPressMask | OwnerGrabButtonMask,
+ ButtonReleaseMask | OwnerGrabButtonMask,
+ KeyPressMask,
+ KeyReleaseMask,
+ EnterWindowMask,
+ LeaveWindowMask,
+ FocusChangeMask,
+ StructureNotifyMask,
+ PropertyChangeMask,
+ 0, /* PROXIMITY_IN */
+ 0 /* PROXIMTY_OUT */
+};
+
+
+void
+gdk_window_init ()
+{
+ XWindowAttributes xattributes;
+ unsigned int width;
+ unsigned int height;
+ unsigned int border_width;
+ unsigned int depth;
+ int x, y;
+
+ XGetGeometry (gdk_display, gdk_root_window, &gdk_root_window,
+ &x, &y, &width, &height, &border_width, &depth);
+ XGetWindowAttributes (gdk_display, gdk_root_window, &xattributes);
+
+ gdk_root_parent.xdisplay = gdk_display;
+ gdk_root_parent.xwindow = gdk_root_window;
+ gdk_root_parent.window_type = GDK_WINDOW_ROOT;
+ gdk_root_parent.window.user_data = NULL;
+}
+
+GdkWindow*
+gdk_window_new (GdkWindow *parent,
+ GdkWindowAttr *attributes,
+ gint attributes_mask)
+{
+ GdkWindow *window;
+ GdkWindowPrivate *private;
+ GdkWindowPrivate *parent_private;
+ GdkVisual *visual;
+ GdkColormap *colormap;
+ Display *parent_display;
+ Window xparent;
+ Visual *xvisual;
+ XSetWindowAttributes xattributes;
+ long xattributes_mask;
+ XSizeHints size_hints;
+ XWMHints wm_hints;
+ XTextProperty text_property;
+ XClassHint *class_hint;
+ int x, y, depth;
+ unsigned int class;
+ char *title;
+ int i;
+
+ g_return_val_if_fail (attributes != NULL, NULL);
+
+ if (!parent)
+ parent = (GdkWindow*) &gdk_root_parent;
+
+ parent_private = (GdkWindowPrivate*) parent;
+ xparent = parent_private->xwindow;
+ parent_display = parent_private->xdisplay;
+
+ private = g_new (GdkWindowPrivate, 1);
+ window = (GdkWindow*) private;
+
+ private->parent = parent;
+ private->xdisplay = parent_display;
+ private->destroyed = FALSE;
+ private->resize_count = 0;
+ private->ref_count = 1;
+ xattributes_mask = 0;
+
+ if (attributes_mask & GDK_WA_X)
+ x = attributes->x;
+ else
+ x = 0;
+
+ if (attributes_mask & GDK_WA_Y)
+ y = attributes->y;
+ else
+ y = 0;
+
+ private->x = x;
+ private->y = y;
+ private->width = (attributes->width > 1) ? (attributes->width) : (1);
+ private->height = (attributes->height > 1) ? (attributes->height) : (1);
+ private->window_type = attributes->window_type;
+ private->extension_events = FALSE;
+ private->dnd_drag_data_type = None;
+ private->dnd_drag_data_typesavail =
+ private->dnd_drop_data_typesavail = NULL;
+ private->dnd_drop_enabled = private->dnd_drag_enabled =
+ private->dnd_drag_accepted = private->dnd_drag_datashow =
+ private->dnd_drop_data_numtypesavail =
+ private->dnd_drag_data_numtypesavail = 0;
+ private->dnd_drag_eventmask = private->dnd_drag_savedeventmask = 0;
+
+ window->user_data = NULL;
+
+ if (attributes_mask & GDK_WA_VISUAL)
+ visual = attributes->visual;
+ else
+ visual = gdk_visual_get_system ();
+ xvisual = ((GdkVisualPrivate*) visual)->xvisual;
+
+ xattributes.event_mask = StructureNotifyMask;
+ for (i = 0; i < nevent_masks; i++)
+ {
+ if (attributes->event_mask & (1 << (i + 1)))
+ xattributes.event_mask |= event_mask_table[i];
+ }
+
+ if (xattributes.event_mask)
+ xattributes_mask |= CWEventMask;
+
+ if (attributes->wclass == GDK_INPUT_OUTPUT)
+ {
+ class = InputOutput;
+ depth = visual->depth;
+
+ if (attributes_mask & GDK_WA_COLORMAP)
+ colormap = attributes->colormap;
+ else
+ colormap = gdk_colormap_get_system ();
+
+ xattributes.background_pixel = BlackPixel (gdk_display, gdk_screen);
+ xattributes.border_pixel = BlackPixel (gdk_display, gdk_screen);
+ xattributes_mask |= CWBorderPixel | CWBackPixel;
+
+ switch (private->window_type)
+ {
+ case GDK_WINDOW_TOPLEVEL:
+ xattributes.colormap = ((GdkColormapPrivate*) colormap)->xcolormap;
+ xattributes_mask |= CWColormap;
+
+ xparent = gdk_root_window;
+ break;
+
+ case GDK_WINDOW_CHILD:
+ xattributes.colormap = ((GdkColormapPrivate*) colormap)->xcolormap;
+ xattributes_mask |= CWColormap;
+ break;
+
+ case GDK_WINDOW_DIALOG:
+ xattributes.colormap = ((GdkColormapPrivate*) colormap)->xcolormap;
+ xattributes_mask |= CWColormap;
+
+ xparent = gdk_root_window;
+ break;
+
+ case GDK_WINDOW_TEMP:
+ xattributes.colormap = ((GdkColormapPrivate*) colormap)->xcolormap;
+ xattributes_mask |= CWColormap;
+
+ xparent = gdk_root_window;
+
+ xattributes.save_under = True;
+ xattributes.override_redirect = True;
+ xattributes.cursor = None;
+ xattributes_mask |= CWSaveUnder | CWOverrideRedirect;
+ break;
+ case GDK_WINDOW_ROOT:
+ g_error ("cannot make windows of type GDK_WINDOW_ROOT");
+ break;
+ case GDK_WINDOW_PIXMAP:
+ g_error ("cannot make windows of type GDK_WINDOW_PIXMAP (use gdk_pixmap_new)");
+ break;
+ }
+ }
+ else
+ {
+ depth = 1;
+ class = InputOnly;
+ colormap = NULL;
+ }
+
+ private->xwindow = XCreateWindow (private->xdisplay, xparent,
+ x, y, private->width, private->height,
+ 0, depth, class, xvisual,
+ xattributes_mask, &xattributes);
+ gdk_xid_table_insert (&private->xwindow, window);
+
+ switch (private->window_type)
+ {
+ case GDK_WINDOW_DIALOG:
+ XSetTransientForHint (private->xdisplay, private->xwindow, xparent);
+ case GDK_WINDOW_TOPLEVEL:
+ case GDK_WINDOW_TEMP:
+ XSetWMProtocols (private->xdisplay, private->xwindow, gdk_wm_window_protocols, 2);
+ break;
+ case GDK_WINDOW_CHILD:
+ if ((attributes->wclass == GDK_INPUT_OUTPUT) &&
+ (colormap != gdk_colormap_get_system ()) &&
+ (colormap != gdk_window_get_colormap (gdk_window_get_toplevel (window))))
+ {
+ g_print ("adding colormap window\n");
+ gdk_window_add_colormap_windows (window);
+ }
+ break;
+ default:
+ break;
+ }
+
+ size_hints.flags = PSize | PBaseSize;
+ size_hints.width = private->width;
+ size_hints.height = private->height;
+ size_hints.base_width = private->width;
+ size_hints.base_height = private->height;
+
+ wm_hints.flags = InputHint | StateHint | WindowGroupHint;
+ wm_hints.window_group = gdk_leader_window;
+ wm_hints.input = True;
+ wm_hints.initial_state = NormalState;
+
+ XSetWMNormalHints (private->xdisplay, private->xwindow, &size_hints);
+ XSetWMHints (private->xdisplay, private->xwindow, &wm_hints);
+
+ if (attributes_mask & GDK_WA_TITLE)
+ title = attributes->title;
+ else
+ title = gdk_progname;
+
+ if (XStringListToTextProperty (&title, 1, &text_property))
+ {
+ XSetWMName (private->xdisplay, private->xwindow, &text_property);
+ XSetWMIconName (private->xdisplay, private->xwindow, &text_property);
+ XFree (text_property.value);
+ }
+
+ if (attributes_mask & GDK_WA_WMCLASS)
+ {
+ class_hint = XAllocClassHint ();
+ class_hint->res_name = attributes->wmclass_name;
+ class_hint->res_class = attributes->wmclass_class;
+ XSetClassHint (private->xdisplay, private->xwindow, class_hint);
+ XFree (class_hint);
+ }
+
+ gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
+ (attributes->cursor) :
+ NULL));
+
+ return window;
+}
+
+GdkWindow *
+gdk_window_foreign_new (guint32 anid)
+{
+ GdkWindow *window;
+ GdkWindowPrivate *private;
+ XWindowAttributes attrs;
+
+ private = g_new (GdkWindowPrivate, 1);
+ window = (GdkWindow*) private;
+
+ XGetWindowAttributes (gdk_display, anid, &attrs);
+
+ private->parent = NULL;
+ private->xwindow = anid;
+ private->xdisplay = gdk_display;
+ private->x = attrs.x;
+ private->y = attrs.y;
+ private->width = attrs.width;
+ private->height = attrs.height;
+ private->resize_count = 0;
+ private->ref_count = 1;
+ if (anid == attrs.root)
+ private->window_type = GDK_WINDOW_ROOT;
+ else
+ private->window_type = GDK_WINDOW_TOPLEVEL;
+ /* the above is probably wrong, but it may not be worth the extra
+ X call to get it right */
+
+ private->destroyed = FALSE;
+ private->extension_events = 0;
+
+ window->user_data = NULL;
+
+ gdk_xid_table_insert (&private->xwindow, window);
+
+ return window;
+}
+
+void
+gdk_window_destroy (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+ GdkWindowPrivate *temp_private;
+ GdkWindow *temp_window;
+ GList *children;
+ GList *tmp;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+ if(private->dnd_drag_data_numtypesavail > 0)
+ {
+ free(private->dnd_drag_data_typesavail);
+ private->dnd_drag_data_typesavail = NULL;
+ }
+ if(private->dnd_drop_data_numtypesavail > 0)
+ {
+ free(private->dnd_drop_data_typesavail);
+ private->dnd_drop_data_typesavail = NULL;
+ }
+
+ switch (private->window_type)
+ {
+ case GDK_WINDOW_TOPLEVEL:
+ case GDK_WINDOW_CHILD:
+ case GDK_WINDOW_DIALOG:
+ case GDK_WINDOW_TEMP:
+ if (private->ref_count >= 1)
+ private->ref_count -= 1;
+
+ if (!private->destroyed || (private->destroyed == 2))
+ {
+ children = gdk_window_get_children (window);
+ tmp = children;
+
+ while (tmp)
+ {
+ temp_window = tmp->data;
+ tmp = tmp->next;
+
+ temp_private = (GdkWindowPrivate*) temp_window;
+ if (temp_private && !temp_private->destroyed)
+ /* Removes some nice coredumps... /David */
+ {
+ temp_private->destroyed = 2;
+ temp_private->ref_count += 1;
+ gdk_window_destroy (temp_window);
+ }
+ }
+
+ g_list_free (children);
+
+ if (!private->destroyed)
+ XDestroyWindow (private->xdisplay, private->xwindow);
+ private->destroyed = TRUE;
+ }
+ break;
+
+ case GDK_WINDOW_ROOT:
+ g_error ("attempted to destroy root window");
+ break;
+
+ case GDK_WINDOW_PIXMAP:
+ g_warning ("called gdk_window_destroy on a pixmap (use gdk_pixmap_destroy)");
+ gdk_pixmap_destroy (window);
+ break;
+ }
+}
+
+void
+gdk_window_real_destroy (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+
+ if (private->extension_events != 0)
+ gdk_input_window_destroy (window);
+
+ if (private->ref_count == 0)
+ {
+ gdk_xid_table_remove (private->xwindow);
+ g_free (window);
+ }
+}
+
+GdkWindow*
+gdk_window_ref (GdkWindow *window)
+{
+ GdkWindowPrivate *private = (GdkWindowPrivate *)window;
+ g_return_if_fail (window != NULL);
+
+ private->ref_count += 1;
+ return window;
+}
+
+void
+gdk_window_unref (GdkWindow *window)
+{
+ GdkWindowPrivate *private = (GdkWindowPrivate *)window;
+ g_return_if_fail (window != NULL);
+
+ private->ref_count -= 1;
+ if (private->ref_count == 0)
+ gdk_window_real_destroy (window);
+}
+
+void
+gdk_window_show (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+ if (!private->destroyed)
+ {
+ XRaiseWindow (private->xdisplay, private->xwindow);
+ XMapWindow (private->xdisplay, private->xwindow);
+ }
+}
+
+void
+gdk_window_hide (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+ if (!private->destroyed)
+ XUnmapWindow (private->xdisplay, private->xwindow);
+}
+
+void
+gdk_window_move (GdkWindow *window,
+ gint x,
+ gint y)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+ XMoveWindow (private->xdisplay, private->xwindow, x, y);
+
+ if (private->window_type == GDK_WINDOW_CHILD)
+ {
+ private->x = x;
+ private->y = y;
+ }
+}
+
+void
+gdk_window_resize (GdkWindow *window,
+ gint width,
+ gint height)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ if (width < 1)
+ width = 1;
+ if (height < 1)
+ height = 1;
+
+ private = (GdkWindowPrivate*) window;
+
+ if (!private->destroyed &&
+ ((private->resize_count > 0) ||
+ (private->width != (guint16) width) ||
+ (private->height != (guint16) height)))
+ {
+ XResizeWindow (private->xdisplay, private->xwindow, width, height);
+ private->resize_count += 1;
+
+ if (private->window_type == GDK_WINDOW_CHILD)
+ {
+ private->width = width;
+ private->height = height;
+ }
+ }
+}
+
+void
+gdk_window_move_resize (GdkWindow *window,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ if (width < 1)
+ width = 1;
+ if (height < 1)
+ height = 1;
+
+ private = (GdkWindowPrivate*) window;
+ XMoveResizeWindow (private->xdisplay, private->xwindow, x, y, width, height);
+
+ if (!private->destroyed &&
+ (private->window_type == GDK_WINDOW_CHILD))
+ {
+ private->x = x;
+ private->y = y;
+ private->width = width;
+ private->height = height;
+ }
+}
+
+void
+gdk_window_reparent (GdkWindow *window,
+ GdkWindow *new_parent,
+ gint x,
+ gint y)
+{
+ GdkWindowPrivate *window_private;
+ GdkWindowPrivate *parent_private;
+
+ g_return_if_fail (window != NULL);
+
+ if (!new_parent)
+ new_parent = (GdkWindow*) &gdk_root_parent;
+
+ window_private = (GdkWindowPrivate*) window;
+ parent_private = (GdkWindowPrivate*) new_parent;
+
+ XReparentWindow (window_private->xdisplay,
+ window_private->xwindow,
+ parent_private->xwindow,
+ x, y);
+}
+
+void
+gdk_window_clear (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+
+ XClearWindow (private->xdisplay, private->xwindow);
+}
+
+void
+gdk_window_clear_area (GdkWindow *window,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+
+ if (!private->destroyed)
+ XClearArea (private->xdisplay, private->xwindow,
+ x, y, width, height, False);
+}
+
+void
+gdk_window_clear_area_e (GdkWindow *window,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+
+ if (!private->destroyed)
+ XClearArea (private->xdisplay, private->xwindow,
+ x, y, width, height, True);
+}
+
+void
+gdk_window_copy_area (GdkWindow *window,
+ GdkGC *gc,
+ gint x,
+ gint y,
+ GdkWindow *source_window,
+ gint source_x,
+ gint source_y,
+ gint width,
+ gint height)
+{
+ GdkWindowPrivate *src_private;
+ GdkWindowPrivate *dest_private;
+ GdkGCPrivate *gc_private;
+
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (gc != NULL);
+
+ if (source_window == NULL)
+ source_window = window;
+
+ src_private = (GdkWindowPrivate*) source_window;
+ dest_private = (GdkWindowPrivate*) window;
+ gc_private = (GdkGCPrivate*) gc;
+
+ if (!src_private->destroyed && !dest_private->destroyed)
+ {
+ XCopyArea (dest_private->xdisplay, src_private->xwindow, dest_private->xwindow,
+ gc_private->xgc,
+ source_x, source_y,
+ width, height,
+ x, y);
+ }
+}
+
+void
+gdk_window_raise (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+
+ if (!private->destroyed)
+ XRaiseWindow (private->xdisplay, private->xwindow);
+}
+
+void
+gdk_window_lower (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+
+ if (!private->destroyed)
+ XLowerWindow (private->xdisplay, private->xwindow);
+}
+
+void
+gdk_window_set_user_data (GdkWindow *window,
+ gpointer user_data)
+{
+ g_return_if_fail (window != NULL);
+
+ window->user_data = user_data;
+}
+
+void
+gdk_window_set_hints (GdkWindow *window,
+ gint x,
+ gint y,
+ gint min_width,
+ gint min_height,
+ gint max_width,
+ gint max_height,
+ gint flags)
+{
+ GdkWindowPrivate *private;
+ XSizeHints size_hints;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+ size_hints.flags = 0;
+
+ if (flags & GDK_HINT_POS)
+ {
+ size_hints.flags |= PPosition;
+ size_hints.x = x;
+ size_hints.y = y;
+ }
+
+ if (flags & GDK_HINT_MIN_SIZE)
+ {
+ size_hints.flags |= PMinSize;
+ size_hints.min_width = min_width;
+ size_hints.min_height = min_height;
+ }
+
+ if (flags & GDK_HINT_MAX_SIZE)
+ {
+ size_hints.flags |= PMaxSize;
+ size_hints.max_width = max_width;
+ size_hints.max_height = max_height;
+ }
+
+ if (flags)
+ XSetWMNormalHints (private->xdisplay, private->xwindow, &size_hints);
+}
+
+void
+gdk_window_set_title (GdkWindow *window,
+ const gchar *title)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+ XStoreName (private->xdisplay, private->xwindow, title);
+ XSetIconName (private->xdisplay, private->xwindow, title);
+}
+
+void
+gdk_window_set_background (GdkWindow *window,
+ GdkColor *color)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+ XSetWindowBackground (private->xdisplay, private->xwindow, color->pixel);
+}
+
+void
+gdk_window_set_back_pixmap (GdkWindow *window,
+ GdkPixmap *pixmap,
+ gint parent_relative)
+{
+ GdkWindowPrivate *window_private;
+ GdkPixmapPrivate *pixmap_private;
+ Pixmap xpixmap;
+
+ g_return_if_fail (window != NULL);
+
+ window_private = (GdkWindowPrivate*) window;
+ pixmap_private = (GdkPixmapPrivate*) pixmap;
+
+ if (pixmap)
+ xpixmap = pixmap_private->xwindow;
+ else
+ xpixmap = None;
+
+ if (parent_relative)
+ xpixmap = ParentRelative;
+
+ XSetWindowBackgroundPixmap (window_private->xdisplay, window_private->xwindow, xpixmap);
+}
+
+void
+gdk_window_set_cursor (GdkWindow *window,
+ GdkCursor *cursor)
+{
+ GdkWindowPrivate *window_private;
+ GdkCursorPrivate *cursor_private;
+ Cursor xcursor;
+
+ g_return_if_fail (window != NULL);
+
+ window_private = (GdkWindowPrivate*) window;
+ cursor_private = (GdkCursorPrivate*) cursor;
+
+ if (!cursor)
+ xcursor = None;
+ else
+ xcursor = cursor_private->xcursor;
+
+ XDefineCursor (window_private->xdisplay, window_private->xwindow, xcursor);
+}
+
+void
+gdk_window_set_colormap (GdkWindow *window,
+ GdkColormap *colormap)
+{
+ GdkWindowPrivate *window_private;
+ GdkColormapPrivate *colormap_private;
+
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (colormap != NULL);
+
+ window_private = (GdkWindowPrivate*) window;
+ colormap_private = (GdkColormapPrivate*) colormap;
+
+ XSetWindowColormap (window_private->xdisplay,
+ window_private->xwindow,
+ colormap_private->xcolormap);
+
+ if (window_private->window_type != GDK_WINDOW_TOPLEVEL)
+ gdk_window_add_colormap_windows (window);
+}
+
+void
+gdk_window_get_user_data (GdkWindow *window,
+ gpointer *data)
+{
+ g_return_if_fail (window != NULL);
+
+ *data = window->user_data;
+}
+
+void
+gdk_window_get_geometry (GdkWindow *window,
+ gint *x,
+ gint *y,
+ gint *width,
+ gint *height,
+ gint *depth)
+{
+ GdkWindowPrivate *window_private;
+ Window root;
+ gint tx;
+ gint ty;
+ guint twidth;
+ guint theight;
+ guint tborder_width;
+ guint tdepth;
+
+ if (!window)
+ window = (GdkWindow*) &gdk_root_parent;
+
+ window_private = (GdkWindowPrivate*) window;
+
+ XGetGeometry (window_private->xdisplay, window_private->xwindow,
+ &root, &tx, &ty, &twidth, &theight, &tborder_width, &tdepth);
+
+ if (x)
+ *x = tx;
+ if (y)
+ *y = ty;
+ if (width)
+ *width = twidth;
+ if (height)
+ *height = theight;
+ if (depth)
+ *depth = tdepth;
+}
+
+void
+gdk_window_get_position (GdkWindow *window,
+ gint *x,
+ gint *y)
+{
+ GdkWindowPrivate *window_private;
+
+ g_return_if_fail (window != NULL);
+
+ window_private = (GdkWindowPrivate*) window;
+
+ if (x)
+ *x = window_private->x;
+ if (y)
+ *y = window_private->y;
+}
+
+void
+gdk_window_get_size (GdkWindow *window,
+ gint *width,
+ gint *height)
+{
+ GdkWindowPrivate *window_private;
+
+ g_return_if_fail (window != NULL);
+
+ window_private = (GdkWindowPrivate*) window;
+
+ if (width)
+ *width = window_private->width;
+ if (height)
+ *height = window_private->height;
+}
+
+
+GdkVisual*
+gdk_window_get_visual (GdkWindow *window)
+{
+ GdkWindowPrivate *window_private;
+ XWindowAttributes window_attributes;
+
+ g_return_val_if_fail (window != NULL, NULL);
+
+ window_private = (GdkWindowPrivate*) window;
+ while (window_private && (window_private->window_type == GDK_WINDOW_PIXMAP))
+ window_private = (GdkWindowPrivate*) window_private->parent;
+
+ if (window_private)
+ {
+ XGetWindowAttributes (window_private->xdisplay,
+ window_private->xwindow,
+ &window_attributes);
+
+ return gdk_visual_lookup (window_attributes.visual);
+ }
+
+ return NULL;
+}
+
+GdkColormap*
+gdk_window_get_colormap (GdkWindow *window)
+{
+ GdkWindowPrivate *window_private;
+ XWindowAttributes window_attributes;
+
+ g_return_val_if_fail (window != NULL, NULL);
+
+ window_private = (GdkWindowPrivate*) window;
+
+ XGetWindowAttributes (window_private->xdisplay,
+ window_private->xwindow,
+ &window_attributes);
+
+ return gdk_colormap_lookup (window_attributes.colormap);
+}
+
+GdkWindowType
+gdk_window_get_type (GdkWindow *window)
+{
+ GdkWindowPrivate *window_private;
+
+ g_return_val_if_fail (window != NULL, (GdkWindowType) -1);
+
+ window_private = (GdkWindowPrivate*) window;
+ return window_private->window_type;
+}
+
+gint
+gdk_window_get_origin (GdkWindow *window,
+ gint *x,
+ gint *y)
+{
+ GdkWindowPrivate *private;
+ gint return_val;
+ Window child;
+ gint tx, ty;
+
+ g_return_val_if_fail (window != NULL, 0);
+
+ private = (GdkWindowPrivate*) window;
+
+ return_val = XTranslateCoordinates (private->xdisplay,
+ private->xwindow,
+ gdk_root_window,
+ 0, 0, &tx, &ty,
+ &child);
+
+ if (x)
+ *x = tx;
+ if (y)
+ *y = ty;
+
+ return return_val;
+}
+
+GdkWindow*
+gdk_window_get_pointer (GdkWindow *window,
+ gint *x,
+ gint *y,
+ GdkModifierType *mask)
+{
+ GdkWindowPrivate *private;
+ GdkWindow *return_val;
+ Window root;
+ Window child;
+ int rootx, rooty;
+ int winx, winy;
+ unsigned int xmask;
+
+ if (!window)
+ window = (GdkWindow*) &gdk_root_parent;
+
+ private = (GdkWindowPrivate*) window;
+
+ return_val = NULL;
+ if (XQueryPointer (private->xdisplay, private->xwindow, &root, &child,
+ &rootx, &rooty, &winx, &winy, &xmask))
+ {
+ if (x) *x = winx;
+ if (y) *y = winy;
+ if (mask) *mask = xmask;
+
+ if (child)
+ return_val = gdk_window_lookup (child);
+ }
+
+ return return_val;
+}
+
+GdkWindow*
+gdk_window_get_parent (GdkWindow *window)
+{
+ g_return_val_if_fail (window != NULL, NULL);
+
+ return ((GdkWindowPrivate*) window)->parent;
+}
+
+GdkWindow*
+gdk_window_get_toplevel (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+
+ g_return_val_if_fail (window != NULL, NULL);
+
+ private = (GdkWindowPrivate*) window;
+
+ while (private->window_type == GDK_WINDOW_CHILD)
+ {
+ window = ((GdkWindowPrivate*) window)->parent;
+ private = (GdkWindowPrivate*) window;
+ }
+
+ return window;
+}
+
+GList*
+gdk_window_get_children (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+ GdkWindow *child;
+ GList *children;
+ Window root;
+ Window parent;
+ Window *xchildren;
+ unsigned int nchildren;
+ unsigned int i;
+
+ g_return_val_if_fail (window != NULL, NULL);
+
+ private = (GdkWindowPrivate*) window;
+
+ XQueryTree (private->xdisplay, private->xwindow,
+ &root, &parent, &xchildren, &nchildren);
+
+ children = NULL;
+
+ if (nchildren > 0)
+ {
+ for (i = 0; i < nchildren; i++)
+ {
+ child = gdk_window_lookup (xchildren[i]);
+ if (child)
+ children = g_list_prepend (children, child);
+ }
+
+ XFree (xchildren);
+ }
+
+ return children;
+}
+
+GdkEventMask
+gdk_window_get_events (GdkWindow *window)
+{
+ XWindowAttributes attrs;
+ GdkEventMask event_mask;
+ int i;
+
+ XGetWindowAttributes (gdk_display, ((GdkWindowPrivate *)window)->xwindow,
+ &attrs);
+
+ event_mask = 0;
+ for (i = 0; i < nevent_masks; i++)
+ {
+ if (attrs.your_event_mask & event_mask_table[i])
+ event_mask |= 1 << (i + 1);
+ }
+
+ return event_mask;
+}
+
+void
+gdk_window_set_events (GdkWindow *window,
+ GdkEventMask event_mask)
+{
+ long xevent_mask;
+ int i;
+
+ xevent_mask = StructureNotifyMask;
+ for (i = 0; i < nevent_masks; i++)
+ {
+ if (event_mask & (1 << (i + 1)))
+ xevent_mask |= event_mask_table[i];
+ }
+
+ XSelectInput (gdk_display, ((GdkWindowPrivate *)window)->xwindow,
+ xevent_mask);
+}
+
+void
+gdk_window_add_colormap_windows (GdkWindow *window)
+{
+ GdkWindow *toplevel;
+ GdkWindowPrivate *toplevel_private;
+ GdkWindowPrivate *window_private;
+ Window *old_windows;
+ Window *new_windows;
+ int i, count;
+
+ g_return_if_fail (window != NULL);
+
+ toplevel = gdk_window_get_toplevel (window);
+ toplevel_private = (GdkWindowPrivate*) toplevel;
+ window_private = (GdkWindowPrivate*) window;
+
+ if (!XGetWMColormapWindows (toplevel_private->xdisplay,
+ toplevel_private->xwindow,
+ &old_windows, &count))
+ {
+ old_windows = NULL;
+ count = 0;
+ }
+
+ for (i = 0; i < count; i++)
+ if (old_windows[i] == window_private->xwindow)
+ return;
+
+ new_windows = g_new (Window, count + 1);
+
+ for (i = 0; i < count; i++)
+ new_windows[i] = old_windows[i];
+ new_windows[count] = window_private->xwindow;
+
+ XSetWMColormapWindows (toplevel_private->xdisplay,
+ toplevel_private->xwindow,
+ new_windows, count + 1);
+
+ g_free (new_windows);
+ if (old_windows)
+ XFree (old_windows);
+}
+
+/*
+ * This needs the X11 shape extension.
+ * If not available, simply remove the call to
+ * XShapeCombineMask. Shaped windows will look
+ * ugly, but programs still work. Stefan Wille
+ */
+void
+gdk_window_shape_combine_mask (GdkWindow *window,
+ GdkBitmap *mask,
+ gint x, gint y)
+{
+ GdkWindowPrivate *window_private;
+ GdkWindowPrivate *pixmap_private;
+
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (mask != NULL);
+
+ window_private = (GdkWindowPrivate*) window;
+ pixmap_private = (GdkWindowPrivate*) mask;
+
+ XShapeCombineMask (window_private->xdisplay,
+ window_private->xwindow,
+ ShapeBounding,
+ x, y, /* offset */
+ (Pixmap)pixmap_private->xwindow,
+ ShapeSet);
+}
+
+void
+gdk_dnd_drag_addwindow (GdkWindow *window)
+{
+ GdkWindowPrivate *window_private;
+
+ g_return_if_fail (window != NULL);
+
+ window_private = (GdkWindowPrivate *) window;
+
+ if (window_private->dnd_drag_enabled == 1 && gdk_dnd.drag_really == 0)
+ {
+ gdk_dnd.drag_numwindows++;
+ gdk_dnd.drag_startwindows = g_realloc (gdk_dnd.drag_startwindows,
+ gdk_dnd.drag_numwindows
+ * sizeof(GdkWindow *));
+ gdk_dnd.drag_startwindows[gdk_dnd.drag_numwindows - 1] = window;
+ window_private->dnd_drag_accepted = 0;
+ }
+ else
+ g_warning ("dnd_really is 1 or drag is not enabled! can't addwindow\n");
+}
+
+void
+gdk_window_dnd_drag_set (GdkWindow *window,
+ guint8 drag_enable,
+ gchar **typelist,
+ guint numtypes)
+{
+ GdkWindowPrivate *window_private;
+ int i, wasset = 0;
+
+ g_return_if_fail (window != NULL);
+ window_private = (GdkWindowPrivate *) window;
+
+ window_private->dnd_drag_enabled = drag_enable ? 1 : 0;
+
+ if (drag_enable)
+ {
+ g_return_if_fail(typelist != NULL);
+
+ if (window_private->dnd_drag_data_numtypesavail > 3)
+ wasset = 1;
+ window_private->dnd_drag_data_numtypesavail = numtypes;
+
+ window_private->dnd_drag_data_typesavail =
+ g_realloc (window_private->dnd_drag_data_typesavail,
+ (numtypes + 1) * sizeof (GdkAtom));
+
+ for (i = 0; i < numtypes; i++)
+ {
+ /* Allow blanket use of ALL to get anything... */
+ if (strcmp (typelist[i], "ALL"))
+ window_private->dnd_drag_data_typesavail[i] =
+ gdk_atom_intern (typelist[i], FALSE);
+ else
+ window_private->dnd_drag_data_typesavail[i] = None;
+ }
+
+ /*
+ * set our extended type list if we need to
+ */
+ if (numtypes > 3)
+ gdk_property_change(window, gdk_dnd.gdk_XdeTypelist,
+ XA_PRIMARY, 32, GDK_PROP_MODE_REPLACE,
+ (guchar *)(window_private->dnd_drag_data_typesavail
+ + (sizeof(GdkAtom) * 3)),
+ (numtypes - 3) * sizeof(GdkAtom));
+ else if (wasset)
+ gdk_property_delete (window, gdk_dnd.gdk_XdeTypelist);
+ }
+ else
+ {
+ free (window_private->dnd_drag_data_typesavail);
+ window_private->dnd_drag_data_typesavail = NULL;
+ window_private->dnd_drag_data_numtypesavail = 0;
+ }
+}
+
+void
+gdk_window_dnd_drop_set (GdkWindow *window,
+ guint8 drop_enable,
+ gchar **typelist,
+ guint numtypes,
+ guint8 destructive_op)
+{
+ GdkWindowPrivate *window_private;
+ int i;
+
+ g_return_if_fail (window != NULL);
+
+ window_private = (GdkWindowPrivate *) window;
+
+ window_private->dnd_drop_enabled = drop_enable ? 1 : 0;
+ if (drop_enable)
+ {
+ g_return_if_fail(typelist != NULL);
+
+ window_private->dnd_drop_data_numtypesavail = numtypes;
+
+ window_private->dnd_drop_data_typesavail =
+ g_realloc (window_private->dnd_drop_data_typesavail,
+ (numtypes + 1) * sizeof (GdkAtom));
+
+ for (i = 0; i < numtypes; i++)
+ window_private->dnd_drop_data_typesavail[i] =
+ gdk_atom_intern (typelist[i], FALSE);
+
+ window_private->dnd_drop_destructive_op = destructive_op;
+ }
+}
+
+/*
+ * This is used to reply to a GDK_DRAG_REQUEST event
+ * (which may be generated by XdeRequest or a confirmed drop...
+ */
+void
+gdk_window_dnd_data_set (GdkWindow *window,
+ GdkEvent *event,
+ gpointer data,
+ gulong data_numbytes)
+{
+ GdkWindowPrivate *window_private;
+ XEvent sev;
+ GdkEventDropDataAvailable tmp_ev;
+ gchar *tmp;
+
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (event != NULL);
+ g_return_if_fail (data != NULL);
+ g_return_if_fail (data_numbytes > 0);
+ g_return_if_fail (event->type == GDK_DRAG_REQUEST);
+
+ g_free (event->dragrequest.data_type);
+ event->dragrequest.data_type = NULL;
+
+ window_private = (GdkWindowPrivate *) window;
+ g_return_if_fail (window_private->dnd_drag_accepted != 0);
+
+ /* We set the property on our window... */
+ gdk_property_change (window, window_private->dnd_drag_data_type,
+ XA_PRIMARY, 8, GDK_PROP_MODE_REPLACE, data,
+ data_numbytes);
+ tmp = gdk_atom_name(window_private->dnd_drag_data_type);
+ g_print("DnD type %s on window %ld\n", tmp, window_private->xwindow);
+ g_free(tmp);
+
+ /*
+ * Then we send the event to tell the receiving window that the
+ * drop has happened
+ */
+ tmp_ev.u.allflags = 0;
+ tmp_ev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
+ tmp_ev.u.flags.isdrop = event->dragrequest.isdrop;
+
+ sev.xclient.type = ClientMessage;
+ sev.xclient.format = 32;
+ sev.xclient.window = event->dragrequest.requestor;
+ sev.xclient.message_type = gdk_dnd.gdk_XdeDataAvailable;
+ sev.xclient.data.l[0] = window_private->xwindow;
+ sev.xclient.data.l[1] = tmp_ev.u.allflags;
+ sev.xclient.data.l[2] = window_private->dnd_drag_data_type;
+
+ if (event->dragrequest.isdrop)
+ sev.xclient.data.l[3] = event->dragrequest.drop_coords.x +
+ (event->dragrequest.drop_coords.y << 16);
+ else
+ sev.xclient.data.l[3] = 0;
+
+ sev.xclient.data.l[4] = 0;
+
+ XSendEvent (gdk_display, event->dragrequest.requestor, False,
+ NoEventMask, &sev);
+}
diff --git a/gdk/x11/gdkx.h b/gdk/x11/gdkx.h
new file mode 100644
index 000000000..cb8e33b44
--- /dev/null
+++ b/gdk/x11/gdkx.h
@@ -0,0 +1,48 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GDK_X_H__
+#define __GDK_X_H__
+
+#include <gdk/gdkprivate.h>
+
+
+#define GDK_ROOT_WINDOW() gdk_root_window
+#define GDK_ROOT_PARENT() &gdk_root_parent
+#define GDK_DISPLAY() gdk_display
+#define GDK_WINDOW_XDISPLAY(win) (((GdkWindowPrivate*) win)->xdisplay)
+#define GDK_WINDOW_XWINDOW(win) (((GdkWindowPrivate*) win)->xwindow)
+#define GDK_IMAGE_XDISPLAY(image) (((GdkImagePrivate*) image)->xdisplay)
+#define GDK_IMAGE_XIMAGE(image) (((GdkImagePrivate*) image)->ximage)
+#define GDK_GC_XDISPLAY(gc) (((GdkGCPrivate*) gc)->xdisplay)
+#define GDK_GC_XGC(gc) (((GdkGCPrivate*) gc)->xgc)
+#define GDK_COLORMAP_XDISPLAY(cmap) (((GdkColormapPrivate*) cmap)->xdisplay)
+#define GDK_COLORMAP_XCOLORMAP(cmap) (((GdkColormapPrivate*) cmap)->xcolormap)
+#define GDK_VISUAL_XVISUAL(vis) (((GdkVisualPrivate*) vis)->xvisual)
+#define GDK_FONT_XDISPLAY(font) (((GdkFontPrivate*) font)->xdisplay)
+#define GDK_FONT_XFONT(font) (((GdkFontPrivate*) font)->xfont)
+
+
+GdkVisual* gdkx_visual_get (VisualID xvisualid);
+GdkColormap* gdkx_colormap_get (Colormap xcolormap);
+/* Utility function in gdk.c - not sure where it belongs, but it's
+ needed in more than one place, so make it public */
+Window gdk_get_client_window (Display *dpy,
+ Window win);
+
+
+#endif /* __GDK_X_H__ */
diff --git a/gdk/x11/gdkxid.c b/gdk/x11/gdkxid.c
new file mode 100644
index 000000000..7ee6075c5
--- /dev/null
+++ b/gdk/x11/gdkxid.c
@@ -0,0 +1,74 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gdkprivate.h"
+
+
+static guint gdk_xid_hash (XID *xid);
+static gint gdk_xid_compare (XID *a,
+ XID *b);
+
+
+GHashTable *xid_ht = NULL;
+
+
+void
+gdk_xid_table_insert (XID *xid,
+ gpointer data)
+{
+ g_return_if_fail (xid != NULL);
+
+ if (!xid_ht)
+ xid_ht = g_hash_table_new ((GHashFunc) gdk_xid_hash,
+ (GCompareFunc) gdk_xid_compare);
+
+ g_hash_table_insert (xid_ht, xid, data);
+}
+
+void
+gdk_xid_table_remove (XID xid)
+{
+ if (!xid_ht)
+ xid_ht = g_hash_table_new ((GHashFunc) gdk_xid_hash,
+ (GCompareFunc) gdk_xid_compare);
+
+ g_hash_table_remove (xid_ht, &xid);
+}
+
+gpointer
+gdk_xid_table_lookup (XID xid)
+{
+ gpointer data;
+
+ data = g_hash_table_lookup (xid_ht, &xid);
+
+ return data;
+}
+
+
+static guint
+gdk_xid_hash (XID *xid)
+{
+ return *xid;
+}
+
+static gint
+gdk_xid_compare (XID *a,
+ XID *b)
+{
+ return (*a == *b);
+}
diff --git a/gdk/x11/gxid.c b/gdk/x11/gxid.c
new file mode 100644
index 000000000..219c08bfe
--- /dev/null
+++ b/gdk/x11/gxid.c
@@ -0,0 +1,844 @@
+/*
+ * gxid version 0.3
+ *
+ * Copyright 1997 Owen Taylor <owt1@cornell.edu>
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/XInput.h>
+
+#include "gxid_proto.h"
+
+/* #define DEBUG_CLIENTS */
+/* #define DEBUG_EVENTS */
+
+char *program_name;
+Display *dpy;
+Window root_window; /* default root window of dpy */
+int port = 0; /* port to listen on */
+int socket_fd = 0; /* file descriptor of socket */
+typedef struct GxidWindow_ GxidWindow;
+
+typedef struct GxidDevice_ GxidDevice;
+struct GxidDevice_ {
+ XID id;
+ int exclusive;
+ int ispointer;
+
+ XDevice *xdevice;
+ int motionnotify_type;
+ int changenotify_type;
+};
+
+struct GxidWindow_ {
+ Window xwindow;
+ /* Immediate child of root that is ancestor of window */
+ Window root_child;
+ int num_devices;
+ GxidDevice **devices;
+};
+
+GxidDevice **devices = NULL;
+int num_devices = 0;
+GxidWindow **windows = NULL;
+int num_windows = 0;
+
+void
+handler(int signal)
+{
+ fprintf(stderr,"%s: dying on signal %d\n",program_name,signal);
+ if (socket_fd)
+ close(socket_fd);
+ exit(1);
+}
+
+void
+init_socket()
+{
+ struct sockaddr_in sin;
+
+ socket_fd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
+ if (socket_fd < 0)
+ {
+ fprintf (stderr, "%s: error getting socket\n",
+ program_name);
+ exit(1);
+ }
+
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(port);
+ sin.sin_addr.s_addr = INADDR_ANY;
+
+ if (bind(socket_fd,(struct sockaddr *)(&sin),
+ sizeof(struct sockaddr_in)) < 0)
+ {
+ fprintf (stderr,"%s: cannot bind to port %d\n",
+ program_name,port);
+ exit(1);
+ }
+
+ if (listen(socket_fd,5) < 0)
+ {
+ fprintf (stderr,"%s: error listening on socket\n",
+ program_name);
+ exit(1);
+ };
+}
+
+#define NUM_EVENTC 2
+static void
+enable_device(GxidDevice *dev)
+{
+ XEventClass xevc[NUM_EVENTC];
+ int num_eventc = NUM_EVENTC;
+ int i,j;
+
+ if (!dev->xdevice)
+ {
+ if (dev->ispointer) return;
+
+ dev->xdevice = XOpenDevice(dpy, dev->id);
+ if (!dev->xdevice) return;
+
+ DeviceMotionNotify (dev->xdevice, dev->motionnotify_type,
+ xevc[0]);
+ ChangeDeviceNotify (dev->xdevice, dev->changenotify_type,
+ xevc[1]);
+
+ /* compress out zero event classes */
+ for (i=0,j=0;i<NUM_EVENTC;i++)
+ {
+ if (xevc[i]) {
+ xevc[j] = xevc[i];
+ j++;
+ }
+ }
+ num_eventc = j;
+
+ XSelectExtensionEvent (dpy, root_window, xevc, num_eventc);
+ }
+}
+
+/* switch the core pointer from whatever it is now to something else,
+ return true on success, false otherwise */
+static int
+switch_core_pointer()
+{
+ GxidDevice *old_pointer = 0;
+ GxidDevice *new_pointer = 0;
+ int result;
+ int i;
+
+ for (i=0;i<num_devices;i++)
+ {
+ if (devices[i]->ispointer)
+ old_pointer = devices[i];
+ else
+ if (!new_pointer && !devices[i]->exclusive)
+ new_pointer = devices[i];
+ }
+
+ if (!old_pointer || !new_pointer)
+ return 0;
+
+#ifdef DEBUG_EVENTS
+ fprintf(stderr,"gxid: Switching core from %ld to %ld\n",
+ old_pointer->id,new_pointer->id);
+#endif
+ result = XChangePointerDevice(dpy,new_pointer->xdevice, 0, 1);
+ if (result != Success)
+ {
+ fprintf(stderr,"gxid: Error %d switching core from %ld to %ld\n",
+ result, old_pointer->id, new_pointer->id);
+ }
+ else
+ {
+ new_pointer->ispointer = 1;
+ old_pointer->ispointer = 0;
+ if (!old_pointer->xdevice)
+ enable_device(old_pointer);
+ }
+
+ return 1;
+}
+
+void
+disable_device(GxidDevice *dev)
+{
+ if (dev->xdevice)
+ {
+ if (dev->ispointer)
+ return;
+ XCloseDevice(dpy,dev->xdevice);
+ dev->xdevice = 0;
+ }
+}
+
+GxidDevice *
+init_device(XDeviceInfo *xdevice)
+{
+ GxidDevice *dev = (GxidDevice *)malloc(sizeof(GxidDevice));
+ XAnyClassPtr class;
+ int num_axes, i;
+
+ dev->id = xdevice->id;
+ dev->exclusive = 0;
+ dev->xdevice = NULL;
+
+ dev->ispointer = (xdevice->use == IsXPointer);
+
+ /* step through the classes */
+
+ num_axes = 0;
+ class = xdevice->inputclassinfo;
+ for (i=0;i<xdevice->num_classes;i++)
+ {
+ if (class->class == ValuatorClass)
+ {
+ XValuatorInfo *xvi = (XValuatorInfo *)class;
+ num_axes = xvi->num_axes;
+ }
+ class = (XAnyClassPtr)(((char *)class) + class->length);
+ }
+
+ /* return NULL if insufficient axes */
+ if (num_axes < 2)
+ {
+ free((void *)dev);
+ return NULL;
+ }
+
+ if (!dev->ispointer)
+ enable_device(dev);
+ return dev;
+}
+
+void
+init_xinput()
+{
+ char **extensions;
+ XDeviceInfo *xdevices;
+ int num_xdevices;
+ int num_extensions;
+ int i;
+
+ extensions = XListExtensions(dpy, &num_extensions);
+ for (i = 0; i < num_extensions &&
+ (strcmp(extensions[i], "XInputExtension") != 0); i++);
+ XFreeExtensionList(extensions);
+ if (i == num_extensions) /* XInput extension not found */
+ {
+ fprintf(stderr,"XInput extension not found\n");
+ exit(1);
+ }
+
+ xdevices = XListInputDevices(dpy, &num_xdevices);
+ devices = (GxidDevice **)malloc(num_xdevices * sizeof(GxidDevice *));
+
+ num_devices = 0;
+ for(i=0; i<num_xdevices; i++)
+ {
+ GxidDevice *dev = init_device(&xdevices[i]);
+ if (dev)
+ devices[num_devices++] = dev;
+ }
+ XFreeDeviceList(xdevices);
+}
+
+/* If this routine needs fixing, the corresponding routine
+ in gdkinputgxi.h will need it too. */
+
+Window
+gxi_find_root_child(Display *dpy, Window w)
+{
+ Window root,parent;
+ Window *children;
+ int nchildren;
+
+ parent = w;
+ do
+ {
+ w = parent;
+ XQueryTree(dpy,w,&root,&parent,&children,&nchildren);
+ if (children) XFree(children);
+ }
+ while (parent != root);
+
+ return w;
+}
+
+int
+handle_claim_device(GxidClaimDevice *msg)
+{
+ int i,j;
+ XID devid = ntohl(msg->device);
+ XID winid = ntohl(msg->window);
+ int exclusive = ntohl(msg->exclusive);
+ GxidDevice *device = NULL;
+ GxidWindow *window = NULL;
+
+#ifdef DEBUG_CLIENTS
+ fprintf(stderr,"device %ld claimed (window 0x%lx)\n",devid,winid);
+#endif
+
+ for (i=0;i<num_devices;i++)
+ {
+ if (devices[i]->id == devid)
+ {
+ device = devices[i];
+ break;
+ }
+ }
+ if (!device)
+ {
+ fprintf(stderr,"%s: Unknown device id %ld\n",program_name,devid);
+ return GXID_RETURN_ERROR;
+ }
+
+ if (device->exclusive)
+ {
+ /* already in use */
+ fprintf(stderr,
+ "%s: Device %ld already claimed in exclusive mode\n",
+ program_name,devid);
+ return GXID_RETURN_ERROR;
+ }
+
+ if (exclusive)
+ {
+ for (i=0;i<num_windows;i++)
+ {
+ for (j=0;j<windows[i]->num_devices;j++)
+ if (windows[i]->devices[j]->id == devid)
+ {
+ /* already in use */
+ fprintf(stderr,
+ "%s: Can't establish exclusive use of device %ld\n",
+ program_name,devid);
+ return GXID_RETURN_ERROR;
+ }
+ }
+ if (device->ispointer)
+ if (!switch_core_pointer())
+ {
+ fprintf(stderr,
+ "%s: Can't free up core pointer %ld\n",
+ program_name,devid);
+ return GXID_RETURN_ERROR;
+ }
+
+ device->exclusive = 1;
+ disable_device(device);
+ XSelectInput(dpy,winid,StructureNotifyMask);
+ }
+ else /* !exclusive */
+ {
+ /* FIXME: this is a bit improper. We probably should do this only
+ when a window is first claimed. But we might be fooled if
+ an old client died without releasing it's windows. So until
+ we look for client-window closings, do it here
+
+ (We do look for closings now...)
+ */
+
+ XSelectInput(dpy,winid,EnterWindowMask|StructureNotifyMask);
+ }
+
+ for (i=0;i<num_windows;i++)
+ {
+ if (windows[i]->xwindow == winid)
+ {
+ window = windows[i];
+ break;
+ }
+ }
+
+ /* Create window structure if no devices have been previously
+ claimed on it */
+ if (!window)
+ {
+ num_windows++;
+ windows = (GxidWindow **)realloc(windows,
+ sizeof(GxidWindow*)*num_windows);
+ window = (GxidWindow *)malloc(sizeof(GxidWindow));
+ windows[num_windows-1] = window;
+
+ window->xwindow = winid;
+ window->root_child = gxi_find_root_child(dpy,winid);
+ window->num_devices = 0;
+ window->devices = 0;
+ }
+
+
+ for (i=0;i<window->num_devices;i++)
+ {
+ if (window->devices[i] == device)
+ return GXID_RETURN_OK;
+ }
+
+ window->num_devices++;
+ window->devices = (GxidDevice **)realloc(window->devices,
+ sizeof(GxidDevice*)*num_devices);
+ /* we need add the device to the window */
+ window->devices[i] = device;
+
+ return GXID_RETURN_OK;
+}
+
+int
+handle_release_device(GxidReleaseDevice *msg)
+{
+ int i,j;
+ XID devid = ntohl(msg->device);
+ XID winid = ntohl(msg->window);
+
+ GxidDevice *device = NULL;
+
+#ifdef DEBUG_CLIENTS
+ fprintf(stderr,"device %ld released (window 0x%lx)\n",devid,winid);
+#endif
+
+ for (i=0;i<num_devices;i++)
+ {
+ if (devices[i]->id == devid)
+ {
+ device = devices[i];
+ break;
+ }
+ }
+ if (!device)
+ {
+ fprintf(stderr,"%s: Unknown device id %ld\n",program_name,devid);
+ return GXID_RETURN_ERROR;
+ }
+
+ for (i=0;i<num_windows;i++)
+ {
+ GxidWindow *w = windows[i];
+
+ if (w->xwindow == winid)
+ for (j=0;j<w->num_devices;j++)
+ if (w->devices[j]->id == devid)
+ {
+ if (j<w->num_devices-1)
+ w->devices[j] = w->devices[w->num_devices-1];
+ w->num_devices--;
+
+ if (w->num_devices == 0)
+ {
+ if (i<num_windows-1)
+ windows[i] = windows[num_windows-1];
+ num_windows--;
+
+ free((void *)w);
+ /* FIXME: should we deselect input? But what
+ what if window is already destroyed */
+ }
+
+ if (device->exclusive)
+ {
+ device->exclusive = 0;
+ enable_device(device);
+ }
+ return GXID_RETURN_OK;
+ }
+ }
+
+ /* device/window combination not found */
+ fprintf(stderr,
+ "%s: Device %ld not claimed for window 0x%lx\n",
+ program_name,devid,winid);
+ return GXID_RETURN_ERROR;
+}
+
+void
+handle_connection()
+{
+ GxidMessage msg;
+ GxidU32 type;
+ int length;
+ GxidI32 retval;
+
+ int conn_fd;
+ struct sockaddr_in sin;
+ int sin_length;
+ int count;
+
+ sin_length = sizeof(struct sockaddr_in);
+ conn_fd = accept(socket_fd,(struct sockaddr *)&sin,&sin_length);
+ if (conn_fd < 0)
+ {
+ fprintf(stderr,"%s: Error accepting connection\n",
+ program_name);
+ exit(1);
+ }
+
+ /* read type and length of message */
+
+ count = read(conn_fd,(char *)&msg,2*sizeof(GxidU32));
+ if (count != 2*sizeof(GxidU32))
+ {
+ fprintf(stderr,"%s: Error reading message header\n",
+ program_name);
+ close(conn_fd);
+ return;
+ }
+ type = ntohl(msg.any.type);
+ length = ntohl(msg.any.length);
+
+ /* read rest of message */
+
+ if (length > sizeof(GxidMessage))
+ {
+ fprintf(stderr,"%s: Bad message length\n",
+ program_name);
+ close(conn_fd);
+ return;
+ }
+
+ count = read(conn_fd,2*sizeof(GxidU32) + (char *)&msg,
+ length - 2*sizeof(GxidU32));
+ if (count != length - 2*sizeof(GxidU32))
+ {
+ fprintf(stderr,"%s: Error reading message body\n",
+ program_name);
+ close(conn_fd);
+ return;
+ }
+
+ switch (type)
+ {
+ case GXID_CLAIM_DEVICE:
+ retval = handle_claim_device((GxidClaimDevice *)&msg);
+ break;
+ case GXID_RELEASE_DEVICE:
+ retval = handle_release_device((GxidReleaseDevice *)&msg);
+ break;
+ default:
+ fprintf(stderr,"%s: Unknown message type: %ld (ignoring)\n",
+ program_name,type);
+ close(conn_fd);
+ return;
+ }
+
+ count = write(conn_fd,&retval,sizeof(GxidI32));
+ if (count != sizeof(GxidI32))
+ {
+ fprintf(stderr,"%s: Error writing return code\n",
+ program_name);
+ }
+
+ close(conn_fd);
+}
+
+void
+handle_motion_notify(XDeviceMotionEvent *event)
+{
+ int i,j;
+ GxidDevice *old_device = NULL;
+ GxidDevice *new_device = NULL;
+ Window w, root, child;
+ int root_x, root_y, x, y, mask;
+
+ for (j=0;j<num_devices;j++)
+ {
+ if (devices[j]->ispointer)
+ old_device = devices[j];
+ if (devices[j]->id == event->deviceid)
+ new_device = devices[j];
+ }
+
+ if (new_device && !new_device->exclusive && !new_device->ispointer)
+ {
+ /* make sure we aren't stealing the pointer back from a slow
+ client */
+ child = root_window;
+ do
+ {
+ w = child;
+ /* FIXME: this fails disasterously if child vanishes between
+ calls. (Which is prone to happening since we get events
+ on root just as the client exits) */
+
+ XQueryPointer(dpy,w,&root,&child,&root_x,&root_y,
+ &x,&y,&mask);
+ }
+ while (child != None);
+
+ for (i=0;i<num_windows;i++)
+ if (windows[i]->xwindow == w)
+ for (j=0;j<windows[i]->num_devices;j++)
+ if (windows[i]->devices[j] == new_device)
+ return;
+
+ /* FIXME: do something smarter with axes */
+ XChangePointerDevice(dpy,new_device->xdevice, 0, 1);
+ new_device->ispointer = 1;
+
+ old_device->ispointer = 0;
+ if (!old_device->xdevice)
+ enable_device(old_device);
+ }
+}
+
+void
+handle_change_notify(XChangeDeviceNotifyEvent *event)
+{
+ int j;
+ GxidDevice *old_device = NULL;
+ GxidDevice *new_device = NULL;
+
+
+ for (j=0;j<num_devices;j++)
+ {
+ if (devices[j]->ispointer)
+ old_device = devices[j];
+ if (devices[j]->id == event->deviceid)
+ new_device = devices[j];
+ }
+
+#ifdef DEBUG_EVENTS
+ fprintf(stderr,"gxid: ChangeNotify event; old = %ld; new = %ld\n",
+ old_device->id, new_device->id);
+#endif
+
+ if (old_device != new_device)
+ {
+ new_device->ispointer = 1;
+
+ old_device->ispointer = 0;
+ if (!old_device->xdevice)
+ enable_device(old_device);
+ }
+}
+
+void
+handle_enter_notify(XEnterWindowEvent *event, GxidWindow *window)
+{
+ int i;
+ GxidDevice *old_pointer = NULL;
+ for (i=0;i<num_devices;i++)
+ {
+ if (devices[i]->ispointer)
+ {
+ old_pointer = devices[i];
+ break;
+ }
+ }
+
+#ifdef DEBUG_EVENTS
+ fprintf(stderr,"gxid: Enter event; oldpointer = %ld\n",
+ old_pointer->id);
+#endif
+
+ if (old_pointer)
+ for (i=0;i<window->num_devices;i++)
+ {
+ if (window->devices[i] == old_pointer)
+ {
+ switch_core_pointer();
+ break;
+ }
+ }
+}
+
+void
+handle_destroy_notify(XDestroyWindowEvent *event)
+{
+ int i,j;
+
+ for (i=0;i<num_windows;i++)
+ if (windows[i]->xwindow == event->window)
+ {
+ GxidWindow *w = windows[i];
+
+ for (j=0;j<w->num_devices;j++)
+ {
+#ifdef DEBUG_CLIENTS
+ fprintf(stderr,"device %ld released on destruction of window 0x%lx.\n",
+ w->devices[j]->id,w->xwindow);
+#endif
+
+ if (w->devices[j]->exclusive)
+ {
+ w->devices[j]->exclusive = 0;
+ enable_device(devices[j]);
+ }
+ }
+
+ if (i<num_windows-1)
+ windows[i] = windows[num_windows-1];
+ num_windows--;
+
+ if (w->devices)
+ free((void *)w->devices);
+ free((void *)w);
+ /* FIXME: should we deselect input? But what
+ what if window is already destroyed */
+
+ return;
+ }
+}
+
+void
+handle_xevent()
+{
+ int i;
+ XEvent event;
+
+ XNextEvent (dpy, &event);
+
+#ifdef DEBUG_EVENTS
+ fprintf(stderr,"Event - type = %d; window = 0x%lx\n",
+ event.type,event.xany.window);
+#endif
+
+ if (event.type == ConfigureNotify)
+ {
+#ifdef DEBUG_EVENTS
+ XConfigureEvent *xce = (XConfigureEvent *)&event;
+ fprintf(stderr," configureNotify: window = 0x%lx\n",xce->window);
+#endif
+ }
+ else if (event.type == EnterNotify)
+ {
+ /* pointer entered a claimed window */
+ for (i=0;i<num_windows;i++)
+ {
+ if (event.xany.window == windows[i]->xwindow)
+ handle_enter_notify((XEnterWindowEvent *)&event,windows[i]);
+ }
+ }
+ else if (event.type == DestroyNotify)
+ {
+ /* A claimed window was destroyed */
+ for (i=0;i<num_windows;i++)
+ {
+ if (event.xany.window == windows[i]->xwindow)
+ handle_destroy_notify((XDestroyWindowEvent *)&event);
+ }
+ }
+ else
+ for (i=0;i<num_devices;i++)
+ {
+ if (event.type == devices[i]->motionnotify_type)
+ {
+ handle_motion_notify((XDeviceMotionEvent *)&event);
+ break;
+ }
+ else if (event.type == devices[i]->changenotify_type)
+ {
+ handle_change_notify((XChangeDeviceNotifyEvent *)&event);
+ break;
+ }
+ }
+}
+
+void
+usage()
+{
+ fprintf(stderr,"Usage: %s [-d display] [-p --gxid-port port]\n",
+ program_name);
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ int i;
+ char *display_name = NULL;
+ fd_set readfds;
+
+ program_name = argv[0];
+
+ for (i=1;i<argc;i++)
+ {
+ if (!strcmp(argv[i],"-d"))
+ {
+ if (++i >= argc) usage();
+ display_name = argv[i];
+ }
+ else if (!strcmp(argv[i],"--gxid-port") ||
+ !strcmp(argv[i],"-p"))
+ {
+ if (++i >= argc) usage();
+ port = atoi(argv[i]);
+ break;
+ }
+ else
+ usage();
+ }
+
+ if (!port)
+ {
+ char *t = getenv("GXID_PORT");
+ if (t)
+ port = atoi(t);
+ else
+ port = 6951;
+ }
+ /* set up a signal handler so we can clean up if killed */
+
+ signal(SIGTERM,handler);
+ signal(SIGINT,handler);
+
+ /* initialize the X connection */
+
+ dpy = XOpenDisplay (display_name);
+ if (!dpy)
+ {
+ fprintf (stderr, "%s: unable to open display '%s'\n",
+ program_name, XDisplayName (display_name));
+ exit (1);
+ }
+
+ root_window = DefaultRootWindow(dpy);
+
+ /* We'll want to do this in the future if we are to support
+ gxid monitoring visibility information for clients */
+#if 0
+ XSelectInput(dpy,root_window,SubstructureNotifyMask);
+#endif
+ init_xinput();
+
+ /* set up our server connection */
+
+ init_socket();
+
+ /* main loop */
+
+ if (XPending(dpy)) /* this seems necessary to get things
+ in sync */
+ handle_xevent();
+ while (1)
+ {
+
+ FD_ZERO(&readfds);
+ FD_SET(ConnectionNumber(dpy),&readfds);
+ FD_SET(socket_fd,&readfds);
+
+ if (select(8*sizeof(readfds),&readfds,
+ (fd_set *)0,(fd_set *)0, (struct timeval *)0) < 0)
+ {
+ fprintf(stderr,"Error in select\n");
+ exit(1);
+ }
+
+ if (FD_ISSET(socket_fd,&readfds))
+ handle_connection(socket_fd);
+
+ while (XPending(dpy))
+ handle_xevent();
+ }
+
+ XCloseDisplay (dpy);
+ exit (0);
+}
diff --git a/gdk/x11/gxid_lib.c b/gdk/x11/gxid_lib.c
new file mode 100644
index 000000000..357b76451
--- /dev/null
+++ b/gdk/x11/gxid_lib.c
@@ -0,0 +1,116 @@
+/*
+ * gxid version 0.3
+ *
+ * Copyright 1997 Owen Taylor <owt1@cornell.edu>
+*/
+
+#include "../config.h"
+
+#ifdef XINPUT_GXI
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include "gxid_lib.h"
+
+/* handles mechanics of communicating with a client */
+static int
+gxid_send_message(char *host, int port, GxidMessage *msg)
+{
+ int socket_fd;
+ struct sockaddr_in sin;
+ int count;
+ GxidI32 retval;
+ struct hostent *he;
+
+ if (!port) port = 6951;
+
+ if (!host || strcmp(host,"localhost") )
+ {
+ /* looking it up as localhost can be _SLOW_ on ppp systems */
+ /* FIXME: Could localhost be anything other than loopback? */
+ host = "127.0.0.1";
+ }
+
+ he = gethostbyname(host);
+ if (!he)
+ {
+ fprintf(stderr,"gxid_lib: error looking up %s\n",host);
+ return GXID_RETURN_ERROR;
+ }
+
+ sin.sin_family = he->h_addrtype;
+ sin.sin_port = htons(port);
+ memcpy(&sin.sin_addr,he->h_addr_list[0],he->h_length);
+
+ socket_fd = socket(AF_INET,SOCK_STREAM,0);
+ if (socket_fd < 0)
+ {
+ fprintf(stderr,"gxid_lib: can't get socket");
+ return GXID_RETURN_ERROR;
+ }
+
+ if (connect(socket_fd, (struct sockaddr *)&sin,
+ sizeof sin) < 0)
+ {
+ fprintf(stderr,"gxid_lib: can't connect to %s:%d\n",host,port);
+ close(socket_fd);
+ return GXID_RETURN_ERROR;
+ }
+
+ count = write(socket_fd,(char *)msg,ntohl(msg->any.length));
+ if (count != ntohl(msg->any.length))
+ {
+ fprintf(stderr,"gxid_lib: error writing");
+ close(socket_fd);
+ return GXID_RETURN_ERROR;
+ }
+
+ /* now read the return code */
+ count = read(socket_fd,(char *)&retval,sizeof(GxidI32));
+ if (count != sizeof(GxidI32))
+ {
+ fprintf(stderr,"gxid_lib: error reading return code");
+ close(socket_fd);
+ return GXID_RETURN_ERROR;
+ }
+
+ close (socket_fd);
+ return ntohl(retval);
+}
+
+/* claim a device. If exclusive, device is claimed exclusively */
+int
+gxid_claim_device(char *host, int port, GxidU32 device, GxidU32 window,
+ int exclusive)
+{
+ GxidClaimDevice msg;
+ msg.type = htonl(GXID_CLAIM_DEVICE);
+ msg.length = htonl(sizeof(GxidClaimDevice));
+ msg.device = htonl(device);
+ msg.window = htonl(window);
+ msg.exclusive = htonl(exclusive);
+
+ return gxid_send_message(host,port,(GxidMessage *)&msg);
+}
+
+/* release a device/window pair */
+int
+gxid_release_device(char *host, int port, GxidU32 device, GxidU32 window)
+{
+ GxidReleaseDevice msg;
+ msg.type = htonl(GXID_RELEASE_DEVICE);
+ msg.length = htonl(sizeof(GxidReleaseDevice));
+ msg.device = htonl(device);
+ msg.window = htonl(window);
+
+ return gxid_send_message(host,port,(GxidMessage *)&msg);
+}
+
+#endif /* XINPUT_GXI */
+
diff --git a/gdk/x11/gxid_lib.h b/gdk/x11/gxid_lib.h
new file mode 100644
index 000000000..6a7103bbe
--- /dev/null
+++ b/gdk/x11/gxid_lib.h
@@ -0,0 +1,6 @@
+#include "gxid_proto.h"
+
+int gxid_claim_device(char *host, int port,
+ GxidU32 device, GxidU32 window, int exclusive);
+int gxid_release_device(char *host, int port, GxidU32 device,
+ GxidU32 window);
diff --git a/gdk/x11/gxid_proto.h b/gdk/x11/gxid_proto.h
new file mode 100644
index 000000000..24959b806
--- /dev/null
+++ b/gdk/x11/gxid_proto.h
@@ -0,0 +1,39 @@
+#define GXID_CLAIM_DEVICE 1
+#define GXID_RELEASE_DEVICE 2
+
+#define GXID_RETURN_OK 0
+#define GXID_RETURN_ERROR -1
+
+typedef struct GxidClaimDevice_ GxidClaimDevice;
+typedef struct GxidReleaseDevice_ GxidReleaseDevice;
+typedef struct GxidMessageAny_ GxidMessageAny;
+typedef union GxidMessage_ GxidMessage;
+
+typedef unsigned long GxidU32;
+typedef long GxidI32;
+
+struct GxidClaimDevice_ {
+ GxidU32 type;
+ GxidU32 length;
+ GxidU32 device;
+ GxidU32 window;
+ GxidU32 exclusive;
+};
+
+struct GxidReleaseDevice_ {
+ GxidU32 type;
+ GxidU32 length;
+ GxidU32 device;
+ GxidU32 window;
+};
+
+struct GxidMessageAny_ {
+ GxidU32 type;
+ GxidU32 length;
+};
+
+union GxidMessage_ {
+ GxidMessageAny any;
+ GxidClaimDevice claim;
+ GxidReleaseDevice release;
+};
diff --git a/glib/.cvsignore b/glib/.cvsignore
new file mode 100644
index 000000000..e0d0bd21d
--- /dev/null
+++ b/glib/.cvsignore
@@ -0,0 +1,11 @@
+*.lo
+config.log
+libtool
+config.status
+stamp-h
+Makefile
+.deps
+_libs
+libglib.la
+testglib
+glibconfig.h
diff --git a/glib/AUTHORS b/glib/AUTHORS
new file mode 100644
index 000000000..67f4e5617
--- /dev/null
+++ b/glib/AUTHORS
@@ -0,0 +1 @@
+Peter Mattis (petm@xcf.berkeley.edu)
diff --git a/glib/COPYING b/glib/COPYING
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/glib/COPYING
diff --git a/glib/ChangeLog b/glib/ChangeLog
new file mode 100644
index 000000000..b119426ca
--- /dev/null
+++ b/glib/ChangeLog
@@ -0,0 +1,10 @@
+Tue Dec 17 13:14:07 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * glib.h: Changed 'g_return_if_fail' and 'g_return_val_if_fail' to
+ not call 'g_string' but to simply stringify the
+ expression. Calling 'g_string' causes the expression to be
+ expanded which is undesired.
+
+Sun Dec 1 01:30:48 1996 Peter Mattis <pmattis@charnley.HIP.Berkeley.EDU>
+
+ * Started ChangeLog
diff --git a/glib/INSTALL b/glib/INSTALL
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/glib/INSTALL
diff --git a/glib/Makefile.am b/glib/Makefile.am
new file mode 100644
index 000000000..18afb93a5
--- /dev/null
+++ b/glib/Makefile.am
@@ -0,0 +1,38 @@
+## Process this file with automake to produce Makefile.in
+
+lib_LTLIBRARIES = libglib.la
+
+libglib_la_SOURCES = \
+ garray.c \
+ gcache.c \
+ gerror.c \
+ ghash.c \
+ glist.c \
+ gmem.c \
+ gprimes.c \
+ gslist.c \
+ gtimer.c \
+ gtree.c \
+ gutils.c \
+ gstring.c
+
+include_HEADERS = \
+ glib.h \
+ glibconfig.h
+
+libglib_la_LDFLAGS = -version-info 1:0:0
+
+INCLUDES =
+
+noinst_PROGRAMS = testglib
+testglib_LDADD = $(top_builddir)/libglib.la
+
+.PHONY: files release
+
+files:
+ @files=`ls $(DISTFILES) 2> /dev/null `; for p in $$files; do \
+ echo $$p; \
+ done
+
+release:
+ $(MAKE) dist distdir=$(PACKAGE)`date +"%y%m%d"`
diff --git a/glib/NEWS b/glib/NEWS
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/glib/NEWS
diff --git a/glib/README b/glib/README
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/glib/README
diff --git a/glib/acconfig.h b/glib/acconfig.h
new file mode 100644
index 000000000..48ca75f8d
--- /dev/null
+++ b/glib/acconfig.h
@@ -0,0 +1,62 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* acconfig.h
+ This file is in the public domain.
+
+ Descriptive text for the C preprocessor macros that
+ the distributed Autoconf macros can define.
+ No software package will use all of them; autoheader copies the ones
+ your configure.in uses into your configuration header file templates.
+
+ The entries are in sort -df order: alphabetical, case insensitive,
+ ignoring punctuation (such as underscores). Although this order
+ can split up related entries, it makes it easier to check whether
+ a given entry is in the file.
+
+ Leave the following blank line there!! Autoheader needs it. */
+
+
+/* Other stuff */
+#undef HAVE_DOPRNT
+#undef HAVE_FLOAT_H
+#undef HAVE_LIMITS_H
+#undef HAVE_LONG_DOUBLE
+#undef HAVE_SYS_SELECT_H
+#undef HAVE_STRERROR
+#undef HAVE_STRSIGNAL
+#undef HAVE_VALUES_H
+#undef HAVE_VPRINTF
+
+#undef NO_FD_SET
+#undef NO_SYS_ERRLIST
+#undef NO_SYS_SIGLIST
+
+#undef SIZEOF_CHAR
+#undef SIZEOF_SHORT
+#undef SIZEOF_LONG
+#undef SIZEOF_INT
+#undef SIZEOF_VOID_P
+
+/* #undef PACKAGE */
+/* #undef VERSION */
+
+
+/* Leave that blank line there!! Autoheader needs it.
+ If you're adding to this file, keep in mind:
+ The entries are in sort -df order: alphabetical, case insensitive,
+ ignoring punctuation (such as underscores). */
diff --git a/glib/aclocal.m4 b/glib/aclocal.m4
new file mode 100644
index 000000000..9f99ab8e7
--- /dev/null
+++ b/glib/aclocal.m4
@@ -0,0 +1,395 @@
+dnl aclocal.m4 generated automatically by aclocal 1.2
+
+# Do all the work for Automake. This macro actually does too much --
+# some checks are only needed if your package does certain things.
+# But this isn't really a big deal.
+
+# serial 1
+
+dnl Usage:
+dnl AM_INIT_AUTOMAKE(package,version, [no-define])
+
+AC_DEFUN(AM_INIT_AUTOMAKE,
+[AC_REQUIRE([AM_PROG_INSTALL])
+PACKAGE=[$1]
+AC_SUBST(PACKAGE)
+VERSION=[$2]
+AC_SUBST(VERSION)
+dnl test to see if srcdir already configured
+if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
+ AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+fi
+ifelse([$3],,
+AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE")
+AC_DEFINE_UNQUOTED(VERSION, "$VERSION"))
+AM_SANITY_CHECK
+AC_ARG_PROGRAM
+dnl FIXME This is truly gross.
+missing_dir=`cd $ac_aux_dir && pwd`
+AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir)
+AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir)
+AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir)
+AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir)
+AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
+AC_PROG_MAKE_SET])
+
+
+# serial 1
+
+AC_DEFUN(AM_PROG_INSTALL,
+[AC_REQUIRE([AC_PROG_INSTALL])
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
+AC_SUBST(INSTALL_SCRIPT)dnl
+])
+
+#
+# Check to make sure that the build environment is sane.
+#
+
+AC_DEFUN(AM_SANITY_CHECK,
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftestfile
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
+ if test "$@" = "X"; then
+ # -L didn't work.
+ set X `ls -t $srcdir/configure conftestfile`
+ fi
+ test "[$]2" = conftestfile
+ )
+then
+ # Ok.
+ :
+else
+ AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+rm -f conftest*
+AC_MSG_RESULT(yes)])
+
+dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY)
+dnl The program must properly implement --version.
+AC_DEFUN(AM_MISSING_PROG,
+[AC_MSG_CHECKING(for working $2)
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf. Sigh.
+if ($2 --version) < /dev/null > /dev/null 2>&1; then
+ $1=$2
+ AC_MSG_RESULT(found)
+else
+ $1="$3/missing $2"
+ AC_MSG_RESULT(missing)
+fi
+AC_SUBST($1)])
+
+# Like AC_CONFIG_HEADER, but automatically create stamp file.
+
+AC_DEFUN(AM_CONFIG_HEADER,
+[AC_PREREQ([2.12])
+AC_CONFIG_HEADER([$1])
+dnl When config.status generates a header, we must update the stamp-h file.
+dnl This file resides in the same directory as the config header
+dnl that is generated. We must strip everything past the first ":",
+dnl and everything past the last "/".
+AC_OUTPUT_COMMANDS(changequote(<<,>>)dnl
+ifelse(patsubst(<<$1>>, <<[^ ]>>, <<>>), <<>>,
+<<test -z "<<$>>CONFIG_HEADERS" || echo timestamp > patsubst(<<$1>>, <<^\([^:]*/\)?.*>>, <<\1>>)stamp-h<<>>dnl>>,
+<<am_indx=1
+for am_file in <<$1>>; do
+ case " <<$>>CONFIG_HEADERS " in
+ *" <<$>>am_file "*<<)>>
+ echo timestamp > `echo <<$>>am_file | sed -e 's%:.*%%' -e 's%[^/]*$%%'`stamp-h$am_indx
+ ;;
+ esac
+ am_indx=`expr "<<$>>am_indx" + 1`
+done<<>>dnl>>)
+changequote([,]))])
+
+
+# serial 17 AM_PROG_LIBTOOL
+AC_DEFUN(AM_PROG_LIBTOOL,
+[AC_REQUIRE([AC_CANONICAL_HOST])
+AC_REQUIRE([AC_PROG_RANLIB])
+AC_REQUIRE([AC_PROG_CC])
+AC_REQUIRE([AM_PROG_LD])
+AC_REQUIRE([AM_PROG_NM])
+AC_REQUIRE([AC_PROG_LN_S])
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+AC_SUBST(LIBTOOL)
+
+dnl Allow the --disable-shared flag to stop us from building shared libs.
+AC_ARG_ENABLE(shared,
+[ --enable-shared build shared libraries [default=yes]],
+[if test "$enableval" = no; then
+ libtool_enable_shared=no
+else
+ libtool_enable_shared=yes
+fi])
+test -n "$libtool_enable_shared" && enable_shared="$libtool_enable_shared"
+libtool_shared=
+test "$enable_shared" = no && libtool_shared=" --disable-shared"
+
+dnl Allow the --disable-static flag to stop us from building static libs.
+AC_ARG_ENABLE(static,
+[ --enable-static build static libraries [default=yes]],
+[if test "$enableval" = no; then
+ libtool_enable_static=no
+else
+ libtool_enable_static=yes
+fi])
+test -n "$libtool_enable_static" && enable_static="$libtool_enable_static"
+libtool_static=
+test "$enable_static" = no && libtool_static=" --disable-static"
+
+libtool_flags="$libtool_shared$libtool_static"
+test "$silent" = yes && libtool_flags="$libtool_flags --silent"
+test "$ac_cv_prog_gcc" = yes && libtool_flags="$libtool_flags --with-gcc"
+test "$ac_cv_prog_gnu_ld" = yes && libtool_flags="$libtool_flags --with-gnu-ld"
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+[case "$host" in
+*-*-irix6*)
+ ac_save_CFLAGS="$CFLAGS"
+ flag_passed=no
+ for f in -32 -64 -n32 ABI -cckr -mips1 -mips2 -mips3 -mips4; do
+ case "$f" in
+ ABI)
+ test -n "$SGI_ABI" && flag_passed=yes
+ if test "$flag_passed" = no && test "$ac_cv_prog_gcc" = yes; then
+ # Choose the ABI flag according to GCC's specs.
+ if $CC -dumpspecs 2>&1 | sed '/^\*link:$/,/^$/!d' | egrep -e '[ ]-32' >/dev/null; then
+ LD="${LD-ld} -32"
+ else
+ LD="${LD-ld} -n32"
+ fi
+ fi
+ ;;
+
+ *)
+ if echo " $CC $CFLAGS " | egrep -e "[ ]$f[ ]" > /dev/null; then
+ flag_passed=yes
+ LD="${LD-ld} $f"
+ fi
+ ;;
+ esac
+ done
+ CFLAGS="$ac_save_CFLAGS"
+ ;;
+
+*-*-sco3.2v5*)
+ # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+ CFLAGS="$CFLAGS -belf"
+ ;;
+esac]
+
+# Actually configure libtool. ac_aux_dir is where install-sh is found.
+CC="$CC" CFLAGS="$CFLAGS" CPPFLAGS="$CPPFLAGS" \
+LD="$LD" NM="$NM" RANLIB="$RANLIB" LN_S="$LN_S" \
+${CONFIG_SHELL-/bin/sh} $ac_aux_dir/ltconfig \
+$libtool_flags --no-verify $ac_aux_dir/ltmain.sh $host \
+|| AC_MSG_ERROR([libtool configure failed])
+])
+
+# AM_PROG_LD - find the path to the GNU or non-GNU linker
+AC_DEFUN(AM_PROG_LD,
+[AC_ARG_WITH(gnu-ld,
+[ --with-gnu-ld assume the C compiler uses GNU ld [default=no]],
+test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no)
+AC_REQUIRE([AC_PROG_CC])
+ac_prog=ld
+if test "$ac_cv_prog_gcc" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ AC_MSG_CHECKING([for ld used by GCC])
+ ac_prog=`($CC -print-prog-name=ld) 2>&5`
+ case "$ac_prog" in
+ # Accept absolute paths.
+ /*)
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ AC_MSG_CHECKING([for GNU ld])
+else
+ AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(ac_cv_path_LD,
+[if test -z "$LD"; then
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog"; then
+ ac_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some GNU ld's only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ if "$ac_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
+ test "$with_gnu_ld" != no && break
+ else
+ test "$with_gnu_ld" != yes && break
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+else
+ ac_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$ac_cv_path_LD"
+if test -n "$LD"; then
+ AC_MSG_RESULT($LD)
+else
+ AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+AC_SUBST(LD)
+AM_PROG_LD_GNU
+])
+
+AC_DEFUN(AM_PROG_LD_GNU,
+[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], ac_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU ld's only accept -v.
+if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+ ac_cv_prog_gnu_ld=yes
+else
+ ac_cv_prog_gnu_ld=no
+fi])
+])
+
+# AM_PROG_NM - find the path to a BSD-compatible name lister
+AC_DEFUN(AM_PROG_NM,
+[AC_MSG_CHECKING([for BSD-compatible nm])
+AC_CACHE_VAL(ac_cv_path_NM,
+[case "$NM" in
+/*)
+ ac_cv_path_NM="$NM" # Let the user override the test with a path.
+ ;;
+*)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in /usr/ucb $PATH /bin; do
+ test -z "$ac_dir" && dir=.
+ if test -f $ac_dir/nm; then
+ # Check to see if the nm accepts a BSD-compat flag.
+ if ($ac_dir/nm -B /dev/null 2>&1; exit 0) | grep /dev/null >/dev/null; then
+ ac_cv_path_NM="$ac_dir/nm -B"
+ elif ($ac_dir/nm -p /dev/null 2>&1; exit 0) | grep /dev/null >/dev/null; then
+ ac_cv_path_NM="$ac_dir/nm -p"
+ else
+ ac_cv_path_NM="$ac_dir/nm"
+ fi
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_NM" && ac_cv_path_NM=nm
+ ;;
+esac])
+NM="$ac_cv_path_NM"
+AC_MSG_RESULT([$NM])
+AC_SUBST(NM)
+])
+
+# Add --enable-maintainer-mode option to configure.
+# From Jim Meyering
+
+# serial 1
+
+AC_DEFUN(AM_MAINTAINER_MODE,
+[AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
+ dnl maintainer-mode is disabled by default
+ AC_ARG_ENABLE(maintainer-mode,
+[ --enable-maintainer-mode enable make rules and dependencies not useful
+ (and sometimes confusing) to the casual installer],
+ USE_MAINTAINER_MODE=$enableval,
+ USE_MAINTAINER_MODE=no)
+ AC_MSG_RESULT($USE_MAINTAINER_MODE)
+ if test $USE_MAINTAINER_MODE = yes; then
+ MAINT=
+ else
+ MAINT='#M#'
+ fi
+ AC_SUBST(MAINT)dnl
+]
+)
+
+
+# serial 1
+
+# @defmac AC_PROG_CC_STDC
+# @maindex PROG_CC_STDC
+# @ovindex CC
+# If the C compiler in not in ANSI C mode by default, try to add an option
+# to output variable @code{CC} to make it so. This macro tries various
+# options that select ANSI C on some system or another. It considers the
+# compiler to be in ANSI C mode if it defines @code{__STDC__} to 1 and
+# handles function prototypes correctly.
+#
+# If you use this macro, you should check after calling it whether the C
+# compiler has been set to accept ANSI C; if not, the shell variable
+# @code{am_cv_prog_cc_stdc} is set to @samp{no}. If you wrote your source
+# code in ANSI C, you can make an un-ANSIfied copy of it by using the
+# program @code{ansi2knr}, which comes with Ghostscript.
+# @end defmac
+
+AC_DEFUN(AM_PROG_CC_STDC,
+[AC_REQUIRE([AC_PROG_CC])
+AC_BEFORE([$0], [AC_C_INLINE])
+AC_BEFORE([$0], [AC_C_CONST])
+AC_MSG_CHECKING(for ${CC-cc} option to accept ANSI C)
+AC_CACHE_VAL(am_cv_prog_cc_stdc,
+[am_cv_prog_cc_stdc=no
+ac_save_CC="$CC"
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX -qlanglvl=ansi
+# Ultrix and OSF/1 -std1
+# HP-UX -Aa -D_HPUX_SOURCE
+# SVR4 -Xc -D__EXTENSIONS__
+for ac_arg in "" -qlanglvl=ansi -std1 "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ AC_TRY_COMPILE(
+[#if !defined(__STDC__) || __STDC__ != 1
+choke me
+#endif
+/* DYNIX/ptx V4.1.3 can't compile sys/stat.h with -Xc -D__EXTENSIONS__. */
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/stat.h>
+#endif
+], [
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};],
+[am_cv_prog_cc_stdc="$ac_arg"; break])
+done
+CC="$ac_save_CC"
+])
+if test -z "$am_cv_prog_cc_stdc"; then
+ AC_MSG_RESULT([none needed])
+else
+ AC_MSG_RESULT($am_cv_prog_cc_stdc)
+fi
+case "x$am_cv_prog_cc_stdc" in
+ x|xno) ;;
+ *) CC="$CC $am_cv_prog_cc_stdc" ;;
+esac
+])
+
diff --git a/glib/config.guess b/glib/config.guess
new file mode 100755
index 000000000..413ed41c0
--- /dev/null
+++ b/glib/config.guess
@@ -0,0 +1,883 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Written by Per Bothner <bothner@cygnus.com>.
+# The master version of this file is at the FSF in /home/gd/gnu/lib.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit system type (host/target name).
+#
+# Only a few systems have been added to this list; please add others
+# (but try to keep the structure clean).
+#
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 8/24/94.)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+trap 'rm -f dummy.c dummy.o dummy; exit 1' 1 2 15
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ alpha:OSF1:*:*)
+ if test $UNAME_RELEASE = "V4.0"; then
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ fi
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ cat <<EOF >dummy.s
+ .globl main
+ .ent main
+main:
+ .frame \$30,0,\$26,0
+ .prologue 0
+ .long 0x47e03d80 # implver $0
+ lda \$2,259
+ .long 0x47e20c21 # amask $2,$1
+ srl \$1,8,\$2
+ sll \$2,2,\$2
+ sll \$0,3,\$0
+ addl \$1,\$0,\$0
+ addl \$2,\$0,\$0
+ ret \$31,(\$26),1
+ .end main
+EOF
+ ${CC-cc} dummy.s -o dummy 2>/dev/null
+ if test "$?" = 0 ; then
+ ./dummy
+ case "$?" in
+ 7)
+ UNAME_MACHINE="alpha"
+ ;;
+ 15)
+ UNAME_MACHINE="alphaev5"
+ ;;
+ 14)
+ UNAME_MACHINE="alphaev56"
+ ;;
+ 10)
+ UNAME_MACHINE="alphapca56"
+ ;;
+ 16)
+ UNAME_MACHINE="alphaev6"
+ ;;
+ esac
+ fi
+ rm -f dummy.s dummy
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr [[A-Z]] [[a-z]]`
+ exit 0 ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit 0 ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-cbm-sysv4
+ exit 0;;
+ amiga:NetBSD:*:*)
+ echo m68k-cbm-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ amiga:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ arc64:OpenBSD:*:*)
+ echo mips64el-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ arc:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ hkmips:OpenBSD:*:*)
+ echo mips-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ pmax:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sgi:OpenBSD:*:*)
+ echo mips-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ wgrisc:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit 0;;
+ arm32:NetBSD:*:*)
+ echo arm-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ exit 0 ;;
+ SR2?01:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit 0;;
+ Pyramid*:OSx*:*:*|MIS*:OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit 0 ;;
+ NILE:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit 0 ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ i86pc:SunOS:5.*:*)
+ echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit 0 ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit 0 ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ atari*:NetBSD:*:*)
+ echo m68k-atari-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ atari*:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sun3*:NetBSD:*:*)
+ echo m68k-sun-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sun3*:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mac68k:NetBSD:*:*)
+ echo m68k-apple-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mac68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme88k:OpenBSD:*:*)
+ echo m88k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit 0 ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit 0 ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ 2020:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit 0 ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ sed 's/^ //' << EOF >dummy.c
+ int main (argc, argv) int argc; char **argv; {
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ ${CC-cc} dummy.c -o dummy \
+ && ./dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+ && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit 0 ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit 0 ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit 0 ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit 0 ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 -o $UNAME_PROCESSOR = mc88110 ] ; then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \
+ -o ${TARGET_BINARY_INTERFACE}x = x ] ; then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit 0 ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit 0 ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit 0 ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit 0 ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i?86:AIX:*:*)
+ echo i386-ibm-aix
+ exit 0 ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ sed 's/^ //' << EOF >dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ echo rs6000-ibm-aix3.2.5
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit 0 ;;
+ *:AIX:*:4)
+ if /usr/sbin/lsattr -EHl proc0 | grep POWER >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=4.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit 0 ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit 0 ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit 0 ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC NetBSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit 0 ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit 0 ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit 0 ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit 0 ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit 0 ;;
+ 9000/[3478]??:HP-UX:*:*)
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/7?? | 9000/8?[1679] ) HP_ARCH=hppa1.1 ;;
+ 9000/8?? ) HP_ARCH=hppa1.0 ;;
+ esac
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ 3050*:HI-UX:*:*)
+ sed 's/^ //' << EOF >dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ echo unknown-hitachi-hiuxwe2
+ exit 0 ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit 0 ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit 0 ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit 0 ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit 0 ;;
+ i?86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit 0 ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit 0 ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ CRAY*X-MP:*:*:*)
+ echo xmp-cray-unicos
+ exit 0 ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE}
+ exit 0 ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
+ exit 0 ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE}
+ exit 0 ;;
+ CRAY-2:*:*:*)
+ echo cray2-cray-unicos
+ exit 0 ;;
+ F300:UNIX_System_V:*:*)
+ FUJITSU_SYS=`uname -p | tr [A-Z] [a-z] | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit 0 ;;
+ F301:UNIX_System_V:*:*)
+ echo f301-fujitsu-uxpv`echo $UNAME_RELEASE | sed 's/ .*//'`
+ exit 0 ;;
+ hp3[0-9][05]:NetBSD:*:*)
+ echo m68k-hp-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ hp300:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ i?86:BSD/386:*:* | *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:FreeBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit 0 ;;
+ *:NetBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ exit 0 ;;
+ *:OpenBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ exit 0 ;;
+ i*:CYGWIN*:*)
+ echo i386-pc-cygwin32
+ exit 0 ;;
+ i*:MINGW*:*)
+ echo i386-pc-mingw32
+ exit 0 ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin32
+ exit 0 ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ *:GNU:*:*)
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit 0 ;;
+ *:Linux:*:*)
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us.
+ ld_help_string=`ld --help 2>&1`
+ ld_supported_emulations=`echo $ld_help_string \
+ | sed -ne '/supported emulations:/!d
+ s/[ ][ ]*/ /g
+ s/.*supported emulations: *//
+ s/ .*//
+ p'`
+ case "$ld_supported_emulations" in
+ i?86linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" ; exit 0 ;;
+ i?86coff) echo "${UNAME_MACHINE}-pc-linux-gnucoff" ; exit 0 ;;
+ sparclinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
+ m68klinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
+ elf32ppc) echo "powerpc-unknown-linux-gnu" ; exit 0 ;;
+ esac
+
+ if test "${UNAME_MACHINE}" = "alpha" ; then
+ sed 's/^ //' <<EOF >dummy.s
+ .globl main
+ .ent main
+ main:
+ .frame \$30,0,\$26,0
+ .prologue 0
+ .long 0x47e03d80 # implver $0
+ lda \$2,259
+ .long 0x47e20c21 # amask $2,$1
+ srl \$1,8,\$2
+ sll \$2,2,\$2
+ sll \$0,3,\$0
+ addl \$1,\$0,\$0
+ addl \$2,\$0,\$0
+ ret \$31,(\$26),1
+ .end main
+EOF
+ LIBC=""
+ ${CC-cc} dummy.s -o dummy 2>/dev/null
+ if test "$?" = 0 ; then
+ ./dummy
+ case "$?" in
+ 7)
+ UNAME_MACHINE="alpha"
+ ;;
+ 15)
+ UNAME_MACHINE="alphaev5"
+ ;;
+ 14)
+ UNAME_MACHINE="alphaev56"
+ ;;
+ 10)
+ UNAME_MACHINE="alphapca56"
+ ;;
+ 16)
+ UNAME_MACHINE="alphaev6"
+ ;;
+ esac
+
+ objdump --private-headers dummy | \
+ grep ld.so.1 > /dev/null
+ if test "$?" = 0 ; then
+ LIBC="libc1"
+ fi
+ fi
+ rm -f dummy.s dummy
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} ; exit 0
+ elif test "${UNAME_MACHINE}" = "mips" ; then
+ cat >dummy.c <<EOF
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+#ifdef __MIPSEB__
+ printf ("%s-unknown-linux-gnu\n", argv[1]);
+#endif
+#ifdef __MIPSEL__
+ printf ("%sel-unknown-linux-gnu\n", argv[1]);
+#endif
+ return 0;
+}
+EOF
+ ${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ else
+ # Either a pre-BFD a.out linker (linux-gnuoldld)
+ # or one that does not give us useful --help.
+ # GCC wants to distinguish between linux-gnuoldld and linux-gnuaout.
+ # If ld does not provide *any* "supported emulations:"
+ # that means it is gnuoldld.
+ echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations:"
+ test $? != 0 && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0
+
+ case "${UNAME_MACHINE}" in
+ i?86)
+ VENDOR=pc;
+ ;;
+ *)
+ VENDOR=unknown;
+ ;;
+ esac
+ # Determine whether the default compiler is a.out or elf
+ cat >dummy.c <<EOF
+#include <features.h>
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+#ifdef __ELF__
+# ifdef __GLIBC__
+# if __GLIBC__ >= 2
+ printf ("%s-${VENDOR}-linux-gnu\n", argv[1]);
+# else
+ printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]);
+# endif
+# else
+ printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]);
+# endif
+#else
+ printf ("%s-${VENDOR}-linux-gnuaout\n", argv[1]);
+#endif
+ return 0;
+}
+EOF
+ ${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ fi ;;
+# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions
+# are messed up and put the nodename in both sysname and nodename.
+ i?86:DYNIX/ptx:4*:*)
+ echo i386-sequent-sysv4
+ exit 0 ;;
+ i?86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit 0 ;;
+ i?86:*:4.*:* | i?86:SYSTEM_V:4.*:*)
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ i?86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit 0 ;;
+ pc:*:*:*)
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i386.
+ echo i386-pc-msdosdjgpp
+ exit 0 ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit 0 ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit 0 ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit 0 ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit 0 ;;
+ M68*:*:R3V[567]*:*)
+ test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+ 3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4.3${OS_REL} && exit 0
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4 && exit 0 ;;
+ m68*:LynxOS:2.*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit 0 ;;
+ i?86:LynxOS:2.*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ rs6000:LynxOS:2.*:* | PowerPC:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit 0 ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit 0 ;;
+ PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit 0 ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit 0 ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit 0 ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit 0 ;;
+ news*:NEWS-OS:*:6*)
+ echo mips-sony-newsos6
+ exit 0 ;;
+ R3000:*System_V*:*:* | R4000:UNIX_SYSV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+cat >dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+#if !defined (ultrix)
+ printf ("vax-dec-bsd\n"); exit (0);
+#else
+ printf ("vax-dec-ultrix\n"); exit (0);
+#endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy && rm dummy.c dummy && exit 0
+rm -f dummy.c dummy
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ c34*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ c38*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ c4*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ esac
+fi
+
+#echo '(Unable to guess system type)' 1>&2
+
+exit 1
diff --git a/glib/config.sub b/glib/config.sub
new file mode 100755
index 000000000..213a6d47d
--- /dev/null
+++ b/glib/config.sub
@@ -0,0 +1,954 @@
+#! /bin/sh
+# Configuration validation subroutine script, version 1.1.
+# Copyright (C) 1991, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+if [ x$1 = x ]
+then
+ echo Configuration name missing. 1>&2
+ echo "Usage: $0 CPU-MFR-OPSYS" 1>&2
+ echo "or $0 ALIAS" 1>&2
+ echo where ALIAS is a recognized configuration type. 1>&2
+ exit 1
+fi
+
+# First pass through any local machine types.
+case $1 in
+ *local*)
+ echo $1
+ exit 0
+ ;;
+ *)
+ ;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ linux-gnu*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple)
+ os=
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco5)
+ os=sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ tahoe | i860 | m32r | m68k | m68000 | m88k | ns32k | arc | arm \
+ | arme[lb] | pyramid | mn10200 | mn10300 \
+ | tron | a29k | 580 | i960 | h8300 | hppa | hppa1.0 | hppa1.1 \
+ | alpha | alphaev5 | alphaev56 | we32k | ns16k | clipper \
+ | i370 | sh | powerpc | powerpcle | 1750a | dsp16xx | pdp11 \
+ | mips64 | mipsel | mips64el | mips64orion | mips64orionel \
+ | mipstx39 | mipstx39el \
+ | sparc | sparclet | sparclite | sparc64 | v850)
+ basic_machine=$basic_machine-unknown
+ ;;
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i[3456]86)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ vax-* | tahoe-* | i[3456]86-* | i860-* | m32r-* | m68k-* | m68000-* \
+ | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | arm-* | c[123]* \
+ | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \
+ | power-* | none-* | 580-* | cray2-* | h8300-* | i960-* \
+ | xmp-* | ymp-* | hppa-* | hppa1.0-* | hppa1.1-* \
+ | alpha-* | alphaev5-* | alphaev56-* | we32k-* | cydra-* \
+ | ns16k-* | pn-* | np1-* | xps100-* | clipper-* | orion-* \
+ | sparclite-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \
+ | sparc64-* | mips64-* | mipsel-* \
+ | mips64el-* | mips64orion-* | mips64orionel-* \
+ | mipstx39-* | mipstx39el-* \
+ | f301-*)
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-cbm
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-cbm
+ os=-amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-cbm
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ cray2)
+ basic_machine=cray2-cray
+ os=-unicos
+ ;;
+ [ctj]90-cray)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k7[0-9][0-9] | hp7[0-9][0-9] | hp9k8[0-9]7 | hp8[0-9]7)
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i[3456]86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i[3456]86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i[3456]86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i[3456]86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ mipsel*-linux*)
+ basic_machine=mipsel-unknown
+ os=-linux-gnu
+ ;;
+ mips*-linux*)
+ basic_machine=mips-unknown
+ os=-linux-gnu
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pentium | p5)
+ basic_machine=i586-intel
+ ;;
+ pentiumpro | p6)
+ basic_machine=i686-intel
+ ;;
+ pentium-* | p5-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ k5)
+ # We don't have specific support for AMD's K5 yet, so just call it a Pentium
+ basic_machine=i586-amd
+ ;;
+ nexen)
+ # We don't have specific support for Nexgen yet, so just call it a Pentium
+ basic_machine=i586-nexgen
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=rs6000-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ xmp)
+ basic_machine=xmp-cray
+ os=-unicos
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ mips)
+ if [ x$os = x-linux-gnu ]; then
+ basic_machine=mips-unknown
+ else
+ basic_machine=mips-mips
+ fi
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sparc)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
+ | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -cygwin32* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux-gnu* | -uxpv*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigaos
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f301-fujitsu)
+ os=-uxpv
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -aix*)
+ vendor=ibm
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -vxsim* | -vxworks*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
diff --git a/glib/configure b/glib/configure
new file mode 100755
index 000000000..becb1c703
--- /dev/null
+++ b/glib/configure
@@ -0,0 +1,2921 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.12
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+ac_help="$ac_help
+ --with-gnu-ld assume the C compiler uses GNU ld [default=no]"
+ac_help="$ac_help
+ --enable-shared build shared libraries [default=yes]"
+ac_help="$ac_help
+ --enable-static build static libraries [default=yes]"
+ac_help="$ac_help
+ --enable-maintainer-mode enable make rules and dependencies not useful
+ (and sometimes confusing) to the casual installer"
+ac_help="$ac_help
+ --enable-debug turn on debugging [default=no]"
+ac_help="$ac_help
+ --enable-ansi turn on strict ansi [default=no]"
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.12"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=glib.h
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:566: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ # Account for people who put trailing slashes in PATH elements.
+ case "$ac_dir/" in
+ /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ for ac_prog in ginstall installbsd scoinst install; do
+ if test -f $ac_dir/$ac_prog; then
+ if test $ac_prog = install &&
+ grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ # OSF/1 installbsd also uses dspmsg, but is usable.
+ :
+ else
+ ac_cv_path_install="$ac_dir/$ac_prog -c"
+ break 2
+ fi
+ fi
+ done
+ ;;
+ esac
+ done
+ IFS="$ac_save_IFS"
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL="$ac_cv_path_install"
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL="$ac_install_sh"
+ fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
+
+
+PACKAGE=glib
+
+VERSION=971109
+
+if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
+ { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; }
+fi
+cat >> confdefs.h <<EOF
+#define PACKAGE "$PACKAGE"
+EOF
+
+cat >> confdefs.h <<EOF
+#define VERSION "$VERSION"
+EOF
+
+echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6
+echo "configure:635: checking whether build environment is sane" >&5
+# Just in case
+sleep 1
+echo timestamp > conftestfile
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
+ if test "" = "X"; then
+ # -L didn't work.
+ set X `ls -t $srcdir/configure conftestfile`
+ fi
+ test "$2" = conftestfile
+ )
+then
+ # Ok.
+ :
+else
+ { echo "configure: error: newly created file is older than distributed files!
+Check your system clock" 1>&2; exit 1; }
+fi
+rm -f conftest*
+echo "$ac_t""yes" 1>&6
+if test "$program_transform_name" = s,x,x,; then
+ program_transform_name=
+else
+ # Double any \ or $. echo might interpret backslashes.
+ cat <<\EOF_SED > conftestsed
+s,\\,\\\\,g; s,\$,$$,g
+EOF_SED
+ program_transform_name="`echo $program_transform_name|sed -f conftestsed`"
+ rm -f conftestsed
+fi
+test "$program_prefix" != NONE &&
+ program_transform_name="s,^,${program_prefix},; $program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+ program_transform_name="s,\$\$,${program_suffix},; $program_transform_name"
+
+# sed with no file args requires a program.
+test "$program_transform_name" = "" && program_transform_name="s,x,x,"
+
+missing_dir=`cd $ac_aux_dir && pwd`
+echo $ac_n "checking for working aclocal""... $ac_c" 1>&6
+echo "configure:682: checking for working aclocal" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf. Sigh.
+if (aclocal --version) < /dev/null > /dev/null 2>&1; then
+ ACLOCAL=aclocal
+ echo "$ac_t""found" 1>&6
+else
+ ACLOCAL="$missing_dir/missing aclocal"
+ echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working autoconf""... $ac_c" 1>&6
+echo "configure:695: checking for working autoconf" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf. Sigh.
+if (autoconf --version) < /dev/null > /dev/null 2>&1; then
+ AUTOCONF=autoconf
+ echo "$ac_t""found" 1>&6
+else
+ AUTOCONF="$missing_dir/missing autoconf"
+ echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working automake""... $ac_c" 1>&6
+echo "configure:708: checking for working automake" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf. Sigh.
+if (automake --version) < /dev/null > /dev/null 2>&1; then
+ AUTOMAKE=automake
+ echo "$ac_t""found" 1>&6
+else
+ AUTOMAKE="$missing_dir/missing automake"
+ echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working autoheader""... $ac_c" 1>&6
+echo "configure:721: checking for working autoheader" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf. Sigh.
+if (autoheader --version) < /dev/null > /dev/null 2>&1; then
+ AUTOHEADER=autoheader
+ echo "$ac_t""found" 1>&6
+else
+ AUTOHEADER="$missing_dir/missing autoheader"
+ echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6
+echo "configure:734: checking for working makeinfo" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf. Sigh.
+if (makeinfo --version) < /dev/null > /dev/null 2>&1; then
+ MAKEINFO=makeinfo
+ echo "$ac_t""found" 1>&6
+else
+ MAKEINFO="$missing_dir/missing makeinfo"
+ echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
+echo "configure:747: checking whether ${MAKE-make} sets \${MAKE}" >&5
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftestmake <<\EOF
+all:
+ @echo 'ac_maketemp="${MAKE}"'
+EOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=`
+if test -n "$ac_maketemp"; then
+ eval ac_cv_prog_make_${ac_make}_set=yes
+else
+ eval ac_cv_prog_make_${ac_make}_set=no
+fi
+rm -f conftestmake
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ SET_MAKE=
+else
+ echo "$ac_t""no" 1>&6
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+
+# Specify a configuration file
+
+
+
+
+
+# Make sure we can run config.sub.
+if $ac_config_sub sun4 >/dev/null 2>&1; then :
+else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking host system type""... $ac_c" 1>&6
+echo "configure:786: checking host system type" >&5
+
+host_alias=$host
+case "$host_alias" in
+NONE)
+ case $nonopt in
+ NONE)
+ if host_alias=`$ac_config_guess`; then :
+ else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
+ fi ;;
+ *) host_alias=$nonopt ;;
+ esac ;;
+esac
+
+host=`$ac_config_sub $host_alias`
+host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$host" 1>&6
+
+# Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:809: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_RANLIB="ranlib"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":"
+fi
+fi
+RANLIB="$ac_cv_prog_RANLIB"
+if test -n "$RANLIB"; then
+ echo "$ac_t""$RANLIB" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:838: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="gcc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:867: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ ac_prog_rejected=no
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# -gt 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ set dummy "$ac_dir/$ac_word" "$@"
+ shift
+ ac_cv_prog_CC="$@"
+ fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:915: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext <<EOF
+#line 925 "configure"
+#include "confdefs.h"
+main(){return(0);}
+EOF
+if { (eval echo configure:929: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ ac_cv_prog_cc_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+ ac_cv_prog_cc_cross=no
+ else
+ ac_cv_prog_cc_cross=yes
+ fi
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:949: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:954: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:963: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+else
+ ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+ GCC=yes
+ ac_test_CFLAGS="${CFLAGS+set}"
+ ac_save_CFLAGS="$CFLAGS"
+ CFLAGS=
+ echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:978: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ ac_cv_prog_cc_g=yes
+else
+ ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+ if test "$ac_test_CFLAGS" = set; then
+ CFLAGS="$ac_save_CFLAGS"
+ elif test $ac_cv_prog_cc_g = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-O2"
+ fi
+else
+ GCC=
+ test "${CFLAGS+set}" = set || CFLAGS="-g"
+fi
+
+# Check whether --with-gnu-ld or --without-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then
+ withval="$with_gnu_ld"
+ test "$withval" = no || with_gnu_ld=yes
+else
+ with_gnu_ld=no
+fi
+
+
+ac_prog=ld
+if test "$ac_cv_prog_gcc" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ echo $ac_n "checking for ld used by GCC""... $ac_c" 1>&6
+echo "configure:1018: checking for ld used by GCC" >&5
+ ac_prog=`($CC -print-prog-name=ld) 2>&5`
+ case "$ac_prog" in
+ # Accept absolute paths.
+ /*)
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ echo $ac_n "checking for GNU ld""... $ac_c" 1>&6
+echo "configure:1036: checking for GNU ld" >&5
+else
+ echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6
+echo "configure:1039: checking for non-GNU ld" >&5
+fi
+if eval "test \"`echo '$''{'ac_cv_path_LD'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -z "$LD"; then
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog"; then
+ ac_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some GNU ld's only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ if "$ac_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
+ test "$with_gnu_ld" != no && break
+ else
+ test "$with_gnu_ld" != yes && break
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+else
+ ac_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$ac_cv_path_LD"
+if test -n "$LD"; then
+ echo "$ac_t""$LD" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+test -z "$LD" && { echo "configure: error: no acceptable ld found in \$PATH" 1>&2; exit 1; }
+
+echo $ac_n "checking if the linker ($LD) is GNU ld""... $ac_c" 1>&6
+echo "configure:1075: checking if the linker ($LD) is GNU ld" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gnu_ld'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # I'd rather use --version here, but apparently some GNU ld's only accept -v.
+if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+ ac_cv_prog_gnu_ld=yes
+else
+ ac_cv_prog_gnu_ld=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gnu_ld" 1>&6
+
+
+echo $ac_n "checking for BSD-compatible nm""... $ac_c" 1>&6
+echo "configure:1091: checking for BSD-compatible nm" >&5
+if eval "test \"`echo '$''{'ac_cv_path_NM'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$NM" in
+/*)
+ ac_cv_path_NM="$NM" # Let the user override the test with a path.
+ ;;
+*)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in /usr/ucb $PATH /bin; do
+ test -z "$ac_dir" && dir=.
+ if test -f $ac_dir/nm; then
+ # Check to see if the nm accepts a BSD-compat flag.
+ if ($ac_dir/nm -B /dev/null 2>&1; exit 0) | grep /dev/null >/dev/null; then
+ ac_cv_path_NM="$ac_dir/nm -B"
+ elif ($ac_dir/nm -p /dev/null 2>&1; exit 0) | grep /dev/null >/dev/null; then
+ ac_cv_path_NM="$ac_dir/nm -p"
+ else
+ ac_cv_path_NM="$ac_dir/nm"
+ fi
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_NM" && ac_cv_path_NM=nm
+ ;;
+esac
+fi
+
+NM="$ac_cv_path_NM"
+echo "$ac_t""$NM" 1>&6
+
+
+echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6
+echo "configure:1126: checking whether ln -s works" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ rm -f conftestdata
+if ln -s X conftestdata 2>/dev/null
+then
+ rm -f conftestdata
+ ac_cv_prog_LN_S="ln -s"
+else
+ ac_cv_prog_LN_S=ln
+fi
+fi
+LN_S="$ac_cv_prog_LN_S"
+if test "$ac_cv_prog_LN_S" = "ln -s"; then
+ echo "$ac_t""yes" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+
+
+
+
+
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+
+
+# Check whether --enable-shared or --disable-shared was given.
+if test "${enable_shared+set}" = set; then
+ enableval="$enable_shared"
+ if test "$enableval" = no; then
+ libtool_enable_shared=no
+else
+ libtool_enable_shared=yes
+fi
+fi
+
+test -n "$libtool_enable_shared" && enable_shared="$libtool_enable_shared"
+libtool_shared=
+test "$enable_shared" = no && libtool_shared=" --disable-shared"
+
+# Check whether --enable-static or --disable-static was given.
+if test "${enable_static+set}" = set; then
+ enableval="$enable_static"
+ if test "$enableval" = no; then
+ libtool_enable_static=no
+else
+ libtool_enable_static=yes
+fi
+fi
+
+test -n "$libtool_enable_static" && enable_static="$libtool_enable_static"
+libtool_static=
+test "$enable_static" = no && libtool_static=" --disable-static"
+
+libtool_flags="$libtool_shared$libtool_static"
+test "$silent" = yes && libtool_flags="$libtool_flags --silent"
+test "$ac_cv_prog_gcc" = yes && libtool_flags="$libtool_flags --with-gcc"
+test "$ac_cv_prog_gnu_ld" = yes && libtool_flags="$libtool_flags --with-gnu-ld"
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case "$host" in
+*-*-irix6*)
+ ac_save_CFLAGS="$CFLAGS"
+ flag_passed=no
+ for f in -32 -64 -n32 ABI -cckr -mips1 -mips2 -mips3 -mips4; do
+ case "$f" in
+ ABI)
+ test -n "$SGI_ABI" && flag_passed=yes
+ if test "$flag_passed" = no && test "$ac_cv_prog_gcc" = yes; then
+ # Choose the ABI flag according to GCC's specs.
+ if $CC -dumpspecs 2>&1 | sed '/^\*link:$/,/^$/!d' | egrep -e '[ ]-32' >/dev/null; then
+ LD="${LD-ld} -32"
+ else
+ LD="${LD-ld} -n32"
+ fi
+ fi
+ ;;
+
+ *)
+ if echo " $CC $CFLAGS " | egrep -e "[ ]$f[ ]" > /dev/null; then
+ flag_passed=yes
+ LD="${LD-ld} $f"
+ fi
+ ;;
+ esac
+ done
+ CFLAGS="$ac_save_CFLAGS"
+ ;;
+
+*-*-sco3.2v5*)
+ # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+ CFLAGS="$CFLAGS -belf"
+ ;;
+esac
+
+# Actually configure libtool. ac_aux_dir is where install-sh is found.
+CC="$CC" CFLAGS="$CFLAGS" CPPFLAGS="$CPPFLAGS" \
+LD="$LD" NM="$NM" RANLIB="$RANLIB" LN_S="$LN_S" \
+${CONFIG_SHELL-/bin/sh} $ac_aux_dir/ltconfig \
+$libtool_flags --no-verify $ac_aux_dir/ltmain.sh $host \
+|| { echo "configure: error: libtool configure failed" 1>&2; exit 1; }
+
+
+echo $ac_n "checking whether to enable maintainer-specific portions of Makefiles""... $ac_c" 1>&6
+echo "configure:1236: checking whether to enable maintainer-specific portions of Makefiles" >&5
+ # Check whether --enable-maintainer-mode or --disable-maintainer-mode was given.
+if test "${enable_maintainer_mode+set}" = set; then
+ enableval="$enable_maintainer_mode"
+ USE_MAINTAINER_MODE=$enableval
+else
+ USE_MAINTAINER_MODE=no
+fi
+
+ echo "$ac_t""$USE_MAINTAINER_MODE" 1>&6
+ if test $USE_MAINTAINER_MODE = yes; then
+ MAINT=
+ else
+ MAINT='#M#'
+ fi
+
+
+
+
+# Make sure we can run config.sub.
+if $ac_config_sub sun4 >/dev/null 2>&1; then :
+else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking host system type""... $ac_c" 1>&6
+echo "configure:1261: checking host system type" >&5
+
+host_alias=$host
+case "$host_alias" in
+NONE)
+ case $nonopt in
+ NONE)
+ if host_alias=`$ac_config_guess`; then :
+ else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
+ fi ;;
+ *) host_alias=$nonopt ;;
+ esac ;;
+esac
+
+host=`$ac_config_sub $host_alias`
+host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$host" 1>&6
+
+
+# Check whether --enable-debug or --disable-debug was given.
+if test "${enable_debug+set}" = set; then
+ enableval="$enable_debug"
+ if eval "test x$enable_debug = xyes"; then
+ DEBUGFLAG="-g"
+fi
+fi
+
+
+# Check whether --enable-ansi or --disable-ansi was given.
+if test "${enable_ansi+set}" = set; then
+ enableval="$enable_ansi"
+ :
+else
+ enable_ansi=no
+fi
+
+
+if test -n "$DEBUGFLAG"; then
+ CFLAGS="$DEBUGFLAG"
+fi
+
+# Checks for programs.
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1308: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="gcc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1337: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ ac_prog_rejected=no
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# -gt 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ set dummy "$ac_dir/$ac_word" "$@"
+ shift
+ ac_cv_prog_CC="$@"
+ fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:1385: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext <<EOF
+#line 1395 "configure"
+#include "confdefs.h"
+main(){return(0);}
+EOF
+if { (eval echo configure:1399: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ ac_cv_prog_cc_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+ ac_cv_prog_cc_cross=no
+ else
+ ac_cv_prog_cc_cross=yes
+ fi
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:1419: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:1424: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1433: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+else
+ ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+ GCC=yes
+ ac_test_CFLAGS="${CFLAGS+set}"
+ ac_save_CFLAGS="$CFLAGS"
+ CFLAGS=
+ echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:1448: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ ac_cv_prog_cc_g=yes
+else
+ ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+ if test "$ac_test_CFLAGS" = set; then
+ CFLAGS="$ac_save_CFLAGS"
+ elif test $ac_cv_prog_cc_g = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-O2"
+ fi
+else
+ GCC=
+ test "${CFLAGS+set}" = set || CFLAGS="-g"
+fi
+
+
+
+
+echo $ac_n "checking for ${CC-cc} option to accept ANSI C""... $ac_c" 1>&6
+echo "configure:1479: checking for ${CC-cc} option to accept ANSI C" >&5
+if eval "test \"`echo '$''{'am_cv_prog_cc_stdc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ am_cv_prog_cc_stdc=no
+ac_save_CC="$CC"
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX -qlanglvl=ansi
+# Ultrix and OSF/1 -std1
+# HP-UX -Aa -D_HPUX_SOURCE
+# SVR4 -Xc -D__EXTENSIONS__
+for ac_arg in "" -qlanglvl=ansi -std1 "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ cat > conftest.$ac_ext <<EOF
+#line 1495 "configure"
+#include "confdefs.h"
+#if !defined(__STDC__) || __STDC__ != 1
+choke me
+#endif
+/* DYNIX/ptx V4.1.3 can't compile sys/stat.h with -Xc -D__EXTENSIONS__. */
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/stat.h>
+#endif
+
+int main() {
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+; return 0; }
+EOF
+if { (eval echo configure:1513: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ am_cv_prog_cc_stdc="$ac_arg"; break
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+done
+CC="$ac_save_CC"
+
+fi
+
+if test -z "$am_cv_prog_cc_stdc"; then
+ echo "$ac_t""none needed" 1>&6
+else
+ echo "$ac_t""$am_cv_prog_cc_stdc" 1>&6
+fi
+case "x$am_cv_prog_cc_stdc" in
+ x|xno) ;;
+ *) CC="$CC $am_cv_prog_cc_stdc" ;;
+esac
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:1547: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ # Account for people who put trailing slashes in PATH elements.
+ case "$ac_dir/" in
+ /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ for ac_prog in ginstall installbsd scoinst install; do
+ if test -f $ac_dir/$ac_prog; then
+ if test $ac_prog = install &&
+ grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ # OSF/1 installbsd also uses dspmsg, but is usable.
+ :
+ else
+ ac_cv_path_install="$ac_dir/$ac_prog -c"
+ break 2
+ fi
+ fi
+ done
+ ;;
+ esac
+ done
+ IFS="$ac_save_IFS"
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL="$ac_cv_path_install"
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL="$ac_install_sh"
+ fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+
+if eval "test x$GCC = xyes"; then
+ test `echo "$CFLAGS" | grep "\-Wall" > /dev/null 2> /dev/null`
+ if test ! $?; then
+ CFLAGS="$CFLAGS -Wall"
+ fi
+
+ if eval "test x$enable_ansi = xyes"; then
+ test `echo "$CFLAGS" | grep "\-ansi" > /dev/null 2> /dev/null`
+ if test ! $?; then
+ CFLAGS="$CFLAGS -ansi"
+ fi
+
+ test `echo "$CFLAGS" | grep "\-pedantic" > /dev/null 2> /dev/null`
+ if test ! $?; then
+ CFLAGS="$CFLAGS -pedantic"
+ fi
+ fi
+fi
+
+# Checks for header files.
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:1618: checking how to run the C preprocessor" >&5
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # This must be in double quotes, not single quotes, because CPP may get
+ # substituted into the Makefile and "${CC-cc}" will confuse make.
+ CPP="${CC-cc} -E"
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp.
+ cat > conftest.$ac_ext <<EOF
+#line 1633 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1639: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -E -traditional-cpp"
+ cat > conftest.$ac_ext <<EOF
+#line 1650 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1656: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+ ac_cv_prog_CPP="$CPP"
+fi
+ CPP="$ac_cv_prog_CPP"
+else
+ ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+echo "configure:1679: checking for ANSI C header files" >&5
+if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1684 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1692: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ ac_cv_header_stdc=yes
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 1709 "configure"
+#include "confdefs.h"
+#include <string.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "memchr" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 1727 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "free" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+if test "$cross_compiling" = yes; then
+ :
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1748 "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int main () { int i; for (i = 0; i < 256; i++)
+if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
+exit (0); }
+
+EOF
+if { (eval echo configure:1759: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+then
+ :
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_header_stdc=no
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_header_stdc" 1>&6
+if test $ac_cv_header_stdc = yes; then
+ cat >> confdefs.h <<\EOF
+#define STDC_HEADERS 1
+EOF
+
+fi
+
+
+# Checks for library functions.
+echo $ac_n "checking for vprintf""... $ac_c" 1>&6
+echo "configure:1785: checking for vprintf" >&5
+if eval "test \"`echo '$''{'ac_cv_func_vprintf'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1790 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char vprintf(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char vprintf();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_vprintf) || defined (__stub___vprintf)
+choke me
+#else
+vprintf();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1813: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_func_vprintf=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_vprintf=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'vprintf`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define HAVE_VPRINTF 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test "$ac_cv_func_vprintf" != yes; then
+echo $ac_n "checking for _doprnt""... $ac_c" 1>&6
+echo "configure:1837: checking for _doprnt" >&5
+if eval "test \"`echo '$''{'ac_cv_func__doprnt'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1842 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char _doprnt(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char _doprnt();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub__doprnt) || defined (__stub____doprnt)
+choke me
+#else
+_doprnt();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1865: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_func__doprnt=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func__doprnt=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'_doprnt`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define HAVE_DOPRNT 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+
+echo $ac_n "checking size of char""... $ac_c" 1>&6
+echo "configure:1891: checking size of char" >&5
+if eval "test \"`echo '$''{'ac_cv_sizeof_char'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1899 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+main()
+{
+ FILE *f=fopen("conftestval", "w");
+ if (!f) exit(1);
+ fprintf(f, "%d\n", sizeof(char));
+ exit(0);
+}
+EOF
+if { (eval echo configure:1910: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_sizeof_char=`cat conftestval`
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_sizeof_char=0
+fi
+rm -fr conftest*
+fi
+
+fi
+echo "$ac_t""$ac_cv_sizeof_char" 1>&6
+cat >> confdefs.h <<EOF
+#define SIZEOF_CHAR $ac_cv_sizeof_char
+EOF
+
+
+echo $ac_n "checking size of short""... $ac_c" 1>&6
+echo "configure:1930: checking size of short" >&5
+if eval "test \"`echo '$''{'ac_cv_sizeof_short'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1938 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+main()
+{
+ FILE *f=fopen("conftestval", "w");
+ if (!f) exit(1);
+ fprintf(f, "%d\n", sizeof(short));
+ exit(0);
+}
+EOF
+if { (eval echo configure:1949: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_sizeof_short=`cat conftestval`
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_sizeof_short=0
+fi
+rm -fr conftest*
+fi
+
+fi
+echo "$ac_t""$ac_cv_sizeof_short" 1>&6
+cat >> confdefs.h <<EOF
+#define SIZEOF_SHORT $ac_cv_sizeof_short
+EOF
+
+
+echo $ac_n "checking size of long""... $ac_c" 1>&6
+echo "configure:1969: checking size of long" >&5
+if eval "test \"`echo '$''{'ac_cv_sizeof_long'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1977 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+main()
+{
+ FILE *f=fopen("conftestval", "w");
+ if (!f) exit(1);
+ fprintf(f, "%d\n", sizeof(long));
+ exit(0);
+}
+EOF
+if { (eval echo configure:1988: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_sizeof_long=`cat conftestval`
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_sizeof_long=0
+fi
+rm -fr conftest*
+fi
+
+fi
+echo "$ac_t""$ac_cv_sizeof_long" 1>&6
+cat >> confdefs.h <<EOF
+#define SIZEOF_LONG $ac_cv_sizeof_long
+EOF
+
+
+echo $ac_n "checking size of int""... $ac_c" 1>&6
+echo "configure:2008: checking size of int" >&5
+if eval "test \"`echo '$''{'ac_cv_sizeof_int'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2016 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+main()
+{
+ FILE *f=fopen("conftestval", "w");
+ if (!f) exit(1);
+ fprintf(f, "%d\n", sizeof(int));
+ exit(0);
+}
+EOF
+if { (eval echo configure:2027: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_sizeof_int=`cat conftestval`
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_sizeof_int=0
+fi
+rm -fr conftest*
+fi
+
+fi
+echo "$ac_t""$ac_cv_sizeof_int" 1>&6
+cat >> confdefs.h <<EOF
+#define SIZEOF_INT $ac_cv_sizeof_int
+EOF
+
+
+echo $ac_n "checking size of void *""... $ac_c" 1>&6
+echo "configure:2047: checking size of void *" >&5
+if eval "test \"`echo '$''{'ac_cv_sizeof_void_p'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2055 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+main()
+{
+ FILE *f=fopen("conftestval", "w");
+ if (!f) exit(1);
+ fprintf(f, "%d\n", sizeof(void *));
+ exit(0);
+}
+EOF
+if { (eval echo configure:2066: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_sizeof_void_p=`cat conftestval`
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_sizeof_void_p=0
+fi
+rm -fr conftest*
+fi
+
+fi
+echo "$ac_t""$ac_cv_sizeof_void_p" 1>&6
+cat >> confdefs.h <<EOF
+#define SIZEOF_VOID_P $ac_cv_sizeof_void_p
+EOF
+
+
+
+echo $ac_n "checking for long double""... $ac_c" 1>&6
+echo "configure:2087: checking for long double" >&5
+if eval "test \"`echo '$''{'ac_cv_c_long_double'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$GCC" = yes; then
+ ac_cv_c_long_double=yes
+else
+if test "$cross_compiling" = yes; then
+ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2098 "configure"
+#include "confdefs.h"
+int main() {
+/* The Stardent Vistra knows sizeof(long double), but does not support it. */
+long double foo = 0.0;
+/* On Ultrix 4.3 cc, long double is 4 and double is 8. */
+exit(sizeof(long double) < sizeof(double)); }
+EOF
+if { (eval echo configure:2106: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_c_long_double=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_c_long_double=no
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_c_long_double" 1>&6
+if test $ac_cv_c_long_double = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_LONG_DOUBLE 1
+EOF
+
+fi
+
+echo $ac_n "checking for working const""... $ac_c" 1>&6
+echo "configure:2130: checking for working const" >&5
+if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2135 "configure"
+#include "confdefs.h"
+
+int main() {
+
+/* Ultrix mips cc rejects this. */
+typedef int charset[2]; const charset x;
+/* SunOS 4.1.1 cc rejects this. */
+char const *const *ccp;
+char **p;
+/* NEC SVR4.0.2 mips cc rejects this. */
+struct point {int x, y;};
+static struct point const zero = {0,0};
+/* AIX XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in an arm
+ of an if-expression whose if-part is not a constant expression */
+const char *g = "string";
+ccp = &g + (g ? g-g : 0);
+/* HPUX 7.0 cc rejects these. */
+++ccp;
+p = (char**) ccp;
+ccp = (char const *const *) p;
+{ /* SCO 3.2v4 cc rejects this. */
+ char *t;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+}
+{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+}
+{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+}
+{ /* AIX XL C 1.02.0.0 rejects this saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; };
+ struct s *b; b->j = 5;
+}
+{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+}
+
+; return 0; }
+EOF
+if { (eval echo configure:2184: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_const=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_c_const=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_c_const" 1>&6
+if test $ac_cv_c_const = no; then
+ cat >> confdefs.h <<\EOF
+#define const
+EOF
+
+fi
+
+echo $ac_n "checking for inline""... $ac_c" 1>&6
+echo "configure:2205: checking for inline" >&5
+if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+ cat > conftest.$ac_ext <<EOF
+#line 2212 "configure"
+#include "confdefs.h"
+
+int main() {
+} $ac_kw foo() {
+; return 0; }
+EOF
+if { (eval echo configure:2219: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_inline=$ac_kw; break
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+done
+
+fi
+
+echo "$ac_t""$ac_cv_c_inline" 1>&6
+case "$ac_cv_c_inline" in
+ inline | yes) ;;
+ no) cat >> confdefs.h <<\EOF
+#define inline
+EOF
+ ;;
+ *) cat >> confdefs.h <<EOF
+#define inline $ac_cv_c_inline
+EOF
+ ;;
+esac
+
+
+for ac_hdr in float.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:2249: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2254 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2259: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+ cat >> confdefs.h <<\EOF
+#define HAVE_FLOAT_H 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+for ac_hdr in limits.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:2292: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2297 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2302: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+ cat >> confdefs.h <<\EOF
+#define HAVE_LIMITS_H 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+for ac_hdr in values.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:2335: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2340 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2345: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+ cat >> confdefs.h <<\EOF
+#define HAVE_VALUES_H 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+
+# Check for strerror and strsignal functions
+for ac_func in strerror strsignal
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:2379: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2384 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2407: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+
+# Check for sys_errlist
+echo $ac_n "checking sys_errlist""... $ac_c" 1>&6
+echo "configure:2434: checking sys_errlist" >&5
+cat > conftest.$ac_ext <<EOF
+#line 2436 "configure"
+#include "confdefs.h"
+
+int main() {
+
+extern char *sys_errlist[];
+extern int sys_nerr;
+sys_errlist[sys_nerr-1][0] = 0;
+
+; return 0; }
+EOF
+if { (eval echo configure:2447: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ glib_ok=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ glib_ok=no
+fi
+rm -f conftest*
+echo "$ac_t""$glib_ok" 1>&6
+if test $glib_ok = no; then
+ cat >> confdefs.h <<\EOF
+#define NO_SYS_ERRLIST 1
+EOF
+
+fi
+
+# Check for sys_siglist
+echo $ac_n "checking sys_siglist""... $ac_c" 1>&6
+echo "configure:2467: checking sys_siglist" >&5
+cat > conftest.$ac_ext <<EOF
+#line 2469 "configure"
+#include "confdefs.h"
+
+int main() {
+
+extern char *sys_siglist[];
+sys_siglist[1][0] = 0;
+
+; return 0; }
+EOF
+if { (eval echo configure:2479: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ glib_ok=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ glib_ok=no
+fi
+rm -f conftest*
+echo "$ac_t""$glib_ok" 1>&6
+if test $glib_ok = no; then
+ cat >> confdefs.h <<\EOF
+#define NO_SYS_SIGLIST 1
+EOF
+
+fi
+
+# Check for sys/select.h
+
+echo $ac_n "checking fd_set and sys/select""... $ac_c" 1>&6
+echo "configure:2500: checking fd_set and sys/select" >&5
+cat > conftest.$ac_ext <<EOF
+#line 2502 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+int main() {
+fd_set readMask, writeMask;
+; return 0; }
+EOF
+if { (eval echo configure:2509: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ gtk_ok=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ gtk_ok=no
+fi
+rm -f conftest*
+if test $gtk_ok = no; then
+ cat > conftest.$ac_ext <<EOF
+#line 2521 "configure"
+#include "confdefs.h"
+#include <sys/select.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "fd_mask" >/dev/null 2>&1; then
+ rm -rf conftest*
+ gtk_ok=yes
+fi
+rm -f conftest*
+
+ if test $gtk_ok = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_SYS_SELECT_H 1
+EOF
+
+ fi
+fi
+echo "$ac_t""$gtk_ok" 1>&6
+if test $gtk_ok = no; then
+ cat >> confdefs.h <<\EOF
+#define NO_FD_SET 1
+EOF
+
+fi
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+DEFS=-DHAVE_CONFIG_H
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.12"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+ac_given_INSTALL="$INSTALL"
+
+trap 'rm -fr `echo "Makefile glibconfig.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
+s%@PACKAGE@%$PACKAGE%g
+s%@VERSION@%$VERSION%g
+s%@ACLOCAL@%$ACLOCAL%g
+s%@AUTOCONF@%$AUTOCONF%g
+s%@AUTOMAKE@%$AUTOMAKE%g
+s%@AUTOHEADER@%$AUTOHEADER%g
+s%@MAKEINFO@%$MAKEINFO%g
+s%@SET_MAKE@%$SET_MAKE%g
+s%@host@%$host%g
+s%@host_alias@%$host_alias%g
+s%@host_cpu@%$host_cpu%g
+s%@host_vendor@%$host_vendor%g
+s%@host_os@%$host_os%g
+s%@RANLIB@%$RANLIB%g
+s%@CC@%$CC%g
+s%@LD@%$LD%g
+s%@NM@%$NM%g
+s%@LN_S@%$LN_S%g
+s%@LIBTOOL@%$LIBTOOL%g
+s%@MAINT@%$MAINT%g
+s%@CPP@%$CPP%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+ case "$ac_given_INSTALL" in
+ [/$]*) INSTALL="$ac_given_INSTALL" ;;
+ *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+ esac
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)'
+ac_dB='\([ ][ ]*\)[^ ]*%\1#\2'
+ac_dC='\3'
+ac_dD='%g'
+# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
+ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_uB='\([ ]\)%\1#\2define\3'
+ac_uC=' '
+ac_uD='\4%g'
+# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_eB='$%\1#\2define\3'
+ac_eC=' '
+ac_eD='%g'
+
+if test "${CONFIG_HEADERS+set}" != set; then
+EOF
+cat >> $CONFIG_STATUS <<EOF
+ CONFIG_HEADERS="glibconfig.h"
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+fi
+for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ echo creating $ac_file
+
+ rm -f conftest.frag conftest.in conftest.out
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ cat $ac_file_inputs > conftest.in
+
+EOF
+
+# Transform confdefs.h into a sed script conftest.vals that substitutes
+# the proper values into config.h.in to produce config.h. And first:
+# Protect against being on the right side of a sed subst in config.status.
+# Protect against being in an unquoted here document in config.status.
+rm -f conftest.vals
+cat > conftest.hdr <<\EOF
+s/[\\&%]/\\&/g
+s%[\\$`]%\\&%g
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
+s%ac_d%ac_u%gp
+s%ac_u%ac_e%gp
+EOF
+sed -n -f conftest.hdr confdefs.h > conftest.vals
+rm -f conftest.hdr
+
+# This sed command replaces #undef with comments. This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >> conftest.vals <<\EOF
+s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
+EOF
+
+# Break up conftest.vals because some shells have a limit on
+# the size of here documents, and old seds have small limits too.
+
+rm -f conftest.tail
+while :
+do
+ ac_lines=`grep -c . conftest.vals`
+ # grep -c gives empty output for an empty file on some AIX systems.
+ if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi
+ # Write a limited-size here document to conftest.frag.
+ echo ' cat > conftest.frag <<CEOF' >> $CONFIG_STATUS
+ sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS
+ echo 'CEOF
+ sed -f conftest.frag conftest.in > conftest.out
+ rm -f conftest.in
+ mv conftest.out conftest.in
+' >> $CONFIG_STATUS
+ sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail
+ rm -f conftest.vals
+ mv conftest.tail conftest.vals
+done
+rm -f conftest.vals
+
+cat >> $CONFIG_STATUS <<\EOF
+ rm -f conftest.frag conftest.h
+ echo "/* $ac_file. Generated automatically by configure. */" > conftest.h
+ cat conftest.in >> conftest.h
+ rm -f conftest.in
+ if cmp -s $ac_file conftest.h 2>/dev/null; then
+ echo "$ac_file is unchanged"
+ rm -f conftest.h
+ else
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ fi
+ rm -f $ac_file
+ mv conftest.h $ac_file
+ fi
+fi; done
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
diff --git a/glib/configure.in b/glib/configure.in
new file mode 100644
index 000000000..d97b441bc
--- /dev/null
+++ b/glib/configure.in
@@ -0,0 +1,116 @@
+# Process this file with autoconf to produce a configure script.
+AC_INIT(glib.h)
+
+dnl Initialize automake stuff
+AM_INIT_AUTOMAKE(glib, 971109)
+
+# Specify a configuration file
+AM_CONFIG_HEADER(glibconfig.h)
+
+dnl Initialize libtool
+AM_PROG_LIBTOOL
+
+dnl Initialize maintainer mode
+AM_MAINTAINER_MODE
+
+AC_CANONICAL_HOST
+
+AC_ARG_ENABLE(debug, [ --enable-debug turn on debugging [default=no]],
+if eval "test x$enable_debug = xyes"; then
+ DEBUGFLAG="-g"
+fi)
+
+AC_ARG_ENABLE(ansi, [ --enable-ansi turn on strict ansi [default=no]],
+ , enable_ansi=no)
+
+if test -n "$DEBUGFLAG"; then
+ CFLAGS="$DEBUGFLAG"
+fi
+
+# Checks for programs.
+AC_PROG_CC
+AM_PROG_CC_STDC
+AC_PROG_INSTALL
+
+if eval "test x$GCC = xyes"; then
+ test `echo "$CFLAGS" | grep "\-Wall" > /dev/null 2> /dev/null`
+ if test ! $?; then
+ CFLAGS="$CFLAGS -Wall"
+ fi
+
+ if eval "test x$enable_ansi = xyes"; then
+ test `echo "$CFLAGS" | grep "\-ansi" > /dev/null 2> /dev/null`
+ if test ! $?; then
+ CFLAGS="$CFLAGS -ansi"
+ fi
+
+ test `echo "$CFLAGS" | grep "\-pedantic" > /dev/null 2> /dev/null`
+ if test ! $?; then
+ CFLAGS="$CFLAGS -pedantic"
+ fi
+ fi
+fi
+
+# Checks for header files.
+AC_HEADER_STDC
+
+# Checks for library functions.
+AC_FUNC_VPRINTF
+
+AC_CHECK_SIZEOF(char)
+AC_CHECK_SIZEOF(short)
+AC_CHECK_SIZEOF(long)
+AC_CHECK_SIZEOF(int)
+AC_CHECK_SIZEOF(void *)
+
+AC_C_LONG_DOUBLE
+AC_C_CONST
+AC_C_INLINE
+
+AC_CHECK_HEADERS(float.h, AC_DEFINE(HAVE_FLOAT_H))
+AC_CHECK_HEADERS(limits.h, AC_DEFINE(HAVE_LIMITS_H))
+AC_CHECK_HEADERS(values.h, AC_DEFINE(HAVE_VALUES_H))
+
+# Check for strerror and strsignal functions
+AC_CHECK_FUNCS(strerror strsignal)
+
+# Check for sys_errlist
+AC_MSG_CHECKING(sys_errlist)
+AC_TRY_LINK(, [
+extern char *sys_errlist[];
+extern int sys_nerr;
+sys_errlist[sys_nerr-1][0] = 0;
+], glib_ok=yes, glib_ok=no)
+AC_MSG_RESULT($glib_ok)
+if test $glib_ok = no; then
+ AC_DEFINE(NO_SYS_ERRLIST)
+fi
+
+# Check for sys_siglist
+AC_MSG_CHECKING(sys_siglist)
+AC_TRY_LINK(, [
+extern char *sys_siglist[];
+sys_siglist[1][0] = 0;
+], glib_ok=yes, glib_ok=no)
+AC_MSG_RESULT($glib_ok)
+if test $glib_ok = no; then
+ AC_DEFINE(NO_SYS_SIGLIST)
+fi
+
+# Check for sys/select.h
+
+AC_MSG_CHECKING([fd_set and sys/select])
+AC_TRY_COMPILE([#include <sys/types.h>],
+ [fd_set readMask, writeMask;], gtk_ok=yes, gtk_ok=no)
+if test $gtk_ok = no; then
+ AC_HEADER_EGREP(fd_mask, sys/select.h, gtk_ok=yes)
+ if test $gtk_ok = yes; then
+ AC_DEFINE(HAVE_SYS_SELECT_H)
+ fi
+fi
+AC_MSG_RESULT($gtk_ok)
+if test $gtk_ok = no; then
+ AC_DEFINE(NO_FD_SET)
+fi
+
+AC_OUTPUT(Makefile)
diff --git a/glib/garray.c b/glib/garray.c
new file mode 100644
index 000000000..370084843
--- /dev/null
+++ b/glib/garray.c
@@ -0,0 +1,142 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <string.h>
+#include "glib.h"
+
+
+#define MIN_ARRAY_SIZE 16
+
+
+typedef struct _GRealArray GRealArray;
+
+struct _GRealArray
+{
+ guint8 *data;
+ guint len;
+ guint alloc;
+ guint zero_terminated;
+};
+
+
+static gint g_nearest_pow (gint num);
+static void g_array_maybe_expand (GRealArray *array,
+ gint len);
+
+
+static GMemChunk *array_mem_chunk = NULL;
+
+
+GArray*
+g_array_new (zero_terminated)
+{
+ GRealArray *array;
+
+ if (!array_mem_chunk)
+ array_mem_chunk = g_mem_chunk_new ("array mem chunk",
+ sizeof (GRealArray),
+ 1024, G_ALLOC_AND_FREE);
+
+ array = g_chunk_new (GRealArray, array_mem_chunk);
+
+ array->data = NULL;
+ array->len = 0;
+ array->alloc = 0;
+ array->zero_terminated = (zero_terminated ? 1 : 0);
+
+ return (GArray*) array;
+}
+
+void
+g_array_free (GArray *array,
+ gint free_segment)
+{
+ if (free_segment)
+ g_free (array->data);
+
+ g_mem_chunk_free (array_mem_chunk, array);
+}
+
+GArray*
+g_rarray_append (GArray *array,
+ gpointer data,
+ gint size)
+{
+ g_array_maybe_expand ((GRealArray*) array, size);
+
+ memcpy (array->data + array->len, data, size);
+
+ array->len += size;
+
+ return array;
+}
+
+GArray*
+g_rarray_prepend (GArray *array,
+ gpointer data,
+ gint size)
+{
+ g_array_maybe_expand ((GRealArray*) array, size);
+
+ memmove (array->data + size, array->data, array->len);
+ memcpy (array->data, data, size);
+
+ array->len += size;
+
+ return array;
+}
+
+GArray*
+g_rarray_truncate (GArray *array,
+ gint length,
+ gint size)
+{
+ if (array->data)
+ memset (array->data + length * size, 0, size);
+ array->len = length;
+ return array;
+}
+
+
+static gint
+g_nearest_pow (gint num)
+{
+ gint n = 1;
+
+ while (n < num)
+ n <<= 1;
+
+ return n;
+}
+
+static void
+g_array_maybe_expand (GRealArray *array,
+ gint len)
+{
+ guint old_alloc;
+
+ if ((array->len + len) > array->alloc)
+ {
+ old_alloc = array->alloc;
+
+ array->alloc = g_nearest_pow (array->len + array->zero_terminated + len);
+ array->alloc = MAX (array->alloc, MIN_ARRAY_SIZE);
+ array->data = g_realloc (array->data, array->alloc);
+
+ memset (array->data + old_alloc, 0, array->alloc - old_alloc);
+ }
+}
diff --git a/glib/gcache.c b/glib/gcache.c
new file mode 100644
index 000000000..b12121995
--- /dev/null
+++ b/glib/gcache.c
@@ -0,0 +1,211 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "glib.h"
+
+
+typedef struct _GCacheNode GCacheNode;
+typedef struct _GRealCache GRealCache;
+
+struct _GCacheNode
+{
+ /* A reference counted node */
+ gpointer value;
+ gint ref_count;
+};
+
+struct _GRealCache
+{
+ /* Called to create a value from a key */
+ GCacheNewFunc value_new_func;
+
+ /* Called to destroy a value */
+ GCacheDestroyFunc value_destroy_func;
+
+ /* Called to duplicate a key */
+ GCacheDupFunc key_dup_func;
+
+ /* Called to destroy a key */
+ GCacheDestroyFunc key_destroy_func;
+
+ /* Associates keys with nodes */
+ GHashTable *key_table;
+
+ /* Associates nodes with keys */
+ GHashTable *value_table;
+};
+
+
+static GCacheNode* g_cache_node_new (gpointer value);
+static void g_cache_node_destroy (GCacheNode *node);
+
+
+static GMemChunk *node_mem_chunk = NULL;
+
+
+GCache*
+g_cache_new (GCacheNewFunc value_new_func,
+ GCacheDestroyFunc value_destroy_func,
+ GCacheDupFunc key_dup_func,
+ GCacheDestroyFunc key_destroy_func,
+ GHashFunc hash_key_func,
+ GHashFunc hash_value_func,
+ GCompareFunc key_compare_func)
+{
+ GRealCache *cache;
+
+ g_return_val_if_fail (value_new_func != NULL, NULL);
+ g_return_val_if_fail (value_destroy_func != NULL, NULL);
+ g_return_val_if_fail (key_dup_func != NULL, NULL);
+ g_return_val_if_fail (key_destroy_func != NULL, NULL);
+ g_return_val_if_fail (hash_key_func != NULL, NULL);
+ g_return_val_if_fail (hash_value_func != NULL, NULL);
+ g_return_val_if_fail (key_compare_func != NULL, NULL);
+
+ cache = g_new (GRealCache, 1);
+ cache->value_new_func = value_new_func;
+ cache->value_destroy_func = value_destroy_func;
+ cache->key_dup_func = key_dup_func;
+ cache->key_destroy_func = key_destroy_func;
+ cache->key_table = g_hash_table_new (hash_key_func, key_compare_func);
+ cache->value_table = g_hash_table_new (hash_value_func, NULL);
+
+ return (GCache*) cache;
+}
+
+void
+g_cache_destroy (GCache *cache)
+{
+ GRealCache *rcache;
+
+ g_return_if_fail (cache != NULL);
+
+ rcache = (GRealCache*) cache;
+ g_hash_table_destroy (rcache->key_table);
+ g_hash_table_destroy (rcache->value_table);
+ g_free (rcache);
+}
+
+gpointer
+g_cache_insert (GCache *cache,
+ gpointer key)
+{
+ GRealCache *rcache;
+ GCacheNode *node;
+ gpointer value;
+
+ g_return_val_if_fail (cache != NULL, NULL);
+
+ rcache = (GRealCache*) cache;
+
+ node = g_hash_table_lookup (rcache->key_table, key);
+ if (node)
+ {
+ node->ref_count += 1;
+ return node->value;
+ }
+
+ key = (* rcache->key_dup_func) (key);
+ value = (* rcache->value_new_func) (key);
+ node = g_cache_node_new (value);
+
+ g_hash_table_insert (rcache->key_table, key, node);
+ g_hash_table_insert (rcache->value_table, value, key);
+
+ return node->value;
+}
+
+void
+g_cache_remove (GCache *cache,
+ gpointer value)
+{
+ GRealCache *rcache;
+ GCacheNode *node;
+ gpointer key;
+
+ g_return_if_fail (cache != NULL);
+
+ rcache = (GRealCache*) cache;
+
+ key = g_hash_table_lookup (rcache->value_table, value);
+ node = g_hash_table_lookup (rcache->key_table, key);
+
+ node->ref_count -= 1;
+ if (node->ref_count == 0)
+ {
+ g_hash_table_remove (rcache->value_table, value);
+ g_hash_table_remove (rcache->key_table, key);
+
+ (* rcache->key_destroy_func) (key);
+ (* rcache->value_destroy_func) (node->value);
+ g_cache_node_destroy (node);
+ }
+}
+
+void
+g_cache_key_foreach (GCache *cache,
+ GHFunc func,
+ gpointer user_data)
+{
+ GRealCache *rcache;
+
+ g_return_if_fail (cache != NULL);
+ g_return_if_fail (func != NULL);
+
+ rcache = (GRealCache*) cache;
+
+ g_hash_table_foreach (rcache->value_table, func, user_data);
+}
+
+void
+g_cache_value_foreach (GCache *cache,
+ GHFunc func,
+ gpointer user_data)
+{
+ GRealCache *rcache;
+
+ g_return_if_fail (cache != NULL);
+ g_return_if_fail (func != NULL);
+
+ rcache = (GRealCache*) cache;
+
+ g_hash_table_foreach (rcache->key_table, func, user_data);
+}
+
+
+static GCacheNode*
+g_cache_node_new (gpointer value)
+{
+ GCacheNode *node;
+
+ if (!node_mem_chunk)
+ node_mem_chunk = g_mem_chunk_new ("cache node mem chunk", sizeof (GCacheNode),
+ 1024, G_ALLOC_AND_FREE);
+
+ node = g_chunk_new (GCacheNode, node_mem_chunk);
+
+ node->value = value;
+ node->ref_count = 1;
+
+ return node;
+}
+
+static void
+g_cache_node_destroy (GCacheNode *node)
+{
+ g_mem_chunk_free (node_mem_chunk, node);
+}
diff --git a/glib/gerror.c b/glib/gerror.c
new file mode 100644
index 000000000..96e1013e9
--- /dev/null
+++ b/glib/gerror.c
@@ -0,0 +1,256 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <sys/times.h>
+#include <sys/types.h>
+
+#include <time.h>
+#include <unistd.h>
+#include "glib.h"
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif /* HAVE_SYS_SELECT_H */
+
+#ifdef STDC_HEADERS
+#include <string.h> /* for bzero on BSD systems */
+#endif
+
+#define INTERACTIVE 0
+#define STACK_TRACE 1
+
+
+#ifndef NO_FD_SET
+# define SELECT_MASK fd_set
+#else
+# ifndef _AIX
+ typedef long fd_mask;
+# endif
+# if defined(_IBMR2)
+# define SELECT_MASK void
+# else
+# define SELECT_MASK int
+# endif
+#endif
+
+
+static int do_query (char *prompt);
+static void debug (char *progname, int method);
+static void stack_trace (char **);
+static void stack_trace_sigchld (int);
+
+
+static int stack_trace_done;
+
+void
+g_debug (char *progname)
+{
+ char buf[32];
+
+ fprintf (stdout, "[n]othing, [e]xit, [s]tack trace, [a]ttach to process: ");
+ fflush (stdout);
+
+ fgets (buf, 32, stdin);
+ if (strcmp (buf, "n\n") == 0)
+ return;
+ else if (strcmp (buf, "s\n") == 0)
+ debug (progname, STACK_TRACE);
+ else if (strcmp (buf, "a\n") == 0)
+ debug (progname, INTERACTIVE);
+ else
+ exit (0);
+}
+
+void
+g_attach_process (char *progname, int query)
+{
+ if (!query || do_query ("attach to process"))
+ debug (progname, INTERACTIVE);
+}
+
+void
+g_stack_trace (char *progname, int query)
+{
+ if (!query || do_query ("print stack trace"))
+ debug (progname, STACK_TRACE);
+}
+
+static int
+do_query (char *prompt)
+{
+ char buf[32];
+
+ fprintf (stdout, "%s (y/n) ", prompt);
+ fflush (stdout);
+
+ fgets (buf, 32, stdin);
+ if ((strcmp (buf, "yes\n") == 0) ||
+ (strcmp (buf, "y\n") == 0) ||
+ (strcmp (buf, "YES\n") == 0) ||
+ (strcmp (buf, "Y\n") == 0))
+ return TRUE;
+
+ return FALSE;
+}
+
+static void
+debug (char *progname,
+ int method)
+{
+ pid_t pid;
+ char buf[16];
+ char *args[4] = { "gdb", NULL, NULL, NULL };
+ volatile int x;
+
+ sprintf (buf, "%d", (int) getpid ());
+
+ args[1] = progname;
+ args[2] = buf;
+
+ switch (method)
+ {
+ case INTERACTIVE:
+ fprintf (stdout, "pid: %s\n", buf);
+ break;
+ case STACK_TRACE:
+ pid = fork ();
+ if (pid == 0)
+ {
+ stack_trace (args);
+ _exit (0);
+ }
+ else if (pid == (pid_t) -1)
+ {
+ perror ("could not fork");
+ return;
+ }
+ break;
+ }
+
+ x = 1;
+ while (x)
+ ;
+}
+
+static void
+stack_trace (char **args)
+{
+ pid_t pid;
+ int in_fd[2];
+ int out_fd[2];
+ SELECT_MASK fdset;
+ SELECT_MASK readset;
+ struct timeval tv;
+ int sel, index, state;
+ char buffer[256];
+ char c;
+
+ stack_trace_done = 0;
+ signal (SIGCHLD, stack_trace_sigchld);
+
+ if ((pipe (in_fd) == -1) || (pipe (out_fd) == -1))
+ {
+ perror ("could open pipe");
+ _exit (0);
+ }
+
+ pid = fork ();
+ if (pid == 0)
+ {
+ close (0); dup (in_fd[0]); /* set the stdin to the in pipe */
+ close (1); dup (out_fd[1]); /* set the stdout to the out pipe */
+ close (2); dup (out_fd[1]); /* set the stderr to the out pipe */
+
+ execvp (args[0], args); /* exec gdb */
+ perror ("exec failed");
+ _exit (0);
+ }
+ else if (pid == (pid_t) -1)
+ {
+ perror ("could not fork");
+ _exit (0);
+ }
+
+ FD_ZERO (&fdset);
+ FD_SET (out_fd[0], &fdset);
+
+ write (in_fd[1], "backtrace\n", 10);
+ write (in_fd[1], "p x = 0\n", 8);
+ write (in_fd[1], "quit\n", 5);
+
+ index = 0;
+ state = 0;
+
+ while (1)
+ {
+ readset = fdset;
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+
+ sel = select (FD_SETSIZE, &readset, NULL, NULL, &tv);
+ if (sel == -1)
+ break;
+
+ if ((sel > 0) && (FD_ISSET (out_fd[0], &readset)))
+ {
+ if (read (out_fd[0], &c, 1))
+ {
+ switch (state)
+ {
+ case 0:
+ if (c == '#')
+ {
+ state = 1;
+ index = 0;
+ buffer[index++] = c;
+ }
+ break;
+ case 1:
+ buffer[index++] = c;
+ if ((c == '\n') || (c == '\r'))
+ {
+ buffer[index] = 0;
+ fprintf (stdout, "%s", buffer);
+ state = 0;
+ index = 0;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ else if (stack_trace_done)
+ break;
+ }
+
+ close (in_fd[0]);
+ close (in_fd[1]);
+ close (out_fd[0]);
+ close (out_fd[1]);
+ _exit (0);
+}
+
+static void
+stack_trace_sigchld (int signum)
+{
+ stack_trace_done = 1;
+}
diff --git a/glib/ghash.c b/glib/ghash.c
new file mode 100644
index 000000000..ed736d4cb
--- /dev/null
+++ b/glib/ghash.c
@@ -0,0 +1,418 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "glib.h"
+
+
+#define HASH_TABLE_MIN_SIZE 11
+#define HASH_TABLE_MAX_SIZE 13845163
+
+
+typedef struct _GHashNode GHashNode;
+typedef struct _GRealHashTable GRealHashTable;
+
+struct _GHashNode
+{
+ gpointer key;
+ gpointer value;
+ GHashNode *next;
+};
+
+struct _GRealHashTable
+{
+ gint size;
+ gint nnodes;
+ gint frozen;
+ GHashNode **nodes;
+ GHashFunc hash_func;
+ GCompareFunc key_compare_func;
+};
+
+
+static void g_hash_table_resize (GHashTable *hash_table);
+static gint g_hash_closest_prime (gint num);
+static GHashNode* g_hash_node_new (gpointer key,
+ gpointer value);
+static void g_hash_node_destroy (GHashNode *hash_node);
+static void g_hash_nodes_destroy (GHashNode *hash_node);
+
+
+extern gint g_primes[];
+extern gint g_nprimes;
+
+static GMemChunk *node_mem_chunk = NULL;
+static GHashNode *node_free_list = NULL;
+
+
+GHashTable*
+g_hash_table_new (GHashFunc hash_func,
+ GCompareFunc key_compare_func)
+{
+ GRealHashTable *hash_table;
+
+ g_return_val_if_fail (hash_func != NULL, NULL);
+
+ hash_table = g_new (GRealHashTable, 1);
+ hash_table->size = 0;
+ hash_table->nnodes = 0;
+ hash_table->frozen = FALSE;
+ hash_table->nodes = NULL;
+ hash_table->hash_func = hash_func;
+ hash_table->key_compare_func = key_compare_func;
+
+ return ((GHashTable*) hash_table);
+}
+
+void
+g_hash_table_destroy (GHashTable *hash_table)
+{
+ GRealHashTable *rhash_table;
+ gint i;
+
+ if (hash_table)
+ {
+ rhash_table = (GRealHashTable*) hash_table;
+
+ for (i = 0; i < rhash_table->size; i++)
+ g_hash_nodes_destroy (rhash_table->nodes[i]);
+
+ if (rhash_table->nodes)
+ g_free (rhash_table->nodes);
+ g_free (rhash_table);
+ }
+}
+
+void
+g_hash_table_insert (GHashTable *hash_table,
+ gpointer key,
+ gpointer value)
+{
+ GRealHashTable *rhash_table;
+ GHashNode *node;
+ guint hash_val;
+
+ if (hash_table)
+ {
+ rhash_table = (GRealHashTable*) hash_table;
+
+ if (rhash_table->size == 0)
+ g_hash_table_resize (hash_table);
+
+ hash_val = (* rhash_table->hash_func) (key) % rhash_table->size;
+
+ node = rhash_table->nodes[hash_val];
+ while (node)
+ {
+ if ((rhash_table->key_compare_func &&
+ (* rhash_table->key_compare_func) (node->key, key)) ||
+ (node->key == key))
+ {
+ node->value = value;
+ return;
+ }
+ node = node->next;
+ }
+
+ node = g_hash_node_new (key, value);
+ node->next = rhash_table->nodes[hash_val];
+ rhash_table->nodes[hash_val] = node;
+
+ rhash_table->nnodes += 1;
+ g_hash_table_resize (hash_table);
+ }
+}
+
+void
+g_hash_table_remove (GHashTable *hash_table,
+ gpointer key)
+{
+ GRealHashTable *rhash_table;
+ GHashNode *node;
+ GHashNode *prev;
+ guint hash_val;
+
+ rhash_table = (GRealHashTable*) hash_table;
+ if (hash_table && rhash_table->size)
+ {
+ hash_val = (* rhash_table->hash_func) (key) % rhash_table->size;
+
+ prev = NULL;
+ node = rhash_table->nodes[hash_val];
+
+ while (node)
+ {
+ if ((rhash_table->key_compare_func &&
+ (* rhash_table->key_compare_func) (node->key, key)) ||
+ (node->key == key))
+ {
+ if (prev)
+ prev->next = node->next;
+ if (node == rhash_table->nodes[hash_val])
+ rhash_table->nodes[hash_val] = node->next;
+
+ g_hash_node_destroy (node);
+
+ rhash_table->nnodes -= 1;
+ g_hash_table_resize (hash_table);
+ break;
+ }
+
+ prev = node;
+ node = node->next;
+ }
+ }
+}
+
+gpointer
+g_hash_table_lookup (GHashTable *hash_table,
+ const gpointer key)
+{
+ GRealHashTable *rhash_table;
+ GHashNode *node;
+ guint hash_val;
+
+ rhash_table = (GRealHashTable*) hash_table;
+ if (hash_table && rhash_table->size)
+ {
+ hash_val = (* rhash_table->hash_func) (key) % rhash_table->size;
+
+ node = rhash_table->nodes[hash_val];
+
+ /* Hash table lookup needs to be fast.
+ * We therefore remove the extra conditional of testing
+ * whether to call the key_compare_func or not from
+ * the inner loop.
+ */
+ if (rhash_table->key_compare_func)
+ {
+ while (node)
+ {
+ if ((* rhash_table->key_compare_func) (node->key, key))
+ return node->value;
+ node = node->next;
+ }
+ }
+ else
+ {
+ while (node)
+ {
+ if (node->key == key)
+ return node->value;
+ node = node->next;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+void
+g_hash_table_freeze (GHashTable *hash_table)
+{
+ GRealHashTable *rhash_table;
+
+ if (hash_table)
+ {
+ rhash_table = (GRealHashTable*) hash_table;
+ rhash_table->frozen = TRUE;
+ }
+}
+
+void
+g_hash_table_thaw (GHashTable *hash_table)
+{
+ GRealHashTable *rhash_table;
+
+ if (hash_table)
+ {
+ rhash_table = (GRealHashTable*) hash_table;
+ rhash_table->frozen = FALSE;
+
+ g_hash_table_resize (hash_table);
+ }
+}
+
+void
+g_hash_table_foreach (GHashTable *hash_table,
+ GHFunc func,
+ gpointer user_data)
+{
+ GRealHashTable *rhash_table;
+ GHashNode *node;
+ gint i;
+
+ if (hash_table)
+ {
+ rhash_table = (GRealHashTable*) hash_table;
+
+ for (i = 0; i < rhash_table->size; i++)
+ {
+ node = rhash_table->nodes[i];
+
+ while (node)
+ {
+ (* func) (node->key, node->value, user_data);
+ node = node->next;
+ }
+ }
+ }
+}
+
+
+static void
+g_hash_table_resize (GHashTable *hash_table)
+{
+ GRealHashTable *rhash_table;
+ GHashNode **new_nodes;
+ GHashNode *node;
+ GHashNode *next;
+ gfloat nodes_per_list;
+ guint hash_val;
+ gint new_size;
+ gint need_resize;
+ gint i;
+
+ if (hash_table)
+ {
+ rhash_table = (GRealHashTable*) hash_table;
+
+ if (rhash_table->size == 0)
+ {
+ rhash_table->size = HASH_TABLE_MIN_SIZE;
+ rhash_table->nodes = g_new (GHashNode*, rhash_table->size);
+
+ for (i = 0; i < rhash_table->size; i++)
+ rhash_table->nodes[i] = NULL;
+ }
+ else if (!rhash_table->frozen)
+ {
+ need_resize = FALSE;
+ nodes_per_list = (gfloat) rhash_table->nnodes / (gfloat) rhash_table->size;
+
+ if (nodes_per_list < 0.3)
+ {
+ if (rhash_table->size > HASH_TABLE_MIN_SIZE)
+ need_resize = TRUE;
+ }
+ else if (nodes_per_list > 3.0)
+ {
+ if (rhash_table->size < HASH_TABLE_MAX_SIZE)
+ need_resize = TRUE;
+ }
+
+ if (need_resize)
+ {
+ new_size = g_hash_closest_prime (rhash_table->nnodes);
+ if (new_size < HASH_TABLE_MIN_SIZE)
+ new_size = HASH_TABLE_MIN_SIZE;
+ else if (new_size > HASH_TABLE_MAX_SIZE)
+ new_size = HASH_TABLE_MAX_SIZE;
+
+ new_nodes = g_new (GHashNode*, new_size);
+
+ for (i = 0; i < new_size; i++)
+ new_nodes[i] = NULL;
+
+ for (i = 0; i < rhash_table->size; i++)
+ {
+ node = rhash_table->nodes[i];
+
+ while (node)
+ {
+ next = node->next;
+
+ hash_val = (* rhash_table->hash_func) (node->key) % new_size;
+ node->next = new_nodes[hash_val];
+ new_nodes[hash_val] = node;
+
+ node = next;
+ }
+ }
+
+ g_free (rhash_table->nodes);
+
+ rhash_table->nodes = new_nodes;
+ rhash_table->size = new_size;
+ }
+ }
+ }
+}
+
+static gint
+g_hash_closest_prime (gint num)
+{
+ gint i;
+
+ for (i = 0; i < g_nprimes; i++)
+ if ((g_primes[i] - num) > 0)
+ return g_primes[i];
+
+ return g_primes[g_nprimes - 1];
+}
+
+static GHashNode*
+g_hash_node_new (gpointer key,
+ gpointer value)
+{
+ GHashNode *hash_node;
+
+ if (node_free_list)
+ {
+ hash_node = node_free_list;
+ node_free_list = node_free_list->next;
+ }
+ else
+ {
+ if (!node_mem_chunk)
+ node_mem_chunk = g_mem_chunk_new ("hash node mem chunk",
+ sizeof (GHashNode),
+ 1024, G_ALLOC_ONLY);
+
+ hash_node = g_chunk_new (GHashNode, node_mem_chunk);
+ }
+
+ hash_node->key = key;
+ hash_node->value = value;
+ hash_node->next = NULL;
+
+ return hash_node;
+}
+
+static void
+g_hash_node_destroy (GHashNode *hash_node)
+{
+ if (hash_node)
+ {
+ hash_node->next = node_free_list;
+ node_free_list = hash_node;
+ }
+}
+
+static void
+g_hash_nodes_destroy (GHashNode *hash_node)
+{
+ GHashNode *node;
+
+ if (hash_node)
+ {
+ node = hash_node;
+ while (node->next)
+ node = node->next;
+ node->next = node_free_list;
+ node_free_list = hash_node;
+ }
+}
diff --git a/glib/glib.h b/glib/glib.h
new file mode 100644
index 000000000..9af5fa1bb
--- /dev/null
+++ b/glib/glib.h
@@ -0,0 +1,674 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __G_LIB_H__
+#define __G_LIB_H__
+
+
+#include <glibconfig.h>
+
+#ifdef USE_DMALLOC
+#include "dmalloc.h"
+#endif
+
+
+/* glib provides definitions for the extrema of many
+ * of the standard types. These are:
+ * G_MINFLOAT
+ * G_MAXFLOAT
+ * G_MINDOUBLE
+ * G_MAXDOUBLE
+ * G_MINSHORT
+ * G_MAXSHORT
+ * G_MININT
+ * G_MAXINT
+ * G_MINLONG
+ * G_MAXLONG
+ */
+
+#ifdef HAVE_FLOAT_H
+
+#include <float.h>
+
+#define G_MINFLOAT FLT_MIN
+#define G_MAXFLOAT FLT_MAX
+#define G_MINDOUBLE DBL_MIN
+#define G_MAXDOUBLE DBL_MAX
+
+#elif HAVE_VALUES_H
+
+#include <values.h>
+
+#define G_MINFLOAT MINFLOAT
+#define G_MAXFLOAT MAXFLOAT
+#define G_MINDOUBLE MINDOUBLE
+#define G_MAXDOUBLE MAXDOUBLE
+
+#endif /* HAVE_VALUES_H */
+
+
+#ifdef HAVE_LIMITS_H
+
+#include <limits.h>
+
+#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
+
+#elif HAVE_VALUES_H
+
+#ifdef HAVE_FLOAT_H
+#include <values.h>
+#endif /* HAVE_FLOAT_H */
+
+#define G_MINSHORT MINSHORT
+#define G_MAXSHORT MAXSHORT
+#define G_MININT MININT
+#define G_MAXINT MAXINT
+#define G_MINLONG MINLONG
+#define G_MAXLONG MAXLONG
+
+#endif /* HAVE_VALUES_H */
+
+
+/* Provide definitions for some commonly used macros.
+ * These are only provided if they haven't already
+ * been defined. It is assumed that if they are already
+ * defined then the current definition is correct.
+ */
+
+#ifndef FALSE
+#define FALSE 0
+#endif /* FALSE */
+
+#ifndef TRUE
+#define TRUE 1
+#endif /* TRUE */
+
+#ifndef NULL
+#define NULL ((void*) 0)
+#endif /* NULL */
+
+#ifndef MAX
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#endif /* MAX */
+
+#ifndef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif /* MIN */
+
+#ifndef ABS
+#define ABS(a) (((a) < 0) ? -(a) : (a))
+#endif /* ABS */
+
+#ifndef CLAMP
+#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
+#endif /* CLAMP */
+
+#ifndef ATEXIT
+#define ATEXIT(proc) (atexit (proc))
+#endif /* ATEXIT */
+
+
+/* Provide macros for easily allocating memory. The macros
+ * will cast the allocated memory to the specified type
+ * in order to avoid compiler warnings. (Makes the code neater).
+ */
+
+#ifdef __DMALLOC_H__
+
+#define g_new(type,count) ALLOC(type,count)
+#define g_new0(type,count) CALLOC(type,count)
+
+#else /* __DMALLOC_H__ */
+
+#define g_new(type, count) \
+ ((type *) g_malloc ((unsigned) sizeof (type) * (count)))
+#define g_new0(type, count) \
+ ((type *) g_malloc0 ((unsigned) sizeof (type) * (count)))
+#endif /* __DMALLOC_H__ */
+
+#define g_chunk_new(type, chunk) \
+ ((type *) g_mem_chunk_alloc (chunk))
+
+
+/* Provide macros for error handling. The "assert" macros will
+ * exit on failur. The "return" macros will exit the current
+ * function. Two different definitions are given for the macros
+ * in order to support gcc's __PRETTY_FUNCTION__ capability.
+ */
+
+#define g_string(x) #x
+
+#ifdef __GNUC__
+
+#define g_assert(expr) \
+ if (!(expr)) \
+ g_error ("file %s: line %d (%s): \"%s\"", \
+ __FILE__, \
+ __LINE__, \
+ __PRETTY_FUNCTION__, \
+ #expr)
+
+#define g_assert_not_reached() \
+ g_error ("file %s: line %d (%s): \"should not be reached\"", \
+ __FILE__, \
+ __LINE__, \
+ __PRETTY_FUNCTION__)
+
+#define g_return_if_fail(expr) \
+ if (!(expr)) \
+ { \
+ g_warning ("file %s: line %d (%s): \"%s\"", \
+ __FILE__, \
+ __LINE__, \
+ __PRETTY_FUNCTION__, \
+ #expr); \
+ return; \
+ }
+
+#define g_return_val_if_fail(expr,val) \
+ if (!(expr)) \
+ { \
+ g_warning ("file %s: line %d (%s): \"%s\"", \
+ __FILE__, \
+ __LINE__, \
+ __PRETTY_FUNCTION__, \
+ #expr); \
+ return val; \
+ }
+
+#else /* __GNUC__ */
+
+#define g_assert(expr) \
+ if (!(expr)) \
+ g_error ("file %s: line %d: \"%s\"", \
+ __FILE__, \
+ __LINE__, \
+ #expr)
+
+#define g_assert_not_reached() \
+ g_error ("file %s: line %d: \"should not be reached\"", \
+ __FILE__, \
+ __LINE__)
+
+#define g_return_if_fail(expr) \
+ if (!(expr)) \
+ { \
+ g_warning ("file %s: line %d: \"%s\"", \
+ __FILE__, \
+ __LINE__, \
+ #expr); \
+ return; \
+ }
+
+#define g_return_val_if_fail(expr, val) \
+ if (!(expr)) \
+ { \
+ g_warning ("file %s: line %d: \"%s\"", \
+ __FILE__, \
+ __LINE__, \
+ #expr); \
+ return val; \
+ }
+
+#endif /* __GNUC__ */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* Provide type definitions for commonly used types.
+ * These are useful because a "gint8" can be adjusted
+ * to be 1 byte (8 bits) on all platforms. Similarly and
+ * more importantly, "gint32" can be adjusted to be
+ * 4 bytes (32 bits) on all platforms.
+ */
+
+typedef char gchar;
+typedef short gshort;
+typedef long glong;
+typedef int gint;
+typedef char gboolean;
+
+typedef unsigned char guchar;
+typedef unsigned short gushort;
+typedef unsigned long gulong;
+typedef unsigned int guint;
+
+typedef float gfloat;
+typedef double gdouble;
+
+#ifdef HAVE_LONG_DOUBLE
+typedef long double gldouble;
+#else /* HAVE_LONG_DOUBLE */
+typedef double gldouble;
+#endif /* HAVE_LONG_DOUBLE */
+
+typedef void* gpointer;
+
+#if (SIZEOF_CHAR == 1)
+typedef signed char gint8;
+typedef unsigned char guint8;
+#endif /* SIZEOF_CHAR */
+
+
+#if (SIZEOF_SHORT == 2)
+typedef signed short gint16;
+typedef unsigned short guint16;
+#endif /* SIZEOF_SHORT */
+
+
+#if (SIZEOF_INT == 4)
+typedef signed int gint32;
+typedef unsigned int guint32;
+#elif (SIZEOF_LONG == 4)
+typedef signed long gint32;
+typedef unsigned long guint32;
+#endif /* SIZEOF_INT */
+
+
+typedef struct _GList GList;
+typedef struct _GSList GSList;
+typedef struct _GHashTable GHashTable;
+typedef struct _GCache GCache;
+typedef struct _GTree GTree;
+typedef struct _GTimer GTimer;
+typedef struct _GMemChunk GMemChunk;
+typedef struct _GListAllocator GListAllocator;
+typedef struct _GStringChunk GStringChunk;
+typedef struct _GString GString;
+typedef struct _GArray GArray;
+
+typedef void (*GFunc) (gpointer data, gpointer user_data);
+typedef void (*GHFunc) (gpointer key, gpointer value, gpointer user_data);
+typedef guint (*GHashFunc) (gpointer key);
+typedef gint (*GCompareFunc) (gpointer a, gpointer b);
+typedef gpointer (*GCacheNewFunc) (gpointer key);
+typedef gpointer (*GCacheDupFunc) (gpointer value);
+typedef void (*GCacheDestroyFunc) (gpointer value);
+typedef gint (*GTraverseFunc) (gpointer key,
+ gpointer value,
+ gpointer data);
+typedef gint (*GSearchFunc) (gpointer key,
+ gpointer data);
+typedef void (*GErrorFunc) (gchar *str);
+typedef void (*GWarningFunc) (gchar *str);
+typedef void (*GPrintFunc) (gchar *str);
+
+
+struct _GList
+{
+ gpointer data;
+ GList *next;
+ GList *prev;
+};
+
+struct _GSList
+{
+ gpointer data;
+ GSList *next;
+};
+
+struct _GString
+{
+ gchar *str;
+ gint len;
+};
+
+struct _GArray
+{
+ gchar *data;
+ guint len;
+};
+
+struct _GHashTable { gint dummy; };
+struct _GCache { gint dummy; };
+struct _GTree { gint dummy; };
+struct _GTimer { gint dummy; };
+struct _GMemChunk { gint dummy; };
+struct _GListAllocator { gint dummy; };
+struct _GStringChunk { gint dummy; };
+
+typedef enum
+{
+ G_IN_ORDER,
+ G_PRE_ORDER,
+ G_POST_ORDER
+} GTraverseType;
+
+/* Doubly linked lists
+ */
+GList* g_list_alloc (void);
+void g_list_free (GList *list);
+void g_list_free_1 (GList *list);
+GList* g_list_append (GList *list,
+ gpointer data);
+GList* g_list_prepend (GList *list,
+ gpointer data);
+GList* g_list_insert (GList *list,
+ gpointer data,
+ gint position);
+GList* g_list_remove (GList *list,
+ gpointer data);
+GList* g_list_remove_link (GList *list,
+ GList *link);
+GList* g_list_reverse (GList *list);
+GList* g_list_nth (GList *list,
+ gint n);
+GList* g_list_find (GList *list,
+ gpointer data);
+GList* g_list_last (GList *list);
+GList* g_list_first (GList *list);
+gint g_list_length (GList *list);
+void g_list_foreach (GList *list,
+ GFunc func,
+ gpointer user_data);
+
+
+/* Singly linked lists
+ */
+GSList* g_slist_alloc (void);
+void g_slist_free (GSList *list);
+void g_slist_free_1 (GSList *list);
+GSList* g_slist_append (GSList *list,
+ gpointer data);
+GSList* g_slist_prepend (GSList *list,
+ gpointer data);
+GSList* g_slist_insert (GSList *list,
+ gpointer data,
+ gint position);
+GSList* g_slist_remove (GSList *list,
+ gpointer data);
+GSList* g_slist_remove_link (GSList *list,
+ GSList *link);
+GSList* g_slist_reverse (GSList *list);
+GSList* g_slist_nth (GSList *list,
+ gint n);
+GSList* g_slist_find (GSList *list,
+ gpointer data);
+GSList* g_slist_last (GSList *list);
+gint g_slist_length (GSList *list);
+void g_slist_foreach (GSList *list,
+ GFunc func,
+ gpointer user_data);
+
+
+/* List Allocators
+ */
+GListAllocator* g_list_allocator_new (void);
+void g_list_allocator_free (GListAllocator* allocator);
+GListAllocator* g_slist_set_allocator (GListAllocator* allocator);
+GListAllocator* g_list_set_allocator (GListAllocator* allocator);
+
+
+/* Hash tables
+ */
+GHashTable* g_hash_table_new (GHashFunc hash_func,
+ GCompareFunc key_compare_func);
+void g_hash_table_destroy (GHashTable *hash_table);
+void g_hash_table_insert (GHashTable *hash_table,
+ gpointer key,
+ gpointer value);
+void g_hash_table_remove (GHashTable *hash_table,
+ gpointer key);
+gpointer g_hash_table_lookup (GHashTable *hash_table,
+ const gpointer key);
+void g_hash_table_freeze (GHashTable *hash_table);
+void g_hash_table_thaw (GHashTable *hash_table);
+void g_hash_table_foreach (GHashTable *hash_table,
+ GHFunc func,
+ gpointer user_data);
+
+
+/* Caches
+ */
+GCache* g_cache_new (GCacheNewFunc value_new_func,
+ GCacheDestroyFunc value_destroy_func,
+ GCacheDupFunc key_dup_func,
+ GCacheDestroyFunc key_destroy_func,
+ GHashFunc hash_key_func,
+ GHashFunc hash_value_func,
+ GCompareFunc key_compare_func);
+void g_cache_destroy (GCache *cache);
+gpointer g_cache_insert (GCache *cache,
+ gpointer key);
+void g_cache_remove (GCache *cache,
+ gpointer value);
+void g_cache_key_foreach (GCache *cache,
+ GHFunc func,
+ gpointer user_data);
+void g_cache_value_foreach (GCache *cache,
+ GHFunc func,
+ gpointer user_data);
+
+
+/* Trees
+ */
+GTree* g_tree_new (GCompareFunc key_compare_func);
+void g_tree_destroy (GTree *tree);
+void g_tree_insert (GTree *tree,
+ gpointer key,
+ gpointer value);
+void g_tree_remove (GTree *tree,
+ gpointer key);
+gpointer g_tree_lookup (GTree *tree,
+ gpointer key);
+void g_tree_traverse (GTree *tree,
+ GTraverseFunc traverse_func,
+ GTraverseType traverse_type,
+ gpointer data);
+gpointer g_tree_search (GTree *tree,
+ GSearchFunc search_func,
+ gpointer data);
+gint g_tree_height (GTree *tree);
+gint g_tree_nnodes (GTree *tree);
+
+
+/* Memory
+ */
+
+#ifdef USE_DMALLOC
+
+#define g_malloc(size) (gpointer) MALLOC(size)
+#define g_malloc0(size) (gpointer) CALLOC(char,size)
+#define g_realloc(mem,size) (gpointer) REALLOC(mem,char,size)
+#define g_free(mem) FREE(mem)
+
+#else /* USE_DMALLOC */
+
+gpointer g_malloc (gulong size);
+gpointer g_malloc0 (gulong size);
+gpointer g_realloc (gpointer mem,
+ gulong size);
+void g_free (gpointer mem);
+
+#endif /* USE_DMALLOC */
+
+void g_mem_profile (void);
+void g_mem_check (gpointer mem);
+
+
+/* "g_mem_chunk_new" creates a new memory chunk.
+ * Memory chunks are used to allocate pieces of memory which are
+ * always the same size. Lists are a good example of such a data type.
+ * The memory chunk allocates and frees blocks of memory as needed.
+ * Just be sure to call "g_mem_chunk_free" and not "g_free" on data
+ * allocated in a mem chunk. ("g_free" will most likely cause a seg
+ * fault...somewhere).
+ *
+ * Oh yeah, GMemChunk is an opaque data type. (You don't really
+ * want to know what's going on inside do you?)
+ */
+
+/* ALLOC_ONLY MemChunk's can only allocate memory. The free operation
+ * is interpreted as a no op. ALLOC_ONLY MemChunk's save 4 bytes per
+ * atom. (They are also useful for lists which use MemChunk to allocate
+ * memory but are also part of the MemChunk implementation).
+ * ALLOC_AND_FREE MemChunk's can allocate and free memory.
+ */
+
+#define G_ALLOC_ONLY 1
+#define G_ALLOC_AND_FREE 2
+
+GMemChunk* g_mem_chunk_new (gchar *name,
+ gint atom_size,
+ gulong area_size,
+ gint type);
+void g_mem_chunk_destroy (GMemChunk *mem_chunk);
+gpointer g_mem_chunk_alloc (GMemChunk *mem_chunk);
+void g_mem_chunk_free (GMemChunk *mem_chunk,
+ gpointer mem);
+void g_mem_chunk_clean (GMemChunk *mem_chunk);
+void g_mem_chunk_reset (GMemChunk *mem_chunk);
+void g_mem_chunk_print (GMemChunk *mem_chunk);
+void g_mem_chunk_info (void);
+
+/* Ah yes...we have a "g_blow_chunks" function.
+ * "g_blow_chunks" simply compresses all the chunks. This operation
+ * consists of freeing every memory area that should be freed (but
+ * which we haven't gotten around to doing yet). And, no,
+ * "g_blow_chunks" doesn't follow the naming scheme, but it is a
+ * much better name than "g_mem_chunk_clean_all" or something
+ * similar.
+ */
+void g_blow_chunks (void);
+
+
+/* Timer
+ */
+GTimer* g_timer_new (void);
+void g_timer_destroy (GTimer *timer);
+void g_timer_start (GTimer *timer);
+void g_timer_stop (GTimer *timer);
+void g_timer_reset (GTimer *timer);
+gdouble g_timer_elapsed (GTimer *timer,
+ gulong *microseconds);
+
+
+/* Output
+ */
+#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
+void g_error (gchar *format, ...) __attribute__ ((format (printf, 1, 2)));
+void g_warning (gchar *format, ...) __attribute__ ((format (printf, 1, 2)));
+void g_message (gchar *format, ...) __attribute__ ((format (printf, 1, 2)));
+void g_print (gchar *format, ...) __attribute__ ((format (printf, 1, 2)));
+#else
+void g_error (gchar *format, ...);
+void g_warning (gchar *format, ...);
+void g_message (gchar *format, ...);
+void g_print (gchar *format, ...);
+#endif
+
+/* Utility functions
+ */
+gchar* g_strdup (const gchar *str);
+gchar* g_strerror (gint errnum);
+gchar* g_strsignal (gint signum);
+
+
+/* Errors
+ */
+GErrorFunc g_set_error_handler (GErrorFunc func);
+GWarningFunc g_set_warning_handler (GWarningFunc func);
+GPrintFunc g_set_message_handler (GPrintFunc func);
+GPrintFunc g_set_print_handler (GPrintFunc func);
+
+void g_debug (char *progname);
+void g_attach_process (char *progname, int query);
+void g_stack_trace (char *progname, int query);
+
+
+/* String Chunks
+ */
+GStringChunk* g_string_chunk_new (gint size);
+void g_string_chunk_free (GStringChunk *chunk);
+gchar* g_string_chunk_insert (GStringChunk *chunk,
+ gchar* string);
+gchar* g_string_chunk_insert_const (GStringChunk *chunk,
+ gchar* string);
+
+/* Strings
+ */
+GString* g_string_new (gchar *init);
+void g_string_free (GString *string,
+ gint free_segment);
+GString* g_string_assign (GString *lval,
+ gchar *rval);
+GString* g_string_truncate (GString *string,
+ gint len);
+GString* g_string_append (GString *string,
+ gchar *val);
+GString* g_string_append_c (GString *string,
+ gchar c);
+GString* g_string_prepend (GString *string,
+ gchar *val);
+GString* g_string_prepend_c (GString *string,
+ gchar c);
+void g_string_sprintf (GString *string,
+ gchar *fmt,
+ ...);
+void g_string_sprintfa (GString *string,
+ gchar *fmt,
+ ...);
+
+/* Resizable arrays
+ */
+#define g_array_append_val(array,type,val) \
+ g_rarray_append (array, (gpointer) &val, sizeof (type))
+#define g_array_append_vals(array,type,vals,nvals) \
+ g_rarray_append (array, (gpointer) vals, sizeof (type) * nvals)
+#define g_array_prepend_val(array,type,val) \
+ g_rarray_prepend (array, (gpointer) &val, sizeof (type))
+#define g_array_prepend_vals(array,type,vals,nvals) \
+ g_rarray_prepend (array, (gpointer) vals, sizeof (type) * nvals)
+#define g_array_truncate(array,type,length) \
+ g_rarray_truncate (array, length, sizeof (type))
+#define g_array_index(array,type,index) \
+ ((type*) array->data)[index]
+
+GArray* g_array_new (gint zero_terminated);
+void g_array_free (GArray *array,
+ gint free_segment);
+GArray* g_rarray_append (GArray *array,
+ gpointer data,
+ gint size);
+GArray* g_rarray_prepend (GArray *array,
+ gpointer data,
+ gint size);
+GArray* g_rarray_truncate (GArray *array,
+ gint length,
+ gint size);
+
+
+/* Hash Functions
+ */
+gint g_string_equal (gpointer v,
+ gpointer v2);
+guint g_string_hash (gpointer v);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __G_LIB_H__ */
diff --git a/glib/glibconfig.h.in b/glib/glibconfig.h.in
new file mode 100644
index 000000000..7a7655952
--- /dev/null
+++ b/glib/glibconfig.h.in
@@ -0,0 +1,67 @@
+/* glibconfig.h.in. Generated automatically from configure.in by autoheader. */
+
+/* Define to empty if the keyword does not work. */
+#undef const
+
+/* Define if you don't have vprintf but do have _doprnt. */
+#undef HAVE_DOPRNT
+
+/* Define if the `long double' type works. */
+#undef HAVE_LONG_DOUBLE
+
+/* Define if you have the vprintf function. */
+#undef HAVE_VPRINTF
+
+/* Define as __inline if that's what the C compiler calls it. */
+#undef inline
+
+/* Define if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Other stuff */
+#undef HAVE_DOPRNT
+#undef HAVE_FLOAT_H
+#undef HAVE_LIMITS_H
+#undef HAVE_LONG_DOUBLE
+#undef HAVE_SYS_SELECT_H
+#undef HAVE_STRERROR
+#undef HAVE_STRSIGNAL
+#undef HAVE_VALUES_H
+#undef HAVE_VPRINTF
+
+#undef NO_FD_SET
+#undef NO_SYS_ERRLIST
+#undef NO_SYS_SIGLIST
+
+/* #undef PACKAGE */
+/* #undef VERSION */
+
+/* The number of bytes in a char. */
+#undef SIZEOF_CHAR
+
+/* The number of bytes in a int. */
+#undef SIZEOF_INT
+
+/* The number of bytes in a long. */
+#undef SIZEOF_LONG
+
+/* The number of bytes in a short. */
+#undef SIZEOF_SHORT
+
+/* The number of bytes in a void *. */
+#undef SIZEOF_VOID_P
+
+/* Define if you have the strerror function. */
+#undef HAVE_STRERROR
+
+/* Define if you have the strsignal function. */
+#undef HAVE_STRSIGNAL
+
+/* Define if you have the <float.h> header file. */
+#undef HAVE_FLOAT_H
+
+/* Define if you have the <limits.h> header file. */
+#undef HAVE_LIMITS_H
+
+/* Define if you have the <values.h> header file. */
+#undef HAVE_VALUES_H
diff --git a/glib/glist.c b/glib/glist.c
new file mode 100644
index 000000000..f5a31d743
--- /dev/null
+++ b/glib/glist.c
@@ -0,0 +1,349 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "glib.h"
+
+
+typedef struct _GRealListAllocator GRealListAllocator;
+
+struct _GRealListAllocator
+{
+ GMemChunk *list_mem_chunk;
+ GList *free_list;
+};
+
+
+static GRealListAllocator *default_allocator = NULL;
+static GRealListAllocator *current_allocator = NULL;
+
+
+GListAllocator*
+g_list_allocator_new ()
+{
+ GRealListAllocator* allocator = g_new (GRealListAllocator, 1);
+
+ allocator->list_mem_chunk = NULL;
+ allocator->free_list = NULL;
+
+ return (GListAllocator*) allocator;
+}
+
+void
+g_list_allocator_free (GListAllocator* fallocator)
+{
+ GRealListAllocator* allocator = (GRealListAllocator *) fallocator;
+
+ if (allocator && allocator->list_mem_chunk)
+ g_mem_chunk_destroy (allocator->list_mem_chunk);
+ if (allocator)
+ g_free (allocator);
+}
+
+GListAllocator*
+g_list_set_allocator (GListAllocator* fallocator)
+{
+ GRealListAllocator* allocator = (GRealListAllocator *) fallocator;
+ GRealListAllocator* old_allocator = current_allocator;
+
+ if (allocator)
+ current_allocator = allocator;
+ else
+ {
+ if (!default_allocator)
+ default_allocator = (GRealListAllocator*) g_list_allocator_new ();
+ current_allocator = default_allocator;
+ }
+
+ if (!current_allocator->list_mem_chunk)
+ current_allocator->list_mem_chunk = g_mem_chunk_new ("list mem chunk",
+ sizeof (GList),
+ 1024,
+ G_ALLOC_ONLY);
+
+ return (GListAllocator*) (old_allocator == default_allocator ? NULL : old_allocator);
+}
+
+
+GList*
+g_list_alloc ()
+{
+ GList *new_list;
+
+ g_list_set_allocator (NULL);
+ if (current_allocator->free_list)
+ {
+ new_list = current_allocator->free_list;
+ current_allocator->free_list = current_allocator->free_list->next;
+ }
+ else
+ {
+ new_list = g_chunk_new (GList, current_allocator->list_mem_chunk);
+ }
+
+ new_list->data = NULL;
+ new_list->next = NULL;
+ new_list->prev = NULL;
+
+ return new_list;
+}
+
+void
+g_list_free (GList *list)
+{
+ GList *last;
+
+ if (list)
+ {
+ last = g_list_last (list);
+ last->next = current_allocator->free_list;
+ current_allocator->free_list = list;
+ }
+}
+
+void
+g_list_free_1 (GList *list)
+{
+ if (list)
+ {
+ list->next = current_allocator->free_list;
+ current_allocator->free_list = list;
+ }
+}
+
+GList*
+g_list_append (GList *list,
+ gpointer data)
+{
+ GList *new_list;
+ GList *last;
+
+ new_list = g_list_alloc ();
+ new_list->data = data;
+
+ if (!list)
+ {
+ list = new_list;
+ }
+ else
+ {
+ last = g_list_last (list);
+ g_assert (last != NULL);
+ last->next = new_list;
+ new_list->prev = last;
+ }
+
+ return list;
+}
+
+GList*
+g_list_prepend (GList *list,
+ gpointer data)
+{
+ GList *new_list;
+
+ new_list = g_list_alloc ();
+ new_list->data = data;
+
+ if (list)
+ {
+ if (list->prev)
+ list->prev->next = new_list;
+ new_list->prev = list->prev;
+ list->prev = new_list;
+ }
+ new_list->next = list;
+
+ return new_list;
+}
+
+GList*
+g_list_insert (GList *list,
+ gpointer data,
+ gint position)
+{
+ GList *new_list;
+ GList *tmp_list;
+
+ if (position < 0)
+ return g_list_append (list, data);
+ else if (position == 0)
+ return g_list_prepend (list, data);
+
+ tmp_list = g_list_nth (list, position);
+ if (!tmp_list)
+ return g_list_append (list, data);
+
+ new_list = g_list_alloc ();
+ new_list->data = data;
+
+ if (tmp_list->prev)
+ tmp_list->prev->next = new_list;
+ new_list->next = tmp_list;
+ new_list->prev = tmp_list->prev;
+ tmp_list->prev = new_list;
+
+ if (tmp_list == list)
+ list = new_list;
+
+ return list;
+}
+
+GList*
+g_list_remove (GList *list,
+ gpointer data)
+{
+ GList *tmp;
+
+ tmp = list;
+ while (tmp)
+ {
+ if (tmp->data == data)
+ {
+ if (tmp->prev)
+ tmp->prev->next = tmp->next;
+ if (tmp->next)
+ tmp->next->prev = tmp->prev;
+
+ if (list == tmp)
+ list = list->next;
+
+ tmp->next = NULL;
+ tmp->prev = NULL;
+ g_list_free (tmp);
+
+ break;
+ }
+
+ tmp = tmp->next;
+ }
+ return list;
+}
+
+GList*
+g_list_remove_link (GList *list,
+ GList *link)
+{
+ if (link)
+ {
+ if (link->prev)
+ link->prev->next = link->next;
+ if (link->next)
+ link->next->prev = link->prev;
+
+ if (link == list)
+ list = list->next;
+
+ link->next = NULL;
+ link->prev = NULL;
+ }
+
+ return list;
+}
+
+GList*
+g_list_reverse (GList *list)
+{
+ GList *tmp;
+ GList *last;
+
+ last = NULL;
+ while (list)
+ {
+ last = list;
+ tmp = list->next;
+ list->next = list->prev;
+ list->prev = tmp;
+ list = tmp;
+ }
+
+ return last;
+}
+
+GList*
+g_list_nth (GList *list,
+ gint n)
+{
+ while ((n-- > 0) && list)
+ list = list->next;
+
+ return list;
+}
+
+GList*
+g_list_find (GList *list,
+ gpointer data)
+{
+ while (list)
+ {
+ if (list->data == data)
+ break;
+ list = list->next;
+ }
+
+ return list;
+}
+
+GList*
+g_list_last (GList *list)
+{
+ if (list)
+ {
+ while (list->next)
+ list = list->next;
+ }
+
+ return list;
+}
+
+GList*
+g_list_first (GList *list)
+{
+ if (list)
+ {
+ while (list->prev)
+ list = list->prev;
+ }
+
+ return list;
+}
+
+gint
+g_list_length (GList *list)
+{
+ gint length;
+
+ length = 0;
+ while (list)
+ {
+ length++;
+ list = list->next;
+ }
+
+ return length;
+}
+
+void
+g_list_foreach (GList *list,
+ GFunc func,
+ gpointer user_data)
+{
+ while (list)
+ {
+ (*func) (list->data, user_data);
+ list = list->next;
+ }
+}
diff --git a/glib/gmem.c b/glib/gmem.c
new file mode 100644
index 000000000..35dfdaba3
--- /dev/null
+++ b/glib/gmem.c
@@ -0,0 +1,824 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <string.h>
+#include "glib.h"
+
+
+/* #define MEM_PROFILE */
+/* #define MEM_CHECK */
+
+
+#define MAX_MEM_AREA 65536L
+#define MEM_AREA_SIZE 4L
+
+#if SIZEOF_VOID_P > SIZEOF_LONG
+#define MEM_ALIGN SIZEOF_VOID_P
+#else
+#define MEM_ALIGN SIZEOF_LONG
+#endif
+
+
+typedef struct _GFreeAtom GFreeAtom;
+typedef struct _GMemArea GMemArea;
+typedef struct _GRealMemChunk GRealMemChunk;
+
+struct _GFreeAtom
+{
+ GFreeAtom *next;
+};
+
+struct _GMemArea
+{
+ GMemArea *next; /* the next mem area */
+ GMemArea *prev; /* the previous mem area */
+ gulong index; /* the current index into the "mem" array */
+ gulong free; /* the number of free bytes in this mem area */
+ gulong allocated; /* the number of atoms allocated from this area */
+ gulong mark; /* is this mem area marked for deletion */
+ gchar mem[MEM_AREA_SIZE]; /* the mem array from which atoms get allocated
+ * the actual size of this array is determined by
+ * the mem chunk "area_size". ANSI says that it
+ * must be declared to be the maximum size it
+ * can possibly be (even though the actual size
+ * may be less).
+ */
+};
+
+struct _GRealMemChunk
+{
+ gchar *name; /* name of this MemChunk...used for debugging output */
+ gint type; /* the type of MemChunk: ALLOC_ONLY or ALLOC_AND_FREE */
+ gint num_mem_areas; /* the number of memory areas */
+ gint num_marked_areas; /* the number of areas marked for deletion */
+ guint atom_size; /* the size of an atom */
+ gulong area_size; /* the size of a memory area */
+ GMemArea *mem_area; /* the current memory area */
+ GMemArea *mem_areas; /* a list of all the mem areas owned by this chunk */
+ GMemArea *free_mem_area; /* the free area...which is about to be destroyed */
+ GFreeAtom *free_atoms; /* the free atoms list */
+ GTree *mem_tree; /* tree of mem areas sorted by memory address */
+ GRealMemChunk *next; /* pointer to the next chunk */
+ GRealMemChunk *prev; /* pointer to the previous chunk */
+};
+
+
+static gulong g_mem_chunk_compute_size (gulong size);
+static gint g_mem_chunk_area_compare (GMemArea *a,
+ GMemArea *b);
+static gint g_mem_chunk_area_search (GMemArea *a,
+ gchar *addr);
+
+
+static GRealMemChunk *mem_chunks = NULL;
+
+#ifdef MEM_PROFILE
+static gulong allocations[4096] = { 0 };
+static gulong allocated_mem = 0;
+static gulong freed_mem = 0;
+#endif /* MEM_PROFILE */
+
+
+#ifndef USE_DMALLOC
+
+gpointer
+g_malloc (gulong size)
+{
+ gpointer p;
+
+
+#if defined(MEM_PROFILE) || defined(MEM_CHECK)
+ gulong *t;
+#endif /* MEM_PROFILE || MEM_CHECK */
+
+
+ if (size == 0)
+ return NULL;
+
+
+#if defined(MEM_PROFILE) || defined(MEM_CHECK)
+ size += SIZEOF_LONG;
+#endif /* MEM_PROFILE || MEM_CHECK */
+
+#ifdef MEM_CHECK
+ size += SIZEOF_LONG;
+#endif /* MEM_CHECK */
+
+
+ p = (gpointer) malloc (size);
+ if (!p)
+ g_error ("could not allocate %ld bytes", size);
+
+
+#ifdef MEM_CHECK
+ size -= SIZEOF_LONG;
+
+ t = p;
+ p = ((guchar*) p + SIZEOF_LONG);
+ *t = 0;
+#endif /* MEM_CHECK */
+
+#if defined(MEM_PROFILE) || defined(MEM_CHECK)
+ size -= SIZEOF_LONG;
+
+ t = p;
+ p = ((guchar*) p + SIZEOF_LONG);
+ *t = size;
+
+#ifdef MEM_PROFILE
+ if (size <= 4095)
+ allocations[size-1] += 1;
+ else
+ allocations[4095] += 1;
+ allocated_mem += size;
+#endif /* MEM_PROFILE */
+#endif /* MEM_PROFILE || MEM_CHECK */
+
+
+ return p;
+}
+
+gpointer
+g_malloc0 (gulong size)
+{
+ gpointer p;
+
+
+#if defined(MEM_PROFILE) || defined(MEM_CHECK)
+ gulong *t;
+#endif /* MEM_PROFILE || MEM_CHECK */
+
+
+ if (size == 0)
+ return NULL;
+
+
+#ifdef MEM_PROFILE
+ size += SIZEOF_LONG;
+#endif /* MEM_PROFILE */
+
+#ifdef MEM_CHECK
+ size += SIZEOF_LONG;
+#endif /* MEM_CHECK */
+
+
+ p = (gpointer) calloc (size, 1);
+ if (!p)
+ g_error ("could not allocate %ld bytes", size);
+
+
+#ifdef MEM_CHECK
+ size -= SIZEOF_LONG;
+
+ t = p;
+ p = ((guchar*) p + SIZEOF_LONG);
+ *t = 0;
+#endif /* MEM_CHECK */
+
+#if defined(MEM_PROFILE) || defined(MEM_CHECK)
+ size -= SIZEOF_LONG;
+
+ t = p;
+ p = ((guchar*) p + SIZEOF_LONG);
+ *t = size;
+
+#ifdef MEM_PROFILE
+ if (size <= 4095)
+ allocations[size-1] += 1;
+ else
+ allocations[4095] += 1;
+ allocated_mem += size;
+#endif /* MEM_PROFILE */
+#endif /* MEM_PROFILE */
+
+
+ return p;
+}
+
+gpointer
+g_realloc (gpointer mem,
+ gulong size)
+{
+ gpointer p;
+
+#if defined(MEM_PROFILE) || defined(MEM_CHECK)
+ gulong *t;
+#endif /* MEM_PROFILE || MEM_CHECK */
+
+
+ if (size == 0)
+ return NULL;
+
+
+#if defined(MEM_PROFILE) || defined(MEM_CHECK)
+ size += SIZEOF_LONG;
+#endif /* MEM_PROFILE || MEM_CHECK */
+
+#ifdef MEM_CHECK
+ size += SIZEOF_LONG;
+#endif /* MEM_CHECK */
+
+
+ if (!mem)
+ p = (gpointer) malloc (size);
+ else
+ {
+#if defined(MEM_PROFILE) || defined(MEM_CHECK)
+ t = (gulong*) ((guchar*) mem - SIZEOF_LONG);
+#ifdef MEM_PROFILE
+ freed_mem += *t;
+#endif /* MEM_PROFILE */
+ mem = t;
+#endif /* MEM_PROFILE || MEM_CHECK */
+
+#ifdef MEM_CHECK
+ t = (gulong*) ((guchar*) mem - SIZEOF_LONG);
+ if (*t >= 1)
+ g_warning ("trying to realloc freed memory\n");
+ mem = t;
+#endif /* MEM_CHECK */
+
+ p = (gpointer) realloc (mem, size);
+ }
+
+ if (!p)
+ g_error ("could not reallocate %ld bytes", size);
+
+
+#ifdef MEM_CHECK
+ size -= SIZEOF_LONG;
+
+ t = p;
+ p = ((guchar*) p + SIZEOF_LONG);
+ *t = 0;
+#endif /* MEM_CHECK */
+
+#if defined(MEM_PROFILE) || defined(MEM_CHECK)
+ size -= SIZEOF_LONG;
+
+ t = p;
+ p = ((guchar*) p + SIZEOF_LONG);
+ *t = size;
+
+#ifdef MEM_PROFILE
+ if (size <= 4095)
+ allocations[size-1] += 1;
+ else
+ allocations[4095] += 1;
+ allocated_mem += size;
+#endif /* MEM_PROFILE */
+#endif /* MEM_PROFILE || MEM_CHECK */
+
+
+ return p;
+}
+
+void
+g_free (gpointer mem)
+{
+ if (mem)
+ {
+#if defined(MEM_PROFILE) || defined(MEM_CHECK)
+ gulong *t;
+ gulong size;
+#endif /* MEM_PROFILE || MEM_CHECK */
+
+#if defined(MEM_PROFILE) || defined(MEM_CHECK)
+ t = (gulong*) ((guchar*) mem - SIZEOF_LONG);
+ size = *t;
+#ifdef MEM_PROFILE
+ freed_mem += size;
+#endif /* MEM_PROFILE */
+ mem = t;
+#endif /* MEM_PROFILE || MEM_CHECK */
+
+#ifdef MEM_CHECK
+ t = (gulong*) ((guchar*) mem - SIZEOF_LONG);
+ if (*t >= 1)
+ g_warning ("freeing previously freed memory\n");
+ *t += 1;
+ mem = t;
+
+ memset ((guchar*) mem + 8, 0, size);
+#else /* MEM_CHECK */
+ free (mem);
+#endif /* MEM_CHECK */
+ }
+}
+
+#endif /* ! USE_DMALLOC */
+
+
+void
+g_mem_profile ()
+{
+#ifdef MEM_PROFILE
+ gint i;
+
+ for (i = 0; i < 4095; i++)
+ if (allocations[i] > 0)
+ g_print ("%lu allocations of %d bytes\n", allocations[i], i + 1);
+
+ if (allocations[4095] > 0)
+ g_print ("%lu allocations of greater than 4095 bytes\n", allocations[4095]);
+ g_print ("%lu bytes allocated\n", allocated_mem);
+ g_print ("%lu bytes freed\n", freed_mem);
+ g_print ("%lu bytes in use\n", allocated_mem - freed_mem);
+#endif /* MEM_PROFILE */
+}
+
+void
+g_mem_check (gpointer mem)
+{
+#ifdef MEM_CHECK
+ gulong *t;
+
+ t = (gulong*) ((guchar*) mem - SIZEOF_LONG - SIZEOF_LONG);
+
+ if (*t >= 1)
+ g_warning ("mem: 0x%08x has been freed: %lu\n", (gulong) mem, *t);
+#endif /* MEM_CHECK */
+}
+
+GMemChunk*
+g_mem_chunk_new (gchar *name,
+ gint atom_size,
+ gulong area_size,
+ gint type)
+{
+ GRealMemChunk *mem_chunk;
+ gulong rarea_size;
+
+ mem_chunk = g_new (struct _GRealMemChunk, 1);
+ mem_chunk->name = name;
+ mem_chunk->type = type;
+ mem_chunk->num_mem_areas = 0;
+ mem_chunk->num_marked_areas = 0;
+ mem_chunk->mem_area = NULL;
+ mem_chunk->free_mem_area = NULL;
+ mem_chunk->free_atoms = NULL;
+ mem_chunk->mem_tree = NULL;
+ mem_chunk->mem_areas = NULL;
+ mem_chunk->atom_size = atom_size;
+
+ if (mem_chunk->type == G_ALLOC_AND_FREE)
+ mem_chunk->mem_tree = g_tree_new ((GCompareFunc) g_mem_chunk_area_compare);
+
+ if (mem_chunk->atom_size % MEM_ALIGN)
+ mem_chunk->atom_size += MEM_ALIGN - (mem_chunk->atom_size % MEM_ALIGN);
+
+ mem_chunk->area_size = area_size;
+ if (mem_chunk->area_size > MAX_MEM_AREA)
+ mem_chunk->area_size = MAX_MEM_AREA;
+ while (mem_chunk->area_size < mem_chunk->atom_size)
+ mem_chunk->area_size *= 2;
+
+ rarea_size = mem_chunk->area_size + sizeof (GMemArea) - MEM_AREA_SIZE;
+ rarea_size = g_mem_chunk_compute_size (rarea_size);
+ mem_chunk->area_size = rarea_size - (sizeof (GMemArea) - MEM_AREA_SIZE);
+
+ /*
+ mem_chunk->area_size -= (sizeof (GMemArea) - MEM_AREA_SIZE);
+ if (mem_chunk->area_size < mem_chunk->atom_size)
+ {
+ mem_chunk->area_size = (mem_chunk->area_size + sizeof (GMemArea) - MEM_AREA_SIZE) * 2;
+ mem_chunk->area_size -= (sizeof (GMemArea) - MEM_AREA_SIZE);
+ }
+
+ if (mem_chunk->area_size % mem_chunk->atom_size)
+ mem_chunk->area_size += mem_chunk->atom_size - (mem_chunk->area_size % mem_chunk->atom_size);
+ */
+
+ mem_chunk->next = mem_chunks;
+ mem_chunk->prev = NULL;
+ if (mem_chunks)
+ mem_chunks->prev = mem_chunk;
+ mem_chunks = mem_chunk;
+
+ return ((GMemChunk*) mem_chunk);
+}
+
+void
+g_mem_chunk_destroy (GMemChunk *mem_chunk)
+{
+ GRealMemChunk *rmem_chunk;
+ GMemArea *mem_areas;
+ GMemArea *temp_area;
+
+ g_assert (mem_chunk != NULL);
+
+ rmem_chunk = (GRealMemChunk*) mem_chunk;
+
+ mem_areas = rmem_chunk->mem_areas;
+ while (mem_areas)
+ {
+ temp_area = mem_areas;
+ mem_areas = mem_areas->next;
+ g_free (temp_area);
+ }
+
+ if (rmem_chunk->next)
+ rmem_chunk->next->prev = rmem_chunk->prev;
+ if (rmem_chunk->prev)
+ rmem_chunk->prev->next = rmem_chunk->next;
+
+ if (rmem_chunk == mem_chunks)
+ mem_chunks = mem_chunks->next;
+
+ if (rmem_chunk->type == G_ALLOC_AND_FREE)
+ g_tree_destroy (rmem_chunk->mem_tree);
+
+ g_free (rmem_chunk);
+}
+
+gpointer
+g_mem_chunk_alloc (GMemChunk *mem_chunk)
+{
+ GRealMemChunk *rmem_chunk;
+ GMemArea *temp_area;
+ gpointer mem;
+
+ g_assert (mem_chunk != NULL);
+
+ rmem_chunk = (GRealMemChunk*) mem_chunk;
+
+ while (rmem_chunk->free_atoms)
+ {
+ /* Get the first piece of memory on the "free_atoms" list.
+ * We can go ahead and destroy the list node we used to keep
+ * track of it with and to update the "free_atoms" list to
+ * point to its next element.
+ */
+ mem = rmem_chunk->free_atoms;
+ rmem_chunk->free_atoms = rmem_chunk->free_atoms->next;
+
+ /* Determine which area this piece of memory is allocated from */
+ temp_area = g_tree_search (rmem_chunk->mem_tree,
+ (GSearchFunc) g_mem_chunk_area_search,
+ mem);
+
+ /* If the area has been marked, then it is being destroyed.
+ * (ie marked to be destroyed).
+ * We check to see if all of the segments on the free list that
+ * reference this area have been removed. This occurs when
+ * the ammount of free memory is less than the allocatable size.
+ * If the chunk should be freed, then we place it in the "free_mem_area".
+ * This is so we make sure not to free the mem area here and then
+ * allocate it again a few lines down.
+ * If we don't allocate a chunk a few lines down then the "free_mem_area"
+ * will be freed.
+ * If there is already a "free_mem_area" then we'll just free this mem area.
+ */
+ if (temp_area->mark)
+ {
+ /* Update the "free" memory available in that area */
+ temp_area->free += rmem_chunk->atom_size;
+
+ if (temp_area->free == rmem_chunk->area_size)
+ {
+ if (temp_area == rmem_chunk->mem_area)
+ rmem_chunk->mem_area = NULL;
+
+ if (rmem_chunk->free_mem_area)
+ {
+ rmem_chunk->num_mem_areas -= 1;
+ rmem_chunk->num_marked_areas -= 1;
+
+ if (temp_area->next)
+ temp_area->next->prev = temp_area->prev;
+ if (temp_area->prev)
+ temp_area->prev->next = temp_area->next;
+ if (temp_area == rmem_chunk->mem_areas)
+ rmem_chunk->mem_areas = rmem_chunk->mem_areas->next;
+ if (temp_area == rmem_chunk->mem_area)
+ rmem_chunk->mem_area = NULL;
+
+ g_free (temp_area);
+ }
+ else
+ rmem_chunk->free_mem_area = temp_area;
+ }
+ }
+ else
+ {
+ /* Update the number of allocated atoms count.
+ */
+ temp_area->allocated += 1;
+
+ /* The area wasn't marked...return the memory
+ */
+ goto outa_here;
+ }
+ }
+
+ /* If there isn't a current mem area or the current mem area is out of space
+ * then allocate a new mem area. We'll first check and see if we can use
+ * the "free_mem_area". Otherwise we'll just malloc the mem area.
+ */
+ if ((!rmem_chunk->mem_area) ||
+ ((rmem_chunk->mem_area->index + rmem_chunk->atom_size) > rmem_chunk->area_size))
+ {
+ if (rmem_chunk->free_mem_area)
+ {
+ rmem_chunk->mem_area = rmem_chunk->free_mem_area;
+ rmem_chunk->free_mem_area = NULL;
+ }
+ else
+ {
+ rmem_chunk->mem_area = (GMemArea*) g_malloc (sizeof (GMemArea) -
+ MEM_AREA_SIZE +
+ rmem_chunk->area_size);
+
+ rmem_chunk->num_mem_areas += 1;
+ rmem_chunk->mem_area->next = rmem_chunk->mem_areas;
+ rmem_chunk->mem_area->prev = NULL;
+
+ if (rmem_chunk->mem_areas)
+ rmem_chunk->mem_areas->prev = rmem_chunk->mem_area;
+ rmem_chunk->mem_areas = rmem_chunk->mem_area;
+
+ if (rmem_chunk->type == G_ALLOC_AND_FREE)
+ g_tree_insert (rmem_chunk->mem_tree, rmem_chunk->mem_area, rmem_chunk->mem_area);
+ }
+
+ rmem_chunk->mem_area->index = 0;
+ rmem_chunk->mem_area->free = rmem_chunk->area_size;
+ rmem_chunk->mem_area->allocated = 0;
+ rmem_chunk->mem_area->mark = 0;
+ }
+ else if (rmem_chunk->free_mem_area)
+ {
+ rmem_chunk->num_mem_areas -= 1;
+
+ if (rmem_chunk->free_mem_area->next)
+ rmem_chunk->free_mem_area->next->prev = rmem_chunk->free_mem_area->prev;
+ if (rmem_chunk->free_mem_area->prev)
+ rmem_chunk->free_mem_area->prev->next = rmem_chunk->free_mem_area->next;
+ if (rmem_chunk->free_mem_area == rmem_chunk->mem_areas)
+ rmem_chunk->mem_areas = rmem_chunk->mem_areas->next;
+
+ if (rmem_chunk->type == G_ALLOC_AND_FREE)
+ g_tree_remove (rmem_chunk->mem_tree, rmem_chunk->free_mem_area);
+
+ g_free (rmem_chunk->free_mem_area);
+ rmem_chunk->free_mem_area = NULL;
+ }
+
+ /* Get the memory and modify the state variables appropriately.
+ */
+ mem = (gpointer) &rmem_chunk->mem_area->mem[rmem_chunk->mem_area->index];
+ rmem_chunk->mem_area->index += rmem_chunk->atom_size;
+ rmem_chunk->mem_area->free -= rmem_chunk->atom_size;
+ rmem_chunk->mem_area->allocated += 1;
+
+outa_here:
+ return mem;
+}
+
+void
+g_mem_chunk_free (GMemChunk *mem_chunk,
+ gpointer mem)
+{
+ GRealMemChunk *rmem_chunk;
+ GMemArea *temp_area;
+ GFreeAtom *free_atom;
+
+ g_assert (mem_chunk != NULL);
+ g_assert (mem != NULL);
+
+ rmem_chunk = (GRealMemChunk*) mem_chunk;
+
+ /* Don't do anything if this is an ALLOC_ONLY chunk
+ */
+ if (rmem_chunk->type == G_ALLOC_AND_FREE)
+ {
+ /* Place the memory on the "free_atoms" list
+ */
+ free_atom = (GFreeAtom*) mem;
+ free_atom->next = rmem_chunk->free_atoms;
+ rmem_chunk->free_atoms = free_atom;
+
+ temp_area = g_tree_search (rmem_chunk->mem_tree,
+ (GSearchFunc) g_mem_chunk_area_search,
+ mem);
+
+ temp_area->allocated -= 1;
+
+ if (temp_area->allocated == 0)
+ {
+ temp_area->mark = 1;
+ rmem_chunk->num_marked_areas += 1;
+
+ g_mem_chunk_clean (mem_chunk);
+ }
+ }
+}
+
+void
+g_mem_chunk_clean (GMemChunk *mem_chunk)
+{
+ GRealMemChunk *rmem_chunk;
+ GMemArea *mem_area;
+ GFreeAtom *prev_free_atom;
+ GFreeAtom *temp_free_atom;
+ gpointer mem;
+
+ g_assert (mem_chunk != NULL);
+
+ rmem_chunk = (GRealMemChunk*) mem_chunk;
+
+ if (rmem_chunk->type == G_ALLOC_AND_FREE)
+ {
+ prev_free_atom = NULL;
+ temp_free_atom = rmem_chunk->free_atoms;
+
+ while (temp_free_atom)
+ {
+ mem = (gpointer) temp_free_atom;
+
+ mem_area = g_tree_search (rmem_chunk->mem_tree,
+ (GSearchFunc) g_mem_chunk_area_search,
+ mem);
+
+ /* If this mem area is marked for destruction then delete the
+ * area and list node and decrement the free mem.
+ */
+ if (mem_area->mark)
+ {
+ if (prev_free_atom)
+ prev_free_atom->next = temp_free_atom->next;
+ else
+ rmem_chunk->free_atoms = temp_free_atom->next;
+ temp_free_atom = temp_free_atom->next;
+
+ mem_area->free += rmem_chunk->atom_size;
+ if (mem_area->free == rmem_chunk->area_size)
+ {
+ rmem_chunk->num_mem_areas -= 1;
+ rmem_chunk->num_marked_areas -= 1;
+
+ if (mem_area->next)
+ mem_area->next->prev = mem_area->prev;
+ if (mem_area->prev)
+ mem_area->prev->next = mem_area->next;
+ if (mem_area == rmem_chunk->mem_areas)
+ rmem_chunk->mem_areas = rmem_chunk->mem_areas->next;
+ if (mem_area == rmem_chunk->mem_area)
+ rmem_chunk->mem_area = NULL;
+
+ if (rmem_chunk->type == G_ALLOC_AND_FREE)
+ g_tree_remove (rmem_chunk->mem_tree, mem_area);
+ g_free (mem_area);
+ }
+ }
+ else
+ {
+ prev_free_atom = temp_free_atom;
+ temp_free_atom = temp_free_atom->next;
+ }
+ }
+ }
+}
+
+void
+g_mem_chunk_reset (GMemChunk *mem_chunk)
+{
+ GRealMemChunk *rmem_chunk;
+ GMemArea *mem_areas;
+ GMemArea *temp_area;
+
+ g_assert (mem_chunk != NULL);
+
+ rmem_chunk = (GRealMemChunk*) mem_chunk;
+
+ mem_areas = rmem_chunk->mem_areas;
+ rmem_chunk->num_mem_areas = 0;
+ rmem_chunk->mem_areas = NULL;
+ rmem_chunk->mem_area = NULL;
+
+ while (mem_areas)
+ {
+ temp_area = mem_areas;
+ mem_areas = mem_areas->next;
+ g_free (temp_area);
+ }
+
+ rmem_chunk->free_atoms = NULL;
+
+ if (rmem_chunk->mem_tree)
+ g_tree_destroy (rmem_chunk->mem_tree);
+ rmem_chunk->mem_tree = g_tree_new ((GCompareFunc) g_mem_chunk_area_compare);
+}
+
+void
+g_mem_chunk_print (GMemChunk *mem_chunk)
+{
+ GRealMemChunk *rmem_chunk;
+ GMemArea *mem_areas;
+ gulong mem;
+
+ g_assert (mem_chunk != NULL);
+
+ rmem_chunk = (GRealMemChunk*) mem_chunk;
+ mem_areas = rmem_chunk->mem_areas;
+ mem = 0;
+
+ while (mem_areas)
+ {
+ mem += rmem_chunk->area_size - mem_areas->free;
+ mem_areas = mem_areas->next;
+ }
+
+ g_print ("%s: %ld bytes using %d mem areas", rmem_chunk->name, mem, rmem_chunk->num_mem_areas);
+}
+
+void
+g_mem_chunk_info ()
+{
+ GRealMemChunk *mem_chunk;
+ gint count;
+
+ count = 0;
+ mem_chunk = mem_chunks;
+ while (mem_chunk)
+ {
+ count += 1;
+ mem_chunk = mem_chunk->next;
+ }
+
+ g_print ("%d mem chunks", count);
+
+ mem_chunk = mem_chunks;
+ while (mem_chunk)
+ {
+ g_mem_chunk_print ((GMemChunk*) mem_chunk);
+ mem_chunk = mem_chunk->next;
+ }
+}
+
+void
+g_blow_chunks ()
+{
+ GRealMemChunk *mem_chunk;
+
+ mem_chunk = mem_chunks;
+ while (mem_chunk)
+ {
+ g_mem_chunk_clean ((GMemChunk*) mem_chunk);
+ mem_chunk = mem_chunk->next;
+ }
+}
+
+
+static gulong
+g_mem_chunk_compute_size (gulong size)
+{
+ gulong power_of_2;
+ gulong lower, upper;
+
+ power_of_2 = 16;
+ while (power_of_2 < size)
+ power_of_2 <<= 1;
+
+ lower = power_of_2 >> 1;
+ upper = power_of_2;
+
+ if ((size - lower) < (upper - size))
+ return lower;
+ return upper;
+}
+
+static gint
+g_mem_chunk_area_compare (GMemArea *a,
+ GMemArea *b)
+{
+ return (a->mem - b->mem);
+}
+
+static gint
+g_mem_chunk_area_search (GMemArea *a,
+ gchar *addr)
+{
+ if (a->mem <= addr)
+ {
+ if (addr < &a->mem[a->index])
+ return 0;
+ return 1;
+ }
+ return -1;
+}
diff --git a/glib/gprimes.c b/glib/gprimes.c
new file mode 100644
index 000000000..8887c0e66
--- /dev/null
+++ b/glib/gprimes.c
@@ -0,0 +1,61 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "glib.h"
+
+
+gint g_primes[] =
+{
+ 11,
+ 15,
+ 23,
+ 35,
+ 49,
+ 73,
+ 109,
+ 163,
+ 251,
+ 367,
+ 557,
+ 823,
+ 1237,
+ 1861,
+ 2777,
+ 4177,
+ 6247,
+ 9371,
+ 14057,
+ 21089,
+ 31627,
+ 47431,
+ 71143,
+ 106721,
+ 160073,
+ 240101,
+ 360163,
+ 540217,
+ 810343,
+ 1215497,
+ 1823231,
+ 2734867,
+ 4102283,
+ 6153409,
+ 9230113,
+ 13845163,
+};
+
+gint g_nprimes = sizeof (g_primes) / sizeof (g_primes[0]);
diff --git a/glib/gslist.c b/glib/gslist.c
new file mode 100644
index 000000000..e09198522
--- /dev/null
+++ b/glib/gslist.c
@@ -0,0 +1,324 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "glib.h"
+
+
+typedef struct _GRealListAllocator GRealListAllocator;
+
+struct _GRealListAllocator
+{
+ GMemChunk *list_mem_chunk;
+ GSList *free_list;
+};
+
+
+static GRealListAllocator *default_allocator = NULL;
+static GRealListAllocator *current_allocator = NULL;
+
+GListAllocator*
+g_slist_set_allocator (GListAllocator* fallocator)
+{
+ GRealListAllocator* allocator = (GRealListAllocator *) fallocator;
+ GRealListAllocator* old_allocator = current_allocator;
+
+ if (allocator)
+ current_allocator = allocator;
+ else
+ {
+ if (!default_allocator)
+ default_allocator = (GRealListAllocator*) g_list_allocator_new ();
+ current_allocator = default_allocator;
+ }
+
+ if (!current_allocator->list_mem_chunk)
+ current_allocator->list_mem_chunk = g_mem_chunk_new ("slist mem chunk",
+ sizeof (GSList),
+ 1024,
+ G_ALLOC_ONLY);
+
+ return (GListAllocator*) (old_allocator == default_allocator ? NULL : old_allocator);
+}
+
+
+GSList*
+g_slist_alloc ()
+{
+ GSList *new_list;
+
+ g_slist_set_allocator (NULL);
+ if (current_allocator->free_list)
+ {
+ new_list = current_allocator->free_list;
+ current_allocator->free_list = current_allocator->free_list->next;
+ }
+ else
+ {
+ new_list = g_chunk_new (GSList, current_allocator->list_mem_chunk);
+ }
+
+ new_list->data = NULL;
+ new_list->next = NULL;
+
+ return new_list;
+}
+
+void
+g_slist_free (GSList *list)
+{
+ GSList *last;
+
+ if (list)
+ {
+ last = g_slist_last (list);
+ last->next = current_allocator->free_list;
+ current_allocator->free_list = list;
+ }
+}
+
+void
+g_slist_free_1 (GSList *list)
+{
+ if (list)
+ {
+ list->next = current_allocator->free_list;
+ current_allocator->free_list = list;
+ }
+}
+
+GSList*
+g_slist_append (GSList *list,
+ gpointer data)
+{
+ GSList *new_list;
+ GSList *last;
+
+ new_list = g_slist_alloc ();
+ new_list->data = data;
+
+ if (!list)
+ {
+ list = new_list;
+ }
+ else
+ {
+ last = g_slist_last (list);
+ g_assert (last != NULL);
+ last->next = new_list;
+ }
+
+ return list;
+}
+
+GSList*
+g_slist_prepend (GSList *list,
+ gpointer data)
+{
+ GSList *new_list;
+
+ new_list = g_slist_alloc ();
+ new_list->data = data;
+ new_list->next = list;
+
+ return new_list;
+}
+
+GSList*
+g_slist_insert (GSList *list,
+ gpointer data,
+ gint position)
+{
+ GSList *prev_list;
+ GSList *tmp_list;
+ GSList *new_list;
+
+ prev_list = NULL;
+ tmp_list = list;
+
+ while (tmp_list && (position-- > 0))
+ {
+ prev_list = tmp_list;
+ tmp_list = tmp_list->next;
+ }
+
+ if (!tmp_list && !prev_list)
+ return list;
+
+ new_list = g_slist_alloc ();
+
+ if (!prev_list)
+ {
+ new_list->next = list;
+ list = new_list;
+ }
+ else
+ {
+ new_list->next = prev_list->next;
+ prev_list->next = new_list;
+ }
+
+ return list;
+}
+
+GSList*
+g_slist_remove (GSList *list,
+ gpointer data)
+{
+ GSList *tmp;
+ GSList *prev;
+
+ prev = NULL;
+ tmp = list;
+
+ while (tmp)
+ {
+ if (tmp->data == data)
+ {
+ if (prev)
+ prev->next = tmp->next;
+ if (list == tmp)
+ list = list->next;
+
+ tmp->next = NULL;
+ g_slist_free (tmp);
+
+ break;
+ }
+
+ prev = tmp;
+ tmp = tmp->next;
+ }
+
+ return list;
+}
+
+GSList*
+g_slist_remove_link (GSList *list,
+ GSList *link)
+{
+ GSList *tmp;
+ GSList *prev;
+
+ prev = NULL;
+ tmp = list;
+
+ while (tmp)
+ {
+ if (tmp == link)
+ {
+ if (prev)
+ prev->next = tmp->next;
+ if (list == tmp)
+ list = list->next;
+
+ tmp->next = NULL;
+ break;
+ }
+
+ prev = tmp;
+ tmp = tmp->next;
+ }
+
+ return list;
+}
+
+GSList*
+g_slist_reverse (GSList *list)
+{
+ GSList *tmp;
+ GSList *prev;
+ GSList *last;
+
+ last = NULL;
+ prev = NULL;
+
+ while (list)
+ {
+ last = list;
+
+ tmp = list->next;
+ list->next = prev;
+
+ prev = list;
+ list = tmp;
+ }
+
+ return last;
+}
+
+GSList*
+g_slist_nth (GSList *list,
+ gint n)
+{
+ while ((n-- > 0) && list)
+ list = list->next;
+
+ return list;
+}
+
+GSList*
+g_slist_find (GSList *list,
+ gpointer data)
+{
+ while (list)
+ {
+ if (list->data == data)
+ break;
+ list = list->next;
+ }
+
+ return list;
+}
+
+GSList*
+g_slist_last (GSList *list)
+{
+ if (list)
+ {
+ while (list->next)
+ list = list->next;
+ }
+
+ return list;
+}
+
+gint
+g_slist_length (GSList *list)
+{
+ gint length;
+
+ length = 0;
+ while (list)
+ {
+ length++;
+ list = list->next;
+ }
+
+ return length;
+}
+
+void
+g_slist_foreach (GSList *list,
+ GFunc func,
+ gpointer user_data)
+{
+ while (list)
+ {
+ (*func) (list->data, user_data);
+ list = list->next;
+ }
+}
diff --git a/glib/gstring.c b/glib/gstring.c
new file mode 100644
index 000000000..457d47ebc
--- /dev/null
+++ b/glib/gstring.c
@@ -0,0 +1,487 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <glib.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+
+typedef struct _GRealStringChunk GRealStringChunk;
+typedef struct _GRealString GRealString;
+
+struct _GRealStringChunk
+{
+ GHashTable *const_table;
+ GSList *storage_list;
+ gint storage_next;
+ gint this_size;
+ gint default_size;
+};
+
+struct _GRealString
+{
+ gchar *str;
+ gint len;
+ gint alloc;
+};
+
+
+static GMemChunk *string_mem_chunk = NULL;
+
+/* Hash Functions.
+ */
+
+/* Pete, you may have these elsewhere. */
+gint
+g_string_equal(gpointer v, gpointer v2)
+{
+ return strcmp ((gchar*) v, (gchar*)v2) == 0;
+}
+
+/* a char* hash function from ASU */
+guint
+g_string_hash(gpointer v)
+{
+ char *s = (char*)v;
+ char *p;
+ guint h=0, g;
+
+ for(p = s; *p != '\0'; p += 1) {
+ h = ( h << 4 ) + *p;
+ if ( ( g = h & 0xf0000000 ) ) {
+ h = h ^ (g >> 24);
+ h = h ^ g;
+ }
+ }
+
+ return h /* % M */;
+}
+
+
+/* String Chunks.
+ */
+
+GStringChunk*
+g_string_chunk_new (gint default_size)
+{
+ GRealStringChunk *new_chunk = g_new (GRealStringChunk, 1);
+ gint size = 1;
+
+ while (size < default_size)
+ size <<= 1;
+
+ new_chunk->const_table = NULL;
+ new_chunk->storage_list = NULL;
+ new_chunk->storage_next = size;
+ new_chunk->default_size = size;
+ new_chunk->this_size = size;
+
+ return (GStringChunk*) new_chunk;
+}
+
+void
+g_string_chunk_free (GStringChunk *fchunk)
+{
+ GRealStringChunk *chunk = (GRealStringChunk*) fchunk;
+ GSList *tmp_list;
+
+ if (chunk->storage_list)
+ {
+ GListAllocator *tmp_allocator = g_slist_set_allocator (NULL);
+
+ for (tmp_list = chunk->storage_list; tmp_list; tmp_list = tmp_list->next)
+ g_free (tmp_list->data);
+
+ g_slist_free (chunk->storage_list);
+
+ g_slist_set_allocator (tmp_allocator);
+ }
+
+ if (chunk->const_table)
+ g_hash_table_destroy (chunk->const_table);
+
+ g_free (chunk);
+}
+
+gchar*
+g_string_chunk_insert (GStringChunk *fchunk,
+ gchar* string)
+{
+ GRealStringChunk *chunk = (GRealStringChunk*) fchunk;
+ gint len = strlen (string);
+ char* pos;
+
+ if ((chunk->storage_next + len + 1) > chunk->this_size)
+ {
+ GListAllocator *tmp_allocator = g_slist_set_allocator (NULL);
+ gint new_size = chunk->default_size;
+
+ while (new_size < len+1)
+ new_size <<= 1;
+
+ chunk->storage_list = g_slist_prepend (chunk->storage_list,
+ g_new (char, new_size));
+
+ chunk->this_size = new_size;
+ chunk->storage_next = 0;
+
+ g_slist_set_allocator (tmp_allocator);
+ }
+
+ pos = ((char*)chunk->storage_list->data) + chunk->storage_next;
+
+ strcpy (pos, string);
+
+ chunk->storage_next += len + 1;
+
+ return pos;
+}
+
+gchar*
+g_string_chunk_insert_const (GStringChunk *fchunk,
+ gchar* string)
+{
+ GRealStringChunk *chunk = (GRealStringChunk*) fchunk;
+ char* lookup;
+
+ if (!chunk->const_table)
+ chunk->const_table = g_hash_table_new (g_string_hash, g_string_equal);
+
+ lookup = (char*) g_hash_table_lookup (chunk->const_table, string);
+
+ if (!lookup)
+ {
+ lookup = g_string_chunk_insert (fchunk, string);
+ g_hash_table_insert (chunk->const_table, lookup, lookup);
+ }
+
+ return lookup;
+}
+
+/* Strings.
+ */
+static gint
+nearest_pow (gint num)
+{
+ gint n = 1;
+
+ while (n < num)
+ n <<= 1;
+
+ return n;
+}
+
+static void
+g_string_maybe_expand (GRealString* string, gint len)
+{
+ if (string->len + len >= string->alloc)
+ {
+ string->alloc = nearest_pow (string->len + len + 1);
+ string->str = g_realloc (string->str, string->alloc);
+ }
+}
+
+GString*
+g_string_new (gchar *init)
+{
+ GRealString *string;
+
+ if (!string_mem_chunk)
+ string_mem_chunk = g_mem_chunk_new ("string mem chunk",
+ sizeof (GRealString),
+ 1024, G_ALLOC_AND_FREE);
+
+ string = g_chunk_new (GRealString, string_mem_chunk);
+
+ string->alloc = 2;
+ string->len = 0;
+ string->str = g_new0(char, 2);
+
+ if (init)
+ g_string_append ((GString*)string, init);
+
+ return (GString*) string;
+}
+
+void
+g_string_free (GString *string, gint free_segment)
+{
+ if (free_segment)
+ g_free (string->str);
+
+ g_mem_chunk_free (string_mem_chunk, string);
+}
+
+GString*
+g_string_assign (GString *lval,
+ char *rval)
+{
+ g_string_truncate (lval, 0);
+ g_string_append (lval, rval);
+
+ return lval;
+}
+
+GString*
+g_string_truncate (GString* fstring, gint len)
+{
+ GRealString *string = (GRealString*)fstring;
+
+ string->len = len;
+
+ string->str[len] = 0;
+
+ return fstring;
+}
+
+GString*
+g_string_append (GString *fstring, gchar *val)
+{
+ GRealString *string = (GRealString*)fstring;
+ int len = strlen (val);
+
+ g_string_maybe_expand (string, len);
+
+ strcpy (string->str + string->len, val);
+
+ string->len += len;
+
+ return fstring;
+}
+
+GString*
+g_string_append_c (GString *fstring, char c)
+{
+ GRealString *string = (GRealString*)fstring;
+
+ g_string_maybe_expand (string, 1);
+
+ string->str[string->len++] = c;
+ string->str[string->len] = 0;
+
+ return fstring;
+}
+
+GString*
+g_string_prepend (GString *fstring, gchar *val)
+{
+ GRealString *string = (GRealString*)fstring;
+ gint len = strlen (val);
+
+ g_string_maybe_expand (string, len);
+
+ memmove (string->str, string->str + len, string->len);
+
+ strncpy (string->str, val, len);
+
+ string->len += len;
+
+ string->str[string->len] = 0;
+
+ return fstring;
+}
+
+GString*
+g_string_prepend_c (GString *fstring, char c)
+{
+ GRealString *string = (GRealString*)fstring;
+
+ g_string_maybe_expand (string, 1);
+
+ memmove (string->str, string->str + 1, string->len);
+
+ string->str[0] = c;
+
+ string->len += 1;
+
+ string->str[string->len] = 0;
+
+ return fstring;
+}
+
+static int
+get_length_upper_bound (gchar* fmt, va_list *args)
+{
+ int len = 0;
+ int short_int;
+ int long_int;
+ int done;
+
+ while (*fmt)
+ {
+ char c = *fmt++;
+
+ short_int = FALSE;
+ long_int = FALSE;
+
+ if (c == '%')
+ {
+ done = FALSE;
+ while (*fmt && !done)
+ {
+ switch (*fmt++)
+ {
+ case '*':
+ len += va_arg(*args, int);
+ break;
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ fmt -= 1;
+ len += strtol (fmt, &fmt, 10);
+ break;
+ case 'h':
+ short_int = TRUE;
+ break;
+ case 'l':
+ long_int = TRUE;
+ break;
+
+ /* I ignore 'q' and 'L', they're not portable anyway. */
+
+ case 's':
+ len += strlen (va_arg (*args, char *));
+ done = TRUE;
+ break;
+ case 'd':
+ case 'i':
+ case 'o':
+ case 'u':
+ case 'x':
+ case 'X':
+ if (long_int)
+ (void)va_arg (*args, long);
+ else if (short_int)
+ (void)va_arg (*args, int);
+ else
+ (void)va_arg (*args, int);
+ len += 32;
+ done = TRUE;
+ break;
+ case 'D':
+ case 'O':
+ case 'U':
+ (void)va_arg (*args, long);
+ len += 32;
+ done = TRUE;
+ break;
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'g':
+ (void)va_arg (*args, double);
+ len += 32;
+ done = TRUE;
+ break;
+ case 'c':
+ (void)va_arg (*args, int);
+ len += 1;
+ done = TRUE;
+ break;
+ case 'p':
+ case 'n':
+ (void)va_arg (*args, void*);
+ len += 32;
+ done = TRUE;
+ break;
+ case '%':
+ len += 1;
+ done = TRUE;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ else
+ len += 1;
+ }
+
+ return len;
+}
+
+char*
+g_vsprintf (gchar *fmt,
+ va_list *args,
+ va_list *args2)
+{
+ static gchar *buf = NULL;
+ static gint alloc = 0;
+
+ gint len = get_length_upper_bound (fmt, args);
+
+ if (len >= alloc)
+ {
+ if (buf)
+ g_free (buf);
+
+ alloc = nearest_pow (MAX(len + 1, 1024));
+
+ buf = g_new (char, alloc);
+ }
+
+ vsprintf (buf, fmt, *args2);
+
+ return buf;
+}
+
+static void
+g_string_sprintfa_int (GString *string,
+ gchar *fmt,
+ va_list *args,
+ va_list *args2)
+{
+ g_string_append (string, g_vsprintf (fmt, args, args2));
+}
+
+void
+g_string_sprintf (GString *string, gchar *fmt, ...)
+{
+ va_list args, args2;
+
+ va_start(args, fmt);
+ va_start(args2, fmt);
+
+ g_string_truncate (string, 0);
+
+ g_string_sprintfa_int (string, fmt, &args, &args2);
+
+ va_end(args);
+ va_end(args2);
+}
+
+void
+g_string_sprintfa (GString *string, gchar *fmt, ...)
+{
+ va_list args, args2;
+
+ va_start(args, fmt);
+ va_start(args2, fmt);
+
+ g_string_sprintfa_int (string, fmt, &args, &args2);
+
+ va_end(args);
+ va_end(args2);
+}
diff --git a/glib/gtimer.c b/glib/gtimer.c
new file mode 100644
index 000000000..c3b720df9
--- /dev/null
+++ b/glib/gtimer.c
@@ -0,0 +1,119 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <sys/time.h>
+#include <unistd.h>
+#include "glib.h"
+
+
+typedef struct _GRealTimer GRealTimer;
+
+struct _GRealTimer
+{
+ struct timeval start;
+ struct timeval end;
+ gint active;
+};
+
+
+GTimer*
+g_timer_new ()
+{
+ GRealTimer *timer;
+
+ timer = g_new (GRealTimer, 1);
+ timer->active = TRUE;
+
+ gettimeofday (&timer->start, NULL);
+
+ return ((GTimer*) timer);
+}
+
+void
+g_timer_destroy (GTimer *timer)
+{
+ g_assert (timer != NULL);
+
+ g_free (timer);
+}
+
+void
+g_timer_start (GTimer *timer)
+{
+ GRealTimer *rtimer;
+
+ g_assert (timer != NULL);
+
+ rtimer = (GRealTimer*) timer;
+ gettimeofday (&rtimer->start, NULL);
+ rtimer->active = 1;
+}
+
+void
+g_timer_stop (GTimer *timer)
+{
+ GRealTimer *rtimer;
+
+ g_assert (timer != NULL);
+
+ rtimer = (GRealTimer*) timer;
+ gettimeofday (&rtimer->end, NULL);
+ rtimer->active = 0;
+}
+
+void
+g_timer_reset (GTimer *timer)
+{
+ GRealTimer *rtimer;
+
+ g_assert (timer != NULL);
+
+ rtimer = (GRealTimer*) timer;
+ gettimeofday (&rtimer->start, NULL);
+}
+
+gdouble
+g_timer_elapsed (GTimer *timer,
+ gulong *microseconds)
+{
+ GRealTimer *rtimer;
+ struct timeval elapsed;
+ gdouble total;
+
+ g_assert (timer != NULL);
+
+ rtimer = (GRealTimer*) timer;
+
+ if (rtimer->active)
+ gettimeofday (&rtimer->end, NULL);
+
+ if (rtimer->start.tv_usec > rtimer->end.tv_usec)
+ {
+ rtimer->end.tv_usec += 1000000;
+ rtimer->end.tv_sec--;
+ }
+
+ elapsed.tv_usec = rtimer->end.tv_usec - rtimer->start.tv_usec;
+ elapsed.tv_sec = rtimer->end.tv_sec - rtimer->start.tv_sec;
+
+ total = elapsed.tv_sec + ((gdouble) elapsed.tv_usec / 1e6);
+
+ if (microseconds)
+ *microseconds = elapsed.tv_usec;
+
+ return total;
+}
diff --git a/glib/gtree.c b/glib/gtree.c
new file mode 100644
index 000000000..61a32a409
--- /dev/null
+++ b/glib/gtree.c
@@ -0,0 +1,718 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "glib.h"
+
+
+typedef struct _GRealTree GRealTree;
+typedef struct _GTreeNode GTreeNode;
+
+struct _GRealTree
+{
+ GTreeNode *root;
+ GCompareFunc key_compare;
+};
+
+struct _GTreeNode
+{
+ gint balance; /* height (left) - height (right) */
+ GTreeNode *left; /* left subtree */
+ GTreeNode *right; /* right subtree */
+ gpointer key; /* key for this node */
+ gpointer value; /* value stored at this node */
+};
+
+
+static GTreeNode* g_tree_node_new (gpointer key,
+ gpointer value);
+static void g_tree_node_destroy (GTreeNode *node);
+static GTreeNode* g_tree_node_insert (GTreeNode *node,
+ GCompareFunc compare,
+ gpointer key,
+ gpointer value,
+ gint *inserted);
+static GTreeNode* g_tree_node_remove (GTreeNode *node,
+ GCompareFunc compare,
+ gpointer key);
+static GTreeNode* g_tree_node_balance (GTreeNode *node);
+static GTreeNode* g_tree_node_remove_leftmost (GTreeNode *node,
+ GTreeNode **leftmost);
+static GTreeNode* g_tree_node_restore_left_balance (GTreeNode *node,
+ gint old_balance);
+static GTreeNode* g_tree_node_restore_right_balance (GTreeNode *node,
+ gint old_balance);
+static gpointer g_tree_node_lookup (GTreeNode *node,
+ GCompareFunc compare,
+ gpointer key);
+static gint g_tree_node_count (GTreeNode *node);
+static gint g_tree_node_pre_order (GTreeNode *node,
+ GTraverseFunc traverse_func,
+ gpointer data);
+static gint g_tree_node_in_order (GTreeNode *node,
+ GTraverseFunc traverse_func,
+ gpointer data);
+static gint g_tree_node_post_order (GTreeNode *node,
+ GTraverseFunc traverse_func,
+ gpointer data);
+static gpointer g_tree_node_search (GTreeNode *node,
+ GSearchFunc search_func,
+ gpointer data);
+static gint g_tree_node_height (GTreeNode *node);
+static GTreeNode* g_tree_node_rotate_left (GTreeNode *node);
+static GTreeNode* g_tree_node_rotate_right (GTreeNode *node);
+static void g_tree_node_check (GTreeNode *node);
+
+
+static GMemChunk *node_mem_chunk = NULL;
+static GSList *node_free_list = NULL;
+
+
+GTree*
+g_tree_new (GCompareFunc key_compare_func)
+{
+ GRealTree *rtree;
+
+ rtree = g_new (GRealTree, 1);
+ rtree->root = NULL;
+ rtree->key_compare = key_compare_func;
+
+ return (GTree*) rtree;
+}
+
+void
+g_tree_destroy (GTree *tree)
+{
+ GRealTree *rtree;
+
+ g_return_if_fail (tree != NULL);
+
+ rtree = (GRealTree*) tree;
+
+ g_tree_node_destroy (rtree->root);
+ g_free (rtree);
+}
+
+void
+g_tree_insert (GTree *tree,
+ gpointer key,
+ gpointer value)
+{
+ GRealTree *rtree;
+ gint inserted;
+
+ g_return_if_fail (tree != NULL);
+
+ rtree = (GRealTree*) tree;
+
+ inserted = FALSE;
+ rtree->root = g_tree_node_insert (rtree->root, rtree->key_compare,
+ key, value, &inserted);
+}
+
+void
+g_tree_remove (GTree *tree,
+ gpointer key)
+{
+ GRealTree *rtree;
+
+ g_return_if_fail (tree != NULL);
+
+ rtree = (GRealTree*) tree;
+
+ rtree->root = g_tree_node_remove (rtree->root, rtree->key_compare, key);
+}
+
+gpointer
+g_tree_lookup (GTree *tree,
+ gpointer key)
+{
+ GRealTree *rtree;
+
+ g_return_val_if_fail (tree != NULL, NULL);
+
+ rtree = (GRealTree*) tree;
+
+ return g_tree_node_lookup (rtree->root, rtree->key_compare, key);
+}
+
+void
+g_tree_traverse (GTree *tree,
+ GTraverseFunc traverse_func,
+ GTraverseType traverse_type,
+ gpointer data)
+{
+ GRealTree *rtree;
+
+ g_return_if_fail (tree != NULL);
+
+ rtree = (GRealTree*) tree;
+
+ g_return_if_fail (rtree->root != NULL);
+
+ switch (traverse_type)
+ {
+ case G_PRE_ORDER:
+ g_tree_node_pre_order (rtree->root, traverse_func, data);
+ break;
+
+ case G_IN_ORDER:
+ g_tree_node_in_order (rtree->root, traverse_func, data);
+ break;
+
+ case G_POST_ORDER:
+ g_tree_node_post_order (rtree->root, traverse_func, data);
+ break;
+ }
+}
+
+gpointer
+g_tree_search (GTree *tree,
+ GSearchFunc search_func,
+ gpointer data)
+{
+ GRealTree *rtree;
+
+ g_return_val_if_fail (tree != NULL, NULL);
+
+ rtree = (GRealTree*) tree;
+
+ if (rtree->root)
+ return g_tree_node_search (rtree->root, search_func, data);
+ return NULL;
+}
+
+gint
+g_tree_height (GTree *tree)
+{
+ GRealTree *rtree;
+
+ g_return_val_if_fail (tree != NULL, 0);
+
+ rtree = (GRealTree*) tree;
+
+ if (rtree->root)
+ return g_tree_node_height (rtree->root);
+ return 0;
+}
+
+gint
+g_tree_nnodes (GTree *tree)
+{
+ GRealTree *rtree;
+
+ g_return_val_if_fail (tree != NULL, 0);
+
+ rtree = (GRealTree*) tree;
+
+ if (rtree->root)
+ return g_tree_node_count (rtree->root);
+ return 0;
+}
+
+
+static GTreeNode*
+g_tree_node_new (gpointer key,
+ gpointer value)
+{
+ GTreeNode *node;
+ GSList *tmp_list;
+
+ if (node_free_list)
+ {
+ tmp_list = node_free_list;
+ node_free_list = node_free_list->next;
+
+ node = tmp_list->data;
+
+ {
+ GListAllocator *tmp_allocator = g_list_set_allocator (NULL);
+ g_slist_free_1 (tmp_list);
+ g_list_set_allocator (tmp_allocator);
+ }
+ }
+ else
+ {
+ if (!node_mem_chunk)
+ node_mem_chunk = g_mem_chunk_new ("tree node mem chunk", sizeof (GTreeNode), 1024, G_ALLOC_ONLY);
+
+ node = g_chunk_new (GTreeNode, node_mem_chunk);
+ }
+
+ node->balance = 0;
+ node->left = NULL;
+ node->right = NULL;
+ node->key = key;
+ node->value = value;
+
+ return node;
+}
+
+static void
+g_tree_node_destroy (GTreeNode *node)
+{
+ if (node)
+ {
+ node_free_list = g_slist_prepend (node_free_list, node);
+ g_tree_node_destroy (node->right);
+ g_tree_node_destroy (node->left);
+ }
+}
+
+static GTreeNode*
+g_tree_node_insert (GTreeNode *node,
+ GCompareFunc compare,
+ gpointer key,
+ gpointer value,
+ gint *inserted)
+{
+ gint old_balance;
+ gint cmp;
+
+ if (!node)
+ {
+ *inserted = TRUE;
+ return g_tree_node_new (key, value);
+ }
+
+ cmp = (* compare) (key, node->key);
+ if (cmp == 0)
+ {
+ *inserted = FALSE;
+ node->value = value;
+ return node;
+ }
+
+ if (cmp < 0)
+ {
+ if (node->left)
+ {
+ old_balance = node->left->balance;
+ node->left = g_tree_node_insert (node->left, compare, key, value, inserted);
+
+ if ((old_balance != node->left->balance) && node->left->balance)
+ node->balance -= 1;
+ }
+ else
+ {
+ *inserted = TRUE;
+ node->left = g_tree_node_new (key, value);
+ node->balance -= 1;
+ }
+ }
+ else if (cmp > 0)
+ {
+ if (node->right)
+ {
+ old_balance = node->right->balance;
+ node->right = g_tree_node_insert (node->right, compare, key, value, inserted);
+
+ if ((old_balance != node->right->balance) && node->right->balance)
+ node->balance += 1;
+ }
+ else
+ {
+ *inserted = TRUE;
+ node->right = g_tree_node_new (key, value);
+ node->balance += 1;
+ }
+ }
+
+ if (*inserted)
+ {
+ if ((node->balance < -1) || (node->balance > 1))
+ node = g_tree_node_balance (node);
+ }
+
+ return node;
+}
+
+static GTreeNode*
+g_tree_node_remove (GTreeNode *node,
+ GCompareFunc compare,
+ gpointer key)
+{
+ GTreeNode *garbage;
+ GTreeNode *new_root;
+ gint old_balance;
+ gint cmp;
+
+ if (!node)
+ return NULL;
+
+ cmp = (* compare) (key, node->key);
+ if (cmp == 0)
+ {
+ garbage = node;
+
+ if (!node->right)
+ {
+ node = node->left;
+ }
+ else
+ {
+ old_balance = node->right->balance;
+ node->right = g_tree_node_remove_leftmost (node->right, &new_root);
+ new_root->left = node->left;
+ new_root->right = node->right;
+ new_root->balance = node->balance;
+ node = g_tree_node_restore_right_balance (new_root, old_balance);
+ }
+
+ node_free_list = g_slist_prepend (node_free_list, garbage);
+ }
+ else if (cmp < 0)
+ {
+ if (node->left)
+ {
+ old_balance = node->left->balance;
+ node->left = g_tree_node_remove (node->left, compare, key);
+ node = g_tree_node_restore_left_balance (node, old_balance);
+ }
+ }
+ else if (cmp > 0)
+ {
+ if (node->right)
+ {
+ old_balance = node->right->balance;
+ node->right = g_tree_node_remove (node->right, compare, key);
+ node = g_tree_node_restore_right_balance (node, old_balance);
+ }
+ }
+
+ return node;
+}
+
+static GTreeNode*
+g_tree_node_balance (GTreeNode *node)
+{
+ if (node->balance < -1)
+ {
+ if (node->left->balance > 0)
+ node->left = g_tree_node_rotate_left (node->left);
+ node = g_tree_node_rotate_right (node);
+ }
+ else if (node->balance > 1)
+ {
+ if (node->right->balance < 0)
+ node->right = g_tree_node_rotate_right (node->right);
+ node = g_tree_node_rotate_left (node);
+ }
+
+ return node;
+}
+
+static GTreeNode*
+g_tree_node_remove_leftmost (GTreeNode *node,
+ GTreeNode **leftmost)
+{
+ gint old_balance;
+
+ if (!node->left)
+ {
+ *leftmost = node;
+ return node->right;
+ }
+
+ old_balance = node->left->balance;
+ node->left = g_tree_node_remove_leftmost (node->left, leftmost);
+ return g_tree_node_restore_left_balance (node, old_balance);
+}
+
+static GTreeNode*
+g_tree_node_restore_left_balance (GTreeNode *node,
+ gint old_balance)
+{
+ if (!node->left)
+ node->balance += 1;
+ else if ((node->left->balance != old_balance) &&
+ (node->left->balance == 0))
+ node->balance += 1;
+
+ if (node->balance > 1)
+ return g_tree_node_balance (node);
+ return node;
+}
+
+static GTreeNode*
+g_tree_node_restore_right_balance (GTreeNode *node,
+ gint old_balance)
+{
+ if (!node->right)
+ node->balance -= 1;
+ else if ((node->right->balance != old_balance) &&
+ (node->right->balance == 0))
+ node->balance -= 1;
+
+ if (node->balance < -1)
+ return g_tree_node_balance (node);
+ return node;
+}
+
+static gpointer
+g_tree_node_lookup (GTreeNode *node,
+ GCompareFunc compare,
+ gpointer key)
+{
+ gint cmp;
+
+ if (!node)
+ return NULL;
+
+ cmp = (* compare) (key, node->key);
+ if (cmp == 0)
+ return node->value;
+
+ if (cmp < 0)
+ {
+ if (node->left)
+ return g_tree_node_lookup (node->left, compare, key);
+ }
+ else if (cmp > 0)
+ {
+ if (node->right)
+ return g_tree_node_lookup (node->right, compare, key);
+ }
+
+ return NULL;
+}
+
+static gint
+g_tree_node_count (GTreeNode *node)
+{
+ gint count;
+
+ count = 1;
+ if (node->left)
+ count += g_tree_node_count (node->left);
+ if (node->right)
+ count += g_tree_node_count (node->right);
+
+ return count;
+}
+
+static gint
+g_tree_node_pre_order (GTreeNode *node,
+ GTraverseFunc traverse_func,
+ gpointer data)
+{
+ if ((*traverse_func) (node->key, node->value, data))
+ return TRUE;
+ if (node->left)
+ {
+ if (g_tree_node_pre_order (node->left, traverse_func, data))
+ return TRUE;
+ }
+ if (node->right)
+ {
+ if (g_tree_node_pre_order (node->right, traverse_func, data))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gint
+g_tree_node_in_order (GTreeNode *node,
+ GTraverseFunc traverse_func,
+ gpointer data)
+{
+ if (node->left)
+ {
+ if (g_tree_node_in_order (node->left, traverse_func, data))
+ return TRUE;
+ }
+ if ((*traverse_func) (node->key, node->value, data))
+ return TRUE;
+ if (node->right)
+ {
+ if (g_tree_node_in_order (node->right, traverse_func, data))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gint
+g_tree_node_post_order (GTreeNode *node,
+ GTraverseFunc traverse_func,
+ gpointer data)
+{
+ if (node->left)
+ {
+ if (g_tree_node_post_order (node->left, traverse_func, data))
+ return TRUE;
+ }
+ if (node->right)
+ {
+ if (g_tree_node_post_order (node->right, traverse_func, data))
+ return TRUE;
+ }
+ if ((*traverse_func) (node->key, node->value, data))
+ return TRUE;
+
+ return FALSE;
+}
+
+static gpointer
+g_tree_node_search (GTreeNode *node,
+ GSearchFunc search_func,
+ gpointer data)
+{
+ gint dir;
+
+ if (!node)
+ return NULL;
+
+ do {
+ dir = (* search_func) (node->key, data);
+ if (dir == 0)
+ return node->value;
+
+ if (dir < 0)
+ node = node->left;
+ else if (dir > 0)
+ node = node->right;
+ } while (node && (dir != 0));
+
+ return NULL;
+}
+
+static gint
+g_tree_node_height (GTreeNode *node)
+{
+ gint left_height;
+ gint right_height;
+
+ if (node)
+ {
+ left_height = 0;
+ right_height = 0;
+
+ if (node->left)
+ left_height = g_tree_node_height (node->left);
+
+ if (node->right)
+ right_height = g_tree_node_height (node->right);
+
+ return MAX (left_height, right_height) + 1;
+ }
+
+ return 0;
+}
+
+static GTreeNode*
+g_tree_node_rotate_left (GTreeNode *node)
+{
+ GTreeNode *left;
+ GTreeNode *right;
+ gint a_bal;
+ gint b_bal;
+
+ left = node->left;
+ right = node->right;
+
+ node->right = right->left;
+ right->left = node;
+
+ a_bal = node->balance;
+ b_bal = right->balance;
+
+ if (b_bal <= 0)
+ {
+ if (a_bal >= 1)
+ right->balance = b_bal - 1;
+ else
+ right->balance = a_bal + b_bal - 2;
+ node->balance = a_bal - 1;
+ }
+ else
+ {
+ if (a_bal <= b_bal)
+ right->balance = a_bal - 2;
+ else
+ right->balance = b_bal - 1;
+ node->balance = a_bal - b_bal - 1;
+ }
+
+ return right;
+}
+
+static GTreeNode*
+g_tree_node_rotate_right (GTreeNode *node)
+{
+ GTreeNode *left;
+ GTreeNode *right;
+ gint a_bal;
+ gint b_bal;
+
+ left = node->left;
+ right = node->right;
+
+ node->left = left->right;
+ left->right = node;
+
+ a_bal = node->balance;
+ b_bal = left->balance;
+
+ if (b_bal <= 0)
+ {
+ if (b_bal > a_bal)
+ left->balance = b_bal + 1;
+ else
+ left->balance = a_bal + 2;
+ node->balance = a_bal - b_bal + 1;
+ }
+ else
+ {
+ if (a_bal <= -1)
+ left->balance = b_bal + 1;
+ else
+ left->balance = a_bal + b_bal + 2;
+ node->balance = a_bal + 1;
+ }
+
+ return left;
+}
+
+static void
+g_tree_node_check (GTreeNode *node)
+{
+ gint left_height;
+ gint right_height;
+ gint balance;
+
+ if (node)
+ {
+ left_height = 0;
+ right_height = 0;
+
+ if (node->left)
+ left_height = g_tree_node_height (node->left);
+ if (node->right)
+ right_height = g_tree_node_height (node->right);
+
+ balance = right_height - left_height;
+ if (balance != node->balance)
+ g_print ("g_tree_node_check: failed: %d ( %d )\n",
+ balance, node->balance);
+
+ if (node->left)
+ g_tree_node_check (node->left);
+ if (node->right)
+ g_tree_node_check (node->right);
+ }
+}
diff --git a/glib/gutils.c b/glib/gutils.c
new file mode 100644
index 000000000..c15332817
--- /dev/null
+++ b/glib/gutils.c
@@ -0,0 +1,732 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include "glib.h"
+
+
+static GErrorFunc error_func = NULL;
+static GWarningFunc warning_func = NULL;
+static GPrintFunc message_func = NULL;
+static GPrintFunc print_func = NULL;
+
+extern char* g_vsprintf (gchar *fmt, va_list *args, va_list *args2);
+
+gchar*
+g_strdup (const gchar *str)
+{
+ gchar *new_str;
+
+ new_str = NULL;
+ if (str)
+ {
+ new_str = g_new (char, strlen (str) + 1);
+ strcpy (new_str, str);
+ }
+
+ return new_str;
+}
+
+gchar*
+g_strerror (gint errnum)
+{
+ static char msg[64];
+
+#ifdef HAVE_STRERROR
+ return strerror (errnum);
+#elif NO_SYS_ERRLIST
+ switch (errnum)
+ {
+#ifdef E2BIG
+ case E2BIG: return "argument list too long";
+#endif
+#ifdef EACCES
+ case EACCES: return "permission denied";
+#endif
+#ifdef EADDRINUSE
+ case EADDRINUSE: return "address already in use";
+#endif
+#ifdef EADDRNOTAVAIL
+ case EADDRNOTAVAIL: return "can't assign requested address";
+#endif
+#ifdef EADV
+ case EADV: return "advertise error";
+#endif
+#ifdef EAFNOSUPPORT
+ case EAFNOSUPPORT: return "address family not supported by protocol family";
+#endif
+#ifdef EAGAIN
+ case EAGAIN: return "no more processes";
+#endif
+#ifdef EALIGN
+ case EALIGN: return "EALIGN";
+#endif
+#ifdef EALREADY
+ case EALREADY: return "operation already in progress";
+#endif
+#ifdef EBADE
+ case EBADE: return "bad exchange descriptor";
+#endif
+#ifdef EBADF
+ case EBADF: return "bad file number";
+#endif
+#ifdef EBADFD
+ case EBADFD: return "file descriptor in bad state";
+#endif
+#ifdef EBADMSG
+ case EBADMSG: return "not a data message";
+#endif
+#ifdef EBADR
+ case EBADR: return "bad request descriptor";
+#endif
+#ifdef EBADRPC
+ case EBADRPC: return "RPC structure is bad";
+#endif
+#ifdef EBADRQC
+ case EBADRQC: return "bad request code";
+#endif
+#ifdef EBADSLT
+ case EBADSLT: return "invalid slot";
+#endif
+#ifdef EBFONT
+ case EBFONT: return "bad font file format";
+#endif
+#ifdef EBUSY
+ case EBUSY: return "mount device busy";
+#endif
+#ifdef ECHILD
+ case ECHILD: return "no children";
+#endif
+#ifdef ECHRNG
+ case ECHRNG: return "channel number out of range";
+#endif
+#ifdef ECOMM
+ case ECOMM: return "communication error on send";
+#endif
+#ifdef ECONNABORTED
+ case ECONNABORTED: return "software caused connection abort";
+#endif
+#ifdef ECONNREFUSED
+ case ECONNREFUSED: return "connection refused";
+#endif
+#ifdef ECONNRESET
+ case ECONNRESET: return "connection reset by peer";
+#endif
+#if defined(EDEADLK) && (!defined(EWOULDBLOCK) || (EDEADLK != EWOULDBLOCK))
+ case EDEADLK: return "resource deadlock avoided";
+#endif
+#ifdef EDEADLOCK
+ case EDEADLOCK: return "resource deadlock avoided";
+#endif
+#ifdef EDESTADDRREQ
+ case EDESTADDRREQ: return "destination address required";
+#endif
+#ifdef EDIRTY
+ case EDIRTY: return "mounting a dirty fs w/o force";
+#endif
+#ifdef EDOM
+ case EDOM: return "math argument out of range";
+#endif
+#ifdef EDOTDOT
+ case EDOTDOT: return "cross mount point";
+#endif
+#ifdef EDQUOT
+ case EDQUOT: return "disk quota exceeded";
+#endif
+#ifdef EDUPPKG
+ case EDUPPKG: return "duplicate package name";
+#endif
+#ifdef EEXIST
+ case EEXIST: return "file already exists";
+#endif
+#ifdef EFAULT
+ case EFAULT: return "bad address in system call argument";
+#endif
+#ifdef EFBIG
+ case EFBIG: return "file too large";
+#endif
+#ifdef EHOSTDOWN
+ case EHOSTDOWN: return "host is down";
+#endif
+#ifdef EHOSTUNREACH
+ case EHOSTUNREACH: return "host is unreachable";
+#endif
+#ifdef EIDRM
+ case EIDRM: return "identifier removed";
+#endif
+#ifdef EINIT
+ case EINIT: return "initialization error";
+#endif
+#ifdef EINPROGRESS
+ case EINPROGRESS: return "operation now in progress";
+#endif
+#ifdef EINTR
+ case EINTR: return "interrupted system call";
+#endif
+#ifdef EINVAL
+ case EINVAL: return "invalid argument";
+#endif
+#ifdef EIO
+ case EIO: return "I/O error";
+#endif
+#ifdef EISCONN
+ case EISCONN: return "socket is already connected";
+#endif
+#ifdef EISDIR
+ case EISDIR: return "illegal operation on a directory";
+#endif
+#ifdef EISNAME
+ case EISNAM: return "is a name file";
+#endif
+#ifdef ELBIN
+ case ELBIN: return "ELBIN";
+#endif
+#ifdef EL2HLT
+ case EL2HLT: return "level 2 halted";
+#endif
+#ifdef EL2NSYNC
+ case EL2NSYNC: return "level 2 not synchronized";
+#endif
+#ifdef EL3HLT
+ case EL3HLT: return "level 3 halted";
+#endif
+#ifdef EL3RST
+ case EL3RST: return "level 3 reset";
+#endif
+#ifdef ELIBACC
+ case ELIBACC: return "can not access a needed shared library";
+#endif
+#ifdef ELIBBAD
+ case ELIBBAD: return "accessing a corrupted shared library";
+#endif
+#ifdef ELIBEXEC
+ case ELIBEXEC: return "can not exec a shared library directly";
+#endif
+#ifdef ELIBMAX
+ case ELIBMAX: return "attempting to link in more shared libraries than system limit";
+#endif
+#ifdef ELIBSCN
+ case ELIBSCN: return ".lib section in a.out corrupted";
+#endif
+#ifdef ELNRNG
+ case ELNRNG: return "link number out of range";
+#endif
+#ifdef ELOOP
+ case ELOOP: return "too many levels of symbolic links";
+#endif
+#ifdef EMFILE
+ case EMFILE: return "too many open files";
+#endif
+#ifdef EMLINK
+ case EMLINK: return "too many links";
+#endif
+#ifdef EMSGSIZE
+ case EMSGSIZE: return "message too long";
+#endif
+#ifdef EMULTIHOP
+ case EMULTIHOP: return "multihop attempted";
+#endif
+#ifdef ENAMETOOLONG
+ case ENAMETOOLONG: return "file name too long";
+#endif
+#ifdef ENAVAIL
+ case ENAVAIL: return "not available";
+#endif
+#ifdef ENET
+ case ENET: return "ENET";
+#endif
+#ifdef ENETDOWN
+ case ENETDOWN: return "network is down";
+#endif
+#ifdef ENETRESET
+ case ENETRESET: return "network dropped connection on reset";
+#endif
+#ifdef ENETUNREACH
+ case ENETUNREACH: return "network is unreachable";
+#endif
+#ifdef ENFILE
+ case ENFILE: return "file table overflow";
+#endif
+#ifdef ENOANO
+ case ENOANO: return "anode table overflow";
+#endif
+#if defined(ENOBUFS) && (!defined(ENOSR) || (ENOBUFS != ENOSR))
+ case ENOBUFS: return "no buffer space available";
+#endif
+#ifdef ENOCSI
+ case ENOCSI: return "no CSI structure available";
+#endif
+#ifdef ENODATA
+ case ENODATA: return "no data available";
+#endif
+#ifdef ENODEV
+ case ENODEV: return "no such device";
+#endif
+#ifdef ENOENT
+ case ENOENT: return "no such file or directory";
+#endif
+#ifdef ENOEXEC
+ case ENOEXEC: return "exec format error";
+#endif
+#ifdef ENOLCK
+ case ENOLCK: return "no locks available";
+#endif
+#ifdef ENOLINK
+ case ENOLINK: return "link has be severed";
+#endif
+#ifdef ENOMEM
+ case ENOMEM: return "not enough memory";
+#endif
+#ifdef ENOMSG
+ case ENOMSG: return "no message of desired type";
+#endif
+#ifdef ENONET
+ case ENONET: return "machine is not on the network";
+#endif
+#ifdef ENOPKG
+ case ENOPKG: return "package not installed";
+#endif
+#ifdef ENOPROTOOPT
+ case ENOPROTOOPT: return "bad proocol option";
+#endif
+#ifdef ENOSPC
+ case ENOSPC: return "no space left on device";
+#endif
+#ifdef ENOSR
+ case ENOSR: return "out of stream resources";
+#endif
+#ifdef ENOSTR
+ case ENOSTR: return "not a stream device";
+#endif
+#ifdef ENOSYM
+ case ENOSYM: return "unresolved symbol name";
+#endif
+#ifdef ENOSYS
+ case ENOSYS: return "function not implemented";
+#endif
+#ifdef ENOTBLK
+ case ENOTBLK: return "block device required";
+#endif
+#ifdef ENOTCONN
+ case ENOTCONN: return "socket is not connected";
+#endif
+#ifdef ENOTDIR
+ case ENOTDIR: return "not a directory";
+#endif
+#ifdef ENOTEMPTY
+ case ENOTEMPTY: return "directory not empty";
+#endif
+#ifdef ENOTNAM
+ case ENOTNAM: return "not a name file";
+#endif
+#ifdef ENOTSOCK
+ case ENOTSOCK: return "socket operation on non-socket";
+#endif
+#ifdef ENOTTY
+ case ENOTTY: return "inappropriate device for ioctl";
+#endif
+#ifdef ENOTUNIQ
+ case ENOTUNIQ: return "name not unique on network";
+#endif
+#ifdef ENXIO
+ case ENXIO: return "no such device or address";
+#endif
+#ifdef EOPNOTSUPP
+ case EOPNOTSUPP: return "operation not supported on socket";
+#endif
+#ifdef EPERM
+ case EPERM: return "not owner";
+#endif
+#ifdef EPFNOSUPPORT
+ case EPFNOSUPPORT: return "protocol family not supported";
+#endif
+#ifdef EPIPE
+ case EPIPE: return "broken pipe";
+#endif
+#ifdef EPROCLIM
+ case EPROCLIM: return "too many processes";
+#endif
+#ifdef EPROCUNAVAIL
+ case EPROCUNAVAIL: return "bad procedure for program";
+#endif
+#ifdef EPROGMISMATCH
+ case EPROGMISMATCH: return "program version wrong";
+#endif
+#ifdef EPROGUNAVAIL
+ case EPROGUNAVAIL: return "RPC program not available";
+#endif
+#ifdef EPROTO
+ case EPROTO: return "protocol error";
+#endif
+#ifdef EPROTONOSUPPORT
+ case EPROTONOSUPPORT: return "protocol not suppored";
+#endif
+#ifdef EPROTOTYPE
+ case EPROTOTYPE: return "protocol wrong type for socket";
+#endif
+#ifdef ERANGE
+ case ERANGE: return "math result unrepresentable";
+#endif
+#if defined(EREFUSED) && (!defined(ECONNREFUSED) || (EREFUSED != ECONNREFUSED))
+ case EREFUSED: return "EREFUSED";
+#endif
+#ifdef EREMCHG
+ case EREMCHG: return "remote address changed";
+#endif
+#ifdef EREMDEV
+ case EREMDEV: return "remote device";
+#endif
+#ifdef EREMOTE
+ case EREMOTE: return "pathname hit remote file system";
+#endif
+#ifdef EREMOTEIO
+ case EREMOTEIO: return "remote i/o error";
+#endif
+#ifdef EREMOTERELEASE
+ case EREMOTERELEASE: return "EREMOTERELEASE";
+#endif
+#ifdef EROFS
+ case EROFS: return "read-only file system";
+#endif
+#ifdef ERPCMISMATCH
+ case ERPCMISMATCH: return "RPC version is wrong";
+#endif
+#ifdef ERREMOTE
+ case ERREMOTE: return "object is remote";
+#endif
+#ifdef ESHUTDOWN
+ case ESHUTDOWN: return "can't send afer socket shutdown";
+#endif
+#ifdef ESOCKTNOSUPPORT
+ case ESOCKTNOSUPPORT: return "socket type not supported";
+#endif
+#ifdef ESPIPE
+ case ESPIPE: return "invalid seek";
+#endif
+#ifdef ESRCH
+ case ESRCH: return "no such process";
+#endif
+#ifdef ESRMNT
+ case ESRMNT: return "srmount error";
+#endif
+#ifdef ESTALE
+ case ESTALE: return "stale remote file handle";
+#endif
+#ifdef ESUCCESS
+ case ESUCCESS: return "Error 0";
+#endif
+#ifdef ETIME
+ case ETIME: return "timer expired";
+#endif
+#ifdef ETIMEDOUT
+ case ETIMEDOUT: return "connection timed out";
+#endif
+#ifdef ETOOMANYREFS
+ case ETOOMANYREFS: return "too many references: can't splice";
+#endif
+#ifdef ETXTBSY
+ case ETXTBSY: return "text file or pseudo-device busy";
+#endif
+#ifdef EUCLEAN
+ case EUCLEAN: return "structure needs cleaning";
+#endif
+#ifdef EUNATCH
+ case EUNATCH: return "protocol driver not attached";
+#endif
+#ifdef EUSERS
+ case EUSERS: return "too many users";
+#endif
+#ifdef EVERSION
+ case EVERSION: return "version mismatch";
+#endif
+#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
+ case EWOULDBLOCK: return "operation would block";
+#endif
+#ifdef EXDEV
+ case EXDEV: return "cross-domain link";
+#endif
+#ifdef EXFULL
+ case EXFULL: return "message tables full";
+#endif
+ }
+#else /* NO_SYS_ERRLIST */
+ extern int sys_nerr;
+ extern char *sys_errlist[];
+
+ if ((errnum > 0) && (errnum <= sys_nerr))
+ return sys_errlist [errnum];
+#endif /* NO_SYS_ERRLIST */
+
+ sprintf (msg, "unknown error (%d)", errnum);
+ return msg;
+}
+
+gchar*
+g_strsignal (gint signum)
+{
+ static char msg[64];
+
+#ifdef HAVE_STRSIGNAL
+ extern char *strsignal (int sig);
+ return strsignal (signum);
+#elif NO_SYS_SIGLIST
+ switch (signum)
+ {
+#ifdef SIGHUP
+ case SIGHUP: return "Hangup";
+#endif
+#ifdef SIGINT
+ case SIGINT: return "Interrupt";
+#endif
+#ifdef SIGQUIT
+ case SIGQUIT: return "Quit";
+#endif
+#ifdef SIGILL
+ case SIGILL: "Illegal instruction";
+#endif
+#ifdef SIGTRAP
+ case SIGTRAP: "Trace/breakpoint trap";
+#endif
+#ifdef SIGABRT
+ case SIGABRT: "IOT trap/Abort";
+#endif
+#ifdef SIGBUS
+ case SIGBUS: "Bus error";
+#endif
+#ifdef SIGFPE
+ case SIGFPE: "Floating point exception";
+#endif
+#ifdef SIGKILL
+ case SIGKILL: "Killed";
+#endif
+#ifdef SIGUSR1
+ case SIGUSR1: "User defined signal 1";
+#endif
+#ifdef SIGSEGV
+ case SIGSEGV: "Segmentation fault";
+#endif
+#ifdef SIGUSR2
+ case SIGUSR2: "User defined signal 2";
+#endif
+#ifdef SIGPIPE
+ case SIGPIPE: "Broken pipe";
+#endif
+#ifdef SIGALRM
+ case SIGALRM: "Alarm clock";
+#endif
+#ifdef SIGTERM
+ case SIGTERM: "Terminated";
+#endif
+#ifdef SIGSTKFLT
+ case SIGSTKFLT: "Stack fault";
+#endif
+#ifdef SIGCHLD
+ case SIGCHLD: "Child exited";
+#endif
+#ifdef SIGCONT
+ case SIGCONT: "Continued";
+#endif
+#ifdef SIGSTOP
+ case SIGSTOP: "Stopped (signal)";
+#endif
+#ifdef SIGTSTP
+ case SIGTSTP: "Stopped";
+#endif
+#ifdef SIGTTIN
+ case SIGTTIN: "Stopped (tty input)";
+#endif
+#ifdef SIGTTOU
+ case SIGTTOU: "Stopped (tty output)";
+#endif
+#ifdef SIGURG
+ case SIGURG: "Urgent condition";
+#endif
+#ifdef SIGXCPU
+ case SIGXCPU: "CPU time limit exceeded";
+#endif
+#ifdef SIGXFSZ
+ case SIGXFSZ: "File size limit exceeded";
+#endif
+#ifdef SIGVTALRM
+ case SIGVTALRM: "Virtual time alarm";
+#endif
+#ifdef SIGPROF
+ case SIGPROF: "Profile signal";
+#endif
+#ifdef SIGWINCH
+ case SIGWINCH: "Window size changed";
+#endif
+#ifdef SIGIO
+ case SIGIO: "Possible I/O";
+#endif
+#ifdef SIGPWR
+ case SIGPWR: "Power failure";
+#endif
+#ifdef SIGUNUSED
+ case SIGUNUSED: return "Unused signal";
+#endif
+ }
+#else /* NO_SYS_SIGLIST */
+ extern char *sys_siglist[];
+ return sys_siglist [signum];
+#endif /* NO_SYS_SIGLIST */
+
+ sprintf (msg, "unknown signal (%d)", signum);
+ return msg;
+}
+
+void
+g_error (gchar *format, ...)
+{
+ va_list args, args2;
+ char *buf;
+
+ va_start (args, format);
+ va_start (args2, format);
+ buf = g_vsprintf (format, &args, &args2);
+ va_end (args);
+ va_end (args2);
+
+ if (error_func)
+ {
+ (* error_func) (buf);
+ }
+ else
+ {
+ fputs ("\n** ERROR **: ", stderr);
+ fputs (buf, stderr);
+ fputc ('\n', stderr);
+ }
+
+ abort ();
+}
+
+void
+g_warning (gchar *format, ...)
+{
+ va_list args, args2;
+ char *buf;
+
+ va_start (args, format);
+ va_start (args2, format);
+ buf = g_vsprintf (format, &args, &args2);
+ va_end (args);
+ va_end (args2);
+
+ if (warning_func)
+ {
+ (* warning_func) (buf);
+ }
+ else
+ {
+ fputs ("\n** WARNING **: ", stderr);
+ fputs (buf, stderr);
+ fputc ('\n', stderr);
+ }
+}
+
+void
+g_message (gchar *format, ...)
+{
+ va_list args, args2;
+ char *buf;
+
+ va_start (args, format);
+ va_start (args2, format);
+ buf = g_vsprintf (format, &args, &args2);
+ va_end (args);
+ va_end (args2);
+
+ if (message_func)
+ {
+ (* message_func) (buf);
+ }
+ else
+ {
+ fputs ("message: ", stdout);
+ fputs (buf, stdout);
+ fputc ('\n', stdout);
+ }
+}
+
+void
+g_print (gchar *format, ...)
+{
+ va_list args, args2;
+ char *buf;
+
+ va_start (args, format);
+ va_start (args2, format);
+ buf = g_vsprintf (format, &args, &args2);
+ va_end (args);
+ va_end (args2);
+
+ if (print_func)
+ {
+ (* print_func) (buf);
+ }
+ else
+ {
+ fputs (buf, stdout);
+ }
+}
+
+GErrorFunc
+g_set_error_handler (GErrorFunc func)
+{
+ GErrorFunc old_error_func;
+
+ old_error_func = error_func;
+ error_func = func;
+
+ return old_error_func;
+}
+
+GWarningFunc
+g_set_warning_handler (GWarningFunc func)
+{
+ GWarningFunc old_warning_func;
+
+ old_warning_func = warning_func;
+ warning_func = func;
+
+ return old_warning_func;
+}
+
+GPrintFunc
+g_set_message_handler (GPrintFunc func)
+{
+ GPrintFunc old_message_func;
+
+ old_message_func = message_func;
+ message_func = func;
+
+ return old_message_func;
+}
+
+GPrintFunc
+g_set_print_handler (GPrintFunc func)
+{
+ GPrintFunc old_print_func;
+
+ old_print_func = print_func;
+ print_func = func;
+
+ return old_print_func;
+}
diff --git a/glib/install-sh b/glib/install-sh
new file mode 100755
index 000000000..89fc9b098
--- /dev/null
+++ b/glib/install-sh
@@ -0,0 +1,238 @@
+#! /bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+#
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+tranformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ true
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ else
+ instcmd=mkdir
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ true
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ true
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ true
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ true
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ true
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
diff --git a/glib/ltconfig b/glib/ltconfig
new file mode 100755
index 000000000..e9d3a8379
--- /dev/null
+++ b/glib/ltconfig
@@ -0,0 +1,1415 @@
+#! /bin/sh
+
+# ltconfig - Create a system-specific libtool.
+# Generated automatically from ltconfig.in by configure.
+# Copyright (C) 1996, 1997, Free Software Foundation, Inc.
+# Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# A lot of this script is taken from autoconf-2.10.
+
+# The name of this program.
+progname=`echo "$0" | sed 's%^.*/%%'`
+
+# Constants:
+PROGRAM=ltconfig
+PACKAGE=libtool
+VERSION=1.0f
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.c 1>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.c $LIBS 1>&5'
+rm="rm -f"
+
+help="Try \`$progname --help' for more information."
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+sed_quote_subst='s/\([\\"$\\\\]\)/\\\1/g'
+
+# Same as above, but don't quote variable references.
+double_quote_subst='s/\([\\"\\\\]\)/\\\1/g'
+
+# Global variables:
+can_build_shared=yes
+enable_shared=yes
+# All known linkers require a `.a' archive for static linking.
+enable_static=yes
+ltmain=
+silent=
+srcdir=
+ac_config_guess=
+ac_config_sub=
+host=
+nonopt=
+verify_host=yes
+with_gcc=no
+with_gnu_ld=no
+
+old_AR="$AR"
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+old_CPPFLAGS="$CPPFLAGS"
+old_LD="$LD"
+old_LN_S="$LN_S"
+old_NM="$NM"
+old_RANLIB="$RANLIB"
+
+# Parse the command line options.
+args=
+prev=
+for option
+do
+ case "$option" in
+ -*=*) optarg=`echo "$option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) optarg= ;;
+ esac
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$prev"; then
+ eval "$prev=\$option"
+ prev=
+ continue
+ fi
+
+ case "$option" in
+ --help) cat <<EOM
+Usage: $progname [OPTION]... LTMAIN [HOST]
+
+Generate a system-specific libtool script.
+
+ --disable-shared do not build shared libraries
+ --disable-static do not build static libraries
+ --help display this help and exit
+ --no-verify do not verify that HOST is a valid host type
+ --quiet same as \`--silent'
+ --silent don't print informational messages
+ --srcdir=DIR find \`config.guess' in DIR
+ --version output version information and exit
+ --with-gcc assume that the GNU C compiler will be used
+ --with-gnu-ld assume that the C compiler uses the GNU linker
+
+LTMAIN is the \`ltmain.sh' shell script fragment that provides basic libtool
+functionality.
+
+HOST is the canonical host system name [default=guessed].
+EOM
+ exit 0
+ ;;
+
+ --disable-shared) enable_shared=no ;;
+
+ --disable-static) enable_static=no ;;
+
+ --quiet | --silent) silent=yes ;;
+
+ --srcdir) prev=srcdir ;;
+ --srcdir=*) srcdir="$optarg" ;;
+
+ --no-verify) verify_host=no ;;
+
+ --version) echo "$PROGRAM (GNU $PACKAGE) $VERSION"; exit 0 ;;
+
+ --with-gcc) with_gcc=yes ;;
+ --with-gnu-ld) with_gnu_ld=yes ;;
+
+ -*)
+ echo "$progname: unrecognized option \`$option'" 1>&2
+ echo "$help" 1>&2
+ exit 1
+ ;;
+
+ *)
+ if test -z "$ltmain"; then
+ ltmain="$option"
+ elif test -z "$host"; then
+# FIXME This generates an unnecessary warning for sparc-sun-solaris4.1.3_U1
+# if test -n "`echo $option| sed 's/[-a-z0-9.]//g'`"; then
+# echo "$progname: warning \`$option' is not a valid host type" 1>&2
+# fi
+ host="$option"
+ else
+ echo "$progname: too many arguments" 1>&2
+ echo "$help" 1>&2
+ exit 1
+ fi ;;
+ esac
+done
+
+if test -z "$ltmain"; then
+ echo "$progname: you must specify a LTMAIN file" 1>&2
+ echo "$help" 1>&2
+ exit 1
+fi
+
+if test -f "$ltmain"; then :
+else
+ echo "$progname: warning: \`$ltmain' does not exist" 1>&2
+fi
+
+# Quote any args containing shell metacharacters.
+ltconfig_args=
+for arg
+do
+ case "$arg" in
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ltconfig_args="$ltconfig_args '$arg'" ;;
+ *) ltconfig_args="$ltconfig_args $arg" ;;
+ esac
+done
+
+# A relevant subset of AC_INIT.
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 5 compiler messages saved in config.log
+# 6 checking for... messages and results
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>>./config.log
+
+# NLS nuisances.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+if test -z "$srcdir"; then
+ # Assume the source directory is the same one as the path to ltmain.sh.
+ srcdir=`echo "$ltmain" | sed 's%/[^/]*$%%'`
+ test "$srcdir" = "$ltmain" && srcdir=.
+fi
+
+trap "$rm conftest*; exit 1" 1 2 15
+if test "$verify_host" = yes; then
+ # Check for config.guess and config.sub.
+ ac_aux_dir=
+ for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+ if test -f $ac_dir/config.guess; then
+ ac_aux_dir=$ac_dir
+ break
+ fi
+ done
+ if test -z "$ac_aux_dir"; then
+ echo "$progname: cannot find config.guess in $srcdir $srcdir/.. $srcdir/../.." 1>&2
+ echo "$help" 1>&2
+ exit 1
+ fi
+ ac_config_guess=$ac_aux_dir/config.guess
+ ac_config_sub=$ac_aux_dir/config.sub
+
+ # Make sure we can run config.sub.
+ if $ac_config_sub sun4 >/dev/null 2>&1; then :
+ else
+ echo "$progname: cannot run $ac_config_sub" 1>&2
+ echo "$help" 1>&2
+ exit 1
+ fi
+
+ echo $ac_n "checking host system type""... $ac_c" 1>&6
+
+ host_alias=$host
+ case "$host_alias" in
+ "")
+ if host_alias=`$ac_config_guess`; then :
+ else
+ echo "$progname: cannot guess host type; you must specify one" 1>&2
+ echo "$help" 1>&2
+ exit 1
+ fi ;;
+ esac
+ host=`$ac_config_sub $host_alias`
+ echo "$ac_t$host" 1>&6
+
+ # Make sure the host verified.
+ test -z "$host" && exit 1
+
+elif test -z "$host"; then
+ echo "$progname: you must specify a host type if you use \`--no-verify'" 1>&2
+ echo "$help" 1>&2
+ exit 1
+else
+ host_alias=$host
+fi
+
+# Transform *-*-linux* to *-*-linux-gnu*, to support old configure scripts.
+case "$host" in
+*-*-linux-gnu*) ;;
+*-*-linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'`
+esac
+
+host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+case "$host_os" in
+aix*)
+ # AIX sometimes has problems with the GCC collect2 program. For some
+ # reason, if we set the COLLECT_NAMES environment variable, the problems
+ # vanish in a puff of smoke.
+ if test "${COLLECT_NAMES+set}" != set; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+ fi
+ ;;
+esac
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR cru $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+
+# Set a sane default for `AR'.
+test -z "$AR" && AR=ar
+
+# If RANLIB is not set, then run the test.
+if test "${RANLIB+set}" != "set"; then
+ result=no
+
+ echo $ac_n "checking for ranlib... $ac_c" 1>&6
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}:"
+ for dir in $PATH; do
+ test -z "$dir" && dir=.
+ if test -f $dir/ranlib; then
+ RANLIB="ranlib"
+ result="ranlib"
+ break
+ fi
+ done
+ IFS="$save_ifs"
+
+ echo "$ac_t$result" 1>&6
+fi
+
+if test -n "$RANLIB"; then
+ old_archive_cmds="$old_archive_cmds;\$RANLIB \$oldlib"
+ old_postinstall_cmds="$old_postinstall_cmds;\$RANLIB \$oldlib"
+fi
+
+# Check to see if we are using GCC.
+if test "$with_gcc" != yes || test -z "$CC"; then
+ # If CC is not set, then try to find GCC or a usable CC.
+ if test -z "$CC"; then
+ echo $ac_n "checking for gcc... $ac_c" 1>&6
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}:"
+ for dir in $PATH; do
+ IFS="$save_ifs"
+ test -z "$dir" && dir=.
+ if test -f $dir/gcc; then
+ CC="gcc"
+ break
+ fi
+ done
+ IFS="$save_ifs"
+
+ if test -n "$CC"; then
+ echo "$ac_t$CC" 1>&6
+ else
+ echo "$ac_t"no 1>&6
+ fi
+ fi
+
+ # Not "gcc", so try "cc", rejecting "/usr/ucb/cc".
+ if test -z "$CC"; then
+ echo $ac_n "checking for cc... $ac_c" 1>&6
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}:"
+ cc_rejected=no
+ for dir in $PATH; do
+ test -z "$dir" && dir=.
+ if test -f $dir/cc; then
+ if test "$dir/cc" = "/usr/ucb/cc"; then
+ cc_rejected=yes
+ continue
+ fi
+ CC="cc"
+ break
+ fi
+ done
+ IFS="$save_ifs"
+ if test $cc_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $CC
+ shift
+ if test $# -gt 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same name, so the bogon will be chosen
+ # first if we set CC to just the name; use the full file name.
+ shift
+ set dummy "$dir/cc" "$@"
+ shift
+ CC="$@"
+ fi
+ fi
+
+ if test -n "$CC"; then
+ echo "$ac_t$CC" 1>&6
+ else
+ echo "$ac_t"no 1>&6
+ fi
+
+ if test -z "$CC"; then
+ echo "$progname: error: no acceptable cc found in \$PATH" 1>&2
+ exit 1
+ fi
+ fi
+
+ # Now see if the compiler is really GCC.
+ with_gcc=no
+ echo $ac_n "checking whether we are using GNU C... $ac_c" 1>&6
+ echo "$progname:394: checking whether we are using GNU C" >&5
+
+ $rm conftest.c
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+ if { ac_try='${CC-cc} -E conftest.c'; { (eval echo $progname:402: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ with_gcc=yes
+ fi
+ $rm conftest.c
+ echo "$ac_t$with_gcc" 1>&6
+fi
+
+# Allow CC to be a program name with arguments.
+set dummy $CC
+compiler="$2"
+
+echo $ac_n "checking for $compiler option to produce PIC... $ac_c" 1>&6
+pic_flag=
+profile_flag_pattern=
+special_shlib_compile_flags=
+wl=
+link_static_flag=
+no_builtin_flag=
+
+if test "$with_gcc" = yes; then
+ profile_flag_pattern='-pg?'
+ wl='-Wl,'
+ link_static_flag='-static'
+ no_builtin_flag=' -fno-builtin'
+
+ case "$host_os" in
+ aix3* | aix4* | irix5* | irix6* | osf3* | osf4*)
+ # PIC is the default for these OSes.
+ ;;
+ os2*)
+ # We can build DLLs from non-PIC.
+ ;;
+ *)
+ pic_flag='-fPIC'
+ ;;
+ esac
+else
+ # PORTME Check for PIC flags for the system compiler.
+ case "$host_os" in
+ aix3* | aix4*)
+ # All AIX code is PIC.
+ link_static_flag='-bnso -bI:/lib/syscalls.exp'
+ ;;
+
+ hpux9* | hpux10*)
+ # Is there a better link_static_flag that works with the bundled CC?
+ wl='-Wl,'
+ link_static_flag='${wl}-a ${wl}archive'
+ pic_flag='+Z'
+ ;;
+
+ irix5* | irix6*)
+ wl='-Wl,'
+ link_static_flag='-non_shared'
+ # PIC (with -KPIC) is the default.
+ ;;
+
+ os2*)
+ # We can build DLLs from non-PIC.
+ ;;
+
+ osf3* | osf4*)
+ # All OSF/1 code is PIC.
+ wl='-Wl,'
+ link_static_flag='-non_shared'
+ ;;
+
+ sco3.2v5*)
+ pic_flag='-Kpic'
+ link_static_flag='-dn'
+ special_shlib_compile_flags='-belf'
+ ;;
+
+ solaris2*)
+ pic_flag='-KPIC'
+ link_static_flag='-Bstatic'
+ wl='-Wl,'
+ ;;
+
+ sunos4*)
+ pic_flag='-PIC'
+ link_static_flag='-Bstatic'
+ wl='-Qoption ld '
+ ;;
+
+ uts4*)
+ pic_flag='-pic'
+ link_static_flag='-Bstatic'
+ ;;
+
+ *)
+ can_build_shared=no
+ ;;
+ esac
+fi
+
+if test -n "$pic_flag"; then
+ echo "$ac_t$pic_flag" 1>&6
+
+ # Check to make sure the pic_flag actually works.
+ echo $ac_n "checking if $compiler PIC flag $pic_flag works... $ac_c" 1>&6
+ $rm conftest*
+ echo > conftest.c
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $pic_flag -DPIC"
+ echo "$progname:507: checking if $compiler PIC flag $pic_flag works" >&5
+ if { (eval echo $progname:508: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.o; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+
+ # On HP-UX, the stripped-down bundled CC doesn't accept +Z, but also
+ # reports no error. So, we need to grep stderr for (Bundled).
+ if grep '(Bundled)' conftest.err >/dev/null; then
+ echo "$ac_t"no 1>&6
+ can_build_shared=no
+ pic_flag=
+ else
+ echo "$ac_t"yes 1>&6
+ pic_flag=" $pic_flag"
+ fi
+ else
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ can_build_shared=no
+ pic_flag=
+ echo "$ac_t"no 1>&6
+ fi
+ CFLAGS="$save_CFLAGS"
+ $rm conftest*
+else
+ echo "$ac_t"none 1>&6
+fi
+
+# Check for any special shared library compilation flags.
+if test -n "$special_shlib_compile_flags"; then
+ echo "$progname: warning: \`$CC' requires \`$special_shlib_compile_flags' to build shared libraries" 1>&2
+ if echo "$old_CC $old_CFLAGS " | egrep -e "[ ]$special_shlib_compile_flags[ ]" >/dev/null; then :
+ else
+ echo "$progname: add \`$special_shlib_compile_flags' to the CC or CFLAGS env variable and reconfigure" 1>&2
+ can_build_shared=no
+ fi
+fi
+
+echo $ac_n "checking if $compiler static flag $link_static_flag works... $ac_c" 1>&6
+$rm conftest*
+echo 'main(){return(0);}' > conftest.c
+save_LDFLAGS="$LDFLAGS"
+LDFLAGS="$LDFLAGS $link_static_flag"
+echo "$progname:550: checking if $compiler static flag $link_static_flag works" >&5
+if { (eval echo $progname:551: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ echo "$ac_t$link_static_flag" 1>&6
+else
+ echo "$ac_t"none 1>&6
+ link_static_flag=
+fi
+LDFLAGS="$save_LDFLAGS"
+$rm conftest*
+
+if test -z "$LN_S"; then
+ # Check to see if we can use ln -s, or we need hard links.
+ echo $ac_n "checking whether ln -s works... $ac_c" 1>&6
+ $rm conftestdata
+ if ln -s X conftestdata 2>/dev/null; then
+ $rm conftestdata
+ LN_S="ln -s"
+ else
+ LN_S=ln
+ fi
+ if test "$LN_S" = "ln -s"; then
+ echo "$ac_t"yes 1>&6
+ else
+ echo "$ac_t"no 1>&6
+ fi
+fi
+
+# Make sure LD is an absolute path.
+if test -z "$LD"; then
+ ac_prog=ld
+ if test "$with_gcc" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ echo $ac_n "checking for ld used by GCC... $ac_c" 1>&6
+ echo "$progname:583: checking for ld used by GCC" >&5
+ ac_prog=`($CC -print-prog-name=ld) 2>&5`
+ case "$ac_prog" in
+ # Accept absolute paths.
+ /*)
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+ elif test "$with_gnu_ld" = yes; then
+ echo $ac_n "checking for GNU ld... $ac_c" 1>&6
+ echo "$progname:601: checking for GNU ld" >&5
+ else
+ echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6
+ echo "$progname:604: checking for non-GNU ld" >&5
+ fi
+
+ if test -z "$LD"; then
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog"; then
+ LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some GNU ld's only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ if "$LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
+ test "$with_gnu_ld" != no && break
+ else
+ test "$with_gnu_ld" != yes && break
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+ fi
+
+ if test -n "$LD"; then
+ echo "$ac_t$LD" 1>&6
+ else
+ echo "$ac_t"no 1>&6
+ fi
+
+ if test -z "$LD"; then
+ echo "$progname: error: no acceptable ld found in \$PATH" 1>&2
+ exit 1
+ fi
+fi
+
+# Check to see if it really is or isn't GNU ld.
+echo $ac_n "checking if the linker ($LD) is GNU ld... $ac_c" 1>&6
+# I'd rather use --version here, but apparently some GNU ld's only accept -v.
+if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+ with_gnu_ld=yes
+else
+ with_gnu_ld=no
+fi
+echo "$ac_t$with_gnu_ld" 1>&6
+
+# See if the linker supports building shared libraries.
+echo $ac_n "checking whether the linker ($LD) supports shared libraries... $ac_c" 1>&6
+
+allow_undefined_flag=
+archive_cmds=
+old_archive_from_new_cmds=
+export_dynamic_flag_spec=
+hardcode_libdir_flag_spec=
+hardcode_libdir_separator=
+hardcode_direct=no
+hardcode_minus_L=no
+hardcode_runpath_var=no
+hardcode_shlibpath_var=unsupported
+runpath_var=
+
+ld_shlibs=yes
+if test "$with_gnu_ld" = yes; then
+ # See if GNU ld supports shared libraries.
+
+ case "$host_os" in
+ sunos4*)
+ ld_shlibs=yes
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ *)
+ if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ ld_shlibs=yes
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ esac
+
+ if test "$ld_shlibs" = yes; then
+ archive_cmds='$CC -shared ${wl}-soname $wl$soname -o $lib$libobjs$deplibs'
+ hardcode_libdir_flag_spec='${wl}-rpath $wl$libdir'
+ export_dynamic_flag_spec='${wl}-export-dynamic'
+ fi
+else
+ # PORTME fill in a description of your system's linker (not GNU ld)
+ case "$host_os" in
+ aix3*)
+ allow_undefined_flag=unsupported
+ archive_cmds='$NM$libobjs | $global_symbol_pipe | sed '"'s/.* //'"' > $lib.exp;$LD -o $objdir/$soname$libobjs -bE:$lib.exp -T512 -H512 -bM:SRE$deplibs;$AR cru $lib $objdir/$soname'
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ hardcode_minus_L=yes
+ if test "$with_gcc" = yes && test -z "$link_static_flag"; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ hardcode_direct=unsupported
+ fi
+ ;;
+
+ aix4*)
+ allow_undefined_flag=unsupported
+ archive_cmds='$NM$libobjs | $global_symbol_pipe | sed '"'s/.* //'"' > $lib.exp;$CC -o $objdir/$soname$libobjs ${wl}-bE:$lib.exp ${wl}-bM:SRE ${wl}-bnoentry$deplibs;$AR cru $lib $objdir/$soname'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ ;;
+
+ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+ # support. Future versions do this automatically, but an explicit c++rt0.o
+ # doesn't break anything, and helps significantly (at the cost of a little
+ # extra space).
+ freebsd2.2*)
+ archive_cmds='$LD -Bshareable -o $lib$libobjs$deplibs /usr/lib/c++rt0.o'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ # Unfortunately, older versions of FreeBSD 2 don't have this feature.
+ freebsd2*)
+ archive_cmds='$LD -Bshareable -o $lib$libobjs$deplibs'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ # FreeBSD 3, at last, uses gcc -shared to do shared libraries.
+ freebsd3*)
+ archive_cmds='$CC -shared -o $lib$libobjs$deplibs'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ hpux9*)
+ archive_cmds='$rm $objdir/$soname;$LD -b +s +b $install_libdir -o $objdir/$soname$libobjs$deplibs;mv $objdir/$soname $lib'
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ ;;
+
+ hpux10*)
+ archive_cmds='$LD -b +h $soname +s +b $install_libdir -o $lib$libobjs$deplibs'
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ ;;
+
+ irix5* | irix6*)
+ archive_cmds='$LD -shared -o $lib -soname $soname -set_version $verstring$libobjs$deplibs'
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ ;;
+
+ netbsd*)
+ # Tested with NetBSD 1.2 ld
+ archive_cmds='$LD -Bshareable -o $lib$libobjs'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ openbsd*)
+ archive_cmds='$LD -Bshareable -o $lib$libobjs$deplibs'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ os2*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ allow_undefined_flag=unsupported
+ archive_cmds='echo "LIBRARY $libname INITINSTANCE" > $objdir/$libname.def;echo "DESCRIPTION \"$libname\"" >> $objdir/$libname.def;echo DATA >> $objdir/$libname.def;echo " SINGLE NONSHARED" >> $objdir/$libname.def;echo EXPORTS >> $objdir/$libname.def;emxexp$libobjs >> $objdir/$libname.def;$CC -Zdll -Zcrtdll -o $lib$libobjs $objdir/$libname.def'
+ old_archive_from_new_cmds='emximp -o $objdir/$libname.a $objdir/$libname.def'
+ ;;
+
+ osf3* | osf4*)
+ allow_undefined_flag=' -expect_unresolved \*'
+ archive_cmds='$LD -shared${allow_undefined_flag} -o $lib -soname $soname -set_version $verstring$libobjs$deplibs'
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ ;;
+
+ sco3.2v5*)
+ archive_cmds='$LD -G -o $lib$libobjs$deplibs'
+ hardcode_direct=yes
+ ;;
+
+ solaris2*)
+ archive_cmds='$LD -G -z text -h $soname -o $lib$libobjs$deplibs'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_shlibpath_var=no
+ ;;
+
+ sunos4*)
+ archive_cmds='$LD -assert pure-text -Bstatic -o $lib$libobjs'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ uts4*)
+ archive_cmds='$LD -G -h $soname -o $lib$libobjs$deplibs'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_direct=no
+ hardcode_minus_L=no
+ hardcode_shlibpath_var=no
+ ;;
+
+ *)
+ ld_shlibs=no
+ can_build_shared=no
+ ;;
+ esac
+fi
+echo "$ac_t$ld_shlibs" 1>&6
+
+if test -z "$NM"; then
+ echo $ac_n "checking for BSD-compatible nm... $ac_c" 1>&6
+ case "$NM" in
+ /*) ;; # Let the user override the test with a path.
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in /usr/ucb $PATH /bin; do
+ test -z "$ac_dir" && dir=.
+ if test -f $ac_dir/nm; then
+ # Check to see if the nm accepts a BSD-compat flag.
+ if ($ac_dir/nm -B /dev/null 2>&1; exit 0) | grep /dev/null >/dev/null; then
+ NM="$ac_dir/nm -B"
+ elif ($ac_dir/nm -p /dev/null 2>&1; exit 0) | grep /dev/null >/dev/null; then
+ NM="$ac_dir/nm -p"
+ else
+ NM="$ac_dir/nm"
+ fi
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$NM" && NM=nm
+ ;;
+ esac
+ echo "$ac_t$NM" 1>&6
+fi
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+echo $ac_n "checking command to parse $NM output... $ac_c" 1>&6
+
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix. What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[BCDEGRSTU]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
+
+# Transform the above into a raw symbol and a C symbol.
+symxfrm='\1 \1'
+
+# Define system-specific variables.
+case "$host_os" in
+aix*)
+ symcode='[BCDTU]'
+ ;;
+solaris2*)
+ symcode='[BDTU]'
+ ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then
+ symcode='[ABCDGISTUW]'
+fi
+
+# Write the raw and C identifiers.
+global_symbol_pipe="sed -n -e 's/^.* $symcode $sympat$/$symxfrm/p'"
+
+# Check to see that the pipe works correctly.
+pipe_works=no
+$rm conftest*
+cat > conftest.c <<EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(){}
+#ifdef __cplusplus
+}
+#endif
+main(){nm_test_var='a';nm_test_func();return(0);}
+EOF
+
+echo "$progname:900: checking if global_symbol_pipe works" >&5
+if { (eval echo $progname:901: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; } && test -s conftest.o; then
+ # Now try to grab the symbols.
+ nlist=conftest.nm
+ if { echo "$progname:904: eval \"$NM conftest.o | $global_symbol_pipe > $nlist\"" >&5; eval "$NM conftest.o | $global_symbol_pipe > $nlist 2>&5"; } && test -s "$nlist"; then
+
+ # Try sorting and uniquifying the output.
+ if sort "$nlist" | uniq > "$nlist"T; then
+ mv -f "$nlist"T "$nlist"
+ wcout=`wc "$nlist" 2>/dev/null`
+ count=`echo "$wcout" | sed 's/^[ ]*\([0-9][0-9]*\).*$/\1/'`
+ (test "$count" -ge 0) 2>/dev/null || count=-1
+ else
+ rm -f "$nlist"T
+ count=-1
+ fi
+
+ # Make sure that we snagged all the symbols we need.
+ if egrep ' nm_test_var$' "$nlist" >/dev/null; then
+ if egrep ' nm_test_func$' "$nlist" >/dev/null; then
+ cat <<EOF > conftest.c
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EOF
+ # Now generate the symbol file.
+ sed 's/^.* \(.*\)$/extern char \1;/' < "$nlist" >> conftest.c
+
+ cat <<EOF >> conftest.c
+#if defined (__STDC__) && __STDC__
+# define __ptr_t void *
+#else
+# define __ptr_t char *
+#endif
+
+/* The number of symbols in dld_preloaded_symbols, -1 if unsorted. */
+int dld_preloaded_symbol_count = $count;
+
+/* The mapping between symbol names and symbols. */
+struct {
+ char *name;
+ __ptr_t address;
+}
+dld_preloaded_symbols[] =
+{
+EOF
+ sed 's/^\(.*\) \(.*\)$/ {"\1", \&\2},/' < "$nlist" >> conftest.c
+ cat <<\EOF >> conftest.c
+ {0},
+};
+
+#ifdef __cplusplus
+}
+#endif
+EOF
+ # Now try linking the two files.
+ mv conftest.o conftestm.o
+ save_LIBS="$LIBS"
+ save_CFLAGS="$CFLAGS"
+ LIBS='conftestm.o'
+ CFLAGS="$CFLAGS$no_builtin_flag"
+ if { (eval echo $progname:962: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ pipe_works=yes
+ else
+ echo "$progname: failed program was:" >&5
+ cat conftest.c >&5
+ fi
+ LIBS="$save_LIBS"
+ else
+ echo "cannot find nm_test_func in $nlist" >&5
+ fi
+ else
+ echo "cannot find nm_test_var in $nlist" >&5
+ fi
+ else
+ echo "cannot run $global_symbol_pipe" >&5
+ fi
+else
+ echo "$progname: failed program was:" >&5
+ cat conftest.c >&5
+fi
+$rm conftest*
+
+# Don't use the global_symbol_pipe unless it works.
+echo "$ac_t$pipe_works" 1>&6
+test "$pipe_works" = yes || global_symbol_pipe=
+
+# Check hardcoding attributes.
+echo $ac_n "checking how to hardcode library paths into programs... $ac_c" 1>&6
+hardcode_action=
+if test -n "$hardcode_libdir_flag_spec" || \
+ test "$hardcode_runpath_var" = yes; then
+
+ # We can hardcode non-existant directories.
+ if test "$hardcode_direct" != no && \
+ test "$hardcode_minus_L" != no && \
+ test "$hardcode_shlibpath_var" != no; then
+
+ # Linking always hardcodes the temporary library directory.
+ hardcode_action=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ hardcode_action=immediate
+ fi
+elif test "$hardcode_direct" != yes && \
+ test "$hardcode_minus_L" != yes && \
+ test "$hardcode_shlibpath_var" != yes; then
+ # We can't hardcode anything.
+ hardcode_action=unsupported
+else
+ # We can only hardcode existing directories.
+ hardcode_action=relink
+fi
+echo "$ac_t$hardcode_action" 1>&6
+test "$hardcode_action" = unsupported && can_build_shared=no
+
+
+reload_flag=
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+echo $ac_n "checking for $LD option to reload object files... $ac_c" 1>&6
+# PORTME Some linker may need a different reload flag.
+reload_flag='-r'
+echo "$ac_t$reload_flag"
+test -n "$reload_flag" && reload_flag=" $reload_flag"
+
+# PORTME Fill in your ld.so characteristics
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+postinstall_cmds=
+finish_cmds=
+shlibpath_var=
+version_type=none
+dynamic_linker="$host_os ld.so"
+
+echo $ac_n "checking dynamic linker characteristics... $ac_c" 1>&6
+case "$host_os" in
+aix3* | aix4*)
+ version_type=linux
+ library_names_spec='$libname.so.$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX has no versioning support, so we append a major version to the name.
+ soname_spec='$libname.so.$major'
+ ;;
+
+freebsd2* | freebsd3*)
+ version_type=sunos
+ library_names_spec='$libname.so.$versuffix $libname.so'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+gnu*)
+ version_type=sunos
+ library_names_spec='$libname.so.$versuffix'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+hpux9* | hpux10*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ dynamic_linker="$host_os dld.sl"
+ version_type=sunos
+ shlibpath_var=SHLIB_PATH
+ library_names_spec='$libname.sl.$versuffix $libname.sl.$major $libname.sl'
+ soname_spec='$libname.sl.$major'
+ # HP-UX runs *really* slowly unless shared libraries are mode 555.
+ postinstall_cmds='chmod 555 $lib'
+ ;;
+
+irix5* | irix6*)
+ version_type=osf
+ soname_spec='$libname.so'
+ library_names_spec='$libname.so.$versuffix $libname.so'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*)
+ dynamic_linker=no
+ ;;
+
+# This must be Linux ELF.
+linux-gnu*)
+ version_type=linux
+ library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so'
+ soname_spec='$libname.so.$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+
+ if test -f /lib/ld.so.1; then
+ dynamic_linker='GNU ld.so'
+ else
+ # Only the GNU ld.so supports shared libraries on MkLinux.
+ case "$host_cpu" in
+ powerpc*) dynamic_linker=no ;;
+ *) dynamic_linker='Linux ld.so' ;;
+ esac
+ fi
+ ;;
+
+netbsd* | openbsd*)
+ version_type=sunos
+ library_names_spec='$libname.so.$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+os2*)
+ version_type=none
+ libname_spec='$name'
+ library_names_spec='$libname.dll $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+osf3* | osf4*)
+ version_type=osf
+ soname_spec='$libname.so'
+ library_names_spec='$libname.so.$versuffix $libname.so'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+sco3.2v5*)
+ version_type=osf
+ soname_spec='$libname.so.$major'
+ library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+solaris2*)
+ version_type=linux
+ library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so'
+ soname_spec='$libname.so.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='$libname.so.$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+uts4*)
+ version_type=linux
+ library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so'
+ soname_spec='$libname.so.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+echo "$ac_t$dynamic_linker"
+test "$dynamic_linker" = no && can_build_shared=no
+
+# FIXME add checks for striplib and old_striplib here.
+# strip -x works for most platforms, though not for static libraries on NetBSD
+# HP-UX requires "-r" for library stripping
+striplib=
+old_striplib=
+
+# Report the final consequences.
+echo "checking if libtool supports shared libraries... $can_build_shared" 1>&6
+
+echo $ac_n "checking whether to build shared libraries... $ac_c" 1>&6
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case "$host_os" in
+aix*)
+ test "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds;\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+esac
+
+echo "$ac_t$enable_shared" 1>&6
+
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+
+echo "checking whether to build static libraries... $enable_static" 1>&6
+
+echo $ac_n "checking for objdir... $ac_c" 1>&6
+rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+ objdir=.libs
+else
+ # MS-DOS does not allow filenames that begin with a dot.
+ objdir=_libs
+fi
+rmdir .libs 2>/dev/null
+echo "$ac_t$objdir" 1>&6
+
+# Now quote all the things that may contain metacharacters.
+for var in old_CC old_CFLAGS old_CPPFLAGS old_LD old_NM old_RANLIB \
+ old_LN_S AR CC LD LN_S NM reload_flag reload_cmds wl pic_flag \
+ link_static_flag no_builtin_flag export_dynamic_flag_spec \
+ profile_flag_pattern libname_spec library_names_spec soname_spec RANLIB \
+ old_archive_cmds old_archive_from_new_cmds old_postinstall_cmds \
+ archive_cmds postinstall_cmds \
+ allow_undefined_flag finish_cmds global_symbol_pipe \
+ striplib old_striplib \
+ hardcode_libdir_flag_spec hardcode_libdir_separator; do
+
+ case "$var" in
+ reload_cmds | old_archive_cmds | old_archive_from_new_cmds | \
+ old_postinstall_cmds | archive_cmds | postinstall_cmds | finish_cmds)
+ # Double-quote double-evaled strings.
+ eval "$var=\`echo \"\$$var\" | sed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\"\`"
+ ;;
+ *)
+ eval "$var=\`echo \"\$$var\" | sed \"\$sed_quote_subst\"\`"
+ ;;
+ esac
+done
+
+ofile=libtool
+trap "$rm $ofile; exit 1" 1 2 15
+echo creating $ofile
+$rm $ofile
+cat <<EOF > $ofile
+#! /bin/sh
+
+# libtool - Provide generalized library-building support services.
+#
+# Generated automatically by $PROGRAM - GNU $PACKAGE $VERSION
+# This program was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# CC="$old_CC" CFLAGS="$old_CFLAGS" CPPFLAGS="$old_CPPFLAGS" \\
+# LD="$old_LD" NM="$old_NM" RANLIB="$old_RANLIB" LN_S="$old_LN_S" \\
+# $0$ltconfig_args
+#
+# Compiler and other test output produced by $progname, useful for
+# debugging $progname, is in ./config.log if it exists.
+
+# The version of $progname that generated this script.
+LTCONFIG_VERSION="$VERSION"
+
+# Shell to use when invoking shell scripts.
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Whether or not to build libtool libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build old-style libraries.
+build_old_libs=$enable_static
+
+# The host system.
+host_alias="$host_alias"
+host="$host"
+
+# The archiver.
+AR="$AR"
+
+# The default C compiler.
+CC="$CC"
+
+# The linker used to build libraries.
+LD="$LD"
+
+# Whether we need hard or soft links.
+LN_S="$LN_S"
+
+# A BSD-compatible nm program.
+NM="$NM"
+
+# The name of the directory that contains temporary libtool files.
+objdir="$objdir"
+
+# How to create reloadable object files.
+reload_flag="$reload_flag"
+reload_cmds="$reload_cmds"
+
+# How to pass a linker flag through the compiler.
+wl="$wl"
+
+# Additional compiler flags for building library objects.
+pic_flag="$pic_flag"
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag="$link_static_flag"
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag="$no_builtin_flag"
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec="$export_dynamic_flag_spec"
+
+# Pattern to match compiler flags for creating libNAME_p libraries:
+profile_flag_pattern="$profile_flag_pattern"
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec="$libname_spec"
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec="$library_names_spec"
+
+# The coded name of the library, if different from the real name.
+soname_spec="$soname_spec"
+
+# Commands used to build and install an old-style archive.
+RANLIB="$RANLIB"
+old_archive_cmds="$old_archive_cmds"
+old_postinstall_cmds="$old_postinstall_cmds"
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds="$old_archive_from_new_cmds"
+
+# Commands used to build and install a shared archive.
+archive_cmds="$archive_cmds"
+postinstall_cmds="$postinstall_cmds"
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag="$allow_undefined_flag"
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds="$finish_cmds"
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe="$global_symbol_pipe"
+
+# How to strip a library file.
+striplib="$striplib"
+old_striplib="$old_striplib"
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec="$hardcode_libdir_flag_spec"
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator="$hardcode_libdir_separator"
+
+# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L
+
+# Set to yes if using RUNPATH_VAR=DIR during linking hardcodes DIR into the
+# resulting binary.
+hardcode_runpath_var=$hardcode_runpath_var
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var
+
+EOF
+
+case "$host_os" in
+aix*)
+ cat <<\EOF >> $ofile
+# AIX sometimes has problems with the GCC collect2 program. For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "${COLLECT_NAMES+set}" != set; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+fi
+
+EOF
+ ;;
+esac
+
+# Detect if we are using a relative or absolute path to ltmain.sh.
+case "$ltmain" in
+/*) cat <<EOF >> $ofile
+# Execute the libtool backend.
+. $ltmain
+EOF
+ ;;
+*) cat <<EOF >> $ofile
+# Find the path to this script.
+thisdir=\`echo "\$0" | sed -e 's%/[^/]*\$%%'\`
+test "X\$0" = "X\$thisdir" && thisdir=.
+
+# Execute the libtool backend.
+. \$thisdir/$ltmain
+EOF
+ ;;
+esac
+
+echo 'exit 1' >> $ofile
+
+chmod +x $ofile
+exit 0
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
diff --git a/glib/ltmain.sh b/glib/ltmain.sh
new file mode 100644
index 000000000..cb46c8498
--- /dev/null
+++ b/glib/ltmain.sh
@@ -0,0 +1,2372 @@
+# ltmain.sh - Provide generalized library-building support services.
+# Generated automatically from ltmain.in by configure.
+# Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+# Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+#FIXME: echo=echo
+echo='printf %s\n'
+if test "X`$echo '\t'`" = 'X\t'; then :
+else
+ # The Solaris and AIX default echo program unquotes backslashes.
+ # This makes it impossible to quote backslashes using
+ # echo "$something" | sed 's/\\/\\\\/g'
+ # So, we emulate echo with printf '%s\n'
+ echo='printf %s\n'
+ if test "X`$echo '\t'`" = 'X\t'; then :
+ else
+ # Oops. We have no working printf. Try to find a not-so-buggy echo.
+ echo=echo
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}:"
+ save_PATH="$PATH"
+ PATH="$PATH":/usr/ucb
+ for dir in $PATH; do
+ if test -f $dir/echo && test "X`$dir/echo '\t'`" = 'X\t'; then
+ echo="$dir/echo"
+ break
+ fi
+ done
+ IFS="$save_ifs"
+ PATH="$save_PATH"
+ fi
+fi
+
+# The name of this program.
+progname=`$echo "$0" | sed 's%^.*/%%'`
+
+# Constants.
+PROGRAM=ltmain.sh
+PACKAGE=libtool
+VERSION=1.0f
+
+default_mode=
+help="Try \`$progname --help' for more information."
+magic="%%%MAGIC variable%%%"
+mkdir="mkdir"
+mv="mv -f"
+rm="rm -f"
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+sed_quote_subst='s/\([\\"$\\\\]\)/\\\1/g'
+
+# NLS nuisances.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+
+if test "$LTCONFIG_VERSION" != "$VERSION"; then
+ $echo "$progname: ltconfig version \`$LTCONFIG_VERSION' does not match $PROGRAM version \`$VERSION'" 1>&2
+ $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
+ exit 1
+fi
+
+if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
+ $echo "$progname: not configured to build any kind of library" 1>&2
+ $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
+ exit 1
+fi
+
+# Global variables.
+mode=$default_mode
+nonopt=
+prev=
+prevopt=
+run=
+show="$echo"
+show_help=
+execute_dlfiles=
+
+# Parse our command line options once, thoroughly.
+while test $# -gt 0
+do
+ arg="$1"
+ shift
+
+ case "$arg" in
+ -*=*) optarg=`$echo "$arg" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) optarg= ;;
+ esac
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$prev"; then
+ case "$prev" in
+ execute_dlfiles)
+ eval "$prev=\"\$$prev \$arg\""
+ ;;
+ *)
+ eval "$prev=\$arg"
+ ;;
+ esac
+
+ prev=
+ prevopt=
+ continue
+ fi
+
+ # Have we seen a non-optional argument yet?
+ case "$arg" in
+ --help)
+ show_help=yes
+ ;;
+
+ --version)
+ $echo "$PROGRAM (GNU $PACKAGE) $VERSION"
+ exit 0
+ ;;
+
+ --dry-run | -n)
+ run=:
+ ;;
+
+ --features)
+ $echo "host: $host"
+ if test "$build_libtool_libs" = yes; then
+ $echo "enable shared libraries"
+ else
+ $echo "disable shared libraries"
+ fi
+ if test "$build_old_libs" = yes; then
+ $echo "enable static libraries"
+ else
+ $echo "disable static libraries"
+ fi
+ exit 0
+ ;;
+
+ --finish) mode="finish" ;;
+
+ --mode) prevopt="--mode" prev=mode ;;
+ --mode=*) mode="$optarg" ;;
+
+ --quiet | --silent)
+ show=:
+ ;;
+
+ -dlopen)
+ prevopt="-dlopen"
+ prev=execute_dlfiles
+ ;;
+
+ -*)
+ $echo "$progname: unrecognized option \`$arg'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+
+ *)
+ nonopt="$arg"
+ break
+ ;;
+ esac
+done
+
+if test -n "$prevopt"; then
+ $echo "$progname: option \`$prevopt' requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+fi
+
+if test -z "$show_help"; then
+
+ # Infer the operation mode.
+ if test -z "$mode"; then
+ case "$nonopt" in
+ *cc | *++)
+ mode=link
+ for arg
+ do
+ case "$arg" in
+ -c)
+ mode=compile
+ break
+ ;;
+ esac
+ done
+ ;;
+ *db | *dbx)
+ mode=execute
+ ;;
+ *install*|cp)
+ mode=install
+ ;;
+ *rm)
+ mode=uninstall
+ ;;
+ *)
+ # If we have no mode, but dlfiles were specified, then do execute mode.
+ test -n "$execute_dlfiles" && mode=execute
+
+ # Just use the default operation mode.
+ if test -z "$mode"; then
+ if test -n "$nonopt"; then
+ $echo "$progname: warning: cannot infer operation mode from \`$nonopt'" 1>&2
+ else
+ $echo "$progname: warning: cannot infer operation mode without MODE-ARGS" 1>&2
+ fi
+ fi
+ ;;
+ esac
+ fi
+
+ # Only execute mode is allowed to have -dlopen flags.
+ if test -n "$execute_dlfiles" && test "$mode" != execute; then
+ $echo "$progname: unrecognized option \`-dlopen'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ # Change the help message to a mode-specific one.
+ generic_help="$help"
+ help="Try \`$progname --help --mode=$mode' for more information."
+
+ # These modes are in order of execution frequency so that they run quickly.
+ case "$mode" in
+ # libtool compile mode
+ compile)
+ progname="$progname: compile"
+ # Get the compilation command and the source file.
+ base_compile=
+ lastarg=
+ srcfile="$nonopt"
+ suppress_output=
+
+ for arg
+ do
+ # The only flag that cannot be specified is the output filename.
+ if test "X$arg" = "X-o"; then
+ $echo "$progname: you cannot specify the output filename with \`-o'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ # Accept the current argument as the source file.
+ lastarg="$srcfile"
+ srcfile="$arg"
+
+ # Aesthetically quote the previous argument.
+
+ # Backslashify any backslashes, double quotes, and dollar signs.
+ # These are the only characters that are still specially
+ # interpreted inside of double-quoted scrings.
+ lastarg=`$echo "$lastarg" | sed "$sed_quote_subst"`
+
+ # Double-quote args containing other shell metacharacters.
+ # Many Bourne shells cannot handle close brackets correctly in scan
+ # sets, so we specify it separately.
+ case "$lastarg" in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ lastarg="\"$lastarg\""
+ ;;
+ esac
+
+ # Add the previous argument to base_compile.
+ if test -z "$base_compile"; then
+ base_compile="$lastarg"
+ else
+ base_compile="$base_compile $lastarg"
+ fi
+ done
+
+ # Get the name of the library object.
+ libobj=`$echo "$srcfile" | sed -e 's%^.*/%%'`
+
+ # Recognize several different file suffixes.
+ xform='[cCFSfm]'
+ case "$libobj" in
+ *.c++) xform=c++ ;;
+ *.cc) xform=cc ;;
+ *.cpp) xform=cpp ;;
+ *.cxx) xform=cxx ;;
+ *.f90) xform=f90 ;;
+ *.for) xform=for ;;
+ esac
+
+ libobj=`$echo "$libobj" | sed -e "s/\.$xform$/.lo/"`
+
+ case "$libobj" in
+ *.lo) obj=`$echo "$libobj" | sed -e 's/\.lo$/.o/'` ;;
+ *)
+ $echo "$progname: cannot determine name of library object from \`$srcfile'" 1>&2
+ exit 1
+ ;;
+ esac
+
+ if test -z "$base_compile"; then
+ $echo "$progname: you must specify a compilation command" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ # Delete any leftover library objects.
+ if test "$build_old_libs" = yes; then
+ $run $rm $obj $libobj
+ trap "$run $rm $obj $libobj; exit 1" 1 2 15
+ else
+ $run $rm $libobj
+ trap "$run $rm $libobj; exit 1" 1 2 15
+ fi
+
+ # Only build a PIC object if we are building libtool libraries.
+ if test "$build_libtool_libs" = yes; then
+ # Without this assignment, base_compile gets emptied.
+ fbsd_hideous_sh_bug=$base_compile
+
+ # All platforms use -DPIC, to notify preprocessed assembler code.
+ $show "$base_compile$pic_flag -DPIC $srcfile"
+ if $run eval "$base_compile\$pic_flag -DPIC \$srcfile"; then :
+ else
+ test -n "$obj" && $run $rm $obj
+ exit 1
+ fi
+
+ # If we have no pic_flag, then copy the object into place and finish.
+ if test -z "$pic_flag"; then
+ $show "$LN_S $obj $libobj"
+ $run $LN_S $obj $libobj
+ exit $?
+ fi
+
+ # Just move the object, then go on to compile the next one
+ $show "$mv $obj $libobj"
+ $run $mv $obj $libobj || exit 1
+
+ # Allow error messages only from the first compilation.
+ suppress_output=' >/dev/null 2>&1'
+ fi
+
+ # Only build a position-dependent object if we build old libraries.
+ if test "$build_old_libs" = yes; then
+ # Suppress compiler output if we already did a PIC compilation.
+ $show "$base_compile $srcfile$suppress_output"
+ if $run eval "$base_compile \$srcfile$suppress_output"; then :
+ else
+ $run $rm $obj $libobj
+ exit 1
+ fi
+ fi
+
+ # Create an invalid libtool object if no PIC, so that we don't accidentally
+ # link it into a program.
+ if test "$build_libtool_libs" != yes; then
+ $show "$echo timestamp > $libobj"
+ $run eval "\$echo timestamp > \$libobj" || exit $?
+ fi
+
+ exit 0
+ ;;
+
+ # libtool link mode
+ link)
+ progname="$progname: link"
+ CC="$nonopt"
+ allow_undefined=no
+ compile_command="$CC"
+ finalize_command="$CC"
+
+ compile_shlibpath=
+ finalize_shlibpath=
+ deplibs=
+ dlfiles=
+ dlprefiles=
+ export_dynamic=no
+ hardcode_libdirs=
+ libobjs=
+ link_against_libtool_libs=
+ ltlibs=
+ objs=
+ prev=
+ prevarg=
+ rpath=
+ perm_rpath=
+ temp_rpath=
+ vinfo=
+
+ # We need to know -static, to get the right output filenames.
+ for arg
+ do
+ case "$arg" in
+ -all-static | -static)
+ if test "X$arg" = "X-all-static" && test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
+ $echo "$progname: warning: complete static linking is impossible in this configuration" 1>&2
+ fi
+ build_libtool_libs=no
+ build_old_libs=yes
+ break
+ ;;
+ esac
+ done
+
+ # See if our shared archives depend on static archives.
+ test -n "$old_archive_from_new_cmds" && build_old_libs=yes
+
+ # Go through the arguments, transforming them on the way.
+ for arg
+ do
+ # If the previous option needs an argument, assign it.
+ if test -n "$prev"; then
+ case "$prev" in
+ output)
+ compile_command="$compile_command @OUTPUT@"
+ finalize_command="$finalize_command @OUTPUT@"
+ ;;
+ esac
+
+ case "$prev" in
+ dlfiles|dlprefiles)
+ case "$arg" in
+ *.la | *.lo) ;; # We handle these cases below.
+ *)
+ dlprefiles="$dlprefiles $arg"
+ test "$prev" = dlfiles && dlfiles="$dlfiles $arg"
+ prev=
+ ;;
+ esac
+ ;;
+ rpath)
+ rpath="$rpath $arg"
+ prev=
+ continue
+ ;;
+ *)
+ eval "$prev=\"\$arg\""
+ prev=
+ continue
+ ;;
+ esac
+ fi
+
+ prevarg="$arg"
+
+ case "$arg" in
+ -all-static)
+ if test -n "$link_static_flag"; then
+ compile_command="$compile_command $link_static_flag"
+ finalize_command="$finalize_command $link_static_flag"
+ fi
+ continue
+ ;;
+
+ -allow-undefined)
+ allow_undefined=yes
+ continue
+ ;;
+
+ -dlopen)
+ prev=dlfiles
+ continue
+ ;;
+
+ -dlpreopen)
+ prev=dlprefiles
+ continue
+ ;;
+
+ -export-dynamic)
+ if test "$export_dynamic" != yes; then
+ export_dynamic=yes
+ if test -n "$export_dynamic_flag_spec"; then
+ arg=`eval \\$echo "$export_dynamic_flag_spec"`
+ else
+ arg=
+ fi
+
+ # Add the symbol object into the linking commands.
+ compile_command="$compile_command @SYMFILE@"
+ finalize_command="$finalize_command @SYMFILE@"
+ fi
+ ;;
+
+ -L*)
+ dir=`$echo "$arg" | sed 's%^-L\(.*\)$%\1%'`
+ case "$dir" in
+ /*)
+ # Add the corresponding hardcode_libdir_flag, if it is not identical.
+ ;;
+ *)
+ $echo "$progname: \`-L$dir' cannot specify a relative directory" 1>&2
+ exit 1
+ ;;
+ esac
+ deplibs="$deplibs $arg"
+ ;;
+
+ -l*) deplibs="$deplibs $arg" ;;
+
+ -o) prev=output ;;
+
+ -rpath)
+ prev=rpath
+ continue
+ ;;
+
+ -static)
+ # If we have no pic_flag, then this is the same as -all-static.
+ if test -z "$pic_flag" && test -n "$link_static_flag"; then
+ compile_command="$compile_command $link_static_flag"
+ finalize_command="$finalize_command $link_static_flag"
+ fi
+ continue
+ ;;
+
+ -version-info)
+ prev=vinfo
+ continue
+ ;;
+
+ # Some other compiler flag.
+ -* | +*)
+ # Unknown arguments in both finalize_command and compile_command need
+ # to be aesthetically quoted because they are evaled later.
+ arg=`$echo "$arg" | sed "$sed_quote_subst"`
+ case "$arg" in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ arg="\"$arg\""
+ ;;
+ esac
+ ;;
+
+ *.o | *.a)
+ # A standard object.
+ objs="$objs $arg"
+ ;;
+
+ *.lo)
+ # A library object.
+ if test "$prev" = dlfiles; then
+ dlfiles="$dlfiles $arg"
+ if test "$build_libtool_libs" = yes; then
+ prev=
+ continue
+ else
+ # If libtool objects are unsupported, then we need to preload.
+ prev=dlprefiles
+ fi
+ fi
+
+ if test "$prev" = dlprefiles; then
+ # Preload the old-style object.
+ dlprefiles="$dlprefiles "`$echo "$arg" | sed 's/\.lo$/\.o/'`
+ prev=
+ fi
+ libobjs="$libobjs $arg"
+ ;;
+
+ *.la)
+ # A libtool-controlled library.
+
+ dlname=
+ libdir=
+ library_names=
+ old_library=
+
+ # Check to see that this really is a libtool archive.
+ if egrep '^# Generated by ltmain.sh' $arg >/dev/null 2>&1; then :
+ else
+ $echo "$progname: \`$arg' is not a valid libtool archive" 1>&2
+ exit 1
+ fi
+
+ # If there is no directory component, then add one.
+ case "$arg" in
+ */*) . $arg ;;
+ *) . ./$arg ;;
+ esac
+
+ if test -z "$libdir"; then
+ $echo "$progname: \`$arg' contains no -rpath information" 1>&2
+ exit 1
+ fi
+
+ # Get the name of the library we link against.
+ linklib=
+ for l in $old_library $library_names; do
+ linklib="$l"
+ done
+
+ if test -z "$linklib"; then
+ $echo "$progname: cannot find name of link library for \`$arg'" 1>&2
+ exit 1
+ fi
+
+ # Find the relevant object directory and library name.
+ name=`$echo "$arg" | sed -e 's%^.*/%%' -e 's/\.la$//' -e 's/^lib//'`
+ dir=`$echo "$arg" | sed 's%/[^/]*$%%'`
+ if test "X$dir" = "X$arg"; then
+ dir="$objdir"
+ else
+ dir="$dir/$objdir"
+ fi
+
+ # This library was specified with -dlopen.
+ if test "$prev" = dlfiles; then
+ dlfiles="$dlfiles $arg"
+ if test -z "$dlname"; then
+ # If there is no dlname, we need to preload.
+ prev=dlprefiles
+ else
+ # We should not create a dependency on this library.
+ prev=
+ continue
+ fi
+ fi
+
+ # The library was specified with -dlpreopen.
+ if test "$prev" = dlprefiles; then
+ # Prefer using a static library (so that no silly _DYNAMIC symbols
+ # are required to link).
+ if test -n "$old_library"; then
+ dlprefiles="$dlprefiles $dir/$old_library"
+ else
+ dlprefiles="$dlprefiles $dir/$linklib"
+ fi
+ prev=
+ fi
+
+ if test "$build_libtool_libs" = yes && test -n "$library_names"; then
+ link_against_libtool_libs="$link_against_libtool_libs $arg"
+ if test -n "$shlibpath_var"; then
+ # Make sure the rpath contains only unique directories.
+ case "$temp_rpath " in
+ *" $dir "*) ;;
+ *) temp_rpath="$temp_rpath $dir" ;;
+ esac
+ fi
+
+ # This is the magic to use -rpath.
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ # Put the magic libdir with the hardcode flag.
+ hardcode_libdirs="$libdir"
+ libdir="@HARDCODE_LIBDIRS@"
+ else
+ # Just accumulate the unique libdirs.
+ case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ libdir=
+ fi
+ fi
+
+ if test -n "$libdir"; then
+ flag=`eval \\$echo \"$hardcode_libdir_flag_spec\"`
+
+ compile_command="$compile_command $flag"
+ finalize_command="$finalize_command $flag"
+ fi
+ elif test "$hardcode_runpath_var" = yes; then
+ # Do the same for the permanent run path.
+ case "$perm_rpath " in
+ *" $libdir "*) ;;
+ *) perm_rpath="$perm_rpath $libdir" ;;
+ esac
+ fi
+
+
+ case "$hardcode_action" in
+ immediate)
+ if test "$hardcode_direct" = no; then
+ compile_command="$compile_command $dir/$linklib"
+ elif test "$hardcode_minus_L" = no; then
+ compile_command="$compile_command -L$dir -l$name"
+ elif test "$hardcode_shlibpath_var" = no; then
+ compile_shlibpath="$compile_shlibpath$dir:"
+ compile_command="$compile_command -l$name"
+ fi
+ ;;
+
+ relink)
+ # We need an absolute path.
+ case "$dir" in
+ /*) ;;
+ *)
+ absdir=`cd "$dir" && pwd`
+ if test -z "$absdir"; then
+ $echo "$progname: cannot determine absolute directory name of \`$dir'" 1>&2
+ exit 1
+ fi
+ dir="$absdir"
+ ;;
+ esac
+
+ if test "$hardcode_direct" = yes; then
+ compile_command="$compile_command $dir/$linklib"
+ elif test "$hardcode_minus_L" = yes; then
+ compile_command="$compile_command -L$dir -l$name"
+ elif test "$hardcode_shlibpath_var" = yes; then
+ compile_shlibpath="$compile_shlibpath$dir:"
+ compile_command="$compile_command -l$name"
+ fi
+ ;;
+
+ *)
+ $echo "$progname: \`$hardcode_action' is an unknown hardcode action" 1>&2
+ exit 1
+ ;;
+ esac
+
+ # Finalize command for both is simple: just hardcode it.
+ if test "$hardcode_direct" = yes; then
+ finalize_command="$finalize_command $libdir/$linklib"
+ elif test "$hardcode_minus_L" = yes; then
+ finalize_command="$finalize_command -L$libdir -l$name"
+ elif test "$hardcode_shlibpath_var" = yes; then
+ finalize_shlibpath="$finalize_shlibpath$libdir:"
+ finalize_command="$finalize_command -l$name"
+ else
+ # We can't seem to hardcode it, guess we'll fake it.
+ finalize_command="$finalize_command -L$libdir -l$name"
+ fi
+ else
+ # Transform directly to old archives if we don't build new libraries.
+ if test -n "$pic_flag" && test -z "$old_library"; then
+ $echo "$progname: cannot find static library for \`$arg'" 1>&2
+ exit 1
+ fi
+
+ # Here we assume that one of hardcode_direct or hardcode_minus_L
+ # is not unsupported. This is valid on all known static and
+ # shared platforms.
+ if test "$hardcode_direct" != unsupported; then
+ test -n "$old_library" && linklib="$old_library"
+ compile_command="$compile_command $dir/$linklib"
+ finalize_command="$finalize_command $dir/$linklib"
+ else
+ compile_command="$compile_command -L$dir -l$name"
+ finalize_command="$finalize_command -L$dir -l$name"
+ fi
+ fi
+ continue
+ ;;
+
+ # Some other compiler argument.
+ *)
+ # Unknown arguments in both finalize_command and compile_command need
+ # to be aesthetically quoted because they are evaled later.
+ arg=`$echo "$arg" | sed "$sed_quote_subst"`
+ case "$arg" in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ arg="\"$arg\""
+ ;;
+ esac
+ ;;
+ esac
+
+ # Now actually substitute the argument into the commands.
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ done
+
+ if test -n "$prev"; then
+ $echo "$progname: the \`$prevarg' option requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ oldlib=
+ oldobjs=
+ case "$output" in
+ "")
+ $echo "$progname: you must specify an output file" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+
+ */*)
+ $echo "$progname: output file \`$output' must have no directory components" 1>&2
+ exit 1
+ ;;
+
+ *.la)
+ # Make sure we only generate libraries of the form `libNAME.la'.
+ case "$output" in
+ lib*) ;;
+ *)
+ $echo "$progname: libtool library \`$arg' must begin with \`lib'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+ esac
+
+ name=`$echo "$output" | sed -e 's/\.la$//' -e 's/^lib//'`
+ libname=`eval \\$echo \"$libname_spec\"`
+
+ # All the library-specific variables (install_libdir is set above).
+ library_names=
+ old_library=
+ dlname=
+ current=0
+ revision=0
+ age=0
+
+ if test -n "$objs"; then
+ $echo "$progname: cannot build libtool library \`$output' from non-libtool objects:$objs" 2>&1
+ exit 1
+ fi
+
+ # How the heck are we supposed to write a wrapper for a shared library?
+ if test -n "$link_against_libtool_libs"; then
+ $echo "$progname: libtool library \`$output' may not depend on uninstalled libraries:$link_against_libtool_libs" 1>&2
+ exit 1
+ fi
+
+ # Add libc to deplibs on all systems.
+ deplibs="$deplibs -lc"
+
+ if test -n "$dlfiles$dlprefiles"; then
+ $echo "$progname: warning: \`-dlopen' is ignored while creating libtool libraries" 1>&2
+ # Nullify the symbol file.
+ compile_command=`$echo "$compile_command" | sed "s% @SYMFILE@%%"`
+ finalize_command=`$echo "$finalize_command" | sed "s% @SYMFILE@%%"`
+ fi
+
+ if test -z "$rpath"; then
+ $echo "$progname: you must specify an installation directory with \`-rpath'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ set dummy $rpath
+ if test $# -gt 2; then
+ $echo "$progname: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2
+ fi
+ install_libdir="$2"
+
+ # Parse the version information argument.
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS=':'
+ set dummy $vinfo
+ IFS="$save_ifs"
+
+ if test -n "$5"; then
+ $echo "$progname: too many parameters to \`-version-info'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ test -n "$2" && current="$2"
+ test -n "$3" && revision="$3"
+ test -n "$4" && age="$4"
+
+ # Check that each of the things are valid numbers.
+ case "$current" in
+ 0 | [1-9] | [1-9][0-9]*) ;;
+ *)
+ $echo "$progname: CURRENT \`$current' is not a nonnegative integer" 1>&2
+ $echo "$progname: \`$vinfo' is not valid version information" 1>&2
+ exit 1
+ ;;
+ esac
+
+ case "$revision" in
+ 0 | [1-9] | [1-9][0-9]*) ;;
+ *)
+ $echo "$progname: REVISION \`$revision' is not a nonnegative integer" 1>&2
+ $echo "$progname: \`$vinfo' is not valid version information" 1>&2
+ exit 1
+ ;;
+ esac
+
+ case "$age" in
+ 0 | [1-9] | [1-9][0-9]*) ;;
+ *)
+ $echo "$progname: AGE \`$age' is not a nonnegative integer" 1>&2
+ $echo "$progname: \`$vinfo' is not valid version information" 1>&2
+ exit 1
+ ;;
+ esac
+
+ if test $age -gt $current; then
+ $echo "$progname: AGE \`$age' is greater than the current interface number \`$current'" 1>&2
+ $echo "$progname: \`$vinfo' is not valid version information" 1>&2
+ exit 1
+ fi
+
+ # Calculate the version variables.
+ version_vars="version_type current age revision"
+ case "$version_type" in
+ none) ;;
+
+ linux)
+ version_vars="$version_vars major versuffix"
+ major=`expr $current - $age`
+ versuffix="$major.$age.$revision"
+ ;;
+
+ osf)
+ version_vars="$version_vars versuffix verstring"
+ major=`expr $current - $age`
+ versuffix="$current.$age.$revision"
+ verstring="$versuffix"
+
+ # Add in all the interfaces that we are compatible with.
+ loop=$age
+ while test $loop != 0; do
+ iface=`expr $current - $loop`
+ loop=`expr $loop - 1`
+ verstring="$verstring:${iface}.0"
+ done
+
+ # Make executables depend on our current version.
+ verstring="$verstring:${current}.0"
+ ;;
+
+ sunos)
+ version_vars="$version_vars major versuffix"
+ major="$current"
+ versuffix="$current.$revision"
+ ;;
+
+ *)
+ $echo "$progname: unknown library version type \`$version_type'" 1>&2
+ $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
+ exit 1
+ ;;
+ esac
+
+ # Create the output directory, or remove our outputs if we need to.
+ if test -d $objdir; then
+ $show "$rm $objdir/$output $objdir/$libname.*"
+ $run $rm $objdir/$output $objdir/$libname.*
+ else
+ $show "$mkdir $objdir"
+ $run $mkdir $objdir
+ status=$?
+ if test $status -eq 0 || test -d $objdir; then :
+ else
+ exit $status
+ fi
+ fi
+
+ # Check to see if the archive will have undefined symbols.
+ if test "$allow_undefined" = yes; then
+ if test "$allow_undefined_flag" = unsupported; then
+ $echo "$progname: warning: undefined symbols not allowed in $host shared libraries" 1>&2
+ build_libtool_libs=no
+ build_old_libs=yes
+ fi
+ else
+ # Clear the flag.
+ allow_undefined_flag=
+ fi
+
+ if test "$build_libtool_libs" = yes; then
+ # Get the real and link names of the library.
+ library_names=`eval \\$echo \"$library_names_spec\"`
+ set dummy $library_names
+ realname="$2"
+ shift; shift
+
+ if test -n "$soname_spec"; then
+ soname=`eval \\$echo \"$soname_spec\"`
+ else
+ soname="$realname"
+ fi
+
+ lib="$objdir/$realname"
+ for link
+ do
+ linknames="$linknames $link"
+ done
+
+ # Use standard objects if they are PIC.
+ test -z "$pic_flag" && libobjs=`$echo "$libobjs " | sed -e 's/\.lo /.o /g' -e 's/ $//g'`
+
+ # Do each of the archive commands.
+ cmds=`eval \\$echo \"$archive_cmds\"`
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS=';'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+
+ # Create links to the real library.
+ for link in $linknames; do
+ $show "(cd $objdir && $LN_S $realname $link)"
+ $run eval '(cd $objdir && $LN_S $realname $link)' || exit $?
+ done
+
+ # If -export-dynamic was specified, set the dlname.
+ if test "$export_dynamic" = yes; then
+ # On all known operating systems, these are identical.
+ dlname="$soname"
+ fi
+ fi
+ ;;
+
+ *.lo | *.o)
+ if test -n "$link_against_libtool_libs"; then
+ $echo "$progname: error: cannot link libtool libraries into reloadable objects" 1>&2
+ exit 1
+ fi
+
+ if test -n "$deplibs"; then
+ $echo "$progname: warning: \`-l' and \`-L' are ignored while creating objects" 1>&2
+ fi
+
+ if test -n "$dlfiles$dlprefiles"; then
+ $echo "$progname: warning: \`-dlopen' is ignored while creating objects" 1>&2
+ # Nullify the symbol file.
+ compile_command=`$echo "$compile_command" | sed "s% @SYMFILE@%%"`
+ finalize_command=`$echo "$finalize_command" | sed "s% @SYMFILE@%%"`
+ fi
+
+ if test -n "$rpath"; then
+ $echo "$progname: warning: \`-rpath' is ignored while creating objects" 1>&2
+ fi
+
+ if test -n "$vinfo"; then
+ $echo "$progname: warning: \`-version-info' is ignored while creating objects" 1>&2
+ fi
+
+ case "$output" in
+ *.lo)
+ if test -n "$objs"; then
+ $echo "$progname: cannot build library object \`$output' from non-libtool objects" 1>&2
+ exit 1
+ fi
+ libobj="$output"
+ obj=`$echo "$output" | sed 's/\.lo$/.o/'`
+ ;;
+ *)
+ libobj=
+ obj="$output"
+ ;;
+ esac
+
+ # Delete the old objects.
+ $run $rm $obj $libobj
+
+ # Create the old-style object.
+ reload_objs="$objs"`$echo "$libobjs " | sed -e 's/[^ ]*\.a //g' -e 's/\.lo /.o /g' -e 's/ $//g'`
+
+ output="$obj"
+ cmds=`eval \\$echo \"$reload_cmds\"`
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS=';'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+
+ # Exit if we aren't doing a library object file.
+ test -z "$libobj" && exit 0
+
+ if test "$build_libtool_libs" != yes; then
+ # Create an invalid libtool object if no PIC, so that we don't
+ # accidentally link it into a program.
+ $show "$echo timestamp > $libobj"
+ $run eval "\$echo timestamp > $libobj" || exit $?
+ exit 0
+ fi
+
+ if test -n "$pic_flag"; then
+ # Only do commands if we really have different PIC objects.
+ reload_objs="$libobjs"
+ output="$libobj"
+ cmds=`eval \\$echo \"$reload_cmds\"`
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS=';'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ else
+ # Just create a symlink.
+ $show "$LN_S $obj $libobj"
+ $run $LN_S $obj $libobj || exit 1
+ fi
+
+ exit 0
+ ;;
+
+ *)
+ if test -n "$vinfo"; then
+ $echo "$progname: warning: \`-version-info' is ignored while linking programs" 1>&2
+ fi
+
+ if test -n "$rpath"; then
+ # If the user specified any rpath flags, then add them.
+ for libdir in $rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ # Put the magic libdir with the hardcode flag.
+ hardcode_libdirs="$libdir"
+ libdir="@HARDCODE_LIBDIRS@"
+ else
+ # Just accumulate the unique libdirs.
+ case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ libdir=
+ fi
+ fi
+
+ if test -n "$libdir"; then
+ flag=`eval \\$echo \"$hardcode_libdir_flag_spec\"`
+
+ compile_command="$compile_command $flag"
+ finalize_command="$finalize_command $flag"
+ fi
+ elif test "$hardcode_runpath_var" = yes; then
+ case "$perm_rpath " in
+ *" $libdir "*) ;;
+ *) perm_rpath="$perm_rpath $libdir" ;;
+ esac
+ fi
+ done
+ fi
+
+ # Substitute the hardcoded libdirs into the compile commands.
+ if test -n "$hardcode_libdir_separator"; then
+ compile_command=`$echo "$compile_command" | sed "s%@HARDCODE_LIBDIRS@%$hardcode_libdirs%g"`
+ finalize_command=`$echo "$finalize_command" | sed "s%@HARDCODE_LIBDIRS@%$hardcode_libdirs%g"`
+ fi
+
+ if test -n "$libobjs" && test "$build_old_libs" = yes; then
+ # Transform all the library objects into standard objects.
+ compile_command=`$echo "$compile_command " | sed -e 's/\.lo /.o /g' -e 's/ $//'`
+ finalize_command=`$echo "$finalize_command " | sed -e 's/\.lo /.o /g' -e 's/ $//'`
+ fi
+
+ if test "$export_dynamic" = yes && test -n "$NM" && test -n "$global_symbol_pipe"; then
+ dlsyms="${output}S.c"
+ else
+ dlsyms=
+ fi
+
+ if test -n "$dlsyms"; then
+ # Add our own program objects to the preloaded list.
+ dlprefiles=`$echo "$objs$dlprefiles " | sed -e 's/\.lo /.o /g' -e 's/ $//'`
+
+ # Discover the nlist of each of the dlfiles.
+ nlist="$objdir/${output}.nm"
+
+ if test -d $objdir; then
+ $show "$rm $nlist ${nlist}T"
+ $run $rm "$nlist" "${nlist}T"
+ else
+ $show "$mkdir $objdir"
+ $run $mkdir $objdir
+ status=$?
+ if test $status -eq 0 || test -d $objdir; then :
+ else
+ exit $status
+ fi
+ fi
+
+ for arg in $dlprefiles; do
+ $show "extracting global C symbols from \`$arg'"
+ $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
+ done
+
+ # Parse the name list into a source file.
+ $show "creating $objdir/$dlsyms"
+ if test -z "$run"; then
+ # Make sure we at least have an empty file.
+ test -f "$nlist" || : > "$nlist"
+
+ # Try sorting and uniquifying the output.
+ if sort "$nlist" | uniq > "$nlist"T; then
+ mv -f "$nlist"T "$nlist"
+ wcout=`wc "$nlist" 2>/dev/null`
+ count=`$echo "$wcout" | sed 's/^[ ]*\([0-9][0-9]*\).*$/\1/'`
+ (test "$count" -ge 0) 2>/dev/null || count=-1
+ else
+ $rm "$nlist"T
+ count=-1
+ fi
+
+ case "$dlsyms" in
+ "") ;;
+ *.c)
+ cat <<EOF > "$objdir/$dlsyms"
+/* $dlsyms - symbol resolution table for \`$output' dlsym emulation. */
+/* Generated by $PROGRAM - GNU $PACKAGE $VERSION */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Prevent the only kind of declaration conflicts we can make. */
+#define dld_preloaded_symbol_count some_other_symbol
+#define dld_preloaded_symbols some_other_symbol
+
+/* External symbol declarations for the compiler. */
+EOF
+ if test -f "$nlist"; then
+ sed -e 's/^.* \(.*\)$/extern char \1;/' < "$nlist" >> "$objdir/$dlsyms"
+ else
+ $echo '/* NONE */' >> "$objdir/$dlsyms"
+EOF
+ fi
+
+ cat <<EOF >> "$objdir/$dlsyms"
+
+#undef dld_preloaded_symbol_count
+#undef dld_preloaded_symbols
+
+#if defined (__STDC__) && __STDC__
+# define __ptr_t void *
+#else
+# define __ptr_t char *
+#endif
+
+/* The number of symbols in dld_preloaded_symbols, -1 if unsorted. */
+int dld_preloaded_symbol_count = $count;
+
+/* The mapping between symbol names and symbols. */
+struct {
+ char *name;
+ __ptr_t address;
+}
+dld_preloaded_symbols[] =
+{
+EOF
+
+ if test -f "$nlist"; then
+ sed 's/^\(.*\) \(.*\)$/ {"\1", \&\2},/' < "$nlist" >> "$objdir/$dlsyms"
+ fi
+
+ cat <<\EOF >> "$objdir/$dlsyms"
+ {0},
+};
+
+#ifdef __cplusplus
+}
+#endif
+EOF
+ ;;
+
+ *)
+ echo "$progname: unknown suffix for \`$dlsyms'" 1>&2
+ exit 1
+ ;;
+ esac
+ fi
+
+ # Now compile the dynamic symbol file.
+ $show "(cd $objdir && $CC -c$no_builtin_flag \"$dlsyms\")"
+ $run eval '(cd $objdir && $CC -c$no_builtin_flag "$dlsyms")' || exit $?
+
+ # Transform the symbol file into the correct name.
+ compile_command=`$echo "$compile_command" | sed "s%@SYMFILE@%$objdir/${output}S.o%"`
+ finalize_command=`$echo "$finalize_command" | sed "s%@SYMFILE@%$objdir/${output}S.o%"`
+ elif test "$export_dynamic" != yes; then
+ test -n "$dlfiles$dlprefiles" && $echo "$progname: warning: \`-dlopen' and \`-dlpreopen' are ignored without \`-export-dynamic'" 1>&2
+ else
+ # We keep going just in case the user didn't refer to
+ # dld_preloaded_symbols. The linker will fail if global_symbol_pipe
+ # really was required.
+ $echo "$progname: not configured to extract global symbols from dlpreopened files" 1>&2
+
+ # Nullify the symbol file.
+ compile_command=`$echo "$compile_command" | sed "s% @SYMFILE@%%"`
+ finalize_command=`$echo "$finalize_command" | sed "s% @SYMFILE@%%"`
+ fi
+
+ if test -z "$link_against_libtool_libs" || test "$build_libtool_libs" != yes; then
+ # Replace the output file specification.
+ compile_command=`$echo "$compile_command" | sed 's%@OUTPUT@%'"$output"'%g'`
+ finalize_command=`$echo "$finalize_command" | sed 's%@OUTPUT@%'"$output"'%g'`
+
+ # We have no uninstalled library dependencies, so finalize right now.
+ $show "$compile_command"
+ $run eval "$compile_command"
+ exit $?
+ fi
+
+ # Replace the output file specification.
+ compile_command=`$echo "$compile_command" | sed 's%@OUTPUT@%'"$objdir/$output"'%g'`
+ finalize_command=`$echo "$finalize_command" | sed 's%@OUTPUT@%'"$objdir/$output"'T%g'`
+
+ # Create the binary in the object directory, then wrap it.
+ if test -d $objdir; then :
+ else
+ $show "$mkdir $objdir"
+ $run $mkdir $objdir || exit $?
+ fi
+
+ if test -n "$shlibpath_var"; then
+ # We should set the shlibpath_var
+ rpath=
+ for dir in $temp_rpath; do
+ case "$dir" in
+ /*)
+ # Absolute path.
+ rpath="$rpath$dir:"
+ ;;
+ *)
+ # Relative path: add a thisdir entry.
+ rpath="$rpath\$thisdir/$dir:"
+ ;;
+ esac
+ done
+ temp_rpath="$rpath"
+ fi
+
+ # Delete the old output file.
+ $run $rm $output
+
+ if test -n "$compile_shlibpath"; then
+ compile_command="$shlibpath_var=\"$compile_shlibpath\$$shlibpath_var\" $compile_command"
+ fi
+ if test -n "$finalize_shlibpath"; then
+ finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
+ fi
+
+ if test -n "$perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $perm_rpath; do
+ rpath="$rpath$dir:"
+ done
+ compile_command="$runpath_var=\"$rpath\$$runpath_var\" $compile_command"
+ finalize_command="$runpath_var=\"$rpath\$$runpath_var\" $finalize_command"
+ fi
+
+ case "$hardcode_action" in
+ relink)
+ # AGH! Flame the AIX and HP-UX people for me, will ya?
+ $echo "$progname: warning: using a buggy system linker" 1>&2
+ $echo "$progname: relinking will be required before \`$output' can be installed" 1>&2
+ ;;
+ esac
+
+ $show "$compile_command"
+ $run eval "$compile_command" || exit $?
+
+ # Now create the wrapper script.
+ $show "creating $output"
+
+ # Quote the finalize command for shipping.
+ finalize_command=`$echo "$finalize_command" | sed "$sed_quote_subst"`
+
+ # Only actually do things if our run command is non-null.
+ if test -z "$run"; then
+ $rm $output
+ trap "$rm $output; exit 1" 1 2 15
+
+ cat > $output <<EOF
+#! /bin/sh
+
+# $output - temporary wrapper script for $objdir/$output
+# Generated by ltmain.sh - GNU $PACKAGE $VERSION
+#
+# The $output program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of \``pwd`'.
+# If it is, it will not operate correctly.
+
+# This environment variable determines our operation mode.
+if test "\$libtool_install_magic" = "$magic"; then
+ # install mode needs the following variables:
+ link_against_libtool_libs='$link_against_libtool_libs'
+ finalize_command="$finalize_command"
+else
+ # When we are sourced in execute mode, \$file and \$echo are already set.
+ if test "\$libtool_execute_magic" = "$magic"; then :
+ else
+ echo='$echo'
+ file="\$0"
+ fi
+
+ # Find the directory that this script lives in.
+ thisdir=\`\$echo "\$file" | sed 's%/[^/]*$%%'\`
+ test "x\$thisdir" = "x\$file" && thisdir=.
+
+ # Follow symbolic links until we get to the real thisdir.
+ file=\`ls -ld "\$file" | sed -n 's/.*-> //p'\`
+ while test -n "\$file"; do
+ destdir=\`\$echo "\$file" | sed 's%/[^/]*\$%%'\`
+
+ # If there was a directory component, then change thisdir.
+ if test "x\$destdir" != "x\$file"; then
+ case "\$destdir" in
+ /*) thisdir="\$destdir" ;;
+ *) thisdir="\$thisdir/\$destdir" ;;
+ esac
+ fi
+
+ file=\`\$echo "\$file" | sed 's%^.*/%%'\`
+ file=\`ls -ld "\$thisdir/\$file" | sed -n 's/.*-> //p'\`
+ done
+
+ # Try to get the absolute directory name.
+ absdir=\`cd "\$thisdir" && pwd\`
+ test -n "\$absdir" && thisdir="\$absdir"
+
+ progdir="\$thisdir/$objdir"
+ program='$output'
+
+ if test -f "\$progdir/\$program"; then
+EOF
+
+ # Export our shlibpath_var if we have one.
+ if test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+ cat >> $output <<EOF
+ # Add our own library path to $shlibpath_var
+ $shlibpath_var="$temp_rpath\$$shlibpath_var"
+
+ # Some systems cannot cope with colon-terminated $shlibpath_var
+ $shlibpath_var=\`\$echo \$$shlibpath_var | sed -e 's/:*\$//'\`
+
+ export $shlibpath_var
+
+EOF
+ fi
+
+ cat >> $output <<EOF
+ if test "\$libtool_execute_magic" != "$magic"; then
+ # Run the actual program with our arguments.
+ args=
+ for arg
+ do
+ # Quote arguments (to preserve shell metacharacters).
+ sed_quote_subst='$sed_quote_subst'
+ arg=\`\$echo "\$arg" | sed "\$sed_quote_subst"\`
+ args="\$args \\"\$arg\\""
+ done
+
+ # Export the path to the program.
+ PATH="\$progdir:\$PATH"
+ export PATH
+
+ eval "exec \$program \$args"
+
+ \$echo "\$0: cannot exec \$program \$args"
+ exit 1
+ fi
+ else
+ # The program doesn't exist.
+ \$echo "\$0: error: \$progdir/\$program does not exist" 1>&2
+ \$echo "This script is just a wrapper for \$program." 1>&2
+ \$echo "See the $PACKAGE documentation for more information." 1>&2
+ exit 1
+ fi
+fi
+EOF
+ chmod +x $output
+ fi
+ exit 0
+ ;;
+ esac
+
+
+ # See if we need to build an old-fashioned archive.
+ if test "$build_old_libs" = "yes"; then
+ # Now set the variables for building old libraries.
+ oldlib="$objdir/$libname.a"
+
+ # Transform .lo files to .o files.
+ oldobjs="$objs"`$echo "$libobjs " | sed -e 's/[^ ]*\.a //g' -e 's/\.lo /.o /g' -e 's/ $//g'`
+
+ if test -d "$objdir"; then
+ $show "$rm $oldlib"
+ $run $rm $oldlib
+ else
+ $show "$mkdir $objdir"
+ $run $mkdir $objdir
+ fi
+
+ # Do each command in the archive commands.
+ if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
+ cmds=`eval \\$echo \"$old_archive_from_new_cmds\"`
+ else
+ cmds=`eval \\$echo \"$old_archive_cmds\"`
+ fi
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS=';'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ fi
+
+ # Now create the libtool archive.
+ case "$output" in
+ *.la)
+ old_library=
+ test "$build_old_libs" = yes && old_library="$libname.a"
+
+ $show "creating $output"
+
+ # Only create the output if not a dry run.
+ if test -z "$run"; then
+ cat > $output <<EOF
+# $output - a libtool library file
+# Generated by ltmain.sh - GNU $PACKAGE $VERSION
+
+# The name that we can dlopen(3).
+dlname='$dlname'
+
+# Names of this library.
+library_names='$library_names'
+
+# The name of the static archive.
+old_library='$old_library'
+
+# Version information for $libname.
+current=$current
+age=$age
+revision=$revision
+
+# Directory that this library needs to be installed in:
+libdir='$install_libdir'
+EOF
+ fi
+
+ # Do a symbolic link so that the libtool archive can be found in
+ # LD_LIBRARY_PATH before the program is installed.
+ $show "(cd $objdir && $LN_S ../$output $output)"
+ $run eval "(cd $objdir && $LN_S ../$output $output)" || exit 1
+ ;;
+ esac
+ exit 0
+ ;;
+
+ # libtool install mode
+ install)
+ progname="$progname: install"
+
+ # There may be an optional /bin/sh argument at the beginning of
+ # install_prog (especially on Windows NT).
+ if test "$nonopt" = "$SHELL"; then
+ # Aesthetically quote it.
+ arg=`$echo "$nonopt" | sed "$sed_quote_subst"`
+ case "$arg" in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$arg "
+ arg="$1"
+ shift
+ else
+ install_prog=
+ arg="$nonopt"
+ fi
+
+ # The real first argument should be the name of the installation program.
+ # Aesthetically quote it.
+ arg=`$echo "$arg" | sed "$sed_quote_subst"`
+ case "$arg" in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$install_prog$arg"
+
+ # We need to accept at least all the BSD install flags.
+ dest=
+ files=
+ opts=
+ prev=
+ install_type=
+ isdir=
+ stripme=
+ for arg
+ do
+ if test -n "$dest"; then
+ files="$files $dest"
+ dest="$arg"
+ continue
+ fi
+
+ case "$arg" in
+ -d) isdir=yes ;;
+ -f) prev="-f" ;;
+ -g) prev="-g" ;;
+ -m) prev="-m" ;;
+ -o) prev="-o" ;;
+ -s)
+ stripme=" -s"
+ continue
+ ;;
+ -*) ;;
+
+ *)
+ # If the previous option needed an argument, then skip it.
+ if test -n "$prev"; then
+ prev=
+ else
+ dest="$arg"
+ continue
+ fi
+ ;;
+ esac
+
+ # Aesthetically quote the argument.
+ arg=`$echo "$arg" | sed "$sed_quote_subst"`
+ case "$arg" in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$install_prog $arg"
+ done
+
+ if test -z "$install_prog"; then
+ $echo "$progname: you must specify an install program" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ if test -n "$prev"; then
+ $echo "$progname: the \`$prev' option requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ if test -z "$files"; then
+ if test -z "$dest"; then
+ $echo "$progname: no file or destination specified" 1>&2
+ else
+ $echo "$progname: you must specify a destination" 1>&2
+ fi
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ # Strip any trailing slash from the destination.
+ dest=`$echo "$dest" | sed 's%/$%%'`
+
+ # Check to see that the destination is a directory.
+ test -d "$dest" && isdir=yes
+ if test -n "$isdir"; then
+ destdir="$dest"
+ destname=
+ else
+ destdir=`$echo "$dest" | sed 's%/[^/]*$%%'`
+ test "X$destdir" = "X$dest" && destdir=.
+ destname=`$echo "$dest" | sed 's%^.*/%%'`
+
+ # Not a directory, so check to see that there is only one file specified.
+ set dummy $files
+ if test $# -gt 2; then
+ $echo "$progname: \`$dest' is not a directory" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+ fi
+ case "$destdir" in
+ /*) ;;
+ *)
+ for file in $files; do
+ case "$file" in
+ *.lo) ;;
+ *)
+ $echo "$progname: \`$destdir' must be an absolute directory name" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+ esac
+ done
+ ;;
+ esac
+
+ # This variable tells wrapper scripts just to set variables rather
+ # than running their programs.
+ libtool_install_magic="$magic"
+
+ staticlibs=
+ future_libdirs=
+ current_libdirs=
+ for file in $files; do
+
+ # Do each installation.
+ case "$file" in
+ *.a)
+ # Do the static libraries later.
+ staticlibs="$staticlibs $file"
+ ;;
+
+ *.la)
+ # Check to see that this really is a libtool archive.
+ if egrep '^# Generated by ltmain.sh' $file >/dev/null 2>&1; then :
+ else
+ $echo "$progname: \`$file' is not a valid libtool archive" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ library_names=
+ old_library=
+ # If there is no directory component, then add one.
+ case "$file" in
+ */*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Add the libdir to current_libdirs if it is the destination.
+ if test "X$destdir" = "X$libdir"; then
+ case "$current_libdirs " in
+ *" $libdir "*) ;;
+ *) current_libdirs="$current_libdirs $libdir" ;;
+ esac
+ else
+ # Note the libdir as a future libdir.
+ case "$future_libdirs " in
+ *" $libdir "*) ;;
+ *) future_libdirs="$future_libdirs $libdir" ;;
+ esac
+ fi
+
+ dir="`$echo "$file" | sed 's%/[^/]*$%%'`/"
+ test "X$dir" = "X$file/" && dir=
+ dir="$dir$objdir"
+
+ # See the names of the shared library.
+ set dummy $library_names
+ if test -n "$2"; then
+ realname="$2"
+ shift
+ shift
+
+ # Install the shared library and build the symlinks.
+ $show "$install_prog $dir/$realname $destdir/$realname"
+ $run eval "$install_prog $dir/$realname $destdir/$realname" || exit $?
+ test "X$dlname" = "X$realname" && dlname=
+
+ # Support stripping libraries.
+ if test -n "$stripme"; then
+ if test -n "$striplib"; then
+ $show "$striplib $destdir/$realname"
+ $run $striplib $destdir/$realname || exit $?
+ else
+ $echo "$progname: warning: no library stripping program" 1>&2
+ fi
+ fi
+
+ if test $# -gt 0; then
+ # Delete the old symlinks.
+ rmcmd="$rm"
+ for linkname
+ do
+ rmcmd="$rmcmd $destdir/$linkname"
+ done
+ $show "$rmcmd"
+ $run $rmcmd
+
+ # ... and create new ones.
+ for linkname
+ do
+ test "X$dlname" = "X$linkname" && dlname=
+ $show "(cd $destdir && $LN_S $realname $linkname)"
+ $run eval "(cd $destdir && $LN_S $realname $linkname)"
+ done
+ fi
+
+ if test -n "$dlname"; then
+ # Install the dynamically-loadable library.
+ $show "$install_prog $dir/$dlname $destdir/$dlname"
+ $run eval "$install_prog $dir/$dlname $destdir/$dlname" || exit $?
+ fi
+
+ # Do each command in the postinstall commands.
+ lib="$destdir/$realname"
+ cmds=`eval \\$echo \"$postinstall_cmds\"`
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS=';'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ fi
+
+ # Install the pseudo-library for information purposes.
+ name=`$echo "$file" | sed 's%^.*/%%'`
+ $show "$install_prog $file $destdir/$name"
+ $run eval "$install_prog $file $destdir/$name" || exit $?
+
+ # Maybe install the static library, too.
+ test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library"
+ ;;
+
+ *.lo)
+ # Install (i.e. copy) a libtool object.
+
+ # Figure out destination file name, if it wasn't already specified.
+ if test -n "$destname"; then
+ destfile="$destdir/$destname"
+ else
+ destfile=`$echo "$file" | sed 's%^.*/%%'`
+ destfile="$destdir/$destfile"
+ fi
+
+ # Deduce the name of the destination old-style object file.
+ case "$destfile" in
+ *.lo)
+ staticdest=`$echo "$destfile" | sed 's/\.lo$/\.o/'`
+ ;;
+ *.o)
+ staticdest="$destfile"
+ destfile=
+ ;;
+ *)
+ $echo "$progname: cannot copy a libtool object to \`$destfile'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+ esac
+
+ # Install the libtool object if requested.
+ if test -n "$destfile"; then
+ $show "$install_prog $file $destfile"
+ $run eval "$install_prog $file $destfile" || exit $?
+ fi
+
+ # Install the old object if enabled.
+ if test "$build_old_libs" = yes; then
+ # Deduce the name of the old-style object file.
+ staticobj=`$echo "$file" | sed 's/\.lo$/\.o/'`
+
+ $show "$install_prog $staticobj $staticdest"
+ $run eval "$install_prog \$staticobj \$staticdest" || exit $?
+ fi
+ exit 0
+ ;;
+
+ *)
+ # Do a test to see if this is really a libtool program.
+ if egrep '^# Generated by ltmain.sh' $file >/dev/null 2>&1; then
+ link_against_libtool_libs=
+ finalize_command=
+
+ # If there is no directory component, then add one.
+ case "$file" in
+ */*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Check the variables that should have been set.
+ if test -z "$link_against_libtool_libs" || test -z "$finalize_command"; then
+ $echo "$progname: invalid libtool wrapper script \`$file'" 1>&2
+ exit 1
+ fi
+
+ finalize=yes
+ for lib in $link_against_libtool_libs; do
+ # Check to see that each library is installed.
+ libdir=
+ if test -f "$lib"; then
+ # If there is no directory component, then add one.
+ case "$lib" in
+ */*) . $lib ;;
+ *) . ./$lib ;;
+ esac
+ fi
+ libfile="$libdir/`$echo "$lib" | sed 's%^.*/%%g'`"
+ if test -z "$libdir"; then
+ $echo "$progname: warning: \`$lib' contains no -rpath information" 1>&2
+ elif test -f "$libfile"; then :
+ else
+ $echo "$progname: warning: \`$lib' has not been installed in \`$libdir'" 1>&2
+ finalize=no
+ fi
+ done
+
+ if test "$hardcode_action" = relink; then
+ if test "$finalize" = yes; then
+ $echo "$progname: warning: relinking \`$file' on behalf of your buggy system linker" 1>&2
+ $show "$finalize_command"
+ if $run eval "$finalize_command"; then :
+ else
+ $echo "$progname: error: relink \`$file' with the above command before installing it" 1>&2
+ continue
+ fi
+ file="$objdir/$file"T
+ else
+ $echo "$progname: warning: cannot relink \`$file' on behalf of your buggy system linker" 1>&2
+ fi
+ else
+ # Install the binary that we compiled earlier.
+ file=`$echo "$file" | sed "s%\([^/]*\)$%$objdir/\1%"`
+ fi
+ fi
+
+ $show "$install_prog$stripme $file $dest"
+ $run eval "$install_prog\$stripme \$file \$dest" || exit $?
+ ;;
+ esac
+ done
+
+ for file in $staticlibs; do
+ name=`$echo "$file" | sed 's%^.*/%%'`
+
+ # Set up the ranlib parameters.
+ oldlib="$destdir/$name"
+
+ $show "$install_prog $file $oldlib"
+ $run eval "$install_prog \$file \$oldlib" || exit $?
+
+ # Support stripping libraries.
+ if test -n "$stripme"; then
+ if test -n "$old_striplib"; then
+ $show "$old_striplib $oldlib"
+ $run $old_striplib $oldlib || exit $?
+ else
+ $echo "$progname: warning: no static library stripping program" 1>&2
+ fi
+ fi
+
+ # Do each command in the postinstall commands.
+ cmds=`eval \\$echo \"$old_postinstall_cmds\"`
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS=';'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ done
+
+ if test -n "$future_libdirs"; then
+ $echo "$progname: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2
+ fi
+
+ if test -n "$current_libdirs"; then
+ # Maybe just do a dry run.
+ test -n "$run" && current_libdirs=" -n$current_libdirs"
+ exec $SHELL $0 --finish$current_libdirs
+ exit 1
+ fi
+
+ exit 0
+ ;;
+
+ # libtool finish mode
+ finish)
+ progname="$progname: finish"
+ libdirs="$nonopt"
+
+ if test -n "$finish_cmds" && test -n "$libdirs"; then
+ for dir
+ do
+ libdirs="$libdirs $dir"
+ done
+
+ for libdir in $libdirs; do
+ # Do each command in the postinstall commands.
+ cmds=`eval \\$echo \"$finish_cmds\"`
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS=';'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd"
+ done
+ IFS="$save_ifs"
+ done
+ fi
+
+ $echo "To link against installed libraries in LIBDIR, users may have to:"
+ if test -n "$shlibpath_var"; then
+ $echo " - add LIBDIR to their \`$shlibpath_var' environment variable"
+ fi
+ $echo " - use the \`-LLIBDIR' linker flag"
+ exit 0
+ ;;
+
+ # libtool execute mode
+ execute)
+ progname="$progname: execute"
+
+ # The first argument is the command name.
+ cmd="$nonopt"
+ if test -z "$cmd"; then
+ $echo "$progname: you must specify a COMMAND" 1>&2
+ $echo "$help"
+ exit 1
+ fi
+
+ # Handle -dlopen flags immediately.
+ for file in $execute_dlfiles; do
+ if test -f "$file"; then :
+ else
+ $echo "$progname: \`$file' is not a file" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ dir=
+ case "$file" in
+ *.la)
+ # Check to see that this really is a libtool archive.
+ if egrep '^# Generated by ltmain.sh' $file >/dev/null 2>&1; then :
+ else
+ $echo "$progname: \`$lib' is not a valid libtool archive" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ # Read the libtool library.
+ dlname=
+ library_names=
+
+ # If there is no directory component, then add one.
+ case "$file" in
+ */*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Skip this library if it cannot be dlopened.
+ if test -z "$dlname"; then
+ # Warn if it was a shared library.
+ test -n "$library_names" && $echo "$progname: warning: \`$file' was not linked with \`-export-dynamic'"
+ continue
+ fi
+
+ dir=`$echo "$file" | sed 's%/[^/]*$%%'`
+ test "X$dir" = "X$file" && dir=.
+
+ if test -f "$dir/$objdir/$dlname"; then
+ dir="$dir/$objdir"
+ else
+ $echo "$progname: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2
+ exit 1
+ fi
+ ;;
+
+ *.lo)
+ # Just add the directory containing the .lo file.
+ dir=`$echo "$file" | sed 's%/[^/]*$%%'`
+ test "X$dir" = "X$file" && dir=.
+ ;;
+
+ *)
+ $echo "$progname: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2
+ continue
+ ;;
+ esac
+
+ # Get the absolute pathname.
+ absdir=`cd "$dir" && pwd`
+ test -n "$absdir" && dir="$absdir"
+
+ # Now add the directory to shlibpath_var.
+ if eval "test -z \"\$$shlibpath_var\""; then
+ eval "$shlibpath_var=\"\$dir\""
+ else
+ eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
+ fi
+ done
+
+ # This variable tells wrapper scripts just to set shlibpath_var
+ # rather than running their programs.
+ libtool_execute_magic="$magic"
+
+ # Check if any of the arguments is a wrapper script.
+ args=
+ for file
+ do
+ case "$file" in
+ -*) ;;
+ *)
+ if egrep '^# Generated by ltmain.sh' $file >/dev/null 2>&1; then
+ # If there is no directory component, then add one.
+ case "$file" in
+ */*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Transform arg to wrapped name.
+ file="$progdir/$program"
+ fi
+ ;;
+ esac
+ # Quote arguments (to preserve shell metacharacters).
+ file=`$echo "$file" | sed "$sed_quote_subst"`
+ args="$args \"$file\""
+ done
+
+ if test -z "$run"; then
+ # Export the shlibpath_var.
+ eval "export $shlibpath_var"
+
+ # Now actually exec the command.
+ eval "exec \$cmd$args"
+
+ $echo "$progname: cannot exec \$cmd$args"
+ exit 1
+ else
+ # Display what would be done.
+ eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\""
+ $echo "export $shlibpath_var"
+ $echo "$cmd$args"
+ exit 0
+ fi
+ ;;
+
+ # libtool uninstall mode
+ uninstall)
+ progname="$progname: uninstall"
+ rm="$nonopt"
+ files=
+
+ for arg
+ do
+ case "$arg" in
+ -*) rm="$rm $arg" ;;
+ *) files="$files $arg" ;;
+ esac
+ done
+
+ if test -z "$rm"; then
+ $echo "$progname: you must specify an RM program" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ for file in $files; do
+ dir=`$echo "$file" | sed -e 's%/[^/]*$%%'`
+ test "X$dir" = "X$file" && dir=.
+ name=`$echo "$file" | sed -e 's%^.*/%%'`
+
+ rmfiles="$file"
+
+ case "$name" in
+ *.la)
+ # Possibly a libtool archive, so verify it.
+ if egrep '^# Generated by ltmain.sh' $file >/dev/null 2>&1; then
+ . $dir/$name
+
+ # Delete the libtool libraries and symlinks.
+ for n in $library_names; do
+ rmfiles="$rmfiles $dir/$n"
+ test "X$n" = "X$dlname" && dlname=
+ done
+ test -n "$dlname" && rmfiles="$rmfiles $dir/$dlname"
+ test -n "$old_library" && rmfiles="$rmfiles $dir/$old_library"
+
+ # FIXME: should reinstall the best remaining shared library.
+ fi
+ ;;
+
+ *.lo)
+ if test "$build_old_libs" = yes; then
+ oldobj=`$echo "$name" | sed 's/\.lo$/\.o/'`
+ rmfiles="$rmfiles $dir/$oldobj"
+ fi
+ ;;
+ esac
+
+ $show "$rm $rmfiles"
+ $run $rm $rmfiles
+ done
+ exit 0
+ ;;
+
+ "")
+ $echo "$progname: you must specify a MODE" 1>&2
+ $echo "$generic_help" 1>&2
+ exit 1
+ ;;
+ esac
+
+ $echo "$progname: invalid operation mode \`$mode'" 1>&2
+ $echo "$generic_help" 1>&2
+ exit 1
+fi # test -z "$show_help"
+
+# We need to display help for each of the modes.
+case "$mode" in
+"") cat <<EOF
+Usage: $progname [OPTION]... [MODE-ARG]...
+
+Provide generalized library-building support services.
+
+-n, --dry-run display commands without modifying any files
+ --features display configuration information and exit
+ --finish same as \`--mode=finish'
+ --help display this help message and exit
+ --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS]
+ --quiet same as \`--silent'
+ --silent don't print informational messages
+ --version print version information
+
+MODE must be one of the following:
+
+ compile compile a source file into a libtool object
+ execute automatically set library path, then run a program
+ finish complete the installation of libtool libraries
+ install install libraries or executables
+ link create a library or an executable
+ uninstall remove libraries from an installed directory
+
+MODE-ARGS vary depending on the MODE. Try \`$progname --help --mode=MODE' for
+a more detailed description of MODE.
+EOF
+ ;;
+
+compile)
+ cat <<EOF
+Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
+
+Compile a source file into a libtool library object.
+
+COMPILE-COMMAND is a command to be used in creating a \`standard' object file
+from the given SOURCEFILE.
+
+The output file name is determined by removing the directory component from
+SOURCEFILE, then substituting the C source code suffix \`.c' with the
+library object suffix, \`.lo'.
+EOF
+ ;;
+
+execute)
+ cat <<EOF
+Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]...
+
+Automatically set library path, then run a program.
+
+This mode accepts the following additional options:
+
+ -dlopen FILE add the directory containing FILE to the library path
+
+This mode sets the library path environment variable according to \`-dlopen'
+flags.
+
+If any of the ARGS are libtool executable wrappers, then they are translated
+into their corresponding uninstalled binary, and any of their required library
+directories are added to the library path.
+
+Then, COMMAND is executed, with ARGS as arguments.
+EOF
+ ;;
+
+finish)
+ cat <<EOF
+Usage: $progname [OPTION]... --mode=finish [LIBDIR]...
+
+Complete the installation of libtool libraries.
+
+Each LIBDIR is a directory that contains libtool libraries.
+
+The commands that this mode executes may require superuser privileges. Use
+the \`--dry-run' option if you just want to see what would be executed.
+EOF
+ ;;
+
+install)
+ cat <<EOF
+Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND...
+
+Install executables or libraries.
+
+INSTALL-COMMAND is the installation command. The first component should be
+either the \`install' or \`cp' program.
+
+The rest of the components are interpreted as arguments to that command (only
+BSD-compatible install options are recognized).
+EOF
+ ;;
+
+link)
+ cat <<EOF
+Usage: $progname [OPTION]... --mode=link LINK-COMMAND...
+
+Link object files or libraries together to form another library, or to
+create an executable program.
+
+LINK-COMMAND is a command using the C compiler that you would use to create
+a program from several object files.
+
+The following components of LINK-COMMAND are treated specially:
+
+ -all-static do not do any dynamic linking at all
+ -allow-undefined allow a libtool library to reference undefined symbols
+ -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime
+ -dlpreopen FILE link in FILE and add its symbols to dld_preloaded_symbols
+ -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
+ -LLIBDIR search LIBDIR for required installed libraries
+ -lNAME OUTPUT-FILE requires the installed library libNAME
+ -o OUTPUT-FILE create OUTPUT-FILE from the specified objects
+ -rpath LIBDIR the created library will eventually be installed in LIBDIR
+ -static do not do any dynamic linking of libtool libraries
+ -version-info CURRENT[:REVISION[:AGE]]
+ specify library version info [each variable defaults to 0]
+
+All other options (arguments beginning with \`-') are ignored.
+
+Every other argument is treated as a filename. Files ending in \`.la' are
+treated as uninstalled libtool libraries, other files are standard or library
+object files.
+
+If the OUTPUT-FILE ends in \`.la', then a libtool library is created, only
+library objects (\`.lo' files) may be specified, and \`-rpath' is required.
+
+If OUTPUT-FILE ends in \`.a', then a standard library is created using \`ar'
+and \`ranlib'.
+
+If OUTPUT-FILE ends in \`.lo' or \`.o', then a reloadable object file is
+created, otherwise an executable program is created.
+EOF
+ ;;
+
+uninstall)
+ cat <<EOF
+Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
+
+Remove libraries from an installation directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, all the files associated with it are deleted.
+Otherwise, only FILE itself is deleted using RM.
+EOF
+ ;;
+
+*)
+ $echo "$progname: invalid operation mode \`$mode'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+esac
+
+$echo
+$echo "Try \`$progname --help' for more information about other modes."
+
+exit 0
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
diff --git a/glib/missing b/glib/missing
new file mode 100755
index 000000000..e4b838ca9
--- /dev/null
+++ b/glib/missing
@@ -0,0 +1,134 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+# Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+# Franc,ois Pinard <pinard@iro.umontreal.ca>, 1996.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program 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 General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+if test $# -eq 0; then
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+fi
+
+case "$1" in
+
+ -h|--h|--he|--hel|--help)
+ echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+ -h, --help display this help and exit
+ -v, --version output version information and exit
+
+Supported PROGRAM values:
+ aclocal touch file \`aclocal.m4'
+ autoconf touch file \`configure'
+ autoheader touch file \`config.h.in'
+ automake touch all \`Makefile.in' files
+ bison touch file \`y.tab.c'
+ makeinfo touch the output file
+ yacc touch file \`y.tab.c'"
+ ;;
+
+ -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+ echo "missing - GNU libit 0.0"
+ ;;
+
+ -*)
+ echo 1>&2 "$0: Unknown \`$1' option"
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+ ;;
+
+ aclocal)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. It should be needed only if
+ you modified \`acinclude.m4' or \`configure.in'. You might want
+ to install the \`Automake' and \`Perl' packages. Grab them from
+ any GNU archive site."
+ touch aclocal.m4
+ ;;
+
+ autoconf)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. It should be needed only if
+ you modified \`configure.in'. You might want to install the
+ \`Autoconf' and \`GNU m4' packages. Grab them from any GNU
+ archive site."
+ touch configure
+ ;;
+
+ autoheader)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. It should be needed only if
+ you modified \`acconfig.h' or \`configure.in'. You might want
+ to install the \`Autoconf' and \`GNU m4' packages. Grab them
+ from any GNU archive site."
+ touch config.h.in
+ ;;
+
+ automake)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. It should be needed only if
+ you modified \`Makefile.am', \`acinclude.m4' or \`configure.in'.
+ You might want to install the \`Automake' and \`Perl' packages.
+ Grab them from any GNU archive site."
+ find . -type f -name Makefile.am -print \
+ | sed 's/^\(.*\).am$/touch \1.in/' \
+ | sh
+ ;;
+
+ bison|yacc)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. It should be needed only if
+ your modified any \`.y' file. For being effective, your
+ modifications might require the \`Bison' package. Grab it from
+ any GNU archive site."
+ touch y.tab.c
+ ;;
+
+ makeinfo)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. It should be needed only if
+ you modified a \`.texi' or \`.texinfo' file, or any other file
+ indirectly affecting the aspect of the manual. The spurious
+ call might also be the consequence of using a buggy \`make' (AIX,
+ DU, IRIX). You might want to install the \`Texinfo' package or
+ the \`GNU make' package. Grab either from any GNU archive site."
+ file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
+ if test -z "$file"; then
+ file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+ file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
+ fi
+ touch $file
+ ;;
+
+ *)
+ echo 1>&2 "\
+WARNING: \`$1' is needed, and you do not seem to have it handy on your
+ system. You might have modified some files without having the
+ proper tools for further handling them. Check the \`README' file,
+ it often tells you about the needed prerequirements for installing
+ this package. You may also peek at any GNU archive site, in case
+ some other package would contain this missing \`$1' program."
+ exit 1
+ ;;
+esac
+
+exit 0
diff --git a/glib/mkinstalldirs b/glib/mkinstalldirs
new file mode 100755
index 000000000..fef1eb941
--- /dev/null
+++ b/glib/mkinstalldirs
@@ -0,0 +1,36 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Last modified: 1994-03-25
+# Public domain
+
+errstatus=0
+
+for file in ${1+"$@"} ; do
+ set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+ shift
+
+ pathcomp=
+ for d in ${1+"$@"} ; do
+ pathcomp="$pathcomp$d"
+ case "$pathcomp" in
+ -* ) pathcomp=./$pathcomp ;;
+ esac
+
+ if test ! -d "$pathcomp"; then
+ echo "mkdir $pathcomp" 1>&2
+ mkdir "$pathcomp" > /dev/null 2>&1 || lasterr=$?
+ fi
+
+ if test ! -d "$pathcomp"; then
+ errstatus=$lasterr
+ fi
+
+ pathcomp="$pathcomp/"
+ done
+done
+
+exit $errstatus
+
+# mkinstalldirs ends here
diff --git a/glib/stamp-h.in b/glib/stamp-h.in
new file mode 100644
index 000000000..9788f7023
--- /dev/null
+++ b/glib/stamp-h.in
@@ -0,0 +1 @@
+timestamp
diff --git a/glib/testglib.c b/glib/testglib.c
new file mode 100644
index 000000000..4357b2364
--- /dev/null
+++ b/glib/testglib.c
@@ -0,0 +1,296 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdio.h>
+#include <string.h>
+#include "glib.h"
+
+int array[10000];
+
+void
+my_hash_callback (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ int *d = value;
+ *d = 1;
+}
+
+guint
+my_hash (gpointer key)
+{
+ return (guint) *((gint*) key);
+}
+
+gint
+my_hash_compare (gpointer a,
+ gpointer b)
+{
+ return *((gint*) a) == *((gint*) b);
+}
+
+gint
+my_compare (gpointer a,
+ gpointer b)
+{
+ char *cha = a;
+ char *chb = b;
+
+ return *cha - *chb;
+}
+
+gint
+my_traverse (gpointer key,
+ gpointer value,
+ gpointer data)
+{
+ char *ch = key;
+ g_print ("%c ", *ch);
+ return FALSE;
+}
+
+int
+main (int argc,
+ char *argv[])
+{
+ GList *list, *t;
+ GSList *slist, *st;
+ GHashTable *hash_table;
+ GMemChunk *mem_chunk;
+ GStringChunk *string_chunk;
+ GTimer *timer;
+ gint nums[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ gchar *mem[10000], *tmp_string, *tmp_string_2;
+ gint i, j;
+ GArray *garray;
+ GString *string1, *string2;
+ GTree *tree;
+ char chars[62];
+
+ g_print ("checking size of gint8...%d (should be 1)\n", sizeof (gint8));
+ g_print ("checking size of gint16...%d (should be 2)\n", sizeof (gint16));
+ g_print ("checking size of gint32...%d (should be 4)\n", sizeof (gint32));
+
+ g_print ("checking doubly linked lists...");
+
+ list = NULL;
+ for (i = 0; i < 10; i++)
+ list = g_list_append (list, &nums[i]);
+ list = g_list_reverse (list);
+
+ for (i = 0; i < 10; i++)
+ {
+ t = g_list_nth (list, i);
+ if (*((gint*) t->data) != (9 - i))
+ g_error ("failed");
+ }
+
+ g_list_free (list);
+
+ g_print ("ok\n");
+
+
+ g_print ("checking singly linked lists...");
+
+ slist = NULL;
+ for (i = 0; i < 10; i++)
+ slist = g_slist_append (slist, &nums[i]);
+ slist = g_slist_reverse (slist);
+
+ for (i = 0; i < 10; i++)
+ {
+ st = g_slist_nth (slist, i);
+ if (*((gint*) st->data) != (9 - i))
+ g_error ("failed");
+ }
+
+ g_slist_free (slist);
+
+ g_print ("ok\n");
+
+
+ g_print ("checking trees...\n");
+
+ tree = g_tree_new (my_compare);
+ i = 0;
+ for (j = 0; j < 10; j++, i++)
+ {
+ chars[i] = '0' + j;
+ g_tree_insert (tree, &chars[i], &chars[i]);
+ }
+ for (j = 0; j < 26; j++, i++)
+ {
+ chars[i] = 'A' + j;
+ g_tree_insert (tree, &chars[i], &chars[i]);
+ }
+ for (j = 0; j < 26; j++, i++)
+ {
+ chars[i] = 'a' + j;
+ g_tree_insert (tree, &chars[i], &chars[i]);
+ }
+
+ g_print ("tree height: %d\n", g_tree_height (tree));
+ g_print ("tree nnodes: %d\n", g_tree_nnodes (tree));
+
+ g_print ("tree: ");
+ g_tree_traverse (tree, my_traverse, G_IN_ORDER, NULL);
+ g_print ("\n");
+
+ for (i = 0; i < 10; i++)
+ g_tree_remove (tree, &chars[i]);
+
+ g_print ("tree height: %d\n", g_tree_height (tree));
+ g_print ("tree nnodes: %d\n", g_tree_nnodes (tree));
+
+ g_print ("tree: ");
+ g_tree_traverse (tree, my_traverse, G_IN_ORDER, NULL);
+ g_print ("\n");
+
+ g_print ("ok\n");
+
+
+ g_print ("checking mem chunks...");
+
+ mem_chunk = g_mem_chunk_new ("test mem chunk", 50, 100, G_ALLOC_AND_FREE);
+
+ for (i = 0; i < 10000; i++)
+ {
+ mem[i] = g_chunk_new (gchar, mem_chunk);
+
+ for (j = 0; j < 50; j++)
+ mem[i][j] = i * j;
+ }
+
+ for (i = 0; i < 10000; i++)
+ {
+ g_mem_chunk_free (mem_chunk, mem[i]);
+ }
+
+ g_print ("ok\n");
+
+
+ g_print ("checking hash tables...");
+
+ hash_table = g_hash_table_new (my_hash, my_hash_compare);
+ for (i = 0; i < 10000; i++)
+ {
+ array[i] = i;
+ g_hash_table_insert (hash_table, &array[i], &array[i]);
+ }
+ g_hash_table_foreach (hash_table, my_hash_callback, NULL);
+
+ for (i = 0; i < 10000; i++)
+ if (array[i] == 0)
+ g_print ("%d\n", i);
+
+ for (i = 0; i < 10000; i++)
+ g_hash_table_remove (hash_table, &array[i]);
+
+ g_hash_table_destroy (hash_table);
+
+ g_print ("ok\n");
+
+
+ g_print ("checking string chunks...");
+
+ string_chunk = g_string_chunk_new (1024);
+
+ for (i = 0; i < 100000; i ++)
+ {
+ tmp_string = g_string_chunk_insert (string_chunk, "hi pete");
+
+ if (strcmp ("hi pete", tmp_string) != 0)
+ g_error ("string chunks are broken.\n");
+ }
+
+ tmp_string_2 = g_string_chunk_insert_const (string_chunk, tmp_string);
+
+ g_assert (tmp_string_2 != tmp_string &&
+ strcmp(tmp_string_2, tmp_string) == 0);
+
+ tmp_string = g_string_chunk_insert_const (string_chunk, tmp_string);
+
+ g_assert (tmp_string_2 == tmp_string);
+
+ g_string_chunk_free (string_chunk);
+
+ g_print ("ok\n");
+
+
+ g_print ("checking arrays...");
+
+ garray = g_array_new (FALSE);
+ for (i = 0; i < 10000; i++)
+ g_array_append_val (garray, gint, i);
+
+ for (i = 0; i < 10000; i++)
+ if (g_array_index (garray, gint, i) != i)
+ g_print ("uh oh: %d ( %d )\n", g_array_index (garray, gint, i), i);
+
+ g_array_free (garray, TRUE);
+
+ garray = g_array_new (FALSE);
+ for (i = 0; i < 10000; i++)
+ g_array_prepend_val (garray, gint, i);
+
+ for (i = 0; i < 10000; i++)
+ if (g_array_index (garray, gint, i) != (10000 - i - 1))
+ g_print ("uh oh: %d ( %d )\n", g_array_index (garray, gint, i), 10000 - i - 1);
+
+ g_array_free (garray, TRUE);
+
+ g_print ("ok\n");
+
+
+ g_print ("checking strings...");
+
+ string1 = g_string_new ("hi pete!");
+ string2 = g_string_new ("");
+
+ g_assert (strcmp ("hi pete!", string1->str) == 0);
+
+ for (i = 0; i < 10000; i++)
+ g_string_append_c (string1, 'a'+(i%26));
+
+ g_string_sprintf (string2, "%s|%0100d|%s|%s|%0*d|%*.*f|%10000.10000f",
+ "this pete guy sure is a wuss, like he's the number ",
+ 1,
+ " wuss. everyone agrees.\n",
+ string1->str,
+ 10, 666, 15, 15, 666.666666666, 666.666666666);
+
+ g_print ("ok\n");
+
+ g_print ("checking timers...\n");
+
+ timer = g_timer_new ();
+ g_print (" spinning for 3 seconds...\n");
+
+ g_timer_start (timer);
+ while (g_timer_elapsed (timer, NULL) < 3)
+ ;
+
+ g_timer_stop (timer);
+ g_timer_destroy (timer);
+
+ g_print ("ok\n");
+
+ /* g_debug (argv[0]); */
+
+
+ return 0;
+}
diff --git a/gtk+.prj b/gtk+.prj
new file mode 100644
index 000000000..2c16fecaf
--- /dev/null
+++ b/gtk+.prj
@@ -0,0 +1,334 @@
+;; -*- Lisp -*-
+(Created-By-Prcs-Version 1 1 0)
+(Project-Description "")
+(Project-Version gtk+ 0 16)
+(Parent-Version gtk+ 0 15)
+(Descends-From -*- -*- -*-)
+(Version-Log "")
+(New-Version-Log "")
+(Checkin-Time "Wed, 19 Feb 1997 15:49:10 -0800")
+(Checkin-Login pmattis)
+(Populate-Ignore ("\\.o$" "\\.a$" "^core$" "^.*/core$"
+ ".*.deps/.*" "\\.dvi$" "\\.aux$" "\\.log"
+ "Makefile$" "config.cache$" "config.log$"
+ "configure$" "gconfig.h$" "stamp-h$"))
+(Files
+;; This is a comment. Fill in files here.
+;; For example: (prcs/checkout.cc ())
+
+; Files added by populate at Thu, 21 Nov 1996 16:48:40 -0800:
+
+ (docs/texinfo.tex (gtk+/1_texinfo.te 1.1 644))
+ (docs/gtk.texi (gtk+/2_gtk.texi 1.5 644))
+ (docs/gdk.texi (gtk+/3_gdk.texi 1.2 644))
+ (docs/Makefile.in (gtk+/4_Makefile.i 1.5 644))
+ (docs/Makefile.am (gtk+/5_Makefile.a 1.2 644))
+ (gtk/testgtk.c (gtk+/6_testgtk.c 1.14 644))
+ (gtk/gtkwindow.h (gtk+/7_gtkwindow. 1.6 644))
+ (gtk/gtkwindow.c (gtk+/8_gtkwindow. 1.10 644))
+ (gtk/gtkwidget.h (gtk+/9_gtkwidget. 1.8 644))
+ (gtk/gtkwidget.c (gtk+/10_gtkwidget. 1.14 644))
+ (gtk/gtkvseparator.h (gtk+/11_gtkvsepara 1.3 644))
+ (gtk/gtkvseparator.c (gtk+/12_gtkvsepara 1.5 644))
+ (gtk/gtkvscrollbar.h (gtk+/13_gtkvscroll 1.3 644))
+ (gtk/gtkvscrollbar.c (gtk+/14_gtkvscroll 1.5 644))
+ (gtk/gtkvscale.h (gtk+/15_gtkvscale. 1.2 644))
+ (gtk/gtkvscale.c (gtk+/16_gtkvscale. 1.7 644))
+ (gtk/gtkvruler.h (gtk+/17_gtkvruler. 1.4 644))
+ (gtk/gtkvruler.c (gtk+/18_gtkvruler. 1.7 644))
+ (gtk/gtkviewport.h (gtk+/19_gtkviewpor 1.3 644))
+ (gtk/gtkviewport.c (gtk+/20_gtkviewpor 1.6 644))
+ (gtk/gtkvbox.h (gtk+/21_gtkvbox.h 1.2 644))
+ (gtk/gtkvbox.c (gtk+/22_gtkvbox.c 1.5 644))
+ (gtk/gtktypeutils.h (gtk+/23_gtktypeuti 1.4 644))
+ (gtk/gtktypeutils.c (gtk+/24_gtktypeuti 1.6 644))
+ (gtk/gtktreeitem.h (gtk+/25_gtktreeite 1.3 644))
+ (gtk/gtktreeitem.c (gtk+/26_gtktreeite 1.4 644))
+ (gtk/gtktree.h (gtk+/27_gtktree.h 1.3 644))
+ (gtk/gtktree.c (gtk+/28_gtktree.c 1.4 644))
+ (gtk/gtktogglebutton.h (gtk+/29_gtktoggleb 1.5 644))
+ (gtk/gtktogglebutton.c (gtk+/30_gtktoggleb 1.8 644))
+ (gtk/gtktable.h (gtk+/31_gtktable.h 1.2 644))
+ (gtk/gtktable.c (gtk+/32_gtktable.c 1.8 644))
+ (gtk/gtkstyle.h (gtk+/33_gtkstyle.h 1.3 644))
+ (gtk/gtkstyle.c (gtk+/34_gtkstyle.c 1.7 644))
+ (gtk/gtksignal.h (gtk+/35_gtksignal. 1.7 644))
+ (gtk/gtksignal.c (gtk+/36_gtksignal. 1.9 644))
+ (gtk/gtkseparator.h (gtk+/37_gtkseparat 1.2 644))
+ (gtk/gtkseparator.c (gtk+/38_gtkseparat 1.4 644))
+ (gtk/gtkscrolledwindow.h (gtk+/39_gtkscrolle 1.2 644))
+ (gtk/gtkscrolledwindow.c (gtk+/40_gtkscrolle 1.8 644))
+ (gtk/gtkscrollbar.h (gtk+/41_gtkscrollb 1.2 644))
+ (gtk/gtkscrollbar.c (gtk+/42_gtkscrollb 1.4 644))
+ (gtk/gtkscale.h (gtk+/43_gtkscale.h 1.4 644))
+ (gtk/gtkscale.c (gtk+/44_gtkscale.c 1.7 644))
+ (gtk/gtkruler.h (gtk+/45_gtkruler.h 1.5 644))
+ (gtk/gtkruler.c (gtk+/46_gtkruler.c 1.8 644))
+ (gtk/gtkrc.h (gtk+/47_gtkrc.h 1.3 644))
+ (gtk/gtkrc.c (gtk+/48_gtkrc.c 1.4 644))
+ (gtk/gtkrange.h (gtk+/49_gtkrange.h 1.4 644))
+ (gtk/gtkrange.c (gtk+/50_gtkrange.c 1.6 644))
+ (gtk/gtkradiobutton.h (gtk+/51_gtkradiobu 1.3 644))
+ (gtk/gtkradiobutton.c (gtk+/b/0_gtkradiobutton.c 1.7 644))
+ (gtk/gtkpixmap.h (gtk+/b/1_gtkpixmap. 1.3 644))
+ (gtk/gtkpixmap.c (gtk+/b/2_gtkpixmap. 1.5 644))
+ (gtk/gtkoptionmenu.h (gtk+/b/3_gtkoptionm 1.5 644))
+ (gtk/gtkoptionmenu.c (gtk+/b/4_gtkoptionm 1.7 644))
+ (gtk/gtkobject.h (gtk+/b/5_gtkobject. 1.6 644))
+ (gtk/gtkobject.c (gtk+/b/6_gtkobject. 1.9 644))
+ (gtk/gtkmisc.h (gtk+/b/7_gtkmisc.h 1.2 644))
+ (gtk/gtkmisc.c (gtk+/b/8_gtkmisc.c 1.4 644))
+ (gtk/gtkmenushell.h (gtk+/b/9_gtkmenushe 1.5 644))
+ (gtk/gtkmenushell.c (gtk+/b/10_gtkmenushe 1.8 644))
+ (gtk/gtkmenuitem.h (gtk+/b/11_gtkmenuite 1.6 644))
+ (gtk/gtkmenuitem.c (gtk+/b/12_gtkmenuite 1.8 644))
+ (gtk/gtkmenubar.h (gtk+/b/13_gtkmenubar 1.4 644))
+ (gtk/gtkmenubar.c (gtk+/b/14_gtkmenubar 1.7 644))
+ (gtk/gtkmenu.h (gtk+/b/15_gtkmenu.h 1.5 644))
+ (gtk/gtkmenu.c (gtk+/b/16_gtkmenu.c 1.8 644))
+ (gtk/gtkmain.h (gtk+/b/17_gtkmain.h 1.4 644))
+ (gtk/gtkmain.c (gtk+/b/18_gtkmain.c 1.11 644))
+ (gtk/gtklistitem.h (gtk+/b/19_gtklistite 1.3 644))
+ (gtk/gtklistitem.c (gtk+/b/20_gtklistite 1.9 644))
+ (gtk/gtklist.h (gtk+/b/21_gtklist.h 1.5 644))
+ (gtk/gtklist.c (gtk+/b/22_gtklist.c 1.10 644))
+ (gtk/gtklabel.h (gtk+/b/23_gtklabel.h 1.2 644))
+ (gtk/gtklabel.c (gtk+/b/24_gtklabel.c 1.7 644))
+ (gtk/gtkitem.h (gtk+/b/25_gtkitem.h 1.3 644))
+ (gtk/gtkitem.c (gtk+/b/26_gtkitem.c 1.7 644))
+ (gtk/gtkimage.h (gtk+/b/27_gtkimage.h 1.2 644))
+ (gtk/gtkimage.c (gtk+/b/28_gtkimage.c 1.4 644))
+ (gtk/gtkhseparator.h (gtk+/b/29_gtkhsepara 1.2 644))
+ (gtk/gtkhseparator.c (gtk+/b/30_gtkhsepara 1.4 644))
+ (gtk/gtkhscrollbar.h (gtk+/b/31_gtkhscroll 1.2 644))
+ (gtk/gtkhscrollbar.c (gtk+/b/32_gtkhscroll 1.4 644))
+ (gtk/gtkhscale.h (gtk+/b/33_gtkhscale. 1.2 644))
+ (gtk/gtkhscale.c (gtk+/b/34_gtkhscale. 1.7 644))
+ (gtk/gtkhruler.h (gtk+/b/35_gtkhruler. 1.4 644))
+ (gtk/gtkhruler.c (gtk+/b/36_gtkhruler. 1.7 644))
+ (gtk/gtkhbox.h (gtk+/b/37_gtkhbox.h 1.2 644))
+ (gtk/gtkhbox.c (gtk+/b/38_gtkhbox.c 1.5 644))
+ (gtk/gtkgc.h (gtk+/b/39_gtkgc.h 1.3 644))
+ (gtk/gtkgc.c (gtk+/b/40_gtkgc.c 1.5 644))
+ (gtk/gtkframe.h (gtk+/b/41_gtkframe.h 1.2 644))
+ (gtk/gtkframe.c (gtk+/b/42_gtkframe.c 1.5 644))
+ (gtk/gtkenums.h (gtk+/b/45_gtkenums.h 1.6 644))
+ (gtk/gtkentry.h (gtk+/b/46_gtkentry.h 1.5 644))
+ (gtk/gtkentry.c (gtk+/b/47_gtkentry.c 1.9 644))
+ (gtk/gtkdrawingarea.h (gtk+/b/48_gtkdrawing 1.4 644))
+ (gtk/gtkdrawingarea.c (gtk+/b/49_gtkdrawing 1.6 644))
+ (gtk/gtkdata.h (gtk+/b/50_gtkdata.h 1.2 644))
+ (gtk/gtkdata.c (gtk+/b/51_gtkdata.c 1.7 644))
+ (gtk/gtkcontainer.h (gtk+/c/0_gtkcontainer.h 1.6 644))
+ (gtk/gtkcontainer.c (gtk+/c/1_gtkcontain 1.10 644))
+ (gtk/gtkcheckbutton.h (gtk+/c/2_gtkcheckbu 1.3 644))
+ (gtk/gtkcheckbutton.c (gtk+/c/3_gtkcheckbu 1.6 644))
+ (gtk/gtkbutton.h (gtk+/c/4_gtkbutton. 1.4 644))
+ (gtk/gtkbutton.c (gtk+/c/5_gtkbutton. 1.9 644))
+ (gtk/gtkbox.h (gtk+/c/6_gtkbox.h 1.2 644))
+ (gtk/gtkbox.c (gtk+/c/7_gtkbox.c 1.5 644))
+ (gtk/gtkbin.h (gtk+/c/8_gtkbin.h 1.2 644))
+ (gtk/gtkbin.c (gtk+/c/9_gtkbin.c 1.6 644))
+ (gtk/gtkarrow.h (gtk+/c/10_gtkarrow.h 1.2 644))
+ (gtk/gtkarrow.c (gtk+/c/11_gtkarrow.c 1.4 644))
+ (gtk/gtkalignment.h (gtk+/c/12_gtkalignme 1.2 644))
+ (gtk/gtkalignment.c (gtk+/c/13_gtkalignme 1.5 644))
+ (gtk/gtkadjustment.h (gtk+/c/14_gtkadjustm 1.3 644))
+ (gtk/gtkadjustment.c (gtk+/c/15_gtkadjustm 1.7 644))
+ (gtk/gtkaccelerator.h (gtk+/c/16_gtkacceler 1.4 644))
+ (gtk/gtkaccelerator.c (gtk+/c/17_gtkacceler 1.4 644))
+ (gtk/gtk.h (gtk+/c/18_gtk.h 1.7 644))
+ (gtk/fnmatch.h (gtk+/c/19_fnmatch.h 1.1 644))
+ (gtk/fnmatch.c (gtk+/c/20_fnmatch.c 1.1 644))
+ (TODO (gtk+/c/21_TODO 1.13 644))
+ (gtk/Makefile.in (gtk+/c/22_Makefile.i 1.10 644))
+ (gtk/Makefile.am (gtk+/c/23_Makefile.a 1.10 644))
+ (gdk/makekeysyms.sed (gtk+/c/24_makekeysym 1.1 644))
+ (gdk/makekeysyms (gtk+/c/25_makekeysym 1.1 755))
+ (gdk/makecursors.sed (gtk+/c/26_makecursor 1.1 644))
+ (gdk/makecursors (gtk+/c/27_makecursor 1.1 755))
+ (gdk/gdkx.h (gtk+/c/28_gdkx.h 1.2 644))
+ (gdk/gdkwindow.c (gtk+/c/29_gdkwindow. 1.8 644))
+ (gdk/gdkvisual.c (gtk+/c/30_gdkvisual. 1.2 644))
+ (gdk/gdktypes.h (gtk+/c/31_gdktypes.h 1.6 644))
+ (gdk/gdkrectangle.c (gtk+/c/32_gdkrectang 1.3 644))
+ (gdk/gdkprivate.h (gtk+/c/33_gdkprivate 1.4 644))
+ (gdk/gdkpixmap.c (gtk+/c/34_gdkpixmap. 1.6 644))
+ (gdk/gdkkeysyms.h (gtk+/c/35_gdkkeysyms 1.2 644))
+ (gdk/gdkimage.c (gtk+/c/36_gdkimage.c 1.4 644))
+ (gdk/gdkglobals.c (gtk+/c/37_gdkglobals 1.3 644))
+ (gdk/gdkgc.c (gtk+/c/38_gdkgc.c 1.6 644))
+ (gdk/gdkfont.c (gtk+/c/39_gdkfont.c 1.4 644))
+ (gdk/gdkdraw.c (gtk+/c/40_gdkdraw.c 1.4 644))
+ (gdk/gdkcursors.h (gtk+/c/41_gdkcursors 1.3 644))
+ (gdk/gdkcursor.c (gtk+/c/42_gdkcursor. 1.3 644))
+ (gdk/gdkcolor.c (gtk+/c/43_gdkcolor.c 1.4 644))
+ (gdk/gdk.h (gtk+/c/44_gdk.h 1.6 644))
+ (gdk/gdk.c (gtk+/c/45_gdk.c 1.8 644))
+ (gdk/Makefile.in (gtk+/c/46_Makefile.i 1.7 644))
+ (gdk/Makefile.am (gtk+/c/47_Makefile.a 1.7 644))
+ (glib/testglib.c (gtk+/c/48_testglib.c 1.8 644))
+ (glib/stamp-h.in (gtk+/c/49_stamp-h.in 1.1 644))
+ (glib/mkinstalldirs (gtk+/c/50_mkinstalld 1.1 755))
+ (glib/install-sh (gtk+/c/51_install-sh 1.1 755))
+ (glib/gutils.c (gtk+/d/0_gutils.c 1.3 644))
+ (glib/gtimer.c (gtk+/d/1_gtimer.c 1.2 644))
+ (glib/gslist.c (gtk+/d/2_gslist.c 1.6 644))
+ (glib/gprimes.c (gtk+/d/3_gprimes.c 1.2 644))
+ (glib/gmem.c (gtk+/d/4_gmem.c 1.9 644))
+ (glib/glist.c (gtk+/d/5_glist.c 1.4 644))
+ (glib/glib.h (gtk+/d/6_glib.h 1.8 644))
+ (glib/ghash.c (gtk+/d/7_ghash.c 1.5 644))
+ (glib/gerror.c (gtk+/d/8_gerror.c 1.4 644))
+ (glib/gconfig.h.in (gtk+/d/9_gconfig.h. 1.3 644))
+ (glib/gconfig.h (gtk+/d/10_gconfig.h 1.6 644))
+ (glib/gcache.c (gtk+/d/11_gcache.c 1.6 644))
+ (glib/configure.in (gtk+/d/12_configure. 1.4 644))
+ (glib/configure (gtk+/d/13_configure 1.4 755))
+ (glib/config.sub (gtk+/d/14_config.sub 1.2 755))
+ (glib/config.guess (gtk+/d/15_config.gue 1.2 755))
+ (glib/aclocal.m4 (gtk+/d/16_aclocal.m4 1.4 644))
+ (glib/acconfig.h (gtk+/d/17_acconfig.h 1.3 644))
+ (glib/README (gtk+/d/18_README 1.1 644))
+ (glib/NEWS (gtk+/d/19_NEWS 1.1 644))
+ (glib/Makefile.in (gtk+/d/20_Makefile.i 1.7 644))
+ (glib/Makefile.am (gtk+/d/21_Makefile.a 1.7 644))
+ (glib/INSTALL (gtk+/d/22_INSTALL 1.1 644))
+ (glib/ChangeLog (gtk+/d/23_ChangeLog 1.2 644))
+ (glib/COPYING (gtk+/d/24_COPYING 1.1 644))
+ (glib/AUTHORS (gtk+/d/25_AUTHORS 1.2 644))
+ (stamp-h.in (gtk+/d/26_stamp-h.in 1.1 644))
+ (mkinstalldirs (gtk+/d/27_mkinstalld 1.1 755))
+ (install-sh (gtk+/d/28_install-sh 1.1 755))
+ (configure.in (gtk+/d/30_configure. 1.8 644))
+ (configure (gtk+/d/31_configure 1.8 755))
+ (config.sub (gtk+/d/32_config.sub 1.2 755))
+ (config.h.in (gtk+/d/33_config.h.i 1.4 644))
+ (config.guess (gtk+/d/34_config.gue 1.2 755))
+ (aclocal.m4 (gtk+/d/35_aclocal.m4 1.4 644))
+ (acconfig.h (gtk+/d/36_acconfig.h 1.3 644))
+ (README (gtk+/d/37_README 1.1 644))
+ (NEWS (gtk+/d/38_NEWS 1.1 644))
+ (Makefile.in (gtk+/d/39_Makefile.i 1.9 644))
+ (Makefile.am (gtk+/d/40_Makefile.a 1.7 644))
+ (INSTALL (gtk+/d/41_INSTALL 1.1 644))
+ (ChangeLog (gtk+/d/42_ChangeLog 1.14 644))
+ (COPYING (gtk+/d/43_COPYING 1.2 644))
+ (AUTHORS (gtk+/d/44_AUTHORS 1.2 644))
+
+; Files added by populate at Mon, 30 Dec 1996 13:14:24 -0800:
+
+ (gtk/gtkmenufactory.h (gtk+/0_gtkmenufac 1.4 644))
+ (gtk/gtkmenufactory.c (gtk+/1_gtkmenufac 1.4 644))
+
+; Files added by populate at Thu, 02 Jan 1997 15:31:44 -0800:
+
+ (gtk/testgtkrc (gtk+/0_testgtkrc 1.2 644))
+
+
+; Files added by populate at Fri, 10 Jan 1997 14:19:47 -0800:
+
+ (gtk/gtkfilesel.h (gtk+/b/0_gtkfilesel.h 1.3 644))
+ (gtk/gtkfilesel.c (gtk+/c/0_gtkfilesel.c 1.7 644))
+ (glib/gstring.c (gtk+/d/0_gstring.c 1.4 644))
+
+; Files added by populate at Fri, 10 Jan 1997 18:01:19 -0800:
+
+ (gdk/gdkselection.c (gtk+/b/0_gdkselection.c 1.5 644))
+
+; Files added by populate at Sun, 19 Jan 1997 18:29:12 -0800:
+
+ (gtk/gtktext.h (gtk+/b/0_gtktext.h 1.4 644))
+ (gtk/gtktext.c (gtk+/c/0_gtktext.c 1.7 644))
+ (gtk/gtkdialog.h (gtk+/d/0_gtkdialog.h 1.2 644))
+ (gtk/gtkdialog.c (gtk+/d/47_gtkdialog. 1.4 644))
+ (gdk/gdkxid.c (gtk+/d/48_gdkxid.c 1.2 644))
+
+; Files added by populate at Thu, 23 Jan 1997 01:29:17 -0800:
+
+ (gtk/gtknotebook.h (gtk+/b/0_gtknotebook.h 1.3 644))
+ (gtk/gtknotebook.c (gtk+/c/0_gtknotebook.c 1.6 644))
+
+; Files added by populate at Thu, 23 Jan 1997 02:06:11 -0800:
+
+ (gtk/line-wrap.xbm (gtk+/b/0_line-wrap.xbm 1.1 644))
+ (gtk/line-arrow.xbm (gtk+/c/0_line-arrow.xbm 1.1 644))
+
+; Files added by populate at Fri, 24 Jan 1997 13:02:44 -0800:
+
+
+
+
+
+
+; Files deleted by populate at Fri, 24 Jan 1997 13:02:44 -0800:
+
+ ; `docs/texinfo3.7.patch'
+
+; Files added by populate at Tue, 28 Jan 1997 16:54:35 -0800:
+
+ (gtk/simple.c (gtk+/e/0_simple.c 1.1 644))
+ (glib/ltmain.sh (gtk+/e/1_ltmain.sh 1.3 644))
+ (glib/ltconfig (gtk+/e/2_ltconfig 1.3 755))
+ (ltmain.sh (gtk+/e/3_ltmain.sh 1.3 644))
+ (ltconfig (gtk+/e/4_ltconfig 1.3 755))
+
+; Files added by populate at Thu, 30 Jan 1997 01:30:38 -0800:
+
+ (glib/gtree.c (gtk+/b/0_gtree.c 1.3 644))
+
+; Files added by populate at Mon, 03 Feb 1997 19:46:14 -0800:
+
+ (makecopyright (gtk+/b/0_makecopyright 1.1 755))
+
+; Files added by populate at Sat, 08 Feb 1997 14:41:52 -0800:
+
+ (gtk/gtkprogressbar.h (gtk+/b/0_gtkprogressbar.h 1.1 644))
+ (gtk/gtkprogressbar.c (gtk+/c/0_gtkprogressbar.c 1.1 644))
+ (glib/garray.c (gtk+/d/0_garray.c 1.1 644))
+
+; Files deleted by populate at Sat, 08 Feb 1997 14:41:52 -0800:
+
+ ; `interp/Makefile.am'
+ ; `interp/Makefile.in'
+ ; `interp/interp.c'
+
+;; Files added by populate at Wed, 19 Feb 1997 15:48:04 -0800:
+
+ (gtk+.xconfig.in (gtk+/b/0_gtk+.xconfig.in 1.1 644))
+
+;; Files deleted by populate at Wed, 19 Feb 1997 15:48:04 -0800:
+
+ ; docs/proposal.tex
+
+;; Files added by populate at Thu, 17 Apr 1997 17:39:47 -0700:
+
+ (docs/macros.texi ())
+ (gdk/gdkproperty.c ())
+ (glib/missing () :symlink)
+ (missing () :symlink)
+
+;; Files deleted by populate at Thu, 17 Apr 1997 17:39:47 -0700:
+
+ ; gtk/gtkcanvas.c
+ ; gtk/gtkcanvas.h
+ ; gtk/gtkfill.c
+ ; gtk/gtkfill.h
+
+;; Files added by populate at Thu, 17 Apr 1997 17:41:14 -0700:
+
+ (gtk/gtktooltips.h ())
+ (gtk/gtktooltips.c ())
+ (gtk/gtkradiomenuitem.h ())
+ (gtk/gtkradiomenuitem.c ())
+ (gtk/gtkpreview.h ())
+ (gtk/gtkpreview.c ())
+ (gtk/gtkcolorsel.h ())
+ (gtk/gtkcolorsel.c ())
+ (gtk/gtkcheckmenuitem.h ())
+ (gtk/gtkcheckmenuitem.c ())
+ (gtk/gtkaspectframe.h ())
+ (gtk/gtkaspectframe.c ())
+)
+(Merge-Parents)
+(New-Merge-Parents)
diff --git a/gtk+.xconfig.in b/gtk+.xconfig.in
new file mode 100644
index 000000000..8843df6ce
--- /dev/null
+++ b/gtk+.xconfig.in
@@ -0,0 +1,3 @@
+X_CFLAGS = @x_cflags@
+X_LDFLAGS = @x_ldflags@
+X_LIBS = @x_libs@
diff --git a/gtk/.cvsignore b/gtk/.cvsignore
new file mode 100644
index 000000000..e5ac5d91d
--- /dev/null
+++ b/gtk/.cvsignore
@@ -0,0 +1,9 @@
+*.lo
+Makefile
+.deps
+_libs
+libgtk.la
+testgtk
+testinput
+testselection
+simple
diff --git a/gtk/3DRings.xpm b/gtk/3DRings.xpm
new file mode 100644
index 000000000..1ca75da75
--- /dev/null
+++ b/gtk/3DRings.xpm
@@ -0,0 +1,116 @@
+/* XPM */
+static char * DRings_xpm[] = {
+"48 48 65 1",
+" c None",
+". c #104010404103",
+"X c #1040208130C2",
+"o c #104014515144",
+"O c #000010402081",
+"+ c #1040104030C2",
+"@ c #208120815144",
+"# c #28A241035965",
+"$ c #30C230C26185",
+"% c #208130C24103",
+"& c #104010402081",
+"* c #104000002081",
+"= c #000010401040",
+"- c #492441036185",
+"; c #596559659E79",
+": c #30C220815144",
+"> c #0820186128A2",
+", c #000000001040",
+"< c #2081104030C2",
+"1 c #514459659658",
+"2 c #514455556185",
+"3 c #104000001040",
+"4 c #000008200000",
+"5 c #618569A6AEBA",
+"6 c #618569A69658",
+"7 c #410345148E38",
+"8 c #104020814103",
+"9 c #79E782079658",
+"0 c #208120814103",
+"q c #596571C69E79",
+"w c #4103514471C6",
+"e c #2081208130C2",
+"r c #6185618571C6",
+"t c #28A228A25965",
+"y c #596561858617",
+"u c #96589E79BEFB",
+"i c #28A230C271C6",
+"p c #38E345145144",
+"a c #79E78207A699",
+"s c #30C2492469A6",
+"d c #410330C25965",
+"f c #410351446185",
+"g c #AEBAAAAAD75C",
+"h c #38E338E34103",
+"j c #EFBEEBADEFBE",
+"k c #208130C25144",
+"l c #9658A289DF7D",
+"z c #208110404103",
+"x c #28A228A26185",
+"c c #8E388A28BEFB",
+"v c #208118612081",
+"b c #38E3451479E7",
+"n c #4924618579E7",
+"m c #86178617B6DA",
+"M c #30C220814103",
+"N c #104030C25144",
+"B c #4103410371C6",
+"V c #86178A28D75C",
+"C c #DF7DDB6CE79D",
+"Z c #BEFBC30BD75C",
+"A c #410330C271C6",
+"S c #30C228A230C2",
+"D c #082008201861",
+"F c #186130C238E3",
+"G c #0000208130C2",
+" .Xo ",
+" O+O@#$% ",
+" &*=+X-;: ",
+" >&=,=<11#2 ",
+" +O34,X567& ",
+" 8X+=,90q9w. ",
+" +e<>3r tyu-& ",
+" Xi%.= paus+ ",
+" Od-@= fga$h ",
+" @y7X, Xrjak ",
+" 2:eaw+ $ag;@ ",
+" .X@8@k@o@X+ +pl9tO ",
+" +zX@x$$isikt8o02crv ",
+" 8@%ip7757ywbs$Ohn6#. ",
+" &0%$p7r215ybw1pzp2-0= ",
+" 8tk$#yw21665n;1+%-p$O ",
+" O<e7pbryq5am9ay6XMpM>3& ",
+" 9.NtpBw16amclVcm1t%kX*88 ",
+" +&etd7r6y9ulgglm6>e>3s@83 ",
+" +0k$y-y69cgCCCZVam%+#ik8X ",
+" O&oi$d725amgCjCZu962ybtx8+p ",
+" &X0x$sBym9VZCCCZca;yBbi%08& ",
+" =++@sApMy5muZZgum6y2wds:>+& ",
+" #tp;1;yB#i25cVucma5;w-pti@8& ",
+" .#2alumnBp:@1r59y9y6ywBS$%0X+= ",
+" %$wmZVu;#tX8X07r1656y2wbp$k@%@OD ",
+" 0Byc9a;h%0>&D&hBrr2r1bwB-AF:0<&*= ",
+" kBf;yr#@X+&<%MkhsBwBwpsB#Bktkt8+Oh ",
+" xt7B-t8*,3O.X00:$i#dBd#bptFek0X.+* ",
+" Xt#b#@=, =&O+X0Ft%ibsp$p$ki%l5sX&= ",
+" &<kvX&4 +O*&<X0e:%$pAti%:edugn0= ",
+" +X@&+, V,O&>+Xt>tktktv0%@k;Cls+ ",
+" =+O*4*X:p;9cy3&&8ve0FMtt$ee0>z7cZ6k ",
+" D=D4,=.k$sBs$ee=+X0Fk%-#t%0X&O0nu9bG ",
+" ,,434*&ze@F<eeeeee><tdhdSMe<&&XAaawx ",
+" 4,4,=+><peeeeee&=<%M%$hSF0X&O&kw5r%Z ",
+" D&vSFMF<>&D =0S-2i& ",
+" +>puB> >0h7s. ",
+" SM5VqM &0t#$8 ",
+" XpVV70 &0kMk. ",
+" XdyB%z *X<%@+ ",
+" &k$b0X+=8X08o ",
+" &e:e+=*X.X+& ",
+" +X.O+X0O.=, ",
+" +>&+0>3&* ",
+" &X0k+O, ",
+" >v,3 ",
+" "};
diff --git a/gtk/FilesQueue.xpm b/gtk/FilesQueue.xpm
new file mode 100644
index 000000000..586d27ec4
--- /dev/null
+++ b/gtk/FilesQueue.xpm
@@ -0,0 +1,98 @@
+/* XPM */
+static char * FilesQueue_xpm[] = {
+"44 31 64 1",
+" c None",
+". c #E79DE38DDF7D",
+"X c #CF3CC71BCF3C",
+"o c #71C675D671C6",
+"O c #B6DAB2CAB6DA",
+"+ c #CF3CD34CCF3C",
+"@ c #DF7DE38DE79D",
+"# c #FFFFFBEEFFFF",
+"$ c #EFBEEFBEEFBE",
+"% c #DF7DDB6CDF7D",
+"& c #BEFBBAEAC71B",
+"* c #BEFBBAEABEFB",
+"= c #BEFBC30BC71B",
+"- c #71C66DB671C6",
+"; c #D75CD34CD75C",
+": c #9E799A699E79",
+"> c #E79DE38DE79D",
+", c #CF3CCB2BC71B",
+"< c #B6DAB2CABEFB",
+"1 c #BEFBBAEAB6DA",
+"2 c #B6DAB6DAB6DA",
+"3 c #618561856185",
+"4 c #C71BBAEABEFB",
+"5 c #AEBAAAAAAEBA",
+"6 c #965892488E38",
+"7 c #A699A699A699",
+"8 c #38E338E338E3",
+"9 c #F7DEF7DEF7DE",
+"0 c #E79DEFBEEFBE",
+"q c #DF7DE38DDF7D",
+"w c #C71BC71BC71B",
+"e c #C71BC30BBEFB",
+"r c #BEFBC30BBEFB",
+"t c #B6DAAAAAAEBA",
+"y c #410345144103",
+"u c #D75CDB6CD75C",
+"i c #C71BCB2BC71B",
+"p c #BEFBCB2BBEFB",
+"a c #9E79A289A699",
+"s c #86178E388E38",
+"d c #CF3CCF3CD75C",
+"f c #CF3CD75CCF3C",
+"g c #C71BC30BCF3C",
+"h c #28A22CB228A2",
+"j c #000000000000",
+"k c #D75CD34CDF7D",
+"l c #10400C300820",
+"z c #E79DEBADEFBE",
+"x c #DF7DDB6CD75C",
+"c c #514459655965",
+"v c #8617861779E7",
+"b c #DF7DD34CD75C",
+"n c #CF3CCB2BCF3C",
+"m c #618555555965",
+"M c #861786178617",
+"N c #30C234D330C2",
+"B c #EFBEEBADE79D",
+"V c #DF7DDB6CE79D",
+"C c #D75CE38DD75C",
+"Z c #514449245144",
+"A c #186120812081",
+"S c #79E77DF779E7",
+"D c #6185659569A6",
+"F c #9E7992489E79",
+" .XoOX+ ",
+" @#$%&*=-o;: ",
+" @>,=O<12*&:-<3X ",
+" >%&1*4*2*OO**56758790 ",
+" 9qX+we=r*&e<<<251t5555yu9 ",
+" $qu++;ipi=p*=p**2tOOO27a5s<- ",
+" #9udfXi;,gi&**4**4r*Ot5t55tehj ",
+" 0qku+u;+d,gg=*=r*&**&<255t<*yl1 ",
+" $$zq@%xk%uf;,w,i=i=e**r=12tO1=8cvj ",
+" $@%>.%.%%%xbkx,w+ni,wwrwe*4*1=;8mMNj ",
+" zz@Bz>>>V%%%C+u;;dfnnfwggi&=&X+yZsNll ",
+" af#9@B0>q>qqq>xk.;;;kfX+XnXw=g,fycMhhN5 ",
+" al5#9$$>qzBV.%x%%b;x+fnf+,X,iiqym6NAo-j ",
+" #roS%#$zz>>V%%xkk%f;;+df,XnwnVZD:8AS-j* ",
+" D-9Oy*9$Bz>q%qx%%u;x;;dknX+d>Zm:hhSDjr ",
+" a3o+>S3z#90@@z.%>qCC%uu;ff%@Zm:NhMoj= ",
+" wlvvo#:3599$>B>q>%%%%+f;fk$ymaalMvjr ",
+" 0.a--S49mct9$z@.qkkqC;xu%@Zm5AlvSj* ",
+" ohu%3:Z:9@y609q@@>..>Cx>$Zm5NhMvjr ",
+" -j797Zv5705y=#$0>>V.%>#Z378AMMj* ",
+" Zj9Xo-McBXDv%90.%%#9cc78AsMj* ",
+" 8hM#M-DSF96cvz0>z#c35Nhs6j1 ",
+" jl9#o63vx#-D###mmt8N66j* ",
+" 5jc@fZF3o%+ZFDm<8A6FjO ",
+" :j50sSay<$ss2Nh:FjO ",
+" 6880&SDMF.rNNFFj1 ",
+" 8jr#:SFScA6ajO ",
+" Alr$DSysajO ",
+" >jy#51:jO ",
+" %Dy*gjO ",
+" alla "};
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
new file mode 100644
index 000000000..60d43b1d2
--- /dev/null
+++ b/gtk/Makefile.am
@@ -0,0 +1,248 @@
+## Process this file with automake to produce Makefile.in
+
+gtkincludedir = $(includedir)/gtk
+
+lib_LTLIBRARIES = libgtk.la
+
+libgtk_la_SOURCES = \
+ gtkaccelerator.c \
+ gtkadjustment.c \
+ gtkaspectframe.c \
+ gtkalignment.c \
+ gtkarrow.c \
+ gtkbin.c \
+ gtkbbox.c \
+ gtkbox.c \
+ gtkbutton.c \
+ gtkcheckbutton.c \
+ gtkcheckmenuitem.c \
+ gtkcolorsel.c \
+ gtkcontainer.c \
+ gtkcurve.c \
+ gtkdata.c \
+ gtkdialog.c \
+ gtkdrawingarea.c \
+ gtkentry.c \
+ gtkeventbox.c \
+ gtkfilesel.c \
+ gtkfixed.c \
+ gtkframe.c \
+ gtkgamma.c \
+ gtkgc.c \
+ gtkhbbox.c \
+ gtkhbox.c \
+ gtkhpaned.c \
+ gtkhruler.c \
+ gtkhscale.c \
+ gtkhscrollbar.c \
+ gtkhseparator.c \
+ gtkimage.c \
+ gtkinputdialog.c \
+ gtkitem.c \
+ gtklabel.c \
+ gtklist.c \
+ gtklistitem.c \
+ gtkmain.c \
+ gtkmenu.c \
+ gtkmenubar.c \
+ gtkmenufactory.c \
+ gtkmenuitem.c \
+ gtkmenushell.c \
+ gtkmisc.c \
+ gtknotebook.c \
+ gtkobject.c \
+ gtkoptionmenu.c \
+ gtkpaned.c \
+ gtkpixmap.c \
+ gtkpreview.c \
+ gtkprogressbar.c \
+ gtkradiobutton.c \
+ gtkradiomenuitem.c \
+ gtkrange.c \
+ gtkrc.c \
+ gtkruler.c \
+ gtkscale.c \
+ gtkscrollbar.c \
+ gtkscrolledwindow.c \
+ gtkselection.c \
+ gtkseparator.c \
+ gtksignal.c \
+ gtkstyle.c \
+ gtktable.c \
+ gtktext.c \
+ gtktogglebutton.c \
+ gtktooltips.c \
+ gtktree.c \
+ gtktreeitem.c \
+ gtktypeutils.c \
+ gtkvbbox.c \
+ gtkvbox.c \
+ gtkviewport.c \
+ gtkvpaned.c \
+ gtkvruler.c \
+ gtkvscale.c \
+ gtkvscrollbar.c \
+ gtkvseparator.c \
+ gtkwidget.c \
+ gtkwindow.c \
+ fnmatch.c \
+ fnmatch.h
+
+gtkinclude_HEADERS = \
+ gtk.h \
+ gtkaccelerator.h \
+ gtkadjustment.h \
+ gtkaspectframe.h \
+ gtkalignment.h \
+ gtkarrow.h \
+ gtkbin.h \
+ gtkbbox.h \
+ gtkbox.h \
+ gtkbutton.h \
+ gtkcheckbutton.h \
+ gtkcheckmenuitem.h \
+ gtkcolorsel.h \
+ gtkcontainer.h \
+ gtkcurve.h \
+ gtkdata.h \
+ gtkdialog.h \
+ gtkdrawingarea.h \
+ gtkentry.h \
+ gtkenums.h \
+ gtkeventbox.h \
+ gtkfilesel.h \
+ gtkfixed.h \
+ gtkframe.h \
+ gtkgamma.h \
+ gtkgc.h \
+ gtkhbbox.h \
+ gtkhbox.h \
+ gtkhpaned.h \
+ gtkhruler.h \
+ gtkhscale.h \
+ gtkhscrollbar.h \
+ gtkhseparator.h \
+ gtkimage.h \
+ gtkinputdialog.h \
+ gtkitem.h \
+ gtklabel.h \
+ gtklist.h \
+ gtklistitem.h \
+ gtkmain.h \
+ gtkmenu.h \
+ gtkmenubar.h \
+ gtkmenufactory.h \
+ gtkmenuitem.h \
+ gtkmenushell.h \
+ gtkmisc.h \
+ gtknotebook.h \
+ gtkobject.h \
+ gtkoptionmenu.h \
+ gtkpaned.h \
+ gtkpixmap.h \
+ gtkpreview.h \
+ gtkprogressbar.h \
+ gtkradiobutton.h \
+ gtkradiomenuitem.h \
+ gtkrange.h \
+ gtkrc.h \
+ gtkruler.h \
+ gtkscale.h \
+ gtkscrollbar.h \
+ gtkscrolledwindow.h \
+ gtkselection.h \
+ gtkseparator.h \
+ gtksignal.h \
+ gtkstyle.h \
+ gtktable.h \
+ gtktext.h \
+ gtktogglebutton.h \
+ gtktooltips.h \
+ gtktree.h \
+ gtktreeitem.h \
+ gtktypeutils.h \
+ gtkvbbox.h \
+ gtkvbox.h \
+ gtkviewport.h \
+ gtkvpaned.h \
+ gtkvruler.h \
+ gtkvscale.h \
+ gtkvscrollbar.h \
+ gtkvseparator.h \
+ gtkwidget.h \
+ gtkwindow.h \
+ gtktypebuiltins.h
+
+../gtk/gtktypebuiltins.h: gtk.defs gentypeinfo.el
+ $(srcdir)/runelisp $(srcdir)/gentypeinfo.el idmac $< $@
+
+gtktypebuiltins.c: gtk.defs gentypeinfo.el
+ $(srcdir)/runelisp $(srcdir)/gentypeinfo.el id $< $@
+
+libgtk_la_LDFLAGS = -version-info 1:0:
+
+EXTRA_DIST = \
+ line-arrow.xbm \
+ line-wrap.xbm \
+ testgtkrc \
+ gtk.defs \
+ runelisp \
+ gentypeinfo.el \
+ gtktypebuiltins.c \
+ test.xpm \
+ marble.xpm \
+ 3DRings.xpm \
+ FilesQueue.xpm \
+ Modeller.xpm
+
+INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/glib @x_cflags@
+
+noinst_PROGRAMS = testgtk testinput testselection simple
+testgtk_LDADD = \
+ libgtk.la \
+ $(top_builddir)/gdk/libgdk.la \
+ @x_ldflags@ \
+ @x_libs@ \
+ $(top_builddir)/glib/libglib.la \
+ -lm
+
+testinput_LDADD = \
+ libgtk.la \
+ $(top_builddir)/gdk/libgdk.la \
+ @x_ldflags@ \
+ @x_libs@ \
+ $(top_builddir)/glib/libglib.la \
+ -lm
+
+testselection_LDADD = \
+ libgtk.la \
+ $(top_builddir)/gdk/libgdk.la \
+ @x_ldflags@ \
+ @x_libs@ \
+ $(top_builddir)/glib/libglib.la \
+ -lm
+
+simple_LDADD = \
+ libgtk.la \
+ $(top_builddir)/gdk/libgdk.la \
+ @x_ldflags@ \
+ @x_libs@ \
+ $(top_builddir)/glib/libglib.la \
+ -lm
+
+DEPS = \
+ $(top_builddir)/gtk/libgtk.la \
+ $(top_builddir)/gdk/libgdk.la \
+ $(top_builddir)/glib/libglib.la
+
+testgtk_DEPENDENCIES = $(DEPS)
+testinput_DEPENDENCIES = $(DEPS)
+testselection_DEPENDENCIES = $(DEPS)
+simple_DEPENDENCIES = $(DEPS)
+
+.PHONY: files
+
+files:
+ @files=`ls $(DISTFILES) 2> /dev/null `; for p in $$files; do \
+ echo $$p; \
+ done
diff --git a/gtk/Modeller.xpm b/gtk/Modeller.xpm
new file mode 100644
index 000000000..62e27f985
--- /dev/null
+++ b/gtk/Modeller.xpm
@@ -0,0 +1,117 @@
+/* XPM */
+static char * InterfaceModeller_app_2_Tile_xpm[] = {
+"48 48 66 1",
+" c None",
+". c #86174D344103",
+"X c #69A651445144",
+"o c #8617410330C2",
+"O c #69A6410338E3",
+"+ c #30C218611861",
+"@ c #AEBA6DB66185",
+"# c #71C638E328A2",
+"$ c #69A634D328A2",
+"% c #30C228A228A2",
+"& c #79E73CF330C2",
+"* c #BEFB9E799E79",
+"= c #8E3869A66185",
+"- c #514424921861",
+"; c #A699A289B6DA",
+": c #A6999E79A699",
+"> c #71C65D756185",
+", c #9E799A69A699",
+"< c #8E3882078E38",
+"1 c #861779E78617",
+"2 c #A6999A69AEBA",
+"3 c #8E388A289658",
+"4 c #71C675D679E7",
+"5 c #96588A289E79",
+"6 c #30C230C238E3",
+"7 c #C71BC71BC71B",
+"8 c #9E79A289AEBA",
+"9 c #AEBAAAAABEFB",
+"0 c #96589248A699",
+"q c #A699AAAAB6DA",
+"w c #AEBAAAAAB6DA",
+"e c #D75CD34CD75C",
+"r c #EFBEE79DEFBE",
+"t c #BEFBB6DABEFB",
+"y c #B6DABAEAC71B",
+"u c #AEBAAEBAB6DA",
+"i c #E79DDB6CDF7D",
+"p c #96588E389658",
+"a c #596559656185",
+"s c #AEBA8E388E38",
+"d c #CF3CCB2BCF3C",
+"f c #9E799A699E79",
+"g c #86177DF78E38",
+"h c #69A6659571C6",
+"j c #AEBAAEBABEFB",
+"k c #96589E799E79",
+"l c #B6DAA699A699",
+"z c #E79DC71BC71B",
+"x c #B6DAB6DAB6DA",
+"c c #861786179658",
+"v c #B6DAB2CABEFB",
+"b c #BEFBAAAAAEBA",
+"n c #C71BBEFBC71B",
+"m c #514441034103",
+"M c #41033CF34103",
+"N c #492428A228A2",
+"B c #AEBAA289B6DA",
+"V c #618530C22081",
+"C c #69A630C228A2",
+"Z c #69A630C22081",
+"A c #596528A22081",
+"S c #492428A22081",
+"D c #618528A22081",
+"F c #596520811861",
+"G c #69A628A22081",
+"H c #FFFF14514103",
+" .X ",
+" .oO+ ",
+" @.o#++ ",
+" @.o$%+ ",
+" @.&#++ ",
+" @.o#++ ",
+" @.o$++ ",
+" @.&#++ ",
+" .O#++ ",
+" *=-$++ ",
+" ;:>+++ ",
+" ;,<1% ",
+" 2,34 ",
+" 2;,51 ",
+" 2,,,,6 ",
+" 7777 28888,6 ",
+" 77777777 2829,,,06 ",
+" 9qwwe7rrrrr77rr 828,9tyt,6 ",
+" uuwriirrieiiieii77pa< 82,8,,,8,06 ",
+" s=1ttiieeeeded77eufgh>j,8,8,k,0,6 ",
+" =@lzieeeeee77eeex:fpcg4>9,,,,qjv6 ",
+" =O=blt7eeee7deenw:ffp<gha:t979;06 ",
+" =OO@=@zieeee7ex:::fffff0,v72444h6 ",
+" =OOo&Osst7iee7wkf:f:ff;t721444ham ",
+" =#&&&&OO@di7eu:ff:fferiv114444hmMX ",
+" =O&&&..o.sdp33fff:errrii7cc1hhh6mmNX= ",
+" =O&&&@.o.@sberrrrrriiuxuxnB;44aMmVCO#OX ",
+" =O&&o@..o.zrrrie777nnxtuxx:x;n:>mV##&&O$mX ",
+" =O&&o....zrrieieuxunx7txx:nnfwpMmVZ#$ZZZVVN ",
+" =O&oooo.*rrde77ewxnxxtnw:f4M%M%+NA#$Z$ZZVmN> ",
+" =Oo&ooo@iree7inxn7nnuuff4h%M>m%S-AZ$CCZDZmSX ",
+" =O&o.o.@rrn7eulun7xxuwp4mm6ahM%--AZCCZDDDANX ",
+" =Ooooo.*rixenuwwn7nxupph%M>>h6mAADVVZVVDDANX ",
+" =O&o.o.zrexwwnwuxxnughX%mahhmMN-AZCCVVDDAAN> ",
+" *XOoo.*iin7n777xxxtphaM+ama>MSNFVCZZVVDAAAS> ",
+" 1O..izewxux7nuuux4%++%hha>%N-DDCZZVDAAAASX ",
+" 1.=ituu:uButnxxuX%>hh>M%++NADZZZVDADAA--X ",
+" :e7f::lnn7*ppnx6ahm6++mNN-ADCZVDDAAAA-SX ",
+" 7nupp:wxxg%MMau6%++NmmmADADVVVVVDAA---NX ",
+" 7uBgh1wwxg6h>m%:MmmVNAVDZVZCVZZDAAAAF-S+X ",
+" nfgaM%pnwhX6%mXb6$DVVZC$C#C$ZZDVAAA---+NX ",
+" 27a%MaM47:mN.OoolmODGZ####$$ZZVDDA-----SSX ",
+" 2gmg<m6p7wmmOo...O$GZ####$$CZVVDAAA----++X ",
+" qBcaM <gxgmXmo.@.o&$$##$$$CZZZDADA-A-++-NX ",
+" M6> paMa HX.@@@oZ$###$$CZVDDAAAA---SS+X ",
+" 43 p=&@@&&$##$CCCVVVAAA--+S+S+%X ",
+" k =o@.##$VVmmmNNNSSSSSS%XXXX ",
+" s>OSSNmN>>aaa177777 "};
diff --git a/gtk/fnmatch.c b/gtk/fnmatch.c
new file mode 100644
index 000000000..0a45770a4
--- /dev/null
+++ b/gtk/fnmatch.c
@@ -0,0 +1,200 @@
+/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
+
+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; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include "fnmatch.h"
+#include <ctype.h>
+
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+ actually compiling the library itself. This code is part of the GNU C
+ Library, but also included in many other GNU distributions. Compiling
+ and linking in this code is a waste when using the GNU C library
+ (especially if it is a shared library). Rather than having every GNU
+ program understand `configure --with-gnu-libc' and omit the object files,
+ it is simpler to just do this in the source for each such file. */
+
+#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
+
+
+#if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS)
+extern int errno;
+#endif
+
+/* Match STRING against the filename pattern PATTERN, returning zero if
+ it matches, nonzero if not. */
+int
+fnmatch (pattern, string, flags)
+ const char *pattern;
+ const char *string;
+ int flags;
+{
+ register const char *p = pattern, *n = string;
+ register char c;
+
+/* Note that this evalutes C many times. */
+#define FOLD(c) ((flags & FNM_CASEFOLD) && isupper (c) ? tolower (c) : (c))
+
+ while ((c = *p++) != '\0')
+ {
+ c = FOLD (c);
+
+ switch (c)
+ {
+ case '?':
+ if (*n == '\0')
+ return FNM_NOMATCH;
+ else if ((flags & FNM_FILE_NAME) && *n == '/')
+ return FNM_NOMATCH;
+ else if ((flags & FNM_PERIOD) && *n == '.' &&
+ (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
+ return FNM_NOMATCH;
+ break;
+
+ case '\\':
+ if (!(flags & FNM_NOESCAPE))
+ {
+ c = *p++;
+ c = FOLD (c);
+ }
+ if (FOLD (*n) != c)
+ return FNM_NOMATCH;
+ break;
+
+ case '*':
+ if ((flags & FNM_PERIOD) && *n == '.' &&
+ (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
+ return FNM_NOMATCH;
+
+ for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
+ if (((flags & FNM_FILE_NAME) && *n == '/') ||
+ (c == '?' && *n == '\0'))
+ return FNM_NOMATCH;
+
+ if (c == '\0')
+ return 0;
+
+ {
+ char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
+ c1 = FOLD (c1);
+ for (--p; *n != '\0'; ++n)
+ if ((c == '[' || FOLD (*n) == c1) &&
+ fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
+ return 0;
+ return FNM_NOMATCH;
+ }
+
+ case '[':
+ {
+ /* Nonzero if the sense of the character class is inverted. */
+ register int not;
+
+ if (*n == '\0')
+ return FNM_NOMATCH;
+
+ if ((flags & FNM_PERIOD) && *n == '.' &&
+ (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
+ return FNM_NOMATCH;
+
+ not = (*p == '!' || *p == '^');
+ if (not)
+ ++p;
+
+ c = *p++;
+ for (;;)
+ {
+ register char cstart = c, cend = c;
+
+ if (!(flags & FNM_NOESCAPE) && c == '\\')
+ cstart = cend = *p++;
+
+ cstart = cend = FOLD (cstart);
+
+ if (c == '\0')
+ /* [ (unterminated) loses. */
+ return FNM_NOMATCH;
+
+ c = *p++;
+ c = FOLD (c);
+
+ if ((flags & FNM_FILE_NAME) && c == '/')
+ /* [/] can never match. */
+ return FNM_NOMATCH;
+
+ if (c == '-' && *p != ']')
+ {
+ cend = *p++;
+ if (!(flags & FNM_NOESCAPE) && cend == '\\')
+ cend = *p++;
+ if (cend == '\0')
+ return FNM_NOMATCH;
+ cend = FOLD (cend);
+
+ c = *p++;
+ }
+
+ if (FOLD (*n) >= cstart && FOLD (*n) <= cend)
+ goto matched;
+
+ if (c == ']')
+ break;
+ }
+ if (!not)
+ return FNM_NOMATCH;
+ break;
+
+ matched:;
+ /* Skip the rest of the [...] that already matched. */
+ while (c != ']')
+ {
+ if (c == '\0')
+ /* [... (unterminated) loses. */
+ return FNM_NOMATCH;
+
+ c = *p++;
+ if (!(flags & FNM_NOESCAPE) && c == '\\')
+ /* XXX 1003.2d11 is unclear if this is right. */
+ ++p;
+ }
+ if (not)
+ return FNM_NOMATCH;
+ }
+ break;
+
+ default:
+ if (c != FOLD (*n))
+ return FNM_NOMATCH;
+ }
+
+ ++n;
+ }
+
+ if (*n == '\0')
+ return 0;
+
+ if ((flags & FNM_LEADING_DIR) && *n == '/')
+ /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */
+ return 0;
+
+ return FNM_NOMATCH;
+}
+
+#endif /* _LIBC or not __GNU_LIBRARY__. */
diff --git a/gtk/fnmatch.h b/gtk/fnmatch.h
new file mode 100644
index 000000000..d9d73b3d8
--- /dev/null
+++ b/gtk/fnmatch.h
@@ -0,0 +1,67 @@
+/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
+
+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; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#ifndef _FNMATCH_H
+
+#define _FNMATCH_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined (__cplusplus) || (defined (__STDC__) && __STDC__)
+#undef __P
+#define __P(protos) protos
+#else /* Not C++ or ANSI C. */
+#undef __P
+#define __P(protos) ()
+/* We can get away without defining `const' here only because in this file
+ it is used only inside the prototype for `fnmatch', which is elided in
+ non-ANSI C where `const' is problematical. */
+#endif /* C++ or ANSI C. */
+
+
+/* We #undef these before defining them because some losing systems
+ (HP-UX A.08.07 for example) define these in <unistd.h>. */
+#undef FNM_PATHNAME
+#undef FNM_NOESCAPE
+#undef FNM_PERIOD
+
+/* Bits set in the FLAGS argument to `fnmatch'. */
+#define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */
+#define FNM_NOESCAPE (1 << 1) /* Backslashes don't quote special chars. */
+#define FNM_PERIOD (1 << 2) /* Leading `.' is matched only explicitly. */
+
+#if !defined (_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 2 || defined (_GNU_SOURCE)
+#define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */
+#define FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match. */
+#define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */
+#endif
+
+/* Value returned by `fnmatch' if STRING does not match PATTERN. */
+#define FNM_NOMATCH 1
+
+/* Match STRING against the filename pattern PATTERN,
+ returning zero if it matches, FNM_NOMATCH if not. */
+extern int fnmatch __P ((const char *__pattern, const char *__string,
+ int __flags));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* fnmatch.h */
diff --git a/gtk/gentypeinfo.el b/gtk/gentypeinfo.el
new file mode 100644
index 000000000..2de6a92d2
--- /dev/null
+++ b/gtk/gentypeinfo.el
@@ -0,0 +1,137 @@
+(require 'cl)
+
+;;; file access
+
+(defun read-file (name)
+ (let ((buf (generate-new-buffer "infile"))
+ (res nil))
+ (save-excursion
+ (set-buffer buf)
+ (insert-file-contents name)
+ (condition-case nil
+ (while t
+ (setq res (cons (read buf) res)))
+ (end-of-file (reverse res))))))
+
+(defun setup-outfile ()
+ (setq standard-output (generate-new-buffer "outfile")))
+
+(defun write-outfile (name)
+ (save-excursion
+ (set-buffer standard-output)
+ (write-region (point-min) (point-max) name)))
+
+;;; string stunts
+
+(defun char-upper-case-p (ch)
+ (eql (upcase ch) ch))
+
+(defun char-lower-case-p (ch)
+ (eql (downcase ch) ch))
+
+(defun canonicalize (str)
+ (if (symbolp str)
+ (setq str (symbol-name str)))
+ (let ((res nil)
+ (start 0)
+ (pos 0)
+ (end (length str))
+ (prevlower nil))
+ (while (< pos end)
+ (let ((ch (elt str pos)))
+ (cond ((memq ch '(?- ?_))
+ (setq res (cons (substring str start pos) res)
+ prevlower nil
+ pos (1+ pos)
+ start pos))
+ ((and (char-upper-case-p ch)
+ prevlower)
+ (setq res (cons (substring str start pos) res)
+ start pos
+ pos (1+ pos)
+ prevlower nil))
+ (t
+ (setq pos (1+ pos)
+ prevlower (char-lower-case-p ch))))))
+ (reverse (mapcar 'downcase (cons (substring str start end) res)))))
+
+(defun syllables-to-string (syls del)
+ (let ((res ""))
+ (while syls
+ (setq res (format "%s%s%s" res (car syls)
+ (if (cdr syls) del ""))
+ syls (cdr syls)))
+ res))
+
+(defun macroname (canon)
+ (syllables-to-string (mapcar 'upcase canon) "_"))
+
+(defun funcname (canon)
+ (syllables-to-string canon "_"))
+
+(defun typename (canon)
+ (syllables-to-string (mapcar 'capitalize canon) ""))
+
+(defun scmname (canon)
+ (syllables-to-string canon "-"))
+
+(defun short-name (canon)
+ (if (equal (car canon) "gtk") (cdr canon) canon))
+
+;;; Code generation
+
+(defun printf (&rest args)
+ (princ (apply 'format args)))
+
+(defun interestingp (form)
+ (and (listp form)
+ (memq (car form) '(define-enum define-flags define-boxed))))
+
+(defun map-interesting (func defs)
+ (mapcar #'(lambda (form)
+ (if (interestingp form)
+ (funcall func form)))
+ defs))
+
+(defun emit-idmacs (defs)
+ (let ((i 0))
+ (map-interesting
+ #'(lambda (form)
+ (let ((name (canonicalize (cadr form))))
+ (printf "#define GTK_TYPE_%s (gtk_type_builtins[%d])\n"
+ (macroname (short-name name)) i))
+ (setq i (1+ i)))
+ defs)
+ (printf "#define GTK_TYPE_NUM_BUILTINS %d\n" i)))
+
+(defun emit-ids (defs)
+ (map-interesting
+ #'(lambda (form)
+ (printf " { %S, %s },\n"
+ (symbol-name (cadr form))
+ (case (car form)
+ ((define-enum) "GTK_TYPE_ENUM")
+ ((define-flags) "GTK_TYPE_FLAGS")
+ ((define-boxed) "GTK_TYPE_BOXED"))))
+ defs))
+
+
+
+(if (< (length command-line-args-left) 3)
+ (error "args: op def-file output-file"))
+
+(setq op (intern (car command-line-args-left)))
+(setq defs (read-file (cadr command-line-args-left)))
+(setq outfile (caddr command-line-args-left))
+(setq command-line-args-left nil)
+
+(setup-outfile)
+(printf "/* generated by gentypeinfo from \"gtk.defs\" */\n\n")
+(case op
+ ((idmac)
+ (emit-idmacs defs))
+ ((id)
+ (emit-ids defs))
+ (else
+ (error "supported ops are: idmac id")))
+(write-outfile outfile)
diff --git a/gtk/gtk.defs b/gtk/gtk.defs
new file mode 100644
index 000000000..0228e7a8b
--- /dev/null
+++ b/gtk/gtk.defs
@@ -0,0 +1,810 @@
+; -*- scheme -*-
+
+;;; Gtk enums
+
+(define-enum GtkWindowType
+ (toplevel GTK_WINDOW_TOPLEVEL)
+ (dialog GTK_WINDOW_DIALOG)
+ (popup GTK_WINDOW_POPUP))
+
+(define-enum GtkStateType
+ (normal GTK_STATE_NORMAL)
+ (active GTK_STATE_ACTIVE)
+ (prelight GTK_STATE_PRELIGHT)
+ (selected GTK_STATE_SELECTED)
+ (insensitive GTK_STATE_INSENSITIVE))
+
+(define-enum GtkDirectionType
+ (tab-forward GTK_DIR_TAB_FORWARD)
+ (tab-backward GTK_DIR_TAB_BACKWARD)
+ (up GTK_DIR_UP)
+ (down GTK_DIR_DOWN)
+ (left GTK_DIR_LEFT)
+ (right GTK_DIR_RIGHT))
+
+(define-enum GtkShadowType
+ (none GTK_SHADOW_NONE)
+ (in GTK_SHADOW_IN)
+ (out GTK_SHADOW_OUT)
+ (etched-in GTK_SHADOW_ETCHED_IN)
+ (etched-out GTK_SHADOW_ETCHED_OUT))
+
+(define-enum GtkArrowType
+ (up GTK_ARROW_UP)
+ (down GTK_ARROW_DOWN)
+ (left GTK_ARROW_LEFT)
+ (right GTK_ARROW_RIGHT))
+
+(define-enum GtkPackType
+ (start GTK_PACK_START)
+ (end GTK_PACK_END))
+
+(define-enum GtkPolicyType
+ (always GTK_POLICY_ALWAYS)
+ (automatic GTK_POLICY_AUTOMATIC))
+
+(define-enum GtkUpdateType
+ (continous GTK_UPDATE_CONTINUOUS)
+ (discontinous GTK_UPDATE_DISCONTINUOUS)
+ (delayed GTK_UPDATE_DELAYED))
+
+(define-flags GtkAttachOptions
+ (expand GTK_EXPAND)
+ (shrink GTK_SHRINK)
+ (fill GTK_FILL))
+
+(define-flags GtkSignalRunType
+ (first GTK_RUN_FIRST)
+ (last GTK_RUN_LAST)
+ (both GTK_RUN_BOTH)
+ (mask GTK_RUN_MASK)
+ (no-recurse GTK_RUN_NO_RECURSE))
+
+(define-enum GtkWindowPosition
+ (none GTK_WIN_POS_NONE)
+ (center GTK_WIN_POS_CENTER)
+ (mouse GTK_WIN_POS_MOUSE))
+
+(define-enum GtkSubmenuDirection
+ (left GTK_DIRECTION_LEFT)
+ (right GTK_DIRECTION_RIGHT))
+
+(define-enum GtkSubmenuPlacement
+ (top-bottom GTK_TOP_BOTTOM)
+ (left-right GTK_LEFT_RIGHT))
+
+(define-enum GtkMenuFactoryType
+ (menu GTK_MENU_FACTORY_MENU)
+ (menu-bar GTK_MENU_FACTORY_MENU_BAR)
+ (option-menu GTK_MENU_FACTORY_OPTION_MENU))
+
+(define-enum GtkMetricType
+ (pixels GTK_PIXELS)
+ (inches GTK_INCHES)
+ (centimeters GTK_CENTIMETERS))
+
+(define-enum GtkScrollType
+ (none GTK_SCROLL_NONE)
+ (step-backward GTK_SCROLL_STEP_BACKWARD)
+ (step-forward GTK_SCROLL_STEP_FORWARD)
+ (page-backward GTK_SCROLL_PAGE_BACKWARD)
+ (page-forward GTK_SCROLL_PAGE_FORWARD))
+
+(define-enum GtkTroughType
+ (none GTK_TROUGH_NONE)
+ (start GTK_TROUGH_START)
+ (end GTK_TROUGH_END))
+
+(define-enum GtkPositionType
+ (left GTK_POS_LEFT)
+ (right GTK_POS_RIGHT)
+ (top GTK_POS_TOP)
+ (bottom GTK_POS_BOTTOM))
+
+(define-enum GtkPreviewType
+ (color GTK_PREVIEW_COLOR)
+ (grayscale GTK_PREVIEW_GRAYSCALE))
+
+(define-flags GtkWidgetFlags
+ (visible GTK_VISIBLE)
+ (mapped GTK_MAPPED)
+ (unmapped GTK_UNMAPPED)
+ (realized GTK_REALIZED)
+ (sensitive GTK_SENSITIVE)
+ (parent-sensitive GTK_PARENT_SENSITIVE)
+ (no-window GTK_NO_WINDOW)
+ (has-focus GTK_HAS_FOCUS)
+ (can-focus GTK_CAN_FOCUS)
+ (has-default GTK_HAS_DEFAULT)
+ (can-default GTK_CAN_DEFAULT)
+ (propagate-state GTK_PROPAGATE_STATE)
+ (anchored GTK_ANCHORED)
+ (basic GTK_BASIC)
+ (user-style GTK_USER_STYLE))
+
+;;; Gdk enums
+
+(define-enum GdkWindowType
+ (root GDK_WINDOW_ROOT)
+ (toplevel GDK_WINDOW_TOPLEVEL)
+ (child GDK_WINDOW_CHILD)
+ (dialog GDK_WINDOW_DIALOG)
+ (temp GDK_WINDOW_TEMP)
+ (pixmap GDK_WINDOW_PIXMAP))
+
+(define-enum GdkWindowClass
+ (input-output GDK_INPUT_OUTPUT)
+ (input-only GDK_INPUT_ONLY))
+
+(define-enum GdkImageType
+ (normal GDK_IMAGE_NORMAL)
+ (shared GDK_IMAGE_SHARED)
+ (fastest GDK_IMAGE_FASTEST))
+
+(define-enum GdkVisualType
+ (static-gray GDK_VISUAL_STATIC_GRAY)
+ (grayscale GDK_VISUAL_GRAYSCALE)
+ (static-color GDK_VISUAL_STATIC_COLOR)
+ (pseudo-color GDK_VISUAL_PSEUDO_COLOR)
+ (true-color GDK_VISUAL_TRUE_COLOR)
+ (direct-color GDK_VISUAL_DIRECT_COLOR))
+
+(define-flags GdkWindowAttributesType
+ (title GDK_WA_TITLE)
+ (x GDK_WA_X)
+ (y GDK_WA_Y)
+ (cursor GDK_WA_CURSOR)
+ (colormap GDK_WA_COLORMAP)
+ (visual GDK_WA_VISUAL))
+
+(define-flags GdkWindowHints
+ (pos GDK_HINT_POS)
+ (min-size GDK_HINT_MIN_SIZE)
+ (max-size GDK_HINT_MAX_SIZE))
+
+(define-enum GdkFunction
+ (copy GDK_COPY)
+ (invert GDK_INVERT)
+ (xor GDK_XOR))
+
+(define-enum GdkFill
+ (solid GDK_SOLID)
+ (tiled GDK_TILED)
+ (stippled GDK_STIPPLED)
+ (opaque-stippled GDK_OPAQUE_STIPPLED))
+
+(define-enum GdkLineStyle
+ (solid GDK_LINE_SOLID)
+ (on-off-dash GDK_LINE_ON_OFF_DASH)
+ (double-dash GDK_LINE_DOUBLE_DASH))
+
+(define-enum GdkCapStyle
+ (not-last GDK_CAP_NOT_LAST)
+ (butt GDK_CAP_BUTT)
+ (round GDK_CAP_ROUND)
+ (projecting GDK_CAP_PROJECTING))
+
+(define-enum GdkJoinStyle
+ (miter GDK_JOIN_MITER)
+ (round GDK_JOIN_ROUND)
+ (bevel GDK_JOIN_BEVEL))
+
+(define-enum GdkCursorType
+ (cursor GDK_LAST_CURSOR))
+
+(define-enum GdkEventType
+ (nothing GDK_NOTHING)
+ (delete GDK_DELETE)
+ (destroy GDK_DESTROY)
+ (expose GDK_EXPOSE)
+ (motion-notify GDK_MOTION_NOTIFY)
+ (button-press GDK_BUTTON_PRESS)
+ (2button-press GDK_2BUTTON_PRESS)
+ (3button-press GDK_3BUTTON_PRESS)
+ (button-release GDK_BUTTON_RELEASE)
+ (key-press GDK_KEY_PRESS)
+ (key-release GDK_KEY_RELEASE)
+ (enter-notify GDK_ENTER_NOTIFY)
+ (leave-notify GDK_LEAVE_NOTIFY)
+ (focus-change GDK_FOCUS_CHANGE)
+ (configure GDK_CONFIGURE)
+ (map GDK_MAP)
+ (unmap GDK_UNMAP)
+ (property-notify GDK_PROPERTY_NOTIFY)
+ (selection-clear GDK_SELECTION_CLEAR)
+ (selection-request GDK_SELECTION_REQUEST)
+ (selection-notify GDK_SELECTION_NOTIFY)
+ (other-event GDK_OTHER_EVENT))
+
+(define-flags GdkEventMask
+ (exposure-mask GDK_EXPOSURE_MASK)
+ (pointer-motion-mask GDK_POINTER_MOTION_MASK)
+ (pointer-motion-hint-mask GDK_POINTER_MOTION_HINT_MASK)
+ (button-motion-mask GDK_BUTTON_MOTION_MASK)
+ (button1-motion-mask GDK_BUTTON1_MOTION_MASK)
+ (button2-motion-mask GDK_BUTTON2_MOTION_MASK)
+ (button3-motion-mask GDK_BUTTON3_MOTION_MASK)
+ (button-press-mask GDK_BUTTON_PRESS_MASK)
+ (button-release-mask GDK_BUTTON_RELEASE_MASK)
+ (key-press-mask GDK_KEY_PRESS_MASK)
+ (key-release-mask GDK_KEY_RELEASE_MASK)
+ (enter-notify-mask GDK_ENTER_NOTIFY_MASK)
+ (leave-notify-mask GDK_LEAVE_NOTIFY_MASK)
+ (focus-change-mask GDK_FOCUS_CHANGE_MASK)
+ (structure-mask GDK_STRUCTURE_MASK)
+ (all-events-mask GDK_ALL_EVENTS_MASK))
+
+(define-enum GdkNotifyType
+ (ancestor GDK_NOTIFY_ANCESTOR)
+ (virtual GDK_NOTIFY_VIRTUAL)
+ (inferior GDK_NOTIFY_INFERIOR)
+ (nonlinear GDK_NOTIFY_NONLINEAR)
+ (nonlinear-virtual GDK_NOTIFY_NONLINEAR_VIRTUAL)
+ (unknown GDK_NOTIFY_UNKNOWN))
+
+(define-flags GdkModifierType
+ (shift-mask GDK_SHIFT_MASK)
+ (lock-mask GDK_LOCK_MASK)
+ (control-mask GDK_CONTROL_MASK)
+ (mod1-mask GDK_MOD1_MASK)
+ (mod2-mask GDK_MOD2_MASK)
+ (mod3-mask GDK_MOD3_MASK)
+ (mod4-mask GDK_MOD4_MASK)
+ (mod5-mask GDK_MOD5_MASK)
+ (button1-mask GDK_BUTTON1_MASK)
+ (button2-mask GDK_BUTTON2_MASK)
+ (button3-mask GDK_BUTTON3_MASK)
+ (button4-mask GDK_BUTTON4_MASK)
+ (button5-mask GDK_BUTTON5_MASK))
+
+(define-enum GdkSubwindowMode
+ (clip-by-children GDK_CLIP_BY_CHILDREN)
+ (include-inferiors GDK_INCLUDE_INFERIORS))
+
+(define-flags GdkInputCondition
+ (read GDK_INPUT_READ)
+ (write GDK_INPUT_WRITE)
+ (exception GDK_INPUT_EXCEPTION))
+
+(define-enum GdkStatus
+ (ok GDK_OK)
+ (error GDK_ERROR)
+ (error-param GDK_ERROR_PARAM)
+ (error-file GDK_ERROR_FILE)
+ (error-mem GDK_ERROR_MEM))
+
+(define-enum GdkByteOrder
+ (lsb-first GDK_LSB_FIRST)
+ (msb-first GDK_MSB_FIRST))
+
+(define-flags GdkGCValuesMask
+ (foreground GDK_GC_FOREGROUND)
+ (background GDK_GC_BACKGROUND)
+ (font GDK_GC_FONT)
+ (function GDK_GC_FUNCTION)
+ (fill GDK_GC_FILL)
+ (tile GDK_GC_TILE)
+ (stipple GDK_GC_STIPPLE)
+ (clip-mask GDK_GC_CLIP_MASK)
+ (subwindow GDK_GC_SUBWINDOW)
+ (ts-x-origin GDK_GC_TS_X_ORIGIN)
+ (ts-y-origin GDK_GC_TS_Y_ORIGIN)
+ (clip-x-origin GDK_GC_CLIP_X_ORIGIN)
+ (clip-y-origin GDK_GC_CLIP_Y_ORIGIN)
+ (exposures GDK_GC_EXPOSURES)
+ (line-width GDK_GC_LINE_WIDTH)
+ (line-style GDK_GC_LINE_STYLE)
+ (cap-style GDK_GC_CAP_STYLE)
+ (join-style GDK_GC_JOIN_STYLE))
+
+(define-enum GdkSelection
+ (primary GDK_SELECTION_PRIMARY)
+ (secondary GDK_SELECTION_SECONDARY))
+
+(define-enum GdkPropertyState
+ (new-value GDK_PROPERTY_NEW_VALUE)
+ (delete GDK_PROPERTY_DELETE))
+
+(define-enum GdkPropMode
+ (replace GDK_PROP_MODE_REPLACE)
+ (prepend GDK_PROP_MODE_PREPEND)
+ (append GDK_PROP_MODE_APPEND))
+
+;;; Gtk boxed types
+
+(define-boxed GtkAcceleratorTable
+ gtk_accelerator_table_ref
+ gtk_accelerator_table_unref)
+
+(define-boxed GtkStyle
+ gtk_style_ref
+ gtk_style_unref)
+
+;;; Gdk boxed types
+
+;(define-boxed GdkPoint
+; gdk_point_copy
+; gdk_point_destroy)
+
+(define-boxed GdkColormap
+ gdk_colormap_ref
+ gdk_colormap_unref)
+
+(define-boxed GdkVisual
+ gdk_visual_ref
+ gdk_visual_unref)
+
+(define-boxed GdkFont
+ gdk_font_ref
+ gdk_font_free)
+
+(define-boxed GdkWindow
+ gdk_window_ref
+ gdk_window_unref)
+
+(define-boxed GdkEvent
+ gdk_event_copy
+ gdk_event_free)
+
+;;; Functions
+
+(define-func gtk_exit
+ none
+ (int code 0))
+
+(define-func gtk_rc_parse
+ none
+ (string file))
+
+(define-func g_mem_chunk_info
+ none)
+
+;; GtkObject
+
+(define-func gtk_object_destroy
+ none
+ (GtkObject object))
+
+;; GtkWidget
+
+(define-object GtkWidget (GtkObject))
+
+(define-func GTK_WIDGET_STATE
+ GtkStateType
+ (GtkWidget widget))
+
+(define-func GTK_WIDGET_FLAGS
+ GtkWidgetFlags
+ (GtkWidget widget))
+
+(define-func GTK_WIDGET_SET_FLAGS
+ none
+ (GtkWidget widget)
+ (GtkWidgetFlags flags))
+
+(define-func GTK_WIDGET_UNSET_FLAGS
+ none
+ (GtkWidget widget)
+ (GtkWidgetFlags flags))
+
+(define-func gtk_widget_destroy
+ none
+ (GtkWidget widget))
+
+(define-func gtk_widget_unparent
+ none
+ (GtkWidget widget))
+
+(define-func gtk_widget_show
+ none
+ (GtkWidget widget))
+
+(define-func gtk_widget_hide
+ none
+ (GtkWidget widget))
+
+(define-func gtk_widget_map
+ none
+ (GtkWidget widget))
+
+(define-func gtk_widget_unmap
+ none
+ (GtkWidget widget))
+
+(define-func gtk_widget_realize
+ none
+ (GtkWidget widget))
+
+(define-func gtk_widget_unrealize
+ none
+ (GtkWidget widget))
+
+;(define-func gtk_widget_install_accelerator
+; none
+; (GtkWidget widget)
+; (GtkAcceleratorTable table)
+; (string signal_name)
+; (char key)
+; (...))
+
+(define-func gtk_widget_remove_accelerator
+ none
+ (GtkWidget widget)
+ (GtkAcceleratorTable table)
+ (string signal_name))
+
+;(define-func gtk_widget_event
+; bool
+; (GtkWidget widget)
+; (GdkEvent event))
+
+(define-func gtk_widget_activate
+ none
+ (GtkWidget widget))
+
+(define-func gtk_widget_reparent
+ none
+ (GtkWidget widget)
+ (GtkWidget new_parent))
+
+(define-func gtk_widget_popup
+ none
+ (GtkWidget widget)
+ (int x)
+ (int y))
+
+(define-func gtk_widget_basic
+ bool
+ (GtkWidget widget))
+
+(define-func gtk_widget_grab_focus
+ none
+ (GtkWidget widget))
+
+(define-func gtk_widget_grab_default
+ none
+ (GtkWidget widget))
+
+(define-func gtk_widget_restore_state
+ none
+ (GtkWidget widget))
+
+(define-func gtk_widget_set_name
+ none
+ (GtkWidget widget)
+ (string name))
+
+(define-func gtk_widget_get_name
+ static_string
+ (GtkWidget widget))
+
+(define-func gtk_widget_set_state
+ none
+ (GtkWidget widget)
+ (GtkStateType state))
+
+(define-func gtk_widget_set_sensitive
+ none
+ (GtkWidget widget)
+ (bool sensitive))
+
+(define-func gtk_widget_set_style
+ none
+ (GtkWidget widget)
+ (GtkStyle style))
+
+(define-func gtk_widget_set_uposition
+ none
+ (GtkWidget widget)
+ (int x)
+ (int y))
+
+(define-func gtk_widget_set_usize
+ none
+ (GtkWidget widget)
+ (int height)
+ (int width))
+
+(define-func gtk_widget_set_events
+ none
+ (GtkWidget widget)
+ (GdkEventMask events))
+
+(define-func gtk_widget_set_extension_events
+ none
+ (GtkWidget widget)
+ (GdkEventMask events))
+
+(define-func gtk_widget_get_toplevel
+ GtkWidget
+ (GtkWidget widget))
+
+;(define-func gtk_widget_get_ancestor
+; GtkWidget
+; (GtkWidget widget)
+; (GtkType type))
+
+(define-func gtk_widget_get_colormap
+ GdkColormap
+ (GtkWidget widget))
+
+(define-func gtk_widget_get_visual
+ GdkVisual
+ (GtkWidget widget))
+
+(define-func gtk_widget_get_style
+ GtkStyle
+ (GtkWidget widget))
+
+(define-func gtk_widget_get_events
+ GdkEventMask
+ (GtkWidget widget))
+
+(define-func gtk_widget_get_extension_events
+ GdkEventMask
+ (GtkWidget widget))
+
+(define-func gtk_widget_push_colormap
+ none
+ (GdkColormap cmap))
+
+(define-func gtk_widget_push_visual
+ none
+ (GdkVisual visual))
+
+(define-func gtk_widget_push_style
+ none
+ (GtkStyle style))
+
+(define-func gtk_widget_pop_colormap
+ none)
+
+(define-func gtk_widget_pop_visual
+ none)
+
+(define-func gtk_widget_pop_style
+ none)
+
+(define-func gtk_widget_set_default_colormap
+ none
+ (GdkColormap cmap))
+
+(define-func gtk_widget_set_default_visual
+ none
+ (GdkVisual visual))
+
+(define-func gtk_widget_set_default_style
+ none
+ (GtkStyle style))
+
+(define-func gtk_widget_get_default_colormap
+ GdkColormap)
+
+(define-func gtk_widget_get_default_visual
+ GdkVisual)
+
+(define-func gtk_widget_get_default_style
+ GtkStyle)
+
+;;; Container
+
+(define-object GtkContainer (GtkWidget))
+
+(define-func gtk_container_border_width
+ none
+ (GtkContainer container)
+ (int border_width))
+
+(define-func gtk_container_add
+ none
+ (GtkContainer container)
+ (GtkWidget widget))
+
+(define-func gtk_container_remove
+ none
+ (GtkContainer container)
+ (GtkWidget widget))
+
+(define-func gtk_container_disable_resize
+ none
+ (GtkContainer container))
+
+(define-func gtk_container_enable_resize
+ none
+ (GtkContainer container))
+
+(define-func gtk_container_block_resize
+ none
+ (GtkContainer container))
+
+(define-func gtk_container_unblock_resize
+ none
+ (GtkContainer container))
+
+(define-func gtk_container_need_resize
+ bool
+ (GtkContainer container)
+ (GtkWidget widget))
+
+(define-func gtk_container_check_resize
+ none
+ (GtkContainer container)
+ (GtkWidget widget))
+
+(define-func gtk_container_focus
+ GtkDirectionType
+ (GtkContainer container)
+ (GtkDirectionType direction))
+
+;;; Bin
+
+(define-object GtkBin (GtkContainer))
+
+;;; Window
+
+(define-object GtkWindow (GtkBin))
+
+(define-func gtk_window_new
+ GtkWidget
+ (GtkWindowType type))
+
+(define-func gtk_window_set_title
+ none
+ (GtkWindow window)
+ (string title))
+
+(define-func gtk_window_set_focus
+ none
+ (GtkWindow window)
+ (GtkWidget focus))
+
+(define-func gtk_window_set_default
+ none
+ (GtkWindow window)
+ (GtkWidget default))
+
+(define-func gtk_window_set_policy
+ none
+ (GtkWindow window)
+ (bool allow_shrink)
+ (bool allow_grow)
+ (bool auto_shrink))
+
+(define-func gtk_window_add_accelerator_table
+ none
+ (GtkWindow window)
+ (GtkAcceleratorTable table))
+
+(define-func gtk_window_remove_accelerator_table
+ none
+ (GtkWindow window)
+ (GtkAcceleratorTable table))
+
+(define-func gtk_window_position
+ none
+ (GtkWindow window)
+ (GtkWindowPosition position))
+
+;;; Box
+
+(define-object GtkBox (GtkContainer))
+
+;;; Table
+
+(define-object GtkTable (GtkContainer))
+
+;;; Button
+
+(define-object GtkButton (GtkContainer))
+
+;;; ToggleButton
+
+(define-object GtkToggleButton (GtkButton))
+
+;;; CheckButton
+
+(define-object GtkCheckButton (GtkToggleButton))
+
+;;; RadioButton
+
+(define-object GtkRadioButton (GtkCheckButton))
+
+
+;; misc
+
+
+(define-func gtk_button_new_with_label
+ GtkWidget
+ (string label))
+
+(define-func gtk_vbox_new
+ GtkWidget
+ (bool homogenous)
+ (int spacing))
+
+(define-func gtk_hbox_new
+ GtkWidget
+ (bool homogenous)
+ (int spacing))
+
+(define-func gtk_hseparator_new
+ GtkWidget)
+
+(define-func gtk_box_pack_start
+ none
+ (GtkBox box)
+ (GtkWidget child)
+ (bool expand)
+ (bool fill)
+ (int padding))
+
+(define-func gtk_table_new
+ GtkWidget
+ (int rows)
+ (int columns)
+ (bool homogenous))
+
+(define-func gtk_table_attach
+ none
+ (GtkTable table)
+ (GtkWidget child)
+ (int left_attach)
+ (int right_attach)
+ (int top_attach)
+ (int bottom_attach)
+ (GtkAttachOptions xoptions)
+ (GtkAttachOptions yoptions)
+ (int xpadding)
+ (int ypadding))
+
+(define-func gtk_table_attach_defaults
+ none
+ (GtkTable table)
+ (GtkWidget child)
+ (int left_attach)
+ (int right_attach)
+ (int top_attach)
+ (int bottom_attach))
+
+(define-func gtk_table_set_row_spacing
+ none
+ (GtkTable table)
+ (int row)
+ (int spacing))
+
+(define-func gtk_table_set_col_spacing
+ none
+ (GtkTable table)
+ (int col)
+ (int spacing))
+
+(define-func gtk_table_set_row_spacings
+ none
+ (GtkTable table)
+ (int spacing))
+
+(define-func gtk_table_set_col_spacings
+ none
+ (GtkTable table)
+ (int spacing))
+
+(define-func gtk_toggle_button_new_with_label
+ GtkWidget
+ (string label))
+
+(define-func gtk_check_button_new_with_label
+ GtkWidget
+ (string label))
+
+(define-func gtk_radio_button_new_with_label_from_widget
+ GtkWidget
+ (GtkRadioButton group)
+ (string label))
+
+(define-func gtk_label_new
+ GtkWidget
+ (string label))
+
+(define-func gtk_frame_new
+ GtkWidget
+ (string label))
diff --git a/gtk/gtk.h b/gtk/gtk.h
new file mode 100644
index 000000000..acd1b1046
--- /dev/null
+++ b/gtk/gtk.h
@@ -0,0 +1,106 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_H__
+#define __GTK_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkaccelerator.h>
+#include <gtk/gtkadjustment.h>
+#include <gtk/gtkalignment.h>
+#include <gtk/gtkaspectframe.h>
+#include <gtk/gtkarrow.h>
+#include <gtk/gtkbin.h>
+#include <gtk/gtkbox.h>
+#include <gtk/gtkbbox.h>
+#include <gtk/gtkbutton.h>
+#include <gtk/gtkcheckbutton.h>
+#include <gtk/gtkcheckmenuitem.h>
+#include <gtk/gtkcolorsel.h>
+#include <gtk/gtkcontainer.h>
+#include <gtk/gtkcurve.h>
+#include <gtk/gtkdata.h>
+#include <gtk/gtkdialog.h>
+#include <gtk/gtkdrawingarea.h>
+#include <gtk/gtkentry.h>
+#include <gtk/gtkenums.h>
+#include <gtk/gtkeventbox.h>
+#include <gtk/gtkfilesel.h>
+#include <gtk/gtkfixed.h>
+#include <gtk/gtkframe.h>
+#include <gtk/gtkgamma.h>
+#include <gtk/gtkgc.h>
+#include <gtk/gtkhbox.h>
+#include <gtk/gtkhbbox.h>
+#include <gtk/gtkhpaned.h>
+#include <gtk/gtkhruler.h>
+#include <gtk/gtkhscale.h>
+#include <gtk/gtkhscrollbar.h>
+#include <gtk/gtkhseparator.h>
+#include <gtk/gtkimage.h>
+#include <gtk/gtkinputdialog.h>
+#include <gtk/gtkitem.h>
+#include <gtk/gtklabel.h>
+#include <gtk/gtklist.h>
+#include <gtk/gtklistitem.h>
+#include <gtk/gtkmain.h>
+#include <gtk/gtkmenu.h>
+#include <gtk/gtkmenubar.h>
+#include <gtk/gtkmenufactory.h>
+#include <gtk/gtkmenuitem.h>
+#include <gtk/gtkmenushell.h>
+#include <gtk/gtkmisc.h>
+#include <gtk/gtknotebook.h>
+#include <gtk/gtkobject.h>
+#include <gtk/gtkoptionmenu.h>
+#include <gtk/gtkpaned.h>
+#include <gtk/gtkpixmap.h>
+#include <gtk/gtkpreview.h>
+#include <gtk/gtkprogressbar.h>
+#include <gtk/gtkradiobutton.h>
+#include <gtk/gtkradiomenuitem.h>
+#include <gtk/gtkrange.h>
+#include <gtk/gtkrc.h>
+#include <gtk/gtkruler.h>
+#include <gtk/gtkscale.h>
+#include <gtk/gtkscrollbar.h>
+#include <gtk/gtkscrolledwindow.h>
+#include <gtk/gtkselection.h>
+#include <gtk/gtkseparator.h>
+#include <gtk/gtksignal.h>
+#include <gtk/gtkstyle.h>
+#include <gtk/gtktable.h>
+#include <gtk/gtktext.h>
+#include <gtk/gtktogglebutton.h>
+#include <gtk/gtktooltips.h>
+#include <gtk/gtktree.h>
+#include <gtk/gtktreeitem.h>
+#include <gtk/gtktypeutils.h>
+#include <gtk/gtkvbox.h>
+#include <gtk/gtkvbbox.h>
+#include <gtk/gtkviewport.h>
+#include <gtk/gtkvpaned.h>
+#include <gtk/gtkvruler.h>
+#include <gtk/gtkvscale.h>
+#include <gtk/gtkvscrollbar.h>
+#include <gtk/gtkvseparator.h>
+#include <gtk/gtkwidget.h>
+#include <gtk/gtkwindow.h>
+
+
+#endif /* __GTK_H__ */
diff --git a/gtk/gtkaccelerator.c b/gtk/gtkaccelerator.c
new file mode 100644
index 000000000..a06a06a99
--- /dev/null
+++ b/gtk/gtkaccelerator.c
@@ -0,0 +1,352 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <ctype.h>
+#include "gtkaccelerator.h"
+#include "gtksignal.h"
+#include "gtkwidget.h"
+
+
+typedef struct _GtkAcceleratorEntry GtkAcceleratorEntry;
+
+struct _GtkAcceleratorEntry
+{
+ guint8 modifiers;
+ GtkObject *object;
+ gint signal_num;
+};
+
+
+static void gtk_accelerator_table_init (GtkAcceleratorTable *table);
+static void gtk_accelerator_table_clean (GtkAcceleratorTable *table);
+
+
+static GtkAcceleratorTable *default_table = NULL;
+static GSList *tables = NULL;
+static guint8 gtk_accelerator_table_default_mod_mask = ~0;
+
+
+GtkAcceleratorTable*
+gtk_accelerator_table_new ()
+{
+ GtkAcceleratorTable *table;
+
+ table = g_new (GtkAcceleratorTable, 1);
+ gtk_accelerator_table_init (table);
+
+ tables = g_slist_prepend (tables, table);
+
+ return table;
+}
+
+GtkAcceleratorTable*
+gtk_accelerator_table_find (GtkObject *object,
+ const gchar *signal_name,
+ guchar accelerator_key,
+ guint8 accelerator_mods)
+{
+ GtkAcceleratorTable *table;
+ GtkAcceleratorEntry *entry;
+ GSList *tmp_list;
+ GList *entries;
+ gint signal_num;
+ guint hash;
+
+ g_return_val_if_fail (object != NULL, NULL);
+ g_return_val_if_fail (signal_name != NULL, NULL);
+
+ signal_num = gtk_signal_lookup (signal_name, GTK_OBJECT_TYPE (object));
+ hash = (guint) accelerator_key;
+
+ tmp_list = tables;
+ while (tmp_list)
+ {
+ table = tmp_list->data;
+ tmp_list = tmp_list->next;
+
+ entries = table->entries[hash];
+ while (entries)
+ {
+ entry = entries->data;
+ entries = entries->next;
+
+ if ((entry->object == object) &&
+ (entry->signal_num == signal_num) &&
+ ((entry->modifiers & table->modifier_mask) ==
+ (accelerator_mods & table->modifier_mask)))
+ return table;
+ }
+ }
+
+ return NULL;
+}
+
+void
+gtk_accelerator_table_destroy (GtkAcceleratorTable *table)
+{
+ g_return_if_fail (table != NULL);
+ g_return_if_fail (table->ref_count <= 0);
+
+ tables = g_slist_remove (tables, table);
+ gtk_accelerator_table_clean (table);
+ g_free (table);
+}
+
+GtkAcceleratorTable*
+gtk_accelerator_table_ref (GtkAcceleratorTable *table)
+{
+ g_return_val_if_fail (table != NULL, NULL);
+
+ table->ref_count += 1;
+ return table;
+}
+
+void
+gtk_accelerator_table_unref (GtkAcceleratorTable *table)
+{
+ g_return_if_fail (table != NULL);
+
+ table->ref_count -= 1;
+ if (table->ref_count <= 0)
+ gtk_accelerator_table_destroy (table);
+}
+
+void
+gtk_accelerator_table_install (GtkAcceleratorTable *table,
+ GtkObject *object,
+ const gchar *signal_name,
+ guchar accelerator_key,
+ guint8 accelerator_mods)
+{
+ GtkAcceleratorEntry *entry;
+ GList *entries;
+ gchar *signame;
+ gint signal_num;
+ guint hash;
+
+ g_return_if_fail (object != NULL);
+
+ if (!table)
+ {
+ if (!default_table)
+ default_table = gtk_accelerator_table_new ();
+ table = default_table;
+ }
+
+ signal_num = gtk_signal_lookup (signal_name, GTK_OBJECT_TYPE (object));
+ g_return_if_fail (signal_num != 0);
+
+ hash = (guint) accelerator_key;
+ entries = table->entries[hash];
+
+ while (entries)
+ {
+ entry = entries->data;
+
+ if ((entry->modifiers & table->modifier_mask) ==
+ (accelerator_mods & table->modifier_mask))
+ {
+ if (GTK_IS_WIDGET (entry->object))
+ {
+ signame = gtk_signal_name (entry->signal_num);
+ gtk_signal_emit_by_name (entry->object,
+ "remove_accelerator",
+ signame);
+ }
+
+ entry->modifiers = accelerator_mods;
+ entry->object = object;
+ entry->signal_num = signal_num;
+ return;
+ }
+
+ entries = entries->next;
+ }
+
+ entry = g_new (GtkAcceleratorEntry, 1);
+ entry->modifiers = accelerator_mods;
+ entry->object = object;
+ entry->signal_num = signal_num;
+
+ table->entries[hash] = g_list_prepend (table->entries[hash], entry);
+}
+
+void
+gtk_accelerator_table_remove (GtkAcceleratorTable *table,
+ GtkObject *object,
+ const gchar *signal_name)
+{
+ GtkAcceleratorEntry *entry;
+ GList *entries;
+ GList *temp_list;
+ gint signal_num;
+ gint i;
+
+ g_return_if_fail (object != NULL);
+
+ if (!table)
+ {
+ if (!default_table)
+ default_table = gtk_accelerator_table_new ();
+ table = default_table;
+ }
+
+ signal_num = gtk_signal_lookup (signal_name, GTK_OBJECT_TYPE (object));
+ g_return_if_fail (signal_num != 0);
+
+ for (i = 0; i < 256; i++)
+ {
+ entries = table->entries[i];
+
+ while (entries)
+ {
+ entry = entries->data;
+
+ if ((entry->object == object) && (entry->signal_num == signal_num))
+ {
+ g_free (entry);
+
+ temp_list = entries;
+ if (entries->next)
+ entries->next->prev = entries->prev;
+ if (entries->prev)
+ entries->prev->next = entries->next;
+ if (table->entries[i] == entries)
+ table->entries[i] = entries->next;
+
+ temp_list->next = NULL;
+ temp_list->prev = NULL;
+ g_list_free (temp_list);
+
+ return;
+ }
+
+ entries = entries->next;
+ }
+ }
+}
+
+gint
+gtk_accelerator_table_check (GtkAcceleratorTable *table,
+ const guchar accelerator_key,
+ guint8 accelerator_mods)
+{
+ GtkAcceleratorEntry *entry;
+ GList *entries;
+ guint hash;
+
+ if (!table)
+ {
+ if (!default_table)
+ default_table = gtk_accelerator_table_new ();
+ table = default_table;
+ }
+
+ hash = (guint) accelerator_key;
+ entries = table->entries[hash];
+
+ while (entries)
+ {
+ entry = entries->data;
+
+ if ((entry->modifiers & table->modifier_mask) ==
+ (accelerator_mods & table->modifier_mask))
+ {
+ gtk_signal_emit (entry->object, entry->signal_num);
+ return TRUE;
+ }
+
+ entries = entries->next;
+ }
+
+ if (!isupper (hash))
+ {
+ hash = toupper (hash);
+ entries = table->entries[hash];
+
+ while (entries)
+ {
+ entry = entries->data;
+
+ if (((entry->modifiers & table->modifier_mask) ==
+ (accelerator_mods & table->modifier_mask)) &&
+ (GTK_IS_WIDGET (entry->object) &&
+ GTK_WIDGET_SENSITIVE (entry->object)))
+ {
+ gtk_signal_emit (entry->object, entry->signal_num);
+ return TRUE;
+ }
+
+ entries = entries->next;
+ }
+ }
+
+ return FALSE;
+}
+
+void
+gtk_accelerator_table_set_mod_mask (GtkAcceleratorTable *table,
+ guint8 modifier_mask)
+{
+ if (table == NULL)
+ {
+ gtk_accelerator_table_default_mod_mask = modifier_mask;
+ }
+ else
+ {
+ table->modifier_mask = modifier_mask;
+ }
+}
+
+static void
+gtk_accelerator_table_init (GtkAcceleratorTable *table)
+{
+ gint i;
+
+ g_return_if_fail (table != NULL);
+
+ for (i = 0; i < 256; i++)
+ table->entries[i] = NULL;
+
+ table->ref_count = 0;
+ table->modifier_mask = gtk_accelerator_table_default_mod_mask;
+}
+
+static void
+gtk_accelerator_table_clean (GtkAcceleratorTable *table)
+{
+ GtkAcceleratorEntry *entry;
+ GList *entries;
+ gint i;
+
+ g_return_if_fail (table != NULL);
+
+ for (i = 0; i < 256; i++)
+ {
+ entries = table->entries[i];
+ while (entries)
+ {
+ entry = entries->data;
+ entries = entries->next;
+
+ g_free (entry);
+ }
+
+ g_list_free (table->entries[i]);
+ table->entries[i] = NULL;
+ }
+}
diff --git a/gtk/gtkaccelerator.h b/gtk/gtkaccelerator.h
new file mode 100644
index 000000000..ac6323209
--- /dev/null
+++ b/gtk/gtkaccelerator.h
@@ -0,0 +1,73 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_ACCELERATOR_H__
+#define __GTK_ACCELERATOR_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkobject.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+typedef struct _GtkAcceleratorTable GtkAcceleratorTable;
+
+struct _GtkAcceleratorTable
+{
+ GList *entries[256];
+ gint ref_count;
+ guint8 modifier_mask;
+};
+
+
+/* Accelerator tables.
+ */
+GtkAcceleratorTable* gtk_accelerator_table_new (void);
+GtkAcceleratorTable* gtk_accelerator_table_find (GtkObject *object,
+ const gchar *signal_name,
+ guchar accelerator_key,
+ guint8 accelerator_mods);
+
+void gtk_accelerator_table_destroy (GtkAcceleratorTable *table);
+GtkAcceleratorTable *gtk_accelerator_table_ref (GtkAcceleratorTable *table);
+void gtk_accelerator_table_unref (GtkAcceleratorTable *table);
+void gtk_accelerator_table_install (GtkAcceleratorTable *table,
+ GtkObject *object,
+ const gchar *signal_name,
+ guchar accelerator_key,
+ guint8 accelerator_mods);
+void gtk_accelerator_table_remove (GtkAcceleratorTable *table,
+ GtkObject *object,
+ const gchar *signal_name);
+gint gtk_accelerator_table_check (GtkAcceleratorTable *table,
+ const guchar accelerator_key,
+ guint8 accelerator_mods);
+
+void gtk_accelerator_table_set_mod_mask (GtkAcceleratorTable *table,
+ guint8 modifier_mask);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_ACCELERATOR_H__ */
diff --git a/gtk/gtkadjustment.c b/gtk/gtkadjustment.c
new file mode 100644
index 000000000..ab6e63d21
--- /dev/null
+++ b/gtk/gtkadjustment.c
@@ -0,0 +1,118 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtkadjustment.h"
+#include "gtksignal.h"
+
+
+enum {
+ CHANGED,
+ VALUE_CHANGED,
+ LAST_SIGNAL
+};
+
+
+static void gtk_adjustment_class_init (GtkAdjustmentClass *klass);
+static void gtk_adjustment_init (GtkAdjustment *adjustment);
+
+
+static gint adjustment_signals[LAST_SIGNAL] = { 0 };
+
+
+guint
+gtk_adjustment_get_type ()
+{
+ static guint adjustment_type = 0;
+
+ if (!adjustment_type)
+ {
+ GtkTypeInfo adjustment_info =
+ {
+ "GtkAdjustment",
+ sizeof (GtkAdjustment),
+ sizeof (GtkAdjustmentClass),
+ (GtkClassInitFunc) gtk_adjustment_class_init,
+ (GtkObjectInitFunc) gtk_adjustment_init,
+ (GtkArgFunc) NULL,
+ };
+
+ adjustment_type = gtk_type_unique (gtk_data_get_type (), &adjustment_info);
+ }
+
+ return adjustment_type;
+}
+
+static void
+gtk_adjustment_class_init (GtkAdjustmentClass *class)
+{
+ GtkObjectClass *object_class;
+
+ object_class = (GtkObjectClass*) class;
+
+ adjustment_signals[CHANGED] =
+ gtk_signal_new ("changed",
+ GTK_RUN_FIRST | GTK_RUN_NO_RECURSE,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkAdjustmentClass, changed),
+ gtk_signal_default_marshaller,
+ GTK_TYPE_NONE, 0);
+ adjustment_signals[VALUE_CHANGED] =
+ gtk_signal_new ("value_changed",
+ GTK_RUN_FIRST | GTK_RUN_NO_RECURSE,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkAdjustmentClass, value_changed),
+ gtk_signal_default_marshaller,
+ GTK_TYPE_NONE, 0);
+
+ gtk_object_class_add_signals (object_class, adjustment_signals, LAST_SIGNAL);
+
+ class->changed = NULL;
+ class->value_changed = NULL;
+}
+
+static void
+gtk_adjustment_init (GtkAdjustment *adjustment)
+{
+ adjustment->value = 0.0;
+ adjustment->lower = 0.0;
+ adjustment->upper = 0.0;
+ adjustment->step_increment = 0.0;
+ adjustment->page_increment = 0.0;
+ adjustment->page_size = 0.0;
+}
+
+GtkObject*
+gtk_adjustment_new (gfloat value,
+ gfloat lower,
+ gfloat upper,
+ gfloat step_increment,
+ gfloat page_increment,
+ gfloat page_size)
+{
+ GtkAdjustment *adjustment;
+
+ adjustment = gtk_type_new (gtk_adjustment_get_type ());
+
+ adjustment->value = value;
+ adjustment->lower = lower;
+ adjustment->upper = upper;
+ adjustment->step_increment = step_increment;
+ adjustment->page_increment = page_increment;
+ adjustment->page_size = page_size;
+
+ return GTK_OBJECT (adjustment);
+}
diff --git a/gtk/gtkadjustment.h b/gtk/gtkadjustment.h
new file mode 100644
index 000000000..7832d1dd1
--- /dev/null
+++ b/gtk/gtkadjustment.h
@@ -0,0 +1,74 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_ADJUSTMENT_H__
+#define __GTK_ADJUSTMENT_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkdata.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_ADJUSTMENT(obj) GTK_CHECK_CAST (obj, gtk_adjustment_get_type (), GtkAdjustment)
+#define GTK_ADJUSTMENT_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_adjustment_get_type (), GtkAdjustmentClass)
+#define GTK_IS_ADJUSTMENT(obj) GTK_CHECK_TYPE (obj, gtk_adjustment_get_type ())
+
+
+typedef struct _GtkAdjustment GtkAdjustment;
+typedef struct _GtkAdjustmentClass GtkAdjustmentClass;
+
+struct _GtkAdjustment
+{
+ GtkData data;
+
+ gfloat lower;
+ gfloat upper;
+ gfloat value;
+ gfloat step_increment;
+ gfloat page_increment;
+ gfloat page_size;
+};
+
+struct _GtkAdjustmentClass
+{
+ GtkDataClass parent_class;
+
+ void (* changed) (GtkAdjustment *adjustment);
+ void (* value_changed) (GtkAdjustment *adjustment);
+};
+
+
+guint gtk_adjustment_get_type (void);
+GtkObject* gtk_adjustment_new (gfloat value,
+ gfloat lower,
+ gfloat upper,
+ gfloat step_increment,
+ gfloat page_increment,
+ gfloat page_size);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_ADJUSTMENT_H__ */
diff --git a/gtk/gtkalignment.c b/gtk/gtkalignment.c
new file mode 100644
index 000000000..b562cff77
--- /dev/null
+++ b/gtk/gtkalignment.c
@@ -0,0 +1,193 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtkalignment.h"
+
+
+static void gtk_alignment_class_init (GtkAlignmentClass *klass);
+static void gtk_alignment_init (GtkAlignment *alignment);
+static void gtk_alignment_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void gtk_alignment_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+
+
+guint
+gtk_alignment_get_type ()
+{
+ static guint alignment_type = 0;
+
+ if (!alignment_type)
+ {
+ GtkTypeInfo alignment_info =
+ {
+ "GtkAlignment",
+ sizeof (GtkAlignment),
+ sizeof (GtkAlignmentClass),
+ (GtkClassInitFunc) gtk_alignment_class_init,
+ (GtkObjectInitFunc) gtk_alignment_init,
+ (GtkArgFunc) NULL,
+ };
+
+ alignment_type = gtk_type_unique (gtk_bin_get_type (), &alignment_info);
+ }
+
+ return alignment_type;
+}
+
+static void
+gtk_alignment_class_init (GtkAlignmentClass *class)
+{
+ GtkWidgetClass *widget_class;
+
+ widget_class = (GtkWidgetClass*) class;
+
+ widget_class->size_request = gtk_alignment_size_request;
+ widget_class->size_allocate = gtk_alignment_size_allocate;
+}
+
+static void
+gtk_alignment_init (GtkAlignment *alignment)
+{
+ GTK_WIDGET_SET_FLAGS (alignment, GTK_NO_WINDOW | GTK_BASIC);
+
+ alignment->xalign = 0.5;
+ alignment->yalign = 0.5;
+ alignment->xscale = 1.0;
+ alignment->yscale = 1.0;
+}
+
+GtkWidget*
+gtk_alignment_new (gfloat xalign,
+ gfloat yalign,
+ gfloat xscale,
+ gfloat yscale)
+{
+ GtkAlignment *alignment;
+
+ alignment = gtk_type_new (gtk_alignment_get_type ());
+
+ alignment->xalign = CLAMP (xalign, 0.0, 1.0);
+ alignment->yalign = CLAMP (yalign, 0.0, 1.0);
+ alignment->xscale = CLAMP (xscale, 0.0, 1.0);
+ alignment->yscale = CLAMP (yscale, 0.0, 1.0);
+
+ return GTK_WIDGET (alignment);
+}
+
+void
+gtk_alignment_set (GtkAlignment *alignment,
+ gfloat xalign,
+ gfloat yalign,
+ gfloat xscale,
+ gfloat yscale)
+{
+ g_return_if_fail (alignment != NULL);
+ g_return_if_fail (GTK_IS_ALIGNMENT (alignment));
+
+ xalign = CLAMP (xalign, 0.0, 1.0);
+ yalign = CLAMP (yalign, 0.0, 1.0);
+ xscale = CLAMP (xscale, 0.0, 1.0);
+ yscale = CLAMP (yscale, 0.0, 1.0);
+
+ if ((alignment->xalign != xalign) ||
+ (alignment->yalign != yalign) ||
+ (alignment->xscale != xscale) ||
+ (alignment->yscale != yscale))
+ {
+ alignment->xalign = xalign;
+ alignment->yalign = yalign;
+ alignment->xscale = xscale;
+ alignment->yscale = yscale;
+
+ gtk_widget_size_allocate (GTK_WIDGET (alignment), &(GTK_WIDGET (alignment)->allocation));
+ gtk_widget_queue_draw (GTK_WIDGET (alignment));
+ }
+}
+
+
+static void
+gtk_alignment_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkAlignment *alignment;
+ GtkBin *bin;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_ALIGNMENT (widget));
+ g_return_if_fail (requisition != NULL);
+
+ alignment = GTK_ALIGNMENT (widget);
+ bin = GTK_BIN (widget);
+
+ requisition->width = GTK_CONTAINER (widget)->border_width * 2;
+ requisition->height = GTK_CONTAINER (widget)->border_width * 2;
+
+ if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
+ {
+ gtk_widget_size_request (bin->child, &bin->child->requisition);
+
+ requisition->width += bin->child->requisition.width;
+ requisition->height += bin->child->requisition.height;
+ }
+}
+
+static void
+gtk_alignment_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkAlignment *alignment;
+ GtkBin *bin;
+ GtkAllocation child_allocation;
+ gint width, height;
+ gint x, y;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_ALIGNMENT (widget));
+ g_return_if_fail (allocation != NULL);
+
+ widget->allocation = *allocation;
+ alignment = GTK_ALIGNMENT (widget);
+ bin = GTK_BIN (widget);
+
+ if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
+ {
+ x = GTK_CONTAINER (alignment)->border_width;
+ y = GTK_CONTAINER (alignment)->border_width;
+ width = allocation->width - 2 * x;
+ height = allocation->height - 2 * y;
+
+ if (width > bin->child->requisition.width)
+ child_allocation.width = (bin->child->requisition.width *
+ (1.0 - alignment->xscale) +
+ width * alignment->xscale);
+ else
+ child_allocation.width = width;
+
+ if (height > bin->child->requisition.height)
+ child_allocation.height = (bin->child->requisition.height *
+ (1.0 - alignment->yscale) +
+ height * alignment->yscale);
+ else
+ child_allocation.height = height;
+
+ child_allocation.x = alignment->xalign * (width - child_allocation.width) + allocation->x + x;
+ child_allocation.y = alignment->yalign * (height - child_allocation.height) + allocation->y + y;
+
+ gtk_widget_size_allocate (bin->child, &child_allocation);
+ }
+}
diff --git a/gtk/gtkalignment.h b/gtk/gtkalignment.h
new file mode 100644
index 000000000..c80ad7f14
--- /dev/null
+++ b/gtk/gtkalignment.h
@@ -0,0 +1,72 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_ALIGNMENT_H__
+#define __GTK_ALIGNMENT_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkbin.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_ALIGNMENT(obj) GTK_CHECK_CAST (obj, gtk_alignment_get_type (), GtkAlignment)
+#define GTK_ALIGNMENT_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_alignment_get_type (), GtkAlignmentClass)
+#define GTK_IS_ALIGNMENT(obj) GTK_CHECK_TYPE (obj, gtk_alignment_get_type ())
+
+
+typedef struct _GtkAlignment GtkAlignment;
+typedef struct _GtkAlignmentClass GtkAlignmentClass;
+
+struct _GtkAlignment
+{
+ GtkBin bin;
+
+ gfloat xalign;
+ gfloat yalign;
+ gfloat xscale;
+ gfloat yscale;
+};
+
+struct _GtkAlignmentClass
+{
+ GtkBinClass parent_class;
+};
+
+
+guint gtk_alignment_get_type (void);
+GtkWidget* gtk_alignment_new (gfloat xalign,
+ gfloat yalign,
+ gfloat xscale,
+ gfloat yscale);
+void gtk_alignment_set (GtkAlignment *alignment,
+ gfloat xalign,
+ gfloat yalign,
+ gfloat xscale,
+ gfloat yscale);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_ALIGNMENT_H__ */
diff --git a/gtk/gtkarrow.c b/gtk/gtkarrow.c
new file mode 100644
index 000000000..b8bc2143e
--- /dev/null
+++ b/gtk/gtkarrow.c
@@ -0,0 +1,165 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtkarrow.h"
+
+
+#define MIN_ARROW_SIZE 11
+
+
+static void gtk_arrow_class_init (GtkArrowClass *klass);
+static void gtk_arrow_init (GtkArrow *arrow);
+static gint gtk_arrow_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+
+
+guint
+gtk_arrow_get_type ()
+{
+ static guint arrow_type = 0;
+
+ if (!arrow_type)
+ {
+ GtkTypeInfo arrow_info =
+ {
+ "GtkArrow",
+ sizeof (GtkArrow),
+ sizeof (GtkArrowClass),
+ (GtkClassInitFunc) gtk_arrow_class_init,
+ (GtkObjectInitFunc) gtk_arrow_init,
+ (GtkArgFunc) NULL,
+ };
+
+ arrow_type = gtk_type_unique (gtk_misc_get_type (), &arrow_info);
+ }
+
+ return arrow_type;
+}
+
+static void
+gtk_arrow_class_init (GtkArrowClass *class)
+{
+ GtkWidgetClass *widget_class;
+
+ widget_class = (GtkWidgetClass*) class;
+
+ widget_class->expose_event = gtk_arrow_expose;
+}
+
+static void
+gtk_arrow_init (GtkArrow *arrow)
+{
+ GTK_WIDGET_SET_FLAGS (arrow, GTK_NO_WINDOW);
+
+ arrow->arrow_type = GTK_ARROW_RIGHT;
+ arrow->shadow_type = GTK_SHADOW_OUT;
+}
+
+GtkWidget*
+gtk_arrow_new (GtkArrowType arrow_type,
+ GtkShadowType shadow_type)
+{
+ GtkArrow *arrow;
+
+ arrow = gtk_type_new (gtk_arrow_get_type ());
+
+ GTK_WIDGET (arrow)->requisition.width = MIN_ARROW_SIZE + GTK_MISC (arrow)->xpad * 2;
+ GTK_WIDGET (arrow)->requisition.height = MIN_ARROW_SIZE + GTK_MISC (arrow)->ypad * 2;
+
+ arrow->arrow_type = arrow_type;
+ arrow->shadow_type = shadow_type;
+
+ return GTK_WIDGET (arrow);
+}
+
+void
+gtk_arrow_set (GtkArrow *arrow,
+ GtkArrowType arrow_type,
+ GtkShadowType shadow_type)
+{
+ g_return_if_fail (arrow != NULL);
+ g_return_if_fail (GTK_IS_ARROW (arrow));
+
+ if (((GtkArrowType) arrow->arrow_type != arrow_type) ||
+ ((GtkShadowType) arrow->shadow_type != shadow_type))
+ {
+ arrow->arrow_type = arrow_type;
+ arrow->shadow_type = shadow_type;
+
+ if (GTK_WIDGET_DRAWABLE (arrow))
+ {
+ gdk_window_clear_area (GTK_WIDGET (arrow)->window,
+ GTK_WIDGET (arrow)->allocation.x + 1,
+ GTK_WIDGET (arrow)->allocation.y + 1,
+ GTK_WIDGET (arrow)->allocation.width - 2,
+ GTK_WIDGET (arrow)->allocation.height - 2);
+ gtk_widget_queue_draw (GTK_WIDGET (arrow));
+ }
+ }
+}
+
+
+static gint
+gtk_arrow_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ GtkArrow *arrow;
+ GtkMisc *misc;
+ GtkShadowType shadow_type;
+ gint width, height;
+ gint x, y;
+ gint extent;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_ARROW (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ arrow = GTK_ARROW (widget);
+ misc = GTK_MISC (widget);
+
+ width = widget->allocation.width - misc->xpad * 2;
+ height = widget->allocation.height - misc->ypad * 2;
+ extent = MIN (width, height);
+
+ x = ((widget->allocation.x + misc->xpad) * (1.0 - misc->xalign) +
+ (widget->allocation.x + widget->allocation.width - extent - misc->ypad) * misc->xalign);
+ y = ((widget->allocation.y + misc->ypad) * (1.0 - misc->yalign) +
+ (widget->allocation.y + widget->allocation.height - extent - misc->ypad) * misc->yalign);
+
+ shadow_type = arrow->shadow_type;
+
+ if (widget->state == GTK_STATE_ACTIVE)
+ {
+ if (shadow_type == GTK_SHADOW_IN)
+ shadow_type = GTK_SHADOW_OUT;
+ else if (shadow_type == GTK_SHADOW_OUT)
+ shadow_type = GTK_SHADOW_IN;
+ else if (shadow_type == GTK_SHADOW_ETCHED_IN)
+ shadow_type = GTK_SHADOW_ETCHED_OUT;
+ else if (shadow_type == GTK_SHADOW_ETCHED_OUT)
+ shadow_type = GTK_SHADOW_ETCHED_IN;
+ }
+
+ gtk_draw_arrow (widget->style, widget->window,
+ widget->state, shadow_type, arrow->arrow_type, TRUE,
+ x, y, extent, extent);
+ }
+
+ return FALSE;
+}
diff --git a/gtk/gtkarrow.h b/gtk/gtkarrow.h
new file mode 100644
index 000000000..5a2edb0f5
--- /dev/null
+++ b/gtk/gtkarrow.h
@@ -0,0 +1,66 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_ARROW_H__
+#define __GTK_ARROW_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkmisc.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_ARROW(obj) GTK_CHECK_CAST (obj, gtk_arrow_get_type (), GtkArrow)
+#define GTK_ARROW_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_arrow_get_type (), GtkArrowClass)
+#define GTK_IS_ARROW(obj) GTK_CHECK_TYPE (obj, gtk_arrow_get_type ())
+
+
+typedef struct _GtkArrow GtkArrow;
+typedef struct _GtkArrowClass GtkArrowClass;
+
+struct _GtkArrow
+{
+ GtkMisc misc;
+
+ gint16 arrow_type;
+ gint16 shadow_type;
+};
+
+struct _GtkArrowClass
+{
+ GtkMiscClass parent_class;
+};
+
+
+guint gtk_arrow_get_type (void);
+GtkWidget* gtk_arrow_new (GtkArrowType arrow_type,
+ GtkShadowType shadow_type);
+void gtk_arrow_set (GtkArrow *arrow,
+ GtkArrowType arrow_type,
+ GtkShadowType shadow_type);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_ARROW_H__ */
diff --git a/gtk/gtkaspectframe.c b/gtk/gtkaspectframe.c
new file mode 100644
index 000000000..2e4795bca
--- /dev/null
+++ b/gtk/gtkaspectframe.c
@@ -0,0 +1,336 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * GtkAspectFrame: Ensure that the child window has a specified aspect ratio
+ * or, if obey_child, has the same aspect ratio as its requested size
+ *
+ * Copyright Owen Taylor 4/9/97
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtkaspectframe.h"
+
+static void gtk_aspect_frame_class_init (GtkAspectFrameClass *klass);
+static void gtk_aspect_frame_init (GtkAspectFrame *aspect_frame);
+static void gtk_aspect_frame_draw (GtkWidget *widget,
+ GdkRectangle *area);
+static void gtk_aspect_frame_paint (GtkWidget *widget,
+ GdkRectangle *area);
+static gint gtk_aspect_frame_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+static void gtk_aspect_frame_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+
+#define MAX_RATIO 10000.0
+#define MIN_RATIO 0.0001
+
+guint
+gtk_aspect_frame_get_type ()
+{
+ static guint aspect_frame_type = 0;
+
+ if (!aspect_frame_type)
+ {
+ GtkTypeInfo aspect_frame_info =
+ {
+ "GtkAspectFrame",
+ sizeof (GtkAspectFrame),
+ sizeof (GtkAspectFrameClass),
+ (GtkClassInitFunc) gtk_aspect_frame_class_init,
+ (GtkObjectInitFunc) gtk_aspect_frame_init,
+ (GtkArgFunc) NULL,
+ };
+
+ aspect_frame_type = gtk_type_unique (gtk_frame_get_type (), &aspect_frame_info);
+ }
+
+ return aspect_frame_type;
+}
+
+static void
+gtk_aspect_frame_class_init (GtkAspectFrameClass *class)
+{
+ GtkWidgetClass *widget_class;
+
+ widget_class = (GtkWidgetClass*) class;
+
+ widget_class->draw = gtk_aspect_frame_draw;
+ widget_class->expose_event = gtk_aspect_frame_expose;
+ widget_class->size_allocate = gtk_aspect_frame_size_allocate;
+}
+
+static void
+gtk_aspect_frame_init (GtkAspectFrame *aspect_frame)
+{
+ aspect_frame->xalign = 0.5;
+ aspect_frame->yalign = 0.5;
+ aspect_frame->ratio = 1.0;
+ aspect_frame->obey_child = 1;
+ aspect_frame->center_allocation.x = -1;
+ aspect_frame->center_allocation.y = -1;
+ aspect_frame->center_allocation.width = 1;
+ aspect_frame->center_allocation.height = 1;
+}
+
+GtkWidget*
+gtk_aspect_frame_new (const gchar *label,
+ gfloat xalign,
+ gfloat yalign,
+ gfloat ratio,
+ gint obey_child)
+{
+ GtkAspectFrame *aspect_frame;
+
+ aspect_frame = gtk_type_new (gtk_aspect_frame_get_type ());
+
+ aspect_frame->xalign = CLAMP (xalign, 0.0, 1.0);
+ aspect_frame->yalign = CLAMP (yalign, 0.0, 1.0);
+ aspect_frame->ratio = CLAMP (ratio, MIN_RATIO, MAX_RATIO);
+ aspect_frame->obey_child = obey_child;
+
+ gtk_frame_set_label (GTK_FRAME(aspect_frame), label);
+
+ return GTK_WIDGET (aspect_frame);
+}
+
+void
+gtk_aspect_frame_set (GtkAspectFrame *aspect_frame,
+ gfloat xalign,
+ gfloat yalign,
+ gfloat ratio,
+ gint obey_child)
+{
+ g_return_if_fail (aspect_frame != NULL);
+ g_return_if_fail (GTK_IS_ASPECT_FRAME (aspect_frame));
+
+ xalign = CLAMP (xalign, 0.0, 1.0);
+ yalign = CLAMP (yalign, 0.0, 1.0);
+ ratio = CLAMP (ratio, MIN_RATIO, MAX_RATIO);
+
+ if ((aspect_frame->xalign != xalign) ||
+ (aspect_frame->yalign != yalign) ||
+ (aspect_frame->ratio != ratio) ||
+ (aspect_frame->obey_child != obey_child))
+ {
+ aspect_frame->xalign = xalign;
+ aspect_frame->yalign = yalign;
+ aspect_frame->ratio = ratio;
+ aspect_frame->obey_child = obey_child;
+
+ gtk_widget_size_allocate (GTK_WIDGET (aspect_frame), &(GTK_WIDGET (aspect_frame)->allocation));
+ gtk_widget_queue_draw (GTK_WIDGET (aspect_frame));
+ }
+}
+
+static void
+gtk_aspect_frame_paint (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ GtkFrame *frame;
+ GtkStateType state;
+ gint height_extra;
+ gint label_area_width;
+ gint x, y;
+ GtkAllocation *allocation;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_ASPECT_FRAME (widget));
+ g_return_if_fail (area != NULL);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ frame = GTK_FRAME (widget);
+ allocation = &GTK_ASPECT_FRAME(widget)->center_allocation;
+
+ state = widget->state;
+ if (!GTK_WIDGET_IS_SENSITIVE (widget))
+ state = GTK_STATE_INSENSITIVE;
+
+ height_extra = frame->label_height - widget->style->klass->xthickness;
+ height_extra = MAX (height_extra, 0);
+
+ x = GTK_CONTAINER (frame)->border_width;
+ y = GTK_CONTAINER (frame)->border_width;
+
+ gtk_draw_shadow (widget->style, widget->window,
+ GTK_STATE_NORMAL, frame->shadow_type,
+ allocation->x + x,
+ allocation->y + y + height_extra / 2,
+ allocation->width - x * 2,
+ allocation->height - y * 2 - height_extra / 2);
+
+ if (frame->label)
+ {
+ label_area_width = (allocation->width +
+ GTK_CONTAINER (frame)->border_width * 2 -
+ widget->style->klass->xthickness * 2);
+
+ x = ((label_area_width - frame->label_width) * frame->label_xalign +
+ GTK_CONTAINER (frame)->border_width + widget->style->klass->xthickness);
+ y = (GTK_CONTAINER (frame)->border_width + widget->style->font->ascent);
+
+ gdk_window_clear_area (widget->window,
+ allocation->x + x + 2,
+ allocation->y + GTK_CONTAINER (frame)->border_width,
+ frame->label_width - 4, frame->label_height);
+ gtk_draw_string (widget->style, widget->window, state,
+ allocation->x + x + 3,
+ allocation->y + y,
+ frame->label);
+ }
+ }
+}
+
+/* the only modification to the next two routines is to call
+ gtk_aspect_frame_paint instead of gtk_frame_paint */
+
+static void
+gtk_aspect_frame_draw (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ GtkBin *bin;
+ GdkRectangle child_area;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_ASPECT_FRAME (widget));
+ g_return_if_fail (area != NULL);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ bin = GTK_BIN (widget);
+
+ gtk_aspect_frame_paint (widget, area);
+
+ if (bin->child && gtk_widget_intersect (bin->child, area, &child_area))
+ gtk_widget_draw (bin->child, &child_area);
+ }
+}
+
+static gint
+gtk_aspect_frame_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ GtkBin *bin;
+ GdkEventExpose child_event;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_ASPECT_FRAME (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ bin = GTK_BIN (widget);
+
+ gtk_aspect_frame_paint (widget, &event->area);
+
+ child_event = *event;
+ if (bin->child &&
+ GTK_WIDGET_NO_WINDOW (bin->child) &&
+ gtk_widget_intersect (bin->child, &event->area, &child_event.area))
+ gtk_widget_event (bin->child, (GdkEvent*) &child_event);
+ }
+
+ return FALSE;
+}
+
+static void
+gtk_aspect_frame_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkFrame *frame;
+ GtkAspectFrame *aspect_frame;
+ GtkBin *bin;
+
+ GtkAllocation child_allocation;
+ gint x,y;
+ gint width,height;
+ gdouble ratio;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_ASPECT_FRAME (widget));
+ g_return_if_fail (allocation != NULL);
+
+ aspect_frame = GTK_ASPECT_FRAME (widget);
+ frame = GTK_FRAME (widget);
+ bin = GTK_BIN (widget);
+
+ if (GTK_WIDGET_MAPPED (widget) &&
+ ((widget->allocation.x != allocation->x) ||
+ (widget->allocation.y != allocation->y) ||
+ (widget->allocation.width != allocation->width) ||
+ (widget->allocation.height != allocation->height)) &&
+ (widget->allocation.width != 0) &&
+ (widget->allocation.height != 0))
+ gdk_window_clear_area (widget->window,
+ widget->allocation.x,
+ widget->allocation.y,
+ widget->allocation.width,
+ widget->allocation.height);
+
+ widget->allocation = *allocation;
+
+ if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
+ {
+ if (aspect_frame->obey_child)
+ {
+ if (bin->child->requisition.height != 0)
+ {
+ ratio = (gdouble)bin->child->requisition.width /
+ bin->child->requisition.height;
+ if (ratio < MIN_RATIO) ratio = MIN_RATIO;
+ }
+ else
+ if (bin->child->requisition.height != 0)
+ ratio = MAX_RATIO;
+ else
+ ratio = 1.0;
+ }
+ else
+ ratio = aspect_frame->ratio;
+
+ x = (GTK_CONTAINER (frame)->border_width +
+ GTK_WIDGET (frame)->style->klass->xthickness);
+ width = allocation->width - x * 2;
+
+ y = (GTK_CONTAINER (frame)->border_width +
+ MAX (frame->label_height, GTK_WIDGET (frame)->style->klass->ythickness));
+ height = (allocation->height - y -
+ GTK_CONTAINER (frame)->border_width -
+ GTK_WIDGET (frame)->style->klass->ythickness);
+
+ if (ratio * height > width)
+ {
+ child_allocation.width = width;
+ child_allocation.height = width/ratio;
+ }
+ else
+ {
+ child_allocation.width = ratio*height;
+ child_allocation.height = height;
+ }
+
+ child_allocation.x = aspect_frame->xalign * (width - child_allocation.width) + allocation->x + x;
+ child_allocation.y = aspect_frame->yalign * (height - child_allocation.height) + allocation->y + y;
+
+ aspect_frame->center_allocation.width = child_allocation.width + 2*x;
+ aspect_frame->center_allocation.x = child_allocation.x - x;
+ aspect_frame->center_allocation.height = child_allocation.height + y +
+ GTK_CONTAINER (frame)->border_width +
+ GTK_WIDGET (frame)->style->klass->ythickness;
+ aspect_frame->center_allocation.y = child_allocation.y - y;
+
+ gtk_widget_size_allocate (bin->child, &child_allocation);
+ }
+}
diff --git a/gtk/gtkaspectframe.h b/gtk/gtkaspectframe.h
new file mode 100644
index 000000000..07f08a4cc
--- /dev/null
+++ b/gtk/gtkaspectframe.h
@@ -0,0 +1,75 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_ASPECT_FRAME_H__
+#define __GTK_ASPECT_FRAME_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkbin.h>
+#include <gtk/gtkframe.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_ASPECT_FRAME(obj) ((GtkAspectFrame*) obj)
+#define GTK_ASPECT_FRAME_CLASS(obj) ((GtkAspectFrameClass*) GTK_OBJECT_CLASS (obj))
+#define GTK_IS_ASPECT_FRAME(obj) (gtk_type_is_a (GTK_WIDGET_TYPE (obj), gtk_aspect_frame_get_type ()))
+
+
+typedef struct _GtkAspectFrame GtkAspectFrame;
+typedef struct _GtkAspectFrameClass GtkAspectFrameClass;
+
+struct _GtkAspectFrame
+{
+ GtkFrame frame;
+
+ gfloat xalign;
+ gfloat yalign;
+ gfloat ratio;
+ gint obey_child;
+
+ GtkAllocation center_allocation;
+};
+
+struct _GtkAspectFrameClass
+{
+ GtkBinClass parent_class;
+};
+
+
+guint gtk_aspect_frame_get_type (void);
+GtkWidget* gtk_aspect_frame_new (const gchar *label,
+ gfloat xalign,
+ gfloat yalign,
+ gfloat ratio,
+ gint obey_child);
+void gtk_aspect_frame_set (GtkAspectFrame *aspect_frame,
+ gfloat xalign,
+ gfloat yalign,
+ gfloat ratio,
+ gint obey_child);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_ASPECT_FRAME_H__ */
diff --git a/gtk/gtkbbox.c b/gtk/gtkbbox.c
new file mode 100644
index 000000000..818493f9a
--- /dev/null
+++ b/gtk/gtkbbox.c
@@ -0,0 +1,228 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtkbbox.h"
+
+
+static void gtk_button_box_class_init (GtkButtonBoxClass *klass);
+static void gtk_button_box_init (GtkButtonBox *box);
+
+
+static gint default_child_min_width = 85;
+static gint default_child_min_height = 27;
+static gint default_child_ipad_x = 7;
+static gint default_child_ipad_y = 0;
+
+
+guint
+gtk_button_box_get_type ()
+{
+ static guint button_box_type = 0;
+
+ if (!button_box_type)
+ {
+ GtkTypeInfo button_box_info =
+ {
+ "GtkButtonBox",
+ sizeof (GtkButtonBox),
+ sizeof (GtkButtonBoxClass),
+ (GtkClassInitFunc) gtk_button_box_class_init,
+ (GtkObjectInitFunc) gtk_button_box_init,
+ (GtkArgFunc) NULL,
+ };
+
+ button_box_type = gtk_type_unique (gtk_box_get_type (), &button_box_info);
+ }
+
+ return button_box_type;
+}
+
+static void
+gtk_button_box_class_init (GtkButtonBoxClass *class)
+{
+ GtkWidgetClass *widget_class;
+
+ widget_class = (GtkWidgetClass*) class;
+}
+
+static void
+gtk_button_box_init (GtkButtonBox *button_box)
+{
+ button_box->spacing = GTK_BUTTONBOX_DEFAULT;
+ button_box->child_min_width = GTK_BUTTONBOX_DEFAULT;
+ button_box->child_min_height = GTK_BUTTONBOX_DEFAULT;
+ button_box->child_ipad_x = GTK_BUTTONBOX_DEFAULT;
+ button_box->child_ipad_y = GTK_BUTTONBOX_DEFAULT;
+ button_box->layout_style = GTK_BUTTONBOX_DEFAULT;
+}
+
+
+/* set default values for child size and child internal padding */
+/* default spacing is in defined in subclasses */
+
+void gtk_button_box_set_child_size_default (gint width, gint height)
+{
+ default_child_min_width = width;
+ default_child_min_height = height;
+}
+
+void gtk_button_box_set_child_ipadding_default (gint ipad_x, gint ipad_y)
+{
+ default_child_ipad_x = ipad_x;
+ default_child_ipad_y = ipad_y;
+}
+
+/* get default values for child size and child internal padding */
+
+void gtk_button_box_get_child_size_default (gint *width, gint *height)
+{
+ *width = default_child_min_width;
+ *height = default_child_min_height;
+}
+
+void gtk_button_box_get_child_ipadding_default (gint *ipad_x, gint *ipad_y)
+{
+ *ipad_x = default_child_ipad_x;
+ *ipad_y = default_child_ipad_y;
+}
+
+/* set per widget values for spacing, child size and child internal padding */
+
+void gtk_button_box_set_spacing (GtkButtonBox *widget, gint spacing)
+{
+ widget->spacing = spacing;
+}
+
+void gtk_button_box_set_child_size (GtkButtonBox *widget, gint width, gint height)
+{
+ widget->child_min_width = width;
+ widget->child_min_height = height;
+}
+
+void gtk_button_box_set_child_ipadding (GtkButtonBox *widget,
+ gint ipad_x, gint ipad_y)
+{
+ widget->child_ipad_x = ipad_x;
+ widget->child_ipad_y = ipad_y;
+}
+
+void gtk_button_box_set_layout (GtkButtonBox *widget, gint layout_style)
+{
+ widget->layout_style = layout_style;
+}
+
+
+/* get per widget values for spacing, child size and child internal padding */
+
+gint gtk_button_box_get_spacing (GtkButtonBox *widget)
+{
+ return widget->spacing;
+}
+
+void gtk_button_box_get_child_size (GtkButtonBox *widget,
+ gint *width, gint *height)
+{
+ *width = widget->child_min_width;
+ *height = widget->child_min_height;
+}
+
+void gtk_button_box_get_child_ipadding (GtkButtonBox *widget,
+ gint* ipad_x, gint *ipad_y)
+{
+ *ipad_x = widget->child_ipad_x;
+ *ipad_y = widget->child_ipad_y;
+}
+
+gint gtk_button_box_get_layout (GtkButtonBox *widget)
+{
+ return widget->layout_style;
+}
+
+
+
+/* Ask children how much space they require and round up
+ to match minimum size and internal padding.
+ Returns the size each single child should have. */
+void
+gtk_button_box_child_requisition (GtkWidget *widget,
+ int *nvis_children,
+ int *width,
+ int *height)
+{
+ GtkButtonBox *bbox;
+ GtkBoxChild *child;
+ GList *children;
+ gint nchildren;
+ gint needed_width;
+ gint needed_height;
+ GtkRequisition child_requisition;
+ gint ipad_w;
+ gint ipad_h;
+ gint width_default;
+ gint height_default;
+ gint ipad_x_default;
+ gint ipad_y_default;
+
+ gint child_min_width;
+ gint child_min_height;
+ gint ipad_x;
+ gint ipad_y;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_BUTTON_BOX (widget));
+
+ bbox = GTK_BUTTON_BOX (widget);
+
+ gtk_button_box_get_child_size_default (&width_default, &height_default);
+ gtk_button_box_get_child_ipadding_default (&ipad_x_default, &ipad_y_default);
+
+ child_min_width = bbox->child_min_width != GTK_BUTTONBOX_DEFAULT
+ ? bbox->child_min_width : width_default;
+ child_min_height = bbox->child_min_height !=GTK_BUTTONBOX_DEFAULT
+ ? bbox->child_min_height : height_default;
+ ipad_x = bbox->child_ipad_x != GTK_BUTTONBOX_DEFAULT
+ ? bbox->child_ipad_x : ipad_x_default;
+ ipad_y = bbox->child_ipad_y != GTK_BUTTONBOX_DEFAULT
+ ? bbox->child_ipad_y : ipad_y_default;
+
+ nchildren = 0;
+ children = GTK_BOX(bbox)->children;
+ needed_width = child_min_width;
+ needed_height = child_min_height;
+ ipad_w = ipad_x * 2;
+ ipad_h = ipad_y * 2;
+
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_VISIBLE (child->widget))
+ {
+ nchildren += 1;
+ gtk_widget_size_request (child->widget, &child_requisition);
+ if (child_requisition.width + ipad_w > needed_width)
+ needed_width = child_requisition.width + ipad_w;
+ if (child_requisition.height + ipad_h > needed_height)
+ needed_height = child_requisition.height + ipad_h;
+ }
+ }
+
+ *nvis_children = nchildren;
+ *width = needed_width;
+ *height = needed_height;
+}
diff --git a/gtk/gtkbbox.h b/gtk/gtkbbox.h
new file mode 100644
index 000000000..816f1f0c2
--- /dev/null
+++ b/gtk/gtkbbox.h
@@ -0,0 +1,93 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_BUTTON_BOX_H__
+#define __GTK_BUTTON_BOX_H__
+
+#include "gtkbox.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_BUTTON_BOX(obj) GTK_CHECK_CAST (obj, gtk_button_box_get_type (), GtkButtonBox)
+#define GTK_BUTTON_BOX_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_button_box_get_type (), GtkButtonBoxClass)
+#define GTK_IS_BUTTON_BOX(obj) GTK_CHECK_TYPE (obj, gtk_button_box_get_type ())
+
+#define GTK_BUTTONBOX_DEFAULT -1
+#define GTK_BUTTONBOX_SPREAD 1
+#define GTK_BUTTONBOX_EDGE 2
+#define GTK_BUTTONBOX_START 3
+#define GTK_BUTTONBOX_END 4
+
+typedef struct _GtkButtonBox GtkButtonBox;
+typedef struct _GtkButtonBoxClass GtkButtonBoxClass;
+
+struct _GtkButtonBox
+{
+ GtkBox box;
+ gint spacing;
+ gint child_min_width;
+ gint child_min_height;
+ gint child_ipad_x;
+ gint child_ipad_y;
+ gint layout_style;
+};
+
+struct _GtkButtonBoxClass
+{
+ GtkBoxClass parent_class;
+};
+
+
+guint gtk_button_box_get_type (void);
+
+void gtk_button_box_get_child_size_default (gint *min_width, gint *min_height);
+void gtk_button_box_get_child_ipadding_default (gint *ipad_x, gint *ipad_y);
+
+void gtk_button_box_set_child_size_default (gint min_width, gint min_height);
+void gtk_button_box_set_child_ipadding_default (gint ipad_x, gint ipad_y);
+
+gint gtk_button_box_get_spacing (GtkButtonBox *widget);
+gint gtk_button_box_get_layout (GtkButtonBox *widget);
+void gtk_button_box_get_child_size (GtkButtonBox *widget,
+ gint *min_width, gint *min_height);
+void gtk_button_box_get_child_ipadding (GtkButtonBox *widget, gint *ipad_x, gint *ipad_y);
+
+void gtk_button_box_set_spacing (GtkButtonBox *widget, gint spacing);
+void gtk_button_box_set_layout (GtkButtonBox *widget, gint layout_style);
+void gtk_button_box_set_child_size (GtkButtonBox *widget,
+ gint min_width, gint min_height);
+void gtk_button_box_set_child_ipadding (GtkButtonBox *widget, gint ipad_x, gint ipad_y);
+
+
+/* Internal method - do not use. */
+void gtk_button_box_child_requisition (GtkWidget *widget,
+ int *nvis_children,
+ int *width,
+ int *height);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_BUTTON_BOX_H__ */
+
+
diff --git a/gtk/gtkbin.c b/gtk/gtkbin.c
new file mode 100644
index 000000000..4cb7efcc1
--- /dev/null
+++ b/gtk/gtkbin.c
@@ -0,0 +1,286 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtkbin.h"
+
+
+static void gtk_bin_class_init (GtkBinClass *klass);
+static void gtk_bin_init (GtkBin *bin);
+static void gtk_bin_destroy (GtkObject *object);
+static void gtk_bin_map (GtkWidget *widget);
+static void gtk_bin_unmap (GtkWidget *widget);
+static void gtk_bin_draw (GtkWidget *widget,
+ GdkRectangle *area);
+static gint gtk_bin_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+static void gtk_bin_add (GtkContainer *container,
+ GtkWidget *widget);
+static void gtk_bin_remove (GtkContainer *container,
+ GtkWidget *widget);
+static void gtk_bin_foreach (GtkContainer *container,
+ GtkCallback callback,
+ gpointer callback_data);
+
+
+static GtkContainerClass *parent_class = NULL;
+
+
+guint
+gtk_bin_get_type ()
+{
+ static guint bin_type = 0;
+
+ if (!bin_type)
+ {
+ GtkTypeInfo bin_info =
+ {
+ "GtkBin",
+ sizeof (GtkBin),
+ sizeof (GtkBinClass),
+ (GtkClassInitFunc) gtk_bin_class_init,
+ (GtkObjectInitFunc) gtk_bin_init,
+ (GtkArgFunc) NULL,
+ };
+
+ bin_type = gtk_type_unique (gtk_container_get_type (), &bin_info);
+ }
+
+ return bin_type;
+}
+
+static void
+gtk_bin_class_init (GtkBinClass *class)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+ GtkContainerClass *container_class;
+
+ object_class = (GtkObjectClass*) class;
+ widget_class = (GtkWidgetClass*) class;
+ container_class = (GtkContainerClass*) class;
+
+ parent_class = gtk_type_class (gtk_container_get_type ());
+
+ object_class->destroy = gtk_bin_destroy;
+
+ widget_class->map = gtk_bin_map;
+ widget_class->unmap = gtk_bin_unmap;
+ widget_class->draw = gtk_bin_draw;
+ widget_class->expose_event = gtk_bin_expose;
+
+ container_class->add = gtk_bin_add;
+ container_class->remove = gtk_bin_remove;
+ container_class->foreach = gtk_bin_foreach;
+}
+
+static void
+gtk_bin_init (GtkBin *bin)
+{
+ GTK_WIDGET_SET_FLAGS (bin, GTK_NO_WINDOW);
+
+ bin->child = NULL;
+}
+
+
+static void
+gtk_bin_destroy (GtkObject *object)
+{
+ GtkBin *bin;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_BIN (object));
+
+ bin = GTK_BIN (object);
+
+ if (bin->child)
+ {
+ bin->child->parent = NULL;
+ gtk_object_unref (GTK_OBJECT (bin->child));
+ gtk_widget_destroy (bin->child);
+ }
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+static void
+gtk_bin_map (GtkWidget *widget)
+{
+ GtkBin *bin;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_BIN (widget));
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
+ bin = GTK_BIN (widget);
+
+ if (!GTK_WIDGET_NO_WINDOW (widget))
+ gdk_window_show (widget->window);
+ else
+ gtk_widget_queue_draw (widget);
+
+ if (bin->child &&
+ GTK_WIDGET_VISIBLE (bin->child) &&
+ !GTK_WIDGET_MAPPED (bin->child))
+ gtk_widget_map (bin->child);
+}
+
+static void
+gtk_bin_unmap (GtkWidget *widget)
+{
+ GtkBin *bin;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_BIN (widget));
+
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
+ bin = GTK_BIN (widget);
+
+ if (GTK_WIDGET_NO_WINDOW (widget))
+ gdk_window_clear_area (widget->window,
+ widget->allocation.x,
+ widget->allocation.y,
+ widget->allocation.width,
+ widget->allocation.height);
+ else
+ gdk_window_hide (widget->window);
+
+ if (bin->child &&
+ GTK_WIDGET_VISIBLE (bin->child) &&
+ GTK_WIDGET_MAPPED (bin->child))
+ gtk_widget_unmap (bin->child);
+}
+
+static void
+gtk_bin_draw (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ GtkBin *bin;
+ GdkRectangle child_area;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_BIN (widget));
+
+ if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget))
+ {
+ bin = GTK_BIN (widget);
+
+ if (bin->child &&
+ gtk_widget_intersect (bin->child, area, &child_area))
+ gtk_widget_draw (bin->child, &child_area);
+ }
+}
+
+static gint
+gtk_bin_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ GtkBin *bin;
+ GdkEventExpose child_event;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_BIN (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ bin = GTK_BIN (widget);
+
+ child_event = *event;
+ if (bin->child &&
+ GTK_WIDGET_NO_WINDOW (bin->child) &&
+ gtk_widget_intersect (bin->child, &event->area, &child_event.area))
+ gtk_widget_event (bin->child, (GdkEvent*) &child_event);
+ }
+
+ return FALSE;
+}
+
+
+static void
+gtk_bin_add (GtkContainer *container,
+ GtkWidget *widget)
+{
+ GtkBin *bin;
+
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_BIN (container));
+ g_return_if_fail (widget != NULL);
+
+ bin = GTK_BIN (container);
+
+ if (!bin->child)
+ {
+ gtk_widget_set_parent (widget, GTK_WIDGET (container));
+
+ if (GTK_WIDGET_VISIBLE (widget->parent))
+ {
+ if (GTK_WIDGET_REALIZED (widget->parent) &&
+ !GTK_WIDGET_REALIZED (widget))
+ gtk_widget_realize (widget);
+
+ if (GTK_WIDGET_MAPPED (widget->parent) &&
+ !GTK_WIDGET_MAPPED (widget))
+ gtk_widget_map (widget);
+ }
+
+ bin->child = widget;
+
+ if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (container))
+ gtk_widget_queue_resize (widget);
+ }
+}
+
+static void
+gtk_bin_remove (GtkContainer *container,
+ GtkWidget *widget)
+{
+ GtkBin *bin;
+
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_BIN (container));
+ g_return_if_fail (widget != NULL);
+
+ bin = GTK_BIN (container);
+
+ if (bin->child == widget)
+ {
+ gtk_widget_unparent (widget);
+
+ bin->child = NULL;
+
+ if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (container))
+ gtk_widget_queue_resize (GTK_WIDGET (container));
+ }
+}
+
+static void
+gtk_bin_foreach (GtkContainer *container,
+ GtkCallback callback,
+ gpointer callback_data)
+{
+ GtkBin *bin;
+
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_BIN (container));
+ g_return_if_fail (callback != NULL);
+
+ bin = GTK_BIN (container);
+
+ if (bin->child)
+ (* callback) (bin->child, callback_data);
+}
diff --git a/gtk/gtkbin.h b/gtk/gtkbin.h
new file mode 100644
index 000000000..c8676ab84
--- /dev/null
+++ b/gtk/gtkbin.h
@@ -0,0 +1,60 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_BIN_H__
+#define __GTK_BIN_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkcontainer.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_BIN(obj) GTK_CHECK_CAST (obj, gtk_bin_get_type (), GtkBin)
+#define GTK_BIN_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_bin_get_type (), GtkBinClass)
+#define GTK_IS_BIN(obj) GTK_CHECK_TYPE (obj, gtk_bin_get_type ())
+
+
+typedef struct _GtkBin GtkBin;
+typedef struct _GtkBinClass GtkBinClass;
+
+struct _GtkBin
+{
+ GtkContainer container;
+
+ GtkWidget *child;
+};
+
+struct _GtkBinClass
+{
+ GtkContainerClass parent_class;
+};
+
+
+guint gtk_bin_get_type (void);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_BIN_H__ */
diff --git a/gtk/gtkbox.c b/gtk/gtkbox.c
new file mode 100644
index 000000000..dfb2fed08
--- /dev/null
+++ b/gtk/gtkbox.c
@@ -0,0 +1,453 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtkbox.h"
+
+
+static void gtk_box_class_init (GtkBoxClass *klass);
+static void gtk_box_init (GtkBox *box);
+static void gtk_box_destroy (GtkObject *object);
+static void gtk_box_map (GtkWidget *widget);
+static void gtk_box_unmap (GtkWidget *widget);
+static void gtk_box_draw (GtkWidget *widget,
+ GdkRectangle *area);
+static gint gtk_box_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+static void gtk_box_add (GtkContainer *container,
+ GtkWidget *widget);
+static void gtk_box_remove (GtkContainer *container,
+ GtkWidget *widget);
+static void gtk_box_foreach (GtkContainer *container,
+ GtkCallback callback,
+ gpointer callback_data);
+
+
+static GtkContainerClass *parent_class = NULL;
+
+
+guint
+gtk_box_get_type ()
+{
+ static guint box_type = 0;
+
+ if (!box_type)
+ {
+ GtkTypeInfo box_info =
+ {
+ "GtkBox",
+ sizeof (GtkBox),
+ sizeof (GtkBoxClass),
+ (GtkClassInitFunc) gtk_box_class_init,
+ (GtkObjectInitFunc) gtk_box_init,
+ (GtkArgFunc) NULL,
+ };
+
+ box_type = gtk_type_unique (gtk_container_get_type (), &box_info);
+ }
+
+ return box_type;
+}
+
+static void
+gtk_box_class_init (GtkBoxClass *class)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+ GtkContainerClass *container_class;
+
+ object_class = (GtkObjectClass*) class;
+ widget_class = (GtkWidgetClass*) class;
+ container_class = (GtkContainerClass*) class;
+
+ parent_class = gtk_type_class (gtk_container_get_type ());
+
+ object_class->destroy = gtk_box_destroy;
+
+ widget_class->map = gtk_box_map;
+ widget_class->unmap = gtk_box_unmap;
+ widget_class->draw = gtk_box_draw;
+ widget_class->expose_event = gtk_box_expose;
+
+ container_class->add = gtk_box_add;
+ container_class->remove = gtk_box_remove;
+ container_class->foreach = gtk_box_foreach;
+}
+
+static void
+gtk_box_init (GtkBox *box)
+{
+ GTK_WIDGET_SET_FLAGS (box, GTK_NO_WINDOW | GTK_BASIC);
+
+ box->children = NULL;
+ box->spacing = 0;
+ box->homogeneous = FALSE;
+}
+
+void
+gtk_box_pack_start (GtkBox *box,
+ GtkWidget *child,
+ gint expand,
+ gint fill,
+ gint padding)
+{
+ GtkBoxChild *child_info;
+
+ g_return_if_fail (box != NULL);
+ g_return_if_fail (GTK_IS_BOX (box));
+ g_return_if_fail (child != NULL);
+
+ child_info = g_new (GtkBoxChild, 1);
+ child_info->widget = child;
+ child_info->padding = padding;
+ child_info->expand = expand ? TRUE : FALSE;
+ child_info->fill = fill ? TRUE : FALSE;
+ child_info->pack = GTK_PACK_START;
+
+ box->children = g_list_append (box->children, child_info);
+
+ gtk_widget_set_parent (child, GTK_WIDGET (box));
+
+ if (GTK_WIDGET_VISIBLE (GTK_WIDGET (box)))
+ {
+ if (GTK_WIDGET_REALIZED (GTK_WIDGET (box)) &&
+ !GTK_WIDGET_REALIZED (child))
+ gtk_widget_realize (child);
+
+ if (GTK_WIDGET_MAPPED (GTK_WIDGET (box)) &&
+ !GTK_WIDGET_MAPPED (child))
+ gtk_widget_map (child);
+ }
+
+ if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (box))
+ gtk_widget_queue_resize (child);
+}
+
+void
+gtk_box_pack_end (GtkBox *box,
+ GtkWidget *child,
+ gint expand,
+ gint fill,
+ gint padding)
+{
+ GtkBoxChild *child_info;
+
+ g_return_if_fail (box != NULL);
+ g_return_if_fail (GTK_IS_BOX (box));
+ g_return_if_fail (child != NULL);
+
+ child_info = g_new (GtkBoxChild, 1);
+ child_info->widget = child;
+ child_info->padding = padding;
+ child_info->expand = expand ? TRUE : FALSE;
+ child_info->fill = fill ? TRUE : FALSE;
+ child_info->pack = GTK_PACK_END;
+
+ box->children = g_list_append (box->children, child_info);
+
+ gtk_widget_set_parent (child, GTK_WIDGET (box));
+
+ if (GTK_WIDGET_VISIBLE (GTK_WIDGET (box)))
+ {
+ if (GTK_WIDGET_REALIZED (GTK_WIDGET (box)) &&
+ !GTK_WIDGET_REALIZED (child))
+ gtk_widget_realize (child);
+
+ if (GTK_WIDGET_MAPPED (GTK_WIDGET (box)) &&
+ !GTK_WIDGET_MAPPED (child))
+ gtk_widget_map (child);
+ }
+
+ if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (box))
+ gtk_widget_queue_resize (child);
+}
+
+void
+gtk_box_pack_start_defaults (GtkBox *box,
+ GtkWidget *child)
+{
+ g_return_if_fail (box != NULL);
+ g_return_if_fail (GTK_IS_BOX (box));
+ g_return_if_fail (child != NULL);
+
+ gtk_box_pack_start (box, child, TRUE, TRUE, 0);
+}
+
+void
+gtk_box_pack_end_defaults (GtkBox *box,
+ GtkWidget *child)
+{
+ g_return_if_fail (box != NULL);
+ g_return_if_fail (GTK_IS_BOX (box));
+ g_return_if_fail (child != NULL);
+
+ gtk_box_pack_end (box, child, TRUE, TRUE, 0);
+}
+
+void
+gtk_box_set_homogeneous (GtkBox *box,
+ gint homogeneous)
+{
+ g_return_if_fail (box != NULL);
+ g_return_if_fail (GTK_IS_BOX (box));
+
+ if ((homogeneous ? TRUE : FALSE) != box->homogeneous)
+ {
+ box->homogeneous = homogeneous ? TRUE : FALSE;
+ gtk_widget_queue_resize (GTK_WIDGET (box));
+ }
+}
+
+void
+gtk_box_set_spacing (GtkBox *box,
+ gint spacing)
+{
+ g_return_if_fail (box != NULL);
+ g_return_if_fail (GTK_IS_BOX (box));
+
+ if (spacing != box->spacing)
+ {
+ box->spacing = spacing;
+ gtk_widget_queue_resize (GTK_WIDGET (box));
+ }
+}
+
+
+static void
+gtk_box_destroy (GtkObject *object)
+{
+ GtkBox *box;
+ GtkBoxChild *child;
+ GList *children;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_BOX (object));
+
+ box = GTK_BOX (object);
+
+ children = box->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ child->widget->parent = NULL;
+ gtk_object_unref (GTK_OBJECT (child->widget));
+ gtk_widget_destroy (child->widget);
+ g_free (child);
+ }
+
+ g_list_free (box->children);
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+static void
+gtk_box_map (GtkWidget *widget)
+{
+ GtkBox *box;
+ GtkBoxChild *child;
+ GList *children;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_BOX (widget));
+
+ box = GTK_BOX (widget);
+ GTK_WIDGET_SET_FLAGS (box, GTK_MAPPED);
+
+ children = box->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_VISIBLE (child->widget) &&
+ !GTK_WIDGET_MAPPED (child->widget))
+ gtk_widget_map (child->widget);
+ }
+}
+
+static void
+gtk_box_unmap (GtkWidget *widget)
+{
+ GtkBox *box;
+ GtkBoxChild *child;
+ GList *children;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_BOX (widget));
+
+ box = GTK_BOX (widget);
+ GTK_WIDGET_UNSET_FLAGS (box, GTK_MAPPED);
+
+ children = box->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_VISIBLE (child->widget) &&
+ GTK_WIDGET_MAPPED (child->widget))
+ gtk_widget_unmap (child->widget);
+ }
+}
+
+static void
+gtk_box_draw (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ GtkBox *box;
+ GtkBoxChild *child;
+ GdkRectangle child_area;
+ GList *children;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_BOX (widget));
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ box = GTK_BOX (widget);
+
+ children = box->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (gtk_widget_intersect (child->widget, area, &child_area))
+ gtk_widget_draw (child->widget, &child_area);
+ }
+ }
+}
+
+static gint
+gtk_box_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ GtkBox *box;
+ GtkBoxChild *child;
+ GdkEventExpose child_event;
+ GList *children;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_BOX (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ box = GTK_BOX (widget);
+
+ child_event = *event;
+
+ children = box->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_NO_WINDOW (child->widget) &&
+ gtk_widget_intersect (child->widget, &event->area, &child_event.area))
+ gtk_widget_event (child->widget, (GdkEvent*) &child_event);
+ }
+ }
+
+ return FALSE;
+}
+
+static void
+gtk_box_add (GtkContainer *container,
+ GtkWidget *widget)
+{
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_BOX (container));
+ g_return_if_fail (widget != NULL);
+
+ gtk_box_pack_start_defaults (GTK_BOX (container), widget);
+}
+
+static void
+gtk_box_remove (GtkContainer *container,
+ GtkWidget *widget)
+{
+ GtkBox *box;
+ GtkBoxChild *child;
+ GList *children;
+
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_BOX (container));
+ g_return_if_fail (widget != NULL);
+
+ box = GTK_BOX (container);
+
+ children = box->children;
+ while (children)
+ {
+ child = children->data;
+
+ if (child->widget == widget)
+ {
+ gtk_widget_unparent (widget);
+
+ box->children = g_list_remove_link (box->children, children);
+ g_list_free (children);
+ g_free (child);
+
+ if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (container))
+ gtk_widget_queue_resize (GTK_WIDGET (container));
+
+ break;
+ }
+
+ children = children->next;
+ }
+}
+
+static void
+gtk_box_foreach (GtkContainer *container,
+ GtkCallback callback,
+ gpointer callback_data)
+{
+ GtkBox *box;
+ GtkBoxChild *child;
+ GList *children;
+
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_BOX (container));
+ g_return_if_fail (callback != NULL);
+
+ box = GTK_BOX (container);
+
+ children = box->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (child->pack == GTK_PACK_START)
+ (* callback) (child->widget, callback_data);
+ }
+
+ children = g_list_last (box->children);
+ while (children)
+ {
+ child = children->data;
+ children = children->prev;
+
+ if (child->pack == GTK_PACK_END)
+ (* callback) (child->widget, callback_data);
+ }
+}
diff --git a/gtk/gtkbox.h b/gtk/gtkbox.h
new file mode 100644
index 000000000..5ff0dd22a
--- /dev/null
+++ b/gtk/gtkbox.h
@@ -0,0 +1,90 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_BOX_H__
+#define __GTK_BOX_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkcontainer.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_BOX(obj) GTK_CHECK_CAST (obj, gtk_box_get_type (), GtkBox)
+#define GTK_BOX_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_box_get_type (), GtkBoxClass)
+#define GTK_IS_BOX(obj) GTK_CHECK_TYPE (obj, gtk_box_get_type ())
+
+
+typedef struct _GtkBox GtkBox;
+typedef struct _GtkBoxClass GtkBoxClass;
+typedef struct _GtkBoxChild GtkBoxChild;
+
+struct _GtkBox
+{
+ GtkContainer container;
+
+ GList *children;
+ gint16 spacing;
+ guint homogeneous : 1;
+};
+
+struct _GtkBoxClass
+{
+ GtkContainerClass parent_class;
+};
+
+struct _GtkBoxChild
+{
+ GtkWidget *widget;
+ guint16 padding;
+ guint expand : 1;
+ guint fill : 1;
+ guint pack : 1;
+};
+
+
+guint gtk_box_get_type (void);
+void gtk_box_pack_start (GtkBox *box,
+ GtkWidget *child,
+ gint expand,
+ gint fill,
+ gint padding);
+void gtk_box_pack_end (GtkBox *box,
+ GtkWidget *child,
+ gint expand,
+ gint fill,
+ gint padding);
+void gtk_box_pack_start_defaults (GtkBox *box,
+ GtkWidget *widget);
+void gtk_box_pack_end_defaults (GtkBox *box,
+ GtkWidget *widget);
+void gtk_box_set_homogeneous (GtkBox *box,
+ gint homogeneous);
+void gtk_box_set_spacing (GtkBox *box,
+ gint spacing);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_BOX_H__ */
diff --git a/gtk/gtkbutton.c b/gtk/gtkbutton.c
new file mode 100644
index 000000000..18afb177a
--- /dev/null
+++ b/gtk/gtkbutton.c
@@ -0,0 +1,915 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtkbutton.h"
+#include "gtklabel.h"
+#include "gtkmain.h"
+#include "gtksignal.h"
+
+
+#define CHILD_SPACING 1
+#define DEFAULT_LEFT_POS 4
+#define DEFAULT_TOP_POS 4
+#define DEFAULT_SPACING 7
+
+
+enum {
+ PRESSED,
+ RELEASED,
+ CLICKED,
+ ENTER,
+ LEAVE,
+ LAST_SIGNAL
+};
+
+
+static void gtk_button_class_init (GtkButtonClass *klass);
+static void gtk_button_init (GtkButton *button);
+static void gtk_button_arg (GtkButton *button,
+ GtkArg *arg);
+static void gtk_button_destroy (GtkObject *object);
+static void gtk_button_map (GtkWidget *widget);
+static void gtk_button_unmap (GtkWidget *widget);
+static void gtk_button_realize (GtkWidget *widget);
+static void gtk_button_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void gtk_button_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static void gtk_button_paint (GtkWidget *widget,
+ GdkRectangle *area);
+static void gtk_button_draw (GtkWidget *widget,
+ GdkRectangle *area);
+static void gtk_button_draw_focus (GtkWidget *widget);
+static void gtk_button_draw_default (GtkWidget *widget);
+static gint gtk_button_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+static gint gtk_button_button_press (GtkWidget *widget,
+ GdkEventButton *event);
+static gint gtk_button_button_release (GtkWidget *widget,
+ GdkEventButton *event);
+static gint gtk_button_enter_notify (GtkWidget *widget,
+ GdkEventCrossing *event);
+static gint gtk_button_leave_notify (GtkWidget *widget,
+ GdkEventCrossing *event);
+static gint gtk_button_focus_in (GtkWidget *widget,
+ GdkEventFocus *event);
+static gint gtk_button_focus_out (GtkWidget *widget,
+ GdkEventFocus *event);
+static void gtk_button_add (GtkContainer *container,
+ GtkWidget *widget);
+static void gtk_button_remove (GtkContainer *container,
+ GtkWidget *widget);
+static void gtk_button_foreach (GtkContainer *container,
+ GtkCallback callback,
+ gpointer callback_data);
+static void gtk_real_button_pressed (GtkButton *button);
+static void gtk_real_button_released (GtkButton *button);
+static void gtk_real_button_enter (GtkButton *button);
+static void gtk_real_button_leave (GtkButton *button);
+
+
+static GtkContainerClass *parent_class;
+static gint button_signals[LAST_SIGNAL] = { 0 };
+
+
+guint
+gtk_button_get_type ()
+{
+ static guint button_type = 0;
+
+ if (!button_type)
+ {
+ GtkTypeInfo button_info =
+ {
+ "GtkButton",
+ sizeof (GtkButton),
+ sizeof (GtkButtonClass),
+ (GtkClassInitFunc) gtk_button_class_init,
+ (GtkObjectInitFunc) gtk_button_init,
+ (GtkArgFunc) gtk_button_arg,
+ };
+
+ button_type = gtk_type_unique (gtk_container_get_type (), &button_info);
+ }
+
+ return button_type;
+}
+
+static void
+gtk_button_class_init (GtkButtonClass *klass)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+ GtkContainerClass *container_class;
+
+ object_class = (GtkObjectClass*) klass;
+ widget_class = (GtkWidgetClass*) klass;
+ container_class = (GtkContainerClass*) klass;
+
+ parent_class = gtk_type_class (gtk_container_get_type ());
+
+ gtk_object_add_arg_type ("GtkButton::label", GTK_TYPE_STRING);
+
+ button_signals[PRESSED] =
+ gtk_signal_new ("pressed",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkButtonClass, pressed),
+ gtk_signal_default_marshaller,
+ GTK_TYPE_NONE, 0);
+ button_signals[RELEASED] =
+ gtk_signal_new ("released",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkButtonClass, released),
+ gtk_signal_default_marshaller,
+ GTK_TYPE_NONE, 0);
+ button_signals[CLICKED] =
+ gtk_signal_new ("clicked",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkButtonClass, clicked),
+ gtk_signal_default_marshaller,
+ GTK_TYPE_NONE, 0);
+ button_signals[ENTER] =
+ gtk_signal_new ("enter",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkButtonClass, enter),
+ gtk_signal_default_marshaller,
+ GTK_TYPE_NONE, 0);
+ button_signals[LEAVE] =
+ gtk_signal_new ("leave",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkButtonClass, leave),
+ gtk_signal_default_marshaller,
+ GTK_TYPE_NONE, 0);
+
+ gtk_object_class_add_signals (object_class, button_signals, LAST_SIGNAL);
+
+ object_class->destroy = gtk_button_destroy;
+
+ widget_class->activate_signal = button_signals[CLICKED];
+ widget_class->map = gtk_button_map;
+ widget_class->unmap = gtk_button_unmap;
+ widget_class->realize = gtk_button_realize;
+ widget_class->draw = gtk_button_draw;
+ widget_class->draw_focus = gtk_button_draw_focus;
+ widget_class->draw_default = gtk_button_draw_default;
+ widget_class->size_request = gtk_button_size_request;
+ widget_class->size_allocate = gtk_button_size_allocate;
+ widget_class->expose_event = gtk_button_expose;
+ widget_class->button_press_event = gtk_button_button_press;
+ widget_class->button_release_event = gtk_button_button_release;
+ widget_class->enter_notify_event = gtk_button_enter_notify;
+ widget_class->leave_notify_event = gtk_button_leave_notify;
+ widget_class->focus_in_event = gtk_button_focus_in;
+ widget_class->focus_out_event = gtk_button_focus_out;
+
+ container_class->add = gtk_button_add;
+ container_class->remove = gtk_button_remove;
+ container_class->foreach = gtk_button_foreach;
+
+ klass->pressed = gtk_real_button_pressed;
+ klass->released = gtk_real_button_released;
+ klass->clicked = NULL;
+ klass->enter = gtk_real_button_enter;
+ klass->leave = gtk_real_button_leave;
+}
+
+static void
+gtk_button_init (GtkButton *button)
+{
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_FOCUS);
+
+ button->child = NULL;
+ button->in_button = FALSE;
+ button->button_down = FALSE;
+}
+
+static void
+gtk_button_arg (GtkButton *button,
+ GtkArg *arg)
+{
+ if (strcmp (arg->name, "label") == 0)
+ {
+ GtkWidget *label;
+
+ gtk_container_disable_resize (GTK_CONTAINER (button));
+
+ if (button->child)
+ gtk_widget_destroy (button->child);
+
+ label = gtk_label_new (GTK_VALUE_STRING(*arg));
+ gtk_widget_show (label);
+
+ gtk_container_add (GTK_CONTAINER (button), label);
+ gtk_container_enable_resize (GTK_CONTAINER (button));
+ }
+}
+
+GtkWidget*
+gtk_button_new ()
+{
+ return GTK_WIDGET (gtk_type_new (gtk_button_get_type ()));
+}
+
+GtkWidget*
+gtk_button_new_with_label (const gchar *label)
+{
+ GtkWidget *button;
+ GtkWidget *label_widget;
+
+ button = gtk_button_new ();
+ label_widget = gtk_label_new (label);
+ gtk_misc_set_alignment (GTK_MISC (label_widget), 0.5, 0.5);
+
+ gtk_container_add (GTK_CONTAINER (button), label_widget);
+ gtk_widget_show (label_widget);
+
+ return button;
+}
+
+void
+gtk_button_pressed (GtkButton *button)
+{
+ gtk_signal_emit (GTK_OBJECT (button), button_signals[PRESSED]);
+}
+
+void
+gtk_button_released (GtkButton *button)
+{
+ gtk_signal_emit (GTK_OBJECT (button), button_signals[RELEASED]);
+}
+
+void
+gtk_button_clicked (GtkButton *button)
+{
+ gtk_signal_emit (GTK_OBJECT (button), button_signals[CLICKED]);
+}
+
+void
+gtk_button_enter (GtkButton *button)
+{
+ gtk_signal_emit (GTK_OBJECT (button), button_signals[ENTER]);
+}
+
+void
+gtk_button_leave (GtkButton *button)
+{
+ gtk_signal_emit (GTK_OBJECT (button), button_signals[LEAVE]);
+}
+
+static void
+gtk_button_destroy (GtkObject *object)
+{
+ GtkButton *button;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_BUTTON (object));
+
+ button = GTK_BUTTON (object);
+
+ if (button->child)
+ {
+ button->child->parent = NULL;
+ gtk_object_unref (GTK_OBJECT (button->child));
+ gtk_widget_destroy (button->child);
+ }
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+static void
+gtk_button_map (GtkWidget *widget)
+{
+ GtkButton *button;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_BUTTON (widget));
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
+ gdk_window_show (widget->window);
+
+ button = GTK_BUTTON (widget);
+
+ if (button->child &&
+ GTK_WIDGET_VISIBLE (button->child) &&
+ !GTK_WIDGET_MAPPED (button->child))
+ gtk_widget_map (button->child);
+}
+
+static void
+gtk_button_unmap (GtkWidget *widget)
+{
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_BUTTON (widget));
+
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
+ gdk_window_hide (widget->window);
+}
+
+static void
+gtk_button_realize (GtkWidget *widget)
+{
+ GtkButton *button;
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_BUTTON (widget));
+
+ button = GTK_BUTTON (widget);
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.x = widget->allocation.x;
+ attributes.y = widget->allocation.y;
+ attributes.width = widget->allocation.width;
+ attributes.height = widget->allocation.height;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
+ attributes.event_mask = gtk_widget_get_events (widget);
+ attributes.event_mask |= (GDK_EXPOSURE_MASK |
+ GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_ENTER_NOTIFY_MASK |
+ GDK_LEAVE_NOTIFY_MASK);
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+
+ widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
+ gdk_window_set_user_data (widget->window, button);
+
+ widget->style = gtk_style_attach (widget->style, widget->window);
+ gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
+}
+
+static void
+gtk_button_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkButton *button;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_BUTTON (widget));
+ g_return_if_fail (requisition != NULL);
+
+ button = GTK_BUTTON (widget);
+
+ requisition->width = (GTK_CONTAINER (widget)->border_width + CHILD_SPACING +
+ GTK_WIDGET (widget)->style->klass->xthickness) * 2;
+ requisition->height = (GTK_CONTAINER (widget)->border_width + CHILD_SPACING +
+ GTK_WIDGET (widget)->style->klass->ythickness) * 2;
+
+ if (GTK_WIDGET_CAN_DEFAULT (widget))
+ {
+ requisition->width += (GTK_WIDGET (widget)->style->klass->xthickness * 2 +
+ DEFAULT_SPACING);
+ requisition->height += (GTK_WIDGET (widget)->style->klass->ythickness * 2 +
+ DEFAULT_SPACING);
+ }
+
+ if (button->child && GTK_WIDGET_VISIBLE (button->child))
+ {
+ gtk_widget_size_request (button->child, &button->child->requisition);
+
+ requisition->width += button->child->requisition.width;
+ requisition->height += button->child->requisition.height;
+ }
+}
+
+static void
+gtk_button_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkButton *button;
+ GtkAllocation child_allocation;
+ gint border_width;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_BUTTON (widget));
+ g_return_if_fail (allocation != NULL);
+
+ widget->allocation = *allocation;
+ border_width = GTK_CONTAINER (widget)->border_width;
+
+ if (GTK_WIDGET_REALIZED (widget))
+ gdk_window_move_resize (widget->window,
+ widget->allocation.x + border_width,
+ widget->allocation.y + border_width,
+ widget->allocation.width - border_width * 2,
+ widget->allocation.height - border_width * 2);
+
+ button = GTK_BUTTON (widget);
+
+ if (button->child && GTK_WIDGET_VISIBLE (button->child))
+ {
+ child_allocation.x = (CHILD_SPACING + GTK_WIDGET (widget)->style->klass->xthickness);
+ child_allocation.y = (CHILD_SPACING + GTK_WIDGET (widget)->style->klass->ythickness);
+
+ child_allocation.width = widget->allocation.width - child_allocation.x * 2 -
+ border_width * 2;
+ child_allocation.height = widget->allocation.height - child_allocation.y * 2 -
+ border_width * 2;
+
+ if (GTK_WIDGET_CAN_DEFAULT (button))
+ {
+ child_allocation.x += (GTK_WIDGET (widget)->style->klass->xthickness +
+ DEFAULT_LEFT_POS);
+ child_allocation.y += (GTK_WIDGET (widget)->style->klass->ythickness +
+ DEFAULT_TOP_POS);
+ child_allocation.width -= (GTK_WIDGET (widget)->style->klass->xthickness * 2 +
+ DEFAULT_SPACING);
+ child_allocation.height -= (GTK_WIDGET (widget)->style->klass->xthickness * 2 +
+ DEFAULT_SPACING);
+ }
+
+ gtk_widget_size_allocate (button->child, &child_allocation);
+ }
+}
+
+static void
+gtk_button_paint (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ GdkRectangle restrict_area;
+ GdkRectangle new_area;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_BUTTON (widget));
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ restrict_area.x = GTK_WIDGET (widget)->style->klass->xthickness;
+ restrict_area.y = GTK_WIDGET (widget)->style->klass->ythickness;
+ restrict_area.width = (GTK_WIDGET (widget)->allocation.width - restrict_area.x * 2 -
+ GTK_CONTAINER (widget)->border_width * 2);
+ restrict_area.height = (GTK_WIDGET (widget)->allocation.height - restrict_area.y * 2 -
+ GTK_CONTAINER (widget)->border_width * 2);
+
+ if (GTK_WIDGET_CAN_DEFAULT (widget))
+ {
+ restrict_area.x += DEFAULT_LEFT_POS;
+ restrict_area.y += DEFAULT_TOP_POS;
+ restrict_area.width -= DEFAULT_SPACING;
+ restrict_area.height -= DEFAULT_SPACING;
+ }
+
+ if (gdk_rectangle_intersect (area, &restrict_area, &new_area))
+ {
+ gtk_style_set_background (widget->style, widget->window, GTK_WIDGET_STATE (widget));
+ gdk_window_clear_area (widget->window,
+ new_area.x, new_area.y,
+ new_area.width, new_area.height);
+ }
+ }
+}
+
+static void
+gtk_button_draw (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ GtkButton *button;
+ GdkRectangle child_area;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_BUTTON (widget));
+ g_return_if_fail (area != NULL);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ button = GTK_BUTTON (widget);
+
+ gtk_button_paint (widget, area);
+
+ if (button->child && gtk_widget_intersect (button->child, area, &child_area))
+ gtk_widget_draw (button->child, &child_area);
+
+ gtk_widget_draw_default (widget);
+ gtk_widget_draw_focus (widget);
+ }
+}
+
+static void
+gtk_button_draw_focus (GtkWidget *widget)
+{
+ GtkButton *button;
+ GtkShadowType shadow_type;
+ gint width, height;
+ gint x, y;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_BUTTON (widget));
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ button = GTK_BUTTON (widget);
+
+ x = 0;
+ y = 0;
+ width = widget->allocation.width - GTK_CONTAINER (widget)->border_width * 2;
+ height = widget->allocation.height - GTK_CONTAINER (widget)->border_width * 2;
+
+ if (GTK_WIDGET_CAN_DEFAULT (widget))
+ {
+ x += widget->style->klass->xthickness;
+ y += widget->style->klass->ythickness;
+ width -= 2 * x + DEFAULT_SPACING;
+ height -= 2 * y + DEFAULT_SPACING;
+ x += DEFAULT_LEFT_POS;
+ y += DEFAULT_TOP_POS;
+ }
+
+ if (GTK_WIDGET_HAS_FOCUS (widget))
+ {
+ x += 1;
+ y += 1;
+ width -= 2;
+ height -= 2;
+ }
+ else
+ {
+ if (GTK_WIDGET_STATE (widget) == GTK_STATE_ACTIVE)
+ gdk_draw_rectangle (widget->window,
+ widget->style->bg_gc[GTK_WIDGET_STATE (widget)], FALSE,
+ x + 1, y + 1, width - 4, height - 4);
+ else
+ gdk_draw_rectangle (widget->window,
+ widget->style->bg_gc[GTK_WIDGET_STATE (widget)], FALSE,
+ x + 2, y + 2, width - 5, height - 5);
+ }
+
+ if (GTK_WIDGET_STATE (widget) == GTK_STATE_ACTIVE)
+ shadow_type = GTK_SHADOW_IN;
+ else
+ shadow_type = GTK_SHADOW_OUT;
+
+ gtk_draw_shadow (widget->style, widget->window,
+ GTK_WIDGET_STATE (widget), shadow_type,
+ x, y, width, height);
+
+ if (GTK_WIDGET_HAS_FOCUS (widget))
+ {
+ x -= 1;
+ y -= 1;
+ width += 2;
+ height += 2;
+
+ gdk_draw_rectangle (widget->window,
+ widget->style->black_gc, FALSE,
+ x, y, width - 1, height - 1);
+ }
+ }
+}
+
+static void
+gtk_button_draw_default (GtkWidget *widget)
+{
+ gint width, height;
+ gint x, y;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_BUTTON (widget));
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ x = 0;
+ y = 0;
+ width = widget->allocation.width - GTK_CONTAINER (widget)->border_width * 2;
+ height = widget->allocation.height - GTK_CONTAINER (widget)->border_width * 2;
+
+ if (GTK_WIDGET_HAS_DEFAULT (widget))
+ {
+ gtk_draw_shadow (widget->style, widget->window,
+ GTK_STATE_NORMAL, GTK_SHADOW_IN,
+ x, y, width, height);
+ }
+ else
+ {
+ gdk_draw_rectangle (widget->window, widget->style->bg_gc[GTK_STATE_NORMAL],
+ FALSE, x, y, width - 1, height - 1);
+ gdk_draw_rectangle (widget->window, widget->style->bg_gc[GTK_STATE_NORMAL],
+ FALSE, x + 1, y + 1, width - 3, height - 3);
+ }
+ }
+}
+
+static gint
+gtk_button_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ GtkButton *button;
+ GdkEventExpose child_event;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_BUTTON (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ button = GTK_BUTTON (widget);
+
+ gtk_button_paint (widget, &event->area);
+
+ child_event = *event;
+ if (button->child && GTK_WIDGET_NO_WINDOW (button->child) &&
+ gtk_widget_intersect (button->child, &event->area, &child_event.area))
+ gtk_widget_event (button->child, (GdkEvent*) &child_event);
+
+ gtk_widget_draw_default (widget);
+ gtk_widget_draw_focus (widget);
+ }
+
+ return FALSE;
+}
+
+static gint
+gtk_button_button_press (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ GtkButton *button;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_BUTTON (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (event->type == GDK_BUTTON_PRESS)
+ {
+ button = GTK_BUTTON (widget);
+
+ if (GTK_WIDGET_CAN_DEFAULT (widget) && (event->button == 1))
+ gtk_widget_grab_default (widget);
+ if (!GTK_WIDGET_HAS_FOCUS (widget))
+ gtk_widget_grab_focus (widget);
+
+ if (event->button == 1)
+ {
+ gtk_grab_add (GTK_WIDGET (button));
+ gtk_button_pressed (button);
+ }
+ }
+
+ return TRUE;
+}
+
+static gint
+gtk_button_button_release (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ GtkButton *button;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_BUTTON (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (event->button == 1)
+ {
+ button = GTK_BUTTON (widget);
+ gtk_grab_remove (GTK_WIDGET (button));
+ gtk_button_released (button);
+ }
+
+ return TRUE;
+}
+
+static gint
+gtk_button_enter_notify (GtkWidget *widget,
+ GdkEventCrossing *event)
+{
+ GtkButton *button;
+ GtkWidget *event_widget;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_BUTTON (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ button = GTK_BUTTON (widget);
+ event_widget = gtk_get_event_widget ((GdkEvent*) event);
+
+ if ((event_widget == widget) &&
+ (event->detail != GDK_NOTIFY_INFERIOR))
+ {
+ button->in_button = TRUE;
+ gtk_button_enter (button);
+ }
+
+ return FALSE;
+}
+
+static gint
+gtk_button_leave_notify (GtkWidget *widget,
+ GdkEventCrossing *event)
+{
+ GtkButton *button;
+ GtkWidget *event_widget;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_BUTTON (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ button = GTK_BUTTON (widget);
+ event_widget = gtk_get_event_widget ((GdkEvent*) event);
+
+ if ((event_widget == widget) &&
+ (event->detail != GDK_NOTIFY_INFERIOR))
+ {
+ button->in_button = FALSE;
+ gtk_button_leave (button);
+ }
+
+ return FALSE;
+}
+
+static gint
+gtk_button_focus_in (GtkWidget *widget,
+ GdkEventFocus *event)
+{
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_BUTTON (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
+ gtk_widget_draw_focus (widget);
+
+ return FALSE;
+}
+
+static gint
+gtk_button_focus_out (GtkWidget *widget,
+ GdkEventFocus *event)
+{
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_BUTTON (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
+ gtk_widget_draw_focus (widget);
+
+ return FALSE;
+}
+
+static void
+gtk_button_add (GtkContainer *container,
+ GtkWidget *widget)
+{
+ GtkButton *button;
+
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_BUTTON (container));
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (gtk_widget_basic (widget));
+
+ button = GTK_BUTTON (container);
+
+ if (!button->child)
+ {
+ gtk_widget_set_parent (widget, GTK_WIDGET (container));
+
+ if (GTK_WIDGET_VISIBLE (widget->parent))
+ {
+ if (GTK_WIDGET_REALIZED (widget->parent) &&
+ !GTK_WIDGET_REALIZED (widget))
+ gtk_widget_realize (widget);
+
+ if (GTK_WIDGET_MAPPED (widget->parent) &&
+ !GTK_WIDGET_MAPPED (widget))
+ gtk_widget_map (widget);
+ }
+
+ button->child = widget;
+
+ if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (container))
+ gtk_widget_queue_resize (widget);
+ }
+}
+
+static void
+gtk_button_remove (GtkContainer *container,
+ GtkWidget *widget)
+{
+ GtkButton *button;
+
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_BUTTON (container));
+
+ button = GTK_BUTTON (container);
+
+ if (button->child == widget)
+ {
+ gtk_widget_unparent (widget);
+
+ button->child = NULL;
+
+ if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (container))
+ gtk_widget_queue_resize (GTK_WIDGET (container));
+ }
+}
+
+static void
+gtk_button_foreach (GtkContainer *container,
+ GtkCallback callback,
+ gpointer callback_data)
+{
+ GtkButton *button;
+
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_BUTTON (container));
+ g_return_if_fail (callback != NULL);
+
+ button = GTK_BUTTON (container);
+
+ if (button->child)
+ (* callback) (button->child, callback_data);
+}
+
+static void
+gtk_real_button_pressed (GtkButton *button)
+{
+ GtkStateType new_state;
+
+ g_return_if_fail (button != NULL);
+ g_return_if_fail (GTK_IS_BUTTON (button));
+
+ button->button_down = TRUE;
+
+ new_state = (button->in_button ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL);
+
+ if (GTK_WIDGET_STATE (button) != new_state)
+ {
+ gtk_widget_set_state (GTK_WIDGET (button), new_state);
+ gtk_widget_queue_draw (GTK_WIDGET (button));
+ }
+}
+
+static void
+gtk_real_button_released (GtkButton *button)
+{
+ GtkStateType new_state;
+
+ g_return_if_fail (button != NULL);
+ g_return_if_fail (GTK_IS_BUTTON (button));
+
+ if (button->button_down)
+ {
+ button->button_down = FALSE;
+
+ if (button->in_button)
+ gtk_button_clicked (button);
+
+ new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL);
+
+ if (GTK_WIDGET_STATE (button) != new_state)
+ {
+ gtk_widget_set_state (GTK_WIDGET (button), new_state);
+ gtk_widget_queue_draw (GTK_WIDGET (button));
+ }
+ }
+}
+
+static void
+gtk_real_button_enter (GtkButton *button)
+{
+ GtkStateType new_state;
+
+ g_return_if_fail (button != NULL);
+ g_return_if_fail (GTK_IS_BUTTON (button));
+
+ new_state = (button->button_down ? GTK_STATE_ACTIVE : GTK_STATE_PRELIGHT);
+
+ if (GTK_WIDGET_STATE (button) != new_state)
+ {
+ gtk_widget_set_state (GTK_WIDGET (button), new_state);
+ gtk_widget_queue_draw (GTK_WIDGET (button));
+ }
+}
+
+static void
+gtk_real_button_leave (GtkButton *button)
+{
+ g_return_if_fail (button != NULL);
+ g_return_if_fail (GTK_IS_BUTTON (button));
+
+ if (GTK_WIDGET_STATE (button) != GTK_STATE_NORMAL)
+ {
+ gtk_widget_set_state (GTK_WIDGET (button), GTK_STATE_NORMAL);
+ gtk_widget_queue_draw (GTK_WIDGET (button));
+ }
+}
diff --git a/gtk/gtkbutton.h b/gtk/gtkbutton.h
new file mode 100644
index 000000000..ec72c99f7
--- /dev/null
+++ b/gtk/gtkbutton.h
@@ -0,0 +1,76 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_BUTTON_H__
+#define __GTK_BUTTON_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkcontainer.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_BUTTON(obj) GTK_CHECK_CAST (obj, gtk_button_get_type (), GtkButton)
+#define GTK_BUTTON_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_button_get_type (), GtkButtonClass)
+#define GTK_IS_BUTTON(obj) GTK_CHECK_TYPE (obj, gtk_button_get_type ())
+
+
+typedef struct _GtkButton GtkButton;
+typedef struct _GtkButtonClass GtkButtonClass;
+
+struct _GtkButton
+{
+ GtkContainer container;
+
+ GtkWidget *child;
+
+ guint in_button : 1;
+ guint button_down : 1;
+};
+
+struct _GtkButtonClass
+{
+ GtkContainerClass parent_class;
+
+ void (* pressed) (GtkButton *button);
+ void (* released) (GtkButton *button);
+ void (* clicked) (GtkButton *button);
+ void (* enter) (GtkButton *button);
+ void (* leave) (GtkButton *button);
+};
+
+
+guint gtk_button_get_type (void);
+GtkWidget* gtk_button_new (void);
+GtkWidget* gtk_button_new_with_label (const gchar *label);
+void gtk_button_pressed (GtkButton *button);
+void gtk_button_released (GtkButton *button);
+void gtk_button_clicked (GtkButton *button);
+void gtk_button_enter (GtkButton *button);
+void gtk_button_leave (GtkButton *button);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_BUTTON_H__ */
diff --git a/gtk/gtkcheckbutton.c b/gtk/gtkcheckbutton.c
new file mode 100644
index 000000000..d7f72ce1c
--- /dev/null
+++ b/gtk/gtkcheckbutton.c
@@ -0,0 +1,362 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtkcheckbutton.h"
+#include "gtklabel.h"
+
+
+#define INDICATOR_SIZE 10
+#define INDICATOR_SPACING 2
+
+#define CHECK_BUTTON_CLASS(w) GTK_CHECK_BUTTON_CLASS (GTK_OBJECT (w)->klass)
+
+
+static void gtk_check_button_class_init (GtkCheckButtonClass *klass);
+static void gtk_check_button_init (GtkCheckButton *check_button);
+static void gtk_check_button_draw (GtkWidget *widget,
+ GdkRectangle *area);
+static void gtk_check_button_draw_focus (GtkWidget *widget);
+static void gtk_check_button_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void gtk_check_button_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static gint gtk_check_button_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+static void gtk_check_button_draw_indicator (GtkCheckButton *check_button,
+ GdkRectangle *area);
+static void gtk_real_check_button_draw_indicator (GtkCheckButton *check_button,
+ GdkRectangle *area);
+
+
+static GtkToggleButtonClass *parent_class = NULL;
+
+
+guint
+gtk_check_button_get_type ()
+{
+ static guint check_button_type = 0;
+
+ if (!check_button_type)
+ {
+ GtkTypeInfo check_button_info =
+ {
+ "GtkCheckButton",
+ sizeof (GtkCheckButton),
+ sizeof (GtkCheckButtonClass),
+ (GtkClassInitFunc) gtk_check_button_class_init,
+ (GtkObjectInitFunc) gtk_check_button_init,
+ (GtkArgFunc) NULL,
+ };
+
+ check_button_type = gtk_type_unique (gtk_toggle_button_get_type (), &check_button_info);
+ }
+
+ return check_button_type;
+}
+
+static void
+gtk_check_button_class_init (GtkCheckButtonClass *class)
+{
+ GtkWidgetClass *widget_class;
+
+ widget_class = (GtkWidgetClass*) class;
+ parent_class = gtk_type_class (gtk_toggle_button_get_type ());
+
+ widget_class->draw = gtk_check_button_draw;
+ widget_class->draw_focus = gtk_check_button_draw_focus;
+ widget_class->size_request = gtk_check_button_size_request;
+ widget_class->size_allocate = gtk_check_button_size_allocate;
+ widget_class->expose_event = gtk_check_button_expose;
+
+ class->indicator_size = INDICATOR_SIZE;
+ class->indicator_spacing = INDICATOR_SPACING;
+ class->draw_indicator = gtk_real_check_button_draw_indicator;
+}
+
+static void
+gtk_check_button_init (GtkCheckButton *check_button)
+{
+ check_button->toggle_button.draw_indicator = TRUE;
+}
+
+GtkWidget*
+gtk_check_button_new ()
+{
+ return GTK_WIDGET (gtk_type_new (gtk_check_button_get_type ()));
+}
+
+
+GtkWidget*
+gtk_check_button_new_with_label (const gchar *label)
+{
+ GtkWidget *check_button;
+ GtkWidget *label_widget;
+
+ check_button = gtk_check_button_new ();
+ label_widget = gtk_label_new (label);
+ gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
+
+ gtk_container_add (GTK_CONTAINER (check_button), label_widget);
+ gtk_widget_show (label_widget);
+
+ return check_button;
+}
+
+static void
+gtk_check_button_draw (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ GtkButton *button;
+ GtkCheckButton *check_button;
+ GdkRectangle child_area;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_CHECK_BUTTON (widget));
+ g_return_if_fail (area != NULL);
+
+ if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget))
+ {
+ check_button = GTK_CHECK_BUTTON (widget);
+
+ if (check_button->toggle_button.draw_indicator)
+ {
+ button = GTK_BUTTON (widget);
+
+ gtk_check_button_draw_indicator (check_button, area);
+
+ if (button->child && GTK_WIDGET_NO_WINDOW (button->child) &&
+ gtk_widget_intersect (button->child, area, &child_area))
+ gtk_widget_draw (button->child, &child_area);
+
+ gtk_widget_draw_focus (widget);
+ }
+ else
+ {
+ if (GTK_WIDGET_CLASS (parent_class)->draw)
+ (* GTK_WIDGET_CLASS (parent_class)->draw) (widget, area);
+ }
+ }
+}
+
+static void
+gtk_check_button_draw_focus (GtkWidget *widget)
+{
+ GtkCheckButton *check_button;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_CHECK_BUTTON (widget));
+
+ if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget))
+ {
+ check_button = GTK_CHECK_BUTTON (widget);
+ if (check_button->toggle_button.draw_indicator)
+ {
+ if (GTK_WIDGET_HAS_FOCUS (widget))
+ gdk_draw_rectangle (widget->window,
+ widget->style->black_gc, FALSE, 0, 0,
+ widget->allocation.width - 1,
+ widget->allocation.height - 1);
+ else
+ gdk_draw_rectangle (widget->window,
+ widget->style->bg_gc[GTK_STATE_NORMAL], FALSE, 0, 0,
+ widget->allocation.width - 1,
+ widget->allocation.height - 1);
+ }
+ else
+ {
+ if (GTK_WIDGET_CLASS (parent_class)->draw_focus)
+ (* GTK_WIDGET_CLASS (parent_class)->draw_focus) (widget);
+ }
+ }
+}
+
+static void
+gtk_check_button_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkCheckButton *check_button;
+ GtkButton *button;
+ gint temp;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_CHECK_BUTTON (widget));
+ g_return_if_fail (requisition != NULL);
+
+ check_button = GTK_CHECK_BUTTON (widget);
+
+ if (GTK_WIDGET_CLASS (parent_class)->size_request)
+ (* GTK_WIDGET_CLASS (parent_class)->size_request) (widget, requisition);
+
+ if (check_button->toggle_button.draw_indicator)
+ {
+ button = GTK_BUTTON (widget);
+
+ requisition->width += (CHECK_BUTTON_CLASS (widget)->indicator_size +
+ CHECK_BUTTON_CLASS (widget)->indicator_spacing * 3 + 2);
+
+ temp = (CHECK_BUTTON_CLASS (widget)->indicator_size +
+ CHECK_BUTTON_CLASS (widget)->indicator_spacing * 2);
+ requisition->height = MAX (requisition->height, temp) + 2;
+ }
+}
+
+static void
+gtk_check_button_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkCheckButton *check_button;
+ GtkButton *button;
+ GtkAllocation child_allocation;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_CHECK_BUTTON (widget));
+ g_return_if_fail (allocation != NULL);
+
+ check_button = GTK_CHECK_BUTTON (widget);
+ if (check_button->toggle_button.draw_indicator)
+ {
+ widget->allocation = *allocation;
+ if (GTK_WIDGET_REALIZED (widget))
+ gdk_window_move_resize (widget->window,
+ allocation->x, allocation->y,
+ allocation->width, allocation->height);
+
+ button = GTK_BUTTON (widget);
+
+ if (button->child && GTK_WIDGET_VISIBLE (button->child))
+ {
+ child_allocation.x = (GTK_CONTAINER (widget)->border_width +
+ CHECK_BUTTON_CLASS (widget)->indicator_size +
+ CHECK_BUTTON_CLASS (widget)->indicator_spacing * 3 + 1);
+ child_allocation.y = GTK_CONTAINER (widget)->border_width + 1;
+ child_allocation.width = (allocation->width - child_allocation.x -
+ GTK_CONTAINER (widget)->border_width - 1);
+ child_allocation.height = allocation->height - child_allocation.y * 2;
+
+ gtk_widget_size_allocate (button->child, &child_allocation);
+ }
+ }
+ else
+ {
+ if (GTK_WIDGET_CLASS (parent_class)->size_allocate)
+ (* GTK_WIDGET_CLASS (parent_class)->size_allocate) (widget, allocation);
+ }
+}
+
+static gint
+gtk_check_button_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ GtkButton *button;
+ GtkCheckButton *check_button;
+ GdkEventExpose child_event;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_CHECK_BUTTON (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget))
+ {
+ check_button = GTK_CHECK_BUTTON (widget);
+
+ if (check_button->toggle_button.draw_indicator)
+ {
+ button = GTK_BUTTON (widget);
+
+ gtk_check_button_draw_indicator (check_button, &event->area);
+
+ child_event = *event;
+ if (button->child && GTK_WIDGET_NO_WINDOW (button->child) &&
+ gtk_widget_intersect (button->child, &event->area, &child_event.area))
+ gtk_widget_event (button->child, (GdkEvent*) &child_event);
+
+ gtk_widget_draw_focus (widget);
+ }
+ else
+ {
+ if (GTK_WIDGET_CLASS (parent_class)->expose_event)
+ (* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event);
+ }
+ }
+
+ return FALSE;
+}
+
+
+static void
+gtk_check_button_draw_indicator (GtkCheckButton *check_button,
+ GdkRectangle *area)
+{
+ GtkCheckButtonClass *class;
+
+ g_return_if_fail (check_button != NULL);
+ g_return_if_fail (GTK_IS_CHECK_BUTTON (check_button));
+ g_return_if_fail (CHECK_BUTTON_CLASS (check_button) != NULL);
+
+ class = CHECK_BUTTON_CLASS (check_button);
+
+ if (class->draw_indicator)
+ (* class->draw_indicator) (check_button, area);
+}
+
+static void
+gtk_real_check_button_draw_indicator (GtkCheckButton *check_button,
+ GdkRectangle *area)
+{
+ GtkWidget *widget;
+ GtkToggleButton *toggle_button;
+ GtkStateType state_type;
+ GtkShadowType shadow_type;
+ gint width, height;
+ gint x, y;
+
+ g_return_if_fail (check_button != NULL);
+ g_return_if_fail (GTK_IS_CHECK_BUTTON (check_button));
+
+ if (GTK_WIDGET_DRAWABLE (check_button))
+ {
+ widget = GTK_WIDGET (check_button);
+ toggle_button = GTK_TOGGLE_BUTTON (check_button);
+
+ state_type = GTK_WIDGET_STATE (widget);
+ if ((state_type != GTK_STATE_NORMAL) &&
+ (state_type != GTK_STATE_PRELIGHT))
+ state_type = GTK_STATE_NORMAL;
+
+ gtk_style_set_background (widget->style, widget->window, state_type);
+ gdk_window_clear_area (widget->window, area->x, area->y, area->width, area->height);
+
+ x = CHECK_BUTTON_CLASS (widget)->indicator_spacing + GTK_CONTAINER (widget)->border_width;
+ y = (widget->allocation.height - CHECK_BUTTON_CLASS (widget)->indicator_size) / 2;
+ width = CHECK_BUTTON_CLASS (widget)->indicator_size;
+ height = CHECK_BUTTON_CLASS (widget)->indicator_size;
+
+ if (GTK_WIDGET_STATE (widget) == GTK_STATE_ACTIVE)
+ shadow_type = GTK_SHADOW_IN;
+ else if ((GTK_WIDGET_STATE (widget) == GTK_STATE_PRELIGHT) && toggle_button->active)
+ shadow_type = GTK_SHADOW_IN;
+ else
+ shadow_type = GTK_SHADOW_OUT;
+
+ gdk_draw_rectangle (widget->window,
+ widget->style->bg_gc[GTK_WIDGET_STATE (widget)],
+ TRUE, x + 1, y + 1, width, height);
+ gtk_draw_shadow (widget->style, widget->window,
+ GTK_WIDGET_STATE (widget), shadow_type,
+ x + 1, y + 1, width, height);
+ }
+}
diff --git a/gtk/gtkcheckbutton.h b/gtk/gtkcheckbutton.h
new file mode 100644
index 000000000..8994db563
--- /dev/null
+++ b/gtk/gtkcheckbutton.h
@@ -0,0 +1,66 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_CHECK_BUTTON_H__
+#define __GTK_CHECK_BUTTON_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtktogglebutton.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_CHECK_BUTTON(obj) GTK_CHECK_CAST (obj, gtk_check_button_get_type (), GtkCheckButton)
+#define GTK_CHECK_BUTTON_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_check_button_get_type (), GtkCheckButtonClass)
+#define GTK_IS_CHECK_BUTTON(obj) GTK_CHECK_TYPE (obj, gtk_check_button_get_type ())
+
+
+typedef struct _GtkCheckButton GtkCheckButton;
+typedef struct _GtkCheckButtonClass GtkCheckButtonClass;
+
+struct _GtkCheckButton
+{
+ GtkToggleButton toggle_button;
+};
+
+struct _GtkCheckButtonClass
+{
+ GtkToggleButtonClass parent_class;
+
+ guint16 indicator_size;
+ guint16 indicator_spacing;
+
+ void (* draw_indicator) (GtkCheckButton *check_button,
+ GdkRectangle *area);
+};
+
+
+guint gtk_check_button_get_type (void);
+GtkWidget* gtk_check_button_new (void);
+GtkWidget* gtk_check_button_new_with_label (const gchar *label);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_CHECK_BUTTON_H__ */
diff --git a/gtk/gtkcheckmenuitem.c b/gtk/gtkcheckmenuitem.c
new file mode 100644
index 000000000..a36dfa75a
--- /dev/null
+++ b/gtk/gtkcheckmenuitem.c
@@ -0,0 +1,250 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtkcheckmenuitem.h"
+#include "gtklabel.h"
+#include "gtksignal.h"
+
+
+#define CHECK_MENU_ITEM_CLASS(w) GTK_CHECK_MENU_ITEM_CLASS (GTK_OBJECT (w)->klass)
+
+
+enum {
+ TOGGLED,
+ LAST_SIGNAL
+};
+
+
+static void gtk_check_menu_item_class_init (GtkCheckMenuItemClass *klass);
+static void gtk_check_menu_item_init (GtkCheckMenuItem *check_menu_item);
+static void gtk_check_menu_item_draw (GtkWidget *widget,
+ GdkRectangle *area);
+static gint gtk_check_menu_item_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+static void gtk_check_menu_item_activate (GtkMenuItem *menu_item);
+static void gtk_check_menu_item_draw_indicator (GtkCheckMenuItem *check_menu_item,
+ GdkRectangle *area);
+static void gtk_real_check_menu_item_draw_indicator (GtkCheckMenuItem *check_menu_item,
+ GdkRectangle *area);
+
+
+static GtkMenuItemClass *parent_class = NULL;
+static gint check_menu_item_signals[LAST_SIGNAL] = { 0 };
+
+
+guint
+gtk_check_menu_item_get_type ()
+{
+ static guint check_menu_item_type = 0;
+
+ if (!check_menu_item_type)
+ {
+ GtkTypeInfo check_menu_item_info =
+ {
+ "GtkCheckMenuItem",
+ sizeof (GtkCheckMenuItem),
+ sizeof (GtkCheckMenuItemClass),
+ (GtkClassInitFunc) gtk_check_menu_item_class_init,
+ (GtkObjectInitFunc) gtk_check_menu_item_init,
+ (GtkArgFunc) NULL,
+ };
+
+ check_menu_item_type = gtk_type_unique (gtk_menu_item_get_type (), &check_menu_item_info);
+ }
+
+ return check_menu_item_type;
+}
+
+GtkWidget*
+gtk_check_menu_item_new ()
+{
+ return GTK_WIDGET (gtk_type_new (gtk_check_menu_item_get_type ()));
+}
+
+GtkWidget*
+gtk_check_menu_item_new_with_label (const gchar *label)
+{
+ GtkWidget *check_menu_item;
+ GtkWidget *label_widget;
+
+ check_menu_item = gtk_check_menu_item_new ();
+ label_widget = gtk_label_new (label);
+ gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
+
+ gtk_container_add (GTK_CONTAINER (check_menu_item), label_widget);
+ gtk_widget_show (label_widget);
+
+ return check_menu_item;
+}
+
+void
+gtk_check_menu_item_set_state (GtkCheckMenuItem *check_menu_item,
+ gint state)
+{
+ g_return_if_fail (check_menu_item != NULL);
+ g_return_if_fail (GTK_IS_CHECK_MENU_ITEM (check_menu_item));
+
+ if (check_menu_item->active != state)
+ gtk_menu_item_activate (GTK_MENU_ITEM (check_menu_item));
+}
+
+void
+gtk_check_menu_item_toggled (GtkCheckMenuItem *check_menu_item)
+{
+ gtk_signal_emit (GTK_OBJECT (check_menu_item), check_menu_item_signals[TOGGLED]);
+}
+
+
+static void
+gtk_check_menu_item_class_init (GtkCheckMenuItemClass *klass)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+ GtkMenuItemClass *menu_item_class;
+
+ object_class = (GtkObjectClass*) klass;
+ widget_class = (GtkWidgetClass*) klass;
+ menu_item_class = (GtkMenuItemClass*) klass;
+
+ parent_class = gtk_type_class (gtk_menu_item_get_type ());
+
+ check_menu_item_signals[TOGGLED] =
+ gtk_signal_new ("toggled",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkCheckMenuItemClass, toggled),
+ gtk_signal_default_marshaller,
+ GTK_TYPE_NONE, 0);
+
+ gtk_object_class_add_signals (object_class, check_menu_item_signals, LAST_SIGNAL);
+
+ widget_class->draw = gtk_check_menu_item_draw;
+ widget_class->expose_event = gtk_check_menu_item_expose;
+
+ menu_item_class->activate = gtk_check_menu_item_activate;
+ menu_item_class->toggle_size = 12;
+
+ klass->toggled = NULL;
+ klass->draw_indicator = gtk_real_check_menu_item_draw_indicator;
+}
+
+static void
+gtk_check_menu_item_init (GtkCheckMenuItem *check_menu_item)
+{
+ check_menu_item->active = FALSE;
+}
+
+static void
+gtk_check_menu_item_draw (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_CHECK_MENU_ITEM (widget));
+ g_return_if_fail (area != NULL);
+
+ if (GTK_WIDGET_CLASS (parent_class)->draw)
+ (* GTK_WIDGET_CLASS (parent_class)->draw) (widget, area);
+
+ gtk_check_menu_item_draw_indicator (GTK_CHECK_MENU_ITEM (widget), area);
+}
+
+static gint
+gtk_check_menu_item_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_CHECK_MENU_ITEM (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (GTK_WIDGET_CLASS (parent_class)->expose_event)
+ (* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event);
+
+ gtk_check_menu_item_draw_indicator (GTK_CHECK_MENU_ITEM (widget), &event->area);
+
+ return FALSE;
+}
+
+static void
+gtk_check_menu_item_activate (GtkMenuItem *menu_item)
+{
+ GtkCheckMenuItem *check_menu_item;
+
+ g_return_if_fail (menu_item != NULL);
+ g_return_if_fail (GTK_IS_CHECK_MENU_ITEM (menu_item));
+
+ check_menu_item = GTK_CHECK_MENU_ITEM (menu_item);
+ check_menu_item->active = !check_menu_item->active;
+
+ gtk_check_menu_item_toggled (check_menu_item);
+ gtk_widget_queue_draw (GTK_WIDGET (check_menu_item));
+}
+
+static void
+gtk_check_menu_item_draw_indicator (GtkCheckMenuItem *check_menu_item,
+ GdkRectangle *area)
+{
+ g_return_if_fail (check_menu_item != NULL);
+ g_return_if_fail (GTK_IS_CHECK_MENU_ITEM (check_menu_item));
+ g_return_if_fail (CHECK_MENU_ITEM_CLASS (check_menu_item) != NULL);
+
+ if (CHECK_MENU_ITEM_CLASS (check_menu_item)->draw_indicator)
+ (* CHECK_MENU_ITEM_CLASS (check_menu_item)->draw_indicator) (check_menu_item, area);
+}
+
+static void
+gtk_real_check_menu_item_draw_indicator (GtkCheckMenuItem *check_menu_item,
+ GdkRectangle *area)
+{
+ GtkWidget *widget;
+ GtkStateType state_type;
+ GtkShadowType shadow_type;
+ gint width, height;
+ gint x, y;
+
+ g_return_if_fail (check_menu_item != NULL);
+ g_return_if_fail (GTK_IS_CHECK_MENU_ITEM (check_menu_item));
+
+ if (GTK_WIDGET_DRAWABLE (check_menu_item))
+ {
+ widget = GTK_WIDGET (check_menu_item);
+
+ width = 8;
+ height = 8;
+ x = (GTK_CONTAINER (check_menu_item)->border_width +
+ widget->style->klass->xthickness + 2);
+ y = (widget->allocation.height - height) / 2;
+
+ gdk_window_clear_area (widget->window, x, y, width, height);
+
+ if (check_menu_item->active ||
+ (GTK_WIDGET_STATE (check_menu_item) == GTK_STATE_PRELIGHT))
+ {
+ state_type = GTK_WIDGET_STATE (widget);
+
+ shadow_type = GTK_SHADOW_IN;
+ if (check_menu_item->active && (state_type == GTK_STATE_PRELIGHT))
+ shadow_type = GTK_SHADOW_OUT;
+
+ gdk_draw_rectangle (widget->window,
+ widget->style->bg_gc[state_type],
+ TRUE, x, y, width, height);
+ gtk_draw_shadow (widget->style, widget->window,
+ state_type, shadow_type,
+ x, y, width, height);
+ }
+ }
+}
diff --git a/gtk/gtkcheckmenuitem.h b/gtk/gtkcheckmenuitem.h
new file mode 100644
index 000000000..1dc816c7c
--- /dev/null
+++ b/gtk/gtkcheckmenuitem.h
@@ -0,0 +1,69 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_MENU_CHECK_ITEM_H__
+#define __GTK_MENU_CHECK_ITEM_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkmenuitem.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_CHECK_MENU_ITEM(obj) ((GtkCheckMenuItem*) obj)
+#define GTK_CHECK_MENU_ITEM_CLASS(obj) ((GtkCheckMenuItemClass*) GTK_OBJECT_CLASS (obj))
+#define GTK_IS_CHECK_MENU_ITEM(obj) (gtk_type_is_a (GTK_WIDGET_TYPE (obj), gtk_check_menu_item_get_type ()))
+
+
+typedef struct _GtkCheckMenuItem GtkCheckMenuItem;
+typedef struct _GtkCheckMenuItemClass GtkCheckMenuItemClass;
+
+struct _GtkCheckMenuItem
+{
+ GtkMenuItem menu_item;
+
+ guint active : 1;
+};
+
+struct _GtkCheckMenuItemClass
+{
+ GtkMenuItemClass parent_class;
+
+ void (* toggled) (GtkCheckMenuItem *check_menu_item);
+ void (* draw_indicator) (GtkCheckMenuItem *check_menu_item,
+ GdkRectangle *area);
+};
+
+
+guint gtk_check_menu_item_get_type (void);
+GtkWidget* gtk_check_menu_item_new (void);
+GtkWidget* gtk_check_menu_item_new_with_label (const gchar *label);
+void gtk_check_menu_item_set_state (GtkCheckMenuItem *check_menu_item,
+ gint state);
+void gtk_check_menu_item_toggled (GtkCheckMenuItem *check_menu_item);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_CHECK_MENU_ITEM_H__ */
diff --git a/gtk/gtkcolorsel.c b/gtk/gtkcolorsel.c
new file mode 100644
index 000000000..78780b2ff
--- /dev/null
+++ b/gtk/gtkcolorsel.c
@@ -0,0 +1,1463 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <math.h>
+#include "gtkcolorsel.h"
+
+
+#define DEGTORAD(a) (2.0*M_PI*a/360.0)
+#define SQR(a) (a*a)
+
+#define TIMER_DELAY 300
+
+#define CIRCLE_RADIUS 65
+
+#define WHEEL_WIDTH 2*CIRCLE_RADIUS+2
+#define WHEEL_HEIGHT 2*CIRCLE_RADIUS+2
+
+#define VALUE_WIDTH 32
+#define VALUE_HEIGHT WHEEL_HEIGHT
+
+#define SAMPLE_WIDTH WHEEL_WIDTH+VALUE_WIDTH+5
+#define SAMPLE_HEIGHT 28
+
+
+enum
+{
+ COLOR_CHANGED,
+ LAST_SIGNAL
+};
+
+enum
+{
+ RGB_INPUTS = 1 << 0,
+ HSV_INPUTS = 1 << 1,
+ OPACITY_INPUTS = 1 << 2
+};
+
+enum
+{
+ SCALE,
+ ENTRY,
+ BOTH
+};
+
+enum
+{
+ HUE,
+ SATURATION,
+ VALUE,
+ RED,
+ GREEN,
+ BLUE,
+ OPACITY,
+ NUM_CHANNELS
+};
+
+typedef struct
+{
+ gchar *label;
+ gfloat lower, upper, step_inc, page_inc;
+ GtkSignalFunc updater;
+} scale_val_type;
+
+
+#define HSV_TO_RGB() gtk_color_selection_hsv_to_rgb( \
+ colorsel->values[HUE], \
+ colorsel->values[SATURATION], \
+ colorsel->values[VALUE], \
+ &colorsel->values[RED], \
+ &colorsel->values[GREEN], \
+ &colorsel->values[BLUE])
+
+#define RGB_TO_HSV() gtk_color_selection_rgb_to_hsv( \
+ colorsel->values[RED], \
+ colorsel->values[GREEN], \
+ colorsel->values[BLUE], \
+ &colorsel->values[HUE], \
+ &colorsel->values[SATURATION], \
+ &colorsel->values[VALUE])
+
+
+static void gtk_color_selection_hsv_updater (GtkWidget *widget,
+ gpointer data);
+static void gtk_color_selection_rgb_updater (GtkWidget *widget,
+ gpointer data);
+static void gtk_color_selection_opacity_updater (GtkWidget *widget,
+ gpointer data);
+static void gtk_color_selection_realize (GtkWidget *widget);
+static void gtk_color_selection_destroy (GtkObject *object);
+static void gtk_color_selection_color_changed (GtkColorSelection *colorsel);
+static void gtk_color_selection_update_input (GtkWidget *scale,
+ GtkWidget *entry,
+ gdouble value);
+static void gtk_color_selection_update_inputs (GtkColorSelection *colorsel,
+ gint inputs,
+ gint which);
+static void gtk_color_selection_update_value (GtkColorSelection *colorsel,
+ gint y);
+static void gtk_color_selection_update_wheel (GtkColorSelection *colorsel,
+ gint x,
+ gint y);
+static void gtk_color_selection_value_resize (GtkWidget *widget,
+ gpointer data);
+static gint gtk_color_selection_value_events (GtkWidget *area,
+ GdkEvent *event);
+static gint gtk_color_selection_value_timeout (GtkColorSelection *colorsel);
+static void gtk_color_selection_wheel_resize (GtkWidget *widget,
+ gpointer data);
+static gint gtk_color_selection_wheel_events (GtkWidget *area,
+ GdkEvent *event);
+static gint gtk_color_selection_wheel_timeout (GtkColorSelection *colorsel);
+static void gtk_color_selection_sample_resize (GtkWidget *widget,
+ gpointer data);
+static void gtk_color_selection_drop_handle (GtkWidget *widget,
+ GdkEvent *event);
+static void gtk_color_selection_drag_handle (GtkWidget *widget,
+ GdkEvent *event);
+static void gtk_color_selection_draw_wheel_marker (GtkColorSelection *colorsel);
+static void gtk_color_selection_draw_wheel_frame (GtkColorSelection *colorsel);
+static void gtk_color_selection_draw_value_marker (GtkColorSelection *colorsel);
+static void gtk_color_selection_draw_value_bar (GtkColorSelection *colorsel,
+ gint resize);
+static void gtk_color_selection_draw_wheel (GtkColorSelection *colorsel,
+ gint resize);
+static void gtk_color_selection_draw_sample (GtkColorSelection *colorsel,
+ gint resize);
+
+static gint gtk_color_selection_eval_wheel (gint x, gint y,
+ gdouble cx, gdouble cy,
+ gdouble *h, gdouble *s);
+
+static void gtk_color_selection_hsv_to_rgb (gdouble h, gdouble s, gdouble v,
+ gdouble *r, gdouble *g, gdouble *b);
+static void gtk_color_selection_rgb_to_hsv (gdouble r, gdouble g, gdouble b,
+ gdouble *h, gdouble *s, gdouble *v);
+
+static void gtk_color_selection_dialog_destroy (GtkObject *object);
+
+
+static GtkVBoxClass *color_selection_parent_class = NULL;
+static GtkWindowClass *color_selection_dialog_parent_class = NULL;
+
+
+static gint color_selection_signals[LAST_SIGNAL] = {0};
+
+
+#define SF GtkSignalFunc
+
+
+scale_val_type scale_vals[NUM_CHANNELS] =
+{
+ {"Hue:", 0.0, 360.0, 1.00, 10.00, (SF) gtk_color_selection_hsv_updater},
+ {"Saturation:", 0.0, 1.0, 0.01, 0.01, (SF) gtk_color_selection_hsv_updater},
+ {"Value:", 0.0, 1.0, 0.01, 0.01, (SF) gtk_color_selection_hsv_updater},
+ {"Red:", 0.0, 1.0, 0.01, 0.01, (SF) gtk_color_selection_rgb_updater},
+ {"Green:", 0.0, 1.0, 0.01, 0.01, (SF) gtk_color_selection_rgb_updater},
+ {"Blue:", 0.0, 1.0, 0.01, 0.01, (SF) gtk_color_selection_rgb_updater},
+ {"Opacity:", 0.0, 1.0, 0.01, 0.01, (SF) gtk_color_selection_opacity_updater}
+};
+
+guint
+gtk_color_selection_get_type ()
+{
+ static guint color_selection_type = 0;
+
+ if (!color_selection_type)
+ {
+ GtkTypeInfo colorsel_info =
+ {
+ "color selection widget",
+ sizeof (GtkColorSelection),
+ sizeof (GtkColorSelectionClass),
+ (GtkClassInitFunc) gtk_color_selection_class_init,
+ (GtkObjectInitFunc) gtk_color_selection_init,
+ };
+
+ color_selection_type = gtk_type_unique (gtk_vbox_get_type (), &colorsel_info);
+ }
+
+ return color_selection_type;
+}
+
+void
+gtk_color_selection_class_init (GtkColorSelectionClass *klass)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+ GtkContainerClass *container_class;
+
+ object_class = (GtkObjectClass*) klass;
+ widget_class = (GtkWidgetClass*) klass;
+ container_class = (GtkContainerClass*) klass;
+
+ color_selection_parent_class = gtk_type_class (gtk_vbox_get_type ());
+
+ color_selection_signals[COLOR_CHANGED] =
+ gtk_signal_new ("color_changed",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkColorSelectionClass, color_changed),
+ gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
+
+ gtk_object_class_add_signals (object_class, color_selection_signals, LAST_SIGNAL);
+
+ object_class->destroy = gtk_color_selection_destroy;
+
+ widget_class->realize = gtk_color_selection_realize;
+}
+
+void
+gtk_color_selection_init (GtkColorSelection *colorsel)
+{
+ GtkWidget *frame, *hbox, *vbox, *hbox2, *label, *table;
+ GtkObject *adj;
+ gint old_mask, n;
+ gchar txt[32];
+
+ for (n = RED; n <= OPACITY; n++)
+ colorsel->values[n] = 1.0;
+
+ RGB_TO_HSV ();
+
+ for (n = HUE; n <= OPACITY; n++)
+ colorsel->old_values[n] = colorsel->values[n];
+
+ colorsel->wheel_gc = NULL;
+ colorsel->value_gc = NULL;
+ colorsel->sample_gc = NULL;
+ colorsel->wheel_buf = NULL;
+ colorsel->value_buf = NULL;
+ colorsel->sample_buf = NULL;
+
+ colorsel->use_opacity = FALSE;
+ colorsel->timer_active = FALSE;
+ colorsel->policy = GTK_UPDATE_CONTINUOUS;
+
+ hbox = gtk_hbox_new (FALSE, 5);
+ gtk_container_border_width (GTK_CONTAINER (hbox), 5);
+ gtk_container_add (GTK_CONTAINER (colorsel), hbox);
+
+ vbox = gtk_vbox_new (FALSE, 5);
+ gtk_container_add (GTK_CONTAINER (hbox), vbox);
+ gtk_widget_show (vbox);
+
+ hbox2 = gtk_hbox_new (FALSE, 5);
+ gtk_container_add (GTK_CONTAINER (vbox), hbox2);
+ gtk_widget_show (hbox2);
+
+ colorsel->wheel_area = gtk_preview_new (GTK_PREVIEW_COLOR);
+ gtk_widget_set_events (colorsel->wheel_area,
+ old_mask |
+ GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_BUTTON_MOTION_MASK |
+ GDK_POINTER_MOTION_HINT_MASK);
+ gtk_preview_size (GTK_PREVIEW (colorsel->wheel_area), WHEEL_WIDTH, WHEEL_HEIGHT);
+ gtk_preview_set_expand (GTK_PREVIEW (colorsel->wheel_area), TRUE);
+ gtk_container_add (GTK_CONTAINER (hbox2), colorsel->wheel_area);
+ gtk_widget_show (colorsel->wheel_area);
+
+ old_mask = gtk_widget_get_events (colorsel->wheel_area);
+
+ gtk_signal_connect (GTK_OBJECT (colorsel->wheel_area), "event",
+ (SF) gtk_color_selection_wheel_events, (gpointer) colorsel->wheel_area);
+ gtk_signal_connect_after (GTK_OBJECT (colorsel->wheel_area), "expose_event",
+ (SF) gtk_color_selection_wheel_events, (gpointer) colorsel->wheel_area);
+ gtk_signal_connect_after (GTK_OBJECT (colorsel->wheel_area), "size_allocate",
+ (SF) gtk_color_selection_wheel_resize, (gpointer) colorsel->wheel_area);
+ gtk_object_set_data (GTK_OBJECT (colorsel->wheel_area), "_GtkColorSelection", (gpointer) colorsel);
+
+ frame = gtk_frame_new (NULL);
+ gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
+ gtk_container_border_width (GTK_CONTAINER (frame), 0);
+ gtk_box_pack_start (GTK_BOX (hbox2), frame, FALSE, TRUE, 0);
+ gtk_widget_show (frame);
+
+ colorsel->value_area = gtk_preview_new (GTK_PREVIEW_COLOR);
+ gtk_preview_size (GTK_PREVIEW (colorsel->value_area), VALUE_WIDTH, VALUE_HEIGHT);
+ gtk_preview_set_expand (GTK_PREVIEW (colorsel->value_area), TRUE);
+ gtk_container_add (GTK_CONTAINER (frame), colorsel->value_area);
+ gtk_widget_show (colorsel->value_area);
+
+ old_mask = gtk_widget_get_events (colorsel->value_area);
+ gtk_widget_set_events (colorsel->value_area,
+ old_mask |
+ GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_BUTTON_MOTION_MASK |
+ GDK_POINTER_MOTION_HINT_MASK);
+
+ gtk_signal_connect_after (GTK_OBJECT (colorsel->value_area), "expose_event",
+ (SF) gtk_color_selection_value_events, (gpointer) colorsel->value_area);
+ gtk_signal_connect_after (GTK_OBJECT (colorsel->value_area), "size_allocate",
+ (SF) gtk_color_selection_value_resize, (gpointer) colorsel->value_area);
+ gtk_signal_connect (GTK_OBJECT (colorsel->value_area), "event",
+ (SF) gtk_color_selection_value_events, (gpointer) colorsel->value_area);
+ gtk_object_set_data (GTK_OBJECT (colorsel->value_area), "_GtkColorSelection", (gpointer) colorsel);
+
+ /* New/old color samples */
+ /* ===================== */
+
+ frame = gtk_frame_new (NULL);
+ gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
+ gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
+ gtk_widget_show (frame);
+
+/* colorsel->sample_area_eb = gtk_button_new ();
+ gtk_container_add (GTK_CONTAINER (frame), colorsel->sample_area_eb);
+ gtk_widget_show (colorsel->sample_area_eb); */
+
+ colorsel->sample_area = gtk_preview_new (GTK_PREVIEW_COLOR);
+ gtk_preview_size (GTK_PREVIEW (colorsel->sample_area), SAMPLE_WIDTH, SAMPLE_HEIGHT);
+ gtk_preview_set_expand (GTK_PREVIEW (colorsel->sample_area), TRUE);
+ gtk_container_add (GTK_CONTAINER (frame),
+ colorsel->sample_area);
+ gtk_widget_set_events(colorsel->sample_area,
+ gtk_widget_get_events(colorsel->sample_area)
+ | GDK_BUTTON_MOTION_MASK
+ | GDK_BUTTON_PRESS_MASK
+ | GDK_BUTTON_RELEASE_MASK
+ | GDK_ENTER_NOTIFY_MASK
+ | GDK_LEAVE_NOTIFY_MASK);
+ gtk_widget_show (colorsel->sample_area);
+
+ gtk_signal_connect_after (GTK_OBJECT (colorsel->sample_area),
+ "size_allocate",
+ GTK_SIGNAL_FUNC (gtk_color_selection_sample_resize),
+ colorsel->sample_area);
+ gtk_object_set_data (GTK_OBJECT (colorsel->sample_area), "_GtkColorSelection", (gpointer) colorsel);
+
+ table = gtk_table_new (NUM_CHANNELS, 3, FALSE);
+ gtk_table_set_col_spacings (GTK_TABLE (table), 3);
+ gtk_box_pack_start (GTK_BOX (hbox), table, FALSE, TRUE, 0);
+
+ for (n = HUE; n <= OPACITY; n++)
+ {
+ label = gtk_label_new (scale_vals[n].label);
+ gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
+ gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, n, n + 1);
+
+ adj = gtk_adjustment_new (colorsel->values[n], scale_vals[n].lower,
+ scale_vals[n].upper, scale_vals[n].step_inc,
+ scale_vals[n].page_inc, 0.0);
+ colorsel->scales[n] = gtk_hscale_new (GTK_ADJUSTMENT (adj));
+ gtk_widget_set_usize (colorsel->scales[n], 128, 0);
+ gtk_scale_set_value_pos (GTK_SCALE (colorsel->scales[n]), GTK_POS_TOP);
+
+ gtk_range_set_update_policy (GTK_RANGE (colorsel->scales[n]), colorsel->policy);
+ gtk_scale_set_draw_value (GTK_SCALE (colorsel->scales[n]), FALSE);
+ gtk_scale_set_digits (GTK_SCALE (colorsel->scales[n]), 2);
+ gtk_table_attach_defaults (GTK_TABLE (table), colorsel->scales[n], 1, 2, n, n + 1);
+
+ colorsel->entries[n] = gtk_entry_new ();
+ gtk_widget_set_usize (colorsel->entries[n], 40, 0);
+ sprintf (txt, "%.2f", colorsel->values[n]);
+ gtk_entry_set_text (GTK_ENTRY (colorsel->entries[n]), txt);
+ gtk_table_attach_defaults (GTK_TABLE (table), colorsel->entries[n], 2, 3, n, n + 1);
+
+ if (n != OPACITY)
+ {
+ gtk_widget_show (label);
+ gtk_widget_show (colorsel->scales[n]);
+ gtk_widget_show (colorsel->entries[n]);
+ }
+
+ gtk_signal_connect_object (GTK_OBJECT (adj), "value_changed",
+ scale_vals[n].updater, (gpointer) colorsel->scales[n]);
+ gtk_object_set_data (GTK_OBJECT (colorsel->scales[n]), "_GtkColorSelection", (gpointer) colorsel);
+ gtk_object_set_data (GTK_OBJECT (colorsel->scales[n]), "_ValueIndex", (gpointer) n);
+ gtk_signal_connect_object (GTK_OBJECT (colorsel->entries[n]), "changed",
+ scale_vals[n].updater, (gpointer) colorsel->entries[n]);
+ gtk_object_set_data (GTK_OBJECT (colorsel->entries[n]), "_GtkColorSelection", (gpointer) colorsel);
+ gtk_object_set_data (GTK_OBJECT (colorsel->entries[n]), "_ValueIndex", (gpointer) n);
+ }
+
+ colorsel->opacity_label = label;
+
+ gtk_widget_show (table);
+ gtk_widget_show (hbox);
+}
+
+GtkWidget *
+gtk_color_selection_new (void)
+{
+ GtkColorSelection *colorsel;
+
+ colorsel = gtk_type_new (gtk_color_selection_get_type ());
+
+ return GTK_WIDGET (colorsel);
+}
+
+void
+gtk_color_selection_set_update_policy (GtkColorSelection *colorsel,
+ GtkUpdateType policy)
+{
+ gint n;
+
+ g_return_if_fail (colorsel != NULL);
+
+ if (policy != colorsel->policy)
+ {
+ colorsel->policy = policy;
+
+ for (n = 0; n < NUM_CHANNELS; n++)
+ gtk_range_set_update_policy (GTK_RANGE (colorsel->scales[n]), policy);
+ }
+}
+
+
+void
+gtk_color_selection_set_color (GtkColorSelection *colorsel,
+ gdouble *color)
+{
+ gint n, i = 0;
+
+ g_return_if_fail (colorsel != NULL);
+ g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
+
+ if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (colorsel)))
+ gtk_color_selection_draw_wheel_marker (colorsel);
+
+ for (n = RED; n <= BLUE; n++)
+ {
+ colorsel->old_values[n] = colorsel->values[n];
+ colorsel->values[n] = color[i++];
+ }
+
+ if (colorsel->use_opacity == TRUE)
+ {
+ colorsel->old_values[OPACITY] = colorsel->values[OPACITY];
+ colorsel->values[OPACITY] = color[i];
+ }
+
+ RGB_TO_HSV ();
+
+ gtk_color_selection_update_inputs (colorsel, RGB_INPUTS | HSV_INPUTS | OPACITY_INPUTS, BOTH);
+
+ if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (colorsel)))
+ {
+ gtk_color_selection_draw_value_bar (colorsel, FALSE);
+ gtk_color_selection_draw_sample (colorsel, FALSE);
+ gtk_color_selection_draw_wheel_marker (colorsel);
+ }
+}
+
+void
+gtk_color_selection_get_color (GtkColorSelection *colorsel,
+ gdouble *color)
+{
+ gint n, i = 0;
+
+ g_return_if_fail (colorsel != NULL);
+ g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
+
+ for (n = RED; n <= BLUE; n++)
+ color[i++] = colorsel->values[n];
+ if (colorsel->use_opacity == TRUE)
+ color[i] = colorsel->values[OPACITY];
+}
+
+static void
+gtk_color_selection_realize (GtkWidget *widget)
+{
+ GtkColorSelection *colorsel;
+ gchar *type_accept_list[] = {"application/x-color"};
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_COLOR_SELECTION (widget));
+
+ colorsel = GTK_COLOR_SELECTION (widget);
+
+ if (GTK_WIDGET_CLASS (color_selection_parent_class)->realize)
+ (*GTK_WIDGET_CLASS (color_selection_parent_class)->realize) (widget);
+
+ gtk_widget_dnd_drag_set (colorsel->sample_area,
+ 1, type_accept_list, 1);
+ gtk_widget_dnd_drop_set (colorsel->sample_area,
+ 1, type_accept_list, 1, 0);
+ gtk_signal_connect_after (GTK_OBJECT (colorsel->sample_area),
+ "drop_data_available_event",
+ GTK_SIGNAL_FUNC (gtk_color_selection_drop_handle),
+ NULL);
+ gtk_signal_connect_after (GTK_OBJECT (colorsel->sample_area),
+ "drag_request_event",
+ GTK_SIGNAL_FUNC (gtk_color_selection_drag_handle),
+ NULL);
+}
+
+static void
+gtk_color_selection_destroy (GtkObject *object)
+{
+ GtkColorSelection *colorsel;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_COLOR_SELECTION (object));
+
+ colorsel = GTK_COLOR_SELECTION (object);
+
+ if (colorsel->wheel_buf != NULL)
+ g_free (colorsel->wheel_buf);
+ if (colorsel->value_buf != NULL)
+ g_free (colorsel->value_buf);
+ if (colorsel->sample_buf != NULL)
+ g_free (colorsel->sample_buf);
+
+ if (GTK_OBJECT_CLASS (color_selection_parent_class)->destroy)
+ (*GTK_OBJECT_CLASS (color_selection_parent_class)->destroy) (object);
+}
+
+static void
+gtk_color_selection_color_changed (GtkColorSelection *colorsel)
+{
+ gtk_signal_emit (GTK_OBJECT (colorsel), color_selection_signals[COLOR_CHANGED]);
+}
+
+static void
+gtk_color_selection_update_input (GtkWidget *scale,
+ GtkWidget *entry,
+ gdouble value)
+{
+ GtkAdjustment *adj;
+ gchar txt[32];
+
+ if (scale != NULL)
+ {
+ adj = gtk_range_get_adjustment (GTK_RANGE (scale));
+ adj->value = (gfloat) value;
+ gtk_signal_handler_block_by_data (GTK_OBJECT (adj), (gpointer) scale);
+ gtk_signal_emit_by_name (GTK_OBJECT (adj), "value_changed");
+ gtk_range_slider_update (GTK_RANGE (scale));
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (adj), (gpointer) scale);
+ }
+
+ if (entry != NULL)
+ {
+ gtk_signal_handler_block_by_data (GTK_OBJECT (entry), (gpointer) entry);
+ sprintf (txt, "%.2f", value);
+ gtk_entry_set_text (GTK_ENTRY (entry), txt);
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (entry), (gpointer) entry);
+ }
+}
+
+static void
+gtk_color_selection_update_inputs (GtkColorSelection *colorsel,
+ gint inputs,
+ gint which)
+{
+ gint n;
+
+ switch (which)
+ {
+ case SCALE:
+ if ((inputs & RGB_INPUTS) != 0)
+ for (n = RED; n <= BLUE; n++)
+ gtk_color_selection_update_input (colorsel->scales[n], NULL,
+ colorsel->values[n]);
+ if ((inputs & HSV_INPUTS) != 0)
+ for (n = HUE; n <= VALUE; n++)
+ gtk_color_selection_update_input (colorsel->scales[n], NULL,
+ colorsel->values[n]);
+ if ((inputs & OPACITY_INPUTS) != 0)
+ gtk_color_selection_update_input(colorsel->scales[OPACITY], NULL,
+ colorsel->values[OPACITY]);
+ break;
+ case ENTRY:
+ if ((inputs & RGB_INPUTS) != 0)
+ for (n = RED; n <= BLUE; n++)
+ gtk_color_selection_update_input (NULL, colorsel->entries[n], colorsel->values[n]);
+ if ((inputs & HSV_INPUTS) != 0)
+ for (n = HUE; n <= VALUE; n++)
+ gtk_color_selection_update_input (NULL, colorsel->entries[n], colorsel->values[n]);
+ if ((inputs & OPACITY_INPUTS) != 0)
+ gtk_color_selection_update_input(NULL, colorsel->entries[OPACITY], colorsel->values[OPACITY]);
+ break;
+ default:
+ if ((inputs & RGB_INPUTS) != 0)
+ for (n = RED; n <= BLUE; n++)
+ gtk_color_selection_update_input (colorsel->scales[n], colorsel->entries[n],
+ colorsel->values[n]);
+ if ((inputs & HSV_INPUTS) != 0)
+ for (n = HUE; n <= VALUE; n++)
+ gtk_color_selection_update_input (colorsel->scales[n], colorsel->entries[n],
+ colorsel->values[n]);
+ if ((inputs & OPACITY_INPUTS) != 0)
+ gtk_color_selection_update_input(colorsel->scales[OPACITY], colorsel->entries[OPACITY],
+ colorsel->values[OPACITY]);
+ break;
+ }
+}
+
+static void
+gtk_color_selection_hsv_updater (GtkWidget *widget,
+ gpointer data)
+{
+ GtkColorSelection *colorsel;
+ GtkAdjustment *adj;
+ gdouble newvalue;
+ gint i, which = SCALE;
+
+ if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (widget)))
+ {
+ colorsel = (GtkColorSelection*) gtk_object_get_data (GTK_OBJECT (widget), "_GtkColorSelection");
+ i = (gint) gtk_object_get_data (GTK_OBJECT (widget), "_ValueIndex");
+
+ if (GTK_IS_SCALE (widget))
+ {
+ adj = gtk_range_get_adjustment (GTK_RANGE (GTK_SCALE (widget)));
+ newvalue = (gdouble) adj->value;
+ which = ENTRY;
+ }
+ else
+ newvalue = (gdouble) atof (gtk_entry_get_text (GTK_ENTRY (widget)));
+
+ if (i == VALUE)
+ {
+ gtk_color_selection_draw_value_marker (colorsel);
+ colorsel->values[i] = newvalue;
+
+ HSV_TO_RGB ();
+
+ gtk_color_selection_draw_value_marker (colorsel);
+ }
+ else
+ {
+ gtk_color_selection_draw_wheel_marker (colorsel);
+ colorsel->values[i] = newvalue;
+
+ HSV_TO_RGB ();
+
+ gtk_color_selection_draw_wheel_marker (colorsel);
+ gtk_color_selection_draw_value_bar (colorsel, FALSE);
+ }
+
+ gtk_color_selection_draw_sample (colorsel, FALSE);
+ gtk_color_selection_color_changed (colorsel);
+ gtk_color_selection_update_inputs (colorsel, HSV_INPUTS, which);
+ gtk_color_selection_update_inputs (colorsel, RGB_INPUTS, BOTH);
+ }
+}
+
+static void
+gtk_color_selection_rgb_updater (GtkWidget *widget,
+ gpointer data)
+{
+ GtkColorSelection *colorsel;
+ GtkAdjustment *adj;
+ gdouble newvalue;
+ gint i, which = SCALE;
+
+ if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (widget)))
+ {
+ colorsel = (GtkColorSelection*) gtk_object_get_data (GTK_OBJECT (widget), "_GtkColorSelection");
+ i = (gint) gtk_object_get_data (GTK_OBJECT (widget), "_ValueIndex");
+
+ if (GTK_IS_SCALE (widget))
+ {
+ adj = gtk_range_get_adjustment (GTK_RANGE (GTK_SCALE (widget)));
+ newvalue = (gdouble) adj->value;
+ which = ENTRY;
+ }
+ else
+ newvalue = (gdouble) atof (gtk_entry_get_text (GTK_ENTRY (widget)));
+
+ gtk_color_selection_draw_wheel_marker (colorsel);
+
+ colorsel->values[i] = newvalue;
+ RGB_TO_HSV ();
+
+ gtk_color_selection_draw_wheel_marker (colorsel);
+ gtk_color_selection_draw_value_bar (colorsel, FALSE);
+ gtk_color_selection_draw_sample (colorsel, FALSE);
+ gtk_color_selection_color_changed (colorsel);
+ gtk_color_selection_update_inputs (colorsel, RGB_INPUTS, which);
+ gtk_color_selection_update_inputs (colorsel, HSV_INPUTS, BOTH);
+ }
+}
+
+static void
+gtk_color_selection_opacity_updater (GtkWidget *widget,
+ gpointer data)
+{
+ GtkColorSelection *colorsel;
+ GtkAdjustment *adj;
+
+ colorsel = (GtkColorSelection*) gtk_object_get_data (GTK_OBJECT (widget), "_GtkColorSelection");
+
+ if (GTK_IS_SCALE (widget))
+ {
+ adj = gtk_range_get_adjustment (GTK_RANGE (widget));
+ colorsel->values[OPACITY] = (gdouble) adj->value;
+ gtk_color_selection_update_input (NULL, colorsel->entries[OPACITY], colorsel->values[OPACITY]);
+ }
+ else
+ {
+ colorsel->values[OPACITY] = (gdouble) atof (gtk_entry_get_text (GTK_ENTRY (widget)));
+ gtk_color_selection_update_input (colorsel->scales[OPACITY], NULL, colorsel->values[OPACITY]);
+ }
+
+ gtk_color_selection_draw_sample (colorsel, FALSE);
+ gtk_color_selection_color_changed (colorsel);
+}
+
+void
+gtk_color_selection_set_opacity (GtkColorSelection *colorsel,
+ gint use_opacity)
+{
+ g_return_if_fail (colorsel != NULL);
+
+ colorsel->use_opacity = use_opacity;
+
+ if (use_opacity == FALSE && GTK_WIDGET_VISIBLE (colorsel->scales[OPACITY]))
+ {
+ gtk_widget_hide (colorsel->opacity_label);
+ gtk_widget_hide (colorsel->scales[OPACITY]);
+ gtk_widget_hide (colorsel->entries[OPACITY]);
+ }
+ else if (use_opacity == TRUE && !GTK_WIDGET_VISIBLE (colorsel->scales[OPACITY]))
+ {
+ gtk_widget_show (colorsel->opacity_label);
+ gtk_widget_show (colorsel->scales[OPACITY]);
+ gtk_widget_show (colorsel->entries[OPACITY]);
+ }
+
+ if (GTK_WIDGET_DRAWABLE (colorsel->sample_area))
+ gtk_color_selection_draw_sample (colorsel, FALSE);
+}
+
+static void
+gtk_color_selection_value_resize (GtkWidget *widget,
+ gpointer data)
+{
+ GtkColorSelection *colorsel;
+
+ colorsel = (GtkColorSelection*) gtk_object_get_data (GTK_OBJECT (widget), "_GtkColorSelection");
+ gtk_color_selection_draw_value_bar (colorsel, TRUE);
+}
+
+static void
+gtk_color_selection_wheel_resize (GtkWidget *widget,
+ gpointer data)
+{
+ GtkColorSelection *colorsel;
+
+ colorsel = (GtkColorSelection*) gtk_object_get_data (GTK_OBJECT (widget), "_GtkColorSelection");
+ gtk_color_selection_draw_wheel (colorsel, TRUE);
+}
+
+static void
+gtk_color_selection_sample_resize (GtkWidget *widget,
+ gpointer data)
+{
+ GtkColorSelection *colorsel;
+
+ colorsel = (GtkColorSelection*) gtk_object_get_data (GTK_OBJECT (widget), "_GtkColorSelection");
+ gtk_color_selection_draw_sample (colorsel, TRUE);
+}
+
+static void
+gtk_color_selection_drop_handle (GtkWidget *widget, GdkEvent *event)
+{
+ int i;
+ GtkColorSelection *w;
+ gdouble *newbuf;
+ g_print("Handling drop in color selection\n");
+ gtk_color_selection_set_color(GTK_COLOR_SELECTION(widget),
+ event->dropdataavailable.data);
+ g_free(event->dropdataavailable.data);
+ g_free(event->dropdataavailable.data_type);
+}
+
+static void
+gtk_color_selection_drag_handle (GtkWidget *widget, GdkEvent *event)
+{
+ g_print("Handling drag in color selector\n");
+ gtk_widget_dnd_data_set(widget, event, GTK_COLOR_SELECTION(widget)->values,
+ sizeof(GTK_COLOR_SELECTION(widget)->values));
+}
+
+static void
+gtk_color_selection_draw_wheel_marker (GtkColorSelection *colorsel)
+{
+ gint xpos, ypos;
+
+ gdk_gc_set_function (colorsel->wheel_gc, GDK_INVERT);
+
+ xpos = (gint) ((-(gdouble) (colorsel->wheel_area->allocation.width) / 2.0) *
+ colorsel->values[SATURATION] * cos (DEGTORAD ((colorsel->values[HUE] - 90)))) +
+ (colorsel->wheel_area->allocation.width >> 1) - 4;
+ ypos = (gint) (((gdouble) (colorsel->wheel_area->allocation.height) / 2.0) *
+ colorsel->values[SATURATION] * sin (DEGTORAD ((colorsel->values[HUE] - 90)))) +
+ (colorsel->wheel_area->allocation.height >> 1) - 4;
+
+ gdk_draw_arc (colorsel->wheel_area->window, colorsel->wheel_gc, FALSE, xpos, ypos, 8, 8, 0, 360 * 64);
+}
+
+static void
+gtk_color_selection_draw_value_marker (GtkColorSelection *colorsel)
+{
+ gint y;
+
+ gdk_gc_set_function (colorsel->value_gc, GDK_INVERT);
+
+ y = (gint) ((gdouble) (colorsel->value_area->allocation.height) * (1.0 - colorsel->values[VALUE]));
+ gdk_draw_line (colorsel->value_area->window, colorsel->value_gc,
+ 0, y, colorsel->value_area->allocation.width, y);
+}
+
+static void
+gtk_color_selection_update_value (GtkColorSelection *colorsel,
+ gint y)
+{
+ gtk_color_selection_draw_value_marker (colorsel);
+
+ if (y < 0)
+ y = 0;
+ else if (y > colorsel->value_area->allocation.height - 1)
+ y = colorsel->value_area->allocation.height - 1;
+
+ colorsel->values[VALUE] = 1.0 - (gdouble) y / (gdouble) (colorsel->value_area->allocation.height);
+
+ HSV_TO_RGB ();
+
+ gtk_color_selection_draw_value_marker (colorsel);
+ gtk_color_selection_draw_sample (colorsel, FALSE);
+ gtk_color_selection_update_input (colorsel->scales[VALUE], colorsel->entries[VALUE],
+ colorsel->values[VALUE]);
+ gtk_color_selection_update_inputs (colorsel, RGB_INPUTS, BOTH);
+}
+
+static void
+gtk_color_selection_update_wheel (GtkColorSelection *colorsel,
+ gint x,
+ gint y)
+{
+ gdouble wid, heig;
+ gint res;
+
+ gtk_color_selection_draw_wheel_marker (colorsel);
+
+ wid = (gdouble) (colorsel->wheel_area->allocation.width) / 2.0;
+ heig = (gdouble) (colorsel->wheel_area->allocation.height) / 2.0;
+
+ res = gtk_color_selection_eval_wheel (x, y, wid, heig, &colorsel->values[HUE],
+ &colorsel->values[SATURATION]);
+
+ HSV_TO_RGB ();
+
+ gtk_color_selection_draw_wheel_marker (colorsel);
+ gtk_color_selection_draw_value_bar (colorsel, FALSE);
+ gtk_color_selection_draw_sample (colorsel, FALSE);
+ gtk_color_selection_update_inputs (colorsel, RGB_INPUTS | HSV_INPUTS, BOTH);
+}
+
+static gint
+gtk_color_selection_value_timeout (GtkColorSelection *colorsel)
+{
+ gint x, y;
+
+ gdk_window_get_pointer (colorsel->value_area->window, &x, &y, NULL);
+ gtk_color_selection_update_value (colorsel, y);
+ gtk_color_selection_color_changed (colorsel);
+
+ return (TRUE);
+}
+
+static gint
+gtk_color_selection_value_events (GtkWidget *area,
+ GdkEvent *event)
+{
+ GtkColorSelection *colorsel;
+ gint y;
+
+ colorsel = (GtkColorSelection*) gtk_object_get_data (GTK_OBJECT (area), "_GtkColorSelection");
+
+ switch (event->type)
+ {
+ case GDK_MAP:
+ gtk_color_selection_draw_value_marker (colorsel);
+ break;
+ case GDK_EXPOSE:
+ if (colorsel->value_gc == NULL)
+ colorsel->value_gc = gdk_gc_new (colorsel->value_area->window);
+ gtk_color_selection_draw_value_marker (colorsel);
+ break;
+ case GDK_BUTTON_PRESS:
+ gtk_grab_add (area);
+ gtk_color_selection_update_value (colorsel, event->button.y);
+ gtk_color_selection_color_changed (colorsel);
+ break;
+ case GDK_BUTTON_RELEASE:
+ gtk_grab_remove (area);
+ if (colorsel->timer_active == TRUE)
+ gtk_timeout_remove (colorsel->timer_tag);
+ colorsel->timer_active = FALSE;
+
+ y = event->button.y;
+ if (event->button.window != area->window)
+ gdk_window_get_pointer (area->window, NULL, &y, NULL);
+
+ gtk_color_selection_update_value (colorsel, y);
+ gtk_color_selection_color_changed (colorsel);
+ break;
+ case GDK_MOTION_NOTIFY:
+ y = event->motion.y;
+
+ if (event->motion.is_hint || (event->motion.window != area->window))
+ gdk_window_get_pointer (area->window, NULL, &y, NULL);
+
+ switch (colorsel->policy)
+ {
+ case GTK_UPDATE_CONTINUOUS:
+ gtk_color_selection_update_value (colorsel, y);
+ gtk_color_selection_color_changed (colorsel);
+ break;
+ case GTK_UPDATE_DELAYED:
+ if (colorsel->timer_active == TRUE)
+ gtk_timeout_remove (colorsel->timer_tag);
+
+ colorsel->timer_tag = gtk_timeout_add (TIMER_DELAY,
+ (GtkFunction) gtk_color_selection_value_timeout,
+ (gpointer) colorsel);
+ colorsel->timer_active = TRUE;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return (FALSE);
+}
+
+static gint
+gtk_color_selection_wheel_timeout (GtkColorSelection *colorsel)
+{
+ gint x, y;
+
+ gdk_window_get_pointer (colorsel->wheel_area->window, &x, &y, NULL);
+ gtk_color_selection_update_wheel (colorsel, x, y);
+ gtk_color_selection_color_changed (colorsel);
+
+ return (TRUE);
+}
+
+static gint
+gtk_color_selection_wheel_events (GtkWidget *area,
+ GdkEvent *event)
+{
+ GtkColorSelection *colorsel;
+ gint x, y;
+
+ colorsel = (GtkColorSelection*) gtk_object_get_data (GTK_OBJECT (area), "_GtkColorSelection");
+
+ switch (event->type)
+ {
+ case GDK_MAP:
+ gtk_color_selection_draw_wheel (colorsel, TRUE);
+ gtk_color_selection_draw_wheel_marker (colorsel);
+ gtk_color_selection_draw_sample (colorsel, TRUE);
+ break;
+ case GDK_EXPOSE:
+ if (colorsel->wheel_gc == NULL)
+ colorsel->wheel_gc = gdk_gc_new (colorsel->wheel_area->window);
+ if (colorsel->sample_gc == NULL)
+ colorsel->sample_gc = gdk_gc_new (colorsel->sample_area->window);
+ if (colorsel->value_gc == NULL)
+ colorsel->value_gc = gdk_gc_new (colorsel->value_area->window);
+ gtk_color_selection_draw_wheel_marker (colorsel);
+ gtk_color_selection_draw_wheel_frame (colorsel);
+ break;
+ case GDK_BUTTON_PRESS:
+ gtk_grab_add (area);
+ gtk_color_selection_update_wheel (colorsel, event->button.x, event->button.y);
+ gtk_color_selection_color_changed (colorsel);
+ break;
+ case GDK_BUTTON_RELEASE:
+ gtk_grab_remove (area);
+ if (colorsel->timer_active == TRUE)
+ gtk_timeout_remove (colorsel->timer_tag);
+ colorsel->timer_active = FALSE;
+
+ x = event->button.x;
+ y = event->button.y;
+
+ if (event->button.window != area->window)
+ gdk_window_get_pointer (area->window, &x, &y, NULL);
+
+ gtk_color_selection_update_wheel (colorsel, x, y);
+ gtk_color_selection_color_changed (colorsel);
+ break;
+ case GDK_MOTION_NOTIFY:
+ x = event->motion.x;
+ y = event->motion.y;
+
+ if (event->motion.is_hint || (event->motion.window != area->window))
+ gdk_window_get_pointer (area->window, &x, &y, NULL);
+
+ switch (colorsel->policy)
+ {
+ case GTK_UPDATE_CONTINUOUS:
+ gtk_color_selection_update_wheel (colorsel, x, y);
+ gtk_color_selection_color_changed (colorsel);
+ break;
+ case GTK_UPDATE_DELAYED:
+ if (colorsel->timer_active == TRUE)
+ gtk_timeout_remove (colorsel->timer_tag);
+ colorsel->timer_tag = gtk_timeout_add (TIMER_DELAY,
+ (GtkFunction) gtk_color_selection_wheel_timeout,
+ (gpointer) colorsel);
+ colorsel->timer_active = TRUE;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return (FALSE);
+}
+
+static void
+gtk_color_selection_draw_value_bar (GtkColorSelection *colorsel,
+ gint resize)
+{
+ gint x, y, i, wid, heig, n;
+ gdouble sv, v, c[3];
+ guchar rc[3];
+
+ wid = colorsel->value_area->allocation.width;
+ heig = colorsel->value_area->allocation.height;
+
+ if (resize)
+ {
+ if (colorsel->value_buf != NULL)
+ g_free (colorsel->value_buf);
+
+ colorsel->value_buf = g_new(guchar, 3 * wid);
+ }
+
+ v = 1.0;
+ sv = 1.0 / (gdouble) (heig - 1);
+
+ for (y = 0; y < heig; y++)
+ {
+ i = 0;
+
+ gtk_color_selection_hsv_to_rgb (colorsel->values[HUE],colorsel->values[SATURATION],v,
+ &c[0], &c[1], &c[2]);
+
+ for (n = 0; n < 3; n++)
+ rc[n] = (guchar) (255.0 * c[n]);
+
+ for (x = 0; x < wid; x++)
+ {
+ for (n = 0; n < 3; n++)
+ colorsel->value_buf[i++] = rc[n];
+ }
+
+ gtk_preview_draw_row (GTK_PREVIEW (colorsel->value_area), colorsel->value_buf, 0, y, wid);
+ v -= sv;
+ }
+
+ gtk_widget_draw (colorsel->value_area, NULL);
+}
+
+static void
+gtk_color_selection_draw_wheel_frame (GtkColorSelection *colorsel)
+{
+ GtkStyle *style;
+ gint w, h;
+
+ style = gtk_widget_get_style (GTK_WIDGET (colorsel));
+
+ w = colorsel->wheel_area->allocation.width;
+ h = colorsel->wheel_area->allocation.height;
+
+ gdk_draw_arc (colorsel->wheel_area->window, style->black_gc,
+ FALSE, 1, 1, w - 1, h - 1, 30 * 64, 180 * 64);
+ gdk_draw_arc (colorsel->wheel_area->window, style->mid_gc[GTK_STATE_NORMAL],
+ FALSE, 0, 0, w, h, 30 * 64, 180 * 64);
+
+ gdk_draw_arc (colorsel->wheel_area->window, style->bg_gc[GTK_STATE_NORMAL],
+ FALSE, 1, 1, w - 1, h - 1, 210 * 64, 180 * 64);
+ gdk_draw_arc (colorsel->wheel_area->window, style->light_gc[GTK_STATE_NORMAL],
+ FALSE, 0, 0, w, h, 210 * 64, 180 * 64);
+}
+
+static void
+gtk_color_selection_draw_wheel (GtkColorSelection *colorsel,
+ gint resize)
+{
+ gint x, y, i, wid, heig, n;
+ gdouble cx, cy, h, s, c[3];
+ guchar bg[3];
+ GtkStyle *style = gtk_widget_get_style (GTK_WIDGET (colorsel));
+
+ wid = colorsel->wheel_area->allocation.width;
+ heig = colorsel->wheel_area->allocation.height;
+
+ if (resize)
+ {
+ if (colorsel->wheel_buf != NULL)
+ g_free (colorsel->wheel_buf);
+
+ colorsel->wheel_buf = g_new(guchar, 3 * wid);
+ }
+
+ cx = (gdouble) (wid) / 2.0;
+ cy = (gdouble) (heig) / 2.0;
+
+ bg[0] = style->bg[GTK_STATE_NORMAL].red >> 8;
+ bg[1] = style->bg[GTK_STATE_NORMAL].green >> 8;
+ bg[2] = style->bg[GTK_STATE_NORMAL].blue >> 8;
+
+ for (y = 0; y < heig; y++)
+ {
+ i = 0;
+ for (x = 0; x < wid; x++)
+ {
+ if (gtk_color_selection_eval_wheel (x, y, cx, cy, &h, &s) == TRUE)
+ {
+ for (n = 0; n < 3; n++)
+ colorsel->wheel_buf[i++] = bg[n];
+ }
+ else
+ {
+ gtk_color_selection_hsv_to_rgb (h, s, 1.0, &c[0], &c[1], &c[2]);
+ for (n = 0; n < 3; n++)
+ colorsel->wheel_buf[i++] = (guchar) (255.0 * c[n]);
+ }
+ }
+
+ gtk_preview_draw_row (GTK_PREVIEW (colorsel->wheel_area), colorsel->wheel_buf, 0, y, wid);
+ }
+
+ gtk_widget_draw (colorsel->wheel_area, NULL);
+}
+
+static void
+gtk_color_selection_draw_sample (GtkColorSelection *colorsel,
+ gint resize)
+{
+ gint x, y, i, wid, heig, f, half, n;
+ guchar c[3 * 2], cc[3 * 4], *cp = c;
+ gdouble o, oldo;
+
+ wid = colorsel->sample_area->allocation.width;
+ heig = colorsel->sample_area->allocation.height;
+ half = wid >> 1;
+
+ if (resize)
+ {
+ if (colorsel->sample_buf != NULL)
+ g_free (colorsel->sample_buf);
+
+ colorsel->sample_buf = g_new(guchar, 3 * wid);
+ }
+
+ i = RED;
+ for (n = 0; n < 3; n++)
+ {
+ c[n] = (guchar) (255.0 * colorsel->old_values[i]);
+ c[n + 3] = (guchar) (255.0 * colorsel->values[i++]);
+ }
+
+ if (colorsel->use_opacity == TRUE)
+ {
+ o = colorsel->values[OPACITY];
+ oldo = colorsel->old_values[OPACITY];
+
+ for (n = 0; n < 3; n++)
+ {
+ cc[n] = (guchar) ((1.0 - oldo) * 192 + (oldo * (gdouble) c[n]));
+ cc[n + 3] = (guchar) ((1.0 - oldo) * 128 + (oldo * (gdouble) c[n]));
+ cc[n + 6] = (guchar) ((1.0 - o) * 192 + (o * (gdouble) c[n + 3]));
+ cc[n + 9] = (guchar) ((1.0 - o) * 128 + (o * (gdouble) c[n + 3]));
+ }
+ cp = cc;
+ }
+
+ for (y = 0; y < heig; y++)
+ {
+ i = 0;
+ for (x = 0; x < wid; x++)
+ {
+ if (colorsel->use_opacity)
+ {
+ f = 3 * (((x % 32) < 16) ^ ((y % 32) < 16));
+ f += (x > half) * 6;
+ }
+ else
+ f = (x > half) * 3;
+
+ for (n = 0; n < 3; n++)
+ colorsel->sample_buf[i++] = cp[n + f];
+ }
+
+ gtk_preview_draw_row (GTK_PREVIEW (colorsel->sample_area), colorsel->sample_buf, 0, y, wid);
+ }
+
+ gtk_widget_draw (colorsel->sample_area, NULL);
+}
+
+static gint
+gtk_color_selection_eval_wheel (gint x, gint y,
+ gdouble cx, gdouble cy,
+ gdouble *h, gdouble *s)
+{
+ gdouble d, r, rx, ry, l;
+
+ rx = (gdouble) x - cx;
+ ry = (gdouble) y - cy;
+
+ d = (SQR (cy) * SQR (rx) + SQR (cx) * SQR (ry) - SQR (cx) * SQR (cy));
+
+ r = sqrt (SQR (rx) + SQR (ry));
+
+ if (r != 0.0)
+ *h = atan2 (rx / r, ry / r);
+ else
+ *h = 0.0;
+
+ l = sqrt (SQR ((cx * cos (*h + 0.5 * M_PI))) + SQR ((cy * sin (*h + 0.5 * M_PI))));
+ *s = r / l;
+ *h = 360.0 * (*h) / (2.0 * M_PI) + 180;
+
+ if (*s == 0.0)
+ *s = 0.00001;
+ else if (*s > 1.0)
+ *s = 1.0;
+
+ return ((d > 0.0));
+}
+
+static void
+gtk_color_selection_hsv_to_rgb (gdouble h, gdouble s, gdouble v,
+ gdouble *r, gdouble *g, gdouble *b)
+{
+ gint i;
+ gdouble f, w, q, t;
+
+ if (s == 0.0)
+ s = 0.000001;
+
+ if (h == -1.0)
+ {
+ *r = v;
+ *g = v;
+ *b = v;
+ }
+ else
+ {
+ if (h == 360.0)
+ h = 0.0;
+ h = h / 60.0;
+ i = (gint) h;
+ f = h - i;
+ w = v * (1.0 - s);
+ q = v * (1.0 - (s * f));
+ t = v * (1.0 - (s * (1.0 - f)));
+
+ switch (i)
+ {
+ case 0:
+ *r = v;
+ *g = t;
+ *b = w;
+ break;
+ case 1:
+ *r = q;
+ *g = v;
+ *b = w;
+ break;
+ case 2:
+ *r = w;
+ *g = v;
+ *b = t;
+ break;
+ case 3:
+ *r = w;
+ *g = q;
+ *b = v;
+ break;
+ case 4:
+ *r = t;
+ *g = w;
+ *b = v;
+ break;
+ case 5:
+ *r = v;
+ *g = w;
+ *b = q;
+ break;
+ }
+ }
+}
+
+static void
+gtk_color_selection_rgb_to_hsv (gdouble r, gdouble g, gdouble b,
+ gdouble *h, gdouble *s, gdouble *v)
+{
+ double max, min, delta;
+
+ max = r;
+ if (g > max)
+ max = g;
+ if (b > max)
+ max = b;
+
+ min = r;
+ if (g < min)
+ min = g;
+ if (b < min)
+ min = b;
+
+ *v = max;
+
+ if (max != 0.0)
+ *s = (max - min) / max;
+ else
+ *s = 0.0;
+
+ if (*s == 0.0)
+ *h = -1.0;
+ else
+ {
+ delta = max - min;
+
+ if (r == max)
+ *h = (g - b) / delta;
+ else if (g == max)
+ *h = 2.0 + (b - r) / delta;
+ else if (b == max)
+ *h = 4.0 + (r - g) / delta;
+
+ *h = *h * 60.0;
+
+ if (*h < 0.0)
+ *h = *h + 360;
+ }
+}
+
+/***************************/
+/* GtkColorSelectionDialog */
+/***************************/
+
+guint
+gtk_color_selection_dialog_get_type ()
+{
+ static guint color_selection_dialog_type = 0;
+
+ if (!color_selection_dialog_type)
+ {
+ GtkTypeInfo colorsel_diag_info =
+ {
+ "color selection dialog",
+ sizeof (GtkColorSelectionDialog),
+ sizeof (GtkColorSelectionDialogClass),
+ (GtkClassInitFunc) gtk_color_selection_dialog_class_init,
+ (GtkObjectInitFunc) gtk_color_selection_dialog_init,
+ };
+
+ color_selection_dialog_type = gtk_type_unique (gtk_window_get_type (), &colorsel_diag_info);
+ }
+
+ return color_selection_dialog_type;
+}
+
+void
+gtk_color_selection_dialog_class_init (GtkColorSelectionDialogClass *class)
+{
+ GtkObjectClass *object_class;
+
+ object_class = (GtkObjectClass*) class;
+
+ color_selection_dialog_parent_class = gtk_type_class (gtk_window_get_type ());
+
+ object_class->destroy = gtk_color_selection_dialog_destroy;
+}
+
+void
+gtk_color_selection_dialog_init (GtkColorSelectionDialog *colorseldiag)
+{
+ GtkWidget *action_area, *frame;
+
+ colorseldiag->main_vbox = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (colorseldiag), 10);
+ gtk_container_add (GTK_CONTAINER (colorseldiag), colorseldiag->main_vbox);
+ gtk_widget_show (colorseldiag->main_vbox);
+
+ frame = gtk_frame_new (NULL);
+ gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
+ gtk_container_add (GTK_CONTAINER (colorseldiag->main_vbox), frame);
+ gtk_widget_show (frame);
+
+ colorseldiag->colorsel = gtk_color_selection_new ();
+ gtk_container_add (GTK_CONTAINER (frame), colorseldiag->colorsel);
+ gtk_widget_show (colorseldiag->colorsel);
+
+ action_area = gtk_hbox_new (TRUE, 10);
+ gtk_box_pack_end (GTK_BOX (colorseldiag->main_vbox), action_area, FALSE, FALSE, 0);
+ gtk_widget_show (action_area);
+
+ colorseldiag->ok_button = gtk_button_new_with_label ("OK");
+ GTK_WIDGET_SET_FLAGS (colorseldiag->ok_button, GTK_CAN_DEFAULT);
+ gtk_box_pack_start (GTK_BOX (action_area), colorseldiag->ok_button, TRUE, TRUE, 0);
+ gtk_widget_grab_default (colorseldiag->ok_button);
+ gtk_widget_show (colorseldiag->ok_button);
+
+ colorseldiag->cancel_button = gtk_button_new_with_label ("Cancel");
+ GTK_WIDGET_SET_FLAGS (colorseldiag->cancel_button, GTK_CAN_DEFAULT);
+ gtk_box_pack_start (GTK_BOX (action_area), colorseldiag->cancel_button, TRUE, TRUE, 0);
+ gtk_widget_show (colorseldiag->cancel_button);
+
+ colorseldiag->help_button = gtk_button_new_with_label ("Help");
+ GTK_WIDGET_SET_FLAGS (colorseldiag->help_button, GTK_CAN_DEFAULT);
+ gtk_box_pack_start (GTK_BOX (action_area), colorseldiag->help_button, TRUE, TRUE, 0);
+ gtk_widget_show (colorseldiag->help_button);
+}
+
+GtkWidget *
+gtk_color_selection_dialog_new (const gchar *title)
+{
+ GtkColorSelectionDialog *colorseldiag;
+
+ colorseldiag = gtk_type_new (gtk_color_selection_dialog_get_type ());
+ gtk_window_set_title (GTK_WINDOW (colorseldiag), title);
+
+ return GTK_WIDGET (colorseldiag);
+}
+
+static void
+gtk_color_selection_dialog_destroy (GtkObject *object)
+{
+ GtkColorSelectionDialog *colorseldiag;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_COLOR_SELECTION_DIALOG (object));
+
+ colorseldiag = GTK_COLOR_SELECTION_DIALOG (object);
+
+
+ if (GTK_OBJECT_CLASS (color_selection_dialog_parent_class)->destroy)
+ (*GTK_OBJECT_CLASS (color_selection_dialog_parent_class)->destroy) (object);
+}
diff --git a/gtk/gtkcolorsel.h b/gtk/gtkcolorsel.h
new file mode 100644
index 000000000..c29ea64f4
--- /dev/null
+++ b/gtk/gtkcolorsel.h
@@ -0,0 +1,152 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_COLORSEL_H__
+#define __GTK_COLORSEL_H__
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <gdk/gdk.h>
+
+#include "gtkwindow.h"
+#include "gtkvbox.h"
+#include "gtkframe.h"
+#include "gtkpreview.h"
+#include "gtkbutton.h"
+#include "gtkentry.h"
+#include "gtkhbox.h"
+#include "gtklabel.h"
+#include "gtkmain.h"
+#include "gtksignal.h"
+#include "gtkmisc.h"
+#include "gtkrange.h"
+#include "gtkscale.h"
+#include "gtkhscale.h"
+#include "gtktable.h"
+#include "gtkeventbox.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_COLOR_SELECTION(obj) GTK_CHECK_CAST (obj, gtk_color_selection_get_type (), GtkColorSelection)
+#define GTK_COLOR_SELECTION_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_color_selection_get_type (), GtkColorSelectionClass)
+#define GTK_IS_COLOR_SELECTION(obj) GTK_CHECK_TYPE (obj, gtk_color_selection_get_type ())
+
+#define GTK_COLOR_SELECTION_DIALOG(obj) GTK_CHECK_CAST (obj, gtk_color_selection_dialog_get_type (), GtkColorSelectionDialog)
+#define GTK_COLOR_SELECTION_DIALOG_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_color_selection_dialog_get_type (), GtkColorSelectionDialogClass)
+#define GTK_IS_COLOR_SELECTION_DIALOG(obj) GTK_CHECK_TYPE (obj, gtk_color_selection_dialog_get_type ())
+
+
+typedef struct _GtkColorSelection GtkColorSelection;
+typedef struct _GtkColorSelectionClass GtkColorSelectionClass;
+
+typedef struct _GtkColorSelectionDialog GtkColorSelectionDialog;
+typedef struct _GtkColorSelectionDialogClass GtkColorSelectionDialogClass;
+
+
+struct _GtkColorSelection
+{
+ GtkVBox vbox;
+
+ GtkWidget *wheel_area;
+ GtkWidget *value_area;
+ GtkWidget *sample_area, *sample_area_eb;
+
+ GtkWidget *scales[8];
+ GtkWidget *entries[8];
+ GtkWidget *opacity_label;
+
+ GdkGC *wheel_gc;
+ GdkGC *value_gc;
+ GdkGC *sample_gc;
+
+ GtkUpdateType policy;
+ gint use_opacity;
+ gint timer_active;
+ gint timer_tag;
+ gdouble values[8];
+ gdouble old_values[8];
+
+ guchar *wheel_buf;
+ guchar *value_buf;
+ guchar *sample_buf;
+};
+
+struct _GtkColorSelectionClass
+{
+ GtkVBoxClass parent_class;
+
+ void (* color_changed) (GtkColorSelection *colorsel);
+};
+
+struct _GtkColorSelectionDialog
+{
+ GtkWindow window;
+
+ GtkWidget *colorsel;
+ GtkWidget *main_vbox;
+ GtkWidget *ok_button;
+ GtkWidget *reset_button;
+ GtkWidget *cancel_button;
+ GtkWidget *help_button;
+};
+
+struct _GtkColorSelectionDialogClass
+{
+ GtkWindowClass parent_class;
+};
+
+
+/* ColorSelection */
+
+guint gtk_color_selection_get_type (void);
+void gtk_color_selection_class_init (GtkColorSelectionClass *klass);
+void gtk_color_selection_init (GtkColorSelection *colorsel);
+
+GtkWidget* gtk_color_selection_new (void);
+
+void gtk_color_selection_set_update_policy (GtkColorSelection *colorsel,
+ GtkUpdateType policy);
+
+void gtk_color_selection_set_opacity (GtkColorSelection *colorsel,
+ gint use_opacity);
+
+void gtk_color_selection_set_color (GtkColorSelection *colorsel,
+ gdouble *color);
+
+void gtk_color_selection_get_color (GtkColorSelection *colorsel,
+ gdouble *color);
+
+/* ColorSelectionDialog */
+
+guint gtk_color_selection_dialog_get_type (void);
+void gtk_color_selection_dialog_class_init (GtkColorSelectionDialogClass *klass);
+void gtk_color_selection_dialog_init (GtkColorSelectionDialog *colorseldiag);
+
+GtkWidget* gtk_color_selection_dialog_new (const gchar *title);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_COLORSEL_H__ */
diff --git a/gtk/gtkcontainer.c b/gtk/gtkcontainer.c
new file mode 100644
index 000000000..977fabc29
--- /dev/null
+++ b/gtk/gtkcontainer.c
@@ -0,0 +1,844 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <string.h>
+#include "gtkcontainer.h"
+#include "gtksignal.h"
+
+
+enum {
+ ADD,
+ REMOVE,
+ NEED_RESIZE,
+ FOREACH,
+ FOCUS,
+ LAST_SIGNAL
+};
+
+
+typedef void (*GtkContainerSignal1) (GtkObject *object,
+ gpointer arg1,
+ gpointer data);
+typedef void (*GtkContainerSignal2) (GtkObject *object,
+ gpointer arg1,
+ gpointer arg2,
+ gpointer data);
+typedef gint (*GtkContainerSignal3) (GtkObject *object,
+ gint arg1,
+ gpointer data);
+typedef gint (*GtkContainerSignal4) (GtkObject *object,
+ gpointer data);
+
+
+static void gtk_container_marshal_signal_1 (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args);
+static void gtk_container_marshal_signal_2 (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args);
+static void gtk_container_marshal_signal_3 (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args);
+static void gtk_container_marshal_signal_4 (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args);
+
+
+static void gtk_container_class_init (GtkContainerClass *klass);
+static void gtk_container_init (GtkContainer *container);
+static void gtk_container_arg (GtkContainer *container,
+ GtkArg *arg);
+static gint gtk_real_container_need_resize (GtkContainer *container);
+static gint gtk_real_container_focus (GtkContainer *container,
+ GtkDirectionType direction);
+static gint gtk_container_focus_tab (GtkContainer *container,
+ GList *children,
+ GtkDirectionType direction);
+static gint gtk_container_focus_up_down (GtkContainer *container,
+ GList *children,
+ GtkDirectionType direction);
+static gint gtk_container_focus_left_right (GtkContainer *container,
+ GList *children,
+ GtkDirectionType direction);
+static gint gtk_container_focus_move (GtkContainer *container,
+ GList *children,
+ GtkDirectionType direction);
+static void gtk_container_children_callback (GtkWidget *widget,
+ gpointer client_data);
+
+
+static gint container_signals[LAST_SIGNAL] = { 0 };
+
+
+guint
+gtk_container_get_type ()
+{
+ static guint container_type = 0;
+
+ if (!container_type)
+ {
+ GtkTypeInfo container_info =
+ {
+ "GtkContainer",
+ sizeof (GtkContainer),
+ sizeof (GtkContainerClass),
+ (GtkClassInitFunc) gtk_container_class_init,
+ (GtkObjectInitFunc) gtk_container_init,
+ (GtkArgFunc) gtk_container_arg,
+ };
+
+ container_type = gtk_type_unique (gtk_widget_get_type (), &container_info);
+ }
+
+ return container_type;
+}
+
+static void
+gtk_container_class_init (GtkContainerClass *class)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+
+ object_class = (GtkObjectClass*) class;
+ widget_class = (GtkWidgetClass*) class;
+
+ gtk_object_add_arg_type ("GtkContainer::border_width", GTK_TYPE_LONG);
+ gtk_object_add_arg_type ("GtkContainer::auto_resize", GTK_TYPE_BOOL);
+ gtk_object_add_arg_type ("GtkContainer::block_resize", GTK_TYPE_BOOL);
+ gtk_object_add_arg_type ("GtkContainer::child", GTK_TYPE_WIDGET);
+
+ container_signals[ADD] =
+ gtk_signal_new ("add",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkContainerClass, add),
+ gtk_container_marshal_signal_1,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_WIDGET);
+ container_signals[REMOVE] =
+ gtk_signal_new ("remove",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkContainerClass, remove),
+ gtk_container_marshal_signal_1,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_WIDGET);
+ container_signals[NEED_RESIZE] =
+ gtk_signal_new ("need_resize",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkContainerClass, need_resize),
+ gtk_container_marshal_signal_4,
+ GTK_TYPE_BOOL, 0,
+ GTK_TYPE_WIDGET);
+ container_signals[FOREACH] =
+ gtk_signal_new ("foreach",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkContainerClass, foreach),
+ gtk_container_marshal_signal_2,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_C_CALLBACK);
+ container_signals[FOCUS] =
+ gtk_signal_new ("focus",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkContainerClass, focus),
+ gtk_container_marshal_signal_3,
+ GTK_TYPE_DIRECTION_TYPE, 1,
+ GTK_TYPE_DIRECTION_TYPE);
+
+ gtk_object_class_add_signals (object_class, container_signals, LAST_SIGNAL);
+
+ class->need_resize = gtk_real_container_need_resize;
+ class->focus = gtk_real_container_focus;
+}
+
+static void
+gtk_container_init (GtkContainer *container)
+{
+ container->focus_child = NULL;
+ container->border_width = 0;
+ container->auto_resize = TRUE;
+ container->need_resize = FALSE;
+ container->block_resize = FALSE;
+}
+
+static void
+gtk_container_arg (GtkContainer *container,
+ GtkArg *arg)
+{
+ if (strcmp (arg->name, "border_width") == 0)
+ {
+ gtk_container_border_width (container, GTK_VALUE_LONG (*arg));
+ }
+ else if (strcmp (arg->name, "auto_resize") == 0)
+ {
+ if (GTK_VALUE_BOOL (*arg))
+ gtk_container_enable_resize (container);
+ else
+ gtk_container_disable_resize (container);
+ }
+ else if (strcmp (arg->name, "block_resize") == 0)
+ {
+ if (GTK_VALUE_BOOL (*arg))
+ gtk_container_block_resize (container);
+ else
+ gtk_container_unblock_resize (container);
+ }
+ else if (strcmp (arg->name, "child") == 0)
+ {
+ gtk_container_add (container, GTK_WIDGET (GTK_VALUE_OBJECT (*arg)));
+ }
+}
+
+void
+gtk_container_border_width (GtkContainer *container,
+ gint border_width)
+{
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_CONTAINER (container));
+
+ if (container->border_width != border_width)
+ {
+ container->border_width = border_width;
+
+ if (container->widget.parent && GTK_WIDGET_VISIBLE (container))
+ gtk_container_need_resize (GTK_CONTAINER (container->widget.parent));
+ }
+}
+
+void
+gtk_container_add (GtkContainer *container,
+ GtkWidget *widget)
+{
+ gtk_signal_emit (GTK_OBJECT (container), container_signals[ADD], widget);
+}
+
+void
+gtk_container_remove (GtkContainer *container,
+ GtkWidget *widget)
+{
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_CONTAINER (container));
+
+ if (container->focus_child == widget)
+ container->focus_child = NULL;
+
+ gtk_signal_emit (GTK_OBJECT (container), container_signals[REMOVE], widget);
+}
+
+void
+gtk_container_disable_resize (GtkContainer *container)
+{
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_CONTAINER (container));
+
+ container->auto_resize = FALSE;
+}
+
+void
+gtk_container_enable_resize (GtkContainer *container)
+{
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_CONTAINER (container));
+
+ container->auto_resize = TRUE;
+ if (container->need_resize)
+ {
+ container->need_resize = FALSE;
+ gtk_widget_queue_resize (GTK_WIDGET (container));
+ }
+}
+
+void
+gtk_container_block_resize (GtkContainer *container)
+{
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_CONTAINER (container));
+
+ container->block_resize = TRUE;
+}
+
+void
+gtk_container_unblock_resize (GtkContainer *container)
+{
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_CONTAINER (container));
+
+ container->block_resize = FALSE;
+}
+
+gint
+gtk_container_need_resize (GtkContainer *container)
+{
+ gint return_val;
+
+ g_return_val_if_fail (container != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_CONTAINER (container), FALSE);
+
+ return_val = FALSE;
+
+ if (!container->block_resize)
+ {
+ if (container->auto_resize)
+ gtk_signal_emit (GTK_OBJECT (container),
+ container_signals[NEED_RESIZE],
+ &return_val);
+ else
+ container->need_resize = TRUE;
+ }
+
+ return return_val;
+}
+
+void
+gtk_container_foreach (GtkContainer *container,
+ GtkCallback callback,
+ gpointer callback_data)
+{
+ gtk_signal_emit (GTK_OBJECT (container),
+ container_signals[FOREACH],
+ callback, callback_data);
+}
+
+gint
+gtk_container_focus (GtkContainer *container,
+ GtkDirectionType direction)
+{
+ gint return_val;
+
+ gtk_signal_emit (GTK_OBJECT (container),
+ container_signals[FOCUS],
+ direction, &return_val);
+
+ return return_val;
+}
+
+GList*
+gtk_container_children (GtkContainer *container)
+{
+ GList *children;
+
+ children = NULL;
+
+ gtk_container_foreach (container,
+ gtk_container_children_callback,
+ &children);
+
+ return g_list_reverse (children);
+}
+
+
+static void
+gtk_container_marshal_signal_1 (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args)
+{
+ GtkContainerSignal1 rfunc;
+
+ rfunc = (GtkContainerSignal1) func;
+
+ (* rfunc) (object, GTK_VALUE_OBJECT (args[0]), func_data);
+}
+
+static void
+gtk_container_marshal_signal_2 (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args)
+{
+ GtkContainerSignal2 rfunc;
+
+ rfunc = (GtkContainerSignal2) func;
+
+ (* rfunc) (object,
+ GTK_VALUE_C_CALLBACK(args[0]).func,
+ GTK_VALUE_C_CALLBACK(args[0]).func_data,
+ func_data);
+}
+
+static void
+gtk_container_marshal_signal_3 (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args)
+{
+ GtkContainerSignal3 rfunc;
+ gint *return_val;
+
+ rfunc = (GtkContainerSignal3) func;
+ return_val = GTK_RETLOC_ENUM (args[1]);
+
+ *return_val = (* rfunc) (object, GTK_VALUE_ENUM(args[0]), func_data);
+}
+
+static void
+gtk_container_marshal_signal_4 (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args)
+{
+ GtkContainerSignal4 rfunc;
+ gint *return_val;
+
+ rfunc = (GtkContainerSignal4) func;
+ return_val = GTK_RETLOC_BOOL (args[0]);
+
+ *return_val = (* rfunc) (object, func_data);
+}
+
+static gint
+gtk_real_container_need_resize (GtkContainer *container)
+{
+ g_return_val_if_fail (container != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_CONTAINER (container), FALSE);
+
+ if (GTK_WIDGET_VISIBLE (container) && container->widget.parent)
+ return gtk_container_need_resize (GTK_CONTAINER (container->widget.parent));
+
+ return FALSE;
+}
+
+static gint
+gtk_real_container_focus (GtkContainer *container,
+ GtkDirectionType direction)
+{
+ GList *children;
+ GList *tmp_list;
+ GList *tmp_list2;
+ gint return_val;
+
+ g_return_val_if_fail (container != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_CONTAINER (container), FALSE);
+
+ /* Fail if the container is insensitive
+ */
+ if (!GTK_WIDGET_SENSITIVE (container))
+ return FALSE;
+
+ return_val = FALSE;
+
+ if (GTK_WIDGET_CAN_FOCUS (container))
+ {
+ gtk_widget_grab_focus (GTK_WIDGET (container));
+ return_val = TRUE;
+ }
+ else
+ {
+ /* Get a list of the containers children
+ */
+ children = gtk_container_children (container);
+
+ if (children)
+ {
+ /* Remove any children which are insensitive
+ */
+ tmp_list = children;
+ while (tmp_list)
+ {
+ if (!GTK_WIDGET_SENSITIVE (tmp_list->data))
+ {
+ tmp_list2 = tmp_list;
+ tmp_list = tmp_list->next;
+
+ children = g_list_remove_link (children, tmp_list2);
+ g_list_free_1 (tmp_list2);
+ }
+ else
+ tmp_list = tmp_list->next;
+ }
+
+ switch (direction)
+ {
+ case GTK_DIR_TAB_FORWARD:
+ case GTK_DIR_TAB_BACKWARD:
+ return_val = gtk_container_focus_tab (container, children, direction);
+ break;
+ case GTK_DIR_UP:
+ case GTK_DIR_DOWN:
+ return_val = gtk_container_focus_up_down (container, children, direction);
+ break;
+ case GTK_DIR_LEFT:
+ case GTK_DIR_RIGHT:
+ return_val = gtk_container_focus_left_right (container, children, direction);
+ break;
+ }
+
+ g_list_free (children);
+ }
+ }
+
+ return return_val;
+}
+
+static gint
+gtk_container_focus_tab (GtkContainer *container,
+ GList *children,
+ GtkDirectionType direction)
+{
+ GtkWidget *child;
+ GtkWidget *child2;
+ GList *tmp_list;
+ gint length;
+ gint i, j;
+
+ length = g_list_length (children);
+
+ /* sort the children in the y direction */
+ for (i = 1; i < length; i++)
+ {
+ j = i;
+ tmp_list = g_list_nth (children, j);
+ child = tmp_list->data;
+
+ while (j > 0)
+ {
+ child2 = tmp_list->prev->data;
+ if (child->allocation.y < child2->allocation.y)
+ {
+ tmp_list->data = tmp_list->prev->data;
+ tmp_list = tmp_list->prev;
+ j--;
+ }
+ else
+ break;
+ }
+
+ tmp_list->data = child;
+ }
+
+ /* sort the children in the x direction while
+ * maintaining the y direction sort.
+ */
+ for (i = 1; i < length; i++)
+ {
+ j = i;
+ tmp_list = g_list_nth (children, j);
+ child = tmp_list->data;
+
+ while (j > 0)
+ {
+ child2 = tmp_list->prev->data;
+ if ((child->allocation.x < child2->allocation.x) &&
+ (child->allocation.y >= child2->allocation.y))
+ {
+ tmp_list->data = tmp_list->prev->data;
+ tmp_list = tmp_list->prev;
+ j--;
+ }
+ else
+ break;
+ }
+
+ tmp_list->data = child;
+ }
+
+ /* if we are going backwards then reverse the order
+ * of the children.
+ */
+ if (direction == GTK_DIR_TAB_BACKWARD)
+ children = g_list_reverse (children);
+
+ return gtk_container_focus_move (container, children, direction);
+}
+
+static gint
+gtk_container_focus_up_down (GtkContainer *container,
+ GList *children,
+ GtkDirectionType direction)
+{
+ GtkWidget *child;
+ GtkWidget *child2;
+ GList *tmp_list;
+ gint dist1, dist2;
+ gint focus_x;
+ gint focus_width;
+ gint length;
+ gint i, j;
+
+ /* return failure if there isn't a focus child */
+ if (container->focus_child)
+ {
+ focus_width = container->focus_child->allocation.width / 2;
+ focus_x = container->focus_child->allocation.x + focus_width;
+ }
+ else
+ {
+ focus_width = GTK_WIDGET (container)->allocation.width;
+ if (GTK_WIDGET_NO_WINDOW (container))
+ focus_x = GTK_WIDGET (container)->allocation.x;
+ else
+ focus_x = 0;
+ }
+
+ length = g_list_length (children);
+
+ /* sort the children in the y direction */
+ for (i = 1; i < length; i++)
+ {
+ j = i;
+ tmp_list = g_list_nth (children, j);
+ child = tmp_list->data;
+
+ while (j > 0)
+ {
+ child2 = tmp_list->prev->data;
+ if (child->allocation.y < child2->allocation.y)
+ {
+ tmp_list->data = tmp_list->prev->data;
+ tmp_list = tmp_list->prev;
+ j--;
+ }
+ else
+ break;
+ }
+
+ tmp_list->data = child;
+ }
+
+ /* sort the children in distance in the x direction
+ * in distance from the current focus child while maintaining the
+ * sort in the y direction
+ */
+ for (i = 1; i < length; i++)
+ {
+ j = i;
+ tmp_list = g_list_nth (children, j);
+ child = tmp_list->data;
+ dist1 = (child->allocation.x + child->allocation.width / 2) - focus_x;
+
+ while (j > 0)
+ {
+ child2 = tmp_list->prev->data;
+ dist2 = (child2->allocation.x + child2->allocation.width / 2) - focus_x;
+
+ if ((dist1 < dist2) &&
+ (child->allocation.y >= child2->allocation.y))
+ {
+ tmp_list->data = tmp_list->prev->data;
+ tmp_list = tmp_list->prev;
+ j--;
+ }
+ else
+ break;
+ }
+
+ tmp_list->data = child;
+ }
+
+ /* go and invalidate any widget which is too
+ * far from the focus widget.
+ */
+ if (!container->focus_child &&
+ (direction == GTK_DIR_UP))
+ focus_x += focus_width;
+
+ tmp_list = children;
+ while (tmp_list)
+ {
+ child = tmp_list->data;
+
+ dist1 = (child->allocation.x + child->allocation.width / 2) - focus_x;
+ if (((direction == GTK_DIR_DOWN) && (dist1 < 0)) ||
+ ((direction == GTK_DIR_UP) && (dist1 > 0)))
+ tmp_list->data = NULL;
+
+ tmp_list = tmp_list->next;
+ }
+
+ if (direction == GTK_DIR_UP)
+ children = g_list_reverse (children);
+
+ return gtk_container_focus_move (container, children, direction);
+}
+
+static gint
+gtk_container_focus_left_right (GtkContainer *container,
+ GList *children,
+ GtkDirectionType direction)
+{
+ GtkWidget *child;
+ GtkWidget *child2;
+ GList *tmp_list;
+ gint dist1, dist2;
+ gint focus_y;
+ gint focus_height;
+ gint length;
+ gint i, j;
+
+ /* return failure if there isn't a focus child */
+ if (container->focus_child)
+ {
+ focus_height = container->focus_child->allocation.height / 2;
+ focus_y = container->focus_child->allocation.y + focus_height;
+ }
+ else
+ {
+ focus_height = GTK_WIDGET (container)->allocation.height;
+ if (GTK_WIDGET_NO_WINDOW (container))
+ focus_y = GTK_WIDGET (container)->allocation.y;
+ else
+ focus_y = 0;
+ }
+
+ length = g_list_length (children);
+
+ /* sort the children in the x direction */
+ for (i = 1; i < length; i++)
+ {
+ j = i;
+ tmp_list = g_list_nth (children, j);
+ child = tmp_list->data;
+
+ while (j > 0)
+ {
+ child2 = tmp_list->prev->data;
+ if (child->allocation.x < child2->allocation.x)
+ {
+ tmp_list->data = tmp_list->prev->data;
+ tmp_list = tmp_list->prev;
+ j--;
+ }
+ else
+ break;
+ }
+
+ tmp_list->data = child;
+ }
+
+ /* sort the children in distance in the y direction
+ * in distance from the current focus child while maintaining the
+ * sort in the x direction
+ */
+ for (i = 1; i < length; i++)
+ {
+ j = i;
+ tmp_list = g_list_nth (children, j);
+ child = tmp_list->data;
+ dist1 = (child->allocation.y + child->allocation.height / 2) - focus_y;
+
+ while (j > 0)
+ {
+ child2 = tmp_list->prev->data;
+ dist2 = (child2->allocation.y + child2->allocation.height / 2) - focus_y;
+
+ if ((dist1 < dist2) &&
+ (child->allocation.x >= child2->allocation.x))
+ {
+ tmp_list->data = tmp_list->prev->data;
+ tmp_list = tmp_list->prev;
+ j--;
+ }
+ else
+ break;
+ }
+
+ tmp_list->data = child;
+ }
+
+ /* go and invalidate any widget which is too
+ * far from the focus widget.
+ */
+ if (!container->focus_child &&
+ (direction == GTK_DIR_LEFT))
+ focus_y += focus_height;
+
+ tmp_list = children;
+ while (tmp_list)
+ {
+ child = tmp_list->data;
+
+ dist1 = (child->allocation.y + child->allocation.height / 2) - focus_y;
+ if (((direction == GTK_DIR_RIGHT) && (dist1 < 0)) ||
+ ((direction == GTK_DIR_LEFT) && (dist1 > 0)))
+ tmp_list->data = NULL;
+
+ tmp_list = tmp_list->next;
+ }
+
+ if (direction == GTK_DIR_LEFT)
+ children = g_list_reverse (children);
+
+ return gtk_container_focus_move (container, children, direction);
+}
+
+static gint
+gtk_container_focus_move (GtkContainer *container,
+ GList *children,
+ GtkDirectionType direction)
+{
+ GtkWidget *focus_child;
+ GtkWidget *child;
+
+ focus_child = container->focus_child;
+ container->focus_child = NULL;
+
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (!child)
+ continue;
+
+ if (focus_child)
+ {
+ if (focus_child == child)
+ {
+ focus_child = NULL;
+
+ if (GTK_WIDGET_VISIBLE (child) &&
+ GTK_IS_CONTAINER (child) &&
+ !GTK_WIDGET_HAS_FOCUS (child))
+ if (gtk_container_focus (GTK_CONTAINER (child), direction))
+ return TRUE;
+ }
+ }
+ else if (GTK_WIDGET_VISIBLE (child))
+ {
+ if (GTK_WIDGET_CAN_FOCUS (child))
+ {
+ gtk_widget_grab_focus (child);
+ return TRUE;
+ }
+ else if (GTK_IS_CONTAINER (child))
+ {
+ if (gtk_container_focus (GTK_CONTAINER (child), direction))
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+
+static void
+gtk_container_children_callback (GtkWidget *widget,
+ gpointer client_data)
+{
+ GList **children;
+
+ children = (GList**) client_data;
+ *children = g_list_prepend (*children, widget);
+}
diff --git a/gtk/gtkcontainer.h b/gtk/gtkcontainer.h
new file mode 100644
index 000000000..80c1ce033
--- /dev/null
+++ b/gtk/gtkcontainer.h
@@ -0,0 +1,95 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_CONTAINER_H__
+#define __GTK_CONTAINER_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkenums.h>
+#include <gtk/gtkwidget.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_CONTAINER(obj) GTK_CHECK_CAST (obj, gtk_container_get_type (), GtkContainer)
+#define GTK_CONTAINER_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_container_get_type, GtkContainerClass)
+#define GTK_IS_CONTAINER(obj) GTK_CHECK_TYPE (obj, gtk_container_get_type ())
+
+#define GTK_TYPE_CONTAINER (gtk_container_get_type ())
+
+typedef struct _GtkContainer GtkContainer;
+typedef struct _GtkContainerClass GtkContainerClass;
+
+struct _GtkContainer
+{
+ GtkWidget widget;
+
+ GtkWidget *focus_child;
+ gint16 border_width;
+ guint auto_resize : 1;
+ guint need_resize : 1;
+ guint block_resize : 1;
+};
+
+struct _GtkContainerClass
+{
+ GtkWidgetClass parent_class;
+
+ void (* add) (GtkContainer *container,
+ GtkWidget *widget);
+ void (* remove) (GtkContainer *container,
+ GtkWidget *widget);
+ gint (* need_resize) (GtkContainer *container);
+ void (* foreach) (GtkContainer *container,
+ GtkCallback callback,
+ gpointer callbabck_data);
+ gint (* focus) (GtkContainer *container,
+ GtkDirectionType direction);
+};
+
+
+
+guint gtk_container_get_type (void);
+void gtk_container_border_width (GtkContainer *container,
+ gint border_width);
+void gtk_container_add (GtkContainer *container,
+ GtkWidget *widget);
+void gtk_container_remove (GtkContainer *container,
+ GtkWidget *widget);
+void gtk_container_disable_resize (GtkContainer *container);
+void gtk_container_enable_resize (GtkContainer *container);
+void gtk_container_block_resize (GtkContainer *container);
+void gtk_container_unblock_resize (GtkContainer *container);
+gint gtk_container_need_resize (GtkContainer *container);
+void gtk_container_foreach (GtkContainer *container,
+ GtkCallback callback,
+ gpointer callback_data);
+gint gtk_container_focus (GtkContainer *container,
+ GtkDirectionType direction);
+GList* gtk_container_children (GtkContainer *container);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_CONTAINER_H__ */
diff --git a/gtk/gtkcurve.c b/gtk/gtkcurve.c
new file mode 100644
index 000000000..d2b6e08c8
--- /dev/null
+++ b/gtk/gtkcurve.c
@@ -0,0 +1,860 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1997 David Mosberger
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <string.h>
+#include <math.h>
+
+#include "gtkcurve.h"
+#include "gtkdrawingarea.h"
+#include "gtkmain.h"
+#include "gtkradiobutton.h"
+#include "gtksignal.h"
+#include "gtktable.h"
+
+#define BOUNDS(a,x,y) (((a) < (x)) ? (x) : (((a) > (y)) ? (y) : (a)))
+#define RADIUS 3 /* radius of the control points */
+#define MIN_DISTANCE 8 /* min distance between control points */
+
+#define GRAPH_MASK (GDK_EXPOSURE_MASK | \
+ GDK_POINTER_MOTION_MASK | \
+ GDK_POINTER_MOTION_HINT_MASK | \
+ GDK_ENTER_NOTIFY_MASK | \
+ GDK_BUTTON_PRESS_MASK | \
+ GDK_BUTTON_RELEASE_MASK | \
+ GDK_BUTTON1_MOTION_MASK)
+
+static GtkDrawingAreaClass *parent_class = NULL;
+static gint curve_type_changed_signal = 0;
+
+
+/* forward declarations: */
+static void gtk_curve_class_init (GtkCurveClass *class);
+static void gtk_curve_init (GtkCurve *curve);
+static void gtk_curve_destroy (GtkObject *object);
+
+
+guint
+gtk_curve_get_type (void)
+{
+ static guint curve_type = 0;
+
+ if (!curve_type)
+ {
+ GtkTypeInfo curve_info =
+ {
+ "GtkCurve",
+ sizeof (GtkCurve),
+ sizeof (GtkCurveClass),
+ (GtkClassInitFunc) gtk_curve_class_init,
+ (GtkObjectInitFunc) gtk_curve_init,
+ (GtkArgFunc) NULL,
+ };
+
+ curve_type = gtk_type_unique (gtk_drawing_area_get_type (), &curve_info);
+ }
+ return curve_type;
+}
+
+static void
+gtk_curve_class_init (GtkCurveClass *class)
+{
+ GtkObjectClass *object_class;
+
+ parent_class = gtk_type_class (gtk_drawing_area_get_type ());
+
+ object_class = (GtkObjectClass *) class;
+
+ curve_type_changed_signal =
+ gtk_signal_new ("curve_type_changed", GTK_RUN_FIRST, object_class->type,
+ GTK_SIGNAL_OFFSET (GtkCurveClass, curve_type_changed),
+ gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
+ gtk_object_class_add_signals (object_class, &curve_type_changed_signal, 1);
+
+ object_class->destroy = gtk_curve_destroy;
+}
+
+static void
+gtk_curve_init (GtkCurve *curve)
+{
+ curve->cursor_type = GDK_TOP_LEFT_ARROW;
+ curve->pixmap = NULL;
+ curve->curve_type = GTK_CURVE_TYPE_SPLINE;
+ curve->height = 0;
+ curve->grab_point = -1;
+
+ curve->num_points = 0;
+ curve->point = 0;
+
+ curve->num_ctlpoints = 0;
+ curve->ctlpoint = NULL;
+}
+
+static int
+project (gfloat value, gfloat min, gfloat max, int norm)
+{
+ return (norm - 1) * ((value - min) / (max - min)) + 0.5;
+}
+
+static gfloat
+unproject (gint value, gfloat min, gfloat max, int norm)
+{
+ return value / (gfloat) (norm - 1) * (max - min) + min;
+}
+
+/* Solve the tridiagonal equation system that determines the second
+ derivatives for the interpolation points. (Based on Numerical
+ Recipies 2nd Edition.) */
+static void
+spline_solve (int n, gfloat x[], gfloat y[], gfloat y2[])
+{
+ gfloat p, sig, *u;
+ gint i, k;
+
+ u = g_malloc ((n - 1) * sizeof (u[0]));
+
+ y2[0] = u[0] = 0.0; /* set lower boundary condition to "natural" */
+
+ for (i = 1; i < n - 1; ++i)
+ {
+ sig = (x[i] - x[i - 1]) / (x[i + 1] - x[i - 1]);
+ p = sig * y2[i - 1] + 2.0;
+ y2[i] = (sig - 1.0) / p;
+ u[i] = ((y[i + 1] - y[i])
+ / (x[i + 1] - x[i]) - (y[i] - y[i - 1]) / (x[i] - x[i - 1]));
+ u[i] = (6.0 * u[i] / (x[i + 1] - x[i - 1]) - sig * u[i - 1]) / p;
+ }
+
+ y2[n - 1] = 0.0;
+ for (k = n - 2; k >= 0; --k)
+ y2[k] = y2[k] * y2[k + 1] + u[k];
+
+ g_free (u);
+}
+
+static gfloat
+spline_eval (int n, gfloat x[], gfloat y[], gfloat y2[], gfloat val)
+{
+ gint k_lo, k_hi, k;
+ gfloat h, b, a;
+
+ /* do a binary search for the right interval: */
+ k_lo = 0; k_hi = n - 1;
+ while (k_hi - k_lo > 1)
+ {
+ k = (k_hi + k_lo) / 2;
+ if (x[k] > val)
+ k_hi = k;
+ else
+ k_lo = k;
+ }
+
+ h = x[k_hi] - x[k_lo];
+ g_assert (h > 0.0);
+
+ a = (x[k_hi] - val) / h;
+ b = (val - x[k_lo]) / h;
+ return a*y[k_lo] + b*y[k_hi] +
+ ((a*a*a - a)*y2[k_lo] + (b*b*b - b)*y2[k_hi]) * (h*h)/6.0;
+}
+
+static void
+gtk_curve_interpolate (GtkCurve *c, gint width, gint height)
+{
+ gfloat *vector;
+ int i;
+
+ vector = g_malloc (width * sizeof (vector[0]));
+
+ gtk_curve_get_vector (c, width, vector);
+
+ c->height = height;
+ if (c->num_points != width)
+ {
+ c->num_points = width;
+ if (c->point)
+ g_free (c->point);
+ c->point = g_malloc (c->num_points * sizeof (c->point[0]));
+ }
+
+ for (i = 0; i < width; ++i)
+ {
+ c->point[i].x = RADIUS + i;
+ c->point[i].y = RADIUS + height
+ - project (vector[i], c->min_y, c->max_y, height);
+ }
+}
+
+static void
+gtk_curve_draw (GtkCurve *c, gint width, gint height)
+{
+ GtkStateType state;
+ GtkStyle *style;
+ gint i;
+
+ if (!c->pixmap)
+ return;
+
+ if (c->height != height || c->num_points != width)
+ gtk_curve_interpolate (c, width, height);
+
+ state = GTK_STATE_NORMAL;
+ if (!GTK_WIDGET_IS_SENSITIVE (GTK_WIDGET (c)))
+ state = GTK_STATE_INSENSITIVE;
+
+ style = GTK_WIDGET (c)->style;
+
+ /* clear the pixmap: */
+ gdk_draw_rectangle (c->pixmap, style->bg_gc[state], TRUE,
+ 0, 0, width + RADIUS * 2, height + RADIUS * 2);
+
+ /* draw the grid lines: (XXX make more meaningful) */
+ for (i = 0; i < 5; i++)
+ {
+ gdk_draw_line (c->pixmap, style->dark_gc[state],
+ RADIUS, i * (height / 4.0) + RADIUS,
+ width + RADIUS, i * (height / 4.0) + RADIUS);
+ gdk_draw_line (c->pixmap, style->dark_gc[state],
+ i * (width / 4.0) + RADIUS, RADIUS,
+ i * (width / 4.0) + RADIUS, height + RADIUS);
+ }
+
+ gdk_draw_points (c->pixmap, style->fg_gc[state], c->point, c->num_points);
+ if (c->curve_type != GTK_CURVE_TYPE_FREE)
+ for (i = 0; i < c->num_ctlpoints; ++i)
+ {
+ gint x, y;
+
+ if (c->ctlpoint[i][0] < c->min_x)
+ continue;
+
+ x = project (c->ctlpoint[i][0], c->min_x, c->max_x,
+ width);
+ y = height -
+ project (c->ctlpoint[i][1], c->min_y, c->max_y,
+ height);
+
+ /* draw a bullet: */
+ gdk_draw_arc (c->pixmap, style->fg_gc[state], TRUE, x, y,
+ RADIUS * 2, RADIUS*2, 0, 360*64);
+ }
+ gdk_draw_pixmap (GTK_WIDGET (c)->window, style->fg_gc[state], c->pixmap,
+ 0, 0, 0, 0, width + RADIUS * 2, height + RADIUS * 2);
+}
+
+static gint
+gtk_curve_graph_events (GtkWidget *widget, GdkEvent *event, GtkCurve *c)
+{
+ GdkCursorType new_type = c->cursor_type;
+ gint i, src, dst, leftbound, rightbound;
+ GdkEventButton *bevent;
+ GdkEventMotion *mevent;
+ GtkWidget *w;
+ gint tx, ty;
+ gint cx, x, y, width, height;
+ gint closest_point = 0;
+ gfloat rx, ry, min_x;
+ guint distance;
+ gint x1, x2, y1, y2;
+
+ w = GTK_WIDGET (c);
+ width = w->allocation.width - RADIUS * 2;
+ height = w->allocation.height - RADIUS * 2;
+
+ /* get the pointer position */
+ gdk_window_get_pointer (w->window, &tx, &ty, NULL);
+ x = BOUNDS ((tx - RADIUS), 0, width);
+ y = BOUNDS ((ty - RADIUS), 0, height);
+
+ min_x = c->min_x;
+
+ distance = ~0U;
+ for (i = 0; i < c->num_ctlpoints; ++i)
+ {
+ cx = project (c->ctlpoint[i][0], min_x, c->max_x, width);
+ if ((guint) abs (x - cx) < distance)
+ {
+ distance = abs (x - cx);
+ closest_point = i;
+ }
+ }
+
+ switch (event->type)
+ {
+ case GDK_CONFIGURE:
+ if (c->pixmap)
+ gdk_pixmap_destroy (c->pixmap);
+ c->pixmap = 0;
+ /* fall through */
+ case GDK_EXPOSE:
+ if (!c->pixmap)
+ c->pixmap = gdk_pixmap_new (w->window,
+ w->allocation.width,
+ w->allocation.height, -1);
+ gtk_curve_draw (c, width, height);
+ break;
+
+ case GDK_BUTTON_PRESS:
+ gtk_grab_add (widget);
+
+ bevent = (GdkEventButton *) event;
+ new_type = GDK_TCROSS;
+
+ switch (c->curve_type)
+ {
+ case GTK_CURVE_TYPE_LINEAR:
+ case GTK_CURVE_TYPE_SPLINE:
+ if (distance > MIN_DISTANCE)
+ {
+ /* insert a new control point */
+ if (c->num_ctlpoints > 0)
+ {
+ cx = project (c->ctlpoint[closest_point][0], min_x,
+ c->max_x, width);
+ if (x > cx)
+ ++closest_point;
+ }
+ ++c->num_ctlpoints;
+ c->ctlpoint =
+ g_realloc (c->ctlpoint,
+ c->num_ctlpoints * sizeof (*c->ctlpoint));
+ for (i = c->num_ctlpoints - 1; i > closest_point; --i)
+ memcpy (c->ctlpoint + i, c->ctlpoint + i - 1,
+ sizeof (*c->ctlpoint));
+ }
+ c->grab_point = closest_point;
+ c->ctlpoint[c->grab_point][0] =
+ unproject (x, min_x, c->max_x, width);
+ c->ctlpoint[c->grab_point][1] =
+ unproject (height - y, c->min_y, c->max_y, height);
+
+ gtk_curve_interpolate (c, width, height);
+ break;
+
+ case GTK_CURVE_TYPE_FREE:
+ c->point[x].x = RADIUS + x;
+ c->point[x].y = RADIUS + y;
+ c->grab_point = x;
+ c->last = y;
+ break;
+ }
+ gtk_curve_draw (c, width, height);
+ break;
+
+ case GDK_BUTTON_RELEASE:
+ gtk_grab_remove (widget);
+
+ /* delete inactive points: */
+ if (c->curve_type != GTK_CURVE_TYPE_FREE)
+ {
+ for (src = dst = 0; src < c->num_ctlpoints; ++src)
+ {
+ if (c->ctlpoint[src][0] >= min_x)
+ {
+ memcpy (c->ctlpoint + dst, c->ctlpoint + src,
+ sizeof (*c->ctlpoint));
+ ++dst;
+ }
+ }
+ if (dst < src)
+ {
+ c->num_ctlpoints -= (src - dst);
+ if (c->num_ctlpoints <= 0)
+ {
+ c->num_ctlpoints = 1;
+ c->ctlpoint[0][0] = min_x;
+ c->ctlpoint[0][1] = c->min_y;
+ gtk_curve_interpolate (c, width, height);
+ gtk_curve_draw (c, width, height);
+ }
+ c->ctlpoint =
+ g_realloc (c->ctlpoint,
+ c->num_ctlpoints * sizeof (*c->ctlpoint));
+ }
+ }
+ new_type = GDK_FLEUR;
+ c->grab_point = -1;
+ break;
+
+ case GDK_MOTION_NOTIFY:
+ mevent = (GdkEventMotion *) event;
+ if (mevent->is_hint)
+ {
+ mevent->x = tx;
+ mevent->y = ty;
+ }
+ switch (c->curve_type)
+ {
+ case GTK_CURVE_TYPE_LINEAR:
+ case GTK_CURVE_TYPE_SPLINE:
+ if (c->grab_point == -1)
+ {
+ /* if no point is grabbed... */
+ if (distance <= MIN_DISTANCE)
+ new_type = GDK_FLEUR;
+ else
+ new_type = GDK_TCROSS;
+ }
+ else
+ {
+ /* drag the grabbed point */
+ new_type = GDK_TCROSS;
+
+ leftbound = -MIN_DISTANCE;
+ if (c->grab_point > 0)
+ leftbound = project (c->ctlpoint[c->grab_point - 1][0],
+ min_x, c->max_x, width);
+
+ rightbound = width + RADIUS * 2 + MIN_DISTANCE;
+ if (c->grab_point + 1 < c->num_ctlpoints)
+ rightbound = project (c->ctlpoint[c->grab_point + 1][0],
+ min_x, c->max_x, width);
+
+ if (tx <= leftbound || tx >= rightbound
+ || ty > height + RADIUS * 2 + MIN_DISTANCE
+ || ty < -MIN_DISTANCE)
+ c->ctlpoint[c->grab_point][0] = min_x - 1.0;
+ else
+ {
+ rx = unproject (x, min_x, c->max_x, width);
+ ry = unproject (height - y, c->min_y, c->max_y, height);
+ c->ctlpoint[c->grab_point][0] = rx;
+ c->ctlpoint[c->grab_point][1] = ry;
+ }
+ gtk_curve_interpolate (c, width, height);
+ gtk_curve_draw (c, width, height);
+ }
+ break;
+
+ case GTK_CURVE_TYPE_FREE:
+ if (c->grab_point != -1)
+ {
+ if (c->grab_point > x)
+ {
+ x1 = x;
+ x2 = c->grab_point;
+ y1 = y;
+ y2 = c->last;
+ }
+ else
+ {
+ x1 = c->grab_point;
+ x2 = x;
+ y1 = c->last;
+ y2 = y;
+ }
+
+ if (x2 != x1)
+ for (i = x1; i <= x2; i++)
+ {
+ c->point[i].x = RADIUS + i;
+ c->point[i].y = RADIUS +
+ (y1 + ((y2 - y1) * (i - x1)) / (x2 - x1));
+ }
+ else
+ {
+ c->point[x].x = RADIUS + x;
+ c->point[x].y = RADIUS + y;
+ }
+ c->grab_point = x;
+ c->last = y;
+ gtk_curve_draw (c, width, height);
+ }
+ if (mevent->state & GDK_BUTTON1_MASK)
+ new_type = GDK_TCROSS;
+ else
+ new_type = GDK_PENCIL;
+ break;
+ }
+ if (new_type != (GdkCursorType) c->cursor_type)
+ {
+ GdkCursor *cursor;
+
+ c->cursor_type = new_type;
+
+ cursor = gdk_cursor_new (c->cursor_type);
+ gdk_window_set_cursor (w->window, cursor);
+ gdk_cursor_destroy (cursor);
+ }
+ break;
+
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+void
+gtk_curve_set_curve_type (GtkCurve *c, GtkCurveType new_type)
+{
+ gfloat rx, dx;
+ gint x, i;
+
+ if (new_type != c->curve_type)
+ {
+ gint width, height;
+
+ width = GTK_WIDGET(c)->allocation.width - RADIUS * 2;
+ height = GTK_WIDGET(c)->allocation.height - RADIUS * 2;
+
+ if (new_type == GTK_CURVE_TYPE_FREE)
+ {
+ gtk_curve_interpolate (c, width, height);
+ c->curve_type = new_type;
+ }
+ else if (c->curve_type == GTK_CURVE_TYPE_FREE)
+ {
+ if (c->ctlpoint)
+ g_free (c->ctlpoint);
+ c->num_ctlpoints = 9;
+ c->ctlpoint = g_malloc (c->num_ctlpoints * sizeof (*c->ctlpoint));
+
+ rx = 0.0;
+ dx = (width - 1) / (gfloat) (c->num_ctlpoints - 1);
+
+ for (i = 0; i < c->num_ctlpoints; ++i, rx += dx)
+ {
+ x = (int) (rx + 0.5);
+ c->ctlpoint[i][0] =
+ unproject (x, c->min_x, c->max_x, width);
+ c->ctlpoint[i][1] =
+ unproject (RADIUS + height - c->point[x].y,
+ c->min_y, c->max_y, height);
+ }
+ c->curve_type = new_type;
+ gtk_curve_interpolate (c, width, height);
+ }
+ else
+ {
+ c->curve_type = new_type;
+ gtk_curve_interpolate (c, width, height);
+ }
+ gtk_signal_emit (GTK_OBJECT (c), curve_type_changed_signal);
+ gtk_curve_draw (c, width, height);
+ }
+}
+
+static void
+gtk_curve_size_graph (GtkCurve *curve)
+{
+ gint width, height;
+ gfloat aspect;
+
+ width = (curve->max_x - curve->min_x) + 1;
+ height = (curve->max_y - curve->min_y) + 1;
+ aspect = width / (gfloat) height;
+ if (width > gdk_screen_width () / 4)
+ width = gdk_screen_width () / 4;
+ if (height > gdk_screen_height () / 4)
+ height = gdk_screen_height () / 4;
+
+ if (aspect < 1.0)
+ width = height * aspect;
+ else
+ height = width / aspect;
+
+ gtk_drawing_area_size (GTK_DRAWING_AREA (curve),
+ width + RADIUS * 2, height + RADIUS * 2);
+}
+
+static void
+gtk_curve_reset_vector (GtkCurve *curve)
+{
+ if (curve->ctlpoint)
+ g_free (curve->ctlpoint);
+
+ curve->num_ctlpoints = 2;
+ curve->ctlpoint = g_malloc (2 * sizeof (curve->ctlpoint[0]));
+ curve->ctlpoint[0][0] = curve->min_x;
+ curve->ctlpoint[0][1] = curve->min_y;
+ curve->ctlpoint[1][0] = curve->max_x;
+ curve->ctlpoint[1][1] = curve->max_y;
+
+ if (curve->pixmap)
+ {
+ gint width, height;
+
+ width = GTK_WIDGET (curve)->allocation.width - RADIUS * 2;
+ height = GTK_WIDGET (curve)->allocation.height - RADIUS * 2;
+
+ if (curve->curve_type == GTK_CURVE_TYPE_FREE)
+ {
+ curve->curve_type = GTK_CURVE_TYPE_LINEAR;
+ gtk_curve_interpolate (curve, width, height);
+ curve->curve_type = GTK_CURVE_TYPE_FREE;
+ }
+ else
+ gtk_curve_interpolate (curve, width, height);
+ gtk_curve_draw (curve, width, height);
+ }
+}
+
+void
+gtk_curve_reset (GtkCurve *c)
+{
+ GtkCurveType old_type;
+
+ old_type = c->curve_type;
+ c->curve_type = GTK_CURVE_TYPE_SPLINE;
+ gtk_curve_reset_vector (c);
+
+ if (old_type != GTK_CURVE_TYPE_SPLINE)
+ gtk_signal_emit (GTK_OBJECT (c), curve_type_changed_signal);
+}
+
+void
+gtk_curve_set_gamma (GtkCurve *c, gfloat gamma)
+{
+ gfloat x, one_over_gamma, height, one_over_width;
+ GtkCurveType old_type;
+ gint i;
+
+ if (c->num_points < 2)
+ return;
+
+ old_type = c->curve_type;
+ c->curve_type = GTK_CURVE_TYPE_FREE;
+
+ if (gamma <= 0)
+ one_over_gamma = 1.0;
+ else
+ one_over_gamma = 1.0 / gamma;
+ one_over_width = 1.0 / (c->num_points - 1);
+ height = c->height;
+ for (i = 0; i < c->num_points; ++i)
+ {
+ x = (gfloat) i / (c->num_points - 1);
+ c->point[i].x = RADIUS + i;
+ c->point[i].y =
+ RADIUS + (height * (1.0 - pow (x, one_over_gamma)) + 0.5);
+ }
+
+ if (old_type != GTK_CURVE_TYPE_FREE)
+ gtk_signal_emit (GTK_OBJECT (c), curve_type_changed_signal);
+
+ gtk_curve_draw (c, c->num_points, c->height);
+}
+
+void
+gtk_curve_set_range (GtkCurve *curve,
+ gfloat min_x, gfloat max_x, gfloat min_y, gfloat max_y)
+{
+ curve->min_x = min_x;
+ curve->max_x = max_x;
+ curve->min_y = min_y;
+ curve->max_y = max_y;
+
+ gtk_curve_size_graph (curve);
+ gtk_curve_reset_vector (curve);
+}
+
+void
+gtk_curve_set_vector (GtkCurve *c, int veclen, gfloat vector[])
+{
+ GtkCurveType old_type;
+ gfloat rx, dx, ry;
+ gint i, height;
+
+ old_type = c->curve_type;
+ c->curve_type = GTK_CURVE_TYPE_FREE;
+
+ if (c->point)
+ height = GTK_WIDGET (c)->allocation.height - RADIUS * 2;
+ else
+ {
+ height = (c->max_y - c->min_y);
+ if (height > gdk_screen_height () / 4)
+ height = gdk_screen_height () / 4;
+
+ c->height = height;
+ c->num_points = veclen;
+ c->point = g_malloc (c->num_points * sizeof (c->point[0]));
+ }
+ rx = 0;
+ dx = (veclen - 1.0) / (c->num_points - 1.0);
+
+ for (i = 0; i < c->num_points; ++i, rx += dx)
+ {
+ ry = vector[(int) (rx + 0.5)];
+ if (ry > c->max_y) ry = c->max_y;
+ if (ry < c->min_y) ry = c->min_y;
+ c->point[i].x = RADIUS + i;
+ c->point[i].y =
+ RADIUS + height - project (ry, c->min_y, c->max_y, height);
+ }
+ if (old_type != GTK_CURVE_TYPE_FREE)
+ gtk_signal_emit (GTK_OBJECT (c), curve_type_changed_signal);
+
+ gtk_curve_draw (c, c->num_points, height);
+}
+
+void
+gtk_curve_get_vector (GtkCurve *c, int veclen, gfloat vector[])
+{
+ gfloat rx, ry, dx, dy, min_x, delta_x, *mem, *xv, *yv, *y2v, prev;
+ gint dst, i, x, next, num_active_ctlpoints = 0, first_active = -1;
+
+ min_x = c->min_x;
+
+ if (c->curve_type != GTK_CURVE_TYPE_FREE)
+ {
+ /* count active points: */
+ prev = min_x - 1.0;
+ for (i = num_active_ctlpoints = 0; i < c->num_ctlpoints; ++i)
+ if (c->ctlpoint[i][0] > prev)
+ {
+ if (first_active < 0)
+ first_active = i;
+ prev = c->ctlpoint[i][0];
+ ++num_active_ctlpoints;
+ }
+
+ /* handle degenerate case: */
+ if (num_active_ctlpoints < 2)
+ {
+ if (num_active_ctlpoints > 0)
+ ry = c->ctlpoint[first_active][1];
+ else
+ ry = c->min_y;
+ if (ry < c->min_y) ry = c->min_y;
+ if (ry > c->max_y) ry = c->max_y;
+ for (x = 0; x < veclen; ++x)
+ vector[x] = ry;
+ return;
+ }
+ }
+
+ switch (c->curve_type)
+ {
+ case GTK_CURVE_TYPE_SPLINE:
+ mem = g_malloc (3 * num_active_ctlpoints * sizeof (gfloat));
+ xv = mem;
+ yv = mem + num_active_ctlpoints;
+ y2v = mem + 2*num_active_ctlpoints;
+
+ prev = min_x - 1.0;
+ for (i = dst = 0; i < c->num_ctlpoints; ++i)
+ if (c->ctlpoint[i][0] > prev)
+ {
+ prev = c->ctlpoint[i][0];
+ xv[dst] = c->ctlpoint[i][0];
+ yv[dst] = c->ctlpoint[i][1];
+ ++dst;
+ }
+
+ spline_solve (num_active_ctlpoints, xv, yv, y2v);
+
+ rx = min_x;
+ dx = (c->max_x - min_x) / (veclen - 1);
+ for (x = 0; x < veclen; ++x, rx += dx)
+ {
+ ry = spline_eval (num_active_ctlpoints, xv, yv, y2v, rx);
+ if (ry < c->min_y) ry = c->min_y;
+ if (ry > c->max_y) ry = c->max_y;
+ vector[x] = ry;
+ }
+
+ g_free (mem);
+ break;
+
+ case GTK_CURVE_TYPE_LINEAR:
+ dx = (c->max_x - min_x) / (veclen - 1);
+ rx = min_x;
+ ry = c->min_y;
+ dy = 0.0;
+ i = first_active;
+ for (x = 0; x < veclen; ++x, rx += dx)
+ {
+ if (rx >= c->ctlpoint[i][0])
+ {
+ if (rx > c->ctlpoint[i][0])
+ ry = c->min_y;
+ dy = 0.0;
+ next = i + 1;
+ while (next < c->num_ctlpoints
+ && c->ctlpoint[next][0] <= c->ctlpoint[i][0])
+ ++next;
+ if (next < c->num_ctlpoints)
+ {
+ delta_x = c->ctlpoint[next][0] - c->ctlpoint[i][0];
+ dy = ((c->ctlpoint[next][1] - c->ctlpoint[i][1])
+ / delta_x);
+ dy *= dx;
+ ry = c->ctlpoint[i][1];
+ i = next;
+ }
+ }
+ vector[x] = ry;
+ ry += dy;
+ }
+ break;
+
+ case GTK_CURVE_TYPE_FREE:
+ if (c->point)
+ {
+ rx = 0.0;
+ dx = c->num_points / (double) veclen;
+ for (x = 0; x < veclen; ++x, rx += dx)
+ vector[x] = unproject (RADIUS + c->height - c->point[(int) rx].y,
+ c->min_y, c->max_y,
+ c->height);
+ }
+ else
+ memset (vector, 0, veclen * sizeof (vector[0]));
+ break;
+ }
+}
+
+GtkWidget*
+gtk_curve_new (void)
+{
+ GtkCurve *curve;
+ gint old_mask;
+
+ curve = gtk_type_new (gtk_curve_get_type ());
+ curve->min_x = 0.0;
+ curve->max_x = 1.0;
+ curve->min_y = 0.0;
+ curve->max_y = 1.0;
+
+ old_mask = gtk_widget_get_events (GTK_WIDGET (curve));
+ gtk_widget_set_events (GTK_WIDGET (curve), old_mask | GRAPH_MASK);
+ gtk_signal_connect (GTK_OBJECT (curve), "event",
+ (GtkSignalFunc) gtk_curve_graph_events, curve);
+ gtk_curve_size_graph (curve);
+
+ return GTK_WIDGET (curve);
+}
+
+static void
+gtk_curve_destroy (GtkObject *object)
+{
+ GtkCurve *curve;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_CURVE (object));
+
+ curve = GTK_CURVE (object);
+ if (curve->pixmap)
+ gdk_pixmap_destroy (curve->pixmap);
+ if (curve->point)
+ g_free (curve->point);
+ if (curve->ctlpoint)
+ g_free (curve->ctlpoint);
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
diff --git a/gtk/gtkcurve.h b/gtk/gtkcurve.h
new file mode 100644
index 000000000..0e1568bc7
--- /dev/null
+++ b/gtk/gtkcurve.h
@@ -0,0 +1,96 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_CURVE_H__
+#define __GTK_CURVE_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkdrawingarea.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_CURVE(obj) GTK_CHECK_CAST (obj, gtk_curve_get_type (), GtkCurve)
+#define GTK_CURVE_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_curve_get_type, GtkCurveClass)
+#define GTK_IS_CURVE(obj) GTK_CHECK_TYPE (obj, gtk_curve_get_type ())
+
+
+typedef struct _GtkCurve GtkCurve;
+typedef struct _GtkCurveClass GtkCurveClass;
+
+typedef enum
+{
+ GTK_CURVE_TYPE_LINEAR, /* linear interpolation */
+ GTK_CURVE_TYPE_SPLINE, /* spline interpolation */
+ GTK_CURVE_TYPE_FREE /* free form curve */
+} GtkCurveType;
+
+struct _GtkCurve
+{
+ GtkDrawingArea graph;
+
+ gint cursor_type;
+ gfloat min_x;
+ gfloat max_x;
+ gfloat min_y;
+ gfloat max_y;
+ GdkPixmap *pixmap;
+ GtkCurveType curve_type;
+ gint height; /* (cached) graph height in pixels */
+ gint grab_point; /* point currently grabbed */
+ gint last;
+
+ /* (cached) curve points: */
+ gint num_points;
+ GdkPoint *point;
+
+ /* control points: */
+ gint num_ctlpoints; /* number of control points */
+ gfloat (*ctlpoint)[2]; /* array of control points */
+};
+
+struct _GtkCurveClass
+{
+ GtkDrawingAreaClass parent_class;
+
+ void (* curve_type_changed) (GtkCurve *curve);
+};
+
+
+guint gtk_curve_get_type (void);
+GtkWidget* gtk_curve_new (void);
+void gtk_curve_reset (GtkCurve *curve);
+void gtk_curve_set_gamma (GtkCurve *curve, gfloat gamma);
+void gtk_curve_set_range (GtkCurve *curve,
+ gfloat min_x, gfloat max_x,
+ gfloat min_y, gfloat max_y);
+void gtk_curve_get_vector (GtkCurve *curve,
+ int veclen, gfloat vector[]);
+void gtk_curve_set_vector (GtkCurve *curve,
+ int veclen, gfloat vector[]);
+void gtk_curve_set_curve_type (GtkCurve *curve, GtkCurveType type);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_CURVE_H__ */
diff --git a/gtk/gtkdata.c b/gtk/gtkdata.c
new file mode 100644
index 000000000..63add29f3
--- /dev/null
+++ b/gtk/gtkdata.c
@@ -0,0 +1,73 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtkdata.h"
+#include "gtksignal.h"
+
+
+enum {
+ DISCONNECT,
+ LAST_SIGNAL
+};
+
+
+static void gtk_data_class_init (GtkDataClass *klass);
+
+
+static gint data_signals[LAST_SIGNAL] = { 0 };
+
+
+guint
+gtk_data_get_type ()
+{
+ static guint data_type = 0;
+
+ if (!data_type)
+ {
+ GtkTypeInfo data_info =
+ {
+ "GtkData",
+ sizeof (GtkData),
+ sizeof (GtkDataClass),
+ (GtkClassInitFunc) gtk_data_class_init,
+ (GtkObjectInitFunc) NULL,
+ (GtkArgFunc) NULL,
+ };
+
+ data_type = gtk_type_unique (gtk_object_get_type (), &data_info);
+ }
+
+ return data_type;
+}
+
+static void
+gtk_data_class_init (GtkDataClass *class)
+{
+ GtkObjectClass *object_class;
+
+ object_class = (GtkObjectClass*) class;
+
+ data_signals[DISCONNECT] =
+ gtk_signal_new ("disconnect",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkDataClass, disconnect),
+ gtk_signal_default_marshaller,
+ GTK_TYPE_NONE, 0);
+
+ gtk_object_class_add_signals (object_class, data_signals, LAST_SIGNAL);
+}
diff --git a/gtk/gtkdata.h b/gtk/gtkdata.h
new file mode 100644
index 000000000..2e9d30b31
--- /dev/null
+++ b/gtk/gtkdata.h
@@ -0,0 +1,60 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_DATA_H__
+#define __GTK_DATA_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkobject.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_DATA(obj) GTK_CHECK_CAST (obj, gtk_data_get_type (), GtkData)
+#define GTK_DATA_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_data_get_type (), GtkDataClass)
+#define GTK_IS_DATA(obj) GTK_CHECK_TYPE (obj, gtk_data_get_type ())
+
+
+typedef struct _GtkData GtkData;
+typedef struct _GtkDataClass GtkDataClass;
+
+struct _GtkData
+{
+ GtkObject object;
+};
+
+struct _GtkDataClass
+{
+ GtkObjectClass parent_class;
+
+ void (* disconnect) (GtkData *data);
+};
+
+
+guint gtk_data_get_type (void);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_DATA_H__ */
diff --git a/gtk/gtkdialog.c b/gtk/gtkdialog.c
new file mode 100644
index 000000000..55da2d137
--- /dev/null
+++ b/gtk/gtkdialog.c
@@ -0,0 +1,80 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtkbutton.h"
+#include "gtkdialog.h"
+#include "gtkhbox.h"
+#include "gtkhseparator.h"
+#include "gtkvbox.h"
+
+
+static void gtk_dialog_class_init (GtkDialogClass *klass);
+static void gtk_dialog_init (GtkDialog *dialog);
+
+
+guint
+gtk_dialog_get_type ()
+{
+ static guint dialog_type = 0;
+
+ if (!dialog_type)
+ {
+ GtkTypeInfo dialog_info =
+ {
+ "GtkDialog",
+ sizeof (GtkDialog),
+ sizeof (GtkDialogClass),
+ (GtkClassInitFunc) gtk_dialog_class_init,
+ (GtkObjectInitFunc) gtk_dialog_init,
+ (GtkArgFunc) NULL,
+ };
+
+ dialog_type = gtk_type_unique (gtk_window_get_type (), &dialog_info);
+ }
+
+ return dialog_type;
+}
+
+static void
+gtk_dialog_class_init (GtkDialogClass *class)
+{
+}
+
+static void
+gtk_dialog_init (GtkDialog *dialog)
+{
+ GtkWidget *separator;
+
+ dialog->vbox = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (dialog), dialog->vbox);
+ gtk_widget_show (dialog->vbox);
+
+ dialog->action_area = gtk_hbox_new (TRUE, 5);
+ gtk_container_border_width (GTK_CONTAINER (dialog->action_area), 10);
+ gtk_box_pack_end (GTK_BOX (dialog->vbox), dialog->action_area, FALSE, TRUE, 0);
+ gtk_widget_show (dialog->action_area);
+
+ separator = gtk_hseparator_new ();
+ gtk_box_pack_end (GTK_BOX (dialog->vbox), separator, FALSE, TRUE, 0);
+ gtk_widget_show (separator);
+}
+
+GtkWidget*
+gtk_dialog_new ()
+{
+ return GTK_WIDGET (gtk_type_new (gtk_dialog_get_type ()));
+}
diff --git a/gtk/gtkdialog.h b/gtk/gtkdialog.h
new file mode 100644
index 000000000..139699682
--- /dev/null
+++ b/gtk/gtkdialog.h
@@ -0,0 +1,64 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_DIALOG_H__
+#define __GTK_DIALOG_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkwindow.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_DIALOG(obj) GTK_CHECK_CAST (obj, gtk_dialog_get_type (), GtkDialog)
+#define GTK_DIALOG_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_dialog_get_type (), GtkDialogClass)
+#define GTK_IS_DIALOG(obj) GTK_CHECK_TYPE (obj, gtk_dialog_get_type ())
+
+
+typedef struct _GtkDialog GtkDialog;
+typedef struct _GtkDialogClass GtkDialogClass;
+typedef struct _GtkDialogButton GtkDialogButton;
+
+
+struct _GtkDialog
+{
+ GtkWindow window;
+
+ GtkWidget *vbox;
+ GtkWidget *action_area;
+};
+
+struct _GtkDialogClass
+{
+ GtkWindowClass parent_class;
+};
+
+
+guint gtk_dialog_get_type (void);
+GtkWidget* gtk_dialog_new (void);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_DIALOG_H__ */
diff --git a/gtk/gtkdrawingarea.c b/gtk/gtkdrawingarea.c
new file mode 100644
index 000000000..3220446a5
--- /dev/null
+++ b/gtk/gtkdrawingarea.c
@@ -0,0 +1,146 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtkdrawingarea.h"
+
+
+static void gtk_drawing_area_class_init (GtkDrawingAreaClass *klass);
+static void gtk_drawing_area_init (GtkDrawingArea *darea);
+static void gtk_drawing_area_realize (GtkWidget *widget);
+static void gtk_drawing_area_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+
+
+guint
+gtk_drawing_area_get_type ()
+{
+ static guint drawing_area_type = 0;
+
+ if (!drawing_area_type)
+ {
+ GtkTypeInfo drawing_area_info =
+ {
+ "GtkDrawingArea",
+ sizeof (GtkDrawingArea),
+ sizeof (GtkDrawingAreaClass),
+ (GtkClassInitFunc) gtk_drawing_area_class_init,
+ (GtkObjectInitFunc) gtk_drawing_area_init,
+ (GtkArgFunc) NULL,
+ };
+
+ drawing_area_type = gtk_type_unique (gtk_widget_get_type (), &drawing_area_info);
+ }
+
+ return drawing_area_type;
+}
+
+static void
+gtk_drawing_area_class_init (GtkDrawingAreaClass *class)
+{
+ GtkWidgetClass *widget_class;
+
+ widget_class = (GtkWidgetClass*) class;
+
+ widget_class->realize = gtk_drawing_area_realize;
+ widget_class->size_allocate = gtk_drawing_area_size_allocate;
+}
+
+static void
+gtk_drawing_area_init (GtkDrawingArea *darea)
+{
+ GTK_WIDGET_SET_FLAGS (darea, GTK_BASIC);
+}
+
+
+GtkWidget*
+gtk_drawing_area_new ()
+{
+ return GTK_WIDGET (gtk_type_new (gtk_drawing_area_get_type ()));
+}
+
+void
+gtk_drawing_area_size (GtkDrawingArea *darea,
+ gint width,
+ gint height)
+{
+ g_return_if_fail (darea != NULL);
+ g_return_if_fail (GTK_IS_DRAWING_AREA (darea));
+
+ GTK_WIDGET (darea)->requisition.width = width;
+ GTK_WIDGET (darea)->requisition.height = height;
+}
+
+static void
+gtk_drawing_area_realize (GtkWidget *widget)
+{
+ GtkDrawingArea *darea;
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_DRAWING_AREA (widget));
+
+ darea = GTK_DRAWING_AREA (widget);
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.x = widget->allocation.x;
+ attributes.y = widget->allocation.y;
+ attributes.width = widget->allocation.width;
+ attributes.height = widget->allocation.height;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
+ attributes.event_mask = gtk_widget_get_events (widget);
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+
+ widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
+ gdk_window_set_user_data (widget->window, darea);
+
+ widget->style = gtk_style_attach (widget->style, widget->window);
+ gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
+}
+
+static void
+gtk_drawing_area_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GdkEventConfigure event;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_DRAWING_AREA (widget));
+ g_return_if_fail (allocation != NULL);
+
+ widget->allocation = *allocation;
+
+ if (GTK_WIDGET_REALIZED (widget))
+ {
+ gdk_window_move_resize (widget->window,
+ allocation->x, allocation->y,
+ allocation->width, allocation->height);
+
+ event.type = GDK_CONFIGURE;
+ event.window = widget->window;
+ event.x = allocation->x;
+ event.y = allocation->y;
+ event.width = allocation->width;
+ event.height = allocation->height;
+
+ gtk_widget_event (widget, (GdkEvent*) &event);
+ }
+}
diff --git a/gtk/gtkdrawingarea.h b/gtk/gtkdrawingarea.h
new file mode 100644
index 000000000..d11445b03
--- /dev/null
+++ b/gtk/gtkdrawingarea.h
@@ -0,0 +1,62 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_DRAWING_AREA_H__
+#define __GTK_DRAWING_AREA_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkwidget.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_DRAWING_AREA(obj) GTK_CHECK_CAST (obj, gtk_drawing_area_get_type (), GtkDrawingArea)
+#define GTK_DRAWING_AREA_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_drawing_area_get_type (), GtkDrawingAreaClass)
+#define GTK_IS_DRAWING_AREA(obj) GTK_CHECK_TYPE (obj, gtk_drawing_area_get_type ())
+
+
+typedef struct _GtkDrawingArea GtkDrawingArea;
+typedef struct _GtkDrawingAreaClass GtkDrawingAreaClass;
+
+struct _GtkDrawingArea
+{
+ GtkWidget widget;
+};
+
+struct _GtkDrawingAreaClass
+{
+ GtkWidgetClass parent_class;
+};
+
+
+guint gtk_drawing_area_get_type (void);
+GtkWidget* gtk_drawing_area_new (void);
+void gtk_drawing_area_size (GtkDrawingArea *darea,
+ gint width,
+ gint height);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_DRAWING_AREA_H__ */
diff --git a/gtk/gtkentry.c b/gtk/gtkentry.c
new file mode 100644
index 000000000..b9c25f63a
--- /dev/null
+++ b/gtk/gtkentry.c
@@ -0,0 +1,1678 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <ctype.h>
+#include <string.h>
+#include "gdk/gdkkeysyms.h"
+#include "gtkentry.h"
+#include "gtkmain.h"
+#include "gtkselection.h"
+#include "gtksignal.h"
+
+#define MIN_ENTRY_WIDTH 150
+#define DRAW_TIMEOUT 20
+#define INNER_BORDER 2
+
+
+enum {
+ INSERT_TEXT,
+ DELETE_TEXT,
+ CHANGED,
+ SET_TEXT,
+ ACTIVATE,
+ LAST_SIGNAL
+};
+
+
+typedef void (*GtkTextFunction) (GtkEntry *entry);
+typedef void (*GtkEntrySignal1) (GtkObject *object,
+ gpointer arg1,
+ gint arg2,
+ gpointer arg3,
+ gpointer data);
+typedef void (*GtkEntrySignal2) (GtkObject *object,
+ gint arg1,
+ gint arg2,
+ gpointer data);
+
+
+static void gtk_entry_marshal_signal_1 (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args);
+static void gtk_entry_marshal_signal_2 (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args);
+
+static void gtk_entry_class_init (GtkEntryClass *klass);
+static void gtk_entry_init (GtkEntry *entry);
+static void gtk_entry_destroy (GtkObject *object);
+static void gtk_entry_realize (GtkWidget *widget);
+static void gtk_entry_unrealize (GtkWidget *widget);
+static void gtk_entry_draw_focus (GtkWidget *widget);
+static void gtk_entry_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void gtk_entry_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static void gtk_entry_draw (GtkWidget *widget,
+ GdkRectangle *area);
+static gint gtk_entry_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+static gint gtk_entry_button_press (GtkWidget *widget,
+ GdkEventButton *event);
+static gint gtk_entry_button_release (GtkWidget *widget,
+ GdkEventButton *event);
+static gint gtk_entry_motion_notify (GtkWidget *widget,
+ GdkEventMotion *event);
+static gint gtk_entry_key_press (GtkWidget *widget,
+ GdkEventKey *event);
+static gint gtk_entry_focus_in (GtkWidget *widget,
+ GdkEventFocus *event);
+static gint gtk_entry_focus_out (GtkWidget *widget,
+ GdkEventFocus *event);
+static gint gtk_entry_selection_clear (GtkWidget *widget,
+ GdkEventSelection *event);
+static void gtk_entry_selection_handler (GtkWidget *widget,
+ GtkSelectionData *selection_data,
+ gpointer data);
+static void gtk_entry_selection_received (GtkWidget *widget,
+ GtkSelectionData *selection_data);
+static void gtk_entry_draw_text (GtkEntry *entry);
+static void gtk_entry_draw_cursor (GtkEntry *entry);
+static void gtk_entry_queue_draw (GtkEntry *entry);
+static gint gtk_entry_timer (gpointer data);
+static gint gtk_entry_position (GtkEntry *entry,
+ gint x);
+ void gtk_entry_adjust_scroll (GtkEntry *entry);
+static void gtk_entry_grow_text (GtkEntry *entry);
+static void gtk_entry_insert_text (GtkEntry *entry,
+ const gchar *new_text,
+ gint new_text_length,
+ gint *position);
+static void gtk_entry_delete_text (GtkEntry *entry,
+ gint start_pos,
+ gint end_pos);
+static void gtk_real_entry_insert_text (GtkEntry *entry,
+ const gchar *new_text,
+ gint new_text_length,
+ gint *position);
+static void gtk_real_entry_delete_text (GtkEntry *entry,
+ gint start_pos,
+ gint end_pos);
+
+static void gtk_move_forward_character (GtkEntry *entry);
+static void gtk_move_backward_character (GtkEntry *entry);
+static void gtk_move_forward_word (GtkEntry *entry);
+static void gtk_move_backward_word (GtkEntry *entry);
+static void gtk_move_beginning_of_line (GtkEntry *entry);
+static void gtk_move_end_of_line (GtkEntry *entry);
+static void gtk_delete_forward_character (GtkEntry *entry);
+static void gtk_delete_backward_character (GtkEntry *entry);
+static void gtk_delete_forward_word (GtkEntry *entry);
+static void gtk_delete_backward_word (GtkEntry *entry);
+static void gtk_delete_line (GtkEntry *entry);
+static void gtk_delete_to_line_end (GtkEntry *entry);
+static void gtk_delete_selection (GtkEntry *entry);
+static void gtk_select_word (GtkEntry *entry);
+static void gtk_select_line (GtkEntry *entry);
+static void gtk_select_region (GtkEntry *entry,
+ gint start,
+ gint end);
+
+
+static GtkWidgetClass *parent_class = NULL;
+static gint entry_signals[LAST_SIGNAL] = { 0 };
+
+static GtkTextFunction control_keys[26] =
+{
+ gtk_move_beginning_of_line, /* a */
+ gtk_move_backward_character, /* b */
+ NULL, /* c */
+ gtk_delete_forward_character, /* d */
+ gtk_move_end_of_line, /* e */
+ gtk_move_forward_character, /* f */
+ NULL, /* g */
+ NULL, /* h */
+ NULL, /* i */
+ NULL, /* j */
+ gtk_delete_to_line_end, /* k */
+ NULL, /* l */
+ NULL, /* m */
+ NULL, /* n */
+ NULL, /* o */
+ NULL, /* p */
+ NULL, /* q */
+ NULL, /* r */
+ NULL, /* s */
+ NULL, /* t */
+ gtk_delete_line, /* u */
+ NULL, /* v */
+ gtk_delete_backward_word, /* w */
+ NULL, /* x */
+ NULL, /* y */
+ NULL, /* z */
+};
+
+static GtkTextFunction alt_keys[26] =
+{
+ NULL, /* a */
+ gtk_move_backward_word, /* b */
+ NULL, /* c */
+ gtk_delete_forward_word, /* d */
+ NULL, /* e */
+ gtk_move_forward_word, /* f */
+ NULL, /* g */
+ NULL, /* h */
+ NULL, /* i */
+ NULL, /* j */
+ NULL, /* k */
+ NULL, /* l */
+ NULL, /* m */
+ NULL, /* n */
+ NULL, /* o */
+ NULL, /* p */
+ NULL, /* q */
+ NULL, /* r */
+ NULL, /* s */
+ NULL, /* t */
+ NULL, /* u */
+ NULL, /* v */
+ NULL, /* w */
+ NULL, /* x */
+ NULL, /* y */
+ NULL, /* z */
+};
+
+
+guint
+gtk_entry_get_type ()
+{
+ static guint entry_type = 0;
+
+ if (!entry_type)
+ {
+ GtkTypeInfo entry_info =
+ {
+ "GtkEntry",
+ sizeof (GtkEntry),
+ sizeof (GtkEntryClass),
+ (GtkClassInitFunc) gtk_entry_class_init,
+ (GtkObjectInitFunc) gtk_entry_init,
+ (GtkArgFunc) NULL,
+ };
+
+ entry_type = gtk_type_unique (gtk_widget_get_type (), &entry_info);
+ }
+
+ return entry_type;
+}
+
+static void
+gtk_entry_class_init (GtkEntryClass *class)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+
+ object_class = (GtkObjectClass*) class;
+ widget_class = (GtkWidgetClass*) class;
+
+ parent_class = gtk_type_class (gtk_widget_get_type ());
+
+ entry_signals[INSERT_TEXT] =
+ gtk_signal_new ("insert_text",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkEntryClass, insert_text),
+ gtk_entry_marshal_signal_1,
+ GTK_TYPE_NONE, 3,
+ GTK_TYPE_STRING, GTK_TYPE_INT,
+ GTK_TYPE_POINTER);
+ entry_signals[DELETE_TEXT] =
+ gtk_signal_new ("delete_text",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkEntryClass, delete_text),
+ gtk_entry_marshal_signal_2,
+ GTK_TYPE_NONE, 2,
+ GTK_TYPE_INT, GTK_TYPE_INT);
+ entry_signals[CHANGED] =
+ gtk_signal_new ("changed",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkEntryClass, changed),
+ gtk_signal_default_marshaller,
+ GTK_TYPE_NONE, 0);
+ entry_signals[SET_TEXT] =
+ gtk_signal_new ("set_text",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkEntryClass, set_text),
+ gtk_signal_default_marshaller,
+ GTK_TYPE_NONE, 0);
+ entry_signals[ACTIVATE] =
+ gtk_signal_new ("activate",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkEntryClass, activate),
+ gtk_signal_default_marshaller,
+ GTK_TYPE_NONE, 0);
+
+ gtk_object_class_add_signals (object_class, entry_signals, LAST_SIGNAL);
+
+ object_class->destroy = gtk_entry_destroy;
+
+ widget_class->realize = gtk_entry_realize;
+ widget_class->unrealize = gtk_entry_unrealize;
+ widget_class->draw_focus = gtk_entry_draw_focus;
+ widget_class->size_request = gtk_entry_size_request;
+ widget_class->size_allocate = gtk_entry_size_allocate;
+ widget_class->draw = gtk_entry_draw;
+ widget_class->expose_event = gtk_entry_expose;
+ widget_class->button_press_event = gtk_entry_button_press;
+ widget_class->button_release_event = gtk_entry_button_release;
+ widget_class->motion_notify_event = gtk_entry_motion_notify;
+ widget_class->key_press_event = gtk_entry_key_press;
+ widget_class->focus_in_event = gtk_entry_focus_in;
+ widget_class->focus_out_event = gtk_entry_focus_out;
+ widget_class->selection_clear_event = gtk_entry_selection_clear;
+ widget_class->selection_received = gtk_entry_selection_received;
+
+ class->insert_text = gtk_real_entry_insert_text;
+ class->delete_text = gtk_real_entry_delete_text;
+ class->changed = gtk_entry_adjust_scroll;
+ class->set_text = NULL; /* user defined handling */
+ class->activate = NULL; /* user defined handling */
+}
+
+static void
+gtk_entry_init (GtkEntry *entry)
+{
+ static GdkAtom text_atom = GDK_NONE;
+
+ GTK_WIDGET_SET_FLAGS (entry, GTK_CAN_FOCUS);
+
+ entry->text_area = NULL;
+ entry->text = NULL;
+ entry->text_size = 0;
+ entry->text_length = 0;
+ entry->current_pos = 0;
+ entry->selection_start_pos = 0;
+ entry->selection_end_pos = 0;
+ entry->scroll_offset = 0;
+ entry->have_selection = FALSE;
+ entry->timer = 0;
+ entry->visible = 1;
+
+ gtk_selection_add_handler (GTK_WIDGET(entry), GDK_SELECTION_PRIMARY,
+ GDK_TARGET_STRING, gtk_entry_selection_handler,
+ NULL, NULL);
+
+ if (!text_atom)
+ text_atom = gdk_atom_intern ("TEXT", FALSE);
+
+ gtk_selection_add_handler (GTK_WIDGET(entry), GDK_SELECTION_PRIMARY,
+ text_atom,
+ gtk_entry_selection_handler,
+ NULL, NULL);
+}
+
+GtkWidget*
+gtk_entry_new ()
+{
+ return GTK_WIDGET (gtk_type_new (gtk_entry_get_type ()));
+}
+
+void
+gtk_entry_set_text (GtkEntry *entry,
+ const gchar *text)
+{
+ gint tmp_pos;
+
+ g_return_if_fail (entry != NULL);
+ g_return_if_fail (GTK_IS_ENTRY (entry));
+
+ gtk_real_entry_delete_text (entry, 0, entry->text_length);
+
+ tmp_pos = 0;
+ gtk_entry_insert_text (entry, text, strlen (text), &tmp_pos);
+ entry->current_pos = tmp_pos;
+
+ entry->selection_start_pos = 0;
+ entry->selection_end_pos = 0;
+
+ if (GTK_WIDGET_DRAWABLE (entry))
+ gtk_entry_draw_text (entry);
+
+ gtk_signal_emit (GTK_OBJECT (entry), entry_signals[SET_TEXT]);
+}
+
+void
+gtk_entry_append_text (GtkEntry *entry,
+ const gchar *text)
+{
+ gint tmp_pos;
+
+ g_return_if_fail (entry != NULL);
+ g_return_if_fail (GTK_IS_ENTRY (entry));
+
+ tmp_pos = entry->text_length;
+ gtk_entry_insert_text (entry, text, strlen (text), &tmp_pos);
+ entry->current_pos = tmp_pos;
+
+ gtk_signal_emit (GTK_OBJECT (entry), entry_signals[SET_TEXT]);
+}
+
+void
+gtk_entry_prepend_text (GtkEntry *entry,
+ const gchar *text)
+{
+ gint tmp_pos;
+
+ g_return_if_fail (entry != NULL);
+ g_return_if_fail (GTK_IS_ENTRY (entry));
+
+ tmp_pos = 0;
+ gtk_entry_insert_text (entry, text, strlen (text), &tmp_pos);
+ entry->current_pos = tmp_pos;
+
+ gtk_signal_emit (GTK_OBJECT (entry), entry_signals[SET_TEXT]);
+}
+
+void
+gtk_entry_set_position (GtkEntry *entry,
+ gint position)
+{
+ g_return_if_fail (entry != NULL);
+ g_return_if_fail (GTK_IS_ENTRY (entry));
+
+ if ((position == -1) || (position > entry->text_length))
+ entry->current_pos = entry->text_length;
+ else
+ entry->current_pos = position;
+}
+
+void
+gtk_entry_set_visibility (GtkEntry *entry,
+ gint visible)
+{
+ g_return_if_fail (entry != NULL);
+ g_return_if_fail (GTK_IS_ENTRY (entry));
+
+ entry->visible = visible;
+}
+
+gchar*
+gtk_entry_get_text (GtkEntry *entry)
+{
+ static char empty_str[2] = "";
+
+ g_return_val_if_fail (entry != NULL, NULL);
+ g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
+
+ if (!entry->text)
+ return empty_str;
+ return entry->text;
+}
+
+
+static void
+gtk_entry_marshal_signal_1 (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args)
+{
+ GtkEntrySignal1 rfunc;
+
+ rfunc = (GtkEntrySignal1) func;
+
+ (* rfunc) (object, GTK_VALUE_STRING (args[0]), GTK_VALUE_INT (args[1]),
+ GTK_VALUE_POINTER (args[2]), func_data);
+}
+
+static void
+gtk_entry_marshal_signal_2 (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args)
+{
+ GtkEntrySignal2 rfunc;
+
+ rfunc = (GtkEntrySignal2) func;
+
+ (* rfunc) (object, GTK_VALUE_INT (args[0]), GTK_VALUE_INT (args[1]),
+ func_data);
+}
+
+static void
+gtk_entry_destroy (GtkObject *object)
+{
+ GtkEntry *entry;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_ENTRY (object));
+
+ entry = GTK_ENTRY (object);
+
+ if (entry->have_selection)
+ gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME);
+
+ if (entry->timer)
+ gtk_timeout_remove (entry->timer);
+
+ if (entry->text)
+ g_free (entry->text);
+ entry->text = NULL;
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+static void
+gtk_entry_realize (GtkWidget *widget)
+{
+ GtkEntry *entry;
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_ENTRY (widget));
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+ entry = GTK_ENTRY (widget);
+
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.x = widget->allocation.x;
+ attributes.y = widget->allocation.y;
+ attributes.width = widget->allocation.width;
+ attributes.height = widget->allocation.height;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
+ attributes.event_mask = gtk_widget_get_events (widget);
+ attributes.event_mask |= (GDK_EXPOSURE_MASK |
+ GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_BUTTON1_MOTION_MASK |
+ GDK_BUTTON3_MOTION_MASK |
+ GDK_POINTER_MOTION_HINT_MASK |
+ GDK_ENTER_NOTIFY_MASK |
+ GDK_LEAVE_NOTIFY_MASK |
+ GDK_KEY_PRESS_MASK);
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+
+ widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
+ gdk_window_set_user_data (widget->window, entry);
+
+ attributes.x = widget->style->klass->xthickness + INNER_BORDER;
+ attributes.y = widget->style->klass->ythickness + INNER_BORDER;
+ attributes.width = widget->allocation.width - attributes.x * 2;
+ attributes.height = widget->allocation.height - attributes.y * 2;
+
+ entry->text_area = gdk_window_new (widget->window, &attributes, attributes_mask);
+ gdk_window_set_user_data (entry->text_area, entry);
+
+ widget->style = gtk_style_attach (widget->style, widget->window);
+
+ gdk_window_set_background (widget->window, &widget->style->white);
+ gdk_window_set_background (entry->text_area, &widget->style->white);
+
+ gdk_window_show (entry->text_area);
+}
+
+static void
+gtk_entry_unrealize (GtkWidget *widget)
+{
+ GtkEntry *entry;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_ENTRY (widget));
+
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_REALIZED);
+ entry = GTK_ENTRY (widget);
+
+ gtk_style_detach (widget->style);
+
+ if (entry->text_area)
+ {
+ gdk_window_set_user_data (entry->text_area, NULL);
+ gdk_window_destroy (entry->text_area);
+ }
+ if (widget->window)
+ {
+ gdk_window_set_user_data (widget->window, NULL);
+ gdk_window_destroy (widget->window);
+ }
+
+ entry->text_area = NULL;
+ widget->window = NULL;
+}
+
+static void
+gtk_entry_draw_focus (GtkWidget *widget)
+{
+ gint width, height;
+ gint x, y;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_ENTRY (widget));
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ x = 0;
+ y = 0;
+ gdk_window_get_size (widget->window, &width, &height);
+
+ if (GTK_WIDGET_HAS_FOCUS (widget))
+ {
+ x += 1;
+ y += 1;
+ width -= 2;
+ height -= 2;
+ }
+ else
+ {
+ gdk_draw_rectangle (widget->window, widget->style->white_gc, FALSE,
+ x + 2, y + 2, width - 5, height - 5);
+ }
+
+ gtk_draw_shadow (widget->style, widget->window,
+ GTK_STATE_NORMAL, GTK_SHADOW_IN,
+ x, y, width, height);
+
+ if (GTK_WIDGET_HAS_FOCUS (widget))
+ {
+ gdk_window_get_size (widget->window, &width, &height);
+ gdk_draw_rectangle (widget->window, widget->style->fg_gc[GTK_STATE_NORMAL],
+ FALSE, 0, 0, width - 1, height - 1);
+ }
+
+ gtk_entry_draw_cursor (GTK_ENTRY (widget));
+ }
+}
+
+static void
+gtk_entry_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_ENTRY (widget));
+ g_return_if_fail (requisition != NULL);
+
+ requisition->width = MIN_ENTRY_WIDTH + (widget->style->klass->xthickness + INNER_BORDER) * 2;
+ requisition->height = (widget->style->font->ascent +
+ widget->style->font->descent +
+ (widget->style->klass->ythickness + INNER_BORDER) * 2);
+}
+
+static void
+gtk_entry_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkEntry *entry;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_ENTRY (widget));
+ g_return_if_fail (allocation != NULL);
+
+ widget->allocation = *allocation;
+ entry = GTK_ENTRY (widget);
+
+ if (GTK_WIDGET_REALIZED (widget))
+ {
+ gdk_window_move_resize (widget->window,
+ allocation->x,
+ allocation->y + (allocation->height - widget->requisition.height) / 2,
+ allocation->width, widget->requisition.height);
+ gdk_window_move_resize (entry->text_area,
+ widget->style->klass->xthickness + INNER_BORDER,
+ widget->style->klass->ythickness + INNER_BORDER,
+ allocation->width - (widget->style->klass->xthickness + INNER_BORDER) * 2,
+ widget->requisition.height - (widget->style->klass->ythickness + INNER_BORDER) * 2);
+
+ entry->scroll_offset = 0;
+ gtk_entry_adjust_scroll (entry);
+ }
+}
+
+static void
+gtk_entry_draw (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_ENTRY (widget));
+ g_return_if_fail (area != NULL);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ gtk_widget_draw_focus (widget);
+ gtk_entry_draw_text (GTK_ENTRY (widget));
+ }
+}
+
+static gint
+gtk_entry_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ GtkEntry *entry;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ entry = GTK_ENTRY (widget);
+
+ if (widget->window == event->window)
+ gtk_widget_draw_focus (widget);
+ else if (entry->text_area == event->window)
+ gtk_entry_draw_text (GTK_ENTRY (widget));
+
+ return FALSE;
+}
+
+static gint
+gtk_entry_button_press (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ GtkEntry *entry;
+ gint tmp_pos;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ entry = GTK_ENTRY (widget);
+ if (!GTK_WIDGET_HAS_FOCUS (widget))
+ gtk_widget_grab_focus (widget);
+
+ if (event->button == 1)
+ {
+ switch (event->type)
+ {
+ case GDK_BUTTON_PRESS:
+ gtk_grab_add (widget);
+
+ tmp_pos = gtk_entry_position (entry, event->x + entry->scroll_offset);
+ gtk_select_region (entry, tmp_pos, tmp_pos);
+ entry->current_pos = entry->selection_start_pos;
+ gtk_entry_queue_draw (entry);
+ break;
+
+ case GDK_2BUTTON_PRESS:
+ gtk_select_word (entry);
+ gtk_entry_queue_draw (entry);
+ break;
+
+ case GDK_3BUTTON_PRESS:
+ gtk_select_line (entry);
+ gtk_entry_queue_draw (entry);
+ break;
+
+ default:
+ break;
+ }
+ }
+ else if (event->type == GDK_BUTTON_PRESS)
+ {
+ if (event->button == 2)
+ {
+ if (entry->selection_start_pos == entry->selection_end_pos)
+ entry->current_pos = gtk_entry_position (entry, event->x + entry->scroll_offset);
+ gtk_selection_convert (widget, GDK_SELECTION_PRIMARY,
+ GDK_TARGET_STRING, event->time);
+ }
+ else
+ {
+ gtk_grab_add (widget);
+
+ tmp_pos = gtk_entry_position (entry, event->x + entry->scroll_offset);
+ gtk_select_region (entry, tmp_pos, tmp_pos);
+ entry->have_selection = FALSE;
+ entry->current_pos = entry->selection_start_pos;
+ gtk_entry_queue_draw (entry);
+ }
+ }
+
+ return FALSE;
+}
+
+static gint
+gtk_entry_button_release (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ GtkEntry *entry;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (event->button == 1)
+ {
+ entry = GTK_ENTRY (widget);
+ gtk_grab_remove (widget);
+
+ entry->have_selection = FALSE;
+ if (entry->selection_start_pos != entry->selection_end_pos)
+ {
+ if (gtk_selection_owner_set (widget,
+ GDK_SELECTION_PRIMARY,
+ event->time))
+ {
+ entry->have_selection = TRUE;
+ gtk_entry_queue_draw (entry);
+ }
+ }
+ else
+ {
+ if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window)
+ gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY, event->time);
+ }
+ }
+ else if (event->button == 3)
+ {
+ gtk_grab_remove (widget);
+ if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window)
+ gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY, event->time);
+ }
+
+ return FALSE;
+}
+
+static gint
+gtk_entry_motion_notify (GtkWidget *widget,
+ GdkEventMotion *event)
+{
+ GtkEntry *entry;
+ gint x;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ entry = GTK_ENTRY (widget);
+
+ x = event->x;
+ if (event->is_hint || (entry->text_area != event->window))
+ gdk_window_get_pointer (entry->text_area, &x, NULL, NULL);
+
+ entry->selection_end_pos = gtk_entry_position (entry, event->x + entry->scroll_offset);
+ entry->current_pos = entry->selection_end_pos;
+ gtk_entry_adjust_scroll (entry);
+ gtk_entry_queue_draw (entry);
+
+ return FALSE;
+}
+
+static gint
+gtk_entry_key_press (GtkWidget *widget,
+ GdkEventKey *event)
+{
+ GtkEntry *entry;
+ gint return_val;
+ gint key;
+ gint tmp_pos;
+ gchar tmp;
+ gint extend_selection;
+ gint selection_pos;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ entry = GTK_ENTRY (widget);
+ return_val = FALSE;
+ extend_selection = FALSE;
+
+ if (entry->selection_start_pos == entry->selection_end_pos)
+ selection_pos = entry->current_pos;
+ else if (entry->selection_start_pos == entry->current_pos)
+ selection_pos = entry->selection_end_pos;
+ else
+ selection_pos = entry->selection_start_pos;
+
+ switch (event->keyval)
+ {
+ case GDK_BackSpace:
+ return_val = TRUE;
+ if (entry->selection_start_pos != entry->selection_end_pos)
+ gtk_delete_selection (entry);
+ else if (event->state & GDK_CONTROL_MASK)
+ gtk_delete_backward_word (entry);
+ else
+ gtk_delete_backward_character (entry);
+ break;
+ case GDK_Clear:
+ return_val = TRUE;
+ gtk_delete_line (entry);
+ break;
+ case GDK_Insert:
+ return_val = TRUE;
+ if (event->state & GDK_SHIFT_MASK)
+ {
+ /* gtk_paste_clipboard(entry) -- NEEDS CLIPBOARD */
+ }
+ else if (event->state & GDK_CONTROL_MASK)
+ {
+ /* gtk_copy_clipboard(entry) -- NEEDS CLIPBOARD */
+ }
+ else
+ {
+ /* gtk_toggle_insert(entry) -- IMPLEMENT */
+ }
+ break;
+ case GDK_Delete:
+ return_val = TRUE;
+ if (entry->selection_start_pos != entry->selection_end_pos)
+ gtk_delete_selection (entry);
+ else
+ {
+ if (event->state & GDK_CONTROL_MASK)
+ gtk_delete_line (entry);
+ else if (event->state & GDK_SHIFT_MASK)
+ /* gtk_cut_clipboard(entry) -- NEEDS CLIPBOARD */ ;
+ else
+ gtk_delete_forward_character (entry);
+ }
+ break;
+ case GDK_Home:
+ return_val = TRUE;
+ if (event->state & GDK_SHIFT_MASK)
+ {
+ if (entry->selection_start_pos == entry->selection_end_pos)
+ entry->selection_start_pos = entry->current_pos;
+ entry->current_pos = entry->selection_end_pos = 0;
+ }
+ else
+ gtk_move_beginning_of_line (entry);
+ break;
+ case GDK_End:
+ return_val = TRUE;
+ if (event->state & GDK_SHIFT_MASK)
+ {
+ if (entry->selection_start_pos == entry->selection_end_pos)
+ entry->selection_start_pos = entry->current_pos;
+ entry->current_pos = entry->selection_end_pos = entry->text_length;
+ }
+ else
+ gtk_move_end_of_line (entry);
+ break;
+ case GDK_Left:
+ return_val = TRUE;
+ if (event->state & GDK_SHIFT_MASK)
+ {
+ if (entry->selection_start_pos == entry->selection_end_pos)
+ entry->selection_start_pos = entry->selection_end_pos = entry->current_pos;
+ if (entry->selection_end_pos > 0)
+ entry->current_pos = --entry->selection_end_pos;
+ }
+ else
+ gtk_move_backward_character (entry);
+ break;
+ case GDK_Right:
+ return_val = TRUE;
+ if (event->state & GDK_SHIFT_MASK)
+ {
+ if (entry->selection_start_pos == entry->selection_end_pos)
+ entry->selection_start_pos = entry->selection_end_pos = entry->current_pos;
+ if (entry->selection_end_pos < entry->text_length)
+ entry->current_pos = ++entry->selection_end_pos;
+ }
+ else
+ gtk_move_forward_character (entry);
+ break;
+ case GDK_Return:
+ return_val = TRUE;
+ gtk_signal_emit (GTK_OBJECT (entry), entry_signals[ACTIVATE]);
+ break;
+ default:
+ if ((event->keyval >= 0x20) && (event->keyval <= 0xFF))
+ {
+ return_val = TRUE;
+ key = event->keyval;
+
+ if (event->state & GDK_CONTROL_MASK)
+ {
+ if ((key >= 'A') && (key <= 'Z'))
+ key -= 'A' - 'a';
+
+ if ((key >= 'a') && (key <= 'z') && control_keys[key - 'a'])
+ (* control_keys[key - 'a']) (entry);
+ }
+ else if (event->state & GDK_MOD1_MASK)
+ {
+ if ((key >= 'A') && (key <= 'Z'))
+ key -= 'A' - 'a';
+
+ if ((key >= 'a') && (key <= 'z') && alt_keys[key - 'a'])
+ (* alt_keys[key - 'a']) (entry);
+ }
+ else
+ {
+ tmp = (gchar) key;
+ gtk_delete_selection (entry);
+
+ tmp_pos = entry->current_pos;
+ gtk_entry_insert_text (entry, &tmp, 1, &tmp_pos);
+ entry->current_pos = tmp_pos;
+ }
+ }
+ break;
+ }
+
+ /* alex stuff */
+ if (entry->selection_start_pos != entry->selection_end_pos)
+ {
+ if (gtk_selection_owner_set (widget, GDK_SELECTION_PRIMARY, event->time))
+ {
+ entry->have_selection = TRUE;
+ gtk_entry_queue_draw (entry);
+ }
+ }
+ else
+ {
+ if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window)
+ gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY, event->time);
+ }
+ /* end of alex stuff */
+
+ if (return_val)
+ {
+ gtk_entry_adjust_scroll (entry);
+ gtk_entry_queue_draw (entry);
+ }
+
+ return return_val;
+}
+
+static gint
+gtk_entry_focus_in (GtkWidget *widget,
+ GdkEventFocus *event)
+{
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
+ gtk_widget_draw_focus (widget);
+
+ return FALSE;
+}
+
+static gint
+gtk_entry_focus_out (GtkWidget *widget,
+ GdkEventFocus *event)
+{
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
+ gtk_widget_draw_focus (widget);
+
+ return FALSE;
+}
+
+static gint
+gtk_entry_selection_clear (GtkWidget *widget,
+ GdkEventSelection *event)
+{
+ GtkEntry *entry;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ entry = GTK_ENTRY (widget);
+
+ if (entry->have_selection)
+ {
+ entry->have_selection = FALSE;
+ gtk_entry_queue_draw (entry);
+ }
+
+ return FALSE;
+}
+
+static void
+gtk_entry_selection_handler (GtkWidget *widget,
+ GtkSelectionData *selection_data,
+ gpointer data)
+{
+ GtkEntry *entry;
+ gint selection_start_pos;
+ gint selection_end_pos;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_ENTRY (widget));
+
+ entry = GTK_ENTRY (widget);
+
+ selection_start_pos = MIN (entry->selection_start_pos, entry->selection_end_pos);
+ selection_end_pos = MAX (entry->selection_start_pos, entry->selection_end_pos);
+
+ gtk_selection_data_set (selection_data,
+ GDK_SELECTION_TYPE_STRING,
+ 8*sizeof(gchar),
+ &entry->text[selection_start_pos],
+ selection_end_pos - selection_start_pos);
+}
+
+static void
+gtk_entry_selection_received (GtkWidget *widget,
+ GtkSelectionData *selection_data)
+{
+ GtkEntry *entry;
+ gint reselect;
+ gint tmp_pos;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_ENTRY (widget));
+
+ entry = GTK_ENTRY (widget);
+
+ if (selection_data->length < 0)
+ return ;
+
+ if (selection_data->target == GDK_TARGET_STRING)
+ {
+ reselect = FALSE;
+ if (entry->selection_start_pos != entry->selection_end_pos)
+ {
+ reselect = TRUE;
+ gtk_delete_selection (entry);
+ }
+
+ tmp_pos = entry->current_pos;
+
+ selection_data->data[selection_data->length] = 0;
+ gtk_entry_insert_text (entry, selection_data->data,
+ strlen (selection_data->data), &tmp_pos);
+
+ if (reselect)
+ {
+ reselect = entry->have_selection;
+ gtk_select_region (entry, entry->current_pos, tmp_pos);
+ entry->have_selection = reselect;
+ }
+
+ entry->current_pos = tmp_pos;
+
+ gtk_entry_queue_draw (entry);
+ }
+}
+
+static void
+gtk_entry_draw_text (GtkEntry *entry)
+{
+ GtkWidget *widget;
+ GtkStateType selected_state;
+ gint selection_start_pos;
+ gint selection_end_pos;
+ gint selection_start_xoffset;
+ gint selection_end_xoffset;
+ gint width, height;
+ gint y;
+
+ g_return_if_fail (entry != NULL);
+ g_return_if_fail (GTK_IS_ENTRY (entry));
+
+ if (entry->timer)
+ {
+ gtk_timeout_remove (entry->timer);
+ entry->timer = 0;
+ }
+
+ if (!entry->visible)
+ {
+ gtk_entry_draw_cursor (entry);
+ return;
+ }
+
+ if (GTK_WIDGET_DRAWABLE (entry))
+ {
+ widget = GTK_WIDGET (entry);
+
+ gdk_window_clear (entry->text_area);
+
+ if (entry->text)
+ {
+ gdk_window_get_size (entry->text_area, &width, &height);
+ y = (height - (widget->style->font->ascent + widget->style->font->descent)) / 2;
+ y += widget->style->font->ascent;
+
+ if (entry->selection_start_pos != entry->selection_end_pos)
+ {
+ selected_state = GTK_STATE_SELECTED;
+ if (!entry->have_selection)
+ selected_state = GTK_STATE_ACTIVE;
+
+ selection_start_pos = MIN (entry->selection_start_pos, entry->selection_end_pos);
+ selection_end_pos = MAX (entry->selection_start_pos, entry->selection_end_pos);
+
+ selection_start_xoffset = gdk_text_width (widget->style->font,
+ entry->text,
+ selection_start_pos);
+ selection_end_xoffset = gdk_text_width (widget->style->font,
+ entry->text,
+ selection_end_pos);
+
+ if (selection_start_pos > 0)
+ gdk_draw_text (entry->text_area, widget->style->font,
+ widget->style->fg_gc[GTK_STATE_NORMAL],
+ -entry->scroll_offset, y,
+ entry->text, selection_start_pos);
+
+ gdk_draw_rectangle (entry->text_area,
+ widget->style->bg_gc[selected_state],
+ TRUE,
+ -entry->scroll_offset + selection_start_xoffset,
+ 0,
+ selection_end_xoffset - selection_start_xoffset,
+ -1);
+
+ gdk_draw_text (entry->text_area, widget->style->font,
+ widget->style->fg_gc[selected_state],
+ -entry->scroll_offset + selection_start_xoffset, y,
+ entry->text + selection_start_pos,
+ selection_end_pos - selection_start_pos);
+
+ if (selection_end_pos < entry->text_length)
+ gdk_draw_string (entry->text_area, widget->style->font,
+ widget->style->fg_gc[GTK_STATE_NORMAL],
+ -entry->scroll_offset + selection_end_xoffset, y,
+ entry->text + selection_end_pos);
+ }
+ else
+ {
+ GdkGCValues values;
+
+ gdk_gc_get_values (widget->style->fg_gc[GTK_STATE_NORMAL], &values);
+ gdk_draw_string (entry->text_area, widget->style->font,
+ widget->style->fg_gc[GTK_STATE_NORMAL],
+ -entry->scroll_offset, y,
+ entry->text);
+ }
+ }
+
+ gtk_entry_draw_cursor (entry);
+ }
+}
+
+static void
+gtk_entry_draw_cursor (GtkEntry *entry)
+{
+ GtkWidget *widget;
+ GdkGC *gc;
+ gint xoffset;
+ gint text_area_height;
+
+ g_return_if_fail (entry != NULL);
+ g_return_if_fail (GTK_IS_ENTRY (entry));
+
+ if (GTK_WIDGET_DRAWABLE (entry))
+ {
+ widget = GTK_WIDGET (entry);
+
+ if (entry->current_pos > 0 && entry->visible)
+ xoffset = gdk_text_width (widget->style->font, entry->text, entry->current_pos);
+ else
+ xoffset = 0;
+ xoffset -= entry->scroll_offset;
+
+ if (GTK_WIDGET_HAS_FOCUS (widget) &&
+ (entry->selection_start_pos == entry->selection_end_pos))
+ gc = widget->style->fg_gc[GTK_STATE_NORMAL];
+ else
+ gc = widget->style->white_gc;
+
+ gdk_window_get_size (entry->text_area, &text_area_height, NULL);
+ gdk_draw_line (entry->text_area, gc, xoffset, 0, xoffset, text_area_height);
+ }
+}
+
+static void
+gtk_entry_queue_draw (GtkEntry *entry)
+{
+ g_return_if_fail (entry != NULL);
+ g_return_if_fail (GTK_IS_ENTRY (entry));
+
+ if (!entry->timer)
+ entry->timer = gtk_timeout_add (DRAW_TIMEOUT, gtk_entry_timer, entry);
+}
+
+static gint
+gtk_entry_timer (gpointer data)
+{
+ GtkEntry *entry;
+
+ g_return_val_if_fail (data != NULL, FALSE);
+
+ entry = GTK_ENTRY (data);
+ entry->timer = 0;
+ gtk_entry_draw_text (entry);
+
+ return FALSE;
+}
+
+static gint
+gtk_entry_position (GtkEntry *entry,
+ gint x)
+{
+ gint return_val;
+ gint char_width;
+ gint sum;
+ gint i;
+
+ g_return_val_if_fail (entry != NULL, 0);
+ g_return_val_if_fail (GTK_IS_ENTRY (entry), 0);
+
+ i = 0;
+ sum = 0;
+
+ if (x > sum)
+ {
+ for (; i < entry->text_length; i++)
+ {
+ char_width = gdk_char_width (GTK_WIDGET (entry)->style->font, entry->text[i]);
+
+ if (x < (sum + char_width / 2))
+ break;
+ sum += char_width;
+ }
+ }
+
+ return_val = i;
+
+ return return_val;
+}
+
+void
+gtk_entry_adjust_scroll (GtkEntry *entry)
+{
+ gint xoffset;
+ gint text_area_width;
+
+ g_return_if_fail (entry != NULL);
+ g_return_if_fail (GTK_IS_ENTRY (entry));
+
+ if (!entry->text_area)
+ return;
+
+ gdk_window_get_size (entry->text_area, &text_area_width, NULL);
+
+ if (entry->current_pos > 0)
+ xoffset = gdk_text_width (GTK_WIDGET (entry)->style->font, entry->text, entry->current_pos);
+ else
+ xoffset = 0;
+ xoffset -= entry->scroll_offset;
+
+ if (xoffset < 0)
+ entry->scroll_offset += xoffset;
+ else if (xoffset > text_area_width)
+ entry->scroll_offset += (xoffset - text_area_width) + 1;
+}
+
+static void
+gtk_entry_grow_text (GtkEntry *entry)
+{
+ gint previous_size;
+ gint i;
+
+ g_return_if_fail (entry != NULL);
+ g_return_if_fail (GTK_IS_ENTRY (entry));
+
+ previous_size = entry->text_size;
+ if (!entry->text_size)
+ entry->text_size = 128;
+ else
+ entry->text_size *= 2;
+ entry->text = g_realloc (entry->text, entry->text_size);
+
+ for (i = previous_size; i < entry->text_size; i++)
+ entry->text[i] = '\0';
+}
+
+static void
+gtk_entry_insert_text (GtkEntry *entry,
+ const gchar *new_text,
+ gint new_text_length,
+ gint *position)
+{
+ gchar buf[64];
+ gchar *text;
+
+ g_return_if_fail (entry != NULL);
+ g_return_if_fail (GTK_IS_ENTRY (entry));
+
+ if (new_text_length <= 64)
+ text = buf;
+ else
+ text = g_new (gchar, new_text_length);
+
+ strncpy (text, new_text, new_text_length);
+
+ gtk_signal_emit (GTK_OBJECT (entry), entry_signals[INSERT_TEXT],
+ text, new_text_length, position);
+ gtk_signal_emit (GTK_OBJECT (entry), entry_signals[CHANGED]);
+
+ if (new_text_length > 64)
+ g_free (text);
+}
+
+static void
+gtk_entry_delete_text (GtkEntry *entry,
+ gint start_pos,
+ gint end_pos)
+{
+ g_return_if_fail (entry != NULL);
+ g_return_if_fail (GTK_IS_ENTRY (entry));
+
+ gtk_signal_emit (GTK_OBJECT (entry), entry_signals[DELETE_TEXT],
+ start_pos, end_pos);
+ gtk_signal_emit (GTK_OBJECT (entry), entry_signals[CHANGED]);
+}
+
+static void
+gtk_real_entry_insert_text (GtkEntry *entry,
+ const gchar *new_text,
+ gint new_text_length,
+ gint *position)
+{
+ gchar *text;
+ gint start_pos;
+ gint end_pos;
+ gint last_pos;
+ gint i;
+
+ g_return_if_fail (entry != NULL);
+ g_return_if_fail (GTK_IS_ENTRY (entry));
+
+ start_pos = *position;
+ end_pos = start_pos + new_text_length;
+ last_pos = new_text_length + entry->text_length;
+
+ while (last_pos >= entry->text_size)
+ gtk_entry_grow_text (entry);
+
+ text = entry->text;
+ for (i = last_pos - 1; i >= end_pos; i--)
+ text[i] = text[i- (end_pos - start_pos)];
+ for (i = start_pos; i < end_pos; i++)
+ text[i] = new_text[i - start_pos];
+
+ entry->text_length += new_text_length;
+ *position = end_pos;
+}
+
+static void
+gtk_real_entry_delete_text (GtkEntry *entry,
+ gint start_pos,
+ gint end_pos)
+{
+ gchar *text;
+ gint deletion_length;
+ gint i;
+
+ g_return_if_fail (entry != NULL);
+ g_return_if_fail (GTK_IS_ENTRY (entry));
+
+ if ((start_pos < end_pos) &&
+ (start_pos >= 0) &&
+ (end_pos <= entry->text_length))
+ {
+ text = entry->text;
+ deletion_length = end_pos - start_pos;
+
+ for (i = end_pos; i < entry->text_length; i++)
+ text[i - deletion_length] = text[i];
+
+ for (i = entry->text_length - deletion_length; i < entry->text_length; i++)
+ text[i] = '\0';
+
+ entry->text_length -= deletion_length;
+ entry->current_pos = start_pos;
+ }
+}
+
+
+static void
+gtk_move_forward_character (GtkEntry *entry)
+{
+ entry->current_pos += 1;
+ if (entry->current_pos > entry->text_length)
+ entry->current_pos = entry->text_length;
+
+ entry->selection_start_pos = 0;
+ entry->selection_end_pos = 0;
+}
+
+static void
+gtk_move_backward_character (GtkEntry *entry)
+{
+ entry->current_pos -= 1;
+ if (entry->current_pos < 0)
+ entry->current_pos = 0;
+
+ entry->selection_start_pos = 0;
+ entry->selection_end_pos = 0;
+}
+
+static void
+gtk_move_forward_word (GtkEntry *entry)
+{
+ gchar *text;
+ gint i;
+
+ if (entry->text)
+ {
+ text = entry->text;
+ i = entry->current_pos;
+
+ if (!((text[i] == '_') || isalnum (text[i])))
+ for (; i < entry->text_length; i++)
+ if ((text[i] == '_') || isalnum (text[i]))
+ break;
+
+ for (; i < entry->text_length; i++)
+ if (!((text[i] == '_') || isalnum (text[i])))
+ break;
+
+ entry->current_pos = i;
+ if (entry->current_pos > entry->text_length)
+ entry->current_pos = entry->text_length;
+ }
+
+ entry->selection_start_pos = 0;
+ entry->selection_end_pos = 0;
+}
+
+static void
+gtk_move_backward_word (GtkEntry *entry)
+{
+ gchar *text;
+ gint i;
+
+ if (entry->text)
+ {
+ text = entry->text;
+ i = entry->current_pos - 1;
+ if (i < 0) /* Per */
+ {
+ entry->selection_start_pos = 0;
+ entry->selection_end_pos = 0;
+ return;
+ }
+
+ if (!((text[i] == '_') || isalnum (text[i])))
+ for (; i >= 0; i--)
+ if ((text[i] == '_') || isalnum (text[i]))
+ break;
+
+ for (; i >= 0; i--)
+ if (!((text[i] == '_') || isalnum (text[i])))
+ {
+ i += 1;
+ break;
+ }
+
+ entry->current_pos = i;
+ if (entry->current_pos < 0)
+ entry->current_pos = 0;
+
+ if (text[entry->current_pos] == ' ')
+ entry->current_pos += 1;
+ }
+
+ entry->selection_start_pos = 0;
+ entry->selection_end_pos = 0;
+}
+
+static void
+gtk_move_beginning_of_line (GtkEntry *entry)
+{
+ entry->current_pos = 0;
+ entry->selection_start_pos = 0;
+ entry->selection_end_pos = 0;
+}
+
+static void
+gtk_move_end_of_line (GtkEntry *entry)
+{
+ entry->current_pos = entry->text_length;
+ entry->selection_start_pos = 0;
+ entry->selection_end_pos = 0;
+}
+
+static void
+gtk_delete_forward_character (GtkEntry *entry)
+{
+ gint old_pos;
+
+ old_pos = entry->current_pos;
+ gtk_move_forward_character (entry);
+ gtk_entry_delete_text (entry, old_pos, entry->current_pos);
+
+ entry->selection_start_pos = 0;
+ entry->selection_end_pos = 0;
+}
+
+static void
+gtk_delete_backward_character (GtkEntry *entry)
+{
+ gint old_pos;
+
+ old_pos = entry->current_pos;
+ gtk_move_backward_character (entry);
+ gtk_entry_delete_text (entry, entry->current_pos, old_pos);
+
+ entry->selection_start_pos = 0;
+ entry->selection_end_pos = 0;
+}
+
+static void
+gtk_delete_forward_word (GtkEntry *entry)
+{
+ gint old_pos;
+
+ old_pos = entry->current_pos;
+ gtk_move_forward_word (entry);
+ gtk_entry_delete_text (entry, old_pos, entry->current_pos);
+
+ entry->selection_start_pos = 0;
+ entry->selection_end_pos = 0;
+}
+
+static void
+gtk_delete_backward_word (GtkEntry *entry)
+{
+ gint old_pos;
+
+ old_pos = entry->current_pos;
+ gtk_move_backward_word (entry);
+ gtk_entry_delete_text (entry, entry->current_pos, old_pos);
+
+ entry->selection_start_pos = 0;
+ entry->selection_end_pos = 0;
+}
+
+static void
+gtk_delete_line (GtkEntry *entry)
+{
+ gtk_entry_delete_text (entry, 0, entry->text_length);
+
+ entry->selection_start_pos = 0;
+ entry->selection_end_pos = 0;
+}
+
+static void
+gtk_delete_to_line_end (GtkEntry *entry)
+{
+ gtk_entry_delete_text (entry, entry->current_pos, entry->text_length);
+
+ entry->selection_start_pos = 0;
+ entry->selection_end_pos = 0;
+}
+
+static void
+gtk_delete_selection (GtkEntry *entry)
+{
+ if (entry->selection_start_pos != entry->selection_end_pos)
+ gtk_entry_delete_text (entry,
+ MIN (entry->selection_start_pos, entry->selection_end_pos),
+ MAX (entry->selection_start_pos, entry->selection_end_pos));
+
+ entry->selection_start_pos = 0;
+ entry->selection_end_pos = 0;
+
+ if (entry->have_selection)
+ {
+ entry->have_selection = FALSE;
+ gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME);
+ }
+}
+
+static void
+gtk_select_word (GtkEntry *entry)
+{
+ gint start_pos;
+ gint end_pos;
+
+ gtk_move_backward_word (entry);
+ start_pos = entry->current_pos;
+
+ gtk_move_forward_word (entry);
+ end_pos = entry->current_pos;
+
+ gtk_select_region (entry, start_pos, end_pos);
+}
+
+static void
+gtk_select_line (GtkEntry *entry)
+{
+ gtk_select_region (entry, 0, entry->text_length);
+ entry->current_pos = entry->selection_end_pos;
+}
+
+static void
+gtk_select_region (GtkEntry *entry,
+ gint start,
+ gint end)
+{
+ entry->have_selection = TRUE;
+ entry->selection_start_pos = start;
+ entry->selection_end_pos = end;
+}
diff --git a/gtk/gtkentry.h b/gtk/gtkentry.h
new file mode 100644
index 000000000..c24bee6c8
--- /dev/null
+++ b/gtk/gtkentry.h
@@ -0,0 +1,94 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_ENTRY_H__
+#define __GTK_ENTRY_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkwidget.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_ENTRY(obj) GTK_CHECK_CAST (obj, gtk_entry_get_type (), GtkEntry)
+#define GTK_ENTRY_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_entry_get_type (), GtkEntryClass)
+#define GTK_IS_ENTRY(obj) GTK_CHECK_TYPE (obj, gtk_entry_get_type ())
+
+
+typedef struct _GtkEntry GtkEntry;
+typedef struct _GtkEntryClass GtkEntryClass;
+
+struct _GtkEntry
+{
+ GtkWidget widget;
+
+ GdkWindow *text_area;
+ gchar *text;
+
+ guint16 text_size;
+ guint16 text_length;
+ gint16 current_pos;
+ gint16 selection_start_pos;
+ gint16 selection_end_pos;
+ gint16 scroll_offset;
+ guint have_selection : 1;
+ guint visible : 1;
+ guint32 timer;
+};
+
+struct _GtkEntryClass
+{
+ GtkWidgetClass parent_class;
+
+ void (* insert_text) (GtkEntry *entry,
+ const gchar *text,
+ gint length,
+ gint *position);
+ void (* delete_text) (GtkEntry *entry,
+ gint start_pos,
+ gint end_pos);
+ void (* changed) (GtkEntry *entry);
+ void (* set_text) (GtkEntry *entry);
+ void (* activate) (GtkEntry *entry);
+};
+
+
+guint gtk_entry_get_type (void);
+GtkWidget* gtk_entry_new (void);
+void gtk_entry_set_text (GtkEntry *entry,
+ const gchar *text);
+void gtk_entry_append_text (GtkEntry *entry,
+ const gchar *text);
+void gtk_entry_prepend_text (GtkEntry *entry,
+ const gchar *text);
+void gtk_entry_set_position (GtkEntry *entry,
+ gint position);
+gchar* gtk_entry_get_text (GtkEntry *entry);
+void gtk_entry_set_visibility (GtkEntry *entry,
+ gint visible);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_ENTRY_H__ */
diff --git a/gtk/gtkenums.h b/gtk/gtkenums.h
new file mode 100644
index 000000000..b82d5e497
--- /dev/null
+++ b/gtk/gtkenums.h
@@ -0,0 +1,191 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_ENUMS_H__
+#define __GTK_ENUMS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* Widget states */
+typedef enum
+{
+ GTK_STATE_NORMAL,
+ GTK_STATE_ACTIVE,
+ GTK_STATE_PRELIGHT,
+ GTK_STATE_SELECTED,
+ GTK_STATE_INSENSITIVE
+} GtkStateType;
+
+/* Window types */
+typedef enum
+{
+ GTK_WINDOW_TOPLEVEL,
+ GTK_WINDOW_DIALOG,
+ GTK_WINDOW_POPUP
+} GtkWindowType;
+
+/* Focus movement types */
+typedef enum
+{
+ GTK_DIR_TAB_FORWARD,
+ GTK_DIR_TAB_BACKWARD,
+ GTK_DIR_UP,
+ GTK_DIR_DOWN,
+ GTK_DIR_LEFT,
+ GTK_DIR_RIGHT
+} GtkDirectionType;
+
+/* Shadow types */
+typedef enum
+{
+ GTK_SHADOW_NONE,
+ GTK_SHADOW_IN,
+ GTK_SHADOW_OUT,
+ GTK_SHADOW_ETCHED_IN,
+ GTK_SHADOW_ETCHED_OUT
+} GtkShadowType;
+
+/* Arrow types */
+typedef enum
+{
+ GTK_ARROW_UP,
+ GTK_ARROW_DOWN,
+ GTK_ARROW_LEFT,
+ GTK_ARROW_RIGHT
+} GtkArrowType;
+
+/* Packing types (for boxes) */
+typedef enum
+{
+ GTK_PACK_START,
+ GTK_PACK_END
+} GtkPackType;
+
+/* Scrollbar policy types (for scrolled windows) */
+typedef enum
+{
+ GTK_POLICY_ALWAYS,
+ GTK_POLICY_AUTOMATIC
+} GtkPolicyType;
+
+/* Data update types (for ranges) */
+typedef enum
+{
+ GTK_UPDATE_CONTINUOUS,
+ GTK_UPDATE_DISCONTINUOUS,
+ GTK_UPDATE_DELAYED
+} GtkUpdateType;
+
+/* Attach options (for tables) */
+typedef enum
+{
+ GTK_EXPAND = 1 << 0,
+ GTK_SHRINK = 1 << 1,
+ GTK_FILL = 1 << 2
+} GtkAttachOptions;
+
+typedef enum
+{
+ GTK_RUN_FIRST = 0x1,
+ GTK_RUN_LAST = 0x2,
+ GTK_RUN_BOTH = 0x3,
+ GTK_RUN_MASK = 0xF,
+ GTK_RUN_NO_RECURSE = 0x10
+} GtkSignalRunType;
+
+typedef enum
+{
+ GTK_WIN_POS_NONE,
+ GTK_WIN_POS_CENTER,
+ GTK_WIN_POS_MOUSE
+} GtkWindowPosition;
+
+typedef enum
+{
+ GTK_DIRECTION_LEFT,
+ GTK_DIRECTION_RIGHT
+} GtkSubmenuDirection;
+
+typedef enum
+{
+ GTK_TOP_BOTTOM,
+ GTK_LEFT_RIGHT
+} GtkSubmenuPlacement;
+
+typedef enum
+{
+ GTK_MENU_FACTORY_MENU,
+ GTK_MENU_FACTORY_MENU_BAR,
+ GTK_MENU_FACTORY_OPTION_MENU
+} GtkMenuFactoryType;
+
+typedef enum
+{
+ GTK_PIXELS,
+ GTK_INCHES,
+ GTK_CENTIMETERS
+} GtkMetricType;
+
+typedef enum
+{
+ GTK_SCROLL_NONE,
+ GTK_SCROLL_STEP_BACKWARD,
+ GTK_SCROLL_STEP_FORWARD,
+ GTK_SCROLL_PAGE_BACKWARD,
+ GTK_SCROLL_PAGE_FORWARD
+} GtkScrollType;
+
+typedef enum
+{
+ GTK_TROUGH_NONE,
+ GTK_TROUGH_START,
+ GTK_TROUGH_END
+} GtkTroughType;
+
+typedef enum
+{
+ GTK_POS_LEFT,
+ GTK_POS_RIGHT,
+ GTK_POS_TOP,
+ GTK_POS_BOTTOM
+} GtkPositionType;
+
+typedef enum
+{
+ GTK_PREVIEW_COLOR,
+ GTK_PREVIEW_GRAYSCALE
+} GtkPreviewType;
+
+/* justification for label and maybe other widgets (text?) */
+typedef enum
+{
+ GTK_JUSTIFY_LEFT,
+ GTK_JUSTIFY_RIGHT,
+ GTK_JUSTIFY_CENTER,
+ GTK_JUSTIFY_FILL
+} GtkJustification;
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_ENUMS_H__ */
diff --git a/gtk/gtkeventbox.c b/gtk/gtkeventbox.c
new file mode 100644
index 000000000..44a0d7a9a
--- /dev/null
+++ b/gtk/gtkeventbox.c
@@ -0,0 +1,226 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtksignal.h"
+#include "gtkeventbox.h"
+
+
+static void gtk_event_box_class_init (GtkEventBoxClass *klass);
+static void gtk_event_box_init (GtkEventBox *event_box);
+static void gtk_event_box_realize (GtkWidget *widget);
+static void gtk_event_box_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void gtk_event_box_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static void gtk_event_box_draw (GtkWidget *widget,
+ GdkRectangle *area);
+static gint gtk_event_box_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+
+
+guint
+gtk_event_box_get_type ()
+{
+ static guint event_box_type = 0;
+
+ if (!event_box_type)
+ {
+ GtkTypeInfo event_box_info =
+ {
+ "GtkEventBox",
+ sizeof (GtkEventBox),
+ sizeof (GtkEventBoxClass),
+ (GtkClassInitFunc) gtk_event_box_class_init,
+ (GtkObjectInitFunc) gtk_event_box_init,
+ (GtkArgFunc) NULL,
+ };
+
+ event_box_type = gtk_type_unique (gtk_bin_get_type (), &event_box_info);
+ }
+
+ return event_box_type;
+}
+
+static void
+gtk_event_box_class_init (GtkEventBoxClass *class)
+{
+ GtkWidgetClass *widget_class;
+
+ widget_class = (GtkWidgetClass*) class;
+
+ widget_class->realize = gtk_event_box_realize;
+ widget_class->size_request = gtk_event_box_size_request;
+ widget_class->size_allocate = gtk_event_box_size_allocate;
+ widget_class->draw = gtk_event_box_draw;
+ widget_class->expose_event = gtk_event_box_expose;
+}
+
+static void
+gtk_event_box_init (GtkEventBox *event_box)
+{
+ GTK_WIDGET_UNSET_FLAGS (event_box, GTK_NO_WINDOW);
+ GTK_WIDGET_SET_FLAGS (event_box, GTK_BASIC);
+}
+
+GtkWidget*
+gtk_event_box_new ()
+{
+ return GTK_WIDGET ( gtk_type_new (gtk_event_box_get_type ()));
+}
+
+static void
+gtk_event_box_realize (GtkWidget *widget)
+{
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_EVENT_BOX (widget));
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+
+ attributes.x = widget->allocation.x;
+ attributes.y = widget->allocation.y;
+ attributes.width = widget->allocation.width;
+ attributes.height = widget->allocation.height;
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
+ attributes.event_mask = gtk_widget_get_events (widget)
+ | GDK_BUTTON_MOTION_MASK
+ | GDK_BUTTON_PRESS_MASK
+ | GDK_BUTTON_RELEASE_MASK
+ | GDK_EXPOSURE_MASK
+ | GDK_ENTER_NOTIFY_MASK
+ | GDK_LEAVE_NOTIFY_MASK;
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+
+ widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
+ gdk_window_set_user_data (widget->window, widget);
+
+ widget->style = gtk_style_attach (widget->style, widget->window);
+ gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
+}
+
+static void
+gtk_event_box_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkBin *bin;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_EVENT_BOX (widget));
+ g_return_if_fail (requisition != NULL);
+
+ bin = GTK_BIN (widget);
+
+ requisition->width = GTK_CONTAINER (widget)->border_width * 2;
+ requisition->height = GTK_CONTAINER (widget)->border_width * 2;
+
+ if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
+ {
+ gtk_widget_size_request (bin->child, &bin->child->requisition);
+
+ requisition->width += bin->child->requisition.width;
+ requisition->height += bin->child->requisition.height;
+ }
+}
+
+static void
+gtk_event_box_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkBin *bin;
+ GtkAllocation child_allocation;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_EVENT_BOX (widget));
+ g_return_if_fail (allocation != NULL);
+
+ widget->allocation = *allocation;
+ bin = GTK_BIN (widget);
+
+ child_allocation.x = 0;
+ child_allocation.y = 0;
+ child_allocation.width = allocation->width - GTK_CONTAINER (widget)->border_width * 2;
+ child_allocation.height = allocation->height - GTK_CONTAINER (widget)->border_width * 2;
+
+ if (GTK_WIDGET_REALIZED (widget))
+ {
+ gdk_window_move_resize (widget->window,
+ allocation->x + GTK_CONTAINER (widget)->border_width,
+ allocation->y + GTK_CONTAINER (widget)->border_width,
+ child_allocation.width,
+ child_allocation.height);
+ }
+
+ if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
+ {
+ gtk_widget_size_allocate (bin->child, &child_allocation);
+ }
+}
+
+static void
+gtk_event_box_draw (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ GtkBin *bin;
+ GdkRectangle child_area;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_EVENT_BOX (widget));
+ g_return_if_fail (area != NULL);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ bin = GTK_BIN (widget);
+
+ if (bin->child)
+ {
+ if (gtk_widget_intersect (bin->child, area, &child_area))
+ gtk_widget_draw (bin->child, &child_area);
+ }
+ }
+}
+
+static gint
+gtk_event_box_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ GtkBin *bin;
+ GdkEventExpose child_event;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_EVENT_BOX (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ bin = GTK_BIN (widget);
+
+ child_event = *event;
+ if (bin->child &&
+ GTK_WIDGET_NO_WINDOW (bin->child) &&
+ gtk_widget_intersect (bin->child, &event->area, &child_event.area))
+ gtk_widget_event (bin->child, (GdkEvent*) &child_event);
+ }
+
+ return FALSE;
+}
+
diff --git a/gtk/gtkeventbox.h b/gtk/gtkeventbox.h
new file mode 100644
index 000000000..d90213dee
--- /dev/null
+++ b/gtk/gtkeventbox.h
@@ -0,0 +1,57 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_EVENT_BOX_H__
+#define __GTK_EVENT_BOX_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkbin.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_EVENT_BOX(obj) GTK_CHECK_CAST (obj, gtk_event_box_get_type (), GtkEventBox)
+#define GTK_EVENT_BOX_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_event_box_get_type (), GtkEventBoxClass)
+#define GTK_IS_EVENT_BOX(obj) GTK_CHECK_TYPE (obj, gtk_event_box_get_type ())
+
+
+typedef struct _GtkEventBox GtkEventBox;
+typedef struct _GtkEventBoxClass GtkEventBoxClass;
+
+struct _GtkEventBox
+{
+ GtkBin bin;
+};
+
+struct _GtkEventBoxClass
+{
+ GtkBinClass parent_class;
+};
+
+guint gtk_event_box_get_type (void);
+GtkWidget* gtk_event_box_new (void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_EVENT_BOX_H__ */
diff --git a/gtk/gtkfilesel.c b/gtk/gtkfilesel.c
new file mode 100644
index 000000000..77f83a87a
--- /dev/null
+++ b/gtk/gtkfilesel.c
@@ -0,0 +1,2161 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <pwd.h>
+#include "fnmatch.h"
+
+#include "gdk/gdkkeysyms.h"
+#include "gtkbutton.h"
+#include "gtkentry.h"
+#include "gtkfilesel.h"
+#include "gtkhbox.h"
+#include "gtklabel.h"
+#include "gtklist.h"
+#include "gtklistitem.h"
+#include "gtkmain.h"
+#include "gtkscrolledwindow.h"
+#include "gtksignal.h"
+#include "gtkvbox.h"
+
+
+#define DIR_LIST_WIDTH 160
+#define DIR_LIST_HEIGHT 175
+#define FILE_LIST_WIDTH 160
+#define FILE_LIST_HEIGHT 175
+
+
+typedef struct _CompletionState CompletionState;
+typedef struct _CompletionDir CompletionDir;
+typedef struct _CompletionDirSent CompletionDirSent;
+typedef struct _CompletionDirEntry CompletionDirEntry;
+typedef struct _CompletionUserDir CompletionUserDir;
+typedef struct _PossibleCompletion PossibleCompletion;
+
+/* Non-external file completion decls and structures */
+
+/* A contant telling PRCS how many directories to cache. Its actually
+ * kept in a list, so the geometry isn't important. */
+#define CMPL_DIRECTORY_CACHE_SIZE 10
+
+/* A constant used to determine whether a substring was an exact
+ * match by first_diff_index()
+ */
+#define PATTERN_MATCH -1
+/* The arguments used by all fnmatch() calls below
+ */
+#define FNMATCH_FLAGS (FNM_PATHNAME | FNM_PERIOD)
+
+#define CMPL_ERRNO_TOO_LONG ((1<<16)-1)
+
+/* This structure contains all the useful information about a directory
+ * for the purposes of filename completion. These structures are cached
+ * in the CompletionState struct. CompletionDir's are reference counted.
+ */
+struct _CompletionDirSent
+{
+ ino_t inode;
+ time_t mtime;
+
+ gint entry_count;
+ gchar *name_buffer; /* memory segment containing names of all entries */
+
+ struct _CompletionDirEntry *entries;
+};
+
+struct _CompletionDir
+{
+ CompletionDirSent *sent;
+
+ gchar *fullname;
+ gint fullname_len;
+
+ struct _CompletionDir *cmpl_parent;
+ gint cmpl_index;
+ gchar *cmpl_text;
+};
+
+/* This structure contains pairs of directory entry names with a flag saying
+ * whether or not they are a valid directory. NOTE: This information is used
+ * to provide the caller with information about whether to update its completions
+ * or try to open a file. Since directories are cached by the directory mtime,
+ * a symlink which points to an invalid file (which will not be a directory),
+ * will not be reevaluated if that file is created, unless the containing
+ * directory is touched. I consider this case to be worth ignoring (josh).
+ */
+struct _CompletionDirEntry
+{
+ gint is_dir;
+ gchar *entry_name;
+};
+
+struct _CompletionUserDir
+{
+ gchar *login;
+ gchar *homedir;
+};
+
+struct _PossibleCompletion
+{
+ /* accessible fields, all are accessed externally by functions
+ * declared above
+ */
+ gchar *text;
+ gint is_a_completion;
+ gint is_directory;
+
+ /* Private fields
+ */
+ gint text_alloc;
+};
+
+struct _CompletionState
+{
+ gint last_valid_char;
+ gchar *updated_text;
+ gint updated_text_len;
+ gint updated_text_alloc;
+ gint re_complete;
+
+ gchar *user_dir_name_buffer;
+ gint user_directories_len;
+ gchar *user_home_dir;
+
+ gchar *last_completion_text;
+
+ gint user_completion_index; /* if >= 0, currently completing ~user */
+
+ struct _CompletionDir *completion_dir; /* directory completing from */
+ struct _CompletionDir *active_completion_dir;
+
+ struct _PossibleCompletion the_completion;
+
+ struct _CompletionDir *reference_dir; /* initial directory */
+
+ GList* directory_storage;
+ GList* directory_sent_storage;
+
+ struct _CompletionUserDir *user_directories;
+};
+
+
+/* File completion functions which would be external, were they used
+ * outside of this file.
+ */
+
+static CompletionState* cmpl_init_state (void);
+static void cmpl_free_state (CompletionState *cmpl_state);
+static gint cmpl_state_okay (CompletionState* cmpl_state);
+static gchar* cmpl_strerror (gint);
+
+static PossibleCompletion* cmpl_completion_matches(gchar *text_to_complete,
+ gchar **remaining_text,
+ CompletionState *cmpl_state);
+
+/* Returns a name for consideration, possibly a completion, this name
+ * will be invalid after the next call to cmpl_next_completion.
+ */
+static char* cmpl_this_completion (PossibleCompletion*);
+
+/* True if this completion matches the given text. Otherwise, this
+ * output can be used to have a list of non-completions.
+ */
+static gint cmpl_is_a_completion (PossibleCompletion*);
+
+/* True if the completion is a directory
+ */
+static gint cmpl_is_directory (PossibleCompletion*);
+
+/* Obtains the next completion, or NULL
+ */
+static PossibleCompletion* cmpl_next_completion (CompletionState*);
+
+/* Updating completions: the return value of cmpl_updated_text() will
+ * be text_to_complete completed as much as possible after the most
+ * recent call to cmpl_completion_matches. For the present
+ * application, this is the suggested replacement for the user's input
+ * string. You must CALL THIS AFTER ALL cmpl_text_completions have
+ * been received.
+ */
+static gchar* cmpl_updated_text (CompletionState* cmpl_state);
+
+/* After updating, to see if the completion was a directory, call
+ * this. If it was, you should consider re-calling completion_matches.
+ */
+static gint cmpl_updated_dir (CompletionState* cmpl_state);
+
+/* Current location: if using file completion, return the current
+ * directory, from which file completion begins. More specifically,
+ * the cwd concatenated with all exact completions up to the last
+ * directory delimiter('/').
+ */
+static gchar* cmpl_reference_position (CompletionState* cmpl_state);
+
+/* backing up: if cmpl_completion_matches returns NULL, you may query
+ * the index of the last completable character into cmpl_updated_text.
+ */
+static gint cmpl_last_valid_char (CompletionState* cmpl_state);
+
+/* When the user selects a non-directory, call cmpl_completion_fullname
+ * to get the full name of the selected file.
+ */
+static gchar* cmpl_completion_fullname (gchar*, CompletionState* cmpl_state);
+
+
+/* Directory operations. */
+static CompletionDir* open_ref_dir (gchar* text_to_complete,
+ gchar** remaining_text,
+ CompletionState* cmpl_state);
+static CompletionDir* open_dir (gchar* dir_name,
+ CompletionState* cmpl_state);
+static CompletionDir* open_user_dir (gchar* text_to_complete,
+ CompletionState *cmpl_state);
+static CompletionDir* open_relative_dir (gchar* dir_name, CompletionDir* dir,
+ CompletionState *cmpl_state);
+static CompletionDirSent* open_new_dir (gchar* dir_name, struct stat* sbuf);
+static gint correct_dir_fullname (CompletionDir* cmpl_dir);
+static gint correct_parent (CompletionDir* cmpl_dir,
+ struct stat *sbuf);
+static gchar* find_parent_dir_fullname (gchar* dirname);
+static CompletionDir* attach_dir (CompletionDirSent* sent,
+ gchar* dir_name,
+ CompletionState *cmpl_state);
+static void free_dir_sent (CompletionDirSent* sent);
+static void free_dir (CompletionDir *dir);
+static void prune_memory_usage(CompletionState *cmpl_state);
+
+/* Completion operations */
+static PossibleCompletion* attempt_homedir_completion(gchar* text_to_complete,
+ CompletionState *cmpl_state);
+static PossibleCompletion* attempt_file_completion(CompletionState *cmpl_state);
+static CompletionDir* find_completion_dir(gchar* text_to_complete,
+ gchar** remaining_text,
+ CompletionState* cmpl_state);
+static PossibleCompletion* append_completion_text(gchar* text,
+ CompletionState* cmpl_state);
+static gint get_pwdb(CompletionState* cmpl_state);
+static gint first_diff_index(gchar* pat, gchar* text);
+static gint compare_user_dir(const void* a, const void* b);
+static gint compare_cmpl_dir(const void* a, const void* b);
+static void update_cmpl(PossibleCompletion* poss,
+ CompletionState* cmpl_state);
+
+static void gtk_file_selection_class_init (GtkFileSelectionClass *klass);
+static void gtk_file_selection_init (GtkFileSelection *filesel);
+static void gtk_file_selection_destroy (GtkObject *object);
+static gint gtk_file_selection_key_press (GtkWidget *widget,
+ GdkEventKey *event,
+ gpointer user_data);
+static gint gtk_file_selection_file_button (GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer user_data);
+static gint gtk_file_selection_dir_button (GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer user_data);
+static void gtk_file_selection_file_list_changed (GtkList *gtklist,
+ gpointer func_data);
+static void gtk_file_selection_dir_list_changed (GtkList *gtklist,
+ gpointer func_data);
+static void gtk_file_selection_populate (GtkFileSelection *fs,
+ gchar *rel_path,
+ gint try_complete);
+static void gtk_file_selection_abort (GtkFileSelection *fs);
+static void gtk_file_selection_free_filename (GtkWidget *widget,
+ gpointer client_data);
+
+
+static GtkWindowClass *parent_class = NULL;
+
+static gchar *list_changed_key = "_gtk_selection_changed_handler_key";
+
+/* Saves errno when something cmpl does fails. */
+static gint cmpl_errno;
+
+
+guint
+gtk_file_selection_get_type ()
+{
+ static guint file_selection_type = 0;
+
+ if (!file_selection_type)
+ {
+ GtkTypeInfo filesel_info =
+ {
+ "GtkFileSelection",
+ sizeof (GtkFileSelection),
+ sizeof (GtkFileSelectionClass),
+ (GtkClassInitFunc) gtk_file_selection_class_init,
+ (GtkObjectInitFunc) gtk_file_selection_init,
+ (GtkArgFunc) NULL,
+ };
+
+ file_selection_type = gtk_type_unique (gtk_window_get_type (), &filesel_info);
+ }
+
+ return file_selection_type;
+}
+
+static void
+gtk_file_selection_class_init (GtkFileSelectionClass *class)
+{
+ GtkObjectClass *object_class;
+
+ object_class = (GtkObjectClass*) class;
+
+ parent_class = gtk_type_class (gtk_window_get_type ());
+
+ object_class->destroy = gtk_file_selection_destroy;
+}
+
+static void
+gtk_file_selection_init (GtkFileSelection *filesel)
+{
+ GtkWidget *dir_vbox;
+ GtkWidget *file_vbox;
+ GtkWidget *entry_vbox;
+ GtkWidget *listbox;
+ GtkWidget *label;
+ GtkWidget *list_hbox;
+ GtkWidget *action_area;
+ gint key;
+
+ filesel->cmpl_state = cmpl_init_state ();
+
+ /* The dialog-sized vertical box */
+ filesel->main_vbox = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (filesel), 10);
+ gtk_container_add (GTK_CONTAINER (filesel), filesel->main_vbox);
+ gtk_widget_show (filesel->main_vbox);
+
+ /* The horizontal box containing the directory and file listboxes */
+ list_hbox = gtk_hbox_new (TRUE, 5);
+ gtk_box_pack_start (GTK_BOX (filesel->main_vbox), list_hbox, TRUE, TRUE, 0);
+ gtk_widget_show (list_hbox);
+
+
+ /* The directories listbox */
+ dir_vbox = gtk_vbox_new (FALSE, 2);
+ gtk_box_pack_start (GTK_BOX (list_hbox), dir_vbox, TRUE, TRUE, 0);
+ gtk_widget_show (dir_vbox);
+
+ label = gtk_label_new ("Directories");
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+ gtk_box_pack_start (GTK_BOX (dir_vbox), label, FALSE, FALSE, 0);
+ gtk_widget_show (label);
+
+ listbox = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (listbox),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_ALWAYS);
+ gtk_box_pack_start (GTK_BOX (dir_vbox), listbox, TRUE, TRUE, 0);
+ gtk_widget_set_usize (listbox, DIR_LIST_WIDTH, DIR_LIST_HEIGHT);
+ gtk_widget_show (listbox);
+
+ filesel->dir_list = gtk_list_new ();
+ gtk_list_set_selection_mode (GTK_LIST (filesel->dir_list), GTK_SELECTION_BROWSE);
+ gtk_signal_connect (GTK_OBJECT (filesel->dir_list), "button_press_event",
+ (GtkSignalFunc) gtk_file_selection_dir_button, filesel);
+ key = gtk_signal_connect (GTK_OBJECT (filesel->dir_list),
+ "selection_changed",
+ (GtkSignalFunc) gtk_file_selection_dir_list_changed,
+ filesel);
+ gtk_object_set_data (GTK_OBJECT (filesel->dir_list), list_changed_key, (gpointer) key);
+ gtk_container_add (GTK_CONTAINER (listbox), filesel->dir_list);
+ gtk_widget_show (filesel->dir_list);
+
+
+ /* The files listbox */
+ file_vbox = gtk_vbox_new (FALSE, 2);
+ gtk_box_pack_start (GTK_BOX (list_hbox), file_vbox, TRUE, TRUE, 0);
+ gtk_widget_show (file_vbox);
+
+ label = gtk_label_new ("Files");
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+ gtk_box_pack_start (GTK_BOX (file_vbox), label, FALSE, FALSE, 0);
+ gtk_widget_show (label);
+
+ listbox = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (listbox),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_ALWAYS);
+ gtk_box_pack_start (GTK_BOX (file_vbox), listbox, TRUE, TRUE, 0);
+ gtk_widget_set_usize (listbox, FILE_LIST_WIDTH, FILE_LIST_HEIGHT);
+ gtk_widget_show (listbox);
+
+ filesel->file_list = gtk_list_new ();
+ gtk_list_set_selection_mode (GTK_LIST (filesel->file_list), GTK_SELECTION_BROWSE);
+ gtk_signal_connect (GTK_OBJECT (filesel->file_list), "button_press_event",
+ (GtkSignalFunc) gtk_file_selection_file_button, filesel);
+ key = gtk_signal_connect (GTK_OBJECT (filesel->file_list),
+ "selection_changed",
+ (GtkSignalFunc) gtk_file_selection_file_list_changed,
+ filesel);
+ gtk_object_set_data (GTK_OBJECT (filesel->file_list), list_changed_key, (gpointer) key);
+ gtk_container_add (GTK_CONTAINER (listbox), filesel->file_list);
+ gtk_widget_show (filesel->file_list);
+
+
+ /* The action area */
+ action_area = gtk_hbox_new (TRUE, 10);
+ gtk_box_pack_end (GTK_BOX (filesel->main_vbox), action_area, FALSE, FALSE, 0);
+ gtk_widget_show (action_area);
+
+ /* The OK button */
+ filesel->ok_button = gtk_button_new_with_label ("OK");
+ GTK_WIDGET_SET_FLAGS (filesel->ok_button, GTK_CAN_DEFAULT);
+ gtk_box_pack_start (GTK_BOX (action_area), filesel->ok_button, TRUE, TRUE, 0);
+ gtk_widget_grab_default (filesel->ok_button);
+ gtk_widget_show (filesel->ok_button);
+
+ /* The Cancel button */
+ filesel->cancel_button = gtk_button_new_with_label ("Cancel");
+ GTK_WIDGET_SET_FLAGS (filesel->cancel_button, GTK_CAN_DEFAULT);
+ gtk_box_pack_start (GTK_BOX (action_area), filesel->cancel_button, TRUE, TRUE, 0);
+ gtk_widget_show (filesel->cancel_button);
+
+ /* The Help button */
+ filesel->help_button = gtk_button_new_with_label ("Help");
+ GTK_WIDGET_SET_FLAGS (filesel->help_button, GTK_CAN_DEFAULT);
+ gtk_box_pack_start (GTK_BOX (action_area), filesel->help_button, TRUE, TRUE, 0);
+ gtk_widget_show (filesel->help_button);
+
+
+ /* The selection entry widget */
+ entry_vbox = gtk_vbox_new (FALSE, 2);
+ gtk_box_pack_end (GTK_BOX (filesel->main_vbox), entry_vbox, FALSE, FALSE, 0);
+ gtk_widget_show (entry_vbox);
+
+ filesel->selection_text = label = gtk_label_new ("");
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+ gtk_box_pack_start (GTK_BOX (entry_vbox), label, FALSE, FALSE, 0);
+ gtk_widget_show (label);
+
+ filesel->selection_entry = gtk_entry_new ();
+ gtk_signal_connect (GTK_OBJECT (filesel->selection_entry), "key_press_event",
+ (GtkSignalFunc) gtk_file_selection_key_press, filesel);
+ gtk_signal_connect_object (GTK_OBJECT (filesel->selection_entry), "focus_in_event",
+ (GtkSignalFunc) gtk_widget_grab_default,
+ GTK_OBJECT (filesel->ok_button));
+ gtk_signal_connect_object (GTK_OBJECT (filesel->selection_entry), "activate",
+ (GtkSignalFunc) gtk_button_clicked,
+ GTK_OBJECT (filesel->ok_button));
+ gtk_box_pack_start (GTK_BOX (entry_vbox), filesel->selection_entry, TRUE, TRUE, 0);
+ gtk_widget_show (filesel->selection_entry);
+
+ if (!cmpl_state_okay (filesel->cmpl_state))
+ {
+ gchar err_buf[256];
+
+ sprintf (err_buf, "Directory unreadable: %s", cmpl_strerror (cmpl_errno));
+
+ gtk_label_set (GTK_LABEL (filesel->selection_text), err_buf);
+ }
+ else
+ {
+ gtk_file_selection_populate (filesel, "", FALSE);
+ }
+
+ gtk_widget_grab_focus (filesel->selection_entry);
+}
+
+GtkWidget*
+gtk_file_selection_new (const gchar *title)
+{
+ GtkFileSelection *filesel;
+
+ filesel = gtk_type_new (gtk_file_selection_get_type ());
+ gtk_window_set_title (GTK_WINDOW (filesel), title);
+
+ return GTK_WIDGET (filesel);
+}
+
+void
+gtk_file_selection_set_filename (GtkFileSelection *filesel,
+ const gchar *filename)
+{
+ char buf[MAXPATHLEN];
+ const char *name, *last_slash;
+
+ g_return_if_fail (filesel != NULL);
+ g_return_if_fail (GTK_IS_FILE_SELECTION (filesel));
+ g_return_if_fail (filename != NULL);
+
+ last_slash = strrchr (filename, '/');
+
+ if (!last_slash)
+ {
+ buf[0] = 0;
+ name = filename;
+ }
+ else
+ {
+ gint len = MIN (MAXPATHLEN - 1, last_slash - filename + 1);
+
+ strncpy (buf, filename, len);
+ buf[len] = 0;
+
+ name = last_slash + 1;
+ }
+
+ gtk_file_selection_populate (filesel, buf, FALSE);
+
+ if (filesel->selection_entry)
+ gtk_entry_set_text (GTK_ENTRY (filesel->selection_entry), name);
+}
+
+gchar*
+gtk_file_selection_get_filename (GtkFileSelection *filesel)
+{
+ static char nothing[2] = "";
+ char *text;
+ char *filename;
+
+ g_return_val_if_fail (filesel != NULL, nothing);
+ g_return_val_if_fail (GTK_IS_FILE_SELECTION (filesel), nothing);
+
+ text = gtk_entry_get_text (GTK_ENTRY (filesel->selection_entry));
+ if (text)
+ {
+ filename = cmpl_completion_fullname (text, filesel->cmpl_state);
+ return filename;
+ }
+
+ return nothing;
+}
+
+static void
+gtk_file_selection_destroy (GtkObject *object)
+{
+ GtkFileSelection *filesel;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_FILE_SELECTION (object));
+
+ filesel = GTK_FILE_SELECTION (object);
+
+ cmpl_free_state (filesel->cmpl_state);
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+static gint
+gtk_file_selection_key_press (GtkWidget *widget,
+ GdkEventKey *event,
+ gpointer user_data)
+{
+ GtkFileSelection *fs;
+ char *text;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (event->keyval == GDK_Tab)
+ {
+ gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "key_press_event");
+
+ fs = GTK_FILE_SELECTION (user_data);
+ text = gtk_entry_get_text (GTK_ENTRY (fs->selection_entry));
+ gtk_file_selection_populate (fs, text, TRUE);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gint
+gtk_file_selection_file_button (GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer user_data)
+{
+ GtkFileSelection *fs;
+ GtkWidget *event_widget;
+ gchar *filename;
+ gboolean handled;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ fs = GTK_FILE_SELECTION (user_data);
+ g_return_val_if_fail (fs != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_FILE_SELECTION (fs), FALSE);
+
+ event_widget = gtk_get_event_widget ((GdkEvent*) event);
+ handled = FALSE;
+ if (GTK_IS_LIST_ITEM (event_widget))
+ {
+ switch (event->type)
+ {
+ case GDK_BUTTON_PRESS:
+ filename = gtk_object_get_user_data (GTK_OBJECT (event_widget));
+ gtk_widget_grab_focus (fs->selection_entry);
+ gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename);
+ handled = TRUE;
+ break;
+
+ case GDK_2BUTTON_PRESS:
+ gtk_button_clicked (GTK_BUTTON (fs->ok_button));
+ handled = TRUE;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return handled;
+}
+
+static void
+gtk_file_selection_file_list_changed (GtkList *list,
+ gpointer func_data)
+{
+ GtkFileSelection *fs;
+
+ g_return_if_fail (func_data != NULL);
+ g_return_if_fail (GTK_IS_FILE_SELECTION (func_data));
+
+ fs = GTK_FILE_SELECTION (func_data);
+
+ /* only act on an appropriate selection
+ */
+ if (list->selection && list->selection->data)
+ {
+ GtkListItem *item;
+
+ item = list->selection->data;
+
+ if (GTK_IS_LIST_ITEM (item))
+ {
+ gchar *filename;
+
+ filename = gtk_object_get_user_data (GTK_OBJECT (item));
+ gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename);
+ }
+ }
+}
+
+static gint
+gtk_file_selection_dir_button (GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer user_data)
+{
+ GtkFileSelection *fs;
+ GtkWidget *event_widget;
+ gchar *filename;
+ gboolean handled;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_LIST (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ fs = GTK_FILE_SELECTION (user_data);
+ g_return_val_if_fail (fs != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_FILE_SELECTION (fs), FALSE);
+
+ event_widget = gtk_get_event_widget ((GdkEvent*) event);
+ handled = FALSE;
+ if (GTK_IS_LIST_ITEM (event_widget))
+ {
+ gint key;
+
+ filename = gtk_object_get_user_data (GTK_OBJECT (event_widget));
+
+ key = (gint) gtk_object_get_data (GTK_OBJECT (widget), list_changed_key);
+
+ switch (event->type)
+ {
+ case GDK_BUTTON_PRESS:
+
+ gtk_signal_handler_block (GTK_OBJECT (widget), key);
+ gtk_widget_activate (GTK_WIDGET (event_widget));
+ gtk_signal_handler_unblock (GTK_OBJECT (widget), key);
+
+ gtk_widget_grab_focus (fs->selection_entry);
+ gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename);
+ handled = TRUE;
+ break;
+
+ case GDK_2BUTTON_PRESS:
+ gtk_file_selection_populate (fs, filename, FALSE);
+ handled = TRUE;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return handled;
+}
+
+static void
+gtk_file_selection_dir_list_changed (GtkList *list,
+ gpointer func_data)
+{
+ GtkFileSelection *fs;
+
+ g_return_if_fail (func_data != NULL);
+ g_return_if_fail (GTK_IS_FILE_SELECTION (func_data));
+
+ fs = GTK_FILE_SELECTION (func_data);
+
+ /* only act on an appropriate selection
+ */
+ if (list->selection && list->selection->data)
+ {
+ GtkListItem *item;
+
+ item = list->selection->data;
+
+ if (GTK_IS_LIST_ITEM (item))
+ {
+ gchar *filename;
+
+ filename = gtk_object_get_user_data (GTK_OBJECT (item));
+
+ if (filename)
+ gtk_file_selection_populate (fs, filename, FALSE);
+ }
+ }
+}
+
+static void
+gtk_file_selection_populate (GtkFileSelection *fs,
+ gchar *rel_path,
+ gint try_complete)
+{
+ CompletionState *cmpl_state;
+ PossibleCompletion* poss;
+ GList *dir_list = NULL;
+ GList *file_list = NULL;
+ GtkWidget *label;
+ gchar* filename;
+ gchar* rem_path = rel_path;
+ gchar* sel_text;
+ gint did_recurse = FALSE;
+ gint possible_count = 0;
+ gint selection_index = -1;
+ gint dir_changed_key;
+
+ g_return_if_fail (fs != NULL);
+ g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+ dir_changed_key = (gint) gtk_object_get_data (GTK_OBJECT (fs->dir_list), list_changed_key);
+ gtk_signal_handler_block (GTK_OBJECT (fs->dir_list), dir_changed_key);
+
+ cmpl_state = (CompletionState*) fs->cmpl_state;
+ poss = cmpl_completion_matches (rel_path, &rem_path, cmpl_state);
+
+ if (!cmpl_state_okay (cmpl_state))
+ {
+ /* Something went wrong. */
+ gtk_file_selection_abort (fs);
+ gtk_signal_handler_unblock (GTK_OBJECT (fs->dir_list), dir_changed_key);
+ return;
+ }
+
+ g_assert (cmpl_state->reference_dir);
+
+ /* Set the dir_list and file_list to be GLists of strdup'd
+ * filenames, including ./ and ../ */
+ dir_list = g_list_prepend (dir_list, g_strdup("./"));
+ dir_list = g_list_prepend (dir_list, g_strdup("../"));
+
+ while (poss)
+ {
+ if (cmpl_is_a_completion (poss))
+ {
+ possible_count += 1;
+
+ filename = g_strdup (cmpl_this_completion (poss));
+
+ if (cmpl_is_directory (poss))
+ {
+ if (strcmp (filename, "./") != 0 &&
+ strcmp (filename, "../") != 0)
+ dir_list = g_list_prepend (dir_list, filename);
+ }
+ else
+ file_list = g_list_prepend (file_list, filename);
+ }
+
+ poss = cmpl_next_completion (cmpl_state);
+ }
+
+ /* File lists are set. */
+
+ g_assert (cmpl_state->reference_dir);
+
+ if (try_complete)
+ {
+ /* User is trying to complete filenames, so advance the user's input
+ * string to the updated_text, which is the common leading substring
+ * of all possible completions, and if its a directory attempt
+ * attempt completions in it. */
+
+ if (cmpl_updated_text (cmpl_state)[0])
+ {
+ if (cmpl_updated_dir (cmpl_state))
+ {
+ gchar* dir_name = g_strdup (cmpl_updated_text (cmpl_state));
+
+ did_recurse = TRUE;
+
+ gtk_file_selection_populate (fs, dir_name, TRUE);
+
+ g_free (dir_name);
+ }
+ else
+ {
+ if (fs->selection_entry)
+ gtk_entry_set_text (GTK_ENTRY (fs->selection_entry),
+ cmpl_updated_text (cmpl_state));
+ }
+ }
+ else
+ {
+ selection_index = cmpl_last_valid_char (cmpl_state) -
+ (strlen (rel_path) - strlen (rem_path));
+ if (fs->selection_entry)
+ gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), rem_path);
+ }
+ }
+ else
+ {
+ if (fs->selection_entry)
+ gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), "");
+ }
+
+ if (!did_recurse)
+ {
+ GList *file_label_list = NULL;
+ GList *dir_label_list = NULL;
+
+ /* This reverses the lists. */
+ while (file_list)
+ {
+ label = gtk_list_item_new_with_label (file_list->data);
+ gtk_object_set_user_data (GTK_OBJECT (label), file_list->data);
+ gtk_widget_show (label);
+
+ file_label_list = g_list_prepend (file_label_list, label);
+ file_list = file_list->next;
+ }
+
+ while (dir_list)
+ {
+ label = gtk_list_item_new_with_label (dir_list->data);
+ gtk_object_set_user_data (GTK_OBJECT (label), dir_list->data);
+ gtk_widget_show (label);
+
+ dir_label_list = g_list_prepend (dir_label_list, label);
+ dir_list = dir_list->next;
+ }
+
+ gtk_container_disable_resize (GTK_CONTAINER (fs));
+
+ if (fs->selection_entry)
+ gtk_entry_set_position (GTK_ENTRY (fs->selection_entry), selection_index);
+
+ if (fs->selection_entry)
+ {
+ sel_text = g_new (char, strlen (cmpl_reference_position (cmpl_state)) +
+ sizeof ("Selection: "));
+ strcpy (sel_text, "Selection: ");
+ strcat (sel_text, cmpl_reference_position (cmpl_state));
+
+ gtk_label_set (GTK_LABEL (fs->selection_text), sel_text);
+ g_free (sel_text);
+ }
+
+ if (fs->dir_list)
+ {
+ gtk_container_foreach (GTK_CONTAINER (fs->dir_list),
+ gtk_file_selection_free_filename, NULL);
+ gtk_list_clear_items (GTK_LIST (fs->dir_list), 0, -1);
+
+ if (dir_label_list)
+ gtk_list_append_items (GTK_LIST (fs->dir_list), dir_label_list);
+ }
+ if (fs->file_list)
+ {
+ gtk_container_foreach (GTK_CONTAINER (fs->file_list),
+ gtk_file_selection_free_filename, NULL);
+ gtk_list_clear_items (GTK_LIST (fs->file_list), 0, -1);
+
+ if (file_label_list)
+ gtk_list_append_items (GTK_LIST (fs->file_list), file_label_list);
+ }
+
+ gtk_container_enable_resize (GTK_CONTAINER (fs));
+ }
+ else
+ {
+ GList *dir_list0 = dir_list;
+ GList *file_list0 = file_list;
+
+ while (dir_list)
+ {
+ GList *tmp = dir_list;
+ dir_list = dir_list->next;
+
+ if (tmp)
+ g_free (tmp->data);
+ }
+
+ while (file_list)
+ {
+ GList *tmp = file_list;
+ file_list = file_list->next;
+
+ if (tmp)
+ g_free (tmp->data);
+ }
+
+ g_list_free (dir_list0);
+ g_list_free (file_list0);
+ }
+
+ gtk_signal_handler_unblock (GTK_OBJECT (fs->dir_list), dir_changed_key);
+}
+
+static void
+gtk_file_selection_abort (GtkFileSelection *fs)
+{
+ gchar err_buf[256];
+
+ sprintf (err_buf, "Directory unreadable: %s", cmpl_strerror (cmpl_errno));
+
+ /* BEEP gdk_beep(); */
+
+ if (fs->selection_entry)
+ gtk_label_set (GTK_LABEL (fs->selection_text), err_buf);
+}
+
+static void
+gtk_file_selection_free_filename (GtkWidget *widget,
+ gpointer client_data)
+{
+ g_return_if_fail (widget != NULL);
+
+ g_free (gtk_object_get_user_data (GTK_OBJECT (widget)));
+ gtk_object_set_user_data (GTK_OBJECT (widget), NULL);
+}
+
+
+
+/**********************************************************************/
+/* External Interface */
+/**********************************************************************/
+
+/* The four completion state selectors
+ */
+static gchar*
+cmpl_updated_text (CompletionState* cmpl_state)
+{
+ return cmpl_state->updated_text;
+}
+
+static gint
+cmpl_updated_dir (CompletionState* cmpl_state)
+{
+ return cmpl_state->re_complete;
+}
+
+static gchar*
+cmpl_reference_position (CompletionState* cmpl_state)
+{
+ return cmpl_state->reference_dir->fullname;
+}
+
+static gint
+cmpl_last_valid_char (CompletionState* cmpl_state)
+{
+ return cmpl_state->last_valid_char;
+}
+
+static gchar*
+cmpl_completion_fullname (gchar* text, CompletionState* cmpl_state)
+{
+ if (text[0] == '/')
+ {
+ strcpy (cmpl_state->updated_text, text);
+ }
+ else if (text[0] == '~')
+ {
+ CompletionDir* dir;
+ char* slash;
+
+ dir = open_user_dir (text, cmpl_state);
+
+ if (!dir)
+ {
+ /* spencer says just return ~something, so
+ * for now just do it. */
+ strcpy (cmpl_state->updated_text, text);
+ }
+ else
+ {
+
+ strcpy (cmpl_state->updated_text, dir->fullname);
+
+ slash = strchr (text, '/');
+
+ if (slash)
+ strcat (cmpl_state->updated_text, slash);
+ }
+ }
+ else
+ {
+ strcpy (cmpl_state->updated_text, cmpl_state->reference_dir->fullname);
+ strcat (cmpl_state->updated_text, "/");
+ strcat (cmpl_state->updated_text, text);
+ }
+
+ return cmpl_state->updated_text;
+}
+
+/* The three completion selectors
+ */
+static gchar*
+cmpl_this_completion (PossibleCompletion* pc)
+{
+ return pc->text;
+}
+
+static gint
+cmpl_is_directory (PossibleCompletion* pc)
+{
+ return pc->is_directory;
+}
+
+static gint
+cmpl_is_a_completion (PossibleCompletion* pc)
+{
+ return pc->is_a_completion;
+}
+
+/**********************************************************************/
+/* Construction, deletion */
+/**********************************************************************/
+
+static CompletionState*
+cmpl_init_state (void)
+{
+ gchar getcwd_buf[2*MAXPATHLEN];
+ CompletionState *new_state;
+
+ new_state = g_new (CompletionState, 1);
+
+ if (!getcwd (getcwd_buf, MAXPATHLEN))
+ {
+ cmpl_errno = errno;
+ return NULL;
+ }
+
+ new_state->reference_dir = NULL;
+ new_state->completion_dir = NULL;
+ new_state->active_completion_dir = NULL;
+
+ if ((new_state->user_home_dir = getenv("HOME")) != NULL)
+ {
+ /* if this fails, get_pwdb will fill it in. */
+ new_state->user_home_dir = g_strdup(new_state->user_home_dir);
+ }
+
+ new_state->directory_storage = NULL;
+ new_state->directory_sent_storage = NULL;
+ new_state->last_valid_char = 0;
+ new_state->updated_text = g_new (gchar, MAXPATHLEN);
+ new_state->updated_text_alloc = MAXPATHLEN;
+ new_state->the_completion.text = g_new (gchar, MAXPATHLEN);
+ new_state->the_completion.text_alloc = MAXPATHLEN;
+ new_state->user_dir_name_buffer = NULL;
+ new_state->user_directories = NULL;
+
+ new_state->reference_dir = open_dir (getcwd_buf, new_state);
+
+ if (!new_state->reference_dir)
+ return NULL;
+
+ return new_state;
+}
+
+static void
+cmpl_free_dir_list(GList* dp0)
+{
+ GList *dp = dp0;
+
+ while (dp) {
+ free_dir (dp->data);
+ dp = dp->next;
+ }
+
+ g_list_free(dp0);
+}
+
+static void
+cmpl_free_dir_sent_list(GList* dp0)
+{
+ GList *dp = dp0;
+
+ while (dp) {
+ free_dir_sent (dp->data);
+ dp = dp->next;
+ }
+
+ g_list_free(dp0);
+}
+
+static void
+cmpl_free_state (CompletionState* cmpl_state)
+{
+ cmpl_free_dir_list(cmpl_state->directory_storage);
+ cmpl_free_dir_sent_list(cmpl_state->directory_sent_storage);
+
+ if (cmpl_state->user_dir_name_buffer)
+ g_free (cmpl_state->user_dir_name_buffer);
+ if (cmpl_state->user_directories)
+ g_free (cmpl_state->user_directories);
+ if (cmpl_state->the_completion.text)
+ g_free (cmpl_state->the_completion.text);
+ if (cmpl_state->updated_text)
+ g_free (cmpl_state->updated_text);
+
+ g_free (cmpl_state);
+}
+
+static void
+free_dir(CompletionDir* dir)
+{
+ g_free(dir->fullname);
+ g_free(dir);
+}
+
+static void
+free_dir_sent(CompletionDirSent* sent)
+{
+ g_free(sent->name_buffer);
+ g_free(sent->entries);
+ g_free(sent);
+}
+
+static void
+prune_memory_usage(CompletionState *cmpl_state)
+{
+ GList* cdsl = cmpl_state->directory_sent_storage;
+ GList* cdl = cmpl_state->directory_storage;
+ GList* cdl0 = cdl;
+ gint len = 0;
+
+ for(; cdsl && len < CMPL_DIRECTORY_CACHE_SIZE; len += 1)
+ cdsl = cdsl->next;
+
+ if (cdsl) {
+ cmpl_free_dir_sent_list(cdsl->next);
+ cdsl->next = NULL;
+ }
+
+ while (cdl) {
+ if (cdl->data == cmpl_state->reference_dir)
+ cmpl_state->directory_storage = g_list_prepend(NULL, cdl->data);
+ else
+ free_dir (cdl->data);
+ cdl = cdl->next;
+ }
+
+ g_list_free(cdl0);
+}
+
+/**********************************************************************/
+/* The main entrances. */
+/**********************************************************************/
+
+static PossibleCompletion*
+cmpl_completion_matches (gchar* text_to_complete,
+ gchar** remaining_text,
+ CompletionState* cmpl_state)
+{
+ gchar* first_slash;
+ PossibleCompletion *poss;
+
+ prune_memory_usage(cmpl_state);
+
+ g_assert(text_to_complete);
+
+ cmpl_state->user_completion_index = -1;
+ cmpl_state->last_completion_text = text_to_complete;
+ cmpl_state->the_completion.text[0] = 0;
+ cmpl_state->last_valid_char = 0;
+ cmpl_state->updated_text_len = -1;
+ cmpl_state->updated_text[0] = 0;
+ cmpl_state->re_complete = FALSE;
+
+ first_slash = strchr(text_to_complete, '/');
+
+ if(text_to_complete[0] == '~' && !first_slash)
+ {
+ /* Text starts with ~ and there is no slash, show all the
+ * home directory completions.
+ */
+ poss = attempt_homedir_completion(text_to_complete, cmpl_state);
+
+ update_cmpl(poss, cmpl_state);
+
+ return poss;
+ }
+
+ cmpl_state->reference_dir =
+ open_ref_dir(text_to_complete, remaining_text, cmpl_state);
+
+ if(!cmpl_state->reference_dir)
+ return NULL;
+
+ cmpl_state->completion_dir =
+ find_completion_dir(*remaining_text, remaining_text, cmpl_state);
+
+ cmpl_state->last_valid_char = *remaining_text - text_to_complete;
+
+ if(!cmpl_state->completion_dir)
+ return NULL;
+
+ cmpl_state->completion_dir->cmpl_index = -1;
+ cmpl_state->completion_dir->cmpl_parent = NULL;
+ cmpl_state->completion_dir->cmpl_text = *remaining_text;
+
+ cmpl_state->active_completion_dir = cmpl_state->completion_dir;
+
+ cmpl_state->reference_dir = cmpl_state->completion_dir;
+
+ poss = attempt_file_completion(cmpl_state);
+
+ update_cmpl(poss, cmpl_state);
+
+ return poss;
+}
+
+static PossibleCompletion*
+cmpl_next_completion (CompletionState* cmpl_state)
+{
+ PossibleCompletion* poss = NULL;
+
+ cmpl_state->the_completion.text[0] = 0;
+
+ if(cmpl_state->user_completion_index >= 0)
+ poss = attempt_homedir_completion(cmpl_state->last_completion_text, cmpl_state);
+ else
+ poss = attempt_file_completion(cmpl_state);
+
+ update_cmpl(poss, cmpl_state);
+
+ return poss;
+}
+
+/**********************************************************************/
+/* Directory Operations */
+/**********************************************************************/
+
+/* Open the directory where completion will begin from, if possible. */
+static CompletionDir*
+open_ref_dir(gchar* text_to_complete,
+ gchar** remaining_text,
+ CompletionState* cmpl_state)
+{
+ gchar* first_slash;
+ CompletionDir *new_dir;
+
+ first_slash = strchr(text_to_complete, '/');
+
+ if (text_to_complete[0] == '/' || !cmpl_state->reference_dir)
+ {
+ new_dir = open_dir("/", cmpl_state);
+
+ if(new_dir)
+ *remaining_text = text_to_complete + 1;
+ }
+ else if (text_to_complete[0] == '~')
+ {
+ new_dir = open_user_dir(text_to_complete, cmpl_state);
+
+ if(new_dir)
+ {
+ if(first_slash)
+ *remaining_text = first_slash + 1;
+ else
+ *remaining_text = text_to_complete + strlen(text_to_complete);
+ }
+ else
+ {
+ return NULL;
+ }
+ }
+ else
+ {
+ *remaining_text = text_to_complete;
+
+ new_dir = open_dir(cmpl_state->reference_dir->fullname, cmpl_state);
+ }
+
+ if(new_dir)
+ {
+ new_dir->cmpl_index = -1;
+ new_dir->cmpl_parent = NULL;
+ }
+
+ return new_dir;
+}
+
+/* open a directory by user name */
+static CompletionDir*
+open_user_dir(gchar* text_to_complete,
+ CompletionState *cmpl_state)
+{
+ gchar *first_slash;
+ gint cmp_len;
+
+ g_assert(text_to_complete && text_to_complete[0] == '~');
+
+ first_slash = strchr(text_to_complete, '/');
+
+ if (first_slash)
+ cmp_len = first_slash - text_to_complete - 1;
+ else
+ cmp_len = strlen(text_to_complete + 1);
+
+ if(!cmp_len)
+ {
+ /* ~/ */
+ if (!cmpl_state->user_home_dir &&
+ !get_pwdb(cmpl_state))
+ return NULL;
+ return open_dir(cmpl_state->user_home_dir, cmpl_state);
+ }
+ else
+ {
+ /* ~user/ */
+ char* copy = g_new(char, cmp_len + 1);
+ struct passwd *pwd;
+ strncpy(copy, text_to_complete + 1, cmp_len);
+ copy[cmp_len] = 0;
+ pwd = getpwnam(copy);
+ g_free(copy);
+ if (!pwd)
+ {
+ cmpl_errno = errno;
+ return NULL;
+ }
+
+ return open_dir(pwd->pw_dir, cmpl_state);
+ }
+}
+
+/* open a directory relative the the current relative directory */
+static CompletionDir*
+open_relative_dir(gchar* dir_name,
+ CompletionDir* dir,
+ CompletionState *cmpl_state)
+{
+ gchar path_buf[2*MAXPATHLEN];
+
+ if(dir->fullname_len + strlen(dir_name) + 2 >= MAXPATHLEN)
+ {
+ cmpl_errno = CMPL_ERRNO_TOO_LONG;
+ return NULL;
+ }
+
+ strcpy(path_buf, dir->fullname);
+
+ if(dir->fullname_len > 1)
+ {
+ path_buf[dir->fullname_len] = '/';
+ strcpy(path_buf + dir->fullname_len + 1, dir_name);
+ }
+ else
+ {
+ strcpy(path_buf + dir->fullname_len, dir_name);
+ }
+
+ return open_dir(path_buf, cmpl_state);
+}
+
+/* after the cache lookup fails, really open a new directory */
+static CompletionDirSent*
+open_new_dir(gchar* dir_name, struct stat* sbuf)
+{
+ CompletionDirSent* sent;
+ DIR* directory;
+ gchar *buffer_ptr;
+ struct dirent *dirent_ptr;
+ gint buffer_size = 0;
+ gint entry_count = 0;
+ gint i;
+ struct stat ent_sbuf;
+ char path_buf[MAXPATHLEN*2];
+ gint path_buf_len;
+
+ sent = g_new(CompletionDirSent, 1);
+ sent->mtime = sbuf->st_mtime;
+ sent->inode = sbuf->st_ino;
+
+ path_buf_len = strlen(dir_name);
+
+ if (path_buf_len > MAXPATHLEN)
+ {
+ cmpl_errno = CMPL_ERRNO_TOO_LONG;
+ return NULL;
+ }
+
+ strcpy(path_buf, dir_name);
+
+ directory = opendir(dir_name);
+
+ if(!directory)
+ {
+ cmpl_errno = errno;
+ return NULL;
+ }
+
+ while((dirent_ptr = readdir(directory)) != NULL)
+ {
+ int entry_len = strlen(dirent_ptr->d_name);
+ buffer_size += entry_len + 1;
+ entry_count += 1;
+
+ if(path_buf_len + entry_len + 2 >= MAXPATHLEN)
+ {
+ cmpl_errno = CMPL_ERRNO_TOO_LONG;
+ closedir(directory);
+ return NULL;
+ }
+ }
+
+ sent->name_buffer = g_new(gchar, buffer_size);
+ sent->entries = g_new(CompletionDirEntry, entry_count);
+ sent->entry_count = entry_count;
+
+ buffer_ptr = sent->name_buffer;
+
+ rewinddir(directory);
+
+ for(i = 0; i < entry_count; i += 1)
+ {
+ dirent_ptr = readdir(directory);
+
+ if(!dirent_ptr)
+ {
+ cmpl_errno = errno;
+ closedir(directory);
+ return NULL;
+ }
+
+ strcpy(buffer_ptr, dirent_ptr->d_name);
+ sent->entries[i].entry_name = buffer_ptr;
+ buffer_ptr += strlen(dirent_ptr->d_name);
+ *buffer_ptr = 0;
+ buffer_ptr += 1;
+
+ path_buf[path_buf_len] = '/';
+ strcpy(path_buf + path_buf_len + 1, dirent_ptr->d_name);
+
+ if(stat(path_buf, &ent_sbuf) >= 0 && S_ISDIR(ent_sbuf.st_mode))
+ sent->entries[i].is_dir = 1;
+ else
+ /* stat may fail, and we don't mind, since it could be a
+ * dangling symlink. */
+ sent->entries[i].is_dir = 0;
+ }
+
+ qsort(sent->entries, sent->entry_count, sizeof(CompletionDirEntry), compare_cmpl_dir);
+
+ closedir(directory);
+
+ return sent;
+}
+
+/* open a directory by absolute pathname */
+static CompletionDir*
+open_dir(gchar* dir_name, CompletionState* cmpl_state)
+{
+ struct stat sbuf;
+ CompletionDirSent *sent;
+ GList* cdsl;
+
+ if(stat(dir_name, &sbuf) < 0)
+ {
+ cmpl_errno = errno;
+ return NULL;
+ }
+
+ cdsl = cmpl_state->directory_sent_storage;
+
+ while (cdsl)
+ {
+ sent = cdsl->data;
+
+ if(sent->inode == sbuf.st_ino &&
+ sent->mtime == sbuf.st_mtime)
+ return attach_dir(sent, dir_name, cmpl_state);
+
+ cdsl = cdsl->next;
+ }
+
+ sent = open_new_dir(dir_name, &sbuf);
+
+ if (sent) {
+ cmpl_state->directory_sent_storage =
+ g_list_prepend(cmpl_state->directory_sent_storage, sent);
+
+ return attach_dir(sent, dir_name, cmpl_state);
+ }
+
+ return NULL;
+}
+
+static CompletionDir*
+attach_dir(CompletionDirSent* sent, gchar* dir_name, CompletionState *cmpl_state)
+{
+ CompletionDir* new_dir;
+
+ new_dir = g_new(CompletionDir, 1);
+
+ cmpl_state->directory_storage =
+ g_list_prepend(cmpl_state->directory_storage, new_dir);
+
+ new_dir->sent = sent;
+ new_dir->fullname = g_strdup(dir_name);
+ new_dir->fullname_len = strlen(dir_name);
+
+ return new_dir;
+}
+
+static gint
+correct_dir_fullname(CompletionDir* cmpl_dir)
+{
+ gint length = strlen(cmpl_dir->fullname);
+ struct stat sbuf;
+
+ if (strcmp(cmpl_dir->fullname + length - 2, "/.") == 0)
+ cmpl_dir->fullname[length - 2] = 0;
+ else if (strcmp(cmpl_dir->fullname + length - 3, "/./") == 0)
+ cmpl_dir->fullname[length - 3] = 0;
+ else if (strcmp(cmpl_dir->fullname + length - 3, "/..") == 0)
+ {
+ if(length == 3)
+ {
+ strcpy(cmpl_dir->fullname, "/");
+ cmpl_dir->fullname_len = 1;
+ return TRUE;
+ }
+
+ if(stat(cmpl_dir->fullname, &sbuf) < 0)
+ {
+ cmpl_errno = errno;
+ return FALSE;
+ }
+
+ cmpl_dir->fullname[length - 3] = 0;
+
+ if(!correct_parent(cmpl_dir, &sbuf))
+ return FALSE;
+ }
+ else if (strcmp(cmpl_dir->fullname + length - 4, "/../") == 0)
+ {
+ if(length == 4)
+ {
+ strcpy(cmpl_dir->fullname, "/");
+ cmpl_dir->fullname_len = 1;
+ return TRUE;
+ }
+
+ if(stat(cmpl_dir->fullname, &sbuf) < 0)
+ {
+ cmpl_errno = errno;
+ return FALSE;
+ }
+
+ cmpl_dir->fullname[length - 4] = 0;
+
+ if(!correct_parent(cmpl_dir, &sbuf))
+ return FALSE;
+ }
+
+ cmpl_dir->fullname_len = strlen(cmpl_dir->fullname);
+
+ return TRUE;
+}
+
+static gint
+correct_parent(CompletionDir* cmpl_dir, struct stat *sbuf)
+{
+ struct stat parbuf;
+ gchar *last_slash;
+ gchar *new_name;
+ gchar c = 0;
+
+ last_slash = strrchr(cmpl_dir->fullname, '/');
+
+ g_assert(last_slash);
+
+ if(last_slash != cmpl_dir->fullname)
+ last_slash[0] = 0;
+ else
+ {
+ c = last_slash[1];
+ last_slash[1] = 0;
+ }
+
+ if (stat(cmpl_dir->fullname, &parbuf) < 0)
+ {
+ cmpl_errno = errno;
+ return FALSE;
+ }
+
+ if (parbuf.st_ino == sbuf->st_ino && parbuf.st_dev == sbuf->st_dev)
+ /* it wasn't a link */
+ return TRUE;
+
+ if(c)
+ last_slash[1] = c;
+ else
+ last_slash[0] = '/';
+
+ /* it was a link, have to figure it out the hard way */
+
+ new_name = find_parent_dir_fullname(cmpl_dir->fullname);
+
+ if (!new_name)
+ return FALSE;
+
+ g_free(cmpl_dir->fullname);
+
+ cmpl_dir->fullname = new_name;
+
+ return TRUE;
+}
+
+static gchar*
+find_parent_dir_fullname(gchar* dirname)
+{
+ gchar buffer[MAXPATHLEN];
+ gchar buffer2[MAXPATHLEN];
+
+ if(!getcwd(buffer, MAXPATHLEN))
+ {
+ cmpl_errno = errno;
+ return NULL;
+ }
+
+ if(chdir(dirname) != 0 || chdir("..") != 0)
+ {
+ cmpl_errno = errno;
+ return NULL;
+ }
+
+ if(!getcwd(buffer2, MAXPATHLEN))
+ {
+ chdir(buffer);
+ cmpl_errno = errno;
+
+ return NULL;
+ }
+
+ if(chdir(buffer) != 0)
+ {
+ cmpl_errno = errno;
+ return NULL;
+ }
+
+ return g_strdup(buffer2);
+}
+
+/**********************************************************************/
+/* Completion Operations */
+/**********************************************************************/
+
+static PossibleCompletion*
+attempt_homedir_completion(gchar* text_to_complete,
+ CompletionState *cmpl_state)
+{
+ gint index, length;
+
+ if (!cmpl_state->user_dir_name_buffer &&
+ !get_pwdb(cmpl_state))
+ return NULL;
+ length = strlen(text_to_complete) - 1;
+
+ cmpl_state->user_completion_index += 1;
+
+ while(cmpl_state->user_completion_index < cmpl_state->user_directories_len)
+ {
+ index = first_diff_index(text_to_complete + 1,
+ cmpl_state->user_directories
+ [cmpl_state->user_completion_index].login);
+
+ switch(index)
+ {
+ case PATTERN_MATCH:
+ break;
+ default:
+ if(cmpl_state->last_valid_char < (index + 1))
+ cmpl_state->last_valid_char = index + 1;
+ cmpl_state->user_completion_index += 1;
+ continue;
+ }
+
+ cmpl_state->the_completion.is_a_completion = 1;
+ cmpl_state->the_completion.is_directory = 1;
+
+ append_completion_text("~", cmpl_state);
+
+ append_completion_text(cmpl_state->
+ user_directories[cmpl_state->user_completion_index].login,
+ cmpl_state);
+
+ return append_completion_text("/", cmpl_state);
+ }
+
+ if(text_to_complete[1] ||
+ cmpl_state->user_completion_index > cmpl_state->user_directories_len)
+ {
+ cmpl_state->user_completion_index = -1;
+ return NULL;
+ }
+ else
+ {
+ cmpl_state->user_completion_index += 1;
+ cmpl_state->the_completion.is_a_completion = 1;
+ cmpl_state->the_completion.is_directory = 1;
+
+ return append_completion_text("~/", cmpl_state);
+ }
+}
+
+/* returns the index (>= 0) of the first differing character,
+ * PATTERN_MATCH if the completion matches */
+static gint
+first_diff_index(gchar* pat, gchar* text)
+{
+ gint diff = 0;
+
+ while(*pat && *text && *text == *pat)
+ {
+ pat += 1;
+ text += 1;
+ diff += 1;
+ }
+
+ if(*pat)
+ return diff;
+
+ return PATTERN_MATCH;
+}
+
+static PossibleCompletion*
+append_completion_text(gchar* text, CompletionState* cmpl_state)
+{
+ gint len, i = 1;
+
+ if(!cmpl_state->the_completion.text)
+ return NULL;
+
+ len = strlen(text) + strlen(cmpl_state->the_completion.text) + 1;
+
+ if(cmpl_state->the_completion.text_alloc > len)
+ {
+ strcat(cmpl_state->the_completion.text, text);
+ return &cmpl_state->the_completion;
+ }
+
+ while(i < len) { i <<= 1; }
+
+ cmpl_state->the_completion.text_alloc = i;
+
+ cmpl_state->the_completion.text = (gchar*)g_realloc(cmpl_state->the_completion.text, i);
+
+ if(!cmpl_state->the_completion.text)
+ return NULL;
+ else
+ {
+ strcat(cmpl_state->the_completion.text, text);
+ return &cmpl_state->the_completion;
+ }
+}
+
+static CompletionDir*
+find_completion_dir(gchar* text_to_complete,
+ gchar** remaining_text,
+ CompletionState* cmpl_state)
+{
+ gchar* first_slash = strchr(text_to_complete, '/');
+ CompletionDir* dir = cmpl_state->reference_dir;
+ *remaining_text = text_to_complete;
+
+ while(first_slash)
+ {
+ gint len = first_slash - *remaining_text;
+ gint found = 0;
+ gint found_index = -1;
+ gint i;
+ gchar* pat_buf = g_new (gchar, len + 1);
+
+ strncpy(pat_buf, *remaining_text, len);
+ pat_buf[len] = 0;
+
+ for(i = 0; i < dir->sent->entry_count; i += 1)
+ {
+ if(dir->sent->entries[i].is_dir &&
+ fnmatch(pat_buf, dir->sent->entries[i].entry_name,
+ FNMATCH_FLAGS)!= FNM_NOMATCH)
+ {
+ if(found)
+ {
+ g_free (pat_buf);
+ return dir;
+ }
+ else
+ {
+ found = 1;
+ found_index = i;
+ }
+ }
+ }
+
+ if(found)
+ {
+ CompletionDir* next = open_relative_dir(dir->sent->entries[found_index].entry_name,
+ dir, cmpl_state);
+
+ if(!next)
+ {
+ g_free (pat_buf);
+ return NULL;
+ }
+
+ next->cmpl_parent = dir;
+
+ dir = next;
+
+ if(!correct_dir_fullname(dir))
+ {
+ g_free(pat_buf);
+ return NULL;
+ }
+
+ *remaining_text = first_slash + 1;
+ first_slash = strchr(*remaining_text, '/');
+ }
+ else
+ {
+ g_free (pat_buf);
+ return NULL;
+ }
+
+ g_free (pat_buf);
+ }
+
+ return dir;
+}
+
+static void
+update_cmpl(PossibleCompletion* poss, CompletionState* cmpl_state)
+{
+ gint cmpl_len;
+
+ if(!poss || !cmpl_is_a_completion(poss))
+ return;
+
+ cmpl_len = strlen(cmpl_this_completion(poss));
+
+ if(cmpl_state->updated_text_alloc < cmpl_len + 1)
+ {
+ cmpl_state->updated_text =
+ (gchar*)g_realloc(cmpl_state->updated_text,
+ cmpl_state->updated_text_alloc);
+ cmpl_state->updated_text_alloc = 2*cmpl_len;
+ }
+
+ if(cmpl_state->updated_text_len < 0)
+ {
+ strcpy(cmpl_state->updated_text, cmpl_this_completion(poss));
+ cmpl_state->updated_text_len = cmpl_len;
+ cmpl_state->re_complete = cmpl_is_directory(poss);
+ }
+ else if(cmpl_state->updated_text_len == 0)
+ {
+ cmpl_state->re_complete = FALSE;
+ }
+ else
+ {
+ gint first_diff =
+ first_diff_index(cmpl_state->updated_text,
+ cmpl_this_completion(poss));
+
+ cmpl_state->re_complete = FALSE;
+
+ if(first_diff == PATTERN_MATCH)
+ return;
+
+ if(first_diff > cmpl_state->updated_text_len)
+ strcpy(cmpl_state->updated_text, cmpl_this_completion(poss));
+
+ cmpl_state->updated_text_len = first_diff;
+ cmpl_state->updated_text[first_diff] = 0;
+ }
+}
+
+static PossibleCompletion*
+attempt_file_completion(CompletionState *cmpl_state)
+{
+ gchar *pat_buf, *first_slash;
+ CompletionDir *dir = cmpl_state->active_completion_dir;
+
+ dir->cmpl_index += 1;
+
+ if(dir->cmpl_index == dir->sent->entry_count)
+ {
+ if(dir->cmpl_parent == NULL)
+ {
+ cmpl_state->active_completion_dir = NULL;
+
+ return NULL;
+ }
+ else
+ {
+ cmpl_state->active_completion_dir = dir->cmpl_parent;
+
+ return attempt_file_completion(cmpl_state);
+ }
+ }
+
+ g_assert(dir->cmpl_text);
+
+ first_slash = strchr(dir->cmpl_text, '/');
+
+ if(first_slash)
+ {
+ gint len = first_slash - dir->cmpl_text;
+
+ pat_buf = g_new (gchar, len + 1);
+ strncpy(pat_buf, dir->cmpl_text, len);
+ pat_buf[len] = 0;
+ }
+ else
+ {
+ gint len = strlen(dir->cmpl_text);
+
+ pat_buf = g_new (gchar, len + 2);
+ strcpy(pat_buf, dir->cmpl_text);
+ strcpy(pat_buf + len, "*");
+ }
+
+ if(first_slash)
+ {
+ if(dir->sent->entries[dir->cmpl_index].is_dir)
+ {
+ if(fnmatch(pat_buf, dir->sent->entries[dir->cmpl_index].entry_name,
+ FNMATCH_FLAGS) != FNM_NOMATCH)
+ {
+ CompletionDir* new_dir;
+
+ new_dir = open_relative_dir(dir->sent->entries[dir->cmpl_index].entry_name,
+ dir, cmpl_state);
+
+ if(!new_dir)
+ {
+ g_free (pat_buf);
+ return NULL;
+ }
+
+ new_dir->cmpl_parent = dir;
+
+ new_dir->cmpl_index = -1;
+ new_dir->cmpl_text = first_slash + 1;
+
+ cmpl_state->active_completion_dir = new_dir;
+
+ g_free (pat_buf);
+ return attempt_file_completion(cmpl_state);
+ }
+ else
+ {
+ g_free (pat_buf);
+ return attempt_file_completion(cmpl_state);
+ }
+ }
+ else
+ {
+ g_free (pat_buf);
+ return attempt_file_completion(cmpl_state);
+ }
+ }
+ else
+ {
+ if(dir->cmpl_parent != NULL)
+ {
+ append_completion_text(dir->fullname +
+ strlen(cmpl_state->completion_dir->fullname) + 1,
+ cmpl_state);
+ append_completion_text("/", cmpl_state);
+ }
+
+ append_completion_text(dir->sent->entries[dir->cmpl_index].entry_name, cmpl_state);
+
+ cmpl_state->the_completion.is_a_completion =
+ (fnmatch(pat_buf, dir->sent->entries[dir->cmpl_index].entry_name,
+ FNMATCH_FLAGS) != FNM_NOMATCH);
+
+ cmpl_state->the_completion.is_directory = dir->sent->entries[dir->cmpl_index].is_dir;
+ if(dir->sent->entries[dir->cmpl_index].is_dir)
+ append_completion_text("/", cmpl_state);
+
+ g_free (pat_buf);
+ return &cmpl_state->the_completion;
+ }
+}
+
+
+static gint
+get_pwdb(CompletionState* cmpl_state)
+{
+ struct passwd *pwd_ptr;
+ gchar* buf_ptr, *home_dir = NULL;
+ gint len = 0, i, count = 0;
+
+ if(cmpl_state->user_dir_name_buffer)
+ return TRUE;
+ setpwent ();
+
+ while ((pwd_ptr = getpwent()) != NULL)
+ {
+ len += strlen(pwd_ptr->pw_name);
+ len += strlen(pwd_ptr->pw_dir);
+ len += 2;
+ count += 1;
+ }
+
+ if (!cmpl_state->user_home_dir)
+ {
+ /* the loser doesn't have $HOME set */
+ setpwent ();
+
+ pwd_ptr = getpwuid(getuid());
+ if(!pwd_ptr)
+ {
+ cmpl_errno = errno;
+ goto error;
+ }
+ home_dir = pwd_ptr->pw_dir;
+
+ len += strlen(home_dir);
+ len += 1;
+ }
+
+ setpwent ();
+
+ cmpl_state->user_dir_name_buffer = g_new(gchar, len);
+ cmpl_state->user_directories = g_new(CompletionUserDir, count);
+ cmpl_state->user_directories_len = count;
+
+ buf_ptr = cmpl_state->user_dir_name_buffer;
+
+ if (!cmpl_state->user_home_dir)
+ {
+ strcpy(buf_ptr, home_dir);
+ cmpl_state->user_home_dir = buf_ptr;
+ buf_ptr += strlen(buf_ptr);
+ buf_ptr += 1;
+ }
+
+ for(i = 0; i < count; i += 1)
+ {
+ pwd_ptr = getpwent();
+ if(!pwd_ptr)
+ {
+ cmpl_errno = errno;
+ goto error;
+ }
+
+ strcpy(buf_ptr, pwd_ptr->pw_name);
+ cmpl_state->user_directories[i].login = buf_ptr;
+ buf_ptr += strlen(buf_ptr);
+ buf_ptr += 1;
+ strcpy(buf_ptr, pwd_ptr->pw_dir);
+ cmpl_state->user_directories[i].homedir = buf_ptr;
+ buf_ptr += strlen(buf_ptr);
+ buf_ptr += 1;
+ }
+
+ qsort(cmpl_state->user_directories,
+ cmpl_state->user_directories_len,
+ sizeof(CompletionUserDir),
+ compare_user_dir);
+
+ endpwent();
+
+ return TRUE;
+
+error:
+
+ if(cmpl_state->user_dir_name_buffer)
+ g_free(cmpl_state->user_dir_name_buffer);
+ if(cmpl_state->user_directories)
+ g_free(cmpl_state->user_directories);
+
+ cmpl_state->user_dir_name_buffer = NULL;
+ cmpl_state->user_directories = NULL;
+
+ return FALSE;
+}
+
+static gint
+compare_user_dir(const void* a, const void* b)
+{
+ return strcmp((((CompletionUserDir*)a))->login,
+ (((CompletionUserDir*)b))->login);
+}
+
+static gint
+compare_cmpl_dir(const void* a, const void* b)
+{
+ return strcmp((((CompletionDirEntry*)a))->entry_name,
+ (((CompletionDirEntry*)b))->entry_name);
+}
+
+static gint
+cmpl_state_okay(CompletionState* cmpl_state)
+{
+ return cmpl_state && cmpl_state->reference_dir;
+}
+
+static gchar*
+cmpl_strerror(gint err)
+{
+ if(err == CMPL_ERRNO_TOO_LONG)
+ return "Name too long";
+ else
+ return g_strerror (err);
+}
diff --git a/gtk/gtkfilesel.h b/gtk/gtkfilesel.h
new file mode 100644
index 000000000..1248ac6a9
--- /dev/null
+++ b/gtk/gtkfilesel.h
@@ -0,0 +1,73 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_FILESEL_H__
+#define __GTK_FILESEL_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkwindow.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_FILE_SELECTION(obj) GTK_CHECK_CAST (obj, gtk_file_selection_get_type (), GtkFileSelection)
+#define GTK_FILE_SELECTION_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_file_selection_get_type (), GtkFileSelectionClass)
+#define GTK_IS_FILE_SELECTION(obj) GTK_CHECK_TYPE (obj, gtk_file_selection_get_type ())
+
+
+typedef struct _GtkFileSelection GtkFileSelection;
+typedef struct _GtkFileSelectionClass GtkFileSelectionClass;
+
+struct _GtkFileSelection
+{
+ GtkWindow window;
+
+ GtkWidget *dir_list;
+ GtkWidget *file_list;
+ GtkWidget *selection_entry;
+ GtkWidget *selection_text;
+ GtkWidget *main_vbox;
+ GtkWidget *ok_button;
+ GtkWidget *cancel_button;
+ GtkWidget *help_button;
+
+ gpointer cmpl_state;
+};
+
+struct _GtkFileSelectionClass
+{
+ GtkWindowClass parent_class;
+};
+
+
+guint gtk_file_selection_get_type (void);
+GtkWidget* gtk_file_selection_new (const gchar *title);
+void gtk_file_selection_set_filename (GtkFileSelection *filesel,
+ const gchar *filename);
+gchar* gtk_file_selection_get_filename (GtkFileSelection *filesel);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_FILESEL_H__ */
diff --git a/gtk/gtkfixed.c b/gtk/gtkfixed.c
new file mode 100644
index 000000000..59eba1f46
--- /dev/null
+++ b/gtk/gtkfixed.c
@@ -0,0 +1,525 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtkfixed.h"
+
+
+static void gtk_fixed_class_init (GtkFixedClass *klass);
+static void gtk_fixed_init (GtkFixed *fixed);
+static void gtk_fixed_destroy (GtkObject *object);
+static void gtk_fixed_map (GtkWidget *widget);
+static void gtk_fixed_unmap (GtkWidget *widget);
+static void gtk_fixed_realize (GtkWidget *widget);
+static void gtk_fixed_unrealize (GtkWidget *widget);
+static void gtk_fixed_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void gtk_fixed_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static void gtk_fixed_paint (GtkWidget *widget,
+ GdkRectangle *area);
+static void gtk_fixed_draw (GtkWidget *widget,
+ GdkRectangle *area);
+static gint gtk_fixed_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+static void gtk_fixed_add (GtkContainer *container,
+ GtkWidget *widget);
+static void gtk_fixed_remove (GtkContainer *container,
+ GtkWidget *widget);
+static void gtk_fixed_foreach (GtkContainer *container,
+ GtkCallback callback,
+ gpointer callback_data);
+
+
+static GtkContainerClass *parent_class = NULL;
+
+
+guint
+gtk_fixed_get_type ()
+{
+ static guint fixed_type = 0;
+
+ if (!fixed_type)
+ {
+ GtkTypeInfo fixed_info =
+ {
+ "GtkFixed",
+ sizeof (GtkFixed),
+ sizeof (GtkFixedClass),
+ (GtkClassInitFunc) gtk_fixed_class_init,
+ (GtkObjectInitFunc) gtk_fixed_init,
+ (GtkArgFunc) NULL,
+ };
+
+ fixed_type = gtk_type_unique (gtk_container_get_type (), &fixed_info);
+ }
+
+ return fixed_type;
+}
+
+static void
+gtk_fixed_class_init (GtkFixedClass *class)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+ GtkContainerClass *container_class;
+
+ object_class = (GtkObjectClass*) class;
+ widget_class = (GtkWidgetClass*) class;
+ container_class = (GtkContainerClass*) class;
+
+ parent_class = gtk_type_class (gtk_container_get_type ());
+
+ object_class->destroy = gtk_fixed_destroy;
+
+ widget_class->map = gtk_fixed_map;
+ widget_class->unmap = gtk_fixed_unmap;
+ widget_class->realize = gtk_fixed_realize;
+ widget_class->unrealize = gtk_fixed_unrealize;
+ widget_class->size_request = gtk_fixed_size_request;
+ widget_class->size_allocate = gtk_fixed_size_allocate;
+ widget_class->draw = gtk_fixed_draw;
+ widget_class->expose_event = gtk_fixed_expose;
+
+ container_class->add = gtk_fixed_add;
+ container_class->remove = gtk_fixed_remove;
+ container_class->foreach = gtk_fixed_foreach;
+}
+
+static void
+gtk_fixed_init (GtkFixed *fixed)
+{
+ GTK_WIDGET_UNSET_FLAGS (fixed, GTK_NO_WINDOW);
+ GTK_WIDGET_SET_FLAGS (fixed, GTK_BASIC);
+
+ fixed->children = NULL;
+}
+
+GtkWidget*
+gtk_fixed_new ()
+{
+ GtkFixed *fixed;
+
+ fixed = gtk_type_new (gtk_fixed_get_type ());
+ return GTK_WIDGET (fixed);
+}
+
+void
+gtk_fixed_put (GtkFixed *fixed,
+ GtkWidget *widget,
+ gint16 x,
+ gint16 y)
+{
+ GtkFixedChild *child_info;
+
+ g_return_if_fail (fixed != NULL);
+ g_return_if_fail (GTK_IS_FIXED (fixed));
+ g_return_if_fail (widget != NULL);
+
+ child_info = g_new (GtkFixedChild, 1);
+ child_info->widget = widget;
+ child_info->x = x;
+ child_info->y = y;
+
+ gtk_widget_set_parent (widget, GTK_WIDGET (fixed));
+
+ fixed->children = g_list_append (fixed->children, child_info);
+
+ if (GTK_WIDGET_REALIZED (fixed) && !GTK_WIDGET_REALIZED (widget))
+ gtk_widget_realize (widget);
+
+ if (GTK_WIDGET_MAPPED (fixed) && !GTK_WIDGET_MAPPED (widget))
+ gtk_widget_map (widget);
+
+ if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (fixed))
+ gtk_widget_queue_resize (GTK_WIDGET (fixed));
+}
+
+void
+gtk_fixed_move (GtkFixed *fixed,
+ GtkWidget *widget,
+ gint16 x,
+ gint16 y)
+{
+ GtkFixedChild *child;
+ GList *children;
+
+ g_return_if_fail (fixed != NULL);
+ g_return_if_fail (GTK_IS_FIXED (fixed));
+ g_return_if_fail (widget != NULL);
+
+ children = fixed->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (child->widget == widget)
+ {
+ child->x = x;
+ child->y = y;
+
+ if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (fixed))
+ gtk_widget_queue_resize (GTK_WIDGET (fixed));
+
+ break;
+ }
+ }
+}
+
+static void
+gtk_fixed_destroy (GtkObject *object)
+{
+ GtkFixed *fixed;
+ GtkFixedChild *child;
+ GList *children;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_FIXED (object));
+
+ fixed = GTK_FIXED (object);
+
+ children = fixed->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ child->widget->parent = NULL;
+ gtk_object_unref (GTK_OBJECT (child->widget));
+ gtk_widget_destroy (child->widget);
+ g_free (child);
+ }
+
+ g_list_free (fixed->children);
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+static void
+gtk_fixed_map (GtkWidget *widget)
+{
+ GtkFixed *fixed;
+ GtkFixedChild *child;
+ GList *children;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_FIXED (widget));
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
+ fixed = GTK_FIXED (widget);
+
+ gdk_window_show (widget->window);
+
+ children = fixed->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_VISIBLE (child->widget) &&
+ !GTK_WIDGET_MAPPED (child->widget))
+ gtk_widget_map (child->widget);
+ }
+}
+
+static void
+gtk_fixed_unmap (GtkWidget *widget)
+{
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_FIXED (widget));
+
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
+}
+
+static void
+gtk_fixed_realize (GtkWidget *widget)
+{
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_FIXED (widget));
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.x = widget->allocation.x;
+ attributes.y = widget->allocation.y;
+ attributes.width = widget->allocation.width;
+ attributes.height = widget->allocation.height;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
+ attributes.event_mask = gtk_widget_get_events (widget);
+ attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK;
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+
+ widget->window = gdk_window_new (widget->parent->window, &attributes,
+ attributes_mask);
+ gdk_window_set_user_data (widget->window, widget);
+
+ widget->style = gtk_style_attach (widget->style, widget->window);
+ gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
+}
+
+static void
+gtk_fixed_unrealize (GtkWidget *widget)
+{
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_FIXED (widget));
+
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_REALIZED | GTK_MAPPED);
+
+ gtk_style_detach (widget->style);
+ gdk_window_destroy (widget->window);
+ widget->window = NULL;
+}
+
+static void
+gtk_fixed_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkFixed *fixed;
+ GtkFixedChild *child;
+ GList *children;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_FIXED (widget));
+ g_return_if_fail (requisition != NULL);
+
+ fixed = GTK_FIXED (widget);
+ requisition->width = 0;
+ requisition->height = 0;
+
+ children = fixed->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_VISIBLE (child->widget))
+ {
+ gtk_widget_size_request (child->widget, &child->widget->requisition);
+
+ requisition->height = MAX (requisition->height,
+ child->y +
+ child->widget->requisition.height);
+ requisition->width = MAX (requisition->width,
+ child->x +
+ child->widget->requisition.width);
+ }
+ }
+
+ requisition->height += GTK_CONTAINER (fixed)->border_width * 2;
+ requisition->width += GTK_CONTAINER (fixed)->border_width * 2;
+}
+
+static void
+gtk_fixed_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkFixed *fixed;
+ GtkFixedChild *child;
+ GtkAllocation child_allocation;
+ GList *children;
+ guint16 border_width;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_FIXED(widget));
+ g_return_if_fail (allocation != NULL);
+
+ fixed = GTK_FIXED (widget);
+
+ widget->allocation = *allocation;
+ if (GTK_WIDGET_REALIZED (widget))
+ gdk_window_move_resize (widget->window,
+ allocation->x,
+ allocation->y,
+ allocation->width,
+ allocation->height);
+
+ border_width = GTK_CONTAINER (fixed)->border_width;
+
+ children = fixed->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_VISIBLE (child->widget))
+ {
+ child_allocation.x = child->x + border_width;
+ child_allocation.y = child->y + border_width;
+ child_allocation.width = child->widget->requisition.width;
+ child_allocation.height = child->widget->requisition.height;
+ gtk_widget_size_allocate (child->widget, &child_allocation);
+ }
+ }
+}
+
+static void
+gtk_fixed_paint (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_FIXED (widget));
+ g_return_if_fail (area != NULL);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ gdk_window_clear_area (widget->window,
+ area->x, area->y,
+ area->width, area->height);
+}
+
+static void
+gtk_fixed_draw (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ GtkFixed *fixed;
+ GtkFixedChild *child;
+ GdkRectangle child_area;
+ GList *children;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_FIXED (widget));
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ fixed = GTK_FIXED (widget);
+ gtk_fixed_paint (widget, area);
+
+ children = fixed->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (gtk_widget_intersect (child->widget, area, &child_area))
+ gtk_widget_draw (child->widget, &child_area);
+ }
+ }
+}
+
+static gint
+gtk_fixed_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ GtkFixed *fixed;
+ GtkFixedChild *child;
+ GdkEventExpose child_event;
+ GList *children;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_FIXED (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ fixed = GTK_FIXED (widget);
+
+ child_event = *event;
+
+ children = fixed->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_NO_WINDOW (child->widget) &&
+ gtk_widget_intersect (child->widget, &event->area,
+ &child_event.area))
+ gtk_widget_event (child->widget, (GdkEvent*) &child_event);
+ }
+ }
+
+ return FALSE;
+}
+
+static void
+gtk_fixed_add (GtkContainer *container,
+ GtkWidget *widget)
+{
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_FIXED (container));
+ g_return_if_fail (widget != NULL);
+
+ gtk_fixed_put (GTK_FIXED (container), widget, 0, 0);
+}
+
+static void
+gtk_fixed_remove (GtkContainer *container,
+ GtkWidget *widget)
+{
+ GtkFixed *fixed;
+ GtkFixedChild *child;
+ GList *children;
+
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_FIXED (container));
+ g_return_if_fail (widget != NULL);
+
+ fixed = GTK_FIXED (container);
+
+ children = fixed->children;
+ while (children)
+ {
+ child = children->data;
+
+ if (child->widget == widget)
+ {
+ gtk_widget_unparent (widget);
+
+ fixed->children = g_list_remove_link (fixed->children, children);
+ g_list_free (children);
+ g_free (child);
+
+ if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (container))
+ gtk_widget_queue_resize (GTK_WIDGET (container));
+
+ break;
+ }
+
+ children = children->next;
+ }
+}
+
+static void
+gtk_fixed_foreach (GtkContainer *container,
+ GtkCallback callback,
+ gpointer callback_data)
+{
+ GtkFixed *fixed;
+ GtkFixedChild *child;
+ GList *children;
+
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_FIXED (container));
+ g_return_if_fail (callback != NULL);
+
+ fixed = GTK_FIXED (container);
+
+ children = fixed->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ (* callback) (child->widget, callback_data);
+ }
+}
diff --git a/gtk/gtkfixed.h b/gtk/gtkfixed.h
new file mode 100644
index 000000000..ee9c131a0
--- /dev/null
+++ b/gtk/gtkfixed.h
@@ -0,0 +1,76 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_FIXED_H__
+#define __GTK_FIXED_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkcontainer.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_FIXED(obj) GTK_CHECK_CAST (obj, gtk_fixed_get_type (), GtkFixed)
+#define GTK_FIXED_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_fixed_get_type (), GtkFixedClass)
+#define GTK_IS_FIXED(obj) GTK_CHECK_TYPE (obj, gtk_fixed_get_type ())
+
+
+typedef struct _GtkFixed GtkFixed;
+typedef struct _GtkFixedClass GtkFixedClass;
+typedef struct _GtkFixedChild GtkFixedChild;
+
+struct _GtkFixed
+{
+ GtkContainer container;
+
+ GList *children;
+};
+
+struct _GtkFixedClass
+{
+ GtkContainerClass parent_class;
+};
+
+struct _GtkFixedChild
+{
+ GtkWidget *widget;
+ gint16 x;
+ gint16 y;
+};
+
+
+guint gtk_fixed_get_type (void);
+GtkWidget* gtk_fixed_new ();
+void gtk_fixed_put (GtkFixed *fixed,
+ GtkWidget *widget,
+ gint16 x,
+ gint16 y);
+void gtk_fixed_move (GtkFixed *fixed,
+ GtkWidget *widget,
+ gint16 x,
+ gint16 y);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_FIXED_H__ */
diff --git a/gtk/gtkframe.c b/gtk/gtkframe.c
new file mode 100644
index 000000000..fe7889743
--- /dev/null
+++ b/gtk/gtkframe.c
@@ -0,0 +1,419 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtkframe.h"
+
+
+static void gtk_frame_class_init (GtkFrameClass *klass);
+static void gtk_frame_init (GtkFrame *frame);
+static void gtk_frame_destroy (GtkObject *object);
+static void gtk_frame_paint (GtkWidget *widget,
+ GdkRectangle *area);
+static void gtk_frame_draw (GtkWidget *widget,
+ GdkRectangle *area);
+static gint gtk_frame_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+static void gtk_frame_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void gtk_frame_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+
+
+static GtkBinClass *parent_class = NULL;
+
+
+guint
+gtk_frame_get_type ()
+{
+ static guint frame_type = 0;
+
+ if (!frame_type)
+ {
+ GtkTypeInfo frame_info =
+ {
+ "GtkFrame",
+ sizeof (GtkFrame),
+ sizeof (GtkFrameClass),
+ (GtkClassInitFunc) gtk_frame_class_init,
+ (GtkObjectInitFunc) gtk_frame_init,
+ (GtkArgFunc) NULL,
+ };
+
+ frame_type = gtk_type_unique (gtk_bin_get_type (), &frame_info);
+ }
+
+ return frame_type;
+}
+
+static void
+gtk_frame_class_init (GtkFrameClass *class)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+
+ object_class = (GtkObjectClass*) class;
+ widget_class = (GtkWidgetClass*) class;
+
+ parent_class = gtk_type_class (gtk_bin_get_type ());
+
+ object_class->destroy = gtk_frame_destroy;
+
+ widget_class->draw = gtk_frame_draw;
+ widget_class->expose_event = gtk_frame_expose;
+ widget_class->size_request = gtk_frame_size_request;
+ widget_class->size_allocate = gtk_frame_size_allocate;
+}
+
+static void
+gtk_frame_init (GtkFrame *frame)
+{
+ GTK_WIDGET_SET_FLAGS (frame, GTK_BASIC);
+
+ frame->label = NULL;
+ frame->shadow_type = GTK_SHADOW_ETCHED_IN;
+ frame->label_width = 0;
+ frame->label_height = 0;
+ frame->label_xalign = 0.0;
+ frame->label_yalign = 0.5;
+}
+
+GtkWidget*
+gtk_frame_new (const gchar *label)
+{
+ GtkFrame *frame;
+
+ frame = gtk_type_new (gtk_frame_get_type ());
+
+ gtk_frame_set_label (frame, label);
+
+ return GTK_WIDGET (frame);
+}
+
+void
+gtk_frame_set_label (GtkFrame *frame,
+ const gchar *label)
+{
+ g_return_if_fail (frame != NULL);
+ g_return_if_fail (GTK_IS_FRAME (frame));
+
+ if ((label && frame->label && (strcmp (frame->label, label) == 0)) ||
+ (!label && !frame->label))
+ return;
+
+ if (frame->label)
+ g_free (frame->label);
+ frame->label = NULL;
+
+ if (label)
+ {
+ frame->label = g_strdup (label);
+ frame->label_width = gdk_string_measure (GTK_WIDGET (frame)->style->font, frame->label) + 7;
+ frame->label_height = (GTK_WIDGET (frame)->style->font->ascent +
+ GTK_WIDGET (frame)->style->font->descent + 1);
+ }
+ else
+ {
+ frame->label_width = 0;
+ frame->label_height = 0;
+ }
+
+ if (GTK_WIDGET_DRAWABLE (frame))
+ {
+ GtkWidget *widget;
+
+ /* clear the old label area
+ */
+ widget = GTK_WIDGET (frame);
+ gdk_window_clear_area (widget->window,
+ widget->allocation.x + GTK_CONTAINER (frame)->border_width,
+ widget->allocation.y + GTK_CONTAINER (frame)->border_width,
+ widget->allocation.width - GTK_CONTAINER (frame)->border_width,
+ widget->allocation.y + frame->label_height);
+
+ gtk_widget_queue_resize (GTK_WIDGET (frame));
+ }
+}
+
+void
+gtk_frame_set_label_align (GtkFrame *frame,
+ gfloat xalign,
+ gfloat yalign)
+{
+ g_return_if_fail (frame != NULL);
+ g_return_if_fail (GTK_IS_FRAME (frame));
+
+ xalign = CLAMP (xalign, 0.0, 1.0);
+ yalign = CLAMP (yalign, 0.0, 1.0);
+
+ if ((xalign != frame->label_xalign) || (yalign != frame->label_yalign))
+ {
+ frame->label_xalign = xalign;
+ frame->label_yalign = yalign;
+
+ if (GTK_WIDGET_VISIBLE (frame))
+ {
+ GtkWidget *widget;
+
+ /* clear the old label area
+ */
+ widget = GTK_WIDGET (frame);
+ gdk_window_clear_area (widget->window,
+ widget->allocation.x + GTK_CONTAINER (frame)->border_width,
+ widget->allocation.y + GTK_CONTAINER (frame)->border_width,
+ widget->allocation.width - GTK_CONTAINER (frame)->border_width,
+ widget->allocation.y + frame->label_height);
+
+ gtk_widget_size_allocate (GTK_WIDGET (frame), &(GTK_WIDGET (frame)->allocation));
+ gtk_widget_queue_draw (GTK_WIDGET (frame));
+ }
+ }
+}
+
+void
+gtk_frame_set_shadow_type (GtkFrame *frame,
+ GtkShadowType type)
+{
+ g_return_if_fail (frame != NULL);
+ g_return_if_fail (GTK_IS_FRAME (frame));
+
+ if ((GtkShadowType) frame->shadow_type != type)
+ {
+ frame->shadow_type = type;
+
+ if (GTK_WIDGET_MAPPED (frame))
+ {
+ gdk_window_clear_area (GTK_WIDGET (frame)->window,
+ GTK_WIDGET (frame)->allocation.x,
+ GTK_WIDGET (frame)->allocation.y,
+ GTK_WIDGET (frame)->allocation.width,
+ GTK_WIDGET (frame)->allocation.height);
+ gtk_widget_size_allocate (GTK_WIDGET (frame), &(GTK_WIDGET (frame)->allocation));
+ gtk_widget_queue_draw (GTK_WIDGET (frame));
+ }
+ }
+}
+
+
+static void
+gtk_frame_destroy (GtkObject *object)
+{
+ GtkFrame *frame;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_FRAME (object));
+
+ frame = GTK_FRAME (object);
+
+ if (frame->label)
+ g_free (frame->label);
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+static void
+gtk_frame_paint (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ GtkFrame *frame;
+ GtkStateType state;
+ gint height_extra;
+ gint label_area_width;
+ gint x, y;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_FRAME (widget));
+ g_return_if_fail (area != NULL);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ frame = GTK_FRAME (widget);
+
+ state = widget->state;
+ if (!GTK_WIDGET_IS_SENSITIVE (widget))
+ state = GTK_STATE_INSENSITIVE;
+
+ height_extra = frame->label_height - widget->style->klass->xthickness;
+ height_extra = MAX (height_extra, 0);
+
+ x = GTK_CONTAINER (frame)->border_width;
+ y = GTK_CONTAINER (frame)->border_width;
+
+ gtk_draw_shadow (widget->style, widget->window,
+ GTK_STATE_NORMAL, frame->shadow_type,
+ widget->allocation.x + x,
+ widget->allocation.y + y + height_extra / 2,
+ widget->allocation.width - x * 2,
+ widget->allocation.height - y * 2 - height_extra / 2);
+
+ if (frame->label)
+ {
+ label_area_width = (widget->allocation.width -
+ GTK_CONTAINER (frame)->border_width * 2 -
+ widget->style->klass->xthickness * 2);
+
+ x = ((label_area_width - frame->label_width) * frame->label_xalign +
+ GTK_CONTAINER (frame)->border_width + widget->style->klass->xthickness);
+ y = (GTK_CONTAINER (frame)->border_width + widget->style->font->ascent);
+
+ gdk_window_clear_area (widget->window,
+ widget->allocation.x + x + 2,
+ widget->allocation.y + GTK_CONTAINER (frame)->border_width,
+ frame->label_width - 4,
+ frame->label_height);
+ gtk_draw_string (widget->style, widget->window, state,
+ widget->allocation.x + x + 3,
+ widget->allocation.y + y,
+ frame->label);
+ }
+ }
+}
+
+static void
+gtk_frame_draw (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ GtkBin *bin;
+ GdkRectangle child_area;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_FRAME (widget));
+ g_return_if_fail (area != NULL);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ bin = GTK_BIN (widget);
+
+ gtk_frame_paint (widget, area);
+
+ if (bin->child && gtk_widget_intersect (bin->child, area, &child_area))
+ gtk_widget_draw (bin->child, &child_area);
+ }
+}
+
+static gint
+gtk_frame_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ GtkBin *bin;
+ GdkEventExpose child_event;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_FRAME (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ bin = GTK_BIN (widget);
+
+ gtk_frame_paint (widget, &event->area);
+
+ child_event = *event;
+ if (bin->child &&
+ GTK_WIDGET_NO_WINDOW (bin->child) &&
+ gtk_widget_intersect (bin->child, &event->area, &child_event.area))
+ gtk_widget_event (bin->child, (GdkEvent*) &child_event);
+ }
+
+ return FALSE;
+}
+
+static void
+gtk_frame_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkFrame *frame;
+ GtkBin *bin;
+ gint tmp_height;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_FRAME (widget));
+ g_return_if_fail (requisition != NULL);
+
+ frame = GTK_FRAME (widget);
+ bin = GTK_BIN (widget);
+
+ requisition->width = (GTK_CONTAINER (widget)->border_width +
+ GTK_WIDGET (widget)->style->klass->xthickness) * 2;
+
+ tmp_height = frame->label_height - GTK_WIDGET (widget)->style->klass->ythickness;
+ tmp_height = MAX (tmp_height, 0);
+
+ requisition->height = tmp_height + (GTK_CONTAINER (widget)->border_width +
+ GTK_WIDGET (widget)->style->klass->ythickness) * 2;
+
+ if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
+ {
+ gtk_widget_size_request (bin->child, &bin->child->requisition);
+
+ requisition->width += MAX (bin->child->requisition.width, frame->label_width);
+ requisition->height += bin->child->requisition.height;
+ }
+ else
+ {
+ requisition->width += frame->label_width;
+ }
+}
+
+static void
+gtk_frame_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkFrame *frame;
+ GtkBin *bin;
+ GtkAllocation child_allocation;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_FRAME (widget));
+ g_return_if_fail (allocation != NULL);
+
+ frame = GTK_FRAME (widget);
+ bin = GTK_BIN (widget);
+
+ if (GTK_WIDGET_MAPPED (widget) &&
+ ((widget->allocation.x != allocation->x) ||
+ (widget->allocation.y != allocation->y) ||
+ (widget->allocation.width != allocation->width) ||
+ (widget->allocation.height != allocation->height)) &&
+ (widget->allocation.width != 0) &&
+ (widget->allocation.height != 0))
+ gdk_window_clear_area (widget->window,
+ widget->allocation.x,
+ widget->allocation.y,
+ widget->allocation.width,
+ widget->allocation.height);
+
+ widget->allocation = *allocation;
+
+ if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
+ {
+ child_allocation.x = (GTK_CONTAINER (frame)->border_width +
+ GTK_WIDGET (frame)->style->klass->xthickness);
+ child_allocation.width = MAX(0, allocation->width - child_allocation.x * 2);
+
+ child_allocation.y = (GTK_CONTAINER (frame)->border_width +
+ MAX (frame->label_height, GTK_WIDGET (frame)->style->klass->ythickness));
+ child_allocation.height = MAX (0, (allocation->height - child_allocation.y -
+ GTK_CONTAINER (frame)->border_width -
+ GTK_WIDGET (frame)->style->klass->ythickness));
+
+ child_allocation.x += allocation->x;
+ child_allocation.y += allocation->y;
+
+ gtk_widget_size_allocate (bin->child, &child_allocation);
+ }
+}
diff --git a/gtk/gtkframe.h b/gtk/gtkframe.h
new file mode 100644
index 000000000..3fe17a3cb
--- /dev/null
+++ b/gtk/gtkframe.h
@@ -0,0 +1,73 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_FRAME_H__
+#define __GTK_FRAME_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkbin.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_FRAME(obj) GTK_CHECK_CAST (obj, gtk_frame_get_type (), GtkFrame)
+#define GTK_FRAME_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_frame_get_type (), GtkFrameClass)
+#define GTK_IS_FRAME(obj) GTK_CHECK_TYPE (obj, gtk_frame_get_type ())
+
+
+typedef struct _GtkFrame GtkFrame;
+typedef struct _GtkFrameClass GtkFrameClass;
+
+struct _GtkFrame
+{
+ GtkBin bin;
+
+ gchar *label;
+ gint16 shadow_type;
+ gint16 label_width;
+ gint16 label_height;
+ gfloat label_xalign;
+ gfloat label_yalign;
+};
+
+struct _GtkFrameClass
+{
+ GtkBinClass parent_class;
+};
+
+
+guint gtk_frame_get_type (void);
+GtkWidget* gtk_frame_new (const gchar *label);
+void gtk_frame_set_label (GtkFrame *frame,
+ const gchar *label);
+void gtk_frame_set_label_align (GtkFrame *frame,
+ gfloat xalign,
+ gfloat yalign);
+void gtk_frame_set_shadow_type (GtkFrame *frame,
+ GtkShadowType type);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_FRAME_H__ */
diff --git a/gtk/gtkgamma.c b/gtk/gtkgamma.c
new file mode 100644
index 000000000..1d7abc6fb
--- /dev/null
+++ b/gtk/gtkgamma.c
@@ -0,0 +1,464 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1997 David Mosberger
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "gtkgamma.h"
+#include "gtkcurve.h"
+#include "gtkdialog.h"
+#include "gtkdrawingarea.h"
+#include "gtkentry.h"
+#include "gtkhbox.h"
+#include "gtklabel.h"
+#include "gtkmain.h"
+#include "gtkpixmap.h"
+#include "gtkradiobutton.h"
+#include "gtksignal.h"
+#include "gtktable.h"
+#include "gtkvbox.h"
+#include "gtkwindow.h"
+
+static GtkVBoxClass *parent_class = NULL;
+
+
+/* forward declarations: */
+static void gtk_gamma_curve_class_init (GtkGammaCurveClass *class);
+static void gtk_gamma_curve_init (GtkGammaCurve *curve);
+static void gtk_gamma_curve_destroy (GtkObject *object);
+
+enum
+ {
+ LINEAR = 0,
+ SPLINE,
+ FREE,
+ GAMMA,
+ RESET,
+ NUM_XPMS
+ };
+
+static char *xpm[][27] =
+ {
+ /* spline: */
+ {
+ /* width height ncolors chars_per_pixel */
+ "16 16 4 1",
+ /* colors */
+ ". c None",
+ "B c #000000",
+ "+ c #BC2D2D",
+ "r c #FF0000",
+ /* pixels */
+ "..............BB",
+ ".........rrrrrrB",
+ ".......rr.......",
+ ".....B+.........",
+ "....BBB.........",
+ "....+B..........",
+ "....r...........",
+ "...r............",
+ "...r............",
+ "..r.............",
+ "..r.............",
+ ".r..............",
+ ".r..............",
+ ".r..............",
+ "B+..............",
+ "BB.............."
+ },
+ /* linear: */
+ {
+ /* width height ncolors chars_per_pixel */
+ "16 16 5 1",
+ /* colors */
+ ". c None", /* transparent */
+ "B c #000000",
+ "' c #7F7F7F",
+ "+ c #824141",
+ "r c #FF0000",
+ /* pixels */
+ "..............BB",
+ "..............+B",
+ "..............r.",
+ ".............r..",
+ ".............r..",
+ "....'B'.....r...",
+ "....BBB.....r...",
+ "....+B+....r....",
+ "....r.r....r....",
+ "...r...r..r.....",
+ "...r...r..r.....",
+ "..r.....rB+.....",
+ "..r.....BBB.....",
+ ".r......'B'.....",
+ "B+..............",
+ "BB.............."
+ },
+ /* free: */
+ {
+ /* width height ncolors chars_per_pixel */
+ "16 16 2 1",
+ /* colors */
+ ". c None",
+ "r c #FF0000",
+ /* pixels */
+ "................",
+ "................",
+ "......r.........",
+ "......r.........",
+ ".......r........",
+ ".......r........",
+ ".......r........",
+ "........r.......",
+ "........r.......",
+ "........r.......",
+ ".....r...r.rrrrr",
+ "....r....r......",
+ "...r.....r......",
+ "..r.......r.....",
+ ".r........r.....",
+ "r..............."
+ },
+ /* gamma: */
+ {
+ /* width height ncolors chars_per_pixel */
+ "16 16 10 1",
+ /* colors */
+ ". c None",
+ "B c #000000",
+ "& c #171717",
+ "# c #2F2F2F",
+ "X c #464646",
+ "= c #5E5E5E",
+ "/ c #757575",
+ "+ c #8C8C8C",
+ "- c #A4A4A4",
+ "` c #BBBBBB",
+ /* pixels */
+ "................",
+ "................",
+ "................",
+ "....B=..+B+.....",
+ "....X&`./&-.....",
+ "...../+.XX......",
+ "......B.B+......",
+ "......X.X.......",
+ "......X&+.......",
+ "......-B........",
+ "....../=........",
+ "......#B........",
+ "......BB........",
+ "......B#........",
+ "................",
+ "................"
+ },
+ /* reset: */
+ {
+ /* width height ncolors chars_per_pixel */
+ "16 16 4 1",
+ /* colors */
+ ". c None",
+ "B c #000000",
+ "+ c #824141",
+ "r c #FF0000",
+ /* pixels */
+ "..............BB",
+ "..............+B",
+ ".............r..",
+ "............r...",
+ "...........r....",
+ "..........r.....",
+ ".........r......",
+ "........r.......",
+ ".......r........",
+ "......r.........",
+ ".....r..........",
+ "....r...........",
+ "...r............",
+ "..r.............",
+ "B+..............",
+ "BB.............."
+ }
+ };
+
+guint
+gtk_gamma_curve_get_type (void)
+{
+ static guint gamma_curve_type = 0;
+
+ if (!gamma_curve_type)
+ {
+ GtkTypeInfo gamma_curve_info =
+ {
+ "GtkGammaCurve",
+ sizeof (GtkGammaCurve),
+ sizeof (GtkGammaCurveClass),
+ (GtkClassInitFunc) gtk_gamma_curve_class_init,
+ (GtkObjectInitFunc) gtk_gamma_curve_init,
+ (GtkArgFunc) NULL,
+ };
+
+ gamma_curve_type =
+ gtk_type_unique (gtk_vbox_get_type (), &gamma_curve_info);
+ }
+ return gamma_curve_type;
+}
+
+static void
+gtk_gamma_curve_class_init (GtkGammaCurveClass *class)
+{
+ GtkObjectClass *object_class;
+
+ parent_class = gtk_type_class (gtk_vbox_get_type ());
+
+ object_class = (GtkObjectClass *) class;
+ object_class->destroy = gtk_gamma_curve_destroy;
+}
+
+static void
+gtk_gamma_curve_init (GtkGammaCurve *curve)
+{
+ curve->gamma = 1.0;
+}
+
+static void
+button_realize_callback (GtkWidget *w)
+{
+ GtkWidget *pixmap;
+ GdkBitmap *mask;
+ GdkPixmap *pm;
+ int i;
+
+ i = (long) gtk_object_get_data (GTK_OBJECT (w), "_GtkGammaCurveIndex");
+ pm = gdk_pixmap_create_from_xpm_d (w->window, &mask,
+ &w->style->bg[GTK_STATE_NORMAL], xpm[i]);
+
+ pixmap = gtk_pixmap_new (pm, mask);
+ gtk_container_add (GTK_CONTAINER (w), pixmap);
+ gtk_widget_show (pixmap);
+
+ gdk_pixmap_destroy (pm);
+ gdk_pixmap_destroy (mask); /* a bitmap is really just a special pixmap */
+}
+
+static void
+button_toggled_callback (GtkWidget *w, gpointer data)
+{
+ GtkGammaCurve *c = data;
+ GtkCurveType type;
+ int active, i;
+
+ if (!GTK_TOGGLE_BUTTON (w)->active)
+ return;
+
+ active = (long) gtk_object_get_data (GTK_OBJECT (w), "_GtkGammaCurveIndex");
+
+ for (i = 0; i < 3; ++i)
+ if ((i != active) && GTK_TOGGLE_BUTTON (c->button[i])->active)
+ break;
+
+ if (i < 3)
+ gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (c->button[i]), FALSE);
+
+ switch (active)
+ {
+ case 0: type = GTK_CURVE_TYPE_SPLINE; break;
+ case 1: type = GTK_CURVE_TYPE_LINEAR; break;
+ default: type = GTK_CURVE_TYPE_FREE; break;
+ }
+ gtk_curve_set_curve_type (GTK_CURVE (c->curve), type);
+}
+
+static void
+gamma_cancel_callback (GtkWidget *w, gpointer data)
+{
+ GtkGammaCurve *c = data;
+
+ gtk_widget_destroy (c->gamma_dialog);
+ c->gamma_dialog = 0;
+}
+
+static void
+gamma_ok_callback (GtkWidget *w, gpointer data)
+{
+ GtkGammaCurve *c = data;
+ gchar *start, *end;
+ gfloat v;
+
+ start = gtk_entry_get_text (GTK_ENTRY (c->gamma_text));
+ if (start)
+ {
+ v = strtod (start, &end);
+ if (end > start && v > 0.0)
+ c->gamma = v;
+ }
+ gtk_curve_set_gamma (GTK_CURVE (c->curve), c->gamma);
+ gamma_cancel_callback (w, data);
+}
+
+static void
+button_clicked_callback (GtkWidget *w, gpointer data)
+{
+ GtkGammaCurve *c = data;
+ int active;
+
+ active = (long) gtk_object_get_data (GTK_OBJECT (w), "_GtkGammaCurveIndex");
+ if (active == 3)
+ /* set gamma */
+ if (c->gamma_dialog)
+ return;
+ else
+ {
+ GtkWidget *vbox, *hbox, *label, *button;
+ gchar buf[64];
+
+ c->gamma_dialog = gtk_dialog_new ();
+ gtk_window_set_title (GTK_WINDOW (c->gamma_dialog), "Gamma");
+ vbox = GTK_DIALOG (c->gamma_dialog)->vbox;
+
+ hbox = gtk_hbox_new (/* homogeneous */ FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 2);
+ gtk_widget_show (hbox);
+
+ label = gtk_label_new ("Gamma value");
+ gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 2);
+ gtk_widget_show (label);
+
+ sprintf (buf, "%g", c->gamma);
+ c->gamma_text = gtk_entry_new ();
+ gtk_entry_set_text (GTK_ENTRY (c->gamma_text), buf);
+ gtk_box_pack_start (GTK_BOX (hbox), c->gamma_text, TRUE, TRUE, 2);
+ gtk_widget_show (c->gamma_text);
+
+ /* fill in action area: */
+ hbox = GTK_DIALOG (c->gamma_dialog)->action_area;
+
+ button = gtk_button_new_with_label ("OK");
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gamma_ok_callback, c);
+ gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("Cancel");
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gamma_cancel_callback, c);
+ gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+ gtk_widget_show (c->gamma_dialog);
+ }
+ else
+ /* reset */
+ gtk_curve_reset (GTK_CURVE (c->curve));
+}
+
+static void
+curve_type_changed_callback (GtkWidget *w, gpointer data)
+{
+ GtkGammaCurve *c = data;
+ GtkCurveType new_type;
+ int active;
+
+ new_type = GTK_CURVE (w)->curve_type;
+ switch (new_type)
+ {
+ case GTK_CURVE_TYPE_SPLINE: active = 0; break;
+ case GTK_CURVE_TYPE_LINEAR: active = 1; break;
+ default: active = 2; break;
+ }
+ if (!GTK_TOGGLE_BUTTON (c->button[active])->active)
+ gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (c->button[active]), TRUE);
+}
+
+GtkWidget*
+gtk_gamma_curve_new (void)
+{
+ GtkGammaCurve *c;
+ GtkWidget *vbox;
+ int i;
+
+ c = gtk_type_new (gtk_gamma_curve_get_type ());
+
+ c->table = gtk_table_new (1, 2, FALSE);
+ gtk_table_set_col_spacings (GTK_TABLE (c->table), 3);
+ gtk_container_add (GTK_CONTAINER (c), c->table);
+
+ c->curve = gtk_curve_new ();
+ gtk_signal_connect (GTK_OBJECT (c->curve), "curve_type_changed",
+ (GtkSignalFunc) curve_type_changed_callback, c);
+ gtk_table_attach_defaults (GTK_TABLE (c->table), c->curve, 0, 1, 0, 1);
+
+ vbox = gtk_vbox_new (/* homogeneous */ FALSE, /* spacing */ 3);
+ gtk_table_attach (GTK_TABLE (c->table), vbox, 1, 2, 0, 1, 0, 0, 0, 0);
+
+ /* toggle buttons: */
+ for (i = 0; i < 3; ++i)
+ {
+ c->button[i] = gtk_toggle_button_new ();
+ gtk_object_set_data (GTK_OBJECT (c->button[i]), "_GtkGammaCurveIndex",
+ (gpointer) (long) i);
+ gtk_container_add (GTK_CONTAINER (vbox), c->button[i]);
+ gtk_signal_connect (GTK_OBJECT (c->button[i]), "realize",
+ (GtkSignalFunc) button_realize_callback, 0);
+ gtk_signal_connect (GTK_OBJECT (c->button[i]), "toggled",
+ (GtkSignalFunc) button_toggled_callback, c);
+ gtk_widget_show (c->button[i]);
+ }
+
+ /* push buttons: */
+ for (i = 3; i < 5; ++i)
+ {
+ c->button[i] = gtk_button_new ();
+ gtk_object_set_data (GTK_OBJECT (c->button[i]), "_GtkGammaCurveIndex",
+ (gpointer) (long) i);
+ gtk_container_add (GTK_CONTAINER (vbox), c->button[i]);
+ gtk_signal_connect (GTK_OBJECT (c->button[i]), "realize",
+ (GtkSignalFunc) button_realize_callback, 0);
+ gtk_signal_connect (GTK_OBJECT (c->button[i]), "clicked",
+ (GtkSignalFunc) button_clicked_callback, c);
+ gtk_widget_show (c->button[i]);
+ }
+
+ gtk_widget_show (vbox);
+ gtk_widget_show (c->table);
+ gtk_widget_show (c->curve);
+
+ return GTK_WIDGET (c);
+}
+
+static void
+gtk_gamma_curve_destroy (GtkObject *object)
+{
+ GtkGammaCurve *c;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_GAMMA_CURVE (object));
+
+ c = GTK_GAMMA_CURVE (object);
+
+ if (c->gamma_dialog)
+ {
+ gtk_widget_destroy (c->gamma_dialog);
+ c->gamma_dialog = 0;
+ }
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
diff --git a/gtk/gtkgamma.h b/gtk/gtkgamma.h
new file mode 100644
index 000000000..872a7bd43
--- /dev/null
+++ b/gtk/gtkgamma.h
@@ -0,0 +1,71 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1997 David Mosberger
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_GAMMA_CURVE_H__
+#define __GTK_GAMMA_CURVE_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkvbox.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_GAMMA_CURVE(obj) \
+ GTK_CHECK_CAST (obj, gtk_gamma_curve_get_type (), GtkGammaCurve)
+#define GTK_GAMMA_CURVE_CLASS(klass) \
+ GTK_CHECK_CLASS_CAST (klass, gtk_gamma_curve_get_type, GtkGammaCurveClass)
+#define GTK_IS_GAMMA_CURVE(obj) \
+ GTK_CHECK_TYPE (obj, gtk_gamma_curve_get_type ())
+
+
+typedef struct _GtkGammaCurve GtkGammaCurve;
+typedef struct _GtkGammaCurveClass GtkGammaCurveClass;
+
+
+struct _GtkGammaCurve
+{
+ GtkVBox vbox;
+
+ GtkWidget *table;
+ GtkWidget *curve;
+ GtkWidget *button[5]; /* spline, linear, free, gamma, reset */
+
+ gfloat gamma;
+ GtkWidget *gamma_dialog;
+ GtkWidget *gamma_text;
+};
+
+struct _GtkGammaCurveClass
+{
+ GtkVBoxClass parent_class;
+};
+
+
+guint gtk_gamma_curve_get_type (void);
+GtkWidget* gtk_gamma_curve_new (void);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_GAMMA_CURVE_H__ */
diff --git a/gtk/gtkgc.c b/gtk/gtkgc.c
new file mode 100644
index 000000000..c9da06984
--- /dev/null
+++ b/gtk/gtkgc.c
@@ -0,0 +1,382 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtkgc.h"
+
+
+typedef struct _GtkGCKey GtkGCKey;
+typedef struct _GtkGCDrawable GtkGCDrawable;
+
+struct _GtkGCKey
+{
+ gint depth;
+ GdkColormap *colormap;
+ GdkGCValues values;
+ GdkGCValuesMask mask;
+};
+
+struct _GtkGCDrawable
+{
+ gint depth;
+ GdkPixmap *drawable;
+};
+
+
+static void gtk_gc_init (void);
+static GtkGCKey* gtk_gc_key_dup (GtkGCKey *key);
+static void gtk_gc_key_destroy (GtkGCKey *key);
+static gpointer gtk_gc_new (gpointer key);
+static void gtk_gc_destroy (gpointer value);
+static guint gtk_gc_key_hash (gpointer key);
+static guint gtk_gc_value_hash (gpointer value);
+static gint gtk_gc_key_compare (gpointer a,
+ gpointer b);
+static guint gtk_gc_drawable_hash (GtkGCDrawable *d);
+static gint gtk_gc_drawable_compare (GtkGCDrawable *a,
+ GtkGCDrawable *b);
+
+
+static gint initialize = TRUE;
+static GCache *gc_cache = NULL;
+static GHashTable *gc_drawable_ht = NULL;
+
+static GMemChunk *key_mem_chunk = NULL;
+
+
+GdkGC*
+gtk_gc_get (gint depth,
+ GdkColormap *colormap,
+ GdkGCValues *values,
+ GdkGCValuesMask values_mask)
+{
+ GtkGCKey key;
+ GdkGC *gc;
+
+ if (initialize)
+ gtk_gc_init ();
+
+ key.depth = depth;
+ key.colormap = colormap;
+ key.values = *values;
+ key.mask = values_mask;
+
+ gc = g_cache_insert (gc_cache, &key);
+
+ return gc;
+}
+
+void
+gtk_gc_release (GdkGC *gc)
+{
+ if (initialize)
+ gtk_gc_init ();
+
+ g_cache_remove (gc_cache, gc);
+}
+
+
+static void
+gtk_gc_init ()
+{
+ initialize = FALSE;
+
+ gc_cache = g_cache_new ((GCacheNewFunc) gtk_gc_new,
+ (GCacheDestroyFunc) gtk_gc_destroy,
+ (GCacheDupFunc) gtk_gc_key_dup,
+ (GCacheDestroyFunc) gtk_gc_key_destroy,
+ (GHashFunc) gtk_gc_key_hash,
+ (GHashFunc) gtk_gc_value_hash,
+ (GCompareFunc) gtk_gc_key_compare);
+
+ gc_drawable_ht = g_hash_table_new ((GHashFunc) gtk_gc_drawable_hash,
+ (GCompareFunc) gtk_gc_drawable_compare);
+}
+
+static GtkGCKey*
+gtk_gc_key_dup (GtkGCKey *key)
+{
+ GtkGCKey *new_key;
+
+ if (!key_mem_chunk)
+ key_mem_chunk = g_mem_chunk_new ("key mem chunk", sizeof (GtkGCKey),
+ 1024, G_ALLOC_AND_FREE);
+
+ new_key = g_chunk_new (GtkGCKey, key_mem_chunk);
+
+ *new_key = *key;
+
+ return new_key;
+}
+
+static void
+gtk_gc_key_destroy (GtkGCKey *key)
+{
+ g_mem_chunk_free (key_mem_chunk, key);
+}
+
+static gpointer
+gtk_gc_new (gpointer key)
+{
+ GtkGCKey *keyval;
+ GtkGCDrawable *drawable;
+ GdkGC *gc;
+
+ keyval = key;
+
+ drawable = g_hash_table_lookup (gc_drawable_ht, &keyval->depth);
+ if (!drawable)
+ {
+ drawable = g_new (GtkGCDrawable, 1);
+ drawable->depth = keyval->depth;
+ drawable->drawable = gdk_pixmap_new (NULL, 1, 1, drawable->depth);
+
+ g_hash_table_insert (gc_drawable_ht, &drawable->depth, drawable);
+ }
+
+ gc = gdk_gc_new_with_values (drawable->drawable, &keyval->values, keyval->mask);
+
+ return (gpointer) gc;
+}
+
+static void
+gtk_gc_destroy (gpointer value)
+{
+ gdk_gc_destroy ((GdkGC*) value);
+}
+
+static guint
+gtk_gc_key_hash (gpointer key)
+{
+ GtkGCKey *keyval;
+ guint hash_val;
+
+ keyval = key;
+ hash_val = 0;
+
+ if (keyval->mask & GDK_GC_FOREGROUND)
+ {
+ hash_val += keyval->values.foreground.pixel;
+ }
+ if (keyval->mask & GDK_GC_BACKGROUND)
+ {
+ hash_val += keyval->values.background.pixel;
+ }
+ if (keyval->mask & GDK_GC_FONT)
+ {
+ hash_val += gdk_font_id (keyval->values.font);
+ }
+ if (keyval->mask & GDK_GC_FUNCTION)
+ {
+ hash_val += (gint) keyval->values.function;
+ }
+ if (keyval->mask & GDK_GC_FILL)
+ {
+ hash_val += (gint) keyval->values.fill;
+ }
+ if (keyval->mask & GDK_GC_TILE)
+ {
+ hash_val += (glong) keyval->values.tile;
+ }
+ if (keyval->mask & GDK_GC_STIPPLE)
+ {
+ hash_val += (glong) keyval->values.stipple;
+ }
+ if (keyval->mask & GDK_GC_CLIP_MASK)
+ {
+ hash_val += (glong) keyval->values.clip_mask;
+ }
+ if (keyval->mask & GDK_GC_SUBWINDOW)
+ {
+ hash_val += (gint) keyval->values.subwindow_mode;
+ }
+ if (keyval->mask & GDK_GC_TS_X_ORIGIN)
+ {
+ hash_val += (gint) keyval->values.ts_x_origin;
+ }
+ if (keyval->mask & GDK_GC_TS_Y_ORIGIN)
+ {
+ hash_val += (gint) keyval->values.ts_y_origin;
+ }
+ if (keyval->mask & GDK_GC_CLIP_X_ORIGIN)
+ {
+ hash_val += (gint) keyval->values.clip_x_origin;
+ }
+ if (keyval->mask & GDK_GC_CLIP_Y_ORIGIN)
+ {
+ hash_val += (gint) keyval->values.clip_y_origin;
+ }
+ if (keyval->mask & GDK_GC_EXPOSURES)
+ {
+ hash_val += (gint) keyval->values.graphics_exposures;
+ }
+ if (keyval->mask & GDK_GC_LINE_WIDTH)
+ {
+ hash_val += (gint) keyval->values.line_width;
+ }
+ if (keyval->mask & GDK_GC_LINE_STYLE)
+ {
+ hash_val += (gint) keyval->values.line_style;
+ }
+ if (keyval->mask & GDK_GC_CAP_STYLE)
+ {
+ hash_val += (gint) keyval->values.cap_style;
+ }
+ if (keyval->mask & GDK_GC_JOIN_STYLE)
+ {
+ hash_val += (gint) keyval->values.join_style;
+ }
+
+ return hash_val;
+}
+
+static guint
+gtk_gc_value_hash (gpointer value)
+{
+ return (gulong) value;
+}
+
+static gint
+gtk_gc_key_compare (gpointer a,
+ gpointer b)
+{
+ GtkGCKey *akey;
+ GtkGCKey *bkey;
+ GdkGCValues *avalues;
+ GdkGCValues *bvalues;
+
+ akey = a;
+ bkey = b;
+
+ avalues = &akey->values;
+ bvalues = &bkey->values;
+
+ if (akey->mask != bkey->mask)
+ return FALSE;
+
+ if (akey->depth != bkey->depth)
+ return FALSE;
+
+ if (akey->colormap != bkey->colormap)
+ return FALSE;
+
+ if (akey->mask & GDK_GC_FOREGROUND)
+ {
+ if (avalues->foreground.pixel != bvalues->foreground.pixel)
+ return FALSE;
+ }
+ if (akey->mask & GDK_GC_BACKGROUND)
+ {
+ if (avalues->background.pixel != bvalues->background.pixel)
+ return FALSE;
+ }
+ if (akey->mask & GDK_GC_FONT)
+ {
+ if (!gdk_font_equal (avalues->font, bvalues->font))
+ return FALSE;
+ }
+ if (akey->mask & GDK_GC_FUNCTION)
+ {
+ if (avalues->function != bvalues->function)
+ return FALSE;
+ }
+ if (akey->mask & GDK_GC_FILL)
+ {
+ if (avalues->fill != bvalues->fill)
+ return FALSE;
+ }
+ if (akey->mask & GDK_GC_TILE)
+ {
+ if (avalues->tile != bvalues->tile)
+ return FALSE;
+ }
+ if (akey->mask & GDK_GC_STIPPLE)
+ {
+ if (avalues->stipple != bvalues->stipple)
+ return FALSE;
+ }
+ if (akey->mask & GDK_GC_CLIP_MASK)
+ {
+ if (avalues->clip_mask != bvalues->clip_mask)
+ return FALSE;
+ }
+ if (akey->mask & GDK_GC_SUBWINDOW)
+ {
+ if (avalues->subwindow_mode != bvalues->subwindow_mode)
+ return FALSE;
+ }
+ if (akey->mask & GDK_GC_TS_X_ORIGIN)
+ {
+ if (avalues->ts_x_origin != bvalues->ts_x_origin)
+ return FALSE;
+ }
+ if (akey->mask & GDK_GC_TS_Y_ORIGIN)
+ {
+ if (avalues->ts_y_origin != bvalues->ts_y_origin)
+ return FALSE;
+ }
+ if (akey->mask & GDK_GC_CLIP_X_ORIGIN)
+ {
+ if (avalues->clip_x_origin != bvalues->clip_x_origin)
+ return FALSE;
+ }
+ if (akey->mask & GDK_GC_CLIP_Y_ORIGIN)
+ {
+ if (avalues->clip_y_origin != bvalues->clip_y_origin)
+ return FALSE;
+ }
+ if (akey->mask & GDK_GC_EXPOSURES)
+ {
+ if (avalues->graphics_exposures != bvalues->graphics_exposures)
+ return FALSE;
+ }
+ if (akey->mask & GDK_GC_LINE_WIDTH)
+ {
+ if (avalues->line_width != bvalues->line_width)
+ return FALSE;
+ }
+ if (akey->mask & GDK_GC_LINE_STYLE)
+ {
+ if (avalues->line_style != bvalues->line_style)
+ return FALSE;
+ }
+ if (akey->mask & GDK_GC_CAP_STYLE)
+ {
+ if (avalues->cap_style != bvalues->cap_style)
+ return FALSE;
+ }
+ if (akey->mask & GDK_GC_JOIN_STYLE)
+ {
+ if (avalues->join_style != bvalues->join_style)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+static guint
+gtk_gc_drawable_hash (GtkGCDrawable *d)
+{
+ return d->depth;
+}
+
+static gint
+gtk_gc_drawable_compare (GtkGCDrawable *a,
+ GtkGCDrawable *b)
+{
+ return (a->depth == b->depth);
+}
diff --git a/gtk/gtkgc.h b/gtk/gtkgc.h
new file mode 100644
index 000000000..ff4ecc466
--- /dev/null
+++ b/gtk/gtkgc.h
@@ -0,0 +1,42 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_GC_H__
+#define __GTK_GC_H__
+
+
+#include <gdk/gdk.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+GdkGC* gtk_gc_get (gint depth,
+ GdkColormap *colormap,
+ GdkGCValues *values,
+ GdkGCValuesMask values_mask);
+void gtk_gc_release (GdkGC *gc);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_GC_H__ */
diff --git a/gtk/gtkhbbox.c b/gtk/gtkhbbox.c
new file mode 100644
index 000000000..9d86c010e
--- /dev/null
+++ b/gtk/gtkhbbox.c
@@ -0,0 +1,269 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "gtkhbbox.h"
+
+
+static void gtk_hbutton_box_class_init (GtkHButtonBoxClass *klass);
+static void gtk_hbutton_box_init (GtkHButtonBox *box);
+static void gtk_hbutton_box_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void gtk_hbutton_box_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+
+static gint default_spacing = 30;
+static gint default_layout_style = GTK_BUTTONBOX_EDGE;
+
+guint
+gtk_hbutton_box_get_type ()
+{
+ static guint hbutton_box_type = 0;
+
+ if (!hbutton_box_type)
+ {
+ GtkTypeInfo hbutton_box_info =
+ {
+ "GtkHButtonBox",
+ sizeof (GtkHButtonBox),
+ sizeof (GtkHButtonBoxClass),
+ (GtkClassInitFunc) gtk_hbutton_box_class_init,
+ (GtkObjectInitFunc) gtk_hbutton_box_init,
+ (GtkArgFunc) NULL,
+ };
+
+ hbutton_box_type = gtk_type_unique (gtk_button_box_get_type (), &hbutton_box_info);
+ }
+
+ return hbutton_box_type;
+}
+
+static void
+gtk_hbutton_box_class_init (GtkHButtonBoxClass *class)
+{
+ GtkWidgetClass *widget_class;
+
+ widget_class = (GtkWidgetClass*) class;
+
+ widget_class->size_request = gtk_hbutton_box_size_request;
+ widget_class->size_allocate = gtk_hbutton_box_size_allocate;
+}
+
+static void
+gtk_hbutton_box_init (GtkHButtonBox *hbutton_box)
+{
+ /* button_box_init has done everything allready */
+}
+
+GtkWidget*
+gtk_hbutton_box_new ()
+{
+ GtkHButtonBox *hbutton_box;
+
+ hbutton_box = gtk_type_new (gtk_hbutton_box_get_type ());
+
+ return GTK_WIDGET (hbutton_box);
+}
+
+
+/* set default value for spacing */
+
+void gtk_hbutton_box_set_spacing_default (gint spacing)
+{
+ default_spacing = spacing;
+}
+
+
+/* set default value for layout style */
+
+void gtk_hbutton_box_set_layout_default (gint layout)
+{
+ default_layout_style = layout;
+}
+
+/* get default value for spacing */
+
+gint gtk_hbutton_box_get_spacing_default (void)
+{
+ return default_spacing;
+}
+
+
+/* get default value for layout style */
+
+gint gtk_hbutton_box_get_layout_default (void)
+{
+ return default_layout_style;
+}
+
+
+
+static void
+gtk_hbutton_box_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkBox *box;
+ GtkButtonBox *bbox;
+ gint nvis_children;
+ gint child_width;
+ gint child_height;
+ gint spacing;
+ gint layout;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_HBUTTON_BOX (widget));
+ g_return_if_fail (requisition != NULL);
+
+ box = GTK_BOX (widget);
+ bbox = GTK_BUTTON_BOX (widget);
+
+ spacing = bbox->spacing != GTK_BUTTONBOX_DEFAULT
+ ? bbox->spacing : default_spacing;
+ layout = bbox->layout_style != GTK_BUTTONBOX_DEFAULT
+ ? bbox->layout_style : default_layout_style;
+
+ gtk_button_box_child_requisition (widget,
+ &nvis_children,
+ &child_width,
+ &child_height);
+
+ if (nvis_children == 0)
+ {
+ requisition->width = 0;
+ requisition->height = 0;
+ }
+ else
+ {
+ switch (layout)
+ {
+ case GTK_BUTTONBOX_SPREAD:
+ requisition->width =
+ nvis_children*child_width + ((nvis_children+1)*spacing);
+ break;
+ case GTK_BUTTONBOX_EDGE:
+ case GTK_BUTTONBOX_START:
+ case GTK_BUTTONBOX_END:
+ requisition->width = nvis_children*child_width + ((nvis_children-1)*spacing);
+ break;
+ default:
+ g_assert_not_reached();
+ break;
+ }
+
+ requisition->height = child_height;
+ }
+
+ requisition->width += GTK_CONTAINER (box)->border_width * 2;
+ requisition->height += GTK_CONTAINER (box)->border_width * 2;
+}
+
+
+
+static void
+gtk_hbutton_box_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkButtonBox *box;
+ GtkHButtonBox *hbox;
+ GtkBoxChild *child;
+ GList *children;
+ GtkAllocation child_allocation;
+ gint nvis_children;
+ gint child_width;
+ gint child_height;
+ gint x = 0;
+ gint y = 0;
+ gint width;
+ gint childspace;
+ gint childspacing = 0;
+ gint layout;
+ gint spacing;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_HBUTTON_BOX (widget));
+ g_return_if_fail (allocation != NULL);
+
+ box = GTK_BUTTON_BOX (widget);
+ hbox = GTK_HBUTTON_BOX (widget);
+ spacing = box->spacing != GTK_BUTTONBOX_DEFAULT
+ ? box->spacing : default_spacing;
+ layout = box->layout_style != GTK_BUTTONBOX_DEFAULT
+ ? box->layout_style : default_layout_style;
+ gtk_button_box_child_requisition (widget,
+ &nvis_children,
+ &child_width,
+ &child_height);
+ widget->allocation = *allocation;
+ width = allocation->width - GTK_CONTAINER (box)->border_width*2;
+ switch (layout)
+ {
+ case GTK_BUTTONBOX_SPREAD:
+ childspacing = (width - (nvis_children*child_width)) / (nvis_children+1);
+ x = allocation->x + GTK_CONTAINER (box)->border_width + childspacing;
+ break;
+ case GTK_BUTTONBOX_EDGE:
+ if (nvis_children >= 2)
+ {
+ childspacing =
+ (width - (nvis_children*child_width)) / (nvis_children-1);
+ x = allocation->x + GTK_CONTAINER (box)->border_width;
+ }
+ else
+ {
+ /* one or zero children, just center */
+ childspacing = width;
+ x = allocation->x + (allocation->width - child_width) / 2;
+ }
+ break;
+ case GTK_BUTTONBOX_START:
+ childspacing = spacing;
+ x = allocation->x + GTK_CONTAINER (box)->border_width;
+ break;
+ case GTK_BUTTONBOX_END:
+ childspacing = spacing;
+ x = allocation->x + allocation->width - child_width * nvis_children
+ - spacing *(nvis_children-1)
+ - GTK_CONTAINER (box)->border_width;
+ break;
+ default:
+ g_assert_not_reached();
+ break;
+ }
+
+
+ y = allocation->y + (allocation->height - child_height) / 2;
+ childspace = child_width + childspacing;
+
+ children = GTK_BOX (box)->children;
+
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_VISIBLE (child->widget))
+ {
+ child_allocation.width = child_width;
+ child_allocation.height = child_height;
+ child_allocation.x = x;
+ child_allocation.y = y;
+ gtk_widget_size_allocate (child->widget, &child_allocation);
+ x += childspace;
+ }
+ }
+}
+
diff --git a/gtk/gtkhbbox.h b/gtk/gtkhbbox.h
new file mode 100644
index 000000000..c61c138b9
--- /dev/null
+++ b/gtk/gtkhbbox.h
@@ -0,0 +1,66 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_HBUTTON_BOX_H__
+#define __GTK_HBUTTON_BOX_H__
+
+
+#include "gtk/gtkbbox.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_HBUTTON_BOX(obj) GTK_CHECK_CAST (obj, gtk_hbutton_box_get_type (), GtkHButtonBox)
+#define GTK_HBUTTON_BOX_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_hbutton_box_get_type (), GtkHButtonBoxClass)
+#define GTK_IS_HBUTTON_BOX(obj) GTK_CHECK_TYPE (obj, gtk_hbutton_box_get_type ())
+
+
+typedef struct _GtkHButtonBox GtkHButtonBox;
+typedef struct _GtkHButtonBoxClass GtkHButtonBoxClass;
+
+struct _GtkHButtonBox
+{
+ GtkButtonBox button_box;
+};
+
+struct _GtkHButtonBoxClass
+{
+ GtkButtonBoxClass parent_class;
+};
+
+
+guint gtk_hbutton_box_get_type (void);
+GtkWidget *gtk_hbutton_box_new (void);
+
+/* buttons can be added by gtk_container_add() */
+
+gint gtk_hbutton_box_get_spacing_default (void);
+gint gtk_hbutton_box_get_layout_default (void);
+
+void gtk_hbutton_box_set_spacing_default (gint spacing);
+void gtk_hbutton_box_set_layout_default (gint layout);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_HBUTTON_BOX_H__ */
diff --git a/gtk/gtkhbox.c b/gtk/gtkhbox.c
new file mode 100644
index 000000000..4cdc926cd
--- /dev/null
+++ b/gtk/gtkhbox.c
@@ -0,0 +1,306 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtkhbox.h"
+
+
+static void gtk_hbox_class_init (GtkHBoxClass *klass);
+static void gtk_hbox_init (GtkHBox *box);
+static void gtk_hbox_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void gtk_hbox_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+
+
+guint
+gtk_hbox_get_type ()
+{
+ static guint hbox_type = 0;
+
+ if (!hbox_type)
+ {
+ GtkTypeInfo hbox_info =
+ {
+ "GtkHBox",
+ sizeof (GtkHBox),
+ sizeof (GtkHBoxClass),
+ (GtkClassInitFunc) gtk_hbox_class_init,
+ (GtkObjectInitFunc) gtk_hbox_init,
+ (GtkArgFunc) NULL,
+ };
+
+ hbox_type = gtk_type_unique (gtk_box_get_type (), &hbox_info);
+ }
+
+ return hbox_type;
+}
+
+static void
+gtk_hbox_class_init (GtkHBoxClass *class)
+{
+ GtkWidgetClass *widget_class;
+
+ widget_class = (GtkWidgetClass*) class;
+
+ widget_class->size_request = gtk_hbox_size_request;
+ widget_class->size_allocate = gtk_hbox_size_allocate;
+}
+
+static void
+gtk_hbox_init (GtkHBox *hbox)
+{
+}
+
+GtkWidget*
+gtk_hbox_new (gint homogeneous,
+ gint spacing)
+{
+ GtkHBox *hbox;
+
+ hbox = gtk_type_new (gtk_hbox_get_type ());
+
+ GTK_BOX (hbox)->spacing = spacing;
+ GTK_BOX (hbox)->homogeneous = homogeneous ? TRUE : FALSE;
+
+ return GTK_WIDGET (hbox);
+}
+
+
+static void
+gtk_hbox_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkBox *box;
+ GtkBoxChild *child;
+ GList *children;
+ gint nvis_children;
+ gint width;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_HBOX (widget));
+ g_return_if_fail (requisition != NULL);
+
+ box = GTK_BOX (widget);
+ requisition->width = 0;
+ requisition->height = 0;
+ nvis_children = 0;
+
+ children = box->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_VISIBLE (child->widget))
+ {
+ gtk_widget_size_request (child->widget, &child->widget->requisition);
+
+ if (box->homogeneous)
+ {
+ width = child->widget->requisition.width + child->padding * 2;
+ requisition->width = MAX (requisition->width, width);
+ }
+ else
+ {
+ requisition->width += child->widget->requisition.width + child->padding * 2;
+ }
+
+ requisition->height = MAX (requisition->height, child->widget->requisition.height);
+
+ nvis_children += 1;
+ }
+ }
+
+ if (nvis_children > 0)
+ {
+ if (box->homogeneous)
+ requisition->width *= nvis_children;
+ requisition->width += (nvis_children - 1) * box->spacing;
+ }
+
+ requisition->width += GTK_CONTAINER (box)->border_width * 2;
+ requisition->height += GTK_CONTAINER (box)->border_width * 2;
+}
+
+static void
+gtk_hbox_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkBox *box;
+ GtkBoxChild *child;
+ GList *children;
+ GtkAllocation child_allocation;
+ gint nvis_children;
+ gint nexpand_children;
+ gint child_width;
+ gint width;
+ gint extra;
+ gint x;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_HBOX (widget));
+ g_return_if_fail (allocation != NULL);
+
+ box = GTK_BOX (widget);
+ widget->allocation = *allocation;
+
+ nvis_children = 0;
+ nexpand_children = 0;
+ children = box->children;
+
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_VISIBLE (child->widget))
+ {
+ nvis_children += 1;
+ if (child->expand)
+ nexpand_children += 1;
+ }
+ }
+
+ if (nvis_children > 0)
+ {
+ if (box->homogeneous)
+ {
+ width = (allocation->width -
+ GTK_CONTAINER (box)->border_width * 2 -
+ (nvis_children - 1) * box->spacing);
+ extra = width / nvis_children;
+ }
+ else if (nexpand_children > 0)
+ {
+ width = allocation->width - widget->requisition.width;
+ extra = width / nexpand_children;
+ }
+ else
+ {
+ width = 0;
+ extra = 0;
+ }
+
+ x = allocation->x + GTK_CONTAINER (box)->border_width;
+ child_allocation.y = allocation->y + GTK_CONTAINER (box)->border_width;
+ child_allocation.height = allocation->height - GTK_CONTAINER (box)->border_width * 2;
+
+ children = box->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if ((child->pack == GTK_PACK_START) && GTK_WIDGET_VISIBLE (child->widget))
+ {
+ if (box->homogeneous)
+ {
+ if (nvis_children == 1)
+ child_width = width;
+ else
+ child_width = extra;
+
+ nvis_children -= 1;
+ width -= extra;
+ }
+ else
+ {
+ child_width = child->widget->requisition.width + child->padding * 2;
+
+ if (child->expand)
+ {
+ if (nexpand_children == 1)
+ child_width += width;
+ else
+ child_width += extra;
+
+ nexpand_children -= 1;
+ width -= extra;
+ }
+ }
+
+ if (child->fill)
+ {
+ child_allocation.width = child_width - child->padding * 2;
+ child_allocation.x = x + child->padding;
+ }
+ else
+ {
+ child_allocation.width = child->widget->requisition.width;
+ child_allocation.x = x + (child_width - child_allocation.width) / 2;
+ }
+
+ gtk_widget_size_allocate (child->widget, &child_allocation);
+
+ x += child_width + box->spacing;
+ }
+ }
+
+ x = allocation->x + allocation->width - GTK_CONTAINER (box)->border_width;
+
+ children = box->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if ((child->pack == GTK_PACK_END) && GTK_WIDGET_VISIBLE (child->widget))
+ {
+ if (box->homogeneous)
+ {
+ if (nvis_children == 1)
+ child_width = width;
+ else
+ child_width = extra;
+
+ nvis_children -= 1;
+ width -= extra;
+ }
+ else
+ {
+ child_width = child->widget->requisition.width + child->padding * 2;
+
+ if (child->expand)
+ {
+ if (nexpand_children == 1)
+ child_width += width;
+ else
+ child_width += extra;
+
+ nexpand_children -= 1;
+ width -= extra;
+ }
+ }
+
+ if (child->fill)
+ {
+ child_allocation.width = child_width - child->padding * 2;
+ child_allocation.x = x + child->padding - child_width;
+ }
+ else
+ {
+ child_allocation.width = child->widget->requisition.width;
+ child_allocation.x = x + (child_width - child_allocation.width) / 2 - child_width;
+ }
+
+ gtk_widget_size_allocate (child->widget, &child_allocation);
+
+ x -= (child_width + box->spacing);
+ }
+ }
+ }
+}
diff --git a/gtk/gtkhbox.h b/gtk/gtkhbox.h
new file mode 100644
index 000000000..7dfbb3dff
--- /dev/null
+++ b/gtk/gtkhbox.h
@@ -0,0 +1,60 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_HBOX_H__
+#define __GTK_HBOX_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkbox.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_HBOX(obj) GTK_CHECK_CAST (obj, gtk_hbox_get_type (), GtkHBox)
+#define GTK_HBOX_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_hbox_get_type (), GtkHBoxClass)
+#define GTK_IS_HBOX(obj) GTK_CHECK_TYPE (obj, gtk_hbox_get_type ())
+
+
+typedef struct _GtkHBox GtkHBox;
+typedef struct _GtkHBoxClass GtkHBoxClass;
+
+struct _GtkHBox
+{
+ GtkBox box;
+};
+
+struct _GtkHBoxClass
+{
+ GtkBoxClass parent_class;
+};
+
+
+guint gtk_hbox_get_type (void);
+GtkWidget* gtk_hbox_new (gint homogeneous,
+ gint spacing);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_HBOX_H__ */
diff --git a/gtk/gtkhpaned.c b/gtk/gtkhpaned.c
new file mode 100644
index 000000000..23c50961e
--- /dev/null
+++ b/gtk/gtkhpaned.c
@@ -0,0 +1,355 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtkhpaned.h"
+#include "gtkmain.h"
+#include "gtksignal.h"
+
+static void gtk_hpaned_class_init (GtkHPanedClass *klass);
+static void gtk_hpaned_init (GtkHPaned *hpaned);
+static void gtk_hpaned_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void gtk_hpaned_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static void gtk_hpaned_draw (GtkWidget *widget,
+ GdkRectangle *area);
+static void gtk_hpaned_xor_line (GtkPaned *paned);
+static gint gtk_hpaned_button_press (GtkWidget *widget,
+ GdkEventButton *event);
+static gint gtk_hpaned_button_release (GtkWidget *widget,
+ GdkEventButton *event);
+static gint gtk_hpaned_motion (GtkWidget *widget,
+ GdkEventMotion *event);
+
+guint
+gtk_hpaned_get_type ()
+{
+ static guint hpaned_type = 0;
+
+ if (!hpaned_type)
+ {
+ GtkTypeInfo hpaned_info =
+ {
+ "GtkHPaned",
+ sizeof (GtkHPaned),
+ sizeof (GtkHPanedClass),
+ (GtkClassInitFunc) gtk_hpaned_class_init,
+ (GtkObjectInitFunc) gtk_hpaned_init,
+ (GtkArgFunc) NULL,
+ };
+
+ hpaned_type = gtk_type_unique (gtk_paned_get_type (), &hpaned_info);
+ }
+
+ return hpaned_type;
+}
+
+static void
+gtk_hpaned_class_init (GtkHPanedClass *class)
+{
+ GtkWidgetClass *widget_class;
+
+ widget_class = (GtkWidgetClass*) class;
+
+ widget_class->size_request = gtk_hpaned_size_request;
+ widget_class->size_allocate = gtk_hpaned_size_allocate;
+ widget_class->draw = gtk_hpaned_draw;
+ widget_class->button_press_event = gtk_hpaned_button_press;
+ widget_class->button_release_event = gtk_hpaned_button_release;
+ widget_class->motion_notify_event = gtk_hpaned_motion;
+}
+
+static void
+gtk_hpaned_init (GtkHPaned *hpaned)
+{
+}
+
+GtkWidget*
+gtk_hpaned_new ()
+{
+ GtkHPaned *hpaned;
+
+ hpaned = gtk_type_new (gtk_hpaned_get_type ());
+
+ return GTK_WIDGET (hpaned);
+}
+
+static void
+gtk_hpaned_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkPaned *paned;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_HPANED (widget));
+ g_return_if_fail (requisition != NULL);
+
+ paned = GTK_PANED (widget);
+ requisition->width = 0;
+ requisition->height = 0;
+
+ if (paned->child1 && GTK_WIDGET_VISIBLE (paned->child1))
+ {
+ gtk_widget_size_request (paned->child1, &paned->child1->requisition);
+
+ requisition->height = paned->child1->requisition.height;
+ requisition->width = paned->child1->requisition.width;
+ }
+
+ if (paned->child2 && GTK_WIDGET_VISIBLE (paned->child2))
+ {
+ gtk_widget_size_request (paned->child2, &paned->child2->requisition);
+
+ requisition->height = MAX(requisition->height,
+ paned->child2->requisition.height);
+ requisition->width += paned->child2->requisition.width;
+ }
+
+ requisition->width += GTK_CONTAINER (paned)->border_width * 2 + paned->gutter_size;
+ requisition->height += GTK_CONTAINER (paned)->border_width * 2;
+}
+
+static void
+gtk_hpaned_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkPaned *paned;
+ GtkAllocation child1_allocation;
+ GtkAllocation child2_allocation;
+ guint16 border_width;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_HPANED (widget));
+ g_return_if_fail (allocation != NULL);
+
+ widget->allocation = *allocation;
+
+ paned = GTK_PANED (widget);
+ border_width = GTK_CONTAINER (paned)->border_width;
+
+ if (!paned->position_set)
+ {
+ if (paned->child1 && GTK_WIDGET_VISIBLE (paned->child1))
+ paned->child1_size = paned->child1->requisition.width;
+ else
+ paned->child1_size = 0;
+ }
+
+ /* Move the handle first so we don't get extra expose events */
+
+ paned->handle_xpos = allocation->x + paned->child1_size + border_width + paned->gutter_size / 2 - paned->handle_size / 2;
+ paned->handle_ypos = allocation->y + allocation->height - border_width - 2*paned->handle_size;
+
+ if (GTK_WIDGET_REALIZED (widget))
+ {
+ gdk_window_move (paned->handle, paned->handle_xpos, paned->handle_ypos);
+ gdk_window_raise (paned->handle);
+ }
+
+ if (GTK_WIDGET_MAPPED (widget))
+ {
+ gdk_window_clear_area (widget->window,
+ paned->groove_rectangle.x,
+ paned->groove_rectangle.y,
+ paned->groove_rectangle.width,
+ paned->groove_rectangle.height);
+ }
+
+ child1_allocation.height = child2_allocation.height = allocation->height - border_width * 2;
+ child1_allocation.width = paned->child1_size;
+ child1_allocation.x = allocation->x + border_width;
+ child1_allocation.y = child2_allocation.y = allocation->y + border_width;
+
+ paned->groove_rectangle.x = child1_allocation.x
+ + child1_allocation.width + paned->gutter_size / 2 - 1;
+ paned->groove_rectangle.y = allocation->y;
+ paned->groove_rectangle.width = 2;
+ paned->groove_rectangle.height = allocation->height;
+
+ child2_allocation.x = paned->groove_rectangle.x + paned->gutter_size / 2 + 1;
+ child2_allocation.width = allocation->x + allocation->width
+ - child2_allocation.x - border_width;
+
+ /* Now allocate the childen, making sure, when resizing not to
+ * overlap the windows */
+ if (GTK_WIDGET_MAPPED(widget) &&
+ paned->child1 && GTK_WIDGET_VISIBLE (paned->child1) &&
+ paned->child1->allocation.width < child1_allocation.width)
+ {
+ if (paned->child2 && GTK_WIDGET_VISIBLE (paned->child2))
+ gtk_widget_size_allocate (paned->child2, &child2_allocation);
+ gtk_widget_size_allocate (paned->child1, &child1_allocation);
+ }
+ else
+ {
+ if (paned->child1 && GTK_WIDGET_VISIBLE (paned->child1))
+ gtk_widget_size_allocate (paned->child1, &child1_allocation);
+ if (paned->child2 && GTK_WIDGET_VISIBLE (paned->child2))
+ gtk_widget_size_allocate (paned->child2, &child2_allocation);
+ }
+}
+
+static void
+gtk_hpaned_draw (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ GtkPaned *paned;
+ GdkRectangle child_area;
+ guint16 border_width;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_PANED (widget));
+
+ if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget))
+ {
+ paned = GTK_PANED (widget);
+ border_width = GTK_CONTAINER (paned)->border_width;
+
+ if (paned->child1 &&
+ gtk_widget_intersect (paned->child1, area, &child_area))
+ gtk_widget_draw (paned->child1, &child_area);
+ if (paned->child2 &&
+ gtk_widget_intersect (paned->child2, area, &child_area))
+ gtk_widget_draw (paned->child2, &child_area);
+
+ gdk_draw_line (widget->window,
+ widget->style->dark_gc[widget->state],
+ widget->allocation.x + border_width + paned->child1_size + paned->gutter_size / 2 - 1,
+ widget->allocation.y,
+ widget->allocation.x + border_width + paned->child1_size + paned->gutter_size / 2 - 1,
+ widget->allocation.y + widget->allocation.height - 1);
+ gdk_draw_line (widget->window,
+ widget->style->light_gc[widget->state],
+ widget->allocation.x + border_width + paned->child1_size + paned->gutter_size / 2,
+ widget->allocation.y,
+ widget->allocation.x + border_width + paned->child1_size + paned->gutter_size / 2,
+ widget->allocation.y + widget->allocation.height - 1);
+ }
+}
+
+static void
+gtk_hpaned_xor_line (GtkPaned *paned)
+{
+ GtkWidget *widget;
+ GdkGCValues values;
+ guint16 xpos;
+
+ widget = GTK_WIDGET(paned);
+
+ if (!paned->xor_gc)
+ {
+ values.foreground = widget->style->white;
+ values.function = GDK_XOR;
+ values.subwindow_mode = GDK_INCLUDE_INFERIORS;
+ paned->xor_gc = gdk_gc_new_with_values (widget->window,
+ &values,
+ GDK_GC_FOREGROUND |
+ GDK_GC_FUNCTION |
+ GDK_GC_SUBWINDOW);
+ }
+
+ xpos = widget->allocation.x + paned->child1_size
+ + GTK_CONTAINER(paned)->border_width + paned->gutter_size / 2;
+
+ gdk_draw_line (widget->window, paned->xor_gc,
+ xpos,
+ widget->allocation.y,
+ xpos,
+ widget->allocation.y + widget->allocation.height - 1);
+}
+
+static gint
+gtk_hpaned_button_press (GtkWidget *widget, GdkEventButton *event)
+{
+ GtkPaned *paned;
+
+ g_return_val_if_fail (widget != NULL,FALSE);
+ g_return_val_if_fail (GTK_IS_PANED (widget),FALSE);
+
+ paned = GTK_PANED (widget);
+
+ if (!paned->in_drag &&
+ (event->window == paned->handle) && (event->button == 1))
+ {
+ paned->in_drag = TRUE;
+ /* We need a server grab here, not gtk_grab_add(), since
+ * we don't want to pass events on to the widget's children */
+ gdk_pointer_grab (paned->handle, FALSE,
+ GDK_POINTER_MOTION_HINT_MASK
+ | GDK_BUTTON1_MOTION_MASK
+ | GDK_BUTTON_RELEASE_MASK,
+ NULL, NULL, event->time);
+ paned->child1_size += event->x - paned->handle_size / 2;
+ paned->child1_size = CLAMP (paned->child1_size, 0,
+ widget->allocation.width - paned->gutter_size
+ - 2 * GTK_CONTAINER (paned)->border_width);
+ gtk_hpaned_xor_line (paned);
+ }
+
+ return TRUE;
+}
+
+static gint
+gtk_hpaned_button_release (GtkWidget *widget, GdkEventButton *event)
+{
+ GtkPaned *paned;
+
+ g_return_val_if_fail (widget != NULL,FALSE);
+ g_return_val_if_fail (GTK_IS_PANED (widget),FALSE);
+
+ paned = GTK_PANED (widget);
+
+ if (paned->in_drag && (event->button == 1))
+ {
+ gtk_hpaned_xor_line (paned);
+ paned->in_drag = FALSE;
+ paned->position_set = TRUE;
+ gdk_pointer_ungrab (event->time);
+ gtk_widget_queue_resize (GTK_WIDGET (paned));
+ }
+
+ return TRUE;
+}
+
+static gint
+gtk_hpaned_motion (GtkWidget *widget, GdkEventMotion *event)
+{
+ GtkPaned *paned;
+ gint x;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_PANED (widget), FALSE);
+
+ if (event->is_hint || event->window != widget->window)
+ gtk_widget_get_pointer(widget, &x, NULL);
+ else
+ x = event->x;
+
+ paned = GTK_PANED (widget);
+
+ if (paned->in_drag)
+ {
+ gtk_hpaned_xor_line (paned);
+ paned->child1_size = x - GTK_CONTAINER (paned)->border_width - paned->gutter_size / 2;
+ paned->child1_size = CLAMP (paned->child1_size, 0,
+ widget->allocation.width - paned->gutter_size
+ - 2 * GTK_CONTAINER (paned)->border_width);
+ gtk_hpaned_xor_line (paned);
+ }
+
+ return TRUE;
+}
diff --git a/gtk/gtkhpaned.h b/gtk/gtkhpaned.h
new file mode 100644
index 000000000..0a352e799
--- /dev/null
+++ b/gtk/gtkhpaned.h
@@ -0,0 +1,59 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_HPANED_H__
+#define __GTK_HPANED_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkpaned.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_HPANED(obj) GTK_CHECK_CAST (obj, gtk_hpaned_get_type (), GtkHPaned)
+#define GTK_HPANED_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_hpaned_get_type (), GtkHPanedClass)
+#define GTK_IS_HPANED(obj) GTK_CHECK_TYPE (obj, gtk_hpaned_get_type ())
+
+
+typedef struct _GtkHPaned GtkHPaned;
+typedef struct _GtkHPanedClass GtkHPanedClass;
+
+struct _GtkHPaned
+{
+ GtkPaned paned;
+};
+
+struct _GtkHPanedClass
+{
+ GtkPanedClass parent_class;
+};
+
+
+guint gtk_hpaned_get_type (void);
+GtkWidget* gtk_hpaned_new ();
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_HPANED_H__ */
diff --git a/gtk/gtkhruler.c b/gtk/gtkhruler.c
new file mode 100644
index 000000000..ab6e69199
--- /dev/null
+++ b/gtk/gtkhruler.c
@@ -0,0 +1,277 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include "gtkhruler.h"
+
+
+#define RULER_HEIGHT 14
+#define MINIMUM_INCR 5
+#define MAXIMUM_SUBDIVIDE 5
+#define MAXIMUM_SCALES 10
+
+#define ROUND(x) ((int) ((x) + 0.5))
+
+
+static void gtk_hruler_class_init (GtkHRulerClass *klass);
+static void gtk_hruler_init (GtkHRuler *hruler);
+static gint gtk_hruler_motion_notify (GtkWidget *widget,
+ GdkEventMotion *event);
+static void gtk_hruler_draw_ticks (GtkRuler *ruler);
+static void gtk_hruler_draw_pos (GtkRuler *ruler);
+
+
+guint
+gtk_hruler_get_type ()
+{
+ static guint hruler_type = 0;
+
+ if (!hruler_type)
+ {
+ GtkTypeInfo hruler_info =
+ {
+ "GtkHRuler",
+ sizeof (GtkHRuler),
+ sizeof (GtkHRulerClass),
+ (GtkClassInitFunc) gtk_hruler_class_init,
+ (GtkObjectInitFunc) gtk_hruler_init,
+ (GtkArgFunc) NULL,
+ };
+
+ hruler_type = gtk_type_unique (gtk_ruler_get_type (), &hruler_info);
+ }
+
+ return hruler_type;
+}
+
+static void
+gtk_hruler_class_init (GtkHRulerClass *klass)
+{
+ GtkWidgetClass *widget_class;
+ GtkRulerClass *ruler_class;
+
+ widget_class = (GtkWidgetClass*) klass;
+ ruler_class = (GtkRulerClass*) klass;
+
+ widget_class->motion_notify_event = gtk_hruler_motion_notify;
+
+ ruler_class->draw_ticks = gtk_hruler_draw_ticks;
+ ruler_class->draw_pos = gtk_hruler_draw_pos;
+}
+
+static void
+gtk_hruler_init (GtkHRuler *hruler)
+{
+ GtkWidget *widget;
+
+ widget = GTK_WIDGET (hruler);
+ widget->requisition.width = widget->style->klass->xthickness * 2 + 1;
+ widget->requisition.height = widget->style->klass->ythickness * 2 + RULER_HEIGHT;
+}
+
+
+GtkWidget*
+gtk_hruler_new ()
+{
+ return GTK_WIDGET (gtk_type_new (gtk_hruler_get_type ()));
+}
+
+static gint
+gtk_hruler_motion_notify (GtkWidget *widget,
+ GdkEventMotion *event)
+{
+ GtkRuler *ruler;
+ gint x;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_HRULER (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ ruler = GTK_RULER (widget);
+
+ if (event->is_hint)
+ gdk_window_get_pointer (widget->window, &x, NULL, NULL);
+ else
+ x = event->x;
+
+ ruler->position = ruler->lower + ((ruler->upper - ruler->lower) * x) / widget->allocation.width;
+
+ /* Make sure the ruler has been allocated already */
+ if (ruler->backing_store != NULL)
+ gtk_ruler_draw_pos (ruler);
+
+ return FALSE;
+}
+
+static void
+gtk_hruler_draw_ticks (GtkRuler *ruler)
+{
+ GtkWidget *widget;
+ GdkGC *gc;
+ gint i;
+ gint width, height;
+ gint xthickness;
+ gint ythickness;
+ gint length;
+ gfloat subd_incr;
+ gfloat step_incr;
+ gfloat increment;
+ gfloat start, end, cur;
+ gchar unit_str[12];
+ gint text_height;
+ gint digit_height;
+ gint pos;
+ gint scale;
+
+ g_return_if_fail (ruler != NULL);
+ g_return_if_fail (GTK_IS_HRULER (ruler));
+
+ if (GTK_WIDGET_DRAWABLE (ruler))
+ {
+ widget = GTK_WIDGET (ruler);
+
+ gc = widget->style->fg_gc[GTK_STATE_NORMAL];
+ xthickness = widget->style->klass->xthickness;
+ ythickness = widget->style->klass->ythickness;
+ digit_height = widget->style->font->ascent;
+
+ width = widget->allocation.width;
+ height = widget->allocation.height - ythickness * 2;
+ gdk_draw_line (ruler->backing_store, gc,
+ xthickness,
+ height + ythickness,
+ widget->allocation.width - xthickness,
+ height + ythickness);
+
+ if ((ruler->upper - ruler->lower) == 0)
+ return;
+
+ increment = (gfloat) width * ruler->metric->pixels_per_unit / (ruler->upper - ruler->lower);
+
+ /* determine the scale
+ * use the maximum extents of the ruler to determine the largest possible
+ * number to be displayed. calculate the height in pixels of this displayed
+ * text as for the vertical ruler case. use this height to find a scale
+ * which leaves sufficient room for drawing the ruler.
+ */
+ scale = ceil (ruler->max_size / ruler->metric->pixels_per_unit);
+ sprintf (unit_str, "%d", scale);
+ text_height = strlen (unit_str) * digit_height + 1;
+
+ for (scale = 0; scale < MAXIMUM_SCALES; scale++)
+ if (ruler->metric->ruler_scale[scale] * increment > 2 * text_height)
+ break;
+
+ if (scale == MAXIMUM_SCALES)
+ scale = MAXIMUM_SCALES - 1;
+
+ for (i = 0; i < MAXIMUM_SUBDIVIDE; i++)
+ {
+ subd_incr = (gfloat) ruler->metric->ruler_scale[scale] / (gfloat) ruler->metric->subdivide[i];
+ step_incr = subd_incr * increment;
+ if (step_incr <= MINIMUM_INCR)
+ break;
+
+ start = floor ((ruler->lower / ruler->metric->pixels_per_unit) / subd_incr) * subd_incr;
+ end = ceil ((ruler->upper / ruler->metric->pixels_per_unit) / subd_incr) * subd_incr;
+
+ length = height / (i + 1) - 1;
+ if (i > 0)
+ length -= 2;
+
+ cur = start;
+ while (cur <= end)
+ {
+ pos = ROUND ((cur - (ruler->lower / ruler->metric->pixels_per_unit)) * increment);
+
+ gdk_draw_line (ruler->backing_store, gc,
+ pos, height + ythickness, pos,
+ height - length + ythickness);
+ if (i == 0)
+ {
+ sprintf (unit_str, "%d", (int) cur);
+ gdk_draw_string (ruler->backing_store, widget->style->font, gc,
+ pos + 2,
+ ythickness + digit_height - 1,
+ unit_str);
+ }
+
+ cur += subd_incr;
+ }
+ }
+ }
+}
+
+static void
+gtk_hruler_draw_pos (GtkRuler *ruler)
+{
+ GtkWidget *widget;
+ GdkGC *gc;
+ int i;
+ gint x, y;
+ gint width, height;
+ gint bs_width, bs_height;
+ gint xthickness;
+ gint ythickness;
+ gfloat increment;
+
+ g_return_if_fail (ruler != NULL);
+ g_return_if_fail (GTK_IS_HRULER (ruler));
+
+ if (GTK_WIDGET_DRAWABLE (ruler))
+ {
+ widget = GTK_WIDGET (ruler);
+
+ gc = widget->style->fg_gc[GTK_STATE_NORMAL];
+ xthickness = widget->style->klass->xthickness;
+ ythickness = widget->style->klass->ythickness;
+ width = widget->allocation.width;
+ height = widget->allocation.height - ythickness * 2;
+
+ bs_width = height / 2;
+ bs_width |= 1; /* make sure it's odd */
+ bs_height = bs_width / 2 + 1;
+
+ if ((bs_width > 0) && (bs_height > 0))
+ {
+ /* If a backing store exists, restore the ruler */
+ if (ruler->backing_store && ruler->non_gr_exp_gc)
+ gdk_draw_pixmap (ruler->widget.window,
+ ruler->non_gr_exp_gc,
+ ruler->backing_store,
+ ruler->xsrc, ruler->ysrc,
+ ruler->xsrc, ruler->ysrc,
+ bs_width, bs_height);
+
+ increment = (gfloat) width / (ruler->upper - ruler->lower);
+
+ x = ROUND ((ruler->position - ruler->lower) * increment) + (xthickness - bs_width) / 2 - 1;
+ y = (height + bs_height) / 2 + ythickness;
+
+ for (i = 0; i < bs_height; i++)
+ gdk_draw_line (widget->window, gc,
+ x + i, y + i,
+ x + bs_width - 1 - i, y + i);
+
+
+ ruler->xsrc = x;
+ ruler->ysrc = y;
+ }
+ }
+}
diff --git a/gtk/gtkhruler.h b/gtk/gtkhruler.h
new file mode 100644
index 000000000..c4bc74436
--- /dev/null
+++ b/gtk/gtkhruler.h
@@ -0,0 +1,59 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_HRULER_H__
+#define __GTK_HRULER_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkruler.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_HRULER(obj) GTK_CHECK_CAST (obj, gtk_hruler_get_type (), GtkHRuler)
+#define GTK_HRULER_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_hruler_get_type (), GtkHRulerClass)
+#define GTK_IS_HRULER(obj) GTK_CHECK_TYPE (obj, gtk_hruler_get_type ())
+
+
+typedef struct _GtkHRuler GtkHRuler;
+typedef struct _GtkHRulerClass GtkHRulerClass;
+
+struct _GtkHRuler
+{
+ GtkRuler ruler;
+};
+
+struct _GtkHRulerClass
+{
+ GtkRulerClass parent_class;
+};
+
+
+guint gtk_hruler_get_type (void);
+GtkWidget* gtk_hruler_new (void);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_HRULER_H__ */
diff --git a/gtk/gtkhscale.c b/gtk/gtkhscale.c
new file mode 100644
index 000000000..3bebd30fc
--- /dev/null
+++ b/gtk/gtkhscale.c
@@ -0,0 +1,436 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdio.h>
+#include "gtkhscale.h"
+#include "gtksignal.h"
+#include "gdk/gdkkeysyms.h"
+
+
+#define SCALE_CLASS(w) GTK_SCALE_CLASS (GTK_OBJECT (w)->klass)
+#define RANGE_CLASS(w) GTK_RANGE_CLASS (GTK_OBJECT (w)->klass)
+
+
+static void gtk_hscale_class_init (GtkHScaleClass *klass);
+static void gtk_hscale_init (GtkHScale *hscale);
+static void gtk_hscale_realize (GtkWidget *widget);
+static void gtk_hscale_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void gtk_hscale_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static void gtk_hscale_pos_trough (GtkHScale *hscale,
+ gint *x,
+ gint *y,
+ gint *w,
+ gint *h);
+static void gtk_hscale_draw_slider (GtkRange *range);
+static void gtk_hscale_draw_value (GtkScale *scale);
+static gint gtk_hscale_trough_keys (GtkRange *range,
+ GdkEventKey *key,
+ GtkScrollType *scroll,
+ GtkTroughType *pos);
+
+guint
+gtk_hscale_get_type ()
+{
+ static guint hscale_type = 0;
+
+ if (!hscale_type)
+ {
+ GtkTypeInfo hscale_info =
+ {
+ "GtkHScale",
+ sizeof (GtkHScale),
+ sizeof (GtkHScaleClass),
+ (GtkClassInitFunc) gtk_hscale_class_init,
+ (GtkObjectInitFunc) gtk_hscale_init,
+ (GtkArgFunc) NULL,
+ };
+
+ hscale_type = gtk_type_unique (gtk_scale_get_type (), &hscale_info);
+ }
+
+ return hscale_type;
+}
+
+static void
+gtk_hscale_class_init (GtkHScaleClass *class)
+{
+ GtkWidgetClass *widget_class;
+ GtkRangeClass *range_class;
+ GtkScaleClass *scale_class;
+
+ widget_class = (GtkWidgetClass*) class;
+ range_class = (GtkRangeClass*) class;
+ scale_class = (GtkScaleClass*) class;
+
+ widget_class->realize = gtk_hscale_realize;
+ widget_class->size_request = gtk_hscale_size_request;
+ widget_class->size_allocate = gtk_hscale_size_allocate;
+
+ range_class->slider_update = gtk_range_default_hslider_update;
+ range_class->trough_click = gtk_range_default_htrough_click;
+ range_class->motion = gtk_range_default_hmotion;
+ range_class->draw_slider = gtk_hscale_draw_slider;
+ range_class->trough_keys = gtk_hscale_trough_keys;
+
+ scale_class->draw_value = gtk_hscale_draw_value;
+}
+
+static void
+gtk_hscale_init (GtkHScale *hscale)
+{
+}
+
+GtkWidget*
+gtk_hscale_new (GtkAdjustment *adjustment)
+{
+ GtkHScale *hscale;
+
+ hscale = gtk_type_new (gtk_hscale_get_type ());
+
+ if (!adjustment)
+ adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+
+ gtk_range_set_adjustment (GTK_RANGE (hscale), adjustment);
+
+ return GTK_WIDGET (hscale);
+}
+
+
+static void
+gtk_hscale_realize (GtkWidget *widget)
+{
+ GtkRange *range;
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+ gint x, y, w, h;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_HSCALE (widget));
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+ range = GTK_RANGE (widget);
+
+ attributes.x = widget->allocation.x;
+ attributes.y = widget->allocation.y;
+ attributes.width = widget->allocation.width;
+ attributes.height = widget->allocation.height;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+ widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
+
+ gtk_hscale_pos_trough (GTK_HSCALE (widget), &x, &y, &w, &h);
+ attributes.x = x;
+ attributes.y = y;
+ attributes.width = w;
+ attributes.height = h;
+ attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_ENTER_NOTIFY_MASK |
+ GDK_LEAVE_NOTIFY_MASK);
+
+ range->trough = gdk_window_new (widget->window, &attributes, attributes_mask);
+
+ attributes.width = SCALE_CLASS (range)->slider_length;
+ attributes.height = RANGE_CLASS (range)->slider_width;
+ attributes.event_mask |= (GDK_BUTTON_MOTION_MASK |
+ GDK_POINTER_MOTION_HINT_MASK);
+
+ range->slider = gdk_window_new (range->trough, &attributes, attributes_mask);
+
+ widget->style = gtk_style_attach (widget->style, widget->window);
+
+ gdk_window_set_user_data (widget->window, widget);
+ gdk_window_set_user_data (range->trough, widget);
+ gdk_window_set_user_data (range->slider, widget);
+
+ gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
+ gtk_style_set_background (widget->style, range->trough, GTK_STATE_ACTIVE);
+ gtk_style_set_background (widget->style, range->slider, GTK_STATE_NORMAL);
+
+ gtk_range_slider_update (GTK_RANGE (widget));
+
+ gdk_window_show (range->slider);
+ gdk_window_show (range->trough);
+}
+
+static void
+gtk_hscale_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkScale *scale;
+ gint value_width;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_HSCALE (widget));
+ g_return_if_fail (requisition != NULL);
+
+ scale = GTK_SCALE (widget);
+
+ requisition->width = (SCALE_CLASS (scale)->slider_length +
+ widget->style->klass->xthickness) * 2;
+ requisition->height = (RANGE_CLASS (scale)->slider_width +
+ widget->style->klass->ythickness * 2);
+
+ if (scale->draw_value)
+ {
+ value_width = gtk_scale_value_width (scale);
+
+ if ((scale->value_pos == GTK_POS_LEFT) ||
+ (scale->value_pos == GTK_POS_RIGHT))
+ {
+ requisition->width += value_width + SCALE_CLASS (scale)->value_spacing;
+ if (requisition->height < (widget->style->font->ascent + widget->style->font->descent))
+ requisition->height = widget->style->font->ascent + widget->style->font->descent;
+ }
+ else if ((scale->value_pos == GTK_POS_TOP) ||
+ (scale->value_pos == GTK_POS_BOTTOM))
+ {
+ if (requisition->width < value_width)
+ requisition->width = value_width;
+ requisition->height += widget->style->font->ascent + widget->style->font->descent;
+ }
+ }
+}
+
+static void
+gtk_hscale_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkRange *range;
+ GtkScale *scale;
+ gint width, height;
+ gint x, y;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_HSCALE (widget));
+ g_return_if_fail (allocation != NULL);
+
+ widget->allocation = *allocation;
+ if (GTK_WIDGET_REALIZED (widget))
+ {
+ range = GTK_RANGE (widget);
+ scale = GTK_SCALE (widget);
+
+ gdk_window_move_resize (widget->window,
+ allocation->x, allocation->y,
+ allocation->width, allocation->height);
+
+ gtk_hscale_pos_trough (GTK_HSCALE (widget), &x, &y, &width, &height);
+
+ gdk_window_move_resize (range->trough, x, y, width, height);
+ gtk_range_slider_update (GTK_RANGE (widget));
+ }
+}
+
+static void
+gtk_hscale_pos_trough (GtkHScale *hscale,
+ gint *x,
+ gint *y,
+ gint *w,
+ gint *h)
+{
+ GtkWidget *widget;
+ GtkScale *scale;
+
+ g_return_if_fail (hscale != NULL);
+ g_return_if_fail (GTK_IS_HSCALE (hscale));
+ g_return_if_fail ((x != NULL) && (y != NULL) && (w != NULL) && (h != NULL));
+
+ widget = GTK_WIDGET (hscale);
+ scale = GTK_SCALE (hscale);
+
+ *w = widget->allocation.width;
+ *h = (RANGE_CLASS (scale)->slider_width +
+ widget->style->klass->ythickness * 2);
+
+ if (scale->draw_value)
+ {
+ *x = 0;
+ *y = 0;
+
+ switch (scale->value_pos)
+ {
+ case GTK_POS_LEFT:
+ *x += gtk_scale_value_width (scale) + SCALE_CLASS (scale)->value_spacing;
+ *y = (widget->allocation.height - *h) / 2;
+ *w -= *x;
+ break;
+ case GTK_POS_RIGHT:
+ *w -= gtk_scale_value_width (scale) + SCALE_CLASS (scale)->value_spacing;
+ *y = (widget->allocation.height - *h) / 2;
+ break;
+ case GTK_POS_TOP:
+ *y = (widget->style->font->ascent + widget->style->font->descent +
+ (widget->allocation.height - widget->requisition.height) / 2);
+ break;
+ case GTK_POS_BOTTOM:
+ *y = (widget->allocation.height - widget->requisition.height) / 2;
+ break;
+ }
+ }
+ else
+ {
+ *x = 0;
+ *y = (widget->allocation.height - *h) / 2;
+ }
+ *x += 1;
+ *w -= 2;
+}
+
+static void
+gtk_hscale_draw_slider (GtkRange *range)
+{
+ GtkStateType state_type;
+ gint width, height;
+
+ g_return_if_fail (range != NULL);
+ g_return_if_fail (GTK_IS_HSCALE (range));
+
+ if (range->slider)
+ {
+ if ((range->in_child == RANGE_CLASS (range)->slider) ||
+ (range->click_child == RANGE_CLASS (range)->slider))
+ state_type = GTK_STATE_PRELIGHT;
+ else
+ state_type = GTK_STATE_NORMAL;
+
+ gtk_style_set_background (GTK_WIDGET (range)->style, range->slider, state_type);
+ gdk_window_clear (range->slider);
+
+ gdk_window_get_size (range->slider, &width, &height);
+ gtk_draw_vline (GTK_WIDGET (range)->style, range->slider,
+ state_type, 1, height - 2, width / 2);
+
+ gtk_draw_shadow (GTK_WIDGET (range)->style, range->slider,
+ state_type, GTK_SHADOW_OUT,
+ 0, 0, -1, -1);
+ }
+}
+
+static void
+gtk_hscale_draw_value (GtkScale *scale)
+{
+ GtkStateType state_type;
+ gchar buffer[16];
+ gint text_width;
+ gint width, height;
+ gint x, y;
+
+ g_return_if_fail (scale != NULL);
+ g_return_if_fail (GTK_IS_HSCALE (scale));
+
+ if (scale->draw_value)
+ {
+ gdk_window_get_size (GTK_WIDGET (scale)->window, &width, &height);
+ gdk_window_clear_area (GTK_WIDGET (scale)->window, 1, 1, width - 2, height - 2);
+
+ sprintf (buffer, "%0.*f", GTK_RANGE (scale)->digits, GTK_RANGE (scale)->adjustment->value);
+ text_width = gdk_string_measure (GTK_WIDGET (scale)->style->font, buffer);
+
+ switch (scale->value_pos)
+ {
+ case GTK_POS_LEFT:
+ gdk_window_get_position (GTK_RANGE (scale)->trough, &x, &y);
+ gdk_window_get_size (GTK_RANGE (scale)->trough, &width, &height);
+
+ x -= SCALE_CLASS (scale)->value_spacing + text_width;
+ y += ((height -
+ (GTK_WIDGET (scale)->style->font->ascent +
+ GTK_WIDGET (scale)->style->font->descent)) / 2 +
+ GTK_WIDGET (scale)->style->font->ascent);
+ break;
+ case GTK_POS_RIGHT:
+ gdk_window_get_position (GTK_RANGE (scale)->trough, &x, &y);
+ gdk_window_get_size (GTK_RANGE (scale)->trough, &width, &height);
+
+ x += width + SCALE_CLASS (scale)->value_spacing;
+ y += ((height -
+ (GTK_WIDGET (scale)->style->font->ascent +
+ GTK_WIDGET (scale)->style->font->descent)) / 2 +
+ GTK_WIDGET (scale)->style->font->ascent);
+ break;
+ case GTK_POS_TOP:
+ gdk_window_get_position (GTK_RANGE (scale)->slider, &x, NULL);
+ gdk_window_get_position (GTK_RANGE (scale)->trough, NULL, &y);
+ gdk_window_get_size (GTK_RANGE (scale)->slider, &width, NULL);
+ gdk_window_get_size (GTK_RANGE (scale)->trough, NULL, &height);
+
+ x += (width - text_width) / 2;
+ y -= GTK_WIDGET (scale)->style->font->descent;
+ break;
+ case GTK_POS_BOTTOM:
+ gdk_window_get_position (GTK_RANGE (scale)->slider, &x, NULL);
+ gdk_window_get_position (GTK_RANGE (scale)->trough, NULL, &y);
+ gdk_window_get_size (GTK_RANGE (scale)->slider, &width, NULL);
+ gdk_window_get_size (GTK_RANGE (scale)->trough, NULL, &height);
+
+ x += (width - text_width) / 2;
+ y += height + GTK_WIDGET (scale)->style->font->ascent;
+ break;
+ }
+
+ state_type = GTK_STATE_NORMAL;
+ if (!GTK_WIDGET_IS_SENSITIVE (scale))
+ state_type = GTK_STATE_INSENSITIVE;
+
+ gtk_draw_string (GTK_WIDGET (scale)->style,
+ GTK_WIDGET (scale)->window,
+ state_type, x, y, buffer);
+ }
+}
+
+static gint
+gtk_hscale_trough_keys(GtkRange *range,
+ GdkEventKey *key,
+ GtkScrollType *scroll,
+ GtkTroughType *pos)
+{
+ gint return_val = FALSE;
+ switch (key->keyval)
+ {
+ case GDK_Left:
+ return_val = TRUE;
+ if (key->state & GDK_CONTROL_MASK)
+ *scroll = GTK_SCROLL_PAGE_BACKWARD;
+ else
+ *scroll = GTK_SCROLL_STEP_BACKWARD;
+ break;
+ case GDK_Right:
+ return_val = TRUE;
+ if (key->state & GDK_CONTROL_MASK)
+ *scroll = GTK_SCROLL_PAGE_FORWARD;
+ else
+ *scroll = GTK_SCROLL_STEP_FORWARD;
+ break;
+ case GDK_Home:
+ return_val = TRUE;
+ *pos = GTK_TROUGH_START;
+ break;
+ case GDK_End:
+ return_val = TRUE;
+ *pos = GTK_TROUGH_END;
+ break;
+ }
+ return return_val;
+}
diff --git a/gtk/gtkhscale.h b/gtk/gtkhscale.h
new file mode 100644
index 000000000..61ae4fdb3
--- /dev/null
+++ b/gtk/gtkhscale.h
@@ -0,0 +1,59 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_HSCALE_H__
+#define __GTK_HSCALE_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkscale.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_HSCALE(obj) GTK_CHECK_CAST (obj, gtk_hscale_get_type (), GtkHScale)
+#define GTK_HSCALE_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_hscale_get_type (), GtkHScaleClass)
+#define GTK_IS_HSCALE(obj) GTK_CHECK_TYPE (obj, gtk_hscale_get_type ())
+
+
+typedef struct _GtkHScale GtkHScale;
+typedef struct _GtkHScaleClass GtkHScaleClass;
+
+struct _GtkHScale
+{
+ GtkScale scale;
+};
+
+struct _GtkHScaleClass
+{
+ GtkScaleClass parent_class;
+};
+
+
+guint gtk_hscale_get_type (void);
+GtkWidget* gtk_hscale_new (GtkAdjustment *adjustment);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_HSCALE_H__ */
diff --git a/gtk/gtkhscrollbar.c b/gtk/gtkhscrollbar.c
new file mode 100644
index 000000000..9b757d406
--- /dev/null
+++ b/gtk/gtkhscrollbar.c
@@ -0,0 +1,383 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtkhscrollbar.h"
+#include "gtksignal.h"
+#include "gdk/gdkkeysyms.h"
+
+
+#define EPSILON 0.01
+
+#define RANGE_CLASS(w) GTK_RANGE_CLASS (GTK_OBJECT (w)->klass)
+
+
+static void gtk_hscrollbar_class_init (GtkHScrollbarClass *klass);
+static void gtk_hscrollbar_init (GtkHScrollbar *hscrollbar);
+static void gtk_hscrollbar_realize (GtkWidget *widget);
+static void gtk_hscrollbar_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static void gtk_hscrollbar_draw_step_forw (GtkRange *range);
+static void gtk_hscrollbar_draw_step_back (GtkRange *range);
+static void gtk_hscrollbar_slider_update (GtkRange *range);
+static void gtk_hscrollbar_calc_slider_size (GtkHScrollbar *hscrollbar);
+static gint gtk_hscrollbar_trough_keys (GtkRange *range,
+ GdkEventKey *key,
+ GtkScrollType *scroll,
+ GtkTroughType *pos);
+
+
+guint
+gtk_hscrollbar_get_type ()
+{
+ static guint hscrollbar_type = 0;
+
+ if (!hscrollbar_type)
+ {
+ GtkTypeInfo hscrollbar_info =
+ {
+ "GtkHScrollbar",
+ sizeof (GtkHScrollbar),
+ sizeof (GtkHScrollbarClass),
+ (GtkClassInitFunc) gtk_hscrollbar_class_init,
+ (GtkObjectInitFunc) gtk_hscrollbar_init,
+ (GtkArgFunc) NULL,
+ };
+
+ hscrollbar_type = gtk_type_unique (gtk_scrollbar_get_type (), &hscrollbar_info);
+ }
+
+ return hscrollbar_type;
+}
+
+static void
+gtk_hscrollbar_class_init (GtkHScrollbarClass *class)
+{
+ GtkWidgetClass *widget_class;
+ GtkRangeClass *range_class;
+
+ widget_class = (GtkWidgetClass*) class;
+ range_class = (GtkRangeClass*) class;
+
+ widget_class->realize = gtk_hscrollbar_realize;
+ widget_class->size_allocate = gtk_hscrollbar_size_allocate;
+
+ range_class->draw_step_forw = gtk_hscrollbar_draw_step_forw;
+ range_class->draw_step_back = gtk_hscrollbar_draw_step_back;
+ range_class->slider_update = gtk_hscrollbar_slider_update;
+ range_class->trough_click = gtk_range_default_htrough_click;
+ range_class->trough_keys = gtk_hscrollbar_trough_keys;
+ range_class->motion = gtk_range_default_hmotion;
+}
+
+static void
+gtk_hscrollbar_init (GtkHScrollbar *hscrollbar)
+{
+ GtkWidget *widget;
+ GtkRequisition *requisition;
+
+ widget = GTK_WIDGET (hscrollbar);
+ GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS);
+ requisition = &widget->requisition;
+
+ requisition->width = (RANGE_CLASS (widget)->min_slider_size +
+ RANGE_CLASS (widget)->stepper_size +
+ RANGE_CLASS (widget)->stepper_slider_spacing +
+ widget->style->klass->xthickness) * 2;
+ requisition->height = (RANGE_CLASS (widget)->slider_width +
+ widget->style->klass->ythickness * 2);
+}
+
+GtkWidget*
+gtk_hscrollbar_new (GtkAdjustment *adjustment)
+{
+ GtkHScrollbar *hscrollbar;
+
+ hscrollbar = gtk_type_new (gtk_hscrollbar_get_type ());
+
+ if (!adjustment)
+ adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+
+ gtk_range_set_adjustment (GTK_RANGE (hscrollbar), adjustment);
+
+ return GTK_WIDGET (hscrollbar);
+}
+
+
+static void
+gtk_hscrollbar_realize (GtkWidget *widget)
+{
+ GtkRange *range;
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_HSCROLLBAR (widget));
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+ range = GTK_RANGE (widget);
+
+ attributes.x = widget->allocation.x;
+ attributes.y = widget->allocation.y + (widget->allocation.height - widget->requisition.height) / 2;
+ attributes.width = widget->allocation.width;
+ attributes.height = widget->requisition.height;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
+ attributes.event_mask = gtk_widget_get_events (widget);
+ attributes.event_mask |= (GDK_EXPOSURE_MASK |
+ GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_ENTER_NOTIFY_MASK |
+ GDK_LEAVE_NOTIFY_MASK);
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+ widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
+ range->trough = widget->window;
+
+ attributes.x = widget->style->klass->xthickness;
+ attributes.y = widget->style->klass->ythickness;
+ attributes.width = RANGE_CLASS (widget)->stepper_size;
+ attributes.height = RANGE_CLASS (widget)->stepper_size;
+
+ range->step_back = gdk_window_new (range->trough, &attributes, attributes_mask);
+
+ attributes.x = (widget->allocation.width -
+ widget->style->klass->xthickness -
+ RANGE_CLASS (widget)->stepper_size);
+
+ range->step_forw = gdk_window_new (range->trough, &attributes, attributes_mask);
+
+ attributes.x = 0;
+ attributes.y = widget->style->klass->ythickness;
+ attributes.width = RANGE_CLASS (widget)->min_slider_size;
+ attributes.height = RANGE_CLASS (widget)->slider_width;
+ attributes.event_mask |= (GDK_BUTTON_MOTION_MASK |
+ GDK_POINTER_MOTION_HINT_MASK);
+
+ range->slider = gdk_window_new (range->trough, &attributes, attributes_mask);
+
+ gtk_hscrollbar_calc_slider_size (GTK_HSCROLLBAR (widget));
+ gtk_range_slider_update (GTK_RANGE (widget));
+
+ widget->style = gtk_style_attach (widget->style, widget->window);
+
+ gdk_window_set_user_data (range->trough, widget);
+ gdk_window_set_user_data (range->slider, widget);
+ gdk_window_set_user_data (range->step_forw, widget);
+ gdk_window_set_user_data (range->step_back, widget);
+
+ gtk_style_set_background (widget->style, range->trough, GTK_STATE_ACTIVE);
+ gtk_style_set_background (widget->style, range->slider, GTK_STATE_NORMAL);
+ gtk_style_set_background (widget->style, range->step_forw, GTK_STATE_ACTIVE);
+ gtk_style_set_background (widget->style, range->step_back, GTK_STATE_ACTIVE);
+
+ gdk_window_show (range->slider);
+ gdk_window_show (range->step_forw);
+ gdk_window_show (range->step_back);
+}
+
+static void
+gtk_hscrollbar_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkRange *range;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_HSCROLLBAR (widget));
+ g_return_if_fail (allocation != NULL);
+
+ widget->allocation = *allocation;
+ if (GTK_WIDGET_REALIZED (widget))
+ {
+ range = GTK_RANGE (widget);
+
+ gdk_window_move_resize (range->trough,
+ allocation->x,
+ allocation->y + (allocation->height - widget->requisition.height) / 2,
+ allocation->width, widget->requisition.height);
+ gdk_window_move_resize (range->step_back,
+ widget->style->klass->xthickness,
+ widget->style->klass->ythickness,
+ RANGE_CLASS (widget)->stepper_size,
+ widget->requisition.height - widget->style->klass->ythickness * 2);
+ gdk_window_move_resize (range->step_forw,
+ allocation->width - widget->style->klass->xthickness -
+ RANGE_CLASS (widget)->stepper_size,
+ widget->style->klass->ythickness,
+ RANGE_CLASS (widget)->stepper_size,
+ widget->requisition.height - widget->style->klass->ythickness * 2);
+ gdk_window_resize (range->slider,
+ RANGE_CLASS (widget)->min_slider_size,
+ widget->requisition.height - widget->style->klass->ythickness * 2);
+
+ gtk_range_slider_update (GTK_RANGE (widget));
+ }
+}
+
+static void
+gtk_hscrollbar_draw_step_forw (GtkRange *range)
+{
+ GtkStateType state_type;
+ GtkShadowType shadow_type;
+
+ g_return_if_fail (range != NULL);
+ g_return_if_fail (GTK_IS_HSCROLLBAR (range));
+
+ if (GTK_WIDGET_DRAWABLE (range))
+ {
+ if (range->in_child == RANGE_CLASS (range)->step_forw)
+ {
+ if (range->click_child == RANGE_CLASS (range)->step_forw)
+ state_type = GTK_STATE_ACTIVE;
+ else
+ state_type = GTK_STATE_PRELIGHT;
+ }
+ else
+ state_type = GTK_STATE_NORMAL;
+
+ if (range->click_child == RANGE_CLASS (range)->step_forw)
+ shadow_type = GTK_SHADOW_IN;
+ else
+ shadow_type = GTK_SHADOW_OUT;
+
+ gtk_draw_arrow (GTK_WIDGET (range)->style, range->step_forw,
+ state_type, shadow_type, GTK_ARROW_RIGHT,
+ TRUE, 0, 0, -1, -1);
+ }
+}
+
+static void
+gtk_hscrollbar_draw_step_back (GtkRange *range)
+{
+ GtkStateType state_type;
+ GtkShadowType shadow_type;
+
+ g_return_if_fail (range != NULL);
+ g_return_if_fail (GTK_IS_HSCROLLBAR (range));
+
+ if (GTK_WIDGET_DRAWABLE (range))
+ {
+ if (range->in_child == RANGE_CLASS (range)->step_back)
+ {
+ if (range->click_child == RANGE_CLASS (range)->step_back)
+ state_type = GTK_STATE_ACTIVE;
+ else
+ state_type = GTK_STATE_PRELIGHT;
+ }
+ else
+ state_type = GTK_STATE_NORMAL;
+
+ if (range->click_child == RANGE_CLASS (range)->step_back)
+ shadow_type = GTK_SHADOW_IN;
+ else
+ shadow_type = GTK_SHADOW_OUT;
+
+ gtk_draw_arrow (GTK_WIDGET (range)->style, range->step_back,
+ state_type, shadow_type, GTK_ARROW_LEFT,
+ TRUE, 0, 0, -1, -1);
+ }
+}
+
+static void
+gtk_hscrollbar_slider_update (GtkRange *range)
+{
+ g_return_if_fail (range != NULL);
+ g_return_if_fail (GTK_IS_HSCROLLBAR (range));
+
+ gtk_hscrollbar_calc_slider_size (GTK_HSCROLLBAR (range));
+ gtk_range_default_hslider_update (range);
+}
+
+static void
+gtk_hscrollbar_calc_slider_size (GtkHScrollbar *hscrollbar)
+{
+ GtkRange *range;
+ gint step_back_x;
+ gint step_back_width;
+ gint step_forw_x;
+ gint slider_width;
+ gint slider_height;
+ gint left, right;
+ gint width;
+
+ g_return_if_fail (hscrollbar != NULL);
+ g_return_if_fail (GTK_IS_HSCROLLBAR (hscrollbar));
+
+ if (GTK_WIDGET_REALIZED (hscrollbar))
+ {
+ range = GTK_RANGE (hscrollbar);
+
+ gdk_window_get_size (range->step_back, &step_back_width, NULL);
+ gdk_window_get_position (range->step_back, &step_back_x, NULL);
+ gdk_window_get_position (range->step_forw, &step_forw_x, NULL);
+
+ left = (step_back_x +
+ step_back_width +
+ RANGE_CLASS (hscrollbar)->stepper_slider_spacing);
+ right = step_forw_x - RANGE_CLASS (hscrollbar)->stepper_slider_spacing;
+ width = right - left;
+
+ if ((range->adjustment->page_size > 0) &&
+ (range->adjustment->lower != range->adjustment->upper))
+ {
+ if (range->adjustment->page_size >
+ (range->adjustment->upper - range->adjustment->lower))
+ range->adjustment->page_size = range->adjustment->upper - range->adjustment->lower;
+
+ width = (width * range->adjustment->page_size /
+ (range->adjustment->upper - range->adjustment->lower));
+
+ if (width < RANGE_CLASS (hscrollbar)->min_slider_size)
+ width = RANGE_CLASS (hscrollbar)->min_slider_size;
+ }
+
+ gdk_window_get_size (range->slider, &slider_width, &slider_height);
+
+ if (slider_width != width)
+ gdk_window_resize (range->slider, width, slider_height);
+ }
+}
+
+static gint
+gtk_hscrollbar_trough_keys(GtkRange *range,
+ GdkEventKey *key,
+ GtkScrollType *scroll,
+ GtkTroughType *pos)
+{
+ gint return_val = FALSE;
+ switch (key->keyval)
+ {
+ case GDK_Left:
+ return_val = TRUE;
+ *scroll = GTK_SCROLL_STEP_BACKWARD;
+ break;
+ case GDK_Right:
+ return_val = TRUE;
+ *scroll = GTK_SCROLL_STEP_FORWARD;
+ break;
+ case GDK_Home:
+ return_val = TRUE;
+ *pos = GTK_TROUGH_START;
+ break;
+ case GDK_End:
+ return_val = TRUE;
+ *pos = GTK_TROUGH_END;
+ break;
+ }
+ return return_val;
+}
diff --git a/gtk/gtkhscrollbar.h b/gtk/gtkhscrollbar.h
new file mode 100644
index 000000000..7d6951259
--- /dev/null
+++ b/gtk/gtkhscrollbar.h
@@ -0,0 +1,59 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_HSCROLLBAR_H__
+#define __GTK_HSCROLLBAR_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkscrollbar.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_HSCROLLBAR(obj) GTK_CHECK_CAST (obj, gtk_hscrollbar_get_type (), GtkHScrollbar)
+#define GTK_HSCROLLBAR_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_hscrollbar_get_type (), GtkHScrollbarClass)
+#define GTK_IS_HSCROLLBAR(obj) GTK_CHECK_TYPE (obj, gtk_hscrollbar_get_type ())
+
+
+typedef struct _GtkHScrollbar GtkHScrollbar;
+typedef struct _GtkHScrollbarClass GtkHScrollbarClass;
+
+struct _GtkHScrollbar
+{
+ GtkScrollbar scrollbar;
+};
+
+struct _GtkHScrollbarClass
+{
+ GtkScrollbarClass parent_class;
+};
+
+
+guint gtk_hscrollbar_get_type (void);
+GtkWidget* gtk_hscrollbar_new (GtkAdjustment *adjustment);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_HSCROLLBAR_H__ */
diff --git a/gtk/gtkhseparator.c b/gtk/gtkhseparator.c
new file mode 100644
index 000000000..5f3a38c20
--- /dev/null
+++ b/gtk/gtkhseparator.c
@@ -0,0 +1,90 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtkhseparator.h"
+
+
+static void gtk_hseparator_class_init (GtkHSeparatorClass *klass);
+static void gtk_hseparator_init (GtkHSeparator *hseparator);
+static gint gtk_hseparator_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+
+
+guint
+gtk_hseparator_get_type ()
+{
+ static guint hseparator_type = 0;
+
+ if (!hseparator_type)
+ {
+ GtkTypeInfo hseparator_info =
+ {
+ "GtkHSeparator",
+ sizeof (GtkHSeparator),
+ sizeof (GtkHSeparatorClass),
+ (GtkClassInitFunc) gtk_hseparator_class_init,
+ (GtkObjectInitFunc) gtk_hseparator_init,
+ (GtkArgFunc) NULL,
+ };
+
+ hseparator_type = gtk_type_unique (gtk_separator_get_type (), &hseparator_info);
+ }
+
+ return hseparator_type;
+}
+
+static void
+gtk_hseparator_class_init (GtkHSeparatorClass *class)
+{
+ GtkWidgetClass *widget_class;
+
+ widget_class = (GtkWidgetClass*) class;
+
+ widget_class->expose_event = gtk_hseparator_expose;
+}
+
+static void
+gtk_hseparator_init (GtkHSeparator *hseparator)
+{
+ GTK_WIDGET (hseparator)->requisition.width = 1;
+ GTK_WIDGET (hseparator)->requisition.height = GTK_WIDGET (hseparator)->style->klass->ythickness;
+}
+
+GtkWidget*
+gtk_hseparator_new ()
+{
+ return GTK_WIDGET (gtk_type_new (gtk_hseparator_get_type ()));
+}
+
+
+static gint
+gtk_hseparator_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_HSEPARATOR (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ gtk_draw_hline (widget->style, widget->window, GTK_STATE_NORMAL,
+ widget->allocation.x,
+ widget->allocation.x + widget->allocation.width,
+ widget->allocation.y + (widget->allocation.height -
+ widget->style->klass->ythickness) / 2);
+
+ return FALSE;
+}
diff --git a/gtk/gtkhseparator.h b/gtk/gtkhseparator.h
new file mode 100644
index 000000000..990263151
--- /dev/null
+++ b/gtk/gtkhseparator.h
@@ -0,0 +1,59 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_HSEPARATOR_H__
+#define __GTK_HSEPARATOR_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkseparator.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_HSEPARATOR(obj) GTK_CHECK_CAST (obj, gtk_hseparator_get_type (), GtkHSeparator)
+#define GTK_HSEPARATOR_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_hseparator_get_type (), GtkHSeparatorClass)
+#define GTK_IS_HSEPARATOR(obj) GTK_CHECK_TYPE (obj, gtk_hseparator_get_type ())
+
+
+typedef struct _GtkHSeparator GtkHSeparator;
+typedef struct _GtkHSeparatorClass GtkHSeparatorClass;
+
+struct _GtkHSeparator
+{
+ GtkSeparator separator;
+};
+
+struct _GtkHSeparatorClass
+{
+ GtkSeparatorClass parent_class;
+};
+
+
+guint gtk_hseparator_get_type (void);
+GtkWidget* gtk_hseparator_new (void);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_HSEPARATOR_H__ */
diff --git a/gtk/gtkimage.c b/gtk/gtkimage.c
new file mode 100644
index 000000000..fddd06a5d
--- /dev/null
+++ b/gtk/gtkimage.c
@@ -0,0 +1,181 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtkcontainer.h"
+#include "gtkimage.h"
+
+
+static void gtk_image_class_init (GtkImageClass *klass);
+static void gtk_image_init (GtkImage *image);
+static gint gtk_image_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+
+
+guint
+gtk_image_get_type ()
+{
+ static guint image_type = 0;
+
+ if (!image_type)
+ {
+ GtkTypeInfo image_info =
+ {
+ "GtkImage",
+ sizeof (GtkImage),
+ sizeof (GtkImageClass),
+ (GtkClassInitFunc) gtk_image_class_init,
+ (GtkObjectInitFunc) gtk_image_init,
+ (GtkArgFunc) NULL,
+ };
+
+ image_type = gtk_type_unique (gtk_misc_get_type (), &image_info);
+ }
+
+ return image_type;
+}
+
+static void
+gtk_image_class_init (GtkImageClass *class)
+{
+ GtkWidgetClass *widget_class;
+
+ widget_class = (GtkWidgetClass*) class;
+
+ widget_class->expose_event = gtk_image_expose;
+}
+
+static void
+gtk_image_init (GtkImage *image)
+{
+ GTK_WIDGET_SET_FLAGS (image, GTK_NO_WINDOW);
+
+ image->image = NULL;
+ image->mask = NULL;
+}
+
+GtkWidget*
+gtk_image_new (GdkImage *val,
+ GdkBitmap *mask)
+{
+ GtkImage *image;
+
+ g_return_val_if_fail (val != NULL, NULL);
+
+ image = gtk_type_new (gtk_image_get_type ());
+
+ gtk_image_set (image, val, mask);
+
+ return GTK_WIDGET (image);
+}
+
+void
+gtk_image_set (GtkImage *image,
+ GdkImage *val,
+ GdkBitmap *mask)
+{
+ g_return_if_fail (image != NULL);
+ g_return_if_fail (GTK_IS_IMAGE (image));
+
+ image->image = val;
+ image->mask = mask;
+
+ if (image->image)
+ {
+ GTK_WIDGET (image)->requisition.width = image->image->width + GTK_MISC (image)->xpad * 2;
+ GTK_WIDGET (image)->requisition.height = image->image->height + GTK_MISC (image)->ypad * 2;
+ }
+ else
+ {
+ GTK_WIDGET (image)->requisition.width = 0;
+ GTK_WIDGET (image)->requisition.height = 0;
+ }
+
+ if (GTK_WIDGET_VISIBLE (image))
+ gtk_widget_queue_resize (GTK_WIDGET (image));
+}
+
+void
+gtk_image_get (GtkImage *image,
+ GdkImage **val,
+ GdkBitmap **mask)
+{
+ g_return_if_fail (image != NULL);
+ g_return_if_fail (GTK_IS_IMAGE (image));
+
+ if (val)
+ *val = image->image;
+ if (mask)
+ *mask = image->mask;
+}
+
+
+static gint
+gtk_image_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ GtkImage *image;
+ GtkMisc *misc;
+ GdkRectangle area;
+ gint x, y;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_IMAGE (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget))
+ {
+ image = GTK_IMAGE (widget);
+ misc = GTK_MISC (widget);
+
+ x = (widget->allocation.x * (1.0 - misc->xalign) +
+ (widget->allocation.x + widget->allocation.width
+ - (widget->requisition.width - misc->xpad * 2)) *
+ misc->xalign) + 0.5;
+ y = (widget->allocation.y * (1.0 - misc->yalign) +
+ (widget->allocation.y + widget->allocation.height
+ - (widget->requisition.height - misc->ypad * 2)) *
+ misc->yalign) + 0.5;
+
+ if (image->mask)
+ {
+ gdk_gc_set_clip_mask (widget->style->black_gc, image->mask);
+ gdk_gc_set_clip_origin (widget->style->black_gc, x, y);
+ }
+
+ area = event->area;
+ if ((area.x < 0) || (area.y < 0))
+ {
+ area.x = area.y = 0;
+ area.width = image->image->width;
+ area.height = image->image->height;
+ }
+
+ gdk_draw_image (widget->window,
+ widget->style->black_gc,
+ image->image,
+ area.x, area.y, x+area.x, y+area.y,
+ area.width, area.height);
+
+ if (image->mask)
+ {
+ gdk_gc_set_clip_mask (widget->style->black_gc, NULL);
+ gdk_gc_set_clip_origin (widget->style->black_gc, 0, 0);
+ }
+ }
+
+ return FALSE;
+}
diff --git a/gtk/gtkimage.h b/gtk/gtkimage.h
new file mode 100644
index 000000000..d3481d51d
--- /dev/null
+++ b/gtk/gtkimage.h
@@ -0,0 +1,69 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_IMAGE_H__
+#define __GTK_IMAGE_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkmisc.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_IMAGE(obj) GTK_CHECK_CAST (obj, gtk_image_get_type (), GtkImage)
+#define GTK_IMAGE_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_image_get_type (), GtkImageClass)
+#define GTK_IS_IMAGE(obj) GTK_CHECK_TYPE (obj, gtk_image_get_type ())
+
+
+typedef struct _GtkImage GtkImage;
+typedef struct _GtkImageClass GtkImageClass;
+
+struct _GtkImage
+{
+ GtkMisc misc;
+
+ GdkImage *image;
+ GdkBitmap *mask;
+};
+
+struct _GtkImageClass
+{
+ GtkMiscClass parent_class;
+};
+
+
+guint gtk_image_get_type (void);
+GtkWidget* gtk_image_new (GdkImage *val,
+ GdkBitmap *mask);
+void gtk_image_set (GtkImage *image,
+ GdkImage *val,
+ GdkBitmap *mask);
+void gtk_image_get (GtkImage *image,
+ GdkImage **val,
+ GdkBitmap **mask);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_IMAGE_H__ */
diff --git a/gtk/gtkinputdialog.c b/gtk/gtkinputdialog.c
new file mode 100644
index 000000000..1d412a32e
--- /dev/null
+++ b/gtk/gtkinputdialog.c
@@ -0,0 +1,546 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * gtkinputdialog.c
+ *
+ * Copyright 1997 Owen Taylor <owt1@cornell.edu>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "gdk/gdkkeysyms.h"
+#include "gtkbutton.h"
+#include "gtkhbox.h"
+#include "gtkhseparator.h"
+#include "gtkinputdialog.h"
+#include "gtklabel.h"
+#include "gtklistitem.h"
+#include "gtkmain.h"
+#include "gtkmenu.h"
+#include "gtkmenuitem.h"
+#include "gtkoptionmenu.h"
+#include "gtkscrolledwindow.h"
+#include "gtksignal.h"
+#include "gtkvbox.h"
+
+typedef void (*GtkInputDialogSignal1) (GtkObject *object,
+ int arg1,
+ gpointer data);
+
+enum
+{
+ ENABLE_DEVICE,
+ DISABLE_DEVICE,
+ LAST_SIGNAL
+};
+
+
+#define AXIS_LIST_WIDTH 160
+#define AXIS_LIST_HEIGHT 175
+
+/* Forward declarations */
+
+static void gtk_input_dialog_marshal_signal1 (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args);
+static void gtk_input_dialog_class_init (GtkInputDialogClass *klass);
+static void gtk_input_dialog_init (GtkInputDialog *inputd);
+static GdkDeviceInfo *gtk_input_dialog_get_device_info(guint32 deviceid);
+static void gtk_input_dialog_set_device(GtkWidget *widget, gpointer data);
+static void gtk_input_dialog_destroy (GtkObject *object);
+static void gtk_input_dialog_set_mapping_mode(GtkWidget *w,
+ gpointer data);
+static void gtk_input_dialog_set_axis(GtkWidget *widget, gpointer data);
+static void gtk_input_dialog_fill_axes (GtkInputDialog *inputd,
+ GdkDeviceInfo *info);
+
+static GtkObjectClass *parent_class = NULL;
+static gint input_dialog_signals[LAST_SIGNAL] = { 0 };
+
+static void
+gtk_input_dialog_marshal_signal1 (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args)
+{
+ GtkInputDialogSignal1 rfunc;
+
+ rfunc = (GtkInputDialogSignal1) func;
+ (* rfunc) (object, GTK_VALUE_INT(args[0]), func_data);
+}
+
+static GdkDeviceInfo *
+gtk_input_dialog_get_device_info(guint32 deviceid)
+{
+ GList *tmp_list = gdk_input_list_devices();
+ while (tmp_list)
+ {
+ if (((GdkDeviceInfo *)tmp_list->data)->deviceid == deviceid)
+ return (GdkDeviceInfo *)tmp_list->data;
+ tmp_list = tmp_list->next;
+ }
+
+ return NULL;
+}
+
+guint
+gtk_input_dialog_get_type ()
+{
+ static guint input_dialog_type = 0;
+
+ if (!input_dialog_type)
+ {
+ GtkTypeInfo input_dialog_info =
+ {
+ "GtkInputDialog",
+ sizeof (GtkInputDialog),
+ sizeof (GtkInputDialogClass),
+ (GtkClassInitFunc) gtk_input_dialog_class_init,
+ (GtkObjectInitFunc) gtk_input_dialog_init,
+ (GtkArgFunc) NULL,
+ };
+
+ input_dialog_type = gtk_type_unique (gtk_dialog_get_type (),
+ &input_dialog_info);
+ }
+
+ return input_dialog_type;
+}
+
+static void
+gtk_input_dialog_class_init (GtkInputDialogClass *klass)
+{
+ GtkObjectClass *object_class;
+
+ object_class = (GtkObjectClass*) klass;
+
+ parent_class = gtk_type_class (gtk_dialog_get_type ());
+
+ input_dialog_signals[ENABLE_DEVICE] =
+ gtk_signal_new ("enable_device",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkInputDialogClass, enable_device),
+ gtk_input_dialog_marshal_signal1,
+ GTK_TYPE_NONE, 1, GTK_TYPE_INT);
+
+ input_dialog_signals[DISABLE_DEVICE] =
+ gtk_signal_new ("disable_device",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkInputDialogClass, disable_device),
+ gtk_input_dialog_marshal_signal1,
+ GTK_TYPE_NONE, 1, GTK_TYPE_INT);
+
+ gtk_object_class_add_signals (object_class, input_dialog_signals,
+ LAST_SIGNAL);
+
+
+ object_class->destroy = gtk_input_dialog_destroy;
+ klass->enable_device = NULL;
+ klass->disable_device = NULL;
+}
+
+static void
+gtk_input_dialog_init (GtkInputDialog *inputd)
+{
+ GtkWidget *vbox;
+ GtkWidget *util_box;
+ GtkWidget *label;
+ GtkWidget *device_menu;
+ GtkWidget *mapping_menu;
+ GtkWidget *menuitem;
+ GtkWidget *optionmenu;
+ GtkWidget *separator;
+
+ GList *tmp_list;
+ GList *device_info;
+
+ device_info = gdk_input_list_devices();
+
+ /* shell and main vbox */
+
+ gtk_window_set_title (GTK_WINDOW (inputd), "Input");
+
+ vbox = gtk_vbox_new (FALSE, 4);
+ gtk_container_border_width(GTK_CONTAINER (vbox), 5);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (inputd)->vbox), vbox, TRUE, TRUE, 0);
+
+ if (g_list_length(device_info) <= 1) /* only core device */
+ {
+ label = gtk_label_new ("No input devices");
+ gtk_container_add (GTK_CONTAINER (vbox), label);
+
+ gtk_widget_show (label);
+ }
+ else
+ {
+ /* menu for selecting device */
+
+ device_menu = gtk_menu_new ();
+
+ for (tmp_list = device_info; tmp_list; tmp_list = tmp_list->next) {
+ GdkDeviceInfo *info = (GdkDeviceInfo *)(tmp_list->data);
+ if (info->deviceid != GDK_CORE_POINTER)
+ {
+ menuitem = gtk_menu_item_new_with_label(info->name);
+
+ gtk_menu_append(GTK_MENU(device_menu),menuitem);
+ gtk_widget_show(menuitem);
+ gtk_object_set_user_data (GTK_OBJECT (menuitem), inputd);
+ gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
+ (GtkSignalFunc) gtk_input_dialog_set_device,
+ (gpointer)((long)info->deviceid));
+ }
+ }
+
+ util_box = gtk_hbox_new (FALSE, 2);
+ gtk_box_pack_start (GTK_BOX (vbox), util_box, FALSE, FALSE, 0);
+
+ label = gtk_label_new("Device:");
+ gtk_box_pack_start (GTK_BOX (util_box), label, FALSE, FALSE, 2);
+
+ optionmenu = gtk_option_menu_new ();
+ gtk_box_pack_start (GTK_BOX (util_box), optionmenu, TRUE, TRUE, 2);
+ gtk_widget_show (optionmenu);
+ gtk_option_menu_set_menu (GTK_OPTION_MENU (optionmenu), device_menu);
+
+ gtk_widget_show (label);
+ gtk_widget_show (util_box);
+
+ /* Device options */
+
+ separator = gtk_hseparator_new();
+ gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, TRUE, 0);
+ gtk_widget_show (separator);
+
+ util_box = gtk_hbox_new (FALSE, 2);
+ gtk_box_pack_start (GTK_BOX (vbox), util_box, FALSE, FALSE, 0);
+
+ /* mapping mode option menu */
+
+ mapping_menu = gtk_menu_new ();
+
+ menuitem = gtk_menu_item_new_with_label("Disabled");
+ gtk_menu_append(GTK_MENU(mapping_menu),menuitem);
+ gtk_object_set_user_data (GTK_OBJECT (menuitem), inputd);
+ gtk_widget_show(menuitem);
+ gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
+ (GtkSignalFunc) gtk_input_dialog_set_mapping_mode,
+ (gpointer)((long)GDK_MODE_DISABLED));
+
+ menuitem = gtk_menu_item_new_with_label("Screen");
+ gtk_menu_append(GTK_MENU(mapping_menu),menuitem);
+ gtk_object_set_user_data (GTK_OBJECT (menuitem), inputd);
+ gtk_widget_show(menuitem);
+ gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
+ (GtkSignalFunc) gtk_input_dialog_set_mapping_mode,
+ (gpointer)((long)GDK_MODE_SCREEN));
+
+ menuitem = gtk_menu_item_new_with_label("Window");
+ gtk_menu_append(GTK_MENU(mapping_menu),menuitem);
+ gtk_object_set_user_data (GTK_OBJECT (menuitem), inputd);
+ gtk_widget_show(menuitem);
+ gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
+ (GtkSignalFunc) gtk_input_dialog_set_mapping_mode,
+ (gpointer)((long)GDK_MODE_WINDOW));
+
+ label = gtk_label_new("Mode: ");
+ gtk_box_pack_start (GTK_BOX (util_box), label, FALSE, FALSE, 2);
+
+ inputd->mode_optionmenu = gtk_option_menu_new ();
+ gtk_box_pack_start (GTK_BOX (util_box), inputd->mode_optionmenu, FALSE, FALSE, 2);
+ gtk_widget_show (inputd->mode_optionmenu);
+ gtk_option_menu_set_menu (GTK_OPTION_MENU (inputd->mode_optionmenu), mapping_menu);
+
+ gtk_widget_show(label);
+
+ gtk_widget_show (util_box);
+
+ util_box = gtk_hbox_new (FALSE, 2);
+ gtk_box_pack_start (GTK_BOX(vbox), util_box, FALSE, FALSE, 0);
+
+ gtk_widget_show (label);
+ gtk_widget_show (util_box);
+
+ /* The axis listbox */
+
+ label = gtk_label_new ("Axes");
+ gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
+
+ inputd->axis_listbox = gtk_scrolled_window_new (NULL, NULL);
+ gtk_widget_set_usize (inputd->axis_listbox, AXIS_LIST_WIDTH, AXIS_LIST_HEIGHT);
+ gtk_box_pack_start (GTK_BOX (vbox), inputd->axis_listbox, TRUE, TRUE, 0);
+ gtk_widget_show (inputd->axis_listbox);
+
+ inputd->axis_list = 0;
+
+ gtk_widget_show(label);
+
+ /* ...set_device expects to get input dialog from widget user data */
+ gtk_object_set_user_data (GTK_OBJECT (inputd), inputd);
+ gtk_input_dialog_set_device(GTK_WIDGET(inputd), (gpointer)((long)
+ ((GdkDeviceInfo *)device_info->data)->deviceid));
+ }
+
+ /* buttons */
+
+ inputd->save_button = gtk_button_new_with_label ("Save");
+ GTK_WIDGET_SET_FLAGS (inputd->save_button, GTK_CAN_DEFAULT);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG(inputd)->action_area),
+ inputd->save_button, TRUE, TRUE, 0);
+ gtk_widget_show (inputd->save_button);
+
+ inputd->close_button = gtk_button_new_with_label ("Close");
+ GTK_WIDGET_SET_FLAGS (inputd->close_button, GTK_CAN_DEFAULT);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG(inputd)->action_area),
+ inputd->close_button, TRUE, TRUE, 0);
+
+ gtk_widget_show (inputd->close_button);
+ gtk_widget_grab_default (inputd->close_button);
+
+ gtk_widget_show (vbox);
+}
+
+
+GtkWidget*
+gtk_input_dialog_new (void)
+{
+ GtkInputDialog *inputd;
+
+ inputd = gtk_type_new (gtk_input_dialog_get_type ());
+
+ return GTK_WIDGET (inputd);
+}
+
+static void
+gtk_input_dialog_set_device(GtkWidget *widget, gpointer data)
+{
+ guint32 deviceid = (guint32)data;
+ GdkDeviceInfo *info;
+
+ GtkInputDialog *inputd = GTK_INPUT_DIALOG(
+ gtk_object_get_user_data(GTK_OBJECT(widget)));
+
+ inputd->current_device = deviceid;
+ info = gtk_input_dialog_get_device_info((guint32)data);
+
+ gtk_input_dialog_fill_axes(inputd, info);
+
+ gtk_option_menu_set_history(GTK_OPTION_MENU(inputd->mode_optionmenu),
+ info->mode);
+}
+
+static void
+gtk_input_dialog_destroy (GtkObject *object)
+{
+ /* GtkInputDialog *inputd = GTK_INPUT_DIALOG (object); */
+
+ /* Clean up ? */
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+static void
+gtk_input_dialog_set_mapping_mode(GtkWidget *w,
+ gpointer data)
+{
+ GtkInputDialog *inputd = GTK_INPUT_DIALOG(
+ gtk_object_get_user_data(GTK_OBJECT(w)));
+ GdkDeviceInfo *info = gtk_input_dialog_get_device_info (inputd->current_device);
+ GdkInputMode old_mode = info->mode;
+ GdkInputMode mode = (GdkInputMode)data;
+
+ if (mode != old_mode)
+ {
+ if (gdk_input_set_mode(inputd->current_device, mode))
+ {
+ if (mode == GDK_MODE_DISABLED)
+ gtk_signal_emit (GTK_OBJECT (inputd),
+ input_dialog_signals[DISABLE_DEVICE],
+ info->deviceid);
+ else
+ gtk_signal_emit (GTK_OBJECT (inputd),
+ input_dialog_signals[ENABLE_DEVICE],
+ info->deviceid);
+ }
+ else
+ gtk_option_menu_set_history (GTK_OPTION_MENU (inputd->mode_optionmenu),
+ old_mode);
+
+ /* FIXME: error dialog ? */
+ }
+}
+
+static void
+gtk_input_dialog_set_axis(GtkWidget *widget, gpointer data)
+{
+ GdkAxisUse use = (GdkAxisUse)data & 0xFFFF;
+ GdkAxisUse old_use;
+ GdkAxisUse *new_axes;
+ GtkInputDialog *inputd = GTK_INPUT_DIALOG (gtk_object_get_user_data (GTK_OBJECT (widget)));
+ GdkDeviceInfo *info = gtk_input_dialog_get_device_info (inputd->current_device);
+
+ gint axis = ((gint)data >> 16) - 1;
+ gint old_axis;
+ int i;
+
+ new_axes = g_new (GdkAxisUse, info->num_axes);
+ old_axis = -1;
+ for (i=0;i<info->num_axes;i++)
+ {
+ new_axes[i] = info->axes[i];
+ if (info->axes[i] == use)
+ old_axis = i;
+ }
+
+ if (axis != -1)
+ old_use = info->axes[axis];
+ else
+ old_use = GDK_AXIS_IGNORE;
+
+ if (axis == old_axis)
+ return;
+
+ /* we must always have an x and a y axis */
+ if ((axis == -1 && (use == GDK_AXIS_X || use == GDK_AXIS_Y)) ||
+ (old_axis == -1 && (old_use == GDK_AXIS_X || old_use == GDK_AXIS_Y)))
+ {
+ gtk_option_menu_set_history (
+ GTK_OPTION_MENU (inputd->axis_items[use]),
+ old_axis + 1);
+ }
+ else
+ {
+ if (axis != -1)
+ new_axes[axis] = use;
+
+ if (old_axis != -1)
+ new_axes[old_axis] = old_use;
+
+ if (old_use != GDK_AXIS_IGNORE)
+ {
+ gtk_option_menu_set_history (
+ GTK_OPTION_MENU (inputd->axis_items[old_use]),
+ old_axis + 1);
+ }
+ gdk_input_set_axes (info->deviceid, new_axes);
+ }
+
+ g_free (new_axes);
+}
+
+static void
+gtk_input_dialog_fill_axes(GtkInputDialog *inputd, GdkDeviceInfo *info)
+{
+ static char *axis_use_strings[GDK_AXIS_LAST] =
+ {
+ "",
+ "X",
+ "Y",
+ "Pressure",
+ "X Tilt",
+ "Y Tilt"
+ };
+
+ int i,j;
+ GtkWidget *list_item;
+ GtkWidget *menu;
+ GtkWidget *option_menu;
+ GtkWidget *vbox;
+ GtkWidget *hbox;
+ GtkWidget *label;
+
+ /* remove all the old items */
+ if (inputd->axis_list)
+ {
+ gtk_widget_hide (inputd->axis_list); /* suppress resizes (or get warnings) */
+ gtk_widget_destroy (inputd->axis_list);
+ }
+ inputd->axis_list = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (inputd->axis_listbox), inputd->axis_list);
+ gtk_widget_show (inputd->axis_list);
+
+ gtk_widget_realize (inputd->axis_list);
+ gdk_window_set_background (inputd->axis_list->window,
+ &inputd->axis_list->style->white);
+
+ for (i=GDK_AXIS_X;i<GDK_AXIS_LAST;i++)
+ {
+ list_item = gtk_list_item_new();
+
+ gtk_box_pack_start(GTK_BOX(inputd->axis_list),list_item,FALSE,FALSE,0);
+ gtk_widget_show (list_item);
+
+ vbox = gtk_vbox_new (FALSE, 0);
+ gtk_container_add(GTK_CONTAINER (list_item), vbox);
+
+ hbox = gtk_hbox_new (FALSE, 2);
+ gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 1);
+
+ /* create the label */
+
+ label = gtk_label_new(axis_use_strings[i]);
+ gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 2);
+
+ /* and the use option menu */
+ menu = gtk_menu_new();
+
+ for (j = -1; j < info->num_axes; j++)
+ {
+ char buffer[16];
+ GtkWidget *menu_item;
+
+ if (j == -1)
+ menu_item = gtk_menu_item_new_with_label ("none");
+ else
+ {
+ sprintf (buffer,"%d",j+1);
+ menu_item = gtk_menu_item_new_with_label (buffer);
+ }
+ gtk_object_set_user_data (GTK_OBJECT (menu_item), inputd);
+ gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
+ (GtkSignalFunc) gtk_input_dialog_set_axis,
+ (gpointer) ((long) (0x10000 * (j + 1) + i)));
+ gtk_widget_show (menu_item);
+ gtk_menu_append (GTK_MENU (menu), menu_item);
+ }
+
+ inputd->axis_items[i] = option_menu = gtk_option_menu_new ();
+ gtk_box_pack_start (GTK_BOX (hbox), option_menu, FALSE, FALSE, 2);
+
+ gtk_widget_show (option_menu);
+ gtk_option_menu_set_menu (GTK_OPTION_MENU (option_menu), menu);
+ for (j = 0; j < info->num_axes; j++)
+ if (info->axes[j] == (GdkAxisUse) i)
+ {
+ gtk_option_menu_set_history (GTK_OPTION_MENU (option_menu), j+1);
+ break;
+ }
+
+ gtk_widget_show (label);
+
+ gtk_widget_show (hbox);
+ gtk_widget_show (vbox);
+ }
+}
diff --git a/gtk/gtkinputdialog.h b/gtk/gtkinputdialog.h
new file mode 100644
index 000000000..93c667f44
--- /dev/null
+++ b/gtk/gtkinputdialog.h
@@ -0,0 +1,76 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_INPUTDIALOG_H__
+#define __GTK_INPUTDIALOG_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkdialog.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_INPUT_DIALOG(obj) GTK_CHECK_CAST (obj, gtk_input_dialog_get_type (), GtkInputDialog)
+#define GTK_INPUT_DIALOG_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_input_dialog_get_type (), GtkInputDialogClass)
+#define GTK_IS_INPUT_DIALOG(obj) GTK_CHECK_TYPE (obj, gtk_input_dialog_get_type ())
+
+
+typedef struct _GtkInputDialog GtkInputDialog;
+typedef struct _GtkInputDialogClass GtkInputDialogClass;
+
+struct _GtkInputDialog
+{
+ GtkDialog dialog;
+
+ GtkWidget *axis_list;
+ GtkWidget *axis_listbox;
+ GtkWidget *mode_optionmenu;
+
+ GtkWidget *close_button;
+ GtkWidget *save_button;
+
+ GtkWidget *axis_items[GDK_AXIS_LAST];
+ guint32 current_device;
+};
+
+struct _GtkInputDialogClass
+{
+ GtkWindowClass parent_class;
+
+ void (* enable_device) (GtkInputDialog *inputd,
+ guint32 devid,
+ gpointer *data);
+ void (* disable_device) (GtkInputDialog *inputd,
+ guint32 devid,
+ gpointer *data);
+};
+
+
+guint gtk_input_dialog_get_type (void);
+GtkWidget* gtk_input_dialog_new ();
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_INPUTDIALOG_H__ */
diff --git a/gtk/gtkitem.c b/gtk/gtkitem.c
new file mode 100644
index 000000000..6dd0ec8dd
--- /dev/null
+++ b/gtk/gtkitem.c
@@ -0,0 +1,191 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtkitem.h"
+#include "gtksignal.h"
+
+
+enum {
+ SELECT,
+ DESELECT,
+ TOGGLE,
+ LAST_SIGNAL
+};
+
+
+static void gtk_item_class_init (GtkItemClass *klass);
+static void gtk_item_init (GtkItem *item);
+static void gtk_item_map (GtkWidget *widget);
+static void gtk_item_unmap (GtkWidget *widget);
+static void gtk_item_realize (GtkWidget *widget);
+
+
+static gint item_signals[LAST_SIGNAL] = { 0 };
+
+
+guint
+gtk_item_get_type ()
+{
+ static guint item_type = 0;
+
+ if (!item_type)
+ {
+ GtkTypeInfo item_info =
+ {
+ "GtkItem",
+ sizeof (GtkItem),
+ sizeof (GtkItemClass),
+ (GtkClassInitFunc) gtk_item_class_init,
+ (GtkObjectInitFunc) gtk_item_init,
+ (GtkArgFunc) NULL,
+ };
+
+ item_type = gtk_type_unique (gtk_bin_get_type (), &item_info);
+ }
+
+ return item_type;
+}
+
+static void
+gtk_item_class_init (GtkItemClass *class)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+
+ object_class = (GtkObjectClass*) class;
+ widget_class = (GtkWidgetClass*) class;
+
+ item_signals[SELECT] =
+ gtk_signal_new ("select",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkItemClass, select),
+ gtk_signal_default_marshaller,
+ GTK_TYPE_NONE, 0);
+ item_signals[DESELECT] =
+ gtk_signal_new ("deselect",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkItemClass, deselect),
+ gtk_signal_default_marshaller,
+ GTK_TYPE_NONE, 0);
+ item_signals[TOGGLE] =
+ gtk_signal_new ("toggle",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkItemClass, toggle),
+ gtk_signal_default_marshaller,
+ GTK_TYPE_NONE, 0);
+
+ gtk_object_class_add_signals (object_class, item_signals, LAST_SIGNAL);
+
+ widget_class->activate_signal = item_signals[TOGGLE];
+ widget_class->map = gtk_item_map;
+ widget_class->unmap = gtk_item_unmap;
+ widget_class->realize = gtk_item_realize;
+
+ class->select = NULL;
+ class->deselect = NULL;
+ class->toggle = NULL;
+}
+
+static void
+gtk_item_init (GtkItem *item)
+{
+ GTK_WIDGET_UNSET_FLAGS (item, GTK_NO_WINDOW);
+}
+
+void
+gtk_item_select (GtkItem *item)
+{
+ gtk_signal_emit (GTK_OBJECT (item), item_signals[SELECT]);
+}
+
+void
+gtk_item_deselect (GtkItem *item)
+{
+ gtk_signal_emit (GTK_OBJECT (item), item_signals[DESELECT]);
+}
+
+void
+gtk_item_toggle (GtkItem *item)
+{
+ gtk_signal_emit (GTK_OBJECT (item), item_signals[TOGGLE]);
+}
+
+
+static void
+gtk_item_map (GtkWidget *widget)
+{
+ GtkBin *bin;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_ITEM (widget));
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
+ gdk_window_show (widget->window);
+
+ bin = GTK_BIN (widget);
+
+ if (bin->child &&
+ GTK_WIDGET_VISIBLE (bin->child) &&
+ !GTK_WIDGET_MAPPED (bin->child))
+ gtk_widget_map (bin->child);
+}
+
+static void
+gtk_item_unmap (GtkWidget *widget)
+{
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_ITEM (widget));
+
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
+ gdk_window_hide (widget->window);
+}
+
+static void
+gtk_item_realize (GtkWidget *widget)
+{
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_ITEM (widget));
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+
+ attributes.x = widget->allocation.x;
+ attributes.y = widget->allocation.y;
+ attributes.width = widget->allocation.width;
+ attributes.height = widget->allocation.height;
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
+ attributes.event_mask = (GDK_EXPOSURE_MASK |
+ GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_ENTER_NOTIFY_MASK |
+ GDK_LEAVE_NOTIFY_MASK);
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+ widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
+ gdk_window_set_user_data (widget->window, widget);
+
+ widget->style = gtk_style_attach (widget->style, widget->window);
+ gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
+}
diff --git a/gtk/gtkitem.h b/gtk/gtkitem.h
new file mode 100644
index 000000000..36cf1ab45
--- /dev/null
+++ b/gtk/gtkitem.h
@@ -0,0 +1,65 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_ITEM_H__
+#define __GTK_ITEM_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkbin.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_ITEM(obj) GTK_CHECK_CAST (obj, gtk_item_get_type (), GtkItem)
+#define GTK_ITEM_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_item_get_type (), GtkItemClass)
+#define GTK_IS_ITEM(obj) GTK_CHECK_TYPE (obj, gtk_item_get_type ())
+
+
+typedef struct _GtkItem GtkItem;
+typedef struct _GtkItemClass GtkItemClass;
+
+struct _GtkItem
+{
+ GtkBin bin;
+};
+
+struct _GtkItemClass
+{
+ GtkBinClass parent_class;
+
+ void (* select) (GtkItem *item);
+ void (* deselect) (GtkItem *item);
+ void (* toggle) (GtkItem *item);
+};
+
+
+guint gtk_item_get_type (void);
+void gtk_item_select (GtkItem *item);
+void gtk_item_deselect (GtkItem *item);
+void gtk_item_toggle (GtkItem *item);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_ITEM_H__ */
diff --git a/gtk/gtklabel.c b/gtk/gtklabel.c
new file mode 100644
index 000000000..5cd1f804f
--- /dev/null
+++ b/gtk/gtklabel.c
@@ -0,0 +1,329 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <string.h>
+#include "gtklabel.h"
+
+
+static void gtk_label_class_init (GtkLabelClass *klass);
+static void gtk_label_init (GtkLabel *label);
+static void gtk_label_destroy (GtkObject *object);
+static void gtk_label_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static gint gtk_label_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+
+
+static GtkMiscClass *parent_class = NULL;
+
+
+guint
+gtk_label_get_type ()
+{
+ static guint label_type = 0;
+
+ if (!label_type)
+ {
+ GtkTypeInfo label_info =
+ {
+ "GtkLabel",
+ sizeof (GtkLabel),
+ sizeof (GtkLabelClass),
+ (GtkClassInitFunc) gtk_label_class_init,
+ (GtkObjectInitFunc) gtk_label_init,
+ (GtkArgFunc) NULL,
+ };
+
+ label_type = gtk_type_unique (gtk_misc_get_type (), &label_info);
+ }
+
+ return label_type;
+}
+
+void
+gtk_label_class_init (GtkLabelClass *class)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+
+ object_class = (GtkObjectClass*) class;
+ widget_class = (GtkWidgetClass*) class;
+
+ parent_class = gtk_type_class (gtk_misc_get_type ());
+
+ object_class->destroy = gtk_label_destroy;
+
+ widget_class->size_request = gtk_label_size_request;
+ widget_class->expose_event = gtk_label_expose;
+}
+
+void
+gtk_label_init (GtkLabel *label)
+{
+ GTK_WIDGET_SET_FLAGS (label, GTK_NO_WINDOW);
+
+ label->label = NULL;
+ label->row = NULL;
+ label->jtype = GTK_JUSTIFY_CENTER;
+}
+
+GtkWidget*
+gtk_label_new (const char *str)
+{
+ GtkLabel *label;
+
+ g_return_val_if_fail (str != NULL, NULL);
+
+ label = gtk_type_new (gtk_label_get_type ());
+
+ gtk_label_set (label, str);
+
+ return GTK_WIDGET (label);
+}
+
+void
+gtk_label_set (GtkLabel *label,
+ const char *str)
+{
+ char* p;
+
+ g_return_if_fail (label != NULL);
+ g_return_if_fail (GTK_IS_LABEL (label));
+ g_return_if_fail (str != NULL);
+
+ if (label->label)
+ g_free (label->label);
+ label->label = g_strdup (str);
+
+ if (label->row)
+ g_slist_free (label->row);
+ label->row = NULL;
+ label->row = g_slist_append (label->row, label->label);
+ p = label->label;
+ while ((p = strchr(p, '\n')))
+ label->row = g_slist_append (label->row, ++p);
+
+ if (GTK_WIDGET_VISIBLE (label))
+ {
+ if (GTK_WIDGET_MAPPED (label))
+ gdk_window_clear_area (GTK_WIDGET (label)->window,
+ GTK_WIDGET (label)->allocation.x,
+ GTK_WIDGET (label)->allocation.y,
+ GTK_WIDGET (label)->allocation.width,
+ GTK_WIDGET (label)->allocation.height);
+
+ gtk_widget_queue_resize (GTK_WIDGET (label));
+ }
+}
+
+void
+gtk_label_set_justify (GtkLabel *label, GtkJustification jtype)
+{
+ g_return_if_fail (label != NULL);
+ g_return_if_fail (GTK_IS_LABEL (label));
+
+ if ((GtkJustification) label->jtype != jtype)
+ {
+ label->jtype = jtype;
+
+ if (GTK_WIDGET_VISIBLE (label))
+ {
+ if (GTK_WIDGET_MAPPED (label))
+ gdk_window_clear_area (GTK_WIDGET (label)->window,
+ GTK_WIDGET (label)->allocation.x,
+ GTK_WIDGET (label)->allocation.y,
+ GTK_WIDGET (label)->allocation.width,
+ GTK_WIDGET (label)->allocation.height);
+
+ gtk_widget_queue_resize (GTK_WIDGET (label));
+ }
+ }
+}
+
+void
+gtk_label_get (GtkLabel *label,
+ char **str)
+{
+ g_return_if_fail (label != NULL);
+ g_return_if_fail (GTK_IS_LABEL (label));
+ g_return_if_fail (str != NULL);
+
+ *str = label->label;
+}
+
+
+static void
+gtk_label_destroy (GtkObject *object)
+{
+ GtkLabel *label;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_LABEL (object));
+
+ label = GTK_LABEL (object);
+
+ if (GTK_WIDGET (object)->parent &&
+ GTK_WIDGET_MAPPED (object))
+ gtk_widget_unmap (GTK_WIDGET (object));
+
+ g_free (label->label);
+ g_slist_free (label->row);
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+static void
+gtk_label_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkLabel *label;
+ GSList *row;
+ gint width;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_LABEL (widget));
+ g_return_if_fail (requisition != NULL);
+
+ label = GTK_LABEL (widget);
+
+ row = label->row;
+ width = 0;
+ while (row)
+ {
+ if (row->next)
+ width = MAX (width,
+ gdk_text_width (GTK_WIDGET (label)->style->font, row->data,
+ (gchar*) row->next->data - (gchar*) row->data));
+ else
+ width = MAX (width, gdk_string_width (GTK_WIDGET (label)->style->font, row->data));
+ row = row->next;
+ }
+
+ requisition->width = width + label->misc.xpad * 2;
+ requisition->height = ((GTK_WIDGET (label)->style->font->ascent +
+ GTK_WIDGET (label)->style->font->descent + 2) *
+ g_slist_length(label->row) +
+ label->misc.ypad * 2);
+}
+
+static gint
+gtk_label_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ GtkLabel *label;
+ GtkMisc *misc;
+ GSList *row;
+ gint state;
+ gint offset;
+ gint len;
+ gint maxl;
+ gint x, y;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_LABEL (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget))
+ {
+ label = GTK_LABEL (widget);
+ misc = GTK_MISC (widget);
+
+ state = widget->state;
+ if (!GTK_WIDGET_IS_SENSITIVE (widget))
+ state = GTK_STATE_INSENSITIVE;
+
+ /* We only draw the label if we have been allocated at least as
+ * much space as we requested. If we have less space than we
+ * need to draw the string then we _should_ have asked our
+ * parent container to resize and a new allocation _should_
+ * be forthcoming so there is no reason to redraw (incorrectly)
+ * here.
+ */
+ if ((widget->allocation.width >= widget->requisition.width) &&
+ (widget->allocation.height >= widget->requisition.height))
+ {
+ maxl = widget->requisition.width - misc->xpad * 2;
+ x = widget->allocation.x + misc->xpad +
+ (widget->allocation.width - widget->requisition.width) * misc->xalign + 0.5;
+ y = (widget->allocation.y * (1.0 - misc->yalign) +
+ (widget->allocation.y + widget->allocation.height - (widget->requisition.height -
+ misc->ypad * 2)) *
+ misc->yalign + widget->style->font->ascent) + 1.5;
+
+ row = label->row;
+ while (row && row->next)
+ {
+ len = (gchar*) row->next->data - (gchar*) row->data;
+ offset = 0;
+ if (label->jtype == GTK_JUSTIFY_CENTER)
+ offset = (maxl - gdk_text_width (widget->style->font, row->data, len)) / 2;
+ else if (label->jtype == GTK_JUSTIFY_RIGHT)
+ offset = (maxl - gdk_text_width (widget->style->font, row->data, len));
+ if (state == GTK_STATE_INSENSITIVE)
+ gdk_draw_text (widget->window, widget->style->font,
+ widget->style->white_gc,
+ offset + x + 1, y + 1, row->data, len);
+
+ gdk_draw_text (widget->window, widget->style->font,
+ widget->style->fg_gc[state],
+ offset + x, y, row->data, len);
+ row = row->next;
+ y += widget->style->font->ascent + widget->style->font->descent + 2;
+ }
+
+ /* COMMENT: we can avoid gdk_text_width() calls here storing in label->row
+ the widths of the rows calculated in gtk_label_set.
+ Once we have a wrapping interface we can support GTK_JUSTIFY_FILL.
+ */
+ offset = 0;
+ if (label->jtype == GTK_JUSTIFY_CENTER)
+ offset = (maxl - gdk_string_width (widget->style->font, row->data)) / 2;
+ else if (label->jtype == GTK_JUSTIFY_RIGHT)
+ offset = (maxl - gdk_string_width (widget->style->font, row->data));
+ if (state == GTK_STATE_INSENSITIVE)
+ gdk_draw_string (widget->window, widget->style->font,
+ widget->style->white_gc,
+ offset + x + 1, y + 1, row->data);
+
+ gdk_draw_string (widget->window, widget->style->font,
+ widget->style->fg_gc[state],
+ offset + x, y, row->data);
+
+ /*
+ gdk_draw_rectangle (widget->window,
+ widget->style->bg_gc[GTK_STATE_SELECTED], FALSE,
+ widget->allocation.x, widget->allocation.y,
+ widget->allocation.width - 1, widget->allocation.height - 1);
+ */
+ }
+ else
+ {
+ /*
+ g_print ("gtk_label_expose: allocation too small: %d %d ( %d %d )\n",
+ widget->allocation.width, widget->allocation.height,
+ widget->requisition.width, widget->requisition.height);
+ */
+ }
+ }
+
+ return TRUE;
+}
+
+
+
+
diff --git a/gtk/gtklabel.h b/gtk/gtklabel.h
new file mode 100644
index 000000000..81eca4afe
--- /dev/null
+++ b/gtk/gtklabel.h
@@ -0,0 +1,69 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_LABEL_H__
+#define __GTK_LABEL_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkmisc.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_LABEL(obj) GTK_CHECK_CAST (obj, gtk_label_get_type (), GtkLabel)
+#define GTK_LABEL_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_label_get_type (), GtkLabelClass)
+#define GTK_IS_LABEL(obj) GTK_CHECK_TYPE (obj, gtk_label_get_type ())
+
+
+typedef struct _GtkLabel GtkLabel;
+typedef struct _GtkLabelClass GtkLabelClass;
+
+struct _GtkLabel
+{
+ GtkMisc misc;
+
+ char *label;
+ GSList *row;
+ guint jtype : 2;
+};
+
+struct _GtkLabelClass
+{
+ GtkMiscClass parent_class;
+};
+
+
+guint gtk_label_get_type (void);
+GtkWidget* gtk_label_new (const char *str);
+void gtk_label_set (GtkLabel *label,
+ const char *str);
+void gtk_label_set_justify (GtkLabel *label,
+ GtkJustification jtype);
+void gtk_label_get (GtkLabel *label,
+ char **str);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_LABEL_H__ */
diff --git a/gtk/gtklist.c b/gtk/gtklist.c
new file mode 100644
index 000000000..7d7d4a66d
--- /dev/null
+++ b/gtk/gtklist.c
@@ -0,0 +1,1007 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtklist.h"
+#include "gtklistitem.h"
+#include "gtkmain.h"
+#include "gtksignal.h"
+
+
+enum {
+ SELECTION_CHANGED,
+ SELECT_CHILD,
+ UNSELECT_CHILD,
+ LAST_SIGNAL
+};
+
+
+typedef void (*GtkListSignal) (GtkObject *object,
+ gpointer arg1,
+ gpointer data);
+
+
+static void gtk_list_class_init (GtkListClass *klass);
+static void gtk_list_init (GtkList *list);
+static void gtk_list_destroy (GtkObject *object);
+static void gtk_list_map (GtkWidget *widget);
+static void gtk_list_unmap (GtkWidget *widget);
+static void gtk_list_realize (GtkWidget *widget);
+static void gtk_list_draw (GtkWidget *widget,
+ GdkRectangle *area);
+static gint gtk_list_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+static gint gtk_list_motion_notify (GtkWidget *widget,
+ GdkEventMotion *event);
+static gint gtk_list_button_press (GtkWidget *widget,
+ GdkEventButton *event);
+static gint gtk_list_button_release (GtkWidget *widget,
+ GdkEventButton *event);
+static void gtk_list_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void gtk_list_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static void gtk_list_add (GtkContainer *container,
+ GtkWidget *widget);
+static void gtk_list_remove (GtkContainer *container,
+ GtkWidget *widget);
+static void gtk_list_foreach (GtkContainer *container,
+ GtkCallback callback,
+ gpointer callback_data);
+
+static void gtk_real_list_select_child (GtkList *list,
+ GtkWidget *child);
+static void gtk_real_list_unselect_child (GtkList *list,
+ GtkWidget *child);
+
+static void gtk_list_marshal_signal (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args);
+
+
+static GtkContainerClass *parent_class = NULL;
+static gint list_signals[LAST_SIGNAL] = { 0 };
+
+
+guint
+gtk_list_get_type ()
+{
+ static guint list_type = 0;
+
+ if (!list_type)
+ {
+ GtkTypeInfo list_info =
+ {
+ "GtkList",
+ sizeof (GtkList),
+ sizeof (GtkListClass),
+ (GtkClassInitFunc) gtk_list_class_init,
+ (GtkObjectInitFunc) gtk_list_init,
+ (GtkArgFunc) NULL,
+ };
+
+ list_type = gtk_type_unique (gtk_container_get_type (), &list_info);
+ }
+
+ return list_type;
+}
+
+static void
+gtk_list_class_init (GtkListClass *class)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+ GtkContainerClass *container_class;
+
+ object_class = (GtkObjectClass*) class;
+ widget_class = (GtkWidgetClass*) class;
+ container_class = (GtkContainerClass*) class;
+
+ parent_class = gtk_type_class (gtk_container_get_type ());
+
+ list_signals[SELECTION_CHANGED] =
+ gtk_signal_new ("selection_changed",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkListClass, selection_changed),
+ gtk_signal_default_marshaller,
+ GTK_TYPE_NONE, 0);
+ list_signals[SELECT_CHILD] =
+ gtk_signal_new ("select_child",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkListClass, select_child),
+ gtk_list_marshal_signal,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_WIDGET);
+ list_signals[UNSELECT_CHILD] =
+ gtk_signal_new ("unselect_child",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkListClass, unselect_child),
+ gtk_list_marshal_signal,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_WIDGET);
+
+ gtk_object_class_add_signals (object_class, list_signals, LAST_SIGNAL);
+
+ object_class->destroy = gtk_list_destroy;
+
+ widget_class->map = gtk_list_map;
+ widget_class->unmap = gtk_list_unmap;
+ widget_class->realize = gtk_list_realize;
+ widget_class->draw = gtk_list_draw;
+ widget_class->expose_event = gtk_list_expose;
+ widget_class->motion_notify_event = gtk_list_motion_notify;
+ widget_class->button_press_event = gtk_list_button_press;
+ widget_class->button_release_event = gtk_list_button_release;
+ widget_class->size_request = gtk_list_size_request;
+ widget_class->size_allocate = gtk_list_size_allocate;
+
+ container_class->add = gtk_list_add;
+ container_class->remove = gtk_list_remove;
+ container_class->foreach = gtk_list_foreach;
+
+ class->selection_changed = NULL;
+ class->select_child = gtk_real_list_select_child;
+ class->unselect_child = gtk_real_list_unselect_child;
+}
+
+static void
+gtk_list_init (GtkList *list)
+{
+ list->children = NULL;
+ list->selection = NULL;
+ list->timer = 0;
+ list->selection_start_pos = 0;
+ list->selection_end_pos = 0;
+ list->selection_mode = GTK_SELECTION_SINGLE;
+ list->scroll_direction = 0;
+ list->have_grab = FALSE;
+}
+
+GtkWidget*
+gtk_list_new ()
+{
+ return GTK_WIDGET (gtk_type_new (gtk_list_get_type ()));
+}
+
+void
+gtk_list_insert_items (GtkList *list,
+ GList *items,
+ gint position)
+{
+ GtkWidget *widget;
+ GList *tmp_list;
+ GList *last;
+ gint nchildren;
+
+ g_return_if_fail (list != NULL);
+ g_return_if_fail (GTK_IS_LIST (list));
+
+ if (!items)
+ return;
+
+ tmp_list = items;
+ while (tmp_list)
+ {
+ widget = tmp_list->data;
+ tmp_list = tmp_list->next;
+
+ gtk_widget_set_parent (widget, GTK_WIDGET (list));
+
+ if (GTK_WIDGET_VISIBLE (widget->parent))
+ {
+ if (GTK_WIDGET_REALIZED (widget->parent) &&
+ !GTK_WIDGET_REALIZED (widget))
+ gtk_widget_realize (widget);
+
+ if (GTK_WIDGET_MAPPED (widget->parent) &&
+ !GTK_WIDGET_MAPPED (widget))
+ gtk_widget_map (widget);
+ }
+ }
+
+ nchildren = g_list_length (list->children);
+ if ((position < 0) || (position > nchildren))
+ position = nchildren;
+
+ if (position == nchildren)
+ {
+ if (list->children)
+ {
+ tmp_list = g_list_last (list->children);
+ tmp_list->next = items;
+ items->prev = tmp_list;
+ }
+ else
+ {
+ list->children = items;
+ }
+ }
+ else
+ {
+ tmp_list = g_list_nth (list->children, position);
+ last = g_list_last (items);
+
+ if (tmp_list->prev)
+ tmp_list->prev->next = items;
+ last->next = tmp_list;
+ items->prev = tmp_list->prev;
+ tmp_list->prev = last;
+
+ if (tmp_list == list->children)
+ list->children = items;
+ }
+
+ if (list->children && !list->selection &&
+ (list->selection_mode == GTK_SELECTION_BROWSE))
+ {
+ widget = list->children->data;
+ gtk_list_select_child (list, widget);
+ }
+
+ if (GTK_WIDGET_VISIBLE (list))
+ gtk_widget_queue_resize (GTK_WIDGET (list));
+}
+
+void
+gtk_list_append_items (GtkList *list,
+ GList *items)
+{
+ g_return_if_fail (list != NULL);
+ g_return_if_fail (GTK_IS_LIST (list));
+
+ gtk_list_insert_items (list, items, -1);
+}
+
+void
+gtk_list_prepend_items (GtkList *list,
+ GList *items)
+{
+ g_return_if_fail (list != NULL);
+ g_return_if_fail (GTK_IS_LIST (list));
+
+ gtk_list_insert_items (list, items, 0);
+}
+
+void
+gtk_list_remove_items (GtkList *list,
+ GList *items)
+{
+ GtkWidget *widget;
+ GList *selected_widgets;
+ GList *tmp_list;
+
+ g_return_if_fail (list != NULL);
+ g_return_if_fail (GTK_IS_LIST (list));
+
+ tmp_list = items;
+ selected_widgets = NULL;
+ widget = NULL;
+
+ while (tmp_list)
+ {
+ widget = tmp_list->data;
+ tmp_list = tmp_list->next;
+
+ if (widget->state == GTK_STATE_SELECTED)
+ selected_widgets = g_list_prepend (selected_widgets, widget);
+
+ list->children = g_list_remove (list->children, widget);
+
+ if (GTK_WIDGET_MAPPED (widget))
+ gtk_widget_unmap (widget);
+
+ gtk_widget_unparent (widget);
+ }
+
+ if (selected_widgets)
+ {
+ tmp_list = selected_widgets;
+ while (tmp_list)
+ {
+ widget = tmp_list->data;
+ tmp_list = tmp_list->next;
+
+ gtk_list_unselect_child (list, widget);
+ }
+
+ gtk_signal_emit (GTK_OBJECT (list), list_signals[SELECTION_CHANGED]);
+ }
+
+ g_list_free (selected_widgets);
+
+ if (list->children && !list->selection &&
+ (list->selection_mode == GTK_SELECTION_BROWSE))
+ {
+ widget = list->children->data;
+ gtk_list_select_child (list, widget);
+ }
+
+ if (GTK_WIDGET_VISIBLE (list))
+ gtk_widget_queue_resize (GTK_WIDGET (list));
+}
+
+void
+gtk_list_clear_items (GtkList *list,
+ gint start,
+ gint end)
+{
+ GtkWidget *widget;
+ GList *start_list;
+ GList *end_list;
+ GList *tmp_list;
+ gint nchildren;
+ gint selection_changed;
+
+ g_return_if_fail (list != NULL);
+ g_return_if_fail (GTK_IS_LIST (list));
+
+ nchildren = g_list_length (list->children);
+
+ if (nchildren > 0)
+ {
+ if ((end < 0) || (end > nchildren))
+ end = nchildren;
+
+ g_return_if_fail (start < end);
+
+ start_list = g_list_nth (list->children, start);
+ end_list = g_list_nth (list->children, end);
+
+ if (start_list->prev)
+ start_list->prev->next = end_list;
+ if (end_list && end_list->prev)
+ end_list->prev->next = NULL;
+ if (end_list)
+ end_list->prev = start_list->prev;
+ if (start_list == list->children)
+ list->children = end_list;
+
+ selection_changed = FALSE;
+ widget = NULL;
+ tmp_list = start_list;
+
+ while (tmp_list)
+ {
+ widget = tmp_list->data;
+ tmp_list = tmp_list->next;
+
+ if (widget->state == GTK_STATE_SELECTED)
+ {
+ selection_changed = TRUE;
+ list->selection = g_list_remove (list->selection, widget);
+ }
+
+ /* list->children = g_list_remove (list->children, widget); */
+ /* gtk_widget_unparent (widget); */
+
+ gtk_widget_destroy (widget);
+ }
+
+ if (list->children && !list->selection &&
+ (list->selection_mode == GTK_SELECTION_BROWSE))
+ {
+ gtk_list_select_child (list, widget);
+ widget = list->children->data;
+ }
+
+ if (selection_changed)
+ gtk_signal_emit (GTK_OBJECT (list), list_signals[SELECTION_CHANGED]);
+
+ gtk_widget_queue_resize (GTK_WIDGET (list));
+ }
+}
+
+void
+gtk_list_select_item (GtkList *list,
+ gint item)
+{
+ GList *tmp_list;
+
+ g_return_if_fail (list != NULL);
+ g_return_if_fail (GTK_IS_LIST (list));
+
+ tmp_list = g_list_nth (list->children, item);
+ if (tmp_list)
+ gtk_list_select_child (list, GTK_WIDGET (tmp_list->data));
+}
+
+void
+gtk_list_unselect_item (GtkList *list,
+ gint item)
+{
+ GList *tmp_list;
+
+ g_return_if_fail (list != NULL);
+ g_return_if_fail (GTK_IS_LIST (list));
+
+ tmp_list = g_list_nth (list->children, item);
+ if (tmp_list)
+ gtk_list_unselect_child (list, GTK_WIDGET (tmp_list->data));
+}
+
+void
+gtk_list_select_child (GtkList *list,
+ GtkWidget *child)
+{
+ gtk_signal_emit (GTK_OBJECT (list), list_signals[SELECT_CHILD], child);
+}
+
+void
+gtk_list_unselect_child (GtkList *list,
+ GtkWidget *child)
+{
+ gtk_signal_emit (GTK_OBJECT (list), list_signals[UNSELECT_CHILD], child);
+}
+
+gint
+gtk_list_child_position (GtkList *list,
+ GtkWidget *child)
+{
+ GList *children;
+ gint pos;
+
+ g_return_val_if_fail (list != NULL, -1);
+ g_return_val_if_fail (GTK_IS_LIST (list), -1);
+ g_return_val_if_fail (child != NULL, -1);
+
+ pos = 0;
+ children = list->children;
+
+ while (children)
+ {
+ if (child == GTK_WIDGET (children->data))
+ return pos;
+
+ pos += 1;
+ children = children->next;
+ }
+
+ return -1;
+}
+
+void
+gtk_list_set_selection_mode (GtkList *list,
+ GtkSelectionMode mode)
+{
+ g_return_if_fail (list != NULL);
+ g_return_if_fail (GTK_IS_LIST (list));
+
+ list->selection_mode = mode;
+}
+
+
+static void
+gtk_list_destroy (GtkObject *object)
+{
+ GtkList *list;
+ GtkWidget *child;
+ GList *children;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_LIST (object));
+
+ list = GTK_LIST (object);
+
+ children = list->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ child->parent = NULL;
+ gtk_object_unref (GTK_OBJECT (child));
+ gtk_widget_destroy (child);
+ }
+
+ g_list_free (list->children);
+ g_list_free (list->selection);
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+static void
+gtk_list_map (GtkWidget *widget)
+{
+ GtkList *list;
+ GtkWidget *child;
+ GList *children;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_LIST (widget));
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
+ list = GTK_LIST (widget);
+
+ gdk_window_show (widget->window);
+
+ children = list->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_VISIBLE (child) &&
+ !GTK_WIDGET_MAPPED (child))
+ gtk_widget_map (child);
+ }
+}
+
+static void
+gtk_list_unmap (GtkWidget *widget)
+{
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_LIST (widget));
+
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
+ gdk_window_hide (widget->window);
+}
+
+static void
+gtk_list_realize (GtkWidget *widget)
+{
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_LIST (widget));
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.x = widget->allocation.x;
+ attributes.y = widget->allocation.y;
+ attributes.width = widget->allocation.width;
+ attributes.height = widget->allocation.height;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
+ attributes.event_mask = GDK_EXPOSURE_MASK;
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+
+ widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
+ gdk_window_set_user_data (widget->window, widget);
+
+ widget->style = gtk_style_attach (widget->style, widget->window);
+ gdk_window_set_background (widget->window, &widget->style->white);
+}
+
+static void
+gtk_list_draw (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ GtkList *list;
+ GtkWidget *child;
+ GdkRectangle child_area;
+ GList *children;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_LIST (widget));
+ g_return_if_fail (area != NULL);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ list = GTK_LIST (widget);
+
+ children = list->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (gtk_widget_intersect (child, area, &child_area))
+ gtk_widget_draw (child, &child_area);
+ }
+ }
+}
+
+static gint
+gtk_list_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ GtkList *list;
+ GtkWidget *child;
+ GdkEventExpose child_event;
+ GList *children;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_LIST (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ list = GTK_LIST (widget);
+
+ child_event = *event;
+
+ children = list->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_NO_WINDOW (child) &&
+ gtk_widget_intersect (child, &event->area, &child_event.area))
+ gtk_widget_event (child, (GdkEvent*) &child_event);
+ }
+ }
+
+ return FALSE;
+}
+
+static gint
+gtk_list_motion_notify (GtkWidget *widget,
+ GdkEventMotion *event)
+{
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_LIST (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ g_print ("gtk_list_motion_notify\n");
+
+ return FALSE;
+}
+
+static gint
+gtk_list_button_press (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ GtkList *list;
+ GtkWidget *item;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_LIST (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ list = GTK_LIST (widget);
+ item = gtk_get_event_widget ((GdkEvent*) event);
+
+ while (!gtk_type_is_a (GTK_WIDGET_TYPE (item), gtk_list_item_get_type ()))
+ item = item->parent;
+
+ gtk_list_select_child (list, item);
+
+ return FALSE;
+}
+
+static gint
+gtk_list_button_release (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ GtkList *list;
+ GtkWidget *item;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_LIST (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ list = GTK_LIST (widget);
+ item = gtk_get_event_widget ((GdkEvent*) event);
+
+ return FALSE;
+}
+
+static void
+gtk_list_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkList *list;
+ GtkWidget *child;
+ GList *children;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_LIST (widget));
+ g_return_if_fail (requisition != NULL);
+
+ list = GTK_LIST (widget);
+ requisition->width = 0;
+ requisition->height = 0;
+
+ children = list->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_VISIBLE (child))
+ {
+ gtk_widget_size_request (child, &child->requisition);
+
+ requisition->width = MAX (requisition->width, child->requisition.width);
+ requisition->height += child->requisition.height;
+ }
+ }
+
+ requisition->width += GTK_CONTAINER (list)->border_width * 2;
+ requisition->height += GTK_CONTAINER (list)->border_width * 2;
+
+ requisition->width = MAX (requisition->width, 1);
+ requisition->height = MAX (requisition->height, 1);
+}
+
+static void
+gtk_list_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkList *list;
+ GtkWidget *child;
+ GtkAllocation child_allocation;
+ GList *children;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_LIST (widget));
+ g_return_if_fail (allocation != NULL);
+
+ list = GTK_LIST (widget);
+
+ widget->allocation = *allocation;
+ if (GTK_WIDGET_REALIZED (widget))
+ gdk_window_move_resize (widget->window,
+ allocation->x, allocation->y,
+ allocation->width, allocation->height);
+
+ if (list->children)
+ {
+ child_allocation.x = GTK_CONTAINER (list)->border_width;
+ child_allocation.y = GTK_CONTAINER (list)->border_width;
+ child_allocation.width = allocation->width - child_allocation.x * 2;
+
+ children = list->children;
+
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_VISIBLE (child))
+ {
+ child_allocation.height = child->requisition.height;
+
+ gtk_widget_size_allocate (child, &child_allocation);
+
+ child_allocation.y += child_allocation.height;
+ }
+ }
+ }
+}
+
+static void
+gtk_list_add (GtkContainer *container,
+ GtkWidget *widget)
+{
+ GtkList *list;
+
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_LIST (container));
+ g_return_if_fail (widget != NULL);
+
+ list = GTK_LIST (container);
+
+ gtk_widget_set_parent (widget, GTK_WIDGET (container));
+ if (GTK_WIDGET_VISIBLE (widget->parent))
+ {
+ if (GTK_WIDGET_REALIZED (widget->parent) &&
+ !GTK_WIDGET_REALIZED (widget))
+ gtk_widget_realize (widget);
+
+ if (GTK_WIDGET_MAPPED (widget->parent) &&
+ !GTK_WIDGET_MAPPED (widget))
+ gtk_widget_map (widget);
+ }
+
+ list->children = g_list_append (list->children, widget);
+
+ if (!list->selection && (list->selection_mode == GTK_SELECTION_BROWSE))
+ {
+ gtk_list_select_child (list, widget);
+ }
+
+ if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (container))
+ gtk_widget_queue_resize (widget);
+}
+
+static void
+gtk_list_remove (GtkContainer *container,
+ GtkWidget *widget)
+{
+ GList *item_list;
+
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_LIST (container));
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (container == GTK_CONTAINER (widget->parent));
+
+
+ item_list = g_list_alloc ();
+ item_list->data = widget;
+
+ gtk_list_remove_items (GTK_LIST (container), item_list);
+
+ g_list_free (item_list);
+}
+
+static void
+gtk_list_foreach (GtkContainer *container,
+ GtkCallback callback,
+ gpointer callback_data)
+{
+ GtkList *list;
+ GtkWidget *child;
+ GList *children;
+
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_LIST (container));
+ g_return_if_fail (callback != NULL);
+
+ list = GTK_LIST (container);
+ children = list->children;
+
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ (* callback) (child, callback_data);
+ }
+}
+
+
+static void
+gtk_real_list_select_child (GtkList *list,
+ GtkWidget *child)
+{
+ GList *selection;
+ GList *tmp_list;
+ GtkWidget *tmp_item;
+
+ g_return_if_fail (list != NULL);
+ g_return_if_fail (GTK_IS_LIST (list));
+ g_return_if_fail (child != NULL);
+ g_return_if_fail (GTK_IS_LIST_ITEM (child));
+
+ switch (list->selection_mode)
+ {
+ case GTK_SELECTION_SINGLE:
+ selection = list->selection;
+
+ while (selection)
+ {
+ tmp_item = selection->data;
+
+ if (tmp_item != child)
+ {
+ gtk_list_item_deselect (GTK_LIST_ITEM (tmp_item));
+
+ tmp_list = selection;
+ selection = selection->next;
+
+ list->selection = g_list_remove_link (list->selection, tmp_list);
+
+ g_list_free (tmp_list);
+ }
+ else
+ selection = selection->next;
+ }
+
+ if (child->state == GTK_STATE_NORMAL)
+ {
+ gtk_list_item_select (GTK_LIST_ITEM (child));
+ list->selection = g_list_prepend (list->selection, child);
+ }
+ else if (child->state == GTK_STATE_SELECTED)
+ {
+ gtk_list_item_deselect (GTK_LIST_ITEM (child));
+ list->selection = g_list_remove (list->selection, child);
+ }
+
+ gtk_signal_emit (GTK_OBJECT (list), list_signals[SELECTION_CHANGED]);
+ break;
+
+ case GTK_SELECTION_BROWSE:
+ selection = list->selection;
+
+ while (selection)
+ {
+ tmp_item = selection->data;
+
+ if (tmp_item != child)
+ {
+ gtk_list_item_deselect (GTK_LIST_ITEM (tmp_item));
+
+ tmp_list = selection;
+ selection = selection->next;
+
+ list->selection = g_list_remove_link (list->selection, tmp_list);
+
+ g_list_free (tmp_list);
+ }
+ else
+ selection = selection->next;
+ }
+
+ if (child->state == GTK_STATE_NORMAL)
+ {
+ gtk_list_item_select (GTK_LIST_ITEM (child));
+ list->selection = g_list_prepend (list->selection, child);
+ gtk_signal_emit (GTK_OBJECT (list), list_signals[SELECTION_CHANGED]);
+ }
+ break;
+
+ case GTK_SELECTION_MULTIPLE:
+ if (child->state == GTK_STATE_NORMAL)
+ {
+ gtk_list_item_select (GTK_LIST_ITEM (child));
+ list->selection = g_list_prepend (list->selection, child);
+ gtk_signal_emit (GTK_OBJECT (list), list_signals[SELECTION_CHANGED]);
+ }
+ else if (child->state == GTK_STATE_SELECTED)
+ {
+ gtk_list_item_deselect (GTK_LIST_ITEM (child));
+ list->selection = g_list_remove (list->selection, child);
+ gtk_signal_emit (GTK_OBJECT (list), list_signals[SELECTION_CHANGED]);
+ }
+ break;
+
+ case GTK_SELECTION_EXTENDED:
+ break;
+ }
+}
+
+static void
+gtk_real_list_unselect_child (GtkList *list,
+ GtkWidget *child)
+{
+ g_return_if_fail (list != NULL);
+ g_return_if_fail (GTK_IS_LIST (list));
+ g_return_if_fail (child != NULL);
+ g_return_if_fail (GTK_IS_LIST_ITEM (child));
+
+ switch (list->selection_mode)
+ {
+ case GTK_SELECTION_SINGLE:
+ case GTK_SELECTION_MULTIPLE:
+ case GTK_SELECTION_BROWSE:
+ if (child->state == GTK_STATE_SELECTED)
+ {
+ gtk_list_item_deselect (GTK_LIST_ITEM (child));
+ list->selection = g_list_remove (list->selection, child);
+ gtk_signal_emit (GTK_OBJECT (list), list_signals[SELECTION_CHANGED]);
+ }
+ break;
+
+ case GTK_SELECTION_EXTENDED:
+ break;
+ }
+}
+
+
+static void
+gtk_list_marshal_signal (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args)
+{
+ GtkListSignal rfunc;
+
+ rfunc = (GtkListSignal) func;
+
+ (* rfunc) (object, GTK_VALUE_OBJECT (args[0]), func_data);
+}
diff --git a/gtk/gtklist.h b/gtk/gtklist.h
new file mode 100644
index 000000000..3eff261b5
--- /dev/null
+++ b/gtk/gtklist.h
@@ -0,0 +1,107 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_LIST_H__
+#define __GTK_LIST_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkcontainer.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_LIST(obj) GTK_CHECK_CAST (obj, gtk_list_get_type (), GtkList)
+#define GTK_LIST_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_list_get_type (), GtkListClass)
+#define GTK_IS_LIST(obj) GTK_CHECK_TYPE (obj, gtk_list_get_type ())
+
+
+typedef struct _GtkList GtkList;
+typedef struct _GtkListClass GtkListClass;
+
+typedef enum
+{
+ GTK_SELECTION_SINGLE,
+ GTK_SELECTION_BROWSE,
+ GTK_SELECTION_MULTIPLE,
+ GTK_SELECTION_EXTENDED
+} GtkSelectionMode;
+
+struct _GtkList
+{
+ GtkContainer container;
+
+ GList *children;
+ GList *selection;
+
+ guint32 timer;
+ guint16 selection_start_pos;
+ guint16 selection_end_pos;
+ guint selection_mode : 2;
+ guint scroll_direction : 1;
+ guint have_grab : 1;
+};
+
+struct _GtkListClass
+{
+ GtkContainerClass parent_class;
+
+ void (* selection_changed) (GtkList *list);
+ void (* select_child) (GtkList *list,
+ GtkWidget *child);
+ void (* unselect_child) (GtkList *list,
+ GtkWidget *child);
+};
+
+
+guint gtk_list_get_type (void);
+GtkWidget* gtk_list_new (void);
+void gtk_list_insert_items (GtkList *list,
+ GList *items,
+ gint position);
+void gtk_list_append_items (GtkList *list,
+ GList *items);
+void gtk_list_prepend_items (GtkList *list,
+ GList *items);
+void gtk_list_remove_items (GtkList *list,
+ GList *items);
+void gtk_list_clear_items (GtkList *list,
+ gint start,
+ gint end);
+void gtk_list_select_item (GtkList *list,
+ gint item);
+void gtk_list_unselect_item (GtkList *list,
+ gint item);
+void gtk_list_select_child (GtkList *list,
+ GtkWidget *child);
+void gtk_list_unselect_child (GtkList *list,
+ GtkWidget *child);
+gint gtk_list_child_position (GtkList *list,
+ GtkWidget *child);
+void gtk_list_set_selection_mode (GtkList *list,
+ GtkSelectionMode mode);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_LIST_H__ */
diff --git a/gtk/gtklistitem.c b/gtk/gtklistitem.c
new file mode 100644
index 000000000..642027025
--- /dev/null
+++ b/gtk/gtklistitem.c
@@ -0,0 +1,394 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtklabel.h"
+#include "gtklistitem.h"
+#include "gtklist.h"
+
+static void gtk_list_item_class_init (GtkListItemClass *klass);
+static void gtk_list_item_init (GtkListItem *list_item);
+static void gtk_list_item_realize (GtkWidget *widget);
+static void gtk_list_item_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void gtk_list_item_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static void gtk_list_item_draw (GtkWidget *widget,
+ GdkRectangle *area);
+static void gtk_list_item_draw_focus (GtkWidget *widget);
+static gint gtk_list_item_button_press (GtkWidget *widget,
+ GdkEventButton *event);
+static gint gtk_list_item_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+static gint gtk_list_item_focus_in (GtkWidget *widget,
+ GdkEventFocus *event);
+static gint gtk_list_item_focus_out (GtkWidget *widget,
+ GdkEventFocus *event);
+static void gtk_real_list_item_select (GtkItem *item);
+static void gtk_real_list_item_deselect (GtkItem *item);
+static void gtk_real_list_item_toggle (GtkItem *item);
+
+
+static GtkItemClass *parent_class = NULL;
+
+
+guint
+gtk_list_item_get_type ()
+{
+ static guint list_item_type = 0;
+
+ if (!list_item_type)
+ {
+ GtkTypeInfo list_item_info =
+ {
+ "GtkListItem",
+ sizeof (GtkListItem),
+ sizeof (GtkListItemClass),
+ (GtkClassInitFunc) gtk_list_item_class_init,
+ (GtkObjectInitFunc) gtk_list_item_init,
+ (GtkArgFunc) NULL,
+ };
+
+ list_item_type = gtk_type_unique (gtk_item_get_type (), &list_item_info);
+ }
+
+ return list_item_type;
+}
+
+static void
+gtk_list_item_class_init (GtkListItemClass *class)
+{
+ GtkWidgetClass *widget_class;
+ GtkItemClass *item_class;
+
+ widget_class = (GtkWidgetClass*) class;
+ item_class = (GtkItemClass*) class;
+
+ parent_class = gtk_type_class (gtk_item_get_type ());
+
+ widget_class->realize = gtk_list_item_realize;
+ widget_class->size_request = gtk_list_item_size_request;
+ widget_class->size_allocate = gtk_list_item_size_allocate;
+ widget_class->draw = gtk_list_item_draw;
+ widget_class->draw_focus = gtk_list_item_draw_focus;
+ widget_class->button_press_event = gtk_list_item_button_press;
+ widget_class->expose_event = gtk_list_item_expose;
+ widget_class->focus_in_event = gtk_list_item_focus_in;
+ widget_class->focus_out_event = gtk_list_item_focus_out;
+
+ item_class->select = gtk_real_list_item_select;
+ item_class->deselect = gtk_real_list_item_deselect;
+ item_class->toggle = gtk_real_list_item_toggle;
+}
+
+static void
+gtk_list_item_init (GtkListItem *list_item)
+{
+ GTK_WIDGET_SET_FLAGS (list_item, GTK_CAN_FOCUS);
+}
+
+GtkWidget*
+gtk_list_item_new ()
+{
+ return GTK_WIDGET (gtk_type_new (gtk_list_item_get_type ()));
+}
+
+GtkWidget*
+gtk_list_item_new_with_label (const gchar *label)
+{
+ GtkWidget *list_item;
+ GtkWidget *label_widget;
+
+ list_item = gtk_list_item_new ();
+ label_widget = gtk_label_new (label);
+ gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
+
+ gtk_container_add (GTK_CONTAINER (list_item), label_widget);
+ gtk_widget_show (label_widget);
+
+ return list_item;
+}
+
+void
+gtk_list_item_select (GtkListItem *list_item)
+{
+ gtk_item_select (GTK_ITEM (list_item));
+}
+
+void
+gtk_list_item_deselect (GtkListItem *list_item)
+{
+ gtk_item_deselect (GTK_ITEM (list_item));
+}
+
+
+static void
+gtk_list_item_realize (GtkWidget *widget)
+{
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_LIST_ITEM (widget));
+
+ if (GTK_WIDGET_CLASS (parent_class)->realize)
+ (* GTK_WIDGET_CLASS (parent_class)->realize) (widget);
+
+ gdk_window_set_background (widget->window, &widget->style->white);
+}
+
+static void
+gtk_list_item_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkBin *bin;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_LIST_ITEM (widget));
+ g_return_if_fail (requisition != NULL);
+
+ bin = GTK_BIN (widget);
+
+ requisition->width = (GTK_CONTAINER (widget)->border_width +
+ widget->style->klass->xthickness) * 2;
+ requisition->height = GTK_CONTAINER (widget)->border_width * 2;
+
+ if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
+ {
+ gtk_widget_size_request (bin->child, &bin->child->requisition);
+
+ requisition->width += bin->child->requisition.width;
+ requisition->height += bin->child->requisition.height;
+ }
+}
+
+static void
+gtk_list_item_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkBin *bin;
+ GtkAllocation child_allocation;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_LIST_ITEM (widget));
+ g_return_if_fail (allocation != NULL);
+
+ widget->allocation = *allocation;
+ if (GTK_WIDGET_REALIZED (widget))
+ gdk_window_move_resize (widget->window,
+ allocation->x, allocation->y,
+ allocation->width, allocation->height);
+
+ bin = GTK_BIN (widget);
+
+ if (bin->child)
+ {
+ child_allocation.x = (GTK_CONTAINER (widget)->border_width +
+ widget->style->klass->xthickness);
+ child_allocation.y = GTK_CONTAINER (widget)->border_width;
+ child_allocation.width = allocation->width - child_allocation.x * 2;
+ child_allocation.height = allocation->height - child_allocation.y * 2;
+
+ gtk_widget_size_allocate (bin->child, &child_allocation);
+ }
+}
+
+static void
+gtk_list_item_draw (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ GtkBin *bin;
+ GdkRectangle child_area;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_LIST_ITEM (widget));
+ g_return_if_fail (area != NULL);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ bin = GTK_BIN (widget);
+
+ if (!GTK_WIDGET_IS_SENSITIVE (widget))
+ gtk_style_set_background (widget->style, widget->window, GTK_STATE_INSENSITIVE);
+ else if (widget->state == GTK_STATE_NORMAL)
+ gdk_window_set_background (widget->window, &widget->style->white);
+ else
+ gtk_style_set_background (widget->style, widget->window, widget->state);
+
+ gdk_window_clear_area (widget->window, area->x, area->y,
+ area->width, area->height);
+
+ if (bin->child && gtk_widget_intersect (bin->child, area, &child_area))
+ gtk_widget_draw (bin->child, &child_area);
+
+ gtk_widget_draw_focus (widget);
+ }
+}
+
+static void
+gtk_list_item_draw_focus (GtkWidget *widget)
+{
+ GdkGC *gc;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_LIST_ITEM (widget));
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ if (GTK_WIDGET_HAS_FOCUS (widget))
+ gc = widget->style->black_gc;
+ else if (!GTK_WIDGET_IS_SENSITIVE (widget))
+ gc = widget->style->bg_gc[GTK_STATE_INSENSITIVE];
+ else if (widget->state == GTK_STATE_NORMAL)
+ gc = widget->style->white_gc;
+ else
+ gc = widget->style->bg_gc[widget->state];
+
+ gdk_draw_rectangle (widget->window, gc, FALSE, 0, 0,
+ widget->allocation.width - 1,
+ widget->allocation.height - 1);
+ }
+}
+
+static gint
+gtk_list_item_button_press (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_LIST_ITEM (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (event->type == GDK_BUTTON_PRESS)
+ if (!GTK_WIDGET_HAS_FOCUS (widget))
+ gtk_widget_grab_focus (widget);
+
+ return FALSE;
+}
+
+static gint
+gtk_list_item_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ GtkBin *bin;
+ GdkEventExpose child_event;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_LIST_ITEM (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ bin = GTK_BIN (widget);
+
+ if (!GTK_WIDGET_IS_SENSITIVE (widget))
+ gdk_window_set_background (widget->window, &widget->style->bg[GTK_STATE_INSENSITIVE]);
+ else if (widget->state == GTK_STATE_NORMAL)
+ gdk_window_set_background (widget->window, &widget->style->white);
+ else
+ gdk_window_set_background (widget->window, &widget->style->bg[widget->state]);
+
+ gdk_window_clear_area (widget->window, event->area.x, event->area.y,
+ event->area.width, event->area.height);
+
+ if (bin->child)
+ {
+ child_event = *event;
+
+ if (GTK_WIDGET_NO_WINDOW (bin->child) &&
+ gtk_widget_intersect (bin->child, &event->area, &child_event.area))
+ gtk_widget_event (bin->child, (GdkEvent*) &child_event);
+ }
+
+ gtk_widget_draw_focus (widget);
+ }
+
+ return FALSE;
+}
+
+static gint
+gtk_list_item_focus_in (GtkWidget *widget,
+ GdkEventFocus *event)
+{
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_LIST_ITEM (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
+ gtk_widget_draw_focus (widget);
+
+ return FALSE;
+}
+
+static gint
+gtk_list_item_focus_out (GtkWidget *widget,
+ GdkEventFocus *event)
+{
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_LIST_ITEM (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
+ gtk_widget_draw_focus (widget);
+
+ return FALSE;
+}
+
+static void
+gtk_real_list_item_select (GtkItem *item)
+{
+ g_return_if_fail (item != NULL);
+ g_return_if_fail (GTK_IS_LIST_ITEM (item));
+
+ if (GTK_WIDGET (item)->state == GTK_STATE_SELECTED)
+ return;
+
+ gtk_widget_set_state (GTK_WIDGET (item), GTK_STATE_SELECTED);
+ gtk_widget_queue_draw (GTK_WIDGET (item));
+}
+
+static void
+gtk_real_list_item_deselect (GtkItem *item)
+{
+ g_return_if_fail (item != NULL);
+ g_return_if_fail (GTK_IS_LIST_ITEM (item));
+
+ if (GTK_WIDGET (item)->state == GTK_STATE_NORMAL)
+ return;
+
+ gtk_widget_set_state (GTK_WIDGET (item), GTK_STATE_NORMAL);
+ gtk_widget_queue_draw (GTK_WIDGET (item));
+}
+
+static void
+gtk_real_list_item_toggle (GtkItem *item)
+{
+ g_return_if_fail (item != NULL);
+ g_return_if_fail (GTK_IS_LIST_ITEM (item));
+
+ if (GTK_WIDGET (item)->parent && GTK_IS_LIST (GTK_WIDGET (item)->parent))
+ gtk_list_select_child (GTK_LIST (GTK_WIDGET (item)->parent),
+ GTK_WIDGET (item));
+ else
+ {
+ /* Should we really bother with this bit? A listitem not in a list?
+ * -Johannes Keukelaar
+ * yes, always be on the save side!
+ * -timj
+ */
+ if (GTK_WIDGET (item)->state == GTK_STATE_SELECTED)
+ gtk_widget_set_state (GTK_WIDGET (item), GTK_STATE_NORMAL);
+ else
+ gtk_widget_set_state (GTK_WIDGET (item), GTK_STATE_SELECTED);
+ gtk_widget_queue_draw (GTK_WIDGET (item));
+ }
+}
diff --git a/gtk/gtklistitem.h b/gtk/gtklistitem.h
new file mode 100644
index 000000000..4220ae73f
--- /dev/null
+++ b/gtk/gtklistitem.h
@@ -0,0 +1,62 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_LIST_ITEM_H__
+#define __GTK_LIST_ITEM_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkitem.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_LIST_ITEM(obj) GTK_CHECK_CAST (obj, gtk_list_item_get_type (), GtkListItem)
+#define GTK_LIST_ITEM_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_list_item_get_type (), GtkListItemClass)
+#define GTK_IS_LIST_ITEM(obj) GTK_CHECK_TYPE (obj, gtk_list_item_get_type ())
+
+
+typedef struct _GtkListItem GtkListItem;
+typedef struct _GtkListItemClass GtkListItemClass;
+
+struct _GtkListItem
+{
+ GtkItem item;
+};
+
+struct _GtkListItemClass
+{
+ GtkItemClass parent_class;
+};
+
+
+guint gtk_list_item_get_type (void);
+GtkWidget* gtk_list_item_new (void);
+GtkWidget* gtk_list_item_new_with_label (const gchar *label);
+void gtk_list_item_select (GtkListItem *list_item);
+void gtk_list_item_deselect (GtkListItem *list_item);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_LIST_ITEM_H__ */
diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c
new file mode 100644
index 000000000..50d262430
--- /dev/null
+++ b/gtk/gtkmain.c
@@ -0,0 +1,1129 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include "gtkbutton.h"
+#include "gtkhscrollbar.h"
+#include "gtkhseparator.h"
+#include "gtkmain.h"
+#include "gtkpreview.h"
+#include "gtkrc.h"
+#include "gtkselection.h"
+#include "gtksignal.h"
+#include "gtktable.h"
+#include "gtktext.h"
+#include "gtkvbox.h"
+#include "gtkvscrollbar.h"
+#include "gtkwidget.h"
+#include "gtkwindow.h"
+
+
+/* Private type definitions
+ */
+typedef struct _GtkInitFunction GtkInitFunction;
+typedef struct _GtkTimeoutFunction GtkTimeoutFunction;
+typedef struct _GtkIdleFunction GtkIdleFunction;
+
+struct _GtkInitFunction
+{
+ GtkFunction function;
+ gpointer data;
+};
+
+struct _GtkTimeoutFunction
+{
+ gint tag;
+ guint32 start;
+ guint32 interval;
+ guint32 originterval;
+ gint interp;
+ GtkFunction function;
+ gpointer data;
+ GtkDestroyNotify destroy;
+};
+
+struct _GtkIdleFunction
+{
+ gint tag;
+ gint interp;
+ GtkFunction function;
+ gpointer data;
+ GtkDestroyNotify destroy;
+};
+
+
+static void gtk_exit_func (void);
+static void gtk_timeout_insert (GtkTimeoutFunction *timeoutf);
+static void gtk_handle_current_timeouts (guint32 the_time);
+static void gtk_handle_current_idles ();
+static void gtk_handle_timeouts (void);
+static void gtk_handle_idle (void);
+static void gtk_handle_timer (void);
+static void gtk_propagate_event (GtkWidget *widget,
+ GdkEvent *event);
+static void gtk_error (char *str);
+static void gtk_warning (char *str);
+static void gtk_message (char *str);
+static void gtk_print (char *str);
+
+
+static int done;
+static int initialized = FALSE;
+static GdkEvent next_event;
+static GdkEvent current_event;
+static gint have_event = FALSE;
+static gint have_next_event = FALSE;
+
+static GList *grabs = NULL; /* A list of grabs. The grabbing widget
+ * is the first one on the list.
+ */
+static GList *init_functions = NULL; /* A list of init functions.
+ */
+static GList *timeout_functions = NULL; /* A list of timeout functions sorted by
+ * when the length of the time interval
+ * remaining. Therefore, the first timeout
+ * function to expire is at the head of
+ * the list and the last to expire is at
+ * the tail of the list.
+ */
+static GList *idle_functions = NULL; /* A list of idle functions.
+ */
+
+static GList *current_idles = NULL;
+static GList *current_timeouts = NULL;
+static GMemChunk *timeout_mem_chunk = NULL;
+static GMemChunk *idle_mem_chunk = NULL;
+
+static GdkVisual *gtk_visual; /* The visual to be used in creating new
+ * widgets.
+ */
+static GdkColormap *gtk_colormap; /* The colormap to be used in creating new
+ * widgets.
+ */
+
+
+void
+gtk_init (int *argc,
+ char ***argv)
+{
+ if (0)
+ {
+ g_set_error_handler (gtk_error);
+ g_set_warning_handler (gtk_warning);
+ g_set_message_handler (gtk_message);
+ g_set_print_handler (gtk_print);
+ }
+
+ /* Initialize "gdk". We simply pass along the 'argc' and 'argv'
+ * parameters as they contain information that
+ */
+ gdk_init (argc, argv);
+
+ /* Initialize the default visual and colormap to be
+ * used in creating widgets. (We want to use the system
+ * defaults so as to be nice to the colormap).
+ */
+ gtk_visual = gdk_visual_get_system ();
+ gtk_colormap = gdk_colormap_get_system ();
+ gtk_rc_init ();
+
+ gtk_type_init ();
+
+ /* Register an exit function to make sure we are able to cleanup.
+ */
+ if (ATEXIT (gtk_exit_func))
+ g_warning ("unable to register exit function");
+
+ /* Set the 'initialized' flag.
+ */
+ initialized = TRUE;
+}
+
+void
+gtk_exit (int errorcode)
+{
+ /* Only if "gtk" has been initialized should we de-initialize.
+ */
+ /* de-initialisation is done by the gtk_exit_funct(),
+ no need to do this here (Alex J.) */
+ gdk_exit(errorcode);
+}
+
+gchar*
+gtk_set_locale ()
+{
+ return gdk_set_locale ();
+}
+
+void
+gtk_main ()
+{
+ GList *tmp_list;
+ GList *functions;
+ GtkInitFunction *init;
+ int old_done;
+
+ tmp_list = functions = init_functions;
+ init_functions = NULL;
+
+ while (tmp_list)
+ {
+ init = tmp_list->data;
+ tmp_list = tmp_list->next;
+
+ (* init->function) (init->data);
+ g_free (init);
+ }
+
+ g_list_free (functions);
+
+ old_done = done;
+ while (!gtk_main_iteration ())
+ ;
+ done = old_done;
+}
+
+void
+gtk_main_quit ()
+{
+ done = TRUE;
+}
+
+gint
+gtk_main_iteration ()
+{
+ GdkEvent event_copy;
+ GtkWidget *event_widget;
+ GtkWidget *grab_widget;
+
+ done = FALSE;
+
+ /* If this is a recursive call, and there are pending timeouts or
+ idles, finish them, then return immediately to avoid blocking
+ in gdk_event_get() */
+ if (current_timeouts)
+ {
+ gtk_handle_current_timeouts( gdk_time_get());
+ return done;
+ }
+ if (current_idles)
+ {
+ gtk_handle_current_idles();
+ return done;
+ }
+
+ /* If there is a valid event in 'next_event' then copy
+ * it to 'event' and unset the flag.
+ */
+ if (have_next_event)
+ {
+ have_next_event = FALSE;
+ have_event = TRUE;
+ current_event = next_event;
+ }
+
+ /* If we don't have an event then get one.
+ */
+ if (!have_event)
+ {
+ /* Handle setting of the "gdk" timer. If there are no
+ * timeout functions, then the timer is turned off.
+ * If there are timeout functions, then the timer is
+ * set to the shortest timeout interval (which is
+ * the first timeout function).
+ */
+ gtk_handle_timer ();
+
+ have_event = gdk_event_get (&current_event, NULL, NULL);
+ }
+
+ /* "gdk_event_get" can return FALSE if the timer goes off
+ * and no events are pending. Therefore, we should make
+ * sure that we got an event before continuing.
+ */
+ if (have_event)
+ {
+ have_event = FALSE;
+
+ /* If there are any events pending then get the next one.
+ */
+ if (gdk_events_pending () > 0)
+ have_next_event = gdk_event_get (&next_event, NULL, NULL);
+
+ /* Try to compress enter/leave notify events. These event
+ * pairs occur when the mouse is dragged quickly across
+ * a window with many buttons (or through a menu). Instead
+ * of highlighting and de-highlighting each widget that
+ * is crossed it is better to simply de-highlight the widget
+ * which contained the mouse initially and highlight the
+ * widget which ends up containing the mouse.
+ */
+ if (have_next_event)
+ if (((current_event.type == GDK_ENTER_NOTIFY) ||
+ (current_event.type == GDK_LEAVE_NOTIFY)) &&
+ ((next_event.type == GDK_ENTER_NOTIFY) ||
+ (next_event.type == GDK_LEAVE_NOTIFY)) &&
+ (next_event.type != current_event.type) &&
+ (next_event.any.window == current_event.any.window))
+ return done;
+
+ /* Find the widget which got the event. We store the widget
+ * in the user_data field of GdkWindow's.
+ */
+ event_widget = gtk_get_event_widget (&current_event);
+
+ /* If there is a grab in effect...
+ */
+ if (grabs)
+ {
+ grab_widget = grabs->data;
+
+ /* If the grab widget is an ancestor of the event widget
+ * then we send the event to the original event widget.
+ * This is the key to implementing modality.
+ */
+ if (gtk_widget_is_ancestor (event_widget, grab_widget))
+ grab_widget = event_widget;
+ }
+ else
+ {
+ grab_widget = event_widget;
+ }
+
+ /* Not all events get sent to the grabbing widget.
+ * The delete, destroy, expose, focus change and resize
+ * events still get sent to the event widget because
+ * 1) these events have no meaning for the grabbing widget
+ * and 2) redirecting these events to the grabbing widget
+ * could cause the display to be messed up.
+ */
+ event_copy = current_event;
+ switch (event_copy.type)
+ {
+ case GDK_NOTHING:
+ break;
+
+ case GDK_DELETE:
+ if (gtk_widget_event (event_widget, &event_copy))
+ gtk_widget_destroy (event_widget);
+ break;
+
+ case GDK_DESTROY:
+ gtk_widget_event (event_widget, &event_copy);
+ gtk_widget_destroy (event_widget);
+ break;
+
+ case GDK_PROPERTY_NOTIFY:
+ /* To handle selection INCR transactions, we select
+ PropertyNotify events on the requestor window and create
+ a corresponding (fake) GdkWindow so that events get
+ here. There won't be a widget though, so we have to handle
+ them specially */
+
+ if (event_widget == NULL)
+ {
+ gtk_selection_incr_event (event_copy.any.window,
+ &event_copy.property);
+ break;
+ }
+ /* otherwise fall through */
+
+ case GDK_EXPOSE:
+ case GDK_FOCUS_CHANGE:
+ case GDK_CONFIGURE:
+ case GDK_MAP:
+ case GDK_UNMAP:
+ case GDK_SELECTION_CLEAR:
+ case GDK_SELECTION_REQUEST:
+ case GDK_SELECTION_NOTIFY:
+ case GDK_CLIENT_EVENT:
+ gtk_widget_event (event_widget, &event_copy);
+ break;
+
+ case GDK_MOTION_NOTIFY:
+ case GDK_BUTTON_PRESS:
+ case GDK_2BUTTON_PRESS:
+ case GDK_3BUTTON_PRESS:
+ case GDK_BUTTON_RELEASE:
+ case GDK_KEY_PRESS:
+ case GDK_KEY_RELEASE:
+ case GDK_PROXIMITY_IN:
+ case GDK_PROXIMITY_OUT:
+ case GDK_OTHER_EVENT:
+ case GDK_DRAG_BEGIN:
+ case GDK_DRAG_REQUEST:
+ case GDK_DROP_ENTER:
+ case GDK_DROP_LEAVE:
+ case GDK_DROP_DATA_AVAIL:
+ gtk_propagate_event (grab_widget, &event_copy);
+ break;
+
+ case GDK_ENTER_NOTIFY:
+ case GDK_LEAVE_NOTIFY:
+ if (grab_widget && GTK_WIDGET_IS_SENSITIVE (grab_widget))
+ gtk_widget_event (grab_widget, &event_copy);
+ break;
+ }
+ }
+ else
+ {
+ if (gdk_events_pending() == 0)
+ gtk_handle_idle ();
+ }
+
+ /* Handle a timeout functions that may have expired.
+ */
+ gtk_handle_timeouts ();
+
+ return done;
+}
+
+gint
+gtk_true (void)
+{
+ return TRUE;
+}
+
+gint
+gtk_false (void)
+{
+ return FALSE;
+}
+
+void
+gtk_grab_add (GtkWidget *widget)
+{
+ /* Place the grab on the front of the list of grabs.
+ */
+ grabs = g_list_prepend (grabs, widget);
+}
+
+void
+gtk_grab_remove (GtkWidget *widget)
+{
+ /* Remove the grab from the list of grabs.
+ * Note: the grab being removed may be in
+ * the middle of the list.
+ */
+ grabs = g_list_remove (grabs, widget);
+}
+
+void
+gtk_init_add (GtkFunction function,
+ gpointer data)
+{
+ GtkInitFunction *init;
+
+ init = g_new (GtkInitFunction, 1);
+ init->function = function;
+ init->data = data;
+
+ init_functions = g_list_prepend (init_functions, init);
+}
+
+static gint
+gtk_timeout_add_internal (guint32 interval,
+ gint interp,
+ GtkFunction function,
+ gpointer data,
+ GtkDestroyNotify destroy)
+{
+ static gint timeout_tag = 1;
+ GtkTimeoutFunction *timeoutf;
+
+ /* Create a new timeout function structure.
+ * The start time is the current time.
+ */
+ if (!timeout_mem_chunk)
+ timeout_mem_chunk = g_mem_chunk_new ("timeout mem chunk", sizeof (GtkTimeoutFunction),
+ 1024, G_ALLOC_AND_FREE);
+
+ timeoutf = g_chunk_new (GtkTimeoutFunction, timeout_mem_chunk);
+
+ timeoutf->tag = timeout_tag++;
+ timeoutf->start = gdk_time_get ();
+ timeoutf->interval = interval;
+ timeoutf->originterval = interval;
+ timeoutf->interp = interp;
+ timeoutf->function = function;
+ timeoutf->data = data;
+ timeoutf->destroy = destroy;
+
+ gtk_timeout_insert (timeoutf);
+
+ return timeoutf->tag;
+}
+
+static void
+gtk_timeout_destroy (GtkTimeoutFunction *timeoutf)
+{
+ if (timeoutf->destroy)
+ (timeoutf->destroy) (timeoutf->data);
+ g_mem_chunk_free (timeout_mem_chunk, timeoutf);
+}
+
+gint
+gtk_timeout_add (guint32 interval,
+ GtkFunction function,
+ gpointer data)
+{
+ return gtk_timeout_add_internal (interval, FALSE, function, data, NULL);
+}
+
+gint
+gtk_timeout_add_interp (guint32 interval,
+ GtkCallbackMarshal function,
+ gpointer data,
+ GtkDestroyNotify destroy)
+{
+ return gtk_timeout_add_internal (interval, TRUE,
+ (GtkFunction) function,
+ data, destroy);
+}
+
+void
+gtk_timeout_remove (gint tag)
+{
+ GtkTimeoutFunction *timeoutf;
+ GList *tmp_list;
+
+ /* Remove a timeout function.
+ * (Which, basically, involves searching the
+ * list for the tag).
+ */
+ tmp_list = timeout_functions;
+ while (tmp_list)
+ {
+ timeoutf = tmp_list->data;
+
+ if (timeoutf->tag == tag)
+ {
+ timeout_functions = g_list_remove_link (timeout_functions, tmp_list);
+ g_list_free (tmp_list);
+ gtk_timeout_destroy (timeoutf);
+
+ return;
+ }
+
+ tmp_list = tmp_list->next;
+ }
+
+ tmp_list = current_timeouts;
+ while (tmp_list)
+ {
+ timeoutf = tmp_list->data;
+
+ if (timeoutf->tag == tag)
+ {
+ current_timeouts = g_list_remove_link (current_timeouts, tmp_list);
+ g_list_free (tmp_list);
+ gtk_timeout_destroy (timeoutf);
+
+ return;
+ }
+
+ tmp_list = tmp_list->next;
+ }
+}
+
+static gint
+gtk_idle_add_internal (gint interp,
+ GtkFunction function,
+ gpointer data,
+ GtkDestroyNotify destroy)
+{
+ static gint idle_tag = 1;
+ GtkIdleFunction *idlef;
+
+ if (!idle_mem_chunk)
+ idle_mem_chunk = g_mem_chunk_new ("idle mem chunk", sizeof (GtkIdleFunction),
+ 1024, G_ALLOC_AND_FREE);
+
+ idlef = g_chunk_new (GtkIdleFunction, idle_mem_chunk);
+
+ idlef->tag = idle_tag++;
+ idlef->interp = interp;
+ idlef->function = function;
+ idlef->data = data;
+ idlef->destroy = destroy;
+
+ idle_functions = g_list_append (idle_functions, idlef);
+
+ return idlef->tag;
+}
+
+static void
+gtk_idle_destroy (GtkIdleFunction *idlef)
+{
+ if (idlef->destroy)
+ idlef->destroy (idlef->data);
+ g_mem_chunk_free (idle_mem_chunk, idlef);
+}
+
+gint
+gtk_idle_add (GtkFunction function,
+ gpointer data)
+{
+ return gtk_idle_add_internal (FALSE, function, data, NULL);
+}
+
+gint
+gtk_idle_add_interp (GtkCallbackMarshal function,
+ gpointer data,
+ GtkDestroyNotify destroy)
+{
+ return gtk_idle_add_internal (TRUE, (GtkFunction)function, data, destroy);
+}
+
+void
+gtk_idle_remove (gint tag)
+{
+ GtkIdleFunction *idlef;
+ GList *tmp_list;
+
+ tmp_list = idle_functions;
+ while (tmp_list)
+ {
+ idlef = tmp_list->data;
+
+ if (idlef->tag == tag)
+ {
+ idle_functions = g_list_remove_link (idle_functions, tmp_list);
+ g_list_free (tmp_list);
+ gtk_idle_destroy (idlef);
+
+ return;
+ }
+
+ tmp_list = tmp_list->next;
+ }
+
+ tmp_list = current_idles;
+ while (tmp_list)
+ {
+ idlef = tmp_list->data;
+
+ if (idlef->tag == tag)
+ {
+ current_idles = g_list_remove_link (current_idles, tmp_list);
+ g_list_free (tmp_list);
+ gtk_idle_destroy (idlef);
+
+ return;
+ }
+
+ tmp_list = tmp_list->next;
+ }
+}
+
+void
+gtk_idle_remove_by_data (gpointer data)
+{
+ GtkIdleFunction *idlef;
+ GList *tmp_list;
+
+ tmp_list = idle_functions;
+ while (tmp_list)
+ {
+ idlef = tmp_list->data;
+
+ if (idlef->data == data)
+ {
+ idle_functions = g_list_remove_link (idle_functions, tmp_list);
+ g_list_free (tmp_list);
+ g_mem_chunk_free (idle_mem_chunk, idlef);
+
+ return;
+ }
+
+ tmp_list = tmp_list->next;
+ }
+
+ tmp_list = current_idles;
+ while (tmp_list)
+ {
+ idlef = tmp_list->data;
+
+ if (idlef->data == data)
+ {
+ current_idles = g_list_remove_link (current_idles, tmp_list);
+ g_list_free (tmp_list);
+ g_mem_chunk_free (idle_mem_chunk, idlef);
+
+ return;
+ }
+
+ tmp_list = tmp_list->next;
+ }
+}
+
+void
+gtk_get_current_event (GdkEvent *event)
+{
+ g_assert (event != NULL);
+
+ *event = current_event;
+}
+
+GtkWidget*
+gtk_get_event_widget (GdkEvent *event)
+{
+ GtkWidget *widget;
+ gdk_window_get_user_data (event->any.window, (void**) &widget);
+
+ return widget;
+}
+
+static void
+gtk_exit_func ()
+{
+ if (initialized)
+ {
+ initialized = FALSE;
+ gtk_preview_uninit ();
+ }
+}
+
+static void
+gtk_timeout_insert (GtkTimeoutFunction *timeoutf)
+{
+ GtkTimeoutFunction *temp;
+ GList *temp_list;
+ GList *new_list;
+
+ g_assert (timeoutf != NULL);
+
+ /* Insert the timeout function appropriately.
+ * Appropriately meaning sort it into the list
+ * of timeout functions.
+ */
+ temp_list = timeout_functions;
+ while (temp_list)
+ {
+ temp = temp_list->data;
+ if (timeoutf->interval < temp->interval)
+ {
+ new_list = g_list_alloc ();
+ new_list->data = timeoutf;
+ new_list->next = temp_list;
+ new_list->prev = temp_list->prev;
+ if (temp_list->prev)
+ temp_list->prev->next = new_list;
+ temp_list->prev = new_list;
+
+ if (temp_list == timeout_functions)
+ timeout_functions = new_list;
+
+ return;
+ }
+
+ temp_list = temp_list->next;
+ }
+
+ timeout_functions = g_list_append (timeout_functions, timeoutf);
+}
+
+static gint
+gtk_invoke_timeout_function (GtkTimeoutFunction *timeoutf)
+{
+ if (!timeoutf->interp)
+ return timeoutf->function (timeoutf->data);
+ else
+ {
+ GtkArg args[1];
+ gint ret_val = FALSE;
+ args[0].name = NULL;
+ args[0].type = GTK_TYPE_BOOL;
+ args[0].d.pointer_data = &ret_val;
+ ((GtkCallbackMarshal)timeoutf->function) (NULL,
+ timeoutf->data,
+ 0, args);
+ return ret_val;
+ }
+}
+
+static void
+gtk_handle_current_timeouts (guint32 the_time)
+{
+ GList *tmp_list;
+ GtkTimeoutFunction *timeoutf;
+
+ while (current_timeouts)
+ {
+ tmp_list = current_timeouts;
+ timeoutf = tmp_list->data;
+
+ current_timeouts = g_list_remove_link (current_timeouts, tmp_list);
+ g_list_free (tmp_list);
+
+ if (gtk_invoke_timeout_function (timeoutf) == FALSE)
+ {
+ gtk_timeout_destroy (timeoutf);
+ }
+ else
+ {
+ timeoutf->interval = timeoutf->originterval;
+ timeoutf->start = the_time;
+ gtk_timeout_insert (timeoutf);
+ }
+ }
+}
+
+/* Utility function - make up for an ommision in glib */
+static GList *
+gtk_main_list_concat (GList *list1, GList *list2)
+{
+ GList *tmp_list;
+ GList *list;
+
+ if (list2)
+ {
+ tmp_list = g_list_last (list1);
+ if (tmp_list)
+ tmp_list->next = list2;
+ else
+ list1 = list2;
+ list2->prev = tmp_list;
+ }
+
+ return list1;
+}
+
+static void
+gtk_handle_timeouts ()
+{
+ guint32 the_time;
+ GList *tmp_list;
+ GList *tmp_list2;
+ GList *tmp_list3;
+ GtkTimeoutFunction *timeoutf;
+
+ /* Caller must already have called gtk_handle_current_timeouts if
+ * necessary */
+ g_assert (current_timeouts == NULL);
+
+ if (timeout_functions)
+ {
+ the_time = gdk_time_get ();
+
+ tmp_list = timeout_functions;
+ while (tmp_list)
+ {
+ timeoutf = tmp_list->data;
+
+ if (timeoutf->interval <= (the_time - timeoutf->start))
+ {
+ tmp_list2 = tmp_list;
+ tmp_list = tmp_list->next;
+
+ timeout_functions = g_list_remove_link (timeout_functions, tmp_list2);
+ current_timeouts = gtk_main_list_concat (current_timeouts, tmp_list2);
+ }
+ else
+ {
+ timeoutf->interval -= (the_time - timeoutf->start);
+ timeoutf->start = the_time;
+ tmp_list = tmp_list->next;
+ }
+ }
+
+ if (current_timeouts)
+ gtk_handle_current_timeouts(the_time);
+ }
+}
+
+static gint
+gtk_idle_invoke_function (GtkIdleFunction *idlef)
+{
+ if (!idlef->interp)
+ return idlef->function (idlef->data);
+ else
+ {
+ GtkArg args[1];
+ gint ret_val = FALSE;
+ args[0].name = NULL;
+ args[0].type = GTK_TYPE_BOOL;
+ args[0].d.pointer_data = &ret_val;
+ ((GtkCallbackMarshal)idlef->function) (NULL,
+ idlef->data,
+ 0, args);
+ return ret_val;
+ }
+}
+
+static void
+gtk_handle_current_idles ()
+{
+ GList *tmp_list;
+ GtkIdleFunction *idlef;
+
+ while (current_idles)
+ {
+ tmp_list = current_idles;
+ idlef = tmp_list->data;
+
+ current_idles = g_list_remove_link (current_idles, tmp_list);
+
+ if (gtk_idle_invoke_function (idlef) == FALSE)
+ {
+ g_list_free (tmp_list);
+ gtk_idle_destroy (idlef);
+ }
+ else
+ {
+ idle_functions = gtk_main_list_concat (idle_functions, tmp_list);
+ }
+ }
+}
+
+static void
+gtk_handle_idle ()
+{
+ GtkIdleFunction *idlef;
+ GList *tmp_list;
+ GList *tmp_list2;
+
+ /* Caller must already have called gtk_handle_current_idles if
+ necessary */
+ g_assert (current_idles == NULL);
+
+ if (idle_functions)
+ {
+ current_idles = idle_functions;
+ idle_functions = NULL;
+
+ gtk_handle_current_idles();
+ }
+}
+
+static void
+gtk_handle_timer ()
+{
+ GtkTimeoutFunction *timeoutf;
+
+ if (idle_functions)
+ {
+ gdk_timer_set (0);
+ gdk_timer_enable ();
+ }
+ else if (timeout_functions)
+ {
+ timeoutf = timeout_functions->data;
+ gdk_timer_set (timeoutf->interval);
+ gdk_timer_enable ();
+ }
+ else
+ {
+ gdk_timer_set (0);
+ gdk_timer_disable ();
+ }
+}
+
+static void
+gtk_propagate_event (GtkWidget *widget,
+ GdkEvent *event)
+{
+ GtkWidget *parent;
+ gint handled_event;
+ gint parent_old_value;
+ gint old_value;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (event != NULL);
+
+ handled_event = FALSE;
+
+ if ((event->type == GDK_KEY_PRESS) ||
+ (event->type == GDK_KEY_RELEASE))
+ {
+ /* Only send key events to window widgets.
+ * The window widget will in turn pass the
+ * key event on to the currently focused widget
+ * for that window.
+ */
+ parent = gtk_widget_get_ancestor (widget, gtk_window_get_type ());
+ if (parent && GTK_WIDGET_IS_SENSITIVE (parent))
+ {
+ parent_old_value = GTK_OBJECT_IN_CALL (parent);
+ GTK_OBJECT_SET_FLAGS (parent, GTK_IN_CALL);
+
+ handled_event = gtk_widget_event (parent, event);
+
+ if (!parent_old_value)
+ GTK_OBJECT_UNSET_FLAGS (parent, GTK_IN_CALL);
+
+ if (GTK_OBJECT_NEED_DESTROY (parent) && !GTK_OBJECT_IN_CALL (parent))
+ {
+ gtk_object_destroy (GTK_OBJECT (parent));
+ return;
+ }
+ }
+ }
+
+ if (!handled_event)
+ {
+ old_value = GTK_OBJECT_IN_CALL (widget);
+ GTK_OBJECT_SET_FLAGS (widget, GTK_IN_CALL);
+
+ /* Other events get propagated up the widget tree
+ * so that parents can see the button and motion
+ * events of the children.
+ */
+ parent = widget;
+ while (parent)
+ {
+ parent_old_value = GTK_OBJECT_IN_CALL (parent);
+ GTK_OBJECT_SET_FLAGS (parent, GTK_IN_CALL);
+
+ handled_event = (!GTK_WIDGET_IS_SENSITIVE (parent) ||
+ gtk_widget_event (parent, event));
+
+ if (!parent_old_value)
+ GTK_OBJECT_UNSET_FLAGS (parent, GTK_IN_CALL);
+
+ if (handled_event)
+ break;
+
+ if (GTK_OBJECT_NEED_DESTROY (parent) && !GTK_OBJECT_IN_CALL (parent))
+ {
+ gtk_object_destroy (GTK_OBJECT (parent));
+ break;
+ }
+
+ parent = parent->parent;
+ }
+
+ if (!old_value)
+ GTK_OBJECT_UNSET_FLAGS (widget, GTK_IN_CALL);
+
+ if (GTK_OBJECT_NEED_DESTROY (widget) && !GTK_OBJECT_IN_CALL (widget))
+ gtk_object_destroy (GTK_OBJECT (widget));
+ }
+}
+
+
+static void
+gtk_error (char *str)
+{
+ gtk_print (str);
+}
+
+static void
+gtk_warning (char *str)
+{
+ gtk_print (str);
+}
+
+static void
+gtk_message (char *str)
+{
+ gtk_print (str);
+}
+
+static void
+gtk_print (char *str)
+{
+ static GtkWidget *window = NULL;
+ static GtkWidget *text;
+ static int level = 0;
+ GtkWidget *box1;
+ GtkWidget *box2;
+ GtkWidget *table;
+ GtkWidget *hscrollbar;
+ GtkWidget *vscrollbar;
+ GtkWidget *separator;
+ GtkWidget *button;
+
+ if (level > 0)
+ {
+ fputs (str, stdout);
+ fflush (stdout);
+ return;
+ }
+
+ if (!window)
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ /*
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) gtk_widget_destroyed,
+ &window);
+ */
+ gtk_window_set_title (GTK_WINDOW (window), "Messages");
+
+ box1 = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), box1);
+ gtk_widget_show (box1);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ table = gtk_table_new (2, 2, FALSE);
+ gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2);
+ gtk_table_set_col_spacing (GTK_TABLE (table), 0, 2);
+ gtk_box_pack_start (GTK_BOX (box2), table, TRUE, TRUE, 0);
+ gtk_widget_show (table);
+
+ text = gtk_text_new (NULL, NULL);
+ gtk_text_set_editable (GTK_TEXT (text), FALSE);
+ gtk_table_attach_defaults (GTK_TABLE (table), text, 0, 1, 0, 1);
+ gtk_widget_show (text);
+ gtk_widget_realize (text);
+
+ hscrollbar = gtk_hscrollbar_new (GTK_TEXT (text)->hadj);
+ gtk_table_attach (GTK_TABLE (table), hscrollbar, 0, 1, 1, 2,
+ GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
+ gtk_widget_show (hscrollbar);
+
+ vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
+ gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
+ GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+ gtk_widget_show (vscrollbar);
+
+ separator = gtk_hseparator_new ();
+ gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
+ gtk_widget_show (separator);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_hide,
+ GTK_OBJECT (window));
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+ }
+
+ level += 1;
+ gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, str, -1);
+ level -= 1;
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+}
diff --git a/gtk/gtkmain.h b/gtk/gtkmain.h
new file mode 100644
index 000000000..9d014e47c
--- /dev/null
+++ b/gtk/gtkmain.h
@@ -0,0 +1,76 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_MAIN_H__
+#define __GTK_MAIN_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkwidget.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* Initialization, exit, mainloop and miscellaneous routines
+ */
+void gtk_init (int *argc,
+ char ***argv);
+void gtk_exit (gint error_code);
+gchar* gtk_set_locale (void);
+void gtk_main (void);
+void gtk_main_quit (void);
+gint gtk_main_iteration (void);
+
+gint gtk_true (void);
+gint gtk_false (void);
+
+void gtk_grab_add (GtkWidget *widget);
+void gtk_grab_remove (GtkWidget *widget);
+
+void gtk_init_add (GtkFunction function,
+ gpointer data);
+
+gint gtk_timeout_add (guint32 interval,
+ GtkFunction function,
+ gpointer data);
+gint gtk_timeout_add_interp (guint32 interval,
+ GtkCallbackMarshal function,
+ gpointer data,
+ GtkDestroyNotify notify);
+void gtk_timeout_remove (gint tag);
+
+gint gtk_idle_add (GtkFunction function,
+ gpointer data);
+gint gtk_idle_add_interp (GtkCallbackMarshal function,
+ gpointer data,
+ GtkDestroyNotify destroy);
+void gtk_idle_remove (gint tag);
+void gtk_idle_remove_by_data (gpointer data);
+
+void gtk_get_current_event (GdkEvent *event);
+GtkWidget* gtk_get_event_widget (GdkEvent *event);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_MAIN_H__ */
diff --git a/gtk/gtkmenu.c b/gtk/gtkmenu.c
new file mode 100644
index 000000000..13fff9023
--- /dev/null
+++ b/gtk/gtkmenu.c
@@ -0,0 +1,732 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <ctype.h>
+#include "gdk/gdkkeysyms.h"
+#include "gtkmain.h"
+#include "gtkmenu.h"
+#include "gtkmenuitem.h"
+#include "gtksignal.h"
+
+
+#define MENU_ITEM_CLASS(w) GTK_MENU_ITEM_CLASS (GTK_OBJECT (w)->klass)
+
+
+static void gtk_menu_class_init (GtkMenuClass *klass);
+static void gtk_menu_init (GtkMenu *menu);
+static void gtk_menu_show (GtkWidget *widget);
+static void gtk_menu_map (GtkWidget *widget);
+static void gtk_menu_unmap (GtkWidget *widget);
+static void gtk_menu_realize (GtkWidget *widget);
+static void gtk_menu_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void gtk_menu_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static void gtk_menu_paint (GtkWidget *widget);
+static void gtk_menu_draw (GtkWidget *widget,
+ GdkRectangle *area);
+static gint gtk_menu_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+static gint gtk_menu_configure (GtkWidget *widget,
+ GdkEventConfigure *event);
+static gint gtk_menu_key_press (GtkWidget *widget,
+ GdkEventKey *event);
+static gint gtk_menu_need_resize (GtkContainer *container);
+static void gtk_menu_deactivate (GtkMenuShell *menu_shell);
+
+
+guint
+gtk_menu_get_type ()
+{
+ static guint menu_type = 0;
+
+ if (!menu_type)
+ {
+ GtkTypeInfo menu_info =
+ {
+ "GtkMenu",
+ sizeof (GtkMenu),
+ sizeof (GtkMenuClass),
+ (GtkClassInitFunc) gtk_menu_class_init,
+ (GtkObjectInitFunc) gtk_menu_init,
+ (GtkArgFunc) NULL,
+ };
+
+ menu_type = gtk_type_unique (gtk_menu_shell_get_type (), &menu_info);
+ }
+
+ return menu_type;
+}
+
+static void
+gtk_menu_class_init (GtkMenuClass *class)
+{
+ GtkWidgetClass *widget_class;
+ GtkContainerClass *container_class;
+ GtkMenuShellClass *menu_shell_class;
+
+ widget_class = (GtkWidgetClass*) class;
+ container_class = (GtkContainerClass*) class;
+ menu_shell_class = (GtkMenuShellClass*) class;
+
+ widget_class->show = gtk_menu_show;
+ widget_class->map = gtk_menu_map;
+ widget_class->unmap = gtk_menu_unmap;
+ widget_class->realize = gtk_menu_realize;
+ widget_class->draw = gtk_menu_draw;
+ widget_class->size_request = gtk_menu_size_request;
+ widget_class->size_allocate = gtk_menu_size_allocate;
+ widget_class->expose_event = gtk_menu_expose;
+ widget_class->configure_event = gtk_menu_configure;
+ widget_class->key_press_event = gtk_menu_key_press;
+
+ container_class->need_resize = gtk_menu_need_resize;
+
+ menu_shell_class->submenu_placement = GTK_LEFT_RIGHT;
+ menu_shell_class->deactivate = gtk_menu_deactivate;
+}
+
+static void
+gtk_menu_init (GtkMenu *menu)
+{
+ GTK_WIDGET_SET_FLAGS (menu, GTK_ANCHORED);
+
+ menu->parent_menu_item = NULL;
+ menu->old_active_menu_item = NULL;
+ menu->accelerator_table = NULL;
+ menu->position_func = NULL;
+ menu->position_func_data = NULL;
+
+ GTK_MENU_SHELL (menu)->menu_flag = TRUE;
+}
+
+GtkWidget*
+gtk_menu_new ()
+{
+ return GTK_WIDGET (gtk_type_new (gtk_menu_get_type ()));
+}
+
+void
+gtk_menu_append (GtkMenu *menu,
+ GtkWidget *child)
+{
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), child);
+}
+
+void
+gtk_menu_prepend (GtkMenu *menu,
+ GtkWidget *child)
+{
+ gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), child);
+}
+
+void
+gtk_menu_insert (GtkMenu *menu,
+ GtkWidget *child,
+ gint position)
+{
+ gtk_menu_shell_insert (GTK_MENU_SHELL (menu), child, position);
+}
+
+void
+gtk_menu_popup (GtkMenu *menu,
+ GtkWidget *parent_menu_shell,
+ GtkWidget *parent_menu_item,
+ GtkMenuPositionFunc func,
+ gpointer data,
+ gint button,
+ guint32 activate_time)
+{
+ g_return_if_fail (menu != NULL);
+ g_return_if_fail (GTK_IS_MENU (menu));
+
+ GTK_MENU_SHELL (menu)->parent_menu_shell = parent_menu_shell;
+ GTK_MENU_SHELL (menu)->active = TRUE;
+ GTK_MENU_SHELL (menu)->button = button;
+
+ menu->parent_menu_item = parent_menu_item;
+ menu->position_func = func;
+ menu->position_func_data = data;
+ GTK_MENU_SHELL (menu)->activate_time = activate_time;
+
+ gtk_widget_show (GTK_WIDGET (menu));
+ gtk_grab_add (GTK_WIDGET (menu));
+}
+
+void
+gtk_menu_popdown (GtkMenu *menu)
+{
+ GtkMenuShell *menu_shell;
+
+ g_return_if_fail (menu != NULL);
+ g_return_if_fail (GTK_IS_MENU (menu));
+
+ menu_shell = GTK_MENU_SHELL (menu);
+
+ menu_shell->parent_menu_shell = NULL;
+ menu_shell->active = FALSE;
+
+ if (menu_shell->active_menu_item)
+ {
+ menu->old_active_menu_item = menu_shell->active_menu_item;
+ gtk_menu_item_deselect (GTK_MENU_ITEM (menu_shell->active_menu_item));
+ menu_shell->active_menu_item = NULL;
+ }
+
+ gtk_widget_hide (GTK_WIDGET (menu));
+ gtk_grab_remove (GTK_WIDGET (menu));
+}
+
+GtkWidget*
+gtk_menu_get_active (GtkMenu *menu)
+{
+ GtkWidget *child;
+ GList *children;
+
+ g_return_val_if_fail (menu != NULL, NULL);
+ g_return_val_if_fail (GTK_IS_MENU (menu), NULL);
+
+ if (!menu->old_active_menu_item)
+ {
+ child = NULL;
+ children = GTK_MENU_SHELL (menu)->children;
+
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (GTK_BIN (child)->child)
+ break;
+ child = NULL;
+ }
+
+ menu->old_active_menu_item = child;
+ }
+
+ return menu->old_active_menu_item;
+}
+
+void
+gtk_menu_set_active (GtkMenu *menu,
+ gint index)
+{
+ GtkWidget *child;
+ GList *tmp_list;
+
+ g_return_if_fail (menu != NULL);
+ g_return_if_fail (GTK_IS_MENU (menu));
+
+ tmp_list = g_list_nth (GTK_MENU_SHELL (menu)->children, index);
+ if (tmp_list)
+ {
+ child = tmp_list->data;
+ if (GTK_BIN (child)->child)
+ menu->old_active_menu_item = child;
+ }
+}
+
+void
+gtk_menu_set_accelerator_table (GtkMenu *menu,
+ GtkAcceleratorTable *table)
+{
+ g_return_if_fail (menu != NULL);
+ g_return_if_fail (GTK_IS_MENU (menu));
+
+ if (menu->accelerator_table)
+ gtk_accelerator_table_unref (menu->accelerator_table);
+
+ menu->accelerator_table = table;
+ if (menu->accelerator_table)
+ gtk_accelerator_table_ref (menu->accelerator_table);
+}
+
+
+static void
+gtk_menu_show (GtkWidget *widget)
+{
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_MENU (widget));
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
+ gtk_widget_map (widget);
+}
+
+static void
+gtk_menu_map (GtkWidget *widget)
+{
+ GtkMenu *menu;
+ GtkMenuShell *menu_shell;
+ GtkWidget *child;
+ GList *children;
+ GtkAllocation allocation;
+ gint x, y;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_MENU (widget));
+
+ menu = GTK_MENU (widget);
+ menu_shell = GTK_MENU_SHELL (widget);
+ GTK_WIDGET_SET_FLAGS (menu_shell, GTK_MAPPED);
+ GTK_WIDGET_UNSET_FLAGS (menu_shell, GTK_UNMAPPED);
+
+ gtk_widget_size_request (widget, &widget->requisition);
+
+ if (menu_shell->menu_flag)
+ {
+ menu_shell->menu_flag = FALSE;
+
+ allocation.x = widget->allocation.x;
+ allocation.y = widget->allocation.y;
+ allocation.width = widget->requisition.width;
+ allocation.height = widget->requisition.height;
+
+ gtk_widget_size_allocate (widget, &allocation);
+ }
+
+ gdk_window_get_pointer (NULL, &x, &y, NULL);
+
+ if (menu->position_func)
+ (* menu->position_func) (menu, &x, &y, menu->position_func_data);
+ else
+ {
+ gint screen_width;
+ gint screen_height;
+
+ screen_width = gdk_screen_width ();
+ screen_height = gdk_screen_height ();
+
+ x -= 2;
+ y -= 2;
+
+ if ((x + widget->requisition.width) > screen_width)
+ x -= ((x + widget->requisition.width) - screen_width);
+ if (x < 0)
+ x = 0;
+ if ((y + widget->requisition.height) > screen_height)
+ y -= ((y + widget->requisition.height) - screen_height);
+ if (y < 0)
+ y = 0;
+ }
+
+ gdk_window_move_resize (widget->window, x, y,
+ widget->requisition.width,
+ widget->requisition.height);
+
+ children = menu_shell->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_VISIBLE (child) && !GTK_WIDGET_MAPPED (child))
+ gtk_widget_map (child);
+ }
+
+ gdk_window_show (widget->window);
+}
+
+static void
+gtk_menu_unmap (GtkWidget *widget)
+{
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_MENU (widget));
+
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
+ GTK_WIDGET_SET_FLAGS (widget, GTK_UNMAPPED);
+ gdk_window_hide (widget->window);
+}
+
+static void
+gtk_menu_realize (GtkWidget *widget)
+{
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_MENU (widget));
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+
+ attributes.x = widget->allocation.x;
+ attributes.y = widget->allocation.y;
+ attributes.width = widget->allocation.width;
+ attributes.height = widget->allocation.height;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
+ attributes.window_type = GDK_WINDOW_TEMP;
+ attributes.event_mask = gtk_widget_get_events (widget);
+ attributes.event_mask |= (GDK_EXPOSURE_MASK |
+ GDK_KEY_PRESS_MASK |
+ GDK_STRUCTURE_MASK);
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+ widget->window = gdk_window_new (NULL, &attributes, attributes_mask);
+ gdk_window_set_user_data (widget->window, widget);
+
+ widget->style = gtk_style_attach (widget->style, widget->window);
+ gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
+}
+
+static void
+gtk_menu_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkMenu *menu;
+ GtkMenuShell *menu_shell;
+ GtkWidget *child;
+ GList *children;
+ gint max_accelerator_size;
+ gint max_toggle_size;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_MENU (widget));
+ g_return_if_fail (requisition != NULL);
+
+ menu = GTK_MENU (widget);
+ menu_shell = GTK_MENU_SHELL (widget);
+
+ requisition->width = 0;
+ requisition->height = 0;
+
+ max_accelerator_size = 0;
+ max_toggle_size = 0;
+
+ children = menu_shell->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_VISIBLE (child))
+ {
+ GTK_MENU_ITEM (child)->show_submenu_indicator = TRUE;
+ gtk_widget_size_request (child, &child->requisition);
+
+ requisition->width = MAX (requisition->width, child->requisition.width);
+ requisition->height += child->requisition.height;
+
+ max_accelerator_size = MAX (max_accelerator_size, GTK_MENU_ITEM (child)->accelerator_size);
+ max_toggle_size = MAX (max_toggle_size, MENU_ITEM_CLASS (child)->toggle_size);
+ }
+ }
+
+ requisition->width += max_toggle_size + max_accelerator_size;
+ requisition->width += (GTK_CONTAINER (menu)->border_width +
+ widget->style->klass->xthickness) * 2;
+ requisition->height += (GTK_CONTAINER (menu)->border_width +
+ widget->style->klass->ythickness) * 2;
+
+ children = menu_shell->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ GTK_MENU_ITEM (child)->accelerator_size = max_accelerator_size;
+ GTK_MENU_ITEM (child)->toggle_size = max_toggle_size;
+ }
+}
+
+static void
+gtk_menu_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkMenu *menu;
+ GtkMenuShell *menu_shell;
+ GtkWidget *child;
+ GtkAllocation child_allocation;
+ GList *children;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_MENU (widget));
+ g_return_if_fail (allocation != NULL);
+
+ menu = GTK_MENU (widget);
+ menu_shell = GTK_MENU_SHELL (widget);
+
+ widget->allocation = *allocation;
+
+ if (menu_shell->children)
+ {
+ child_allocation.x = (GTK_CONTAINER (menu)->border_width +
+ widget->style->klass->xthickness);
+ child_allocation.y = (GTK_CONTAINER (menu)->border_width +
+ widget->style->klass->ythickness);
+ child_allocation.width = allocation->width - child_allocation.x * 2;
+
+ children = menu_shell->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_VISIBLE (child))
+ {
+ child_allocation.height = child->requisition.height;
+
+ gtk_widget_size_allocate (child, &child_allocation);
+
+ child_allocation.y += child_allocation.height;
+ }
+ }
+ }
+}
+
+static void
+gtk_menu_paint (GtkWidget *widget)
+{
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_MENU (widget));
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ gtk_draw_shadow (widget->style,
+ widget->window,
+ GTK_STATE_NORMAL,
+ GTK_SHADOW_OUT,
+ 0, 0,
+ widget->allocation.width,
+ widget->allocation.height);
+ }
+}
+
+static void
+gtk_menu_draw (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ GtkMenuShell *menu_shell;
+ GtkWidget *child;
+ GdkRectangle child_area;
+ GList *children;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_MENU (widget));
+ g_return_if_fail (area != NULL);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ gtk_menu_paint (widget);
+
+ menu_shell = GTK_MENU_SHELL (widget);
+
+ children = menu_shell->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (gtk_widget_intersect (child, area, &child_area))
+ gtk_widget_draw (child, &child_area);
+ }
+ }
+}
+
+static gint
+gtk_menu_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ GtkMenuShell *menu_shell;
+ GtkWidget *child;
+ GdkEventExpose child_event;
+ GList *children;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_MENU (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (!GTK_WIDGET_UNMAPPED (widget))
+ GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ gtk_menu_paint (widget);
+
+ menu_shell = GTK_MENU_SHELL (widget);
+ child_event = *event;
+
+ children = menu_shell->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_NO_WINDOW (child) &&
+ gtk_widget_intersect (child, &event->area, &child_event.area))
+ gtk_widget_event (child, (GdkEvent*) &child_event);
+ }
+ }
+
+ return FALSE;
+}
+
+static gint
+gtk_menu_configure (GtkWidget *widget,
+ GdkEventConfigure *event)
+{
+ GtkAllocation allocation;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_MENU (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (GTK_MENU_SHELL (widget)->menu_flag)
+ {
+ GTK_MENU_SHELL (widget)->menu_flag = FALSE;
+
+ allocation.x = 0;
+ allocation.y = 0;
+ allocation.width = event->width;
+ allocation.height = event->height;
+
+ gtk_widget_size_allocate (widget, &allocation);
+ }
+
+ return FALSE;
+}
+
+static gint
+gtk_menu_key_press (GtkWidget *widget,
+ GdkEventKey *event)
+{
+ GtkAllocation allocation;
+ GtkAcceleratorTable *table;
+ GtkMenuShell *menu_shell;
+ GtkMenuItem *menu_item;
+ gchar *signame;
+ int delete;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_MENU (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ delete = ((event->keyval == GDK_Delete) ||
+ (event->keyval == GDK_BackSpace));
+
+ if (delete || ((event->keyval >= 0x20) && (event->keyval <= 0xFF)))
+ {
+ menu_shell = GTK_MENU_SHELL (widget);
+ menu_item = GTK_MENU_ITEM (menu_shell->active_menu_item);
+
+ if (menu_item && GTK_BIN (menu_item)->child)
+ {
+ /* block resizes */
+ gtk_container_block_resize (GTK_CONTAINER (widget));
+
+ table = NULL;
+ /* if the menu item currently has an accelerator then we'll
+ * remove it before we do anything else.
+ */
+ if (menu_item->accelerator_signal)
+ {
+ signame = gtk_signal_name (menu_item->accelerator_signal);
+ table = gtk_accelerator_table_find (GTK_OBJECT (widget),
+ signame,
+ menu_item->accelerator_key,
+ menu_item->accelerator_mods);
+ if (!table)
+ table = GTK_MENU (widget)->accelerator_table;
+ gtk_widget_remove_accelerator (GTK_WIDGET (menu_item),
+ table, signame);
+ }
+
+ if (!table)
+ table = GTK_MENU (widget)->accelerator_table;
+
+ /* if we aren't simply deleting the accelerator, then we'll install
+ * the new one now.
+ */
+ if (!delete)
+ gtk_widget_install_accelerator (GTK_WIDGET (menu_item),
+ table, "activate",
+ toupper (event->keyval),
+ event->state);
+
+ /* check and see if the menu has changed size. */
+ gtk_widget_size_request (widget, &widget->requisition);
+
+ allocation.x = widget->allocation.x;
+ allocation.y = widget->allocation.y;
+ allocation.width = widget->requisition.width;
+ allocation.height = widget->requisition.height;
+
+ if ((allocation.width == widget->allocation.width) &&
+ (allocation.height == widget->allocation.height))
+ {
+ gtk_widget_queue_draw (widget);
+ }
+ else
+ {
+ gtk_widget_size_allocate (GTK_WIDGET (widget), &allocation);
+ gtk_menu_map (widget);
+ }
+
+ /* unblock resizes */
+ gtk_container_unblock_resize (GTK_CONTAINER (widget));
+ }
+ }
+
+ return FALSE;
+}
+
+static gint
+gtk_menu_need_resize (GtkContainer *container)
+{
+ GtkAllocation allocation;
+
+ g_return_val_if_fail (container != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_MENU (container), FALSE);
+
+ if (GTK_WIDGET_VISIBLE (container))
+ {
+ GTK_MENU_SHELL (container)->menu_flag = FALSE;
+
+ gtk_widget_size_request (GTK_WIDGET (container),
+ &GTK_WIDGET (container)->requisition);
+
+ allocation.x = GTK_WIDGET (container)->allocation.x;
+ allocation.y = GTK_WIDGET (container)->allocation.y;
+ allocation.width = GTK_WIDGET (container)->requisition.width;
+ allocation.height = GTK_WIDGET (container)->requisition.height;
+
+ gtk_widget_size_allocate (GTK_WIDGET (container), &allocation);
+ }
+ else
+ {
+ GTK_MENU_SHELL (container)->menu_flag = TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+gtk_menu_deactivate (GtkMenuShell *menu_shell)
+{
+ GtkMenuShell *parent;
+
+ g_return_if_fail (menu_shell != NULL);
+ g_return_if_fail (GTK_IS_MENU (menu_shell));
+
+ parent = GTK_MENU_SHELL (menu_shell->parent_menu_shell);
+
+ menu_shell->activate_time = 0;
+ gtk_menu_popdown (GTK_MENU (menu_shell));
+
+ if (parent)
+ gtk_menu_shell_deactivate (parent);
+}
diff --git a/gtk/gtkmenu.h b/gtk/gtkmenu.h
new file mode 100644
index 000000000..5cd5d28fa
--- /dev/null
+++ b/gtk/gtkmenu.h
@@ -0,0 +1,94 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_MENU_H__
+#define __GTK_MENU_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkaccelerator.h>
+#include <gtk/gtkmenushell.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_MENU(obj) GTK_CHECK_CAST (obj, gtk_menu_get_type (), GtkMenu)
+#define GTK_MENU_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_menu_get_type (), GtkMenuClass)
+#define GTK_IS_MENU(obj) GTK_CHECK_TYPE (obj, gtk_menu_get_type ())
+
+
+typedef struct _GtkMenu GtkMenu;
+typedef struct _GtkMenuClass GtkMenuClass;
+
+typedef void (*GtkMenuPositionFunc) (GtkMenu *menu,
+ gint *x,
+ gint *y,
+ gpointer user_data);
+
+struct _GtkMenu
+{
+ GtkMenuShell menu_shell;
+
+ GList *children;
+
+ GtkWidget *parent_menu_item;
+ GtkWidget *old_active_menu_item;
+
+ GtkAcceleratorTable *accelerator_table;
+ GtkMenuPositionFunc position_func;
+ gpointer position_func_data;
+};
+
+struct _GtkMenuClass
+{
+ GtkMenuShellClass parent_class;
+};
+
+
+guint gtk_menu_get_type (void);
+GtkWidget* gtk_menu_new (void);
+void gtk_menu_append (GtkMenu *menu,
+ GtkWidget *child);
+void gtk_menu_prepend (GtkMenu *menu,
+ GtkWidget *child);
+void gtk_menu_insert (GtkMenu *menu,
+ GtkWidget *child,
+ gint position);
+void gtk_menu_popup (GtkMenu *menu,
+ GtkWidget *parent_menu_shell,
+ GtkWidget *parent_menu_item,
+ GtkMenuPositionFunc func,
+ gpointer data,
+ gint button,
+ guint32 activate_time);
+void gtk_menu_popdown (GtkMenu *menu);
+GtkWidget* gtk_menu_get_active (GtkMenu *menu);
+void gtk_menu_set_active (GtkMenu *menu,
+ gint index);
+void gtk_menu_set_accelerator_table (GtkMenu *menu,
+ GtkAcceleratorTable *table);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_MENU_H__ */
diff --git a/gtk/gtkmenubar.c b/gtk/gtkmenubar.c
new file mode 100644
index 000000000..19f0aa3e7
--- /dev/null
+++ b/gtk/gtkmenubar.c
@@ -0,0 +1,310 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtkmain.h"
+#include "gtkmenubar.h"
+#include "gtkmenuitem.h"
+
+
+#define BORDER_SPACING 2
+#define CHILD_SPACING 3
+
+
+static void gtk_menu_bar_class_init (GtkMenuBarClass *klass);
+static void gtk_menu_bar_init (GtkMenuBar *menu_bar);
+static void gtk_menu_bar_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void gtk_menu_bar_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static void gtk_menu_bar_paint (GtkWidget *widget);
+static void gtk_menu_bar_draw (GtkWidget *widget,
+ GdkRectangle *area);
+static gint gtk_menu_bar_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+
+
+guint
+gtk_menu_bar_get_type ()
+{
+ static guint menu_bar_type = 0;
+
+ if (!menu_bar_type)
+ {
+ GtkTypeInfo menu_bar_info =
+ {
+ "GtkMenuBar",
+ sizeof (GtkMenuBar),
+ sizeof (GtkMenuBarClass),
+ (GtkClassInitFunc) gtk_menu_bar_class_init,
+ (GtkObjectInitFunc) gtk_menu_bar_init,
+ (GtkArgFunc) NULL,
+ };
+
+ menu_bar_type = gtk_type_unique (gtk_menu_shell_get_type (), &menu_bar_info);
+ }
+
+ return menu_bar_type;
+}
+
+static void
+gtk_menu_bar_class_init (GtkMenuBarClass *class)
+{
+ GtkWidgetClass *widget_class;
+ GtkMenuShellClass *menu_shell_class;
+
+ widget_class = (GtkWidgetClass*) class;
+ menu_shell_class = (GtkMenuShellClass*) class;
+
+ widget_class->draw = gtk_menu_bar_draw;
+ widget_class->size_request = gtk_menu_bar_size_request;
+ widget_class->size_allocate = gtk_menu_bar_size_allocate;
+ widget_class->expose_event = gtk_menu_bar_expose;
+
+ menu_shell_class->submenu_placement = GTK_TOP_BOTTOM;
+}
+
+static void
+gtk_menu_bar_init (GtkMenuBar *menu_bar)
+{
+}
+
+GtkWidget*
+gtk_menu_bar_new ()
+{
+ return GTK_WIDGET (gtk_type_new (gtk_menu_bar_get_type ()));
+}
+
+void
+gtk_menu_bar_append (GtkMenuBar *menu_bar,
+ GtkWidget *child)
+{
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar), child);
+}
+
+void
+gtk_menu_bar_prepend (GtkMenuBar *menu_bar,
+ GtkWidget *child)
+{
+ gtk_menu_shell_prepend (GTK_MENU_SHELL (menu_bar), child);
+}
+
+void
+gtk_menu_bar_insert (GtkMenuBar *menu_bar,
+ GtkWidget *child,
+ gint position)
+{
+ gtk_menu_shell_insert (GTK_MENU_SHELL (menu_bar), child, position);
+}
+
+
+static void
+gtk_menu_bar_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkMenuBar *menu_bar;
+ GtkMenuShell *menu_shell;
+ GtkWidget *child;
+ GList *children;
+ gint nchildren;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_MENU_BAR (widget));
+ g_return_if_fail (requisition != NULL);
+
+ requisition->width = 0;
+ requisition->height = 0;
+
+ if (GTK_WIDGET_VISIBLE (widget))
+ {
+ menu_bar = GTK_MENU_BAR (widget);
+ menu_shell = GTK_MENU_SHELL (widget);
+
+ nchildren = 0;
+ children = menu_shell->children;
+
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_VISIBLE (child))
+ {
+ GTK_MENU_ITEM (child)->show_submenu_indicator = FALSE;
+ gtk_widget_size_request (child, &child->requisition);
+
+ requisition->width += child->requisition.width;
+ requisition->height = MAX (requisition->height, child->requisition.height);
+
+ nchildren += 1;
+ }
+ }
+
+ requisition->width += (GTK_CONTAINER (menu_bar)->border_width +
+ widget->style->klass->xthickness +
+ BORDER_SPACING) * 2;
+ requisition->height += (GTK_CONTAINER (menu_bar)->border_width +
+ widget->style->klass->ythickness +
+ BORDER_SPACING) * 2;
+
+ if (nchildren > 0)
+ requisition->width += 2 * CHILD_SPACING * (nchildren - 1);
+ }
+}
+
+static void
+gtk_menu_bar_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkMenuBar *menu_bar;
+ GtkMenuShell *menu_shell;
+ GtkWidget *child;
+ GList *children;
+ GtkAllocation child_allocation;
+ guint offset;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_MENU_BAR (widget));
+ g_return_if_fail (allocation != NULL);
+
+ menu_bar = GTK_MENU_BAR (widget);
+ menu_shell = GTK_MENU_SHELL (widget);
+
+ widget->allocation = *allocation;
+ if (GTK_WIDGET_REALIZED (widget))
+ gdk_window_move_resize (widget->window,
+ allocation->x, allocation->y,
+ allocation->width, allocation->height);
+
+ if (menu_shell->children)
+ {
+ child_allocation.x = (GTK_CONTAINER (menu_bar)->border_width +
+ widget->style->klass->xthickness +
+ BORDER_SPACING);
+ offset = child_allocation.x; /* Window edge to menubar start */
+
+ child_allocation.y = (GTK_CONTAINER (menu_bar)->border_width +
+ widget->style->klass->ythickness +
+ BORDER_SPACING);
+ child_allocation.height = allocation->height - child_allocation.y * 2;
+
+ children = menu_shell->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ /* Support for the right justified help menu */
+ if ( (children == NULL) && (GTK_IS_MENU_ITEM(child))
+ && (GTK_MENU_ITEM(child)->right_justify)) {
+ child_allocation.x = allocation->width -
+ child_allocation.width - CHILD_SPACING - offset;
+ }
+ if (GTK_WIDGET_VISIBLE (child))
+ {
+ child_allocation.width = child->requisition.width;
+
+ gtk_widget_size_allocate (child, &child_allocation);
+
+ child_allocation.x += child_allocation.width + CHILD_SPACING * 2;
+ }
+ }
+ }
+}
+
+static void
+gtk_menu_bar_paint (GtkWidget *widget)
+{
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_MENU_BAR (widget));
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ gtk_draw_shadow (widget->style,
+ widget->window,
+ GTK_STATE_NORMAL,
+ GTK_SHADOW_OUT,
+ 0, 0,
+ widget->allocation.width,
+ widget->allocation.height);
+ }
+}
+
+static void
+gtk_menu_bar_draw (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ GtkMenuShell *menu_shell;
+ GtkWidget *child;
+ GdkRectangle child_area;
+ GList *children;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_MENU_BAR (widget));
+ g_return_if_fail (area != NULL);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ gtk_menu_bar_paint (widget);
+
+ menu_shell = GTK_MENU_SHELL (widget);
+
+ children = menu_shell->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (gtk_widget_intersect (child, area, &child_area))
+ gtk_widget_draw (child, &child_area);
+ }
+ }
+}
+
+static gint
+gtk_menu_bar_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ GtkMenuShell *menu_shell;
+ GtkWidget *child;
+ GdkEventExpose child_event;
+ GList *children;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_MENU_BAR (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ gtk_menu_bar_paint (widget);
+
+ menu_shell = GTK_MENU_SHELL (widget);
+ child_event = *event;
+
+ children = menu_shell->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_NO_WINDOW (child) &&
+ gtk_widget_intersect (child, &event->area, &child_event.area))
+ gtk_widget_event (child, (GdkEvent*) &child_event);
+ }
+ }
+
+ return FALSE;
+}
diff --git a/gtk/gtkmenubar.h b/gtk/gtkmenubar.h
new file mode 100644
index 000000000..691e8f36f
--- /dev/null
+++ b/gtk/gtkmenubar.h
@@ -0,0 +1,66 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_MENU_BAR_H__
+#define __GTK_MENU_BAR_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkmenushell.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_MENU_BAR(obj) GTK_CHECK_CAST (obj, gtk_menu_bar_get_type (), GtkMenuBar)
+#define GTK_MENU_BAR_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_menu_bar_get_type (), GtkMenuBarClass)
+#define GTK_IS_MENU_BAR(obj) GTK_CHECK_TYPE (obj, gtk_menu_bar_get_type ())
+
+
+typedef struct _GtkMenuBar GtkMenuBar;
+typedef struct _GtkMenuBarClass GtkMenuBarClass;
+
+struct _GtkMenuBar
+{
+ GtkMenuShell menu_shell;
+};
+
+struct _GtkMenuBarClass
+{
+ GtkMenuShellClass parent_class;
+};
+
+
+guint gtk_menu_bar_get_type (void);
+GtkWidget* gtk_menu_bar_new (void);
+void gtk_menu_bar_append (GtkMenuBar *menu_bar,
+ GtkWidget *child);
+void gtk_menu_bar_prepend (GtkMenuBar *menu_bar,
+ GtkWidget *child);
+void gtk_menu_bar_insert (GtkMenuBar *menu_bar,
+ GtkWidget *child,
+ gint position);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_MENU_BAR_H__ */
diff --git a/gtk/gtkmenufactory.c b/gtk/gtkmenufactory.c
new file mode 100644
index 000000000..d6e9ea684
--- /dev/null
+++ b/gtk/gtkmenufactory.c
@@ -0,0 +1,541 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <string.h>
+#include "gtkcheckmenuitem.h"
+#include "gtkmenu.h"
+#include "gtkmenubar.h"
+#include "gtkmenufactory.h"
+#include "gtkmenuitem.h"
+#include "gtksignal.h"
+
+
+enum
+{
+ CREATE = 1 << 0,
+ DESTROY = 1 << 1,
+ CHECK = 1 << 2
+};
+
+
+static void gtk_menu_factory_create (GtkMenuFactory *factory,
+ GtkMenuEntry *entry,
+ GtkWidget *parent,
+ const char *path);
+static void gtk_menu_factory_remove (GtkMenuFactory *factory,
+ GtkWidget *parent,
+ const char *path);
+static GtkWidget* gtk_menu_factory_make_widget (GtkMenuFactory *factory);
+static GtkMenuPath* gtk_menu_factory_get (GtkWidget *parent,
+ const char *path,
+ int flags);
+static GtkMenuPath* gtk_menu_factory_find_recurse (GtkMenuFactory *factory,
+ GtkWidget *parent,
+ const char *path);
+static void gtk_menu_factory_parse_accelerator (const char *accelerator,
+ char *accelerator_key,
+ guint8 *accelerator_mods);
+
+
+GtkMenuFactory*
+gtk_menu_factory_new (GtkMenuFactoryType type)
+{
+ GtkMenuFactory *factory;
+
+ factory = g_new (GtkMenuFactory, 1);
+ factory->path = NULL;
+ factory->type = type;
+ factory->table = NULL;
+ factory->widget = NULL;
+ factory->subfactories = NULL;
+
+ return factory;
+}
+
+void
+gtk_menu_factory_destroy (GtkMenuFactory *factory)
+{
+ GtkMenuFactory *subfactory;
+ GList *tmp_list;
+
+ g_return_if_fail (factory != NULL);
+
+ if (factory->path)
+ g_free (factory->path);
+
+ tmp_list = factory->subfactories;
+ while (tmp_list)
+ {
+ subfactory = tmp_list->data;
+ tmp_list = tmp_list->next;
+
+ gtk_menu_factory_destroy (subfactory);
+ }
+}
+
+void
+gtk_menu_factory_add_entries (GtkMenuFactory *factory,
+ GtkMenuEntry *entries,
+ int nentries)
+{
+ int i;
+
+ g_return_if_fail (factory != NULL);
+ g_return_if_fail (entries != NULL);
+ g_return_if_fail (nentries > 0);
+
+ if (!factory->widget)
+ factory->widget = gtk_menu_factory_make_widget (factory);
+
+ for (i = 0; i < nentries; i++)
+ gtk_menu_factory_create (factory, &entries[i], factory->widget, entries[i].path);
+}
+
+void
+gtk_menu_factory_add_subfactory (GtkMenuFactory *factory,
+ GtkMenuFactory *subfactory,
+ const char *path)
+{
+ g_return_if_fail (factory != NULL);
+ g_return_if_fail (subfactory != NULL);
+ g_return_if_fail (path != NULL);
+
+ if (subfactory->path)
+ g_free (subfactory->path);
+ subfactory->path = g_strdup (path);
+
+ factory->subfactories = g_list_append (factory->subfactories, subfactory);
+}
+
+void
+gtk_menu_factory_remove_paths (GtkMenuFactory *factory,
+ char **paths,
+ int npaths)
+{
+ int i;
+
+ g_return_if_fail (factory != NULL);
+ g_return_if_fail (paths != NULL);
+ g_return_if_fail (npaths > 0);
+
+ if (factory->widget)
+ {
+ for (i = 0; i < npaths; i++)
+ gtk_menu_factory_remove (factory, factory->widget, paths[i]);
+ }
+}
+
+void
+gtk_menu_factory_remove_entries (GtkMenuFactory *factory,
+ GtkMenuEntry *entries,
+ int nentries)
+{
+ int i;
+
+ g_return_if_fail (factory != NULL);
+ g_return_if_fail (entries != NULL);
+ g_return_if_fail (nentries > 0);
+
+ if (factory->widget)
+ {
+ for (i = 0; i < nentries; i++)
+ gtk_menu_factory_remove (factory, factory->widget, entries[i].path);
+ }
+}
+
+void
+gtk_menu_factory_remove_subfactory (GtkMenuFactory *factory,
+ GtkMenuFactory *subfactory,
+ const char *path)
+{
+ g_return_if_fail (factory != NULL);
+ g_return_if_fail (subfactory != NULL);
+ g_return_if_fail (path != NULL);
+
+ g_warning ("FIXME: gtk_menu_factory_remove_subfactory");
+}
+
+GtkMenuPath*
+gtk_menu_factory_find (GtkMenuFactory *factory,
+ const char *path)
+{
+ g_return_val_if_fail (factory != NULL, NULL);
+ g_return_val_if_fail (path != NULL, NULL);
+
+ return gtk_menu_factory_find_recurse (factory, factory->widget, path);
+}
+
+
+static void
+gtk_menu_factory_create (GtkMenuFactory *factory,
+ GtkMenuEntry *entry,
+ GtkWidget *parent,
+ const char *path)
+{
+ GtkMenuFactory *subfactory;
+ GtkMenuPath *menu_path;
+ GtkWidget *menu;
+ GList *tmp_list;
+ char tmp_path[256];
+ char accelerator_key;
+ guint8 accelerator_mods;
+ char *p;
+
+ g_return_if_fail (factory != NULL);
+ g_return_if_fail (entry != NULL);
+
+ /* If 'path' is empty, then simply return.
+ */
+ if (!path || path[0] == '\0')
+ return;
+
+ /* Strip off the next part of the path.
+ */
+ p = strchr (path, '/');
+
+ /* If this is the last part of the path ('p' is
+ * NULL), then we create an item.
+ */
+ if (!p)
+ {
+ /* Check to see if this item is a separator.
+ */
+ if (strcmp (path, "<separator>") == 0)
+ {
+ entry->widget = gtk_menu_item_new ();
+ gtk_container_add (GTK_CONTAINER (parent), entry->widget);
+ gtk_widget_show (entry->widget);
+ }
+ else
+ {
+ if (strncmp (path, "<check>", 7) == 0)
+ menu_path = gtk_menu_factory_get (parent, path + 7, CREATE | CHECK);
+ else
+ menu_path = gtk_menu_factory_get (parent, path, CREATE);
+ entry->widget = menu_path->widget;
+
+ if (strcmp (path, "<nothing>") == 0)
+ gtk_widget_hide (entry->widget);
+
+ if (entry->accelerator)
+ {
+ gtk_menu_factory_parse_accelerator (entry->accelerator,
+ &accelerator_key,
+ &accelerator_mods);
+ if (!factory->table)
+ {
+ factory->table = gtk_accelerator_table_new ();
+ gtk_accelerator_table_ref (factory->table);
+ }
+
+ gtk_widget_install_accelerator (menu_path->widget,
+ factory->table,
+ "activate",
+ accelerator_key,
+ accelerator_mods);
+ }
+
+ if (entry->callback)
+ gtk_signal_connect (GTK_OBJECT (menu_path->widget), "activate",
+ (GtkSignalFunc) entry->callback,
+ entry->callback_data);
+ }
+ }
+ else
+ {
+ strncpy (tmp_path, path, (unsigned int) ((long) p - (long) path));
+ tmp_path[(long) p - (long) path] = '\0';
+
+ menu_path = gtk_menu_factory_get (parent, tmp_path, 0);
+ if (!menu_path)
+ {
+ tmp_list = factory->subfactories;
+ while (tmp_list)
+ {
+ subfactory = tmp_list->data;
+ tmp_list = tmp_list->next;
+
+ if (subfactory->path &&
+ (strcmp (subfactory->path, tmp_path) == 0))
+ {
+ if (!subfactory->widget)
+ subfactory->widget = gtk_menu_factory_make_widget (subfactory);
+ gtk_menu_factory_create (subfactory, entry, subfactory->widget, p + 1);
+ return;
+ }
+ }
+
+ menu_path = gtk_menu_factory_get (parent, tmp_path, CREATE);
+ }
+
+ entry->widget = menu_path->widget;
+ menu = GTK_MENU_ITEM (menu_path->widget)->submenu;
+
+ if (!menu)
+ {
+ menu = gtk_menu_new ();
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_path->widget), menu);
+
+ if (!factory->table)
+ {
+ factory->table = gtk_accelerator_table_new ();
+ gtk_accelerator_table_ref (factory->table);
+ }
+ gtk_menu_set_accelerator_table (GTK_MENU (menu), factory->table);
+ }
+
+ gtk_menu_factory_create (factory, entry, menu, p + 1);
+ }
+}
+
+static void
+gtk_menu_factory_remove (GtkMenuFactory *factory,
+ GtkWidget *parent,
+ const char *path)
+{
+ GtkMenuFactory *subfactory;
+ GtkMenuPath *menu_path;
+ GtkWidget *menu;
+ GList *tmp_list;
+ char tmp_path[256];
+ char *p;
+
+ if (!path || path[0] == '\0')
+ return;
+
+ p = strchr (path, '/');
+
+ if (!p)
+ {
+ if (parent)
+ gtk_menu_factory_get (parent, path, DESTROY);
+ }
+ else
+ {
+ strncpy (tmp_path, path, (unsigned int) ((long) p - (long) path));
+ tmp_path[(long) p - (long) path] = '\0';
+
+ menu_path = gtk_menu_factory_get (parent, tmp_path, 0);
+ if (!menu_path)
+ {
+ tmp_list = factory->subfactories;
+ while (tmp_list)
+ {
+ subfactory = tmp_list->data;
+ tmp_list = tmp_list->next;
+
+ if (subfactory->path &&
+ (strcmp (subfactory->path, tmp_path) == 0))
+ {
+ if (!subfactory->widget)
+ return;
+ gtk_menu_factory_remove (subfactory, subfactory->widget, p + 1);
+ }
+ }
+ }
+ else
+ {
+ menu = GTK_MENU_ITEM (menu_path->widget)->submenu;
+ if (menu)
+ gtk_menu_factory_remove (factory, menu, p + 1);
+ }
+ }
+}
+
+static GtkWidget*
+gtk_menu_factory_make_widget (GtkMenuFactory *factory)
+{
+ GtkWidget *widget;
+
+ g_return_val_if_fail (factory != NULL, NULL);
+
+ switch (factory->type)
+ {
+ case GTK_MENU_FACTORY_MENU:
+ widget = gtk_menu_new ();
+
+ if (!factory->table)
+ {
+ factory->table = gtk_accelerator_table_new ();
+ gtk_accelerator_table_ref (factory->table);
+ }
+ gtk_menu_set_accelerator_table (GTK_MENU (widget), factory->table);
+ return widget;
+ case GTK_MENU_FACTORY_MENU_BAR:
+ return gtk_menu_bar_new ();
+ case GTK_MENU_FACTORY_OPTION_MENU:
+ g_error ("not implemented");
+ break;
+ }
+
+ return NULL;
+}
+
+static GtkMenuPath*
+gtk_menu_factory_get (GtkWidget *parent,
+ const char *path,
+ int flags)
+{
+ GtkMenuPath *menu_path;
+ GList *tmp_list;
+
+ tmp_list = gtk_object_get_user_data (GTK_OBJECT (parent));
+ while (tmp_list)
+ {
+ menu_path = tmp_list->data;
+ tmp_list = tmp_list->next;
+
+ if (strcmp (menu_path->path, path) == 0)
+ {
+ if (flags & DESTROY)
+ {
+ tmp_list = gtk_object_get_user_data (GTK_OBJECT (parent));
+ tmp_list = g_list_remove (tmp_list, menu_path);
+ gtk_object_set_user_data (GTK_OBJECT (parent), tmp_list);
+
+ gtk_widget_destroy (menu_path->widget);
+ g_free (menu_path->path);
+ g_free (menu_path);
+
+ return NULL;
+ }
+ else
+ {
+ return menu_path;
+ }
+ }
+ }
+
+ if (flags & CREATE)
+ {
+ menu_path = g_new (GtkMenuPath, 1);
+ menu_path->path = g_strdup (path);
+
+ if (flags & CHECK)
+ menu_path->widget = gtk_check_menu_item_new_with_label (path);
+ else
+ menu_path->widget = gtk_menu_item_new_with_label (path);
+
+ gtk_container_add (GTK_CONTAINER (parent), menu_path->widget);
+ gtk_object_set_user_data (GTK_OBJECT (menu_path->widget), NULL);
+ gtk_widget_show (menu_path->widget);
+
+ tmp_list = gtk_object_get_user_data (GTK_OBJECT (parent));
+ tmp_list = g_list_prepend (tmp_list, menu_path);
+ gtk_object_set_user_data (GTK_OBJECT (parent), tmp_list);
+
+ return menu_path;
+ }
+
+ return NULL;
+}
+
+static GtkMenuPath*
+gtk_menu_factory_find_recurse (GtkMenuFactory *factory,
+ GtkWidget *parent,
+ const char *path)
+{
+ GtkMenuFactory *subfactory;
+ GtkMenuPath *menu_path;
+ GtkWidget *menu;
+ GList *tmp_list;
+ char tmp_path[256];
+ char *p;
+
+ if (!path || path[0] == '\0')
+ return NULL;
+
+ p = strchr (path, '/');
+
+ if (!p)
+ {
+ if (parent)
+ return gtk_menu_factory_get (parent, path, 0);
+ }
+ else
+ {
+ strncpy (tmp_path, path, (unsigned int) ((long) p - (long) path));
+ tmp_path[(long) p - (long) path] = '\0';
+
+ menu_path = gtk_menu_factory_get (parent, tmp_path, 0);
+ if (!menu_path)
+ {
+ tmp_list = factory->subfactories;
+ while (tmp_list)
+ {
+ subfactory = tmp_list->data;
+ tmp_list = tmp_list->next;
+
+ if (subfactory->path &&
+ (strcmp (subfactory->path, tmp_path) == 0))
+ {
+ if (!subfactory->widget)
+ return NULL;
+ return gtk_menu_factory_find_recurse (subfactory, subfactory->widget, p + 1);
+ }
+ }
+
+ return NULL;
+ }
+
+ menu = GTK_MENU_ITEM (menu_path->widget)->submenu;
+ if (menu)
+ return gtk_menu_factory_find_recurse (factory, menu, p + 1);
+ }
+
+ return NULL;
+}
+
+static void
+gtk_menu_factory_parse_accelerator (const char *accelerator,
+ char *accelerator_key,
+ guint8 *accelerator_mods)
+{
+ int done;
+
+ g_return_if_fail (accelerator != NULL);
+ g_return_if_fail (accelerator_key != NULL);
+ g_return_if_fail (accelerator_mods != NULL);
+
+ *accelerator_key = 0;
+ *accelerator_mods = 0;
+
+ done = FALSE;
+ while (!done)
+ {
+ if (strncmp (accelerator, "<shift>", 7) == 0)
+ {
+ accelerator += 7;
+ *accelerator_mods |= GDK_SHIFT_MASK;
+ }
+ else if (strncmp (accelerator, "<alt>", 5) == 0)
+ {
+ accelerator += 5;
+ *accelerator_mods |= GDK_MOD1_MASK;
+ }
+ else if (strncmp (accelerator, "<control>", 9) == 0)
+ {
+ accelerator += 9;
+ *accelerator_mods |= GDK_CONTROL_MASK;
+ }
+ else
+ {
+ done = TRUE;
+ *accelerator_key = accelerator[0];
+ }
+ }
+}
diff --git a/gtk/gtkmenufactory.h b/gtk/gtkmenufactory.h
new file mode 100644
index 000000000..d95fdb775
--- /dev/null
+++ b/gtk/gtkmenufactory.h
@@ -0,0 +1,88 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_MENU_FACTORY_H__
+#define __GTK_MENU_FACTORY_H__
+
+
+#include <gtk/gtkwidget.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+typedef struct _GtkMenuEntry GtkMenuEntry;
+typedef struct _GtkMenuPath GtkMenuPath;
+typedef struct _GtkMenuFactory GtkMenuFactory;
+
+typedef void (*GtkMenuCallback) (GtkWidget *widget,
+ gpointer user_data);
+
+struct _GtkMenuEntry
+{
+ char *path;
+ char *accelerator;
+ GtkMenuCallback callback;
+ gpointer callback_data;
+ GtkWidget *widget;
+};
+
+struct _GtkMenuPath
+{
+ char *path;
+ GtkWidget *widget;
+};
+
+struct _GtkMenuFactory
+{
+ char *path;
+ GtkMenuFactoryType type;
+ GtkAcceleratorTable *table;
+ GtkWidget *widget;
+ GList *subfactories;
+};
+
+
+GtkMenuFactory* gtk_menu_factory_new (GtkMenuFactoryType type);
+void gtk_menu_factory_destroy (GtkMenuFactory *factory);
+void gtk_menu_factory_add_entries (GtkMenuFactory *factory,
+ GtkMenuEntry *entries,
+ int nentries);
+void gtk_menu_factory_add_subfactory (GtkMenuFactory *factory,
+ GtkMenuFactory *subfactory,
+ const char *path);
+void gtk_menu_factory_remove_paths (GtkMenuFactory *factory,
+ char **paths,
+ int npaths);
+void gtk_menu_factory_remove_entries (GtkMenuFactory *factory,
+ GtkMenuEntry *entries,
+ int nentries);
+void gtk_menu_factory_remove_subfactory (GtkMenuFactory *factory,
+ GtkMenuFactory *subfactory,
+ const char *path);
+GtkMenuPath* gtk_menu_factory_find (GtkMenuFactory *factory,
+ const char *path);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_MENU_FACTORY_H__ */
diff --git a/gtk/gtkmenuitem.c b/gtk/gtkmenuitem.c
new file mode 100644
index 000000000..f7715fb25
--- /dev/null
+++ b/gtk/gtkmenuitem.c
@@ -0,0 +1,746 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <string.h>
+#include "gtklabel.h"
+#include "gtkmain.h"
+#include "gtkmenu.h"
+#include "gtkmenuitem.h"
+#include "gtksignal.h"
+
+
+#define BORDER_SPACING 3
+#define SELECT_TIMEOUT 20
+
+#define MENU_ITEM_CLASS(w) GTK_MENU_ITEM_CLASS (GTK_OBJECT (w)->klass)
+
+
+enum {
+ ACTIVATE,
+ LAST_SIGNAL
+};
+
+
+static void gtk_menu_item_class_init (GtkMenuItemClass *klass);
+static void gtk_menu_item_init (GtkMenuItem *menu_item);
+static void gtk_menu_item_destroy (GtkObject *object);
+static void gtk_menu_item_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void gtk_menu_item_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static gint gtk_menu_item_install_accel (GtkWidget *widget,
+ const gchar *signal_name,
+ gchar key,
+ guint8 modifiers);
+static void gtk_menu_item_remove_accel (GtkWidget *widget,
+ const gchar *signal_name);
+static void gtk_menu_item_paint (GtkWidget *widget,
+ GdkRectangle *area);
+static void gtk_menu_item_draw (GtkWidget *widget,
+ GdkRectangle *area);
+static gint gtk_menu_item_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+static gint gtk_menu_item_enter (GtkWidget *widget,
+ GdkEventCrossing *event);
+static gint gtk_menu_item_leave (GtkWidget *widget,
+ GdkEventCrossing *event);
+static void gtk_real_menu_item_select (GtkItem *item);
+static void gtk_real_menu_item_deselect (GtkItem *item);
+static gint gtk_menu_item_select_timeout (gpointer data);
+static void gtk_menu_item_position_menu (GtkMenu *menu,
+ gint *x,
+ gint *y,
+ gpointer user_data);
+
+static GtkItemClass *parent_class;
+static gint menu_item_signals[LAST_SIGNAL] = { 0 };
+
+
+guint
+gtk_menu_item_get_type ()
+{
+ static guint menu_item_type = 0;
+
+ if (!menu_item_type)
+ {
+ GtkTypeInfo menu_item_info =
+ {
+ "GtkMenuItem",
+ sizeof (GtkMenuItem),
+ sizeof (GtkMenuItemClass),
+ (GtkClassInitFunc) gtk_menu_item_class_init,
+ (GtkObjectInitFunc) gtk_menu_item_init,
+ (GtkArgFunc) NULL,
+ };
+
+ menu_item_type = gtk_type_unique (gtk_item_get_type (), &menu_item_info);
+ }
+
+ return menu_item_type;
+}
+
+static void
+gtk_menu_item_class_init (GtkMenuItemClass *klass)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+ GtkItemClass *item_class;
+
+ object_class = (GtkObjectClass*) klass;
+ widget_class = (GtkWidgetClass*) klass;
+ item_class = (GtkItemClass*) klass;
+
+ parent_class = gtk_type_class (gtk_item_get_type ());
+
+ menu_item_signals[ACTIVATE] =
+ gtk_signal_new ("activate",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkMenuItemClass, activate),
+ gtk_signal_default_marshaller,
+ GTK_TYPE_NONE, 0);
+
+ gtk_object_class_add_signals (object_class, menu_item_signals, LAST_SIGNAL);
+
+ object_class->destroy = gtk_menu_item_destroy;
+
+ widget_class->activate_signal = menu_item_signals[ACTIVATE];
+ widget_class->size_request = gtk_menu_item_size_request;
+ widget_class->size_allocate = gtk_menu_item_size_allocate;
+ widget_class->install_accelerator = gtk_menu_item_install_accel;
+ widget_class->remove_accelerator = gtk_menu_item_remove_accel;
+ widget_class->draw = gtk_menu_item_draw;
+ widget_class->expose_event = gtk_menu_item_expose;
+ widget_class->enter_notify_event = gtk_menu_item_enter;
+ widget_class->leave_notify_event = gtk_menu_item_leave;
+
+ item_class->select = gtk_real_menu_item_select;
+ item_class->deselect = gtk_real_menu_item_deselect;
+
+ klass->activate = NULL;
+
+ klass->toggle_size = 0;
+ klass->shift_text = "Shft";
+ klass->control_text = "Ctl";
+ klass->alt_text = "Alt";
+ klass->separator_text = "+";
+}
+
+static void
+gtk_menu_item_init (GtkMenuItem *menu_item)
+{
+ menu_item->submenu = NULL;
+ menu_item->accelerator_key = 0;
+ menu_item->accelerator_mods = 0;
+ menu_item->accelerator_size = 0;
+ menu_item->accelerator_signal = 0;
+ menu_item->toggle_size = 0;
+ menu_item->show_toggle_indicator = FALSE;
+ menu_item->show_submenu_indicator = FALSE;
+ menu_item->submenu_direction = GTK_DIRECTION_RIGHT;
+ menu_item->submenu_placement = GTK_TOP_BOTTOM;
+ menu_item->right_justify = FALSE;
+
+ menu_item->timer = 0;
+}
+
+GtkWidget*
+gtk_menu_item_new ()
+{
+ return GTK_WIDGET (gtk_type_new (gtk_menu_item_get_type ()));
+}
+
+GtkWidget*
+gtk_menu_item_new_with_label (const gchar *label)
+{
+ GtkWidget *menu_item;
+ GtkWidget *label_widget;
+
+ menu_item = gtk_menu_item_new ();
+ label_widget = gtk_label_new (label);
+ gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
+
+ gtk_container_add (GTK_CONTAINER (menu_item), label_widget);
+ gtk_widget_show (label_widget);
+
+ return menu_item;
+}
+
+static void
+gtk_menu_item_destroy (GtkObject *object)
+{
+ GtkMenuItem *menu_item;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_MENU_ITEM (object));
+
+ menu_item = GTK_MENU_ITEM (object);
+
+ if (menu_item->submenu)
+ {
+ gtk_object_unref (GTK_OBJECT (menu_item->submenu));
+ /* gtk_widget_destroy (menu_item->submenu); */
+ }
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+void
+gtk_menu_item_set_submenu (GtkMenuItem *menu_item,
+ GtkWidget *submenu)
+{
+ g_return_if_fail (menu_item != NULL);
+ g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
+
+ if (menu_item->submenu)
+ {
+ g_return_if_fail (!GTK_WIDGET_VISIBLE (menu_item->submenu));
+ gtk_object_unref (GTK_OBJECT (menu_item->submenu));
+ }
+
+ menu_item->submenu = submenu;
+
+ if (menu_item->submenu)
+ gtk_object_ref (GTK_OBJECT (menu_item->submenu));
+
+ if (GTK_WIDGET (menu_item)->parent)
+ gtk_widget_queue_resize (GTK_WIDGET (menu_item));
+}
+
+void
+gtk_menu_item_set_placement (GtkMenuItem *menu_item,
+ GtkSubmenuPlacement placement)
+{
+ g_return_if_fail (menu_item != NULL);
+ g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
+
+ menu_item->submenu_placement = placement;
+}
+
+void
+gtk_menu_item_accelerator_size (GtkMenuItem *menu_item)
+{
+ char buf[32];
+
+ g_return_if_fail (menu_item != NULL);
+ g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
+
+ if (menu_item->accelerator_key)
+ {
+ gtk_menu_item_accelerator_text (menu_item, buf);
+ menu_item->accelerator_size = gdk_string_width (GTK_WIDGET (menu_item)->style->font, buf) + 13;
+ }
+ else if (menu_item->submenu && menu_item->show_submenu_indicator)
+ {
+ menu_item->accelerator_size = 21;
+ }
+ else
+ {
+ menu_item->accelerator_size = 0;
+ }
+}
+
+void
+gtk_menu_item_accelerator_text (GtkMenuItem *menu_item,
+ gchar *buffer)
+{
+ g_return_if_fail (menu_item != NULL);
+ g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
+
+ if (menu_item->accelerator_key)
+ {
+ buffer[0] = '\0';
+ if (menu_item->accelerator_mods & GDK_SHIFT_MASK)
+ {
+ strcat (buffer, MENU_ITEM_CLASS (menu_item)->shift_text);
+ strcat (buffer, MENU_ITEM_CLASS (menu_item)->separator_text);
+ }
+ if (menu_item->accelerator_mods & GDK_CONTROL_MASK)
+ {
+ strcat (buffer, MENU_ITEM_CLASS (menu_item)->control_text);
+ strcat (buffer, MENU_ITEM_CLASS (menu_item)->separator_text);
+ }
+ if (menu_item->accelerator_mods & GDK_MOD1_MASK)
+ {
+ strcat (buffer, MENU_ITEM_CLASS (menu_item)->alt_text);
+ strcat (buffer, MENU_ITEM_CLASS (menu_item)->separator_text);
+ }
+ strncat (buffer, &menu_item->accelerator_key, 1);
+ }
+}
+
+void
+gtk_menu_item_configure (GtkMenuItem *menu_item,
+ gint show_toggle_indicator,
+ gint show_submenu_indicator)
+{
+ g_return_if_fail (menu_item != NULL);
+ g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
+
+ menu_item->show_toggle_indicator = (show_toggle_indicator == TRUE);
+ menu_item->show_submenu_indicator = (show_submenu_indicator == TRUE);
+}
+
+void
+gtk_menu_item_select (GtkMenuItem *menu_item)
+{
+ gtk_item_select (GTK_ITEM (menu_item));
+}
+
+void
+gtk_menu_item_deselect (GtkMenuItem *menu_item)
+{
+ gtk_item_deselect (GTK_ITEM (menu_item));
+}
+
+void
+gtk_menu_item_activate (GtkMenuItem *menu_item)
+{
+ gtk_signal_emit (GTK_OBJECT (menu_item), menu_item_signals[ACTIVATE]);
+}
+
+
+static void
+gtk_menu_item_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkBin *bin;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_MENU_ITEM (widget));
+ g_return_if_fail (requisition != NULL);
+
+ bin = GTK_BIN (widget);
+
+ gtk_menu_item_accelerator_size (GTK_MENU_ITEM (widget));
+
+ requisition->width = (GTK_CONTAINER (widget)->border_width +
+ widget->style->klass->xthickness +
+ BORDER_SPACING) * 2;
+ requisition->height = (GTK_CONTAINER (widget)->border_width +
+ widget->style->klass->ythickness) * 2;
+
+ if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
+ {
+ gtk_widget_size_request (bin->child, &bin->child->requisition);
+
+ requisition->width += bin->child->requisition.width;
+ requisition->height += bin->child->requisition.height;
+ }
+}
+
+static void
+gtk_menu_item_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkBin *bin;
+ GtkAllocation child_allocation;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_MENU_ITEM (widget));
+ g_return_if_fail (allocation != NULL);
+
+ widget->allocation = *allocation;
+ if (GTK_WIDGET_REALIZED (widget))
+ gdk_window_move_resize (widget->window,
+ allocation->x, allocation->y,
+ allocation->width, allocation->height);
+
+ bin = GTK_BIN (widget);
+
+ if (bin->child)
+ {
+ child_allocation.x = (GTK_CONTAINER (widget)->border_width +
+ widget->style->klass->xthickness +
+ BORDER_SPACING);
+ child_allocation.y = GTK_CONTAINER (widget)->border_width;
+ child_allocation.width = allocation->width - child_allocation.x * 2;
+ child_allocation.height = allocation->height - child_allocation.y * 2;
+ child_allocation.x += GTK_MENU_ITEM (widget)->toggle_size;
+ child_allocation.width -= (GTK_MENU_ITEM (widget)->toggle_size +
+ GTK_MENU_ITEM (widget)->accelerator_size);
+
+ gtk_widget_size_allocate (bin->child, &child_allocation);
+ }
+}
+
+static gint
+gtk_menu_item_install_accel (GtkWidget *widget,
+ const gchar *signal_name,
+ gchar key,
+ guint8 modifiers)
+{
+ GtkMenuItem *menu_item;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_MENU_ITEM (widget), FALSE);
+ g_return_val_if_fail (signal_name != NULL, FALSE);
+
+ menu_item = GTK_MENU_ITEM (widget);
+
+ menu_item->accelerator_signal = gtk_signal_lookup (signal_name, GTK_OBJECT_TYPE (widget));
+ if (menu_item->accelerator_signal > 0)
+ {
+ menu_item->accelerator_key = key;
+ menu_item->accelerator_mods = modifiers;
+
+ if (widget->parent)
+ gtk_widget_queue_resize (widget);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+gtk_menu_item_remove_accel (GtkWidget *widget,
+ const gchar *signal_name)
+{
+ GtkMenuItem *menu_item;
+ gint signal_num;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_MENU_ITEM (widget));
+ g_return_if_fail (signal_name != NULL);
+
+ menu_item = GTK_MENU_ITEM (widget);
+
+ signal_num = gtk_signal_lookup (signal_name, GTK_OBJECT_TYPE (widget));
+ if (menu_item->accelerator_signal == signal_num)
+ {
+ menu_item->accelerator_key = 0;
+ menu_item->accelerator_mods = 0;
+ menu_item->accelerator_signal = 0;
+
+ if (GTK_WIDGET_VISIBLE (widget))
+ {
+ gtk_widget_queue_draw (widget);
+ GTK_MENU_SHELL (widget->parent)->menu_flag = TRUE;
+ }
+ else
+ gtk_container_need_resize (GTK_CONTAINER (widget->parent));
+ }
+}
+
+static void
+gtk_menu_item_paint (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ GtkMenuItem *menu_item;
+ GtkStateType state_type;
+ GtkShadowType shadow_type;
+ GdkFont *font;
+ gint width, height;
+ gint x, y;
+ char buf[32];
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_MENU_ITEM (widget));
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ menu_item = GTK_MENU_ITEM (widget);
+
+ state_type = widget->state;
+ if (!GTK_WIDGET_IS_SENSITIVE (widget))
+ state_type = GTK_STATE_INSENSITIVE;
+
+ gtk_style_set_background (widget->style, widget->window, state_type);
+ gdk_window_clear_area (widget->window, area->x, area->y, area->width, area->height);
+
+ x = GTK_CONTAINER (menu_item)->border_width;
+ y = GTK_CONTAINER (menu_item)->border_width;
+ width = widget->allocation.width - x * 2;
+ height = widget->allocation.height - y * 2;
+
+ if ((state_type == GTK_STATE_PRELIGHT) &&
+ (GTK_BIN (menu_item)->child))
+ gtk_draw_shadow (widget->style,
+ widget->window,
+ GTK_STATE_PRELIGHT,
+ GTK_SHADOW_OUT,
+ x, y, width, height);
+
+ if (menu_item->accelerator_key)
+ {
+ gtk_menu_item_accelerator_text (menu_item, buf);
+
+ font = widget->style->font;
+ x = x + width - menu_item->accelerator_size + 13 - 4;
+ y = y + ((height - (font->ascent + font->descent)) / 2) + font->ascent;
+
+ if (state_type == GTK_STATE_INSENSITIVE)
+ gdk_draw_string (widget->window, widget->style->font,
+ widget->style->white_gc,
+ x + 1, y + 1, buf);
+
+ gdk_draw_string (widget->window, widget->style->font,
+ widget->style->fg_gc[state_type],
+ x, y, buf);
+ }
+ else if (menu_item->submenu && menu_item->show_submenu_indicator)
+ {
+ shadow_type = GTK_SHADOW_OUT;
+ if (state_type == GTK_STATE_PRELIGHT)
+ shadow_type = GTK_SHADOW_IN;
+
+ gtk_draw_arrow (widget->style, widget->window,
+ state_type, shadow_type, GTK_ARROW_RIGHT, FALSE,
+ x + width - 15, y + height / 2 - 5, 10, 10);
+ }
+ else if (!GTK_BIN (menu_item)->child)
+ {
+ gtk_draw_hline (widget->style, widget->window, GTK_STATE_NORMAL,
+ 0, widget->allocation.width, 0);
+ }
+ }
+}
+
+static void
+gtk_menu_item_draw (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ GtkBin *bin;
+ GdkRectangle child_area;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_MENU_ITEM (widget));
+ g_return_if_fail (area != NULL);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ gtk_menu_item_paint (widget, area);
+
+ bin = GTK_BIN (widget);
+
+ if (bin->child)
+ {
+ if (gtk_widget_intersect (bin->child, area, &child_area))
+ gtk_widget_draw (bin->child, &child_area);
+ }
+ }
+}
+
+static gint
+gtk_menu_item_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ GtkBin *bin;
+ GdkEventExpose child_event;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_MENU_ITEM (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ gtk_menu_item_paint (widget, &event->area);
+
+ bin = GTK_BIN (widget);
+
+ if (bin->child)
+ {
+ child_event = *event;
+
+ if (GTK_WIDGET_NO_WINDOW (bin->child) &&
+ gtk_widget_intersect (bin->child, &event->area, &child_event.area))
+ gtk_widget_event (bin->child, (GdkEvent*) &child_event);
+ }
+ }
+
+ return FALSE;
+}
+
+static gint
+gtk_menu_item_enter (GtkWidget *widget,
+ GdkEventCrossing *event)
+{
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_MENU_ITEM (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ return gtk_widget_event (widget->parent, (GdkEvent*) event);
+}
+
+static gint
+gtk_menu_item_leave (GtkWidget *widget,
+ GdkEventCrossing *event)
+{
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_MENU_ITEM (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ return gtk_widget_event (widget->parent, (GdkEvent*) event);
+}
+
+static void
+gtk_real_menu_item_select (GtkItem *item)
+{
+ GtkMenuItem *menu_item;
+
+ g_return_if_fail (item != NULL);
+ g_return_if_fail (GTK_IS_MENU_ITEM (item));
+
+ menu_item = GTK_MENU_ITEM (item);
+
+ if (menu_item->submenu && !GTK_WIDGET_VISIBLE (menu_item->submenu))
+ menu_item->timer = gtk_timeout_add (SELECT_TIMEOUT, gtk_menu_item_select_timeout, menu_item);
+
+ gtk_widget_set_state (GTK_WIDGET (menu_item), GTK_STATE_PRELIGHT);
+ gtk_widget_draw (GTK_WIDGET (menu_item), NULL);
+}
+
+static void
+gtk_real_menu_item_deselect (GtkItem *item)
+{
+ GtkMenuItem *menu_item;
+
+ g_return_if_fail (item != NULL);
+ g_return_if_fail (GTK_IS_MENU_ITEM (item));
+
+ menu_item = GTK_MENU_ITEM (item);
+
+ if (menu_item->submenu)
+ {
+ if (menu_item->timer)
+ gtk_timeout_remove (menu_item->timer);
+ else
+ gtk_menu_popdown (GTK_MENU (menu_item->submenu));
+ }
+
+ gtk_widget_set_state (GTK_WIDGET (menu_item), GTK_STATE_NORMAL);
+ gtk_widget_draw (GTK_WIDGET (menu_item), NULL);
+}
+
+static gint
+gtk_menu_item_select_timeout (gpointer data)
+{
+ GtkMenuItem *menu_item;
+
+ menu_item = GTK_MENU_ITEM (data);
+ menu_item->timer = 0;
+
+ gtk_menu_popup (GTK_MENU (menu_item->submenu),
+ GTK_WIDGET (menu_item)->parent,
+ GTK_WIDGET (menu_item),
+ gtk_menu_item_position_menu,
+ menu_item,
+ GTK_MENU_SHELL (GTK_WIDGET (menu_item)->parent)->button,
+ 0);
+
+ return FALSE;
+}
+
+static void
+gtk_menu_item_position_menu (GtkMenu *menu,
+ gint *x,
+ gint *y,
+ gpointer user_data)
+{
+ GtkMenuItem *menu_item;
+ GtkMenuItem *parent_menu_item;
+ gint screen_width;
+ gint screen_height;
+ gint twidth, theight;
+ gint tx, ty;
+
+ g_return_if_fail (menu != NULL);
+ g_return_if_fail (x != NULL);
+ g_return_if_fail (y != NULL);
+
+ menu_item = GTK_MENU_ITEM (user_data);
+
+ twidth = GTK_WIDGET (menu)->requisition.width;
+ theight = GTK_WIDGET (menu)->requisition.height;
+
+ screen_width = gdk_screen_width ();
+ screen_height = gdk_screen_height ();
+
+ g_return_if_fail (gdk_window_get_origin (GTK_WIDGET (menu_item)->window, &tx, &ty));
+
+ switch (menu_item->submenu_placement)
+ {
+ case GTK_TOP_BOTTOM:
+ if ((ty + GTK_WIDGET (menu_item)->allocation.height + theight) <= screen_height)
+ ty += GTK_WIDGET (menu_item)->allocation.height;
+ else if ((ty - theight) >= 0)
+ ty -= theight;
+ else
+ ty += GTK_WIDGET (menu_item)->allocation.height;
+
+ if ((tx + twidth) > screen_width)
+ {
+ tx -= ((tx + twidth) - screen_width);
+ if (tx < 0)
+ tx = 0;
+ }
+ break;
+
+ case GTK_LEFT_RIGHT:
+ menu_item->submenu_direction = GTK_DIRECTION_RIGHT;
+ parent_menu_item = GTK_MENU_ITEM (GTK_MENU (GTK_WIDGET (menu_item)->parent)->parent_menu_item);
+ if (parent_menu_item)
+ menu_item->submenu_direction = parent_menu_item->submenu_direction;
+
+ switch (menu_item->submenu_direction)
+ {
+ case GTK_DIRECTION_LEFT:
+ if ((tx - twidth) >= 0)
+ tx -= twidth;
+ else
+ {
+ menu_item->submenu_direction = GTK_DIRECTION_RIGHT;
+ tx += GTK_WIDGET (menu_item)->allocation.width - 5;
+ }
+ break;
+
+ case GTK_DIRECTION_RIGHT:
+ if ((tx + GTK_WIDGET (menu_item)->allocation.width + twidth - 5) <= screen_width)
+ tx += GTK_WIDGET (menu_item)->allocation.width - 5;
+ else
+ {
+ menu_item->submenu_direction = GTK_DIRECTION_LEFT;
+ tx -= twidth;
+ }
+ break;
+ }
+
+ if ((ty + GTK_WIDGET (menu_item)->allocation.height / 4 + theight) <= screen_height)
+ ty += GTK_WIDGET (menu_item)->allocation.height / 4;
+ else
+ {
+ ty -= ((ty + theight) - screen_height);
+ if (ty < 0)
+ ty = 0;
+ }
+ break;
+ }
+
+ *x = tx;
+ *y = ty;
+}
+
+void
+gtk_menu_item_right_justify(GtkMenuItem *menuitem)
+{
+ g_return_if_fail (menuitem != NULL);
+ g_return_if_fail (GTK_IS_MENU_ITEM (menuitem));
+
+ menuitem->right_justify = 1;
+}
diff --git a/gtk/gtkmenuitem.h b/gtk/gtkmenuitem.h
new file mode 100644
index 000000000..da5168109
--- /dev/null
+++ b/gtk/gtkmenuitem.h
@@ -0,0 +1,98 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_MENU_ITEM_H__
+#define __GTK_MENU_ITEM_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkitem.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_MENU_ITEM(obj) GTK_CHECK_CAST (obj, gtk_menu_item_get_type (), GtkMenuItem)
+#define GTK_MENU_ITEM_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_menu_item_get_type (), GtkMenuItemClass)
+#define GTK_IS_MENU_ITEM(obj) GTK_CHECK_TYPE (obj, gtk_menu_item_get_type ())
+
+
+typedef struct _GtkMenuItem GtkMenuItem;
+typedef struct _GtkMenuItemClass GtkMenuItemClass;
+
+struct _GtkMenuItem
+{
+ GtkItem item;
+
+ GtkWidget *submenu;
+
+ gint accelerator_signal;
+ gchar accelerator_key;
+ guint8 accelerator_mods;
+ guint16 accelerator_size;
+ guint16 toggle_size;
+
+ guint show_toggle_indicator : 1;
+ guint show_submenu_indicator : 1;
+ guint submenu_placement : 1;
+ guint submenu_direction : 1;
+ guint right_justify: 1;
+ gint timer;
+};
+
+struct _GtkMenuItemClass
+{
+ GtkItemClass parent_class;
+
+ gint toggle_size;
+
+ gchar *shift_text;
+ gchar *control_text;
+ gchar *alt_text;
+ gchar *separator_text;
+
+ void (* activate) (GtkMenuItem *menu_item);
+};
+
+
+guint gtk_menu_item_get_type (void);
+GtkWidget* gtk_menu_item_new (void);
+GtkWidget* gtk_menu_item_new_with_label (const gchar *label);
+void gtk_menu_item_set_submenu (GtkMenuItem *menu_item,
+ GtkWidget *submenu);
+void gtk_menu_item_set_placement (GtkMenuItem *menu_item,
+ GtkSubmenuPlacement placement);
+void gtk_menu_item_accelerator_size (GtkMenuItem *menu_item);
+void gtk_menu_item_accelerator_text (GtkMenuItem *menu_item,
+ gchar *buffer);
+void gtk_menu_item_configure (GtkMenuItem *menu_item,
+ gint show_toggle_indicator,
+ gint show_submenu_indicator);
+void gtk_menu_item_select (GtkMenuItem *menu_item);
+void gtk_menu_item_deselect (GtkMenuItem *menu_item);
+void gtk_menu_item_activate (GtkMenuItem *menu_item);
+void gtk_menu_item_right_justify (GtkMenuItem *menu_item);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_MENU_ITEM_H__ */
diff --git a/gtk/gtkmenushell.c b/gtk/gtkmenushell.c
new file mode 100644
index 000000000..6d3de5a7f
--- /dev/null
+++ b/gtk/gtkmenushell.c
@@ -0,0 +1,633 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtkmain.h"
+#include "gtkmenuitem.h"
+#include "gtkmenushell.h"
+#include "gtksignal.h"
+
+
+#define MENU_SHELL_TIMEOUT 500
+#define MENU_SHELL_CLASS(w) GTK_MENU_SHELL_CLASS (GTK_OBJECT (w)->klass)
+
+
+enum {
+ DEACTIVATE,
+ LAST_SIGNAL
+};
+
+
+static void gtk_menu_shell_class_init (GtkMenuShellClass *klass);
+static void gtk_menu_shell_init (GtkMenuShell *menu_shell);
+static void gtk_menu_shell_destroy (GtkObject *object);
+static void gtk_menu_shell_map (GtkWidget *widget);
+static void gtk_menu_shell_realize (GtkWidget *widget);
+static gint gtk_menu_shell_button_press (GtkWidget *widget,
+ GdkEventButton *event);
+static gint gtk_menu_shell_button_release (GtkWidget *widget,
+ GdkEventButton *event);
+static gint gtk_menu_shell_enter_notify (GtkWidget *widget,
+ GdkEventCrossing *event);
+static gint gtk_menu_shell_leave_notify (GtkWidget *widget,
+ GdkEventCrossing *event);
+static void gtk_menu_shell_add (GtkContainer *container,
+ GtkWidget *widget);
+static void gtk_menu_shell_remove (GtkContainer *container,
+ GtkWidget *widget);
+static void gtk_menu_shell_foreach (GtkContainer *container,
+ GtkCallback callback,
+ gpointer callback_data);
+static void gtk_real_menu_shell_deactivate (GtkMenuShell *menu_shell);
+static gint gtk_menu_shell_is_item (GtkMenuShell *menu_shell,
+ GtkWidget *child);
+
+
+static GtkContainerClass *parent_class = NULL;
+static gint menu_shell_signals[LAST_SIGNAL] = { 0 };
+
+
+guint
+gtk_menu_shell_get_type ()
+{
+ static guint menu_shell_type = 0;
+
+ if (!menu_shell_type)
+ {
+ GtkTypeInfo menu_shell_info =
+ {
+ "GtkMenuShell",
+ sizeof (GtkMenuShell),
+ sizeof (GtkMenuShellClass),
+ (GtkClassInitFunc) gtk_menu_shell_class_init,
+ (GtkObjectInitFunc) gtk_menu_shell_init,
+ (GtkArgFunc) NULL,
+ };
+
+ menu_shell_type = gtk_type_unique (gtk_container_get_type (), &menu_shell_info);
+ }
+
+ return menu_shell_type;
+}
+
+static void
+gtk_menu_shell_class_init (GtkMenuShellClass *klass)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+ GtkContainerClass *container_class;
+
+ object_class = (GtkObjectClass*) klass;
+ widget_class = (GtkWidgetClass*) klass;
+ container_class = (GtkContainerClass*) klass;
+
+ parent_class = gtk_type_class (gtk_container_get_type ());
+
+ menu_shell_signals[DEACTIVATE] =
+ gtk_signal_new ("deactivate",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkMenuShellClass, deactivate),
+ gtk_signal_default_marshaller,
+ GTK_TYPE_NONE, 0);
+
+ gtk_object_class_add_signals (object_class, menu_shell_signals, LAST_SIGNAL);
+
+ object_class->destroy = gtk_menu_shell_destroy;
+
+ widget_class->map = gtk_menu_shell_map;
+ widget_class->realize = gtk_menu_shell_realize;
+ widget_class->button_press_event = gtk_menu_shell_button_press;
+ widget_class->button_release_event = gtk_menu_shell_button_release;
+ widget_class->enter_notify_event = gtk_menu_shell_enter_notify;
+ widget_class->leave_notify_event = gtk_menu_shell_leave_notify;
+
+ container_class->add = gtk_menu_shell_add;
+ container_class->remove = gtk_menu_shell_remove;
+ container_class->foreach = gtk_menu_shell_foreach;
+
+ klass->submenu_placement = GTK_TOP_BOTTOM;
+ klass->deactivate = gtk_real_menu_shell_deactivate;
+}
+
+static void
+gtk_menu_shell_init (GtkMenuShell *menu_shell)
+{
+ menu_shell->children = NULL;
+ menu_shell->active_menu_item = NULL;
+ menu_shell->parent_menu_shell = NULL;
+ menu_shell->active = FALSE;
+ menu_shell->have_grab = FALSE;
+ menu_shell->have_xgrab = FALSE;
+ menu_shell->ignore_leave = FALSE;
+ menu_shell->button = 0;
+ menu_shell->menu_flag = 0;
+ menu_shell->activate_time = 0;
+}
+
+void
+gtk_menu_shell_append (GtkMenuShell *menu_shell,
+ GtkWidget *child)
+{
+ gtk_menu_shell_insert (menu_shell, child, -1);
+}
+
+void
+gtk_menu_shell_prepend (GtkMenuShell *menu_shell,
+ GtkWidget *child)
+{
+ gtk_menu_shell_insert (menu_shell, child, 0);
+}
+
+void
+gtk_menu_shell_insert (GtkMenuShell *menu_shell,
+ GtkWidget *child,
+ gint position)
+{
+ GList *tmp_list;
+ GList *new_list;
+ gint nchildren;
+
+ g_return_if_fail (menu_shell != NULL);
+ g_return_if_fail (GTK_IS_MENU_SHELL (menu_shell));
+ g_return_if_fail (child != NULL);
+ g_return_if_fail (GTK_IS_MENU_ITEM (child));
+
+ gtk_widget_set_parent (child, GTK_WIDGET (menu_shell));
+
+ if (GTK_WIDGET_VISIBLE (child->parent))
+ {
+ if (GTK_WIDGET_REALIZED (child->parent) &&
+ !GTK_WIDGET_REALIZED (child))
+ gtk_widget_realize (child);
+
+ if (GTK_WIDGET_MAPPED (child->parent) &&
+ !GTK_WIDGET_MAPPED (child))
+ gtk_widget_map (child);
+ }
+
+ nchildren = g_list_length (menu_shell->children);
+ if ((position < 0) || (position > nchildren))
+ position = nchildren;
+
+ if (position == nchildren)
+ {
+ menu_shell->children = g_list_append (menu_shell->children, child);
+ }
+ else
+ {
+ tmp_list = g_list_nth (menu_shell->children, position);
+ new_list = g_list_alloc ();
+ new_list->data = child;
+
+ if (tmp_list->prev)
+ tmp_list->prev->next = new_list;
+ new_list->next = tmp_list;
+ new_list->prev = tmp_list->prev;
+ tmp_list->prev = new_list;
+
+ if (tmp_list == menu_shell->children)
+ menu_shell->children = new_list;
+ }
+
+ if (GTK_WIDGET_VISIBLE (menu_shell))
+ gtk_widget_queue_resize (GTK_WIDGET (menu_shell));
+}
+
+void
+gtk_menu_shell_deactivate (GtkMenuShell *menu_shell)
+{
+ g_return_if_fail (menu_shell != NULL);
+ g_return_if_fail (GTK_IS_MENU_SHELL (menu_shell));
+
+ gtk_signal_emit (GTK_OBJECT (menu_shell), menu_shell_signals[DEACTIVATE]);
+}
+
+static void
+gtk_menu_shell_destroy (GtkObject *object)
+{
+ GtkMenuShell *menu_shell;
+ GtkWidget *child;
+ GList *children;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_MENU_SHELL (object));
+
+ menu_shell = GTK_MENU_SHELL (object);
+
+ children = menu_shell->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ child->parent = NULL;
+ gtk_object_unref (GTK_OBJECT (child));
+ gtk_widget_destroy (child);
+ }
+
+ g_list_free (menu_shell->children);
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+static void
+gtk_menu_shell_map (GtkWidget *widget)
+{
+ GtkMenuShell *menu_shell;
+ GtkWidget *child;
+ GList *children;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_MENU_SHELL (widget));
+
+ menu_shell = GTK_MENU_SHELL (widget);
+ GTK_WIDGET_SET_FLAGS (menu_shell, GTK_MAPPED);
+ gdk_window_show (widget->window);
+
+ children = menu_shell->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_VISIBLE (child) && !GTK_WIDGET_MAPPED (child))
+ gtk_widget_map (child);
+ }
+}
+
+static void
+gtk_menu_shell_realize (GtkWidget *widget)
+{
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_MENU_SHELL (widget));
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+
+ attributes.x = widget->allocation.x;
+ attributes.y = widget->allocation.y;
+ attributes.width = widget->allocation.width;
+ attributes.height = widget->allocation.height;
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
+ attributes.event_mask = gtk_widget_get_events (widget);
+ attributes.event_mask |= (GDK_EXPOSURE_MASK |
+ GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_ENTER_NOTIFY_MASK |
+ GDK_LEAVE_NOTIFY_MASK);
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+ widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
+ gdk_window_set_user_data (widget->window, widget);
+
+ widget->style = gtk_style_attach (widget->style, widget->window);
+ gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
+}
+
+static gint
+gtk_menu_shell_button_press (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ GtkMenuShell *menu_shell;
+ GtkWidget *menu_item;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_MENU_SHELL (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (event->type != GDK_BUTTON_PRESS)
+ return FALSE;
+
+ menu_shell = GTK_MENU_SHELL (widget);
+
+ if (menu_shell->parent_menu_shell)
+ {
+ gtk_widget_event (menu_shell->parent_menu_shell, (GdkEvent*) event);
+ }
+ else if (!menu_shell->active || !menu_shell->button)
+ {
+ if (!menu_shell->active)
+ {
+ gtk_grab_add (GTK_WIDGET (widget));
+ menu_shell->have_grab = TRUE;
+ }
+ menu_shell->active = TRUE;
+
+ menu_item = gtk_get_event_widget ((GdkEvent*) event);
+ if (GTK_IS_MENU_ITEM (menu_item) && gtk_menu_shell_is_item (menu_shell, menu_item))
+ {
+ if ((menu_item->parent == widget) &&
+ (menu_item != menu_shell->active_menu_item))
+ {
+ if (menu_shell->active_menu_item)
+ gtk_menu_item_deselect (GTK_MENU_ITEM (menu_shell->active_menu_item));
+
+ menu_shell->active_menu_item = menu_item;
+ gtk_menu_item_set_placement (GTK_MENU_ITEM (menu_shell->active_menu_item),
+ MENU_SHELL_CLASS (menu_shell)->submenu_placement);
+ gtk_menu_item_select (GTK_MENU_ITEM (menu_shell->active_menu_item));
+ }
+ }
+ else if (!menu_shell->button)
+ {
+ gtk_menu_shell_deactivate (menu_shell);
+ }
+
+ if (menu_shell->active)
+ menu_shell->button = event->button;
+ }
+ else
+ {
+ widget = gtk_get_event_widget ((GdkEvent*) event);
+ if (widget == GTK_WIDGET (menu_shell))
+ gtk_menu_shell_deactivate (menu_shell);
+ }
+
+ return TRUE;
+}
+
+static gint
+gtk_menu_shell_button_release (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ GtkMenuShell *menu_shell;
+ GtkWidget *menu_item;
+ gint deactivate;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_MENU_SHELL (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ menu_shell = GTK_MENU_SHELL (widget);
+ if (menu_shell->active)
+ {
+ if (menu_shell->button && (event->button != menu_shell->button))
+ {
+ menu_shell->button = 0;
+ if (menu_shell->parent_menu_shell)
+ gtk_widget_event (menu_shell->parent_menu_shell, (GdkEvent*) event);
+ return TRUE;
+ }
+
+ menu_shell->button = 0;
+ menu_item = gtk_get_event_widget ((GdkEvent*) event);
+ deactivate = TRUE;
+
+ if ((event->time - menu_shell->activate_time) > MENU_SHELL_TIMEOUT)
+ {
+ if (menu_shell->active_menu_item == menu_item)
+ {
+ if (GTK_MENU_ITEM (menu_item)->submenu == NULL)
+ {
+ gtk_menu_shell_deactivate (menu_shell);
+ gtk_widget_activate (menu_item);
+ return TRUE;
+ }
+ }
+ else if (menu_shell->parent_menu_shell)
+ {
+ menu_shell->active = TRUE;
+ gtk_widget_event (menu_shell->parent_menu_shell, (GdkEvent*) event);
+ return TRUE;
+ }
+ }
+ else
+ deactivate = FALSE;
+
+ if ((!deactivate || (menu_shell->active_menu_item == menu_item)) &&
+ (gdk_pointer_grab (widget->window, TRUE,
+ GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
+ GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK,
+ NULL, NULL, event->time) == 0))
+ {
+ deactivate = FALSE;
+ menu_shell->have_xgrab = TRUE;
+ menu_shell->ignore_leave = TRUE;
+ }
+ else
+ deactivate = TRUE;
+
+ if (deactivate)
+ gtk_menu_shell_deactivate (menu_shell);
+ }
+
+ return TRUE;
+}
+
+static gint
+gtk_menu_shell_enter_notify (GtkWidget *widget,
+ GdkEventCrossing *event)
+{
+ GtkMenuShell *menu_shell;
+ GtkWidget *menu_item;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_MENU_SHELL (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ menu_shell = GTK_MENU_SHELL (widget);
+ if (menu_shell->active)
+ {
+ menu_item = gtk_get_event_widget ((GdkEvent*) event);
+
+ if (!GTK_WIDGET_IS_SENSITIVE (menu_item))
+ return TRUE;
+
+ if ((menu_item->parent == widget) &&
+ (menu_shell->active_menu_item != menu_item) &&
+ GTK_IS_MENU_ITEM (menu_item))
+ {
+ if ((event->detail != GDK_NOTIFY_INFERIOR) &&
+ (GTK_WIDGET_STATE (menu_item) != GTK_STATE_PRELIGHT))
+ {
+ if (menu_shell->active_menu_item)
+ gtk_menu_item_deselect (GTK_MENU_ITEM (menu_shell->active_menu_item));
+
+ menu_shell->active_menu_item = menu_item;
+ gtk_menu_item_set_placement (GTK_MENU_ITEM (menu_shell->active_menu_item),
+ MENU_SHELL_CLASS (menu_shell)->submenu_placement);
+ gtk_menu_item_select (GTK_MENU_ITEM (menu_shell->active_menu_item));
+ }
+ }
+ else if (menu_shell->parent_menu_shell)
+ {
+ gtk_widget_event (menu_shell->parent_menu_shell, (GdkEvent*) event);
+ }
+ }
+
+ return TRUE;
+}
+
+static gint
+gtk_menu_shell_leave_notify (GtkWidget *widget,
+ GdkEventCrossing *event)
+{
+ GtkMenuShell *menu_shell;
+ GtkMenuItem *menu_item;
+ GtkWidget *event_widget;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_MENU_SHELL (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (GTK_WIDGET_VISIBLE (widget))
+ {
+ menu_shell = GTK_MENU_SHELL (widget);
+ event_widget = gtk_get_event_widget ((GdkEvent*) event);
+
+ if (!GTK_IS_MENU_ITEM (event_widget))
+ return TRUE;
+
+ menu_item = GTK_MENU_ITEM (event_widget);
+
+ if (!GTK_WIDGET_IS_SENSITIVE (menu_item))
+ return TRUE;
+
+ if (menu_shell->ignore_leave)
+ {
+ menu_shell->ignore_leave = FALSE;
+ return TRUE;
+ }
+
+ if ((menu_shell->active_menu_item == event_widget) &&
+ (menu_item->submenu == NULL))
+ {
+ if ((event->detail != GDK_NOTIFY_INFERIOR) &&
+ (GTK_WIDGET_STATE (menu_item) != GTK_STATE_NORMAL))
+ {
+ gtk_menu_item_deselect (GTK_MENU_ITEM (menu_shell->active_menu_item));
+ menu_shell->active_menu_item = NULL;
+ }
+ }
+ else if (menu_shell->parent_menu_shell)
+ {
+ gtk_widget_event (menu_shell->parent_menu_shell, (GdkEvent*) event);
+ }
+ }
+
+ return TRUE;
+}
+
+static void
+gtk_menu_shell_add (GtkContainer *container,
+ GtkWidget *widget)
+{
+ gtk_menu_shell_append (GTK_MENU_SHELL (container), widget);
+}
+
+static void
+gtk_menu_shell_remove (GtkContainer *container,
+ GtkWidget *widget)
+{
+ GtkMenuShell *menu_shell;
+
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_MENU_SHELL (container));
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_MENU_ITEM (widget));
+
+ gtk_widget_unparent (widget);
+
+ menu_shell = GTK_MENU_SHELL (container);
+ menu_shell->children = g_list_remove (menu_shell->children, widget);
+
+ if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (container))
+ gtk_widget_queue_resize (GTK_WIDGET (container));
+}
+
+static void
+gtk_menu_shell_foreach (GtkContainer *container,
+ GtkCallback callback,
+ gpointer callback_data)
+{
+ GtkMenuShell *menu_shell;
+ GtkWidget *child;
+ GList *children;
+
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_MENU_SHELL (container));
+ g_return_if_fail (callback != NULL);
+
+ menu_shell = GTK_MENU_SHELL (container);
+
+ children = menu_shell->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ (* callback) (child, callback_data);
+ }
+}
+
+
+static void
+gtk_real_menu_shell_deactivate (GtkMenuShell *menu_shell)
+{
+ g_return_if_fail (menu_shell != NULL);
+ g_return_if_fail (GTK_IS_MENU_SHELL (menu_shell));
+
+ if (menu_shell->active)
+ {
+ menu_shell->button = 0;
+ menu_shell->active = FALSE;
+
+ if (menu_shell->active_menu_item)
+ {
+ gtk_menu_item_deselect (GTK_MENU_ITEM (menu_shell->active_menu_item));
+ menu_shell->active_menu_item = NULL;
+ }
+
+ if (menu_shell->have_grab)
+ {
+ menu_shell->have_grab = FALSE;
+ gtk_grab_remove (GTK_WIDGET (menu_shell));
+ }
+ if (menu_shell->have_xgrab)
+ {
+ menu_shell->have_xgrab = FALSE;
+ gdk_pointer_ungrab (GDK_CURRENT_TIME);
+ }
+ }
+}
+
+static gint
+gtk_menu_shell_is_item (GtkMenuShell *menu_shell,
+ GtkWidget *child)
+{
+ GtkMenuShell *parent;
+
+ g_return_val_if_fail (menu_shell != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_MENU_SHELL (menu_shell), FALSE);
+ g_return_val_if_fail (child != NULL, FALSE);
+
+ parent = GTK_MENU_SHELL (child->parent);
+ while (parent && GTK_IS_MENU_SHELL (parent))
+ {
+ if (parent == menu_shell)
+ return TRUE;
+ parent = GTK_MENU_SHELL (parent->parent_menu_shell);
+ }
+
+ return FALSE;
+}
diff --git a/gtk/gtkmenushell.h b/gtk/gtkmenushell.h
new file mode 100644
index 000000000..a468631ed
--- /dev/null
+++ b/gtk/gtkmenushell.h
@@ -0,0 +1,83 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_MENU_SHELL_H__
+#define __GTK_MENU_SHELL_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkcontainer.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_MENU_SHELL(obj) GTK_CHECK_CAST (obj, gtk_menu_shell_get_type (), GtkMenuShell)
+#define GTK_MENU_SHELL_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_menu_shell_get_type (), GtkMenuShellClass)
+#define GTK_IS_MENU_SHELL(obj) GTK_CHECK_TYPE (obj, gtk_menu_shell_get_type ())
+
+
+typedef struct _GtkMenuShell GtkMenuShell;
+typedef struct _GtkMenuShellClass GtkMenuShellClass;
+
+struct _GtkMenuShell
+{
+ GtkContainer container;
+
+ GList *children;
+ GtkWidget *active_menu_item;
+ GtkWidget *parent_menu_shell;
+
+ guint active : 1;
+ guint have_grab : 1;
+ guint have_xgrab : 1;
+ guint button : 2;
+ guint ignore_leave : 1;
+ guint menu_flag : 1;
+
+ guint32 activate_time;
+};
+
+struct _GtkMenuShellClass
+{
+ GtkContainerClass parent_class;
+
+ guint submenu_placement : 1;
+
+ void (*deactivate) (GtkMenuShell *menu_shell);
+};
+
+
+guint gtk_menu_shell_get_type (void);
+void gtk_menu_shell_append (GtkMenuShell *menu_shell,
+ GtkWidget *child);
+void gtk_menu_shell_prepend (GtkMenuShell *menu_shell,
+ GtkWidget *child);
+void gtk_menu_shell_insert (GtkMenuShell *menu_shell,
+ GtkWidget *child,
+ gint position);
+void gtk_menu_shell_deactivate (GtkMenuShell *menu_shell);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_MENU_SHELL_H__ */
diff --git a/gtk/gtkmisc.c b/gtk/gtkmisc.c
new file mode 100644
index 000000000..0ef8f0731
--- /dev/null
+++ b/gtk/gtkmisc.c
@@ -0,0 +1,181 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtkcontainer.h"
+#include "gtkmisc.h"
+
+
+static void gtk_misc_class_init (GtkMiscClass *klass);
+static void gtk_misc_init (GtkMisc *misc);
+static void gtk_misc_realize (GtkWidget *widget);
+
+
+guint
+gtk_misc_get_type ()
+{
+ static guint misc_type = 0;
+
+ if (!misc_type)
+ {
+ GtkTypeInfo misc_info =
+ {
+ "GtkMisc",
+ sizeof (GtkMisc),
+ sizeof (GtkMiscClass),
+ (GtkClassInitFunc) gtk_misc_class_init,
+ (GtkObjectInitFunc) gtk_misc_init,
+ (GtkArgFunc) NULL,
+ };
+
+ misc_type = gtk_type_unique (gtk_widget_get_type (), &misc_info);
+ }
+
+ return misc_type;
+}
+
+static void
+gtk_misc_class_init (GtkMiscClass *class)
+{
+ GtkWidgetClass *widget_class;
+
+ widget_class = (GtkWidgetClass*) class;
+
+ widget_class->realize = gtk_misc_realize;
+}
+
+static void
+gtk_misc_init (GtkMisc *misc)
+{
+ GTK_WIDGET_SET_FLAGS (misc, GTK_BASIC);
+
+ misc->xalign = 0.5;
+ misc->yalign = 0.5;
+ misc->xpad = 0;
+ misc->ypad = 0;
+}
+
+void
+gtk_misc_set_alignment (GtkMisc *misc,
+ gfloat xalign,
+ gfloat yalign)
+{
+ g_return_if_fail (misc != NULL);
+ g_return_if_fail (GTK_IS_MISC (misc));
+
+ if (xalign < 0.0)
+ xalign = 0.0;
+ else if (xalign > 1.0)
+ xalign = 1.0;
+
+ if (yalign < 0.0)
+ yalign = 0.0;
+ else if (yalign > 1.0)
+ yalign = 1.0;
+
+ if ((xalign != misc->xalign) || (yalign != misc->yalign))
+ {
+ misc->xalign = xalign;
+ misc->yalign = yalign;
+
+ /* clear the area that was allocated before the change
+ */
+ if (GTK_WIDGET_VISIBLE (misc))
+ {
+ GtkWidget *widget;
+
+ widget = GTK_WIDGET (misc);
+ gdk_window_clear_area (widget->window,
+ widget->allocation.x,
+ widget->allocation.y,
+ widget->allocation.width,
+ widget->allocation.height);
+ }
+
+ gtk_widget_queue_draw (GTK_WIDGET (misc));
+ }
+}
+
+void
+gtk_misc_set_padding (GtkMisc *misc,
+ gint xpad,
+ gint ypad)
+{
+ GtkRequisition *requisition;
+
+ g_return_if_fail (misc != NULL);
+ g_return_if_fail (GTK_IS_MISC (misc));
+
+ if (xpad < 0)
+ xpad = 0;
+ if (ypad < 0)
+ ypad = 0;
+
+ if ((xpad != misc->xpad) || (ypad != misc->ypad))
+ {
+ requisition = &(GTK_WIDGET (misc)->requisition);
+ requisition->width -= misc->xpad * 2;
+ requisition->height -= misc->ypad * 2;
+
+ misc->xpad = xpad;
+ misc->ypad = ypad;
+
+ requisition->width += misc->xpad * 2;
+ requisition->height += misc->ypad * 2;
+
+ if (GTK_WIDGET (misc)->parent && GTK_WIDGET_VISIBLE (misc))
+ gtk_widget_queue_resize (GTK_WIDGET (misc));
+ }
+}
+
+static void
+gtk_misc_realize (GtkWidget *widget)
+{
+ GtkMisc *misc;
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_MISC (widget));
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+ misc = GTK_MISC (widget);
+
+ if (GTK_WIDGET_NO_WINDOW (widget))
+ {
+ widget->window = widget->parent->window;
+ widget->style = gtk_style_attach (widget->style, widget->window);
+ }
+ else
+ {
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.x = widget->allocation.x;
+ attributes.y = widget->allocation.y;
+ attributes.width = widget->allocation.width;
+ attributes.height = widget->allocation.height;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
+ attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+
+ widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
+ gdk_window_set_user_data (widget->window, widget);
+
+ widget->style = gtk_style_attach (widget->style, widget->window);
+ gdk_window_set_back_pixmap (widget->window, NULL, TRUE);
+ }
+}
diff --git a/gtk/gtkmisc.h b/gtk/gtkmisc.h
new file mode 100644
index 000000000..1bc9cbb93
--- /dev/null
+++ b/gtk/gtkmisc.h
@@ -0,0 +1,70 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_MISC_H__
+#define __GTK_MISC_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkwidget.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_MISC(obj) GTK_CHECK_CAST (obj, gtk_misc_get_type (), GtkMisc)
+#define GTK_MISC_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_misc_get_type (), GtkMiscClass)
+#define GTK_IS_MISC(obj) GTK_CHECK_TYPE (obj, gtk_misc_get_type ())
+
+
+typedef struct _GtkMisc GtkMisc;
+typedef struct _GtkMiscClass GtkMiscClass;
+
+struct _GtkMisc
+{
+ GtkWidget widget;
+
+ gfloat xalign;
+ gfloat yalign;
+
+ guint16 xpad;
+ guint16 ypad;
+};
+
+struct _GtkMiscClass
+{
+ GtkWidgetClass parent_class;
+};
+
+
+guint gtk_misc_get_type (void);
+void gtk_misc_set_alignment (GtkMisc *misc,
+ gfloat xalign,
+ gfloat yalign);
+void gtk_misc_set_padding (GtkMisc *misc,
+ gint xpad,
+ gint ypad);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_LABEL_H__ */
diff --git a/gtk/gtknotebook.c b/gtk/gtknotebook.c
new file mode 100644
index 000000000..0b3115034
--- /dev/null
+++ b/gtk/gtknotebook.c
@@ -0,0 +1,1303 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtknotebook.h"
+
+
+#define CHILD_SPACING 2
+#define TAB_OVERLAP 2
+#define TAB_CURVATURE 1
+
+
+static void gtk_notebook_class_init (GtkNotebookClass *klass);
+static void gtk_notebook_init (GtkNotebook *notebook);
+static void gtk_notebook_destroy (GtkObject *object);
+static void gtk_notebook_map (GtkWidget *widget);
+static void gtk_notebook_unmap (GtkWidget *widget);
+static void gtk_notebook_realize (GtkWidget *widget);
+static void gtk_notebook_unrealize (GtkWidget *widget);
+static void gtk_notebook_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void gtk_notebook_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static void gtk_notebook_paint (GtkWidget *widget,
+ GdkRectangle *area);
+static void gtk_notebook_draw (GtkWidget *widget,
+ GdkRectangle *area);
+static gint gtk_notebook_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+static gint gtk_notebook_button_press (GtkWidget *widget,
+ GdkEventButton *event);
+static void gtk_notebook_add (GtkContainer *container,
+ GtkWidget *widget);
+static void gtk_notebook_remove (GtkContainer *container,
+ GtkWidget *widget);
+static void gtk_notebook_foreach (GtkContainer *container,
+ GtkCallback callback,
+ gpointer callback_data);
+static void gtk_notebook_switch_page (GtkNotebook *notebook,
+ GtkNotebookPage *page);
+static void gtk_notebook_draw_tab (GtkNotebook *notebook,
+ GtkNotebookPage *page,
+ GdkRectangle *area);
+static void gtk_notebook_pages_allocate (GtkNotebook *notebook,
+ GtkAllocation *allocation);
+static void gtk_notebook_page_allocate (GtkNotebook *notebook,
+ GtkNotebookPage *page,
+ GtkAllocation *allocation);
+
+
+static GtkContainerClass *parent_class = NULL;
+
+
+guint
+gtk_notebook_get_type ()
+{
+ static guint notebook_type = 0;
+
+ if (!notebook_type)
+ {
+ GtkTypeInfo notebook_info =
+ {
+ "GtkNotebook",
+ sizeof (GtkNotebook),
+ sizeof (GtkNotebookClass),
+ (GtkClassInitFunc) gtk_notebook_class_init,
+ (GtkObjectInitFunc) gtk_notebook_init,
+ (GtkArgFunc) NULL,
+ };
+
+ notebook_type = gtk_type_unique (gtk_container_get_type (), &notebook_info);
+ }
+
+ return notebook_type;
+}
+
+static void
+gtk_notebook_class_init (GtkNotebookClass *class)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+ GtkContainerClass *container_class;
+
+ object_class = (GtkObjectClass*) class;
+ widget_class = (GtkWidgetClass*) class;
+ container_class = (GtkContainerClass*) class;
+
+ parent_class = gtk_type_class (gtk_container_get_type ());
+
+ object_class->destroy = gtk_notebook_destroy;
+
+ widget_class->map = gtk_notebook_map;
+ widget_class->unmap = gtk_notebook_unmap;
+ widget_class->realize = gtk_notebook_realize;
+ widget_class->unrealize = gtk_notebook_unrealize;
+ widget_class->size_request = gtk_notebook_size_request;
+ widget_class->size_allocate = gtk_notebook_size_allocate;
+ widget_class->draw = gtk_notebook_draw;
+ widget_class->expose_event = gtk_notebook_expose;
+ widget_class->button_press_event = gtk_notebook_button_press;
+
+ container_class->add = gtk_notebook_add;
+ container_class->remove = gtk_notebook_remove;
+ container_class->foreach = gtk_notebook_foreach;
+}
+
+static void
+gtk_notebook_init (GtkNotebook *notebook)
+{
+ notebook->cur_page = NULL;
+ notebook->children = NULL;
+ notebook->show_tabs = TRUE;
+ notebook->show_border = TRUE;
+ notebook->tab_pos = GTK_POS_TOP;
+}
+
+GtkWidget*
+gtk_notebook_new ()
+{
+ return GTK_WIDGET (gtk_type_new (gtk_notebook_get_type ()));
+}
+
+void
+gtk_notebook_append_page (GtkNotebook *notebook,
+ GtkWidget *child,
+ GtkWidget *tab_label)
+{
+ g_return_if_fail (notebook != NULL);
+ g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
+ g_return_if_fail (child != NULL);
+ g_return_if_fail (tab_label != NULL);
+
+ gtk_notebook_insert_page (notebook, child, tab_label, -1);
+}
+
+void
+gtk_notebook_prepend_page (GtkNotebook *notebook,
+ GtkWidget *child,
+ GtkWidget *tab_label)
+{
+ g_return_if_fail (notebook != NULL);
+ g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
+ g_return_if_fail (child != NULL);
+ g_return_if_fail (tab_label != NULL);
+
+ gtk_notebook_insert_page (notebook, child, tab_label, 0);
+}
+
+void
+gtk_notebook_insert_page (GtkNotebook *notebook,
+ GtkWidget *child,
+ GtkWidget *tab_label,
+ gint position)
+{
+ GtkNotebookPage *page;
+ gint nchildren;
+
+ g_return_if_fail (notebook != NULL);
+ g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
+ g_return_if_fail (child != NULL);
+ g_return_if_fail (tab_label != NULL);
+
+ page = g_new (GtkNotebookPage, 1);
+ page->child = child;
+ page->tab_label = tab_label;
+ page->requisition.width = 0;
+ page->requisition.height = 0;
+ page->allocation.x = 0;
+ page->allocation.y = 0;
+ page->allocation.width = 0;
+ page->allocation.height = 0;
+
+ nchildren = g_list_length (notebook->children);
+ if ((position < 0) || (position > nchildren))
+ position = nchildren;
+
+ notebook->children = g_list_insert (notebook->children, page, position);
+
+ if (!notebook->cur_page)
+ notebook->cur_page = page;
+
+ gtk_widget_show (tab_label);
+ gtk_widget_set_parent (child, GTK_WIDGET (notebook));
+ gtk_widget_set_parent (tab_label, GTK_WIDGET (notebook));
+
+ if (GTK_WIDGET_VISIBLE (notebook))
+ {
+ if (GTK_WIDGET_REALIZED (notebook) &&
+ !GTK_WIDGET_REALIZED (child))
+ gtk_widget_realize (child);
+
+ if (GTK_WIDGET_MAPPED (notebook) &&
+ !GTK_WIDGET_MAPPED (child) && notebook->cur_page == page)
+ gtk_widget_map (child);
+
+ if (GTK_WIDGET_REALIZED (notebook) &&
+ !GTK_WIDGET_REALIZED (tab_label))
+ gtk_widget_realize (tab_label);
+
+ if (GTK_WIDGET_MAPPED (notebook) &&
+ !GTK_WIDGET_MAPPED (tab_label))
+ gtk_widget_map (tab_label);
+ }
+
+ if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (notebook))
+ gtk_widget_queue_resize (child);
+}
+
+void
+gtk_notebook_remove_page (GtkNotebook *notebook,
+ gint page_num)
+{
+ GtkNotebookPage *page;
+ GList *tmp_list;
+
+ g_return_if_fail (notebook != NULL);
+ g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
+
+ tmp_list = g_list_nth (notebook->children, page_num);
+ if (tmp_list)
+ {
+ page = tmp_list->data;
+
+ if (notebook->cur_page == page)
+ gtk_notebook_prev_page (notebook);
+ if (notebook->cur_page == page)
+ notebook->cur_page = NULL;
+
+ notebook->children = g_list_remove_link (notebook->children, tmp_list);
+ g_list_free (tmp_list);
+ g_free (page);
+ }
+}
+
+gint
+gtk_notebook_current_page (GtkNotebook *notebook)
+{
+ GList *children;
+ gint cur_page;
+
+ g_return_val_if_fail (notebook != NULL, -1);
+ g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
+
+ if (notebook->cur_page)
+ {
+ cur_page = 0;
+ children = notebook->children;
+
+ while (children)
+ {
+ if (children->data == notebook->cur_page)
+ break;
+ children = children->next;
+ cur_page += 1;
+ }
+
+ if (!children)
+ cur_page = -1;
+ }
+ else
+ {
+ cur_page = -1;
+ }
+
+ return cur_page;
+}
+
+void
+gtk_notebook_set_page (GtkNotebook *notebook,
+ gint page_num)
+{
+ GtkNotebookPage *page;
+ GList *tmp_list;
+
+ g_return_if_fail (notebook != NULL);
+ g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
+
+ tmp_list = g_list_nth (notebook->children, page_num);
+ if (tmp_list)
+ {
+ page = tmp_list->data;
+ gtk_notebook_switch_page (notebook, page);
+ }
+}
+
+void
+gtk_notebook_next_page (GtkNotebook *notebook)
+{
+ GtkNotebookPage *page;
+ GList *children;
+
+ g_return_if_fail (notebook != NULL);
+ g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
+
+ children = notebook->children;
+ while (children)
+ {
+ page = children->data;
+
+ if (notebook->cur_page == page)
+ {
+ children = children->next;
+ if (!children)
+ children = notebook->children;
+ page = children->data;
+
+ gtk_notebook_switch_page (notebook, page);
+ }
+
+ children = children->next;
+ }
+}
+
+void
+gtk_notebook_prev_page (GtkNotebook *notebook)
+{
+ GtkNotebookPage *page;
+ GList *children;
+
+ g_return_if_fail (notebook != NULL);
+ g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
+
+ children = notebook->children;
+ while (children)
+ {
+ page = children->data;
+
+ if (notebook->cur_page == page)
+ {
+ children = children->prev;
+ if (!children)
+ children = g_list_last (notebook->children);
+ page = children->data;
+
+ gtk_notebook_switch_page (notebook, page);
+ }
+
+ children = children->next;
+ }
+}
+
+void
+gtk_notebook_set_tab_pos (GtkNotebook *notebook,
+ GtkPositionType pos)
+{
+ g_return_if_fail (notebook != NULL);
+ g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
+
+ if (notebook->tab_pos != pos)
+ {
+ notebook->tab_pos = pos;
+
+ if (GTK_WIDGET_VISIBLE (notebook))
+ gtk_widget_queue_resize (GTK_WIDGET (notebook));
+ }
+}
+
+void
+gtk_notebook_set_show_tabs (GtkNotebook *notebook,
+ gint show_tabs)
+{
+ g_return_if_fail (notebook != NULL);
+ g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
+
+ if (notebook->show_tabs != show_tabs)
+ {
+ notebook->show_tabs = show_tabs;
+
+ if (GTK_WIDGET_VISIBLE (notebook))
+ gtk_widget_queue_resize (GTK_WIDGET (notebook));
+ }
+}
+
+void
+gtk_notebook_set_show_border (GtkNotebook *notebook,
+ gint show_border)
+{
+ g_return_if_fail (notebook != NULL);
+ g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
+
+ if (notebook->show_border != show_border)
+ {
+ notebook->show_border = show_border;
+
+ if (GTK_WIDGET_VISIBLE (notebook))
+ gtk_widget_queue_resize (GTK_WIDGET (notebook));
+ }
+}
+
+static void
+gtk_notebook_destroy (GtkObject *object)
+{
+ GtkNotebook *notebook;
+ GtkNotebookPage *page;
+ GList *children;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_NOTEBOOK (object));
+
+ notebook = GTK_NOTEBOOK (object);
+
+ children = notebook->children;
+ while (children)
+ {
+ page = children->data;
+ children = children->next;
+
+ page->child->parent = NULL;
+ page->tab_label->parent = NULL;
+
+ gtk_object_unref (GTK_OBJECT (page->child));
+ gtk_object_unref (GTK_OBJECT (page->tab_label));
+
+ gtk_widget_destroy (page->child);
+ gtk_widget_destroy (page->tab_label);
+
+ g_free (page);
+ }
+
+ g_list_free (notebook->children);
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+static void
+gtk_notebook_map (GtkWidget *widget)
+{
+ GtkNotebook *notebook;
+ GtkNotebookPage *page;
+ GList *children;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_NOTEBOOK (widget));
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
+ gdk_window_show (widget->window);
+
+ notebook = GTK_NOTEBOOK (widget);
+
+ if (notebook->cur_page &&
+ GTK_WIDGET_VISIBLE (notebook->cur_page->child) &&
+ !GTK_WIDGET_MAPPED (notebook->cur_page->child))
+ gtk_widget_map (notebook->cur_page->child);
+
+ children = notebook->children;
+ while (children)
+ {
+ page = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_VISIBLE (page->child) &&
+ !GTK_WIDGET_MAPPED (page->tab_label))
+ gtk_widget_map (page->tab_label);
+ }
+}
+
+static void
+gtk_notebook_unmap (GtkWidget *widget)
+{
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_NOTEBOOK (widget));
+
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
+ gdk_window_hide (widget->window);
+}
+
+static void
+gtk_notebook_realize (GtkWidget *widget)
+{
+ GtkNotebook *notebook;
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_NOTEBOOK (widget));
+
+ notebook = GTK_NOTEBOOK (widget);
+ GTK_WIDGET_SET_FLAGS (notebook, GTK_REALIZED);
+
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.x = widget->allocation.x;
+ attributes.y = widget->allocation.y;
+ attributes.width = widget->allocation.width;
+ attributes.height = widget->allocation.height;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
+ attributes.event_mask = gtk_widget_get_events (widget);
+ attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK;
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+
+ widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
+ gdk_window_set_user_data (widget->window, notebook);
+
+ widget->style = gtk_style_attach (widget->style, widget->window);
+ gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
+}
+
+static void
+gtk_notebook_unrealize (GtkWidget *widget)
+{
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_NOTEBOOK (widget));
+
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_REALIZED | GTK_MAPPED);
+
+ gtk_style_detach (widget->style);
+ gdk_window_destroy (widget->window);
+ widget->window = NULL;
+}
+
+static void
+gtk_notebook_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkNotebook *notebook;
+ GtkNotebookPage *page;
+ GList *children;
+ gint tab_width;
+ gint tab_height;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_NOTEBOOK (widget));
+ g_return_if_fail (requisition != NULL);
+
+ notebook = GTK_NOTEBOOK (widget);
+ widget->requisition.width = 0;
+ widget->requisition.height = 0;
+
+ children = notebook->children;
+ while (children)
+ {
+ page = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_VISIBLE (page->child))
+ {
+ gtk_widget_size_request (page->child, &page->child->requisition);
+
+ widget->requisition.width = MAX (widget->requisition.width,
+ page->child->requisition.width);
+ widget->requisition.height = MAX (widget->requisition.height,
+ page->child->requisition.height);
+ }
+ }
+
+ widget->requisition.width += GTK_CONTAINER (widget)->border_width * 2;
+ widget->requisition.height += GTK_CONTAINER (widget)->border_width * 2;
+
+ if (notebook->show_tabs)
+ {
+ widget->requisition.width += GTK_WIDGET (widget)->style->klass->xthickness * 2;
+ widget->requisition.height += GTK_WIDGET (widget)->style->klass->ythickness * 2;
+
+ tab_width = 0;
+ tab_height = 0;
+
+ children = notebook->children;
+ while (children)
+ {
+ page = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_VISIBLE (page->child))
+ {
+ gtk_widget_size_request (page->tab_label, &page->tab_label->requisition);
+
+ page->requisition.width = (page->tab_label->requisition.width +
+ (GTK_WIDGET (widget)->style->klass->xthickness +
+ CHILD_SPACING) * 2);
+ page->requisition.height = (page->tab_label->requisition.height +
+ (GTK_WIDGET (widget)->style->klass->ythickness +
+ CHILD_SPACING) * 2);
+
+ switch (notebook->tab_pos)
+ {
+ case GTK_POS_TOP:
+ case GTK_POS_BOTTOM:
+ page->requisition.width -= TAB_OVERLAP;
+ page->requisition.height -= GTK_WIDGET (widget)->style->klass->ythickness;
+
+ tab_width += page->requisition.width;
+ tab_height = MAX (tab_height, page->requisition.height);
+ break;
+ case GTK_POS_LEFT:
+ case GTK_POS_RIGHT:
+ page->requisition.width -= GTK_WIDGET (widget)->style->klass->xthickness;
+ page->requisition.height -= TAB_OVERLAP;
+
+ tab_width = MAX (tab_width, page->requisition.width);
+ tab_height += page->requisition.height;
+ break;
+ }
+ }
+ }
+
+ children = notebook->children;
+ while (children)
+ {
+ page = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_VISIBLE (page->child))
+ {
+ if ((notebook->tab_pos == GTK_POS_TOP) ||
+ (notebook->tab_pos == GTK_POS_BOTTOM))
+ page->requisition.height = tab_height;
+ else
+ page->requisition.width = tab_width;
+ }
+ }
+
+ switch (notebook->tab_pos)
+ {
+ case GTK_POS_TOP:
+ case GTK_POS_BOTTOM:
+ tab_width += GTK_WIDGET (widget)->style->klass->xthickness;
+ widget->requisition.width = MAX (widget->requisition.width, tab_width);
+ widget->requisition.height += tab_height;
+ break;
+ case GTK_POS_LEFT:
+ case GTK_POS_RIGHT:
+ tab_height += GTK_WIDGET (widget)->style->klass->ythickness;
+ widget->requisition.width += tab_width;
+ widget->requisition.height = MAX (widget->requisition.height, tab_height);
+ break;
+ }
+ }
+ else if (notebook->show_border)
+ {
+ widget->requisition.width += GTK_WIDGET (widget)->style->klass->xthickness * 2;
+ widget->requisition.height += GTK_WIDGET (widget)->style->klass->ythickness * 2;
+ }
+}
+
+static void
+gtk_notebook_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkNotebook *notebook;
+ GtkNotebookPage *page;
+ GtkAllocation child_allocation;
+ GList *children;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_NOTEBOOK (widget));
+ g_return_if_fail (allocation != NULL);
+
+ widget->allocation = *allocation;
+ if (GTK_WIDGET_REALIZED (widget))
+ gdk_window_move_resize (widget->window,
+ allocation->x, allocation->y,
+ allocation->width, allocation->height);
+
+ notebook = GTK_NOTEBOOK (widget);
+ if (notebook->children)
+ {
+ child_allocation.x = GTK_CONTAINER (widget)->border_width;
+ child_allocation.y = GTK_CONTAINER (widget)->border_width;
+ child_allocation.width = allocation->width - child_allocation.x * 2;
+ child_allocation.height = allocation->height - child_allocation.y * 2;
+
+ if (notebook->show_tabs || notebook->show_border)
+ {
+ child_allocation.x += GTK_WIDGET (widget)->style->klass->xthickness;
+ child_allocation.y += GTK_WIDGET (widget)->style->klass->ythickness;
+ child_allocation.width -= GTK_WIDGET (widget)->style->klass->xthickness * 2;
+ child_allocation.height -= GTK_WIDGET (widget)->style->klass->ythickness * 2;
+
+ if (notebook->show_tabs && notebook->children)
+ {
+ switch (notebook->tab_pos)
+ {
+ case GTK_POS_TOP:
+ child_allocation.y += notebook->cur_page->requisition.height;
+ case GTK_POS_BOTTOM:
+ child_allocation.height -= notebook->cur_page->requisition.height;
+ break;
+ case GTK_POS_LEFT:
+ child_allocation.x += notebook->cur_page->requisition.width;
+ case GTK_POS_RIGHT:
+ child_allocation.width -= notebook->cur_page->requisition.width;
+ break;
+ }
+ }
+ }
+
+ children = notebook->children;
+ while (children)
+ {
+ page = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_VISIBLE (page->child))
+ gtk_widget_size_allocate (page->child, &child_allocation);
+ }
+
+ if (notebook->show_tabs && notebook->children)
+ gtk_notebook_pages_allocate (notebook, allocation);
+ }
+}
+
+static void
+gtk_notebook_paint (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ GtkNotebook *notebook;
+ GtkNotebookPage *page;
+ GList *children;
+ GdkPoint points[6];
+ gint width, height;
+ gint x, y;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_NOTEBOOK (widget));
+ g_return_if_fail (area != NULL);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ notebook = GTK_NOTEBOOK (widget);
+
+ gdk_window_clear_area (widget->window,
+ area->x, area->y,
+ area->width, area->height);
+
+ if (notebook->show_tabs || notebook->show_border)
+ {
+ x = GTK_CONTAINER (widget)->border_width;
+ y = GTK_CONTAINER (widget)->border_width;
+ width = widget->allocation.width - x * 2;
+ height = widget->allocation.height - y * 2;
+
+ if (notebook->show_tabs && notebook->children)
+ {
+ switch (notebook->tab_pos)
+ {
+ case GTK_POS_TOP:
+ y += notebook->cur_page->allocation.height;
+ case GTK_POS_BOTTOM:
+ height -= notebook->cur_page->allocation.height;
+ break;
+ case GTK_POS_LEFT:
+ x += notebook->cur_page->allocation.width;
+ case GTK_POS_RIGHT:
+ width -= notebook->cur_page->allocation.width;
+ break;
+ }
+
+ switch (notebook->tab_pos)
+ {
+ case GTK_POS_TOP:
+ points[0].x = notebook->cur_page->allocation.x;
+ points[0].y = y;
+ points[1].x = x;
+ points[1].y = y;
+ points[2].x = x;
+ points[2].y = y + height - 1;
+ points[3].x = x + width - 1;
+ points[3].y = y + height - 1;
+ points[4].x = x + width - 1;
+ points[4].y = y;
+ points[5].x = (notebook->cur_page->allocation.x +
+ notebook->cur_page->allocation.width -
+ GTK_WIDGET (notebook)->style->klass->xthickness);
+ points[5].y = y;
+
+ if (points[5].x == (x + width))
+ points[5].x -= 1;
+ break;
+ case GTK_POS_BOTTOM:
+ points[0].x = (notebook->cur_page->allocation.x +
+ notebook->cur_page->allocation.width -
+ GTK_WIDGET (notebook)->style->klass->xthickness);
+ points[0].y = y + height - 1;
+ points[1].x = x + width - 1;
+ points[1].y = y + height - 1;
+ points[2].x = x + width - 1;
+ points[2].y = y;
+ points[3].x = x;
+ points[3].y = y;
+ points[4].x = x;
+ points[4].y = y + height - 1;
+ points[5].x = notebook->cur_page->allocation.x;
+ points[5].y = y + height - 1;
+
+ if (points[0].x == (x + width))
+ points[0].x -= 1;
+ break;
+ case GTK_POS_LEFT:
+ points[0].x = x;
+ points[0].y = (notebook->cur_page->allocation.y +
+ notebook->cur_page->allocation.height -
+ GTK_WIDGET (notebook)->style->klass->ythickness);
+ points[1].x = x;
+ points[1].y = y + height - 1;
+ points[2].x = x + width - 1;
+ points[2].y = y + height - 1;
+ points[3].x = x + width - 1;
+ points[3].y = y;
+ points[4].x = x;
+ points[4].y = y;
+ points[5].x = x;
+ points[5].y = notebook->cur_page->allocation.y;
+
+ if (points[0].y == (y + height))
+ points[0].y -= 1;
+ break;
+ case GTK_POS_RIGHT:
+ points[0].x = x + width - 1;
+ points[0].y = notebook->cur_page->allocation.y;
+ points[1].x = x + width - 1;
+ points[1].y = y;
+ points[2].x = x;
+ points[2].y = y;
+ points[3].x = x;
+ points[3].y = y + height - 1;
+ points[4].x = x + width - 1;
+ points[4].y = y + height - 1;
+ points[5].x = x + width - 1;
+ points[5].y = (notebook->cur_page->allocation.y +
+ notebook->cur_page->allocation.height -
+ GTK_WIDGET (notebook)->style->klass->ythickness);
+
+ if (points[5].y == (y + height))
+ points[5].y -= 1;
+ break;
+ }
+
+ gtk_draw_polygon (widget->style, widget->window,
+ GTK_STATE_NORMAL, GTK_SHADOW_OUT,
+ points, 6, FALSE);
+
+ children = g_list_last (notebook->children);
+ while (children)
+ {
+ page = children->data;
+ children = children->prev;
+
+ if (notebook->cur_page != page)
+ gtk_notebook_draw_tab (notebook, page, area);
+ }
+
+ if (notebook->cur_page)
+ gtk_notebook_draw_tab (notebook, notebook->cur_page, area);
+ }
+ else if (notebook->show_border)
+ {
+ gtk_draw_shadow (widget->style, widget->window,
+ GTK_STATE_NORMAL, GTK_SHADOW_OUT,
+ x, y, width, height);
+ }
+ }
+ }
+}
+
+static void
+gtk_notebook_draw (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ GtkNotebook *notebook;
+ GdkRectangle child_area;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_NOTEBOOK (widget));
+ g_return_if_fail (area != NULL);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ notebook = GTK_NOTEBOOK (widget);
+
+ gtk_notebook_paint (widget, area);
+
+ if (notebook->cur_page &&
+ gtk_widget_intersect (notebook->cur_page->child, area, &child_area))
+ gtk_widget_draw (notebook->cur_page->child, &child_area);
+ }
+}
+
+static gint
+gtk_notebook_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ GtkNotebook *notebook;
+ GdkEventExpose child_event;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ notebook = GTK_NOTEBOOK (widget);
+
+ gtk_notebook_paint (widget, &event->area);
+
+ child_event = *event;
+ if (notebook->cur_page && GTK_WIDGET_NO_WINDOW (notebook->cur_page->child) &&
+ gtk_widget_intersect (notebook->cur_page->child, &event->area, &child_event.area))
+ gtk_widget_event (notebook->cur_page->child, (GdkEvent*) &child_event);
+ }
+
+ return FALSE;
+}
+
+static gint
+gtk_notebook_button_press (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ GtkNotebook *notebook;
+ GtkNotebookPage *page;
+ GList *children;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if ((event->type != GDK_BUTTON_PRESS) ||
+ (event->window != widget->window))
+ return FALSE;
+
+ notebook = GTK_NOTEBOOK (widget);
+
+ children = notebook->children;
+ while (children)
+ {
+ page = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_VISIBLE (page->child) &&
+ (event->x >= page->allocation.x) &&
+ (event->y >= page->allocation.y) &&
+ (event->x <= (page->allocation.x + page->allocation.width)) &&
+ (event->y <= (page->allocation.y + page->allocation.height)))
+ {
+ gtk_notebook_switch_page (notebook, page);
+ break;
+ }
+ }
+
+ return FALSE;
+}
+
+static void
+gtk_notebook_add (GtkContainer *container,
+ GtkWidget *widget)
+{
+ g_warning ("gtk_notebook_add: use gtk_notebook_{append,prepend}_page instead\n");
+}
+
+static void
+gtk_notebook_remove (GtkContainer *container,
+ GtkWidget *widget)
+{
+ GtkNotebook *notebook;
+ GtkNotebookPage *page;
+ GList *children;
+
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_NOTEBOOK (container));
+ g_return_if_fail (widget != NULL);
+
+ notebook = GTK_NOTEBOOK (container);
+
+ children = notebook->children;
+ while (children)
+ {
+ page = children->data;
+
+ if (page->child == widget)
+ {
+ gtk_widget_unparent (page->child);
+ gtk_widget_unparent (page->tab_label);
+
+ notebook->children = g_list_remove_link (notebook->children, children);
+ g_list_free (children);
+ g_free (page);
+
+ if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (container))
+ gtk_widget_queue_resize (GTK_WIDGET (container));
+
+ break;
+ }
+
+ children = children->next;
+ }
+}
+
+static void
+gtk_notebook_foreach (GtkContainer *container,
+ GtkCallback callback,
+ gpointer callback_data)
+{
+ GtkNotebook *notebook;
+ GtkNotebookPage *page;
+ GList *children;
+
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_NOTEBOOK (container));
+ g_return_if_fail (callback != NULL);
+
+ notebook = GTK_NOTEBOOK (container);
+
+ children = notebook->children;
+ while (children)
+ {
+ page = children->data;
+ children = children->next;
+
+ (* callback) (page->child, callback_data);
+ }
+}
+
+static void
+gtk_notebook_switch_page (GtkNotebook *notebook,
+ GtkNotebookPage *page)
+{
+ g_return_if_fail (notebook != NULL);
+ g_return_if_fail (page != NULL);
+
+ if (notebook->cur_page != page)
+ {
+ if (notebook->cur_page && GTK_WIDGET_MAPPED (notebook->cur_page->child))
+ gtk_widget_unmap (notebook->cur_page->child);
+
+ notebook->cur_page = page;
+ gtk_notebook_pages_allocate (notebook, &GTK_WIDGET (notebook)->allocation);
+
+ if (GTK_WIDGET_MAPPED (notebook))
+ gtk_widget_map (notebook->cur_page->child);
+
+ if (GTK_WIDGET_DRAWABLE (notebook))
+ gtk_widget_queue_draw (GTK_WIDGET (notebook));
+ }
+}
+
+static void
+gtk_notebook_draw_tab (GtkNotebook *notebook,
+ GtkNotebookPage *page,
+ GdkRectangle *area)
+{
+ GdkRectangle child_area;
+ GdkRectangle page_area;
+ GtkStateType state_type;
+ GdkPoint points[6];
+
+ g_return_if_fail (notebook != NULL);
+ g_return_if_fail (page != NULL);
+ g_return_if_fail (area != NULL);
+
+ page_area.x = page->allocation.x;
+ page_area.y = page->allocation.y;
+ page_area.width = page->allocation.width;
+ page_area.height = page->allocation.height;
+
+ if (gdk_rectangle_intersect (&page_area, area, &child_area))
+ {
+ switch (notebook->tab_pos)
+ {
+ case GTK_POS_TOP:
+ points[0].x = page->allocation.x + page->allocation.width - 1;
+ points[0].y = page->allocation.y + page->allocation.height - 1;
+
+ points[1].x = page->allocation.x + page->allocation.width - 1;
+ points[1].y = page->allocation.y + TAB_CURVATURE;
+
+ points[2].x = page->allocation.x + page->allocation.width - TAB_CURVATURE - 1;
+ points[2].y = page->allocation.y;
+
+ points[3].x = page->allocation.x + TAB_CURVATURE;
+ points[3].y = page->allocation.y;
+
+ points[4].x = page->allocation.x;
+ points[4].y = page->allocation.y + TAB_CURVATURE;
+
+ points[5].x = page->allocation.x;
+ points[5].y = page->allocation.y + page->allocation.height - 1;
+ break;
+ case GTK_POS_BOTTOM:
+ points[0].x = page->allocation.x;
+ points[0].y = page->allocation.y;
+
+ points[1].x = page->allocation.x;
+ points[1].y = page->allocation.y + page->allocation.height - TAB_CURVATURE - 1;
+
+ points[2].x = page->allocation.x + TAB_CURVATURE;
+ points[2].y = page->allocation.y + page->allocation.height - 1;
+
+ points[3].x = page->allocation.x + page->allocation.width - TAB_CURVATURE - 1;
+ points[3].y = page->allocation.y + page->allocation.height - 1;
+
+ points[4].x = page->allocation.x + page->allocation.width - 1;
+ points[4].y = page->allocation.y + page->allocation.height - TAB_CURVATURE - 1;
+
+ points[5].x = page->allocation.x + page->allocation.width - 1;
+ points[5].y = page->allocation.y;
+ break;
+ case GTK_POS_LEFT:
+ points[0].x = page->allocation.x + page->allocation.width - 1;
+ points[0].y = page->allocation.y;
+
+ points[1].x = page->allocation.x + TAB_CURVATURE;
+ points[1].y = page->allocation.y;
+
+ points[2].x = page->allocation.x;
+ points[2].y = page->allocation.y + TAB_CURVATURE;
+
+ points[3].x = page->allocation.x;
+ points[3].y = page->allocation.y + page->allocation.height - TAB_CURVATURE - 1;
+
+ points[4].x = page->allocation.x + TAB_CURVATURE;
+ points[4].y = page->allocation.y + page->allocation.height - 1;
+
+ points[5].x = page->allocation.x + page->allocation.width - 1;
+ points[5].y = page->allocation.y + page->allocation.height - 1;
+ break;
+ case GTK_POS_RIGHT:
+ points[0].x = page->allocation.x;
+ points[0].y = page->allocation.y + page->allocation.height - 1;
+
+ points[1].x = page->allocation.x + page->allocation.width - TAB_CURVATURE - 1;
+ points[1].y = page->allocation.y + page->allocation.height - 1;
+
+ points[2].x = page->allocation.x + page->allocation.width - 1;
+ points[2].y = page->allocation.y + page->allocation.height - TAB_CURVATURE - 1;
+
+ points[3].x = page->allocation.x + page->allocation.width - 1;
+ points[3].y = page->allocation.y + TAB_CURVATURE;
+
+ points[4].x = page->allocation.x + page->allocation.width - TAB_CURVATURE - 1;
+ points[4].y = page->allocation.y;
+
+ points[5].x = page->allocation.x;
+ points[5].y = page->allocation.y;
+ break;
+ }
+
+ if (notebook->cur_page == page)
+ state_type = GTK_STATE_NORMAL;
+ else
+ state_type = GTK_STATE_ACTIVE;
+
+ gtk_draw_polygon (GTK_WIDGET (notebook)->style,
+ GTK_WIDGET (notebook)->window,
+ state_type, GTK_SHADOW_OUT,
+ points, 6, (notebook->cur_page != page));
+
+ if (gtk_widget_intersect (page->tab_label, area, &child_area))
+ gtk_widget_draw (page->tab_label, &child_area);
+ }
+}
+
+static void
+gtk_notebook_pages_allocate (GtkNotebook *notebook,
+ GtkAllocation *allocation)
+{
+ GtkNotebookPage *page;
+ GtkAllocation child_allocation;
+ GList *children;
+
+ if (notebook->show_tabs && notebook->children)
+ {
+ child_allocation.x = GTK_CONTAINER (notebook)->border_width;
+ child_allocation.y = GTK_CONTAINER (notebook)->border_width;
+
+ switch (notebook->tab_pos)
+ {
+ case GTK_POS_BOTTOM:
+ child_allocation.y = allocation->height - notebook->cur_page->requisition.height;
+ case GTK_POS_TOP:
+ child_allocation.height = notebook->cur_page->requisition.height;
+ break;
+ case GTK_POS_RIGHT:
+ child_allocation.x = allocation->width - notebook->cur_page->requisition.width;
+ case GTK_POS_LEFT:
+ child_allocation.width = notebook->cur_page->requisition.width;
+ break;
+ }
+
+ children = notebook->children;
+ while (children)
+ {
+ page = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_VISIBLE (page->child))
+ {
+ switch (notebook->tab_pos)
+ {
+ case GTK_POS_TOP:
+ case GTK_POS_BOTTOM:
+ child_allocation.width = page->requisition.width + TAB_OVERLAP;
+ break;
+ case GTK_POS_LEFT:
+ case GTK_POS_RIGHT:
+ child_allocation.height = page->requisition.height + TAB_OVERLAP;
+ break;
+ }
+
+ gtk_notebook_page_allocate (notebook, page, &child_allocation);
+
+ switch (notebook->tab_pos)
+ {
+ case GTK_POS_TOP:
+ case GTK_POS_BOTTOM:
+ child_allocation.x += child_allocation.width - TAB_OVERLAP;
+ break;
+ case GTK_POS_LEFT:
+ case GTK_POS_RIGHT:
+ child_allocation.y += child_allocation.height - TAB_OVERLAP;
+ break;
+ }
+ }
+ }
+ }
+}
+
+static void
+gtk_notebook_page_allocate (GtkNotebook *notebook,
+ GtkNotebookPage *page,
+ GtkAllocation *allocation)
+{
+ GtkAllocation child_allocation;
+ gint xthickness, ythickness;
+
+ g_return_if_fail (notebook != NULL);
+ g_return_if_fail (page != NULL);
+ g_return_if_fail (allocation != NULL);
+
+ page->allocation = *allocation;
+
+ xthickness = GTK_WIDGET (notebook)->style->klass->xthickness;
+ ythickness = GTK_WIDGET (notebook)->style->klass->ythickness;
+
+ if (notebook->cur_page != page)
+ {
+ switch (notebook->tab_pos)
+ {
+ case GTK_POS_TOP:
+ page->allocation.y += ythickness;
+ case GTK_POS_BOTTOM:
+ page->allocation.height -= ythickness;
+ break;
+ case GTK_POS_LEFT:
+ page->allocation.x += xthickness;
+ case GTK_POS_RIGHT:
+ page->allocation.width -= xthickness;
+ break;
+ }
+ }
+
+ switch (notebook->tab_pos)
+ {
+ case GTK_POS_TOP:
+ child_allocation.x = xthickness + CHILD_SPACING;
+ child_allocation.y = ythickness + CHILD_SPACING;
+ child_allocation.width = page->allocation.width - child_allocation.x * 2;
+ child_allocation.height = page->allocation.height - child_allocation.y;
+ child_allocation.x += page->allocation.x;
+ child_allocation.y += page->allocation.y;
+ break;
+ case GTK_POS_BOTTOM:
+ child_allocation.x = xthickness + CHILD_SPACING;
+ child_allocation.y = ythickness + CHILD_SPACING;
+ child_allocation.width = page->allocation.width - child_allocation.x * 2;
+ child_allocation.height = page->allocation.height - child_allocation.y;
+ child_allocation.x += page->allocation.x;
+ child_allocation.y = page->allocation.y;
+ break;
+ case GTK_POS_LEFT:
+ child_allocation.x = xthickness + CHILD_SPACING;
+ child_allocation.y = ythickness + CHILD_SPACING;
+ child_allocation.width = page->allocation.width - child_allocation.x;
+ child_allocation.height = page->allocation.height - child_allocation.y * 2;
+ child_allocation.x += page->allocation.x;
+ child_allocation.y += page->allocation.y;
+ break;
+ case GTK_POS_RIGHT:
+ child_allocation.x = xthickness + CHILD_SPACING;
+ child_allocation.y = ythickness + CHILD_SPACING;
+ child_allocation.width = page->allocation.width - child_allocation.x;
+ child_allocation.height = page->allocation.height - child_allocation.y * 2;
+ child_allocation.x = page->allocation.x;
+ child_allocation.y += page->allocation.y;
+ break;
+ }
+
+ gtk_widget_size_allocate (page->tab_label, &child_allocation);
+}
diff --git a/gtk/gtknotebook.h b/gtk/gtknotebook.h
new file mode 100644
index 000000000..402823b2e
--- /dev/null
+++ b/gtk/gtknotebook.h
@@ -0,0 +1,98 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_NOTEBOOK_H__
+#define __GTK_NOTEBOOK_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkcontainer.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_NOTEBOOK(obj) GTK_CHECK_CAST (obj, gtk_notebook_get_type (), GtkNotebook)
+#define GTK_NOTEBOOK_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_notebook_get_type (), GtkNotebookClass)
+#define GTK_IS_NOTEBOOK(obj) GTK_CHECK_TYPE (obj, gtk_notebook_get_type ())
+
+
+typedef struct _GtkNotebook GtkNotebook;
+typedef struct _GtkNotebookClass GtkNotebookClass;
+typedef struct _GtkNotebookPage GtkNotebookPage;
+
+struct _GtkNotebook
+{
+ GtkContainer container;
+
+ GtkNotebookPage *cur_page;
+ GList *children;
+
+ guint show_tabs : 1;
+ guint show_border : 1;
+ guint tab_pos : 2;
+};
+
+struct _GtkNotebookClass
+{
+ GtkContainerClass parent_class;
+};
+
+struct _GtkNotebookPage
+{
+ GtkWidget *child;
+ GtkWidget *tab_label;
+ GtkRequisition requisition;
+ GtkAllocation allocation;
+};
+
+
+guint gtk_notebook_get_type (void);
+GtkWidget* gtk_notebook_new (void);
+void gtk_notebook_append_page (GtkNotebook *notebook,
+ GtkWidget *child,
+ GtkWidget *tab_label);
+void gtk_notebook_prepend_page (GtkNotebook *notebook,
+ GtkWidget *child,
+ GtkWidget *tab_label);
+void gtk_notebook_insert_page (GtkNotebook *notebook,
+ GtkWidget *child,
+ GtkWidget *tab_label,
+ gint position);
+void gtk_notebook_remove_page (GtkNotebook *notebook,
+ gint page_num);
+gint gtk_notebook_current_page (GtkNotebook *notebook);
+void gtk_notebook_set_page (GtkNotebook *notebook,
+ gint page_num);
+void gtk_notebook_next_page (GtkNotebook *notebook);
+void gtk_notebook_prev_page (GtkNotebook *notebook);
+void gtk_notebook_set_tab_pos (GtkNotebook *notebook,
+ GtkPositionType pos);
+void gtk_notebook_set_show_tabs (GtkNotebook *notebook,
+ gint show_tabs);
+void gtk_notebook_set_show_border (GtkNotebook *notebook,
+ gint show_border);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_NOTEBOOK_H__ */
diff --git a/gtk/gtkobject.c b/gtk/gtkobject.c
new file mode 100644
index 000000000..ffe487e89
--- /dev/null
+++ b/gtk/gtkobject.c
@@ -0,0 +1,994 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdarg.h>
+#include <string.h>
+#include "gtkobject.h"
+#include "gtksignal.h"
+
+
+#define OBJECT_DATA_ID_CHUNK 1024
+
+
+enum {
+ DESTROY,
+ LAST_SIGNAL
+};
+
+
+typedef struct _GtkObjectData GtkObjectData;
+typedef struct _GtkArgInfo GtkArgInfo;
+
+struct _GtkObjectData
+{
+ guint id;
+ gpointer data;
+ GtkObjectData *next;
+};
+
+struct _GtkArgInfo
+{
+ char *name;
+ GtkType type;
+};
+
+
+static void gtk_object_class_init (GtkObjectClass *klass);
+static void gtk_object_init (GtkObject *object);
+static void gtk_object_arg (GtkObject *object,
+ GtkArg *arg);
+static void gtk_real_object_destroy (GtkObject *object);
+static void gtk_object_data_init (void);
+static GtkObjectData* gtk_object_data_new (void);
+static void gtk_object_data_destroy (GtkObjectData *odata);
+static guint* gtk_object_data_id_alloc (void);
+GtkArg* gtk_object_collect_args (gint *nargs,
+ va_list args1,
+ va_list args2);
+
+
+static gint object_signals[LAST_SIGNAL] = { 0 };
+
+static gint object_data_init = TRUE;
+static GHashTable *object_data_ht = NULL;
+static GMemChunk *object_data_mem_chunk = NULL;
+static GtkObjectData *object_data_free_list = NULL;
+static GSList *object_data_id_list = NULL;
+static gint object_data_id_index = 0;
+
+static GHashTable *arg_info_ht = NULL;
+
+static const char *user_data_key = "user_data";
+
+
+/*****************************************
+ * gtk_object_get_type:
+ *
+ * arguments:
+ *
+ * results:
+ * The type identifier for GtkObject's
+ *****************************************/
+
+void
+gtk_object_init_type ()
+{
+ GtkType object_type = 0;
+ GtkTypeInfo object_info =
+ {
+ "GtkObject",
+ sizeof (GtkObject),
+ sizeof (GtkObjectClass),
+ (GtkClassInitFunc) gtk_object_class_init,
+ (GtkObjectInitFunc) gtk_object_init,
+ (GtkArgFunc) gtk_object_arg,
+ };
+
+ object_type = gtk_type_unique (0, &object_info);
+ g_assert (object_type == GTK_TYPE_OBJECT);
+}
+
+GtkType
+gtk_object_get_type ()
+{
+ return GTK_TYPE_OBJECT;
+}
+
+/*****************************************
+ * gtk_object_class_init:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+static void
+gtk_object_class_init (GtkObjectClass *class)
+{
+ class->signals = NULL;
+ class->nsignals = 0;
+
+ gtk_object_add_arg_type ("GtkObject::user_data", GTK_TYPE_POINTER);
+ gtk_object_add_arg_type ("GtkObject::signal", GTK_TYPE_SIGNAL);
+
+ object_signals[DESTROY] =
+ gtk_signal_new ("destroy",
+ GTK_RUN_LAST,
+ class->type,
+ GTK_SIGNAL_OFFSET (GtkObjectClass, destroy),
+ gtk_signal_default_marshaller,
+ GTK_TYPE_NONE, 0);
+
+ gtk_object_class_add_signals (class, object_signals, LAST_SIGNAL);
+
+ class->destroy = gtk_real_object_destroy;
+}
+
+/*****************************************
+ * gtk_object_init:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+static void
+gtk_object_init (GtkObject *object)
+{
+ object->flags = 0;
+ object->ref_count = 0;
+ object->object_data = NULL;
+}
+
+/*****************************************
+ * gtk_object_arg:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+static void
+gtk_object_arg (GtkObject *object,
+ GtkArg *arg)
+{
+ if (strcmp (arg->name, "user_data") == 0)
+ {
+ gtk_object_set_user_data (object, GTK_VALUE_POINTER (*arg));
+ }
+ else if (strncmp (arg->name, "signal", 6) == 0)
+ {
+ if ((arg->name[6] != ':') || (arg->name[7] != ':'))
+ {
+ g_print ("invalid signal argument: \"%s\"\n", arg->name);
+ return;
+ }
+
+ gtk_signal_connect (object, arg->name + 8,
+ (GtkSignalFunc) GTK_VALUE_SIGNAL (*arg).f,
+ GTK_VALUE_SIGNAL (*arg).d);
+ }
+}
+
+/*****************************************
+ * gtk_object_class_add_signals:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_object_class_add_signals (GtkObjectClass *class,
+ gint *signals,
+ gint nsignals)
+{
+ gint *new_signals;
+ gint i;
+
+ g_return_if_fail (class != NULL);
+
+ new_signals = g_new (gint, class->nsignals + nsignals);
+ for (i = 0; i < class->nsignals; i++)
+ new_signals[i] = class->signals[i];
+ for (i = 0; i < nsignals; i++)
+ new_signals[class->nsignals + i] = signals[i];
+
+ class->signals = new_signals;
+ class->nsignals += nsignals;
+}
+
+/*****************************************
+ * gtk_object_ref:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_object_ref (GtkObject *object)
+{
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_OBJECT (object));
+
+ object->ref_count += 1;
+}
+
+/*****************************************
+ * gtk_object_new:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_object_unref (GtkObject *object)
+{
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_OBJECT (object));
+
+ if (object->ref_count > 0)
+ object->ref_count -= 1;
+}
+
+/*****************************************
+ * gtk_object_new:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+GtkObject*
+gtk_object_new (guint type,
+ ...)
+{
+ GtkObject *obj;
+ GtkArg *args;
+ gint nargs;
+ va_list args1;
+ va_list args2;
+
+ obj = gtk_type_new (type);
+
+ va_start (args1, type);
+ va_start (args2, type);
+
+ args = gtk_object_collect_args (&nargs, args1, args2);
+ gtk_object_setv (obj, nargs, args);
+ g_free (args);
+
+ va_end (args1);
+ va_end (args2);
+
+ return obj;
+}
+
+/*****************************************
+ * gtk_object_newv:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+GtkObject*
+gtk_object_newv (guint type,
+ gint nargs,
+ GtkArg *args)
+{
+ gpointer obj;
+
+ obj = gtk_type_new (type);
+ gtk_object_setv (obj, nargs, args);
+
+ return obj;
+}
+
+/*****************************************
+ * gtk_object_set:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_object_set (GtkObject *obj,
+ ...)
+{
+ GtkArg *args;
+ gint nargs;
+ va_list args1;
+ va_list args2;
+
+ g_return_if_fail (obj != NULL);
+
+ va_start (args1, obj);
+ va_start (args2, obj);
+
+ args = gtk_object_collect_args (&nargs, args1, args2);
+ gtk_object_setv (obj, nargs, args);
+ g_free (args);
+
+ va_end (args1);
+ va_end (args2);
+}
+
+/*****************************************
+ * gtk_object_setv:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_object_setv (GtkObject *obj,
+ gint nargs,
+ GtkArg *args)
+{
+ guint class_type;
+ char class_name[1024];
+ char *arg_name;
+ int i;
+
+ g_return_if_fail (obj != NULL);
+
+ for (i = 0; i < nargs; i++)
+ {
+ arg_name = strchr (args[i].name, ':');
+ if (!arg_name || (arg_name[0] != ':') || (arg_name[1] != ':'))
+ {
+ g_print ("invalid arg name: \"%s\"\n", args[i].name);
+ continue;
+ }
+
+ strncpy (class_name, args[i].name, (long) (arg_name - args[i].name));
+ class_name[(long) (arg_name - args[i].name)] = '\0';
+
+ args[i].name = arg_name + 2;
+
+ class_type = gtk_type_from_name (class_name);
+ gtk_type_set_arg (obj, class_type, &args[i]);
+ }
+}
+
+/*****************************************
+ * gtk_object_add_arg_type:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_object_add_arg_type (const char *arg_name,
+ GtkType arg_type)
+{
+ GtkArgInfo *info;
+
+ info = g_new (GtkArgInfo, 1);
+ info->name = g_strdup(arg_name);
+ info->type = arg_type;
+
+ if (!arg_info_ht)
+ arg_info_ht = g_hash_table_new (g_string_hash, g_string_equal);
+
+ g_hash_table_insert (arg_info_ht, info->name, info);
+}
+
+/*****************************************
+ * gtk_object_get_arg_type:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+GtkType
+gtk_object_get_arg_type (const char *arg_name)
+{
+ GtkArgInfo *info;
+ char buffer[1024];
+ char *t;
+
+ if (!arg_info_ht)
+ return GTK_TYPE_INVALID;
+
+ t = strchr (arg_name, ':');
+ if (!t || (t[0] != ':') || (t[1] != ':'))
+ {
+ g_print ("invalid arg name: \"%s\"\n", arg_name);
+ return GTK_TYPE_INVALID;
+ }
+
+ t = strchr (t + 2, ':');
+ if (t)
+ {
+ strncpy (buffer, arg_name, (long) (t - arg_name));
+ buffer[(long) (t - arg_name)] = '\0';
+ arg_name = buffer;
+ }
+
+ info = g_hash_table_lookup (arg_info_ht, (gpointer) arg_name);
+ if (info)
+ return info->type;
+
+ return GTK_TYPE_INVALID;
+}
+
+/*****************************************
+ * gtk_object_destroy:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_object_destroy (GtkObject *object)
+{
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_OBJECT (object));
+
+ if ((object->ref_count > 0) || GTK_OBJECT_IN_CALL (object))
+ {
+ GTK_OBJECT_SET_FLAGS (object, GTK_NEED_DESTROY);
+ }
+ else
+ {
+ GTK_OBJECT_UNSET_FLAGS (object, GTK_NEED_DESTROY);
+ GTK_OBJECT_SET_FLAGS (object, GTK_BEING_DESTROYED);
+
+ gtk_signal_emit (object, object_signals[DESTROY]);
+ }
+}
+
+/*****************************************
+ * gtk_object_set_data:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_object_set_data (GtkObject *object,
+ const gchar *key,
+ gpointer data)
+{
+ GtkObjectData *odata;
+ GtkObjectData *prev;
+ guint *id;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_OBJECT (object));
+ g_return_if_fail (key != NULL);
+
+ if (object_data_init)
+ gtk_object_data_init ();
+
+ id = g_hash_table_lookup (object_data_ht, (gpointer) key);
+
+ if (!data)
+ {
+ if (id)
+ {
+ prev = NULL;
+ odata = object->object_data;
+
+ while (odata)
+ {
+ if (odata->id == *id)
+ {
+ if (prev)
+ prev->next = odata->next;
+ if (odata == object->object_data)
+ object->object_data = odata->next;
+
+ gtk_object_data_destroy (odata);
+ break;
+ }
+
+ prev = odata;
+ odata = odata->next;
+ }
+ }
+ }
+ else
+ {
+ if (!id)
+ {
+ id = gtk_object_data_id_alloc ();
+ g_hash_table_insert (object_data_ht, (gpointer) key, id);
+ }
+
+ odata = object->object_data;
+ while (odata)
+ {
+ if (odata->id == *id)
+ {
+ odata->data = data;
+ return;
+ }
+
+ odata = odata->next;
+ }
+
+ odata = gtk_object_data_new ();
+ odata->id = *id;
+ odata->data = data;
+
+ odata->next = object->object_data;
+ object->object_data = odata;
+ }
+}
+
+/*****************************************
+ * gtk_object_get_data:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+gpointer
+gtk_object_get_data (GtkObject *object,
+ const gchar *key)
+{
+ GtkObjectData *odata;
+ guint *id;
+
+ g_return_val_if_fail (object != NULL, NULL);
+ g_return_val_if_fail (GTK_IS_OBJECT (object), NULL);
+ g_return_val_if_fail (key != NULL, NULL);
+
+ if (object_data_init)
+ gtk_object_data_init ();
+
+ id = g_hash_table_lookup (object_data_ht, (gpointer) key);
+ if (id)
+ {
+ odata = object->object_data;
+ while (odata)
+ {
+ if (odata->id == *id)
+ return odata->data;
+ odata = odata->next;
+ }
+ }
+
+ return NULL;
+}
+
+/*****************************************
+ * gtk_object_remove_data:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_object_remove_data (GtkObject *object,
+ const gchar *key)
+{
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_OBJECT (object));
+ g_return_if_fail (key != NULL);
+
+ gtk_object_set_data (object, key, NULL);
+}
+
+/*****************************************
+ * gtk_object_set_user_data:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_object_set_user_data (GtkObject *object,
+ gpointer data)
+{
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_OBJECT (object));
+
+ gtk_object_set_data (object, user_data_key, data);
+}
+
+/*****************************************
+ * gtk_object_get_user_data:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+gpointer
+gtk_object_get_user_data (GtkObject *object)
+{
+ g_return_val_if_fail (object != NULL, NULL);
+ g_return_val_if_fail (GTK_IS_OBJECT (object), NULL);
+
+ return gtk_object_get_data (object, user_data_key);
+}
+
+/*****************************************
+ * gtk_object_check_cast:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+GtkObject*
+gtk_object_check_cast (GtkObject *obj,
+ GtkType cast_type)
+{
+ if (obj && obj->klass && !gtk_type_is_a (obj->klass->type, cast_type))
+ {
+ gchar *from_name = gtk_type_name (obj->klass->type);
+ gchar *to_name = gtk_type_name (cast_type);
+
+ g_warning ("invalid cast from \"%s\" to \"%s\"",
+ from_name ? from_name : "(unknown)",
+ to_name ? to_name : "(unknown)");
+ }
+
+ return obj;
+}
+
+/*****************************************
+ * gtk_object_check_class_cast:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+GtkObjectClass*
+gtk_object_check_class_cast (GtkObjectClass *klass,
+ GtkType cast_type)
+{
+ if (klass && !gtk_type_is_a (klass->type, cast_type))
+ g_warning ("invalid cast from \"%sClass\" to \"%sClass\"",
+ gtk_type_name (klass->type),
+ gtk_type_name (cast_type));
+
+ return klass;
+}
+
+/*****************************************
+ * gtk_real_object_destroy:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+static void
+gtk_real_object_destroy (GtkObject *object)
+{
+ GtkObjectData *odata;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_OBJECT (object));
+
+ gtk_signal_handlers_destroy (object);
+
+ if (object->object_data)
+ {
+ odata = object->object_data;
+ while (odata->next)
+ odata = odata->next;
+
+ odata->next = object_data_free_list;
+ object_data_free_list = object->object_data;
+ }
+
+ g_free (object);
+}
+
+/*****************************************
+ * gtk_object_data_init:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+static void
+gtk_object_data_init ()
+{
+ if (object_data_init)
+ {
+ object_data_init = FALSE;
+
+ object_data_ht = g_hash_table_new (g_string_hash, g_string_equal);
+ }
+}
+
+/*****************************************
+ * gtk_object_data_new:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+static GtkObjectData*
+gtk_object_data_new ()
+{
+ GtkObjectData *odata;
+
+ if (!object_data_mem_chunk)
+ object_data_mem_chunk = g_mem_chunk_new ("object data mem chunk",
+ sizeof (GtkObjectData),
+ 1024, G_ALLOC_AND_FREE);
+
+ odata = g_chunk_new (GtkObjectData, object_data_mem_chunk);
+
+ odata->id = 0;
+ odata->data = NULL;
+ odata->next = NULL;
+
+ return odata;
+}
+
+/*****************************************
+ * gtk_object_data_destroy:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+static void
+gtk_object_data_destroy (GtkObjectData *odata)
+{
+ g_return_if_fail (odata != NULL);
+
+ g_mem_chunk_free (object_data_mem_chunk, odata);
+}
+
+/*****************************************
+ * gtk_object_data_id_alloc:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+static guint*
+gtk_object_data_id_alloc ()
+{
+ static guint next_id = 1;
+ guint *ids;
+
+ if (!object_data_id_list ||
+ (object_data_id_index == OBJECT_DATA_ID_CHUNK))
+ {
+ ids = g_new (guint, OBJECT_DATA_ID_CHUNK);
+ object_data_id_index = 0;
+ object_data_id_list = g_slist_prepend (object_data_id_list, ids);
+ }
+ else
+ {
+ ids = object_data_id_list->data;
+ }
+
+ ids[object_data_id_index] = next_id++;
+ return &ids[object_data_id_index++];
+}
+
+/*****************************************
+ * gtk_object_data_id_alloc:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+GtkArg*
+gtk_object_collect_args (gint *nargs,
+ va_list args1,
+ va_list args2)
+{
+ GtkArg *args;
+ GtkType type;
+ char *name;
+ int done;
+ int i, n;
+
+ n = 0;
+ done = FALSE;
+
+ while (!done)
+ {
+ name = va_arg (args1, char *);
+ if (!name)
+ {
+ done = TRUE;
+ continue;
+ }
+
+ type = gtk_object_get_arg_type (name);
+
+ switch (GTK_FUNDAMENTAL_TYPE (type))
+ {
+ case GTK_TYPE_INVALID:
+ g_print ("invalid arg name: \"%s\" %x\n", name, type);
+ (void) va_arg (args1, long);
+ continue;
+ case GTK_TYPE_NONE:
+ break;
+ case GTK_TYPE_CHAR:
+ case GTK_TYPE_BOOL:
+ case GTK_TYPE_INT:
+ case GTK_TYPE_UINT:
+ case GTK_TYPE_ENUM:
+ case GTK_TYPE_FLAGS:
+ (void) va_arg (args1, gint);
+ break;
+ case GTK_TYPE_LONG:
+ case GTK_TYPE_ULONG:
+ (void) va_arg (args1, glong);
+ break;
+ case GTK_TYPE_FLOAT:
+ (void) va_arg (args1, gfloat);
+ break;
+ case GTK_TYPE_STRING:
+ (void) va_arg (args1, gchar*);
+ break;
+ case GTK_TYPE_POINTER:
+ case GTK_TYPE_BOXED:
+ (void) va_arg (args1, gpointer);
+ break;
+ case GTK_TYPE_SIGNAL:
+ (void) va_arg (args1, GtkFunction);
+ (void) va_arg (args1, gpointer);
+ break;
+ case GTK_TYPE_FOREIGN:
+ (void) va_arg (args1, gpointer);
+ (void) va_arg (args1, GtkDestroyNotify);
+ break;
+ case GTK_TYPE_CALLBACK:
+ (void) va_arg (args1, GtkCallbackMarshal);
+ (void) va_arg (args1, gpointer);
+ (void) va_arg (args1, GtkDestroyNotify);
+ break;
+ case GTK_TYPE_C_CALLBACK:
+ (void) va_arg (args1, GtkFunction);
+ (void) va_arg (args1, gpointer);
+ break;
+ case GTK_TYPE_ARGS:
+ (void) va_arg (args1, gint);
+ (void) va_arg (args1, GtkArg*);
+ break;
+ case GTK_TYPE_OBJECT:
+ (void) va_arg (args1, GtkObject*);
+ break;
+ default:
+ g_error ("unsupported type %s in args", gtk_type_name (type));
+ break;
+ }
+
+ n += 1;
+ }
+
+ *nargs = n;
+ args = NULL;
+
+ if (n > 0)
+ {
+ args = g_new0 (GtkArg, n);
+
+ for (i = 0; i < n; i++)
+ {
+ args[i].name = va_arg (args2, char *);
+ args[i].type = gtk_object_get_arg_type (args[i].name);
+
+ switch (GTK_FUNDAMENTAL_TYPE (args[i].type))
+ {
+ case GTK_TYPE_INVALID:
+ (void) va_arg (args2, long);
+ i -= 1;
+ continue;
+ case GTK_TYPE_NONE:
+ break;
+ case GTK_TYPE_CHAR:
+ GTK_VALUE_CHAR(args[i]) = va_arg (args2, gint);
+ break;
+ case GTK_TYPE_BOOL:
+ GTK_VALUE_BOOL(args[i]) = va_arg (args2, gint);
+ break;
+ case GTK_TYPE_INT:
+ GTK_VALUE_INT(args[i]) = va_arg (args2, gint);
+ break;
+ case GTK_TYPE_UINT:
+ GTK_VALUE_UINT(args[i]) = va_arg (args2, guint);
+ break;
+ case GTK_TYPE_ENUM:
+ GTK_VALUE_ENUM(args[i]) = va_arg (args2, gint);
+ break;
+ case GTK_TYPE_FLAGS:
+ GTK_VALUE_FLAGS(args[i]) = va_arg (args2, gint);
+ break;
+ case GTK_TYPE_LONG:
+ GTK_VALUE_LONG(args[i]) = va_arg (args2, glong);
+ break;
+ case GTK_TYPE_ULONG:
+ GTK_VALUE_ULONG(args[i]) = va_arg (args2, gulong);
+ break;
+ case GTK_TYPE_FLOAT:
+ GTK_VALUE_FLOAT(args[i]) = va_arg (args2, gfloat);
+ break;
+ case GTK_TYPE_STRING:
+ GTK_VALUE_STRING(args[i]) = va_arg (args2, gchar*);
+ break;
+ case GTK_TYPE_POINTER:
+ GTK_VALUE_POINTER(args[i]) = va_arg (args2, gpointer);
+ break;
+ case GTK_TYPE_BOXED:
+ GTK_VALUE_BOXED(args[i]) = va_arg (args2, gpointer);
+ break;
+ case GTK_TYPE_SIGNAL:
+ GTK_VALUE_SIGNAL(args[i]).f = va_arg (args2, GtkFunction);
+ GTK_VALUE_SIGNAL(args[i]).d = va_arg (args2, gpointer);
+ break;
+ case GTK_TYPE_FOREIGN:
+ GTK_VALUE_FOREIGN(args[i]).data = va_arg (args2, gpointer);
+ GTK_VALUE_FOREIGN(args[i]).notify =
+ va_arg (args2, GtkDestroyNotify);
+ break;
+ case GTK_TYPE_CALLBACK:
+ GTK_VALUE_CALLBACK(args[i]).marshal =
+ va_arg (args2, GtkCallbackMarshal);
+ GTK_VALUE_CALLBACK(args[i]).data = va_arg (args2, gpointer);
+ GTK_VALUE_CALLBACK(args[i]).notify =
+ va_arg (args2, GtkDestroyNotify);
+ break;
+ case GTK_TYPE_C_CALLBACK:
+ GTK_VALUE_C_CALLBACK(args[i]).func = va_arg (args2, GtkFunction);
+ GTK_VALUE_C_CALLBACK(args[i]).func_data =
+ va_arg (args2, gpointer);
+ break;
+ case GTK_TYPE_ARGS:
+ GTK_VALUE_ARGS(args[i]).n_args = va_arg (args2, gint);
+ GTK_VALUE_ARGS(args[i]).args = va_arg (args2, GtkArg*);
+ break;
+ case GTK_TYPE_OBJECT:
+ GTK_VALUE_OBJECT(args[i]) = va_arg (args2, GtkObject*);
+ g_assert (GTK_VALUE_OBJECT(args[i]) == NULL ||
+ GTK_CHECK_TYPE (GTK_VALUE_OBJECT(args[i]),
+ args[i].type));
+ break;
+ default:
+ g_error ("unsupported type %s in args",
+ gtk_type_name (args[i].type));
+ break;
+ }
+ }
+ }
+
+ return args;
+}
diff --git a/gtk/gtkobject.h b/gtk/gtkobject.h
new file mode 100644
index 000000000..023bbbf0c
--- /dev/null
+++ b/gtk/gtkobject.h
@@ -0,0 +1,250 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_OBJECT_H__
+#define __GTK_OBJECT_H__
+
+
+#include <gtk/gtkenums.h>
+#include <gtk/gtktypeutils.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* GtkObject only uses the first 3 bits of the "flags" field.
+ * They refer to the following flags.
+ * GtkWidget uses the remaining bits. Though this is a kinda nasty
+ * break up, it does make the size of GtkWidget smaller.
+ */
+enum
+{
+ GTK_NEED_DESTROY = 1 << 0,
+ GTK_BEING_DESTROYED = 1 << 1,
+ GTK_IN_CALL = 1 << 2
+};
+
+
+/* The debugging versions of the casting macros make sure the cast is "ok"
+ * before proceeding, but they are definately slower than their less
+ * careful counterparts as they involve no less than 3 function calls.
+ */
+#ifdef NDEBUG
+
+#define GTK_CHECK_CAST(obj,cast_type,cast) ((cast*) obj)
+#define GTK_CHECK_CLASS_CAST(klass,cast_type,cast) ((cast*) klass)
+
+#else /* NDEBUG */
+
+#define GTK_CHECK_CAST(obj,cast_type,cast) \
+ ((cast*) gtk_object_check_cast ((GtkObject*) obj, cast_type))
+
+#define GTK_CHECK_CLASS_CAST(klass,cast_type,cast) \
+ ((cast*) gtk_object_check_class_cast ((GtkObjectClass*) klass, cast_type))
+
+#endif /* NDEBUG */
+
+
+/* Determines whether 'obj' is a type of 'otype'.
+ */
+#define GTK_CHECK_TYPE(obj,otype) (gtk_type_is_a (((GtkObject*) obj)->klass->type, otype))
+
+
+/* Macro for casting a pointer to a GtkObject pointer.
+ */
+#define GTK_OBJECT(obj) GTK_CHECK_CAST (obj, gtk_object_get_type (), GtkObject)
+
+/* Macros for extracting various fields from GtkObject and
+ * GtkObjectClass.
+ */
+#define GTK_OBJECT_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_object_get_type (), GtkObjectClass)
+#define GTK_OBJECT_FLAGS(obj) (GTK_OBJECT (obj)->flags)
+#define GTK_OBJECT_NEED_DESTROY(obj) (GTK_OBJECT_FLAGS (obj) & GTK_NEED_DESTROY)
+#define GTK_OBJECT_BEING_DESTROYED(obj) (GTK_OBJECT_FLAGS (obj) & GTK_BEING_DESTROYED)
+#define GTK_OBJECT_IN_CALL(obj) (GTK_OBJECT_FLAGS (obj) & GTK_IN_CALL)
+#define GTK_OBJECT_DESTROY(obj) (GTK_OBJECT (obj)->klass->destroy)
+#define GTK_OBJECT_TYPE(obj) (GTK_OBJECT (obj)->klass->type)
+#define GTK_OBJECT_SIGNALS(obj) (GTK_OBJECT (obj)->klass->signals)
+#define GTK_OBJECT_NSIGNALS(obj) (GTK_OBJECT (obj)->klass->signals)
+
+/* Macro for testing whether "obj" is of type GtkObject.
+ */
+#define GTK_IS_OBJECT(obj) GTK_CHECK_TYPE (obj, gtk_object_get_type ())
+
+/* Macros for setting and clearing bits in the "flags" field of GtkObject.
+ */
+#define GTK_OBJECT_SET_FLAGS(obj,flag) (GTK_OBJECT_FLAGS (obj) |= (flag))
+#define GTK_OBJECT_UNSET_FLAGS(obj,flag) (GTK_OBJECT_FLAGS (obj) &= ~(flag))
+
+
+typedef struct _GtkObjectClass GtkObjectClass;
+
+
+/* GtkObject is the base of the object hierarchy. It defines
+ * the few basic items that all derived classes contain.
+ */
+struct _GtkObject
+{
+ /* 32 bits of flags. GtkObject only uses 3 of these bits and
+ * GtkWidget uses the rest. This is done because structs are
+ * aligned on 4 or 8 byte boundaries. If bitfields were used
+ * both here and in GtkWidget much space would be wasted.
+ */
+ guint32 flags;
+
+ /* 16 bit reference count. "gtk_object_destroy" actually only
+ * destroys an object when its ref count is 0. (Decrementing
+ * a reference count of 0 is defined as a no-op).
+ */
+ guint16 ref_count;
+
+ /* A pointer to the objects class. This will actually point to
+ * the derived objects class struct (which will be derived from
+ * GtkObjectClass).
+ */
+ GtkObjectClass *klass;
+
+ /* The list of signal handlers and other data
+ * fields for this object.
+ */
+ gpointer object_data;
+};
+
+/* GtkObjectClass is the base of the class hierarchy. It defines
+ * the basic necessities for the class mechanism to work. Namely,
+ * the "type", "signals" and "nsignals" fields.
+ */
+struct _GtkObjectClass
+{
+ /* The type identifier for the objects class. There is
+ * one unique identifier per class.
+ */
+ guint type;
+
+ /* The signals this object class handles. "signals" is an
+ * array of signal ID's.
+ */
+ gint *signals;
+
+ /* The number of signals listed in "signals".
+ */
+ gint nsignals;
+
+ /* The destroy function for objects. In one way ore another
+ * this is defined for all objects. If an object class overrides
+ * this method in order to perform class specific destruction
+ * then it should still call it after it is finished with its
+ * own cleanup. (See the destroy function for GtkWidget for
+ * an example of how to do this).
+ */
+ void (* destroy) (GtkObject *object);
+};
+
+
+/* Get the type identifier for GtkObject's.
+ */
+guint gtk_object_get_type (void);
+
+/* Append "signals" to those already defined in "class".
+ */
+void gtk_object_class_add_signals (GtkObjectClass *klass,
+ gint *signals,
+ gint nsignals);
+
+void gtk_object_ref (GtkObject *object);
+
+void gtk_object_unref (GtkObject *object);
+
+GtkObject* gtk_object_new (guint type,
+ ...);
+
+GtkObject* gtk_object_newv (guint type,
+ gint nargs,
+ GtkArg *args);
+
+void gtk_object_set (GtkObject *obj,
+ ...);
+
+void gtk_object_setv (GtkObject *obj,
+ gint nargs,
+ GtkArg *args);
+
+void gtk_object_add_arg_type (const char *arg_name,
+ GtkType arg_type);
+
+GtkType gtk_object_get_arg_type (const char *arg_name);
+
+/* Emit the "destroy" signal for "object". Normally it is
+ * permissible to emit a signal for an object instead of
+ * calling the corresponding convenience routine, however
+ * "gtk_object_destroy" should be called instead of emitting
+ * the signal manually as it checks to see if the object is
+ * currently handling another signal emittion (very likely)
+ * and sets the GTK_NEED_DESTROY flag which tells the object
+ * to be destroyed when it is done handling the signal emittion.
+ */
+void gtk_object_destroy (GtkObject *object);
+
+/* Set 'data' to the "object_data" field of the object. The
+ * data is indexed by the "key". If there is already data
+ * associated with "key" then the new data will replace it.
+ * If 'data' is NULL then this call is equivalent to
+ * 'gtk_object_remove_data'.
+ */
+void gtk_object_set_data (GtkObject *object,
+ const gchar *key,
+ gpointer data);
+
+/* Get the data associated with "key".
+ */
+gpointer gtk_object_get_data (GtkObject *object,
+ const gchar *key);
+
+/* Remove the data associated with "key". This call is
+ * equivalent to 'gtk_object_set_data' where 'data' is NULL.
+ */
+void gtk_object_remove_data (GtkObject *object,
+ const gchar *key);
+
+/* Set the "user_data" object data field of "object". It should
+ * be noted that this is no different than calling 'gtk_object_data_add'
+ * with a key of "user_data". It is merely provided as a convenience.
+ */
+void gtk_object_set_user_data (GtkObject *object,
+ gpointer data);
+
+/* Get the "user_data" object data field of "object". It should
+ * be noted that this is no different than calling 'gtk_object_data_find'
+ * with a key of "user_data". It is merely provided as a convenience.
+ */
+gpointer gtk_object_get_user_data (GtkObject *object);
+
+GtkObject* gtk_object_check_cast (GtkObject *obj,
+ GtkType cast_type);
+
+GtkObjectClass* gtk_object_check_class_cast (GtkObjectClass *klass,
+ GtkType cast_type);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_OBJECT_H__ */
diff --git a/gtk/gtkoptionmenu.c b/gtk/gtkoptionmenu.c
new file mode 100644
index 000000000..919aa2669
--- /dev/null
+++ b/gtk/gtkoptionmenu.c
@@ -0,0 +1,584 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtkmenu.h"
+#include "gtkmenuitem.h"
+#include "gtkoptionmenu.h"
+#include "gtksignal.h"
+
+
+#define CHILD_LEFT_SPACING 5
+#define CHILD_RIGHT_SPACING 1
+#define CHILD_TOP_SPACING 1
+#define CHILD_BOTTOM_SPACING 1
+#define OPTION_INDICATOR_WIDTH 12
+#define OPTION_INDICATOR_HEIGHT 8
+#define OPTION_INDICATOR_SPACING 2
+
+
+static void gtk_option_menu_class_init (GtkOptionMenuClass *klass);
+static void gtk_option_menu_init (GtkOptionMenu *option_menu);
+static void gtk_option_menu_destroy (GtkObject *object);
+static void gtk_option_menu_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void gtk_option_menu_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static void gtk_option_menu_paint (GtkWidget *widget,
+ GdkRectangle *area);
+static void gtk_option_menu_draw (GtkWidget *widget,
+ GdkRectangle *area);
+static gint gtk_option_menu_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+static gint gtk_option_menu_button_press (GtkWidget *widget,
+ GdkEventButton *event);
+static void gtk_option_menu_deactivate (GtkMenuShell *menu_shell,
+ GtkOptionMenu *option_menu);
+static void gtk_option_menu_update_contents (GtkOptionMenu *option_menu);
+static void gtk_option_menu_remove_contents (GtkOptionMenu *option_menu);
+static void gtk_option_menu_calc_size (GtkOptionMenu *option_menu);
+static void gtk_option_menu_position (GtkMenu *menu,
+ gint *x,
+ gint *y,
+ gpointer user_data);
+
+
+static GtkButtonClass *parent_class = NULL;
+
+
+guint
+gtk_option_menu_get_type ()
+{
+ static guint option_menu_type = 0;
+
+ if (!option_menu_type)
+ {
+ GtkTypeInfo option_menu_info =
+ {
+ "GtkOptionMenu",
+ sizeof (GtkOptionMenu),
+ sizeof (GtkOptionMenuClass),
+ (GtkClassInitFunc) gtk_option_menu_class_init,
+ (GtkObjectInitFunc) gtk_option_menu_init,
+ (GtkArgFunc) NULL,
+ };
+
+ option_menu_type = gtk_type_unique (gtk_button_get_type (), &option_menu_info);
+ }
+
+ return option_menu_type;
+}
+
+static void
+gtk_option_menu_class_init (GtkOptionMenuClass *class)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+ GtkButtonClass *button_class;
+
+ object_class = (GtkObjectClass*) class;
+ widget_class = (GtkWidgetClass*) class;
+ button_class = (GtkButtonClass*) class;
+
+ parent_class = gtk_type_class (gtk_button_get_type ());
+
+ object_class->destroy = gtk_option_menu_destroy;
+
+ widget_class->draw = gtk_option_menu_draw;
+ widget_class->draw_focus = NULL;
+ widget_class->size_request = gtk_option_menu_size_request;
+ widget_class->size_allocate = gtk_option_menu_size_allocate;
+ widget_class->expose_event = gtk_option_menu_expose;
+ widget_class->button_press_event = gtk_option_menu_button_press;
+}
+
+static void
+gtk_option_menu_init (GtkOptionMenu *option_menu)
+{
+ GTK_WIDGET_UNSET_FLAGS (option_menu, GTK_CAN_FOCUS);
+
+ option_menu->menu = NULL;
+ option_menu->menu_item = NULL;
+ option_menu->width = 0;
+ option_menu->height = 0;
+}
+
+GtkWidget*
+gtk_option_menu_new ()
+{
+ return GTK_WIDGET (gtk_type_new (gtk_option_menu_get_type ()));
+}
+
+GtkWidget*
+gtk_option_menu_get_menu (GtkOptionMenu *option_menu)
+{
+ g_return_val_if_fail (option_menu != NULL, NULL);
+ g_return_val_if_fail (GTK_IS_OPTION_MENU (option_menu), NULL);
+
+ return option_menu->menu;
+}
+
+void
+gtk_option_menu_set_menu (GtkOptionMenu *option_menu,
+ GtkWidget *menu)
+{
+ g_return_if_fail (option_menu != NULL);
+ g_return_if_fail (GTK_IS_OPTION_MENU (option_menu));
+ g_return_if_fail (menu != NULL);
+ g_return_if_fail (GTK_IS_MENU (menu));
+
+ gtk_option_menu_remove_menu (option_menu);
+
+ option_menu->menu = menu;
+ gtk_object_ref (GTK_OBJECT (option_menu->menu));
+
+ gtk_option_menu_calc_size (option_menu);
+
+ gtk_signal_connect (GTK_OBJECT (option_menu->menu), "deactivate",
+ (GtkSignalFunc) gtk_option_menu_deactivate,
+ option_menu);
+
+ if (GTK_WIDGET (option_menu)->parent)
+ gtk_widget_queue_resize (GTK_WIDGET (option_menu));
+
+ gtk_option_menu_update_contents (option_menu);
+}
+
+void
+gtk_option_menu_remove_menu (GtkOptionMenu *option_menu)
+{
+ g_return_if_fail (option_menu != NULL);
+ g_return_if_fail (GTK_IS_OPTION_MENU (option_menu));
+
+ if (option_menu->menu)
+ {
+ gtk_option_menu_remove_contents (option_menu);
+ gtk_signal_disconnect_by_data (GTK_OBJECT (option_menu->menu),
+ option_menu);
+
+ gtk_object_unref (GTK_OBJECT (option_menu->menu));
+ option_menu->menu = NULL;
+ }
+}
+
+void
+gtk_option_menu_set_history (GtkOptionMenu *option_menu,
+ gint index)
+{
+ GtkWidget *menu_item;
+
+ g_return_if_fail (option_menu != NULL);
+ g_return_if_fail (GTK_IS_OPTION_MENU (option_menu));
+
+ if (option_menu->menu)
+ {
+ gtk_menu_set_active (GTK_MENU (option_menu->menu), index);
+ menu_item = gtk_menu_get_active (GTK_MENU (option_menu->menu));
+
+ if (menu_item != option_menu->menu_item)
+ {
+ gtk_option_menu_remove_contents (option_menu);
+ gtk_option_menu_update_contents (option_menu);
+ }
+ }
+}
+
+
+static void
+gtk_option_menu_destroy (GtkObject *object)
+{
+ GtkOptionMenu *option_menu;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_OPTION_MENU (object));
+
+ option_menu = GTK_OPTION_MENU (object);
+
+ gtk_option_menu_remove_contents (option_menu);
+ if (option_menu->menu)
+ {
+ gtk_object_unref (GTK_OBJECT (option_menu->menu));
+ gtk_widget_destroy (option_menu->menu);
+ }
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+static void
+gtk_option_menu_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkOptionMenu *option_menu;
+ gint tmp;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_OPTION_MENU (widget));
+ g_return_if_fail (requisition != NULL);
+
+ option_menu = GTK_OPTION_MENU (widget);
+
+ requisition->width = ((GTK_CONTAINER (widget)->border_width +
+ GTK_WIDGET (widget)->style->klass->xthickness) * 2 +
+ option_menu->width +
+ OPTION_INDICATOR_WIDTH +
+ OPTION_INDICATOR_SPACING * 5 +
+ CHILD_LEFT_SPACING + CHILD_RIGHT_SPACING);
+ requisition->height = ((GTK_CONTAINER (widget)->border_width +
+ GTK_WIDGET (widget)->style->klass->ythickness) * 2 +
+ option_menu->height +
+ CHILD_TOP_SPACING + CHILD_BOTTOM_SPACING);
+
+ tmp = (requisition->height - option_menu->height +
+ OPTION_INDICATOR_HEIGHT + OPTION_INDICATOR_SPACING * 2);
+ requisition->height = MAX (requisition->height, tmp);
+}
+
+static void
+gtk_option_menu_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkWidget *child;
+ GtkAllocation child_allocation;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_OPTION_MENU (widget));
+ g_return_if_fail (allocation != NULL);
+
+ widget->allocation = *allocation;
+ if (GTK_WIDGET_REALIZED (widget))
+ gdk_window_move_resize (widget->window,
+ allocation->x, allocation->y,
+ allocation->width, allocation->height);
+
+ child = GTK_BUTTON (widget)->child;
+ if (child && GTK_WIDGET_VISIBLE (child))
+ {
+ child_allocation.x = (GTK_CONTAINER (widget)->border_width +
+ GTK_WIDGET (widget)->style->klass->xthickness);
+ child_allocation.y = (GTK_CONTAINER (widget)->border_width +
+ GTK_WIDGET (widget)->style->klass->ythickness);
+ child_allocation.width = (allocation->width - child_allocation.x * 2 -
+ OPTION_INDICATOR_WIDTH - OPTION_INDICATOR_SPACING * 5 -
+ CHILD_LEFT_SPACING - CHILD_RIGHT_SPACING);
+ child_allocation.height = (allocation->height - child_allocation.y * 2 -
+ CHILD_TOP_SPACING - CHILD_BOTTOM_SPACING);
+ child_allocation.x += CHILD_LEFT_SPACING;
+ child_allocation.y += CHILD_RIGHT_SPACING;
+
+ gtk_widget_size_allocate (child, &child_allocation);
+ }
+}
+
+static void
+gtk_option_menu_paint (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ GdkRectangle restrict_area;
+ GdkRectangle new_area;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_OPTION_MENU (widget));
+ g_return_if_fail (area != NULL);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ restrict_area.x = GTK_CONTAINER (widget)->border_width;
+ restrict_area.y = GTK_CONTAINER (widget)->border_width;
+ restrict_area.width = widget->allocation.width - restrict_area.x * 2;
+ restrict_area.height = widget->allocation.height - restrict_area.y * 2;
+
+ if (gdk_rectangle_intersect (area, &restrict_area, &new_area))
+ {
+ gtk_style_set_background (widget->style, widget->window, GTK_WIDGET_STATE (widget));
+ gdk_window_clear_area (widget->window,
+ new_area.x, new_area.y,
+ new_area.width, new_area.height);
+
+ gtk_draw_shadow (widget->style, widget->window,
+ GTK_WIDGET_STATE (widget), GTK_SHADOW_OUT,
+ restrict_area.x, restrict_area.y,
+ restrict_area.width, restrict_area.height);
+
+ gtk_draw_shadow (widget->style, widget->window,
+ GTK_WIDGET_STATE (widget), GTK_SHADOW_OUT,
+ restrict_area.x + restrict_area.width - restrict_area.x -
+ OPTION_INDICATOR_WIDTH - OPTION_INDICATOR_SPACING * 4,
+ restrict_area.y + (restrict_area.height - OPTION_INDICATOR_HEIGHT) / 2,
+ OPTION_INDICATOR_WIDTH, OPTION_INDICATOR_HEIGHT);
+ }
+ }
+}
+
+static void
+gtk_option_menu_draw (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ GtkWidget *child;
+ GdkRectangle child_area;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_OPTION_MENU (widget));
+ g_return_if_fail (area != NULL);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ gtk_option_menu_paint (widget, area);
+
+ child = GTK_BUTTON (widget)->child;
+ if (child && gtk_widget_intersect (child, area, &child_area))
+ gtk_widget_draw (child, &child_area);
+ }
+}
+
+static gint
+gtk_option_menu_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ GtkWidget *child;
+ GdkEventExpose child_event;
+ gint remove_child;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_OPTION_MENU (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ gtk_option_menu_paint (widget, &event->area);
+
+ remove_child = FALSE;
+ child = GTK_BUTTON (widget)->child;
+
+ if (!child)
+ {
+ if (!GTK_OPTION_MENU (widget)->menu)
+ return FALSE;
+ gtk_option_menu_update_contents (GTK_OPTION_MENU (widget));
+ child = GTK_BUTTON (widget)->child;
+ if (!child)
+ return FALSE;
+ remove_child = TRUE;
+ }
+
+ child_event = *event;
+
+ if (GTK_WIDGET_NO_WINDOW (child) &&
+ gtk_widget_intersect (child, &event->area, &child_event.area))
+ gtk_widget_event (child, (GdkEvent*) &child_event);
+
+ if (remove_child)
+ gtk_option_menu_remove_contents (GTK_OPTION_MENU (widget));
+ }
+
+ return FALSE;
+}
+
+static gint
+gtk_option_menu_button_press (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ GtkOptionMenu *option_menu;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_OPTION_MENU (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if ((event->type == GDK_BUTTON_PRESS) &&
+ (event->button == 1))
+ {
+ option_menu = GTK_OPTION_MENU (widget);
+ gtk_option_menu_remove_contents (option_menu);
+ gtk_menu_popup (GTK_MENU (option_menu->menu), NULL, NULL,
+ gtk_option_menu_position, option_menu,
+ event->button, event->time);
+ }
+
+ return FALSE;
+}
+
+static void
+gtk_option_menu_deactivate (GtkMenuShell *menu_shell,
+ GtkOptionMenu *option_menu)
+{
+ g_return_if_fail (menu_shell != NULL);
+ g_return_if_fail (option_menu != NULL);
+ g_return_if_fail (GTK_IS_OPTION_MENU (option_menu));
+
+ gtk_option_menu_update_contents (option_menu);
+}
+
+static void
+gtk_option_menu_update_contents (GtkOptionMenu *option_menu)
+{
+ GtkWidget *child;
+
+ g_return_if_fail (option_menu != NULL);
+ g_return_if_fail (GTK_IS_OPTION_MENU (option_menu));
+
+ if (option_menu->menu)
+ {
+ gtk_option_menu_remove_contents (option_menu);
+
+ option_menu->menu_item = gtk_menu_get_active (GTK_MENU (option_menu->menu));
+ if (option_menu->menu_item)
+ {
+ child = GTK_BIN (option_menu->menu_item)->child;
+ if (child)
+ {
+ gtk_container_block_resize (GTK_CONTAINER (option_menu));
+ if (GTK_WIDGET (option_menu)->state != child->state)
+ gtk_widget_set_state (child, GTK_WIDGET (option_menu)->state);
+ gtk_widget_reparent (child, GTK_WIDGET (option_menu));
+ gtk_container_unblock_resize (GTK_CONTAINER (option_menu));
+ }
+
+ gtk_widget_size_allocate (GTK_WIDGET (option_menu),
+ &(GTK_WIDGET (option_menu)->allocation));
+
+ if (GTK_WIDGET_DRAWABLE (option_menu))
+ gtk_widget_queue_draw (GTK_WIDGET (option_menu));
+ }
+ }
+}
+
+static void
+gtk_option_menu_remove_contents (GtkOptionMenu *option_menu)
+{
+ g_return_if_fail (option_menu != NULL);
+ g_return_if_fail (GTK_IS_OPTION_MENU (option_menu));
+
+ if (GTK_BUTTON (option_menu)->child)
+ {
+ gtk_container_block_resize (GTK_CONTAINER (option_menu));
+ if (GTK_WIDGET (option_menu->menu_item)->state != GTK_BUTTON (option_menu)->child->state)
+ gtk_widget_set_state (GTK_BUTTON (option_menu)->child,
+ GTK_WIDGET (option_menu->menu_item)->state);
+ GTK_WIDGET_UNSET_FLAGS (GTK_BUTTON (option_menu)->child, GTK_MAPPED | GTK_REALIZED);
+ gtk_widget_reparent (GTK_BUTTON (option_menu)->child, option_menu->menu_item);
+ gtk_container_unblock_resize (GTK_CONTAINER (option_menu));
+ option_menu->menu_item = NULL;
+ }
+}
+
+static void
+gtk_option_menu_calc_size (GtkOptionMenu *option_menu)
+{
+ GtkWidget *child;
+ GList *children;
+
+ g_return_if_fail (option_menu != NULL);
+ g_return_if_fail (GTK_IS_OPTION_MENU (option_menu));
+
+ option_menu->width = 0;
+ option_menu->height = 0;
+
+ if (option_menu->menu)
+ {
+ children = GTK_MENU_SHELL (option_menu->menu)->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_VISIBLE (child))
+ {
+ gtk_widget_size_request (child, &child->requisition);
+
+ option_menu->width = MAX (option_menu->width, child->requisition.width);
+ option_menu->height = MAX (option_menu->height, child->requisition.height);
+ }
+ }
+ }
+}
+
+static void
+gtk_option_menu_position (GtkMenu *menu,
+ gint *x,
+ gint *y,
+ gpointer user_data)
+{
+ GtkOptionMenu *option_menu;
+ GtkWidget *active;
+ GtkWidget *child;
+ GList *children;
+ gint shift_menu;
+ gint screen_width;
+ gint screen_height;
+ gint menu_xpos;
+ gint menu_ypos;
+ gint width;
+ gint height;
+
+ g_return_if_fail (user_data != NULL);
+ g_return_if_fail (GTK_IS_OPTION_MENU (user_data));
+
+ option_menu = GTK_OPTION_MENU (user_data);
+
+ width = GTK_WIDGET (menu)->allocation.width;
+ height = GTK_WIDGET (menu)->allocation.height;
+
+ active = gtk_menu_get_active (GTK_MENU (option_menu->menu));
+ children = GTK_MENU_SHELL (option_menu->menu)->children;
+ gdk_window_get_origin (GTK_WIDGET (option_menu)->window, &menu_xpos, &menu_ypos);
+
+ menu_ypos += GTK_WIDGET (option_menu)->allocation.height / 2 - 2;
+
+ if (active != NULL)
+ menu_ypos -= active->requisition.height / 2;
+
+ while (children)
+ {
+ child = children->data;
+
+ if (active == child)
+ break;
+
+ menu_ypos -= child->allocation.height;
+ children = children->next;
+ }
+
+ screen_width = gdk_screen_width ();
+ screen_height = gdk_screen_height ();
+
+ shift_menu = FALSE;
+ if (menu_ypos < 0)
+ {
+ menu_ypos = 0;
+ shift_menu = TRUE;
+ }
+ else if ((menu_ypos + height) > screen_height)
+ {
+ menu_ypos -= ((menu_ypos + height) - screen_height);
+ shift_menu = TRUE;
+ }
+
+ if (shift_menu)
+ {
+ if ((menu_xpos + GTK_WIDGET (option_menu)->allocation.width + width) <= screen_width)
+ menu_xpos += GTK_WIDGET (option_menu)->allocation.width;
+ else
+ menu_xpos -= width;
+ }
+
+ if (menu_xpos < 0)
+ menu_xpos = 0;
+ else if ((menu_xpos + width) > screen_width)
+ menu_xpos -= ((menu_xpos + width) - screen_width);
+
+ *x = menu_xpos;
+ *y = menu_ypos;
+}
diff --git a/gtk/gtkoptionmenu.h b/gtk/gtkoptionmenu.h
new file mode 100644
index 000000000..bbddf2309
--- /dev/null
+++ b/gtk/gtkoptionmenu.h
@@ -0,0 +1,71 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_OPTION_MENU_H__
+#define __GTK_OPTION_MENU_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkbutton.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_OPTION_MENU(obj) GTK_CHECK_CAST (obj, gtk_option_menu_get_type (), GtkOptionMenu)
+#define GTK_OPTION_MENU_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_option_menu_get_type (), GtkOptionMenuClass)
+#define GTK_IS_OPTION_MENU(obj) GTK_CHECK_TYPE (obj, gtk_option_menu_get_type ())
+
+
+typedef struct _GtkOptionMenu GtkOptionMenu;
+typedef struct _GtkOptionMenuClass GtkOptionMenuClass;
+
+struct _GtkOptionMenu
+{
+ GtkButton button;
+
+ GtkWidget *menu;
+ GtkWidget *menu_item;
+
+ guint16 width;
+ guint16 height;
+};
+
+struct _GtkOptionMenuClass
+{
+ GtkButtonClass parent_class;
+};
+
+
+guint gtk_option_menu_get_type (void);
+GtkWidget* gtk_option_menu_new (void);
+GtkWidget* gtk_option_menu_get_menu (GtkOptionMenu *option_menu);
+void gtk_option_menu_set_menu (GtkOptionMenu *option_menu,
+ GtkWidget *menu);
+void gtk_option_menu_remove_menu (GtkOptionMenu *option_menu);
+void gtk_option_menu_set_history (GtkOptionMenu *option_menu,
+ gint index);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_OPTION_MENU_H__ */
diff --git a/gtk/gtkpaned.c b/gtk/gtkpaned.c
new file mode 100644
index 000000000..d6b53db3d
--- /dev/null
+++ b/gtk/gtkpaned.c
@@ -0,0 +1,452 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtkpaned.h"
+
+
+static void gtk_paned_class_init (GtkPanedClass *klass);
+static void gtk_paned_init (GtkPaned *paned);
+static void gtk_paned_destroy (GtkObject *object);
+static void gtk_paned_realize (GtkWidget *widget);
+static void gtk_paned_map (GtkWidget *widget);
+static void gtk_paned_unmap (GtkWidget *widget);
+static void gtk_paned_unrealize (GtkWidget *widget);
+static gint gtk_paned_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+static void gtk_paned_add (GtkContainer *container,
+ GtkWidget *widget);
+static void gtk_paned_remove (GtkContainer *container,
+ GtkWidget *widget);
+static void gtk_paned_foreach (GtkContainer *container,
+ GtkCallback callback,
+ gpointer callback_data);
+
+
+static GtkContainerClass *parent_class = NULL;
+
+
+guint
+gtk_paned_get_type ()
+{
+ static guint paned_type = 0;
+
+ if (!paned_type)
+ {
+ GtkTypeInfo paned_info =
+ {
+ "GtkPaned",
+ sizeof (GtkPaned),
+ sizeof (GtkPanedClass),
+ (GtkClassInitFunc) gtk_paned_class_init,
+ (GtkObjectInitFunc) gtk_paned_init,
+ (GtkArgFunc) NULL,
+ };
+
+ paned_type = gtk_type_unique (gtk_container_get_type (), &paned_info);
+ }
+
+ return paned_type;
+}
+
+static void
+gtk_paned_class_init (GtkPanedClass *class)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+ GtkContainerClass *container_class;
+
+ object_class = (GtkObjectClass*) class;
+ widget_class = (GtkWidgetClass*) class;
+ container_class = (GtkContainerClass*) class;
+
+ parent_class = gtk_type_class (gtk_container_get_type ());
+
+ object_class->destroy = gtk_paned_destroy;
+
+ widget_class->realize = gtk_paned_realize;
+ widget_class->map = gtk_paned_map;
+ widget_class->unmap = gtk_paned_unmap;
+ widget_class->unrealize = gtk_paned_unrealize;
+ widget_class->expose_event = gtk_paned_expose;
+
+ container_class->add = gtk_paned_add;
+ container_class->remove = gtk_paned_remove;
+ container_class->foreach = gtk_paned_foreach;
+}
+
+static void
+gtk_paned_init (GtkPaned *paned)
+{
+ GTK_WIDGET_SET_FLAGS (paned, GTK_NO_WINDOW);
+
+ paned->child1 = NULL;
+ paned->child2 = NULL;
+ paned->handle = NULL;
+ paned->xor_gc = NULL;
+
+ paned->handle_size = 10;
+ paned->gutter_size = 6;
+ paned->position_set = FALSE;
+ paned->in_drag = FALSE;
+
+ paned->handle_xpos = -1;
+ paned->handle_ypos = -1;
+}
+
+
+static void
+gtk_paned_destroy (GtkObject *object)
+{
+ GtkPaned *paned;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_PANED (object));
+
+ paned = GTK_PANED (object);
+
+ if (paned->child1)
+ {
+ paned->child1->parent = NULL;
+ gtk_object_unref (GTK_OBJECT (paned->child1));
+ gtk_widget_destroy (paned->child1);
+ }
+ if (paned->child2)
+ {
+ paned->child2->parent = NULL;
+ gtk_object_unref (GTK_OBJECT (paned->child2));
+ gtk_widget_destroy (paned->child2);
+ }
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+static void
+gtk_paned_realize (GtkWidget *widget)
+{
+ GtkPaned *paned;
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_PANED (widget));
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+ paned = GTK_PANED (widget);
+
+ attributes.x = paned->handle_xpos;
+ attributes.y = paned->handle_ypos;
+ attributes.width = paned->handle_size;
+ attributes.height = paned->handle_size;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
+ attributes.cursor = gdk_cursor_new(GDK_CROSS);
+ attributes.event_mask = gtk_widget_get_events (widget);
+ attributes.event_mask |= (GDK_EXPOSURE_MASK |
+ GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_POINTER_MOTION_MASK |
+ GDK_POINTER_MOTION_HINT_MASK);
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP |
+ GDK_WA_CURSOR;
+
+ paned->handle = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
+ gdk_window_set_user_data (paned->handle, widget);
+ gdk_window_show (paned->handle);
+ gdk_window_raise (paned->handle);
+
+ widget->window = widget->parent->window;
+ widget->style = gtk_style_attach (widget->style, widget->window);
+
+ gtk_style_set_background (widget->style, paned->handle, GTK_STATE_NORMAL);
+}
+
+static void
+gtk_paned_map (GtkWidget *widget)
+{
+ GtkPaned *paned;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_PANED (widget));
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
+ paned = GTK_PANED (widget);
+
+ gdk_window_show (paned->handle);
+ gtk_widget_queue_draw (widget);
+
+ if (paned->child1 &&
+ GTK_WIDGET_VISIBLE (paned->child1) &&
+ !GTK_WIDGET_MAPPED (paned->child1))
+ gtk_widget_map (paned->child1);
+ if (paned->child2 &&
+ GTK_WIDGET_VISIBLE (paned->child2) &&
+ !GTK_WIDGET_MAPPED (paned->child2))
+ gtk_widget_map (paned->child2);
+}
+
+static void
+gtk_paned_unmap (GtkWidget *widget)
+{
+ GtkPaned *paned;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_PANED (widget));
+
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
+ paned = GTK_PANED (widget);
+
+ gdk_window_clear_area (widget->window,
+ widget->allocation.x,
+ widget->allocation.y,
+ widget->allocation.width,
+ widget->allocation.height);
+ gdk_window_hide (paned->handle);
+
+ if (paned->child1 &&
+ GTK_WIDGET_VISIBLE (paned->child1) &&
+ GTK_WIDGET_MAPPED (paned->child1))
+ gtk_widget_unmap (paned->child1);
+ if (paned->child2 &&
+ GTK_WIDGET_VISIBLE (paned->child2) &&
+ GTK_WIDGET_MAPPED (paned->child2))
+ gtk_widget_unmap (paned->child2);
+}
+
+static void
+gtk_paned_unrealize (GtkWidget *widget)
+{
+ GtkPaned *paned;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_PANED (widget));
+
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_REALIZED);
+ paned = GTK_PANED (widget);
+
+ gtk_style_detach (widget->style);
+
+ if (paned->xor_gc)
+ gdk_gc_destroy (paned->xor_gc);
+ if (paned->handle)
+ gdk_window_destroy (paned->handle);
+
+ paned->handle = NULL;
+ widget->window = NULL;
+}
+
+static gint
+gtk_paned_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ GtkPaned *paned;
+ GdkEventExpose child_event;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_PANED (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ paned = GTK_PANED (widget);
+
+ /* An expose event for the handle */
+ if (event->window == paned->handle)
+ {
+ gdk_window_set_background (paned->handle,
+ &widget->style->bg[widget->state]);
+ gdk_window_clear (paned->handle);
+ gtk_draw_shadow (widget->style, paned->handle,
+ GTK_WIDGET_STATE(widget),
+ GTK_SHADOW_OUT, 0, 0,
+ paned->handle_size, paned->handle_size);
+ }
+ else
+ {
+ child_event = *event;
+ if (paned->child1 &&
+ GTK_WIDGET_NO_WINDOW (paned->child1) &&
+ gtk_widget_intersect (paned->child1, &event->area, &child_event.area))
+ gtk_widget_event (paned->child1, (GdkEvent*) &child_event);
+
+ if (paned->child2 &&
+ GTK_WIDGET_NO_WINDOW (paned->child2) &&
+ gtk_widget_intersect (paned->child2, &event->area, &child_event.area))
+ gtk_widget_event (paned->child2, (GdkEvent*) &child_event);
+
+ /* redraw the groove if necessary */
+ child_event.area = paned->groove_rectangle;
+ if (gtk_widget_intersect (widget, &event->area, &child_event.area))
+ gtk_widget_draw (widget, &child_event.area);
+ }
+ }
+ return FALSE;
+}
+
+void
+gtk_paned_add1 (GtkPaned *paned,
+ GtkWidget *widget)
+{
+ g_return_if_fail (widget != NULL);
+
+ if (!paned->child1)
+ {
+ gtk_widget_set_parent (widget, GTK_WIDGET (paned));
+
+ if (GTK_WIDGET_VISIBLE (widget->parent))
+ {
+ if (GTK_WIDGET_REALIZED (widget->parent) &&
+ !GTK_WIDGET_REALIZED (widget))
+ gtk_widget_realize (widget);
+
+ if (GTK_WIDGET_MAPPED (widget->parent) &&
+ !GTK_WIDGET_MAPPED (widget))
+ gtk_widget_map (widget);
+ }
+
+ paned->child1 = widget;
+
+ if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (paned))
+ gtk_widget_queue_resize (widget);
+ }
+}
+
+void
+gtk_paned_add2 (GtkPaned *paned,
+ GtkWidget *widget)
+{
+ g_return_if_fail (widget != NULL);
+
+ if (!paned->child2)
+ {
+ gtk_widget_set_parent (widget, GTK_WIDGET (paned));
+
+ if (GTK_WIDGET_VISIBLE (widget->parent))
+ {
+ if (GTK_WIDGET_REALIZED (widget->parent) &&
+ !GTK_WIDGET_REALIZED (widget))
+ gtk_widget_realize (widget);
+
+ if (GTK_WIDGET_MAPPED (widget->parent) &&
+ !GTK_WIDGET_MAPPED (widget))
+ gtk_widget_map (widget);
+ }
+
+ paned->child2 = widget;
+
+ if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (paned))
+ gtk_widget_queue_resize (widget);
+ }
+}
+
+static void
+gtk_paned_add (GtkContainer *container,
+ GtkWidget *widget)
+{
+ GtkPaned *paned;
+
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_PANED (container));
+ g_return_if_fail (widget != NULL);
+
+ paned = GTK_PANED (container);
+
+ if (!paned->child1)
+ gtk_paned_add1 (GTK_PANED (container),widget);
+ else if (!paned->child2)
+ gtk_paned_add2 (GTK_PANED (container),widget);
+}
+
+static void
+gtk_paned_remove (GtkContainer *container,
+ GtkWidget *widget)
+{
+ GtkPaned *paned;
+
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_PANED (container));
+ g_return_if_fail (widget != NULL);
+
+ paned = GTK_PANED (container);
+
+ if (paned->child1 == widget)
+ {
+ gtk_widget_unparent (widget);
+
+ paned->child1 = NULL;
+
+ if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (container))
+ gtk_widget_queue_resize (GTK_WIDGET (container));
+ }
+ else if (paned->child2 == widget)
+ {
+ gtk_widget_unparent (widget);
+
+ paned->child2 = NULL;
+
+ if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (container))
+ gtk_widget_queue_resize (GTK_WIDGET (container));
+ }
+}
+
+static void
+gtk_paned_foreach (GtkContainer *container,
+ GtkCallback callback,
+ gpointer callback_data)
+{
+ GtkPaned *paned;
+
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_PANED (container));
+ g_return_if_fail (callback != NULL);
+
+ paned = GTK_PANED (container);
+
+ if (paned->child1)
+ (* callback) (paned->child1, callback_data);
+ if (paned->child2)
+ (* callback) (paned->child2, callback_data);
+}
+
+void
+gtk_paned_handle_size (GtkPaned *paned, guint16 size)
+{
+ gint x,y;
+
+ if (paned->handle)
+ {
+ gdk_window_get_geometry (paned->handle, &x, &y, NULL, NULL, NULL);
+ gdk_window_move_resize (paned->handle,
+ x + paned->handle_size / 2 - size / 2,
+ y + paned->handle_size / 2 - size / 2,
+ size, size);
+ }
+
+ paned->handle_size = size;
+}
+
+void
+gtk_paned_gutter_size (GtkPaned *paned, guint16 size)
+{
+ paned->gutter_size = size;
+
+ if (GTK_WIDGET_VISIBLE (GTK_WIDGET (paned)))
+ gtk_widget_queue_resize (GTK_WIDGET (paned));
+}
diff --git a/gtk/gtkpaned.h b/gtk/gtkpaned.h
new file mode 100644
index 000000000..1b25263b0
--- /dev/null
+++ b/gtk/gtkpaned.h
@@ -0,0 +1,78 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_PANED_H__
+#define __GTK_PANED_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkcontainer.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_PANED(obj) GTK_CHECK_CAST (obj, gtk_paned_get_type (), GtkPaned)
+#define GTK_PANED_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_paned_get_type (), GtkPanedClass)
+#define GTK_IS_PANED(obj) GTK_CHECK_TYPE (obj, gtk_paned_get_type ())
+
+
+typedef struct _GtkPaned GtkPaned;
+typedef struct _GtkPanedClass GtkPanedClass;
+
+struct _GtkPaned
+{
+ GtkContainer container;
+
+ GtkWidget *child1;
+ GtkWidget *child2;
+
+ GdkWindow *handle;
+ GdkRectangle groove_rectangle;
+ GdkGC *xor_gc;
+
+ guint16 handle_size;
+ guint16 gutter_size;
+
+ gint child1_size;
+ guint position_set : 1;
+ guint in_drag : 1;
+
+ gint16 handle_xpos;
+ gint16 handle_ypos;
+};
+
+struct _GtkPanedClass
+{
+ GtkContainerClass parent_class;
+};
+
+
+guint gtk_paned_get_type (void);
+void gtk_paned_add1 (GtkPaned *paned, GtkWidget *child);
+void gtk_paned_add2 (GtkPaned *paned, GtkWidget *child);
+void gtk_paned_handle_size (GtkPaned *paned, guint16 size);
+void gtk_paned_gutter_size (GtkPaned *paned, guint16 size);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_PANED_H__ */
diff --git a/gtk/gtkpixmap.c b/gtk/gtkpixmap.c
new file mode 100644
index 000000000..ae640f81f
--- /dev/null
+++ b/gtk/gtkpixmap.c
@@ -0,0 +1,176 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtkcontainer.h"
+#include "gtkpixmap.h"
+
+
+static void gtk_pixmap_class_init (GtkPixmapClass *klass);
+static void gtk_pixmap_init (GtkPixmap *pixmap);
+static gint gtk_pixmap_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+
+
+guint
+gtk_pixmap_get_type ()
+{
+ static guint pixmap_type = 0;
+
+ if (!pixmap_type)
+ {
+ GtkTypeInfo pixmap_info =
+ {
+ "GtkPixmap",
+ sizeof (GtkPixmap),
+ sizeof (GtkPixmapClass),
+ (GtkClassInitFunc) gtk_pixmap_class_init,
+ (GtkObjectInitFunc) gtk_pixmap_init,
+ (GtkArgFunc) NULL,
+ };
+
+ pixmap_type = gtk_type_unique (gtk_misc_get_type (), &pixmap_info);
+ }
+
+ return pixmap_type;
+}
+
+static void
+gtk_pixmap_class_init (GtkPixmapClass *class)
+{
+ GtkWidgetClass *widget_class;
+
+ widget_class = (GtkWidgetClass*) class;
+
+ widget_class->expose_event = gtk_pixmap_expose;
+}
+
+static void
+gtk_pixmap_init (GtkPixmap *pixmap)
+{
+ GTK_WIDGET_SET_FLAGS (pixmap, GTK_NO_WINDOW);
+
+ pixmap->pixmap = NULL;
+ pixmap->mask = NULL;
+}
+
+GtkWidget*
+gtk_pixmap_new (GdkPixmap *val,
+ GdkBitmap *mask)
+{
+ GtkPixmap *pixmap;
+
+ g_return_val_if_fail (val != NULL, NULL);
+
+ pixmap = gtk_type_new (gtk_pixmap_get_type ());
+
+ gtk_pixmap_set (pixmap, val, mask);
+
+ return GTK_WIDGET (pixmap);
+}
+
+void
+gtk_pixmap_set (GtkPixmap *pixmap,
+ GdkPixmap *val,
+ GdkBitmap *mask)
+{
+ gint width;
+ gint height;
+
+ g_return_if_fail (pixmap != NULL);
+ g_return_if_fail (GTK_IS_PIXMAP (pixmap));
+ g_return_if_fail (val != NULL);
+
+ pixmap->pixmap = val;
+ pixmap->mask = mask;
+
+ if (pixmap->pixmap)
+ {
+ gdk_window_get_size (pixmap->pixmap, &width, &height);
+ GTK_WIDGET (pixmap)->requisition.width = width + GTK_MISC (pixmap)->xpad * 2;
+ GTK_WIDGET (pixmap)->requisition.height = height + GTK_MISC (pixmap)->ypad * 2;
+ }
+ else
+ {
+ GTK_WIDGET (pixmap)->requisition.width = 0;
+ GTK_WIDGET (pixmap)->requisition.height = 0;
+ }
+
+ if (GTK_WIDGET_VISIBLE (pixmap))
+ gtk_widget_queue_resize (GTK_WIDGET (pixmap));
+}
+
+void
+gtk_pixmap_get (GtkPixmap *pixmap,
+ GdkPixmap **val,
+ GdkBitmap **mask)
+{
+ g_return_if_fail (pixmap != NULL);
+ g_return_if_fail (GTK_IS_PIXMAP (pixmap));
+
+ if (val)
+ *val = pixmap->pixmap;
+ if (mask)
+ *mask = pixmap->mask;
+}
+
+
+static gint
+gtk_pixmap_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ GtkPixmap *pixmap;
+ GtkMisc *misc;
+ gint x, y;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_PIXMAP (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ pixmap = GTK_PIXMAP (widget);
+ misc = GTK_MISC (widget);
+
+ x = (widget->allocation.x * (1.0 - misc->xalign) +
+ (widget->allocation.x + widget->allocation.width
+ - (widget->requisition.width - misc->xpad * 2)) *
+ misc->xalign) + 0.5;
+ y = (widget->allocation.y * (1.0 - misc->yalign) +
+ (widget->allocation.y + widget->allocation.height
+ - (widget->requisition.height - misc->ypad * 2)) *
+ misc->yalign) + 0.5;
+
+ if (pixmap->mask)
+ {
+ gdk_gc_set_clip_mask (widget->style->black_gc, pixmap->mask);
+ gdk_gc_set_clip_origin (widget->style->black_gc, x, y);
+ }
+
+ gdk_draw_pixmap (widget->window,
+ widget->style->black_gc,
+ pixmap->pixmap,
+ 0, 0, x, y, -1, -1);
+
+ if (pixmap->mask)
+ {
+ gdk_gc_set_clip_mask (widget->style->black_gc, NULL);
+ gdk_gc_set_clip_origin (widget->style->black_gc, 0, 0);
+ }
+ }
+
+ return FALSE;
+}
diff --git a/gtk/gtkpixmap.h b/gtk/gtkpixmap.h
new file mode 100644
index 000000000..970d4f40f
--- /dev/null
+++ b/gtk/gtkpixmap.h
@@ -0,0 +1,69 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_PIXMAP_H__
+#define __GTK_PIXMAP_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkmisc.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_PIXMAP(obj) GTK_CHECK_CAST (obj, gtk_pixmap_get_type (), GtkPixmap)
+#define GTK_PIXMAP_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_pixmap_get_type (), GtkPixmapClass)
+#define GTK_IS_PIXMAP(obj) GTK_CHECK_TYPE (obj, gtk_pixmap_get_type ())
+
+
+typedef struct _GtkPixmap GtkPixmap;
+typedef struct _GtkPixmapClass GtkPixmapClass;
+
+struct _GtkPixmap
+{
+ GtkMisc misc;
+
+ GdkPixmap *pixmap;
+ GdkBitmap *mask;
+};
+
+struct _GtkPixmapClass
+{
+ GtkMiscClass parent_class;
+};
+
+
+guint gtk_pixmap_get_type (void);
+GtkWidget* gtk_pixmap_new (GdkPixmap *pixmap,
+ GdkBitmap *mask);
+void gtk_pixmap_set (GtkPixmap *pixmap,
+ GdkPixmap *val,
+ GdkBitmap *mask);
+void gtk_pixmap_get (GtkPixmap *pixmap,
+ GdkPixmap **val,
+ GdkBitmap **mask);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_PIXMAP_H__ */
diff --git a/gtk/gtkpreview.c b/gtk/gtkpreview.c
new file mode 100644
index 000000000..4246a321a
--- /dev/null
+++ b/gtk/gtkpreview.c
@@ -0,0 +1,1571 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <math.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include "gdk/gdkx.h"
+#include "gtkpreview.h"
+#include "gtksignal.h"
+
+
+#define IMAGE_SIZE 256
+#define PREVIEW_CLASS(w) GTK_PREVIEW_CLASS (GTK_OBJECT (w)->klass)
+#define COLOR_COMPOSE(r,g,b) (lookup_red[r] | lookup_green[g] | lookup_blue[b])
+
+
+typedef struct _GtkPreviewProp GtkPreviewProp;
+typedef void (*GtkTransferFunc) (guchar *dest, guchar *src, gint count);
+
+struct _GtkPreviewProp
+{
+ guint16 ref_count;
+ guint16 nred_shades;
+ guint16 ngreen_shades;
+ guint16 nblue_shades;
+ guint16 ngray_shades;
+};
+
+
+static void gtk_preview_class_init (GtkPreviewClass *klass);
+static void gtk_preview_init (GtkPreview *preview);
+static void gtk_preview_destroy (GtkObject *object);
+static void gtk_preview_realize (GtkWidget *widget);
+static void gtk_preview_unrealize (GtkWidget *widget);
+static gint gtk_preview_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+static void gtk_preview_make_buffer (GtkPreview *preview);
+static void gtk_preview_get_visuals (GtkPreviewClass *klass);
+static void gtk_preview_get_cmaps (GtkPreviewClass *klass);
+static void gtk_preview_dither_init (GtkPreviewClass *klass);
+static void gtk_fill_lookup_array (gulong *array,
+ int depth,
+ int shift,
+ int prec);
+static void gtk_trim_cmap (GtkPreviewClass *klass);
+static void gtk_create_8_bit (GtkPreviewClass *klass);
+
+static void gtk_color_8 (guchar *src,
+ guchar *data,
+ gint x,
+ gint y,
+ gulong width);
+static void gtk_color_16 (guchar *src,
+ guchar *data,
+ gulong width);
+static void gtk_color_24 (guchar *src,
+ guchar *data,
+ gulong width);
+static void gtk_grayscale_8 (guchar *src,
+ guchar *data,
+ gint x,
+ gint y,
+ gulong width);
+static void gtk_grayscale_16 (guchar *src,
+ guchar *data,
+ gulong width);
+static void gtk_grayscale_24 (guchar *src,
+ guchar *data,
+ gulong width);
+
+static gint gtk_get_preview_prop (guint *nred,
+ guint *nblue,
+ guint *ngreen,
+ guint *ngray);
+static void gtk_set_preview_prop (guint nred,
+ guint ngreen,
+ guint nblue,
+ guint ngray);
+
+/* transfer functions:
+ * destination byte order/source bpp/destination bpp
+ */
+static void gtk_lsbmsb_1_1 (guchar *dest,
+ guchar *src,
+ gint count);
+static void gtk_lsb_2_2 (guchar *dest,
+ guchar *src,
+ gint count);
+static void gtk_msb_2_2 (guchar *dest,
+ guchar *src,
+ gint count);
+static void gtk_lsb_3_3 (guchar *dest,
+ guchar *src,
+ gint count);
+static void gtk_msb_3_3 (guchar *dest,
+ guchar *src,
+ gint count);
+static void gtk_lsb_3_4 (guchar *dest,
+ guchar *src,
+ gint count);
+static void gtk_msb_3_4 (guchar *dest,
+ guchar *src,
+ gint count);
+
+
+static GtkWidgetClass *parent_class = NULL;
+static GtkPreviewClass *preview_class = NULL;
+static GtkPreviewInfo *preview_info = NULL;
+static gint install_cmap = FALSE;
+
+
+guint
+gtk_preview_get_type ()
+{
+ static guint preview_type = 0;
+
+ if (!preview_type)
+ {
+ GtkTypeInfo preview_info =
+ {
+ "GtkPreview",
+ sizeof (GtkPreview),
+ sizeof (GtkPreviewClass),
+ (GtkClassInitFunc) gtk_preview_class_init,
+ (GtkObjectInitFunc) gtk_preview_init,
+ (GtkArgFunc) NULL,
+ };
+
+ preview_type = gtk_type_unique (gtk_widget_get_type (), &preview_info);
+ }
+
+ return preview_type;
+}
+
+static void
+gtk_preview_class_init (GtkPreviewClass *klass)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+
+ object_class = (GtkObjectClass*) klass;
+ widget_class = (GtkWidgetClass*) klass;
+
+ parent_class = gtk_type_class (gtk_widget_get_type ());
+ preview_class = klass;
+
+ object_class->destroy = gtk_preview_destroy;
+
+ widget_class->realize = gtk_preview_realize;
+ widget_class->unrealize = gtk_preview_unrealize;
+ widget_class->expose_event = gtk_preview_expose;
+
+ if (preview_info)
+ klass->info = *preview_info;
+ else
+ {
+ klass->info.visual = NULL;
+ klass->info.cmap = NULL;
+
+ klass->info.color_pixels = NULL;
+ klass->info.gray_pixels = NULL;
+ klass->info.reserved_pixels = NULL;
+
+ klass->info.lookup_red = NULL;
+ klass->info.lookup_green = NULL;
+ klass->info.lookup_blue = NULL;
+
+ klass->info.dither_red = NULL;
+ klass->info.dither_green = NULL;
+ klass->info.dither_blue = NULL;
+ klass->info.dither_gray = NULL;
+ klass->info.dither_matrix = NULL;
+
+ klass->info.nred_shades = 6;
+ klass->info.ngreen_shades = 6;
+ klass->info.nblue_shades = 4;
+ klass->info.ngray_shades = 24;
+ klass->info.nreserved = 0;
+
+ klass->info.bpp = 0;
+ klass->info.cmap_alloced = FALSE;
+ klass->info.gamma = 1.0;
+ }
+
+ klass->image = NULL;
+
+ gtk_preview_get_visuals (klass);
+ gtk_preview_get_cmaps (klass);
+ gtk_preview_dither_init (klass);
+}
+
+static void
+gtk_preview_init (GtkPreview *preview)
+{
+ GTK_WIDGET_SET_FLAGS (preview, GTK_BASIC);
+
+ preview->buffer = NULL;
+ preview->buffer_width = 0;
+ preview->buffer_height = 0;
+ preview->expand = FALSE;
+}
+
+void
+gtk_preview_uninit ()
+{
+ GtkPreviewProp *prop;
+ GdkAtom property;
+
+ if (preview_class && !install_cmap &&
+ (preview_class->info.visual->type != GDK_VISUAL_TRUE_COLOR) &&
+ (preview_class->info.visual->type != GDK_VISUAL_DIRECT_COLOR))
+ {
+ property = gdk_atom_intern ("GTK_PREVIEW_INFO", FALSE);
+
+ if (gdk_property_get (NULL, property, property,
+ 0, sizeof (GtkPreviewProp), FALSE,
+ NULL, NULL, NULL, (guchar**) &prop))
+ {
+ prop->ref_count = ntohs (prop->ref_count) - 1;
+ if (prop->ref_count == 0)
+ {
+ gdk_property_delete (NULL, property);
+ }
+ else
+ {
+ prop->ref_count = htons (prop->ref_count);
+ gdk_property_change (NULL, property, property, 16,
+ GDK_PROP_MODE_REPLACE,
+ (guchar*) prop, 5);
+ }
+ }
+ }
+}
+
+GtkWidget*
+gtk_preview_new (GtkPreviewType type)
+{
+ GtkPreview *preview;
+
+ preview = gtk_type_new (gtk_preview_get_type ());
+ preview->type = type;
+
+ return GTK_WIDGET (preview);
+}
+
+void
+gtk_preview_size (GtkPreview *preview,
+ gint width,
+ gint height)
+{
+ g_return_if_fail (preview != NULL);
+ g_return_if_fail (GTK_IS_PREVIEW (preview));
+
+ if ((width != GTK_WIDGET (preview)->requisition.width) ||
+ (height != GTK_WIDGET (preview)->requisition.height))
+ {
+ GTK_WIDGET (preview)->requisition.width = width;
+ GTK_WIDGET (preview)->requisition.height = height;
+
+ if (preview->buffer)
+ g_free (preview->buffer);
+ preview->buffer = NULL;
+ }
+}
+
+void
+gtk_preview_put (GtkPreview *preview,
+ GdkWindow *window,
+ GdkGC *gc,
+ gint srcx,
+ gint srcy,
+ gint destx,
+ gint desty,
+ gint width,
+ gint height)
+{
+ GtkWidget *widget;
+ GdkImage *image;
+ GdkRectangle r1, r2, r3;
+ GtkTransferFunc transfer_func;
+ guchar *image_mem;
+ guchar *src, *dest;
+ gint x, xe, x2;
+ gint y, ye, y2;
+ guint dest_rowstride;
+ guint src_bpp;
+ guint dest_bpp;
+ gint i;
+
+ g_return_if_fail (preview != NULL);
+ g_return_if_fail (GTK_IS_PREVIEW (preview));
+ g_return_if_fail (window != NULL);
+
+ if (!preview->buffer)
+ return;
+
+ widget = GTK_WIDGET (preview);
+
+ r1.x = srcx;
+ r1.y = srcy;
+ r1.width = preview->buffer_width;
+ r1.height = preview->buffer_height;
+
+ r2.x = destx;
+ r2.y = desty;
+ r2.width = width;
+ r2.height = height;
+
+ if (!gdk_rectangle_intersect (&r1, &r2, &r3))
+ return;
+
+ x2 = r3.x + r3.width;
+ y2 = r3.y + r3.height;
+
+ if (!preview_class->image)
+ preview_class->image = gdk_image_new (GDK_IMAGE_FASTEST,
+ preview_class->info.visual,
+ IMAGE_SIZE, IMAGE_SIZE);
+ image = preview_class->image;
+ src_bpp = preview_class->info.bpp;
+
+ image_mem = image->mem;
+ dest_bpp = image->bpp;
+ dest_rowstride = image->bpl;
+
+ transfer_func = NULL;
+
+ switch (dest_bpp)
+ {
+ case 1:
+ switch (src_bpp)
+ {
+ case 1:
+ transfer_func = gtk_lsbmsb_1_1;
+ break;
+ }
+ break;
+ case 2:
+ switch (src_bpp)
+ {
+ case 2:
+ if (image->byte_order == GDK_MSB_FIRST)
+ transfer_func = gtk_msb_2_2;
+ else
+ transfer_func = gtk_lsb_2_2;
+ break;
+ case 3:
+ break;
+ }
+ break;
+ case 3:
+ switch (src_bpp)
+ {
+ case 3:
+ if (image->byte_order == GDK_MSB_FIRST)
+ transfer_func = gtk_msb_3_3;
+ else
+ transfer_func = gtk_lsb_3_3;
+ break;
+ }
+ break;
+ case 4:
+ switch (src_bpp)
+ {
+ case 3:
+ if (image->byte_order == GDK_MSB_FIRST)
+ transfer_func = gtk_msb_3_4;
+ else
+ transfer_func = gtk_lsb_3_4;
+ break;
+ }
+ break;
+ }
+
+ if (!transfer_func)
+ {
+ g_warning ("unsupported byte order/src bpp/dest bpp combination: %s:%d:%d",
+ (image->byte_order == GDK_MSB_FIRST) ? "msb" : "lsb", src_bpp, dest_bpp);
+ return;
+ }
+
+ for (y = r3.y; y < y2; y += IMAGE_SIZE)
+ {
+ for (x = r3.x; x < x2; x += IMAGE_SIZE)
+ {
+ xe = x + IMAGE_SIZE;
+ if (xe > x2)
+ xe = x2;
+
+ ye = y + IMAGE_SIZE;
+ if (ye > y2)
+ ye = y2;
+
+ for (i = y; i < ye; i++)
+ {
+ src = preview->buffer + (((gulong) (i - r1.y) * (gulong) preview->buffer_width) +
+ (x - r1.x)) * (gulong) src_bpp;
+ dest = image_mem + ((gulong) (i - y) * dest_rowstride);
+
+ if (xe > x)
+ (* transfer_func) (dest, src, xe - x);
+ }
+
+ gdk_draw_image (window, gc,
+ image, 0, 0, x, y,
+ xe - x, ye - y);
+ gdk_flush ();
+ }
+ }
+}
+
+void
+gtk_preview_put_row (GtkPreview *preview,
+ guchar *src,
+ guchar *dest,
+ gint x,
+ gint y,
+ gint w)
+{
+ g_return_if_fail (preview != NULL);
+ g_return_if_fail (GTK_IS_PREVIEW (preview));
+ g_return_if_fail (src != NULL);
+ g_return_if_fail (dest != NULL);
+
+ switch (preview->type)
+ {
+ case GTK_PREVIEW_COLOR:
+ switch (preview_class->info.visual->depth)
+ {
+ case 8:
+ gtk_color_8 (src, dest, x, y, w);
+ break;
+ case 15:
+ case 16:
+ gtk_color_16 (src, dest, w);
+ break;
+ case 24:
+ case 32:
+ gtk_color_24 (src, dest, w);
+ break;
+ }
+ break;
+ case GTK_PREVIEW_GRAYSCALE:
+ switch (preview_class->info.visual->depth)
+ {
+ case 8:
+ gtk_grayscale_8 (src, dest, x, y, w);
+ break;
+ case 15:
+ case 16:
+ gtk_grayscale_16 (src, dest, w);
+ break;
+ case 24:
+ case 32:
+ gtk_grayscale_24 (src, dest, w);
+ break;
+ }
+ break;
+ }
+}
+
+void
+gtk_preview_draw_row (GtkPreview *preview,
+ guchar *data,
+ gint x,
+ gint y,
+ gint w)
+{
+ guchar *dest;
+
+ g_return_if_fail (preview != NULL);
+ g_return_if_fail (GTK_IS_PREVIEW (preview));
+ g_return_if_fail (data != NULL);
+
+ if ((w <= 0) || (y < 0))
+ return;
+
+ g_return_if_fail (data != NULL);
+
+ gtk_preview_make_buffer (preview);
+
+ if (y >= preview->buffer_height)
+ return;
+
+ switch (preview->type)
+ {
+ case GTK_PREVIEW_COLOR:
+ switch (preview_class->info.visual->depth)
+ {
+ case 8:
+ dest = preview->buffer + ((gulong) y * (gulong) preview->buffer_width + (gulong) x);
+ gtk_color_8 (data, dest, x, y, w);
+ break;
+ case 15:
+ case 16:
+ dest = preview->buffer + ((gulong) y * (gulong) preview->buffer_width + (gulong) x) * 2;
+ gtk_color_16 (data, dest, w);
+ break;
+ case 24:
+ case 32:
+ dest = preview->buffer + ((gulong) y * (gulong) preview->buffer_width + (gulong) x) * 3;
+ gtk_color_24 (data, dest, w);
+ break;
+ }
+ break;
+ case GTK_PREVIEW_GRAYSCALE:
+ switch (preview_class->info.visual->depth)
+ {
+ case 8:
+ dest = preview->buffer + ((gulong) y * (gulong) preview->buffer_width + (gulong) x);
+ gtk_grayscale_8 (data, dest, x, y, w);
+ break;
+ case 15:
+ case 16:
+ dest = preview->buffer + ((gulong) y * (gulong) preview->buffer_width + (gulong) x) * 2;
+ gtk_grayscale_16 (data, dest, w);
+ break;
+ case 24:
+ case 32:
+ dest = preview->buffer + ((gulong) y * (gulong) preview->buffer_width + (gulong) x) * 3;
+ gtk_grayscale_24 (data, dest, w);
+ break;
+ }
+ break;
+ }
+}
+
+void
+gtk_preview_set_expand (GtkPreview *preview,
+ gint expand)
+{
+ g_return_if_fail (preview != NULL);
+ g_return_if_fail (GTK_IS_PREVIEW (preview));
+
+ preview->expand = (expand != FALSE);
+}
+
+void
+gtk_preview_set_gamma (double _gamma)
+{
+ g_return_if_fail (preview_class == NULL);
+
+ if (!preview_info)
+ {
+ preview_info = g_new0 (GtkPreviewInfo, 1);
+ preview_info->nred_shades = 6;
+ preview_info->ngreen_shades = 6;
+ preview_info->nblue_shades = 4;
+ preview_info->ngray_shades = 24;
+ }
+
+ preview_info->gamma = _gamma;
+}
+
+void
+gtk_preview_set_color_cube (guint nred_shades,
+ guint ngreen_shades,
+ guint nblue_shades,
+ guint ngray_shades)
+{
+ g_return_if_fail (preview_class == NULL);
+
+ if (!preview_info)
+ {
+ preview_info = g_new0 (GtkPreviewInfo, 1);
+ preview_info->gamma = 1.0;
+ }
+
+ preview_info->nred_shades = nred_shades;
+ preview_info->ngreen_shades = ngreen_shades;
+ preview_info->nblue_shades = nblue_shades;
+ preview_info->ngray_shades = ngray_shades;
+}
+
+void
+gtk_preview_set_install_cmap (gint _install_cmap)
+{
+ /* g_return_if_fail (preview_class == NULL); */
+
+ install_cmap = _install_cmap;
+}
+
+void
+gtk_preview_set_reserved (gint nreserved)
+{
+ if (!preview_info)
+ preview_info = g_new0 (GtkPreviewInfo, 1);
+
+ preview_info->nreserved = nreserved;
+}
+
+GdkVisual*
+gtk_preview_get_visual ()
+{
+ if (!preview_class)
+ preview_class = gtk_type_class (gtk_preview_get_type ());
+
+ return preview_class->info.visual;
+}
+
+GdkColormap*
+gtk_preview_get_cmap ()
+{
+ if (!preview_class)
+ preview_class = gtk_type_class (gtk_preview_get_type ());
+
+ return preview_class->info.cmap;
+}
+
+GtkPreviewInfo*
+gtk_preview_get_info ()
+{
+ if (!preview_class)
+ preview_class = gtk_type_class (gtk_preview_get_type ());
+
+ return &preview_class->info;
+}
+
+
+static void
+gtk_preview_destroy (GtkObject *object)
+{
+ GtkPreview *preview;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_PREVIEW (object));
+
+ preview = GTK_PREVIEW (object);
+ if (preview->buffer)
+ g_free (preview->buffer);
+ preview->type = (GtkPreviewType) -1;
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+static void
+gtk_preview_realize (GtkWidget *widget)
+{
+ GtkPreview *preview;
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_PREVIEW (widget));
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+ preview = GTK_PREVIEW (widget);
+
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.x = widget->allocation.x;
+ attributes.y = widget->allocation.y;
+ attributes.width = widget->allocation.width;
+ attributes.height = widget->allocation.height;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
+ attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+
+ widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
+ gdk_window_set_user_data (widget->window, widget);
+
+ widget->style = gtk_style_attach (widget->style, widget->window);
+ gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
+}
+
+static void
+gtk_preview_unrealize (GtkWidget *widget)
+{
+ GtkPreview *preview;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_PREVIEW (widget));
+
+ preview = GTK_PREVIEW (widget);
+
+ if (GTK_WIDGET_CLASS (parent_class)->unrealize)
+ (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
+}
+
+static gint
+gtk_preview_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ GtkPreview *preview;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_PREVIEW (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ preview = GTK_PREVIEW (widget);
+
+ gtk_preview_put (GTK_PREVIEW (widget),
+ widget->window, widget->style->black_gc,
+ (widget->allocation.width - preview->buffer_width) / 2,
+ (widget->allocation.height - preview->buffer_height) / 2,
+ event->area.x, event->area.y,
+ event->area.width, event->area.height);
+ }
+
+ return FALSE;
+}
+
+static void
+gtk_preview_make_buffer (GtkPreview *preview)
+{
+ GtkWidget *widget;
+ gint width;
+ gint height;
+
+ g_return_if_fail (preview != NULL);
+ g_return_if_fail (GTK_IS_PREVIEW (preview));
+
+ widget = GTK_WIDGET (preview);
+
+ if (preview->expand &&
+ (widget->allocation.width != 0) &&
+ (widget->allocation.height != 0))
+ {
+ width = widget->allocation.width;
+ height = widget->allocation.height;
+ }
+ else
+ {
+ width = widget->requisition.width;
+ height = widget->requisition.height;
+ }
+
+ if (!preview->buffer ||
+ (preview->buffer_width != width) ||
+ (preview->buffer_height != height))
+ {
+ if (preview->buffer)
+ g_free (preview->buffer);
+
+ preview->buffer_width = width;
+ preview->buffer_height = height;
+
+ preview->buffer = g_new0 (guchar,
+ preview->buffer_width *
+ preview->buffer_height *
+ preview_class->info.bpp);
+ }
+}
+
+static void
+gtk_preview_get_visuals (GtkPreviewClass *klass)
+{
+ static GdkVisualType types[] =
+ {
+ GDK_VISUAL_TRUE_COLOR,
+ GDK_VISUAL_DIRECT_COLOR,
+ GDK_VISUAL_TRUE_COLOR,
+ GDK_VISUAL_DIRECT_COLOR,
+ GDK_VISUAL_TRUE_COLOR,
+ GDK_VISUAL_DIRECT_COLOR,
+ GDK_VISUAL_TRUE_COLOR,
+ GDK_VISUAL_DIRECT_COLOR,
+ GDK_VISUAL_PSEUDO_COLOR
+ };
+ static gint depths[] = { 24, 24, 32, 32, 16, 16, 15, 15, 8 };
+ static gint nvisual_types = sizeof (types) / sizeof (types[0]);
+
+ int i;
+
+ g_return_if_fail (klass != NULL);
+
+ if (!klass->info.visual)
+ for (i = 0; i < nvisual_types; i++)
+ if ((klass->info.visual = gdk_visual_get_best_with_both (depths[i], types[i])))
+ {
+ if ((klass->info.visual->type == GDK_VISUAL_TRUE_COLOR) ||
+ (klass->info.visual->type == GDK_VISUAL_DIRECT_COLOR))
+ {
+ klass->info.lookup_red = g_new (gulong, 256);
+ klass->info.lookup_green = g_new (gulong, 256);
+ klass->info.lookup_blue = g_new (gulong, 256);
+
+ gtk_fill_lookup_array (klass->info.lookup_red,
+ klass->info.visual->depth,
+ klass->info.visual->red_shift,
+ 8 - klass->info.visual->red_prec);
+ gtk_fill_lookup_array (klass->info.lookup_green,
+ klass->info.visual->depth,
+ klass->info.visual->green_shift,
+ 8 - klass->info.visual->green_prec);
+ gtk_fill_lookup_array (klass->info.lookup_blue,
+ klass->info.visual->depth,
+ klass->info.visual->blue_shift,
+ 8 - klass->info.visual->blue_prec);
+ }
+ break;
+ }
+
+ if (!klass->info.visual)
+ {
+ g_warning ("unable to find a suitable visual for color image display.\n");
+ return;
+ }
+
+ switch (klass->info.visual->depth)
+ {
+ case 8:
+ klass->info.bpp = 1;
+ break;
+ case 15:
+ case 16:
+ klass->info.bpp = 2;
+ break;
+ case 24:
+ case 32:
+ klass->info.bpp = 3;
+ break;
+ }
+}
+
+static void
+gtk_preview_get_cmaps (GtkPreviewClass *klass)
+{
+ g_return_if_fail (klass != NULL);
+ g_return_if_fail (klass->info.visual != NULL);
+
+ if ((klass->info.visual->type != GDK_VISUAL_TRUE_COLOR) &&
+ (klass->info.visual->type != GDK_VISUAL_DIRECT_COLOR))
+ {
+ if (install_cmap)
+ {
+ klass->info.cmap = gdk_colormap_new (klass->info.visual, FALSE);
+ klass->info.cmap_alloced = install_cmap;
+
+ gtk_trim_cmap (klass);
+ gtk_create_8_bit (klass);
+ }
+ else
+ {
+ guint nred;
+ guint ngreen;
+ guint nblue;
+ guint ngray;
+ gint set_prop;
+
+ klass->info.cmap = gdk_colormap_get_system ();
+
+ set_prop = TRUE;
+ if (gtk_get_preview_prop (&nred, &ngreen, &nblue, &ngray))
+ {
+ set_prop = FALSE;
+
+ klass->info.nred_shades = nred;
+ klass->info.ngreen_shades = ngreen;
+ klass->info.nblue_shades = nblue;
+ klass->info.ngray_shades = ngray;
+
+ if (klass->info.nreserved)
+ {
+ klass->info.reserved_pixels = g_new (gulong, klass->info.nreserved);
+ if (!gdk_colors_alloc (klass->info.cmap, 0, NULL, 0,
+ klass->info.reserved_pixels,
+ klass->info.nreserved))
+ {
+ g_free (klass->info.reserved_pixels);
+ klass->info.reserved_pixels = NULL;
+ }
+ }
+ }
+ else
+ {
+ gtk_trim_cmap (klass);
+ }
+
+ gtk_create_8_bit (klass);
+
+ if (set_prop)
+ gtk_set_preview_prop (klass->info.nred_shades,
+ klass->info.ngreen_shades,
+ klass->info.nblue_shades,
+ klass->info.ngray_shades);
+ }
+ }
+ else
+ {
+ if (klass->info.visual == gdk_visual_get_system ())
+ klass->info.cmap = gdk_colormap_get_system ();
+ else
+ klass->info.cmap = gdk_colormap_new (klass->info.visual, FALSE);
+ klass->info.cmap_alloced = TRUE;
+
+ klass->info.nred_shades = 0;
+ klass->info.ngreen_shades = 0;
+ klass->info.nblue_shades = 0;
+ klass->info.ngray_shades = 0;
+ }
+}
+
+static void
+gtk_preview_dither_init (GtkPreviewClass *klass)
+{
+ int i, j, k;
+ unsigned char low_shade, high_shade;
+ unsigned short index;
+ long red_mult, green_mult;
+ double red_matrix_width;
+ double green_matrix_width;
+ double blue_matrix_width;
+ double gray_matrix_width;
+ double red_colors_per_shade;
+ double green_colors_per_shade;
+ double blue_colors_per_shade;
+ double gray_colors_per_shade;
+ gulong *gray_pixels;
+ gint shades_r, shades_g, shades_b, shades_gray;
+ GtkDitherInfo *red_ordered_dither;
+ GtkDitherInfo *green_ordered_dither;
+ GtkDitherInfo *blue_ordered_dither;
+ GtkDitherInfo *gray_ordered_dither;
+ guchar ***dither_matrix;
+ guchar DM[8][8] =
+ {
+ { 0, 32, 8, 40, 2, 34, 10, 42 },
+ { 48, 16, 56, 24, 50, 18, 58, 26 },
+ { 12, 44, 4, 36, 14, 46, 6, 38 },
+ { 60, 28, 52, 20, 62, 30, 54, 22 },
+ { 3, 35, 11, 43, 1, 33, 9, 41 },
+ { 51, 19, 59, 27, 49, 17, 57, 25 },
+ { 15, 47, 7, 39, 13, 45, 5, 37 },
+ { 63, 31, 55, 23, 61, 29, 53, 21 }
+ };
+
+ if (klass->info.visual->type != GDK_VISUAL_PSEUDO_COLOR)
+ return;
+
+ shades_r = klass->info.nred_shades;
+ shades_g = klass->info.ngreen_shades;
+ shades_b = klass->info.nblue_shades;
+ shades_gray = klass->info.ngray_shades;
+
+ red_mult = shades_g * shades_b;
+ green_mult = shades_b;
+
+ red_colors_per_shade = 255.0 / (shades_r - 1);
+ red_matrix_width = red_colors_per_shade / 64;
+
+ green_colors_per_shade = 255.0 / (shades_g - 1);
+ green_matrix_width = green_colors_per_shade / 64;
+
+ blue_colors_per_shade = 255.0 / (shades_b - 1);
+ blue_matrix_width = blue_colors_per_shade / 64;
+
+ gray_colors_per_shade = 255.0 / (shades_gray - 1);
+ gray_matrix_width = gray_colors_per_shade / 64;
+
+ /* alloc the ordered dither arrays for accelerated dithering */
+
+ klass->info.dither_red = g_new (GtkDitherInfo, 256);
+ klass->info.dither_green = g_new (GtkDitherInfo, 256);
+ klass->info.dither_blue = g_new (GtkDitherInfo, 256);
+ klass->info.dither_gray = g_new (GtkDitherInfo, 256);
+
+ red_ordered_dither = klass->info.dither_red;
+ green_ordered_dither = klass->info.dither_green;
+ blue_ordered_dither = klass->info.dither_blue;
+ gray_ordered_dither = klass->info.dither_gray;
+
+ dither_matrix = g_new (guchar**, 8);
+ for (i = 0; i < 8; i++)
+ {
+ dither_matrix[i] = g_new (guchar*, 8);
+ for (j = 0; j < 8; j++)
+ dither_matrix[i][j] = g_new (guchar, 65);
+ }
+
+ klass->info.dither_matrix = dither_matrix;
+
+ /* setup the ordered_dither_matrices */
+
+ for (i = 0; i < 8; i++)
+ for (j = 0; j < 8; j++)
+ for (k = 0; k <= 64; k++)
+ dither_matrix[i][j][k] = (DM[i][j] < k) ? 1 : 0;
+
+ /* setup arrays containing three bytes of information for red, green, & blue */
+ /* the arrays contain :
+ * 1st byte: low end shade value
+ * 2nd byte: high end shade value
+ * 3rd & 4th bytes: ordered dither matrix index
+ */
+
+ gray_pixels = klass->info.gray_pixels;
+
+ for (i = 0; i < 256; i++)
+ {
+
+ /* setup the red information */
+ {
+ low_shade = (unsigned char) (i / red_colors_per_shade);
+ if (low_shade == (shades_r - 1))
+ low_shade--;
+ high_shade = low_shade + 1;
+
+ index = (unsigned short)
+ (((double) i - low_shade * red_colors_per_shade) /
+ red_matrix_width);
+
+ low_shade *= red_mult;
+ high_shade *= red_mult;
+
+ red_ordered_dither[i].s[1] = index;
+ red_ordered_dither[i].c[0] = low_shade;
+ red_ordered_dither[i].c[1] = high_shade;
+ }
+
+
+ /* setup the green information */
+ {
+ low_shade = (unsigned char) (i / green_colors_per_shade);
+ if (low_shade == (shades_g - 1))
+ low_shade--;
+ high_shade = low_shade + 1;
+
+ index = (unsigned short)
+ (((double) i - low_shade * green_colors_per_shade) /
+ green_matrix_width);
+
+ low_shade *= green_mult;
+ high_shade *= green_mult;
+
+ green_ordered_dither[i].s[1] = index;
+ green_ordered_dither[i].c[0] = low_shade;
+ green_ordered_dither[i].c[1] = high_shade;
+ }
+
+
+ /* setup the blue information */
+ {
+ low_shade = (unsigned char) (i / blue_colors_per_shade);
+ if (low_shade == (shades_b - 1))
+ low_shade--;
+ high_shade = low_shade + 1;
+
+ index = (unsigned short)
+ (((double) i - low_shade * blue_colors_per_shade) /
+ blue_matrix_width);
+
+ blue_ordered_dither[i].s[1] = index;
+ blue_ordered_dither[i].c[0] = low_shade;
+ blue_ordered_dither[i].c[1] = high_shade;
+ }
+
+
+ /* setup the gray information */
+ {
+ low_shade = (unsigned char) (i / gray_colors_per_shade);
+ if (low_shade == (shades_gray - 1))
+ low_shade--;
+ high_shade = low_shade + 1;
+
+ index = (unsigned short)
+ (((double) i - low_shade * gray_colors_per_shade) /
+ gray_matrix_width);
+
+ gray_ordered_dither[i].s[1] = index;
+ gray_ordered_dither[i].c[0] = gray_pixels[low_shade];
+ gray_ordered_dither[i].c[1] = gray_pixels[high_shade];
+ }
+ }
+}
+
+static void
+gtk_fill_lookup_array (gulong *array,
+ int depth,
+ int shift,
+ int prec)
+{
+ double one_over_gamma;
+ double ind;
+ int val;
+ int i;
+
+ if (preview_class->info.gamma != 0.0)
+ one_over_gamma = 1.0 / preview_class->info.gamma;
+ else
+ one_over_gamma = 1.0;
+
+ for (i = 0; i < 256; i++)
+ {
+ if (one_over_gamma == 1.0)
+ array[i] = ((i >> prec) << shift);
+ else
+ {
+ ind = (double) i / 255.0;
+ val = (int) (255 * pow (ind, one_over_gamma));
+ array[i] = ((val >> prec) << shift);
+ }
+ }
+}
+
+static void
+gtk_trim_cmap (GtkPreviewClass *klass)
+{
+ gulong pixels[256];
+ guint nred;
+ guint ngreen;
+ guint nblue;
+ guint ngray;
+ guint nreserved;
+ guint total;
+ guint tmp;
+ gint success;
+
+ nred = klass->info.nred_shades;
+ ngreen = klass->info.ngreen_shades;
+ nblue = klass->info.nblue_shades;
+ ngray = klass->info.ngray_shades;
+ nreserved = klass->info.nreserved;
+
+ success = FALSE;
+ while (!success)
+ {
+ total = nred * ngreen * nblue + ngray + nreserved;
+
+ if (total <= 256)
+ {
+ if ((nred < 2) || (ngreen < 2) || (nblue < 2) || (ngray < 2))
+ success = TRUE;
+ else
+ {
+ success = gdk_colors_alloc (klass->info.cmap, 0, NULL, 0, pixels, total);
+ if (success)
+ {
+ if (nreserved > 0)
+ {
+ klass->info.reserved_pixels = g_new (gulong, nreserved);
+ memcpy (klass->info.reserved_pixels, pixels, sizeof (gulong) * nreserved);
+ gdk_colors_free (klass->info.cmap, &pixels[nreserved],
+ total - nreserved, 0);
+ }
+ else
+ {
+ gdk_colors_free (klass->info.cmap, pixels, total, 0);
+ }
+ }
+ }
+ }
+
+ if (!success)
+ {
+ if ((nblue >= nred) && (nblue >= ngreen))
+ nblue = nblue - 1;
+ else if ((nred >= ngreen) && (nred >= nblue))
+ nred = nred - 1;
+ else
+ {
+ tmp = log (ngray) / log (2);
+
+ if (ngreen >= tmp)
+ ngreen = ngreen - 1;
+ else
+ ngray -= 1;
+ }
+ }
+ }
+
+ if ((nred < 2) || (ngreen < 2) || (nblue < 2) || (ngray < 2))
+ {
+ g_print ("Unable to allocate sufficient colormap entries.\n");
+ g_print ("Try exiting other color intensive applications.\n");
+ return;
+ }
+
+ /* If any of the shade values has changed, issue a warning */
+ if ((nred != klass->info.nred_shades) ||
+ (ngreen != klass->info.ngreen_shades) ||
+ (nblue != klass->info.nblue_shades) ||
+ (ngray != klass->info.ngray_shades))
+ {
+ g_print ("Not enough colors to satisfy requested color cube.\n");
+ g_print ("Reduced color cube shades from\n");
+ g_print ("[%d of Red, %d of Green, %d of Blue, %d of Gray] ==> [%d of Red, %d of Green, %d of Blue, %d of Gray]\n",
+ klass->info.nred_shades, klass->info.ngreen_shades,
+ klass->info.nblue_shades, klass->info.ngray_shades,
+ nred, ngreen, nblue, ngray);
+ }
+
+ klass->info.nred_shades = nred;
+ klass->info.ngreen_shades = ngreen;
+ klass->info.nblue_shades = nblue;
+ klass->info.ngray_shades = ngray;
+}
+
+static void
+gtk_create_8_bit (GtkPreviewClass *klass)
+{
+ unsigned int r, g, b;
+ unsigned int rv, gv, bv;
+ unsigned int dr, dg, db, dgray;
+ GdkColor color;
+ gulong *pixels;
+ double one_over_gamma;
+ int i;
+
+ if (!klass->info.color_pixels)
+ klass->info.color_pixels = g_new (gulong, 256);
+
+ if (!klass->info.gray_pixels)
+ klass->info.gray_pixels = g_new (gulong, 256);
+
+ if (klass->info.gamma != 0.0)
+ one_over_gamma = 1.0 / klass->info.gamma;
+ else
+ one_over_gamma = 1.0;
+
+ dr = klass->info.nred_shades - 1;
+ dg = klass->info.ngreen_shades - 1;
+ db = klass->info.nblue_shades - 1;
+ dgray = klass->info.ngray_shades - 1;
+
+ pixels = klass->info.color_pixels;
+
+ for (r = 0, i = 0; r <= dr; r++)
+ for (g = 0; g <= dg; g++)
+ for (b = 0; b <= db; b++, i++)
+ {
+ rv = (unsigned int) ((r * klass->info.visual->colormap_size) / dr);
+ gv = (unsigned int) ((g * klass->info.visual->colormap_size) / dg);
+ bv = (unsigned int) ((b * klass->info.visual->colormap_size) / db);
+ color.red = ((int) (255 * pow ((double) rv / 256.0, one_over_gamma))) * 257;
+ color.green = ((int) (255 * pow ((double) gv / 256.0, one_over_gamma))) * 257;
+ color.blue = ((int) (255 * pow ((double) bv / 256.0, one_over_gamma))) * 257;
+
+ if (!gdk_color_alloc (klass->info.cmap, &color))
+ {
+ g_error ("could not initialize 8-bit combined colormap");
+ return;
+ }
+
+ pixels[i] = color.pixel;
+ }
+
+ pixels = klass->info.gray_pixels;
+
+ for (i = 0; i < (int) klass->info.ngray_shades; i++)
+ {
+ color.red = (i * klass->info.visual->colormap_size) / dgray;
+ color.red = ((int) (255 * pow ((double) color.red / 256.0, one_over_gamma))) * 257;
+ color.green = color.red;
+ color.blue = color.red;
+
+ if (!gdk_color_alloc (klass->info.cmap, &color))
+ {
+ g_error ("could not initialize 8-bit combined colormap");
+ return;
+ }
+
+ pixels[i] = color.pixel;
+ }
+}
+
+
+static void
+gtk_color_8 (guchar *src,
+ guchar *dest,
+ gint x,
+ gint y,
+ gulong width)
+{
+ gulong *colors;
+ GtkDitherInfo *dither_red;
+ GtkDitherInfo *dither_green;
+ GtkDitherInfo *dither_blue;
+ GtkDitherInfo r, g, b;
+ guchar **dither_matrix;
+ guchar *matrix;
+
+ colors = preview_class->info.color_pixels;
+ dither_red = preview_class->info.dither_red;
+ dither_green = preview_class->info.dither_green;
+ dither_blue = preview_class->info.dither_blue;
+ dither_matrix = preview_class->info.dither_matrix[y & 0x7];
+
+ while (width--)
+ {
+ r = dither_red[src[0]];
+ g = dither_green[src[1]];
+ b = dither_blue[src[2]];
+ src += 3;
+
+ matrix = dither_matrix[x++ & 0x7];
+ *dest++ = colors[(r.c[matrix[r.s[1]]] +
+ g.c[matrix[g.s[1]]] +
+ b.c[matrix[b.s[1]]])];
+ }
+}
+
+static void
+gtk_color_16 (guchar *src,
+ guchar *dest,
+ gulong width)
+{
+ gulong *lookup_red;
+ gulong *lookup_green;
+ gulong *lookup_blue;
+ gulong val;
+
+ lookup_red = preview_class->info.lookup_red;
+ lookup_green = preview_class->info.lookup_green;
+ lookup_blue = preview_class->info.lookup_blue;
+
+ while (width--)
+ {
+ val = COLOR_COMPOSE (src[0], src[1], src[2]);
+ dest[0] = val;
+ dest[1] = val >> 8;
+ dest += 2;
+ src += 3;
+ }
+}
+
+static void
+gtk_color_24 (guchar *src,
+ guchar *dest,
+ gulong width)
+{
+ gulong *lookup_red;
+ gulong *lookup_green;
+ gulong *lookup_blue;
+ gulong val;
+
+ lookup_red = preview_class->info.lookup_red;
+ lookup_green = preview_class->info.lookup_green;
+ lookup_blue = preview_class->info.lookup_blue;
+
+ while (width--)
+ {
+ val = COLOR_COMPOSE (src[0], src[1], src[2]);
+ dest[0] = val;
+ dest[1] = val >> 8;
+ dest[2] = val >> 16;
+ dest += 3;
+ src += 3;
+ }
+}
+
+static void
+gtk_grayscale_8 (guchar *src,
+ guchar *dest,
+ gint x,
+ gint y,
+ gulong width)
+{
+ GtkDitherInfo *dither_gray;
+ GtkDitherInfo gray;
+ guchar **dither_matrix;
+ guchar *matrix;
+
+ dither_gray = preview_class->info.dither_gray;
+ dither_matrix = preview_class->info.dither_matrix[y & 0x7];
+
+ while (width--)
+ {
+ gray = dither_gray[*src++];
+ matrix = dither_matrix[x++ & 0x7];
+ *dest++ = gray.c[matrix[gray.s[1]]];
+ }
+}
+
+static void
+gtk_grayscale_16 (guchar *src,
+ guchar *dest,
+ gulong width)
+{
+ gulong *lookup_red;
+ gulong *lookup_green;
+ gulong *lookup_blue;
+ gulong val;
+
+ lookup_red = preview_class->info.lookup_red;
+ lookup_green = preview_class->info.lookup_green;
+ lookup_blue = preview_class->info.lookup_blue;
+
+ while (width--)
+ {
+ val = COLOR_COMPOSE (*src, *src, *src);
+ dest[0] = val;
+ dest[1] = val >> 8;
+ dest += 2;
+ src += 1;
+ }
+}
+
+static void
+gtk_grayscale_24 (guchar *src,
+ guchar *dest,
+ gulong width)
+{
+ gulong *lookup_red;
+ gulong *lookup_green;
+ gulong *lookup_blue;
+ gulong val;
+
+ lookup_red = preview_class->info.lookup_red;
+ lookup_green = preview_class->info.lookup_green;
+ lookup_blue = preview_class->info.lookup_blue;
+
+ while (width--)
+ {
+ val = COLOR_COMPOSE (*src, *src, *src);
+ dest[0] = val;
+ dest[1] = val >> 8;
+ dest[2] = val >> 16;
+ dest += 3;
+ src += 1;
+ }
+}
+
+
+static gint
+gtk_get_preview_prop (guint *nred,
+ guint *ngreen,
+ guint *nblue,
+ guint *ngray)
+{
+ GtkPreviewProp *prop;
+ GdkAtom property;
+
+ property = gdk_atom_intern ("GTK_PREVIEW_INFO", FALSE);
+
+ if (gdk_property_get (NULL, property, property,
+ 0, sizeof (GtkPreviewProp), FALSE,
+ NULL, NULL, NULL, (guchar**) &prop))
+ {
+ *nred = ntohs (prop->nred_shades);
+ *ngreen = ntohs (prop->ngreen_shades);
+ *nblue = ntohs (prop->nblue_shades);
+ *ngray = ntohs (prop->ngray_shades);
+
+ prop->ref_count = htons (ntohs (prop->ref_count) + 1);
+ gdk_property_change (NULL, property, property, 16,
+ GDK_PROP_MODE_REPLACE,
+ (guchar*) prop, 5);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+gtk_set_preview_prop (guint nred,
+ guint ngreen,
+ guint nblue,
+ guint ngray)
+{
+ GtkPreviewProp prop;
+ GdkAtom property;
+
+ property = gdk_atom_intern ("GTK_PREVIEW_INFO", FALSE);
+
+ prop.ref_count = htons (1);
+ prop.nred_shades = htons (nred);
+ prop.ngreen_shades = htons (ngreen);
+ prop.nblue_shades = htons (nblue);
+ prop.ngray_shades = htons (ngray);
+
+ gdk_property_change (NULL, property, property, 16,
+ GDK_PROP_MODE_REPLACE,
+ (guchar*) &prop, 5);
+}
+
+
+static void
+gtk_lsbmsb_1_1 (guchar *dest,
+ guchar *src,
+ gint count)
+{
+ memcpy (dest, src, count);
+}
+
+static void
+gtk_lsb_2_2 (guchar *dest,
+ guchar *src,
+ gint count)
+{
+ memcpy (dest, src, count * 2);
+}
+
+static void
+gtk_msb_2_2 (guchar *dest,
+ guchar *src,
+ gint count)
+{
+ while (count--)
+ {
+ dest[0] = src[1];
+ dest[1] = src[0];
+ dest += 2;
+ src += 2;
+ }
+}
+
+static void
+gtk_lsb_3_3 (guchar *dest,
+ guchar *src,
+ gint count)
+{
+ memcpy (dest, src, count * 3);
+}
+
+static void
+gtk_msb_3_3 (guchar *dest,
+ guchar *src,
+ gint count)
+{
+ while (count--)
+ {
+ dest[0] = src[2];
+ dest[1] = src[1];
+ dest[2] = src[0];
+ dest += 3;
+ src += 3;
+ }
+}
+
+static void
+gtk_lsb_3_4 (guchar *dest,
+ guchar *src,
+ gint count)
+{
+ while (count--)
+ {
+ dest[0] = src[0];
+ dest[1] = src[1];
+ dest[2] = src[2];
+ dest += 4;
+ src += 3;
+ }
+}
+
+static void
+gtk_msb_3_4 (guchar *dest,
+ guchar *src,
+ gint count)
+{
+ while (count--)
+ {
+ dest[1] = src[2];
+ dest[2] = src[1];
+ dest[3] = src[0];
+ dest += 4;
+ src += 3;
+ }
+}
diff --git a/gtk/gtkpreview.h b/gtk/gtkpreview.h
new file mode 100644
index 000000000..2fe6ad5e0
--- /dev/null
+++ b/gtk/gtkpreview.h
@@ -0,0 +1,144 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_PREVIEW_H__
+#define __GTK_PREVIEW_H__
+
+
+#include <gtk/gtkwidget.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_PREVIEW(obj) GTK_CHECK_CAST (obj, gtk_preview_get_type (), GtkPreview)
+#define GTK_PREVIEW_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_preview_get_type (), GtkPreviewClass)
+#define GTK_IS_PREVIEW(obj) GTK_CHECK_TYPE (obj, gtk_preview_get_type ())
+
+
+typedef struct _GtkPreview GtkPreview;
+typedef struct _GtkPreviewInfo GtkPreviewInfo;
+typedef union _GtkDitherInfo GtkDitherInfo;
+typedef struct _GtkPreviewClass GtkPreviewClass;
+
+struct _GtkPreview
+{
+ GtkWidget widget;
+
+ guchar *buffer;
+ guint16 buffer_width;
+ guint16 buffer_height;
+
+ guint type : 1;
+ guint expand : 1;
+};
+
+struct _GtkPreviewInfo
+{
+ GdkVisual *visual;
+ GdkColormap *cmap;
+
+ gulong *color_pixels;
+ gulong *gray_pixels;
+ gulong *reserved_pixels;
+
+ gulong *lookup_red;
+ gulong *lookup_green;
+ gulong *lookup_blue;
+
+ GtkDitherInfo *dither_red;
+ GtkDitherInfo *dither_green;
+ GtkDitherInfo *dither_blue;
+ GtkDitherInfo *dither_gray;
+ guchar ***dither_matrix;
+
+ guint nred_shades;
+ guint ngreen_shades;
+ guint nblue_shades;
+ guint ngray_shades;
+ guint nreserved;
+
+ guint bpp;
+ gint cmap_alloced;
+ gdouble gamma;
+};
+
+union _GtkDitherInfo
+{
+ gushort s[2];
+ guchar c[4];
+};
+
+struct _GtkPreviewClass
+{
+ GtkWidgetClass parent_class;
+
+ GtkPreviewInfo info;
+
+ GdkImage *image;
+};
+
+
+guint gtk_preview_get_type (void);
+void gtk_preview_uninit (void);
+GtkWidget* gtk_preview_new (GtkPreviewType type);
+void gtk_preview_size (GtkPreview *preview,
+ gint width,
+ gint height);
+void gtk_preview_put (GtkPreview *preview,
+ GdkWindow *window,
+ GdkGC *gc,
+ gint srcx,
+ gint srcy,
+ gint destx,
+ gint desty,
+ gint width,
+ gint height);
+void gtk_preview_put_row (GtkPreview *preview,
+ guchar *src,
+ guchar *dest,
+ gint x,
+ gint y,
+ gint w);
+void gtk_preview_draw_row (GtkPreview *preview,
+ guchar *data,
+ gint x,
+ gint y,
+ gint w);
+void gtk_preview_set_expand (GtkPreview *preview,
+ gint expand);
+
+void gtk_preview_set_gamma (double gamma);
+void gtk_preview_set_color_cube (guint nred_shades,
+ guint ngreen_shades,
+ guint nblue_shades,
+ guint ngray_shades);
+void gtk_preview_set_install_cmap (gint install_cmap);
+void gtk_preview_set_reserved (gint nreserved);
+GdkVisual* gtk_preview_get_visual (void);
+GdkColormap* gtk_preview_get_cmap (void);
+GtkPreviewInfo* gtk_preview_get_info (void);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_PREVIEW_H__ */
diff --git a/gtk/gtkprogressbar.c b/gtk/gtkprogressbar.c
new file mode 100644
index 000000000..8db560ba0
--- /dev/null
+++ b/gtk/gtkprogressbar.c
@@ -0,0 +1,259 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtkprogressbar.h"
+
+
+#define MIN_WIDTH 200
+#define MIN_HEIGHT 20
+
+
+static void gtk_progress_bar_class_init (GtkProgressBarClass *klass);
+static void gtk_progress_bar_init (GtkProgressBar *pbar);
+static void gtk_progress_bar_realize (GtkWidget *widget);
+static void gtk_progress_bar_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static gint gtk_progress_bar_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+static void gtk_progress_bar_make_pixmap (GtkProgressBar *pbar);
+static void gtk_progress_bar_paint (GtkProgressBar *pbar);
+
+
+guint
+gtk_progress_bar_get_type ()
+{
+ static guint progress_bar_type = 0;
+
+ if (!progress_bar_type)
+ {
+ GtkTypeInfo progress_bar_info =
+ {
+ "GtkProgressBar",
+ sizeof (GtkProgressBar),
+ sizeof (GtkProgressBarClass),
+ (GtkClassInitFunc) gtk_progress_bar_class_init,
+ (GtkObjectInitFunc) gtk_progress_bar_init,
+ (GtkArgFunc) NULL,
+ };
+
+ progress_bar_type = gtk_type_unique (gtk_widget_get_type (), &progress_bar_info);
+ }
+
+ return progress_bar_type;
+}
+
+static void
+gtk_progress_bar_class_init (GtkProgressBarClass *class)
+{
+ GtkWidgetClass *widget_class;
+
+ widget_class = (GtkWidgetClass*) class;
+
+ widget_class->realize = gtk_progress_bar_realize;
+ widget_class->size_allocate = gtk_progress_bar_size_allocate;
+ widget_class->expose_event = gtk_progress_bar_expose;
+}
+
+static void
+gtk_progress_bar_init (GtkProgressBar *pbar)
+{
+ GTK_WIDGET_SET_FLAGS (pbar, GTK_BASIC);
+
+ GTK_WIDGET (pbar)->requisition.width = MIN_WIDTH;
+ GTK_WIDGET (pbar)->requisition.height = MIN_HEIGHT;
+ pbar->offscreen_pixmap = NULL;
+ pbar->percentage = 0;
+}
+
+
+GtkWidget*
+gtk_progress_bar_new ()
+{
+ return GTK_WIDGET (gtk_type_new (gtk_progress_bar_get_type ()));
+}
+
+void
+gtk_progress_bar_update (GtkProgressBar *pbar,
+ gfloat percentage)
+{
+ g_return_if_fail (pbar != NULL);
+ g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
+
+ if (percentage < 0.0)
+ percentage = 0.0;
+ else if (percentage > 1.0)
+ percentage = 1.0;
+
+ if (pbar->percentage != percentage)
+ {
+ pbar->percentage = percentage;
+ gtk_progress_bar_paint (pbar);
+ gtk_widget_queue_draw (GTK_WIDGET (pbar));
+ }
+}
+
+static void
+gtk_progress_bar_realize (GtkWidget *widget)
+{
+ GtkProgressBar *pbar;
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_PROGRESS_BAR (widget));
+
+ pbar = GTK_PROGRESS_BAR (widget);
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.x = widget->allocation.x;
+ attributes.y = widget->allocation.y;
+ attributes.width = widget->allocation.width;
+ attributes.height = widget->allocation.height;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
+ attributes.event_mask = gtk_widget_get_events (widget);
+ attributes.event_mask |= GDK_EXPOSURE_MASK;
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+
+ widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
+ gdk_window_set_user_data (widget->window, pbar);
+
+ widget->style = gtk_style_attach (widget->style, widget->window);
+ gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
+
+ gtk_progress_bar_make_pixmap (pbar);
+}
+
+static void
+gtk_progress_bar_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_PROGRESS_BAR (widget));
+ g_return_if_fail (allocation != NULL);
+
+ widget->allocation = *allocation;
+
+ if (GTK_WIDGET_REALIZED (widget))
+ {
+ gdk_window_move_resize (widget->window,
+ allocation->x, allocation->y,
+ allocation->width, allocation->height);
+
+ gtk_progress_bar_make_pixmap (GTK_PROGRESS_BAR (widget));
+ }
+}
+
+static gint
+gtk_progress_bar_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ GtkProgressBar *pbar;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_PROGRESS_BAR (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ pbar = GTK_PROGRESS_BAR (widget);
+
+ gdk_draw_pixmap (widget->window,
+ widget->style->black_gc,
+ pbar->offscreen_pixmap,
+ 0, 0, 0, 0,
+ widget->allocation.width,
+ widget->allocation.height);
+ }
+
+ return FALSE;
+}
+
+static void
+gtk_progress_bar_make_pixmap (GtkProgressBar *pbar)
+{
+ GtkWidget *widget;
+
+ g_return_if_fail (pbar != NULL);
+ g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
+
+ if (GTK_WIDGET_REALIZED (pbar))
+ {
+ widget = GTK_WIDGET (pbar);
+
+ if (pbar->offscreen_pixmap)
+ gdk_pixmap_destroy (pbar->offscreen_pixmap);
+
+ pbar->offscreen_pixmap = gdk_pixmap_new (widget->window,
+ widget->allocation.width,
+ widget->allocation.height,
+ -1);
+
+ gtk_progress_bar_paint (pbar);
+ }
+}
+
+static void
+gtk_progress_bar_paint (GtkProgressBar *pbar)
+{
+ GtkWidget *widget;
+ int amount;
+
+ g_return_if_fail (pbar != NULL);
+ g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
+
+ if (pbar->offscreen_pixmap)
+ {
+ widget = GTK_WIDGET (pbar);
+
+ gtk_draw_shadow (widget->style,
+ pbar->offscreen_pixmap,
+ GTK_STATE_NORMAL, GTK_SHADOW_IN, 0, 0,
+ widget->allocation.width,
+ widget->allocation.height);
+
+ gdk_draw_rectangle (pbar->offscreen_pixmap,
+ widget->style->bg_gc[GTK_STATE_ACTIVE], TRUE,
+ widget->style->klass->xthickness,
+ widget->style->klass->ythickness,
+ widget->allocation.width - widget->style->klass->xthickness * 2,
+ widget->allocation.height - widget->style->klass->ythickness * 2);
+
+
+ amount = pbar->percentage * (widget->allocation.width - widget->style->klass->xthickness * 2);
+ if (amount > 0)
+ {
+ gdk_draw_rectangle (pbar->offscreen_pixmap,
+ widget->style->bg_gc[GTK_STATE_PRELIGHT], TRUE,
+ widget->style->klass->xthickness,
+ widget->style->klass->ythickness,
+ amount,
+ widget->allocation.height - widget->style->klass->ythickness * 2);
+
+ gtk_draw_shadow (widget->style,
+ pbar->offscreen_pixmap,
+ GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
+ widget->style->klass->xthickness,
+ widget->style->klass->ythickness,
+ amount,
+ widget->allocation.height - widget->style->klass->ythickness * 2);
+ }
+ }
+}
diff --git a/gtk/gtkprogressbar.h b/gtk/gtkprogressbar.h
new file mode 100644
index 000000000..e831dfb97
--- /dev/null
+++ b/gtk/gtkprogressbar.h
@@ -0,0 +1,64 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_PROGRESS_BAR_H__
+#define __GTK_PROGRESS_BAR_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkwidget.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_PROGRESS_BAR(obj) GTK_CHECK_CAST (obj, gtk_progress_bar_get_type (), GtkProgressBar)
+#define GTK_PROGRESS_BAR_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_progress_bar_get_type (), GtkProgressBarClass)
+#define GTK_IS_PROGRESS_BAR(obj) GTK_CHECK_TYPE (obj, gtk_progress_bar_get_type ())
+
+
+typedef struct _GtkProgressBar GtkProgressBar;
+typedef struct _GtkProgressBarClass GtkProgressBarClass;
+
+struct _GtkProgressBar
+{
+ GtkWidget widget;
+
+ GdkPixmap *offscreen_pixmap;
+ gfloat percentage;
+};
+
+struct _GtkProgressBarClass
+{
+ GtkWidgetClass parent_class;
+};
+
+
+guint gtk_progress_bar_get_type (void);
+GtkWidget* gtk_progress_bar_new (void);
+void gtk_progress_bar_update (GtkProgressBar *pbar,
+ gfloat percentage);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_PROGRESS_BAR_H__ */
diff --git a/gtk/gtkradiobutton.c b/gtk/gtkradiobutton.c
new file mode 100644
index 000000000..0c52836e9
--- /dev/null
+++ b/gtk/gtkradiobutton.c
@@ -0,0 +1,321 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtklabel.h"
+#include "gtkradiobutton.h"
+#include "gtksignal.h"
+
+
+#define CHECK_BUTTON_CLASS(w) GTK_CHECK_BUTTON_CLASS (GTK_OBJECT (w)->klass)
+
+
+static void gtk_radio_button_class_init (GtkRadioButtonClass *klass);
+static void gtk_radio_button_init (GtkRadioButton *radio_button);
+static void gtk_radio_button_destroy (GtkObject *object);
+static void gtk_radio_button_clicked (GtkButton *button);
+static void gtk_radio_button_draw_indicator (GtkCheckButton *check_button,
+ GdkRectangle *area);
+
+
+static GtkCheckButtonClass *parent_class = NULL;
+
+
+guint
+gtk_radio_button_get_type ()
+{
+ static guint radio_button_type = 0;
+
+ if (!radio_button_type)
+ {
+ GtkTypeInfo radio_button_info =
+ {
+ "GtkRadioButton",
+ sizeof (GtkRadioButton),
+ sizeof (GtkRadioButtonClass),
+ (GtkClassInitFunc) gtk_radio_button_class_init,
+ (GtkObjectInitFunc) gtk_radio_button_init,
+ (GtkArgFunc) NULL,
+ };
+
+ radio_button_type = gtk_type_unique (gtk_check_button_get_type (), &radio_button_info);
+ }
+
+ return radio_button_type;
+}
+
+static void
+gtk_radio_button_class_init (GtkRadioButtonClass *class)
+{
+ GtkObjectClass *object_class;
+ GtkButtonClass *button_class;
+ GtkCheckButtonClass *check_button_class;
+
+ object_class = (GtkObjectClass*) class;
+ button_class = (GtkButtonClass*) class;
+ check_button_class = (GtkCheckButtonClass*) class;
+
+ parent_class = gtk_type_class (gtk_check_button_get_type ());
+
+ object_class->destroy = gtk_radio_button_destroy;
+
+ button_class->clicked = gtk_radio_button_clicked;
+
+ check_button_class->draw_indicator = gtk_radio_button_draw_indicator;
+}
+
+static void
+gtk_radio_button_init (GtkRadioButton *radio_button)
+{
+ radio_button->group = NULL;
+}
+
+GtkWidget*
+gtk_radio_button_new (GSList *group)
+{
+ GtkRadioButton *radio_button;
+ GtkRadioButton *tmp_button;
+ GSList *tmp_list;
+
+ radio_button = gtk_type_new (gtk_radio_button_get_type ());
+
+ tmp_list = group;
+ radio_button->group = g_slist_prepend (group, radio_button);
+
+ if (tmp_list)
+ {
+ while (tmp_list)
+ {
+ tmp_button = tmp_list->data;
+ tmp_list = tmp_list->next;
+
+ tmp_button->group = radio_button->group;
+ }
+ }
+ else
+ {
+ GTK_TOGGLE_BUTTON (radio_button)->active = TRUE;
+ gtk_widget_set_state (GTK_WIDGET (radio_button), GTK_STATE_ACTIVE);
+ }
+
+ return GTK_WIDGET (radio_button);
+}
+
+GtkWidget*
+gtk_radio_button_new_with_label (GSList *group,
+ const gchar *label)
+{
+ GtkWidget *radio_button;
+ GtkWidget *label_widget;
+
+ radio_button = gtk_radio_button_new (group);
+ label_widget = gtk_label_new (label);
+ gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
+
+ gtk_container_add (GTK_CONTAINER (radio_button), label_widget);
+ gtk_widget_show (label_widget);
+
+ return radio_button;
+}
+
+GtkWidget*
+gtk_radio_button_new_from_widget (GtkRadioButton *group)
+{
+ GSList *l = NULL;
+ if (group)
+ l = gtk_radio_button_group (group);
+ return gtk_radio_button_new (l);
+}
+
+
+GtkWidget*
+gtk_radio_button_new_with_label_from_widget (GtkRadioButton *group,
+ const gchar *label)
+{
+ GSList *l = NULL;
+ if (group)
+ l = gtk_radio_button_group (group);
+ return gtk_radio_button_new_with_label (l, label);
+}
+
+GSList*
+gtk_radio_button_group (GtkRadioButton *radio_button)
+{
+ g_return_val_if_fail (radio_button != NULL, NULL);
+ g_return_val_if_fail (GTK_IS_RADIO_BUTTON (radio_button), NULL);
+
+ return radio_button->group;
+}
+
+
+static void
+gtk_radio_button_destroy (GtkObject *object)
+{
+ GtkRadioButton *radio_button;
+ GtkRadioButton *tmp_button;
+ GSList *tmp_list;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_RADIO_BUTTON (object));
+
+ radio_button = GTK_RADIO_BUTTON (object);
+
+ radio_button->group = g_slist_remove (radio_button->group, radio_button);
+ tmp_list = radio_button->group;
+
+ while (tmp_list)
+ {
+ tmp_button = tmp_list->data;
+ tmp_list = tmp_list->next;
+
+ tmp_button->group = radio_button->group;
+ }
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+static void
+gtk_radio_button_clicked (GtkButton *button)
+{
+ GtkToggleButton *toggle_button;
+ GtkRadioButton *radio_button;
+ GtkToggleButton *tmp_button;
+ GtkStateType new_state;
+ GSList *tmp_list;
+ gint toggled;
+
+ g_return_if_fail (button != NULL);
+ g_return_if_fail (GTK_IS_RADIO_BUTTON (button));
+
+ radio_button = GTK_RADIO_BUTTON (button);
+ toggle_button = GTK_TOGGLE_BUTTON (button);
+ toggled = FALSE;
+
+ if (toggle_button->active)
+ {
+ tmp_button = NULL;
+ tmp_list = radio_button->group;
+
+ while (tmp_list)
+ {
+ tmp_button = tmp_list->data;
+ tmp_list = tmp_list->next;
+
+ if (tmp_button->active && (tmp_button != toggle_button))
+ break;
+
+ tmp_button = NULL;
+ }
+
+ if (!tmp_button)
+ {
+ new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_ACTIVE);
+ }
+ else
+ {
+ toggled = TRUE;
+ toggle_button->active = !toggle_button->active;
+ new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL);
+ }
+ }
+ else
+ {
+ toggled = TRUE;
+ toggle_button->active = !toggle_button->active;
+
+ tmp_list = radio_button->group;
+ while (tmp_list)
+ {
+ tmp_button = tmp_list->data;
+ tmp_list = tmp_list->next;
+
+ if (tmp_button->active && (tmp_button != toggle_button))
+ {
+ gtk_button_clicked (GTK_BUTTON (tmp_button));
+ break;
+ }
+ }
+
+ new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_ACTIVE);
+ }
+
+ if (GTK_WIDGET_STATE (button) != new_state)
+ gtk_widget_set_state (GTK_WIDGET (button), new_state);
+ if (toggled)
+ gtk_toggle_button_toggled (toggle_button);
+ gtk_widget_queue_draw (GTK_WIDGET (button));
+}
+
+static void
+gtk_radio_button_draw_indicator (GtkCheckButton *check_button,
+ GdkRectangle *area)
+{
+ GtkWidget *widget;
+ GtkButton *button;
+ GtkToggleButton *toggle_button;
+ GtkStateType state_type;
+ GtkShadowType shadow_type;
+ GdkPoint pts[4];
+ gint width, height;
+ gint x, y;
+
+ g_return_if_fail (check_button != NULL);
+ g_return_if_fail (GTK_IS_RADIO_BUTTON (check_button));
+
+ if (GTK_WIDGET_VISIBLE (check_button) && GTK_WIDGET_MAPPED (check_button))
+ {
+ widget = GTK_WIDGET (check_button);
+ button = GTK_BUTTON (check_button);
+ toggle_button = GTK_TOGGLE_BUTTON (check_button);
+
+ state_type = GTK_WIDGET_STATE (widget);
+ if ((state_type != GTK_STATE_NORMAL) &&
+ (state_type != GTK_STATE_PRELIGHT))
+ state_type = GTK_STATE_NORMAL;
+
+ gtk_style_set_background (widget->style, widget->window, state_type);
+ gdk_window_clear_area (widget->window, area->x, area->y, area->width, area->height);
+
+ x = CHECK_BUTTON_CLASS (widget)->indicator_spacing + GTK_CONTAINER (widget)->border_width;
+ y = (widget->allocation.height - CHECK_BUTTON_CLASS (widget)->indicator_size) / 2;
+ width = CHECK_BUTTON_CLASS (widget)->indicator_size;
+ height = CHECK_BUTTON_CLASS (widget)->indicator_size;
+
+ if (GTK_WIDGET_STATE (widget) == GTK_STATE_ACTIVE)
+ shadow_type = GTK_SHADOW_IN;
+ else if ((GTK_WIDGET_STATE (widget) == GTK_STATE_PRELIGHT) && toggle_button->active)
+ shadow_type = GTK_SHADOW_IN;
+ else
+ shadow_type = GTK_SHADOW_OUT;
+
+ pts[0].x = x + width / 2;
+ pts[0].y = y;
+ pts[1].x = x + width;
+ pts[1].y = y + height / 2;
+ pts[2].x = pts[0].x;
+ pts[2].y = y + height;
+ pts[3].x = x;
+ pts[3].y = pts[1].y;
+
+ gdk_draw_polygon (widget->window,
+ widget->style->bg_gc[GTK_WIDGET_STATE (widget)],
+ TRUE, pts, 4);
+ gtk_draw_diamond (widget->style, widget->window,
+ GTK_WIDGET_STATE (widget), shadow_type,
+ x, y, width, height);
+ }
+}
diff --git a/gtk/gtkradiobutton.h b/gtk/gtkradiobutton.h
new file mode 100644
index 000000000..bf346c27e
--- /dev/null
+++ b/gtk/gtkradiobutton.h
@@ -0,0 +1,69 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_RADIO_BUTTON_H__
+#define __GTK_RADIO_BUTTON_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkcheckbutton.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_RADIO_BUTTON(obj) GTK_CHECK_CAST (obj, gtk_radio_button_get_type (), GtkRadioButton)
+#define GTK_RADIO_BUTTON_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_radio_button_get_type (), GtkRadioButtonClass)
+#define GTK_IS_RADIO_BUTTON(obj) GTK_CHECK_TYPE (obj, gtk_radio_button_get_type ())
+
+
+typedef struct _GtkRadioButton GtkRadioButton;
+typedef struct _GtkRadioButtonClass GtkRadioButtonClass;
+
+struct _GtkRadioButton
+{
+ GtkCheckButton check_button;
+
+ GSList *group;
+};
+
+struct _GtkRadioButtonClass
+{
+ GtkCheckButtonClass parent_class;
+};
+
+
+guint gtk_radio_button_get_type (void);
+GtkWidget* gtk_radio_button_new (GSList *group);
+GtkWidget* gtk_radio_button_new_from_widget (GtkRadioButton *group);
+GtkWidget* gtk_radio_button_new_with_label (GSList *group,
+ const gchar *label);
+GtkWidget* gtk_radio_button_new_interp (GtkRadioButton *group);
+GtkWidget* gtk_radio_button_new_with_label_interp
+ (GtkRadioButton *group,
+ const gchar *label);
+GSList* gtk_radio_button_group (GtkRadioButton *radio_button);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_RADIO_BUTTON_H__ */
diff --git a/gtk/gtkradiomenuitem.c b/gtk/gtkradiomenuitem.c
new file mode 100644
index 000000000..edfcff673
--- /dev/null
+++ b/gtk/gtkradiomenuitem.c
@@ -0,0 +1,240 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtklabel.h"
+#include "gtkradiomenuitem.h"
+
+
+static void gtk_radio_menu_item_class_init (GtkRadioMenuItemClass *klass);
+static void gtk_radio_menu_item_init (GtkRadioMenuItem *radio_menu_item);
+static void gtk_radio_menu_item_activate (GtkMenuItem *menu_item);
+static void gtk_radio_menu_item_draw_indicator (GtkCheckMenuItem *check_menu_item,
+ GdkRectangle *area);
+
+
+guint
+gtk_radio_menu_item_get_type ()
+{
+ static guint radio_menu_item_type = 0;
+
+ if (!radio_menu_item_type)
+ {
+ GtkTypeInfo radio_menu_item_info =
+ {
+ "GtkRadioMenuItem",
+ sizeof (GtkRadioMenuItem),
+ sizeof (GtkRadioMenuItemClass),
+ (GtkClassInitFunc) gtk_radio_menu_item_class_init,
+ (GtkObjectInitFunc) gtk_radio_menu_item_init,
+ (GtkArgFunc) NULL,
+ };
+
+ radio_menu_item_type = gtk_type_unique (gtk_check_menu_item_get_type (), &radio_menu_item_info);
+ }
+
+ return radio_menu_item_type;
+}
+
+GtkWidget*
+gtk_radio_menu_item_new (GSList *group)
+{
+ GtkRadioMenuItem *radio_menu_item;
+ GtkRadioMenuItem *tmp_menu_item;
+ GSList *tmp_list;
+
+ radio_menu_item = gtk_type_new (gtk_radio_menu_item_get_type ());
+
+ tmp_list = group;
+ radio_menu_item->group = g_slist_prepend (group, radio_menu_item);
+
+ if (tmp_list)
+ {
+ while (tmp_list)
+ {
+ tmp_menu_item = tmp_list->data;
+ tmp_list = tmp_list->next;
+
+ tmp_menu_item->group = radio_menu_item->group;
+ }
+ }
+ else
+ {
+ GTK_CHECK_MENU_ITEM (radio_menu_item)->active = TRUE;
+ }
+
+ return GTK_WIDGET (radio_menu_item);
+}
+
+GtkWidget*
+gtk_radio_menu_item_new_with_label (GSList *group,
+ const gchar *label)
+{
+ GtkWidget *radio_menu_item;
+ GtkWidget *label_widget;
+
+ radio_menu_item = gtk_radio_menu_item_new (group);
+ label_widget = gtk_label_new (label);
+ gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
+
+ gtk_container_add (GTK_CONTAINER (radio_menu_item), label_widget);
+ gtk_widget_show (label_widget);
+
+ return radio_menu_item;
+}
+
+GSList*
+gtk_radio_menu_item_group (GtkRadioMenuItem *radio_menu_item)
+{
+ g_return_val_if_fail (radio_menu_item != NULL, NULL);
+ g_return_val_if_fail (GTK_IS_RADIO_MENU_ITEM (radio_menu_item), NULL);
+
+ return radio_menu_item->group;
+}
+
+
+static void
+gtk_radio_menu_item_class_init (GtkRadioMenuItemClass *klass)
+{
+ GtkMenuItemClass *menu_item_class;
+ GtkCheckMenuItemClass *check_menu_item_class;
+
+ menu_item_class = (GtkMenuItemClass*) klass;
+ check_menu_item_class = (GtkCheckMenuItemClass*) klass;
+
+ menu_item_class->activate = gtk_radio_menu_item_activate;
+
+ check_menu_item_class->draw_indicator = gtk_radio_menu_item_draw_indicator;
+}
+
+static void
+gtk_radio_menu_item_init (GtkRadioMenuItem *radio_menu_item)
+{
+ radio_menu_item->group = NULL;
+}
+
+static void
+gtk_radio_menu_item_activate (GtkMenuItem *menu_item)
+{
+ GtkRadioMenuItem *radio_menu_item;
+ GtkCheckMenuItem *check_menu_item;
+ GtkCheckMenuItem *tmp_menu_item;
+ GSList *tmp_list;
+ gint toggled;
+
+ g_return_if_fail (menu_item != NULL);
+ g_return_if_fail (GTK_IS_RADIO_MENU_ITEM (menu_item));
+
+ radio_menu_item = GTK_RADIO_MENU_ITEM (menu_item);
+ check_menu_item = GTK_CHECK_MENU_ITEM (menu_item);
+ toggled = FALSE;
+
+ if (check_menu_item->active)
+ {
+ tmp_menu_item = NULL;
+ tmp_list = radio_menu_item->group;
+
+ while (tmp_list)
+ {
+ tmp_menu_item = tmp_list->data;
+ tmp_list = tmp_list->next;
+
+ if (tmp_menu_item->active && (tmp_menu_item != check_menu_item))
+ break;
+
+ tmp_menu_item = NULL;
+ }
+
+ if (tmp_menu_item)
+ {
+ toggled = TRUE;
+ check_menu_item->active = !check_menu_item->active;
+ }
+ }
+ else
+ {
+ toggled = TRUE;
+ check_menu_item->active = !check_menu_item->active;
+
+ tmp_list = radio_menu_item->group;
+ while (tmp_list)
+ {
+ tmp_menu_item = tmp_list->data;
+ tmp_list = tmp_list->next;
+
+ if (tmp_menu_item->active && (tmp_menu_item != check_menu_item))
+ {
+ gtk_menu_item_activate (GTK_MENU_ITEM (tmp_menu_item));
+ break;
+ }
+ }
+ }
+
+ if (toggled)
+ gtk_check_menu_item_toggled (check_menu_item);
+ gtk_widget_queue_draw (GTK_WIDGET (radio_menu_item));
+}
+
+static void
+gtk_radio_menu_item_draw_indicator (GtkCheckMenuItem *check_menu_item,
+ GdkRectangle *area)
+{
+ GtkWidget *widget;
+ GtkStateType state_type;
+ GtkShadowType shadow_type;
+ GdkPoint pts[4];
+ gint width, height;
+ gint x, y;
+
+ g_return_if_fail (check_menu_item != NULL);
+ g_return_if_fail (GTK_IS_RADIO_MENU_ITEM (check_menu_item));
+
+ if (GTK_WIDGET_DRAWABLE (check_menu_item))
+ {
+ widget = GTK_WIDGET (check_menu_item);
+
+ width = 8;
+ height = 8;
+ x = (GTK_CONTAINER (check_menu_item)->border_width +
+ widget->style->klass->xthickness + 2);
+ y = (widget->allocation.height - height) / 2;
+
+ gdk_window_clear_area (widget->window, x, y, width, height);
+
+ if (check_menu_item->active ||
+ (GTK_WIDGET_STATE (check_menu_item) == GTK_STATE_PRELIGHT))
+ {
+ state_type = GTK_WIDGET_STATE (widget);
+ shadow_type = GTK_SHADOW_IN;
+
+ pts[0].x = x + width / 2;
+ pts[0].y = y;
+ pts[1].x = x + width;
+ pts[1].y = y + height / 2;
+ pts[2].x = pts[0].x;
+ pts[2].y = y + height;
+ pts[3].x = x;
+ pts[3].y = pts[1].y;
+
+ gdk_draw_polygon (widget->window,
+ widget->style->bg_gc[state_type],
+ TRUE, pts, 4);
+ gtk_draw_diamond (widget->style, widget->window,
+ state_type, shadow_type,
+ x, y, width, height);
+ }
+ }
+}
diff --git a/gtk/gtkradiomenuitem.h b/gtk/gtkradiomenuitem.h
new file mode 100644
index 000000000..28abafc6b
--- /dev/null
+++ b/gtk/gtkradiomenuitem.h
@@ -0,0 +1,64 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_RADIO_MENU_ITEM_H__
+#define __GTK_RADIO_MENU_ITEM_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkcheckmenuitem.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_RADIO_MENU_ITEM(obj) GTK_CHECK_CAST (obj, gtk_radio_menu_item_get_type (), GtkRadioMenuItem)
+#define GTK_RADIO_MENU_ITEM_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_radio_menu_item_get_type (), GtkRadioMenuItemClass)
+#define GTK_IS_RADIO_MENU_ITEM(obj) GTK_CHECK_TYPE (obj, gtk_radio_menu_item_get_type ())
+
+
+typedef struct _GtkRadioMenuItem GtkRadioMenuItem;
+typedef struct _GtkRadioMenuItemClass GtkRadioMenuItemClass;
+
+struct _GtkRadioMenuItem
+{
+ GtkCheckMenuItem check_menu_item;
+
+ GSList *group;
+};
+
+struct _GtkRadioMenuItemClass
+{
+ GtkCheckMenuItemClass parent_class;
+};
+
+
+guint gtk_radio_menu_item_get_type (void);
+GtkWidget* gtk_radio_menu_item_new (GSList *group);
+GtkWidget* gtk_radio_menu_item_new_with_label (GSList *group,
+ const gchar *label);
+GSList* gtk_radio_menu_item_group (GtkRadioMenuItem *radio_menu_item);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_RADIO_MENU_ITEM_H__ */
diff --git a/gtk/gtkrange.c b/gtk/gtkrange.c
new file mode 100644
index 000000000..f00bbf683
--- /dev/null
+++ b/gtk/gtkrange.c
@@ -0,0 +1,1369 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdio.h>
+#include "gtkmain.h"
+#include "gtkrange.h"
+#include "gtksignal.h"
+
+
+#define SCROLL_TIMER_LENGTH 20
+#define SCROLL_INITIAL_DELAY 100
+#define SCROLL_DELAY_LENGTH 300
+
+#define RANGE_CLASS(w) GTK_RANGE_CLASS (GTK_OBJECT (w)->klass)
+
+
+static void gtk_range_class_init (GtkRangeClass *klass);
+static void gtk_range_init (GtkRange *range);
+static void gtk_range_destroy (GtkObject *object);
+static void gtk_range_draw (GtkWidget *widget,
+ GdkRectangle *area);
+static void gtk_range_draw_focus (GtkWidget *widget);
+static void gtk_range_unrealize (GtkWidget *widget);
+static gint gtk_range_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+static gint gtk_range_button_press (GtkWidget *widget,
+ GdkEventButton *event);
+static gint gtk_range_button_release (GtkWidget *widget,
+ GdkEventButton *event);
+static gint gtk_range_motion_notify (GtkWidget *widget,
+ GdkEventMotion *event);
+static gint gtk_range_key_press (GtkWidget *widget,
+ GdkEventKey *event);
+static gint gtk_range_enter_notify (GtkWidget *widget,
+ GdkEventCrossing *event);
+static gint gtk_range_leave_notify (GtkWidget *widget,
+ GdkEventCrossing *event);
+static gint gtk_range_focus_in (GtkWidget *widget,
+ GdkEventFocus *event);
+static gint gtk_range_focus_out (GtkWidget *widget,
+ GdkEventFocus *event);
+static void gtk_real_range_draw_trough (GtkRange *range);
+static void gtk_real_range_draw_slider (GtkRange *range);
+static gint gtk_real_range_timer (GtkRange *range);
+static gint gtk_range_scroll (GtkRange *range);
+
+static void gtk_range_add_timer (GtkRange *range);
+static void gtk_range_remove_timer (GtkRange *range);
+
+static void gtk_range_adjustment_changed (GtkAdjustment *adjustment,
+ gpointer data);
+static void gtk_range_adjustment_value_changed (GtkAdjustment *adjustment,
+ gpointer data);
+
+static void gtk_range_trough_hdims (GtkRange *range,
+ gint *left,
+ gint *right);
+static void gtk_range_trough_vdims (GtkRange *range,
+ gint *top,
+ gint *bottom);
+
+static GtkWidgetClass *parent_class = NULL;
+
+
+guint
+gtk_range_get_type ()
+{
+ static guint range_type = 0;
+
+ if (!range_type)
+ {
+ GtkTypeInfo range_info =
+ {
+ "GtkRange",
+ sizeof (GtkRange),
+ sizeof (GtkRangeClass),
+ (GtkClassInitFunc) gtk_range_class_init,
+ (GtkObjectInitFunc) gtk_range_init,
+ (GtkArgFunc) NULL,
+ };
+
+ range_type = gtk_type_unique (gtk_widget_get_type (), &range_info);
+ }
+
+ return range_type;
+}
+
+static void
+gtk_range_class_init (GtkRangeClass *class)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+
+ object_class = (GtkObjectClass*) class;
+ widget_class = (GtkWidgetClass*) class;
+
+ parent_class = gtk_type_class (gtk_widget_get_type ());
+
+ object_class->destroy = gtk_range_destroy;
+
+ widget_class->draw = gtk_range_draw;
+ widget_class->draw_focus = gtk_range_draw_focus;
+ widget_class->unrealize = gtk_range_unrealize;
+ widget_class->expose_event = gtk_range_expose;
+ widget_class->button_press_event = gtk_range_button_press;
+ widget_class->button_release_event = gtk_range_button_release;
+ widget_class->motion_notify_event = gtk_range_motion_notify;
+ widget_class->key_press_event = gtk_range_key_press;
+ widget_class->enter_notify_event = gtk_range_enter_notify;
+ widget_class->leave_notify_event = gtk_range_leave_notify;
+ widget_class->focus_in_event = gtk_range_focus_in;
+ widget_class->focus_out_event = gtk_range_focus_out;
+
+ class->slider_width = 11;
+ class->stepper_size = 11;
+ class->stepper_slider_spacing = 1;
+ class->min_slider_size = 7;
+ class->trough = 1;
+ class->slider = 2;
+ class->step_forw = 3;
+ class->step_back = 4;
+ class->draw_background = NULL;
+ class->draw_trough = gtk_real_range_draw_trough;
+ class->draw_slider = gtk_real_range_draw_slider;
+ class->draw_step_forw = NULL;
+ class->draw_step_back = NULL;
+ class->trough_click = NULL;
+ class->trough_keys = NULL;
+ class->motion = NULL;
+ class->timer = gtk_real_range_timer;
+}
+
+static void
+gtk_range_init (GtkRange *range)
+{
+ range->trough = NULL;
+ range->slider = NULL;
+ range->step_forw = NULL;
+ range->step_back = NULL;
+
+ range->x_click_point = 0;
+ range->y_click_point = 0;
+ range->button = 0;
+ range->digits = -1;
+ range->policy = GTK_UPDATE_CONTINUOUS;
+ range->scroll_type = GTK_SCROLL_NONE;
+ range->in_child = 0;
+ range->click_child = 0;
+ range->need_timer = FALSE;
+ range->timer = 0;
+ range->old_value = 0.0;
+ range->old_lower = 0.0;
+ range->old_upper = 0.0;
+ range->old_page_size = 0.0;
+ range->adjustment = NULL;
+}
+
+GtkAdjustment*
+gtk_range_get_adjustment (GtkRange *range)
+{
+ g_return_val_if_fail (range != NULL, NULL);
+ g_return_val_if_fail (GTK_IS_RANGE (range), NULL);
+
+ return range->adjustment;
+}
+
+void
+gtk_range_set_update_policy (GtkRange *range,
+ GtkUpdateType policy)
+{
+ g_return_if_fail (range != NULL);
+ g_return_if_fail (GTK_IS_RANGE (range));
+
+ range->policy = policy;
+}
+
+void
+gtk_range_set_adjustment (GtkRange *range,
+ GtkAdjustment *adjustment)
+{
+ g_return_if_fail (range != NULL);
+ g_return_if_fail (GTK_IS_RANGE (range));
+
+ if (range->adjustment)
+ {
+ gtk_signal_disconnect_by_data (GTK_OBJECT (range->adjustment), (gpointer) range);
+ gtk_object_unref (GTK_OBJECT (range->adjustment));
+ }
+
+ range->adjustment = adjustment;
+ gtk_object_ref (GTK_OBJECT (range->adjustment));
+
+ gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
+ (GtkSignalFunc) gtk_range_adjustment_changed,
+ (gpointer) range);
+ gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
+ (GtkSignalFunc) gtk_range_adjustment_value_changed,
+ (gpointer) range);
+
+ range->old_value = adjustment->value;
+ range->old_lower = adjustment->lower;
+ range->old_upper = adjustment->upper;
+ range->old_page_size = adjustment->page_size;
+
+ gtk_range_adjustment_changed (range->adjustment, (gpointer) range);
+}
+
+void
+gtk_range_draw_background (GtkRange *range)
+{
+ g_return_if_fail (range != NULL);
+ g_return_if_fail (GTK_IS_RANGE (range));
+
+ if (range->trough && RANGE_CLASS (range)->draw_background)
+ (* RANGE_CLASS (range)->draw_background) (range);
+}
+
+void
+gtk_range_draw_trough (GtkRange *range)
+{
+ g_return_if_fail (range != NULL);
+ g_return_if_fail (GTK_IS_RANGE (range));
+
+ if (range->trough && RANGE_CLASS (range)->draw_trough)
+ (* RANGE_CLASS (range)->draw_trough) (range);
+}
+
+void
+gtk_range_draw_slider (GtkRange *range)
+{
+ g_return_if_fail (range != NULL);
+ g_return_if_fail (GTK_IS_RANGE (range));
+
+ if (range->slider && RANGE_CLASS (range)->draw_slider)
+ (* RANGE_CLASS (range)->draw_slider) (range);
+}
+
+void
+gtk_range_draw_step_forw (GtkRange *range)
+{
+ g_return_if_fail (range != NULL);
+ g_return_if_fail (GTK_IS_RANGE (range));
+
+ if (range->step_forw && RANGE_CLASS (range)->draw_step_forw)
+ (* RANGE_CLASS (range)->draw_step_forw) (range);
+}
+
+void
+gtk_range_draw_step_back (GtkRange *range)
+{
+ g_return_if_fail (range != NULL);
+ g_return_if_fail (GTK_IS_RANGE (range));
+
+ if (range->step_back && RANGE_CLASS (range)->draw_step_back)
+ (* RANGE_CLASS (range)->draw_step_back) (range);
+}
+
+void
+gtk_range_slider_update (GtkRange *range)
+{
+ g_return_if_fail (range != NULL);
+ g_return_if_fail (GTK_IS_RANGE (range));
+
+ if (RANGE_CLASS (range)->slider_update)
+ (* RANGE_CLASS (range)->slider_update) (range);
+}
+
+gint
+gtk_range_trough_click (GtkRange *range,
+ gint x,
+ gint y)
+{
+ g_return_val_if_fail (range != NULL, GTK_TROUGH_NONE);
+ g_return_val_if_fail (GTK_IS_RANGE (range), GTK_TROUGH_NONE);
+
+ if (RANGE_CLASS (range)->trough_click)
+ return (* RANGE_CLASS (range)->trough_click) (range, x, y);
+
+ return GTK_TROUGH_NONE;
+}
+
+void
+gtk_range_default_hslider_update (GtkRange *range)
+{
+ gint left;
+ gint right;
+ gint x;
+
+ g_return_if_fail (range != NULL);
+ g_return_if_fail (GTK_IS_RANGE (range));
+
+ if (GTK_WIDGET_REALIZED (range))
+ {
+ gtk_range_trough_hdims (range, &left, &right);
+ x = left;
+
+ if (range->adjustment->value < range->adjustment->lower)
+ {
+ range->adjustment->value = range->adjustment->lower;
+ gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
+ }
+ else if (range->adjustment->value > range->adjustment->upper)
+ {
+ range->adjustment->value = range->adjustment->upper;
+ gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
+ }
+
+ if (range->adjustment->lower != (range->adjustment->upper - range->adjustment->page_size))
+ x += ((right - left) * (range->adjustment->value - range->adjustment->lower) /
+ (range->adjustment->upper - range->adjustment->lower - range->adjustment->page_size));
+
+ if (x < left)
+ x = left;
+ else if (x > right)
+ x = right;
+
+ gdk_window_move (range->slider, x, GTK_WIDGET (range)->style->klass->ythickness);
+ }
+}
+
+void
+gtk_range_default_vslider_update (GtkRange *range)
+{
+ gint top;
+ gint bottom;
+ gint y;
+
+ g_return_if_fail (range != NULL);
+ g_return_if_fail (GTK_IS_RANGE (range));
+
+ if (GTK_WIDGET_REALIZED (range))
+ {
+ gtk_range_trough_vdims (range, &top, &bottom);
+ y = top;
+
+ if (range->adjustment->value < range->adjustment->lower)
+ {
+ range->adjustment->value = range->adjustment->lower;
+ gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
+ }
+ else if (range->adjustment->value > range->adjustment->upper)
+ {
+ range->adjustment->value = range->adjustment->upper;
+ gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
+ }
+
+ if (range->adjustment->lower != (range->adjustment->upper - range->adjustment->page_size))
+ y += ((bottom - top) * (range->adjustment->value - range->adjustment->lower) /
+ (range->adjustment->upper - range->adjustment->lower - range->adjustment->page_size));
+
+ if (y < top)
+ y = top;
+ else if (y > bottom)
+ y = bottom;
+
+ gdk_window_move (range->slider, GTK_WIDGET (range)->style->klass->ythickness, y);
+ }
+}
+
+gint
+gtk_range_default_htrough_click (GtkRange *range,
+ gint x,
+ gint y)
+{
+ gint xthickness;
+ gint ythickness;
+ gint trough_width;
+ gint trough_height;
+ gint slider_x;
+
+ g_return_val_if_fail (range != NULL, GTK_TROUGH_NONE);
+ g_return_val_if_fail (GTK_IS_RANGE (range), GTK_TROUGH_NONE);
+
+ xthickness = GTK_WIDGET (range)->style->klass->xthickness;
+ ythickness = GTK_WIDGET (range)->style->klass->ythickness;
+
+ if ((x > xthickness) && (y > ythickness))
+ {
+ gdk_window_get_size (range->trough, &trough_width, &trough_height);
+
+ if ((x < (trough_width - xthickness) && (y < (trough_height - ythickness))))
+ {
+ gdk_window_get_position (range->slider, &slider_x, NULL);
+
+ if (x < slider_x)
+ return GTK_TROUGH_START;
+ else
+ return GTK_TROUGH_END;
+ }
+ }
+
+ return GTK_TROUGH_NONE;
+}
+
+gint
+gtk_range_default_vtrough_click (GtkRange *range,
+ gint x,
+ gint y)
+{
+ gint xthickness;
+ gint ythickness;
+ gint trough_width;
+ gint trough_height;
+ gint slider_y;
+
+ g_return_val_if_fail (range != NULL, GTK_TROUGH_NONE);
+ g_return_val_if_fail (GTK_IS_RANGE (range), GTK_TROUGH_NONE);
+
+ xthickness = GTK_WIDGET (range)->style->klass->xthickness;
+ ythickness = GTK_WIDGET (range)->style->klass->ythickness;
+
+ if ((x > xthickness) && (y > ythickness))
+ {
+ gdk_window_get_size (range->trough, &trough_width, &trough_height);
+
+ if ((x < (trough_width - xthickness) && (y < (trough_height - ythickness))))
+ {
+ gdk_window_get_position (range->slider, NULL, &slider_y);
+
+ if (y < slider_y)
+ return GTK_TROUGH_START;
+ else
+ return GTK_TROUGH_END;
+ }
+ }
+
+ return GTK_TROUGH_NONE;
+}
+
+void
+gtk_range_default_hmotion (GtkRange *range,
+ gint xdelta,
+ gint ydelta)
+{
+ gdouble old_value;
+ gint left, right;
+ gint slider_x, slider_y;
+ gint new_pos;
+
+ g_return_if_fail (range != NULL);
+ g_return_if_fail (GTK_IS_RANGE (range));
+
+ range = GTK_RANGE (range);
+
+ gdk_window_get_position (range->slider, &slider_x, &slider_y);
+ gtk_range_trough_hdims (range, &left, &right);
+
+ if (left == right)
+ return;
+
+ new_pos = slider_x + xdelta;
+
+ if (new_pos < left)
+ new_pos = left;
+ else if (new_pos > right)
+ new_pos = right;
+
+ old_value = range->adjustment->value;
+ range->adjustment->value = ((range->adjustment->upper -
+ range->adjustment->lower -
+ range->adjustment->page_size) *
+ (new_pos - left) / (right - left) +
+ range->adjustment->lower);
+
+ if (range->digits >= 0)
+ {
+ char buffer[64];
+
+ sprintf (buffer, "%0.*f", range->digits, range->adjustment->value);
+ sscanf (buffer, "%f", &range->adjustment->value);
+ }
+
+ if (old_value != range->adjustment->value)
+ {
+ if (range->policy == GTK_UPDATE_CONTINUOUS)
+ {
+ gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
+ }
+ else
+ {
+ gtk_range_slider_update (range);
+ gtk_range_draw_background (range);
+
+ if (range->policy == GTK_UPDATE_DELAYED)
+ {
+ gtk_range_remove_timer (range);
+ range->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
+ (GtkFunction) RANGE_CLASS (range)->timer,
+ (gpointer) range);
+ }
+ }
+ }
+}
+
+void
+gtk_range_default_vmotion (GtkRange *range,
+ gint xdelta,
+ gint ydelta)
+{
+ gdouble old_value;
+ gint top, bottom;
+ gint slider_x, slider_y;
+ gint new_pos;
+
+ g_return_if_fail (range != NULL);
+ g_return_if_fail (GTK_IS_RANGE (range));
+
+ range = GTK_RANGE (range);
+
+ gdk_window_get_position (range->slider, &slider_x, &slider_y);
+ gtk_range_trough_vdims (range, &top, &bottom);
+
+ if (bottom == top)
+ return;
+
+ new_pos = slider_y + ydelta;
+
+ if (new_pos < top)
+ new_pos = top;
+ else if (new_pos > bottom)
+ new_pos = bottom;
+
+ old_value = range->adjustment->value;
+ range->adjustment->value = ((range->adjustment->upper -
+ range->adjustment->lower -
+ range->adjustment->page_size) *
+ (new_pos - top) / (bottom - top) +
+ range->adjustment->lower);
+
+ if (range->digits >= 0)
+ {
+ char buffer[64];
+
+ sprintf (buffer, "%0.*f", range->digits, range->adjustment->value);
+ sscanf (buffer, "%f", &range->adjustment->value);
+ }
+
+ if (old_value != range->adjustment->value)
+ {
+ if (range->policy == GTK_UPDATE_CONTINUOUS)
+ {
+ gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
+ }
+ else
+ {
+ gtk_range_slider_update (range);
+ gtk_range_draw_background (range);
+
+ if (range->policy == GTK_UPDATE_DELAYED)
+ {
+ gtk_range_remove_timer (range);
+ range->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
+ (GtkFunction) RANGE_CLASS (range)->timer,
+ (gpointer) range);
+ }
+ }
+ }
+}
+
+gfloat
+gtk_range_calc_value (GtkRange *range,
+ gint position)
+{
+ return 0.0;
+}
+
+
+static void
+gtk_range_destroy (GtkObject *object)
+{
+ GtkRange *range;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_RANGE (object));
+
+ range = GTK_RANGE (object);
+
+ if (range->adjustment)
+ gtk_object_unref (GTK_OBJECT (range->adjustment));
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+static void
+gtk_range_draw (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ GtkRange *range;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_RANGE (widget));
+ g_return_if_fail (area != NULL);
+
+ if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget))
+ {
+ range = GTK_RANGE (widget);
+
+ gtk_range_draw_background (range);
+ gtk_range_draw_trough (range);
+ gtk_range_draw_slider (range);
+ gtk_range_draw_step_forw (range);
+ gtk_range_draw_step_back (range);
+ }
+}
+
+static void
+gtk_range_draw_focus (GtkWidget *widget)
+{
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_RANGE (widget));
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ gtk_range_draw_trough (GTK_RANGE (widget));
+}
+
+static void
+gtk_range_unrealize (GtkWidget *widget)
+{
+ GtkRange *range;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_RANGE (widget));
+
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_REALIZED);
+ range = GTK_RANGE (widget);
+
+ gtk_style_detach (widget->style);
+
+ if (range->slider)
+ gdk_window_destroy (range->slider);
+ if (range->trough)
+ gdk_window_destroy (range->trough);
+ if (range->step_forw)
+ gdk_window_destroy (range->step_forw);
+ if (range->step_back)
+ gdk_window_destroy (range->step_back);
+ if (widget->window)
+ gdk_window_destroy (widget->window);
+
+ range->slider = NULL;
+ range->trough = NULL;
+ range->step_forw = NULL;
+ range->step_back = NULL;
+ widget->window = NULL;
+}
+
+static gint
+gtk_range_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ GtkRange *range;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ range = GTK_RANGE (widget);
+
+ if (event->window == range->trough)
+ {
+ gtk_range_draw_trough (range);
+ }
+ else if (event->window == widget->window)
+ {
+ gtk_range_draw_background (range);
+ }
+ else if (event->window == range->slider)
+ {
+ gtk_range_draw_slider (range);
+ }
+ else if (event->window == range->step_forw)
+ {
+ gtk_range_draw_step_forw (range);
+ }
+ else if (event->window == range->step_back)
+ {
+ gtk_range_draw_step_back (range);
+ }
+ return FALSE;
+}
+
+static gint
+gtk_range_button_press (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ GtkRange *range;
+ gint trough_part;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (!GTK_WIDGET_HAS_FOCUS (widget))
+ gtk_widget_grab_focus (widget);
+
+ range = GTK_RANGE (widget);
+ if (!range->button)
+ {
+ gtk_grab_add (widget);
+
+ range->button = event->button;
+ range->x_click_point = event->x;
+ range->y_click_point = event->y;
+
+ if (event->window == range->trough)
+ {
+ range->click_child = RANGE_CLASS (range)->trough;
+
+ trough_part = gtk_range_trough_click (range, event->x, event->y);
+
+ range->scroll_type = GTK_SCROLL_NONE;
+ if (trough_part == GTK_TROUGH_START)
+ range->scroll_type = GTK_SCROLL_PAGE_BACKWARD;
+ else if (trough_part == GTK_TROUGH_END)
+ range->scroll_type = GTK_SCROLL_PAGE_FORWARD;
+
+ if (range->scroll_type != GTK_SCROLL_NONE)
+ {
+ gtk_range_scroll (range);
+ gtk_range_add_timer (range);
+ }
+ }
+ else if (event->window == range->slider)
+ {
+ range->click_child = RANGE_CLASS (range)->slider;
+ range->scroll_type = GTK_SCROLL_NONE;
+ }
+ else if (event->window == range->step_forw)
+ {
+ range->click_child = RANGE_CLASS (range)->step_forw;
+ range->scroll_type = GTK_SCROLL_STEP_FORWARD;
+
+ gtk_range_scroll (range);
+ gtk_range_add_timer (range);
+ gtk_range_draw_step_forw (range);
+ }
+ else if (event->window == range->step_back)
+ {
+ range->click_child = RANGE_CLASS (range)->step_back;
+ range->scroll_type = GTK_SCROLL_STEP_BACKWARD;
+
+ gtk_range_scroll (range);
+ gtk_range_add_timer (range);
+ gtk_range_draw_step_back (range);
+ }
+ }
+
+ return FALSE;
+}
+
+static gint
+gtk_range_button_release (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ GtkRange *range;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ range = GTK_RANGE (widget);
+
+ if (range->button == event->button)
+ {
+ gtk_grab_remove (widget);
+
+ range->button = 0;
+ range->x_click_point = -1;
+ range->y_click_point = -1;
+
+ if (range->click_child == RANGE_CLASS (range)->slider)
+ {
+ if (range->policy == GTK_UPDATE_DELAYED)
+ gtk_range_remove_timer (range);
+
+ if ((range->policy != GTK_UPDATE_CONTINUOUS) &&
+ (range->old_value != range->adjustment->value))
+ gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
+ }
+ else if ((range->click_child == RANGE_CLASS (range)->trough) ||
+ (range->click_child == RANGE_CLASS (range)->step_forw) ||
+ (range->click_child == RANGE_CLASS (range)->step_back))
+ {
+ gtk_range_remove_timer (range);
+
+ if ((range->policy != GTK_UPDATE_CONTINUOUS) &&
+ (range->old_value != range->adjustment->value))
+ gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
+
+ if (range->click_child == RANGE_CLASS (range)->step_forw)
+ {
+ range->click_child = 0;
+ gtk_range_draw_step_forw (range);
+ }
+ else if (range->click_child == RANGE_CLASS (range)->step_back)
+ {
+ range->click_child = 0;
+ gtk_range_draw_step_back (range);
+ }
+ }
+
+ range->click_child = 0;
+ }
+
+ return FALSE;
+}
+
+static gint
+gtk_range_motion_notify (GtkWidget *widget,
+ GdkEventMotion *event)
+{
+ GtkRange *range;
+ GdkModifierType mods;
+ gint x, y, mask;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ range = GTK_RANGE (widget);
+
+ if (range->click_child == RANGE_CLASS (range)->slider)
+ {
+ x = event->x;
+ y = event->y;
+
+ if (event->is_hint || (event->window != range->slider))
+ gdk_window_get_pointer (range->slider, &x, &y, &mods);
+
+ switch (range->button)
+ {
+ case 1:
+ mask = GDK_BUTTON1_MASK;
+ break;
+ case 2:
+ mask = GDK_BUTTON2_MASK;
+ break;
+ case 3:
+ mask = GDK_BUTTON3_MASK;
+ break;
+ default:
+ mask = 0;
+ break;
+ }
+
+ if (mods & mask)
+ {
+ if (RANGE_CLASS (range)->motion)
+ (* RANGE_CLASS (range)->motion) (range, x - range->x_click_point, y - range->y_click_point);
+ }
+ }
+
+ return FALSE;
+}
+
+static gint
+gtk_range_key_press (GtkWidget *widget,
+ GdkEventKey *event)
+{
+ GtkRange *range;
+ gint return_val;
+ GtkScrollType scroll = GTK_SCROLL_NONE;
+ GtkTroughType pos = GTK_TROUGH_NONE;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ range = GTK_RANGE (widget);
+ return_val = FALSE;
+
+ if (RANGE_CLASS (range)->trough_keys)
+ return_val = (* RANGE_CLASS (range)->trough_keys) (range, event, &scroll, &pos);
+
+ if (return_val)
+ {
+ if (scroll != GTK_SCROLL_NONE)
+ {
+ range->scroll_type = scroll;
+ gtk_range_scroll (range);
+ if (range->old_value != range->adjustment->value)
+ {
+ gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
+ switch (range->scroll_type)
+ {
+ case GTK_SCROLL_STEP_BACKWARD:
+ gtk_range_draw_step_back (range);
+ break;
+ case GTK_SCROLL_STEP_FORWARD:
+ gtk_range_draw_step_forw (range);
+ break;
+ }
+ }
+ }
+ if (pos != GTK_TROUGH_NONE)
+ {
+ if (pos == GTK_TROUGH_START)
+ range->adjustment->value = range->adjustment->lower;
+ else
+ range->adjustment->value =
+ range->adjustment->upper - range->adjustment->page_size;
+
+ if (range->old_value != range->adjustment->value)
+ {
+ gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment),
+ "value_changed");
+
+ gtk_range_slider_update (range);
+ gtk_range_draw_background (range);
+ }
+ }
+ }
+ return return_val;
+}
+
+static gint
+gtk_range_enter_notify (GtkWidget *widget,
+ GdkEventCrossing *event)
+{
+ GtkRange *range;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ range = GTK_RANGE (widget);
+
+ if (event->window == range->trough)
+ {
+ range->in_child = RANGE_CLASS (range)->trough;
+ }
+ else if (event->window == range->slider)
+ {
+ range->in_child = RANGE_CLASS (range)->slider;
+
+ if ((range->click_child == 0) ||
+ (range->click_child == RANGE_CLASS (range)->trough))
+ gtk_range_draw_slider (range);
+ }
+ else if (event->window == range->step_forw)
+ {
+ range->in_child = RANGE_CLASS (range)->step_forw;
+
+ if ((range->click_child == 0) ||
+ (range->click_child == RANGE_CLASS (range)->trough))
+ gtk_range_draw_step_forw (range);
+ }
+ else if (event->window == range->step_back)
+ {
+ range->in_child = RANGE_CLASS (range)->step_back;
+
+ if ((range->click_child == 0) ||
+ (range->click_child == RANGE_CLASS (range)->trough))
+ gtk_range_draw_step_back (range);
+ }
+
+ return FALSE;
+}
+
+static gint
+gtk_range_leave_notify (GtkWidget *widget,
+ GdkEventCrossing *event)
+{
+ GtkRange *range;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ range = GTK_RANGE (widget);
+
+ range->in_child = 0;
+
+ if (event->window == range->trough)
+ {
+ }
+ else if (event->window == range->slider)
+ {
+ if ((range->click_child == 0) ||
+ (range->click_child == RANGE_CLASS (range)->trough))
+ gtk_range_draw_slider (range);
+ }
+ else if (event->window == range->step_forw)
+ {
+ if ((range->click_child == 0) ||
+ (range->click_child == RANGE_CLASS (range)->trough))
+ gtk_range_draw_step_forw (range);
+ }
+ else if (event->window == range->step_back)
+ {
+ if ((range->click_child == 0) ||
+ (range->click_child == RANGE_CLASS (range)->trough))
+ gtk_range_draw_step_back (range);
+ }
+
+ return FALSE;
+}
+
+static gint
+gtk_range_focus_in (GtkWidget *widget,
+ GdkEventFocus *event)
+{
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
+ gtk_widget_draw_focus (widget);
+
+ return FALSE;
+}
+
+static gint
+gtk_range_focus_out (GtkWidget *widget,
+ GdkEventFocus *event)
+{
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
+ gtk_widget_draw_focus (widget);
+
+ return FALSE;
+}
+
+static void
+gtk_real_range_draw_trough (GtkRange *range)
+{
+ g_return_if_fail (range != NULL);
+ g_return_if_fail (GTK_IS_RANGE (range));
+
+ if (range->trough)
+ {
+ gtk_draw_shadow (GTK_WIDGET (range)->style, range->trough,
+ GTK_STATE_NORMAL, GTK_SHADOW_IN,
+ 0, 0, -1, -1);
+
+ if (GTK_WIDGET_HAS_FOCUS (range))
+ gdk_draw_rectangle (GTK_WIDGET (range)->window,
+ GTK_WIDGET (range)->style->black_gc,
+ FALSE, 0, 0,
+ GTK_WIDGET (range)->allocation.width - 1,
+ GTK_WIDGET (range)->allocation.height - 1);
+ else if (range->trough != GTK_WIDGET (range)->window)
+ gdk_draw_rectangle (GTK_WIDGET (range)->window,
+ GTK_WIDGET (range)->style->bg_gc[GTK_STATE_NORMAL],
+ FALSE, 0, 0,
+ GTK_WIDGET (range)->allocation.width - 1,
+ GTK_WIDGET (range)->allocation.height - 1);
+ }
+}
+
+static void
+gtk_real_range_draw_slider (GtkRange *range)
+{
+ GtkStateType state_type;
+
+ g_return_if_fail (range != NULL);
+ g_return_if_fail (GTK_IS_RANGE (range));
+
+ if (range->slider)
+ {
+ if ((range->in_child == RANGE_CLASS (range)->slider) ||
+ (range->click_child == RANGE_CLASS (range)->slider))
+ state_type = GTK_STATE_PRELIGHT;
+ else
+ state_type = GTK_STATE_NORMAL;
+
+ gtk_style_set_background (GTK_WIDGET (range)->style, range->slider, state_type);
+ gdk_window_clear (range->slider);
+
+ gtk_draw_shadow (GTK_WIDGET (range)->style, range->slider,
+ state_type, GTK_SHADOW_OUT,
+ 0, 0, -1, -1);
+ }
+}
+
+static gint
+gtk_real_range_timer (GtkRange *range)
+{
+ gint return_val;
+
+ g_return_val_if_fail (range != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_RANGE (range), FALSE);
+
+ return_val = TRUE;
+ if (range->click_child == RANGE_CLASS (range)->slider)
+ {
+ if (range->policy == GTK_UPDATE_DELAYED)
+ gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
+ return_val = FALSE;
+ }
+ else
+ {
+ if (!range->timer)
+ {
+ return_val = FALSE;
+ if (range->need_timer)
+ range->timer = gtk_timeout_add (SCROLL_TIMER_LENGTH,
+ (GtkFunction) RANGE_CLASS (range)->timer,
+ (gpointer) range);
+ else
+ return FALSE;
+ range->need_timer = FALSE;
+ }
+
+ if (gtk_range_scroll (range))
+ return return_val;
+ }
+
+ return return_val;
+}
+
+static gint
+gtk_range_scroll (GtkRange *range)
+{
+ gfloat new_value;
+ gint return_val;
+
+ g_return_val_if_fail (range != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_RANGE (range), FALSE);
+
+ new_value = range->adjustment->value;
+ return_val = TRUE;
+
+ switch (range->scroll_type)
+ {
+ case GTK_SCROLL_NONE:
+ break;
+
+ case GTK_SCROLL_STEP_BACKWARD:
+ new_value -= range->adjustment->step_increment;
+ if (new_value <= range->adjustment->lower)
+ {
+ new_value = range->adjustment->lower;
+ return_val = FALSE;
+ range->timer = 0;
+ }
+ break;
+
+ case GTK_SCROLL_STEP_FORWARD:
+ new_value += range->adjustment->step_increment;
+ if (new_value >= (range->adjustment->upper - range->adjustment->page_size))
+ {
+ new_value = range->adjustment->upper - range->adjustment->page_size;
+ return_val = FALSE;
+ range->timer = 0;
+ }
+ break;
+
+ case GTK_SCROLL_PAGE_BACKWARD:
+ new_value -= range->adjustment->page_increment;
+ if (new_value <= range->adjustment->lower)
+ {
+ new_value = range->adjustment->lower;
+ return_val = FALSE;
+ range->timer = 0;
+ }
+ break;
+
+ case GTK_SCROLL_PAGE_FORWARD:
+ new_value += range->adjustment->page_increment;
+ if (new_value >= (range->adjustment->upper - range->adjustment->page_size))
+ {
+ new_value = range->adjustment->upper - range->adjustment->page_size;
+ return_val = FALSE;
+ range->timer = 0;
+ }
+ break;
+ }
+
+ if (new_value != range->adjustment->value)
+ {
+ range->adjustment->value = new_value;
+
+ if ((range->policy == GTK_UPDATE_CONTINUOUS) ||
+ (!return_val && (range->policy == GTK_UPDATE_DELAYED)))
+ {
+ gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
+ }
+ else
+ {
+ gtk_range_slider_update (range);
+ gtk_range_draw_background (range);
+ }
+ }
+
+ return return_val;
+}
+
+
+static void
+gtk_range_add_timer (GtkRange *range)
+{
+ g_return_if_fail (range != NULL);
+ g_return_if_fail (GTK_IS_RANGE (range));
+
+ if (!range->timer)
+ {
+ range->need_timer = TRUE;
+ range->timer = gtk_timeout_add (SCROLL_INITIAL_DELAY,
+ (GtkFunction) RANGE_CLASS (range)->timer,
+ (gpointer) range);
+ }
+}
+
+static void
+gtk_range_remove_timer (GtkRange *range)
+{
+ g_return_if_fail (range != NULL);
+ g_return_if_fail (GTK_IS_RANGE (range));
+
+ if (range->timer)
+ {
+ gtk_timeout_remove (range->timer);
+ range->timer = 0;
+ }
+ range->need_timer = FALSE;
+}
+
+static void
+gtk_range_adjustment_changed (GtkAdjustment *adjustment,
+ gpointer data)
+{
+ GtkRange *range;
+
+ g_return_if_fail (adjustment != NULL);
+ g_return_if_fail (data != NULL);
+
+ range = GTK_RANGE (data);
+
+ if (((range->old_lower != adjustment->lower) ||
+ (range->old_upper != adjustment->upper) ||
+ (range->old_page_size != adjustment->page_size)) &&
+ (range->old_value == adjustment->value))
+ {
+ if ((adjustment->lower == adjustment->upper) ||
+ (range->old_lower == (range->old_upper - range->old_page_size)))
+ {
+ adjustment->value = adjustment->lower;
+ gtk_signal_emit_by_name (GTK_OBJECT (adjustment), "value_changed");
+ }
+ }
+
+ if ((range->old_value != adjustment->value) ||
+ (range->old_lower != adjustment->lower) ||
+ (range->old_upper != adjustment->upper) ||
+ (range->old_page_size != adjustment->page_size))
+ {
+ gtk_range_slider_update (range);
+ gtk_range_draw_background (range);
+
+ range->old_value = adjustment->value;
+ range->old_lower = adjustment->lower;
+ range->old_upper = adjustment->upper;
+ range->old_page_size = adjustment->page_size;
+ }
+}
+
+static void
+gtk_range_adjustment_value_changed (GtkAdjustment *adjustment,
+ gpointer data)
+{
+ GtkRange *range;
+
+ g_return_if_fail (adjustment != NULL);
+ g_return_if_fail (data != NULL);
+
+ range = GTK_RANGE (data);
+
+ if (range->old_value != adjustment->value)
+ {
+ gtk_range_slider_update (range);
+ gtk_range_draw_background (range);
+
+ range->old_value = adjustment->value;
+ }
+}
+
+
+static void
+gtk_range_trough_hdims (GtkRange *range,
+ gint *left,
+ gint *right)
+{
+ gint trough_width;
+ gint slider_length;
+ gint tmp_width;
+ gint tleft;
+ gint tright;
+
+ g_return_if_fail (range != NULL);
+
+ gdk_window_get_size (range->trough, &trough_width, NULL);
+ gdk_window_get_size (range->slider, &slider_length, NULL);
+
+ tleft = GTK_WIDGET (range)->style->klass->xthickness;
+ tright = trough_width - slider_length - GTK_WIDGET (range)->style->klass->xthickness;
+
+ if (range->step_back)
+ {
+ gdk_window_get_size (range->step_back, &tmp_width, NULL);
+ tleft += (tmp_width + RANGE_CLASS (range)->stepper_slider_spacing);
+ }
+
+ if (range->step_forw)
+ {
+ gdk_window_get_size (range->step_forw, &tmp_width, NULL);
+ tright -= (tmp_width + RANGE_CLASS (range)->stepper_slider_spacing);
+ }
+
+ if (left)
+ *left = tleft;
+ if (right)
+ *right = tright;
+}
+
+static void
+gtk_range_trough_vdims (GtkRange *range,
+ gint *top,
+ gint *bottom)
+{
+ gint trough_height;
+ gint slider_length;
+ gint tmp_height;
+ gint ttop;
+ gint tbottom;
+
+ g_return_if_fail (range != NULL);
+
+ gdk_window_get_size (range->trough, NULL, &trough_height);
+ gdk_window_get_size (range->slider, NULL, &slider_length);
+
+ ttop = GTK_WIDGET (range)->style->klass->xthickness;
+ tbottom = trough_height - slider_length - GTK_WIDGET (range)->style->klass->ythickness;
+
+ if (range->step_back)
+ {
+ gdk_window_get_size (range->step_back, NULL, &tmp_height);
+ ttop += (tmp_height + RANGE_CLASS (range)->stepper_slider_spacing);
+ }
+
+ if (range->step_forw)
+ {
+ gdk_window_get_size (range->step_forw, NULL, &tmp_height);
+ tbottom -= (tmp_height + RANGE_CLASS (range)->stepper_slider_spacing);
+ }
+
+ if (top)
+ *top = ttop;
+ if (bottom)
+ *bottom = tbottom;
+}
diff --git a/gtk/gtkrange.h b/gtk/gtkrange.h
new file mode 100644
index 000000000..47ff50a36
--- /dev/null
+++ b/gtk/gtkrange.h
@@ -0,0 +1,144 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_RANGE_H__
+#define __GTK_RANGE_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkadjustment.h>
+#include <gtk/gtkwidget.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_RANGE(obj) GTK_CHECK_CAST (obj, gtk_range_get_type (), GtkRange)
+#define GTK_RANGE_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_range_get_type (), GtkRangeClass)
+#define GTK_IS_RANGE(obj) GTK_CHECK_TYPE (obj, gtk_range_get_type ())
+
+
+typedef struct _GtkRange GtkRange;
+typedef struct _GtkRangeClass GtkRangeClass;
+
+struct _GtkRange
+{
+ GtkWidget widget;
+
+ GdkWindow *trough;
+ GdkWindow *slider;
+ GdkWindow *step_forw;
+ GdkWindow *step_back;
+
+ gint16 x_click_point;
+ gint16 y_click_point;
+
+ guint8 button;
+ gint8 digits;
+ guint policy : 2;
+ guint scroll_type : 3;
+ guint in_child : 3;
+ guint click_child : 3;
+ guint need_timer : 1;
+
+ guint32 timer;
+
+ gfloat old_value;
+ gfloat old_lower;
+ gfloat old_upper;
+ gfloat old_page_size;
+
+ GtkAdjustment *adjustment;
+};
+
+struct _GtkRangeClass
+{
+ GtkWidgetClass parent_class;
+
+ gint slider_width;
+ gint stepper_size;
+ gint stepper_slider_spacing;
+ gint min_slider_size;
+
+ guint8 trough;
+ guint8 slider;
+ guint8 step_forw;
+ guint8 step_back;
+
+ void (* draw_background) (GtkRange *range);
+ void (* draw_trough) (GtkRange *range);
+ void (* draw_slider) (GtkRange *range);
+ void (* draw_step_forw) (GtkRange *range);
+ void (* draw_step_back) (GtkRange *range);
+ void (* slider_update) (GtkRange *range);
+ gint (* trough_click) (GtkRange *range,
+ gint x,
+ gint y);
+ gint (* trough_keys) (GtkRange *range,
+ GdkEventKey *key,
+ GtkScrollType *scroll,
+ GtkTroughType *trough);
+ void (* motion) (GtkRange *range,
+ gint xdelta,
+ gint ydelta);
+ gint (* timer) (GtkRange *range);
+};
+
+
+guint gtk_range_get_type (void);
+GtkAdjustment* gtk_range_get_adjustment (GtkRange *range);
+void gtk_range_set_update_policy (GtkRange *range,
+ GtkUpdateType policy);
+void gtk_range_set_adjustment (GtkRange *range,
+ GtkAdjustment *adjustment);
+
+void gtk_range_draw_background (GtkRange *range);
+void gtk_range_draw_trough (GtkRange *range);
+void gtk_range_draw_slider (GtkRange *range);
+void gtk_range_draw_step_forw (GtkRange *range);
+void gtk_range_draw_step_back (GtkRange *range);
+void gtk_range_slider_update (GtkRange *range);
+gint gtk_range_trough_click (GtkRange *range,
+ gint x,
+ gint y);
+
+void gtk_range_default_hslider_update (GtkRange *range);
+void gtk_range_default_vslider_update (GtkRange *range);
+gint gtk_range_default_htrough_click (GtkRange *range,
+ gint x,
+ gint y);
+gint gtk_range_default_vtrough_click (GtkRange *range,
+ gint x,
+ gint y);
+void gtk_range_default_hmotion (GtkRange *range,
+ gint xdelta,
+ gint ydelta);
+void gtk_range_default_vmotion (GtkRange *range,
+ gint xdelta,
+ gint ydelta);
+gfloat gtk_range_calc_value (GtkRange *range,
+ gint position);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_RANGE_H__ */
diff --git a/gtk/gtkrc.c b/gtk/gtkrc.c
new file mode 100644
index 000000000..86bc20121
--- /dev/null
+++ b/gtk/gtkrc.c
@@ -0,0 +1,1489 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "gtkrc.h"
+
+
+enum {
+ TOKEN_EOF,
+ TOKEN_LEFT_CURLY,
+ TOKEN_RIGHT_CURLY,
+ TOKEN_LEFT_BRACE,
+ TOKEN_RIGHT_BRACE,
+ TOKEN_EQUAL_SIGN,
+ TOKEN_COMMA,
+ TOKEN_INTEGER,
+ TOKEN_FLOAT,
+ TOKEN_STRING,
+ TOKEN_SYMBOL,
+ TOKEN_ACTIVE,
+ TOKEN_BASE,
+ TOKEN_BG,
+ TOKEN_BG_PIXMAP,
+ TOKEN_FG,
+ TOKEN_FONT,
+ TOKEN_FONTSET,
+ TOKEN_INSENSITIVE,
+ TOKEN_NORMAL,
+ TOKEN_PIXMAP_PATH,
+ TOKEN_PRELIGHT,
+ TOKEN_SELECTED,
+ TOKEN_STYLE,
+ TOKEN_TEXT,
+ TOKEN_WIDGET,
+ TOKEN_WIDGET_CLASS
+};
+
+enum {
+ PARSE_OK,
+ PARSE_ERROR,
+ PARSE_SYNTAX
+};
+
+enum {
+ PARSE_START,
+ PARSE_COMMENT,
+ PARSE_STRING,
+ PARSE_SYMBOL,
+ PARSE_NUMBER
+};
+
+
+typedef struct _GtkRcStyle GtkRcStyle;
+typedef struct _GtkRcSet GtkRcSet;
+
+struct _GtkRcStyle
+{
+ int initialize;
+ char *name;
+ char *font_name;
+ char *fontset_name;
+ char *bg_pixmap_name[5];
+ GtkStyle *style;
+};
+
+struct _GtkRcSet
+{
+ char *set;
+ GtkRcStyle *rc_style;
+};
+
+
+static guint gtk_rc_style_hash (const char *name);
+static gint gtk_rc_style_compare (const char *a,
+ const char *b);
+static GtkRcStyle* gtk_rc_style_find (const char *name);
+static GtkRcStyle* gtk_rc_styles_match (GSList *sets,
+ const char *path);
+static gint gtk_rc_style_match (const char *set,
+ const char *path);
+static void gtk_rc_style_init (GtkRcStyle *rc_style);
+static gint gtk_rc_get_token (void);
+static gint gtk_rc_simple_token (char ch);
+static gint gtk_rc_symbol_token (const char *sym);
+static gint gtk_rc_get_next_token (void);
+static gint gtk_rc_peek_next_token (void);
+static gint gtk_rc_parse_statement (void);
+static gint gtk_rc_parse_style (void);
+static gint gtk_rc_parse_style_option (GtkRcStyle *rc_style);
+static gint gtk_rc_parse_base (GtkStyle *style);
+static gint gtk_rc_parse_bg (GtkStyle *style);
+static gint gtk_rc_parse_fg (GtkStyle *style);
+static gint gtk_rc_parse_bg_pixmap (GtkRcStyle *rc_style);
+static gint gtk_rc_parse_font (GtkRcStyle *rc_style);
+static gint gtk_rc_parse_fontset (GtkRcStyle *rc_style);
+static gint gtk_rc_parse_state (GtkStateType *state);
+static gint gtk_rc_parse_color (GdkColor *color);
+static gint gtk_rc_parse_pixmap_path (void);
+static void gtk_rc_parse_pixmap_path_string (gchar *pix_path);
+static char* gtk_rc_find_pixmap_in_path (gchar *pixmap_file);
+static gint gtk_rc_parse_widget_style (void);
+static gint gtk_rc_parse_widget_class_style (void);
+static char* gtk_rc_widget_path (GtkWidget *widget);
+static char* gtk_rc_widget_class_path (GtkWidget *widget);
+
+
+static struct
+{
+ char *name;
+ int token;
+} symbols[] =
+ {
+ { "ACTIVE", TOKEN_ACTIVE },
+ { "base", TOKEN_BASE },
+ { "bg", TOKEN_BG },
+ { "bg_pixmap", TOKEN_BG_PIXMAP },
+ { "fg", TOKEN_FG },
+ { "font", TOKEN_FONT },
+ { "fontset", TOKEN_FONTSET },
+ { "INSENSITIVE", TOKEN_INSENSITIVE },
+ { "NORMAL", TOKEN_NORMAL },
+ { "pixmap_path", TOKEN_PIXMAP_PATH },
+ { "PRELIGHT", TOKEN_PRELIGHT },
+ { "SELECTED", TOKEN_SELECTED },
+ { "style", TOKEN_STYLE },
+ { "text", TOKEN_TEXT },
+ { "widget", TOKEN_WIDGET },
+ { "widget_class", TOKEN_WIDGET_CLASS },
+ };
+
+static int nsymbols = sizeof (symbols) / sizeof (symbols[0]);
+
+static struct
+{
+ char ch;
+ int token;
+} simple_tokens[] =
+ {
+ { '{', TOKEN_LEFT_CURLY },
+ { '}', TOKEN_RIGHT_CURLY },
+ { '[', TOKEN_LEFT_BRACE },
+ { ']', TOKEN_RIGHT_BRACE },
+ { '=', TOKEN_EQUAL_SIGN },
+ { ',', TOKEN_COMMA },
+ };
+
+static int nsimple_tokens = sizeof (simple_tokens) / sizeof (simple_tokens[0]);
+
+static FILE *input_fp = NULL;
+static char *buffer = NULL;
+static char *tokenbuf = NULL;
+static int position = 0;
+static int linenum = 1;
+static int buffer_size = 1024;
+static int tokenbuf_size = 1024;
+
+static int done;
+static int cur_token;
+static int next_token;
+
+static char *token_str;
+static double token_float;
+static int token_int;
+
+static GHashTable *rc_style_ht = NULL;
+static GSList *widget_sets = NULL;
+static GSList *widget_class_sets = NULL;
+
+#define GTK_RC_MAX_PIXMAP_PATHS 128
+static gchar *pixmap_path[GTK_RC_MAX_PIXMAP_PATHS];
+
+
+void
+gtk_rc_init ()
+{
+ rc_style_ht = g_hash_table_new ((GHashFunc) gtk_rc_style_hash,
+ (GCompareFunc) gtk_rc_style_compare);
+}
+
+void
+gtk_rc_parse (const char *filename)
+{
+ input_fp = fopen (filename, "r");
+ if (!input_fp)
+ return;
+
+ buffer = g_new (char, buffer_size + tokenbuf_size);
+ tokenbuf = buffer + buffer_size;
+ position = 0;
+ linenum = 1;
+
+ cur_token = -1;
+ next_token = -1;
+ done = FALSE;
+
+ while (!done)
+ {
+ if (gtk_rc_parse_statement () != PARSE_OK)
+ {
+ g_warning ("rc file parse error: \"%s\" line %d",
+ filename, linenum);
+ done = TRUE;
+ }
+ }
+
+ fclose (input_fp);
+
+ g_free (buffer);
+
+ buffer = NULL;
+ tokenbuf = NULL;
+ position = 0;
+ linenum = 1;
+}
+
+GtkStyle*
+gtk_rc_get_style (GtkWidget *widget)
+{
+ GtkRcStyle *rc_style;
+ char *path;
+
+ if (widget_sets)
+ {
+ path = gtk_rc_widget_path (widget);
+ if (path)
+ {
+ rc_style = gtk_rc_styles_match (widget_sets, path);
+ g_free (path);
+
+ if (rc_style)
+ {
+ gtk_rc_style_init (rc_style);
+ return rc_style->style;
+ }
+ }
+ }
+
+ if (widget_class_sets)
+ {
+ path = gtk_rc_widget_class_path (widget);
+ if (path)
+ {
+ rc_style = gtk_rc_styles_match (widget_class_sets, path);
+ g_free (path);
+
+ if (rc_style)
+ {
+ gtk_rc_style_init (rc_style);
+ return rc_style->style;
+ }
+ }
+ }
+
+ return widget->style;
+}
+
+void
+gtk_rc_add_widget_name_style (GtkStyle *style,
+ const char *pattern)
+{
+ GtkRcStyle *rc_style;
+ GtkRcSet *rc_set;
+ int i;
+
+ gtk_style_ref (style);
+
+ rc_style = g_new (GtkRcStyle, 1);
+ rc_style->initialize = FALSE;
+ rc_style->name = NULL;
+ rc_style->font_name = NULL;
+ rc_style->fontset_name = NULL;
+
+ for (i = 0; i < 5; i++)
+ rc_style->bg_pixmap_name[i] = NULL;
+
+ rc_style->style = style;
+
+ rc_set = g_new (GtkRcSet, 1);
+ rc_set->set = g_strdup (pattern);
+ rc_set->rc_style = rc_style;
+
+ widget_sets = g_slist_append (widget_sets, rc_set);
+}
+
+void
+gtk_rc_add_widget_class_style (GtkStyle *style,
+ const char *pattern)
+{
+ GtkRcStyle *rc_style;
+ GtkRcSet *rc_set;
+ int i;
+
+ gtk_style_ref (style);
+
+ rc_style = g_new (GtkRcStyle, 1);
+ rc_style->initialize = FALSE;
+ rc_style->name = NULL;
+ rc_style->font_name = NULL;
+ rc_style->fontset_name = NULL;
+
+ for (i = 0; i < 5; i++)
+ rc_style->bg_pixmap_name[i] = NULL;
+
+ rc_style->style = style;
+
+ rc_set = g_new (GtkRcSet, 1);
+ rc_set->set = g_strdup (pattern);
+ rc_set->rc_style = rc_style;
+
+ widget_class_sets = g_slist_append (widget_class_sets, rc_set);
+}
+
+
+static guint
+gtk_rc_style_hash (const char *name)
+{
+ guint result;
+
+ result = 0;
+ while (*name)
+ result += (result << 3) + *name++;
+
+ return result;
+}
+
+static gint
+gtk_rc_style_compare (const char *a,
+ const char *b)
+{
+ return (strcmp (a, b) == 0);
+}
+
+static GtkRcStyle*
+gtk_rc_style_find (const char *name)
+{
+ GtkRcStyle *rc_style;
+
+ rc_style = g_hash_table_lookup (rc_style_ht, (gpointer) name);
+
+ return rc_style;
+}
+
+static GtkRcStyle*
+gtk_rc_styles_match (GSList *sets,
+ const char *path)
+{
+ GtkRcSet *rc_set;
+
+ while (sets)
+ {
+ rc_set = sets->data;
+ sets = sets->next;
+
+ if (gtk_rc_style_match (rc_set->set, path))
+ return rc_set->rc_style;
+ }
+
+ return NULL;
+}
+
+static gint
+gtk_rc_style_match (const char *set,
+ const char *path)
+{
+ char ch;
+
+ while (1)
+ {
+ ch = *set++;
+ if (ch == '\0')
+ return (*path == '\0');
+
+ switch (ch)
+ {
+ case '*':
+ while (*set == '*')
+ set++;
+
+ ch = *set++;
+ if (ch == '\0')
+ return TRUE;
+
+ while (*path)
+ {
+ while (*path && (ch != *path))
+ path++;
+
+ if (!(*path))
+ return FALSE;
+
+ path++;
+ if (gtk_rc_style_match (set, path))
+ return TRUE;
+ }
+ break;
+
+ case '?':
+ break;
+
+ default:
+ if (ch == *path)
+ path++;
+ else
+ return FALSE;
+ break;
+ }
+ }
+
+ return TRUE;
+}
+
+static void
+gtk_rc_style_init (GtkRcStyle *rc_style)
+{
+ GdkFont *old_font;
+ gint i;
+
+ if (rc_style->initialize)
+ {
+ rc_style->initialize = FALSE;
+
+ if (rc_style->fontset_name)
+ {
+ old_font = rc_style->style->font;
+ rc_style->style->font = gdk_fontset_load (rc_style->fontset_name);
+ if (rc_style->style->font)
+ gdk_fontset_free (old_font);
+ else
+ rc_style->style->font = old_font;
+ }
+ else if (rc_style->font_name)
+ {
+ old_font = rc_style->style->font;
+ rc_style->style->font = gdk_font_load (rc_style->font_name);
+ if (rc_style->style->font)
+ gdk_font_free (old_font);
+ else
+ rc_style->style->font = old_font;
+ }
+
+ for (i = 0; i < 5; i++)
+ if (rc_style->bg_pixmap_name[i])
+ {
+ if (strcmp (rc_style->bg_pixmap_name[i], "<parent>") == 0)
+ rc_style->style->bg_pixmap[i] = (GdkPixmap*) GDK_PARENT_RELATIVE;
+ else
+ rc_style->style->bg_pixmap[i] = gdk_pixmap_create_from_xpm (NULL, NULL,
+ &rc_style->style->bg[i],
+ rc_style->bg_pixmap_name[i]);
+ }
+ }
+}
+
+static gint
+gtk_rc_get_token ()
+{
+ int tokenpos;
+ int state;
+ int count;
+ int token;
+ int hex_number = FALSE;
+ int float_number = FALSE;
+ char ch;
+
+ tokenpos = 0;
+ state = PARSE_START;
+
+ while (1)
+ {
+ if (position >= (buffer_size - 1))
+ position = 0;
+ if (!position || (buffer[position] == '\0'))
+ {
+ count = fread (buffer, sizeof (char), buffer_size - 1, input_fp);
+ if ((count == 0) && feof (input_fp))
+ return TOKEN_EOF;
+ buffer[count] = '\0';
+ }
+
+ ch = buffer[position++];
+ if (ch == '\n')
+ linenum += 1;
+
+ switch (state)
+ {
+ case PARSE_START:
+ token = gtk_rc_simple_token (ch);
+
+ if (token)
+ return token;
+ else if (ch == '#')
+ state = PARSE_COMMENT;
+ else if (ch == '"')
+ state = PARSE_STRING;
+ else if ((ch == ' ') || (ch == '\t') || (ch == '\n'))
+ break;
+ else if (ch == '.')
+ {
+ hex_number = FALSE;
+ float_number = TRUE;
+ tokenbuf[tokenpos++] = ch;
+ state = PARSE_NUMBER;
+ }
+ else if ((ch == '$') || (ch == '#'))
+ {
+ hex_number = TRUE;
+ float_number = FALSE;
+ state = PARSE_NUMBER;
+ }
+ else if (isdigit (ch))
+ {
+ hex_number = FALSE;
+ float_number = FALSE;
+ tokenbuf[tokenpos++] = ch;
+ state = PARSE_NUMBER;
+ }
+ else
+ {
+ tokenbuf[tokenpos++] = ch;
+ state = PARSE_SYMBOL;
+ }
+ break;
+
+ case PARSE_COMMENT:
+ if (ch == '\n')
+ state = PARSE_START;
+ break;
+
+ case PARSE_STRING:
+ if (ch != '"')
+ {
+ tokenbuf[tokenpos++] = ch;
+ }
+ else
+ {
+ tokenbuf[tokenpos] = '\0';
+ token_str = tokenbuf;
+ return TOKEN_STRING;
+ }
+ break;
+
+ case PARSE_SYMBOL:
+ if ((ch != ' ') && (ch != '\t') && (ch != '\n') &&
+ (gtk_rc_simple_token (ch) == 0))
+ {
+ tokenbuf[tokenpos++] = ch;
+ }
+ else
+ {
+ position -= 1;
+ tokenbuf[tokenpos] = '\0';
+ token_str = tokenbuf;
+ return gtk_rc_symbol_token (tokenbuf);
+ }
+ break;
+
+ case PARSE_NUMBER:
+ if (isdigit (ch) || (hex_number && isxdigit (ch)))
+ {
+ tokenbuf[tokenpos++] = ch;
+ }
+ else if (!hex_number && !float_number && (ch == '.'))
+ {
+ float_number = TRUE;
+ tokenbuf[tokenpos++] = ch;
+ }
+ else if (!float_number &&
+ (ch == 'x') && (tokenpos == 1) &&
+ (tokenbuf[0] == '0'))
+ {
+ hex_number = TRUE;
+ tokenpos = 0;
+ }
+ else
+ {
+ position -= 1;
+ tokenbuf[tokenpos] = '\0';
+ if (float_number)
+ {
+ sscanf (tokenbuf, "%lf", &token_float);
+ return TOKEN_FLOAT;
+ }
+ else
+ {
+ sscanf (tokenbuf, (hex_number ? "%x" : "%d"), &token_int);
+ return TOKEN_INTEGER;
+ }
+ }
+ break;
+ }
+ }
+}
+
+static gint
+gtk_rc_simple_token (char ch)
+{
+ gint i;
+
+ for (i = 0; i < nsimple_tokens; i++)
+ if (simple_tokens[i].ch == ch)
+ return simple_tokens[i].token;
+
+ return 0;
+}
+
+static gint
+gtk_rc_symbol_token (const char *sym)
+{
+ gint i;
+
+ for (i = 0; i < nsymbols; i++)
+ if (strcmp (symbols[i].name, sym) == 0)
+ return symbols[i].token;
+
+ return TOKEN_STRING;
+}
+
+static gint
+gtk_rc_get_next_token ()
+{
+ if (next_token != -1)
+ {
+ cur_token = next_token;
+ next_token = -1;
+ }
+ else
+ {
+ cur_token = gtk_rc_get_token ();
+ }
+
+ return cur_token;
+}
+
+static gint
+gtk_rc_peek_next_token ()
+{
+ if (next_token == -1)
+ next_token = gtk_rc_get_token ();
+
+ return next_token;
+}
+
+static gint
+gtk_rc_parse_statement ()
+{
+ gint token;
+ gint error;
+
+ token = gtk_rc_peek_next_token ();
+ if (!token)
+ {
+ done = TRUE;
+ return PARSE_OK;
+ }
+
+ error = gtk_rc_parse_style ();
+ if (error != PARSE_SYNTAX)
+ return error;
+
+ error = gtk_rc_parse_pixmap_path ();
+ if (error != PARSE_SYNTAX)
+ return error;
+
+ error = gtk_rc_parse_widget_style ();
+ if (error != PARSE_SYNTAX)
+ return error;
+
+ error = gtk_rc_parse_widget_class_style ();
+
+ return error;
+}
+
+static gint
+gtk_rc_parse_style ()
+{
+ GtkRcStyle *rc_style;
+ GtkRcStyle *parent_style;
+ gint token;
+ gint error;
+ gint insert;
+ gint i;
+
+ token = gtk_rc_peek_next_token ();
+ if (!token)
+ return PARSE_ERROR;
+ if (token != TOKEN_STYLE)
+ return PARSE_SYNTAX;
+ token = gtk_rc_get_next_token ();
+
+ token = gtk_rc_get_next_token ();
+ if (!token || (token != TOKEN_STRING))
+ return PARSE_ERROR;
+
+ insert = FALSE;
+ rc_style = g_hash_table_lookup (rc_style_ht, token_str);
+
+ if (!rc_style)
+ {
+ insert = TRUE;
+ rc_style = g_new (GtkRcStyle, 1);
+ rc_style->initialize = TRUE;
+ rc_style->name = g_strdup (token_str);
+ rc_style->font_name = NULL;
+ rc_style->fontset_name = NULL;
+
+ for (i = 0; i < 5; i++)
+ rc_style->bg_pixmap_name[i] = NULL;
+
+ rc_style->style = gtk_style_new ();
+ gtk_style_ref (rc_style->style);
+ }
+
+ token = gtk_rc_peek_next_token ();
+ if (token == TOKEN_EQUAL_SIGN)
+ {
+ token = gtk_rc_get_next_token ();
+
+ token = gtk_rc_get_next_token ();
+ if (!token || (token != TOKEN_STRING))
+ {
+ if (insert)
+ {
+ gtk_style_unref (rc_style->style);
+ g_free (rc_style);
+ }
+ return PARSE_ERROR;
+ }
+
+ parent_style = g_hash_table_lookup (rc_style_ht, token_str);
+ if (parent_style)
+ {
+ for (i = 0; i < 5; i++)
+ {
+ rc_style->style->fg[i] = parent_style->style->fg[i];
+ rc_style->style->bg[i] = parent_style->style->bg[i];
+ rc_style->style->light[i] = parent_style->style->light[i];
+ rc_style->style->dark[i] = parent_style->style->dark[i];
+ rc_style->style->mid[i] = parent_style->style->mid[i];
+ rc_style->style->text[i] = parent_style->style->text[i];
+ rc_style->style->base[i] = parent_style->style->base[i];
+ }
+
+ rc_style->style->black = parent_style->style->black;
+ rc_style->style->white = parent_style->style->white;
+
+ if (rc_style->fontset_name)
+ {
+ g_free (rc_style->fontset_name);
+ rc_style->fontset_name = g_strdup (parent_style->fontset_name);
+ }
+ else if (rc_style->font_name)
+ {
+ g_free (rc_style->font_name);
+ rc_style->font_name = g_strdup (parent_style->font_name);
+ }
+
+ for (i = 0; i < 5; i++)
+ {
+ if (rc_style->bg_pixmap_name[i])
+ g_free (rc_style->bg_pixmap_name[i]);
+ rc_style->bg_pixmap_name[i] = g_strdup (parent_style->bg_pixmap_name[i]);
+ }
+ }
+ }
+
+ token = gtk_rc_get_next_token ();
+ if (!token || (token != TOKEN_LEFT_CURLY))
+ {
+ if (insert)
+ {
+ gtk_style_unref (rc_style->style);
+ g_free (rc_style);
+ }
+ return PARSE_ERROR;
+ }
+
+ while (1)
+ {
+ error = gtk_rc_parse_style_option (rc_style);
+ if (error == PARSE_SYNTAX)
+ break;
+ if (error == PARSE_ERROR)
+ {
+ if (insert)
+ {
+ gtk_style_unref (rc_style->style);
+ g_free (rc_style);
+ }
+ return error;
+ }
+ }
+
+ token = gtk_rc_get_next_token ();
+ if (!token || (token != TOKEN_RIGHT_CURLY))
+ {
+ if (insert)
+ {
+ if (rc_style->fontset_name)
+ g_free (rc_style->fontset_name);
+ else if (rc_style->font_name)
+ g_free (rc_style->font_name);
+
+ for (i = 0; i < 5; i++)
+ if (rc_style->bg_pixmap_name[i])
+ g_free (rc_style->bg_pixmap_name[i]);
+
+ gtk_style_unref (rc_style->style);
+ g_free (rc_style);
+ }
+ return PARSE_ERROR;
+ }
+
+ if (insert)
+ g_hash_table_insert (rc_style_ht, rc_style->name, rc_style);
+
+ return PARSE_OK;
+}
+
+static gint
+gtk_rc_parse_style_option (GtkRcStyle *rc_style)
+{
+ gint token;
+ gint error;
+
+ token = gtk_rc_peek_next_token ();
+ if (!token)
+ return PARSE_ERROR;
+
+ error = gtk_rc_parse_base (rc_style->style);
+ if (error != PARSE_SYNTAX)
+ return error;
+
+ error = gtk_rc_parse_bg (rc_style->style);
+ if (error != PARSE_SYNTAX)
+ return error;
+
+ error = gtk_rc_parse_fg (rc_style->style);
+ if (error != PARSE_SYNTAX)
+ return error;
+
+ error = gtk_rc_parse_bg_pixmap (rc_style);
+ if (error != PARSE_SYNTAX)
+ return error;
+
+ error = gtk_rc_parse_font (rc_style);
+ if (error != PARSE_SYNTAX)
+ return error;
+
+ error = gtk_rc_parse_fontset (rc_style);
+
+ return error;
+}
+
+static gint
+gtk_rc_parse_base (GtkStyle *style)
+{
+ GtkStateType state;
+ gint token;
+ gint error;
+
+ token = gtk_rc_peek_next_token ();
+ if (!token)
+ return PARSE_ERROR;
+ if (token != TOKEN_BASE)
+ return PARSE_SYNTAX;
+ token = gtk_rc_get_next_token ();
+
+ error = gtk_rc_parse_state (&state);
+ if (error != PARSE_OK)
+ return error;
+
+ token = gtk_rc_get_next_token ();
+ if (!token || (token != TOKEN_EQUAL_SIGN))
+ return PARSE_ERROR;
+
+ error = gtk_rc_parse_color (&style->base[state]);
+
+ return error;
+}
+
+static gint
+gtk_rc_parse_bg (GtkStyle *style)
+{
+ GtkStateType state;
+ gint token;
+ gint error;
+
+ token = gtk_rc_peek_next_token ();
+ if (!token)
+ return PARSE_ERROR;
+ if (token != TOKEN_BG)
+ return PARSE_SYNTAX;
+ token = gtk_rc_get_next_token ();
+
+ error = gtk_rc_parse_state (&state);
+ if (error != PARSE_OK)
+ return error;
+
+ token = gtk_rc_get_next_token ();
+ if (!token || (token != TOKEN_EQUAL_SIGN))
+ return PARSE_ERROR;
+
+ error = gtk_rc_parse_color (&style->bg[state]);
+
+ return error;
+}
+
+static gint
+gtk_rc_parse_fg (GtkStyle *style)
+{
+ GtkStateType state;
+ gint token;
+ gint error;
+
+ token = gtk_rc_peek_next_token ();
+ if (!token)
+ return PARSE_ERROR;
+ if (token != TOKEN_FG)
+ return PARSE_SYNTAX;
+ token = gtk_rc_get_next_token ();
+
+ error = gtk_rc_parse_state (&state);
+ if (error != PARSE_OK)
+ return error;
+
+ token = gtk_rc_get_next_token ();
+ if (!token || (token != TOKEN_EQUAL_SIGN))
+ return PARSE_ERROR;
+
+ error = gtk_rc_parse_color (&style->fg[state]);
+
+ return error;
+}
+
+static gint
+gtk_rc_parse_bg_pixmap (GtkRcStyle *rc_style)
+{
+ GtkStateType state;
+ gint token;
+ gint error;
+ gchar *pixmap_file;
+
+ token = gtk_rc_peek_next_token ();
+ if (!token)
+ return PARSE_ERROR;
+ if (token != TOKEN_BG_PIXMAP)
+ return PARSE_SYNTAX;
+ token = gtk_rc_get_next_token ();
+
+ error = gtk_rc_parse_state (&state);
+ if (error != PARSE_OK)
+ return error;
+
+ token = gtk_rc_get_next_token ();
+ if (!token || (token != TOKEN_EQUAL_SIGN))
+ return PARSE_ERROR;
+
+ token = gtk_rc_get_next_token ();
+ if (!token || (token != TOKEN_STRING))
+ return PARSE_ERROR;
+
+ if (strcmp (token_str, "<parent>"))
+ pixmap_file = gtk_rc_find_pixmap_in_path (token_str);
+ else
+ pixmap_file = g_strdup(token_str);
+
+ if (pixmap_file)
+ {
+ if (rc_style->bg_pixmap_name[state])
+ g_free (rc_style->bg_pixmap_name[state]);
+ rc_style->bg_pixmap_name[state] = pixmap_file;
+ }
+
+ return PARSE_OK;
+}
+
+static char*
+gtk_rc_find_pixmap_in_path (gchar *pixmap_file)
+{
+ gint i;
+ FILE *fp;
+ gchar *buf;
+
+ for (i = 0; (i < GTK_RC_MAX_PIXMAP_PATHS) && (pixmap_path[i] != NULL); i++)
+ {
+ buf = g_malloc (strlen (pixmap_path[i]) + strlen (pixmap_file) + 2);
+ sprintf (buf, "%s%c%s", pixmap_path[i], '/', pixmap_file);
+
+ fp = fopen (buf, "r");
+ if (fp)
+ {
+ fclose (fp);
+ return buf;
+ }
+
+ g_free (buf);
+ }
+
+ g_warning ("Unable to locate image file in pixmap_path: \"%s\" line %d",
+ pixmap_file, linenum);
+
+ return NULL;
+}
+
+static gint
+gtk_rc_parse_font (GtkRcStyle *rc_style)
+{
+ gint token;
+
+ token = gtk_rc_peek_next_token ();
+ if (!token)
+ return PARSE_ERROR;
+ if (token != TOKEN_FONT)
+ return PARSE_SYNTAX;
+ token = gtk_rc_get_next_token ();
+
+ token = gtk_rc_get_next_token ();
+ if (!token || (token != TOKEN_EQUAL_SIGN))
+ return PARSE_ERROR;
+
+ token = gtk_rc_get_next_token ();
+ if (!token || (token != TOKEN_STRING))
+ return PARSE_ERROR;
+
+ if (rc_style->font_name)
+ g_free (rc_style->font_name);
+ rc_style->font_name = g_strdup (token_str);
+
+ return PARSE_OK;
+}
+
+static gint
+gtk_rc_parse_fontset (GtkRcStyle *rc_style)
+{
+ gint token;
+
+ token = gtk_rc_peek_next_token ();
+ if (!token)
+ return PARSE_ERROR;
+ if (token != TOKEN_FONTSET)
+ return PARSE_SYNTAX;
+ token = gtk_rc_get_next_token ();
+
+ token = gtk_rc_get_next_token ();
+ if (!token || (token != TOKEN_EQUAL_SIGN))
+ return PARSE_ERROR;
+
+ token = gtk_rc_get_next_token ();
+ if (!token || (token != TOKEN_STRING))
+ return PARSE_ERROR;
+
+ if (rc_style->fontset_name)
+ g_free (rc_style->fontset_name);
+ rc_style->fontset_name = g_strdup (token_str);
+
+ return PARSE_OK;
+}
+
+static gint
+gtk_rc_parse_state (GtkStateType *state)
+{
+ gint token;
+
+ token = gtk_rc_peek_next_token ();
+ if (!token)
+ return PARSE_ERROR;
+ if (token != TOKEN_LEFT_BRACE)
+ return PARSE_SYNTAX;
+ token = gtk_rc_get_next_token ();
+
+ token = gtk_rc_get_next_token ();
+ if (token == TOKEN_ACTIVE)
+ *state = GTK_STATE_ACTIVE;
+ else if (token == TOKEN_INSENSITIVE)
+ *state = GTK_STATE_INSENSITIVE;
+ else if (token == TOKEN_NORMAL)
+ *state = GTK_STATE_NORMAL;
+ else if (token == TOKEN_PRELIGHT)
+ *state = GTK_STATE_PRELIGHT;
+ else if (token == TOKEN_SELECTED)
+ *state = GTK_STATE_SELECTED;
+ else
+ return PARSE_ERROR;
+
+ token = gtk_rc_get_next_token ();
+ if (!token || (token != TOKEN_RIGHT_BRACE))
+ return PARSE_ERROR;
+
+ return PARSE_OK;
+}
+
+static gint
+gtk_rc_parse_color (GdkColor *color)
+{
+ gint token;
+ gint length;
+ gint temp;
+ gchar buf[9];
+ gint i, j;
+
+ token = gtk_rc_peek_next_token ();
+ if (!token)
+ return PARSE_ERROR;
+
+ switch (token)
+ {
+ case TOKEN_LEFT_CURLY:
+ token = gtk_rc_get_next_token ();
+
+ token = gtk_rc_get_next_token ();
+ if (!token || ((token != TOKEN_INTEGER) && (token != TOKEN_FLOAT)))
+ return PARSE_ERROR;
+
+ if (token == TOKEN_FLOAT)
+ token_int = token_float * 65535.0;
+ if (token_int < 0)
+ token_int = 0;
+ if (token_int > 65535)
+ token_int = 65535;
+
+ color->red = token_int;
+
+ token = gtk_rc_get_next_token ();
+ if (!token || (token != TOKEN_COMMA))
+ return PARSE_ERROR;
+
+ token = gtk_rc_get_next_token ();
+ if (!token || ((token != TOKEN_INTEGER) && (token != TOKEN_FLOAT)))
+ return PARSE_ERROR;
+
+ if (token == TOKEN_FLOAT)
+ token_int = token_float * 65535.0;
+ if (token_int < 0)
+ token_int = 0;
+ if (token_int > 65535)
+ token_int = 65535;
+
+ color->green = token_int;
+
+ token = gtk_rc_get_next_token ();
+ if (!token || (token != TOKEN_COMMA))
+ return PARSE_ERROR;
+
+ token = gtk_rc_get_next_token ();
+ if (!token || ((token != TOKEN_INTEGER) && (token != TOKEN_FLOAT)))
+ return PARSE_ERROR;
+
+ if (token == TOKEN_FLOAT)
+ token_int = token_float * 65535.0;
+ if (token_int < 0)
+ token_int = 0;
+ if (token_int > 65535)
+ token_int = 65535;
+
+ color->blue = token_int;
+
+ token = gtk_rc_get_next_token ();
+ if (!token || (token != TOKEN_RIGHT_CURLY))
+ return PARSE_ERROR;
+ break;
+
+ case TOKEN_STRING:
+ token = gtk_rc_get_next_token ();
+
+ if (token_str[0] != '#')
+ return PARSE_ERROR;
+
+ length = strlen (token_str) - 1;
+ if (((length % 3) != 0) || (length > 12))
+ return PARSE_ERROR;
+ length /= 3;
+
+ for (i = 0, j = 1; i < length; i++, j++)
+ buf[i] = token_str[j];
+ buf[i] = '\0';
+
+ sscanf (buf, "%x", &temp);
+ color->red = temp;
+
+ for (i = 0; i < length; i++, j++)
+ buf[i] = token_str[j];
+ buf[i] = '\0';
+
+ sscanf (buf, "%x", &temp);
+ color->green = temp;
+
+ for (i = 0; i < length; i++, j++)
+ buf[i] = token_str[j];
+ buf[i] = '\0';
+
+ sscanf (buf, "%x", &temp);
+ color->blue = temp;
+
+ if (length == 1)
+ {
+ color->red *= 4369;
+ color->green *= 4369;
+ color->blue *= 4369;
+ }
+ else if (length == 2)
+ {
+ color->red *= 257;
+ color->green *= 257;
+ color->blue *= 257;
+ }
+ else if (length == 3)
+ {
+ color->red *= 16;
+ color->green *= 16;
+ color->blue *= 16;
+ }
+ break;
+
+ default:
+ return PARSE_SYNTAX;
+ }
+
+ return PARSE_OK;
+}
+
+static gint
+gtk_rc_parse_pixmap_path ()
+{
+ gint token;
+
+ token = gtk_rc_peek_next_token ();
+ if (!token)
+ return PARSE_ERROR;
+ if (token != TOKEN_PIXMAP_PATH)
+ return PARSE_SYNTAX;
+ token = gtk_rc_get_next_token ();
+
+ token = gtk_rc_get_next_token ();
+
+ if (!token || (token != TOKEN_STRING))
+ return PARSE_ERROR;
+
+ gtk_rc_parse_pixmap_path_string(token_str);
+
+ return PARSE_OK;
+}
+
+static void gtk_rc_parse_pixmap_path_string(gchar *pix_path)
+{
+ gchar *buf;
+ gint end_offset;
+ gint start_offset = 0;
+ gint path_len;
+ gint path_num;
+
+ /* free the old one, or just add to the old one ? */
+ for (path_num=0; pixmap_path[path_num]; path_num++)
+ {
+ g_free(pixmap_path[path_num]);
+ pixmap_path[path_num] = NULL;
+ }
+
+ path_num = 0;
+
+ path_len = strlen(pix_path);
+
+ buf = g_strdup(pix_path);
+
+ for(end_offset = 0; end_offset <= path_len; end_offset++)
+ {
+ if ( (buf[end_offset] == ':') || (end_offset == path_len) )
+ {
+ buf[end_offset] = '\0';
+ pixmap_path[path_num] = g_strdup(buf + start_offset);
+ path_num++;
+ pixmap_path[path_num] = NULL;
+ start_offset = end_offset + 1;
+ g_free(buf);
+ buf = g_strdup(pix_path);
+ }
+ }
+ g_free(buf);
+}
+
+static gint
+gtk_rc_parse_widget_style ()
+{
+ GtkRcSet *rc_set;
+ gint token;
+
+ token = gtk_rc_peek_next_token ();
+ if (!token)
+ return PARSE_ERROR;
+ if (token != TOKEN_WIDGET)
+ return PARSE_SYNTAX;
+ token = gtk_rc_get_next_token ();
+
+ token = gtk_rc_get_next_token ();
+ if (!token || (token != TOKEN_STRING))
+ return PARSE_ERROR;
+
+ rc_set = g_new (GtkRcSet, 1);
+ rc_set->set = g_strdup (token_str);
+
+ token = gtk_rc_get_next_token ();
+ if (!token || (token != TOKEN_STYLE))
+ {
+ g_free (rc_set->set);
+ g_free (rc_set);
+ return PARSE_ERROR;
+ }
+
+ token = gtk_rc_get_next_token ();
+ if (!token || (token != TOKEN_STRING))
+ {
+ g_free (rc_set->set);
+ g_free (rc_set);
+ return PARSE_ERROR;
+ }
+
+ rc_set->rc_style = gtk_rc_style_find (token_str);
+ if (!rc_set->rc_style)
+ {
+ g_free (rc_set->set);
+ g_free (rc_set);
+ return PARSE_ERROR;
+ }
+
+ widget_sets = g_slist_append (widget_sets, rc_set);
+
+ return PARSE_OK;
+}
+
+static gint
+gtk_rc_parse_widget_class_style ()
+{
+ GtkRcSet *rc_set;
+ gint token;
+
+ token = gtk_rc_peek_next_token ();
+ if (!token)
+ return PARSE_ERROR;
+ if (token != TOKEN_WIDGET_CLASS)
+ return PARSE_SYNTAX;
+ token = gtk_rc_get_next_token ();
+
+ token = gtk_rc_get_next_token ();
+ if (!token || (token != TOKEN_STRING))
+ return PARSE_ERROR;
+
+ rc_set = g_new (GtkRcSet, 1);
+ rc_set->set = g_strdup (token_str);
+
+ token = gtk_rc_get_next_token ();
+ if (!token || (token != TOKEN_STYLE))
+ {
+ g_free (rc_set->set);
+ g_free (rc_set);
+ return PARSE_ERROR;
+ }
+
+ token = gtk_rc_get_next_token ();
+ if (!token || (token != TOKEN_STRING))
+ {
+ g_free (rc_set->set);
+ g_free (rc_set);
+ return PARSE_ERROR;
+ }
+
+ rc_set->rc_style = gtk_rc_style_find (token_str);
+ if (!rc_set->rc_style)
+ {
+ g_free (rc_set->set);
+ g_free (rc_set);
+ return PARSE_ERROR;
+ }
+
+ widget_class_sets = g_slist_append (widget_class_sets, rc_set);
+
+ return PARSE_OK;
+}
+
+static char*
+gtk_rc_widget_path (GtkWidget *widget)
+{
+ GtkWidget *tmp_widget;
+ char *path;
+ char *name;
+ int pathlength;
+ int namelength;
+
+ path = NULL;
+ pathlength = 0;
+
+ tmp_widget = widget;
+ while (tmp_widget)
+ {
+ name = gtk_widget_get_name (tmp_widget);
+ pathlength += strlen (name);
+
+ tmp_widget = tmp_widget->parent;
+
+ if (tmp_widget)
+ pathlength += 1;
+ }
+
+ path = g_new (char, pathlength + 1);
+ path[pathlength] = '\0';
+
+ tmp_widget = widget;
+ while (tmp_widget)
+ {
+ name = gtk_widget_get_name (tmp_widget);
+ namelength = strlen (name);
+
+ strncpy (&path[pathlength - namelength], name, namelength);
+ pathlength -= namelength;
+
+ tmp_widget = tmp_widget->parent;
+
+ if (tmp_widget)
+ {
+ pathlength -= 1;
+ path[pathlength] = '.';
+ }
+ }
+
+ return path;
+}
+
+static char*
+gtk_rc_widget_class_path (GtkWidget *widget)
+{
+ GtkWidget *tmp_widget;
+ char *path;
+ char *name;
+ int pathlength;
+ int namelength;
+
+ path = NULL;
+ pathlength = 0;
+
+ tmp_widget = widget;
+ while (tmp_widget)
+ {
+ name = gtk_type_name (GTK_WIDGET_TYPE (tmp_widget));
+ pathlength += strlen (name);
+
+ tmp_widget = tmp_widget->parent;
+
+ if (tmp_widget)
+ pathlength += 1;
+ }
+
+ path = g_new (char, pathlength + 1);
+ path[pathlength] = '\0';
+
+ tmp_widget = widget;
+ while (tmp_widget)
+ {
+ name = gtk_type_name (GTK_WIDGET_TYPE (tmp_widget));
+ namelength = strlen (name);
+
+ strncpy (&path[pathlength - namelength], name, namelength);
+ pathlength -= namelength;
+
+ tmp_widget = tmp_widget->parent;
+
+ if (tmp_widget)
+ {
+ pathlength -= 1;
+ path[pathlength] = '.';
+ }
+ }
+
+ return path;
+}
diff --git a/gtk/gtkrc.h b/gtk/gtkrc.h
new file mode 100644
index 000000000..8c761bb9e
--- /dev/null
+++ b/gtk/gtkrc.h
@@ -0,0 +1,45 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_RC_H__
+#define __GTK_RC_H__
+
+
+#include <gtk/gtkstyle.h>
+#include <gtk/gtkwidget.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+void gtk_rc_init (void);
+void gtk_rc_parse (const char *filename);
+GtkStyle* gtk_rc_get_style (GtkWidget *widget);
+void gtk_rc_add_widget_name_style (GtkStyle *style,
+ const char *pattern);
+void gtk_rc_add_widget_class_style (GtkStyle *style,
+ const char *pattern);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_RC_H__ */
diff --git a/gtk/gtkruler.c b/gtk/gtkruler.c
new file mode 100644
index 000000000..dad0e11f6
--- /dev/null
+++ b/gtk/gtkruler.c
@@ -0,0 +1,305 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtkruler.h"
+
+
+static void gtk_ruler_class_init (GtkRulerClass *klass);
+static void gtk_ruler_init (GtkRuler *ruler);
+static void gtk_ruler_realize (GtkWidget *widget);
+static void gtk_ruler_unrealize (GtkWidget *widget);
+static void gtk_ruler_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static gint gtk_ruler_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+static void gtk_ruler_make_pixmap (GtkRuler *ruler);
+
+
+static GtkRulerMetric ruler_metrics[] =
+{
+ {"Pixels", "Pi", 1.0, { 1, 2, 5, 10, 25, 50, 100, 250, 500, 1000 }, { 1, 5, 10, 50, 100 }},
+ {"Inches", "In", 72.0, { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512 }, { 1, 2, 4, 8, 16 }},
+ {"Centimeters", "Cn", 28.35, { 1, 2, 5, 10, 25, 50, 100, 250, 500, 1000 }, { 1, 5, 10, 50, 100 }},
+};
+
+
+guint
+gtk_ruler_get_type ()
+{
+ static guint ruler_type = 0;
+
+ if (!ruler_type)
+ {
+ GtkTypeInfo ruler_info =
+ {
+ "GtkRuler",
+ sizeof (GtkRuler),
+ sizeof (GtkRulerClass),
+ (GtkClassInitFunc) gtk_ruler_class_init,
+ (GtkObjectInitFunc) gtk_ruler_init,
+ (GtkArgFunc) NULL,
+ };
+
+ ruler_type = gtk_type_unique (gtk_widget_get_type (), &ruler_info);
+ }
+
+ return ruler_type;
+}
+
+static void
+gtk_ruler_class_init (GtkRulerClass *class)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+
+ object_class = (GtkObjectClass*) class;
+ widget_class = (GtkWidgetClass*) class;
+
+ widget_class->realize = gtk_ruler_realize;
+ widget_class->unrealize = gtk_ruler_unrealize;
+ widget_class->size_allocate = gtk_ruler_size_allocate;
+ widget_class->expose_event = gtk_ruler_expose;
+
+ class->draw_ticks = NULL;
+ class->draw_pos = NULL;
+}
+
+static void
+gtk_ruler_init (GtkRuler *ruler)
+{
+ ruler->backing_store = NULL;
+ ruler->non_gr_exp_gc = NULL;
+ ruler->xsrc = 0;
+ ruler->ysrc = 0;
+ ruler->slider_size = 0;
+ ruler->lower = 0;
+ ruler->upper = 0;
+ ruler->position = 0;
+ ruler->max_size = 0;
+
+ gtk_ruler_set_metric (ruler, GTK_PIXELS);
+}
+
+void
+gtk_ruler_set_metric (GtkRuler *ruler,
+ GtkMetricType metric)
+{
+ g_return_if_fail (ruler != NULL);
+ g_return_if_fail (GTK_IS_RULER (ruler));
+
+ ruler->metric = &ruler_metrics[metric];
+
+ if (GTK_WIDGET_DRAWABLE (ruler))
+ gtk_widget_queue_draw (GTK_WIDGET (ruler));
+}
+
+void
+gtk_ruler_set_range (GtkRuler *ruler,
+ gfloat lower,
+ gfloat upper,
+ gfloat position,
+ gfloat max_size)
+{
+ g_return_if_fail (ruler != NULL);
+ g_return_if_fail (GTK_IS_RULER (ruler));
+
+ ruler->lower = lower;
+ ruler->upper = upper;
+ ruler->position = position;
+ ruler->max_size = max_size;
+
+ if (GTK_WIDGET_DRAWABLE (ruler))
+ gtk_widget_queue_draw (GTK_WIDGET (ruler));
+}
+
+void
+gtk_ruler_draw_ticks (GtkRuler *ruler)
+{
+ g_return_if_fail (ruler != NULL);
+ g_return_if_fail (GTK_IS_RULER (ruler));
+
+ if (GTK_RULER_CLASS (GTK_OBJECT (ruler)->klass)->draw_ticks)
+ (* GTK_RULER_CLASS (GTK_OBJECT (ruler)->klass)->draw_ticks) (ruler);
+}
+
+void
+gtk_ruler_draw_pos (GtkRuler *ruler)
+{
+ g_return_if_fail (ruler != NULL);
+ g_return_if_fail (GTK_IS_RULER (ruler));
+
+ if (GTK_RULER_CLASS (GTK_OBJECT (ruler)->klass)->draw_pos)
+ (* GTK_RULER_CLASS (GTK_OBJECT (ruler)->klass)->draw_pos) (ruler);
+}
+
+
+static void
+gtk_ruler_realize (GtkWidget *widget)
+{
+ GtkRuler *ruler;
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_RULER (widget));
+
+ ruler = GTK_RULER (widget);
+ GTK_WIDGET_SET_FLAGS (ruler, GTK_REALIZED);
+
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.x = widget->allocation.x;
+ attributes.y = widget->allocation.y;
+ attributes.width = widget->allocation.width;
+ attributes.height = widget->allocation.height;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
+ attributes.event_mask = gtk_widget_get_events (widget);
+ attributes.event_mask |= (GDK_EXPOSURE_MASK |
+ GDK_POINTER_MOTION_MASK |
+ GDK_POINTER_MOTION_HINT_MASK);
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+
+ widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
+ gdk_window_set_user_data (widget->window, ruler);
+
+ widget->style = gtk_style_attach (widget->style, widget->window);
+ gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
+
+ gtk_ruler_make_pixmap (ruler);
+}
+
+static void
+gtk_ruler_unrealize (GtkWidget *widget)
+{
+ GtkRuler *ruler;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_RULER (widget));
+
+ ruler = GTK_RULER (widget);
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_REALIZED | GTK_MAPPED);
+
+ gtk_style_detach (widget->style);
+ gdk_window_destroy (widget->window);
+ widget->window = NULL;
+
+ if (ruler->backing_store)
+ gdk_pixmap_destroy (ruler->backing_store);
+ if (ruler->non_gr_exp_gc)
+ gdk_gc_destroy (ruler->non_gr_exp_gc);
+
+ ruler->backing_store = NULL;
+ ruler->non_gr_exp_gc = NULL;
+}
+
+static void
+gtk_ruler_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkRuler *ruler;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_RULER (widget));
+
+ ruler = GTK_RULER (widget);
+ widget->allocation = *allocation;
+
+ if (GTK_WIDGET_REALIZED (widget))
+ {
+ gdk_window_move_resize (widget->window,
+ allocation->x, allocation->y,
+ allocation->width, allocation->height);
+
+ gtk_ruler_make_pixmap (ruler);
+ }
+}
+
+static gint
+gtk_ruler_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ GtkRuler *ruler;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_RULER (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ ruler = GTK_RULER (widget);
+
+ gdk_draw_rectangle (ruler->backing_store,
+ widget->style->bg_gc[GTK_STATE_NORMAL],
+ TRUE, 0, 0,
+ widget->allocation.width,
+ widget->allocation.height);
+
+ gtk_ruler_draw_ticks (ruler);
+
+ gtk_draw_shadow (widget->style, ruler->backing_store,
+ GTK_STATE_NORMAL, GTK_SHADOW_OUT, 0, 0,
+ widget->allocation.width,
+ widget->allocation.height);
+
+ gdk_draw_pixmap (widget->window,
+ ruler->non_gr_exp_gc,
+ ruler->backing_store,
+ 0, 0, 0, 0,
+ widget->allocation.width,
+ widget->allocation.height);
+
+ gtk_ruler_draw_pos (ruler);
+ }
+
+ return FALSE;
+}
+
+static void
+gtk_ruler_make_pixmap (GtkRuler *ruler)
+{
+ GtkWidget *widget;
+ gint width;
+ gint height;
+
+ widget = GTK_WIDGET (ruler);
+
+ if (ruler->backing_store)
+ {
+ gdk_window_get_size (ruler->backing_store, &width, &height);
+ if ((width == widget->allocation.width) &&
+ (height == widget->allocation.height))
+ return;
+
+ gdk_pixmap_destroy (ruler->backing_store);
+ }
+
+ ruler->backing_store = gdk_pixmap_new (widget->window,
+ widget->allocation.width,
+ widget->allocation.height,
+ -1);
+
+ ruler->xsrc = 0;
+ ruler->ysrc = 0;
+
+ if (!ruler->non_gr_exp_gc)
+ {
+ ruler->non_gr_exp_gc = gdk_gc_new (widget->window);
+ gdk_gc_set_exposures (ruler->non_gr_exp_gc, FALSE);
+ }
+}
diff --git a/gtk/gtkruler.h b/gtk/gtkruler.h
new file mode 100644
index 000000000..c74b20321
--- /dev/null
+++ b/gtk/gtkruler.h
@@ -0,0 +1,91 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_RULER_H__
+#define __GTK_RULER_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkwidget.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_RULER(obj) GTK_CHECK_CAST (obj, gtk_ruler_get_type (), GtkRuler)
+#define GTK_RULER_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_ruler_get_type (), GtkRulerClass)
+#define GTK_IS_RULER(obj) GTK_CHECK_TYPE (obj, gtk_ruler_get_type ())
+
+
+typedef struct _GtkRuler GtkRuler;
+typedef struct _GtkRulerClass GtkRulerClass;
+typedef struct _GtkRulerMetric GtkRulerMetric;
+
+struct _GtkRuler
+{
+ GtkWidget widget;
+
+ GdkPixmap *backing_store;
+ GdkGC *non_gr_exp_gc;
+ GtkRulerMetric *metric;
+ gint xsrc, ysrc;
+ gint slider_size;
+
+ gfloat lower;
+ gfloat upper;
+ gfloat position;
+ gfloat max_size;
+};
+
+struct _GtkRulerClass
+{
+ GtkWidgetClass parent_class;
+
+ void (* draw_ticks) (GtkRuler *ruler);
+ void (* draw_pos) (GtkRuler *ruler);
+};
+
+struct _GtkRulerMetric
+{
+ gchar *metric_name;
+ gchar *abbrev;
+ gfloat pixels_per_unit;
+ gfloat ruler_scale[10];
+ gint subdivide[5]; /* five possible modes of subdivision */
+};
+
+
+guint gtk_ruler_get_type (void);
+void gtk_ruler_set_metric (GtkRuler *ruler,
+ GtkMetricType metric);
+void gtk_ruler_set_range (GtkRuler *ruler,
+ gfloat lower,
+ gfloat upper,
+ gfloat position,
+ gfloat max_size);
+void gtk_ruler_draw_ticks (GtkRuler *ruler);
+void gtk_ruler_draw_pos (GtkRuler *ruler);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_RULER_H__ */
diff --git a/gtk/gtkscale.c b/gtk/gtkscale.c
new file mode 100644
index 000000000..ba2f18616
--- /dev/null
+++ b/gtk/gtkscale.c
@@ -0,0 +1,229 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <math.h>
+#include "gtkcontainer.h"
+#include "gtkscale.h"
+
+
+#define SCALE_CLASS(w) GTK_SCALE_CLASS (GTK_OBJECT (w)->klass)
+
+
+static void gtk_scale_class_init (GtkScaleClass *klass);
+static void gtk_scale_init (GtkScale *scale);
+static void gtk_scale_destroy (GtkObject *object);
+static void gtk_scale_draw_background (GtkRange *range);
+
+
+static GtkRangeClass *parent_class = NULL;
+
+
+guint
+gtk_scale_get_type ()
+{
+ static guint scale_type = 0;
+
+ if (!scale_type)
+ {
+ GtkTypeInfo scale_info =
+ {
+ "GtkScale",
+ sizeof (GtkScale),
+ sizeof (GtkScaleClass),
+ (GtkClassInitFunc) gtk_scale_class_init,
+ (GtkObjectInitFunc) gtk_scale_init,
+ (GtkArgFunc) NULL,
+ };
+
+ scale_type = gtk_type_unique (gtk_range_get_type (), &scale_info);
+ }
+
+ return scale_type;
+}
+
+static void
+gtk_scale_class_init (GtkScaleClass *class)
+{
+ GtkObjectClass *object_class;
+ GtkRangeClass *range_class;
+
+ object_class = (GtkObjectClass*) class;
+ range_class = (GtkRangeClass*) class;
+
+ parent_class = gtk_type_class (gtk_range_get_type ());
+
+ object_class->destroy = gtk_scale_destroy;
+
+ range_class->draw_background = gtk_scale_draw_background;
+
+ class->slider_length = 31;
+ class->value_spacing = 2;
+ class->draw_value = NULL;
+}
+
+static void
+gtk_scale_init (GtkScale *scale)
+{
+ GTK_WIDGET_SET_FLAGS (scale, GTK_CAN_FOCUS);
+ GTK_RANGE (scale)->digits = 1;
+ scale->draw_value = TRUE;
+ scale->value_pos = GTK_POS_TOP;
+}
+
+void
+gtk_scale_set_digits (GtkScale *scale,
+ gint digits)
+{
+ g_return_if_fail (scale != NULL);
+ g_return_if_fail (GTK_IS_SCALE (scale));
+
+ if (GTK_RANGE (scale)->digits != digits)
+ {
+ GTK_RANGE (scale)->digits = digits;
+
+ if (GTK_WIDGET_VISIBLE (scale) && GTK_WIDGET_MAPPED (scale))
+ gtk_widget_queue_resize (GTK_WIDGET (scale));
+ }
+}
+
+void
+gtk_scale_set_draw_value (GtkScale *scale,
+ gint draw_value)
+{
+ g_return_if_fail (scale != NULL);
+ g_return_if_fail (GTK_IS_SCALE (scale));
+
+ if (scale->draw_value != draw_value)
+ {
+ scale->draw_value = (draw_value != 0);
+
+ if (GTK_WIDGET_VISIBLE (scale) && GTK_WIDGET_MAPPED (scale))
+ gtk_widget_queue_resize (GTK_WIDGET (scale));
+ }
+}
+
+void
+gtk_scale_set_value_pos (GtkScale *scale,
+ GtkPositionType pos)
+{
+ g_return_if_fail (scale != NULL);
+ g_return_if_fail (GTK_IS_SCALE (scale));
+
+ if (scale->value_pos != pos)
+ {
+ scale->value_pos = pos;
+
+ if (GTK_WIDGET_VISIBLE (scale) && GTK_WIDGET_MAPPED (scale))
+ gtk_widget_queue_resize (GTK_WIDGET (scale));
+ }
+}
+
+gint
+gtk_scale_value_width (GtkScale *scale)
+{
+ GtkRange *range;
+ gchar buffer[128];
+ gfloat value;
+ gint temp;
+ gint return_val;
+ gint digits;
+ gint i, j;
+
+ g_return_val_if_fail (scale != NULL, 0);
+ g_return_val_if_fail (GTK_IS_SCALE (scale), 0);
+
+ return_val = 0;
+ if (scale->draw_value)
+ {
+ range = GTK_RANGE (scale);
+
+ value = ABS (range->adjustment->lower);
+ if (value == 0) value = 1;
+ digits = log10 (value) + 1;
+ if (digits > 13)
+ digits = 13;
+
+ i = 0;
+ if (range->adjustment->lower < 0)
+ buffer[i++] = '-';
+ for (j = 0; j < digits; j++)
+ buffer[i++] = '0';
+ if (GTK_RANGE (scale)->digits)
+ buffer[i++] = '.';
+ for (j = 0; j < GTK_RANGE (scale)->digits; j++)
+ buffer[i++] = '0';
+ buffer[i] = '\0';
+
+ return_val = gdk_string_measure (GTK_WIDGET (scale)->style->font, buffer);
+
+ value = ABS (range->adjustment->upper);
+ if (value == 0) value = 1;
+ digits = log10 (value) + 1;
+ if (digits > 13)
+ digits = 13;
+
+ i = 0;
+ if (range->adjustment->lower < 0)
+ buffer[i++] = '-';
+ for (j = 0; j < digits; j++)
+ buffer[i++] = '0';
+ if (GTK_RANGE (scale)->digits)
+ buffer[i++] = '.';
+ for (j = 0; j < GTK_RANGE (scale)->digits; j++)
+ buffer[i++] = '0';
+ buffer[i] = '\0';
+
+ temp = gdk_string_measure (GTK_WIDGET (scale)->style->font, buffer);
+ return_val = MAX (return_val, temp);
+ }
+
+ return return_val;
+}
+
+void
+gtk_scale_draw_value (GtkScale *scale)
+{
+ g_return_if_fail (scale != NULL);
+ g_return_if_fail (GTK_IS_SCALE (scale));
+
+ if (SCALE_CLASS (scale)->draw_value)
+ (* SCALE_CLASS (scale)->draw_value) (scale);
+}
+
+
+static void
+gtk_scale_destroy (GtkObject *object)
+{
+ GtkRange *range;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_SCALE (object));
+
+ range = GTK_RANGE (object);
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+static void
+gtk_scale_draw_background (GtkRange *range)
+{
+ g_return_if_fail (range != NULL);
+ g_return_if_fail (GTK_IS_SCALE (range));
+
+ gtk_scale_draw_value (GTK_SCALE (range));
+}
diff --git a/gtk/gtkscale.h b/gtk/gtkscale.h
new file mode 100644
index 000000000..6fe2e4925
--- /dev/null
+++ b/gtk/gtkscale.h
@@ -0,0 +1,75 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_SCALE_H__
+#define __GTK_SCALE_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkrange.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_SCALE(obj) GTK_CHECK_CAST (obj, gtk_scale_get_type (), GtkScale)
+#define GTK_SCALE_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_scale_get_type (), GtkScaleClass)
+#define GTK_IS_SCALE(obj) GTK_CHECK_TYPE (obj, gtk_scale_get_type ())
+
+
+typedef struct _GtkScale GtkScale;
+typedef struct _GtkScaleClass GtkScaleClass;
+
+struct _GtkScale
+{
+ GtkRange range;
+
+ guint draw_value : 1;
+ guint value_pos : 2;
+};
+
+struct _GtkScaleClass
+{
+ GtkRangeClass parent_class;
+
+ gint slider_length;
+ gint value_spacing;
+
+ void (* draw_value) (GtkScale *scale);
+};
+
+
+guint gtk_scale_get_type (void);
+void gtk_scale_set_digits (GtkScale *scale,
+ gint digits);
+void gtk_scale_set_draw_value (GtkScale *scale,
+ gint draw_value);
+void gtk_scale_set_value_pos (GtkScale *scale,
+ GtkPositionType pos);
+gint gtk_scale_value_width (GtkScale *scale);
+
+void gtk_scale_draw_value (GtkScale *scale);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_SCALE_H__ */
diff --git a/gtk/gtkscrollbar.c b/gtk/gtkscrollbar.c
new file mode 100644
index 000000000..3f5088b44
--- /dev/null
+++ b/gtk/gtkscrollbar.c
@@ -0,0 +1,54 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtkscrollbar.h"
+
+static void gtk_scrollbar_class_init (GtkScrollbarClass *klass);
+static void gtk_scrollbar_init (GtkScrollbar *scrollbar);
+
+guint
+gtk_scrollbar_get_type ()
+{
+ static guint scrollbar_type = 0;
+
+ if (!scrollbar_type)
+ {
+ GtkTypeInfo scrollbar_info =
+ {
+ "GtkScrollbar",
+ sizeof (GtkScrollbar),
+ sizeof (GtkScrollbarClass),
+ (GtkClassInitFunc) gtk_scrollbar_class_init,
+ (GtkObjectInitFunc) gtk_scrollbar_init,
+ (GtkArgFunc) NULL,
+ };
+
+ scrollbar_type = gtk_type_unique (gtk_range_get_type (), &scrollbar_info);
+ }
+
+ return scrollbar_type;
+}
+
+static void
+gtk_scrollbar_class_init (GtkScrollbarClass *class)
+{
+}
+
+static void
+gtk_scrollbar_init (GtkScrollbar *scrollbar)
+{
+}
diff --git a/gtk/gtkscrollbar.h b/gtk/gtkscrollbar.h
new file mode 100644
index 000000000..14aadad1a
--- /dev/null
+++ b/gtk/gtkscrollbar.h
@@ -0,0 +1,58 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_SCROLLBAR_H__
+#define __GTK_SCROLLBAR_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkrange.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_SCROLLBAR(obj) GTK_CHECK_CAST (obj, gtk_scrollbar_get_type (), GtkScrollbar)
+#define GTK_SCROLLBAR_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_scrollbar_get_type (), GtkScrollbarClass)
+#define GTK_IS_SCROLLBAR(obj) GTK_CHECK_TYPE (obj, gtk_scrollbar_get_type ())
+
+
+typedef struct _GtkScrollbar GtkScrollbar;
+typedef struct _GtkScrollbarClass GtkScrollbarClass;
+
+struct _GtkScrollbar
+{
+ GtkRange range;
+};
+
+struct _GtkScrollbarClass
+{
+ GtkRangeClass parent_class;
+};
+
+
+guint gtk_scrollbar_get_type (void);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_SCROLLBAR_H__ */
diff --git a/gtk/gtkscrolledwindow.c b/gtk/gtkscrolledwindow.c
new file mode 100644
index 000000000..79cc67aaf
--- /dev/null
+++ b/gtk/gtkscrolledwindow.c
@@ -0,0 +1,510 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtkscrolledwindow.h"
+#include "gtksignal.h"
+
+
+#define SCROLLBAR_SPACING 5
+
+
+static void gtk_scrolled_window_class_init (GtkScrolledWindowClass *klass);
+static void gtk_scrolled_window_init (GtkScrolledWindow *scrolled_window);
+static void gtk_scrolled_window_destroy (GtkObject *object);
+static void gtk_scrolled_window_map (GtkWidget *widget);
+static void gtk_scrolled_window_unmap (GtkWidget *widget);
+static void gtk_scrolled_window_draw (GtkWidget *widget,
+ GdkRectangle *area);
+static void gtk_scrolled_window_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void gtk_scrolled_window_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static void gtk_scrolled_window_add (GtkContainer *container,
+ GtkWidget *widget);
+static void gtk_scrolled_window_remove (GtkContainer *container,
+ GtkWidget *widget);
+static void gtk_scrolled_window_foreach (GtkContainer *container,
+ GtkCallback callback,
+ gpointer callback_data);
+static void gtk_scrolled_window_viewport_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static void gtk_scrolled_window_adjustment_changed (GtkAdjustment *adjustment,
+ gpointer data);
+
+
+static GtkContainerClass *parent_class = NULL;
+
+
+guint
+gtk_scrolled_window_get_type ()
+{
+ static guint scrolled_window_type = 0;
+
+ if (!scrolled_window_type)
+ {
+ GtkTypeInfo scrolled_window_info =
+ {
+ "GtkScrolledWindow",
+ sizeof (GtkScrolledWindow),
+ sizeof (GtkScrolledWindowClass),
+ (GtkClassInitFunc) gtk_scrolled_window_class_init,
+ (GtkObjectInitFunc) gtk_scrolled_window_init,
+ (GtkArgFunc) NULL,
+ };
+
+ scrolled_window_type = gtk_type_unique (gtk_container_get_type (), &scrolled_window_info);
+ }
+
+ return scrolled_window_type;
+}
+
+static void
+gtk_scrolled_window_class_init (GtkScrolledWindowClass *class)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+ GtkContainerClass *container_class;
+
+ object_class = (GtkObjectClass*) class;
+ widget_class = (GtkWidgetClass*) class;
+ container_class = (GtkContainerClass*) class;
+
+ parent_class = gtk_type_class (gtk_container_get_type ());
+
+ object_class->destroy = gtk_scrolled_window_destroy;
+
+ widget_class->map = gtk_scrolled_window_map;
+ widget_class->unmap = gtk_scrolled_window_unmap;
+ widget_class->draw = gtk_scrolled_window_draw;
+ widget_class->size_request = gtk_scrolled_window_size_request;
+ widget_class->size_allocate = gtk_scrolled_window_size_allocate;
+
+ container_class->add = gtk_scrolled_window_add;
+ container_class->remove = gtk_scrolled_window_remove;
+ container_class->foreach = gtk_scrolled_window_foreach;
+}
+
+static void
+gtk_scrolled_window_init (GtkScrolledWindow *scrolled_window)
+{
+ GTK_WIDGET_SET_FLAGS (scrolled_window, GTK_NO_WINDOW);
+
+ scrolled_window->hscrollbar = NULL;
+ scrolled_window->vscrollbar = NULL;
+ scrolled_window->hscrollbar_policy = GTK_POLICY_ALWAYS;
+ scrolled_window->vscrollbar_policy = GTK_POLICY_ALWAYS;
+}
+
+GtkWidget*
+gtk_scrolled_window_new (GtkAdjustment *hadjustment,
+ GtkAdjustment *vadjustment)
+{
+ GtkScrolledWindow *scrolled_window;
+
+ scrolled_window = gtk_type_new (gtk_scrolled_window_get_type ());
+
+ scrolled_window->viewport = gtk_viewport_new (hadjustment, vadjustment);
+ hadjustment = gtk_viewport_get_hadjustment (GTK_VIEWPORT (scrolled_window->viewport));
+ vadjustment = gtk_viewport_get_vadjustment (GTK_VIEWPORT (scrolled_window->viewport));
+
+ gtk_signal_connect (GTK_OBJECT (hadjustment), "changed",
+ (GtkSignalFunc) gtk_scrolled_window_adjustment_changed,
+ (gpointer) scrolled_window);
+ gtk_signal_connect (GTK_OBJECT (vadjustment), "changed",
+ (GtkSignalFunc) gtk_scrolled_window_adjustment_changed,
+ (gpointer) scrolled_window);
+
+ scrolled_window->hscrollbar = gtk_hscrollbar_new (hadjustment);
+ scrolled_window->vscrollbar = gtk_vscrollbar_new (vadjustment);
+
+ gtk_widget_set_parent (scrolled_window->viewport, GTK_WIDGET (scrolled_window));
+ gtk_widget_set_parent (scrolled_window->hscrollbar, GTK_WIDGET (scrolled_window));
+ gtk_widget_set_parent (scrolled_window->vscrollbar, GTK_WIDGET (scrolled_window));
+
+ gtk_widget_show (scrolled_window->viewport);
+ gtk_widget_show (scrolled_window->hscrollbar);
+ gtk_widget_show (scrolled_window->vscrollbar);
+
+ return GTK_WIDGET (scrolled_window);
+}
+
+GtkAdjustment*
+gtk_scrolled_window_get_hadjustment (GtkScrolledWindow *scrolled_window)
+{
+ g_return_val_if_fail (scrolled_window != NULL, NULL);
+ g_return_val_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window), NULL);
+
+ return gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar));
+}
+
+GtkAdjustment*
+gtk_scrolled_window_get_vadjustment (GtkScrolledWindow *scrolled_window)
+{
+ g_return_val_if_fail (scrolled_window != NULL, NULL);
+ g_return_val_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window), NULL);
+
+ return gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar));
+}
+
+void
+gtk_scrolled_window_set_policy (GtkScrolledWindow *scrolled_window,
+ GtkPolicyType hscrollbar_policy,
+ GtkPolicyType vscrollbar_policy)
+{
+ g_return_if_fail (scrolled_window != NULL);
+ g_return_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window));
+
+ if ((scrolled_window->hscrollbar_policy != hscrollbar_policy) ||
+ (scrolled_window->vscrollbar_policy != vscrollbar_policy))
+ {
+ scrolled_window->hscrollbar_policy = hscrollbar_policy;
+ scrolled_window->vscrollbar_policy = vscrollbar_policy;
+
+ if (GTK_WIDGET (scrolled_window)->parent)
+ gtk_widget_queue_resize (GTK_WIDGET (scrolled_window));
+ }
+}
+
+
+static void
+gtk_scrolled_window_destroy (GtkObject *object)
+{
+ GtkScrolledWindow *scrolled_window;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_SCROLLED_WINDOW (object));
+
+ scrolled_window = GTK_SCROLLED_WINDOW (object);
+
+ gtk_widget_destroy (scrolled_window->viewport);
+ gtk_widget_destroy (scrolled_window->hscrollbar);
+ gtk_widget_destroy (scrolled_window->vscrollbar);
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+static void
+gtk_scrolled_window_map (GtkWidget *widget)
+{
+ GtkScrolledWindow *scrolled_window;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_SCROLLED_WINDOW (widget));
+
+ if (!GTK_WIDGET_MAPPED (widget))
+ {
+ GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
+ scrolled_window = GTK_SCROLLED_WINDOW (widget);
+
+ if (GTK_WIDGET_VISIBLE (scrolled_window->viewport) &&
+ !GTK_WIDGET_MAPPED (scrolled_window->viewport))
+ gtk_widget_map (scrolled_window->viewport);
+
+ if (GTK_WIDGET_VISIBLE (scrolled_window->hscrollbar) &&
+ !GTK_WIDGET_MAPPED (scrolled_window->hscrollbar))
+ gtk_widget_map (scrolled_window->hscrollbar);
+
+ if (GTK_WIDGET_VISIBLE (scrolled_window->vscrollbar) &&
+ !GTK_WIDGET_MAPPED (scrolled_window->vscrollbar))
+ gtk_widget_map (scrolled_window->vscrollbar);
+ }
+}
+
+static void
+gtk_scrolled_window_unmap (GtkWidget *widget)
+{
+ GtkScrolledWindow *scrolled_window;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_SCROLLED_WINDOW (widget));
+
+ if (GTK_WIDGET_MAPPED (widget))
+ {
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
+ scrolled_window = GTK_SCROLLED_WINDOW (widget);
+
+ if (GTK_WIDGET_MAPPED (scrolled_window->viewport))
+ gtk_widget_unmap (scrolled_window->viewport);
+
+ if (GTK_WIDGET_MAPPED (scrolled_window->hscrollbar))
+ gtk_widget_unmap (scrolled_window->hscrollbar);
+
+ if (GTK_WIDGET_MAPPED (scrolled_window->vscrollbar))
+ gtk_widget_unmap (scrolled_window->vscrollbar);
+ }
+}
+
+static void
+gtk_scrolled_window_draw (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ GtkScrolledWindow *scrolled_window;
+ GdkRectangle child_area;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_SCROLLED_WINDOW (widget));
+ g_return_if_fail (area != NULL);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ scrolled_window = GTK_SCROLLED_WINDOW (widget);
+
+ if (gtk_widget_intersect (scrolled_window->viewport, area, &child_area))
+ gtk_widget_draw (scrolled_window->viewport, &child_area);
+
+ if (gtk_widget_intersect (scrolled_window->hscrollbar, area, &child_area))
+ gtk_widget_draw (scrolled_window->hscrollbar, &child_area);
+
+ if (gtk_widget_intersect (scrolled_window->vscrollbar, area, &child_area))
+ gtk_widget_draw (scrolled_window->vscrollbar, &child_area);
+ }
+}
+
+static void
+gtk_scrolled_window_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkScrolledWindow *scrolled_window;
+ gint extra_height;
+ gint extra_width;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_SCROLLED_WINDOW (widget));
+ g_return_if_fail (requisition != NULL);
+
+ scrolled_window = GTK_SCROLLED_WINDOW (widget);
+
+ requisition->width = 0;
+ requisition->height = 0;
+
+ if (GTK_WIDGET_VISIBLE (scrolled_window->viewport))
+ {
+ gtk_widget_size_request (scrolled_window->viewport, &scrolled_window->viewport->requisition);
+
+ requisition->width += scrolled_window->viewport->requisition.width;
+ requisition->height += scrolled_window->viewport->requisition.height;
+ }
+
+ extra_width = 0;
+ extra_height = 0;
+
+ if ((scrolled_window->hscrollbar_policy == GTK_POLICY_AUTOMATIC) ||
+ GTK_WIDGET_VISIBLE (scrolled_window->hscrollbar))
+ {
+ gtk_widget_size_request (scrolled_window->hscrollbar,
+ &scrolled_window->hscrollbar->requisition);
+
+ requisition->width = MAX (requisition->width, scrolled_window->hscrollbar->requisition.width);
+ extra_height = SCROLLBAR_SPACING + scrolled_window->hscrollbar->requisition.height;
+ }
+
+ if ((scrolled_window->vscrollbar_policy == GTK_POLICY_AUTOMATIC) ||
+ GTK_WIDGET_VISIBLE (scrolled_window->vscrollbar))
+ {
+ gtk_widget_size_request (scrolled_window->vscrollbar,
+ &scrolled_window->vscrollbar->requisition);
+
+ requisition->height = MAX (requisition->height, scrolled_window->vscrollbar->requisition.height);
+ extra_width = SCROLLBAR_SPACING + scrolled_window->vscrollbar->requisition.width;
+ }
+
+ requisition->width += GTK_CONTAINER (widget)->border_width * 2 + extra_width;
+ requisition->height += GTK_CONTAINER (widget)->border_width * 2 + extra_height;
+}
+
+static void
+gtk_scrolled_window_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkScrolledWindow *scrolled_window;
+ GtkAllocation viewport_allocation;
+ GtkAllocation child_allocation;
+ guint previous_hvis;
+ guint previous_vvis;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_SCROLLED_WINDOW (widget));
+ g_return_if_fail (allocation != NULL);
+
+ scrolled_window = GTK_SCROLLED_WINDOW (widget);
+ widget->allocation = *allocation;
+
+ gtk_scrolled_window_viewport_allocate (widget, &viewport_allocation);
+
+ gtk_container_disable_resize (GTK_CONTAINER (scrolled_window));
+
+ if (GTK_WIDGET_VISIBLE (scrolled_window->viewport))
+ {
+ do {
+ gtk_scrolled_window_viewport_allocate (widget, &viewport_allocation);
+
+ child_allocation.x = viewport_allocation.x + allocation->x;
+ child_allocation.y = viewport_allocation.y + allocation->y;
+ child_allocation.width = viewport_allocation.width;
+ child_allocation.height = viewport_allocation.height;
+
+ previous_hvis = GTK_WIDGET_VISIBLE (scrolled_window->hscrollbar);
+ previous_vvis = GTK_WIDGET_VISIBLE (scrolled_window->vscrollbar);
+
+ gtk_widget_size_allocate (scrolled_window->viewport, &child_allocation);
+ } while ((previous_hvis != GTK_WIDGET_VISIBLE (scrolled_window->hscrollbar)) ||
+ (previous_vvis != GTK_WIDGET_VISIBLE (scrolled_window->vscrollbar)));
+ }
+
+ if (GTK_WIDGET_VISIBLE (scrolled_window->hscrollbar))
+ {
+ child_allocation.x = viewport_allocation.x;
+ child_allocation.y = viewport_allocation.y + viewport_allocation.height + SCROLLBAR_SPACING;
+ child_allocation.width = viewport_allocation.width;
+ child_allocation.height = scrolled_window->hscrollbar->requisition.height;
+ child_allocation.x += allocation->x;
+ child_allocation.y += allocation->y;
+
+ gtk_widget_size_allocate (scrolled_window->hscrollbar, &child_allocation);
+ }
+
+ if (GTK_WIDGET_VISIBLE (scrolled_window->vscrollbar))
+ {
+ child_allocation.x = viewport_allocation.x + viewport_allocation.width + SCROLLBAR_SPACING;
+ child_allocation.y = viewport_allocation.y;
+ child_allocation.width = scrolled_window->vscrollbar->requisition.width;
+ child_allocation.height = viewport_allocation.height;
+ child_allocation.x += allocation->x;
+ child_allocation.y += allocation->y;
+
+ gtk_widget_size_allocate (scrolled_window->vscrollbar, &child_allocation);
+ }
+
+ gtk_container_enable_resize (GTK_CONTAINER (scrolled_window));
+}
+
+static void
+gtk_scrolled_window_add (GtkContainer *container,
+ GtkWidget *widget)
+{
+ GtkScrolledWindow *scrolled_window;
+
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_SCROLLED_WINDOW (container));
+ g_return_if_fail (widget != NULL);
+
+ scrolled_window = GTK_SCROLLED_WINDOW (container);
+ gtk_container_add (GTK_CONTAINER (scrolled_window->viewport), widget);
+}
+
+static void
+gtk_scrolled_window_remove (GtkContainer *container,
+ GtkWidget *widget)
+{
+ GtkScrolledWindow *scrolled_window;
+
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_SCROLLED_WINDOW (container));
+ g_return_if_fail (widget != NULL);
+
+ scrolled_window = GTK_SCROLLED_WINDOW (container);
+ gtk_container_remove (GTK_CONTAINER (scrolled_window->viewport), widget);
+}
+
+static void
+gtk_scrolled_window_foreach (GtkContainer *container,
+ GtkCallback callback,
+ gpointer callback_data)
+{
+ GtkScrolledWindow *scrolled_window;
+
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_SCROLLED_WINDOW (container));
+ g_return_if_fail (callback != NULL);
+
+ scrolled_window = GTK_SCROLLED_WINDOW (container);
+
+ (* callback) (scrolled_window->viewport, callback_data);
+}
+
+static void
+gtk_scrolled_window_viewport_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkScrolledWindow *scrolled_window;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (allocation != NULL);
+
+ scrolled_window = GTK_SCROLLED_WINDOW (widget);
+
+ allocation->x = GTK_CONTAINER (widget)->border_width;
+ allocation->y = GTK_CONTAINER (widget)->border_width;
+ allocation->width = widget->allocation.width - allocation->x * 2;
+ allocation->height = widget->allocation.height - allocation->y * 2;
+
+ if (GTK_WIDGET_VISIBLE (scrolled_window->vscrollbar))
+ allocation->width -= scrolled_window->vscrollbar->requisition.width + SCROLLBAR_SPACING;
+ if (GTK_WIDGET_VISIBLE (scrolled_window->hscrollbar))
+ allocation->height -= scrolled_window->hscrollbar->requisition.height + SCROLLBAR_SPACING;
+}
+
+static void
+gtk_scrolled_window_adjustment_changed (GtkAdjustment *adjustment,
+ gpointer data)
+{
+ GtkScrolledWindow *scrolled_win;
+ GtkWidget *scrollbar;
+ gint hide_scrollbar;
+ gint policy;
+
+ g_return_if_fail (adjustment != NULL);
+ g_return_if_fail (data != NULL);
+
+ scrolled_win = GTK_SCROLLED_WINDOW (data);
+
+ if (adjustment == gtk_range_get_adjustment (GTK_RANGE (scrolled_win->hscrollbar)))
+ {
+ scrollbar = scrolled_win->hscrollbar;
+ policy = scrolled_win->hscrollbar_policy;
+ }
+ else if (adjustment == gtk_range_get_adjustment (GTK_RANGE (scrolled_win->vscrollbar)))
+ {
+ scrollbar = scrolled_win->vscrollbar;
+ policy = scrolled_win->vscrollbar_policy;
+ }
+ else
+ {
+ g_warning ("could not determine which adjustment scrollbar received change signal for");
+ return;
+ }
+
+ if (policy == GTK_POLICY_AUTOMATIC)
+ {
+ hide_scrollbar = FALSE;
+
+ if ((adjustment->upper - adjustment->lower) <= adjustment->page_size)
+ hide_scrollbar = TRUE;
+
+ if (hide_scrollbar)
+ {
+ if (GTK_WIDGET_VISIBLE (scrollbar))
+ gtk_widget_hide (scrollbar);
+ }
+ else
+ {
+ if (!GTK_WIDGET_VISIBLE (scrollbar))
+ gtk_widget_show (scrollbar);
+ }
+ }
+}
diff --git a/gtk/gtkscrolledwindow.h b/gtk/gtkscrolledwindow.h
new file mode 100644
index 000000000..34a01ef6c
--- /dev/null
+++ b/gtk/gtkscrolledwindow.h
@@ -0,0 +1,74 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_SCROLLED_WINDOW_H__
+#define __GTK_SCROLLED_WINDOW_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkhscrollbar.h>
+#include <gtk/gtkvscrollbar.h>
+#include <gtk/gtkviewport.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_SCROLLED_WINDOW(obj) GTK_CHECK_CAST (obj, gtk_scrolled_window_get_type (), GtkScrolledWindow)
+#define GTK_SCROLLED_WINDOW_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_scrolled_window_get_type (), GtkScrolledWindowClass)
+#define GTK_IS_SCROLLED_WINDOW(obj) GTK_CHECK_TYPE (obj, gtk_scrolled_window_get_type ())
+
+
+typedef struct _GtkScrolledWindow GtkScrolledWindow;
+typedef struct _GtkScrolledWindowClass GtkScrolledWindowClass;
+
+struct _GtkScrolledWindow
+{
+ GtkContainer container;
+
+ GtkWidget *viewport;
+ GtkWidget *hscrollbar;
+ GtkWidget *vscrollbar;
+
+ guint8 hscrollbar_policy;
+ guint8 vscrollbar_policy;
+};
+
+struct _GtkScrolledWindowClass
+{
+ GtkContainerClass parent_class;
+};
+
+
+guint gtk_scrolled_window_get_type (void);
+GtkWidget* gtk_scrolled_window_new (GtkAdjustment *hadjustment,
+ GtkAdjustment *vadjustment);
+GtkAdjustment* gtk_scrolled_window_get_hadjustment (GtkScrolledWindow *scrolled_window);
+GtkAdjustment* gtk_scrolled_window_get_vadjustment (GtkScrolledWindow *scrolled_window);
+void gtk_scrolled_window_set_policy (GtkScrolledWindow *scrolled_window,
+ GtkPolicyType hscrollbar_policy,
+ GtkPolicyType vscrollbar_policy);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_SCROLLED_WINDOW_H__ */
diff --git a/gtk/gtkselection.c b/gtk/gtkselection.c
new file mode 100644
index 000000000..ca6f5742f
--- /dev/null
+++ b/gtk/gtkselection.c
@@ -0,0 +1,1388 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* This file implements most of the work of the ICCM selection protocol.
+ * The code was written after an intensive study of the equivalent part
+ * of John Ousterhout's Tk toolkit, and does many things in much the
+ * same way.
+ *
+ * The one thing in the ICCM that isn't fully supported here (or in Tk)
+ * is side effects targets. For these to be handled properly, MULTIPLE
+ * targets need to be done in the order specified. This cannot be
+ * guaranteed with the way we do things, since if we are doing INCR
+ * transfers, the order will depend on the timing of the requestor.
+ *
+ * By Owen Taylor <owt1@cornell.edu> 8/16/97
+ */
+
+/* Terminology note: when not otherwise specified, the term "incr" below
+ * refers to the _sending_ part of the INCR protocol. The receiving
+ * portion is referred to just as "retrieval". (Terminology borrowed
+ * from Tk, because there is no good opposite to "retrieval" in English.
+ * "send" can't be made into a noun gracefully and we're already using
+ * "emission" for something else ....)
+ */
+
+/* The MOTIF entry widget seems to ask for the TARGETS target, then
+ (regardless of the reply) ask for the TEXT target. It's slightly
+ possible though that it somehow thinks we are responding negatively
+ to the TARGETS request, though I don't really think so ... */
+
+#include <stdarg.h>
+#include <gdk/gdkx.h>
+/* we need this for gdk_window_lookup() */
+#include "gtkmain.h"
+#include "gtkselection.h"
+#include "gtksignal.h"
+
+/* #define DEBUG_SELECTION */
+
+/* Maximum size of a sent chunk, in bytes. Also the default size of
+ our buffers */
+#define GTK_SELECTION_MAX_SIZE 4000
+
+enum {
+ INCR,
+ MULTIPLE,
+ TARGETS,
+ TIMESTAMP,
+ LAST_ATOM
+};
+
+typedef struct _GtkSelectionInfo GtkSelectionInfo;
+typedef struct _GtkIncrConversion GtkIncrConversion;
+typedef struct _GtkIncrInfo GtkIncrInfo;
+typedef struct _GtkRetrievalInfo GtkRetrievalInfo;
+typedef struct _GtkSelectionHandler GtkSelectionHandler;
+
+struct _GtkSelectionInfo
+{
+ GdkAtom selection;
+ GtkWidget *widget; /* widget that owns selection */
+ guint32 time; /* time used to acquire selection */
+};
+
+struct _GtkIncrConversion
+{
+ GdkAtom target; /* Requested target */
+ GdkAtom property; /* Property to store in */
+ GtkSelectionData data; /* The data being supplied */
+ gint offset; /* Current offset in sent selection.
+ * -1 => All done
+ * -2 => Only the final (empty) portion
+ * left to send */
+};
+
+struct _GtkIncrInfo
+{
+ GtkWidget *widget; /* Selection owner */
+ GdkWindow *requestor; /* Requestor window - we create a GdkWindow
+ so we can receive events */
+ GdkAtom selection; /* Selection we're sending */
+
+ GtkIncrConversion *conversions; /* Information about requested conversions -
+ * With MULTIPLE requests (benighted 1980's
+ * hardware idea), there can be more than
+ * one */
+ gint num_conversions;
+ gint num_incrs; /* number of remaining INCR style transactions */
+ guint32 idle_time;
+};
+
+
+struct _GtkRetrievalInfo
+{
+ GtkWidget *widget;
+ GdkAtom selection; /* Selection being retrieved. */
+ GdkAtom target; /* Form of selection that we requested */
+ guint32 idle_time; /* Number of seconds since we last heard
+ from selection owner */
+ guchar *buffer; /* Buffer in which to accumulate results */
+ gint offset; /* Current offset in buffer, -1 indicates
+ not yet started */
+};
+
+struct _GtkSelectionHandler
+{
+ GdkAtom selection; /* selection thats handled */
+ GdkAtom target; /* target thats handled */
+ GtkSelectionFunction function; /* callback function */
+ GtkRemoveFunction remove_func; /* called when callback is removed */
+ gpointer data; /* callback data */
+};
+
+/* Local Functions */
+static void gtk_selection_init (void);
+static gint gtk_selection_incr_timeout (GtkIncrInfo *info);
+static gint gtk_selection_retrieval_timeout (GtkRetrievalInfo *info);
+static void gtk_selection_retrieval_report (GtkRetrievalInfo *info,
+ GdkAtom type, gint format,
+ guchar *buffer, gint length);
+static GtkSelectionHandler *gtk_selection_find_handler (GtkWidget *widget,
+ GdkAtom selection,
+ GdkAtom target);
+static void gtk_selection_default_handler (GtkWidget *widget,
+ GtkSelectionData *data);
+
+/* Local Data */
+static gint initialize = TRUE;
+static GList *current_retrievals = NULL;
+static GList *current_incrs = NULL;
+static GList *current_selections = NULL;
+
+static GdkAtom gtk_selection_atoms[LAST_ATOM];
+static const char *gtk_selection_handler_key = "selection_handlers";
+
+/*************************************************************
+ * gtk_selection_owner_set:
+ * Claim ownership of a selection.
+ * arguments:
+ * widget: new selection owner
+ * selection: which selection
+ * time: time (use GDK_CURRENT_TIME only if necessary)
+ *
+ * results:
+ *************************************************************/
+
+gint
+gtk_selection_owner_set (GtkWidget *widget,
+ GdkAtom selection,
+ guint32 time)
+{
+ GList *tmp_list;
+ GtkWidget *old_owner;
+ GtkSelectionInfo *selection_info;
+ GdkWindow *window;
+
+ if (widget == NULL)
+ window = NULL;
+ else
+ {
+ if (!GTK_WIDGET_REALIZED (widget))
+ gtk_widget_realize (widget);
+
+ window = widget->window;
+ }
+
+ tmp_list = current_selections;
+ while (tmp_list)
+ {
+ selection_info = (GtkSelectionInfo *)tmp_list->data;
+
+ if (selection_info->selection == selection)
+ break;
+
+ tmp_list = tmp_list->next;
+ }
+
+ if (tmp_list == NULL)
+ selection_info = NULL;
+ else
+ if (selection_info->widget == widget)
+ return TRUE;
+
+ if (gdk_selection_owner_set (window, selection, time, TRUE))
+ {
+ old_owner = NULL;
+
+ if (widget == NULL)
+ {
+ if (selection_info)
+ {
+ old_owner = selection_info->widget;
+ current_selections = g_list_remove_link (current_selections,
+ tmp_list);
+ g_list_free (tmp_list);
+ g_free (selection_info);
+ }
+ }
+ else
+ {
+ if (selection_info == NULL)
+ {
+ selection_info = g_new (GtkSelectionInfo, 1);
+ selection_info->selection = selection;
+ selection_info->widget = widget;
+ selection_info->time = time;
+ current_selections = g_list_append (current_selections,
+ selection_info);
+ }
+ else
+ {
+ old_owner = selection_info->widget;
+ selection_info->widget = widget;
+ selection_info->time = time;
+ }
+ }
+ /* If another widget in the application lost the selection,
+ * send it a GDK_SELECTION_CLEAR event, unless we're setting
+ * the owner to None, in which case an event will be sent */
+ if (old_owner && (widget != NULL))
+ {
+ GdkEventSelection event;
+
+ event.type = GDK_SELECTION_CLEAR;
+ event.window = old_owner->window;
+ event.selection = selection;
+ event.time = time;
+
+ gtk_widget_event (widget, (GdkEvent *) &event);
+ }
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+/*************************************************************
+ * gtk_selection_add_handler:
+ * Add a handler for a specified selection/target pair
+ *
+ * arguments:
+ * widget: The widget the handler applies to
+ * selection:
+ * target:
+ * format: Format in which this handler will return data
+ * function: Callback function (can be NULL)
+ * data: User data for callback
+ *
+ * results:
+ *************************************************************/
+
+void
+gtk_selection_add_handler (GtkWidget *widget,
+ GdkAtom selection,
+ GdkAtom target,
+ GtkSelectionFunction function,
+ GtkRemoveFunction remove_func,
+ gpointer data)
+{
+ GList *selection_handlers;
+ GList *tmp_list;
+ GtkSelectionHandler *handler;
+
+ g_return_if_fail (widget != NULL);
+ if (initialize)
+ gtk_selection_init ();
+
+ selection_handlers = gtk_object_get_data (GTK_OBJECT (widget),
+ gtk_selection_handler_key);
+
+ /* Reuse old handler structure, if present */
+ tmp_list = selection_handlers;
+ while (tmp_list)
+ {
+ handler = (GtkSelectionHandler *)tmp_list->data;
+ if ((handler->selection == selection) && (handler->target == target))
+ {
+ if (handler->remove_func)
+ (*handler->remove_func)(handler->data);
+ if (function)
+ {
+ handler->function = function;
+ handler->remove_func = remove_func;
+ handler->data = data;
+ }
+ else
+ {
+ selection_handlers = g_list_remove_link (selection_handlers,
+ tmp_list);
+ g_list_free (tmp_list);
+ g_free (handler);
+ }
+ return;
+ }
+ tmp_list = tmp_list->next;
+ }
+
+ if (tmp_list == NULL && function)
+ {
+ handler = g_new (GtkSelectionHandler, 1);
+ handler->selection = selection;
+ handler->target = target;
+ handler->function = function;
+ handler->remove_func = remove_func;
+ handler->data = data;
+ selection_handlers = g_list_append (selection_handlers, handler);
+ }
+
+ gtk_object_set_data (GTK_OBJECT (widget), gtk_selection_handler_key,
+ selection_handlers);
+}
+
+/*************************************************************
+ * gtk_selection_remove_all:
+ * Removes all handlers and unsets ownership of all
+ * selections for a widget. Called when widget is being
+ * destroyed
+ *
+ * arguments:
+ * widget: The widget
+ * results:
+ *************************************************************/
+
+void
+gtk_selection_remove_all (GtkWidget *widget)
+{
+ GList *tmp_list;
+ GList *next;
+ GtkSelectionInfo *selection_info;
+ GList *selection_handlers;
+ GtkSelectionHandler *handler;
+
+ /* Remove pending requests/incrs for this widget */
+
+ tmp_list = current_incrs;
+ while (tmp_list)
+ {
+ next = tmp_list->next;
+ if (((GtkIncrInfo *)tmp_list->data)->widget == widget)
+ {
+ current_incrs = g_list_remove_link (current_incrs, tmp_list);
+ /* structure will be freed in timeout */
+ g_list_free (tmp_list);
+ }
+ tmp_list = next;
+ }
+
+ tmp_list = current_retrievals;
+ while (tmp_list)
+ {
+ next = tmp_list->next;
+ if (((GtkRetrievalInfo *)tmp_list->data)->widget == widget)
+ {
+ current_retrievals = g_list_remove_link (current_retrievals,
+ tmp_list);
+ /* structure will be freed in timeout */
+ g_list_free (tmp_list);
+ }
+ tmp_list = next;
+ }
+
+ /* Disclaim ownership of any selections */
+
+ tmp_list = current_selections;
+ while (tmp_list)
+ {
+ next = tmp_list->next;
+ selection_info = (GtkSelectionInfo *)tmp_list->data;
+
+ if (selection_info->widget == widget)
+ {
+ gdk_selection_owner_set (NULL,
+ selection_info->selection,
+ GDK_CURRENT_TIME, FALSE);
+ current_selections = g_list_remove_link (current_selections,
+ tmp_list);
+ g_list_free (tmp_list);
+ g_free (selection_info);
+ }
+
+ tmp_list = next;
+ }
+
+ /* Now remove all handlers */
+
+ selection_handlers = gtk_object_get_data (GTK_OBJECT (widget),
+ gtk_selection_handler_key);
+
+ tmp_list = selection_handlers;
+ while (tmp_list)
+ {
+ next = tmp_list->next;
+ handler = (GtkSelectionHandler *)tmp_list->data;
+
+ if (handler->remove_func)
+ (*handler->remove_func)(handler->data);
+
+ g_free (handler);
+
+ tmp_list = next;
+ }
+
+ g_list_free (selection_handlers);
+}
+
+/*************************************************************
+ * gtk_selection_convert:
+ * Request the contents of a selection. When received,
+ * a "selection_received" signal will be generated.
+ *
+ * arguments:
+ * widget: The widget which acts as requestor
+ * selection: Which selection to get
+ * target: Form of information desired (e.g., STRING)
+ * time: Time of request (usually of triggering event)
+ * In emergency, you could use GDK_CURRENT_TIME
+ *
+ * results:
+ * TRUE if requested succeeded. FALSE if we could not process
+ * request. (e.g., there was already a request in process for
+ * this widget).
+ *************************************************************/
+
+gint
+gtk_selection_convert (GtkWidget *widget,
+ GdkAtom selection,
+ GdkAtom target,
+ guint32 time)
+{
+ GtkRetrievalInfo *info;
+ GList *tmp_list;
+ GdkWindow *owner_window;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+
+ if (initialize)
+ gtk_selection_init ();
+
+ if (!GTK_WIDGET_REALIZED (widget))
+ gtk_widget_realize (widget);
+
+ /* Check to see if there are already any retrievals in progress for
+ this widget. If we changed GDK to use the selection for the
+ window property in which to store the retrieved information, then
+ we could support multiple retrievals for different selections.
+ This might be useful for DND. */
+
+ tmp_list = current_retrievals;
+ while (tmp_list)
+ {
+ info = (GtkRetrievalInfo *)tmp_list->data;
+ if (info->widget == widget)
+ return FALSE;
+ tmp_list = tmp_list->next;
+ }
+
+ info = g_new (GtkRetrievalInfo, 1);
+
+ info->widget = widget;
+ info->selection = selection;
+ info->target = target;
+ info->buffer = NULL;
+ info->offset = -1;
+
+ /* Check if this process has current owner. If so, call handler
+ procedure directly to avoid deadlocks with INCR. */
+
+ owner_window = gdk_selection_owner_get (selection);
+
+ if (owner_window != NULL)
+ {
+ GtkWidget *owner_widget;
+ GtkSelectionHandler *handler;
+ GtkSelectionData selection_data;
+
+ selection_data.selection = selection;
+ selection_data.target = target;
+ selection_data.data = NULL;
+ selection_data.length = -1;
+
+ gdk_window_get_user_data (owner_window, (gpointer *)&owner_widget);
+
+ if (owner_widget != NULL)
+ {
+ handler = gtk_selection_find_handler (owner_widget, selection, target);
+ if (handler)
+ (* handler->function)(owner_widget,
+ &selection_data,
+ handler->data);
+ else /* try the default handler */
+ gtk_selection_default_handler (owner_widget,
+ &selection_data);
+
+ gtk_selection_retrieval_report (info,
+ selection_data.type,
+ selection_data.format,
+ selection_data.data,
+ selection_data.length);
+
+ g_free (selection_data.data);
+
+ g_free (info);
+ return TRUE;
+ }
+ }
+
+ /* Otherwise, we need to go through X */
+
+ current_retrievals = g_list_append (current_retrievals, info);
+ gdk_selection_convert (widget->window, selection, target, time);
+ gtk_timeout_add (1000, (GtkFunction) gtk_selection_retrieval_timeout, info);
+
+ return TRUE;
+}
+
+/*************************************************************
+ * gtk_selection_data_set:
+ * Store new data into a GtkSelectionData object. Should
+ * _only_ by called from a selection handler callback.
+ * Null terminates the stored data.
+ * arguments:
+ * type: the type of selection data
+ * format: format (number of bits in a unit)
+ * data: pointer to the data (will be copied)
+ * length: length of the data
+ * results:
+ *************************************************************/
+
+void
+gtk_selection_data_set (GtkSelectionData *selection_data,
+ GdkAtom type,
+ gint format,
+ guchar *data,
+ gint length)
+{
+ if (selection_data->data)
+ g_free (selection_data->data);
+
+ selection_data->type = type;
+ selection_data->format = format;
+
+ if (data)
+ {
+ selection_data->data = g_new (guchar, length+1);
+ memcpy (selection_data->data, data, length);
+ selection_data->data[length] = 0;
+ }
+ else
+ selection_data->data = NULL;
+
+ selection_data->length = length;
+}
+
+/*************************************************************
+ * gtk_selection_init:
+ * Initialize local variables
+ * arguments:
+ *
+ * results:
+ *************************************************************/
+
+static void
+gtk_selection_init (void)
+{
+ gtk_selection_atoms[INCR] = gdk_atom_intern ("INCR", FALSE);
+ gtk_selection_atoms[MULTIPLE] = gdk_atom_intern ("MULTIPLE", FALSE);
+ gtk_selection_atoms[TIMESTAMP] = gdk_atom_intern ("TIMESTAMP", FALSE);
+ gtk_selection_atoms[TARGETS] = gdk_atom_intern ("TARGETS", FALSE);
+}
+
+/*************************************************************
+ * gtk_selection_clear:
+ * Handler for "selection_clear_event"
+ * arguments:
+ * widget:
+ * event:
+ * results:
+ *************************************************************/
+
+gint
+gtk_selection_clear (GtkWidget *widget,
+ GdkEventSelection *event)
+{
+ /* FIXME: there can be a problem if we change the selection
+ via gtk_selection_owner_set after another client claims
+ the selection, but before we get the notification event.
+ Tk filters based on serial #'s, which aren't retained by
+ GTK. Filtering based on time's will be inherently
+ somewhat unreliable. */
+
+ GList *tmp_list;
+ GtkSelectionInfo *selection_info;
+
+ tmp_list = current_selections;
+ while (tmp_list)
+ {
+ selection_info = (GtkSelectionInfo *)tmp_list->data;
+
+ if ((selection_info->selection == event->selection) &&
+ (selection_info->widget == widget))
+ break;
+
+ tmp_list = tmp_list->next;
+ }
+
+ if (tmp_list == NULL || selection_info->time > event->time)
+ return TRUE;
+
+ current_selections = g_list_remove_link (current_selections, tmp_list);
+ g_list_free (tmp_list);
+ g_free (selection_info);
+
+ return TRUE;
+}
+
+
+/*************************************************************
+ * gtk_selection_request:
+ * Handler for "selection_request_event"
+ * arguments:
+ * widget:
+ * event:
+ * results:
+ *************************************************************/
+
+gint
+gtk_selection_request (GtkWidget *widget,
+ GdkEventSelection *event)
+{
+ GtkIncrInfo *info;
+ GtkSelectionHandler *handler;
+ GList *tmp_list;
+ guchar *mult_atoms;
+ int i;
+
+ /* Check if we own selection */
+
+ tmp_list = current_selections;
+ while (tmp_list)
+ {
+ GtkSelectionInfo *selection_info = (GtkSelectionInfo *)tmp_list->data;
+
+ if ((selection_info->selection == event->selection) &&
+ (selection_info->widget == widget))
+ break;
+
+ tmp_list = tmp_list->next;
+ }
+
+ if (tmp_list == NULL)
+ return FALSE;
+
+ info = g_new(GtkIncrInfo, 1);
+
+ info->widget = widget;
+ info->selection = event->selection;
+ info->num_incrs = 0;
+
+ /* Create GdkWindow structure for the requestor */
+
+ info->requestor = gdk_window_lookup (event->requestor);
+ if (!info->requestor)
+ info->requestor = gdk_window_foreign_new (event->requestor);
+
+ /* Determine conversions we need to perform */
+
+ if (event->target == gtk_selection_atoms[MULTIPLE])
+ {
+ GdkAtom type;
+ gint format;
+ gint length;
+
+ mult_atoms = NULL;
+ if (!gdk_property_get (info->requestor, event->property, GDK_SELECTION_TYPE_ATOM,
+ 0, GTK_SELECTION_MAX_SIZE, FALSE,
+ &type, &format, &length, &mult_atoms) ||
+ type != GDK_SELECTION_TYPE_ATOM || format != 8*sizeof(GdkAtom))
+ {
+ gdk_selection_send_notify (event->requestor, event->selection,
+ event->target, GDK_NONE, event->time);
+ g_free (mult_atoms);
+ g_free (info);
+ return TRUE;
+ }
+
+ info->num_conversions = length / (2*sizeof (GdkAtom));
+ info->conversions = g_new (GtkIncrConversion, info->num_conversions);
+
+ for (i=0; i<info->num_conversions; i++)
+ {
+ info->conversions[i].target = ((GdkAtom *)mult_atoms)[2*i];
+ info->conversions[i].property = ((GdkAtom *)mult_atoms)[2*i+1];
+ }
+ }
+ else /* only a single conversion */
+ {
+ info->conversions = g_new (GtkIncrConversion, 1);
+ info->num_conversions = 1;
+ info->conversions[0].target = event->target;
+ info->conversions[0].property = event->property;
+ mult_atoms = (guchar *)info->conversions;
+ }
+
+ /* Loop through conversions and determine which of these are big
+ enough to require doing them via INCR */
+ for (i=0; i<info->num_conversions; i++)
+ {
+ GtkSelectionData data;
+ gint items;
+
+ data.selection = event->selection;
+ data.target = info->conversions[i].target;
+ data.data = NULL;
+ data.length = -1;
+
+#ifdef DEBUG_SELECTION
+ g_print("Selection %ld, target %ld (%s) requested by 0x%x (property = %ld)\n",
+ event->selection, info->conversions[i].target,
+ gdk_atom_name(info->conversions[i].target),
+ event->requestor, event->property);
+#endif
+
+ handler = gtk_selection_find_handler (widget, event->selection,
+ info->conversions[i].target);
+ if (handler)
+ (* handler->function)(widget, &data, handler->data);
+ else
+ gtk_selection_default_handler (widget, &data);
+
+ if (data.length < 0)
+ {
+ ((GdkAtom *)mult_atoms)[2*i+1] = GDK_NONE;
+ info->conversions[i].property = GDK_NONE;
+ continue;
+ }
+
+ g_return_val_if_fail ((data.format >= 8)
+ && (data.format % 8 == 0), FALSE)
+
+ items = (data.length + data.format/8 - 1) / (data.format/8);
+
+ if (data.length > GTK_SELECTION_MAX_SIZE)
+ {
+ /* Sending via INCR */
+
+ info->conversions[i].offset = 0;
+ info->conversions[i].data = data;
+ info->num_incrs++;
+
+ gdk_property_change (info->requestor,
+ info->conversions[i].property,
+ gtk_selection_atoms[INCR],
+ 8*sizeof (GdkAtom),
+ GDK_PROP_MODE_REPLACE,
+ (guchar *)&items, 1);
+ }
+ else
+ {
+ info->conversions[i].offset = -1;
+
+ gdk_property_change (info->requestor,
+ info->conversions[i].property,
+ data.type,
+ data.format,
+ GDK_PROP_MODE_REPLACE,
+ data.data, items);
+
+ g_free (data.data);
+ }
+ }
+
+ /* If we have some INCR's, we need to send the rest of the data in
+ a callback */
+
+ if (info->num_incrs > 0)
+ {
+ /* FIXME: this could be dangerous if window doesn't still
+ exist */
+
+#ifdef DEBUG_SELECTION
+ g_print("Starting INCR...\n");
+#endif
+
+ gdk_window_set_events (info->requestor,
+ gdk_window_get_events (info->requestor) |
+ GDK_PROPERTY_CHANGE_MASK);
+ current_incrs = g_list_append (current_incrs, info);
+ gtk_timeout_add (1000, (GtkFunction)gtk_selection_incr_timeout, info);
+ }
+
+ /* If it was a MULTIPLE request, set the property to indicate which
+ conversions succeeded */
+ if (event->target == gtk_selection_atoms[MULTIPLE])
+ {
+ gdk_property_change (info->requestor, event->property,
+ GDK_SELECTION_TYPE_ATOM, 8*sizeof(GdkAtom),
+ GDK_PROP_MODE_REPLACE,
+ mult_atoms, info->num_conversions);
+ g_free (mult_atoms);
+ }
+
+ gdk_selection_send_notify (event->requestor, event->selection, event->target,
+ event->property, event->time);
+
+ if (info->num_incrs == 0)
+ {
+ g_free (info->conversions);
+ g_free (info);
+ }
+
+ return TRUE;
+}
+
+/*************************************************************
+ * gtk_selection_incr_event:
+ * Called whenever an PropertyNotify event occurs for an
+ * GdkWindow with user_data == NULL. These will be notifications
+ * that a window we are sending the selection to via the
+ * INCR protocol has deleted a property and is ready for
+ * more data.
+ *
+ * arguments:
+ * window: the requestor window
+ * event: the property event structure
+ *
+ * results:
+ *************************************************************/
+
+gint
+gtk_selection_incr_event (GdkWindow *window,
+ GdkEventProperty *event)
+{
+ GList *tmp_list;
+ GtkIncrInfo *info;
+ gint num_bytes;
+ guchar *buffer;
+
+ int i;
+
+ if (event->state != GDK_PROPERTY_DELETE)
+ return FALSE;
+
+#ifdef DEBUG_SELECTION
+ g_print("PropertyDelete, property %ld\n", event->atom);
+#endif
+
+ /* Now find the appropriate ongoing INCR */
+ tmp_list = current_incrs;
+ while (tmp_list)
+ {
+ info = (GtkIncrInfo *)tmp_list->data;
+ if (info->requestor == event->window)
+ break;
+
+ tmp_list = tmp_list->next;
+ }
+
+ if (tmp_list == NULL)
+ return FALSE;
+
+ /* Find out which target this is for */
+ for (i=0; i<info->num_conversions; i++)
+ {
+ if (info->conversions[i].property == event->atom &&
+ info->conversions[i].offset != -1)
+ {
+ info->idle_time = 0;
+
+ if (info->conversions[i].offset == -2) /* only the last 0-length
+ piece*/
+ {
+ num_bytes = 0;
+ buffer = NULL;
+ }
+ else
+ {
+ num_bytes = info->conversions[i].data.length -
+ info->conversions[i].offset;
+ buffer = info->conversions[i].data.data +
+ info->conversions[i].offset;
+
+ if (num_bytes > GTK_SELECTION_MAX_SIZE)
+ {
+ num_bytes = GTK_SELECTION_MAX_SIZE;
+ info->conversions[i].offset += GTK_SELECTION_MAX_SIZE;
+ }
+ else
+ info->conversions[i].offset = -2;
+ }
+#ifdef DEBUG_SELECTION
+ g_print("INCR: put %d bytes (offset = %d) into window 0x%lx , property %ld\n",
+ num_bytes, info->conversions[i].offset,
+ GDK_WINDOW_XWINDOW(info->requestor), event->atom);
+#endif
+ gdk_property_change (info->requestor, event->atom,
+ info->conversions[i].data.type,
+ info->conversions[i].data.format,
+ GDK_PROP_MODE_REPLACE,
+ buffer,
+ (num_bytes + info->conversions[i].data.format/8 - 1) /
+ (info->conversions[i].data.format/8));
+
+ if (info->conversions[i].offset == -2)
+ {
+ g_free (info->conversions[i].data.data);
+ info->conversions[i].data.data = NULL;
+ }
+
+ if (num_bytes == 0)
+ {
+ info->num_incrs--;
+ info->conversions[i].offset = -1;
+ }
+ }
+ break;
+ }
+
+ /* Check if we're finished with all the targets */
+
+ if (info->num_incrs == 0)
+ {
+ current_incrs = g_list_remove_link (current_incrs, tmp_list);
+ g_list_free (tmp_list);
+ /* Let the timeout free it */
+ }
+
+ return TRUE;
+}
+
+/*************************************************************
+ * gtk_selection_incr_timeout:
+ * Timeout callback for the sending portion of the INCR
+ * protocol
+ * arguments:
+ * info: Information about this incr
+ * results:
+ *************************************************************/
+
+static gint
+gtk_selection_incr_timeout (GtkIncrInfo *info)
+{
+ GList *tmp_list;
+
+ /* Determine if retrieval has finished by checking if it still in
+ list of pending retrievals */
+
+ tmp_list = current_incrs;
+ while (tmp_list)
+ {
+ if (info == (GtkIncrInfo *)tmp_list->data)
+ break;
+ tmp_list = tmp_list->next;
+ }
+
+ /* If retrieval is finished */
+ if (!tmp_list || info->idle_time >= 5)
+ {
+ if (tmp_list && info->idle_time >= 5)
+ {
+ current_incrs = g_list_remove_link (current_incrs, tmp_list);
+ g_list_free (tmp_list);
+ }
+
+ g_free (info->conversions);
+ /* FIXME: we should check if requestor window is still in use,
+ and if not, remove it? */
+
+ g_free (info);
+
+ return FALSE; /* remove timeout */
+ }
+ else
+ {
+ info->idle_time++;
+
+ return TRUE; /* timeout will happen again */
+ }
+}
+
+/*************************************************************
+ * gtk_selection_notify:
+ * Handler for "selection_notify_event" signals on windows
+ * where a retrieval is currently in process. The selection
+ * owner has responded to our conversion request.
+ * arguments:
+ * widget: Widget getting signal
+ * event: Selection event structure
+ * info: Information about this retrieval
+ * results:
+ * was event handled?
+ *************************************************************/
+
+gint
+gtk_selection_notify (GtkWidget *widget,
+ GdkEventSelection *event)
+{
+ GList *tmp_list;
+ GtkRetrievalInfo *info;
+ guchar *buffer;
+ gint length;
+ GdkAtom type;
+ gint format;
+
+#ifdef DEBUG_SELECTION
+ g_print("Initial receipt of selection %ld, target %ld (property = %ld)\n",
+ event->selection, event->target, event->property);
+#endif
+
+ tmp_list = current_retrievals;
+ while (tmp_list)
+ {
+ info = (GtkRetrievalInfo *)tmp_list->data;
+ if (info->widget == widget && info->selection == event->selection)
+ break;
+ tmp_list = tmp_list->next;
+ }
+
+ if (!tmp_list) /* no retrieval in progress */
+ return FALSE;
+
+ if (event->property == GDK_NONE)
+ {
+ current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
+ g_list_free (tmp_list);
+ /* structure will be freed in timeout */
+ gtk_selection_retrieval_report (info,
+ GDK_NONE, 0, NULL, -1);
+
+ return TRUE;
+ }
+
+ length = gdk_selection_property_get (widget->window, &buffer,
+ &type, &format);
+
+ if (type == gtk_selection_atoms[INCR])
+ {
+ /* The remainder of the selection will come through PropertyNotify
+ events */
+
+ info->idle_time = 0;
+ info->offset = 0; /* Mark as OK to proceed */
+ gdk_window_set_events (widget->window,
+ gdk_window_get_events (widget->window)
+ | GDK_PROPERTY_CHANGE_MASK);
+ }
+ else
+ {
+ /* We don't delete the info structure - that will happen in timeout */
+ current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
+ g_list_free (tmp_list);
+
+ info->offset = length;
+ gtk_selection_retrieval_report (info,
+ type, format,
+ buffer, length);
+ }
+
+ gdk_property_delete (widget->window, event->property);
+
+ g_free (buffer);
+
+ return TRUE;
+}
+
+/*************************************************************
+ * gtk_selection_property_notify:
+ * Handler for "property_notify_event" signals on windows
+ * where a retrieval is currently in process. The selection
+ * owner has added more data.
+ * arguments:
+ * widget: Widget getting signal
+ * event: Property event structure
+ * info: Information about this retrieval
+ * results:
+ * was event handled?
+ *************************************************************/
+
+gint
+gtk_selection_property_notify (GtkWidget *widget,
+ GdkEventProperty *event)
+{
+ GList *tmp_list;
+ GtkRetrievalInfo *info;
+ guchar *new_buffer;
+ int length;
+ GdkAtom type;
+ gint format;
+
+ if ((event->state != GDK_PROPERTY_NEW_VALUE) || /* property was deleted */
+ (event->atom != gdk_selection_property)) /* not the right property */
+ return FALSE;
+
+#ifdef DEBUG_SELECTION
+ g_print("PropertyNewValue, property %ld\n",
+ event->atom);
+#endif
+
+ tmp_list = current_retrievals;
+ while (tmp_list)
+ {
+ info = (GtkRetrievalInfo *)tmp_list->data;
+ if (info->widget == widget)
+ break;
+ tmp_list = tmp_list->next;
+ }
+
+ if (!tmp_list) /* No retrieval in progress */
+ return FALSE;
+
+ if (info->offset < 0) /* We haven't got the SelectionNotify
+ for this retrieval yet */
+ return FALSE;
+
+ info->idle_time = 0;
+
+ length = gdk_selection_property_get (widget->window, &new_buffer,
+ &type, &format);
+ gdk_property_delete (widget->window, event->atom);
+
+ /* We could do a lot better efficiency-wise by paying attention to
+ what length was sent in the initial INCR transaction, instead of
+ doing memory allocation at every step. But its only guaranteed to
+ be a _lower bound_ (pretty useless!) */
+
+ if (length == 0 || type == GDK_NONE) /* final zero length portion */
+ {
+ /* Info structure will be freed in timeout */
+ current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
+ g_list_free (tmp_list);
+ gtk_selection_retrieval_report (info,
+ type, format,
+ (type == GDK_NONE) ? NULL : info->buffer,
+ (type == GDK_NONE) ? -1 : info->offset);
+ }
+ else /* append on newly arrived data */
+ {
+ if (!info->buffer)
+ {
+#ifdef DEBUG_SELECTION
+ g_print("Start - Adding %d bytes at offset 0\n",
+ length);
+#endif
+ info->buffer = new_buffer;
+ info->offset = length;
+ }
+ else
+ {
+
+#ifdef DEBUG_SELECTION
+ g_print("Appending %d bytes at offset %d\n",
+ length,info->offset);
+#endif
+ /* We copy length+1 bytes to preserve guaranteed null termination */
+ info->buffer = g_realloc (info->buffer, info->offset+length+1);
+ memcpy (info->buffer + info->offset, new_buffer, length+1);
+ info->offset += length;
+ g_free (new_buffer);
+ }
+ }
+
+ return TRUE;
+}
+
+/*************************************************************
+ * gtk_selection_retrieval_timeout:
+ * Timeout callback while receiving a selection.
+ * arguments:
+ * info: Information about this retrieval
+ * results:
+ *************************************************************/
+
+static gint
+gtk_selection_retrieval_timeout (GtkRetrievalInfo *info)
+{
+ GList *tmp_list;
+
+ /* Determine if retrieval has finished by checking if it still in
+ list of pending retrievals */
+
+ tmp_list = current_retrievals;
+ while (tmp_list)
+ {
+ if (info == (GtkRetrievalInfo *)tmp_list->data)
+ break;
+ tmp_list = tmp_list->next;
+ }
+
+ /* If retrieval is finished */
+ if (!tmp_list || info->idle_time >= 5)
+ {
+ if (tmp_list && info->idle_time >= 5)
+ {
+ current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
+ g_list_free (tmp_list);
+ gtk_selection_retrieval_report (info, GDK_NONE, 0, NULL, -1);
+ }
+
+ g_free (info->buffer);
+ g_free (info);
+
+ return FALSE; /* remove timeout */
+ }
+ else
+ {
+ info->idle_time++;
+
+ return TRUE; /* timeout will happen again */
+ }
+
+}
+
+/*************************************************************
+ * gtk_selection_retrieval_report:
+ * Emits a "selection_received" signal.
+ * arguments:
+ * info: information about the retrieval that completed
+ * buffer: buffer containing data (NULL => errror)
+ * results:
+ *************************************************************/
+
+static void
+gtk_selection_retrieval_report (GtkRetrievalInfo *info,
+ GdkAtom type, gint format,
+ guchar *buffer, gint length)
+{
+ GtkSelectionData data;
+
+ data.selection = info->selection;
+ data.target = info->target;
+ data.type = type;
+ data.format = format;
+
+ data.length = length;
+ data.data = buffer;
+
+ gtk_signal_emit_by_name (GTK_OBJECT(info->widget),
+ "selection_received", &data);
+}
+
+/*************************************************************
+ * gtk_selection_find_handler:
+ * Find handler for specified widget/selection/target
+ * arguments:
+ * widget:
+ * selection:
+ * target:
+ * results:
+ *************************************************************/
+
+static GtkSelectionHandler *
+gtk_selection_find_handler (GtkWidget *widget,
+ GdkAtom selection,
+ GdkAtom target)
+{
+ GList *tmp_list;
+ GtkSelectionHandler *handler;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+
+ tmp_list = gtk_object_get_data (GTK_OBJECT (widget),
+ gtk_selection_handler_key);
+
+ while (tmp_list)
+ {
+ handler = (GtkSelectionHandler *)tmp_list->data;
+ if ((handler->selection == selection) && (handler->target == target))
+ return handler;
+ tmp_list = tmp_list->next;
+ }
+
+ return NULL;
+}
+
+
+/*************************************************************
+ * gtk_selection_default_handler:
+ * Handles some default targets that exist for any widget
+ * If it can't fit results into buffer, returns -1. This
+ * won't happen in any conceivable case, since it would
+ * require 1000 selection targets!
+ *
+ * arguments:
+ * widget: selection owner
+ * selection: selection requested
+ * target: target requested
+ * buffer: buffer to write results into
+ * length: size of buffer
+ * type: type atom
+ * format: length of type's units in bits
+ *
+ * results:
+ * Number of bytes written to buffer, -1 if error
+ *************************************************************/
+
+static void
+gtk_selection_default_handler (GtkWidget *widget,
+ GtkSelectionData *data)
+{
+ if (data->target == gtk_selection_atoms[TIMESTAMP])
+ {
+ /* Time which was used to obtain selection */
+ GList *tmp_list;
+ GtkSelectionInfo *selection_info;
+
+ tmp_list = current_selections;
+ while (tmp_list)
+ {
+ selection_info = (GtkSelectionInfo *)tmp_list->data;
+ if ((selection_info->widget == widget) &&
+ (selection_info->selection == data->selection))
+ {
+ gtk_selection_data_set (data,
+ GDK_SELECTION_TYPE_INTEGER,
+ sizeof (guint32)*8,
+ (guchar *)&selection_info->time,
+ sizeof (guint32));
+ return;
+ }
+
+ tmp_list = tmp_list->next;
+ }
+
+ data->length = -1;
+ }
+ else if (data->target == gtk_selection_atoms[TARGETS])
+ {
+ /* List of all targets supported for this widget/selection pair */
+ GdkAtom *p;
+ gint count;
+ GList *tmp_list;
+ GtkSelectionHandler *handler;
+
+ count = 3;
+ tmp_list = gtk_object_get_data (GTK_OBJECT(widget),
+ gtk_selection_handler_key);
+ while (tmp_list)
+ {
+ handler = (GtkSelectionHandler *)tmp_list->data;
+
+ if (handler->selection == data->selection)
+ count++;
+
+ tmp_list = tmp_list->next;
+ }
+
+ data->type = GDK_SELECTION_TYPE_ATOM;
+ data->format = 8*sizeof (GdkAtom);
+ data->length = count*sizeof (GdkAtom);
+
+ p = g_new (GdkAtom, count);
+ data->data = (guchar *)p;
+
+ *p++ = gtk_selection_atoms[TIMESTAMP];
+ *p++ = gtk_selection_atoms[TARGETS];
+ *p++ = gtk_selection_atoms[MULTIPLE];
+
+ tmp_list = gtk_object_get_data (GTK_OBJECT(widget),
+ gtk_selection_handler_key);
+ while (tmp_list)
+ {
+ handler = (GtkSelectionHandler *)tmp_list->data;
+
+ if (handler->selection == data->selection)
+ *p++ = handler->target;
+
+ tmp_list = tmp_list->next;
+ }
+ }
+ else
+ {
+ data->length = -1;
+ }
+}
diff --git a/gtk/gtkselection.h b/gtk/gtkselection.h
new file mode 100644
index 000000000..18f3dc4b5
--- /dev/null
+++ b/gtk/gtkselection.h
@@ -0,0 +1,91 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_SELECTION_H__
+#define __GTK_SELECTION_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkenums.h>
+#include <gtk/gtkwidget.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _GtkSelectionData GtkSelectioData;
+
+/* a callback function that provides the selection. Arguments are:
+ widget: selection owner
+ offset: offset into selection
+ buffer: buffer into which to store selection
+ length: length of buffer
+ bytes_after: (sizeof(selection) - offset - length ) (return)
+ data: callback data */
+
+typedef void (*GtkSelectionFunction) (GtkWidget *widget,
+ GtkSelectionData *selection_data,
+ gpointer data);
+
+/* Public interface */
+
+gint gtk_selection_owner_set (GtkWidget *widget,
+ GdkAtom selection,
+ guint32 time);
+void gtk_selection_add_handler (GtkWidget *widget,
+ GdkAtom selection,
+ GdkAtom target,
+ GtkSelectionFunction function,
+ GtkRemoveFunction remove_func,
+ gpointer data);
+gint gtk_selection_convert (GtkWidget *widget,
+ GdkAtom selection,
+ GdkAtom target,
+ guint32 time);
+
+
+void gtk_selection_data_set (GtkSelectionData *selection_data,
+ GdkAtom type,
+ gint format,
+ guchar *data,
+ gint length);
+
+/* Called when a widget is destroyed */
+
+void gtk_selection_remove_all (GtkWidget *widget);
+
+/* Event handlers */
+
+gint gtk_selection_clear (GtkWidget *widget,
+ GdkEventSelection *event);
+gint gtk_selection_request (GtkWidget *widget,
+ GdkEventSelection *event);
+gint gtk_selection_incr_event (GdkWindow *window,
+ GdkEventProperty *event);
+gint gtk_selection_notify (GtkWidget *widget,
+ GdkEventSelection *event);
+gint gtk_selection_property_notify (GtkWidget *widget,
+ GdkEventProperty *event);
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_SELECTION_H__ */
diff --git a/gtk/gtkseparator.c b/gtk/gtkseparator.c
new file mode 100644
index 000000000..6ad41ad5b
--- /dev/null
+++ b/gtk/gtkseparator.c
@@ -0,0 +1,57 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtkseparator.h"
+
+
+static void gtk_separator_class_init (GtkSeparatorClass *klass);
+static void gtk_separator_init (GtkSeparator *separator);
+
+
+guint
+gtk_separator_get_type ()
+{
+ static guint separator_type = 0;
+
+ if (!separator_type)
+ {
+ GtkTypeInfo separator_info =
+ {
+ "GtkSeparator",
+ sizeof (GtkSeparator),
+ sizeof (GtkSeparatorClass),
+ (GtkClassInitFunc) gtk_separator_class_init,
+ (GtkObjectInitFunc) gtk_separator_init,
+ (GtkArgFunc) NULL,
+ };
+
+ separator_type = gtk_type_unique (gtk_widget_get_type (), &separator_info);
+ }
+
+ return separator_type;
+}
+
+static void
+gtk_separator_class_init (GtkSeparatorClass *class)
+{
+}
+
+static void
+gtk_separator_init (GtkSeparator *separator)
+{
+ GTK_WIDGET_SET_FLAGS (separator, GTK_NO_WINDOW | GTK_BASIC);
+}
diff --git a/gtk/gtkseparator.h b/gtk/gtkseparator.h
new file mode 100644
index 000000000..bfccd337a
--- /dev/null
+++ b/gtk/gtkseparator.h
@@ -0,0 +1,58 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_SEPARATOR_H__
+#define __GTK_SEPARATOR_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkwidget.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_SEPARATOR(obj) GTK_CHECK_CAST (obj, gtk_separator_get_type (), GtkSeparator)
+#define GTK_SEPARATOR_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_separator_get_type (), GtkSeparatorClass)
+#define GTK_IS_SEPARATOR(obj) GTK_CHECK_TYPE (obj, gtk_separator_get_type ())
+
+
+typedef struct _GtkSeparator GtkSeparator;
+typedef struct _GtkSeparatorClass GtkSeparatorClass;
+
+struct _GtkSeparator
+{
+ GtkWidget widget;
+};
+
+struct _GtkSeparatorClass
+{
+ GtkWidgetClass parent_class;
+};
+
+
+guint gtk_separator_get_type (void);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_SEPARATOR_H__ */
diff --git a/gtk/gtksignal.c b/gtk/gtksignal.c
new file mode 100644
index 000000000..65efdb991
--- /dev/null
+++ b/gtk/gtksignal.c
@@ -0,0 +1,1322 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdarg.h>
+#include "gtksignal.h"
+
+
+#define MAX_PARAMS 20
+#define DONE 1
+#define RESTART 2
+
+#define GTK_RUN_TYPE(x) ((x) & GTK_RUN_MASK)
+
+
+typedef struct _GtkSignal GtkSignal;
+typedef struct _GtkSignalInfo GtkSignalInfo;
+typedef struct _GtkHandler GtkHandler;
+typedef struct _GtkHandlerInfo GtkHandlerInfo;
+typedef struct _GtkEmission GtkEmission;
+
+typedef void (*GtkSignalMarshaller0) (GtkObject *object,
+ gpointer data);
+
+struct _GtkSignalInfo
+{
+ gchar *name;
+ gint object_type;
+ gint signal_type;
+};
+
+struct _GtkSignal
+{
+ GtkSignalInfo info;
+ gint function_offset;
+ GtkSignalRunType run_type;
+ GtkSignalMarshaller marshaller;
+ GtkType return_val;
+ GtkType *params;
+ gint nparams;
+};
+
+struct _GtkHandler
+{
+ guint16 id;
+ guint signal_type : 13;
+ guint object_signal : 1;
+ guint blocked : 1;
+ guint after : 1;
+ guint no_marshal : 1;
+ GtkSignalFunc func;
+ gpointer func_data;
+ GtkSignalDestroy destroy_func;
+ GtkHandler *next;
+};
+
+struct _GtkHandlerInfo
+{
+ GtkObject *object;
+ GtkSignalMarshaller marshaller;
+ GtkArg *params;
+ GtkType *param_types;
+ GtkType return_val;
+ GtkSignalRunType run_type;
+ gint nparams;
+ gint signal_type;
+};
+
+struct _GtkEmission
+{
+ GtkObject *object;
+ gint signal_type;
+};
+
+
+static void gtk_signal_init (void);
+static guint gtk_signal_hash (gint *key);
+static gint gtk_signal_compare (gint *a,
+ gint *b);
+static guint gtk_signal_info_hash (GtkSignalInfo *a);
+static gint gtk_signal_info_compare (GtkSignalInfo *a,
+ GtkSignalInfo *b);
+static GtkHandler* gtk_signal_handler_new (void);
+static void gtk_signal_handler_destroy (GtkHandler *handler);
+static void gtk_signal_handler_insert (GtkObject *object,
+ GtkHandler *handler);
+static gint gtk_signal_real_emit (GtkObject *object,
+ gint signal_type,
+ va_list args);
+static GtkHandler* gtk_signal_get_handlers (GtkObject *object,
+ gint signal_type);
+static gint gtk_signal_connect_by_type (GtkObject *object,
+ gint signal_type,
+ gint object_signal,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkSignalDestroy destroy_func,
+ gint after,
+ gint no_marshal);
+static GtkEmission* gtk_emission_new (void);
+static void gtk_emission_destroy (GtkEmission *emission);
+static void gtk_emission_add (GList **emissions,
+ GtkObject *object,
+ gint signal_type);
+static void gtk_emission_remove (GList **emissions,
+ GtkObject *object,
+ gint signal_type);
+static gint gtk_emission_check (GList *emissions,
+ GtkObject *object,
+ gint signal_type);
+static gint gtk_handlers_run (GtkHandler *handlers,
+ GtkHandlerInfo *info,
+ gint after);
+static void gtk_params_get (GtkArg *params,
+ gint nparams,
+ GtkType *param_types,
+ GtkType return_val,
+ va_list args);
+
+
+static gint initialize = TRUE;
+static GHashTable *signal_hash_table = NULL;
+static GHashTable *signal_info_hash_table = NULL;
+static gint next_signal = 1;
+static gint next_handler_id = 1;
+
+static const char *handler_key = "signal_handlers";
+
+static GMemChunk *handler_mem_chunk = NULL;
+static GMemChunk *emission_mem_chunk = NULL;
+
+static GList *current_emissions = NULL;
+static GList *stop_emissions = NULL;
+static GList *restart_emissions = NULL;
+
+static GtkSignalMarshal marshal = NULL;
+static GtkSignalDestroy destroy = NULL;
+
+
+gint
+gtk_signal_new (const gchar *name,
+ GtkSignalRunType run_type,
+ gint object_type,
+ gint function_offset,
+ GtkSignalMarshaller marshaller,
+ GtkType return_val,
+ gint nparams,
+ ...)
+{
+ GtkType *params;
+ GtkSignal *signal;
+ GtkSignalInfo info;
+ gint *type;
+ gint i;
+ va_list args;
+
+ g_return_val_if_fail (name != NULL, 0);
+ g_return_val_if_fail (marshaller != NULL, 0);
+ g_return_val_if_fail (nparams < 10, 0);
+
+ if (initialize)
+ gtk_signal_init ();
+
+ info.name = (char*)name;
+ info.object_type = object_type;
+
+ type = g_hash_table_lookup (signal_info_hash_table, &info);
+ if (type)
+ {
+ g_warning ("signal \"%s\" already exists in the \"%s\" class ancestry\n",
+ name, gtk_type_name (object_type));
+ return 0;
+ }
+
+ signal = g_new (GtkSignal, 1);
+ signal->info.name = g_strdup(name);
+ signal->info.object_type = object_type;
+ signal->info.signal_type = next_signal++;
+ signal->function_offset = function_offset;
+ signal->run_type = run_type;
+ signal->marshaller = marshaller;
+ signal->return_val = return_val;
+ signal->params = NULL;
+ signal->nparams = nparams;
+
+ g_hash_table_insert (signal_hash_table, &signal->info.signal_type, signal);
+ g_hash_table_insert (signal_info_hash_table, &signal->info, &signal->info.signal_type);
+
+ if (nparams > 0)
+ {
+ signal->params = g_new (GtkType, nparams);
+ params = signal->params;
+
+ va_start (args, nparams);
+
+ for (i = 0; i < nparams; i++)
+ params[i] = va_arg (args, GtkType);
+
+ va_end (args);
+ }
+
+ return signal->info.signal_type;
+}
+
+gint
+gtk_signal_lookup (const gchar *name,
+ gint object_type)
+{
+ GtkSignalInfo info;
+ gint *type;
+
+ g_return_val_if_fail (name != NULL, 0);
+
+ if (initialize)
+ gtk_signal_init ();
+
+ info.name = (char*)name;
+
+ while (object_type)
+ {
+ info.object_type = object_type;
+
+ type = g_hash_table_lookup (signal_info_hash_table, &info);
+ if (type)
+ return *type;
+
+ object_type = gtk_type_parent (object_type);
+ }
+
+ return 0;
+}
+
+gchar*
+gtk_signal_name (gint signal_num)
+{
+ GtkSignal *signal;
+
+ signal = g_hash_table_lookup (signal_hash_table, &signal_num);
+ if (signal)
+ return signal->info.name;
+
+ return NULL;
+}
+
+gint
+gtk_signal_emit (GtkObject *object,
+ gint signal_type,
+ ...)
+{
+ gint return_val;
+
+ va_list args;
+
+ g_return_val_if_fail (object != NULL, FALSE);
+
+ if (initialize)
+ gtk_signal_init ();
+
+ va_start (args, signal_type);
+
+ return_val = gtk_signal_real_emit (object, signal_type, args);
+
+ va_end (args);
+
+ return return_val;
+}
+
+gint
+gtk_signal_emit_by_name (GtkObject *object,
+ const gchar *name,
+ ...)
+{
+ gint return_val;
+ gint type;
+ va_list args;
+
+ g_return_val_if_fail (object != NULL, FALSE);
+
+ if (initialize)
+ gtk_signal_init ();
+
+ return_val = TRUE;
+ type = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
+
+ if (type)
+ {
+ va_start (args, name);
+
+ return_val = gtk_signal_real_emit (object, type, args);
+
+ va_end (args);
+ }
+
+ return return_val;
+}
+
+void
+gtk_signal_emit_stop (GtkObject *object,
+ gint signal_type)
+{
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (signal_type >= 1);
+
+ if (initialize)
+ gtk_signal_init ();
+
+ if (gtk_emission_check (current_emissions, object, signal_type))
+ gtk_emission_add (&stop_emissions, object, signal_type);
+}
+
+void
+gtk_signal_emit_stop_by_name (GtkObject *object,
+ const gchar *name)
+{
+ gint type;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (name != NULL);
+
+ if (initialize)
+ gtk_signal_init ();
+
+ type = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
+ if (type)
+ gtk_signal_emit_stop (object, type);
+}
+
+gint
+gtk_signal_connect (GtkObject *object,
+ const gchar *name,
+ GtkSignalFunc func,
+ gpointer func_data)
+{
+ gint type;
+
+ g_return_val_if_fail (object != NULL, 0);
+
+ if (initialize)
+ gtk_signal_init ();
+
+ type = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
+ if (!type)
+ {
+ g_warning ("could not find signal type \"%s\" in the \"%s\" class ancestry",
+ name, gtk_type_name (GTK_OBJECT_TYPE (object)));
+ return 0;
+ }
+
+ return gtk_signal_connect_by_type (object, type, FALSE,
+ func, func_data, NULL,
+ FALSE, FALSE);
+}
+
+gint
+gtk_signal_connect_after (GtkObject *object,
+ const gchar *name,
+ GtkSignalFunc func,
+ gpointer func_data)
+{
+ gint type;
+
+ g_return_val_if_fail (object != NULL, 0);
+
+ if (initialize)
+ gtk_signal_init ();
+
+ type = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
+ if (!type)
+ {
+ g_warning ("could not find signal type \"%s\" in the \"%s\" class ancestry",
+ name, gtk_type_name (GTK_OBJECT_TYPE (object)));
+ return 0;
+ }
+
+ return gtk_signal_connect_by_type (object, type, FALSE,
+ func, func_data, NULL,
+ TRUE, FALSE);
+}
+
+gint
+gtk_signal_connect_interp (GtkObject *object,
+ gchar *name,
+ GtkCallbackMarshal func,
+ gpointer func_data,
+ GtkDestroyNotify destroy_func,
+ gint after)
+{
+ gint type;
+
+ g_return_val_if_fail (object != NULL, 0);
+
+ if (initialize)
+ gtk_signal_init ();
+
+ type = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
+ if (!type)
+ {
+ g_warning ("could not find signal type \"%s\" in the \"%s\" class ancestry",
+ name, gtk_type_name (GTK_OBJECT_TYPE (object)));
+ return 0;
+ }
+
+ return gtk_signal_connect_by_type (object, type, FALSE,
+ (GtkSignalFunc) func, func_data,
+ destroy_func, after, TRUE);
+}
+
+gint
+gtk_signal_connect_object (GtkObject *object,
+ const gchar *name,
+ GtkSignalFunc func,
+ GtkObject *slot_object)
+{
+ gint type;
+
+ g_return_val_if_fail (object != NULL, 0);
+
+ if (initialize)
+ gtk_signal_init ();
+
+ type = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
+ if (!type)
+ {
+ g_warning ("could not find signal type \"%s\" in the \"%s\" class ancestry",
+ name, gtk_type_name (GTK_OBJECT_TYPE (object)));
+ return 0;
+ }
+
+ return gtk_signal_connect_by_type (object, type, TRUE,
+ func, slot_object, NULL,
+ FALSE, FALSE);
+}
+
+gint
+gtk_signal_connect_object_after (GtkObject *object,
+ const gchar *name,
+ GtkSignalFunc func,
+ GtkObject *slot_object)
+{
+ gint type;
+
+ g_return_val_if_fail (object != NULL, 0);
+
+ if (initialize)
+ gtk_signal_init ();
+
+ type = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
+ if (!type)
+ {
+ g_warning ("could not find signal type \"%s\" in the \"%s\" class ancestry",
+ name, gtk_type_name (GTK_OBJECT_TYPE (object)));
+ return 0;
+ }
+
+ return gtk_signal_connect_by_type (object, type, TRUE,
+ func, slot_object, NULL,
+ TRUE, FALSE);
+}
+
+void
+gtk_signal_disconnect (GtkObject *object,
+ gint anid)
+{
+ GtkHandler *tmp;
+ GtkHandler *prev;
+
+ g_return_if_fail (object != NULL);
+
+ if (initialize)
+ gtk_signal_init ();
+
+ prev = NULL;
+ tmp = gtk_object_get_data (object, handler_key);
+
+ while (tmp)
+ {
+ if (tmp->id == anid)
+ {
+ if (prev)
+ prev->next = tmp->next;
+ else
+ gtk_object_set_data (object, handler_key, tmp->next);
+ gtk_signal_handler_destroy (tmp);
+ return;
+ }
+
+ prev = tmp;
+ tmp = tmp->next;
+ }
+
+ g_warning ("could not find handler (%d)", anid);
+}
+
+void
+gtk_signal_disconnect_by_data (GtkObject *object,
+ gpointer data)
+{
+ GtkHandler *start;
+ GtkHandler *tmp;
+ GtkHandler *prev;
+ gint found_one;
+
+ g_return_if_fail (object != NULL);
+
+ if (initialize)
+ gtk_signal_init ();
+
+ prev = NULL;
+ start = gtk_object_get_data (object, handler_key);
+ tmp = start;
+ found_one = FALSE;
+
+ while (tmp)
+ {
+ if (tmp->func_data == data)
+ {
+ found_one = TRUE;
+
+ if (prev)
+ prev->next = tmp->next;
+ else
+ start = tmp->next;
+
+ gtk_signal_handler_destroy (tmp);
+
+ if (prev)
+ {
+ tmp = prev->next;
+ }
+ else
+ {
+ prev = NULL;
+ tmp = start;
+ }
+ }
+ else
+ {
+ prev = tmp;
+ tmp = tmp->next;
+ }
+ }
+
+ gtk_object_set_data (object, handler_key, start);
+
+ if (!found_one)
+ g_warning ("could not find handler containing data (0x%0lX)", (long) data);
+}
+
+void
+gtk_signal_handler_block (GtkObject *object,
+ gint anid)
+{
+ GtkHandler *tmp;
+
+ g_return_if_fail (object != NULL);
+
+ if (initialize)
+ gtk_signal_init ();
+
+ tmp = gtk_object_get_data (object, handler_key);
+
+ while (tmp)
+ {
+ if (tmp->id == anid)
+ {
+ tmp->blocked = TRUE;
+ return;
+ }
+
+ tmp = tmp->next;
+ }
+
+ g_warning ("could not find handler (%d)", anid);
+}
+
+void
+gtk_signal_handler_block_by_data (GtkObject *object,
+ gpointer data)
+{
+ GtkHandler *tmp;
+ gint found_one;
+
+ g_return_if_fail (object != NULL);
+
+ if (initialize)
+ gtk_signal_init ();
+
+ found_one = FALSE;
+ tmp = gtk_object_get_data (object, handler_key);
+
+ while (tmp)
+ {
+ if (tmp->func_data == data)
+ {
+ tmp->blocked = TRUE;
+ found_one = TRUE;
+ }
+
+ tmp = tmp->next;
+ }
+
+ if (!found_one)
+ g_warning ("could not find handler containing data (0x%0lX)", (long) data);
+}
+
+void
+gtk_signal_handler_unblock (GtkObject *object,
+ gint anid)
+{
+ GtkHandler *tmp;
+
+ g_return_if_fail (object != NULL);
+
+ if (initialize)
+ gtk_signal_init ();
+
+ tmp = gtk_object_get_data (object, handler_key);
+
+ while (tmp)
+ {
+ if (tmp->id == anid)
+ {
+ tmp->blocked = FALSE;
+ return;
+ }
+
+ tmp = tmp->next;
+ }
+
+ g_warning ("could not find handler (%d)", anid);
+}
+
+void
+gtk_signal_handler_unblock_by_data (GtkObject *object,
+ gpointer data)
+{
+ GtkHandler *tmp;
+ gint found_one;
+
+ g_return_if_fail (object != NULL);
+
+ if (initialize)
+ gtk_signal_init ();
+
+ found_one = FALSE;
+ tmp = gtk_object_get_data (object, handler_key);
+
+ while (tmp)
+ {
+ if (tmp->func_data == data)
+ {
+ tmp->blocked = FALSE;
+ found_one = TRUE;
+ }
+
+ tmp = tmp->next;
+ }
+
+ if (!found_one)
+ g_warning ("could not find handler containing data (0x%0lX)", (long) data);
+}
+
+void
+gtk_signal_handlers_destroy (GtkObject *object)
+{
+ GtkHandler *list;
+ GtkHandler *handler;
+
+ list = gtk_object_get_data (object, handler_key);
+ if (list)
+ {
+ while (list)
+ {
+ handler = list->next;
+ gtk_signal_handler_destroy (list);
+ list = handler;
+ }
+
+ gtk_object_remove_data (object, handler_key);
+ }
+}
+
+void
+gtk_signal_default_marshaller (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *params)
+{
+ GtkSignalMarshaller0 rfunc;
+
+ rfunc = (GtkSignalMarshaller0) func;
+
+ (* rfunc) (object, func_data);
+}
+
+void
+gtk_signal_set_funcs (GtkSignalMarshal marshal_func,
+ GtkSignalDestroy destroy_func)
+{
+ marshal = marshal_func;
+ destroy = destroy_func;
+}
+
+
+static void
+gtk_signal_init ()
+{
+ if (initialize)
+ {
+ initialize = FALSE;
+ signal_hash_table = g_hash_table_new ((GHashFunc) gtk_signal_hash,
+ (GCompareFunc) gtk_signal_compare);
+ signal_info_hash_table = g_hash_table_new ((GHashFunc) gtk_signal_info_hash,
+ (GCompareFunc) gtk_signal_info_compare);
+ }
+}
+
+static guint
+gtk_signal_hash (gint *key)
+{
+ return (guint) *key;
+}
+
+static gint
+gtk_signal_compare (gint *a,
+ gint *b)
+{
+ return (*a == *b);
+}
+
+static guint
+gtk_signal_info_hash (GtkSignalInfo *a)
+{
+ return (g_string_hash (a->name) + a->object_type);
+}
+
+static gint
+gtk_signal_info_compare (GtkSignalInfo *a,
+ GtkSignalInfo *b)
+{
+ return ((a->object_type == b->object_type) &&
+ g_string_equal (a->name, b->name));
+}
+
+static GtkHandler*
+gtk_signal_handler_new ()
+{
+ GtkHandler *handler;
+
+ if (!handler_mem_chunk)
+ handler_mem_chunk = g_mem_chunk_new ("handler mem chunk", sizeof (GtkHandler),
+ 1024, G_ALLOC_AND_FREE);
+
+ handler = g_chunk_new (GtkHandler, handler_mem_chunk);
+
+ handler->id = 0;
+ handler->signal_type = 0;
+ handler->object_signal = FALSE;
+ handler->blocked = FALSE;
+ handler->after = FALSE;
+ handler->no_marshal = FALSE;
+ handler->func = NULL;
+ handler->func_data = NULL;
+ handler->destroy_func = NULL;
+ handler->next = NULL;
+
+ return handler;
+}
+
+static void
+gtk_signal_handler_destroy (GtkHandler *handler)
+{
+ if (!handler->func && destroy)
+ (* destroy) (handler->func_data);
+ else if (handler->destroy_func)
+ (* handler->destroy_func) (handler->func_data);
+ g_mem_chunk_free (handler_mem_chunk, handler);
+}
+
+static void
+gtk_signal_handler_insert (GtkObject *object,
+ GtkHandler *handler)
+{
+ GtkHandler *start;
+ GtkHandler *tmp;
+ GtkHandler *prev;
+
+ start = gtk_object_get_data (object, handler_key);
+ if (!start)
+ {
+ gtk_object_set_data (object, handler_key, handler);
+ }
+ else
+ {
+ prev = NULL;
+ tmp = start;
+
+ while (tmp)
+ {
+ if (tmp->signal_type < handler->signal_type)
+ {
+ if (prev)
+ prev->next = handler;
+ else
+ gtk_object_set_data (object, handler_key, handler);
+ handler->next = tmp;
+ break;
+ }
+
+ if (!tmp->next)
+ {
+ tmp->next = handler;
+ break;
+ }
+
+ prev = tmp;
+ tmp = tmp->next;
+ }
+ }
+}
+
+static gint
+gtk_signal_real_emit (GtkObject *object,
+ gint signal_type,
+ va_list args)
+{
+ gint old_value;
+ GtkSignal *signal;
+ GtkHandler *handlers;
+ GtkHandlerInfo info;
+ guchar **signal_func_offset;
+ gint being_destroyed;
+ GtkArg params[MAX_PARAMS];
+
+ g_return_val_if_fail (object != NULL, FALSE);
+ g_return_val_if_fail (signal_type >= 1, TRUE);
+
+ being_destroyed = GTK_OBJECT_BEING_DESTROYED (object);
+ if (!GTK_OBJECT_NEED_DESTROY (object))
+ {
+ signal = g_hash_table_lookup (signal_hash_table, &signal_type);
+ g_return_val_if_fail (signal != NULL, TRUE);
+ g_return_val_if_fail (gtk_type_is_a (GTK_OBJECT_TYPE (object), signal->info.object_type), TRUE);
+
+ if ((signal->run_type & GTK_RUN_NO_RECURSE) &&
+ gtk_emission_check (current_emissions, object, signal_type))
+ {
+ gtk_emission_add (&restart_emissions, object, signal_type);
+ return TRUE;
+ }
+
+ old_value = GTK_OBJECT_IN_CALL (object);
+ GTK_OBJECT_SET_FLAGS (object, GTK_IN_CALL);
+
+ gtk_params_get (params, signal->nparams, signal->params, signal->return_val, args);
+
+ gtk_emission_add (&current_emissions, object, signal_type);
+
+ restart:
+ if (GTK_RUN_TYPE (signal->run_type) != GTK_RUN_LAST)
+ {
+ signal_func_offset = (guchar**) ((guchar*) object->klass + signal->function_offset);
+ if (*signal_func_offset)
+ (* signal->marshaller) (object, (GtkSignalFunc) *signal_func_offset, NULL, params);
+ if (GTK_OBJECT_NEED_DESTROY (object))
+ goto done;
+ }
+
+ info.object = object;
+ info.marshaller = signal->marshaller;
+ info.params = params;
+ info.param_types = signal->params;
+ info.return_val = signal->return_val;
+ info.nparams = signal->nparams;
+ info.run_type = signal->run_type;
+ info.signal_type = signal_type;
+
+ handlers = gtk_signal_get_handlers (object, signal_type);
+ switch (gtk_handlers_run (handlers, &info, FALSE))
+ {
+ case DONE:
+ goto done;
+ case RESTART:
+ goto restart;
+ }
+
+ if (GTK_RUN_TYPE (signal->run_type) != GTK_RUN_FIRST)
+ {
+ signal_func_offset = (guchar**) ((guchar*) object->klass + signal->function_offset);
+ if (*signal_func_offset)
+ (* signal->marshaller) (object, (GtkSignalFunc) *signal_func_offset, NULL, params);
+ if (being_destroyed || GTK_OBJECT_NEED_DESTROY (object))
+ goto done;
+ }
+
+ switch (gtk_handlers_run (handlers, &info, TRUE))
+ {
+ case DONE:
+ goto done;
+ case RESTART:
+ goto restart;
+ }
+
+ done:
+ gtk_emission_remove (&current_emissions, object, signal_type);
+
+ if (signal->run_type & GTK_RUN_NO_RECURSE)
+ gtk_emission_remove (&restart_emissions, object, signal_type);
+
+ if (!being_destroyed && !old_value)
+ GTK_OBJECT_UNSET_FLAGS (object, GTK_IN_CALL);
+ }
+
+ if (!being_destroyed && GTK_OBJECT_NEED_DESTROY (object) && !GTK_OBJECT_IN_CALL (object))
+ {
+ gtk_object_destroy (object);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static GtkHandler*
+gtk_signal_get_handlers (GtkObject *object,
+ gint signal_type)
+{
+ GtkHandler *handlers;
+
+ g_return_val_if_fail (object != NULL, NULL);
+ g_return_val_if_fail (signal_type >= 1, NULL);
+
+ handlers = gtk_object_get_data (object, handler_key);
+
+ while (handlers)
+ {
+ if (handlers->signal_type == signal_type)
+ return handlers;
+ handlers = handlers->next;
+ }
+
+ return NULL;
+}
+
+static gint
+gtk_signal_connect_by_type (GtkObject *object,
+ gint signal_type,
+ gint object_signal,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkSignalDestroy destroy_func,
+ gint after,
+ gint no_marshal)
+{
+ GtkHandler *handler;
+ gint *object_signals;
+ gint nsignals;
+ gint found_it;
+ gint i;
+
+ g_return_val_if_fail (object != NULL, 0);
+ g_return_val_if_fail (object->klass != NULL, 0);
+ g_return_val_if_fail (object->klass->signals != NULL, 0);
+
+ /* Search through the signals for this object and make
+ * sure the one we are adding is valid. If it isn't then
+ * issue a warning and return.
+ */
+ object_signals = object->klass->signals;
+ nsignals = object->klass->nsignals;
+ found_it = FALSE;
+
+ for (i = 0; i < nsignals; i++)
+ if (object_signals[i] == signal_type)
+ {
+ found_it = TRUE;
+ break;
+ }
+
+ if (!found_it)
+ {
+ g_warning ("could not find signal (%d) in object's list of signals", signal_type);
+ return 0;
+ }
+
+ handler = gtk_signal_handler_new ();
+ handler->id = next_handler_id++;
+ handler->signal_type = signal_type;
+ handler->object_signal = object_signal;
+ handler->func = func;
+ handler->func_data = func_data;
+ handler->destroy_func = destroy_func;
+
+ if (after)
+ handler->after = TRUE;
+ handler->no_marshal = no_marshal;
+
+ gtk_signal_handler_insert (object, handler);
+ return handler->id;
+}
+
+static GtkEmission*
+gtk_emission_new ()
+{
+ GtkEmission *emission;
+
+ if (!emission_mem_chunk)
+ emission_mem_chunk = g_mem_chunk_new ("emission mem chunk", sizeof (GtkEmission),
+ 1024, G_ALLOC_AND_FREE);
+
+ emission = g_chunk_new (GtkEmission, emission_mem_chunk);
+
+ emission->object = NULL;
+ emission->signal_type = 0;
+
+ return emission;
+}
+
+static void
+gtk_emission_destroy (GtkEmission *emission)
+{
+ g_mem_chunk_free (emission_mem_chunk, emission);
+}
+
+static void
+gtk_emission_add (GList **emissions,
+ GtkObject *object,
+ gint signal_type)
+{
+ GtkEmission *emission;
+
+ g_return_if_fail (emissions != NULL);
+ g_return_if_fail (object != NULL);
+
+ emission = gtk_emission_new ();
+ emission->object = object;
+ emission->signal_type = signal_type;
+
+ *emissions = g_list_prepend (*emissions, emission);
+}
+
+static void
+gtk_emission_remove (GList **emissions,
+ GtkObject *object,
+ gint signal_type)
+{
+ GtkEmission *emission;
+ GList *tmp;
+
+ g_return_if_fail (emissions != NULL);
+ g_return_if_fail (object != NULL);
+
+ tmp = *emissions;
+ while (tmp)
+ {
+ emission = tmp->data;
+
+ if ((emission->object == object) &&
+ (emission->signal_type == signal_type))
+ {
+ gtk_emission_destroy (emission);
+ *emissions = g_list_remove_link (*emissions, tmp);
+ g_list_free (tmp);
+ break;
+ }
+
+ tmp = tmp->next;
+ }
+}
+
+static gint
+gtk_emission_check (GList *emissions,
+ GtkObject *object,
+ gint signal_type)
+{
+ GtkEmission *emission;
+ GList *tmp;
+
+ g_return_val_if_fail (object != NULL, FALSE);
+
+ tmp = emissions;
+ while (tmp)
+ {
+ emission = tmp->data;
+ tmp = tmp->next;
+
+ if ((emission->object == object) &&
+ (emission->signal_type == signal_type))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gint
+gtk_handlers_run (GtkHandler *handlers,
+ GtkHandlerInfo *info,
+ gint after)
+{
+ while (handlers && (handlers->signal_type == info->signal_type))
+ {
+ if (!handlers->blocked && (handlers->after == after))
+ {
+ if (handlers->func)
+ {
+ if (handlers->no_marshal)
+ (* (GtkCallbackMarshal)handlers->func) (info->object,
+ handlers->func_data,
+ info->nparams,
+ info->params);
+ else if (handlers->object_signal)
+ (* info->marshaller) (GTK_OBJECT (handlers->func_data),
+ handlers->func,
+ handlers->func_data,
+ info->params);
+ else
+ (* info->marshaller) (info->object,
+ handlers->func,
+ handlers->func_data,
+ info->params);
+ }
+ else if (marshal)
+ (* marshal) (info->object,
+ handlers->func_data,
+ info->nparams,
+ info->params,
+ info->param_types,
+ info->return_val);
+
+ if (GTK_OBJECT_NEED_DESTROY (info->object))
+ return DONE;
+ else if (gtk_emission_check (stop_emissions, info->object, info->signal_type))
+ {
+ gtk_emission_remove (&stop_emissions, info->object, info->signal_type);
+
+ if (info->run_type & GTK_RUN_NO_RECURSE)
+ gtk_emission_remove (&restart_emissions, info->object, info->signal_type);
+ return DONE;
+ }
+ else if ((info->run_type & GTK_RUN_NO_RECURSE) &&
+ gtk_emission_check (restart_emissions, info->object, info->signal_type))
+ {
+ gtk_emission_remove (&restart_emissions, info->object, info->signal_type);
+ return RESTART;
+ }
+ }
+
+ handlers = handlers->next;
+ }
+
+ return 0;
+}
+
+static void
+gtk_params_get (GtkArg *params,
+ gint nparams,
+ GtkType *param_types,
+ GtkType return_val,
+ va_list args)
+{
+ int i;
+
+ for (i = 0; i < nparams; i++)
+ {
+ if (param_types[i] != GTK_TYPE_NONE)
+ {
+ params[i].type = param_types[i];
+ params[i].name = NULL;
+ }
+
+ switch (GTK_FUNDAMENTAL_TYPE (param_types[i]))
+ {
+ case GTK_TYPE_INVALID:
+ break;
+ case GTK_TYPE_NONE:
+ break;
+ case GTK_TYPE_CHAR:
+ GTK_VALUE_CHAR(params[i]) = va_arg (args, gint);
+ break;
+ case GTK_TYPE_BOOL:
+ GTK_VALUE_BOOL(params[i]) = va_arg (args, gint);
+ break;
+ case GTK_TYPE_INT:
+ GTK_VALUE_INT(params[i]) = va_arg (args, gint);
+ break;
+ case GTK_TYPE_UINT:
+ GTK_VALUE_UINT(params[i]) = va_arg (args, guint);
+ break;
+ case GTK_TYPE_ENUM:
+ GTK_VALUE_ENUM(params[i]) = va_arg (args, gint);
+ break;
+ case GTK_TYPE_FLAGS:
+ GTK_VALUE_FLAGS(params[i]) = va_arg (args, gint);
+ break;
+ case GTK_TYPE_LONG:
+ GTK_VALUE_LONG(params[i]) = va_arg (args, glong);
+ break;
+ case GTK_TYPE_ULONG:
+ GTK_VALUE_ULONG(params[i]) = va_arg (args, gulong);
+ break;
+ case GTK_TYPE_FLOAT:
+ GTK_VALUE_FLOAT(params[i]) = va_arg (args, gfloat);
+ break;
+ case GTK_TYPE_STRING:
+ GTK_VALUE_STRING(params[i]) = va_arg (args, gchar*);
+ break;
+ case GTK_TYPE_POINTER:
+ GTK_VALUE_POINTER(params[i]) = va_arg (args, gpointer);
+ break;
+ case GTK_TYPE_BOXED:
+ GTK_VALUE_BOXED(params[i]) = va_arg (args, gpointer);
+ break;
+ case GTK_TYPE_SIGNAL:
+ GTK_VALUE_SIGNAL(params[i]).f = va_arg (args, GtkFunction);
+ GTK_VALUE_SIGNAL(params[i]).d = va_arg (args, gpointer);
+ break;
+ case GTK_TYPE_FOREIGN:
+ GTK_VALUE_FOREIGN(params[i]).data = va_arg (args, gpointer);
+ GTK_VALUE_FOREIGN(params[i]).notify =
+ va_arg (args, GtkDestroyNotify);
+ break;
+ case GTK_TYPE_CALLBACK:
+ GTK_VALUE_CALLBACK(params[i]).marshal =
+ va_arg (args, GtkCallbackMarshal);
+ GTK_VALUE_CALLBACK(params[i]).data = va_arg (args, gpointer);
+ GTK_VALUE_CALLBACK(params[i]).notify =
+ va_arg (args, GtkDestroyNotify);
+ break;
+ case GTK_TYPE_C_CALLBACK:
+ GTK_VALUE_C_CALLBACK(params[i]).func = va_arg (args, GtkFunction);
+ GTK_VALUE_C_CALLBACK(params[i]).func_data = va_arg (args, gpointer);
+ break;
+ case GTK_TYPE_ARGS:
+ GTK_VALUE_ARGS(params[i]).n_args = va_arg (args, int);
+ GTK_VALUE_ARGS(params[i]).args = va_arg (args, GtkArg*);
+ break;
+ case GTK_TYPE_OBJECT:
+ GTK_VALUE_OBJECT(params[i]) = va_arg (args, GtkObject*);
+ g_assert (GTK_VALUE_OBJECT(params[i]) == NULL ||
+ GTK_CHECK_TYPE (GTK_VALUE_OBJECT(params[i]),
+ params[i].type));
+ break;
+ default:
+ g_error ("unsupported type %s in signal arg",
+ gtk_type_name (params[i].type));
+ break;
+ }
+ }
+
+ if (return_val != GTK_TYPE_NONE)
+ {
+ params[i].type = return_val;
+ params[i].name = NULL;
+ }
+
+ switch (GTK_FUNDAMENTAL_TYPE (return_val))
+ {
+ case GTK_TYPE_INVALID:
+ break;
+ case GTK_TYPE_NONE:
+ break;
+ case GTK_TYPE_CHAR:
+ params[i].d.pointer_data = va_arg (args, gchar*);
+ break;
+ case GTK_TYPE_BOOL:
+ params[i].d.pointer_data = va_arg (args, gint*);
+ break;
+ case GTK_TYPE_INT:
+ params[i].d.pointer_data = va_arg (args, gint*);
+ break;
+ case GTK_TYPE_UINT:
+ params[i].d.pointer_data = va_arg (args, guint*);
+ break;
+ case GTK_TYPE_ENUM:
+ params[i].d.pointer_data = va_arg (args, gint*);
+ break;
+ case GTK_TYPE_FLAGS:
+ params[i].d.pointer_data = va_arg (args, gint*);
+ break;
+ case GTK_TYPE_LONG:
+ params[i].d.pointer_data = va_arg (args, glong*);
+ break;
+ case GTK_TYPE_ULONG:
+ params[i].d.pointer_data = va_arg (args, gulong*);
+ break;
+ case GTK_TYPE_FLOAT:
+ params[i].d.pointer_data = va_arg (args, gfloat*);
+ break;
+ case GTK_TYPE_STRING:
+ params[i].d.pointer_data = va_arg (args, gchar**);
+ break;
+ case GTK_TYPE_POINTER:
+ params[i].d.pointer_data = va_arg (args, gpointer*);
+ break;
+ case GTK_TYPE_BOXED:
+ params[i].d.pointer_data = va_arg (args, gpointer*);
+ break;
+ case GTK_TYPE_OBJECT:
+ params[i].d.pointer_data = va_arg (args, GtkObject**);
+ break;
+ case GTK_TYPE_SIGNAL:
+ case GTK_TYPE_FOREIGN:
+ case GTK_TYPE_CALLBACK:
+ case GTK_TYPE_C_CALLBACK:
+ case GTK_TYPE_ARGS:
+ default:
+ g_error ("unsupported type %s in signal return",
+ gtk_type_name (return_val));
+ break;
+ }
+}
diff --git a/gtk/gtksignal.h b/gtk/gtksignal.h
new file mode 100644
index 000000000..68ff99902
--- /dev/null
+++ b/gtk/gtksignal.h
@@ -0,0 +1,124 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_SIGNAL_H__
+#define __GTK_SIGNAL_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkenums.h>
+#include <gtk/gtkobject.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#ifdef offsetof
+#define GTK_SIGNAL_OFFSET(t, f) ((int) offsetof (t, f))
+#else /* offsetof */
+#define GTK_SIGNAL_OFFSET(t, f) ((int) ((char*) &((t*) 0)->f))
+#endif /* offsetof */
+
+#define GTK_SIGNAL_FUNC(f) ((GtkSignalFunc) f)
+
+
+typedef void (*GtkSignalFunc) (void);
+typedef void (*GtkSignalMarshaller) (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args);
+typedef void (*GtkSignalMarshal) (GtkObject *object,
+ gpointer data,
+ gint nparams,
+ GtkArg *args,
+ GtkType *arg_types,
+ GtkType return_type);
+typedef void (*GtkSignalDestroy) (gpointer data);
+
+
+gint gtk_signal_new (const gchar *name,
+ GtkSignalRunType run_type,
+ gint object_type,
+ gint function_offset,
+ GtkSignalMarshaller marshaller,
+ GtkType return_val,
+ gint nparams,
+ ...);
+gint gtk_signal_lookup (const gchar *name,
+ gint object_type);
+gchar* gtk_signal_name (gint signal_num);
+gint gtk_signal_emit (GtkObject *object,
+ gint signal_type,
+ ...);
+gint gtk_signal_emit_by_name (GtkObject *object,
+ const gchar *name,
+ ...);
+void gtk_signal_emit_stop (GtkObject *object,
+ gint signal_type);
+void gtk_signal_emit_stop_by_name (GtkObject *object,
+ const gchar *name);
+gint gtk_signal_connect (GtkObject *object,
+ const gchar *name,
+ GtkSignalFunc func,
+ gpointer func_data);
+gint gtk_signal_connect_after (GtkObject *object,
+ const gchar *name,
+ GtkSignalFunc func,
+ gpointer func_data);
+gint gtk_signal_connect_object (GtkObject *object,
+ const gchar *name,
+ GtkSignalFunc func,
+ GtkObject *slot_object);
+gint gtk_signal_connect_object_after (GtkObject *object,
+ const gchar *name,
+ GtkSignalFunc func,
+ GtkObject *slot_object);
+gint gtk_signal_connect_interp (GtkObject *object,
+ gchar *name,
+ GtkCallbackMarshal func,
+ gpointer data,
+ GtkDestroyNotify destroy_func,
+ gint after);
+void gtk_signal_disconnect (GtkObject *object,
+ gint anid);
+void gtk_signal_disconnect_by_data (GtkObject *object,
+ gpointer data);
+void gtk_signal_handler_block (GtkObject *object,
+ gint anid);
+void gtk_signal_handler_block_by_data (GtkObject *object,
+ gpointer data);
+void gtk_signal_handler_unblock (GtkObject *object,
+ gint anid);
+void gtk_signal_handler_unblock_by_data (GtkObject *object,
+ gpointer data);
+void gtk_signal_handlers_destroy (GtkObject *object);
+void gtk_signal_default_marshaller (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args);
+void gtk_signal_set_funcs (GtkSignalMarshal marshal_func,
+ GtkSignalDestroy destroy_func);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_SIGNAL_H__ */
diff --git a/gtk/gtkstyle.c b/gtk/gtkstyle.c
new file mode 100644
index 000000000..ae8c1a5d9
--- /dev/null
+++ b/gtk/gtkstyle.c
@@ -0,0 +1,1795 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <math.h>
+#include "gtkgc.h"
+#include "gtkstyle.h"
+
+
+#define LIGHTNESS_MULT 1.3
+#define DARKNESS_MULT 0.7
+
+
+typedef struct _GtkStyleKey GtkStyleKey;
+
+struct _GtkStyleKey
+{
+ GdkColor fg[5];
+ GdkColor bg[5];
+ GdkColor text[5];
+ GdkColor base[5];
+
+ GdkPixmap *bg_pixmap[5];
+
+ GdkFont *font;
+
+ gint depth;
+ GdkColormap *colormap;
+ GtkStyleClass *klass;
+};
+
+
+static void gtk_style_init (GtkStyle *style);
+static void gtk_styles_init (void);
+static void gtk_style_remove (GtkStyle *style);
+static GtkStyle* gtk_style_find (GtkStyle *style,
+ GdkColormap *cmap,
+ gint depth);
+static GtkStyle* gtk_style_new_from_key (GtkStyleKey *key);
+static GtkStyleKey* gtk_style_key_dup (GtkStyleKey *key);
+static void gtk_style_destroy (GtkStyle *style);
+static void gtk_style_key_destroy (GtkStyleKey *key);
+static guint gtk_style_key_hash (GtkStyleKey *key);
+static guint gtk_style_value_hash (GtkStyle *style);
+static gint gtk_style_key_compare (GtkStyleKey *a,
+ GtkStyleKey *b);
+
+static void gtk_default_draw_hline (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ gint x1,
+ gint x2,
+ gint y);
+static void gtk_default_draw_vline (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ gint y1,
+ gint y2,
+ gint x);
+static void gtk_default_draw_shadow (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
+static void gtk_default_draw_polygon (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ GdkPoint *points,
+ gint npoints,
+ gint fill);
+static void gtk_default_draw_arrow (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ GtkArrowType arrow_type,
+ gint fill,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
+static void gtk_default_draw_diamond (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
+static void gtk_default_draw_oval (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
+static void gtk_default_draw_string (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ gint x,
+ gint y,
+ const gchar *string);
+
+static void gtk_style_shade (GdkColor *a, GdkColor *b, gdouble k);
+static void rgb_to_hls (gdouble *r, gdouble *g, gdouble *b);
+static void hls_to_rgb (gdouble *h, gdouble *l, gdouble *s);
+
+
+static GtkStyleClass default_class =
+{
+ 2,
+ 2,
+ gtk_default_draw_hline,
+ gtk_default_draw_vline,
+ gtk_default_draw_shadow,
+ gtk_default_draw_polygon,
+ gtk_default_draw_arrow,
+ gtk_default_draw_diamond,
+ gtk_default_draw_oval,
+ gtk_default_draw_string,
+};
+
+static GdkColor gtk_default_normal_fg = { 0, 0, 0, 0 };
+static GdkColor gtk_default_active_fg = { 0, 0, 0, 0 };
+static GdkColor gtk_default_prelight_fg = { 0, 0, 0, 0 };
+static GdkColor gtk_default_selected_fg = { 0, 0xffff, 0xffff, 0xffff };
+static GdkColor gtk_default_insensitive_fg = { 0, 0x7530, 0x7530, 0x7530 };
+
+static GdkColor gtk_default_normal_bg = { 0, 0xd6d6, 0xd6d6, 0xd6d6 };
+static GdkColor gtk_default_active_bg = { 0, 0xc350, 0xc350, 0xc350 };
+static GdkColor gtk_default_prelight_bg = { 0, 0xea60, 0xea60, 0xea60 };
+static GdkColor gtk_default_selected_bg = { 0, 0, 0, 0x9c40 };
+static GdkColor gtk_default_insensitive_bg = { 0, 0xd6d6, 0xd6d6, 0xd6d6 };
+
+static GdkFont *default_font = NULL;
+
+static gint initialize = TRUE;
+static GCache *style_cache = NULL;
+static GSList *unattached_styles = NULL;
+
+static GMemChunk *key_mem_chunk = NULL;
+
+
+GtkStyle*
+gtk_style_new ()
+{
+ GtkStyle *style;
+ gint i;
+
+ style = g_new (GtkStyle, 1);
+
+ if (!default_font)
+ default_font = gdk_font_load ("-adobe-helvetica-medium-r-normal--*-120-*-*-*-*-*-*");
+
+ style->font = default_font;
+ gdk_font_ref (style->font);
+
+ style->ref_count = 0;
+ style->attach_count = 0;
+ style->colormap = NULL;
+ style->depth = -1;
+ style->klass = &default_class;
+
+ style->black.red = 0;
+ style->black.green = 0;
+ style->black.blue = 0;
+
+ style->white.red = 65535;
+ style->white.green = 65535;
+ style->white.blue = 65535;
+
+ style->black_gc = NULL;
+ style->white_gc = NULL;
+
+ style->fg[GTK_STATE_NORMAL] = gtk_default_normal_fg;
+ style->fg[GTK_STATE_ACTIVE] = gtk_default_active_fg;
+ style->fg[GTK_STATE_PRELIGHT] = gtk_default_prelight_fg;
+ style->fg[GTK_STATE_SELECTED] = gtk_default_selected_fg;
+ style->fg[GTK_STATE_INSENSITIVE] = gtk_default_insensitive_fg;
+
+ style->bg[GTK_STATE_NORMAL] = gtk_default_normal_bg;
+ style->bg[GTK_STATE_ACTIVE] = gtk_default_active_bg;
+ style->bg[GTK_STATE_PRELIGHT] = gtk_default_prelight_bg;
+ style->bg[GTK_STATE_SELECTED] = gtk_default_selected_bg;
+ style->bg[GTK_STATE_INSENSITIVE] = gtk_default_insensitive_bg;
+
+ for (i = 0; i < 5; i++)
+ {
+ style->text[i] = style->fg[i];
+ style->base[i] = style->white;
+ }
+
+ for (i = 0; i < 5; i++)
+ style->bg_pixmap[i] = NULL;
+
+ for (i = 0; i < 5; i++)
+ {
+ style->fg_gc[i] = NULL;
+ style->bg_gc[i] = NULL;
+ style->light_gc[i] = NULL;
+ style->dark_gc[i] = NULL;
+ style->mid_gc[i] = NULL;
+ style->text_gc[i] = NULL;
+ style->base_gc[i] = NULL;
+ }
+
+ unattached_styles = g_slist_prepend (unattached_styles, style);
+
+ return style;
+}
+
+GtkStyle*
+gtk_style_attach (GtkStyle *style,
+ GdkWindow *window)
+{
+ GtkStyle *new_style;
+ GdkColormap *colormap;
+ gint depth;
+
+ g_return_val_if_fail (style != NULL, NULL);
+ g_return_val_if_fail (window != NULL, NULL);
+
+ colormap = gdk_window_get_colormap (window);
+ gdk_window_get_geometry (window, NULL, NULL, NULL, NULL, &depth);
+
+ new_style = gtk_style_find (style, colormap, depth);
+
+ if (new_style && (new_style != style))
+ {
+ gtk_style_unref (style);
+ style = new_style;
+ gtk_style_ref (style);
+ }
+
+ if (style->attach_count == 0)
+ unattached_styles = g_slist_remove (unattached_styles, style);
+
+ style->attach_count += 1;
+
+ return style;
+}
+
+void
+gtk_style_detach (GtkStyle *style)
+{
+ gint i;
+
+ g_return_if_fail (style != NULL);
+
+ style->attach_count -= 1;
+ if (style->attach_count == 0)
+ {
+ unattached_styles = g_slist_prepend (unattached_styles, style);
+
+ gtk_gc_release (style->black_gc);
+ gtk_gc_release (style->white_gc);
+
+ style->black_gc = NULL;
+ style->white_gc = NULL;
+
+ for (i = 0; i < 5; i++)
+ {
+ gtk_gc_release (style->fg_gc[i]);
+ gtk_gc_release (style->bg_gc[i]);
+ gtk_gc_release (style->light_gc[i]);
+ gtk_gc_release (style->dark_gc[i]);
+ gtk_gc_release (style->mid_gc[i]);
+ gtk_gc_release (style->text_gc[i]);
+ gtk_gc_release (style->base_gc[i]);
+
+ style->fg_gc[i] = NULL;
+ style->bg_gc[i] = NULL;
+ style->light_gc[i] = NULL;
+ style->dark_gc[i] = NULL;
+ style->mid_gc[i] = NULL;
+ style->text_gc[i] = NULL;
+ style->base_gc[i] = NULL;
+ }
+
+ style->depth = -1;
+ style->colormap = NULL;
+ }
+
+ gtk_style_remove (style);
+}
+
+GtkStyle*
+gtk_style_ref (GtkStyle *style)
+{
+ g_return_val_if_fail (style != NULL, NULL);
+
+ style->ref_count += 1;
+ return style;
+}
+
+void
+gtk_style_unref (GtkStyle *style)
+{
+ g_return_if_fail (style != NULL);
+
+ style->ref_count -= 1;
+ if (style->ref_count == 0)
+ gtk_style_destroy (style);
+}
+
+void
+gtk_style_set_background (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type)
+{
+ GdkPixmap *pixmap;
+ gint parent_relative;
+
+ g_return_if_fail (style != NULL);
+ g_return_if_fail (window != NULL);
+
+ if (style->bg_pixmap[state_type])
+ {
+ if (style->bg_pixmap[state_type] == (GdkPixmap*) GDK_PARENT_RELATIVE)
+ {
+ pixmap = NULL;
+ parent_relative = TRUE;
+ }
+ else
+ {
+ pixmap = style->bg_pixmap[state_type];
+ parent_relative = FALSE;
+ }
+
+ gdk_window_set_back_pixmap (window, pixmap, parent_relative);
+ }
+ else
+ gdk_window_set_background (window, &style->bg[state_type]);
+}
+
+
+void
+gtk_draw_hline (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ gint x1,
+ gint x2,
+ gint y)
+{
+ g_return_if_fail (style != NULL);
+ g_return_if_fail (style->klass != NULL);
+ g_return_if_fail (style->klass->draw_hline != NULL);
+
+ (*style->klass->draw_hline) (style, window, state_type, x1, x2, y);
+}
+
+
+void
+gtk_draw_vline (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ gint y1,
+ gint y2,
+ gint x)
+{
+ g_return_if_fail (style != NULL);
+ g_return_if_fail (style->klass != NULL);
+ g_return_if_fail (style->klass->draw_vline != NULL);
+
+ (*style->klass->draw_vline) (style, window, state_type, y1, y2, x);
+}
+
+
+void
+gtk_draw_shadow (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ g_return_if_fail (style != NULL);
+ g_return_if_fail (style->klass != NULL);
+ g_return_if_fail (style->klass->draw_shadow != NULL);
+
+ (*style->klass->draw_shadow) (style, window, state_type, shadow_type, x, y, width, height);
+}
+
+void
+gtk_draw_polygon (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ GdkPoint *points,
+ gint npoints,
+ gint fill)
+{
+ g_return_if_fail (style != NULL);
+ g_return_if_fail (style->klass != NULL);
+ g_return_if_fail (style->klass->draw_shadow != NULL);
+
+ (*style->klass->draw_polygon) (style, window, state_type, shadow_type, points, npoints, fill);
+}
+
+void
+gtk_draw_arrow (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ GtkArrowType arrow_type,
+ gint fill,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ g_return_if_fail (style != NULL);
+ g_return_if_fail (style->klass != NULL);
+ g_return_if_fail (style->klass->draw_arrow != NULL);
+
+ (*style->klass->draw_arrow) (style, window, state_type, shadow_type, arrow_type, fill, x, y, width, height);
+}
+
+
+void
+gtk_draw_diamond (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ g_return_if_fail (style != NULL);
+ g_return_if_fail (style->klass != NULL);
+ g_return_if_fail (style->klass->draw_diamond != NULL);
+
+ (*style->klass->draw_diamond) (style, window, state_type, shadow_type, x, y, width, height);
+}
+
+
+void
+gtk_draw_oval (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ g_return_if_fail (style != NULL);
+ g_return_if_fail (style->klass != NULL);
+ g_return_if_fail (style->klass->draw_oval != NULL);
+
+ (*style->klass->draw_oval) (style, window, state_type, shadow_type, x, y, width, height);
+}
+
+void
+gtk_draw_string (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ gint x,
+ gint y,
+ const gchar *string)
+{
+ g_return_if_fail (style != NULL);
+ g_return_if_fail (style->klass != NULL);
+ g_return_if_fail (style->klass->draw_oval != NULL);
+
+ (*style->klass->draw_string) (style, window, state_type, x, y, string);
+}
+
+
+static void
+gtk_style_init (GtkStyle *style)
+{
+ GdkGCValues gc_values;
+ GdkGCValuesMask gc_values_mask;
+ GdkColormap *colormap;
+ gint i;
+
+ g_return_if_fail (style != NULL);
+
+ if (style->attach_count == 0)
+ {
+ for (i = 0; i < 5; i++)
+ {
+ gtk_style_shade (&style->bg[i], &style->light[i], LIGHTNESS_MULT);
+ gtk_style_shade (&style->bg[i], &style->dark[i], DARKNESS_MULT);
+
+ style->mid[i].red = (style->light[i].red + style->dark[i].red) / 2;
+ style->mid[i].green = (style->light[i].green + style->dark[i].green) / 2;
+ style->mid[i].blue = (style->light[i].blue + style->dark[i].blue) / 2;
+ }
+
+ colormap = style->colormap;
+
+ gdk_color_black (colormap, &style->black);
+ gdk_color_white (colormap, &style->white);
+
+ gc_values_mask = GDK_GC_FOREGROUND | GDK_GC_FONT;
+ if (style->font->type == GDK_FONT_FONT)
+ {
+ gc_values.font = style->font;
+ }
+ else if (style->font->type == GDK_FONT_FONTSET)
+ {
+ gc_values.font = default_font;
+ }
+
+ gc_values.foreground = style->black;
+ style->black_gc = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
+
+ gc_values.foreground = style->white;
+ style->white_gc = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
+
+ for (i = 0; i < 5; i++)
+ {
+ if (!gdk_color_alloc (colormap, &style->fg[i]))
+ g_warning ("unable to allocate color: ( %d %d %d )",
+ style->fg[i].red, style->fg[i].green, style->fg[i].blue);
+ if (!gdk_color_alloc (colormap, &style->bg[i]))
+ g_warning ("unable to allocate color: ( %d %d %d )",
+ style->bg[i].red, style->bg[i].green, style->bg[i].blue);
+ if (!gdk_color_alloc (colormap, &style->light[i]))
+ g_warning ("unable to allocate color: ( %d %d %d )",
+ style->light[i].red, style->light[i].green, style->light[i].blue);
+ if (!gdk_color_alloc (colormap, &style->dark[i]))
+ g_warning ("unable to allocate color: ( %d %d %d )",
+ style->dark[i].red, style->dark[i].green, style->dark[i].blue);
+ if (!gdk_color_alloc (colormap, &style->mid[i]))
+ g_warning ("unable to allocate color: ( %d %d %d )",
+ style->mid[i].red, style->mid[i].green, style->mid[i].blue);
+ if (!gdk_color_alloc (colormap, &style->text[i]))
+ g_warning ("unable to allocate color: ( %d %d %d )",
+ style->text[i].red, style->text[i].green, style->text[i].blue);
+ if (!gdk_color_alloc (colormap, &style->base[i]))
+ g_warning ("unable to allocate color: ( %d %d %d )",
+ style->base[i].red, style->base[i].green, style->base[i].blue);
+
+ gc_values.foreground = style->fg[i];
+ style->fg_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
+
+ gc_values.foreground = style->bg[i];
+ style->bg_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
+
+ gc_values.foreground = style->light[i];
+ style->light_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
+
+ gc_values.foreground = style->dark[i];
+ style->dark_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
+
+ gc_values.foreground = style->mid[i];
+ style->mid_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
+
+ gc_values.foreground = style->text[i];
+ style->text_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
+
+ gc_values.foreground = style->base[i];
+ style->base_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
+ }
+ }
+}
+
+static void
+gtk_styles_init ()
+{
+ if (initialize)
+ {
+ initialize = FALSE;
+
+ style_cache = g_cache_new ((GCacheNewFunc) gtk_style_new_from_key,
+ (GCacheDestroyFunc) gtk_style_destroy,
+ (GCacheDupFunc) gtk_style_key_dup,
+ (GCacheDestroyFunc) gtk_style_key_destroy,
+ (GHashFunc) gtk_style_key_hash,
+ (GHashFunc) gtk_style_value_hash,
+ (GCompareFunc) gtk_style_key_compare);
+ }
+}
+
+static void
+gtk_style_remove (GtkStyle *style)
+{
+ if (initialize)
+ gtk_styles_init ();
+
+ g_cache_remove (style_cache, style);
+}
+
+static GtkStyle*
+gtk_style_find (GtkStyle *style,
+ GdkColormap *cmap,
+ gint depth)
+{
+ GtkStyleKey key;
+ gint i;
+
+ if (initialize)
+ gtk_styles_init ();
+
+ for (i = 0; i < 5; i++)
+ {
+ key.fg[i] = style->fg[i];
+ key.bg[i] = style->bg[i];
+ key.text[i] = style->text[i];
+ key.base[i] = style->base[i];
+ key.bg_pixmap[i] = style->bg_pixmap[i];
+ }
+
+ key.font = style->font;
+ key.klass = style->klass;
+ key.depth = depth;
+ key.colormap = cmap;
+
+ style = g_cache_insert (style_cache, &key);
+
+ return style;
+}
+
+static GtkStyle*
+gtk_style_new_from_key (GtkStyleKey *key)
+{
+ GtkStyle *style;
+ GSList *list;
+ gint i;
+
+ style = NULL;
+ list = unattached_styles;
+
+ while (list)
+ {
+ style = list->data;
+ list = list->next;
+
+ if ((style->depth != -1) && (style->depth != key->depth))
+ {
+ style = NULL;
+ continue;
+ }
+ if (style->colormap && (style->colormap != key->colormap))
+ {
+ style = NULL;
+ continue;
+ }
+ if (style->klass != key->klass)
+ {
+ style = NULL;
+ continue;
+ }
+ if (!gdk_font_equal (style->font, key->font))
+ {
+ style = NULL;
+ continue;
+ }
+
+ for (i = 0; style && (i < 5); i++)
+ {
+ if (style->bg_pixmap[i] != key->bg_pixmap[i])
+ {
+ style = NULL;
+ continue;
+ }
+
+ if ((style->fg[i].red != key->fg[i].red) ||
+ (style->fg[i].green != key->fg[i].green) ||
+ (style->fg[i].blue != key->fg[i].blue))
+ {
+ style = NULL;
+ continue;
+ }
+
+ if ((style->bg[i].red != key->bg[i].red) ||
+ (style->bg[i].green != key->bg[i].green) ||
+ (style->bg[i].blue != key->bg[i].blue))
+ {
+ style = NULL;
+ continue;
+ }
+
+ if ((style->text[i].red != key->text[i].red) ||
+ (style->text[i].green != key->text[i].green) ||
+ (style->text[i].blue != key->text[i].blue))
+ {
+ style = NULL;
+ continue;
+ }
+
+ if ((style->base[i].red != key->base[i].red) ||
+ (style->base[i].green != key->base[i].green) ||
+ (style->base[i].blue != key->base[i].blue))
+ {
+ style = NULL;
+ continue;
+ }
+ }
+
+ if (style)
+ break;
+ }
+
+ if (!style)
+ {
+ style = g_new (GtkStyle, 1);
+
+ style->ref_count = 0;
+ style->attach_count = 0;
+
+ style->font = key->font;
+ gdk_font_ref (style->font);
+
+ style->depth = key->depth;
+ style->colormap = key->colormap;
+ style->klass = key->klass;
+
+ style->black.red = 0;
+ style->black.green = 0;
+ style->black.blue = 0;
+
+ style->white.red = 65535;
+ style->white.green = 65535;
+ style->white.blue = 65535;
+
+ style->black_gc = NULL;
+ style->white_gc = NULL;
+
+ for (i = 0; i < 5; i++)
+ {
+ style->fg[i] = key->fg[i];
+ style->bg[i] = key->bg[i];
+ style->text[i] = key->text[i];
+ style->base[i] = key->base[i];
+ }
+
+ for (i = 0; i < 5; i++)
+ style->bg_pixmap[i] = key->bg_pixmap[i];
+
+ for (i = 0; i < 5; i++)
+ {
+ style->fg_gc[i] = NULL;
+ style->bg_gc[i] = NULL;
+ style->light_gc[i] = NULL;
+ style->dark_gc[i] = NULL;
+ style->mid_gc[i] = NULL;
+ style->text_gc[i] = NULL;
+ style->base_gc[i] = NULL;
+ }
+ }
+
+ if (style->depth == -1)
+ style->depth = key->depth;
+ if (!style->colormap)
+ style->colormap = key->colormap;
+
+ gtk_style_init (style);
+
+ return style;
+}
+
+static GtkStyleKey*
+gtk_style_key_dup (GtkStyleKey *key)
+{
+ GtkStyleKey *new_key;
+
+ if (!key_mem_chunk)
+ key_mem_chunk = g_mem_chunk_new ("key mem chunk", sizeof (GtkStyleKey),
+ 1024, G_ALLOC_AND_FREE);
+
+ new_key = g_chunk_new (GtkStyleKey, key_mem_chunk);
+
+ *new_key = *key;
+
+ return new_key;
+}
+
+static void
+gtk_style_destroy (GtkStyle *style)
+{
+ gint i;
+
+ if (style->ref_count != 0)
+ return;
+
+ if (style->attach_count > 0)
+ {
+ gtk_gc_release (style->black_gc);
+ gtk_gc_release (style->white_gc);
+
+ for (i = 0; i < 5; i++)
+ {
+ gtk_gc_release (style->fg_gc[i]);
+ gtk_gc_release (style->bg_gc[i]);
+ gtk_gc_release (style->light_gc[i]);
+ gtk_gc_release (style->dark_gc[i]);
+ gtk_gc_release (style->mid_gc[i]);
+ gtk_gc_release (style->text_gc[i]);
+ gtk_gc_release (style->base_gc[i]);
+ }
+ }
+
+ unattached_styles = g_slist_remove (unattached_styles, style);
+
+ if (style->font->type == GDK_FONT_FONT)
+ gdk_font_free (style->font);
+ else if (style->font->type == GDK_FONT_FONTSET)
+ gdk_fontset_free (style->font);
+ else
+ g_error("undefined font type\n");
+
+ g_free (style);
+}
+
+static void
+gtk_style_key_destroy (GtkStyleKey *key)
+{
+ g_mem_chunk_free (key_mem_chunk, key);
+}
+
+static guint
+gtk_style_key_hash (GtkStyleKey *key)
+{
+ guint hash_val;
+ gint i;
+
+ hash_val = 0;
+
+ for (i = 0; i < 5; i++)
+ {
+ hash_val += key->fg[i].red + key->fg[i].green + key->fg[i].blue;
+ hash_val += key->bg[i].red + key->bg[i].green + key->bg[i].blue;
+ hash_val += key->text[i].red + key->text[i].green + key->text[i].blue;
+ hash_val += key->base[i].red + key->base[i].green + key->base[i].blue;
+ }
+
+ hash_val += (guint) gdk_font_id (key->font);
+ hash_val += (guint) key->depth;
+ hash_val += (gulong) key->colormap;
+ hash_val += (gulong) key->klass;
+
+ return hash_val;
+}
+
+static guint
+gtk_style_value_hash (GtkStyle *style)
+{
+ guint hash_val;
+ gint i;
+
+ hash_val = 0;
+
+ for (i = 0; i < 5; i++)
+ {
+ hash_val += style->fg[i].red + style->fg[i].green + style->fg[i].blue;
+ hash_val += style->bg[i].red + style->bg[i].green + style->bg[i].blue;
+ hash_val += style->text[i].red + style->text[i].green + style->text[i].blue;
+ hash_val += style->base[i].red + style->base[i].green + style->base[i].blue;
+ }
+
+ hash_val += (guint) gdk_font_id (style->font);
+ hash_val += (gulong) style->klass;
+
+ return hash_val;
+}
+
+static gint
+gtk_style_key_compare (GtkStyleKey *a,
+ GtkStyleKey *b)
+{
+ gint i;
+
+ if (a->depth != b->depth)
+ return FALSE;
+ if (a->colormap != b->colormap)
+ return FALSE;
+ if (a->klass != b->klass)
+ return FALSE;
+ if (!gdk_font_equal (a->font, b->font))
+ return FALSE;
+
+ for (i = 0; i < 5; i++)
+ {
+ if (a->bg_pixmap[i] != b->bg_pixmap[i])
+ return FALSE;
+
+ if ((a->fg[i].red != b->fg[i].red) ||
+ (a->fg[i].green != b->fg[i].green) ||
+ (a->fg[i].blue != b->fg[i].blue))
+ return FALSE;
+ if ((a->bg[i].red != b->bg[i].red) ||
+ (a->bg[i].green != b->bg[i].green) ||
+ (a->bg[i].blue != b->bg[i].blue))
+ return FALSE;
+ if ((a->text[i].red != b->text[i].red) ||
+ (a->text[i].green != b->text[i].green) ||
+ (a->text[i].blue != b->text[i].blue))
+ return FALSE;
+ if ((a->base[i].red != b->base[i].red) ||
+ (a->base[i].green != b->base[i].green) ||
+ (a->base[i].blue != b->base[i].blue))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+static void
+gtk_default_draw_hline (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ gint x1,
+ gint x2,
+ gint y)
+{
+ gint thickness_light;
+ gint thickness_dark;
+ gint i;
+
+ g_return_if_fail (style != NULL);
+ g_return_if_fail (window != NULL);
+
+ thickness_light = style->klass->ythickness / 2;
+ thickness_dark = style->klass->ythickness - thickness_light;
+
+ for (i = 0; i < thickness_dark; i++)
+ {
+ gdk_draw_line (window, style->light_gc[state_type], x2 - i - 1, y + i, x2, y + i);
+ gdk_draw_line (window, style->dark_gc[state_type], x1, y + i, x2 - i - 1, y + i);
+ }
+
+ y += thickness_dark;
+ for (i = 0; i < thickness_light; i++)
+ {
+ gdk_draw_line (window, style->dark_gc[state_type], x1, y + i, x1 + thickness_light - i - 1, y + i);
+ gdk_draw_line (window, style->light_gc[state_type], x1 + thickness_light - i - 1, y + i, x2, y + i);
+ }
+}
+
+
+static void
+gtk_default_draw_vline (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ gint y1,
+ gint y2,
+ gint x)
+{
+ gint thickness_light;
+ gint thickness_dark;
+ gint i;
+
+ g_return_if_fail (style != NULL);
+ g_return_if_fail (window != NULL);
+
+ thickness_light = style->klass->xthickness / 2;
+ thickness_dark = style->klass->xthickness - thickness_light;
+
+ for (i = 0; i < thickness_dark; i++)
+ {
+ gdk_draw_line (window, style->light_gc[state_type], x + i, y2 - i - 1, x + i, y2);
+ gdk_draw_line (window, style->dark_gc[state_type], x + i, y1, x + i, y2 - i - 1);
+ }
+
+ x += thickness_dark;
+ for (i = 0; i < thickness_light; i++)
+ {
+ gdk_draw_line (window, style->dark_gc[state_type], x + i, y1, x + i, y1 + thickness_light - i);
+ gdk_draw_line (window, style->light_gc[state_type], x + i, y1 + thickness_light - i, x + i, y2);
+ }
+}
+
+
+static void
+gtk_default_draw_shadow (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ GdkGC *gc1;
+ GdkGC *gc2;
+ gint thickness_light;
+ gint thickness_dark;
+ gint i;
+
+ g_return_if_fail (style != NULL);
+ g_return_if_fail (window != NULL);
+
+ if ((width == -1) && (height == -1))
+ gdk_window_get_size (window, &width, &height);
+ else if (width == -1)
+ gdk_window_get_size (window, &width, NULL);
+ else if (height == -1)
+ gdk_window_get_size (window, NULL, &height);
+
+ switch (shadow_type)
+ {
+ case GTK_SHADOW_NONE:
+ gc1 = NULL;
+ gc2 = NULL;
+ break;
+ case GTK_SHADOW_IN:
+ case GTK_SHADOW_ETCHED_IN:
+ gc1 = style->light_gc[state_type];
+ gc2 = style->dark_gc[state_type];
+ break;
+ case GTK_SHADOW_OUT:
+ case GTK_SHADOW_ETCHED_OUT:
+ gc1 = style->dark_gc[state_type];
+ gc2 = style->light_gc[state_type];
+ break;
+ }
+
+ switch (shadow_type)
+ {
+ case GTK_SHADOW_NONE:
+ break;
+
+ case GTK_SHADOW_IN:
+ gdk_draw_line (window, gc1,
+ x, y + height - 1, x + width - 1, y + height - 1);
+ gdk_draw_line (window, gc1,
+ x + width - 1, y, x + width - 1, y + height - 1);
+
+ gdk_draw_line (window, style->bg_gc[state_type],
+ x + 1, y + height - 2, x + width - 2, y + height - 2);
+ gdk_draw_line (window, style->bg_gc[state_type],
+ x + width - 2, y + 1, x + width - 2, y + height - 2);
+
+ gdk_draw_line (window, style->black_gc,
+ x + 1, y + 1, x + width - 2, y + 1);
+ gdk_draw_line (window, style->black_gc,
+ x + 1, y + 1, x + 1, y + height - 2);
+
+ gdk_draw_line (window, gc2,
+ x, y, x + width - 1, y);
+ gdk_draw_line (window, gc2,
+ x, y, x, y + height - 1);
+ break;
+
+ case GTK_SHADOW_OUT:
+ gdk_draw_line (window, gc1,
+ x + 1, y + height - 2, x + width - 2, y + height - 2);
+ gdk_draw_line (window, gc1,
+ x + width - 2, y + 1, x + width - 2, y + height - 2);
+
+ gdk_draw_line (window, gc2,
+ x, y, x + width - 1, y);
+ gdk_draw_line (window, gc2,
+ x, y, x, y + height - 1);
+
+ gdk_draw_line (window, style->bg_gc[state_type],
+ x + 1, y + 1, x + width - 2, y + 1);
+ gdk_draw_line (window, style->bg_gc[state_type],
+ x + 1, y + 1, x + 1, y + height - 2);
+
+ gdk_draw_line (window, style->black_gc,
+ x, y + height - 1, x + width - 1, y + height - 1);
+ gdk_draw_line (window, style->black_gc,
+ x + width - 1, y, x + width - 1, y + height - 1);
+ break;
+
+ case GTK_SHADOW_ETCHED_IN:
+ case GTK_SHADOW_ETCHED_OUT:
+ thickness_light = 1;
+ thickness_dark = 1;
+
+ for (i = 0; i < thickness_dark; i++)
+ {
+ gdk_draw_line (window, gc1,
+ x + i,
+ y + height - i - 1,
+ x + width - i - 1,
+ y + height - i - 1);
+ gdk_draw_line (window, gc1,
+ x + width - i - 1,
+ y + i,
+ x + width - i - 1,
+ y + height - i - 1);
+
+ gdk_draw_line (window, gc2,
+ x + i,
+ y + i,
+ x + width - i - 2,
+ y + i);
+ gdk_draw_line (window, gc2,
+ x + i,
+ y + i,
+ x + i,
+ y + height - i - 2);
+ }
+
+ for (i = 0; i < thickness_light; i++)
+ {
+ gdk_draw_line (window, gc1,
+ x + thickness_dark + i,
+ y + thickness_dark + i,
+ x + width - thickness_dark - i - 1,
+ y + thickness_dark + i);
+ gdk_draw_line (window, gc1,
+ x + thickness_dark + i,
+ y + thickness_dark + i,
+ x + thickness_dark + i,
+ y + height - thickness_dark - i - 1);
+
+ gdk_draw_line (window, gc2,
+ x + thickness_dark + i,
+ y + height - thickness_light - i - 1,
+ x + width - thickness_light - 1,
+ y + height - thickness_light - i - 1);
+ gdk_draw_line (window, gc2,
+ x + width - thickness_light - i - 1,
+ y + thickness_dark + i,
+ x + width - thickness_light - i - 1,
+ y + height - thickness_light - 1);
+ }
+ break;
+ }
+}
+
+
+static void
+gtk_default_draw_polygon (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ GdkPoint *points,
+ gint npoints,
+ gint fill)
+{
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif /* M_PI */
+#ifndef M_PI_4
+#define M_PI_4 0.78539816339744830962
+#endif /* M_PI_4 */
+
+ static const gdouble pi_over_4 = M_PI_4;
+ static const gdouble pi_3_over_4 = M_PI_4 * 3;
+
+ GdkGC *gc1;
+ GdkGC *gc2;
+ GdkGC *gc3;
+ GdkGC *gc4;
+ gdouble angle;
+ gint xadjust;
+ gint yadjust;
+ gint i;
+
+ g_return_if_fail (style != NULL);
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (points != NULL);
+
+ switch (shadow_type)
+ {
+ case GTK_SHADOW_IN:
+ gc1 = style->bg_gc[state_type];
+ gc2 = style->dark_gc[state_type];
+ gc3 = style->light_gc[state_type];
+ gc4 = style->black_gc;
+ break;
+ case GTK_SHADOW_OUT:
+ gc1 = style->dark_gc[state_type];
+ gc2 = style->light_gc[state_type];
+ gc3 = style->black_gc;
+ gc4 = style->bg_gc[state_type];
+ break;
+ default:
+ return;
+ }
+
+ if (fill)
+ gdk_draw_polygon (window, style->bg_gc[state_type], TRUE, points, npoints);
+
+ npoints -= 1;
+ for (i = 0; i < npoints; i++)
+ {
+ if ((points[i].x == points[i+1].x) &&
+ (points[i].y == points[i+1].y))
+ {
+ angle = 0;
+ }
+ else
+ {
+ angle = atan2 (points[i+1].y - points[i].y,
+ points[i+1].x - points[i].x);
+ }
+
+ if ((angle > -pi_3_over_4) && (angle < pi_over_4))
+ {
+ while (angle < 0)
+ angle += M_PI;
+ while (angle > M_PI)
+ angle -= M_PI;
+
+ if ((angle > pi_3_over_4) || (angle < pi_over_4))
+ {
+ xadjust = 0;
+ yadjust = 1;
+ }
+ else
+ {
+ xadjust = 1;
+ yadjust = 0;
+ }
+
+ gdk_draw_line (window, gc1,
+ points[i].x-xadjust, points[i].y-yadjust,
+ points[i+1].x-xadjust, points[i+1].y-yadjust);
+ gdk_draw_line (window, gc3,
+ points[i].x, points[i].y,
+ points[i+1].x, points[i+1].y);
+ }
+ }
+
+ for (i = 0; i < npoints; i++)
+ {
+ if ((points[i].x == points[i+1].x) &&
+ (points[i].y == points[i+1].y))
+ {
+ angle = 0;
+ }
+ else
+ {
+ angle = atan2 (points[i+1].y - points[i].y,
+ points[i+1].x - points[i].x);
+ }
+
+ if ((angle <= -pi_3_over_4) || (angle >= pi_over_4))
+ {
+ while (angle < 0)
+ angle += M_PI;
+ while (angle > M_PI)
+ angle -= M_PI;
+
+ if ((angle > pi_3_over_4) || (angle < pi_over_4))
+ {
+ xadjust = 0;
+ yadjust = 1;
+ }
+ else
+ {
+ xadjust = 1;
+ yadjust = 0;
+ }
+
+ gdk_draw_line (window, gc4,
+ points[i].x+xadjust, points[i].y+yadjust,
+ points[i+1].x+xadjust, points[i+1].y+yadjust);
+ gdk_draw_line (window, gc2,
+ points[i].x, points[i].y,
+ points[i+1].x, points[i+1].y);
+ }
+ }
+}
+
+
+static void
+gtk_default_draw_arrow (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ GtkArrowType arrow_type,
+ gint fill,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ GdkGC *gc1;
+ GdkGC *gc2;
+ GdkGC *gc3;
+ GdkGC *gc4;
+ gint half_width;
+ gint half_height;
+ GdkPoint points[3];
+
+ g_return_if_fail (style != NULL);
+ g_return_if_fail (window != NULL);
+
+ switch (shadow_type)
+ {
+ case GTK_SHADOW_IN:
+ gc1 = style->bg_gc[state_type];
+ gc2 = style->dark_gc[state_type];
+ gc3 = style->light_gc[state_type];
+ gc4 = style->black_gc;
+ break;
+ case GTK_SHADOW_OUT:
+ gc1 = style->dark_gc[state_type];
+ gc2 = style->light_gc[state_type];
+ gc3 = style->black_gc;
+ gc4 = style->bg_gc[state_type];
+ break;
+ default:
+ return;
+ }
+
+ if ((width == -1) && (height == -1))
+ gdk_window_get_size (window, &width, &height);
+ else if (width == -1)
+ gdk_window_get_size (window, &width, NULL);
+ else if (height == -1)
+ gdk_window_get_size (window, NULL, &height);
+
+ half_width = width / 2;
+ half_height = height / 2;
+
+ switch (arrow_type)
+ {
+ case GTK_ARROW_UP:
+ if (fill)
+ {
+ points[0].x = x + half_width;
+ points[0].y = y;
+ points[1].x = x;
+ points[1].y = y + height - 1;
+ points[2].x = x + width - 1;
+ points[2].y = y + height - 1;
+
+ gdk_draw_polygon (window, style->bg_gc[state_type], TRUE, points, 3);
+ }
+
+ gdk_draw_line (window, gc1,
+ x + 1, y + height - 2,
+ x + width - 2, y + height - 2);
+ gdk_draw_line (window, gc3,
+ x + 0, y + height - 1,
+ x + width - 1, y + height - 1);
+
+ gdk_draw_line (window, gc1,
+ x + width - 2, y + height - 1,
+ x + half_width, y + 1);
+ gdk_draw_line (window, gc3,
+ x + width - 1, y + height - 1,
+ x + half_width, y);
+
+ gdk_draw_line (window, gc4,
+ x + half_width, y + 1,
+ x + 1, y + height - 1);
+ gdk_draw_line (window, gc2,
+ x + half_width, y,
+ x, y + height - 1);
+ break;
+ case GTK_ARROW_DOWN:
+ if (fill)
+ {
+ points[0].x = x + width - 1;
+ points[0].y = y;
+ points[1].x = x;
+ points[1].y = y;
+ points[2].x = x + half_width;
+ points[2].y = y + height - 1;
+
+ gdk_draw_polygon (window, style->bg_gc[state_type], TRUE, points, 3);
+ }
+
+ gdk_draw_line (window, gc4,
+ x + width - 2,
+ y + 1, x + 1, y + 1);
+ gdk_draw_line (window, gc2,
+ x + width - 1, y,
+ x, y);
+
+ gdk_draw_line (window, gc4,
+ x + 1, y,
+ x + half_width, y + height - 2);
+ gdk_draw_line (window, gc2,
+ x, y,
+ x + half_width, y + height - 1);
+
+ gdk_draw_line (window, gc1,
+ x + half_width, y + height - 2,
+ x + width - 2, y);
+ gdk_draw_line (window, gc3,
+ x + half_width, y + height - 1,
+ x + width - 1, y);
+ break;
+ case GTK_ARROW_LEFT:
+ if (fill)
+ {
+ points[0].x = x;
+ points[0].y = y + half_height;
+ points[1].x = x + width - 1;
+ points[1].y = y + height - 1;
+ points[2].x = x + width - 1;
+ points[2].y = y;
+
+ gdk_draw_polygon (window, style->bg_gc[state_type], TRUE, points, 3);
+ }
+
+ gdk_draw_line (window, gc1,
+ x + 1, y + half_height,
+ x + width - 1, y + height - 1);
+ gdk_draw_line (window, gc3,
+ x, y + half_height,
+ x + width - 1, y + height - 1);
+
+ gdk_draw_line (window, gc1,
+ x + width - 2, y + height - 1,
+ x + width - 2, y + 1);
+ gdk_draw_line (window, gc3,
+ x + width - 1, y + height - 1,
+ x + width - 1, y);
+
+ gdk_draw_line (window, gc4,
+ x + width - 1, y + 1,
+ x + 1, y + half_width);
+ gdk_draw_line (window, gc2,
+ x + width - 1, y,
+ x, y + half_width);
+ break;
+ case GTK_ARROW_RIGHT:
+ if (fill)
+ {
+ points[0].x = x + width - 1;
+ points[0].y = y + half_height;
+ points[1].x = x;
+ points[1].y = y;
+ points[2].x = x;
+ points[2].y = y + height - 1;
+
+ gdk_draw_polygon (window, style->bg_gc[state_type], TRUE, points, 3);
+ }
+
+ gdk_draw_line (window, gc4,
+ x + width - 1, y + half_height,
+ x + 1, y + 1);
+ gdk_draw_line (window, gc2,
+ x + width - 1, y + half_height,
+ x, y);
+
+ gdk_draw_line (window, gc4,
+ x + 1, y + 1,
+ x + 1, y + height - 2);
+ gdk_draw_line (window, gc2,
+ x, y,
+ x, y + height - 1);
+
+ gdk_draw_line (window, gc1,
+ x + 1, y + height - 2,
+ x + width - 1, y + half_height);
+ gdk_draw_line (window, gc3,
+ x, y + height - 1,
+ x + width - 1, y + half_height);
+ break;
+ }
+}
+
+
+static void
+gtk_default_draw_diamond (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ gint half_width;
+ gint half_height;
+
+ g_return_if_fail (style != NULL);
+ g_return_if_fail (window != NULL);
+
+ if ((width == -1) && (height == -1))
+ gdk_window_get_size (window, &width, &height);
+ else if (width == -1)
+ gdk_window_get_size (window, &width, NULL);
+ else if (height == -1)
+ gdk_window_get_size (window, NULL, &height);
+
+ half_width = width / 2;
+ half_height = height / 2;
+
+ switch (shadow_type)
+ {
+ case GTK_SHADOW_IN:
+ gdk_draw_line (window, style->bg_gc[state_type],
+ x + 2, y + half_height,
+ x + half_width, y + height - 2);
+ gdk_draw_line (window, style->bg_gc[state_type],
+ x + half_width, y + height - 2,
+ x + width - 2, y + half_height);
+ gdk_draw_line (window, style->light_gc[state_type],
+ x + 1, y + half_height,
+ x + half_width, y + height - 1);
+ gdk_draw_line (window, style->light_gc[state_type],
+ x + half_width, y + height - 1,
+ x + width - 1, y + half_height);
+ gdk_draw_line (window, style->light_gc[state_type],
+ x, y + half_height,
+ x + half_width, y + height);
+ gdk_draw_line (window, style->light_gc[state_type],
+ x + half_width, y + height,
+ x + width, y + half_height);
+
+ gdk_draw_line (window, style->black_gc,
+ x + 2, y + half_height,
+ x + half_width, y + 2);
+ gdk_draw_line (window, style->black_gc,
+ x + half_width, y + 2,
+ x + width - 2, y + half_height);
+ gdk_draw_line (window, style->dark_gc[state_type],
+ x + 1, y + half_height,
+ x + half_width, y + 1);
+ gdk_draw_line (window, style->dark_gc[state_type],
+ x + half_width, y + 1,
+ x + width - 1, y + half_height);
+ gdk_draw_line (window, style->dark_gc[state_type],
+ x, y + half_height,
+ x + half_width, y);
+ gdk_draw_line (window, style->dark_gc[state_type],
+ x + half_width, y,
+ x + width, y + half_height);
+ break;
+ case GTK_SHADOW_OUT:
+ gdk_draw_line (window, style->dark_gc[state_type],
+ x + 2, y + half_height,
+ x + half_width, y + height - 2);
+ gdk_draw_line (window, style->dark_gc[state_type],
+ x + half_width, y + height - 2,
+ x + width - 2, y + half_height);
+ gdk_draw_line (window, style->dark_gc[state_type],
+ x + 1, y + half_height,
+ x + half_width, y + height - 1);
+ gdk_draw_line (window, style->dark_gc[state_type],
+ x + half_width, y + height - 1,
+ x + width - 1, y + half_height);
+ gdk_draw_line (window, style->black_gc,
+ x, y + half_height,
+ x + half_width, y + height);
+ gdk_draw_line (window, style->black_gc,
+ x + half_width, y + height,
+ x + width, y + half_height);
+
+ gdk_draw_line (window, style->bg_gc[state_type],
+ x + 2, y + half_height,
+ x + half_width, y + 2);
+ gdk_draw_line (window, style->bg_gc[state_type],
+ x + half_width, y + 2,
+ x + width - 2, y + half_height);
+ gdk_draw_line (window, style->light_gc[state_type],
+ x + 1, y + half_height,
+ x + half_width, y + 1);
+ gdk_draw_line (window, style->light_gc[state_type],
+ x + half_width, y + 1,
+ x + width - 1, y + half_height);
+ gdk_draw_line (window, style->light_gc[state_type],
+ x, y + half_height,
+ x + half_width, y);
+ gdk_draw_line (window, style->light_gc[state_type],
+ x + half_width, y,
+ x + width, y + half_height);
+ break;
+ default:
+ break;
+ }
+}
+
+
+static void
+gtk_default_draw_oval (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ g_return_if_fail (style != NULL);
+ g_return_if_fail (window != NULL);
+}
+
+static void
+gtk_default_draw_string (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ gint x,
+ gint y,
+ const gchar *string)
+{
+ g_return_if_fail (style != NULL);
+ g_return_if_fail (window != NULL);
+
+ if (state_type == GTK_STATE_INSENSITIVE)
+ gdk_draw_string (window, style->font, style->white_gc, x + 1, y + 1, string);
+ gdk_draw_string (window, style->font, style->fg_gc[state_type], x, y, string);
+}
+
+
+static void
+gtk_style_shade (GdkColor *a,
+ GdkColor *b,
+ gdouble k)
+{
+ gdouble red;
+ gdouble green;
+ gdouble blue;
+
+ red = (gdouble) a->red / 65535.0;
+ green = (gdouble) a->green / 65535.0;
+ blue = (gdouble) a->blue / 65535.0;
+
+ rgb_to_hls (&red, &green, &blue);
+
+ green *= k;
+ if (green > 1.0)
+ green = 1.0;
+ else if (green < 0.0)
+ green = 0.0;
+
+ blue *= k;
+ if (blue > 1.0)
+ blue = 1.0;
+ else if (blue < 0.0)
+ blue = 0.0;
+
+ hls_to_rgb (&red, &green, &blue);
+
+ b->red = red * 65535.0;
+ b->green = green * 65535.0;
+ b->blue = blue * 65535.0;
+}
+
+static void
+rgb_to_hls (gdouble *r,
+ gdouble *g,
+ gdouble *b)
+{
+ gdouble min;
+ gdouble max;
+ gdouble red;
+ gdouble green;
+ gdouble blue;
+ gdouble h, l, s;
+ gdouble delta;
+
+ red = *r;
+ green = *g;
+ blue = *b;
+
+ if (red > green)
+ {
+ if (red > blue)
+ max = red;
+ else
+ max = blue;
+
+ if (green < blue)
+ min = green;
+ else
+ min = blue;
+ }
+ else
+ {
+ if (green > blue)
+ max = green;
+ else
+ max = blue;
+
+ if (red < blue)
+ min = red;
+ else
+ min = blue;
+ }
+
+ l = (max + min) / 2;
+ s = 0;
+ h = 0;
+
+ if (max != min)
+ {
+ if (l <= 0.5)
+ s = (max - min) / (max + min);
+ else
+ s = (max - min) / (2 - max - min);
+
+ delta = max -min;
+ if (red == max)
+ h = (green - blue) / delta;
+ else if (green == max)
+ h = 2 + (blue - red) / delta;
+ else if (blue == max)
+ h = 4 + (red - green) / delta;
+
+ h *= 60;
+ if (h < 0.0)
+ h += 360;
+ }
+
+ *r = h;
+ *g = l;
+ *b = s;
+}
+
+static void
+hls_to_rgb (gdouble *h,
+ gdouble *l,
+ gdouble *s)
+{
+ gdouble hue;
+ gdouble lightness;
+ gdouble saturation;
+ gdouble m1, m2;
+ gdouble r, g, b;
+
+ lightness = *l;
+ saturation = *s;
+
+ if (lightness <= 0.5)
+ m2 = lightness * (1 + saturation);
+ else
+ m2 = lightness + saturation - lightness * saturation;
+ m1 = 2 * lightness - m2;
+
+ if (saturation == 0)
+ {
+ *h = lightness;
+ *l = lightness;
+ *s = lightness;
+ }
+ else
+ {
+ hue = *h + 120;
+ while (hue > 360)
+ hue -= 360;
+ while (hue < 0)
+ hue += 360;
+
+ if (hue < 60)
+ r = m1 + (m2 - m1) * hue / 60;
+ else if (hue < 180)
+ r = m2;
+ else if (hue < 240)
+ r = m1 + (m2 - m1) * (240 - hue) / 60;
+ else
+ r = m1;
+
+ hue = *h;
+ while (hue > 360)
+ hue -= 360;
+ while (hue < 0)
+ hue += 360;
+
+ if (hue < 60)
+ g = m1 + (m2 - m1) * hue / 60;
+ else if (hue < 180)
+ g = m2;
+ else if (hue < 240)
+ g = m1 + (m2 - m1) * (240 - hue) / 60;
+ else
+ g = m1;
+
+ hue = *h - 120;
+ while (hue > 360)
+ hue -= 360;
+ while (hue < 0)
+ hue += 360;
+
+ if (hue < 60)
+ b = m1 + (m2 - m1) * hue / 60;
+ else if (hue < 180)
+ b = m2;
+ else if (hue < 240)
+ b = m1 + (m2 - m1) * (240 - hue) / 60;
+ else
+ b = m1;
+
+ *h = r;
+ *l = g;
+ *s = b;
+ }
+}
diff --git a/gtk/gtkstyle.h b/gtk/gtkstyle.h
new file mode 100644
index 000000000..c0ec33736
--- /dev/null
+++ b/gtk/gtkstyle.h
@@ -0,0 +1,217 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_STYLE_H__
+#define __GTK_STYLE_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkenums.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+typedef struct _GtkStyle GtkStyle;
+typedef struct _GtkStyleClass GtkStyleClass;
+
+/* This is used for having dynamic style changing stuff */
+/* fg, bg, light, dark, mid, text, base */
+#define GTK_STYLE_NUM_STYLECOLORS() 7*5
+
+struct _GtkStyle
+{
+ GdkColor fg[5];
+ GdkColor bg[5];
+ GdkColor light[5];
+ GdkColor dark[5];
+ GdkColor mid[5];
+ GdkColor text[5];
+ GdkColor base[5];
+
+ GdkColor black;
+ GdkColor white;
+ GdkFont *font;
+
+ GdkGC *fg_gc[5];
+ GdkGC *bg_gc[5];
+ GdkGC *light_gc[5];
+ GdkGC *dark_gc[5];
+ GdkGC *mid_gc[5];
+ GdkGC *text_gc[5];
+ GdkGC *base_gc[5];
+ GdkGC *black_gc;
+ GdkGC *white_gc;
+
+ GdkPixmap *bg_pixmap[5];
+
+ gint ref_count;
+ gint attach_count;
+
+ gint depth;
+ GdkColormap *colormap;
+
+ GtkStyleClass *klass;
+};
+
+struct _GtkStyleClass
+{
+ gint xthickness;
+ gint ythickness;
+
+ void (*draw_hline) (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ gint x1,
+ gint x2,
+ gint y);
+ void (*draw_vline) (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ gint y1,
+ gint y2,
+ gint x);
+ void (*draw_shadow) (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
+ void (*draw_polygon) (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ GdkPoint *point,
+ gint npoints,
+ gint fill);
+ void (*draw_arrow) (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ GtkArrowType arrow_type,
+ gint fill,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
+ void (*draw_diamond) (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
+ void (*draw_oval) (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
+ void (*draw_string) (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ gint x,
+ gint y,
+ const gchar *string);
+};
+
+
+GtkStyle* gtk_style_new (void);
+GtkStyle* gtk_style_attach (GtkStyle *style,
+ GdkWindow *window);
+void gtk_style_detach (GtkStyle *style);
+GtkStyle *gtk_style_ref (GtkStyle *style);
+void gtk_style_unref (GtkStyle *style);
+void gtk_style_set_background (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type);
+
+
+void gtk_draw_hline (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ gint x1,
+ gint x2,
+ gint y);
+void gtk_draw_vline (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ gint y1,
+ gint y2,
+ gint x);
+void gtk_draw_shadow (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
+void gtk_draw_polygon (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ GdkPoint *points,
+ gint npoints,
+ gint fill);
+void gtk_draw_arrow (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ GtkArrowType arrow_type,
+ gint fill,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
+void gtk_draw_diamond (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
+void gtk_draw_oval (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
+void gtk_draw_string (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ gint x,
+ gint y,
+ const gchar *string);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_STYLE_H__ */
diff --git a/gtk/gtktable.c b/gtk/gtktable.c
new file mode 100644
index 000000000..7711524de
--- /dev/null
+++ b/gtk/gtktable.c
@@ -0,0 +1,1178 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtktable.h"
+
+
+static void gtk_table_class_init (GtkTableClass *klass);
+static void gtk_table_init (GtkTable *table);
+static void gtk_table_destroy (GtkObject *object);
+static void gtk_table_map (GtkWidget *widget);
+static void gtk_table_unmap (GtkWidget *widget);
+static void gtk_table_draw (GtkWidget *widget,
+ GdkRectangle *area);
+static gint gtk_table_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+static void gtk_table_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void gtk_table_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static void gtk_table_add (GtkContainer *container,
+ GtkWidget *widget);
+static void gtk_table_remove (GtkContainer *container,
+ GtkWidget *widget);
+static void gtk_table_foreach (GtkContainer *container,
+ GtkCallback callback,
+ gpointer callback_data);
+
+static void gtk_table_size_request_init (GtkTable *table);
+static void gtk_table_size_request_pass1 (GtkTable *table);
+static void gtk_table_size_request_pass2 (GtkTable *table);
+static void gtk_table_size_request_pass3 (GtkTable *table);
+
+static void gtk_table_size_allocate_init (GtkTable *table);
+static void gtk_table_size_allocate_pass1 (GtkTable *table);
+static void gtk_table_size_allocate_pass2 (GtkTable *table);
+
+
+static GtkContainerClass *parent_class = NULL;
+
+
+guint
+gtk_table_get_type ()
+{
+ static guint table_type = 0;
+
+ if (!table_type)
+ {
+ GtkTypeInfo table_info =
+ {
+ "GtkTable",
+ sizeof (GtkTable),
+ sizeof (GtkTableClass),
+ (GtkClassInitFunc) gtk_table_class_init,
+ (GtkObjectInitFunc) gtk_table_init,
+ (GtkArgFunc) NULL,
+ };
+
+ table_type = gtk_type_unique (gtk_container_get_type (), &table_info);
+ }
+
+ return table_type;
+}
+
+static void
+gtk_table_class_init (GtkTableClass *class)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+ GtkContainerClass *container_class;
+
+ object_class = (GtkObjectClass*) class;
+ widget_class = (GtkWidgetClass*) class;
+ container_class = (GtkContainerClass*) class;
+
+ parent_class = gtk_type_class (gtk_container_get_type ());
+
+ object_class->destroy = gtk_table_destroy;
+
+ widget_class->map = gtk_table_map;
+ widget_class->unmap = gtk_table_unmap;
+ widget_class->draw = gtk_table_draw;
+ widget_class->expose_event = gtk_table_expose;
+ widget_class->size_request = gtk_table_size_request;
+ widget_class->size_allocate = gtk_table_size_allocate;
+
+ container_class->add = gtk_table_add;
+ container_class->remove = gtk_table_remove;
+ container_class->foreach = gtk_table_foreach;
+}
+
+static void
+gtk_table_init (GtkTable *table)
+{
+ GTK_WIDGET_SET_FLAGS (table, GTK_NO_WINDOW | GTK_BASIC);
+
+ table->children = NULL;
+ table->rows = NULL;
+ table->cols = NULL;
+ table->nrows = 0;
+ table->ncols = 0;
+ table->homogeneous = FALSE;
+}
+
+GtkWidget*
+gtk_table_new (gint rows,
+ gint columns,
+ gint homogeneous)
+{
+ GtkTable *table;
+ gint row, col;
+
+ table = gtk_type_new (gtk_table_get_type ());
+
+ table->nrows = rows;
+ table->ncols = columns;
+ table->homogeneous = (homogeneous ? TRUE : FALSE);
+
+ table->rows = g_new (GtkTableRowCol, table->nrows);
+ table->cols = g_new (GtkTableRowCol, table->ncols);
+
+ for (row = 0; row < table->nrows; row++)
+ {
+ table->rows[row].requisition = 0;
+ table->rows[row].allocation = 0;
+ table->rows[row].spacing = 0;
+ table->rows[row].need_expand = 0;
+ table->rows[row].need_shrink = 0;
+ table->rows[row].expand = 0;
+ table->rows[row].shrink = 0;
+ }
+
+ for (col = 0; col < table->ncols; col++)
+ {
+ table->cols[col].requisition = 0;
+ table->cols[col].allocation = 0;
+ table->cols[col].spacing = 0;
+ table->cols[col].need_expand = 0;
+ table->cols[col].need_shrink = 0;
+ table->cols[col].expand = 0;
+ table->cols[col].shrink = 0;
+ }
+
+ return GTK_WIDGET (table);
+}
+
+void
+gtk_table_attach (GtkTable *table,
+ GtkWidget *child,
+ gint left_attach,
+ gint right_attach,
+ gint top_attach,
+ gint bottom_attach,
+ gint xoptions,
+ gint yoptions,
+ gint xpadding,
+ gint ypadding)
+{
+ GtkTableChild *table_child;
+
+ g_return_if_fail (table != NULL);
+ g_return_if_fail (GTK_IS_TABLE (table));
+ g_return_if_fail (child != NULL);
+
+ g_return_if_fail ((left_attach >= 0) && (left_attach < table->ncols));
+ g_return_if_fail ((left_attach < right_attach) && (right_attach <= table->ncols));
+ g_return_if_fail ((top_attach >= 0) && (top_attach < table->nrows));
+ g_return_if_fail ((top_attach < bottom_attach) && (bottom_attach <= table->nrows));
+
+ table_child = g_new (GtkTableChild, 1);
+ table_child->widget = child;
+ table_child->left_attach = left_attach;
+ table_child->right_attach = right_attach;
+ table_child->top_attach = top_attach;
+ table_child->bottom_attach = bottom_attach;
+ table_child->xexpand = (xoptions & GTK_EXPAND) != 0;
+ table_child->xshrink = (xoptions & GTK_SHRINK) != 0;
+ table_child->xfill = (xoptions & GTK_FILL) != 0;
+ table_child->xpadding = xpadding;
+ table_child->yexpand = (yoptions & GTK_EXPAND) != 0;
+ table_child->yshrink = (yoptions & GTK_SHRINK) != 0;
+ table_child->yfill = (yoptions & GTK_FILL) != 0;
+ table_child->ypadding = ypadding;
+
+ table->children = g_list_prepend (table->children, table_child);
+
+ gtk_widget_set_parent (child, GTK_WIDGET (table));
+
+ if (GTK_WIDGET_VISIBLE (GTK_WIDGET (table)))
+ {
+ if (GTK_WIDGET_REALIZED (GTK_WIDGET (table)) &&
+ !GTK_WIDGET_REALIZED (child))
+ gtk_widget_realize (child);
+
+ if (GTK_WIDGET_MAPPED (GTK_WIDGET (table)) &&
+ !GTK_WIDGET_MAPPED (child))
+ gtk_widget_map (child);
+ }
+
+ if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (table))
+ gtk_widget_queue_resize (child);
+}
+
+void
+gtk_table_attach_defaults (GtkTable *table,
+ GtkWidget *widget,
+ gint left_attach,
+ gint right_attach,
+ gint top_attach,
+ gint bottom_attach)
+{
+ gtk_table_attach (table, widget,
+ left_attach, right_attach,
+ top_attach, bottom_attach,
+ GTK_EXPAND | GTK_FILL,
+ GTK_EXPAND | GTK_FILL,
+ 0, 0);
+}
+
+void
+gtk_table_set_row_spacing (GtkTable *table,
+ gint row,
+ gint spacing)
+{
+ g_return_if_fail (table != NULL);
+ g_return_if_fail (GTK_IS_TABLE (table));
+ g_return_if_fail ((row >= 0) && (row < (table->nrows - 1)));
+
+ if (table->rows[row].spacing != spacing)
+ {
+ table->rows[row].spacing = spacing;
+
+ if (GTK_WIDGET_VISIBLE (table))
+ gtk_widget_queue_resize (GTK_WIDGET (table));
+ }
+}
+
+void
+gtk_table_set_col_spacing (GtkTable *table,
+ gint column,
+ gint spacing)
+{
+ g_return_if_fail (table != NULL);
+ g_return_if_fail (GTK_IS_TABLE (table));
+ g_return_if_fail ((column >= 0) && (column < (table->ncols - 1)));
+
+ if (table->cols[column].spacing != spacing)
+ {
+ table->cols[column].spacing = spacing;
+
+ if (GTK_WIDGET_VISIBLE (table))
+ gtk_widget_queue_resize (GTK_WIDGET (table));
+ }
+}
+
+void
+gtk_table_set_row_spacings (GtkTable *table,
+ gint spacing)
+{
+ gint row;
+
+ g_return_if_fail (table != NULL);
+ g_return_if_fail (GTK_IS_TABLE (table));
+
+ for (row = 0; row < table->nrows - 1; row++)
+ table->rows[row].spacing = spacing;
+
+ if (GTK_WIDGET_VISIBLE (table))
+ gtk_widget_queue_resize (GTK_WIDGET (table));
+}
+
+void
+gtk_table_set_col_spacings (GtkTable *table,
+ gint spacing)
+{
+ gint col;
+
+ g_return_if_fail (table != NULL);
+ g_return_if_fail (GTK_IS_TABLE (table));
+
+ for (col = 0; col < table->ncols - 1; col++)
+ table->cols[col].spacing = spacing;
+
+ if (GTK_WIDGET_VISIBLE (table))
+ gtk_widget_queue_resize (GTK_WIDGET (table));
+}
+
+
+static void
+gtk_table_destroy (GtkObject *object)
+{
+ GtkTable *table;
+ GtkTableChild *child;
+ GList *children;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_TABLE (object));
+
+ table = GTK_TABLE (object);
+
+ children = table->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ child->widget->parent = NULL;
+ gtk_object_unref (GTK_OBJECT (child->widget));
+ gtk_widget_destroy (child->widget);
+ g_free (child);
+ }
+
+ g_list_free (table->children);
+ g_free (table->rows);
+ g_free (table->cols);
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+static void
+gtk_table_map (GtkWidget *widget)
+{
+ GtkTable *table;
+ GtkTableChild *child;
+ GList *children;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_TABLE (widget));
+
+ table = GTK_TABLE (widget);
+ GTK_WIDGET_SET_FLAGS (table, GTK_MAPPED);
+
+ children = table->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_VISIBLE (child->widget) &&
+ !GTK_WIDGET_MAPPED (child->widget))
+ gtk_widget_map (child->widget);
+ }
+}
+
+static void
+gtk_table_unmap (GtkWidget *widget)
+{
+ GtkTable *table;
+ GtkTableChild *child;
+ GList *children;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_TABLE (widget));
+
+ table = GTK_TABLE (widget);
+ GTK_WIDGET_UNSET_FLAGS (table, GTK_MAPPED);
+
+ children = table->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_VISIBLE (child->widget) &&
+ GTK_WIDGET_MAPPED (child->widget))
+ gtk_widget_unmap (child->widget);
+ }
+}
+
+static void
+gtk_table_draw (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ GtkTable *table;
+ GtkTableChild *child;
+ GList *children;
+ GdkRectangle child_area;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_TABLE (widget));
+
+ if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget))
+ {
+ table = GTK_TABLE (widget);
+
+ children = table->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (gtk_widget_intersect (child->widget, area, &child_area))
+ gtk_widget_draw (child->widget, &child_area);
+ }
+ }
+}
+
+static gint
+gtk_table_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ GtkTable *table;
+ GtkTableChild *child;
+ GList *children;
+ GdkEventExpose child_event;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_TABLE (widget), FALSE);
+
+ if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget))
+ {
+ table = GTK_TABLE (widget);
+
+ child_event = *event;
+
+ children = table->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_NO_WINDOW (child->widget) &&
+ gtk_widget_intersect (child->widget, &event->area, &child_event.area))
+ gtk_widget_event (child->widget, (GdkEvent*) &child_event);
+ }
+ }
+
+ return FALSE;
+}
+
+static void
+gtk_table_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkTable *table;
+ gint row, col;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_TABLE (widget));
+ g_return_if_fail (requisition != NULL);
+
+ table = GTK_TABLE (widget);
+
+ requisition->width = 0;
+ requisition->height = 0;
+
+ gtk_table_size_request_init (table);
+ gtk_table_size_request_pass1 (table);
+ gtk_table_size_request_pass2 (table);
+ gtk_table_size_request_pass3 (table);
+ gtk_table_size_request_pass2 (table);
+
+ for (col = 0; col < table->ncols; col++)
+ requisition->width += table->cols[col].requisition;
+ for (col = 0; col < table->ncols - 1; col++)
+ requisition->width += table->cols[col].spacing;
+
+ for (row = 0; row < table->nrows; row++)
+ requisition->height += table->rows[row].requisition;
+ for (row = 0; row < table->nrows - 1; row++)
+ requisition->height += table->rows[row].spacing;
+
+ requisition->width += GTK_CONTAINER (table)->border_width * 2;
+ requisition->height += GTK_CONTAINER (table)->border_width * 2;
+}
+
+static void
+gtk_table_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkTable *table;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_TABLE (widget));
+ g_return_if_fail (allocation != NULL);
+
+ widget->allocation = *allocation;
+ table = GTK_TABLE (widget);
+
+ gtk_table_size_allocate_init (table);
+ gtk_table_size_allocate_pass1 (table);
+ gtk_table_size_allocate_pass2 (table);
+}
+
+static void
+gtk_table_add (GtkContainer *container,
+ GtkWidget *widget)
+{
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_TABLE (container));
+ g_return_if_fail (widget != NULL);
+
+ gtk_table_attach_defaults (GTK_TABLE (container), widget, 0, 1, 0, 1);
+}
+
+static void
+gtk_table_remove (GtkContainer *container,
+ GtkWidget *widget)
+{
+ GtkTable *table;
+ GtkTableChild *child;
+ GList *children;
+
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_TABLE (container));
+ g_return_if_fail (widget != NULL);
+
+ table = GTK_TABLE (container);
+ children = table->children;
+
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (child->widget == widget)
+ {
+ gtk_widget_unparent (widget);
+
+ table->children = g_list_remove (table->children, child);
+ g_free (child);
+
+ if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (container))
+ gtk_widget_queue_resize (GTK_WIDGET (container));
+ break;
+ }
+ }
+}
+
+static void
+gtk_table_foreach (GtkContainer *container,
+ GtkCallback callback,
+ gpointer callback_data)
+{
+ GtkTable *table;
+ GtkTableChild *child;
+ GList *children;
+
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_TABLE (container));
+ g_return_if_fail (callback != NULL);
+
+ table = GTK_TABLE (container);
+ children = table->children;
+
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ (* callback) (child->widget, callback_data);
+ }
+}
+
+static void
+gtk_table_size_request_init (GtkTable *table)
+{
+ GtkTableChild *child;
+ GList *children;
+ gint row, col;
+
+ for (row = 0; row < table->nrows; row++)
+ table->rows[row].requisition = 0;
+ for (col = 0; col < table->ncols; col++)
+ table->cols[col].requisition = 0;
+
+ children = table->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_VISIBLE (child->widget))
+ gtk_widget_size_request (child->widget, &child->widget->requisition);
+ }
+}
+
+static void
+gtk_table_size_request_pass1 (GtkTable *table)
+{
+ GtkTableChild *child;
+ GList *children;
+ gint width;
+ gint height;
+
+ children = table->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_VISIBLE (child->widget))
+ {
+ /* Child spans a single column.
+ */
+ if (child->left_attach == (child->right_attach - 1))
+ {
+ width = child->widget->requisition.width + child->xpadding * 2;
+ table->cols[child->left_attach].requisition = MAX (table->cols[child->left_attach].requisition, width);
+ }
+
+ /* Child spans a single row.
+ */
+ if (child->top_attach == (child->bottom_attach - 1))
+ {
+ height = child->widget->requisition.height + child->ypadding * 2;
+ table->rows[child->top_attach].requisition = MAX (table->rows[child->top_attach].requisition, height);
+ }
+ }
+ }
+}
+
+static void
+gtk_table_size_request_pass2 (GtkTable *table)
+{
+ gint max_width;
+ gint max_height;
+ gint row, col;
+
+ if (table->homogeneous)
+ {
+ max_width = 0;
+ max_height = 0;
+
+ for (col = 0; col < table->ncols; col++)
+ max_width = MAX (max_width, table->cols[col].requisition);
+ for (row = 0; row < table->nrows; row++)
+ max_height = MAX (max_height, table->rows[row].requisition);
+
+ for (col = 0; col < table->ncols; col++)
+ table->cols[col].requisition = max_width;
+ for (row = 0; row < table->nrows; row++)
+ table->rows[row].requisition = max_height;
+ }
+}
+
+static void
+gtk_table_size_request_pass3 (GtkTable *table)
+{
+ GtkTableChild *child;
+ GList *children;
+ gint width, height;
+ gint row, col;
+ gint extra;
+
+ children = table->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_VISIBLE (child->widget))
+ {
+ /* Child spans multiple columns.
+ */
+ if (child->left_attach != (child->right_attach - 1))
+ {
+ /* Check and see if there is already enough space
+ * for the child.
+ */
+ width = 0;
+ for (col = child->left_attach; col < child->right_attach; col++)
+ {
+ width += table->cols[col].requisition;
+ if ((col + 1) < child->right_attach)
+ width += table->cols[col].spacing;
+ }
+
+ /* If we need to request more space for this child to fill
+ * its requisition, then divide up the needed space evenly
+ * amongst the columns it spans.
+ */
+ if (width < child->widget->requisition.width)
+ {
+ width = child->widget->requisition.width - width;
+ extra = width / (child->right_attach - child->left_attach);
+
+ for (col = child->left_attach; col < child->right_attach; col++)
+ {
+ if ((col + 1) < child->right_attach)
+ table->cols[col].requisition += extra;
+ else
+ table->cols[col].requisition += width;
+ width -= extra;
+ }
+ }
+ }
+
+ /* Child spans multiple rows.
+ */
+ if (child->top_attach != (child->bottom_attach - 1))
+ {
+ /* Check and see if there is already enough space
+ * for the child.
+ */
+ height = 0;
+ for (row = child->top_attach; row < child->bottom_attach; row++)
+ {
+ height += table->rows[row].requisition;
+ if ((row + 1) < child->bottom_attach)
+ height += table->rows[row].spacing;
+ }
+
+ /* If we need to request more space for this child to fill
+ * its requisition, then divide up the needed space evenly
+ * amongst the columns it spans.
+ */
+ if (height < child->widget->requisition.height)
+ {
+ height = child->widget->requisition.height - height;
+ extra = height / (child->bottom_attach - child->top_attach);
+
+ for (row = child->top_attach; row < child->bottom_attach; row++)
+ {
+ if ((row + 1) < child->bottom_attach)
+ table->rows[row].requisition += extra;
+ else
+ table->rows[row].requisition += height;
+ height -= extra;
+ }
+ }
+ }
+ }
+ }
+}
+
+static void
+gtk_table_size_allocate_init (GtkTable *table)
+{
+ GtkTableChild *child;
+ GList *children;
+ gint row, col;
+ gint has_expand;
+ gint has_shrink;
+
+ /* Initialize the rows and cols.
+ * By default, rows and cols do not expand and do shrink.
+ * Those values are modified by the children that occupy
+ * the rows and cols.
+ */
+ for (col = 0; col < table->ncols; col++)
+ {
+ table->cols[col].allocation = table->cols[col].requisition;
+ table->cols[col].need_expand = FALSE;
+ table->cols[col].need_shrink = TRUE;
+ table->cols[col].expand = FALSE;
+ table->cols[col].shrink = TRUE;
+ }
+ for (row = 0; row < table->nrows; row++)
+ {
+ table->rows[row].allocation = table->rows[row].requisition;
+ table->rows[row].need_expand = FALSE;
+ table->rows[row].need_shrink = TRUE;
+ table->rows[row].expand = FALSE;
+ table->rows[row].shrink = TRUE;
+ }
+
+ /* Loop over all the children and adjust the row and col values
+ * based on whether the children want to be allowed to expand
+ * or shrink. This loop handles children that occupy a single
+ * row or column.
+ */
+ children = table->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_VISIBLE (child->widget))
+ {
+ if (child->left_attach == (child->right_attach - 1))
+ {
+ if (child->xexpand)
+ table->cols[child->left_attach].expand = TRUE;
+
+ if (!child->xshrink)
+ table->cols[child->left_attach].shrink = FALSE;
+ }
+
+ if (child->top_attach == (child->bottom_attach - 1))
+ {
+ if (child->yexpand)
+ table->rows[child->top_attach].expand = TRUE;
+
+ if (!child->yshrink)
+ table->rows[child->top_attach].shrink = FALSE;
+ }
+ }
+ }
+
+ /* Loop over all the children again and this time handle children
+ * which span multiple rows or columns.
+ */
+ children = table->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_VISIBLE (child->widget))
+ {
+ if (child->left_attach != (child->right_attach - 1))
+ {
+ if (child->xexpand)
+ {
+ has_expand = FALSE;
+ for (col = child->left_attach; col < child->right_attach; col++)
+ if (table->cols[col].expand)
+ {
+ has_expand = TRUE;
+ break;
+ }
+
+ if (!has_expand)
+ for (col = child->left_attach; col < child->right_attach; col++)
+ table->cols[col].need_expand = TRUE;
+ }
+
+ if (!child->xshrink)
+ {
+ has_shrink = TRUE;
+ for (col = child->left_attach; col < child->right_attach; col++)
+ if (!table->cols[col].shrink)
+ {
+ has_shrink = FALSE;
+ break;
+ }
+
+ if (has_shrink)
+ for (col = child->left_attach; col < child->right_attach; col++)
+ table->cols[col].need_shrink = FALSE;
+ }
+ }
+
+ if (child->top_attach != (child->bottom_attach - 1))
+ {
+ if (child->yexpand)
+ {
+ has_expand = FALSE;
+ for (row = child->top_attach; row < child->bottom_attach; row++)
+ if (table->rows[row].expand)
+ {
+ has_expand = TRUE;
+ break;
+ }
+
+ if (!has_expand)
+ for (row = child->top_attach; row < child->bottom_attach; row++)
+ table->rows[row].need_expand = TRUE;
+ }
+
+ if (!child->yshrink)
+ {
+ has_shrink = TRUE;
+ for (row = child->top_attach; row < child->bottom_attach; row++)
+ if (!table->rows[row].shrink)
+ {
+ has_shrink = FALSE;
+ break;
+ }
+
+ if (has_shrink)
+ for (row = child->top_attach; row < child->bottom_attach; row++)
+ table->rows[row].need_shrink = FALSE;
+ }
+ }
+ }
+ }
+
+ /* Loop over the columns and set the expand and shrink values
+ * if the column can be expanded or shrunk.
+ */
+ for (col = 0; col < table->ncols; col++)
+ {
+ if (table->cols[col].need_expand)
+ table->cols[col].expand = TRUE;
+ if (!table->cols[col].need_shrink)
+ table->cols[col].shrink = FALSE;
+ }
+
+ /* Loop over the rows and set the expand and shrink values
+ * if the row can be expanded or shrunk.
+ */
+ for (row = 0; row < table->nrows; row++)
+ {
+ if (table->rows[row].need_expand)
+ table->rows[row].expand = TRUE;
+ if (!table->rows[row].need_shrink)
+ table->rows[row].shrink = FALSE;
+ }
+}
+
+static void
+gtk_table_size_allocate_pass1 (GtkTable *table)
+{
+ gint real_width;
+ gint real_height;
+ gint width, height;
+ gint row, col;
+ gint nexpand;
+ gint nshrink;
+ gint extra;
+
+ /* If we were allocated more space than we requested
+ * then we have to expand any expandable rows and columns
+ * to fill in the extra space.
+ */
+
+ real_width = GTK_WIDGET (table)->allocation.width - GTK_CONTAINER (table)->border_width * 2;
+ real_height = GTK_WIDGET (table)->allocation.height - GTK_CONTAINER (table)->border_width * 2;
+
+ if (table->homogeneous)
+ {
+ nexpand = 0;
+ for (col = 0; col < table->ncols; col++)
+ if (table->cols[col].expand)
+ {
+ nexpand += 1;
+ break;
+ }
+
+ if (nexpand > 0)
+ {
+ width = real_width;
+
+ for (col = 0; col < table->ncols - 1; col++)
+ width -= table->cols[col].spacing;
+
+ extra = width / table->ncols;
+
+ for (col = 0; col < table->ncols; col++)
+ {
+ if ((col + 1) == table->ncols)
+ table->cols[col].allocation = width;
+ else
+ table->cols[col].allocation = extra;
+
+ width -= extra;
+ }
+ }
+ }
+ else
+ {
+ width = 0;
+ nexpand = 0;
+ nshrink = 0;
+
+ for (col = 0; col < table->ncols; col++)
+ {
+ width += table->cols[col].requisition;
+ if (table->cols[col].expand)
+ nexpand += 1;
+ if (table->cols[col].shrink)
+ nshrink += 1;
+ }
+ for (col = 0; col < table->ncols - 1; col++)
+ width += table->cols[col].spacing;
+
+ /* Check to see if we were allocated more width than we requested.
+ */
+ if ((width < real_width) && (nexpand >= 1))
+ {
+ width = real_width - width;
+ extra = width / nexpand;
+
+ for (col = 0; col < table->ncols; col++)
+ if (table->cols[col].expand)
+ {
+ if (nexpand == 1)
+ table->cols[col].allocation += width;
+ else
+ table->cols[col].allocation += extra;
+
+ width -= extra;
+ nexpand -= 1;
+ }
+ }
+
+ /* Check to see if we were allocated less width than we requested.
+ */
+ if ((width > real_width) && (nshrink >= 1))
+ {
+ width = width - real_width;
+ extra = width / nshrink;
+
+ for (col = 0; col < table->ncols; col++)
+ if (table->cols[col].shrink)
+ {
+ if (nshrink == 1)
+ table->cols[col].allocation -= width;
+ else
+ table->cols[col].allocation -= extra;
+
+ width -= extra;
+ nshrink -= 1;
+ }
+ }
+ }
+
+ if (table->homogeneous)
+ {
+ nexpand = 0;
+ for (row = 0; row < table->nrows; row++)
+ if (table->rows[row].expand)
+ {
+ nexpand += 1;
+ break;
+ }
+
+ if (nexpand > 0)
+ {
+ height = real_height;
+
+ for (row = 0; row < table->nrows - 1; row++)
+ height -= table->rows[row].spacing;
+
+ extra = height / table->nrows;
+
+ for (row = 0; row < table->nrows; row++)
+ {
+ if ((row + 1) == table->nrows)
+ table->rows[row].allocation = height;
+ else
+ table->rows[row].allocation = extra;
+
+ height -= extra;
+ }
+ }
+ }
+ else
+ {
+ height = 0;
+ nexpand = 0;
+ nshrink = 0;
+
+ for (row = 0; row < table->nrows; row++)
+ {
+ height += table->rows[row].requisition;
+ if (table->rows[row].expand)
+ nexpand += 1;
+ if (table->rows[row].shrink)
+ nshrink += 1;
+ }
+ for (row = 0; row < table->nrows - 1; row++)
+ height += table->rows[row].spacing;
+
+ /* Check to see if we were allocated more height than we requested.
+ */
+ if ((height < real_height) && (nexpand >= 1))
+ {
+ height = real_height - height;
+ extra = height / nexpand;
+
+ for (row = 0; row < table->nrows; row++)
+ if (table->rows[row].expand)
+ {
+ if (nexpand == 1)
+ table->rows[row].allocation += height;
+ else
+ table->rows[row].allocation += extra;
+
+ height -= extra;
+ nexpand -= 1;
+ }
+ }
+
+ /* Check to see if we were allocated less height than we requested.
+ */
+ if ((height > real_height) && (nshrink >= 1))
+ {
+ height = height - real_height;
+ extra = height / nshrink;
+
+ for (row = 0; row < table->nrows; row++)
+ if (table->rows[row].shrink)
+ {
+ if (nshrink == 1)
+ table->rows[row].allocation -= height;
+ else
+ table->rows[row].allocation -= extra;
+
+ height -= extra;
+ nshrink -= 1;
+ }
+ }
+ }
+}
+
+static void
+gtk_table_size_allocate_pass2 (GtkTable *table)
+{
+ GtkTableChild *child;
+ GList *children;
+ gint max_width;
+ gint max_height;
+ gint x, y;
+ gint row, col;
+ GtkAllocation allocation;
+
+ children = table->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_VISIBLE (child->widget))
+ {
+ x = GTK_WIDGET (table)->allocation.x + GTK_CONTAINER (table)->border_width;
+ y = GTK_WIDGET (table)->allocation.y + GTK_CONTAINER (table)->border_width;
+ max_width = 0;
+ max_height = 0;
+
+ for (col = 0; col < child->left_attach; col++)
+ {
+ x += table->cols[col].allocation;
+ x += table->cols[col].spacing;
+ }
+
+ for (col = child->left_attach; col < child->right_attach; col++)
+ {
+ max_width += table->cols[col].allocation;
+ if ((col + 1) < child->right_attach)
+ max_width += table->cols[col].spacing;
+ }
+
+ for (row = 0; row < child->top_attach; row++)
+ {
+ y += table->rows[row].allocation;
+ y += table->rows[row].spacing;
+ }
+
+ for (row = child->top_attach; row < child->bottom_attach; row++)
+ {
+ max_height += table->rows[row].allocation;
+ if ((row + 1) < child->bottom_attach)
+ max_height += table->rows[row].spacing;
+ }
+
+ if (child->xfill)
+ {
+ allocation.width = max_width - child->xpadding * 2;
+ allocation.x = x + (max_width - allocation.width) / 2;
+ }
+ else
+ {
+ allocation.width = child->widget->requisition.width;
+ allocation.x = x + (max_width - allocation.width) / 2;
+ }
+
+ if (child->yfill)
+ {
+ allocation.height = max_height - child->ypadding * 2;
+ allocation.y = y + (max_height - allocation.height) / 2;
+ }
+ else
+ {
+ allocation.height = child->widget->requisition.height;
+ allocation.y = y + (max_height - allocation.height) / 2;
+ }
+
+ gtk_widget_size_allocate (child->widget, &allocation);
+ }
+ }
+}
diff --git a/gtk/gtktable.h b/gtk/gtktable.h
new file mode 100644
index 000000000..f144e78d2
--- /dev/null
+++ b/gtk/gtktable.h
@@ -0,0 +1,126 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_TABLE_H__
+#define __GTK_TABLE_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkcontainer.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_TABLE(obj) GTK_CHECK_CAST (obj, gtk_table_get_type (), GtkTable)
+#define GTK_TABLE_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_table_get_type (), GtkTableClass)
+#define GTK_IS_TABLE(obj) GTK_CHECK_TYPE (obj, gtk_table_get_type ())
+
+
+typedef struct _GtkTable GtkTable;
+typedef struct _GtkTableClass GtkTableClass;
+typedef struct _GtkTableChild GtkTableChild;
+typedef struct _GtkTableRowCol GtkTableRowCol;
+
+struct _GtkTable
+{
+ GtkContainer container;
+
+ GList *children;
+ GtkTableRowCol *rows;
+ GtkTableRowCol *cols;
+ guint16 nrows;
+ guint16 ncols;
+
+ guint homogeneous : 1;
+};
+
+struct _GtkTableClass
+{
+ GtkContainerClass parent_class;
+};
+
+struct _GtkTableChild
+{
+ GtkWidget *widget;
+ guint16 left_attach;
+ guint16 right_attach;
+ guint16 top_attach;
+ guint16 bottom_attach;
+ guint16 xpadding;
+ guint16 ypadding;
+ guint xexpand : 1;
+ guint yexpand : 1;
+ guint xshrink : 1;
+ guint yshrink : 1;
+ guint xfill : 1;
+ guint yfill : 1;
+};
+
+struct _GtkTableRowCol
+{
+ guint16 requisition;
+ guint16 allocation;
+ guint16 spacing;
+ guint need_expand : 1;
+ guint need_shrink : 1;
+ guint expand : 1;
+ guint shrink : 1;
+};
+
+
+guint gtk_table_get_type (void);
+GtkWidget* gtk_table_new (gint rows,
+ gint columns,
+ gint homogeneous);
+
+void gtk_table_attach (GtkTable *table,
+ GtkWidget *child,
+ gint left_attach,
+ gint right_attach,
+ gint top_attach,
+ gint bottom_attach,
+ gint xoptions,
+ gint yoptions,
+ gint xpadding,
+ gint ypadding);
+void gtk_table_attach_defaults (GtkTable *table,
+ GtkWidget *widget,
+ gint left_attach,
+ gint right_attach,
+ gint top_attach,
+ gint bottom_attach);
+void gtk_table_set_row_spacing (GtkTable *table,
+ gint row,
+ gint spacing);
+void gtk_table_set_col_spacing (GtkTable *table,
+ gint column,
+ gint spacing);
+void gtk_table_set_row_spacings (GtkTable *table,
+ gint spacing);
+void gtk_table_set_col_spacings (GtkTable *table,
+ gint spacing);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_TABLE_H__ */
diff --git a/gtk/gtktext.c b/gtk/gtktext.c
new file mode 100644
index 000000000..ae3dd4b5c
--- /dev/null
+++ b/gtk/gtktext.c
@@ -0,0 +1,3522 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <ctype.h>
+#include <string.h>
+#include "gdk/gdkkeysyms.h"
+#include "gtkmain.h"
+#include "gtksignal.h"
+#include "gtktext.h"
+#include "line-wrap.xbm"
+#include "line-arrow.xbm"
+
+
+#define INITIAL_BUFFER_SIZE 1024
+#define INITIAL_LINE_CACHE_SIZE 256
+#define MIN_GAP_SIZE 256
+#define LINE_DELIM '\n'
+#define MIN_TEXT_WIDTH_LINES 20
+#define MIN_TEXT_HEIGHT_LINES 10
+#define TEXT_BORDER_ROOM 3
+#define LINE_WRAP_ROOM 8 /* The bitmaps are 6 wide. */
+#define DEFAULT_TAB_STOP_WIDTH 4
+#define SCROLL_PIXELS 5
+#define KEY_SCROLL_PIXELS 10
+
+#define SET_PROPERTY_MARK(m, p, o) do { \
+ (m)->property = (p); \
+ (m)->offset = (o); \
+ } while (0)
+#define MARK_CURRENT_PROPERTY(mark) ((TextProperty*)(mark)->property->data)
+#define MARK_NEXT_PROPERTY(mark) ((TextProperty*)(mark)->property->next->data)
+#define MARK_PREV_PROPERTY(mark) ((TextProperty*)((mark)->property->prev ? \
+ (mark)->property->prev->data \
+ : NULL))
+#define MARK_PREV_LIST_PTR(mark) ((mark)->property->prev)
+#define MARK_LIST_PTR(mark) ((mark)->property)
+#define MARK_NEXT_LIST_PTR(mark) ((mark)->property->next)
+#define MARK_OFFSET(mark) ((mark)->offset)
+#define MARK_PROPERTY_LENGTH(mark) (MARK_CURRENT_PROPERTY(mark)->length)
+#define MARK_CURRENT_FONT(mark) (((TextProperty*)(mark)->property->data)->font->gdk_font)
+#define MARK_CURRENT_FORE(mark) (((TextProperty*)(mark)->property->data)->fore_color)
+#define MARK_CURRENT_BACK(mark) (((TextProperty*)(mark)->property->data)->back_color)
+#define MARK_CURRENT_TEXT_FONT(m) (((TextProperty*)(m)->property->data)->font)
+#define TEXT_INDEX(t, index) ((index) < (t)->gap_position ? (t)->text[index] : \
+ (t)->text[(index) + (t)->gap_size])
+#define TEXT_LENGTH(t) ((t)->text_end - (t)->gap_size)
+#define FONT_HEIGHT(f) ((f)->ascent + (f)->descent)
+#define LINE_HEIGHT(l) ((l).font_ascent + (l).font_descent)
+#define LINE_CONTAINS(l, i) ((l).start.index <= (i) && (l).end.index >= (i))
+#define LINE_STARTS_AT(l, i) ((l).start.index == (i))
+#define LINE_START_PIXEL(l) ((l).tab_cont.pixel_offset)
+#define LAST_INDEX(t, m) ((m).index == TEXT_LENGTH(t))
+#define CACHE_DATA(c) (*(LineParams*)(c)->data)
+
+
+typedef struct _TextFont TextFont;
+typedef struct _TextProperty TextProperty;
+typedef struct _TabStopMark TabStopMark;
+typedef struct _PrevTabCont PrevTabCont;
+typedef struct _FetchLinesData FetchLinesData;
+typedef struct _LineParams LineParams;
+typedef struct _SetVerticalScrollData SetVerticalScrollData;
+
+typedef gint (*LineIteratorFunction) (GtkText* text, LineParams* lp, void* data);
+
+typedef enum
+{
+ FetchLinesPixels,
+ FetchLinesCount
+} FLType;
+
+struct _SetVerticalScrollData {
+ gint pixel_height;
+ gint last_didnt_wrap;
+ gint last_line_start;
+ GtkPropertyMark mark;
+};
+
+struct _TextFont
+{
+ /* The actual font. */
+ GdkFont *gdk_font;
+
+ gint16 char_widths[256];
+};
+
+struct _TextProperty
+{
+ /* Font. */
+ TextFont* font;
+
+ /* Background Color. */
+ GdkColor* back_color;
+
+ /* Foreground Color. */
+ GdkColor* fore_color;
+
+ /* Length of this property. */
+ guint length;
+};
+
+struct _TabStopMark
+{
+ GList* tab_stops; /* Index into list containing the next tab position. If
+ * NULL, using default widths. */
+ gint to_next_tab;
+};
+
+struct _PrevTabCont
+{
+ guint pixel_offset;
+ TabStopMark tab_start;
+};
+
+struct _FetchLinesData
+{
+ GList* new_lines;
+ FLType fl_type;
+ gint data;
+ gint data_max;
+};
+
+struct _LineParams
+{
+ guint font_ascent;
+ guint font_descent;
+ guint pixel_width;
+ guint displayable_chars;
+ guint wraps : 1;
+
+ PrevTabCont tab_cont;
+ PrevTabCont tab_cont_next;
+
+ GtkPropertyMark start;
+ GtkPropertyMark end;
+};
+
+
+static void gtk_text_class_init (GtkTextClass *klass);
+static void gtk_text_init (GtkText *text);
+static void gtk_text_destroy (GtkObject *object);
+static void gtk_text_realize (GtkWidget *widget);
+static void gtk_text_unrealize (GtkWidget *widget);
+static void gtk_text_draw_focus (GtkWidget *widget);
+static void gtk_text_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void gtk_text_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static void gtk_text_adjustment (GtkAdjustment *adjustment,
+ GtkText *text);
+static void gtk_text_disconnect (GtkAdjustment *adjustment,
+ GtkText *text);
+
+/* Event handlers */
+static void gtk_text_draw (GtkWidget *widget,
+ GdkRectangle *area);
+static gint gtk_text_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+static gint gtk_text_button_press (GtkWidget *widget,
+ GdkEventButton *event);
+static gint gtk_text_button_release (GtkWidget *widget,
+ GdkEventButton *event);
+static gint gtk_text_motion_notify (GtkWidget *widget,
+ GdkEventMotion *event);
+static gint gtk_text_key_press (GtkWidget *widget,
+ GdkEventKey *event);
+static gint gtk_text_focus_in (GtkWidget *widget,
+ GdkEventFocus *event);
+static gint gtk_text_focus_out (GtkWidget *widget,
+ GdkEventFocus *event);
+static gint gtk_text_selection_clear (GtkWidget *widget,
+ GdkEventSelection *event);
+static gint gtk_text_selection_request (GtkWidget *widget,
+ GdkEventSelection *event);
+static gint gtk_text_selection_notify (GtkWidget *widget,
+ GdkEventSelection *event);
+
+static void move_gap_to_point (GtkText* text);
+static void make_forward_space (GtkText* text, guint len);
+static void insert_text_property (GtkText* text, GdkFont* font,
+ GdkColor *fore, GdkColor* back, guint len);
+static void delete_text_property (GtkText* text, guint len);
+static void init_properties (GtkText *text);
+static guint pixel_height_of (GtkText* text, GList* cache_line);
+
+/* Property Movement and Size Computations */
+static void advance_mark (GtkPropertyMark* mark);
+static void decrement_mark (GtkPropertyMark* mark);
+static void advance_mark_n (GtkPropertyMark* mark, gint n);
+static void decrement_mark_n (GtkPropertyMark* mark, gint n);
+static void move_mark_n (GtkPropertyMark* mark, gint n);
+static GtkPropertyMark find_mark (GtkText* text, guint mark_position);
+static GtkPropertyMark find_mark_near (GtkText* text, guint mark_position, const GtkPropertyMark* near);
+static void find_line_containing_point (GtkText* text, guint point);
+static TextProperty* new_text_property (GdkFont* font, GdkColor* fore, GdkColor* back, guint length);
+
+/* Display */
+static gint total_line_height (GtkText* text,
+ GList* line,
+ gint line_count);
+static LineParams find_line_params (GtkText* text,
+ const GtkPropertyMark *mark,
+ const PrevTabCont *tab_cont,
+ PrevTabCont *next_cont);
+static void recompute_geometry (GtkText* text);
+static void insert_char_line_expose (GtkText* text, gchar key, guint old_pixels);
+static void delete_char_line_expose (GtkText* text, gchar key, guint old_pixels);
+static void clear_area (GtkText *text, GdkRectangle *area);
+static void draw_line (GtkText* text,
+ gint pixel_height,
+ LineParams* lp);
+static void draw_line_wrap (GtkText* text,
+ guint height);
+static void draw_cursor (GtkText* text, gint absolute);
+static void undraw_cursor (GtkText* text, gint absolute);
+static gint drawn_cursor_min (GtkText* text);
+static gint drawn_cursor_max (GtkText* text);
+static void expose_text (GtkText* text, GdkRectangle *area, gboolean cursor);
+
+/* Search and Placement. */
+static void find_cursor (GtkText* text);
+static void find_cursor_at_line (GtkText* text,
+ const LineParams* start_line,
+ gint pixel_height);
+static void mouse_click_1 (GtkText* text, GdkEventButton *event);
+
+/* Scrolling. */
+static void adjust_adj (GtkText* text, GtkAdjustment* adj);
+static void scroll_up (GtkText* text, gint diff);
+static void scroll_down (GtkText* text, gint diff);
+static void scroll_int (GtkText* text, gint diff);
+
+/* Cache Management. */
+static GList* remove_cache_line (GtkText* text, GList* list);
+
+/* Key Motion. */
+static void move_cursor_buffer_ver (GtkText *text, int dir);
+static void move_cursor_page_ver (GtkText *text, int dir);
+static void move_cursor_ver (GtkText *text, int count);
+static void move_cursor_hor (GtkText *text, int count);
+
+/*#define DEBUG_GTK_TEXT*/
+
+#if defined(DEBUG_GTK_TEXT) && defined(__GNUC__)
+/* Debugging utilities. */
+static void gtk_text_assert_mark (GtkText *text,
+ GtkPropertyMark *mark,
+ GtkPropertyMark *before,
+ GtkPropertyMark *after,
+ const gchar *msg,
+ const gchar *where,
+ gint line);
+
+static void gtk_text_assert (GtkText *text,
+ const gchar *msg,
+ gint line);
+static void gtk_text_show_cache_line (GtkText *text, GList *cache,
+ const char* what, const char* func, gint line);
+static void gtk_text_show_cache (GtkText *text, const char* func, gint line);
+static void gtk_text_show_adj (GtkText *text,
+ GtkAdjustment *adj,
+ const char* what,
+ const char* func,
+ gint line);
+static void gtk_text_show_props (GtkText* test,
+ const char* func,
+ int line);
+
+#define TDEBUG(args) g_print args
+#define TEXT_ASSERT(text) gtk_text_assert (text,__PRETTY_FUNCTION__,__LINE__)
+#define TEXT_ASSERT_MARK(text,mark,msg) gtk_text_assert_mark (text,mark, \
+ __PRETTY_FUNCTION__,msg,__LINE__)
+#define TEXT_SHOW(text) gtk_text_show_cache (text, __PRETTY_FUNCTION__,__LINE__)
+#define TEXT_SHOW_LINE(text,line,msg) gtk_text_show_cache_line (text,line,msg,\
+ __PRETTY_FUNCTION__,__LINE__)
+#define TEXT_SHOW_ADJ(text,adj,msg) gtk_text_show_adj (text,adj,msg, \
+ __PRETTY_FUNCTION__,__LINE__)
+#else
+#define TDEBUG(args)
+#define TEXT_ASSERT(text)
+#define TEXT_ASSERT_MARK(text,mark,msg)
+#define TEXT_SHOW(text)
+#define TEXT_SHOW_LINE(text,line,msg)
+#define TEXT_SHOW_ADJ(text,adj,msg)
+#endif
+
+/* Memory Management. */
+static GMemChunk *params_mem_chunk = NULL;
+static GMemChunk *text_property_chunk = NULL;
+
+static GtkWidgetClass *parent_class = NULL;
+
+
+/**********************************************************************/
+/* Widget Crap */
+/**********************************************************************/
+
+guint
+gtk_text_get_type ()
+{
+ static guint text_type = 0;
+
+ if (!text_type)
+ {
+ GtkTypeInfo text_info =
+ {
+ "GtkText",
+ sizeof (GtkText),
+ sizeof (GtkTextClass),
+ (GtkClassInitFunc) gtk_text_class_init,
+ (GtkObjectInitFunc) gtk_text_init,
+ (GtkArgFunc) NULL,
+ };
+
+ text_type = gtk_type_unique (gtk_widget_get_type (), &text_info);
+ }
+
+ return text_type;
+}
+
+static void
+gtk_text_class_init (GtkTextClass *class)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+
+ object_class = (GtkObjectClass*) class;
+ widget_class = (GtkWidgetClass*) class;
+
+ parent_class = gtk_type_class (gtk_widget_get_type ());
+
+ object_class->destroy = gtk_text_destroy;
+
+ widget_class->realize = gtk_text_realize;
+ widget_class->unrealize = gtk_text_unrealize;
+ widget_class->draw_focus = gtk_text_draw_focus;
+ widget_class->size_request = gtk_text_size_request;
+ widget_class->size_allocate = gtk_text_size_allocate;
+ widget_class->draw = gtk_text_draw;
+ widget_class->expose_event = gtk_text_expose;
+ widget_class->button_press_event = gtk_text_button_press;
+ widget_class->button_release_event = gtk_text_button_release;
+ widget_class->motion_notify_event = gtk_text_motion_notify;
+ widget_class->key_press_event = gtk_text_key_press;
+ widget_class->focus_in_event = gtk_text_focus_in;
+ widget_class->focus_out_event = gtk_text_focus_out;
+ widget_class->selection_clear_event = gtk_text_selection_clear;
+ widget_class->selection_request_event = gtk_text_selection_request;
+ widget_class->selection_notify_event = gtk_text_selection_notify;
+}
+
+static void
+gtk_text_init (GtkText *text)
+{
+ GTK_WIDGET_SET_FLAGS (text, GTK_CAN_FOCUS);
+
+ text->text = g_new (guchar, INITIAL_BUFFER_SIZE);
+ text->text_len = INITIAL_BUFFER_SIZE;
+
+ if (!params_mem_chunk)
+ params_mem_chunk = g_mem_chunk_new ("LineParams",
+ sizeof (LineParams),
+ 256 * sizeof (LineParams),
+ G_ALLOC_AND_FREE);
+
+ text->default_tab_width = 4;
+ text->tab_stops = NULL;
+
+ text->tab_stops = g_list_prepend (text->tab_stops, (void*)8);
+ text->tab_stops = g_list_prepend (text->tab_stops, (void*)8);
+
+ text->line_wrap = TRUE;
+ text->is_editable = TRUE;
+}
+
+GtkWidget*
+gtk_text_new (GtkAdjustment *hadj,
+ GtkAdjustment *vadj)
+{
+ GtkText *text;
+
+ text = gtk_type_new (gtk_text_get_type ());
+
+ gtk_text_set_adjustments (text, hadj, vadj);
+
+ return GTK_WIDGET (text);
+}
+
+void
+gtk_text_set_editable (GtkText *text,
+ gint editable)
+{
+ g_return_if_fail (text != NULL);
+ g_return_if_fail (GTK_IS_TEXT (text));
+
+ text->is_editable = (editable != FALSE);
+ text->is_editable = FALSE; /* UNTIL JOSH FIXES IT */
+}
+
+void
+gtk_text_set_adjustments (GtkText *text,
+ GtkAdjustment *hadj,
+ GtkAdjustment *vadj)
+{
+ g_return_if_fail (text != NULL);
+ g_return_if_fail (GTK_IS_TEXT (text));
+
+ if (text->hadj && (text->hadj != hadj))
+ {
+ gtk_signal_disconnect_by_data (GTK_OBJECT (text->hadj), text);
+ gtk_object_unref (GTK_OBJECT (text->hadj));
+ }
+
+ if (text->vadj && (text->vadj != vadj))
+ {
+ gtk_signal_disconnect_by_data (GTK_OBJECT (text->vadj), text);
+ gtk_object_unref (GTK_OBJECT (text->vadj));
+ }
+
+ if (!hadj)
+ hadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
+
+ if (!vadj)
+ vadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
+
+ if (text->hadj != hadj)
+ {
+ text->hadj = hadj;
+ gtk_object_ref (GTK_OBJECT (text->hadj));
+
+ gtk_signal_connect (GTK_OBJECT (text->hadj), "changed",
+ (GtkSignalFunc) gtk_text_adjustment,
+ text);
+ gtk_signal_connect (GTK_OBJECT (text->hadj), "value_changed",
+ (GtkSignalFunc) gtk_text_adjustment,
+ text);
+ gtk_signal_connect (GTK_OBJECT (text->hadj), "disconnect",
+ (GtkSignalFunc) gtk_text_disconnect,
+ text);
+ }
+
+ if (text->vadj != vadj)
+ {
+ text->vadj = vadj;
+ gtk_object_ref (GTK_OBJECT (text->vadj));
+
+ gtk_signal_connect (GTK_OBJECT (text->vadj), "changed",
+ (GtkSignalFunc) gtk_text_adjustment,
+ text);
+ gtk_signal_connect (GTK_OBJECT (text->vadj), "value_changed",
+ (GtkSignalFunc) gtk_text_adjustment,
+ text);
+ gtk_signal_connect (GTK_OBJECT (text->vadj), "disconnect",
+ (GtkSignalFunc) gtk_text_disconnect,
+ text);
+ }
+}
+
+void
+gtk_text_set_point (GtkText *text,
+ guint index)
+{
+ g_return_if_fail (text != NULL);
+ g_return_if_fail (GTK_IS_TEXT (text));
+ g_return_if_fail (index >= 0 && index <= TEXT_LENGTH (text))
+
+ text->point = find_mark (text, index);
+}
+
+guint
+gtk_text_get_point (GtkText *text)
+{
+ g_return_val_if_fail (text != NULL, 0);
+ g_return_val_if_fail (GTK_IS_TEXT (text), 0);
+
+ return text->point.index;
+}
+
+guint
+gtk_text_get_length (GtkText *text)
+{
+ g_return_val_if_fail (text != NULL, 0);
+ g_return_val_if_fail (GTK_IS_TEXT (text), 0);
+
+ return TEXT_LENGTH (text);
+}
+
+void
+gtk_text_freeze (GtkText *text)
+{
+ g_return_if_fail (text != NULL);
+ g_return_if_fail (GTK_IS_TEXT (text));
+
+ text->freeze = TRUE;
+}
+
+void
+gtk_text_thaw (GtkText *text)
+{
+ g_return_if_fail (text != NULL);
+ g_return_if_fail (GTK_IS_TEXT (text));
+
+ text->freeze = FALSE;
+
+ if (GTK_WIDGET_DRAWABLE (text))
+ {
+ recompute_geometry (text);
+ gtk_widget_queue_draw (GTK_WIDGET (text));
+ }
+}
+
+void
+gtk_text_insert (GtkText *text,
+ GdkFont *font,
+ GdkColor *fore,
+ GdkColor *back,
+ const char *chars,
+ gint length)
+{
+ g_return_if_fail (text != NULL);
+ g_return_if_fail (GTK_IS_TEXT (text));
+
+ g_assert (GTK_WIDGET_REALIZED (text));
+
+ /* back may be NULL, fore may not. */
+ if (fore == NULL)
+ fore = &text->widget.style->fg[GTK_STATE_NORMAL];
+
+ /* This must be because we need to have the style set up. */
+ g_assert (GTK_WIDGET_REALIZED(text));
+
+ if (length < 0)
+ length = strlen (chars);
+
+ if (length == 0)
+ return;
+
+ move_gap_to_point (text);
+
+ if (font == NULL)
+ font = GTK_WIDGET (text)->style->font;
+
+ make_forward_space (text, length);
+
+ memcpy (text->text + text->gap_position, chars, length);
+
+ insert_text_property (text, font, fore, back, length);
+
+ text->gap_size -= length;
+ text->gap_position += length;
+
+ advance_mark_n (&text->point, length);
+}
+
+gint
+gtk_text_backward_delete (GtkText *text,
+ guint nchars)
+{
+ g_return_val_if_fail (text != NULL, 0);
+ g_return_val_if_fail (GTK_IS_TEXT (text), 0);
+
+ if (nchars > text->point.index || nchars <= 0)
+ return FALSE;
+
+ gtk_text_set_point (text, text->point.index - nchars);
+
+ return gtk_text_foreward_delete (text, nchars);
+}
+
+gint
+gtk_text_foreward_delete (GtkText *text,
+ guint nchars)
+{
+ g_return_val_if_fail (text != NULL, 0);
+ g_return_val_if_fail (GTK_IS_TEXT (text), 0);
+
+ if (text->point.index + nchars > TEXT_LENGTH (text) || nchars <= 0)
+ return FALSE;
+
+ move_gap_to_point (text);
+
+ text->gap_size += nchars;
+
+ delete_text_property (text, nchars);
+
+ return TRUE;
+}
+
+static void
+gtk_text_destroy (GtkObject *object)
+{
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_TEXT (object));
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+static void
+gtk_text_realize (GtkWidget *widget)
+{
+ GtkText *text;
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_TEXT (widget));
+
+ text = (GtkText*) widget;
+ GTK_WIDGET_SET_FLAGS (text, GTK_REALIZED);
+
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.x = widget->allocation.x;
+ attributes.y = widget->allocation.y;
+ attributes.width = widget->allocation.width;
+ attributes.height = widget->allocation.height;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
+ attributes.event_mask = gtk_widget_get_events (widget);
+ attributes.event_mask |= (GDK_EXPOSURE_MASK |
+ GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_BUTTON_MOTION_MASK |
+ GDK_ENTER_NOTIFY_MASK |
+ GDK_LEAVE_NOTIFY_MASK |
+ GDK_KEY_PRESS_MASK);
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+
+ widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
+ gdk_window_set_user_data (widget->window, text);
+
+ attributes.x = (widget->style->klass->xthickness + TEXT_BORDER_ROOM);
+ attributes.y = (widget->style->klass->ythickness + TEXT_BORDER_ROOM);
+ attributes.width = widget->allocation.width - attributes.x * 2;
+ attributes.height = widget->allocation.height - attributes.y * 2;
+
+ text->text_area = gdk_window_new (widget->window, &attributes, attributes_mask);
+ gdk_window_set_user_data (text->text_area, text);
+
+ widget->style = gtk_style_attach (widget->style, widget->window);
+
+ /* Can't call gtk_style_set_background here because its handled specially */
+ if (!text->widget.style->bg_pixmap[GTK_STATE_NORMAL])
+ gdk_window_set_background (text->widget.window, &text->widget.style->bg[GTK_STATE_NORMAL]);
+
+ if (!text->widget.style->bg_pixmap[GTK_STATE_NORMAL])
+ gdk_window_set_background (text->text_area, &text->widget.style->bg[GTK_STATE_NORMAL]);
+
+ text->line_wrap_bitmap = gdk_bitmap_create_from_data (text->text_area,
+ (gchar*) line_wrap_bits,
+ line_wrap_width,
+ line_wrap_height);
+
+ text->line_arrow_bitmap = gdk_bitmap_create_from_data (text->text_area,
+ (gchar*) line_arrow_bits,
+ line_arrow_width,
+ line_arrow_height);
+
+ text->gc = gdk_gc_new (text->text_area);
+ gdk_gc_set_exposures (text->gc, TRUE);
+ gdk_gc_set_foreground (text->gc, &widget->style->fg[GTK_STATE_NORMAL]);
+
+ init_properties (text);
+
+ gdk_window_show (text->text_area);
+}
+
+static void
+gtk_text_unrealize (GtkWidget *widget)
+{
+ GtkText *text;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_TEXT (widget));
+
+ text = GTK_TEXT (widget);
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_REALIZED | GTK_MAPPED);
+
+ gtk_style_detach (widget->style);
+ gdk_window_destroy (widget->window);
+ gdk_window_destroy (text->text_area);
+ gdk_gc_destroy (text->gc);
+
+ widget->window = NULL;
+ text->text_area = NULL;
+ text->gc = NULL;
+}
+
+static void
+clear_focus_area (GtkText *text, gint area_x, gint area_y, gint area_width, gint area_height)
+{
+ gint ythick = TEXT_BORDER_ROOM + text->widget.style->klass->ythickness;
+ gint xthick = TEXT_BORDER_ROOM + text->widget.style->klass->xthickness;
+
+ gint width, height;
+ gint xorig, yorig;
+ gint x, y;
+
+ gdk_window_get_size (text->widget.style->bg_pixmap[GTK_STATE_NORMAL], &width, &height);
+
+ yorig = - text->first_onscreen_ver_pixel + ythick;
+ xorig = - text->first_onscreen_hor_pixel + xthick;
+
+ while (yorig > 0)
+ yorig -= height;
+
+ while (xorig > 0)
+ xorig -= width;
+
+ for (y = area_y; y < area_y + area_height; )
+ {
+ gint yoff = (y - yorig) % height;
+ gint yw = MIN(height - yoff, (area_y + area_height) - y);
+
+ for (x = area_x; x < area_x + area_width; )
+ {
+ gint xoff = (x - xorig) % width;
+ gint xw = MIN(width - xoff, (area_x + area_width) - x);
+
+ gdk_draw_pixmap (text->widget.window,
+ text->gc,
+ text->widget.style->bg_pixmap[GTK_STATE_NORMAL],
+ xoff,
+ yoff,
+ x,
+ y,
+ xw,
+ yw);
+
+ x += width - xoff;
+ }
+ y += height - yoff;
+ }
+}
+
+static void
+gtk_text_draw_focus (GtkWidget *widget)
+{
+ GtkText *text;
+ gint width, height;
+ gint x, y;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_TEXT (widget));
+
+ text = GTK_TEXT (widget);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ TDEBUG (("in gtk_text_draw_focus\n"));
+
+ x = 0;
+ y = 0;
+ width = widget->allocation.width;
+ height = widget->allocation.height;
+
+ if (widget->style->bg_pixmap[GTK_STATE_NORMAL])
+ {
+ gint ythick = TEXT_BORDER_ROOM + widget->style->klass->ythickness;
+ gint xthick = TEXT_BORDER_ROOM + widget->style->klass->xthickness;
+
+ /* top rect */
+ clear_focus_area (text, 0, 0, width, ythick);
+ /* right rect */
+ clear_focus_area (text, 0, ythick, xthick, height - 2 * ythick);
+ /* left rect */
+ clear_focus_area (text, width - xthick, ythick, xthick, height - 2 * ythick);
+ /* bottom rect */
+ clear_focus_area (text, 0, height - ythick, width, ythick);
+ }
+
+ if (GTK_WIDGET_HAS_FOCUS (widget))
+ {
+ x += 1;
+ y += 1;
+ width -= 2;
+ height -= 2;
+
+ gdk_draw_rectangle (widget->window,
+ widget->style->fg_gc[GTK_STATE_NORMAL],
+ FALSE, 0, 0,
+ widget->allocation.width - 1,
+ widget->allocation.height - 1);
+ }
+ else
+ {
+ gdk_draw_rectangle (widget->window,
+ widget->style->white_gc, FALSE,
+ x + 2,
+ y + 2,
+ width - 1 - 2,
+ height - 1 - 2);
+ }
+
+ gtk_draw_shadow (widget->style, widget->window,
+ GTK_STATE_NORMAL, GTK_SHADOW_IN,
+ x, y, width, height);
+ }
+ else
+ {
+ TDEBUG (("in gtk_text_draw_focus (undrawable !!!)\n"));
+ }
+}
+
+static void
+gtk_text_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ gint xthickness;
+ gint ythickness;
+ gint char_height;
+ gint char_width;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_TEXT (widget));
+ g_return_if_fail (requisition != NULL);
+
+ xthickness = widget->style->klass->xthickness + TEXT_BORDER_ROOM;
+ ythickness = widget->style->klass->ythickness + TEXT_BORDER_ROOM;
+
+ char_height = MIN_TEXT_HEIGHT_LINES * (widget->style->font->ascent +
+ widget->style->font->descent);
+
+ char_width = MIN_TEXT_WIDTH_LINES * (gdk_text_width (widget->style->font,
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
+ 26)
+ / 26);
+
+ requisition->width = char_width + xthickness * 2;
+ requisition->height = char_height + ythickness * 2;
+}
+
+static void
+gtk_text_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkText *text;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_TEXT (widget));
+ g_return_if_fail (allocation != NULL);
+
+ text = GTK_TEXT (widget);
+
+ widget->allocation = *allocation;
+ if (GTK_WIDGET_REALIZED (widget))
+ {
+ gdk_window_move_resize (widget->window,
+ allocation->x, allocation->y,
+ allocation->width, allocation->height);
+
+ gdk_window_move_resize (text->text_area,
+ widget->style->klass->xthickness + TEXT_BORDER_ROOM,
+ widget->style->klass->ythickness + TEXT_BORDER_ROOM,
+ widget->allocation.width - (widget->style->klass->xthickness +
+ TEXT_BORDER_ROOM) * 2,
+ widget->allocation.height - (widget->style->klass->ythickness +
+ TEXT_BORDER_ROOM) * 2);
+
+ recompute_geometry (text);
+ }
+}
+
+static void
+gtk_text_draw (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_TEXT (widget));
+ g_return_if_fail (area != NULL);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ expose_text (GTK_TEXT (widget), area, TRUE);
+ gtk_widget_draw_focus (widget);
+ }
+}
+
+static gint
+gtk_text_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_TEXT (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (event->window == GTK_TEXT (widget)->text_area)
+ {
+ TDEBUG (("in gtk_text_expose (expose)\n"));
+ expose_text (GTK_TEXT (widget), &event->area, TRUE);
+ }
+ else if (event->count == 0)
+ {
+ TDEBUG (("in gtk_text_expose (focus)\n"));
+ gtk_widget_draw_focus (widget);
+ }
+
+ return FALSE;
+}
+
+static gint
+gtk_text_button_press (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ GtkText *text;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_TEXT (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ text = GTK_TEXT(widget);
+ if (!GTK_WIDGET_HAS_FOCUS (widget))
+ gtk_widget_grab_focus (widget);
+
+ if (event->type == GDK_BUTTON_PRESS && event->button != 2)
+ gtk_grab_add (widget);
+
+ if (event->button == 1)
+ {
+ switch (event->type)
+ {
+ case GDK_BUTTON_PRESS:
+ undraw_cursor (GTK_TEXT (widget), FALSE);
+ mouse_click_1 (GTK_TEXT (widget), event);
+ draw_cursor (GTK_TEXT (widget), FALSE);
+ /* start selection */
+ break;
+
+ case GDK_2BUTTON_PRESS:
+ /* select word */
+ break;
+
+ case GDK_3BUTTON_PRESS:
+ /* select line */
+ break;
+
+ default:
+ break;
+ }
+ }
+ else if (event->type == GDK_BUTTON_PRESS)
+ {
+ if (event->button == 2)
+ {
+ /* insert selection. */
+ }
+ else
+ {
+ /* start selection */
+ }
+ }
+
+ return FALSE;
+}
+
+static gint
+gtk_text_button_release (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ GtkText *text;
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_TEXT (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (event->button != 2)
+ {
+ gtk_grab_remove (widget);
+
+ text = GTK_TEXT (widget);
+
+ /* stop selecting. */
+ }
+
+ return FALSE;
+}
+
+static gint
+gtk_text_motion_notify (GtkWidget *widget,
+ GdkEventMotion *event)
+{
+ GtkText *text;
+ gint x;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_TEXT (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ text = GTK_TEXT (widget);
+
+ x = event->x;
+ if (event->is_hint || (text->text_area != event->window))
+ gdk_window_get_pointer (text->text_area, &x, NULL, NULL);
+
+ /* update selection */
+
+ return FALSE;
+}
+
+static void
+gtk_text_insert_1_at_point (GtkText* text, char key)
+{
+ gtk_text_insert (text,
+ MARK_CURRENT_FONT (&text->point),
+ MARK_CURRENT_FORE (&text->point),
+ MARK_CURRENT_BACK (&text->point),
+ &key, 1);
+}
+
+static gint
+gtk_text_key_press (GtkWidget *widget,
+ GdkEventKey *event)
+{
+ GtkText *text;
+ gchar key;
+ gint return_val;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_TEXT (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ return_val = FALSE;
+
+ text = GTK_TEXT (widget);
+
+ if (!return_val)
+ {
+ key = event->keyval;
+ return_val = TRUE;
+
+ if (text->is_editable == FALSE)
+ {
+ switch (event->keyval)
+ {
+ case GDK_Home: scroll_int (text, -text->vadj->value); break;
+ case GDK_End: scroll_int (text, +text->vadj->upper); break;
+ case GDK_Page_Up: scroll_int (text, -text->vadj->page_increment); break;
+ case GDK_Page_Down: scroll_int (text, +text->vadj->page_increment); break;
+ case GDK_Up: scroll_int (text, -KEY_SCROLL_PIXELS); break;
+ case GDK_Down: scroll_int (text, +KEY_SCROLL_PIXELS); break;
+ default: break;
+ }
+ }
+ else
+ {
+ text->point = find_mark (text, text->cursor_mark.index);
+
+ switch (event->keyval)
+ {
+ case GDK_Home: move_cursor_buffer_ver (text, -1); break;
+ case GDK_End: move_cursor_buffer_ver (text, +1); break;
+ case GDK_Page_Up: move_cursor_page_ver (text, -1); break;
+ case GDK_Page_Down: move_cursor_page_ver (text, +1); break;
+ case GDK_Up: move_cursor_ver (text, -1); break;
+ case GDK_Down: move_cursor_ver (text, +1); break;
+ case GDK_Left: move_cursor_hor (text, -1); break;
+ case GDK_Right: move_cursor_hor (text, +1); break;
+
+ case GDK_BackSpace:
+ if (!text->has_cursor || text->cursor_mark.index == 0)
+ break;
+
+ gtk_text_backward_delete (text, 1);
+ break;
+ case GDK_Delete:
+ if (!text->has_cursor || LAST_INDEX (text, text->cursor_mark))
+ break;
+
+ gtk_text_foreward_delete (text, 1);
+ break;
+ case GDK_Tab:
+ if (!text->has_cursor)
+ break;
+
+ gtk_text_insert_1_at_point (text, '\t');
+ break;
+ case GDK_Return:
+ if (!text->has_cursor)
+ break;
+
+ gtk_text_insert_1_at_point (text, '\n');
+ break;
+ default:
+ if (!text->has_cursor)
+ break;
+
+ if ((event->keyval >= 0x20) && (event->keyval <= 0x7e))
+ {
+ return_val = TRUE;
+
+ if (event->state & GDK_CONTROL_MASK)
+ {
+ if ((key >= 'A') && (key <= 'Z'))
+ key -= 'A' - 'a';
+
+ if ((key >= 'a') && (key <= 'z') && text->control_keys[(int) (key - 'a')])
+ (* text->control_keys[(int) (key - 'a')]) (text);
+ }
+ else if (event->state & GDK_MOD1_MASK)
+ {
+ g_message ("alt key");
+
+ if ((key >= 'A') && (key <= 'Z'))
+ key -= 'A' - 'a';
+
+ if ((key >= 'a') && (key <= 'z') && text->alt_keys[(int) (key - 'a')])
+ (* text->alt_keys[(int) (key - 'a')]) (text);
+ }
+ else
+ {
+ gtk_text_insert_1_at_point (text, key);
+ }
+ }
+ else
+ {
+ return_val = FALSE;
+ }
+ break;
+ }
+ }
+ }
+
+ return return_val;
+}
+
+static gint
+gtk_text_focus_in (GtkWidget *widget,
+ GdkEventFocus *event)
+{
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_TEXT (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ TDEBUG (("in gtk_text_focus_in\n"));
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
+ gtk_widget_draw_focus (widget);
+
+ draw_cursor (GTK_TEXT(widget), TRUE);
+
+ return FALSE;
+}
+
+static gint
+gtk_text_focus_out (GtkWidget *widget,
+ GdkEventFocus *event)
+{
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_TEXT (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ TDEBUG (("in gtk_text_focus_out\n"));
+
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
+ gtk_widget_draw_focus (widget);
+
+ undraw_cursor (GTK_TEXT(widget), TRUE);
+
+ return FALSE;
+}
+
+static void
+gtk_text_adjustment (GtkAdjustment *adjustment,
+ GtkText *text)
+{
+ g_return_if_fail (adjustment != NULL);
+ g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
+ g_return_if_fail (text != NULL);
+ g_return_if_fail (GTK_IS_TEXT (text));
+
+ if (adjustment == text->hadj)
+ {
+ g_warning ("horizontal scrolling not implemented");
+ }
+ else
+ {
+ gint diff = ((gint)adjustment->value) - text->last_ver_value;
+
+ if (diff != 0)
+ {
+ undraw_cursor (text, FALSE);
+
+ if (diff > 0)
+ scroll_down (text, diff);
+ else /* if (diff < 0) */
+ scroll_up (text, diff);
+
+ draw_cursor (text, FALSE);
+
+ text->last_ver_value = adjustment->value;
+ }
+ }
+}
+
+static void
+gtk_text_disconnect (GtkAdjustment *adjustment,
+ GtkText *text)
+{
+ g_return_if_fail (adjustment != NULL);
+ g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
+ g_return_if_fail (text != NULL);
+ g_return_if_fail (GTK_IS_TEXT (text));
+
+ if (adjustment == text->hadj)
+ text->hadj = NULL;
+ if (adjustment == text->vadj)
+ text->vadj = NULL;
+}
+
+
+static GtkPropertyMark
+find_this_line_start_mark (GtkText* text, guint point_position, const GtkPropertyMark* near)
+{
+ GtkPropertyMark mark;
+
+ mark = find_mark_near (text, point_position, near);
+
+ while (mark.index > 0 &&
+ TEXT_INDEX (text, mark.index - 1) != LINE_DELIM)
+ decrement_mark (&mark);
+
+ return mark;
+}
+
+static void
+init_tab_cont (GtkText* text, PrevTabCont* tab_cont)
+{
+ tab_cont->pixel_offset = 0;
+ tab_cont->tab_start.tab_stops = text->tab_stops;
+ tab_cont->tab_start.to_next_tab = (gulong) text->tab_stops->data;
+
+ if (!tab_cont->tab_start.to_next_tab)
+ tab_cont->tab_start.to_next_tab = text->default_tab_width;
+}
+
+static void
+line_params_iterate (GtkText* text,
+ const GtkPropertyMark* mark0,
+ const PrevTabCont* tab_mark0,
+ gint8 alloc,
+ void* data,
+ LineIteratorFunction iter)
+ /* mark0 MUST be a real line start. if ALLOC, allocate line params
+ * from a mem chunk. DATA is passed to ITER_CALL, which is called
+ * for each line following MARK, iteration continues unless ITER_CALL
+ * returns TRUE. */
+{
+ GtkPropertyMark mark = *mark0;
+ PrevTabCont tab_conts[2];
+ LineParams *lp, lpbuf;
+ gint tab_cont_index = 0;
+
+ if (tab_mark0)
+ tab_conts[0] = *tab_mark0;
+ else
+ init_tab_cont (text, tab_conts);
+
+ for (;;)
+ {
+ if (alloc)
+ lp = g_chunk_new (LineParams, params_mem_chunk);
+ else
+ lp = &lpbuf;
+
+ *lp = find_line_params (text, &mark, tab_conts + tab_cont_index,
+ tab_conts + (tab_cont_index + 1) % 2);
+
+ if ((*iter) (text, lp, data))
+ return;
+
+ if (LAST_INDEX (text, lp->end))
+ break;
+
+ mark = lp->end;
+ advance_mark (&mark);
+ tab_cont_index = (tab_cont_index + 1) % 2;
+ }
+}
+
+static gint
+fetch_lines_iterator (GtkText* text, LineParams* lp, void* data)
+{
+ FetchLinesData *fldata = (FetchLinesData*) data;
+
+ fldata->new_lines = g_list_prepend (fldata->new_lines, lp);
+
+ switch (fldata->fl_type)
+ {
+ case FetchLinesCount:
+ if (!text->line_wrap || !lp->wraps)
+ fldata->data += 1;
+
+ if (fldata->data >= fldata->data_max)
+ return TRUE;
+
+ break;
+ case FetchLinesPixels:
+
+ fldata->data += LINE_HEIGHT(*lp);
+
+ if (fldata->data >= fldata->data_max)
+ return TRUE;
+
+ break;
+ }
+
+ return FALSE;
+}
+
+static GList*
+fetch_lines (GtkText* text,
+ const GtkPropertyMark* mark0,
+ const PrevTabCont* tab_cont0,
+ FLType fl_type,
+ gint data)
+{
+ FetchLinesData fl_data;
+
+ fl_data.new_lines = NULL;
+ fl_data.data = 0;
+ fl_data.data_max = data;
+ fl_data.fl_type = fl_type;
+
+ line_params_iterate (text, mark0, tab_cont0, TRUE, &fl_data, fetch_lines_iterator);
+
+ return g_list_reverse (fl_data.new_lines);
+}
+
+static void
+fetch_lines_backward (GtkText* text)
+{
+ GList* new_lines = NULL, *new_line_start;
+
+ GtkPropertyMark mark = find_this_line_start_mark (text,
+ CACHE_DATA(text->line_start_cache).start.index - 1,
+ &CACHE_DATA(text->line_start_cache).start);
+
+ new_line_start = new_lines = fetch_lines (text, &mark, NULL, FetchLinesCount, 1);
+
+ while (new_line_start->next)
+ new_line_start = new_line_start->next;
+
+ new_line_start->next = text->line_start_cache;
+ text->line_start_cache->prev = new_line_start;
+}
+
+static void
+fetch_lines_forward (GtkText* text, gint line_count)
+{
+ GtkPropertyMark mark;
+ GList* line = text->line_start_cache;
+
+ while(line->next)
+ line = line->next;
+
+ mark = CACHE_DATA(line).end;
+
+ if (LAST_INDEX (text, mark))
+ return;
+
+ advance_mark(&mark);
+
+ line->next = fetch_lines (text, &mark, &CACHE_DATA(line).tab_cont_next, FetchLinesCount, line_count);
+
+ if (line->next)
+ line->next->prev = line;
+}
+
+static gint
+total_line_height (GtkText* text, GList* line, gint line_count)
+{
+ gint height = 0;
+
+ for (; line && line_count > 0; line = line->next)
+ {
+ height += LINE_HEIGHT(CACHE_DATA(line));
+
+ if (!text->line_wrap || !CACHE_DATA(line).wraps)
+ line_count -= 1;
+
+ if (!line->next)
+ fetch_lines_forward (text, line_count);
+ }
+
+ return height;
+}
+
+static void
+swap_lines (GtkText* text, GList* old, GList* new, gint old_line_count)
+{
+ if (old == text->line_start_cache)
+ {
+ GList* last;
+
+ for (; old_line_count > 0; old_line_count -= 1)
+ {
+ while (text->line_start_cache &&
+ text->line_wrap &&
+ CACHE_DATA(text->line_start_cache).wraps)
+ remove_cache_line(text, text->line_start_cache);
+
+ remove_cache_line(text, text->line_start_cache);
+ }
+
+ last = g_list_last (new);
+
+ last->next = text->line_start_cache;
+
+ if (text->line_start_cache)
+ text->line_start_cache->prev = last;
+
+ text->line_start_cache = new;
+ }
+ else
+ {
+ GList *last;
+
+ g_assert (old->prev);
+
+ last = old->prev;
+
+ for (; old_line_count > 0; old_line_count -= 1)
+ {
+ while (old && text->line_wrap && CACHE_DATA(old).wraps)
+ old = remove_cache_line (text, old);
+
+ old = remove_cache_line (text, old);
+ }
+
+ last->next = new;
+ new->prev = last;
+
+ last = g_list_last (new);
+
+ last->next = old;
+
+ if (old)
+ old->prev = last;
+ }
+}
+
+static void
+correct_cache_delete (GtkText* text, gint lines)
+{
+ GList* cache = text->current_line;
+ gint i;
+
+ for (i = 0; cache && i < lines; i += 1, cache = cache->next)
+ /* nothing */;
+
+ for (; cache; cache = cache->next)
+ {
+ GtkPropertyMark *start = &CACHE_DATA(cache).start;
+ GtkPropertyMark *end = &CACHE_DATA(cache).end;
+
+ start->index -= 1;
+ end->index -= 1;
+
+ if (start->property == text->point.property)
+ start->offset = start->index - (text->point.index - text->point.offset);
+
+ if (end->property == text->point.property)
+ end->offset = end->index - (text->point.index - text->point.offset);
+
+ /*TEXT_ASSERT_MARK(text, start, "start");*/
+ /*TEXT_ASSERT_MARK(text, end, "end");*/
+ }
+}
+
+static void
+delete_char_line_expose (GtkText* text, gchar key, guint old_pixels)
+{
+ gint pixel_height;
+ guint new_pixels = 0;
+ gint old_line_count = 1 + (key == LINE_DELIM);
+ GdkRectangle rect;
+ GList* new_line = NULL;
+ gint width, height;
+
+ text->cursor_virtual_x = 0;
+
+ undraw_cursor (text, FALSE);
+
+ correct_cache_delete (text, old_line_count);
+
+ pixel_height = pixel_height_of(text, text->current_line) -
+ LINE_HEIGHT(CACHE_DATA(text->current_line));
+
+ if (CACHE_DATA(text->current_line).start.index == text->point.index)
+ CACHE_DATA(text->current_line).start = text->point;
+
+ new_line = fetch_lines (text,
+ &CACHE_DATA(text->current_line).start,
+ &CACHE_DATA(text->current_line).tab_cont,
+ FetchLinesCount,
+ 1);
+
+ swap_lines (text, text->current_line, new_line, old_line_count);
+
+ text->current_line = new_line;
+
+ new_pixels = total_line_height (text, new_line, 1);
+
+ gdk_window_get_size (text->text_area, &width, &height);
+
+ if (old_pixels != new_pixels)
+ {
+ gdk_draw_pixmap (text->text_area,
+ text->gc,
+ text->text_area,
+ 0,
+ pixel_height + old_pixels,
+ 0,
+ pixel_height + new_pixels,
+ width,
+ height);
+
+ text->vadj->upper += new_pixels;
+ text->vadj->upper -= old_pixels;
+ adjust_adj (text, text->vadj);
+ }
+
+ rect.x = 0;
+ rect.y = pixel_height;
+ rect.width = width;
+ rect.height = new_pixels;
+
+ expose_text (text, &rect, FALSE);
+ gtk_text_draw_focus ( (GtkWidget *) text);
+
+ text->cursor_mark = text->point;
+
+ find_cursor (text);
+
+ draw_cursor (text, FALSE);
+
+ TEXT_ASSERT (text);
+ TEXT_SHOW(text);
+}
+
+static void
+correct_cache_insert (GtkText* text)
+{
+ GList* cache = text->current_line;
+
+ for (; cache; cache = cache->next)
+ {
+ GtkPropertyMark *start = &CACHE_DATA(cache).start;
+ GtkPropertyMark *end = &CACHE_DATA(cache).end;
+
+ if (start->index >= text->point.index)
+ {
+ if (start->property == text->point.property)
+ move_mark_n(start, 1);
+ else
+ start->index += 1;
+ }
+
+ if (end->index >= text->point.index)
+ {
+ if (end->property == text->point.property)
+ move_mark_n(end, 1);
+ else
+ end->index += 1;
+ }
+
+ /*TEXT_ASSERT_MARK(text, start, "start");*/
+ /*TEXT_ASSERT_MARK(text, end, "end");*/
+ }
+}
+
+
+static void
+insert_char_line_expose (GtkText* text, gchar key, guint old_pixels)
+{
+ gint pixel_height;
+ guint new_pixels = 0;
+ guint new_line_count = 1 + (key == LINE_DELIM);
+ GdkRectangle rect;
+ GList* new_line = NULL;
+ gint width, height;
+
+ text->cursor_virtual_x = 0;
+
+ undraw_cursor (text, FALSE);
+
+ correct_cache_insert (text);
+
+ TEXT_SHOW_ADJ (text, text->vadj, "vadj");
+
+ pixel_height = pixel_height_of(text, text->current_line) -
+ LINE_HEIGHT(CACHE_DATA(text->current_line));
+
+ new_line = fetch_lines (text,
+ &CACHE_DATA(text->current_line).start,
+ &CACHE_DATA(text->current_line).tab_cont,
+ FetchLinesCount,
+ new_line_count);
+
+ swap_lines (text, text->current_line, new_line, 1);
+
+ text->current_line = new_line;
+
+ new_pixels = total_line_height (text, new_line, new_line_count);
+
+ gdk_window_get_size (text->text_area, &width, &height);
+
+ if (old_pixels != new_pixels)
+ {
+ gdk_draw_pixmap (text->text_area,
+ text->gc,
+ text->text_area,
+ 0,
+ pixel_height + old_pixels,
+ 0,
+ pixel_height + new_pixels,
+ width,
+ height + (old_pixels - new_pixels) - pixel_height);
+
+ text->vadj->upper += new_pixels;
+ text->vadj->upper -= old_pixels;
+ adjust_adj (text, text->vadj);
+ }
+
+ rect.x = 0;
+ rect.y = pixel_height;
+ rect.width = width;
+ rect.height = new_pixels;
+
+ expose_text (text, &rect, FALSE);
+ gtk_text_draw_focus ( (GtkWidget *) text);
+
+ text->cursor_mark = text->point;
+
+ find_cursor (text);
+
+ draw_cursor (text, FALSE);
+
+ TEXT_SHOW_ADJ (text, text->vadj, "vadj");
+ TEXT_ASSERT (text);
+ TEXT_SHOW(text);
+}
+
+static guint
+font_hash (gpointer font)
+{
+ return gdk_font_id ((GdkFont*) font);
+}
+
+static TextFont*
+get_text_font (GdkFont* gfont)
+{
+ static GHashTable *font_cache_table = NULL;
+ TextFont* tf;
+ gpointer lu;
+ gint i;
+
+ if (!font_cache_table)
+ font_cache_table = g_hash_table_new (font_hash, (GCompareFunc) gdk_font_equal);
+
+ lu = g_hash_table_lookup (font_cache_table, gfont);
+
+ if (lu)
+ return (TextFont*)lu;
+
+ tf = g_new (TextFont, 1);
+
+ tf->gdk_font = gfont;
+
+ for(i = 0; i < 256; i += 1)
+ tf->char_widths[i] = gdk_char_width (gfont, (char)i);
+
+ g_hash_table_insert (font_cache_table, gfont, tf);
+
+ return tf;
+}
+
+static gint
+text_properties_equal (TextProperty* prop, GdkFont* font, GdkColor *fore, GdkColor *back)
+{
+ return prop->font == get_text_font(font) &&
+ (fore == prop->fore_color || gdk_color_equal(prop->fore_color, fore)) &&
+ (back == prop->back_color || (back && prop->back_color && gdk_color_equal(prop->back_color, back)));
+}
+
+static TextProperty*
+new_text_property (GdkFont* font, GdkColor* fore, GdkColor* back, guint length)
+{
+ TextProperty *prop;
+
+ if (text_property_chunk == NULL)
+ {
+ text_property_chunk = g_mem_chunk_new ("text property mem chunk",
+ sizeof(TextProperty),
+ 1024*sizeof(TextProperty),
+ G_ALLOC_ONLY);
+ }
+
+ prop = g_chunk_new(TextProperty, text_property_chunk);
+
+ prop->font = get_text_font (font);
+ prop->fore_color = fore;
+ prop->back_color = back;
+ prop->length = length;
+
+ return prop;
+}
+
+/* Flop the memory between the point and the gap around like a
+ * dead fish. */
+static void
+move_gap_to_point (GtkText* text)
+{
+ if (text->gap_position < text->point.index)
+ {
+ gint diff = text->point.index - text->gap_position;
+
+ memmove (text->text + text->gap_position,
+ text->text + text->gap_position + text->gap_size,
+ diff);
+
+ text->gap_position = text->point.index;
+ }
+ else if (text->gap_position > text->point.index)
+ {
+ gint diff = text->gap_position - text->point.index;
+
+ memmove (text->text + text->point.index + text->gap_size,
+ text->text + text->point.index,
+ diff);
+
+ text->gap_position = text->point.index;
+ }
+}
+
+/* Increase the gap size. */
+static void
+make_forward_space (GtkText* text, guint len)
+{
+ if (text->gap_size < len)
+ {
+ guint sum = MAX(2*len, MIN_GAP_SIZE) + text->text_end;
+
+ if (sum >= text->text_len)
+ {
+ guint i = 1;
+
+ while (i <= sum) i <<= 1;
+
+ text->text = (guchar*)g_realloc(text->text, i);
+ }
+
+ memmove (text->text + text->gap_position + text->gap_size + 2*len,
+ text->text + text->gap_position + text->gap_size,
+ text->text_end - (text->gap_position + text->gap_size));
+
+ text->text_end += len*2;
+ text->gap_size += len*2;
+ }
+}
+
+/* Inserts into the text property list a list element that guarantees
+ * that for len characters following the point, text has the correct
+ * property. does not move point. adjusts text_properties_point and
+ * text_properties_point_offset relative to the current value of
+ * point. */
+static void
+insert_text_property (GtkText* text, GdkFont* font,
+ GdkColor *fore, GdkColor* back, guint len)
+{
+ GtkPropertyMark *mark = &text->point;
+ TextProperty* forward_prop = MARK_CURRENT_PROPERTY(mark);
+ TextProperty* backward_prop = MARK_PREV_PROPERTY(mark);
+
+ if (MARK_OFFSET(mark) == 0)
+ {
+ /* Point is on the boundary of two properties.
+ * If it is the same as either, grow, else insert
+ * a new one. */
+
+ if (text_properties_equal(forward_prop, font, fore, back))
+ {
+ /* Grow the property in front of us. */
+
+ MARK_PROPERTY_LENGTH(mark) += len;
+ }
+ else if (backward_prop &&
+ text_properties_equal(backward_prop, font, fore, back))
+ {
+ /* Grow property behind us, point property and offset
+ * change. */
+
+ SET_PROPERTY_MARK (&text->point,
+ MARK_PREV_LIST_PTR (mark),
+ backward_prop->length);
+
+ backward_prop->length += len;
+ }
+ else
+ {
+ /* Splice a new property into the list. */
+
+ GList* new_prop = g_list_alloc();
+
+ new_prop->next = MARK_LIST_PTR(mark);
+ new_prop->prev = MARK_PREV_LIST_PTR(mark);
+ new_prop->next->prev = new_prop;
+
+ if (new_prop->prev)
+ new_prop->prev->next = new_prop;
+
+ new_prop->data = new_text_property (font, fore, back, len);
+
+ SET_PROPERTY_MARK (mark, new_prop, 0);
+ }
+ }
+ else
+ {
+ /* In the middle of forward_prop, if properties are equal,
+ * just add to its length, else split it into two and splice
+ * in a new one. */
+ if (text_properties_equal (forward_prop, font, fore, back))
+ {
+ forward_prop->length += len;
+ }
+ else
+ {
+ GList* new_prop = g_list_alloc();
+ GList* new_prop_forward = g_list_alloc();
+ gint old_length = forward_prop->length;
+ GList* next = MARK_NEXT_LIST_PTR(mark);
+
+ /* Set the new lengths according to where they are split. Construct
+ * two new properties. */
+ forward_prop->length = MARK_OFFSET(mark);
+
+ new_prop_forward->data = new_text_property(forward_prop->font->gdk_font,
+ fore,
+ back,
+ old_length - forward_prop->length);
+
+ new_prop->data = new_text_property(font, fore, back, len);
+
+ /* Now splice things in. */
+ MARK_NEXT_LIST_PTR(mark) = new_prop;
+ new_prop->prev = MARK_LIST_PTR(mark);
+
+ new_prop->next = new_prop_forward;
+ new_prop_forward->prev = new_prop;
+
+ new_prop_forward->next = next;
+
+ if (next)
+ next->prev = new_prop_forward;
+
+ SET_PROPERTY_MARK (mark, new_prop, 0);
+ }
+ }
+
+ while (text->text_properties_end->next)
+ text->text_properties_end = text->text_properties_end->next;
+
+ while (text->text_properties->prev)
+ text->text_properties = text->text_properties->prev;
+}
+
+static void
+delete_text_property (GtkText* text, guint nchars)
+{
+ /* Delete nchars forward from point. */
+ TextProperty *prop;
+ GList *tmp;
+ gint is_first;
+
+ for(; nchars; nchars -= 1)
+ {
+ prop = MARK_CURRENT_PROPERTY(&text->point);
+
+ prop->length -= 1;
+
+ if (prop->length == 0)
+ {
+ tmp = MARK_LIST_PTR (&text->point);
+
+ is_first = tmp == text->text_properties;
+
+ MARK_LIST_PTR (&text->point) = g_list_remove_link (tmp, tmp);
+ text->point.offset = 0;
+
+ g_mem_chunk_free (text_property_chunk, prop);
+
+ prop = MARK_CURRENT_PROPERTY (&text->point);
+
+ if (is_first)
+ text->text_properties = MARK_LIST_PTR (&text->point);
+
+ g_assert (prop->length != 0);
+ }
+ else if (prop->length == text->point.offset)
+ {
+ MARK_LIST_PTR (&text->point) = MARK_NEXT_LIST_PTR (&text->point);
+ text->point.offset = 0;
+ }
+ }
+}
+
+static void
+init_properties (GtkText *text)
+{
+ if (!text->text_properties)
+ {
+ text->text_properties = g_list_alloc();
+ text->text_properties->next = NULL;
+ text->text_properties->prev = NULL;
+ text->text_properties->data = new_text_property (text->widget.style->font,
+ &text->widget.style->fg[GTK_STATE_NORMAL],
+ &text->widget.style->bg[GTK_STATE_NORMAL],
+ 1);
+ text->text_properties_end = text->text_properties;
+
+ SET_PROPERTY_MARK (&text->point, text->text_properties, 0);
+
+ text->point.index = 0;
+ }
+}
+
+
+/**********************************************************************/
+/* Property Movement */
+/**********************************************************************/
+
+static void
+move_mark_n (GtkPropertyMark* mark, gint n)
+{
+ if (n > 0)
+ advance_mark_n(mark, n);
+ else if (n < 0)
+ decrement_mark_n(mark, -n);
+}
+
+static void
+advance_mark_n (GtkPropertyMark* mark, gint n)
+{
+ gint i;
+
+ g_assert (n > 0);
+
+ for (i = 0; i < n; i += 1)
+ advance_mark (mark);
+}
+
+static void
+advance_mark (GtkPropertyMark* mark)
+{
+ TextProperty* prop = MARK_CURRENT_PROPERTY (mark);
+
+ mark->index += 1;
+
+ if (prop->length > mark->offset + 1)
+ mark->offset += 1;
+ else
+ {
+ mark->property = MARK_NEXT_LIST_PTR (mark);
+ mark->offset = 0;
+ }
+}
+
+static void
+decrement_mark (GtkPropertyMark* mark)
+{
+ mark->index -= 1;
+
+ if (mark->offset > 0)
+ mark->offset -= 1;
+ else
+ {
+ mark->property = MARK_PREV_LIST_PTR (mark);
+ mark->offset = MARK_CURRENT_PROPERTY (mark)->length - 1;
+ }
+}
+
+static void
+decrement_mark_n (GtkPropertyMark* mark, gint n)
+{
+ gint i;
+
+ g_assert (n > 0);
+
+ for (i = 0; i < n; i += 1)
+ decrement_mark (mark);
+}
+
+static GtkPropertyMark
+find_mark (GtkText* text, guint mark_position)
+{
+ return find_mark_near (text, mark_position, &text->point);
+}
+
+/* This can be optimized in two ways.
+ * First, advances can be made in units of the current TextProperty
+ * length, when possible. This will reduce computation and function
+ * call overhead.
+ *
+ * You can also start from the end, what a drag.
+ */
+static GtkPropertyMark
+find_mark_near (GtkText* text, guint mark_position, const GtkPropertyMark* near)
+{
+ gint diffa;
+ gint diffb;
+
+ GtkPropertyMark mark;
+
+ if (!near)
+ diffa = mark_position + 1;
+ else
+ diffa = mark_position - near->index;
+
+ diffb = mark_position;
+
+ if (diffa < 0)
+ diffa = -diffa;
+
+ if (diffa <= diffb)
+ {
+ mark = *near;
+ }
+ else
+ {
+ mark.index = 0;
+ mark.property = text->text_properties;
+ mark.offset = 0;
+ }
+
+ if (mark.index > mark_position)
+ {
+ while (mark.index > mark_position)
+ decrement_mark (&mark);
+ }
+ else
+ {
+ while (mark_position > mark.index)
+ advance_mark (&mark);
+ }
+
+ return mark;
+}
+
+static void
+find_line_containing_point (GtkText* text, guint point)
+{
+ GList* cache;
+ gint height;
+
+ text->current_line = NULL;
+
+ if (!text->line_start_cache->next)
+ {
+ /* @@@ Its visible, right? */
+ text->current_line = text->line_start_cache;
+ return;
+ }
+
+ while ( ( (text->first_cut_pixels != 0) &&
+ (CACHE_DATA(text->line_start_cache->next).start.index > point) ) ||
+ ( (text->first_cut_pixels == 0) &&
+ (CACHE_DATA(text->line_start_cache).start.index > point) ) )
+ {
+ scroll_int (text, - SCROLL_PIXELS);
+ g_assert (text->line_start_cache->next);
+ }
+
+ TEXT_SHOW (text);
+ gdk_window_get_size (text->text_area, NULL, &height);
+
+ for (cache = text->line_start_cache; cache; cache = cache->next)
+ {
+ guint lph;
+
+ if (CACHE_DATA(cache).end.index >= point ||
+ LAST_INDEX(text, CACHE_DATA(cache).end))
+ {
+ text->current_line = cache; /* LOOK HERE, this proc has an
+ * important side effect. */
+ return;
+ }
+
+ TEXT_SHOW_LINE (text, cache, "cache");
+
+ lph = pixel_height_of (text, cache->next);
+
+ while (lph > height || lph == 0)
+ {
+ TEXT_SHOW_LINE (text, cache, "cache");
+ TEXT_SHOW_LINE (text, cache->next, "cache->next");
+ scroll_int (text, LINE_HEIGHT(CACHE_DATA(cache->next)));
+ lph = pixel_height_of (text, cache->next);
+ }
+ }
+
+ g_assert (FALSE); /* Must set text->current_line here */
+}
+
+static guint
+pixel_height_of (GtkText* text, GList* cache_line)
+{
+ gint pixels = - text->first_cut_pixels;
+ GList *cache = text->line_start_cache;
+
+ while (TRUE) {
+ pixels += LINE_HEIGHT (CACHE_DATA(cache));
+
+ if (cache->data == cache_line->data)
+ break;
+
+ cache = cache->next;
+ }
+
+ return pixels;
+}
+
+/**********************************************************************/
+/* Search and Placement */
+/**********************************************************************/
+
+static gint
+find_char_width (GtkText* text, const GtkPropertyMark *mark, const TabStopMark *tab_mark)
+{
+ gchar ch = TEXT_INDEX (text, mark->index);
+ gint16* char_widths = MARK_CURRENT_TEXT_FONT (mark)->char_widths;
+
+ if (ch == '\t')
+ {
+ return tab_mark->to_next_tab * char_widths[' '];
+ }
+ else
+ {
+ return char_widths[ch & 0xff];
+ }
+}
+
+static void
+advance_tab_mark (GtkText* text, TabStopMark* tab_mark, gchar ch)
+{
+ if (tab_mark->to_next_tab == 1 || ch == '\t')
+ {
+ if (tab_mark->tab_stops->next)
+ {
+ tab_mark->tab_stops = tab_mark->tab_stops->next;
+ tab_mark->to_next_tab = (gulong) tab_mark->tab_stops->data;
+ }
+ else
+ {
+ tab_mark->to_next_tab = text->default_tab_width;
+ }
+ }
+ else
+ {
+ tab_mark->to_next_tab -= 1;
+ }
+}
+
+static void
+advance_tab_mark_n (GtkText* text, TabStopMark* tab_mark, gint n)
+ /* No tabs! */
+{
+ while (n--)
+ advance_tab_mark (text, tab_mark, 0);
+}
+
+static void
+find_cursor_at_line (GtkText* text, const LineParams* start_line, gint pixel_height)
+{
+ gchar ch;
+
+ GtkPropertyMark mark = start_line->start;
+ TabStopMark tab_mark = start_line->tab_cont.tab_start;
+ gint pixel_width = LINE_START_PIXEL (*start_line);
+
+ while (mark.index < text->cursor_mark.index)
+ {
+ pixel_width += find_char_width (text, &mark, &tab_mark);
+
+ advance_tab_mark (text, &tab_mark, TEXT_INDEX(text, mark.index));
+ advance_mark (&mark);
+ }
+
+ text->cursor_pos_x = pixel_width;
+ text->cursor_pos_y = pixel_height;
+ text->cursor_char_offset = start_line->font_descent;
+ text->cursor_mark = mark;
+
+ ch = TEXT_INDEX (text, mark.index);
+
+ if (!isspace(ch))
+ text->cursor_char = ch;
+ else
+ text->cursor_char = 0;
+}
+
+static void
+find_cursor (GtkText* text)
+{
+ if (!text->has_cursor)
+ return;
+
+ find_line_containing_point (text, text->cursor_mark.index);
+
+ g_assert (text->cursor_mark.index >= text->first_line_start_index);
+
+ if (text->current_line)
+ find_cursor_at_line (text,
+ &CACHE_DATA(text->current_line),
+ pixel_height_of(text, text->current_line));
+}
+
+static void
+mouse_click_1_at_line (GtkText *text, const LineParams* lp,
+ guint line_pixel_height,
+ gint button_x)
+{
+ GtkPropertyMark mark = lp->start;
+ TabStopMark tab_mark = lp->tab_cont.tab_start;
+
+ guint char_width = find_char_width(text, &mark, &tab_mark);
+ guint pixel_width = LINE_START_PIXEL (*lp) + (char_width+1)/2;
+
+ text->cursor_pos_y = line_pixel_height;
+
+ for (;;)
+ {
+ gchar ch = TEXT_INDEX (text, mark.index);
+
+ if (button_x < pixel_width || mark.index == lp->end.index)
+ {
+ text->cursor_pos_x = pixel_width - (char_width+1)/2;
+ text->cursor_mark = mark;
+ text->cursor_char_offset = lp->font_descent;
+
+ if (!isspace(ch))
+ text->cursor_char = ch;
+ else
+ text->cursor_char = 0;
+
+ break;
+ }
+
+ advance_tab_mark (text, &tab_mark, ch);
+ advance_mark (&mark);
+
+ pixel_width += char_width/2;
+
+ char_width = find_char_width (text, &mark, &tab_mark);
+
+ pixel_width += (char_width+1)/2;
+ }
+}
+
+static void
+mouse_click_1 (GtkText* text, GdkEventButton *event)
+{
+ if (text->is_editable)
+ {
+ gint pixel_height;
+ GList* cache = text->line_start_cache;
+
+ g_assert (cache);
+
+ pixel_height = - text->first_cut_pixels;
+
+ text->has_cursor = 1;
+
+ for (; cache; cache = cache->next)
+ {
+ pixel_height += LINE_HEIGHT(CACHE_DATA(cache));
+
+ if (event->y < pixel_height || !cache->next)
+ {
+ mouse_click_1_at_line (text, &CACHE_DATA(cache), pixel_height, event->x);
+
+ find_cursor (text);
+
+ return;
+ }
+ }
+ }
+}
+
+/**********************************************************************/
+/* Cache Manager */
+/**********************************************************************/
+
+static void
+free_cache (GtkText* text)
+{
+ GList* cache = text->line_start_cache;
+
+ for (; cache; cache = cache->next)
+ g_mem_chunk_free (params_mem_chunk, cache->data);
+
+ g_list_free (text->line_start_cache);
+
+ text->line_start_cache = NULL;
+}
+
+static GList*
+remove_cache_line (GtkText* text, GList* member)
+{
+ if (member == text->line_start_cache)
+ {
+ if (text->line_start_cache)
+ text->line_start_cache = text->line_start_cache->next;
+ return text->line_start_cache;
+ }
+ else
+ {
+ GList *list = member->prev;
+
+ list->next = list->next->next;
+ if (list->next)
+ list->next->prev = list;
+
+ member->next = NULL;
+ g_mem_chunk_free (params_mem_chunk, member->data);
+ g_list_free (member);
+
+ return list->next;
+ }
+}
+
+/**********************************************************************/
+/* Key Motion */
+/**********************************************************************/
+
+static void
+move_cursor_buffer_ver (GtkText *text, int dir)
+{
+ if (dir > 0)
+ scroll_int (text, text->vadj->upper);
+ else
+ scroll_int (text, - text->vadj->value);
+}
+
+static void
+move_cursor_page_ver (GtkText *text, int dir)
+{
+ scroll_int (text, dir * text->vadj->page_increment);
+}
+
+static void
+move_cursor_ver (GtkText *text, int count)
+{
+ gint i;
+ GtkPropertyMark mark;
+ gint offset;
+
+ if (!text->has_cursor)
+ {
+ scroll_int (text, count * KEY_SCROLL_PIXELS);
+ return;
+ }
+
+ mark = find_this_line_start_mark (text, text->cursor_mark.index, &text->cursor_mark);
+ offset = text->cursor_mark.index - mark.index;
+
+ if (offset > text->cursor_virtual_x)
+ text->cursor_virtual_x = offset;
+
+ if (count < 0)
+ {
+ if (mark.index == 0)
+ return;
+
+ decrement_mark (&mark);
+ mark = find_this_line_start_mark (text, mark.index, &mark);
+ }
+ else
+ {
+ mark = text->cursor_mark;
+
+ while (!LAST_INDEX(text, mark) && TEXT_INDEX(text, mark.index) != LINE_DELIM)
+ advance_mark (&mark);
+
+ if (LAST_INDEX(text, mark))
+ return;
+
+ advance_mark (&mark);
+ }
+
+ for (i=0; i < text->cursor_virtual_x; i += 1, advance_mark(&mark))
+ if (LAST_INDEX(text, mark) || TEXT_INDEX(text, mark.index) == LINE_DELIM)
+ break;
+
+ undraw_cursor (text, FALSE);
+
+ text->cursor_mark = mark;
+
+ find_cursor (text);
+
+ draw_cursor (text, FALSE);
+}
+
+static void
+move_cursor_hor (GtkText *text, int count)
+{
+ /* count should be +-1. */
+ if (!text->has_cursor)
+ return;
+
+ if ( (count > 0 && text->cursor_mark.index + count > TEXT_LENGTH(text)) ||
+ (count < 0 && text->cursor_mark.index < (- count)) ||
+ (count == 0) )
+ return;
+
+ text->cursor_virtual_x = 0;
+
+ undraw_cursor (text, FALSE);
+
+ move_mark_n (&text->cursor_mark, count);
+
+ find_cursor (text);
+
+ draw_cursor (text, FALSE);
+}
+
+/**********************************************************************/
+/* Scrolling */
+/**********************************************************************/
+
+static void
+adjust_adj (GtkText* text, GtkAdjustment* adj)
+{
+ gint height;
+
+ gdk_window_get_size (text->text_area, NULL, &height);
+
+ adj->step_increment = MIN (adj->upper, (float) SCROLL_PIXELS);
+ adj->page_increment = MIN (adj->upper, height - (float) KEY_SCROLL_PIXELS);
+ adj->page_size = MIN (adj->upper, height);
+ adj->value = MIN (adj->value, adj->upper - adj->page_size);
+ adj->value = MAX (adj->value, 0.0);
+
+ gtk_signal_emit_by_name (GTK_OBJECT (adj), "changed");
+}
+
+static gint
+set_vertical_scroll_iterator (GtkText* text, LineParams* lp, void* data)
+{
+ gint *pixel_count = (gint*) data;
+
+ if (text->first_line_start_index == lp->start.index)
+ text->vadj->value = (float) *pixel_count;
+
+ *pixel_count += LINE_HEIGHT (*lp);
+
+ return FALSE;
+}
+
+static gint
+set_vertical_scroll_find_iterator (GtkText* text, LineParams* lp, void* data)
+{
+ SetVerticalScrollData *svdata = (SetVerticalScrollData *) data;
+ gint return_val;
+
+ if (svdata->last_didnt_wrap)
+ svdata->last_line_start = lp->start.index;
+
+ if (svdata->pixel_height <= (gint) text->vadj->value &&
+ svdata->pixel_height + LINE_HEIGHT(*lp) > (gint) text->vadj->value)
+ {
+ svdata->mark = lp->start;
+
+ text->first_cut_pixels = (gint)text->vadj->value - svdata->pixel_height;
+ text->first_onscreen_ver_pixel = svdata->pixel_height;
+ text->first_line_start_index = svdata->last_line_start;
+
+ return_val = TRUE;
+ }
+ else
+ {
+ svdata->pixel_height += LINE_HEIGHT (*lp);
+
+ return_val = FALSE;
+ }
+
+ if (!lp->wraps)
+ svdata->last_didnt_wrap = TRUE;
+ else
+ svdata->last_didnt_wrap = FALSE;
+
+ return return_val;
+}
+
+static GtkPropertyMark
+set_vertical_scroll (GtkText* text)
+{
+ GtkPropertyMark mark = find_mark (text, 0);
+ SetVerticalScrollData data;
+ gint height;
+ gint pixel_count = 0;
+ gint orig_value;
+
+ line_params_iterate (text, &mark, NULL, FALSE, &pixel_count, set_vertical_scroll_iterator);
+
+ text->vadj->upper = (float) pixel_count;
+ orig_value = (gint) text->vadj->value;
+
+ gdk_window_get_size (text->text_area, NULL, &height);
+
+ text->vadj->step_increment = MIN (text->vadj->upper, (float) SCROLL_PIXELS);
+ text->vadj->page_increment = MIN (text->vadj->upper, height - (float) KEY_SCROLL_PIXELS);
+ text->vadj->page_size = MIN (text->vadj->upper, height);
+ text->vadj->value = MIN (text->vadj->value, text->vadj->upper - text->vadj->page_size);
+ text->vadj->value = MAX (text->vadj->value, 0.0);
+
+ text->last_ver_value = (gint)text->vadj->value;
+ text->first_cut_pixels = 0;
+
+ gtk_signal_emit_by_name (GTK_OBJECT (text->vadj), "changed");
+
+ if (text->vadj->value != orig_value)
+ {
+ /* We got clipped, and don't really know which line to put first. */
+ data.pixel_height = 0;
+ data.last_didnt_wrap = TRUE;
+
+ line_params_iterate (text, &mark, NULL,
+ FALSE, &data,
+ set_vertical_scroll_find_iterator);
+
+ return data.mark;
+ }
+ else
+ {
+ return find_mark (text, text->first_line_start_index);
+ }
+}
+
+static void
+scroll_int (GtkText* text, gint diff)
+{
+ gfloat upper;
+
+ text->vadj->value += diff;
+
+ upper = text->vadj->upper - text->vadj->page_size;
+ text->vadj->value = MIN (text->vadj->value, upper);
+ text->vadj->value = MAX (text->vadj->value, 0.0);
+
+ gtk_signal_emit_by_name (GTK_OBJECT (text->vadj), "value_changed");
+}
+
+static gint last_visible_line_height (GtkText* text)
+{
+ GList *cache = text->line_start_cache;
+ gint height;
+
+ gdk_window_get_size (text->text_area, NULL, &height);
+
+ for (; cache->next; cache = cache->next)
+ if (pixel_height_of(text, cache->next) > height)
+ break;
+
+ if (cache)
+ return pixel_height_of(text, cache) - 1;
+ else
+ return 0;
+}
+
+static gint first_visible_line_height (GtkText* text)
+{
+ if (text->first_cut_pixels)
+ return pixel_height_of(text, text->line_start_cache) + 1;
+ else
+ return 1;
+}
+
+static void
+scroll_down (GtkText* text, gint diff0)
+{
+ GdkRectangle rect;
+ gint real_diff = 0;
+ gint width, height;
+
+ text->first_onscreen_ver_pixel += diff0;
+
+ while (diff0-- > 0)
+ {
+ g_assert (text->line_start_cache &&
+ text->line_start_cache->next);
+
+ if (text->first_cut_pixels < LINE_HEIGHT(CACHE_DATA(text->line_start_cache)) - 1)
+ {
+ text->first_cut_pixels += 1;
+ }
+ else
+ {
+ text->first_cut_pixels = 0;
+
+ text->line_start_cache = text->line_start_cache->next;
+
+ text->first_line_start_index =
+ CACHE_DATA(text->line_start_cache).start.index;
+
+ if (!text->line_start_cache->next)
+ fetch_lines_forward (text, 1);
+ }
+
+ real_diff += 1;
+ }
+
+ gdk_window_get_size (text->text_area, &width, &height);
+ if (height > real_diff)
+ gdk_draw_pixmap (text->text_area,
+ text->gc,
+ text->text_area,
+ 0,
+ real_diff,
+ 0,
+ 0,
+ width,
+ height - real_diff);
+
+ rect.x = 0;
+ rect.y = MAX (0, height - real_diff);
+ rect.width = width;
+ rect.height = MIN (height, real_diff);
+
+ expose_text (text, &rect, FALSE);
+ gtk_text_draw_focus ( (GtkWidget *) text);
+
+ if (text->current_line)
+ {
+ gint cursor_min;
+
+ text->cursor_pos_y -= real_diff;
+ cursor_min = drawn_cursor_min(text);
+
+ if (cursor_min < 0)
+ {
+ GdkEventButton button;
+
+ button.x = text->cursor_pos_x;
+ button.y = first_visible_line_height (text);
+
+ mouse_click_1 (text, &button);
+ }
+ }
+}
+
+static void
+scroll_up (GtkText* text, gint diff0)
+{
+ gint real_diff = 0;
+ GdkRectangle rect;
+ gint width, height;
+
+ text->first_onscreen_ver_pixel += diff0;
+
+ while (diff0++ < 0)
+ {
+ g_assert (text->line_start_cache);
+
+ if (text->first_cut_pixels > 0)
+ {
+ text->first_cut_pixels -= 1;
+ }
+ else
+ {
+ if (!text->line_start_cache->prev)
+ fetch_lines_backward (text);
+
+ text->line_start_cache = text->line_start_cache->prev;
+
+ text->first_line_start_index =
+ CACHE_DATA(text->line_start_cache).start.index;
+
+ text->first_cut_pixels = LINE_HEIGHT(CACHE_DATA(text->line_start_cache)) - 1;
+ }
+
+ real_diff += 1;
+ }
+
+ gdk_window_get_size (text->text_area, &width, &height);
+ if (height > real_diff)
+ gdk_draw_pixmap (text->text_area,
+ text->gc,
+ text->text_area,
+ 0,
+ 0,
+ 0,
+ real_diff,
+ width,
+ height - real_diff);
+
+ rect.x = 0;
+ rect.y = 0;
+ rect.width = width;
+ rect.height = MIN (height, real_diff);
+
+ expose_text (text, &rect, FALSE);
+ gtk_text_draw_focus ( (GtkWidget *) text);
+
+ if (text->current_line)
+ {
+ gint cursor_max;
+ gint height;
+
+ text->cursor_pos_y += real_diff;
+ cursor_max = drawn_cursor_max(text);
+ gdk_window_get_size (text->text_area, NULL, &height);
+
+ if (cursor_max >= height)
+ {
+ GdkEventButton button;
+
+ button.x = text->cursor_pos_x;
+ button.y = last_visible_line_height(text);
+
+ mouse_click_1 (text, &button);
+ }
+ }
+}
+
+/**********************************************************************/
+/* Display Code */
+/**********************************************************************/
+
+/* Assumes mark starts a line. Calculates the height, width, and
+ * displayable character count of a single DISPLAYABLE line. That
+ * means that in line-wrap mode, this does may not compute the
+ * properties of an entire line. */
+static LineParams
+find_line_params (GtkText* text,
+ const GtkPropertyMark* mark,
+ const PrevTabCont *tab_cont,
+ PrevTabCont *next_cont)
+{
+ LineParams lp;
+ TabStopMark tab_mark = tab_cont->tab_start;
+ guint max_display_pixels;
+ gchar ch;
+ gint ch_width;
+ GdkFont *font;
+
+ gdk_window_get_size (text->text_area, (gint*) &max_display_pixels, NULL);
+ max_display_pixels -= LINE_WRAP_ROOM;
+
+ lp.wraps = 0;
+ lp.tab_cont = *tab_cont;
+ lp.start = *mark;
+ lp.end = *mark;
+ lp.pixel_width = tab_cont->pixel_offset;
+ lp.displayable_chars = 0;
+ lp.font_ascent = 0;
+ lp.font_descent = 0;
+
+ init_tab_cont (text, next_cont);
+
+ while (!LAST_INDEX(text, lp.end))
+ {
+ g_assert (lp.end.property);
+
+ ch = TEXT_INDEX (text, lp.end.index);
+ font = MARK_CURRENT_FONT (&lp.end);
+
+ if (ch == LINE_DELIM)
+ {
+ /* Newline doesn't count in computation of line height, even
+ * if its in a bigger font than the rest of the line. Unless,
+ * of course, there are no other characters. */
+
+ if (!lp.font_ascent && !lp.font_descent)
+ {
+ lp.font_ascent = font->ascent;
+ lp.font_descent = font->descent;
+ }
+
+ lp.tab_cont_next = *next_cont;
+
+ return lp;
+ }
+
+ ch_width = find_char_width (text, &lp.end, &tab_mark);
+
+ if (ch_width + lp.pixel_width > max_display_pixels)
+ {
+ lp.wraps = 1;
+
+ if (text->line_wrap)
+ {
+ next_cont->tab_start = tab_mark;
+ next_cont->pixel_offset = 0;
+
+ if (ch == '\t')
+ {
+ /* Here's the tough case, a tab is wrapping. */
+ gint pixels_avail = max_display_pixels - lp.pixel_width;
+ gint space_width = MARK_CURRENT_TEXT_FONT(&lp.end)->char_widths[' '];
+ gint spaces_avail = pixels_avail / space_width;
+
+ if (spaces_avail == 0)
+ {
+ decrement_mark (&lp.end);
+ }
+ else
+ {
+ advance_tab_mark (text, &next_cont->tab_start, '\t');
+ next_cont->pixel_offset = space_width * (tab_mark.to_next_tab -
+ spaces_avail);
+ lp.displayable_chars += 1;
+ }
+ }
+ else
+ {
+ /* Don't include this character, it will wrap. */
+ decrement_mark (&lp.end);
+ }
+
+ lp.tab_cont_next = *next_cont;
+
+ return lp;
+ }
+ }
+ else
+ {
+ lp.displayable_chars += 1;
+ }
+
+ lp.font_ascent = MAX (font->ascent, lp.font_ascent);
+ lp.font_descent = MAX (font->descent, lp.font_descent);
+ lp.pixel_width += ch_width;
+
+ advance_mark(&lp.end);
+ advance_tab_mark (text, &tab_mark, ch);
+ }
+
+ if (LAST_INDEX(text, lp.start))
+ {
+ /* Special case, empty last line. */
+ font = MARK_CURRENT_FONT (&lp.end);
+
+ lp.font_ascent = font->ascent;
+ lp.font_descent = font->descent;
+ }
+
+ lp.tab_cont_next = *next_cont;
+
+ return lp;
+}
+
+static void
+expand_scratch_buffer (GtkText* text, guint len)
+{
+ if (len >= text->scratch_buffer_len)
+ {
+ guint i = 1;
+
+ while (i <= len && i < MIN_GAP_SIZE) i <<= 1;
+
+ if (text->scratch_buffer)
+ text->scratch_buffer = g_new (guchar, i);
+ else
+ text->scratch_buffer = g_realloc (text->scratch_buffer, i);
+
+ text->scratch_buffer_len = i;
+ }
+}
+
+static void
+draw_line (GtkText* text,
+ gint pixel_start_height,
+ LineParams* lp)
+{
+ GdkGCValues gc_values;
+ gint i;
+ gint len = 0;
+ guint running_offset = lp->tab_cont.pixel_offset;
+ guchar* buffer;
+
+ GtkPropertyMark mark = lp->start;
+ TabStopMark tab_mark = lp->tab_cont.tab_start;
+ gint pixel_height = pixel_start_height + lp->font_ascent;
+ guint chars = lp->displayable_chars;
+
+ /* First provide a contiguous segment of memory. This makes reading
+ * the code below *much* easier, and only incurs the cost of copying
+ * when the line being displayed spans the gap. */
+ if (mark.index <= text->gap_position &&
+ mark.index + chars > text->gap_position)
+ {
+ expand_scratch_buffer (text, chars);
+
+ for (i = 0; i < chars; i += 1)
+ text->scratch_buffer[i] = TEXT_INDEX(text, mark.index + i);
+
+ buffer = text->scratch_buffer;
+ }
+ else
+ {
+ if (mark.index >= text->gap_position)
+ buffer = text->text + mark.index + text->gap_size;
+ else
+ buffer = text->text + mark.index;
+ }
+
+ if (running_offset > 0 && MARK_CURRENT_BACK (&mark))
+ {
+ gdk_gc_set_foreground (text->gc, MARK_CURRENT_BACK (&mark));
+
+ gdk_draw_rectangle (text->text_area,
+ text->gc,
+ TRUE,
+ 0,
+ pixel_start_height,
+ running_offset,
+ LINE_HEIGHT (*lp));
+ }
+
+ for (; chars > 0; chars -= len, buffer += len, len = 0)
+ {
+ if (buffer[0] != '\t')
+ {
+ guchar* next_tab = memchr (buffer, '\t', chars);
+ gint pixel_width;
+ GdkFont *font;
+
+ len = MIN (MARK_CURRENT_PROPERTY (&mark)->length - mark.offset, chars);
+
+ if (next_tab)
+ len = MIN (len, next_tab - buffer);
+
+ font = MARK_CURRENT_PROPERTY (&mark)->font->gdk_font;
+ if (font->type == GDK_FONT_FONT)
+ {
+ gdk_gc_set_font (text->gc, font);
+ gdk_gc_get_values (text->gc, &gc_values);
+ pixel_width = gdk_text_width (gc_values.font,
+ (gchar*) buffer, len);
+ }
+ else
+ pixel_width = gdk_text_width (font, (gchar*) buffer, len);
+
+ if (MARK_CURRENT_BACK (&mark))
+ {
+ gdk_gc_set_foreground (text->gc, MARK_CURRENT_BACK (&mark));
+
+ gdk_draw_rectangle (text->text_area,
+ text->gc,
+ TRUE,
+ running_offset,
+ pixel_start_height,
+ pixel_width,
+ LINE_HEIGHT(*lp));
+ }
+
+ gdk_gc_set_foreground (text->gc, MARK_CURRENT_FORE (&mark));
+
+ gdk_draw_text (text->text_area, MARK_CURRENT_FONT (&mark),
+ text->gc,
+ running_offset,
+ pixel_height,
+ (gchar*) buffer,
+ len);
+
+ running_offset += pixel_width;
+
+ advance_tab_mark_n (text, &tab_mark, len);
+ }
+ else
+ {
+ len = 1;
+
+ if (MARK_CURRENT_BACK (&mark))
+ {
+ gint pixels_remaining;
+ gint space_width;
+ gint spaces_avail;
+
+ gdk_window_get_size (text->text_area, &pixels_remaining, NULL);
+ pixels_remaining -= (LINE_WRAP_ROOM + running_offset);
+
+ space_width = MARK_CURRENT_TEXT_FONT(&mark)->char_widths[' '];
+
+ spaces_avail = pixels_remaining / space_width;
+ spaces_avail = MIN (spaces_avail, tab_mark.to_next_tab);
+
+ gdk_gc_set_foreground (text->gc, MARK_CURRENT_BACK (&mark));
+
+ gdk_draw_rectangle (text->text_area,
+ text->gc,
+ TRUE,
+ running_offset,
+ pixel_start_height,
+ spaces_avail * space_width,
+ LINE_HEIGHT (*lp));
+ }
+
+ running_offset += tab_mark.to_next_tab *
+ MARK_CURRENT_TEXT_FONT(&mark)->char_widths[' '];
+
+ advance_tab_mark (text, &tab_mark, '\t');
+ }
+
+ advance_mark_n (&mark, len);
+ }
+}
+
+static void
+draw_line_wrap (GtkText* text, guint height /* baseline height */)
+{
+ gint width;
+ GdkPixmap *bitmap;
+ gint bitmap_width;
+ gint bitmap_height;
+
+ if (text->line_wrap)
+ {
+ bitmap = text->line_wrap_bitmap;
+ bitmap_width = line_wrap_width;
+ bitmap_height = line_wrap_height;
+ }
+ else
+ {
+ bitmap = text->line_arrow_bitmap;
+ bitmap_width = line_arrow_width;
+ bitmap_height = line_arrow_height;
+ }
+
+ gdk_window_get_size (text->text_area, &width, NULL);
+ width -= LINE_WRAP_ROOM;
+
+ gdk_gc_set_stipple (text->gc,
+ bitmap);
+
+ gdk_gc_set_fill (text->gc, GDK_STIPPLED);
+
+ gdk_gc_set_foreground (text->gc, &text->widget.style->fg[GTK_STATE_NORMAL]);
+
+ gdk_gc_set_ts_origin (text->gc,
+ width + 1,
+ height - bitmap_height - 1);
+
+ gdk_draw_rectangle (text->text_area,
+ text->gc,
+ TRUE,
+ width + 1,
+ height - bitmap_height - 1 /* one pixel above the baseline. */,
+ bitmap_width,
+ bitmap_height);
+
+ gdk_gc_set_ts_origin (text->gc, 0, 0);
+
+ gdk_gc_set_fill (text->gc, GDK_SOLID);
+}
+
+static void
+undraw_cursor (GtkText* text, gint absolute)
+{
+ TDEBUG (("in undraw_cursor\n"));
+
+ if (absolute)
+ text->cursor_drawn_level = 0;
+
+ if (text->has_cursor && (text->cursor_drawn_level ++ == 0))
+ {
+ GdkFont* font;
+
+ g_assert(text->cursor_mark.property);
+
+ font = MARK_CURRENT_FONT(&text->cursor_mark);
+
+ if (text->widget.style->bg_pixmap[GTK_STATE_NORMAL])
+ {
+ GdkRectangle rect;
+
+ rect.x = text->cursor_pos_x;
+ rect.y = text->cursor_pos_y - text->cursor_char_offset - font->ascent;
+ rect.width = 1;
+ rect.height = font->ascent + 1; /* @@@ I add one here because draw_line is inclusive, right? */
+
+ clear_area (text, &rect);
+ }
+ else
+ {
+ if (MARK_CURRENT_BACK (&text->cursor_mark))
+ gdk_gc_set_foreground (text->gc, MARK_CURRENT_BACK (&text->cursor_mark));
+ else
+ gdk_gc_set_foreground (text->gc, &text->widget.style->bg[GTK_STATE_NORMAL]);
+
+ gdk_draw_line (text->text_area, text->gc, text->cursor_pos_x,
+ text->cursor_pos_y - text->cursor_char_offset, text->cursor_pos_x,
+ text->cursor_pos_y - text->cursor_char_offset - font->ascent);
+ }
+
+ if (text->cursor_char)
+ {
+ if (font->type == GDK_FONT_FONT)
+ gdk_gc_set_font (text->gc, font);
+
+ gdk_gc_set_foreground (text->gc, MARK_CURRENT_FORE (&text->cursor_mark));
+
+ gdk_draw_text (text->text_area, font,
+ text->gc,
+ text->cursor_pos_x,
+ text->cursor_pos_y - text->cursor_char_offset,
+ &text->cursor_char,
+ 1);
+ }
+ }
+}
+
+static gint
+drawn_cursor_min (GtkText* text)
+{
+ if (text->has_cursor)
+ {
+ GdkFont* font;
+
+ g_assert(text->cursor_mark.property);
+
+ font = MARK_CURRENT_FONT(&text->cursor_mark);
+
+ return text->cursor_pos_y - text->cursor_char_offset - font->ascent;
+ }
+ else
+ return 0;
+}
+
+static gint
+drawn_cursor_max (GtkText* text)
+{
+ if (text->has_cursor)
+ {
+ GdkFont* font;
+
+ g_assert(text->cursor_mark.property);
+
+ font = MARK_CURRENT_FONT(&text->cursor_mark);
+
+ return text->cursor_pos_y - text->cursor_char_offset;
+ }
+ else
+ return 0;
+}
+
+static void
+draw_cursor (GtkText* text, gint absolute)
+{
+ TDEBUG (("in draw_cursor\n"));
+
+ if (absolute)
+ text->cursor_drawn_level = 1;
+
+ if (text->has_cursor && (--text->cursor_drawn_level == 0))
+ {
+ GdkFont* font;
+
+ g_assert (text->cursor_mark.property);
+
+ font = MARK_CURRENT_FONT (&text->cursor_mark);
+
+ gdk_gc_set_foreground (text->gc, &text->widget.style->fg[GTK_STATE_NORMAL]);
+
+ gdk_draw_line (text->text_area, text->gc, text->cursor_pos_x,
+ text->cursor_pos_y - text->cursor_char_offset,
+ text->cursor_pos_x,
+ text->cursor_pos_y - text->cursor_char_offset - font->ascent);
+ }
+}
+
+static void
+clear_area (GtkText *text, GdkRectangle *area)
+{
+ if (text->widget.style->bg_pixmap[GTK_STATE_NORMAL])
+ {
+ gint width, height;
+ gint x = area->x, y = area->y;
+ gint xorig, yorig;
+
+ gdk_window_get_size (text->widget.style->bg_pixmap[GTK_STATE_NORMAL], &width, &height);
+
+ yorig = - text->first_onscreen_ver_pixel;
+ xorig = - text->first_onscreen_hor_pixel;
+
+ for (y = area->y; y < area->y + area->height; )
+ {
+ gint yoff = (y - yorig) % height;
+ gint yw = MIN(height - yoff, (area->y + area->height) - y);
+
+ for (x = area->x; x < area->x + area->width; )
+ {
+ gint xoff = (x - xorig) % width;
+ gint xw = MIN(width - xoff, (area->x + area->width) - x);
+
+ gdk_draw_pixmap (text->text_area,
+ text->gc,
+ text->widget.style->bg_pixmap[GTK_STATE_NORMAL],
+ xoff,
+ yoff,
+ x,
+ y,
+ xw,
+ yw);
+
+ x += width - xoff;
+ }
+ y += height - yoff;
+ }
+ }
+ else
+ gdk_window_clear_area (text->text_area, area->x, area->y, area->width, area->height);
+}
+
+static void
+expose_text (GtkText* text, GdkRectangle *area, gboolean cursor)
+{
+ GList *cache = text->line_start_cache;
+ gint pixels = - text->first_cut_pixels;
+ gint min_y = area->y;
+ gint max_y = area->y + area->height;
+ gint height;
+
+ gdk_window_get_size (text->text_area, NULL, &height);
+ max_y = MIN (max_y, height);
+
+ TDEBUG (("in expose x=%d y=%d w=%d h=%d\n", area->x, area->y, area->width, area->height));
+
+ clear_area (text, area);
+
+ for (; pixels < height; cache = cache->next)
+ {
+ if (pixels < max_y && (pixels + LINE_HEIGHT(CACHE_DATA(cache))) >= min_y)
+ {
+ draw_line (text, pixels, &CACHE_DATA(cache));
+
+ if (CACHE_DATA(cache).wraps)
+ draw_line_wrap (text, pixels + CACHE_DATA(cache).font_ascent);
+ }
+
+ if (cursor && text->has_cursor && GTK_WIDGET_HAS_FOCUS (&text->widget))
+ {
+ if (CACHE_DATA(cache).start.index <= text->cursor_mark.index &&
+ CACHE_DATA(cache).end.index >= text->cursor_mark.index)
+ draw_cursor (text, TRUE);
+ }
+
+ pixels += LINE_HEIGHT(CACHE_DATA(cache));
+
+ if (!cache->next)
+ {
+ fetch_lines_forward (text, 1);
+
+ if (!cache->next)
+ break;
+ }
+ }
+}
+
+static void
+recompute_geometry (GtkText* text)
+{
+ GtkPropertyMark start_mark;
+ gint height;
+ gint width;
+
+ free_cache (text);
+
+ start_mark = set_vertical_scroll (text);
+
+ gdk_window_get_size (text->text_area, &width, &height);
+
+ text->line_start_cache = fetch_lines (text,
+ &start_mark,
+ NULL,
+ FetchLinesPixels,
+ height + text->first_cut_pixels);
+
+ find_cursor (text);
+}
+
+/**********************************************************************/
+/* Selection */
+/**********************************************************************/
+
+static gint
+gtk_text_selection_clear (GtkWidget *widget,
+ GdkEventSelection *event)
+{
+#if 0
+ GtkEntry *entry;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ entry = GTK_ENTRY (widget);
+
+ if (entry->have_selection)
+ {
+ entry->have_selection = FALSE;
+ gtk_entry_queue_draw (entry);
+ }
+#endif
+ return FALSE;
+}
+
+static gint
+gtk_text_selection_request (GtkWidget *widget,
+ GdkEventSelection *event)
+{
+#if 0
+
+ GtkEntry *entry;
+ gint selection_start_pos;
+ gint selection_end_pos;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ entry = GTK_ENTRY (widget);
+ if (entry->selection_start_pos != entry->selection_end_pos)
+ {
+ selection_start_pos = MIN (entry->selection_start_pos, entry->selection_end_pos);
+ selection_end_pos = MAX (entry->selection_start_pos, entry->selection_end_pos);
+
+ gdk_selection_set (event->requestor, event->selection,
+ event->property, event->time,
+ (guchar*) &entry->text[selection_start_pos],
+ selection_end_pos - selection_start_pos);
+ }
+#endif
+ return FALSE;
+}
+
+static gint
+gtk_text_selection_notify (GtkWidget *widget,
+ GdkEventSelection *event)
+{
+#if 0
+ GtkEntry *entry;
+ gchar *data;
+ gint tmp_pos;
+ gint reselect;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ entry = GTK_ENTRY (widget);
+
+ gdk_selection_get (widget->window, (guchar**) &data);
+
+ reselect = FALSE;
+ if (entry->selection_start_pos != entry->selection_end_pos)
+ {
+ reselect = TRUE;
+ gtk_delete_selection (entry);
+ }
+
+ tmp_pos = entry->current_pos;
+ gtk_entry_insert_text (entry, data, strlen (data), &tmp_pos);
+
+ if (reselect)
+ {
+ reselect = entry->have_selection;
+ gtk_select_region (entry, entry->current_pos, tmp_pos);
+ entry->have_selection = reselect;
+ }
+
+ entry->current_pos = tmp_pos;
+
+ gtk_entry_queue_draw (entry);
+#endif
+ return FALSE;
+}
+
+/**********************************************************************/
+/* Debug */
+/**********************************************************************/
+
+#ifdef DEBUG_GTK_TEXT
+static void
+gtk_text_show_cache_line (GtkText *text, GList *cache,
+ const char* what, const char* func, gint line)
+{
+ LineParams *lp = &CACHE_DATA(cache);
+ gint i;
+
+ g_print ("%s:%d: cache line %s s=%d,e=%d,lh=%d (",
+ func,
+ line,
+ what,
+ lp->start.index,
+ lp->end.index,
+ LINE_HEIGHT(*lp));
+
+ for (i = lp->start.index; i < (lp->end.index + lp->wraps); i += 1)
+ g_print ("%c", TEXT_INDEX (text, i));
+
+ g_print (")\n");
+}
+
+static void
+gtk_text_show_cache (GtkText *text, const char* func, gint line)
+{
+ GList *l = text->line_start_cache;
+
+ g_print ("*** line cache ***\n");
+ for (; l; l = l->next)
+ gtk_text_show_cache_line (text, l, "all", func, line);
+}
+
+static void
+gtk_text_assert_mark (GtkText *text,
+ GtkPropertyMark *mark,
+ GtkPropertyMark *before,
+ GtkPropertyMark *after,
+ const gchar *msg,
+ const gchar *where,
+ gint line)
+{
+ GtkPropertyMark correct_mark = find_mark (text, mark->index);
+
+ if (mark->offset != correct_mark.offset ||
+ mark->property != correct_mark.property)
+ g_warning ("incorrect %s text property marker in %s:%d, index %d -- bad!", where, msg, line, mark->index);
+}
+
+static void
+gtk_text_assert (GtkText *text,
+ const gchar *msg,
+ gint line)
+{
+ GList* cache = text->line_start_cache;
+ GtkPropertyMark* before_mark = NULL;
+ GtkPropertyMark* after_mark = NULL;
+
+ gtk_text_show_props (text, msg, line);
+
+ for (; cache->prev; cache = cache->prev)
+ /* nothing */;
+
+ g_print ("*** line markers ***\n");
+
+ for (; cache; cache = cache->next)
+ {
+ after_mark = &CACHE_DATA(cache).end;
+ gtk_text_assert_mark (text, &CACHE_DATA(cache).start, before_mark, after_mark, msg, "start", line);
+ before_mark = &CACHE_DATA(cache).start;
+
+ if (cache->next)
+ after_mark = &CACHE_DATA(cache->next).start;
+ else
+ after_mark = NULL;
+
+ gtk_text_assert_mark (text, &CACHE_DATA(cache).end, before_mark, after_mark, msg, "end", line);
+ before_mark = &CACHE_DATA(cache).end;
+ }
+}
+
+static void
+gtk_text_show_adj (GtkText *text,
+ GtkAdjustment *adj,
+ const char* what,
+ const char* func,
+ gint line)
+{
+ g_print ("*** adjustment ***\n");
+
+ g_print ("%s:%d: %s adjustment l=%.1f u=%.1f v=%.1f si=%.1f pi=%.1f ps=%.1f\n",
+ func,
+ line,
+ what,
+ adj->lower,
+ adj->upper,
+ adj->value,
+ adj->step_increment,
+ adj->page_increment,
+ adj->page_size);
+}
+
+static void
+gtk_text_show_props (GtkText *text,
+ const char* msg,
+ int line)
+{
+ GList* props = text->text_properties;
+ int proplen = 0;
+
+ g_print ("%s:%d: ", msg, line);
+
+ for (; props; props = props->next)
+ {
+ TextProperty *p = (TextProperty*)props->data;
+
+ proplen += p->length;
+
+ g_print ("[%d,%p,%p,%p,%p] ", p->length, p, p->font, p->fore_color, p->back_color);
+ }
+
+ g_print ("\n");
+
+ if (proplen - 1 != TEXT_LENGTH(text))
+ g_warning ("incorrect property list length in %s:%d -- bad!", msg, line);
+}
+#endif
diff --git a/gtk/gtktext.h b/gtk/gtktext.h
new file mode 100644
index 000000000..012d679a3
--- /dev/null
+++ b/gtk/gtktext.h
@@ -0,0 +1,204 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_TEXT_H__
+#define __GTK_TEXT_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkadjustment.h>
+#include <gtk/gtkwidget.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_TEXT(obj) GTK_CHECK_CAST (obj, gtk_text_get_type (), GtkText)
+#define GTK_TEXT_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_text_get_type (), GtkTextClass)
+#define GTK_IS_TEXT(obj) GTK_CHECK_TYPE (obj, gtk_text_get_type ())
+
+
+typedef struct _GtkPropertyMark GtkPropertyMark;
+typedef struct _GtkText GtkText;
+typedef struct _GtkTextClass GtkTextClass;
+
+typedef void (*GtkTextFunction) (GtkText *text);
+
+struct _GtkPropertyMark
+{
+ /* Position in list. */
+ GList* property;
+
+ /* Offset into that property. */
+ guint offset;
+
+ /* Current index. */
+ guint index;
+};
+
+struct _GtkText
+{
+ GtkWidget widget;
+
+ GdkWindow *text_area;
+
+ GtkAdjustment *hadj;
+ GtkAdjustment *vadj;
+
+ GdkGC *gc;
+
+ GdkPixmap* line_wrap_bitmap;
+ GdkPixmap* line_arrow_bitmap;
+
+ /* GAPPED TEXT SEGMENT */
+
+ /* The text, a single segment of text a'la emacs, with a gap
+ * where insertion occurs. */
+ guchar* text;
+ /* The allocated length of the text segment. */
+ guint text_len;
+ /* The gap position, index into address where a char
+ * should be inserted. */
+ guint gap_position;
+ /* The gap size, s.t. *(text + gap_position + gap_size) is
+ * the first valid character following the gap. */
+ guint gap_size;
+ /* The last character position, index into address where a
+ * character should be appeneded. Thus, text_end - gap_size
+ * is the length of the actual data. */
+ guint text_end;
+ /* LINE START CACHE */
+
+ /* A cache of line-start information. Data is a LineParam*. */
+ GList *line_start_cache;
+ /* Index to the start of the first visible line. */
+ guint first_line_start_index;
+ /* The number of pixels cut off of the top line. */
+ guint first_cut_pixels;
+ /* First visible horizontal pixel. */
+ guint first_onscreen_hor_pixel;
+ /* First visible vertical pixel. */
+ guint first_onscreen_ver_pixel;
+
+ /* FLAGS */
+
+ /* True iff the cursor has been placed yet. */
+ guint has_cursor : 1;
+ /* True iff this buffer is editable. (Allowing a cursor to be placed). */
+ guint is_editable : 1;
+ /* True iff this buffer is wrapping lines, otherwise it is using a
+ * horizontal scrollbar. */
+ guint line_wrap : 1;
+ /* Frozen, don't do updates. @@@ fixme */
+ guint freeze : 1;
+ /* Whether a selection. */
+ guint has_selection : 1;
+ /* Whether the selection is in the clipboard. */
+ guint own_selection : 1;
+ /* Whether it has been realized yet. */
+
+ /* TEXT PROPERTIES */
+
+ /* A doubly-linked-list containing TextProperty objects. */
+ GList *text_properties;
+ /* The end of this list. */
+ GList *text_properties_end;
+ /* The first node before or on the point along with its offset to
+ * the point and the buffer's current point. This is the only
+ * PropertyMark whose index is guaranteed to remain correct
+ * following a buffer insertion or deletion. */
+ GtkPropertyMark point;
+
+ /* SCRATCH AREA */
+
+ guchar* scratch_buffer;
+ guint scratch_buffer_len;
+
+ /* SCROLLING */
+
+ gint last_ver_value;
+
+ /* CURSOR */
+
+ gint cursor_pos_x; /* Position of cursor. */
+ gint cursor_pos_y; /* Baseline of line cursor is drawn on. */
+ GtkPropertyMark cursor_mark; /* Where it is in the buffer. */
+ gchar cursor_char; /* Character to redraw. */
+ gchar cursor_char_offset; /* Distance from baseline of the font. */
+ gint cursor_virtual_x; /* Where it would be if it could be. */
+ gint cursor_drawn_level; /* How many people have undrawn. */
+
+ /* Current Line */
+
+ GList *current_line;
+
+ /* Tab Stops */
+
+ GList *tab_stops;
+ gint default_tab_width;
+
+ /* Key bindings */
+
+ GtkTextFunction control_keys[26];
+ GtkTextFunction alt_keys[26];
+
+ /* Selection nonsense. */
+
+ guint selection_start;
+ guint selection_stop;
+};
+
+struct _GtkTextClass
+{
+ GtkWidgetClass parent_class;
+};
+
+
+guint gtk_text_get_type (void);
+GtkWidget* gtk_text_new (GtkAdjustment *hadj,
+ GtkAdjustment *vadj);
+void gtk_text_set_editable (GtkText *text,
+ gint editable);
+void gtk_text_set_adjustments (GtkText *text,
+ GtkAdjustment *hadj,
+ GtkAdjustment *vadj);
+void gtk_text_set_point (GtkText *text,
+ guint index);
+guint gtk_text_get_point (GtkText *text);
+guint gtk_text_get_length (GtkText *text);
+void gtk_text_freeze (GtkText *text);
+void gtk_text_thaw (GtkText *text);
+void gtk_text_insert (GtkText *text,
+ GdkFont *font,
+ GdkColor *fore,
+ GdkColor *back,
+ const char *chars,
+ gint length);
+gint gtk_text_backward_delete (GtkText *text,
+ guint nchars);
+gint gtk_text_foreward_delete (GtkText *text,
+ guint nchars);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_TEXT_H__ */
diff --git a/gtk/gtktogglebutton.c b/gtk/gtktogglebutton.c
new file mode 100644
index 000000000..eabcb1b26
--- /dev/null
+++ b/gtk/gtktogglebutton.c
@@ -0,0 +1,372 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtklabel.h"
+#include "gtkmain.h"
+#include "gtksignal.h"
+#include "gtktogglebutton.h"
+
+
+#define DEFAULT_LEFT_POS 4
+#define DEFAULT_TOP_POS 4
+#define DEFAULT_SPACING 7
+
+enum {
+ TOGGLED,
+ LAST_SIGNAL
+};
+
+
+static void gtk_toggle_button_class_init (GtkToggleButtonClass *klass);
+static void gtk_toggle_button_init (GtkToggleButton *toggle_button);
+static void gtk_toggle_button_draw_focus (GtkWidget *widget);
+static void gtk_toggle_button_pressed (GtkButton *button);
+static void gtk_toggle_button_released (GtkButton *button);
+static void gtk_toggle_button_clicked (GtkButton *button);
+static void gtk_toggle_button_enter (GtkButton *button);
+static void gtk_toggle_button_leave (GtkButton *button);
+
+
+static gint toggle_button_signals[LAST_SIGNAL] = { 0 };
+
+
+guint
+gtk_toggle_button_get_type ()
+{
+ static guint toggle_button_type = 0;
+
+ if (!toggle_button_type)
+ {
+ GtkTypeInfo toggle_button_info =
+ {
+ "GtkToggleButton",
+ sizeof (GtkToggleButton),
+ sizeof (GtkToggleButtonClass),
+ (GtkClassInitFunc) gtk_toggle_button_class_init,
+ (GtkObjectInitFunc) gtk_toggle_button_init,
+ (GtkArgFunc) NULL,
+ };
+
+ toggle_button_type = gtk_type_unique (gtk_button_get_type (), &toggle_button_info);
+ }
+
+ return toggle_button_type;
+}
+
+static void
+gtk_toggle_button_class_init (GtkToggleButtonClass *class)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+ GtkContainerClass *container_class;
+ GtkButtonClass *button_class;
+
+ object_class = (GtkObjectClass*) class;
+ widget_class = (GtkWidgetClass*) class;
+ container_class = (GtkContainerClass*) class;
+ button_class = (GtkButtonClass*) class;
+
+ toggle_button_signals[TOGGLED] =
+ gtk_signal_new ("toggled",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkToggleButtonClass, toggled),
+ gtk_signal_default_marshaller,
+ GTK_TYPE_NONE, 0);
+
+ gtk_object_class_add_signals (object_class, toggle_button_signals, LAST_SIGNAL);
+
+ widget_class->draw_focus = gtk_toggle_button_draw_focus;
+ widget_class->draw_default = NULL;
+
+ button_class->pressed = gtk_toggle_button_pressed;
+ button_class->released = gtk_toggle_button_released;
+ button_class->clicked = gtk_toggle_button_clicked;
+ button_class->enter = gtk_toggle_button_enter;
+ button_class->leave = gtk_toggle_button_leave;
+
+ class->toggled = NULL;
+}
+
+static void
+gtk_toggle_button_init (GtkToggleButton *toggle_button)
+{
+ toggle_button->active = FALSE;
+ toggle_button->draw_indicator = FALSE;
+}
+
+
+GtkWidget*
+gtk_toggle_button_new ()
+{
+ return GTK_WIDGET (gtk_type_new (gtk_toggle_button_get_type ()));
+}
+
+GtkWidget*
+gtk_toggle_button_new_with_label (const gchar *label)
+{
+ GtkWidget *toggle_button;
+ GtkWidget *label_widget;
+
+ toggle_button = gtk_toggle_button_new ();
+ label_widget = gtk_label_new (label);
+ gtk_misc_set_alignment (GTK_MISC (label_widget), 0.5, 0.5);
+
+ gtk_container_add (GTK_CONTAINER (toggle_button), label_widget);
+ gtk_widget_show (label_widget);
+
+ return toggle_button;
+}
+
+void
+gtk_toggle_button_set_mode (GtkToggleButton *toggle_button,
+ gint draw_indicator)
+{
+ g_return_if_fail (toggle_button != NULL);
+ g_return_if_fail (GTK_IS_TOGGLE_BUTTON (toggle_button));
+
+ draw_indicator = draw_indicator ? TRUE : FALSE;
+
+ if (toggle_button->draw_indicator != draw_indicator)
+ {
+ toggle_button->draw_indicator = draw_indicator;
+
+ if (GTK_WIDGET_VISIBLE (toggle_button))
+ gtk_widget_queue_resize (GTK_WIDGET (toggle_button));
+ }
+}
+
+void
+gtk_toggle_button_set_state (GtkToggleButton *toggle_button,
+ gint state)
+{
+ g_return_if_fail (toggle_button != NULL);
+ g_return_if_fail (GTK_IS_TOGGLE_BUTTON (toggle_button));
+
+ if (toggle_button->active != state)
+ gtk_button_clicked (GTK_BUTTON (toggle_button));
+}
+
+void
+gtk_toggle_button_toggled (GtkToggleButton *toggle_button)
+{
+ gtk_signal_emit (GTK_OBJECT (toggle_button), toggle_button_signals[TOGGLED]);
+}
+
+
+static void
+gtk_toggle_button_draw_focus (GtkWidget *widget)
+{
+ GtkButton *button;
+ GtkToggleButton *toggle_button;
+ GtkShadowType shadow_type;
+ gint width, height;
+ gint x, y;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_TOGGLE_BUTTON (widget));
+
+ if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget))
+ {
+ button = GTK_BUTTON (widget);
+ toggle_button = GTK_TOGGLE_BUTTON (widget);
+
+ x = 0;
+ y = 0;
+ width = widget->allocation.width;
+ height = widget->allocation.height;
+
+ if (GTK_WIDGET_CAN_DEFAULT (widget))
+ {
+ x += widget->style->klass->xthickness;
+ y += widget->style->klass->ythickness;
+ width -= 2 * x + DEFAULT_SPACING;
+ height -= 2 * y + DEFAULT_SPACING;
+ x += DEFAULT_LEFT_POS;
+ y += DEFAULT_TOP_POS;
+ }
+
+ if (GTK_WIDGET_HAS_FOCUS (widget))
+ {
+ x += 1;
+ y += 1;
+ width -= 2;
+ height -= 2;
+ }
+ else
+ {
+ if (GTK_WIDGET_STATE (widget) == GTK_STATE_ACTIVE)
+ gdk_draw_rectangle (widget->window,
+ widget->style->bg_gc[GTK_WIDGET_STATE (widget)], FALSE,
+ x + 1, y + 1, width - 4, height - 4);
+ else
+ gdk_draw_rectangle (widget->window,
+ widget->style->bg_gc[GTK_WIDGET_STATE (widget)], FALSE,
+ x + 2, y + 2, width - 5, height - 5);
+ }
+
+ if (GTK_WIDGET_STATE (widget) == GTK_STATE_ACTIVE)
+ shadow_type = GTK_SHADOW_IN;
+ else if ((GTK_WIDGET_STATE (widget) == GTK_STATE_PRELIGHT) && toggle_button->active)
+ shadow_type = GTK_SHADOW_IN;
+ else
+ shadow_type = GTK_SHADOW_OUT;
+
+ gtk_draw_shadow (widget->style, widget->window,
+ GTK_WIDGET_STATE (widget), shadow_type,
+ x, y, width, height);
+
+ if (GTK_WIDGET_HAS_FOCUS (widget))
+ {
+ x -= 1;
+ y -= 1;
+ width += 2;
+ height += 2;
+
+ gdk_draw_rectangle (widget->window,
+ widget->style->black_gc, FALSE,
+ x, y, width - 1, height - 1);
+ }
+ }
+}
+
+static void
+gtk_toggle_button_pressed (GtkButton *button)
+{
+ GtkToggleButton *toggle_button;
+ GtkStateType new_state;
+
+ g_return_if_fail (button != NULL);
+ g_return_if_fail (GTK_IS_TOGGLE_BUTTON (button));
+
+ toggle_button = GTK_TOGGLE_BUTTON (button);
+
+ button->button_down = TRUE;
+
+ if (toggle_button->active)
+ new_state = (button->in_button ? GTK_STATE_NORMAL : GTK_STATE_ACTIVE);
+ else
+ new_state = (button->in_button ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL);
+
+ if (GTK_WIDGET_STATE (button) != new_state)
+ {
+ gtk_widget_set_state (GTK_WIDGET (button), new_state);
+ gtk_widget_queue_draw (GTK_WIDGET (button));
+ }
+}
+
+static void
+gtk_toggle_button_released (GtkButton *button)
+{
+ GtkToggleButton *toggle_button;
+ GtkStateType new_state;
+
+ g_return_if_fail (button != NULL);
+ g_return_if_fail (GTK_IS_TOGGLE_BUTTON (button));
+
+ if (button->button_down)
+ {
+ toggle_button = GTK_TOGGLE_BUTTON (button);
+
+ button->button_down = FALSE;
+
+ if (button->in_button)
+ {
+ gtk_button_clicked (button);
+ }
+ else
+ {
+ if (toggle_button->active)
+ new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_ACTIVE);
+ else
+ new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL);
+
+ if (GTK_WIDGET_STATE (button) != new_state)
+ {
+ gtk_widget_set_state (GTK_WIDGET (button), new_state);
+ gtk_widget_queue_draw (GTK_WIDGET (button));
+ }
+ }
+ }
+}
+
+static void
+gtk_toggle_button_clicked (GtkButton *button)
+{
+ GtkToggleButton *toggle_button;
+ GtkStateType new_state;
+
+ g_return_if_fail (button != NULL);
+ g_return_if_fail (GTK_IS_TOGGLE_BUTTON (button));
+
+ toggle_button = GTK_TOGGLE_BUTTON (button);
+ toggle_button->active = !toggle_button->active;
+
+ gtk_toggle_button_toggled (toggle_button);
+
+ if (toggle_button->active)
+ new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_ACTIVE);
+ else
+ new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL);
+
+ if (GTK_WIDGET_STATE (button) != new_state)
+ gtk_widget_set_state (GTK_WIDGET (button), new_state);
+ gtk_widget_queue_draw (GTK_WIDGET (button));
+}
+
+static void
+gtk_toggle_button_enter (GtkButton *button)
+{
+ GtkToggleButton *toggle_button;
+ GtkStateType new_state;
+
+ g_return_if_fail (button != NULL);
+ g_return_if_fail (GTK_IS_TOGGLE_BUTTON (button));
+
+ toggle_button = GTK_TOGGLE_BUTTON (button);
+
+ if (toggle_button->active)
+ new_state = (button->button_down ? GTK_STATE_NORMAL : GTK_STATE_PRELIGHT);
+ else
+ new_state = (button->button_down ? GTK_STATE_ACTIVE : GTK_STATE_PRELIGHT);
+
+ if (GTK_WIDGET_STATE (button) != new_state)
+ {
+ gtk_widget_set_state (GTK_WIDGET (button), new_state);
+ gtk_widget_queue_draw (GTK_WIDGET (button));
+ }
+}
+
+static void
+gtk_toggle_button_leave (GtkButton *button)
+{
+ GtkToggleButton *toggle_button;
+ GtkStateType new_state;
+
+ g_return_if_fail (button != NULL);
+ g_return_if_fail (GTK_IS_TOGGLE_BUTTON (button));
+
+ toggle_button = GTK_TOGGLE_BUTTON (button);
+
+ new_state = (toggle_button->active ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL);
+
+ if (GTK_WIDGET_STATE (button) != new_state)
+ {
+ gtk_widget_set_state (GTK_WIDGET (button), new_state);
+ gtk_widget_queue_draw (GTK_WIDGET (button));
+ }
+}
diff --git a/gtk/gtktogglebutton.h b/gtk/gtktogglebutton.h
new file mode 100644
index 000000000..e48d1cf5a
--- /dev/null
+++ b/gtk/gtktogglebutton.h
@@ -0,0 +1,70 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_TOGGLE_BUTTON_H__
+#define __GTK_TOGGLE_BUTTON_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkbutton.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_TOGGLE_BUTTON(obj) GTK_CHECK_CAST (obj, gtk_toggle_button_get_type (), GtkToggleButton)
+#define GTK_TOGGLE_BUTTON_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_toggle_button_get_type (), GtkToggleButtonClass)
+#define GTK_IS_TOGGLE_BUTTON(obj) GTK_CHECK_TYPE (obj, gtk_toggle_button_get_type ())
+
+
+typedef struct _GtkToggleButton GtkToggleButton;
+typedef struct _GtkToggleButtonClass GtkToggleButtonClass;
+
+struct _GtkToggleButton
+{
+ GtkButton button;
+
+ guint active : 1;
+ guint draw_indicator : 1;
+};
+
+struct _GtkToggleButtonClass
+{
+ GtkButtonClass parent_class;
+
+ void (* toggled) (GtkToggleButton *toggle_button);
+};
+
+
+guint gtk_toggle_button_get_type (void);
+GtkWidget* gtk_toggle_button_new (void);
+GtkWidget* gtk_toggle_button_new_with_label (const gchar *label);
+void gtk_toggle_button_set_mode (GtkToggleButton *toggle_button,
+ gint draw_indicator);
+void gtk_toggle_button_set_state (GtkToggleButton *toggle_button,
+ gint state);
+void gtk_toggle_button_toggled (GtkToggleButton *toggle_button);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_TOGGLE_BUTTON_H__ */
diff --git a/gtk/gtktooltips.c b/gtk/gtktooltips.c
new file mode 100644
index 000000000..953d42592
--- /dev/null
+++ b/gtk/gtktooltips.c
@@ -0,0 +1,632 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <string.h>
+
+#include "gtkmain.h"
+#include "gtkwidget.h"
+#include "gtkwindow.h"
+#include "gtksignal.h"
+#include "gtkstyle.h"
+#include "gtktooltips.h"
+
+
+#define DEFAULT_DELAY 500 /* Default delay in ms */
+
+
+static gint gtk_tooltips_event_handler (GtkWidget *widget,
+ GdkEvent *event);
+static void gtk_tooltips_widget_unmap (GtkWidget *widget,
+ gpointer data);
+static void gtk_tooltips_widget_remove (GtkWidget *widget,
+ gpointer data);
+static void gtk_tooltips_set_active_widget (GtkTooltips *tooltips,
+ GtkWidget *widget);
+static gint gtk_tooltips_widget_visible (GtkWidget *widget);
+static gint gtk_tooltips_timeout (gpointer data);
+static void gtk_tooltips_draw_tips (GtkTooltips *tooltips);
+
+
+GtkTooltips *
+gtk_tooltips_new ()
+{
+ GtkTooltips *tooltips;
+
+ tooltips = g_new0 (GtkTooltips, 1);
+
+ if (tooltips != NULL)
+ {
+ tooltips->ref_count = 0;
+ tooltips->pending_destroy = 0;
+
+ tooltips->enabled = TRUE;
+ tooltips->numwidgets = 0;
+ tooltips->delay = DEFAULT_DELAY;
+ tooltips->widget_list = NULL;
+ tooltips->gc = NULL;
+ tooltips->foreground = NULL;
+ tooltips->background = NULL;
+ tooltips->tip_window = NULL;
+ }
+
+ return tooltips;
+}
+
+GtkTooltips*
+gtk_tooltips_ref (GtkTooltips *tooltips)
+{
+ g_return_val_if_fail (tooltips != NULL, NULL);
+ tooltips->ref_count += 1;
+ return tooltips;
+}
+
+void
+gtk_tooltips_unref (GtkTooltips *tooltips)
+{
+ g_return_if_fail (tooltips != NULL);
+ tooltips->ref_count -= 1;
+ if (tooltips->ref_count == 0 && tooltips->pending_destroy)
+ gtk_tooltips_destroy (tooltips);
+}
+
+void
+gtk_tooltips_free_string (gpointer data, gpointer user_data)
+{
+ if (data)
+ g_free (data);
+}
+
+static void
+gtk_tooltips_destroy_data (GtkTooltips *tooltips,
+ GtkTooltipsData *tooltipsdata)
+{
+ g_free (tooltipsdata->tips_text);
+ g_list_foreach (tooltipsdata->row, gtk_tooltips_free_string, 0);
+ if (tooltipsdata->row)
+ g_list_free (tooltipsdata->row);
+ gtk_signal_disconnect_by_data (GTK_OBJECT (tooltipsdata->widget),
+ (gpointer) tooltips);
+ gtk_widget_set_events(tooltipsdata->widget,tooltipsdata->old_event_mask);
+ g_free (tooltipsdata);
+}
+
+void
+gtk_tooltips_destroy (GtkTooltips *tooltips)
+{
+ GList *current;
+ GtkTooltipsData *tooltipsdata;
+
+ g_return_if_fail (tooltips != NULL);
+
+ if (tooltips->ref_count > 0)
+ {
+ tooltips->pending_destroy = 1;
+ return;
+ }
+
+ if (tooltips->timer_active == TRUE)
+ {
+ tooltips->timer_active = FALSE;
+ gtk_timeout_remove (tooltips->timer_tag);
+ }
+
+ if (tooltips->widget_list != NULL)
+ {
+ current = g_list_first (tooltips->widget_list);
+ while (current != NULL)
+ {
+ tooltipsdata = (GtkTooltipsData*) current->data;
+ gtk_tooltips_destroy_data (tooltips, tooltipsdata);
+ current = current->next;
+ }
+ g_list_free (tooltips->widget_list);
+ }
+
+ if (tooltips->tip_window != NULL)
+ gtk_widget_destroy (tooltips->tip_window);
+
+ if (tooltips->gc != NULL)
+ gdk_gc_destroy (tooltips->gc);
+
+ g_free (tooltips);
+}
+
+static void
+gtk_tooltips_layout_text (GtkTooltips *tooltips, GtkTooltipsData *data)
+{
+ GtkStyle *style = gtk_widget_get_default_style ();
+ gchar *row_end, *text, *row_text, *break_pos;
+ gint i, row_width, window_width = 0;
+ size_t len;
+
+ g_list_foreach (data->row, gtk_tooltips_free_string, 0);
+ if (data->row)
+ g_list_free (data->row);
+ data->row = 0;
+ data->font = style->font;
+ data->width = 0;
+
+ text = data->tips_text;
+ if (!text)
+ return;
+
+ while (*text)
+ {
+ row_end = strchr (text, '\n');
+ if (!row_end)
+ row_end = strchr (text, '\0');
+
+ len = row_end - text + 1;
+ row_text = g_new(gchar, len);
+ memcpy (row_text, text, len - 1);
+ row_text[len - 1] = '\0';
+
+ /* now either adjust the window's width or shorten the row until
+ it fits in the window */
+
+ while (1)
+ {
+ row_width = gdk_string_width (data->font, row_text);
+ if (!window_width)
+ {
+ /* make an initial guess at window's width: */
+
+ if (row_width > gdk_screen_width () / 4)
+ window_width = gdk_screen_width () / 4;
+ else
+ window_width = row_width;
+ }
+ if (row_width <= window_width)
+ break;
+
+ if (strchr (row_text, ' '))
+ {
+ /* the row is currently too wide, but we have blanks in
+ the row so we can break it into smaller pieces */
+
+ gint avg_width = row_width / strlen (row_text);
+
+ i = window_width;
+ if (avg_width)
+ i /= avg_width;
+ if ((size_t) i >= len)
+ i = len - 1;
+
+ break_pos = strchr (row_text + i, ' ');
+ if (!break_pos)
+ {
+ break_pos = row_text + i;
+ while (*--break_pos != ' ');
+ }
+ *break_pos = '\0';
+ }
+ else
+ {
+ /* we can't break this row into any smaller pieces, so
+ we have no choice but to widen the window: */
+
+ window_width = row_width;
+ break;
+ }
+ }
+ if (row_width > data->width)
+ data->width = row_width;
+ data->row = g_list_append (data->row, row_text);
+ text += strlen (row_text);
+ if (!*text)
+ break;
+
+ if (text[0] == '\n' && text[1])
+ /* end of paragraph and there is more text to come */
+ data->row = g_list_append (data->row, 0);
+ ++text; /* skip blank or newline */
+ }
+ data->width += 8; /* leave some border */
+}
+
+void
+gtk_tooltips_enable (GtkTooltips *tooltips)
+{
+ g_return_if_fail (tooltips != NULL);
+
+ tooltips->enabled = TRUE;
+}
+
+void
+gtk_tooltips_disable (GtkTooltips *tooltips)
+{
+ g_return_if_fail (tooltips != NULL);
+
+ tooltips->enabled = FALSE;
+
+ if (tooltips->timer_active == TRUE)
+ {
+ gtk_timeout_remove (tooltips->timer_tag);
+ tooltips->timer_active = FALSE;
+ }
+
+ if (tooltips->active_widget != NULL)
+ {
+ if (tooltips->tip_window != NULL)
+ gtk_widget_hide (tooltips->tip_window);
+ tooltips->active_widget = NULL;
+ }
+}
+
+void
+gtk_tooltips_set_delay (GtkTooltips *tooltips,
+ gint delay)
+{
+ g_return_if_fail (tooltips != NULL);
+
+ tooltips->delay = delay;
+}
+
+void
+gtk_tooltips_set_tips (GtkTooltips *tooltips,
+ GtkWidget *widget,
+ const gchar *tips_text)
+{
+ GtkTooltipsData *tooltipsdata;
+
+ g_return_if_fail (tooltips != NULL);
+ g_return_if_fail (widget != NULL);
+
+ if (gtk_object_get_data (GTK_OBJECT (widget), "_GtkTooltips") != NULL)
+ gtk_tooltips_widget_remove (widget, NULL);
+
+ if (gtk_object_get_data (GTK_OBJECT (widget), "_GtkTooltips") != NULL)
+ gtk_tooltips_widget_remove (widget, NULL);
+
+ tooltipsdata = g_new(GtkTooltipsData, 1);
+
+ if (tooltipsdata != NULL)
+ {
+ memset (tooltipsdata, 0, sizeof (*tooltipsdata));
+ tooltipsdata->widget = widget;
+
+ tooltipsdata->tips_text = g_strdup (tips_text);
+ if (!tooltipsdata->tips_text)
+ {
+ g_free (tooltipsdata);
+ return;
+ }
+
+ gtk_tooltips_layout_text (tooltips, tooltipsdata);
+ tooltips->widget_list = g_list_append (tooltips->widget_list,
+ tooltipsdata);
+ tooltips->numwidgets++;
+ tooltipsdata->old_event_mask = gtk_widget_get_events (widget);
+
+ gtk_signal_connect_after(GTK_OBJECT (widget), "event",
+ (GtkSignalFunc) gtk_tooltips_event_handler,
+ (gpointer) tooltips);
+
+ gtk_object_set_data (GTK_OBJECT (widget), "_GtkTooltips",
+ (gpointer) tooltips);
+
+ gtk_signal_connect (GTK_OBJECT (widget), "destroy",
+ (GtkSignalFunc) gtk_tooltips_widget_remove,
+ (gpointer) tooltips);
+
+ gtk_signal_connect (GTK_OBJECT (widget), "unmap",
+ (GtkSignalFunc) gtk_tooltips_widget_unmap,
+ (gpointer) tooltips);
+
+ gtk_signal_connect (GTK_OBJECT (widget), "unrealize",
+ (GtkSignalFunc) gtk_tooltips_widget_unmap,
+ (gpointer) tooltips);
+ }
+}
+
+void
+gtk_tooltips_set_colors (GtkTooltips *tooltips,
+ GdkColor *background,
+ GdkColor *foreground)
+{
+ g_return_if_fail (tooltips != NULL);
+
+ if (background != NULL)
+ tooltips->foreground = foreground;
+ if (foreground != NULL)
+ tooltips->background = background;
+}
+
+static void
+gtk_tooltips_draw_tips (GtkTooltips * tooltips)
+{
+ GtkWidget *widget;
+ GtkStyle *style = gtk_widget_get_default_style ();
+ gint gap, x, y, w, h, scr_w, scr_h, baseline_skip;
+ GtkTooltipsData *data;
+ GList *el;
+
+ if (tooltips->tip_window == NULL)
+ {
+ tooltips->tip_window = gtk_window_new (GTK_WINDOW_POPUP);
+ gtk_window_set_policy (GTK_WINDOW (tooltips->tip_window), FALSE, FALSE, TRUE);
+ }
+ else
+ gtk_widget_hide (tooltips->tip_window);
+
+ widget = tooltips->active_widget->widget;
+
+ scr_w = gdk_screen_width ();
+ scr_h = gdk_screen_height ();
+
+ data = tooltips->active_widget;
+ if (data->font != style->font)
+ gtk_tooltips_layout_text (tooltips, data);
+
+ gap = (style->font->ascent + style->font->descent) / 4;
+ if (gap < 2)
+ gap = 2;
+ baseline_skip = style->font->ascent + style->font->descent + gap;
+ w = data->width;
+ h = 8 - gap;
+ for (el = data->row; el; el = el->next)
+ if (el->data)
+ h += baseline_skip;
+ else
+ h += baseline_skip / 2;
+ if (h < 8)
+ h = 8;
+
+ gdk_window_get_pointer (NULL, &x, NULL, NULL);
+ gdk_window_get_origin (widget->window, NULL, &y);
+
+ x -= ((w >> 1) + 4);
+
+ if ((x + w) > scr_w)
+ x -= (x + w) - scr_w;
+ else if (x < 0)
+ x = 0;
+
+ if ((y + h + widget->allocation.height + 4) > scr_h)
+ y = y - h - 4;
+ else
+ y = y + widget->allocation.height + 4;
+
+ gtk_widget_set_usize (tooltips->tip_window, w + 1, h + 1);
+ gtk_widget_popup (tooltips->tip_window, x, y);
+
+ if (tooltips->gc == NULL)
+ tooltips->gc = gdk_gc_new (tooltips->tip_window->window);
+
+ if (tooltips->background != NULL)
+ {
+ gdk_gc_set_foreground (tooltips->gc, tooltips->background);
+ gdk_gc_set_background (tooltips->gc, tooltips->foreground);
+ }
+ else
+ {
+ gdk_gc_set_foreground (tooltips->gc, &style->bg[GTK_STATE_NORMAL]);
+ gdk_gc_set_background (tooltips->gc, &style->fg[GTK_STATE_NORMAL]);
+ }
+
+ gdk_gc_set_font (tooltips->gc, style->font);
+ gdk_draw_rectangle (tooltips->tip_window->window, tooltips->gc, TRUE, 0, 0, w, h);
+
+ if (tooltips->foreground != NULL)
+ {
+ gdk_gc_set_foreground (tooltips->gc, tooltips->foreground);
+ gdk_gc_set_background (tooltips->gc, tooltips->background);
+ }
+ else
+ {
+ gdk_gc_set_foreground (tooltips->gc, &style->fg[GTK_STATE_NORMAL]);
+ gdk_gc_set_background (tooltips->gc, &style->bg[GTK_STATE_NORMAL]);
+ }
+
+ gdk_draw_rectangle (tooltips->tip_window->window, tooltips->gc, FALSE, 0, 0, w, h);
+ y = style->font->ascent + 4;
+
+ for (el = data->row; el; el = el->next)
+ {
+ if (el->data)
+ {
+ gdk_draw_string (tooltips->tip_window->window, style->font,
+ tooltips->gc, 4, y, el->data);
+ y += baseline_skip;
+ }
+ else
+ y += baseline_skip / 2;
+ }
+}
+
+static gint
+gtk_tooltips_timeout (gpointer data)
+{
+ GtkTooltips *tooltips = (GtkTooltips *) data;
+
+ if (tooltips->active_widget != NULL &&
+ GTK_WIDGET_DRAWABLE (tooltips->active_widget->widget))
+ gtk_tooltips_draw_tips (tooltips);
+
+ return FALSE;
+}
+
+static gint
+gtk_tooltips_widget_visible (GtkWidget *widget)
+{
+ GtkWidget *current;
+
+ current = widget;
+
+ while (current != NULL)
+ {
+ if (!GTK_WIDGET_MAPPED (current) || !GTK_WIDGET_REALIZED (current))
+ return FALSE;
+ current = current->parent;
+ }
+
+ return TRUE;
+}
+
+static void
+gtk_tooltips_set_active_widget (GtkTooltips *tooltips,
+ GtkWidget *widget)
+{
+ GtkTooltipsData *tooltipsdata;
+ GList *current;
+
+ current = g_list_first (tooltips->widget_list);
+ tooltips->active_widget = NULL;
+
+ while (current != NULL)
+ {
+ tooltipsdata = (GtkTooltipsData*) current->data;
+
+ if (widget == tooltipsdata->widget &&
+ gtk_tooltips_widget_visible (tooltipsdata->widget) == TRUE)
+ {
+ tooltips->active_widget = tooltipsdata;
+ return;
+ }
+
+ current = current->next;
+ }
+}
+
+static gint
+gtk_tooltips_event_handler (GtkWidget *widget,
+ GdkEvent *event)
+{
+ GtkTooltips *tooltips;
+ GtkTooltipsData *old_widget;
+ gint returnval = FALSE;
+
+ tooltips = (GtkTooltips*) gtk_object_get_data (GTK_OBJECT (widget),"_GtkTooltips");
+
+ if (tooltips->enabled == FALSE)
+ return returnval;
+
+ if ((event->type == GDK_LEAVE_NOTIFY || event->type == GDK_ENTER_NOTIFY) &&
+ event->crossing.detail == GDK_NOTIFY_INFERIOR)
+ return returnval;
+
+ if (event->type == GDK_LEAVE_NOTIFY)
+ {
+ if (tooltips->timer_active == TRUE)
+ {
+ gtk_timeout_remove (tooltips->timer_tag);
+ tooltips->timer_active = FALSE;
+ }
+ if (tooltips->tip_window != NULL)
+ gtk_widget_hide (tooltips->tip_window);
+ tooltips->active_widget = NULL;
+ }
+ else if (event->type == GDK_MOTION_NOTIFY || event->type == GDK_ENTER_NOTIFY)
+ {
+ old_widget = tooltips->active_widget;
+#if 0
+ if (widget->window != event->crossing.window)
+ tooltips->active_widget = NULL;
+ else
+#endif
+ gtk_tooltips_set_active_widget (tooltips, widget);
+
+ if (old_widget != tooltips->active_widget)
+ {
+ if (tooltips->timer_active == TRUE)
+ {
+ gtk_timeout_remove (tooltips->timer_tag);
+ tooltips->timer_active = FALSE;
+ }
+ if (tooltips->active_widget != NULL)
+ {
+ if (tooltips->tip_window != NULL)
+ gtk_widget_hide (tooltips->tip_window);
+
+ tooltips->timer_tag = gtk_timeout_add (tooltips->delay,
+ gtk_tooltips_timeout, (gpointer) tooltips);
+
+ tooltips->timer_active = TRUE;
+ }
+ }
+ else if (tooltips->active_widget == NULL)
+ {
+ if (tooltips->tip_window != NULL)
+ gtk_widget_hide (tooltips->tip_window);
+ }
+ }
+ else
+ {
+ if (tooltips->tip_window != NULL)
+ gtk_widget_hide (tooltips->tip_window);
+ }
+
+ return returnval;
+}
+
+static void
+gtk_tooltips_widget_unmap (GtkWidget *widget,
+ gpointer data)
+{
+ GtkTooltips *tooltips;
+
+ tooltips = (GtkTooltips*) gtk_object_get_data (GTK_OBJECT (widget), "_GtkTooltips");
+
+ if (tooltips->active_widget &&
+ (tooltips->active_widget->widget == widget))
+ {
+ if (tooltips->tip_window != NULL)
+ gtk_widget_hide (tooltips->tip_window);
+ tooltips->active_widget = NULL;
+ }
+}
+
+static void
+gtk_tooltips_widget_remove (GtkWidget *widget,
+ gpointer data)
+{
+ GtkTooltips *tooltips;
+ GtkTooltipsData *tooltipsdata;
+ GList *list;
+
+ tooltips = (GtkTooltips*) gtk_object_get_data (GTK_OBJECT (widget), "_GtkTooltips");
+
+ gtk_tooltips_widget_unmap (widget, data);
+
+ list = g_list_first (tooltips->widget_list);
+ while (list)
+ {
+ tooltipsdata = (GtkTooltipsData*) list->data;
+
+ if (tooltipsdata->widget == widget)
+ break;
+
+ list = list->next;
+ }
+
+ if (list)
+ {
+ tooltipsdata = (GtkTooltipsData*) list->data;
+
+ g_free (tooltipsdata->tips_text);
+ g_list_foreach (tooltipsdata->row, gtk_tooltips_free_string, 0);
+ g_list_free (tooltipsdata->row);
+ gtk_signal_disconnect_by_data (GTK_OBJECT (tooltipsdata->widget), (gpointer) tooltips);
+ gtk_widget_set_events (tooltipsdata->widget,tooltipsdata->old_event_mask);
+ g_free (tooltipsdata);
+
+ tooltips->widget_list = g_list_remove (tooltips->widget_list, tooltipsdata);
+ }
+
+ gtk_object_set_data (GTK_OBJECT (widget), "_GtkTooltips", NULL);
+}
diff --git a/gtk/gtktooltips.h b/gtk/gtktooltips.h
new file mode 100644
index 000000000..e3ac59696
--- /dev/null
+++ b/gtk/gtktooltips.h
@@ -0,0 +1,88 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_TOOLTIPS_H__
+#define __GTK_TOOLTIPS_H__
+
+#include <gdk/gdk.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+typedef struct
+{
+ GtkWidget *widget;
+ gchar *tips_text;
+ GdkFont *font;
+ gint width;
+ GList *row;
+ gint old_event_mask;
+} GtkTooltipsData;
+
+typedef struct
+{
+ GtkWidget *tip_window;
+ GtkTooltipsData *active_widget;
+ GList *widget_list;
+
+ GdkGC *gc;
+ GdkColor *foreground;
+ GdkColor *background;
+
+ gint numwidgets;
+ gint enabled;
+ gint inside;
+ gint delay;
+ gint timer_tag;
+ gint timer_active;
+
+ gint ref_count;
+ gint pending_destroy;
+} GtkTooltips;
+
+
+GtkTooltips* gtk_tooltips_new (void);
+
+void gtk_tooltips_destroy (GtkTooltips *tooltips);
+GtkTooltips* gtk_tooltips_ref (GtkTooltips *tooltips);
+void gtk_tooltips_unref (GtkTooltips *tooltips);
+
+void gtk_tooltips_enable (GtkTooltips *tooltips);
+
+void gtk_tooltips_disable (GtkTooltips *tooltips);
+
+void gtk_tooltips_set_delay (GtkTooltips *tooltips,
+ gint delay);
+
+void gtk_tooltips_set_tips (GtkTooltips *tooltips,
+ GtkWidget *widget,
+ const gchar *tips_text);
+
+void gtk_tooltips_set_colors (GtkTooltips *tooltips,
+ GdkColor *background,
+ GdkColor *foreground);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_TOOLTIPS_H__ */
diff --git a/gtk/gtktree.c b/gtk/gtktree.c
new file mode 100644
index 000000000..f3981ea0a
--- /dev/null
+++ b/gtk/gtktree.c
@@ -0,0 +1,81 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtktree.h"
+
+
+static void gtk_tree_class_init (GtkTreeClass *klass);
+static void gtk_tree_init (GtkTree *tree);
+
+
+guint
+gtk_tree_get_type ()
+{
+ static guint tree_type = 0;
+
+ if (!tree_type)
+ {
+ GtkTypeInfo tree_info =
+ {
+ "GtkTree",
+ sizeof (GtkTree),
+ sizeof (GtkTreeClass),
+ (GtkClassInitFunc) gtk_tree_class_init,
+ (GtkObjectInitFunc) gtk_tree_init,
+ (GtkArgFunc) NULL,
+ };
+
+ tree_type = gtk_type_unique (gtk_container_get_type (), &tree_info);
+ }
+
+ return tree_type;
+}
+
+static void
+gtk_tree_class_init (GtkTreeClass *class)
+{
+}
+
+static void
+gtk_tree_init (GtkTree *tree)
+{
+}
+
+GtkWidget*
+gtk_tree_new ()
+{
+ return GTK_WIDGET (gtk_type_new (gtk_tree_get_type ()));
+}
+
+void
+gtk_tree_append (GtkTree *tree,
+ GtkWidget *child)
+{
+}
+
+void
+gtk_tree_prepend (GtkTree *tree,
+ GtkWidget *child)
+{
+}
+
+void
+gtk_tree_insert (GtkTree *tree,
+ GtkWidget *child,
+ gint position)
+{
+}
diff --git a/gtk/gtktree.h b/gtk/gtktree.h
new file mode 100644
index 000000000..1486a82ab
--- /dev/null
+++ b/gtk/gtktree.h
@@ -0,0 +1,68 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_TREE_H__
+#define __GTK_TREE_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkcontainer.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_TREE(obj) GTK_CHECK_CAST (obj, gtk_tree_get_type (), GtkTree)
+#define GTK_TREE_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_tree_get_type (), GtkTreeClass)
+#define GTK_IS_TREE(obj) GTK_CHECK_TYPE (obj, gtk_tree_get_type ())
+
+
+typedef struct _GtkTree GtkTree;
+typedef struct _GtkTreeClass GtkTreeClass;
+
+struct _GtkTree
+{
+ GtkContainer container;
+
+ GList *children;
+};
+
+struct _GtkTreeClass
+{
+ GtkContainerClass parent_class;
+};
+
+
+guint gtk_tree_get_type (void);
+GtkWidget* gtk_tree_new (void);
+void gtk_tree_append (GtkTree *tree,
+ GtkWidget *child);
+void gtk_tree_prepend (GtkTree *tree,
+ GtkWidget *child);
+void gtk_tree_insert (GtkTree *tree,
+ GtkWidget *child,
+ gint position);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_TREE_H__ */
diff --git a/gtk/gtktreeitem.c b/gtk/gtktreeitem.c
new file mode 100644
index 000000000..8f0d9f078
--- /dev/null
+++ b/gtk/gtktreeitem.c
@@ -0,0 +1,108 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtklabel.h"
+#include "gtktreeitem.h"
+
+
+static void gtk_tree_item_class_init (GtkTreeItemClass *klass);
+static void gtk_tree_item_init (GtkTreeItem *tree_item);
+
+
+guint
+gtk_tree_item_get_type ()
+{
+ static guint tree_item_type = 0;
+
+ if (!tree_item_type)
+ {
+ GtkTypeInfo tree_item_info =
+ {
+ "GtkTreeItem",
+ sizeof (GtkTreeItem),
+ sizeof (GtkTreeItemClass),
+ (GtkClassInitFunc) gtk_tree_item_class_init,
+ (GtkObjectInitFunc) gtk_tree_item_init,
+ (GtkArgFunc) NULL,
+ };
+
+ tree_item_type = gtk_type_unique (gtk_item_get_type (), &tree_item_info);
+ }
+
+ return tree_item_type;
+}
+
+static void
+gtk_tree_item_class_init (GtkTreeItemClass *class)
+{
+}
+
+static void
+gtk_tree_item_init (GtkTreeItem *tree_item)
+{
+}
+
+
+GtkWidget*
+gtk_tree_item_new ()
+{
+ return GTK_WIDGET (gtk_type_new (gtk_tree_item_get_type ()));
+}
+
+GtkWidget*
+gtk_tree_item_new_with_label (gchar *label)
+{
+ GtkWidget *tree_item;
+ GtkWidget *label_widget;
+
+ tree_item = gtk_tree_item_new ();
+ label_widget = gtk_label_new (label);
+ gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
+
+ gtk_container_add (GTK_CONTAINER (tree_item), label_widget);
+ gtk_widget_show (label_widget);
+
+ return tree_item;
+}
+
+void
+gtk_tree_item_set_subtree (GtkTreeItem *tree_item,
+ GtkWidget *subtree)
+{
+ g_return_if_fail (tree_item != NULL);
+ g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
+}
+
+void
+gtk_tree_item_select (GtkTreeItem *tree_item)
+{
+}
+
+void
+gtk_tree_item_deselect (GtkTreeItem *tree_item)
+{
+}
+
+void
+gtk_tree_item_expand (GtkTreeItem *tree_item)
+{
+}
+
+void
+gtk_tree_item_collapse (GtkTreeItem *tree_item)
+{
+}
diff --git a/gtk/gtktreeitem.h b/gtk/gtktreeitem.h
new file mode 100644
index 000000000..921f681bc
--- /dev/null
+++ b/gtk/gtktreeitem.h
@@ -0,0 +1,72 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_TREE_ITEM_H__
+#define __GTK_TREE_ITEM_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkitem.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_TREE_ITEM(obj) GTK_CHECK_CAST (obj, gtk_tree_item_get_type (), GtkTreeItem)
+#define GTK_TREE_ITEM_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_tree_item_get_type (), GtkTreeItemClass)
+#define GTK_IS_TREE_ITEM(obj) GTK_CHECK_TYPE (obj, gtk_tree_item_get_type ())
+
+
+typedef struct _GtkTreeItem GtkTreeItem;
+typedef struct _GtkTreeItemClass GtkTreeItemClass;
+
+struct _GtkTreeItem
+{
+ GtkItem item;
+
+ GtkWidget *child;
+ GtkWidget *subtree;
+};
+
+struct _GtkTreeItemClass
+{
+ GtkItemClass parent_class;
+
+ void (* expand) (GtkTreeItem *tree_item);
+ void (* collapse) (GtkTreeItem *tree_item);
+};
+
+
+guint gtk_tree_item_get_type (void);
+GtkWidget* gtk_tree_item_new (void);
+GtkWidget* gtk_tree_item_new_with_label (gchar *label);
+void gtk_tree_item_set_subtree (GtkTreeItem *tree_item,
+ GtkWidget *subtree);
+void gtk_tree_item_select (GtkTreeItem *tree_item);
+void gtk_tree_item_deselect (GtkTreeItem *tree_item);
+void gtk_tree_item_expand (GtkTreeItem *tree_item);
+void gtk_tree_item_collapse (GtkTreeItem *tree_item);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_TREE_ITEM_H__ */
diff --git a/gtk/gtktypebuiltins.c b/gtk/gtktypebuiltins.c
new file mode 100644
index 000000000..e43573119
--- /dev/null
+++ b/gtk/gtktypebuiltins.c
@@ -0,0 +1,53 @@
+/* generated by gentypeinfo from "gtk.defs" */
+
+ { "GtkWindowType", GTK_TYPE_ENUM },
+ { "GtkStateType", GTK_TYPE_ENUM },
+ { "GtkDirectionType", GTK_TYPE_ENUM },
+ { "GtkShadowType", GTK_TYPE_ENUM },
+ { "GtkArrowType", GTK_TYPE_ENUM },
+ { "GtkPackType", GTK_TYPE_ENUM },
+ { "GtkPolicyType", GTK_TYPE_ENUM },
+ { "GtkUpdateType", GTK_TYPE_ENUM },
+ { "GtkAttachOptions", GTK_TYPE_FLAGS },
+ { "GtkSignalRunType", GTK_TYPE_FLAGS },
+ { "GtkWindowPosition", GTK_TYPE_ENUM },
+ { "GtkSubmenuDirection", GTK_TYPE_ENUM },
+ { "GtkSubmenuPlacement", GTK_TYPE_ENUM },
+ { "GtkMenuFactoryType", GTK_TYPE_ENUM },
+ { "GtkMetricType", GTK_TYPE_ENUM },
+ { "GtkScrollType", GTK_TYPE_ENUM },
+ { "GtkTroughType", GTK_TYPE_ENUM },
+ { "GtkPositionType", GTK_TYPE_ENUM },
+ { "GtkPreviewType", GTK_TYPE_ENUM },
+ { "GtkWidgetFlags", GTK_TYPE_FLAGS },
+ { "GdkWindowType", GTK_TYPE_ENUM },
+ { "GdkWindowClass", GTK_TYPE_ENUM },
+ { "GdkImageType", GTK_TYPE_ENUM },
+ { "GdkVisualType", GTK_TYPE_ENUM },
+ { "GdkWindowAttributesType", GTK_TYPE_FLAGS },
+ { "GdkWindowHints", GTK_TYPE_FLAGS },
+ { "GdkFunction", GTK_TYPE_ENUM },
+ { "GdkFill", GTK_TYPE_ENUM },
+ { "GdkLineStyle", GTK_TYPE_ENUM },
+ { "GdkCapStyle", GTK_TYPE_ENUM },
+ { "GdkJoinStyle", GTK_TYPE_ENUM },
+ { "GdkCursorType", GTK_TYPE_ENUM },
+ { "GdkEventType", GTK_TYPE_ENUM },
+ { "GdkEventMask", GTK_TYPE_FLAGS },
+ { "GdkNotifyType", GTK_TYPE_ENUM },
+ { "GdkModifierType", GTK_TYPE_FLAGS },
+ { "GdkSubwindowMode", GTK_TYPE_ENUM },
+ { "GdkInputCondition", GTK_TYPE_FLAGS },
+ { "GdkStatus", GTK_TYPE_ENUM },
+ { "GdkByteOrder", GTK_TYPE_ENUM },
+ { "GdkGCValuesMask", GTK_TYPE_FLAGS },
+ { "GdkSelection", GTK_TYPE_ENUM },
+ { "GdkPropertyState", GTK_TYPE_ENUM },
+ { "GdkPropMode", GTK_TYPE_ENUM },
+ { "GtkAcceleratorTable", GTK_TYPE_BOXED },
+ { "GtkStyle", GTK_TYPE_BOXED },
+ { "GdkColormap", GTK_TYPE_BOXED },
+ { "GdkVisual", GTK_TYPE_BOXED },
+ { "GdkFont", GTK_TYPE_BOXED },
+ { "GdkWindow", GTK_TYPE_BOXED },
+ { "GdkEvent", GTK_TYPE_BOXED },
diff --git a/gtk/gtktypebuiltins.h b/gtk/gtktypebuiltins.h
new file mode 100644
index 000000000..ba9131f0f
--- /dev/null
+++ b/gtk/gtktypebuiltins.h
@@ -0,0 +1,54 @@
+/* generated by gentypeinfo from "gtk.defs" */
+
+#define GTK_TYPE_WINDOW_TYPE (gtk_type_builtins[0])
+#define GTK_TYPE_STATE_TYPE (gtk_type_builtins[1])
+#define GTK_TYPE_DIRECTION_TYPE (gtk_type_builtins[2])
+#define GTK_TYPE_SHADOW_TYPE (gtk_type_builtins[3])
+#define GTK_TYPE_ARROW_TYPE (gtk_type_builtins[4])
+#define GTK_TYPE_PACK_TYPE (gtk_type_builtins[5])
+#define GTK_TYPE_POLICY_TYPE (gtk_type_builtins[6])
+#define GTK_TYPE_UPDATE_TYPE (gtk_type_builtins[7])
+#define GTK_TYPE_ATTACH_OPTIONS (gtk_type_builtins[8])
+#define GTK_TYPE_SIGNAL_RUN_TYPE (gtk_type_builtins[9])
+#define GTK_TYPE_WINDOW_POSITION (gtk_type_builtins[10])
+#define GTK_TYPE_SUBMENU_DIRECTION (gtk_type_builtins[11])
+#define GTK_TYPE_SUBMENU_PLACEMENT (gtk_type_builtins[12])
+#define GTK_TYPE_MENU_FACTORY_TYPE (gtk_type_builtins[13])
+#define GTK_TYPE_METRIC_TYPE (gtk_type_builtins[14])
+#define GTK_TYPE_SCROLL_TYPE (gtk_type_builtins[15])
+#define GTK_TYPE_TROUGH_TYPE (gtk_type_builtins[16])
+#define GTK_TYPE_POSITION_TYPE (gtk_type_builtins[17])
+#define GTK_TYPE_PREVIEW_TYPE (gtk_type_builtins[18])
+#define GTK_TYPE_WIDGET_FLAGS (gtk_type_builtins[19])
+#define GTK_TYPE_GDK_WINDOW_TYPE (gtk_type_builtins[20])
+#define GTK_TYPE_GDK_WINDOW_CLASS (gtk_type_builtins[21])
+#define GTK_TYPE_GDK_IMAGE_TYPE (gtk_type_builtins[22])
+#define GTK_TYPE_GDK_VISUAL_TYPE (gtk_type_builtins[23])
+#define GTK_TYPE_GDK_WINDOW_ATTRIBUTES_TYPE (gtk_type_builtins[24])
+#define GTK_TYPE_GDK_WINDOW_HINTS (gtk_type_builtins[25])
+#define GTK_TYPE_GDK_FUNCTION (gtk_type_builtins[26])
+#define GTK_TYPE_GDK_FILL (gtk_type_builtins[27])
+#define GTK_TYPE_GDK_LINE_STYLE (gtk_type_builtins[28])
+#define GTK_TYPE_GDK_CAP_STYLE (gtk_type_builtins[29])
+#define GTK_TYPE_GDK_JOIN_STYLE (gtk_type_builtins[30])
+#define GTK_TYPE_GDK_CURSOR_TYPE (gtk_type_builtins[31])
+#define GTK_TYPE_GDK_EVENT_TYPE (gtk_type_builtins[32])
+#define GTK_TYPE_GDK_EVENT_MASK (gtk_type_builtins[33])
+#define GTK_TYPE_GDK_NOTIFY_TYPE (gtk_type_builtins[34])
+#define GTK_TYPE_GDK_MODIFIER_TYPE (gtk_type_builtins[35])
+#define GTK_TYPE_GDK_SUBWINDOW_MODE (gtk_type_builtins[36])
+#define GTK_TYPE_GDK_INPUT_CONDITION (gtk_type_builtins[37])
+#define GTK_TYPE_GDK_STATUS (gtk_type_builtins[38])
+#define GTK_TYPE_GDK_BYTE_ORDER (gtk_type_builtins[39])
+#define GTK_TYPE_GDK_GCVALUES_MASK (gtk_type_builtins[40])
+#define GTK_TYPE_GDK_SELECTION (gtk_type_builtins[41])
+#define GTK_TYPE_GDK_PROPERTY_STATE (gtk_type_builtins[42])
+#define GTK_TYPE_GDK_PROP_MODE (gtk_type_builtins[43])
+#define GTK_TYPE_ACCELERATOR_TABLE (gtk_type_builtins[44])
+#define GTK_TYPE_STYLE (gtk_type_builtins[45])
+#define GTK_TYPE_GDK_COLORMAP (gtk_type_builtins[46])
+#define GTK_TYPE_GDK_VISUAL (gtk_type_builtins[47])
+#define GTK_TYPE_GDK_FONT (gtk_type_builtins[48])
+#define GTK_TYPE_GDK_WINDOW (gtk_type_builtins[49])
+#define GTK_TYPE_GDK_EVENT (gtk_type_builtins[50])
+#define GTK_TYPE_NUM_BUILTINS 51
diff --git a/gtk/gtktypeutils.c b/gtk/gtktypeutils.c
new file mode 100644
index 000000000..46e035fd9
--- /dev/null
+++ b/gtk/gtktypeutils.c
@@ -0,0 +1,459 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <string.h>
+#include "gtkobject.h"
+#include "gtktypeutils.h"
+
+
+typedef struct _GtkTypeNode GtkTypeNode;
+
+struct _GtkTypeNode
+{
+ GtkType type;
+ gint init_class;
+ gpointer klass;
+ GtkTypeInfo type_info;
+ GtkTypeNode *parent;
+ GList *children;
+};
+
+
+static void gtk_type_insert (guint parent_type,
+ GtkType type,
+ GtkTypeInfo *type_info);
+static void gtk_type_class_init (GtkTypeNode *node);
+static void gtk_type_object_init (GtkTypeNode *node,
+ gpointer object);
+static guint gtk_type_hash (GtkType *key);
+static gint gtk_type_compare (GtkType *a,
+ GtkType *b);
+static guint gtk_type_name_hash (const char *key);
+static gint gtk_type_name_compare (const char *a,
+ const char *b);
+static void gtk_type_init_builtin_types ();
+
+
+static int initialize = TRUE;
+static GHashTable *type_hash_table = NULL;
+static GHashTable *name_hash_table = NULL;
+
+
+void
+gtk_type_init ()
+{
+ if (initialize)
+ {
+ g_assert (sizeof (GtkType) >= 4);
+
+ initialize = FALSE;
+ type_hash_table = g_hash_table_new ((GHashFunc) gtk_type_hash,
+ (GCompareFunc) gtk_type_compare);
+ name_hash_table = g_hash_table_new ((GHashFunc) gtk_type_name_hash,
+ (GCompareFunc) gtk_type_name_compare);
+ gtk_type_init_builtin_types ();
+ }
+}
+
+GtkType
+gtk_type_unique (GtkType parent_type,
+ GtkTypeInfo *type_info)
+{
+ static guint next_seqno = 0;
+ GtkType new_type;
+
+ g_return_val_if_fail (type_info != NULL, 0);
+
+ if (initialize)
+ gtk_type_init ();
+
+ next_seqno++;
+ if (parent_type == GTK_TYPE_INVALID)
+ new_type = next_seqno;
+ else
+ new_type = GTK_TYPE_MAKE (GTK_FUNDAMENTAL_TYPE (parent_type), next_seqno);
+ gtk_type_insert (parent_type, new_type, type_info);
+
+ return new_type;
+}
+
+gchar*
+gtk_type_name (GtkType type)
+{
+ GtkTypeNode *node;
+
+ if (initialize)
+ gtk_type_init ();
+
+ node = g_hash_table_lookup (type_hash_table, &type);
+
+ if (node)
+ return node->type_info.type_name;
+
+ return NULL;
+}
+
+GtkType
+gtk_type_from_name (const gchar *name)
+{
+ GtkTypeNode *node;
+
+ if (initialize)
+ gtk_type_init ();
+
+ node = g_hash_table_lookup (name_hash_table, (gpointer) name);
+
+ if (node)
+ return node->type;
+
+ return 0;
+}
+
+GtkType
+gtk_type_parent (GtkType type)
+{
+ GtkTypeNode *node;
+
+ if (initialize)
+ gtk_type_init ();
+
+ node = g_hash_table_lookup (type_hash_table, &type);
+
+ if (node && node->parent)
+ return node->parent->type;
+
+ return 0;
+}
+
+gpointer
+gtk_type_class (GtkType type)
+{
+ GtkTypeNode *node;
+
+ if (initialize)
+ gtk_type_init ();
+
+ node = g_hash_table_lookup (type_hash_table, &type);
+ g_return_val_if_fail (node != NULL, NULL);
+
+ if (node->init_class)
+ gtk_type_class_init (node);
+
+ return node->klass;
+}
+
+gpointer
+gtk_type_new (GtkType type)
+{
+ GtkTypeNode *node;
+ gpointer object;
+
+ if (initialize)
+ gtk_type_init ();
+
+ node = g_hash_table_lookup (type_hash_table, &type);
+ g_return_val_if_fail (node != NULL, NULL);
+
+ object = g_new0 (guchar, node->type_info.object_size);
+ ((GtkObject*) object)->klass = gtk_type_class (type);
+ gtk_type_object_init (node, object);
+
+ return object;
+}
+
+void
+gtk_type_describe_heritage (GtkType type)
+{
+ GtkTypeNode *node;
+ gint first;
+
+ if (initialize)
+ gtk_type_init ();
+
+ node = g_hash_table_lookup (type_hash_table, &type);
+ first = TRUE;
+
+ while (node)
+ {
+ if (first)
+ {
+ first = FALSE;
+ g_print ("is a ");
+ }
+
+ if (node->type_info.type_name)
+ g_print ("%s\n", node->type_info.type_name);
+ else
+ g_print ("<unnamed type>\n");
+
+ node = node->parent;
+ }
+}
+
+void
+gtk_type_describe_tree (GtkType type,
+ gint show_size)
+{
+ static gint indent = 0;
+ GtkTypeNode *node;
+ GtkTypeNode *child;
+ GList *children;
+ gint old_indent;
+ gint i;
+
+ if (initialize)
+ gtk_type_init ();
+
+ node = g_hash_table_lookup (type_hash_table, &type);
+
+ for (i = 0; i < indent; i++)
+ g_print (" ");
+
+ if (node->type_info.type_name)
+ g_print ("%s", node->type_info.type_name);
+ else
+ g_print ("<unnamed type>");
+
+ if (show_size)
+ g_print (" ( %d bytes )\n", node->type_info.object_size);
+ else
+ g_print ("\n");
+
+ old_indent = indent;
+ indent += 4;
+
+ children = node->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ gtk_type_describe_tree (child->type, show_size);
+ }
+
+ indent = old_indent;
+}
+
+gint
+gtk_type_is_a (GtkType type,
+ GtkType is_a_type)
+{
+ GtkTypeNode *node;
+
+ if (initialize)
+ gtk_type_init ();
+
+ node = g_hash_table_lookup (type_hash_table, &type);
+
+ while (node)
+ {
+ if (node->type == is_a_type)
+ return TRUE;
+ node = node->parent;
+ }
+
+ return FALSE;
+}
+
+void
+gtk_type_set_arg (GtkObject *object,
+ GtkType type,
+ GtkArg *arg)
+{
+ GtkTypeNode *node;
+
+ if (initialize)
+ gtk_type_init ();
+
+ node = g_hash_table_lookup (type_hash_table, &type);
+
+ if (node->type_info.arg_func)
+ (* node->type_info.arg_func) (object, arg);
+}
+
+static void
+gtk_type_insert (GtkType parent_type,
+ GtkType type,
+ GtkTypeInfo *type_info)
+{
+ GtkTypeNode *node;
+ GtkTypeNode *parent;
+
+ parent = g_hash_table_lookup (type_hash_table, &parent_type);
+
+ node = g_new (GtkTypeNode, 1);
+ node->type = type;
+ node->init_class = TRUE;
+ node->klass = NULL;
+ node->type_info = *type_info;
+ node->parent = parent;
+ node->children = NULL;
+
+ if (node->parent)
+ node->parent->children = g_list_append (node->parent->children, node);
+
+ g_hash_table_insert (type_hash_table, &node->type, node);
+ g_hash_table_insert (name_hash_table, node->type_info.type_name, node);
+}
+
+static void
+gtk_type_class_init (GtkTypeNode *node)
+{
+ GtkObjectClass *object_class;
+
+ if (node->init_class)
+ {
+ node->init_class = FALSE;
+ node->klass = g_new0 (guchar, node->type_info.class_size);
+
+ if (node->parent)
+ {
+ if (node->parent->init_class)
+ gtk_type_class_init (node->parent);
+
+ memcpy (node->klass, node->parent->klass, node->parent->type_info.class_size);
+ }
+
+ object_class = node->klass;
+ object_class->type = node->type;
+
+ if (node->type_info.class_init_func)
+ (* node->type_info.class_init_func) (node->klass);
+ }
+}
+
+static void
+gtk_type_object_init (GtkTypeNode *node,
+ gpointer object)
+{
+ if (node->parent)
+ gtk_type_object_init (node->parent, object);
+
+ if (node->type_info.object_init_func)
+ (* node->type_info.object_init_func) (object);
+}
+
+static guint
+gtk_type_hash (GtkType *key)
+{
+ return GTK_TYPE_SEQNO (*key);
+}
+
+static gint
+gtk_type_compare (GtkType *a,
+ GtkType *b)
+{
+ g_return_val_if_fail(a != NULL && b != NULL, 0);
+ return (*a == *b);
+}
+
+static guint
+gtk_type_name_hash (const char *key)
+{
+ guint result;
+
+ result = 0;
+ while (*key)
+ result += (result << 3) + *key++;
+
+ return result;
+}
+
+static gint
+gtk_type_name_compare (const char *a,
+ const char *b)
+{
+ return (strcmp (a, b) == 0);
+}
+
+static GtkType
+gtk_type_register_builtin (char *name,
+ GtkType parent)
+{
+ GtkTypeInfo info;
+
+ info.type_name = name;
+ info.object_size = info.class_size = 0;
+ info.class_init_func = NULL;
+ info.object_init_func = NULL;
+ info.arg_func = NULL;
+
+ return gtk_type_unique (parent, &info);
+}
+
+extern void gtk_object_init_type ();
+
+GtkType gtk_type_builtins[GTK_TYPE_NUM_BUILTINS];
+
+static void
+gtk_type_init_builtin_types ()
+{
+ /* GTK_TYPE_INVALID has typeid 0. The first type id returned by
+ gtk_type_unique is 1, which is GTK_TYPE_NONE. And so on. */
+
+ static struct {
+ GtkType enum_id;
+ gchar *name;
+ } fundamental_info[] = {
+ { GTK_TYPE_NONE, "void" },
+ { GTK_TYPE_CHAR, "char" },
+ { GTK_TYPE_BOOL, "bool" },
+ { GTK_TYPE_INT, "int" },
+ { GTK_TYPE_UINT, "uint" },
+ { GTK_TYPE_LONG, "long" },
+ { GTK_TYPE_ULONG, "ulong" },
+ { GTK_TYPE_FLOAT, "float" },
+ { GTK_TYPE_STRING, "string" },
+ { GTK_TYPE_ENUM, "enum" },
+ { GTK_TYPE_FLAGS, "flags" },
+ { GTK_TYPE_BOXED, "boxed" },
+ { GTK_TYPE_FOREIGN, "foreign" },
+ { GTK_TYPE_CALLBACK, "callback" },
+ { GTK_TYPE_ARGS, "args" },
+
+ { GTK_TYPE_POINTER, "pointer" },
+ { GTK_TYPE_SIGNAL, "signal" },
+ { GTK_TYPE_C_CALLBACK, "c_callback" }
+ };
+
+ static struct {
+ char *name;
+ GtkType parent;
+ } builtin_info[] = {
+#include "gtktypebuiltins.c"
+ { NULL }
+ };
+
+ int i;
+
+ for (i = 0; i < sizeof (fundamental_info)/sizeof(fundamental_info[0]); i++)
+ {
+ GtkType id;
+ id = gtk_type_register_builtin (fundamental_info[i].name,
+ GTK_TYPE_INVALID);
+ g_assert (id == fundamental_info[i].enum_id);
+ }
+
+ gtk_object_init_type ();
+
+ for (i = 0; builtin_info[i].name; i++)
+ {
+ gtk_type_builtins[i] =
+ gtk_type_register_builtin (builtin_info[i].name,
+ builtin_info[i].parent);
+ }
+}
diff --git a/gtk/gtktypeutils.h b/gtk/gtktypeutils.h
new file mode 100644
index 000000000..911885be9
--- /dev/null
+++ b/gtk/gtktypeutils.h
@@ -0,0 +1,196 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_TYPE_UTILS_H__
+#define __GTK_TYPE_UTILS_H__
+
+
+#include <gdk/gdk.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* Fundamental Types */
+
+typedef enum
+{
+ GTK_TYPE_INVALID,
+ GTK_TYPE_NONE,
+ GTK_TYPE_CHAR,
+ GTK_TYPE_BOOL,
+ GTK_TYPE_INT,
+ GTK_TYPE_UINT,
+ GTK_TYPE_LONG,
+ GTK_TYPE_ULONG,
+ GTK_TYPE_FLOAT,
+ GTK_TYPE_STRING,
+ GTK_TYPE_ENUM,
+ GTK_TYPE_FLAGS,
+ GTK_TYPE_BOXED,
+ GTK_TYPE_FOREIGN,
+ GTK_TYPE_CALLBACK,
+ GTK_TYPE_ARGS,
+
+ GTK_TYPE_POINTER,
+
+ /* it'd be great if the next two could be removed eventually */
+ GTK_TYPE_SIGNAL,
+ GTK_TYPE_C_CALLBACK,
+
+ GTK_TYPE_OBJECT
+
+} GtkFundamentalType;
+
+typedef guint GtkType;
+
+/* Builtin Types */
+
+extern GtkType gtk_type_builtins[];
+#include <gtk/gtktypebuiltins.h>
+
+/* General Types */
+
+#define GTK_TYPE_MAKE(ft, seqno) (((seqno)<<8)|ft)
+#define GTK_FUNDAMENTAL_TYPE(t) ((GtkFundamentalType)((t)&0xFF))
+#define GTK_TYPE_SEQNO(t) ((t)>0xFF? (t)>>8:(t))
+
+typedef struct _GtkArg GtkArg;
+typedef struct _GtkObject GtkObject; /* forward declaration of object type */
+typedef struct _GtkTypeInfo GtkTypeInfo;
+
+typedef void (*GtkClassInitFunc) (gpointer klass);
+typedef void (*GtkObjectInitFunc) (gpointer object);
+typedef void (*GtkArgFunc) (GtkObject *object, GtkArg *arg);
+typedef gint (*GtkFunction) (gpointer data);
+typedef void (*GtkRemoveFunction) (gpointer data);
+typedef void (*GtkCallbackMarshal) (GtkObject *object,
+ gpointer data,
+ int n_args,
+ GtkArg *args);
+typedef void (*GtkDestroyNotify) (gpointer data);
+
+struct _GtkArg
+{
+ GtkType type;
+ char *name;
+
+ union {
+ gchar char_data;
+ gint int_data;
+ guint uint_data;
+ gint bool_data;
+ glong long_data;
+ gulong ulong_data;
+ gfloat float_data;
+ gchar *string_data;
+ gpointer pointer_data;
+ GtkObject *object_data;
+ struct {
+ GtkCallbackMarshal marshal;
+ gpointer data;
+ GtkDestroyNotify notify;
+ } callback_data;
+ struct {
+ gpointer data;
+ GtkDestroyNotify notify;
+ } foreign_data;
+ struct {
+ gint n_args;
+ GtkArg *args;
+ } args_data;
+ struct {
+ GtkFunction f;
+ gpointer d;
+ } signal_data;
+ struct {
+ GtkFunction func;
+ gpointer func_data;
+ } c_callback_data;
+ } d;
+};
+
+#define GTK_VALUE_CHAR(a) ((a).d.char_data)
+#define GTK_VALUE_BOOL(a) ((a).d.bool_data)
+#define GTK_VALUE_INT(a) ((a).d.int_data)
+#define GTK_VALUE_UINT(a) ((a).d.uint_data)
+#define GTK_VALUE_LONG(a) ((a).d.long_data)
+#define GTK_VALUE_ULONG(a) ((a).d.ulong_data)
+#define GTK_VALUE_FLOAT(a) ((a).d.float_data)
+#define GTK_VALUE_STRING(a) ((a).d.string_data)
+#define GTK_VALUE_ENUM(a) ((a).d.int_data)
+#define GTK_VALUE_FLAGS(a) ((a).d.int_data)
+#define GTK_VALUE_BOXED(a) ((a).d.pointer_data)
+#define GTK_VALUE_FOREIGN(a) ((a).d.foreign_data)
+#define GTK_VALUE_CALLBACK(a) ((a).d.callback_data)
+#define GTK_VALUE_ARGS(a) ((a).d.args_data)
+#define GTK_VALUE_OBJECT(a) ((a).d.object_data)
+#define GTK_VALUE_POINTER(a) ((a).d.pointer_data)
+#define GTK_VALUE_SIGNAL(a) ((a).d.signal_data)
+#define GTK_VALUE_C_CALLBACK(a) ((a).d.c_callback_data)
+
+#define GTK_RETLOC_CHAR(a) ((gchar*)(a).d.pointer_data)
+#define GTK_RETLOC_BOOL(a) ((gint*)(a).d.pointer_data)
+#define GTK_RETLOC_INT(a) ((gint*)(a).d.pointer_data)
+#define GTK_RETLOC_UINT(a) ((guint*)(a).d.pointer_data)
+#define GTK_RETLOC_LONG(a) ((glong*)(a).d.pointer_data)
+#define GTK_RETLOC_ULONG(a) ((gulong*)(a).d.pointer_data)
+#define GTK_RETLOC_FLOAT(a) ((gfloat*)(a).d.pointer_data)
+#define GTK_RETLOC_STRING(a) ((gchar**)(a).d.pointer_data)
+#define GTK_RETLOC_ENUM(a) ((gint*)(a).d.pointer_data)
+#define GTK_RETLOC_FLAGS(a) ((gint*)(a).d.pointer_data)
+#define GTK_RETLOC_BOXED(a) ((gpointer*)(a).d.pointer_data)
+#define GTK_RETLOC_OBJECT(a) ((GtkObject**)(a).d.pointer_data)
+#define GTK_RETLOC_POINTER(a) ((gpointer*)(a).d.pointer_data)
+
+struct _GtkTypeInfo
+{
+ gchar *type_name;
+ guint object_size;
+ guint class_size;
+ GtkClassInitFunc class_init_func;
+ GtkObjectInitFunc object_init_func;
+ GtkArgFunc arg_func;
+};
+
+
+void gtk_type_init (void);
+GtkType gtk_type_unique (guint parent_type,
+ GtkTypeInfo *type_info);
+gchar* gtk_type_name (guint type);
+GtkType gtk_type_from_name (const gchar *name);
+GtkType gtk_type_parent (GtkType type);
+gpointer gtk_type_class (GtkType type);
+gpointer gtk_type_new (GtkType type);
+void gtk_type_describe_heritage (GtkType type);
+void gtk_type_describe_tree (GtkType type,
+ gint show_size);
+gint gtk_type_is_a (GtkType type,
+ GtkType is_a_type);
+void gtk_type_set_arg (GtkObject *object,
+ GtkType type,
+ GtkArg *arg);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_TYPE_UTILS_H__ */
diff --git a/gtk/gtkvbbox.c b/gtk/gtkvbbox.c
new file mode 100644
index 000000000..4fc867fdf
--- /dev/null
+++ b/gtk/gtkvbbox.c
@@ -0,0 +1,272 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtkvbbox.h"
+
+
+static void gtk_vbutton_box_class_init (GtkVButtonBoxClass *klass);
+static void gtk_vbutton_box_init (GtkVButtonBox *box);
+static void gtk_vbutton_box_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void gtk_vbutton_box_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+
+static gint default_spacing = 10;
+static gint default_layout_style = GTK_BUTTONBOX_EDGE;
+
+guint
+gtk_vbutton_box_get_type ()
+{
+ static guint vbutton_box_type = 0;
+
+ if (!vbutton_box_type)
+ {
+ GtkTypeInfo vbutton_box_info =
+ {
+ "GtkVButtonBox",
+ sizeof (GtkVButtonBox),
+ sizeof (GtkVButtonBoxClass),
+ (GtkClassInitFunc) gtk_vbutton_box_class_init,
+ (GtkObjectInitFunc) gtk_vbutton_box_init,
+ (GtkArgFunc) NULL,
+ };
+
+ vbutton_box_type = gtk_type_unique (gtk_button_box_get_type (), &vbutton_box_info);
+ }
+
+ return vbutton_box_type;
+}
+
+static void
+gtk_vbutton_box_class_init (GtkVButtonBoxClass *class)
+{
+ GtkWidgetClass *widget_class;
+
+ widget_class = (GtkWidgetClass*) class;
+
+ widget_class->size_request = gtk_vbutton_box_size_request;
+ widget_class->size_allocate = gtk_vbutton_box_size_allocate;
+}
+
+static void
+gtk_vbutton_box_init (GtkVButtonBox *vbutton_box)
+{
+ /* button_box_init has done everything allready */
+}
+
+GtkWidget*
+gtk_vbutton_box_new ()
+{
+ GtkVButtonBox *vbutton_box;
+
+ vbutton_box = gtk_type_new (gtk_vbutton_box_get_type ());
+ return GTK_WIDGET (vbutton_box);
+}
+
+
+
+/* set default value for spacing */
+
+void gtk_vbutton_box_set_spacing_default (gint spacing)
+{
+ default_spacing = spacing;
+}
+
+
+/* set default value for layout style */
+
+void gtk_vbutton_box_set_layout_default (gint layout)
+{
+ default_layout_style = layout;
+}
+
+/* get default value for spacing */
+
+gint gtk_vbutton_box_get_spacing_default (void)
+{
+ return default_spacing;
+}
+
+
+
+/* get default value for layout style */
+
+gint gtk_vbutton_box_get_layout_default (void)
+{
+ return default_layout_style;
+}
+
+
+
+
+static void
+gtk_vbutton_box_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkBox *box;
+ GtkButtonBox *bbox;
+ gint nvis_children;
+ gint child_width;
+ gint child_height;
+ gint spacing;
+ gint layout;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_VBUTTON_BOX (widget));
+ g_return_if_fail (requisition != NULL);
+
+ box = GTK_BOX (widget);
+ bbox = GTK_BUTTON_BOX (widget);
+
+ spacing = bbox->spacing != GTK_BUTTONBOX_DEFAULT
+ ? bbox->spacing : default_spacing;
+ layout = bbox->layout_style != GTK_BUTTONBOX_DEFAULT
+ ? bbox->layout_style : default_layout_style;
+
+ gtk_button_box_child_requisition (widget,
+ &nvis_children,
+ &child_width,
+ &child_height);
+
+ if (nvis_children == 0)
+ {
+ requisition->width = 0;
+ requisition->height = 0;
+ }
+ else
+ {
+ switch (layout)
+ {
+ case GTK_BUTTONBOX_SPREAD:
+ requisition->height =
+ nvis_children*child_height + ((nvis_children+1)*spacing);
+ break;
+ case GTK_BUTTONBOX_EDGE:
+ case GTK_BUTTONBOX_START:
+ case GTK_BUTTONBOX_END:
+ requisition->height =
+ nvis_children*child_height + ((nvis_children-1)*spacing);
+ break;
+ default:
+ g_assert_not_reached();
+ break;
+ }
+
+ requisition->width = child_width;
+ }
+
+ requisition->width += GTK_CONTAINER (box)->border_width * 2;
+ requisition->height += GTK_CONTAINER (box)->border_width * 2;
+}
+
+
+
+static void
+gtk_vbutton_box_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkButtonBox *box;
+ GtkVButtonBox *hbox;
+ GtkBoxChild *child;
+ GList *children;
+ GtkAllocation child_allocation;
+ gint nvis_children;
+ gint child_width;
+ gint child_height;
+ gint x = 0;
+ gint y = 0;
+ gint height;
+ gint childspace;
+ gint childspacing = 0;
+ gint layout;
+ gint spacing;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_VBUTTON_BOX (widget));
+ g_return_if_fail (allocation != NULL);
+
+ box = GTK_BUTTON_BOX (widget);
+ hbox = GTK_VBUTTON_BOX (widget);
+ spacing = box->spacing != GTK_BUTTONBOX_DEFAULT
+ ? box->spacing : default_spacing;
+ layout = box->layout_style != GTK_BUTTONBOX_DEFAULT
+ ? box->layout_style : default_layout_style;
+ gtk_button_box_child_requisition (widget,
+ &nvis_children,
+ &child_width,
+ &child_height);
+ widget->allocation = *allocation;
+ height = allocation->height - GTK_CONTAINER (box)->border_width*2;
+ switch (layout)
+ {
+ case GTK_BUTTONBOX_SPREAD:
+ childspacing = (height - (nvis_children*child_height)) / (nvis_children+1);
+ y = allocation->y + GTK_CONTAINER (box)->border_width + childspacing;
+ break;
+ case GTK_BUTTONBOX_EDGE:
+ if (nvis_children >= 2)
+ {
+ childspacing =
+ (height - (nvis_children*child_height)) / (nvis_children-1);
+ y = allocation->y + GTK_CONTAINER (box)->border_width;
+ }
+ else
+ {
+ /* one or zero children, just center */
+ childspacing = height;
+ y = allocation->y + (allocation->height - child_height) / 2;
+ }
+ break;
+ case GTK_BUTTONBOX_START:
+ childspacing = spacing;
+ y = allocation->y + GTK_CONTAINER (box)->border_width;
+ break;
+ case GTK_BUTTONBOX_END:
+ childspacing = spacing;
+ y = allocation->x + allocation->height - child_height * nvis_children
+ - spacing * (nvis_children-1)
+ - GTK_CONTAINER (box)->border_width;
+ break;
+ default:
+ g_assert_not_reached();
+ break;
+ }
+
+
+ x = allocation->x + (allocation->width - child_width) / 2;
+ childspace = child_height + childspacing;
+
+ children = GTK_BOX (box)->children;
+
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_VISIBLE (child->widget))
+ {
+ child_allocation.width = child_width;
+ child_allocation.height = child_height;
+ child_allocation.x = x;
+ child_allocation.y = y;
+ gtk_widget_size_allocate (child->widget, &child_allocation);
+ y += childspace;
+ }
+ }
+}
+
+
diff --git a/gtk/gtkvbbox.h b/gtk/gtkvbbox.h
new file mode 100644
index 000000000..310553d2a
--- /dev/null
+++ b/gtk/gtkvbbox.h
@@ -0,0 +1,66 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_VBUTTON_BOX_H__
+#define __GTK_VBUTTON_BOX_H__
+
+
+#include "gtkbbox.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_VBUTTON_BOX(obj) GTK_CHECK_CAST (obj, gtk_vbutton_box_get_type (), GtkVButtonBox)
+#define GTK_VBUTTON_BOX_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_vbutton_box_get_type (), GtkVButtonBoxClass)
+#define GTK_IS_VBUTTON_BOX(obj) GTK_CHECK_TYPE (obj, gtk_vbutton_box_get_type ())
+
+
+typedef struct _GtkVButtonBox GtkVButtonBox;
+typedef struct _GtkVButtonBoxClass GtkVButtonBoxClass;
+
+struct _GtkVButtonBox
+{
+ GtkButtonBox button_box;
+};
+
+struct _GtkVButtonBoxClass
+{
+ GtkButtonBoxClass parent_class;
+};
+
+
+guint gtk_vbutton_box_get_type (void);
+GtkWidget *gtk_vbutton_box_new (void);
+
+/* buttons can be added by gtk_container_add() */
+
+gint gtk_vbutton_box_get_spacing_default (void);
+void gtk_vbutton_box_set_spacing_default (gint spacing);
+
+void gtk_vbutton_box_set_spacing_default (gint spacing);
+void gtk_vbutton_box_set_layout_default (gint layout);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_VBUTTON_BOX_H__ */
diff --git a/gtk/gtkvbox.c b/gtk/gtkvbox.c
new file mode 100644
index 000000000..585e99b87
--- /dev/null
+++ b/gtk/gtkvbox.c
@@ -0,0 +1,306 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtkvbox.h"
+
+
+static void gtk_vbox_class_init (GtkVBoxClass *klass);
+static void gtk_vbox_init (GtkVBox *box);
+static void gtk_vbox_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void gtk_vbox_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+
+
+guint
+gtk_vbox_get_type ()
+{
+ static guint vbox_type = 0;
+
+ if (!vbox_type)
+ {
+ GtkTypeInfo vbox_info =
+ {
+ "GtkVBox",
+ sizeof (GtkVBox),
+ sizeof (GtkVBoxClass),
+ (GtkClassInitFunc) gtk_vbox_class_init,
+ (GtkObjectInitFunc) gtk_vbox_init,
+ (GtkArgFunc) NULL,
+ };
+
+ vbox_type = gtk_type_unique (gtk_box_get_type (), &vbox_info);
+ }
+
+ return vbox_type;
+}
+
+static void
+gtk_vbox_class_init (GtkVBoxClass *class)
+{
+ GtkWidgetClass *widget_class;
+
+ widget_class = (GtkWidgetClass*) class;
+
+ widget_class->size_request = gtk_vbox_size_request;
+ widget_class->size_allocate = gtk_vbox_size_allocate;
+}
+
+static void
+gtk_vbox_init (GtkVBox *vbox)
+{
+}
+
+GtkWidget*
+gtk_vbox_new (gint homogeneous,
+ gint spacing)
+{
+ GtkVBox *vbox;
+
+ vbox = gtk_type_new (gtk_vbox_get_type ());
+
+ GTK_BOX (vbox)->spacing = spacing;
+ GTK_BOX (vbox)->homogeneous = homogeneous ? TRUE : FALSE;
+
+ return GTK_WIDGET (vbox);
+}
+
+
+static void
+gtk_vbox_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkBox *box;
+ GtkBoxChild *child;
+ GList *children;
+ gint nvis_children;
+ gint height;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_VBOX (widget));
+ g_return_if_fail (requisition != NULL);
+
+ box = GTK_BOX (widget);
+ requisition->width = 0;
+ requisition->height = 0;
+ nvis_children = 0;
+
+ children = box->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_VISIBLE (child->widget))
+ {
+ gtk_widget_size_request (child->widget, &child->widget->requisition);
+
+ if (box->homogeneous)
+ {
+ height = child->widget->requisition.height + child->padding * 2;
+ requisition->height = MAX (requisition->height, height);
+ }
+ else
+ {
+ requisition->height += child->widget->requisition.height + child->padding * 2;
+ }
+
+ requisition->width = MAX (requisition->width, child->widget->requisition.width);
+
+ nvis_children += 1;
+ }
+ }
+
+ if (nvis_children > 0)
+ {
+ if (box->homogeneous)
+ requisition->height *= nvis_children;
+ requisition->height += (nvis_children - 1) * box->spacing;
+ }
+
+ requisition->width += GTK_CONTAINER (box)->border_width * 2;
+ requisition->height += GTK_CONTAINER (box)->border_width * 2;
+}
+
+static void
+gtk_vbox_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkBox *box;
+ GtkBoxChild *child;
+ GList *children;
+ GtkAllocation child_allocation;
+ gint nvis_children;
+ gint nexpand_children;
+ gint child_height;
+ gint height;
+ gint extra;
+ gint y;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_VBOX (widget));
+ g_return_if_fail (allocation != NULL);
+
+ box = GTK_BOX (widget);
+ widget->allocation = *allocation;
+
+ nvis_children = 0;
+ nexpand_children = 0;
+ children = box->children;
+
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if (GTK_WIDGET_VISIBLE (child->widget))
+ {
+ nvis_children += 1;
+ if (child->expand)
+ nexpand_children += 1;
+ }
+ }
+
+ if (nvis_children > 0)
+ {
+ if (box->homogeneous)
+ {
+ height = (allocation->height -
+ GTK_CONTAINER (box)->border_width * 2 -
+ (nvis_children - 1) * box->spacing);
+ extra = height / nvis_children;
+ }
+ else if (nexpand_children > 0)
+ {
+ height = allocation->height - widget->requisition.height;
+ extra = height / nexpand_children;
+ }
+ else
+ {
+ height = 0;
+ extra = 0;
+ }
+
+ y = allocation->y + GTK_CONTAINER (box)->border_width;
+ child_allocation.x = allocation->x + GTK_CONTAINER (box)->border_width;
+ child_allocation.width = allocation->width - GTK_CONTAINER (box)->border_width * 2;
+
+ children = box->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if ((child->pack == GTK_PACK_START) && GTK_WIDGET_VISIBLE (child->widget))
+ {
+ if (box->homogeneous)
+ {
+ if (nvis_children == 1)
+ child_height = height;
+ else
+ child_height = extra;
+
+ nvis_children -= 1;
+ height -= extra;
+ }
+ else
+ {
+ child_height = child->widget->requisition.height + child->padding * 2;
+
+ if (child->expand)
+ {
+ if (nexpand_children == 1)
+ child_height += height;
+ else
+ child_height += extra;
+
+ nexpand_children -= 1;
+ height -= extra;
+ }
+ }
+
+ if (child->fill)
+ {
+ child_allocation.height = child_height - child->padding * 2;
+ child_allocation.y = y + child->padding;
+ }
+ else
+ {
+ child_allocation.height = child->widget->requisition.height;
+ child_allocation.y = y + (child_height - child_allocation.height) / 2;
+ }
+
+ gtk_widget_size_allocate (child->widget, &child_allocation);
+
+ y += child_height + box->spacing;
+ }
+ }
+
+ y = allocation->y + allocation->height - GTK_CONTAINER (box)->border_width;
+
+ children = box->children;
+ while (children)
+ {
+ child = children->data;
+ children = children->next;
+
+ if ((child->pack == GTK_PACK_END) && GTK_WIDGET_VISIBLE (child->widget))
+ {
+ if (box->homogeneous)
+ {
+ if (nvis_children == 1)
+ child_height = height;
+ else
+ child_height = extra;
+
+ nvis_children -= 1;
+ height -= extra;
+ }
+ else
+ {
+ child_height = child->widget->requisition.height + child->padding * 2;
+
+ if (child->expand)
+ {
+ if (nexpand_children == 1)
+ child_height += height;
+ else
+ child_height += extra;
+
+ nexpand_children -= 1;
+ height -= extra;
+ }
+ }
+
+ if (child->fill)
+ {
+ child_allocation.height = child_height - child->padding * 2;
+ child_allocation.y = y + child->padding - child_height;
+ }
+ else
+ {
+ child_allocation.height = child->widget->requisition.height;
+ child_allocation.y = y + (child_height - child_allocation.height) / 2 - child_height;
+ }
+
+ gtk_widget_size_allocate (child->widget, &child_allocation);
+
+ y -= (child_height + box->spacing);
+ }
+ }
+ }
+}
diff --git a/gtk/gtkvbox.h b/gtk/gtkvbox.h
new file mode 100644
index 000000000..aad32c914
--- /dev/null
+++ b/gtk/gtkvbox.h
@@ -0,0 +1,60 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_VBOX_H__
+#define __GTK_VBOX_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkbox.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_VBOX(obj) GTK_CHECK_CAST (obj, gtk_vbox_get_type (), GtkVBox)
+#define GTK_VBOX_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_vbox_get_type (), GtkVBoxClass)
+#define GTK_IS_VBOX(obj) GTK_CHECK_TYPE (obj, gtk_vbox_get_type ())
+
+
+typedef struct _GtkVBox GtkVBox;
+typedef struct _GtkVBoxClass GtkVBoxClass;
+
+struct _GtkVBox
+{
+ GtkBox box;
+};
+
+struct _GtkVBoxClass
+{
+ GtkBoxClass parent_class;
+};
+
+
+guint gtk_vbox_get_type (void);
+GtkWidget* gtk_vbox_new (gint homogeneous,
+ gint spacing);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_VBOX_H__ */
diff --git a/gtk/gtkviewport.c b/gtk/gtkviewport.c
new file mode 100644
index 000000000..dfa00c4b0
--- /dev/null
+++ b/gtk/gtkviewport.c
@@ -0,0 +1,616 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtksignal.h"
+#include "gtkviewport.h"
+
+
+static void gtk_viewport_class_init (GtkViewportClass *klass);
+static void gtk_viewport_init (GtkViewport *viewport);
+static void gtk_viewport_map (GtkWidget *widget);
+static void gtk_viewport_unmap (GtkWidget *widget);
+static void gtk_viewport_realize (GtkWidget *widget);
+static void gtk_viewport_unrealize (GtkWidget *widget);
+static void gtk_viewport_paint (GtkWidget *widget,
+ GdkRectangle *area);
+static void gtk_viewport_draw (GtkWidget *widget,
+ GdkRectangle *area);
+static gint gtk_viewport_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+static void gtk_viewport_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void gtk_viewport_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static gint gtk_viewport_need_resize (GtkContainer *container);
+static void gtk_viewport_adjustment_changed (GtkAdjustment *adjustment,
+ gpointer data);
+static void gtk_viewport_adjustment_value_changed (GtkAdjustment *adjustment,
+ gpointer data);
+
+
+guint
+gtk_viewport_get_type ()
+{
+ static guint viewport_type = 0;
+
+ if (!viewport_type)
+ {
+ GtkTypeInfo viewport_info =
+ {
+ "GtkViewport",
+ sizeof (GtkViewport),
+ sizeof (GtkViewportClass),
+ (GtkClassInitFunc) gtk_viewport_class_init,
+ (GtkObjectInitFunc) gtk_viewport_init,
+ (GtkArgFunc) NULL,
+ };
+
+ viewport_type = gtk_type_unique (gtk_bin_get_type (), &viewport_info);
+ }
+
+ return viewport_type;
+}
+
+static void
+gtk_viewport_class_init (GtkViewportClass *class)
+{
+ GtkWidgetClass *widget_class;
+ GtkContainerClass *container_class;
+
+ widget_class = (GtkWidgetClass*) class;
+ container_class = (GtkContainerClass*) class;
+
+ widget_class->map = gtk_viewport_map;
+ widget_class->unmap = gtk_viewport_unmap;
+ widget_class->realize = gtk_viewport_realize;
+ widget_class->unrealize = gtk_viewport_unrealize;
+ widget_class->draw = gtk_viewport_draw;
+ widget_class->expose_event = gtk_viewport_expose;
+ widget_class->size_request = gtk_viewport_size_request;
+ widget_class->size_allocate = gtk_viewport_size_allocate;
+
+ container_class->need_resize = gtk_viewport_need_resize;
+}
+
+static void
+gtk_viewport_init (GtkViewport *viewport)
+{
+ GTK_WIDGET_UNSET_FLAGS (viewport, GTK_NO_WINDOW);
+ GTK_WIDGET_SET_FLAGS (viewport, GTK_BASIC);
+
+ viewport->shadow_type = GTK_SHADOW_IN;
+ viewport->main_window = NULL;
+ viewport->view_window = NULL;
+ viewport->hadjustment = NULL;
+ viewport->vadjustment = NULL;
+}
+
+GtkWidget*
+gtk_viewport_new (GtkAdjustment *hadjustment,
+ GtkAdjustment *vadjustment)
+{
+ GtkViewport *viewport;
+
+ viewport = gtk_type_new (gtk_viewport_get_type ());
+
+ if (!hadjustment)
+ hadjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+
+ if (!vadjustment)
+ vadjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+
+ gtk_viewport_set_hadjustment (viewport, hadjustment);
+ gtk_viewport_set_vadjustment (viewport, vadjustment);
+
+ return GTK_WIDGET (viewport);
+}
+
+GtkAdjustment*
+gtk_viewport_get_hadjustment (GtkViewport *viewport)
+{
+ g_return_val_if_fail (viewport != NULL, NULL);
+ g_return_val_if_fail (GTK_IS_VIEWPORT (viewport), NULL);
+
+ return viewport->hadjustment;
+}
+
+GtkAdjustment*
+gtk_viewport_get_vadjustment (GtkViewport *viewport)
+{
+ g_return_val_if_fail (viewport != NULL, NULL);
+ g_return_val_if_fail (GTK_IS_VIEWPORT (viewport), NULL);
+
+ return viewport->vadjustment;
+}
+
+void
+gtk_viewport_set_hadjustment (GtkViewport *viewport,
+ GtkAdjustment *adjustment)
+{
+ g_return_if_fail (viewport != NULL);
+ g_return_if_fail (GTK_IS_VIEWPORT (viewport));
+ g_return_if_fail (adjustment != NULL);
+
+ if (viewport->hadjustment)
+ {
+ gtk_signal_disconnect_by_data (GTK_OBJECT (viewport->hadjustment), (gpointer) viewport);
+ gtk_object_unref (GTK_OBJECT (viewport->hadjustment));
+ }
+
+ viewport->hadjustment = adjustment;
+ gtk_object_ref (GTK_OBJECT (viewport->hadjustment));
+
+ gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
+ (GtkSignalFunc) gtk_viewport_adjustment_changed,
+ (gpointer) viewport);
+ gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
+ (GtkSignalFunc) gtk_viewport_adjustment_value_changed,
+ (gpointer) viewport);
+
+ gtk_viewport_adjustment_changed (adjustment, (gpointer) viewport);
+}
+
+void
+gtk_viewport_set_vadjustment (GtkViewport *viewport,
+ GtkAdjustment *adjustment)
+{
+ g_return_if_fail (viewport != NULL);
+ g_return_if_fail (GTK_IS_VIEWPORT (viewport));
+ g_return_if_fail (adjustment != NULL);
+
+ if (viewport->vadjustment)
+ {
+ gtk_signal_disconnect_by_data (GTK_OBJECT (viewport->vadjustment), (gpointer) viewport);
+ gtk_object_unref (GTK_OBJECT (viewport->vadjustment));
+ }
+
+ viewport->vadjustment = adjustment;
+ gtk_object_ref (GTK_OBJECT (viewport->vadjustment));
+
+ gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
+ (GtkSignalFunc) gtk_viewport_adjustment_changed,
+ (gpointer) viewport);
+ gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
+ (GtkSignalFunc) gtk_viewport_adjustment_value_changed,
+ (gpointer) viewport);
+
+ gtk_viewport_adjustment_changed (adjustment, (gpointer) viewport);
+}
+
+void
+gtk_viewport_set_shadow_type (GtkViewport *viewport,
+ GtkShadowType type)
+{
+ g_return_if_fail (viewport != NULL);
+ g_return_if_fail (GTK_IS_VIEWPORT (viewport));
+
+ if ((GtkShadowType) viewport->shadow_type != type)
+ {
+ viewport->shadow_type = type;
+
+ if (GTK_WIDGET_VISIBLE (viewport))
+ {
+ gtk_widget_size_allocate (GTK_WIDGET (viewport), &(GTK_WIDGET (viewport)->allocation));
+ gtk_widget_queue_draw (GTK_WIDGET (viewport));
+ }
+ }
+}
+
+
+static void
+gtk_viewport_map (GtkWidget *widget)
+{
+ GtkViewport *viewport;
+ GtkBin *bin;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_VIEWPORT (widget));
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
+ viewport = GTK_VIEWPORT (widget);
+ bin = GTK_BIN (widget);
+
+ gdk_window_show (viewport->main_window);
+
+ if (bin->child &&
+ GTK_WIDGET_VISIBLE (bin->child) &&
+ !GTK_WIDGET_MAPPED (bin->child))
+ gtk_widget_map (bin->child);
+}
+
+static void
+gtk_viewport_unmap (GtkWidget *widget)
+{
+ GtkViewport *viewport;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_VIEWPORT (widget));
+
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
+ viewport = GTK_VIEWPORT (widget);
+
+ gdk_window_hide (viewport->main_window);
+}
+
+static void
+gtk_viewport_realize (GtkWidget *widget)
+{
+ GtkViewport *viewport;
+ GdkWindowAttr attributes;
+ GtkRequisition *child_requisition;
+ gint attributes_mask;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_VIEWPORT (widget));
+
+ viewport = GTK_VIEWPORT (widget);
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+
+ attributes.x = widget->allocation.x + GTK_CONTAINER (widget)->border_width;
+ attributes.y = widget->allocation.y + GTK_CONTAINER (widget)->border_width;
+ attributes.width = widget->allocation.width - GTK_CONTAINER (widget)->border_width * 2;
+ attributes.height = widget->allocation.height - GTK_CONTAINER (widget)->border_width * 2;
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
+ attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+
+ viewport->main_window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
+ gdk_window_set_user_data (viewport->main_window, viewport);
+
+ attributes.x += widget->style->klass->xthickness;
+ attributes.y += widget->style->klass->ythickness;
+ attributes.width -= widget->style->klass->xthickness * 2;
+ attributes.height -= widget->style->klass->ythickness * 2;
+
+ viewport->view_window = gdk_window_new (viewport->main_window, &attributes, attributes_mask);
+ gdk_window_set_user_data (viewport->view_window, viewport);
+
+ attributes.x = 0;
+ attributes.y = 0;
+
+ if (GTK_BIN (viewport)->child)
+ {
+ child_requisition = &GTK_WIDGET (GTK_BIN (viewport)->child)->requisition;
+ attributes.width = child_requisition->width;
+ attributes.height = child_requisition->height;
+ }
+
+ widget->window = gdk_window_new (viewport->view_window, &attributes, attributes_mask);
+ gdk_window_set_user_data (widget->window, viewport);
+
+ widget->style = gtk_style_attach (widget->style, viewport->main_window);
+ gtk_style_set_background (widget->style, viewport->main_window, GTK_STATE_NORMAL);
+ gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
+
+ gdk_window_show (widget->window);
+ gdk_window_show (viewport->view_window);
+}
+
+static void
+gtk_viewport_unrealize (GtkWidget *widget)
+{
+ GtkViewport *viewport;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_VIEWPORT (widget));
+
+ viewport = GTK_VIEWPORT (widget);
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_REALIZED | GTK_MAPPED);
+
+ gtk_style_detach (widget->style);
+
+ gdk_window_destroy (widget->window);
+ gdk_window_destroy (viewport->view_window);
+ gdk_window_destroy (viewport->main_window);
+
+ widget->window = NULL;
+ viewport->view_window = NULL;
+ viewport->main_window = NULL;
+}
+
+static void
+gtk_viewport_paint (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ GtkViewport *viewport;
+ GtkStateType state;
+ gint x, y;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_VIEWPORT (widget));
+ g_return_if_fail (area != NULL);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ viewport = GTK_VIEWPORT (widget);
+
+ state = widget->state;
+ if (!GTK_WIDGET_IS_SENSITIVE (widget))
+ state = GTK_STATE_INSENSITIVE;
+
+ x = GTK_CONTAINER (viewport)->border_width;
+ y = GTK_CONTAINER (viewport)->border_width;
+
+ gtk_draw_shadow (widget->style, viewport->main_window,
+ GTK_STATE_NORMAL, viewport->shadow_type,
+ 0, 0, -1, -1);
+ }
+}
+
+static void
+gtk_viewport_draw (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ GtkViewport *viewport;
+ GtkBin *bin;
+ GdkRectangle tmp_area;
+ GdkRectangle child_area;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_VIEWPORT (widget));
+ g_return_if_fail (area != NULL);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ viewport = GTK_VIEWPORT (widget);
+ bin = GTK_BIN (widget);
+
+ gtk_viewport_paint (widget, area);
+
+ if (bin->child)
+ {
+ tmp_area = *area;
+ tmp_area.x += viewport->hadjustment->value;
+ tmp_area.y += viewport->vadjustment->value;
+
+ if (gtk_widget_intersect (bin->child, &tmp_area, &child_area))
+ gtk_widget_draw (bin->child, &child_area);
+ }
+ }
+}
+
+static gint
+gtk_viewport_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ GtkViewport *viewport;
+ GtkBin *bin;
+ GdkEventExpose child_event;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_VIEWPORT (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ viewport = GTK_VIEWPORT (widget);
+ bin = GTK_BIN (widget);
+
+ if (event->window == viewport->main_window)
+ gtk_viewport_paint (widget, &event->area);
+
+ child_event = *event;
+ if (bin->child &&
+ GTK_WIDGET_NO_WINDOW (bin->child) &&
+ gtk_widget_intersect (bin->child, &event->area, &child_event.area))
+ gtk_widget_event (bin->child, (GdkEvent*) &child_event);
+ }
+
+ return FALSE;
+}
+
+static void
+gtk_viewport_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkViewport *viewport;
+ GtkBin *bin;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_VIEWPORT (widget));
+ g_return_if_fail (requisition != NULL);
+
+ viewport = GTK_VIEWPORT (widget);
+ bin = GTK_BIN (widget);
+
+ requisition->width = (GTK_CONTAINER (widget)->border_width +
+ GTK_WIDGET (widget)->style->klass->xthickness) * 2 + 5;
+
+ requisition->height = (GTK_CONTAINER (widget)->border_width * 2 +
+ GTK_WIDGET (widget)->style->klass->ythickness) * 2 + 5;
+
+ if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
+ gtk_widget_size_request (bin->child, &bin->child->requisition);
+}
+
+static void
+gtk_viewport_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkViewport *viewport;
+ GtkBin *bin;
+ GtkAllocation child_allocation;
+ gint hval, vval;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_VIEWPORT (widget));
+ g_return_if_fail (allocation != NULL);
+
+ widget->allocation = *allocation;
+ viewport = GTK_VIEWPORT (widget);
+ bin = GTK_BIN (widget);
+
+ child_allocation.x = GTK_WIDGET (viewport)->style->klass->xthickness;
+ child_allocation.width = allocation->width - child_allocation.x * 2;
+
+ child_allocation.y = GTK_WIDGET (viewport)->style->klass->ythickness;
+ child_allocation.height = allocation->height - child_allocation.y * 2;
+
+ if (GTK_WIDGET_REALIZED (widget))
+ {
+ gdk_window_move_resize (viewport->main_window,
+ allocation->x + GTK_CONTAINER (viewport)->border_width,
+ allocation->y + GTK_CONTAINER (viewport)->border_width,
+ allocation->width - GTK_CONTAINER (viewport)->border_width * 2,
+ allocation->height - GTK_CONTAINER (viewport)->border_width * 2);
+
+ gdk_window_move_resize (viewport->view_window,
+ child_allocation.x,
+ child_allocation.y,
+ child_allocation.width,
+ child_allocation.height);
+ }
+
+ viewport->hadjustment->page_size = child_allocation.width;
+ viewport->hadjustment->page_increment = viewport->hadjustment->page_size / 2;
+ viewport->hadjustment->step_increment = 10;
+
+ viewport->vadjustment->page_size = child_allocation.height;
+ viewport->vadjustment->page_increment = viewport->vadjustment->page_size / 2;
+ viewport->vadjustment->step_increment = 10;
+
+ hval = viewport->hadjustment->value;
+ vval = viewport->vadjustment->value;
+
+ if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
+ {
+ viewport->hadjustment->lower = 0;
+ viewport->hadjustment->upper = MAX (bin->child->requisition.width,
+ child_allocation.width);
+
+ hval = CLAMP (hval, 0,
+ viewport->hadjustment->upper -
+ viewport->hadjustment->page_size);
+
+ viewport->vadjustment->lower = 0;
+ viewport->vadjustment->upper = MAX (bin->child->requisition.height,
+ child_allocation.height);
+
+ vval = CLAMP (vval, 0,
+ viewport->vadjustment->upper -
+ viewport->vadjustment->page_size);
+ }
+
+ if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
+ {
+ child_allocation.x = 0;
+ child_allocation.y = 0;
+
+ child_allocation.width = viewport->hadjustment->upper;
+ child_allocation.height = viewport->vadjustment->upper;
+
+ if (!GTK_WIDGET_REALIZED (widget))
+ gtk_widget_realize (widget);
+
+ gdk_window_resize (widget->window,
+ child_allocation.width,
+ child_allocation.height);
+
+ child_allocation.x = 0;
+ child_allocation.y = 0;
+ gtk_widget_size_allocate (bin->child, &child_allocation);
+ }
+
+ gtk_signal_emit_by_name (GTK_OBJECT (viewport->hadjustment), "changed");
+ gtk_signal_emit_by_name (GTK_OBJECT (viewport->vadjustment), "changed");
+ if (viewport->hadjustment->value != hval)
+ {
+ viewport->hadjustment->value = hval;
+ gtk_signal_emit_by_name (GTK_OBJECT (viewport->hadjustment), "value_changed");
+ }
+ if (viewport->vadjustment->value != vval)
+ {
+ viewport->vadjustment->value = vval;
+ gtk_signal_emit_by_name (GTK_OBJECT (viewport->vadjustment), "value_changed");
+ }
+}
+
+static gint
+gtk_viewport_need_resize (GtkContainer *container)
+{
+ GtkBin *bin;
+
+ g_return_val_if_fail (container != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_VIEWPORT (container), FALSE);
+
+ if (GTK_WIDGET_REALIZED (container))
+ {
+ bin = GTK_BIN (container);
+
+ gtk_widget_size_request (bin->child, &bin->child->requisition);
+
+ gtk_widget_size_allocate (GTK_WIDGET (container),
+ &(GTK_WIDGET (container)->allocation));
+ }
+
+ return FALSE;
+}
+
+static void
+gtk_viewport_adjustment_changed (GtkAdjustment *adjustment,
+ gpointer data)
+{
+ GtkViewport *viewport;
+
+ g_return_if_fail (adjustment != NULL);
+ g_return_if_fail (data != NULL);
+ g_return_if_fail (GTK_IS_VIEWPORT (data));
+
+ viewport = GTK_VIEWPORT (data);
+}
+
+static void
+gtk_viewport_adjustment_value_changed (GtkAdjustment *adjustment,
+ gpointer data)
+{
+ GtkViewport *viewport;
+ GtkBin *bin;
+ GtkAllocation child_allocation;
+ gint width, height;
+
+ g_return_if_fail (adjustment != NULL);
+ g_return_if_fail (data != NULL);
+ g_return_if_fail (GTK_IS_VIEWPORT (data));
+
+ viewport = GTK_VIEWPORT (data);
+ bin = GTK_BIN (data);
+
+ if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
+ {
+ gdk_window_get_size (viewport->view_window, &width, &height);
+
+ child_allocation.x = 0;
+ child_allocation.y = 0;
+
+ if (viewport->hadjustment->lower != (viewport->hadjustment->upper -
+ viewport->hadjustment->page_size))
+ child_allocation.x = viewport->hadjustment->lower - viewport->hadjustment->value;
+
+ if (viewport->vadjustment->lower != (viewport->vadjustment->upper -
+ viewport->vadjustment->page_size))
+ child_allocation.y = viewport->vadjustment->lower - viewport->vadjustment->value;
+
+ if (GTK_WIDGET_REALIZED (viewport))
+ gdk_window_move (GTK_WIDGET (viewport)->window,
+ child_allocation.x,
+ child_allocation.y);
+ }
+}
diff --git a/gtk/gtkviewport.h b/gtk/gtkviewport.h
new file mode 100644
index 000000000..9af4e8720
--- /dev/null
+++ b/gtk/gtkviewport.h
@@ -0,0 +1,75 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_VIEWPORT_H__
+#define __GTK_VIEWPORT_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkadjustment.h>
+#include <gtk/gtkbin.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_VIEWPORT(obj) GTK_CHECK_CAST (obj, gtk_viewport_get_type (), GtkViewport)
+#define GTK_VIEWPORT_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_viewport_get_type (), GtkViewportClass)
+#define GTK_IS_VIEWPORT(obj) GTK_CHECK_TYPE (obj, gtk_viewport_get_type ())
+
+
+typedef struct _GtkViewport GtkViewport;
+typedef struct _GtkViewportClass GtkViewportClass;
+
+struct _GtkViewport
+{
+ GtkBin bin;
+
+ gint shadow_type;
+ GdkWindow *main_window;
+ GdkWindow *view_window;
+ GtkAdjustment *hadjustment;
+ GtkAdjustment *vadjustment;
+};
+
+struct _GtkViewportClass
+{
+ GtkBinClass parent_class;
+};
+
+
+guint gtk_viewport_get_type (void);
+GtkWidget* gtk_viewport_new (GtkAdjustment *hadjustment,
+ GtkAdjustment *vadjustment);
+GtkAdjustment* gtk_viewport_get_hadjustment (GtkViewport *viewport);
+GtkAdjustment* gtk_viewport_get_vadjustment (GtkViewport *viewport);
+void gtk_viewport_set_hadjustment (GtkViewport *viewport,
+ GtkAdjustment *adjustment);
+void gtk_viewport_set_vadjustment (GtkViewport *viewport,
+ GtkAdjustment *adjustment);
+void gtk_viewport_set_shadow_type (GtkViewport *viewport,
+ GtkShadowType type);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_VIEWPORT_H__ */
diff --git a/gtk/gtkvpaned.c b/gtk/gtkvpaned.c
new file mode 100644
index 000000000..2dae03209
--- /dev/null
+++ b/gtk/gtkvpaned.c
@@ -0,0 +1,356 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtkvpaned.h"
+#include "gtkmain.h"
+#include "gtksignal.h"
+
+static void gtk_vpaned_class_init (GtkVPanedClass *klass);
+static void gtk_vpaned_init (GtkVPaned *vpaned);
+static void gtk_vpaned_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void gtk_vpaned_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static void gtk_vpaned_draw (GtkWidget *widget,
+ GdkRectangle *area);
+static void gtk_vpaned_xor_line (GtkPaned *paned);
+static gint gtk_vpaned_button_press (GtkWidget *widget,
+ GdkEventButton *event);
+static gint gtk_vpaned_button_release (GtkWidget *widget,
+ GdkEventButton *event);
+static gint gtk_vpaned_motion (GtkWidget *widget,
+ GdkEventMotion *event);
+
+guint
+gtk_vpaned_get_type ()
+{
+ static guint vpaned_type = 0;
+
+ if (!vpaned_type)
+ {
+ GtkTypeInfo vpaned_info =
+ {
+ "GtkVPaned",
+ sizeof (GtkVPaned),
+ sizeof (GtkVPanedClass),
+ (GtkClassInitFunc) gtk_vpaned_class_init,
+ (GtkObjectInitFunc) gtk_vpaned_init,
+ (GtkArgFunc) NULL,
+ };
+
+ vpaned_type = gtk_type_unique (gtk_paned_get_type (), &vpaned_info);
+ }
+
+ return vpaned_type;
+}
+
+static void
+gtk_vpaned_class_init (GtkVPanedClass *class)
+{
+ GtkWidgetClass *widget_class;
+
+ widget_class = (GtkWidgetClass*) class;
+
+ widget_class->size_request = gtk_vpaned_size_request;
+ widget_class->size_allocate = gtk_vpaned_size_allocate;
+ widget_class->draw = gtk_vpaned_draw;
+ widget_class->button_press_event = gtk_vpaned_button_press;
+ widget_class->button_release_event = gtk_vpaned_button_release;
+ widget_class->motion_notify_event = gtk_vpaned_motion;
+}
+
+static void
+gtk_vpaned_init (GtkVPaned *vpaned)
+{
+}
+
+GtkWidget*
+gtk_vpaned_new ()
+{
+ GtkVPaned *vpaned;
+
+ vpaned = gtk_type_new (gtk_vpaned_get_type ());
+
+ return GTK_WIDGET (vpaned);
+}
+
+static void
+gtk_vpaned_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkPaned *paned;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_VPANED (widget));
+ g_return_if_fail (requisition != NULL);
+
+ paned = GTK_PANED (widget);
+ requisition->width = 0;
+ requisition->height = 0;
+
+ if (paned->child1 && GTK_WIDGET_VISIBLE (paned->child1))
+ {
+ gtk_widget_size_request (paned->child1, &paned->child1->requisition);
+
+ requisition->height = paned->child1->requisition.height;
+ requisition->width = paned->child1->requisition.width;
+ }
+
+ if (paned->child2 && GTK_WIDGET_VISIBLE (paned->child2))
+ {
+ gtk_widget_size_request (paned->child2, &paned->child2->requisition);
+
+ requisition->width = MAX (requisition->width,
+ paned->child2->requisition.width);
+ requisition->height += paned->child2->requisition.height;
+ }
+
+ requisition->height += GTK_CONTAINER (paned)->border_width * 2 + paned->gutter_size;
+ requisition->width += GTK_CONTAINER (paned)->border_width * 2;
+}
+
+static void
+gtk_vpaned_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkPaned *paned;
+ GtkAllocation child1_allocation;
+ GtkAllocation child2_allocation;
+ guint16 border_width;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_VPANED (widget));
+ g_return_if_fail (allocation != NULL);
+
+ widget->allocation = *allocation;
+
+ paned = GTK_PANED (widget);
+ border_width = GTK_CONTAINER (paned)->border_width;
+
+ if (!paned->position_set)
+ {
+ if (paned->child1 && GTK_WIDGET_VISIBLE (paned->child1))
+ paned->child1_size = paned->child1->requisition.height;
+ else
+ paned->child1_size = 0;
+ }
+
+ /* Move the handle first so we don't get extra expose events */
+
+ paned->handle_xpos = allocation->x + allocation->width - border_width - 2 * paned->handle_size;
+ paned->handle_ypos = allocation->y + paned->child1_size + border_width + paned->gutter_size / 2 - paned->handle_size / 2;
+
+ if (GTK_WIDGET_REALIZED (widget))
+ {
+ gdk_window_move (paned->handle, paned->handle_xpos, paned->handle_ypos);
+ gdk_window_raise (paned->handle);
+ }
+
+ if (GTK_WIDGET_MAPPED (widget))
+ {
+ gdk_window_clear_area (widget->window,
+ paned->groove_rectangle.x,
+ paned->groove_rectangle.y,
+ paned->groove_rectangle.width,
+ paned->groove_rectangle.height);
+ }
+
+ child1_allocation.width = child2_allocation.width = allocation->width - border_width * 2;
+ child1_allocation.height = paned->child1_size;
+ child1_allocation.x = child2_allocation.x = allocation->x + border_width;
+ child1_allocation.y = allocation->y + border_width;
+
+ paned->groove_rectangle.y = child1_allocation.y
+ + child1_allocation.height + paned->gutter_size / 2 - 1;
+ paned->groove_rectangle.x = allocation->x;
+ paned->groove_rectangle.height = 2;
+ paned->groove_rectangle.width = allocation->width;
+
+ child2_allocation.y = paned->groove_rectangle.y + paned->gutter_size / 2 + 1;
+ child2_allocation.height = allocation->y + allocation->height
+ - child2_allocation.y - border_width;
+
+ /* Now allocate the childen, making sure, when resizing not to
+ * overlap the windows */
+ if (GTK_WIDGET_MAPPED(widget) &&
+ paned->child1 && GTK_WIDGET_VISIBLE (paned->child1) &&
+ paned->child1->allocation.height < child1_allocation.height)
+ {
+ if (paned->child2 && GTK_WIDGET_VISIBLE (paned->child2))
+ gtk_widget_size_allocate (paned->child2, &child2_allocation);
+ gtk_widget_size_allocate (paned->child1, &child1_allocation);
+ }
+ else
+ {
+ if (paned->child1 && GTK_WIDGET_VISIBLE (paned->child1))
+ gtk_widget_size_allocate (paned->child1, &child1_allocation);
+ if (paned->child2 && GTK_WIDGET_VISIBLE (paned->child2))
+ gtk_widget_size_allocate (paned->child2, &child2_allocation);
+ }
+}
+
+static void
+gtk_vpaned_draw (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ GtkPaned *paned;
+ GdkRectangle child_area;
+ guint16 border_width;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_PANED (widget));
+
+ if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget))
+ {
+ paned = GTK_PANED (widget);
+ border_width = GTK_CONTAINER (paned)->border_width;
+
+ if (paned->child1 &&
+ gtk_widget_intersect (paned->child1, area, &child_area))
+ gtk_widget_draw (paned->child1, &child_area);
+ if (paned->child2 &&
+ gtk_widget_intersect (paned->child2, area, &child_area))
+ gtk_widget_draw (paned->child2, &child_area);
+
+ gdk_draw_line (widget->window,
+ widget->style->dark_gc[widget->state],
+ widget->allocation.x,
+ widget->allocation.y + border_width + paned->child1_size + paned->gutter_size / 2 - 1,
+ widget->allocation.x + widget->allocation.width - 1,
+ widget->allocation.y + border_width + paned->child1_size + paned->gutter_size / 2 - 1);
+ gdk_draw_line (widget->window,
+ widget->style->light_gc[widget->state],
+ widget->allocation.x,
+ widget->allocation.y + border_width + paned->child1_size + paned->gutter_size / 2,
+ widget->allocation.x + widget->allocation.width - 1,
+ widget->allocation.y + border_width + paned->child1_size + paned->gutter_size / 2);
+ }
+}
+
+static void
+gtk_vpaned_xor_line (GtkPaned *paned)
+{
+ GtkWidget *widget;
+ GdkGCValues values;
+ guint16 ypos;
+
+ widget = GTK_WIDGET(paned);
+
+ if (!paned->xor_gc)
+ {
+ values.foreground = widget->style->white;
+ values.function = GDK_XOR;
+ values.subwindow_mode = GDK_INCLUDE_INFERIORS;
+ paned->xor_gc = gdk_gc_new_with_values (widget->window,
+ &values,
+ GDK_GC_FOREGROUND |
+ GDK_GC_FUNCTION |
+ GDK_GC_SUBWINDOW);
+ }
+
+ ypos = widget->allocation.y + paned->child1_size
+ + GTK_CONTAINER (paned)->border_width + paned->gutter_size / 2;
+
+ gdk_draw_line (widget->window, paned->xor_gc,
+ widget->allocation.x,
+ ypos,
+ widget->allocation.x + widget->allocation.width - 1,
+ ypos);
+}
+
+static gint
+gtk_vpaned_button_press (GtkWidget *widget, GdkEventButton *event)
+{
+ GtkPaned *paned;
+
+ g_return_val_if_fail (widget != NULL,FALSE);
+ g_return_val_if_fail (GTK_IS_PANED (widget),FALSE);
+
+ paned = GTK_PANED (widget);
+
+ if (!paned->in_drag &&
+ (event->window == paned->handle) && (event->button == 1))
+ {
+ paned->in_drag = TRUE;
+ /* We need a server grab here, not gtk_grab_add(), since
+ * we don't want to pass events on to the widget's children */
+ gdk_pointer_grab (paned->handle, FALSE,
+ GDK_POINTER_MOTION_HINT_MASK
+ | GDK_BUTTON1_MOTION_MASK
+ | GDK_BUTTON_RELEASE_MASK,
+ NULL, NULL, event->time);
+ paned->child1_size += event->y - paned->handle_size / 2;
+ paned->child1_size = CLAMP (paned->child1_size, 0,
+ widget->allocation.height - paned->gutter_size
+ - 2 * GTK_CONTAINER (paned)->border_width);
+ gtk_vpaned_xor_line (paned);
+ }
+
+ return TRUE;
+}
+
+static gint
+gtk_vpaned_button_release (GtkWidget *widget, GdkEventButton *event)
+{
+ GtkPaned *paned;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_PANED (widget), FALSE);
+
+ paned = GTK_PANED (widget);
+
+ if (paned->in_drag && (event->button == 1))
+ {
+ gtk_vpaned_xor_line (paned);
+ paned->in_drag = FALSE;
+ paned->position_set = TRUE;
+ gdk_pointer_ungrab (event->time);
+ gtk_widget_queue_resize (GTK_WIDGET (paned));
+ }
+
+ return TRUE;
+}
+
+static gint
+gtk_vpaned_motion (GtkWidget *widget, GdkEventMotion *event)
+{
+ GtkPaned *paned;
+ gint y;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_PANED (widget), FALSE);
+
+ if (event->is_hint || event->window != widget->window)
+ gtk_widget_get_pointer(widget, NULL, &y);
+ else
+ y = event->y;
+
+ paned = GTK_PANED (widget);
+
+ if (paned->in_drag)
+ {
+ gtk_vpaned_xor_line (paned);
+ paned->child1_size = y - GTK_CONTAINER (paned)->border_width -
+ paned->gutter_size/2;
+ paned->child1_size = CLAMP (paned->child1_size, 0,
+ widget->allocation.height - paned->gutter_size
+ - 2 * GTK_CONTAINER (paned)->border_width);
+ gtk_vpaned_xor_line (paned);
+ }
+
+ return TRUE;
+}
diff --git a/gtk/gtkvpaned.h b/gtk/gtkvpaned.h
new file mode 100644
index 000000000..9e66c1255
--- /dev/null
+++ b/gtk/gtkvpaned.h
@@ -0,0 +1,59 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_VPANED_H__
+#define __GTK_VPANED_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkpaned.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_VPANED(obj) GTK_CHECK_CAST (obj, gtk_vpaned_get_type (), GtkVPaned)
+#define GTK_VPANED_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_vpaned_get_type (), GtkVPanedClass)
+#define GTK_IS_VPANED(obj) GTK_CHECK_TYPE (obj, gtk_vpaned_get_type ())
+
+
+typedef struct _GtkVPaned GtkVPaned;
+typedef struct _GtkVPanedClass GtkVPanedClass;
+
+struct _GtkVPaned
+{
+ GtkPaned paned;
+};
+
+struct _GtkVPanedClass
+{
+ GtkPanedClass parent_class;
+};
+
+
+guint gtk_vpaned_get_type (void);
+GtkWidget* gtk_vpaned_new ();
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_VPANED_H__ */
diff --git a/gtk/gtkvruler.c b/gtk/gtkvruler.c
new file mode 100644
index 000000000..43fe16bb7
--- /dev/null
+++ b/gtk/gtkvruler.c
@@ -0,0 +1,282 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include "gtkvruler.h"
+
+
+#define RULER_WIDTH 14
+#define MINIMUM_INCR 5
+#define MAXIMUM_SUBDIVIDE 5
+#define MAXIMUM_SCALES 10
+
+#define ROUND(x) ((int) ((x) + 0.5))
+
+
+static void gtk_vruler_class_init (GtkVRulerClass *klass);
+static void gtk_vruler_init (GtkVRuler *vruler);
+static gint gtk_vruler_motion_notify (GtkWidget *widget,
+ GdkEventMotion *event);
+static void gtk_vruler_draw_ticks (GtkRuler *ruler);
+static void gtk_vruler_draw_pos (GtkRuler *ruler);
+
+
+guint
+gtk_vruler_get_type ()
+{
+ static guint vruler_type = 0;
+
+ if (!vruler_type)
+ {
+ GtkTypeInfo vruler_info =
+ {
+ "GtkVRuler",
+ sizeof (GtkVRuler),
+ sizeof (GtkVRulerClass),
+ (GtkClassInitFunc) gtk_vruler_class_init,
+ (GtkObjectInitFunc) gtk_vruler_init,
+ (GtkArgFunc) NULL,
+ };
+
+ vruler_type = gtk_type_unique (gtk_ruler_get_type (), &vruler_info);
+ }
+
+ return vruler_type;
+}
+
+static void
+gtk_vruler_class_init (GtkVRulerClass *klass)
+{
+ GtkWidgetClass *widget_class;
+ GtkRulerClass *ruler_class;
+
+ widget_class = (GtkWidgetClass*) klass;
+ ruler_class = (GtkRulerClass*) klass;
+
+ widget_class->motion_notify_event = gtk_vruler_motion_notify;
+
+ ruler_class->draw_ticks = gtk_vruler_draw_ticks;
+ ruler_class->draw_pos = gtk_vruler_draw_pos;
+}
+
+static void
+gtk_vruler_init (GtkVRuler *vruler)
+{
+ GtkWidget *widget;
+
+ widget = GTK_WIDGET (vruler);
+ widget->requisition.width = widget->style->klass->xthickness * 2 + RULER_WIDTH;
+ widget->requisition.height = widget->style->klass->ythickness * 2 + 1;
+}
+
+GtkWidget*
+gtk_vruler_new ()
+{
+ return GTK_WIDGET (gtk_type_new (gtk_vruler_get_type ()));
+}
+
+
+static gint
+gtk_vruler_motion_notify (GtkWidget *widget,
+ GdkEventMotion *event)
+{
+ GtkRuler *ruler;
+ gint y;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_VRULER (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ ruler = GTK_RULER (widget);
+
+ if (event->is_hint)
+ gdk_window_get_pointer (widget->window, NULL, &y, NULL);
+ else
+ y = event->y;
+
+ ruler->position = ruler->lower + ((ruler->upper - ruler->lower) * y) / widget->allocation.height;
+
+ /* Make sure the ruler has been allocated already */
+ if (ruler->backing_store != NULL)
+ gtk_ruler_draw_pos (ruler);
+
+ return FALSE;
+}
+
+static void
+gtk_vruler_draw_ticks (GtkRuler *ruler)
+{
+ GtkWidget *widget;
+ GdkGC *gc;
+ gint i, j;
+ gint width, height;
+ gint xthickness;
+ gint ythickness;
+ gint length;
+ gfloat subd_incr;
+ gfloat step_incr;
+ gfloat increment;
+ gfloat start, end, cur;
+ gchar unit_str[12];
+ gchar digit_str[2] = { '\0', '\0' };
+ gint text_height;
+ gint digit_height;
+ gint pos;
+ gint scale;
+
+ g_return_if_fail (ruler != NULL);
+ g_return_if_fail (GTK_IS_VRULER (ruler));
+
+ if (GTK_WIDGET_DRAWABLE (ruler))
+ {
+ widget = GTK_WIDGET (ruler);
+
+ gc = widget->style->fg_gc[GTK_STATE_NORMAL];
+ xthickness = widget->style->klass->xthickness;
+ ythickness = widget->style->klass->ythickness;
+ digit_height = widget->style->font->ascent;
+
+ width = widget->allocation.height;
+ height = widget->allocation.width - ythickness * 2;
+ gdk_draw_line (ruler->backing_store, gc,
+ height + xthickness,
+ ythickness,
+ height + xthickness,
+ widget->allocation.height - ythickness);
+
+ if ((ruler->upper - ruler->lower) == 0)
+ return;
+
+ increment = (gfloat) width * ruler->metric->pixels_per_unit / (ruler->upper - ruler->lower);
+
+ /* determine the scale
+ * use the maximum extents of the ruler to determine the largest possible
+ * number to be displayed. calculate the height in pixels of this displayed
+ * text as for the vertical ruler case. use this height to find a scale
+ * which leaves sufficient room for drawing the ruler.
+ */
+ scale = ceil (ruler->max_size / ruler->metric->pixels_per_unit);
+ sprintf (unit_str, "%d", scale);
+ text_height = strlen (unit_str) * digit_height + 1;
+
+ for (scale = 0; scale < MAXIMUM_SCALES; scale++)
+ if (ruler->metric->ruler_scale[scale] * increment > 2 * text_height)
+ break;
+
+ if (scale == MAXIMUM_SCALES)
+ scale = MAXIMUM_SCALES - 1;
+
+ for (i = 0; i < MAXIMUM_SUBDIVIDE; i++)
+ {
+ subd_incr = (gfloat) ruler->metric->ruler_scale[scale] / (gfloat) ruler->metric->subdivide[i];
+ step_incr = subd_incr * increment;
+ if (step_incr <= MINIMUM_INCR)
+ break;
+
+ start = floor ((ruler->lower / ruler->metric->pixels_per_unit) / subd_incr) * subd_incr;
+ end = ceil ((ruler->upper / ruler->metric->pixels_per_unit) / subd_incr) * subd_incr;
+
+ length = height / (i + 1) - 1;
+
+ cur = start;
+ while (cur <= end)
+ {
+ pos = ROUND ((cur - (ruler->lower / ruler->metric->pixels_per_unit)) * increment);
+
+ gdk_draw_line (ruler->backing_store, gc,
+ height + xthickness - length,
+ pos,
+ height + xthickness,
+ pos);
+
+ if (i == 0)
+ {
+ sprintf (unit_str, "%d", (int) cur);
+ for (j = 0; j < (int) strlen (unit_str); j++)
+ {
+ digit_str[0] = unit_str[j];
+ gdk_draw_string (ruler->backing_store, widget->style->font, gc,
+ xthickness + 1,
+ pos + digit_height * (j + 1) + 1,
+ digit_str);
+ }
+ }
+
+ cur += subd_incr;
+ }
+ }
+ }
+}
+
+static void
+gtk_vruler_draw_pos (GtkRuler *ruler)
+{
+ GtkWidget *widget;
+ GdkGC *gc;
+ int i;
+ gint x, y;
+ gint width, height;
+ gint bs_width, bs_height;
+ gint xthickness;
+ gint ythickness;
+ gfloat increment;
+
+ g_return_if_fail (ruler != NULL);
+ g_return_if_fail (GTK_IS_VRULER (ruler));
+
+ if (GTK_WIDGET_DRAWABLE (ruler))
+ {
+ widget = GTK_WIDGET (ruler);
+
+ gc = widget->style->fg_gc[GTK_STATE_NORMAL];
+ xthickness = widget->style->klass->xthickness;
+ ythickness = widget->style->klass->ythickness;
+ width = widget->allocation.width - xthickness * 2;
+ height = widget->allocation.height;
+
+ bs_height = width / 2;
+ bs_height |= 1; /* make sure it's odd */
+ bs_width = bs_height / 2 + 1;
+
+ if ((bs_width > 0) && (bs_height > 0))
+ {
+ /* If a backing store exists, restore the ruler */
+ if (ruler->backing_store && ruler->non_gr_exp_gc)
+ gdk_draw_pixmap (ruler->widget.window,
+ ruler->non_gr_exp_gc,
+ ruler->backing_store,
+ ruler->xsrc, ruler->ysrc,
+ ruler->xsrc, ruler->ysrc,
+ bs_width, bs_height);
+
+ increment = (gfloat) height / (ruler->upper - ruler->lower);
+
+ x = (width + bs_width) / 2 + xthickness;
+ y = ROUND ((ruler->position - ruler->lower) * increment) + (ythickness - bs_height) / 2 - 1;
+
+ for (i = 0; i < bs_width; i++)
+ gdk_draw_line (widget->window, gc,
+ x + i, y + i,
+ x + i, y + bs_height - 1 - i);
+
+ ruler->xsrc = x;
+ ruler->ysrc = y;
+ }
+ }
+}
diff --git a/gtk/gtkvruler.h b/gtk/gtkvruler.h
new file mode 100644
index 000000000..22bef7164
--- /dev/null
+++ b/gtk/gtkvruler.h
@@ -0,0 +1,59 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_VRULER_H__
+#define __GTK_VRULER_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkruler.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_VRULER(obj) GTK_CHECK_CAST (obj, gtk_vruler_get_type (), GtkVRuler)
+#define GTK_VRULER_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_vruler_get_type (), GtkVRulerClass)
+#define GTK_IS_VRULER(obj) GTK_CHECK_TYPE (obj, gtk_vruler_get_type ())
+
+
+typedef struct _GtkVRuler GtkVRuler;
+typedef struct _GtkVRulerClass GtkVRulerClass;
+
+struct _GtkVRuler
+{
+ GtkRuler ruler;
+};
+
+struct _GtkVRulerClass
+{
+ GtkRulerClass parent_class;
+};
+
+
+guint gtk_vruler_get_type (void);
+GtkWidget* gtk_vruler_new (void);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_VRULER_H__ */
diff --git a/gtk/gtkvscale.c b/gtk/gtkvscale.c
new file mode 100644
index 000000000..9c2e3058f
--- /dev/null
+++ b/gtk/gtkvscale.c
@@ -0,0 +1,441 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdio.h>
+#include "gtkvscale.h"
+#include "gtksignal.h"
+#include "gdk/gdkkeysyms.h"
+
+
+#define SCALE_CLASS(w) GTK_SCALE_CLASS (GTK_OBJECT (w)->klass)
+#define RANGE_CLASS(w) GTK_RANGE_CLASS (GTK_OBJECT (w)->klass)
+
+
+static void gtk_vscale_class_init (GtkVScaleClass *klass);
+static void gtk_vscale_init (GtkVScale *vscale);
+static void gtk_vscale_realize (GtkWidget *widget);
+static void gtk_vscale_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void gtk_vscale_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static void gtk_vscale_pos_trough (GtkVScale *vscale,
+ gint *x,
+ gint *y,
+ gint *w,
+ gint *h);
+static void gtk_vscale_draw_slider (GtkRange *range);
+static void gtk_vscale_draw_value (GtkScale *scale);
+static gint gtk_vscale_trough_keys (GtkRange *range,
+ GdkEventKey *key,
+ GtkScrollType *scroll,
+ GtkTroughType *pos);
+
+
+guint
+gtk_vscale_get_type ()
+{
+ static guint vscale_type = 0;
+
+ if (!vscale_type)
+ {
+ GtkTypeInfo vscale_info =
+ {
+ "GtkVScale",
+ sizeof (GtkVScale),
+ sizeof (GtkVScaleClass),
+ (GtkClassInitFunc) gtk_vscale_class_init,
+ (GtkObjectInitFunc) gtk_vscale_init,
+ (GtkArgFunc) NULL,
+ };
+
+ vscale_type = gtk_type_unique (gtk_scale_get_type (), &vscale_info);
+ }
+
+ return vscale_type;
+}
+
+static void
+gtk_vscale_class_init (GtkVScaleClass *class)
+{
+ GtkWidgetClass *widget_class;
+ GtkRangeClass *range_class;
+ GtkScaleClass *scale_class;
+
+ widget_class = (GtkWidgetClass*) class;
+ range_class = (GtkRangeClass*) class;
+ scale_class = (GtkScaleClass*) class;
+
+ widget_class->realize = gtk_vscale_realize;
+ widget_class->size_request = gtk_vscale_size_request;
+ widget_class->size_allocate = gtk_vscale_size_allocate;
+
+ range_class->slider_update = gtk_range_default_vslider_update;
+ range_class->trough_click = gtk_range_default_vtrough_click;
+ range_class->motion = gtk_range_default_vmotion;
+ range_class->draw_slider = gtk_vscale_draw_slider;
+ range_class->trough_keys = gtk_vscale_trough_keys;
+
+ scale_class->draw_value = gtk_vscale_draw_value;
+}
+
+static void
+gtk_vscale_init (GtkVScale *vscale)
+{
+}
+
+GtkWidget*
+gtk_vscale_new (GtkAdjustment *adjustment)
+{
+ GtkVScale *vscale;
+
+ vscale = gtk_type_new (gtk_vscale_get_type ());
+
+ if (!adjustment)
+ adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+
+ gtk_range_set_adjustment (GTK_RANGE (vscale), adjustment);
+
+ return GTK_WIDGET (vscale);
+}
+
+
+static void
+gtk_vscale_realize (GtkWidget *widget)
+{
+ GtkRange *range;
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+ gint x, y, w, h;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_VSCALE (widget));
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+ range = GTK_RANGE (widget);
+
+ attributes.x = widget->allocation.x;
+ attributes.y = widget->allocation.y;
+ attributes.width = widget->allocation.width;
+ attributes.height = widget->allocation.height;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+ widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
+
+ gtk_vscale_pos_trough (GTK_VSCALE (widget), &x, &y, &w, &h);
+ attributes.x = x;
+ attributes.y = y;
+ attributes.width = w;
+ attributes.height = h;
+ attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_ENTER_NOTIFY_MASK |
+ GDK_LEAVE_NOTIFY_MASK);
+
+ range->trough = gdk_window_new (widget->window, &attributes, attributes_mask);
+
+ attributes.width = RANGE_CLASS (range)->slider_width;
+ attributes.height = SCALE_CLASS (range)->slider_length;
+ attributes.event_mask |= (GDK_BUTTON_MOTION_MASK |
+ GDK_POINTER_MOTION_HINT_MASK);
+
+ range->slider = gdk_window_new (range->trough, &attributes, attributes_mask);
+
+ widget->style = gtk_style_attach (widget->style, widget->window);
+
+ gdk_window_set_user_data (widget->window, widget);
+ gdk_window_set_user_data (range->trough, widget);
+ gdk_window_set_user_data (range->slider, widget);
+
+ gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
+ gtk_style_set_background (widget->style, range->trough, GTK_STATE_ACTIVE);
+ gtk_style_set_background (widget->style, range->slider, GTK_STATE_NORMAL);
+
+ gtk_range_slider_update (GTK_RANGE (widget));
+
+ gdk_window_show (range->slider);
+ gdk_window_show (range->trough);
+}
+
+static void
+gtk_vscale_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkScale *scale;
+ gint value_width;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_VSCALE (widget));
+ g_return_if_fail (requisition != NULL);
+
+ scale = GTK_SCALE (widget);
+
+ requisition->width = (RANGE_CLASS (scale)->slider_width +
+ widget->style->klass->ythickness * 2);
+ requisition->height = (SCALE_CLASS (scale)->slider_length +
+ widget->style->klass->xthickness) * 2;
+
+ if (scale->draw_value)
+ {
+ value_width = gtk_scale_value_width (scale);
+
+ if ((scale->value_pos == GTK_POS_LEFT) ||
+ (scale->value_pos == GTK_POS_RIGHT))
+ {
+ requisition->width += value_width + SCALE_CLASS (scale)->value_spacing;
+ if (requisition->height < (widget->style->font->ascent + widget->style->font->descent))
+ requisition->height = widget->style->font->ascent + widget->style->font->descent;
+ }
+ else if ((scale->value_pos == GTK_POS_TOP) ||
+ (scale->value_pos == GTK_POS_BOTTOM))
+ {
+ if (requisition->width < value_width)
+ requisition->width = value_width;
+ requisition->height += widget->style->font->ascent + widget->style->font->descent;
+ }
+ }
+}
+
+static void
+gtk_vscale_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkRange *range;
+ GtkScale *scale;
+ gint width, height;
+ gint x, y;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_VSCALE (widget));
+ g_return_if_fail (allocation != NULL);
+
+ widget->allocation = *allocation;
+ if (GTK_WIDGET_REALIZED (widget))
+ {
+ range = GTK_RANGE (widget);
+ scale = GTK_SCALE (widget);
+
+ gdk_window_move_resize (widget->window,
+ allocation->x, allocation->y,
+ allocation->width, allocation->height);
+
+ gtk_vscale_pos_trough (GTK_VSCALE (widget), &x, &y, &width, &height);
+
+ gdk_window_move_resize (range->trough, x, y, width, height);
+ gtk_range_slider_update (GTK_RANGE (widget));
+ }
+}
+
+static void
+gtk_vscale_pos_trough (GtkVScale *vscale,
+ gint *x,
+ gint *y,
+ gint *w,
+ gint *h)
+{
+ GtkWidget *widget;
+ GtkScale *scale;
+
+ g_return_if_fail (vscale != NULL);
+ g_return_if_fail (GTK_IS_VSCALE (vscale));
+ g_return_if_fail ((x != NULL) && (y != NULL) && (w != NULL) && (h != NULL));
+
+ widget = GTK_WIDGET (vscale);
+ scale = GTK_SCALE (vscale);
+
+ *w = (RANGE_CLASS (scale)->slider_width +
+ widget->style->klass->xthickness * 2);
+ *h = widget->allocation.height;
+
+ if (scale->draw_value)
+ {
+ *x = 0;
+ *y = 0;
+
+ switch (scale->value_pos)
+ {
+ case GTK_POS_LEFT:
+ *x = (gtk_scale_value_width (scale) +
+ (widget->allocation.width - widget->requisition.width) / 2);
+ break;
+ case GTK_POS_RIGHT:
+ *x = (widget->allocation.width - widget->requisition.width) / 2;
+ break;
+ case GTK_POS_TOP:
+ *x = (widget->allocation.width - *w) / 2;
+ *y = widget->style->font->ascent + widget->style->font->descent;
+ *h -= *y;
+ break;
+ case GTK_POS_BOTTOM:
+ *x = (widget->allocation.width - *w) / 2;
+ *h -= widget->style->font->ascent + widget->style->font->descent;
+ break;
+ }
+ }
+ else
+ {
+ *x = (widget->allocation.width - *w) / 2;
+ *y = 0;
+ }
+ *y += 1;
+ *h -= 2;
+}
+
+static void
+gtk_vscale_draw_slider (GtkRange *range)
+{
+ GtkStateType state_type;
+ gint width, height;
+
+ g_return_if_fail (range != NULL);
+ g_return_if_fail (GTK_IS_VSCALE (range));
+
+ if (range->slider)
+ {
+ if ((range->in_child == RANGE_CLASS (range)->slider) ||
+ (range->click_child == RANGE_CLASS (range)->slider))
+ state_type = GTK_STATE_PRELIGHT;
+ else
+ state_type = GTK_STATE_NORMAL;
+
+ gtk_style_set_background (GTK_WIDGET (range)->style, range->slider, state_type);
+ gdk_window_clear (range->slider);
+
+ gdk_window_get_size (range->slider, &width, &height);
+ gtk_draw_hline (GTK_WIDGET (range)->style, range->slider,
+ state_type, 1, width - 2, height / 2);
+
+ gtk_draw_shadow (GTK_WIDGET (range)->style, range->slider,
+ state_type, GTK_SHADOW_OUT,
+ 0, 0, -1, -1);
+ }
+}
+
+static void
+gtk_vscale_draw_value (GtkScale *scale)
+{
+ GtkStateType state_type;
+ gchar buffer[16];
+ gint text_width;
+ gint width, height;
+ gint x, y;
+
+ g_return_if_fail (scale != NULL);
+ g_return_if_fail (GTK_IS_VSCALE (scale));
+
+ if (scale->draw_value)
+ {
+ gdk_window_get_size (GTK_WIDGET (scale)->window, &width, &height);
+ gdk_window_clear_area (GTK_WIDGET (scale)->window, 1, 1, width - 3, height - 3);
+
+ sprintf (buffer, "%0.*f", GTK_RANGE (scale)->digits, GTK_RANGE (scale)->adjustment->value);
+ text_width = gdk_string_measure (GTK_WIDGET (scale)->style->font, buffer);
+
+ switch (scale->value_pos)
+ {
+ case GTK_POS_LEFT:
+ gdk_window_get_position (GTK_RANGE (scale)->trough, &x, NULL);
+ gdk_window_get_position (GTK_RANGE (scale)->slider, NULL, &y);
+ gdk_window_get_size (GTK_RANGE (scale)->trough, &width, NULL);
+ gdk_window_get_size (GTK_RANGE (scale)->slider, NULL, &height);
+
+ x -= SCALE_CLASS (scale)->value_spacing + text_width;
+ y += ((height -
+ (GTK_WIDGET (scale)->style->font->ascent +
+ GTK_WIDGET (scale)->style->font->descent)) / 2 +
+ GTK_WIDGET (scale)->style->font->ascent);
+ break;
+ case GTK_POS_RIGHT:
+ gdk_window_get_position (GTK_RANGE (scale)->trough, &x, NULL);
+ gdk_window_get_position (GTK_RANGE (scale)->slider, NULL, &y);
+ gdk_window_get_size (GTK_RANGE (scale)->trough, &width, NULL);
+ gdk_window_get_size (GTK_RANGE (scale)->slider, NULL, &height);
+
+ x += width + SCALE_CLASS (scale)->value_spacing;
+ y += ((height -
+ (GTK_WIDGET (scale)->style->font->ascent +
+ GTK_WIDGET (scale)->style->font->descent)) / 2 +
+ GTK_WIDGET (scale)->style->font->ascent);
+ break;
+ case GTK_POS_TOP:
+ gdk_window_get_position (GTK_RANGE (scale)->trough, &x, &y);
+ gdk_window_get_size (GTK_RANGE (scale)->slider, &width, NULL);
+ gdk_window_get_size (GTK_RANGE (scale)->trough, NULL, &height);
+
+ x += (width - text_width) / 2;
+ y -= GTK_WIDGET (scale)->style->font->descent;
+ break;
+ case GTK_POS_BOTTOM:
+ gdk_window_get_position (GTK_RANGE (scale)->trough, &x, &y);
+ gdk_window_get_size (GTK_RANGE (scale)->slider, &width, NULL);
+ gdk_window_get_size (GTK_RANGE (scale)->trough, NULL, &height);
+
+ x += (width - text_width) / 2;
+ y += height + GTK_WIDGET (scale)->style->font->ascent;
+ break;
+ }
+
+ state_type = GTK_STATE_NORMAL;
+ if (!GTK_WIDGET_IS_SENSITIVE (scale))
+ state_type = GTK_STATE_INSENSITIVE;
+
+ gtk_draw_string (GTK_WIDGET (scale)->style,
+ GTK_WIDGET (scale)->window,
+ state_type, x, y, buffer);
+ }
+}
+
+static gint
+gtk_vscale_trough_keys(GtkRange *range,
+ GdkEventKey *key,
+ GtkScrollType *scroll,
+ GtkTroughType *pos)
+{
+ gint return_val = FALSE;
+ switch (key->keyval)
+ {
+ case GDK_Up:
+ return_val = TRUE;
+ *scroll = GTK_SCROLL_STEP_BACKWARD;
+ break;
+ case GDK_Down:
+ return_val = TRUE;
+ *scroll = GTK_SCROLL_STEP_FORWARD;
+ break;
+ case GDK_Page_Up:
+ return_val = TRUE;
+ *scroll = GTK_SCROLL_PAGE_BACKWARD;
+ break;
+ case GDK_Page_Down:
+ return_val = TRUE;
+ *scroll = GTK_SCROLL_PAGE_FORWARD;
+ break;
+ case GDK_Home:
+ return_val = TRUE;
+ *pos = GTK_TROUGH_START;
+ break;
+ case GDK_End:
+ return_val = TRUE;
+ *pos = GTK_TROUGH_END;
+ break;
+ }
+ return return_val;
+}
diff --git a/gtk/gtkvscale.h b/gtk/gtkvscale.h
new file mode 100644
index 000000000..75862d389
--- /dev/null
+++ b/gtk/gtkvscale.h
@@ -0,0 +1,59 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_VSCALE_H__
+#define __GTK_VSCALE_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkscale.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_VSCALE(obj) GTK_CHECK_CAST (obj, gtk_vscale_get_type (), GtkVScale)
+#define GTK_VSCALE_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_vscale_get_type (), GtkVScaleClass)
+#define GTK_IS_VSCALE(obj) GTK_CHECK_TYPE (obj, gtk_vscale_get_type ())
+
+
+typedef struct _GtkVScale GtkVScale;
+typedef struct _GtkVScaleClass GtkVScaleClass;
+
+struct _GtkVScale
+{
+ GtkScale scale;
+};
+
+struct _GtkVScaleClass
+{
+ GtkScaleClass parent_class;
+};
+
+
+guint gtk_vscale_get_type (void);
+GtkWidget* gtk_vscale_new (GtkAdjustment *adjustment);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_VSCALE_H__ */
diff --git a/gtk/gtkvscrollbar.c b/gtk/gtkvscrollbar.c
new file mode 100644
index 000000000..87421c7bf
--- /dev/null
+++ b/gtk/gtkvscrollbar.c
@@ -0,0 +1,387 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtkvscrollbar.h"
+#include "gtksignal.h"
+#include "gdk/gdkkeysyms.h"
+
+
+#define EPSILON 0.01
+
+#define RANGE_CLASS(w) GTK_RANGE_CLASS (GTK_OBJECT (w)->klass)
+
+
+static void gtk_vscrollbar_class_init (GtkVScrollbarClass *klass);
+static void gtk_vscrollbar_init (GtkVScrollbar *vscrollbar);
+static void gtk_vscrollbar_realize (GtkWidget *widget);
+static void gtk_vscrollbar_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static void gtk_vscrollbar_draw_step_forw (GtkRange *range);
+static void gtk_vscrollbar_draw_step_back (GtkRange *range);
+static void gtk_vscrollbar_slider_update (GtkRange *range);
+static void gtk_vscrollbar_calc_slider_size (GtkVScrollbar *vscrollbar);
+static gint gtk_vscrollbar_trough_keys (GtkRange *range,
+ GdkEventKey *key,
+ GtkScrollType *scroll,
+ GtkTroughType *pos);
+
+guint
+gtk_vscrollbar_get_type ()
+{
+ static guint vscrollbar_type = 0;
+
+ if (!vscrollbar_type)
+ {
+ GtkTypeInfo vscrollbar_info =
+ {
+ "GtkVScrollbar",
+ sizeof (GtkVScrollbar),
+ sizeof (GtkVScrollbarClass),
+ (GtkClassInitFunc) gtk_vscrollbar_class_init,
+ (GtkObjectInitFunc) gtk_vscrollbar_init,
+ (GtkArgFunc) NULL,
+ };
+
+ vscrollbar_type = gtk_type_unique (gtk_scrollbar_get_type (), &vscrollbar_info);
+ }
+
+ return vscrollbar_type;
+}
+
+static void
+gtk_vscrollbar_class_init (GtkVScrollbarClass *klass)
+{
+ GtkWidgetClass *widget_class;
+ GtkRangeClass *range_class;
+
+ widget_class = (GtkWidgetClass*) klass;
+ range_class = (GtkRangeClass*) klass;
+
+ widget_class->realize = gtk_vscrollbar_realize;
+ widget_class->size_allocate = gtk_vscrollbar_size_allocate;
+
+ range_class->draw_step_forw = gtk_vscrollbar_draw_step_forw;
+ range_class->draw_step_back = gtk_vscrollbar_draw_step_back;
+ range_class->slider_update = gtk_vscrollbar_slider_update;
+ range_class->trough_click = gtk_range_default_vtrough_click;
+ range_class->trough_keys = gtk_vscrollbar_trough_keys;
+ range_class->motion = gtk_range_default_vmotion;
+}
+
+static void
+gtk_vscrollbar_init (GtkVScrollbar *vscrollbar)
+{
+ GtkWidget *widget;
+ GtkRequisition *requisition;
+
+ widget = GTK_WIDGET (vscrollbar);
+ requisition = &widget->requisition;
+
+ requisition->width = (RANGE_CLASS (widget)->slider_width +
+ widget->style->klass->xthickness * 2);
+ requisition->height = (RANGE_CLASS (widget)->min_slider_size +
+ RANGE_CLASS (widget)->stepper_size +
+ RANGE_CLASS (widget)->stepper_slider_spacing +
+ widget->style->klass->ythickness) * 2;
+}
+
+GtkWidget*
+gtk_vscrollbar_new (GtkAdjustment *adjustment)
+{
+ GtkVScrollbar *vscrollbar;
+
+ vscrollbar = gtk_type_new (gtk_vscrollbar_get_type ());
+
+ if (!adjustment)
+ adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+
+ gtk_range_set_adjustment (GTK_RANGE (vscrollbar), adjustment);
+
+ return GTK_WIDGET (vscrollbar);
+}
+
+
+static void
+gtk_vscrollbar_realize (GtkWidget *widget)
+{
+ GtkRange *range;
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_VSCROLLBAR (widget));
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+ range = GTK_RANGE (widget);
+
+ attributes.x = widget->allocation.x + (widget->allocation.width - widget->requisition.width) / 2;
+ attributes.y = widget->allocation.y;
+ attributes.width = widget->requisition.width;
+ attributes.height = widget->allocation.height;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
+ attributes.event_mask = gtk_widget_get_events (widget);
+ attributes.event_mask |= (GDK_EXPOSURE_MASK |
+ GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_ENTER_NOTIFY_MASK |
+ GDK_LEAVE_NOTIFY_MASK);
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+ widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
+ range->trough = widget->window;
+
+ attributes.x = widget->style->klass->xthickness;
+ attributes.y = widget->style->klass->ythickness;
+ attributes.width = RANGE_CLASS (widget)->stepper_size;
+ attributes.height = RANGE_CLASS (widget)->stepper_size;
+
+ range->step_back = gdk_window_new (range->trough, &attributes, attributes_mask);
+
+ attributes.y = (widget->allocation.height -
+ widget->style->klass->ythickness -
+ RANGE_CLASS (widget)->stepper_size);
+
+ range->step_forw = gdk_window_new (range->trough, &attributes, attributes_mask);
+
+ attributes.x = widget->style->klass->ythickness;
+ attributes.y = 0;
+ attributes.width = RANGE_CLASS (widget)->slider_width;
+ attributes.height = RANGE_CLASS (widget)->min_slider_size;
+ attributes.event_mask |= (GDK_BUTTON_MOTION_MASK |
+ GDK_POINTER_MOTION_HINT_MASK);
+
+ range->slider = gdk_window_new (range->trough, &attributes, attributes_mask);
+
+ gtk_vscrollbar_calc_slider_size (GTK_VSCROLLBAR (widget));
+ gtk_range_slider_update (GTK_RANGE (widget));
+
+ widget->style = gtk_style_attach (widget->style, widget->window);
+
+ gdk_window_set_user_data (range->trough, widget);
+ gdk_window_set_user_data (range->slider, widget);
+ gdk_window_set_user_data (range->step_forw, widget);
+ gdk_window_set_user_data (range->step_back, widget);
+
+ gtk_style_set_background (widget->style, range->trough, GTK_STATE_ACTIVE);
+ gtk_style_set_background (widget->style, range->slider, GTK_STATE_NORMAL);
+ gtk_style_set_background (widget->style, range->step_forw, GTK_STATE_ACTIVE);
+ gtk_style_set_background (widget->style, range->step_back, GTK_STATE_ACTIVE);
+
+ gdk_window_show (range->slider);
+ gdk_window_show (range->step_forw);
+ gdk_window_show (range->step_back);
+}
+
+static void
+gtk_vscrollbar_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkRange *range;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_VSCROLLBAR (widget));
+ g_return_if_fail (allocation != NULL);
+
+ widget->allocation = *allocation;
+ if (GTK_WIDGET_REALIZED (widget))
+ {
+ range = GTK_RANGE (widget);
+
+ gdk_window_move_resize (range->trough,
+ allocation->x + (allocation->width - widget->requisition.width) / 2,
+ allocation->y,
+ widget->requisition.width, allocation->height);
+ gdk_window_move_resize (range->step_back,
+ widget->style->klass->xthickness,
+ widget->style->klass->ythickness,
+ widget->requisition.width - widget->style->klass->xthickness * 2,
+ RANGE_CLASS (widget)->stepper_size);
+ gdk_window_move_resize (range->step_forw,
+ widget->style->klass->xthickness,
+ allocation->height - widget->style->klass->ythickness -
+ RANGE_CLASS (widget)->stepper_size,
+ widget->requisition.width - widget->style->klass->xthickness * 2,
+ RANGE_CLASS (widget)->stepper_size);
+ gdk_window_resize (range->slider,
+ widget->requisition.width - widget->style->klass->xthickness * 2,
+ RANGE_CLASS (range)->min_slider_size);
+
+ gtk_range_slider_update (GTK_RANGE (widget));
+ }
+}
+
+static void
+gtk_vscrollbar_draw_step_forw (GtkRange *range)
+{
+ GtkStateType state_type;
+ GtkShadowType shadow_type;
+
+ g_return_if_fail (range != NULL);
+ g_return_if_fail (GTK_IS_VSCROLLBAR (range));
+
+ if (GTK_WIDGET_DRAWABLE (range))
+ {
+ if (range->in_child == RANGE_CLASS (range)->step_forw)
+ {
+ if (range->click_child == RANGE_CLASS (range)->step_forw)
+ state_type = GTK_STATE_ACTIVE;
+ else
+ state_type = GTK_STATE_PRELIGHT;
+ }
+ else
+ state_type = GTK_STATE_NORMAL;
+
+ if (range->click_child == RANGE_CLASS (range)->step_forw)
+ shadow_type = GTK_SHADOW_IN;
+ else
+ shadow_type = GTK_SHADOW_OUT;
+
+ gtk_draw_arrow (GTK_WIDGET (range)->style, range->step_forw,
+ state_type, shadow_type, GTK_ARROW_DOWN,
+ TRUE, 0, 0, -1, -1);
+ }
+}
+
+static void
+gtk_vscrollbar_draw_step_back (GtkRange *range)
+{
+ GtkStateType state_type;
+ GtkShadowType shadow_type;
+
+ g_return_if_fail (range != NULL);
+ g_return_if_fail (GTK_IS_VSCROLLBAR (range));
+
+ if (GTK_WIDGET_DRAWABLE (range))
+ {
+ if (range->in_child == RANGE_CLASS (range)->step_back)
+ {
+ if (range->click_child == RANGE_CLASS (range)->step_back)
+ state_type = GTK_STATE_ACTIVE;
+ else
+ state_type = GTK_STATE_PRELIGHT;
+ }
+ else
+ state_type = GTK_STATE_NORMAL;
+
+ if (range->click_child == RANGE_CLASS (range)->step_back)
+ shadow_type = GTK_SHADOW_IN;
+ else
+ shadow_type = GTK_SHADOW_OUT;
+
+ gtk_draw_arrow (GTK_WIDGET (range)->style, range->step_back,
+ state_type, shadow_type, GTK_ARROW_UP,
+ TRUE, 0, 0, -1, -1);
+ }
+}
+
+static void
+gtk_vscrollbar_slider_update (GtkRange *range)
+{
+ g_return_if_fail (range != NULL);
+ g_return_if_fail (GTK_IS_VSCROLLBAR (range));
+
+ gtk_vscrollbar_calc_slider_size (GTK_VSCROLLBAR (range));
+ gtk_range_default_vslider_update (range);
+}
+
+static void
+gtk_vscrollbar_calc_slider_size (GtkVScrollbar *vscrollbar)
+{
+ GtkRange *range;
+ gint step_back_y;
+ gint step_back_height;
+ gint step_forw_y;
+ gint slider_width;
+ gint slider_height;
+ gint top, bottom;
+ gint height;
+
+ g_return_if_fail (vscrollbar != NULL);
+ g_return_if_fail (GTK_IS_VSCROLLBAR (vscrollbar));
+
+ if (GTK_WIDGET_REALIZED (vscrollbar))
+ {
+ range = GTK_RANGE (vscrollbar);
+
+ gdk_window_get_size (range->step_back, NULL, &step_back_height);
+ gdk_window_get_position (range->step_back, NULL, &step_back_y);
+ gdk_window_get_position (range->step_forw, NULL, &step_forw_y);
+
+ top = (step_back_y +
+ step_back_height +
+ RANGE_CLASS (vscrollbar)->stepper_slider_spacing);
+ bottom = step_forw_y - RANGE_CLASS (vscrollbar)->stepper_slider_spacing;
+ height = bottom - top;
+
+ if ((range->adjustment->page_size > 0) &&
+ (range->adjustment->lower != range->adjustment->upper))
+ {
+ if (range->adjustment->page_size >
+ (range->adjustment->upper - range->adjustment->lower))
+ range->adjustment->page_size = range->adjustment->upper - range->adjustment->lower;
+
+ height = (height * range->adjustment->page_size /
+ (range->adjustment->upper - range->adjustment->lower));
+
+ if (height < RANGE_CLASS (vscrollbar)->min_slider_size)
+ height = RANGE_CLASS (vscrollbar)->min_slider_size;
+ }
+
+ gdk_window_get_size (range->slider, &slider_width, &slider_height);
+
+ if (slider_height != height)
+ gdk_window_resize (range->slider, slider_width, height);
+ }
+}
+
+static gint
+gtk_vscrollbar_trough_keys(GtkRange *range,
+ GdkEventKey *key,
+ GtkScrollType *scroll,
+ GtkTroughType *pos)
+{
+ gint return_val = FALSE;
+ switch (key->keyval)
+ {
+ case GDK_Up:
+ return_val = TRUE;
+ *scroll = GTK_SCROLL_STEP_BACKWARD;
+ break;
+ case GDK_Down:
+ return_val = TRUE;
+ *scroll = GTK_SCROLL_STEP_FORWARD;
+ break;
+ case GDK_Page_Up:
+ return_val = TRUE;
+ if (key->state & GDK_CONTROL_MASK)
+ *pos = GTK_TROUGH_START;
+ else
+ *scroll = GTK_SCROLL_PAGE_BACKWARD;
+ break;
+ case GDK_Page_Down:
+ return_val = TRUE;
+ if (key->state & GDK_CONTROL_MASK)
+ *pos = GTK_TROUGH_END;
+ else
+ *scroll = GTK_SCROLL_PAGE_FORWARD;
+ break;
+ }
+ return return_val;
+}
diff --git a/gtk/gtkvscrollbar.h b/gtk/gtkvscrollbar.h
new file mode 100644
index 000000000..3160fc075
--- /dev/null
+++ b/gtk/gtkvscrollbar.h
@@ -0,0 +1,59 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_VSCROLLBAR_H__
+#define __GTK_VSCROLLBAR_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkscrollbar.h>
+
+
+#define GTK_VSCROLLBAR(obj) GTK_CHECK_CAST (obj, gtk_vscrollbar_get_type (), GtkVScrollbar)
+#define GTK_VSCROLLBAR_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_vscrollbar_get_type (), GtkVScrollbarClass)
+#define GTK_IS_VSCROLLBAR(obj) GTK_CHECK_TYPE (obj, gtk_vscrollbar_get_type ())
+
+
+typedef struct _GtkVScrollbar GtkVScrollbar;
+typedef struct _GtkVScrollbarClass GtkVScrollbarClass;
+
+struct _GtkVScrollbar
+{
+ GtkScrollbar scrollbar;
+};
+
+struct _GtkVScrollbarClass
+{
+ GtkScrollbarClass parent_class;
+};
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+guint gtk_vscrollbar_get_type (void);
+GtkWidget* gtk_vscrollbar_new (GtkAdjustment *adjustment);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_VSCROLLBAR_H__ */
diff --git a/gtk/gtkvseparator.c b/gtk/gtkvseparator.c
new file mode 100644
index 000000000..fbbba19ff
--- /dev/null
+++ b/gtk/gtkvseparator.c
@@ -0,0 +1,90 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gtkvseparator.h"
+
+
+static void gtk_vseparator_class_init (GtkVSeparatorClass *klass);
+static void gtk_vseparator_init (GtkVSeparator *vseparator);
+static gint gtk_vseparator_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+
+
+guint
+gtk_vseparator_get_type ()
+{
+ static guint vseparator_type = 0;
+
+ if (!vseparator_type)
+ {
+ GtkTypeInfo vseparator_info =
+ {
+ "GtkVSeparator",
+ sizeof (GtkVSeparator),
+ sizeof (GtkVSeparatorClass),
+ (GtkClassInitFunc) gtk_vseparator_class_init,
+ (GtkObjectInitFunc) gtk_vseparator_init,
+ (GtkArgFunc) NULL,
+ };
+
+ vseparator_type = gtk_type_unique (gtk_separator_get_type (), &vseparator_info);
+ }
+
+ return vseparator_type;
+}
+
+static void
+gtk_vseparator_class_init (GtkVSeparatorClass *klass)
+{
+ GtkWidgetClass *widget_class;
+
+ widget_class = (GtkWidgetClass*) klass;
+
+ widget_class->expose_event = gtk_vseparator_expose;
+}
+
+static void
+gtk_vseparator_init (GtkVSeparator *vseparator)
+{
+ GTK_WIDGET (vseparator)->requisition.width = GTK_WIDGET (vseparator)->style->klass->xthickness;
+ GTK_WIDGET (vseparator)->requisition.height = 1;
+}
+
+GtkWidget*
+gtk_vseparator_new ()
+{
+ return GTK_WIDGET (gtk_type_new (gtk_vseparator_get_type ()));
+}
+
+
+static gint
+gtk_vseparator_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_VSEPARATOR (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ gtk_draw_vline (widget->style, widget->window, GTK_STATE_NORMAL,
+ widget->allocation.y,
+ widget->allocation.y + widget->allocation.height,
+ widget->allocation.x + (widget->allocation.width -
+ widget->style->klass->xthickness) / 2);
+
+ return FALSE;
+}
diff --git a/gtk/gtkvseparator.h b/gtk/gtkvseparator.h
new file mode 100644
index 000000000..74d07dd68
--- /dev/null
+++ b/gtk/gtkvseparator.h
@@ -0,0 +1,59 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_VSEPARATOR_H__
+#define __GTK_VSEPARATOR_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkseparator.h>
+
+
+#define GTK_VSEPARATOR(obj) GTK_CHECK_CAST (obj, gtk_vseparator_get_type (), GtkVSeparator)
+#define GTK_VSEPARATOR_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_vseparator_get_type (), GtkVSeparatorClass)
+#define GTK_IS_VSEPARATOR(obj) GTK_CHECK_TYPE (obj, gtk_vseparator_get_type ())
+
+
+typedef struct _GtkVSeparator GtkVSeparator;
+typedef struct _GtkVSeparatorClass GtkVSeparatorClass;
+
+struct _GtkVSeparator
+{
+ GtkSeparator separator;
+};
+
+struct _GtkVSeparatorClass
+{
+ GtkSeparatorClass parent_class;
+};
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+guint gtk_vseparator_get_type (void);
+GtkWidget* gtk_vseparator_new (void);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_SEPARATOR_H__ */
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
new file mode 100644
index 000000000..26e0c9bbc
--- /dev/null
+++ b/gtk/gtkwidget.c
@@ -0,0 +1,3390 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdarg.h>
+#include <string.h>
+#include "gtkcontainer.h"
+#include "gtkmain.h"
+#include "gtkrc.h"
+#include "gtkselection.h"
+#include "gtksignal.h"
+#include "gtkwidget.h"
+#include "gtkwindow.h"
+#include "gdk/gdk.h"
+#include "gdk/gdkx.h"
+
+
+#define WIDGET_CLASS(w) GTK_WIDGET_CLASS (GTK_OBJECT (w)->klass)
+
+
+enum {
+ SHOW,
+ HIDE,
+ MAP,
+ UNMAP,
+ REALIZE,
+ UNREALIZE,
+ DRAW,
+ DRAW_FOCUS,
+ DRAW_DEFAULT,
+ SIZE_REQUEST,
+ SIZE_ALLOCATE,
+ STATE_CHANGED,
+ INSTALL_ACCELERATOR,
+ REMOVE_ACCELERATOR,
+ EVENT,
+ BUTTON_PRESS_EVENT,
+ BUTTON_RELEASE_EVENT,
+ MOTION_NOTIFY_EVENT,
+ DELETE_EVENT,
+ DESTROY_EVENT,
+ EXPOSE_EVENT,
+ KEY_PRESS_EVENT,
+ KEY_RELEASE_EVENT,
+ ENTER_NOTIFY_EVENT,
+ LEAVE_NOTIFY_EVENT,
+ CONFIGURE_EVENT,
+ FOCUS_IN_EVENT,
+ FOCUS_OUT_EVENT,
+ MAP_EVENT,
+ UNMAP_EVENT,
+ PROPERTY_NOTIFY_EVENT,
+ SELECTION_CLEAR_EVENT,
+ SELECTION_REQUEST_EVENT,
+ SELECTION_NOTIFY_EVENT,
+ SELECTION_RECEIVED,
+ PROXIMITY_IN_EVENT,
+ PROXIMITY_OUT_EVENT,
+ DRAG_BEGIN_EVENT,
+ DRAG_REQUEST_EVENT,
+ DROP_ENTER_EVENT,
+ DROP_LEAVE_EVENT,
+ DROP_DATA_AVAILABLE_EVENT,
+ OTHER_EVENT,
+ LAST_SIGNAL
+};
+
+
+typedef void (*GtkWidgetSignal1) (GtkObject *object,
+ gpointer arg1,
+ gpointer data);
+typedef gint (*GtkWidgetSignal2) (GtkObject *object,
+ gpointer arg1,
+ gchar arg2,
+ gchar arg3,
+ gpointer data);
+typedef void (*GtkWidgetSignal3) (GtkObject *object,
+ gpointer arg1,
+ gpointer data);
+typedef gint (*GtkWidgetSignal4) (GtkObject *object,
+ gpointer arg1,
+ gpointer data);
+
+
+static void gtk_widget_marshal_signal_1 (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args);
+static void gtk_widget_marshal_signal_2 (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args);
+static void gtk_widget_marshal_signal_3 (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args);
+static void gtk_widget_marshal_signal_4 (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args);
+
+static void gtk_widget_class_init (GtkWidgetClass *klass);
+static void gtk_widget_init (GtkWidget *widget);
+static void gtk_widget_arg (GtkWidget *widget,
+ GtkArg *arg);
+static void gtk_real_widget_destroy (GtkObject *object);
+static void gtk_real_widget_show (GtkWidget *widget);
+static void gtk_real_widget_hide (GtkWidget *widget);
+static void gtk_real_widget_map (GtkWidget *widget);
+static void gtk_real_widget_unmap (GtkWidget *widget);
+static void gtk_real_widget_realize (GtkWidget *widget);
+static void gtk_real_widget_unrealize (GtkWidget *widget);
+static void gtk_real_widget_draw (GtkWidget *widget,
+ GdkRectangle *area);
+static gint gtk_real_widget_queue_draw (GtkWidget *widget);
+static gint gtk_real_widget_queue_resize (GtkWidget *widget);
+static void gtk_real_widget_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+
+static GdkColormap* gtk_widget_peek_colormap (void);
+static GdkVisual* gtk_widget_peek_visual (void);
+static GtkStyle* gtk_widget_peek_style (void);
+
+static void gtk_widget_set_parent_sensitive (GtkWidget *widget,
+ gpointer client_data);
+static void gtk_widget_propagate_restore (GtkWidget *widget,
+ gpointer client_data);
+static void gtk_widget_propagate_state (GtkWidget *widget,
+ gpointer client_data);
+static void gtk_widget_draw_children_recurse (GtkWidget *widget,
+ gpointer client_data);
+static void gtk_widget_set_style_internal (GtkWidget *widget,
+ GtkStyle *style);
+static void gtk_widget_set_style_recurse (GtkWidget *widget,
+ gpointer client_data);
+
+extern GtkArg* gtk_object_collect_args (gint *nargs,
+ va_list args1,
+ va_list args2);
+
+static GtkWidgetAuxInfo* gtk_widget_aux_info_new (void);
+static void gtk_widget_aux_info_destroy (GtkWidgetAuxInfo *aux_info);
+
+static GtkObjectClass *parent_class = NULL;
+static gint widget_signals[LAST_SIGNAL] = { 0 };
+
+static GMemChunk *aux_info_mem_chunk = NULL;
+
+static GdkColormap *default_colormap = NULL;
+static GdkVisual *default_visual = NULL;
+static GtkStyle *default_style = NULL;
+
+static GSList *colormap_stack = NULL;
+static GSList *visual_stack = NULL;
+static GSList *style_stack = NULL;
+
+static const char *aux_info_key = "aux_info";
+static const char *colormap_key = "colormap";
+static const char *visual_key = "visual";
+static const char *event_key = "event_mask";
+static const char *resize_widgets_key = "resize_widgets";
+static const char *extension_event_key = "extension_event_mode";
+static const char *redraw_handler_key = "redraw_handler_tag";
+static const char *resize_handler_key = "resize_handler_tag";
+static const char *shape_info_key = "shape_info";
+
+
+
+/*****************************************
+ * gtk_widget_get_type:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+guint
+gtk_widget_get_type ()
+{
+ static guint widget_type = 0;
+
+ if (!widget_type)
+ {
+ GtkTypeInfo widget_info =
+ {
+ "GtkWidget",
+ sizeof (GtkWidget),
+ sizeof (GtkWidgetClass),
+ (GtkClassInitFunc) gtk_widget_class_init,
+ (GtkObjectInitFunc) gtk_widget_init,
+ (GtkArgFunc) gtk_widget_arg,
+ };
+
+ widget_type = gtk_type_unique (gtk_object_get_type (), &widget_info);
+ }
+
+ return widget_type;
+}
+
+/*****************************************
+ * gtk_widget_class_init:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+static void
+gtk_widget_class_init (GtkWidgetClass *klass)
+{
+ GtkObjectClass *object_class;
+
+ object_class = (GtkObjectClass*) klass;
+
+ parent_class = gtk_type_class (gtk_object_get_type ());
+
+ gtk_object_add_arg_type ("GtkWidget::x", GTK_TYPE_INT);
+ gtk_object_add_arg_type ("GtkWidget::y", GTK_TYPE_INT);
+ gtk_object_add_arg_type ("GtkWidget::width", GTK_TYPE_INT);
+ gtk_object_add_arg_type ("GtkWidget::height", GTK_TYPE_INT);
+ gtk_object_add_arg_type ("GtkWidget::visible", GTK_TYPE_BOOL);
+ gtk_object_add_arg_type ("GtkWidget::sensitive", GTK_TYPE_BOOL);
+ gtk_object_add_arg_type ("GtkWidget::events", GTK_TYPE_GDK_EVENT_MASK);
+ gtk_object_add_arg_type ("GtkWidget::extension_events", GTK_TYPE_GDK_EVENT_MASK);
+ gtk_object_add_arg_type ("GtkWidget::name", GTK_TYPE_STRING);
+ gtk_object_add_arg_type ("GtkWidget::style", GTK_TYPE_STYLE);
+ gtk_object_add_arg_type ("GtkWidget::parent", GTK_TYPE_CONTAINER);
+
+ widget_signals[SHOW] =
+ gtk_signal_new ("show",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, show),
+ gtk_signal_default_marshaller,
+ GTK_TYPE_NONE, 0);
+ widget_signals[HIDE] =
+ gtk_signal_new ("hide",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, hide),
+ gtk_signal_default_marshaller,
+ GTK_TYPE_NONE, 0);
+ widget_signals[MAP] =
+ gtk_signal_new ("map",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, map),
+ gtk_signal_default_marshaller,
+ GTK_TYPE_NONE, 0);
+ widget_signals[UNMAP] =
+ gtk_signal_new ("unmap",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, unmap),
+ gtk_signal_default_marshaller,
+ GTK_TYPE_NONE, 0);
+ widget_signals[REALIZE] =
+ gtk_signal_new ("realize",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, realize),
+ gtk_signal_default_marshaller,
+ GTK_TYPE_NONE, 0);
+ widget_signals[UNREALIZE] =
+ gtk_signal_new ("unrealize",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, unrealize),
+ gtk_signal_default_marshaller,
+ GTK_TYPE_NONE, 0);
+ widget_signals[DRAW] =
+ gtk_signal_new ("draw",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, draw),
+ gtk_widget_marshal_signal_1,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_POINTER);
+ widget_signals[DRAW_FOCUS] =
+ gtk_signal_new ("draw_focus",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, draw_focus),
+ gtk_signal_default_marshaller,
+ GTK_TYPE_NONE, 0);
+ widget_signals[DRAW_DEFAULT] =
+ gtk_signal_new ("draw_default",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, draw_default),
+ gtk_signal_default_marshaller,
+ GTK_TYPE_NONE, 0);
+ widget_signals[SIZE_REQUEST] =
+ gtk_signal_new ("size_request",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, size_request),
+ gtk_widget_marshal_signal_1,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_POINTER);
+ widget_signals[SIZE_ALLOCATE] =
+ gtk_signal_new ("size_allocate",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, size_allocate),
+ gtk_widget_marshal_signal_1,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_POINTER);
+ widget_signals[STATE_CHANGED] =
+ gtk_signal_new ("state_changed",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, state_changed),
+ gtk_signal_default_marshaller,
+ GTK_TYPE_NONE, 0);
+ widget_signals[INSTALL_ACCELERATOR] =
+ gtk_signal_new ("install_accelerator",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, install_accelerator),
+ gtk_widget_marshal_signal_2,
+ GTK_TYPE_BOOL, 3,
+ GTK_TYPE_STRING,
+ GTK_TYPE_CHAR,
+ GTK_TYPE_INT);
+ widget_signals[REMOVE_ACCELERATOR] =
+ gtk_signal_new ("remove_accelerator",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, remove_accelerator),
+ gtk_widget_marshal_signal_3,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_STRING);
+ widget_signals[EVENT] =
+ gtk_signal_new ("event",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, event),
+ gtk_widget_marshal_signal_4,
+ GTK_TYPE_BOOL, 1,
+ GTK_TYPE_GDK_EVENT);
+ widget_signals[BUTTON_PRESS_EVENT] =
+ gtk_signal_new ("button_press_event",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, button_press_event),
+ gtk_widget_marshal_signal_4,
+ GTK_TYPE_BOOL, 1,
+ GTK_TYPE_GDK_EVENT);
+ widget_signals[BUTTON_RELEASE_EVENT] =
+ gtk_signal_new ("button_release_event",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, button_release_event),
+ gtk_widget_marshal_signal_4,
+ GTK_TYPE_BOOL, 1,
+ GTK_TYPE_GDK_EVENT);
+ widget_signals[MOTION_NOTIFY_EVENT] =
+ gtk_signal_new ("motion_notify_event",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, motion_notify_event),
+ gtk_widget_marshal_signal_4,
+ GTK_TYPE_BOOL, 1,
+ GTK_TYPE_GDK_EVENT);
+ widget_signals[DELETE_EVENT] =
+ gtk_signal_new ("delete_event",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, delete_event),
+ gtk_widget_marshal_signal_4,
+ GTK_TYPE_BOOL, 1,
+ GTK_TYPE_GDK_EVENT);
+ widget_signals[DESTROY_EVENT] =
+ gtk_signal_new ("destroy_event",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, destroy_event),
+ gtk_widget_marshal_signal_4,
+ GTK_TYPE_BOOL, 1,
+ GTK_TYPE_GDK_EVENT);
+ widget_signals[EXPOSE_EVENT] =
+ gtk_signal_new ("expose_event",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, expose_event),
+ gtk_widget_marshal_signal_4,
+ GTK_TYPE_BOOL, 1,
+ GTK_TYPE_GDK_EVENT);
+ widget_signals[KEY_PRESS_EVENT] =
+ gtk_signal_new ("key_press_event",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, key_press_event),
+ gtk_widget_marshal_signal_4,
+ GTK_TYPE_BOOL, 1,
+ GTK_TYPE_GDK_EVENT);
+ widget_signals[KEY_RELEASE_EVENT] =
+ gtk_signal_new ("key_release_event",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, key_release_event),
+ gtk_widget_marshal_signal_4,
+ GTK_TYPE_BOOL, 1,
+ GTK_TYPE_GDK_EVENT);
+ widget_signals[ENTER_NOTIFY_EVENT] =
+ gtk_signal_new ("enter_notify_event",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, enter_notify_event),
+ gtk_widget_marshal_signal_4,
+ GTK_TYPE_BOOL, 1,
+ GTK_TYPE_GDK_EVENT);
+ widget_signals[LEAVE_NOTIFY_EVENT] =
+ gtk_signal_new ("leave_notify_event",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, leave_notify_event),
+ gtk_widget_marshal_signal_4,
+ GTK_TYPE_BOOL, 1,
+ GTK_TYPE_GDK_EVENT);
+ widget_signals[CONFIGURE_EVENT] =
+ gtk_signal_new ("configure_event",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, configure_event),
+ gtk_widget_marshal_signal_4,
+ GTK_TYPE_BOOL, 1,
+ GTK_TYPE_GDK_EVENT);
+ widget_signals[FOCUS_IN_EVENT] =
+ gtk_signal_new ("focus_in_event",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, focus_in_event),
+ gtk_widget_marshal_signal_4,
+ GTK_TYPE_BOOL, 1,
+ GTK_TYPE_GDK_EVENT);
+ widget_signals[FOCUS_OUT_EVENT] =
+ gtk_signal_new ("focus_out_event",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, focus_out_event),
+ gtk_widget_marshal_signal_4,
+ GTK_TYPE_BOOL, 1,
+ GTK_TYPE_GDK_EVENT);
+ widget_signals[MAP_EVENT] =
+ gtk_signal_new ("map_event",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, map_event),
+ gtk_widget_marshal_signal_4,
+ GTK_TYPE_BOOL, 1,
+ GTK_TYPE_GDK_EVENT);
+ widget_signals[UNMAP_EVENT] =
+ gtk_signal_new ("unmap_event",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, unmap_event),
+ gtk_widget_marshal_signal_4,
+ GTK_TYPE_BOOL, 1,
+ GTK_TYPE_GDK_EVENT);
+ widget_signals[PROPERTY_NOTIFY_EVENT] =
+ gtk_signal_new ("property_notify_event",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, property_notify_event),
+ gtk_widget_marshal_signal_4,
+ GTK_TYPE_BOOL, 1,
+ GTK_TYPE_GDK_EVENT);
+ widget_signals[SELECTION_CLEAR_EVENT] =
+ gtk_signal_new ("selection_clear_event",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, selection_clear_event),
+ gtk_widget_marshal_signal_4,
+ GTK_TYPE_BOOL, 1,
+ GTK_TYPE_GDK_EVENT);
+ widget_signals[SELECTION_REQUEST_EVENT] =
+ gtk_signal_new ("selection_request_event",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, selection_request_event),
+ gtk_widget_marshal_signal_4,
+ GTK_TYPE_BOOL, 1,
+ GTK_TYPE_GDK_EVENT);
+ widget_signals[SELECTION_NOTIFY_EVENT] =
+ gtk_signal_new ("selection_notify_event",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, selection_notify_event),
+ gtk_widget_marshal_signal_4,
+ GTK_TYPE_BOOL, 1,
+ GTK_TYPE_GDK_EVENT);
+ widget_signals[SELECTION_RECEIVED] =
+ gtk_signal_new ("selection_received",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, selection_received),
+ gtk_widget_marshal_signal_1,
+ GTK_TYPE_BOOL, 1,
+ GTK_TYPE_GDK_EVENT);
+ widget_signals[PROXIMITY_IN_EVENT] =
+ gtk_signal_new ("proximity_in_event",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, proximity_in_event),
+ gtk_widget_marshal_signal_4,
+ GTK_TYPE_BOOL, 1,
+ GTK_TYPE_GDK_EVENT);
+ widget_signals[PROXIMITY_OUT_EVENT] =
+ gtk_signal_new ("proximity_out_event",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, proximity_out_event),
+ gtk_widget_marshal_signal_4,
+ GTK_TYPE_BOOL, 1,
+ GTK_TYPE_GDK_EVENT);
+ widget_signals[DRAG_BEGIN_EVENT] =
+ gtk_signal_new ("drag_begin_event",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, drag_begin_event),
+ gtk_widget_marshal_signal_4,
+ GTK_TYPE_BOOL, 1,
+ GTK_TYPE_GDK_EVENT);
+ widget_signals[DRAG_REQUEST_EVENT] =
+ gtk_signal_new ("drag_request_event",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, drag_request_event),
+ gtk_widget_marshal_signal_4,
+ GTK_TYPE_BOOL, 1,
+ GTK_TYPE_GDK_EVENT);
+ widget_signals[DROP_ENTER_EVENT] =
+ gtk_signal_new ("drop_enter_event",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, drop_enter_event),
+ gtk_widget_marshal_signal_4,
+ GTK_TYPE_BOOL, 1,
+ GTK_TYPE_GDK_EVENT);
+ widget_signals[DROP_LEAVE_EVENT] =
+ gtk_signal_new ("drop_leave_event",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, drop_leave_event),
+ gtk_widget_marshal_signal_4,
+ GTK_TYPE_BOOL, 1,
+ GTK_TYPE_GDK_EVENT);
+ widget_signals[DROP_DATA_AVAILABLE_EVENT] =
+ gtk_signal_new ("drop_data_available_event",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass,
+ drop_data_available_event),
+ gtk_widget_marshal_signal_4,
+ GTK_TYPE_BOOL, 1,
+ GTK_TYPE_GDK_EVENT);
+ widget_signals[OTHER_EVENT] =
+ gtk_signal_new ("other_event",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, other_event),
+ gtk_widget_marshal_signal_4,
+ GTK_TYPE_BOOL, 1,
+ GTK_TYPE_GDK_EVENT);
+
+ gtk_object_class_add_signals (object_class, widget_signals, LAST_SIGNAL);
+
+ object_class->destroy = gtk_real_widget_destroy;
+
+ klass->activate_signal = 0;
+ klass->show = gtk_real_widget_show;
+ klass->hide = gtk_real_widget_hide;
+ klass->map = gtk_real_widget_map;
+ klass->unmap = gtk_real_widget_unmap;
+ klass->realize = gtk_real_widget_realize;
+ klass->unrealize = gtk_real_widget_unrealize;
+ klass->draw = gtk_real_widget_draw;
+ klass->draw_focus = NULL;
+ klass->size_request = NULL;
+ klass->size_allocate = gtk_real_widget_size_allocate;
+ klass->state_changed = NULL;
+ klass->install_accelerator = NULL;
+ klass->remove_accelerator = NULL;
+ klass->event = NULL;
+ klass->button_press_event = NULL;
+ klass->button_release_event = NULL;
+ klass->motion_notify_event = NULL;
+ klass->delete_event = NULL;
+ klass->destroy_event = NULL;
+ klass->expose_event = NULL;
+ klass->key_press_event = NULL;
+ klass->key_release_event = NULL;
+ klass->enter_notify_event = NULL;
+ klass->leave_notify_event = NULL;
+ klass->configure_event = NULL;
+ klass->focus_in_event = NULL;
+ klass->focus_out_event = NULL;
+ klass->map_event = NULL;
+ klass->unmap_event = NULL;
+ klass->property_notify_event = gtk_selection_property_notify;
+ klass->selection_clear_event = gtk_selection_clear;
+ klass->selection_request_event = gtk_selection_request;
+ klass->selection_notify_event = gtk_selection_notify;
+ klass->selection_received = NULL;
+ klass->proximity_in_event = NULL;
+ klass->proximity_out_event = NULL;
+ klass->drag_begin_event = NULL;
+ klass->drag_request_event = NULL;
+ klass->drop_enter_event = NULL;
+ klass->drop_leave_event = NULL;
+ klass->drop_data_available_event = NULL;
+ klass->other_event = NULL;
+}
+
+/*****************************************
+ * gtk_widget_arg:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+static void
+gtk_widget_arg (GtkWidget *widget,
+ GtkArg *arg)
+{
+ if (strcmp (arg->name, "x") == 0)
+ {
+ gtk_widget_set_uposition (widget, GTK_VALUE_INT(*arg), -2);
+ }
+ else if (strcmp (arg->name, "y") == 0)
+ {
+ gtk_widget_set_uposition (widget, -2, GTK_VALUE_INT(*arg));
+ }
+ else if (strcmp (arg->name, "width") == 0)
+ {
+ gtk_widget_set_usize (widget, GTK_VALUE_INT(*arg), -1);
+ }
+ else if (strcmp (arg->name, "height") == 0)
+ {
+ gtk_widget_set_usize (widget, -1, GTK_VALUE_INT(*arg));
+ }
+ else if (strcmp (arg->name, "visible") == 0)
+ {
+ if (GTK_VALUE_BOOL(*arg))
+ gtk_widget_show (widget);
+ else
+ gtk_widget_hide (widget);
+ }
+ else if (strcmp (arg->name, "sensitive") == 0)
+ {
+ gtk_widget_set_sensitive (widget, GTK_VALUE_BOOL(*arg));
+ }
+ else if (strcmp (arg->name, "events") == 0)
+ {
+ gtk_widget_set_events (widget, GTK_VALUE_FLAGS(*arg));
+ }
+ else if (strcmp (arg->name, "extension_events") == 0)
+ {
+ gtk_widget_set_extension_events (widget, GTK_VALUE_FLAGS(*arg));
+ }
+ else if (strcmp (arg->name, "name") == 0)
+ {
+ gtk_widget_set_name (widget, GTK_VALUE_STRING(*arg));
+ }
+ else if (strcmp (arg->name, "style") == 0)
+ {
+ gtk_widget_set_style (widget, (GtkStyle*)GTK_VALUE_BOXED(*arg));
+ }
+ else if (strcmp (arg->name, "parent") == 0)
+ {
+ gtk_container_add (GTK_CONTAINER (GTK_VALUE_OBJECT(*arg)), widget);
+ }
+}
+
+/*****************************************
+ * gtk_widget_init:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+static void
+gtk_widget_init (GtkWidget *widget)
+{
+ GdkColormap *colormap;
+ GdkVisual *visual;
+
+ GTK_OBJECT_FLAGS (widget) = GTK_SENSITIVE | GTK_PARENT_SENSITIVE;
+ widget->state = GTK_STATE_NORMAL;
+ widget->saved_state = GTK_STATE_NORMAL;
+ widget->name = NULL;
+ widget->requisition.width = 0;
+ widget->requisition.height = 0;
+ widget->allocation.x = -1;
+ widget->allocation.y = -1;
+ widget->allocation.width = 1;
+ widget->allocation.height = 1;
+ widget->window = NULL;
+ widget->parent = NULL;
+
+ widget->style = gtk_widget_peek_style ();
+ gtk_style_ref (widget->style);
+
+ colormap = gtk_widget_peek_colormap ();
+ visual = gtk_widget_peek_visual ();
+
+ if (colormap != gtk_widget_get_default_colormap ())
+ gtk_object_set_data (GTK_OBJECT (widget), colormap_key, colormap);
+
+ if (visual != gtk_widget_get_default_visual ())
+ gtk_object_set_data (GTK_OBJECT (widget), visual_key, visual);
+}
+
+/*****************************************
+ * gtk_widget_new:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+GtkWidget*
+gtk_widget_new (guint type,
+ ...)
+{
+ GtkObject *obj;
+ GtkArg *args;
+ gint nargs;
+ va_list args1;
+ va_list args2;
+
+ g_return_val_if_fail (gtk_type_is_a (type, gtk_widget_get_type ()), NULL);
+
+ obj = gtk_type_new (type);
+
+ va_start (args1, type);
+ va_start (args2, type);
+
+ args = gtk_object_collect_args (&nargs, args1, args2);
+ gtk_object_setv (obj, nargs, args);
+ g_free (args);
+
+ va_end (args1);
+ va_end (args2);
+
+ return GTK_WIDGET (obj);
+}
+
+/*****************************************
+ * gtk_widget_newv:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+GtkWidget*
+gtk_widget_newv (guint type,
+ gint nargs,
+ GtkArg *args)
+{
+ g_return_val_if_fail (gtk_type_is_a (type, gtk_widget_get_type ()), NULL);
+
+ return GTK_WIDGET (gtk_object_newv (type, nargs, args));
+}
+
+/*****************************************
+ * gtk_widget_set:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_set (GtkWidget *widget,
+ ...)
+{
+ GtkArg *args;
+ gint nargs;
+ va_list args1;
+ va_list args2;
+
+ g_return_if_fail (widget != NULL);
+
+ va_start (args1, widget);
+ va_start (args2, widget);
+
+ args = gtk_object_collect_args (&nargs, args1, args2);
+ gtk_object_setv (GTK_OBJECT (widget), nargs, args);
+ g_free (args);
+
+ va_end (args1);
+ va_end (args2);
+}
+
+/*****************************************
+ * gtk_widget_setv:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_setv (GtkWidget *widget,
+ gint nargs,
+ GtkArg *args)
+{
+ gtk_object_setv (GTK_OBJECT (widget), nargs, args);
+}
+
+/*****************************************
+ * gtk_widget_destroy:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_destroy (GtkWidget *widget)
+{
+ GSList *resize_widgets;
+ GSList *tmp_list;
+ gint tag;
+
+ g_return_if_fail (widget != NULL);
+
+ if (GTK_WIDGET_REDRAW_PENDING (widget))
+ {
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_REDRAW_PENDING);
+ gtk_object_unref (GTK_OBJECT (widget));
+ tag = (gint) gtk_object_get_data (GTK_OBJECT (widget), redraw_handler_key);
+ gtk_idle_remove (tag);
+ gtk_object_set_data (GTK_OBJECT (widget), redraw_handler_key, (gpointer) 0);
+ }
+
+ if (GTK_WIDGET_ANCHORED (widget) &&
+ GTK_WIDGET_RESIZE_PENDING (widget))
+ {
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_RESIZE_PENDING);
+ gtk_object_unref (GTK_OBJECT (widget));
+ tag = (gint) gtk_object_get_data (GTK_OBJECT (widget), resize_handler_key);
+ gtk_idle_remove (tag);
+ gtk_object_set_data (GTK_OBJECT (widget), resize_handler_key, (gpointer) 0);
+
+ resize_widgets = gtk_object_get_data (GTK_OBJECT (widget), resize_widgets_key);
+
+ tmp_list = resize_widgets;
+ while (tmp_list)
+ {
+ GtkWidget *child;
+
+ child = tmp_list->data;
+ tmp_list = tmp_list->next;
+
+ /* referencing needed? */
+ GTK_WIDGET_UNSET_FLAGS (child, GTK_RESIZE_NEEDED);
+ gtk_object_unref (GTK_OBJECT (child));
+ }
+
+ if (resize_widgets)
+ {
+ gtk_object_set_data (GTK_OBJECT (widget), resize_widgets_key, NULL);
+ g_slist_free (resize_widgets);
+ }
+ }
+
+ if (GTK_WIDGET_RESIZE_NEEDED (widget))
+ {
+ GtkWidget *toplevel;
+
+ toplevel = gtk_widget_get_toplevel (widget);
+ resize_widgets = gtk_object_get_data (GTK_OBJECT (toplevel), resize_widgets_key);
+
+ if (resize_widgets)
+ {
+ resize_widgets = g_slist_remove (resize_widgets, widget);
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_RESIZE_NEEDED);
+ gtk_object_unref (GTK_OBJECT (widget));
+
+ gtk_object_set_data (GTK_OBJECT (toplevel), resize_widgets_key, resize_widgets);
+ }
+ }
+
+
+ if (widget->parent)
+ {
+ if (!GTK_OBJECT_BEING_DESTROYED (widget->parent))
+ gtk_container_remove (GTK_CONTAINER (widget->parent), widget);
+ else
+ gtk_object_unref (GTK_OBJECT (widget));
+ }
+ gtk_object_destroy (GTK_OBJECT (widget));
+}
+
+/*****************************************
+ * gtk_widget_unparent: do any cleanup necessary necessary before
+ * setting parent = NULL. In particular, remove
+ * the focus properly.
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_unparent (GtkWidget *widget)
+{
+ GtkWidget *toplevel;
+ GtkWidget *child;
+
+ g_return_if_fail (widget != NULL);
+
+ toplevel = gtk_widget_get_toplevel (widget);
+ if (GTK_IS_WINDOW (toplevel))
+ {
+ child = GTK_WINDOW (toplevel)->focus_widget;
+
+ while (child && child != widget)
+ child = child->parent;
+
+ if (child == widget)
+ gtk_window_set_focus (GTK_WINDOW (toplevel), NULL);
+ }
+
+ if (widget->window &&
+ GTK_WIDGET_NO_WINDOW (widget) &&
+ GTK_WIDGET_DRAWABLE (widget))
+ gdk_window_clear_area (widget->window,
+ widget->allocation.x,
+ widget->allocation.y,
+ widget->allocation.width,
+ widget->allocation.height);
+
+ widget->parent = NULL;
+
+ gtk_object_unref (GTK_OBJECT (widget));
+}
+
+/*****************************************
+ * gtk_widget_show:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_show (GtkWidget *widget)
+{
+ g_return_if_fail (widget != NULL);
+
+ if (!GTK_WIDGET_VISIBLE (widget))
+ gtk_signal_emit (GTK_OBJECT (widget), widget_signals[SHOW]);
+}
+
+/*****************************************
+ * gtk_widget_hide:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_hide (GtkWidget *widget)
+{
+ g_return_if_fail (widget != NULL);
+
+ if (GTK_WIDGET_VISIBLE (widget))
+ gtk_signal_emit (GTK_OBJECT (widget), widget_signals[HIDE]);
+}
+
+/*****************************************
+ * gtk_widget_map:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_map (GtkWidget *widget)
+{
+ g_return_if_fail (widget != NULL);
+
+ if (!GTK_WIDGET_MAPPED (widget))
+ {
+ if (!GTK_WIDGET_REALIZED (widget))
+ gtk_widget_realize (widget);
+
+ gtk_signal_emit (GTK_OBJECT (widget), widget_signals[MAP]);
+ }
+}
+
+/*****************************************
+ * gtk_widget_unmap:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_unmap (GtkWidget *widget)
+{
+ g_return_if_fail (widget != NULL);
+
+ if (GTK_WIDGET_MAPPED (widget))
+ gtk_signal_emit (GTK_OBJECT (widget), widget_signals[UNMAP]);
+}
+
+/*****************************************
+ * gtk_widget_realize:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_realize (GtkWidget *widget)
+{
+ GtkStyle *new_style;
+ gint events;
+ GdkExtensionMode mode;
+ GtkWidgetShapeInfo *shape_info;
+
+ g_return_if_fail (widget != NULL);
+
+ if (!GTK_WIDGET_REALIZED (widget))
+ {
+ /*
+ if (GTK_IS_CONTAINER (widget) && !GTK_WIDGET_NO_WINDOW (widget))
+ g_print ("%s\n", gtk_type_name (GTK_WIDGET_TYPE (widget)));
+ */
+
+ if (widget->parent && !GTK_WIDGET_REALIZED (widget->parent))
+ gtk_widget_realize (widget->parent);
+
+ if (!GTK_WIDGET_USER_STYLE (widget))
+ {
+ new_style = gtk_rc_get_style (widget);
+ if (new_style != widget->style)
+ gtk_widget_set_style_internal (widget, new_style);
+ }
+
+ gtk_signal_emit (GTK_OBJECT (widget), widget_signals[REALIZE]);
+
+ if (GTK_WIDGET_HAS_SHAPE_MASK(widget))
+ {
+ shape_info = gtk_object_get_data (GTK_OBJECT (widget),
+ shape_info_key);
+ g_assert (shape_info != 0);
+ gdk_window_shape_combine_mask (widget->window,
+ shape_info->shape_mask,
+ shape_info->offset_x,
+ shape_info->offset_y);
+ }
+
+ if (!GTK_WIDGET_NO_WINDOW (widget))
+ {
+ mode = gtk_widget_get_extension_events (widget);
+ if (mode != GDK_EXTENSION_EVENTS_NONE)
+ {
+ events = gtk_widget_get_events (widget);
+ gdk_input_set_extension_events (widget->window, events, mode);
+ }
+ }
+
+ }
+}
+
+/*****************************************
+ * gtk_widget_unrealize:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_unrealize (GtkWidget *widget)
+{
+ g_return_if_fail (widget != NULL);
+
+ if (GTK_WIDGET_REALIZED (widget))
+ gtk_signal_emit (GTK_OBJECT (widget), widget_signals[UNREALIZE]);
+}
+
+/*****************************************
+ * gtk_widget_queue_draw:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_queue_draw (GtkWidget *widget)
+{
+ GtkWidget *parent;
+ gint tag;
+
+ g_return_if_fail (widget != NULL);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ /* We queue the redraw if:
+ * a) the widget is not already queued for redraw and
+ * b) non of the widgets ancestors are queued for redraw.
+ */
+ parent = widget;
+ while (parent)
+ {
+ if (GTK_WIDGET_REDRAW_PENDING (parent))
+ return;
+ parent = parent->parent;
+ }
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REDRAW_PENDING);
+ gtk_object_ref (GTK_OBJECT (widget));
+ tag = gtk_idle_add ((GtkFunction) gtk_real_widget_queue_draw, widget);
+ gtk_object_set_data (GTK_OBJECT (widget), redraw_handler_key, (gpointer) tag);
+ }
+}
+
+/*****************************************
+ * gtk_widget_queue_resize:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_queue_resize (GtkWidget *widget)
+{
+ GtkWidget *toplevel;
+ GSList *resize_widgets;
+ gint tag;
+
+ g_return_if_fail (widget != NULL);
+
+ toplevel = gtk_widget_get_toplevel (widget);
+ if (GTK_WIDGET_ANCHORED (toplevel))
+ {
+ if (GTK_WIDGET_VISIBLE (toplevel))
+ {
+ if (!GTK_WIDGET_RESIZE_PENDING (toplevel))
+ {
+ GTK_WIDGET_SET_FLAGS (toplevel, GTK_RESIZE_PENDING);
+ gtk_object_ref (GTK_OBJECT (toplevel));
+ tag = gtk_idle_add ((GtkFunction) gtk_real_widget_queue_resize, toplevel);
+ gtk_object_set_data (GTK_OBJECT (toplevel), resize_handler_key, (gpointer) tag);
+ }
+
+ resize_widgets = gtk_object_get_data (GTK_OBJECT (toplevel), resize_widgets_key);
+ if (g_slist_find (resize_widgets, widget) == NULL)
+ {
+ /* referencing needed? */
+ GTK_WIDGET_SET_FLAGS (widget, GTK_RESIZE_NEEDED);
+ gtk_object_ref (GTK_OBJECT (widget));
+ resize_widgets = g_slist_prepend (resize_widgets, widget);
+
+ gtk_object_set_data (GTK_OBJECT (toplevel), resize_widgets_key, resize_widgets);
+ }
+ }
+ else
+ {
+ gtk_container_need_resize (GTK_CONTAINER (toplevel));
+ }
+ }
+}
+
+/*****************************************
+ * gtk_widget_draw:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_draw (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ GdkRectangle temp_area;
+
+ g_return_if_fail (widget != NULL);
+
+ if (GTK_WIDGET_DRAWABLE (widget) &&
+ !GTK_WIDGET_REDRAW_PENDING (widget))
+ {
+ if (!area)
+ {
+ if (GTK_WIDGET_NO_WINDOW (widget))
+ {
+ temp_area.x = widget->allocation.x;
+ temp_area.y = widget->allocation.y;
+ }
+ else
+ {
+ temp_area.x = 0;
+ temp_area.y = 0;
+ }
+
+ temp_area.width = widget->allocation.width;
+ temp_area.height = widget->allocation.height;
+ area = &temp_area;
+ }
+
+ gtk_signal_emit (GTK_OBJECT (widget), widget_signals[DRAW], area);
+ }
+}
+
+/*****************************************
+ * gtk_widget_draw_focus:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_draw_focus (GtkWidget *widget)
+{
+ g_return_if_fail (widget != NULL);
+
+ gtk_signal_emit (GTK_OBJECT (widget), widget_signals[DRAW_FOCUS]);
+}
+
+/*****************************************
+ * gtk_widget_draw_default:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_draw_default (GtkWidget *widget)
+{
+ g_return_if_fail (widget != NULL);
+
+ gtk_signal_emit (GTK_OBJECT (widget), widget_signals[DRAW_DEFAULT]);
+}
+
+/*****************************************
+ * gtk_widget_draw_children:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_draw_children (GtkWidget *widget)
+{
+ g_return_if_fail (widget != NULL);
+
+ if (GTK_IS_CONTAINER (widget))
+ gtk_container_foreach (GTK_CONTAINER (widget),
+ gtk_widget_draw_children_recurse,
+ NULL);
+}
+
+/*****************************************
+ * gtk_widget_size_request:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkWidgetAuxInfo *aux_info;
+
+ g_return_if_fail (widget != NULL);
+
+ if (gtk_signal_emit (GTK_OBJECT (widget), widget_signals[SIZE_REQUEST], requisition))
+ {
+ aux_info = gtk_object_get_data (GTK_OBJECT (widget), aux_info_key);
+ if (aux_info)
+ {
+ if (aux_info->width > 0)
+ requisition->width = aux_info->width;
+ if (aux_info->height > 0)
+ requisition->height = aux_info->height;
+ }
+ }
+}
+
+/*****************************************
+ * gtk_widget_size_allocate:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkWidgetAuxInfo *aux_info;
+ GtkAllocation real_allocation;
+
+ g_return_if_fail (widget != NULL);
+
+ real_allocation = *allocation;
+ aux_info = gtk_object_get_data (GTK_OBJECT (widget), aux_info_key);
+
+ if (aux_info)
+ {
+ if (aux_info->x != -1)
+ real_allocation.x = aux_info->x;
+ if (aux_info->y != -1)
+ real_allocation.y = aux_info->y;
+ }
+
+ gtk_signal_emit (GTK_OBJECT (widget), widget_signals[SIZE_ALLOCATE], &real_allocation);
+}
+
+/*****************************************
+ * gtk_widget_install_accelerator:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_install_accelerator (GtkWidget *widget,
+ GtkAcceleratorTable *table,
+ const gchar *signal_name,
+ gchar key,
+ guint8 modifiers)
+{
+ gint return_val;
+
+ g_return_if_fail (widget != NULL);
+
+ return_val = TRUE;
+ if (gtk_signal_emit (GTK_OBJECT (widget), widget_signals[INSTALL_ACCELERATOR],
+ signal_name, key, modifiers, &return_val) && return_val)
+ gtk_accelerator_table_install (table, GTK_OBJECT (widget), signal_name, key, modifiers);
+}
+
+/*****************************************
+ * gtk_widget_remove_accelerator:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_remove_accelerator (GtkWidget *widget,
+ GtkAcceleratorTable *table,
+ const gchar *signal_name)
+{
+ g_return_if_fail (widget != NULL);
+
+ if (gtk_signal_emit (GTK_OBJECT (widget), widget_signals[REMOVE_ACCELERATOR], signal_name))
+ gtk_accelerator_table_remove (table, GTK_OBJECT (widget), signal_name);
+}
+
+/*****************************************
+ * gtk_widget_event:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+gint
+gtk_widget_event (GtkWidget *widget,
+ GdkEvent *event)
+{
+ gint return_val;
+ gint signal_num;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+
+ return_val = FALSE;
+ if (gtk_signal_emit (GTK_OBJECT (widget), widget_signals[EVENT], event, &return_val))
+ {
+ if (return_val)
+ return TRUE;
+
+ switch (event->type)
+ {
+ case GDK_NOTHING:
+ signal_num = -1;
+ break;
+ case GDK_BUTTON_PRESS:
+ case GDK_2BUTTON_PRESS:
+ case GDK_3BUTTON_PRESS:
+ signal_num = BUTTON_PRESS_EVENT;
+ break;
+ case GDK_BUTTON_RELEASE:
+ signal_num = BUTTON_RELEASE_EVENT;
+ break;
+ case GDK_MOTION_NOTIFY:
+ signal_num = MOTION_NOTIFY_EVENT;
+ break;
+ case GDK_DELETE:
+ signal_num = DELETE_EVENT;
+ break;
+ case GDK_DESTROY:
+ signal_num = DESTROY_EVENT;
+ break;
+ case GDK_EXPOSE:
+ signal_num = EXPOSE_EVENT;
+ break;
+ case GDK_KEY_PRESS:
+ signal_num = KEY_PRESS_EVENT;
+ break;
+ case GDK_KEY_RELEASE:
+ signal_num = KEY_RELEASE_EVENT;
+ break;
+ case GDK_ENTER_NOTIFY:
+ signal_num = ENTER_NOTIFY_EVENT;
+ break;
+ case GDK_LEAVE_NOTIFY:
+ signal_num = LEAVE_NOTIFY_EVENT;
+ break;
+ case GDK_FOCUS_CHANGE:
+ if (event->focus_change.in)
+ signal_num = FOCUS_IN_EVENT;
+ else
+ signal_num = FOCUS_OUT_EVENT;
+ break;
+ case GDK_CONFIGURE:
+ signal_num = CONFIGURE_EVENT;
+ break;
+ case GDK_MAP:
+ signal_num = MAP_EVENT;
+ break;
+ case GDK_UNMAP:
+ signal_num = UNMAP_EVENT;
+ break;
+ case GDK_PROPERTY_NOTIFY:
+ signal_num = PROPERTY_NOTIFY_EVENT;
+ break;
+ case GDK_SELECTION_CLEAR:
+ signal_num = SELECTION_CLEAR_EVENT;
+ break;
+ case GDK_SELECTION_REQUEST:
+ signal_num = SELECTION_REQUEST_EVENT;
+ break;
+ case GDK_SELECTION_NOTIFY:
+ signal_num = SELECTION_NOTIFY_EVENT;
+ break;
+ case GDK_PROXIMITY_IN:
+ signal_num = PROXIMITY_IN_EVENT;
+ break;
+ case GDK_PROXIMITY_OUT:
+ signal_num = PROXIMITY_OUT_EVENT;
+ break;
+ case GDK_DRAG_BEGIN:
+ signal_num = DRAG_BEGIN_EVENT;
+ break;
+ case GDK_DRAG_REQUEST:
+ signal_num = DRAG_REQUEST_EVENT;
+ break;
+ case GDK_DROP_ENTER:
+ signal_num = DROP_ENTER_EVENT;
+ break;
+ case GDK_DROP_LEAVE:
+ signal_num = DROP_LEAVE_EVENT;
+ break;
+ case GDK_DROP_DATA_AVAIL:
+ signal_num = DROP_DATA_AVAILABLE_EVENT;
+ break;
+ case GDK_OTHER_EVENT:
+ signal_num = OTHER_EVENT;
+ break;
+ default:
+ g_warning ("could not determine signal number for event: %d", event->type);
+ return return_val;
+ }
+
+ if (signal_num != -1)
+ gtk_signal_emit (GTK_OBJECT (widget), widget_signals[signal_num], event, &return_val);
+ }
+
+ return return_val;
+}
+
+/*****************************************
+ * gtk_widget_activate:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_activate (GtkWidget *widget)
+{
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ if (WIDGET_CLASS (widget)->activate_signal)
+ gtk_signal_emit (GTK_OBJECT (widget), WIDGET_CLASS (widget)->activate_signal);
+}
+
+/*****************************************
+ * gtk_widget_reparent:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_reparent (GtkWidget *widget,
+ GtkWidget *new_parent)
+{
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (new_parent != NULL);
+ g_return_if_fail (GTK_IS_CONTAINER (new_parent));
+
+ if (widget->parent != new_parent)
+ {
+ gtk_container_remove (GTK_CONTAINER (widget->parent), widget);
+ gtk_container_add (GTK_CONTAINER (new_parent), widget);
+
+ if (GTK_WIDGET_REALIZED (widget))
+ {
+ if (GTK_WIDGET_REALIZED (new_parent) && !GTK_WIDGET_NO_WINDOW (widget))
+ {
+ gdk_window_reparent (widget->window, widget->parent->window, 0, 0);
+ }
+ else
+ {
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_REALIZED | GTK_MAPPED);
+ if (!GTK_WIDGET_NO_WINDOW (widget))
+ gdk_window_destroy (widget->window);
+ widget->window = NULL;
+
+ if (GTK_WIDGET_REALIZED (new_parent))
+ gtk_widget_realize (widget);
+ if (GTK_WIDGET_MAPPED (new_parent))
+ gtk_widget_map (widget);
+ }
+ }
+
+ if (!GTK_WIDGET_REALIZED (widget) && GTK_WIDGET_REALIZED (new_parent))
+ gtk_widget_realize (widget);
+ if (!GTK_WIDGET_MAPPED (widget) && GTK_WIDGET_MAPPED (new_parent))
+ gtk_widget_map (widget);
+
+ gtk_widget_queue_resize (widget);
+ }
+}
+
+/*****************************************
+ * gtk_widget_popup:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_popup (GtkWidget *widget,
+ gint x,
+ gint y)
+{
+ g_return_if_fail (widget != NULL);
+
+ if (!GTK_WIDGET_VISIBLE (widget))
+ {
+ if (!GTK_WIDGET_REALIZED (widget))
+ gtk_widget_realize (widget);
+ if (!GTK_WIDGET_NO_WINDOW (widget))
+ gdk_window_move (widget->window, x, y);
+ gtk_widget_show (widget);
+ }
+}
+
+/*****************************************
+ * gtk_widget_intersect:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+gint
+gtk_widget_intersect (GtkWidget *widget,
+ GdkRectangle *area,
+ GdkRectangle *intersection)
+{
+ GdkRectangle *dest;
+ GdkRectangle tmp;
+ gint return_val;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (area != NULL, FALSE);
+
+ if (intersection)
+ dest = intersection;
+ else
+ dest = &tmp;
+
+ return_val = gdk_rectangle_intersect ((GdkRectangle*) &widget->allocation, area, dest);
+
+ if (return_val && intersection && !GTK_WIDGET_NO_WINDOW (widget))
+ {
+ intersection->x -= widget->allocation.x;
+ intersection->y -= widget->allocation.y;
+ }
+
+ return return_val;
+}
+
+
+gint
+gtk_widget_basic (GtkWidget *widget)
+{
+ GList *children;
+ GList *tmp_list;
+ gint return_val;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+
+ if (!GTK_WIDGET_BASIC (widget))
+ return FALSE;
+ else if (GTK_IS_CONTAINER (widget))
+ {
+ children = gtk_container_children (GTK_CONTAINER (widget));
+ if (children)
+ {
+ return_val = TRUE;
+ tmp_list = children;
+
+ while (tmp_list)
+ {
+ if (!gtk_widget_basic (GTK_WIDGET (tmp_list->data)))
+ {
+ return_val = FALSE;
+ break;
+ }
+
+ tmp_list = tmp_list->next;
+ }
+
+ g_list_free (children);
+ return return_val;
+ }
+ }
+
+ return TRUE;
+}
+
+
+/*****************************************
+ * gtk_widget_grab_focus:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_grab_focus (GtkWidget *widget)
+{
+ GtkWidget *window;
+ GtkWidget *child;
+ gint window_type;
+
+ g_return_if_fail (widget != NULL);
+
+ window_type = gtk_window_get_type ();
+ window = widget->parent;
+ child = widget;
+
+ while (window && !gtk_type_is_a (GTK_WIDGET_TYPE (window), window_type))
+ {
+ GTK_CONTAINER (window)->focus_child = child;
+ child = window;
+ window = window->parent;
+ }
+
+ if (window && gtk_type_is_a (GTK_WIDGET_TYPE (window), window_type))
+ {
+ GTK_CONTAINER (window)->focus_child = child;
+ gtk_window_set_focus (GTK_WINDOW (window), widget);
+ }
+}
+
+/*****************************************
+ * gtk_widget_grab_default:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_grab_default (GtkWidget *widget)
+{
+ GtkWidget *window;
+ gint window_type;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (widget));
+
+ window_type = gtk_window_get_type ();
+ window = widget->parent;
+
+ while (window && !gtk_type_is_a (GTK_WIDGET_TYPE (window), window_type))
+ window = window->parent;
+
+ if (window && gtk_type_is_a (GTK_WIDGET_TYPE (window), window_type))
+ gtk_window_set_default (GTK_WINDOW (window), widget);
+}
+
+/*****************************************
+ * gtk_widget_restore_state:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_restore_state (GtkWidget *widget)
+{
+ g_return_if_fail (widget != NULL);
+
+ widget->state = widget->saved_state;
+ if (gtk_signal_emit (GTK_OBJECT (widget), widget_signals[STATE_CHANGED]))
+ {
+ if (GTK_IS_CONTAINER (widget))
+ gtk_container_foreach (GTK_CONTAINER (widget),
+ gtk_widget_propagate_restore,
+ NULL);
+ }
+}
+
+/*****************************************
+ * gtk_widget_set_name:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_set_name (GtkWidget *widget,
+ const gchar *name)
+{
+ GtkStyle *new_style;
+
+ g_return_if_fail (widget != NULL);
+
+ if (widget->name)
+ g_free (widget->name);
+ widget->name = g_strdup (name);
+
+ if (!GTK_WIDGET_USER_STYLE (widget))
+ {
+ new_style = gtk_rc_get_style (widget);
+ gtk_widget_set_style_internal (widget, new_style);
+ }
+}
+
+/*****************************************
+ * gtk_widget_get_name:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+gchar*
+gtk_widget_get_name (GtkWidget *widget)
+{
+ g_return_val_if_fail (widget != NULL, NULL);
+
+ if (widget->name)
+ return widget->name;
+ return gtk_type_name (GTK_WIDGET_TYPE (widget));
+}
+
+/*****************************************
+ * gtk_widget_set_state:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_set_state (GtkWidget *widget,
+ GtkStateType state)
+{
+ g_return_if_fail (widget != NULL);
+
+ if (widget->state != state)
+ {
+ widget->saved_state = widget->state;
+ widget->state = state;
+
+ if (!gtk_signal_emit (GTK_OBJECT (widget), widget_signals[STATE_CHANGED]))
+ return;
+ }
+
+ if (GTK_IS_CONTAINER (widget))
+ gtk_container_foreach (GTK_CONTAINER (widget),
+ gtk_widget_propagate_state,
+ (gpointer) &state);
+}
+
+/*****************************************
+ * gtk_widget_set_sensitive:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_set_sensitive (GtkWidget *widget,
+ gint sensitive)
+{
+ GtkWidget *window;
+ gint old_val;
+
+ g_return_if_fail (widget != NULL);
+
+ old_val = GTK_WIDGET_IS_SENSITIVE (widget);
+
+ if (sensitive)
+ {
+ GTK_WIDGET_SET_FLAGS (widget, GTK_SENSITIVE);
+ }
+ else
+ {
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_SENSITIVE);
+
+ if (GTK_WIDGET_HAS_FOCUS (widget))
+ {
+ window = gtk_widget_get_ancestor (widget, gtk_window_get_type ());
+ if (window)
+ gtk_window_set_focus (GTK_WINDOW (window), NULL);
+ }
+ }
+
+ if (GTK_IS_CONTAINER (widget))
+ gtk_container_foreach (GTK_CONTAINER (widget),
+ gtk_widget_set_parent_sensitive,
+ &sensitive);
+
+ if (old_val != GTK_WIDGET_IS_SENSITIVE (widget))
+ gtk_widget_queue_draw (widget);
+}
+
+/*****************************************
+ * gtk_widget_set_parent:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_set_parent (GtkWidget *widget,
+ GtkWidget *parent)
+{
+ GtkStyle *style;
+ gint sensitive;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (parent != NULL);
+
+ gtk_object_ref (GTK_OBJECT (widget));
+
+ widget->parent = parent;
+
+ sensitive = GTK_WIDGET_IS_SENSITIVE (parent);
+ gtk_widget_set_parent_sensitive (widget, &sensitive);
+
+ if ((widget->parent->state != GTK_STATE_NORMAL) &&
+ (widget->parent->state != widget->state))
+ gtk_widget_set_state (widget, widget->parent->state);
+
+ while (parent->parent != NULL)
+ parent = parent->parent;
+
+ if (GTK_WIDGET_ANCHORED (parent))
+ {
+ if (!GTK_WIDGET_USER_STYLE (widget))
+ {
+ style = gtk_rc_get_style (widget);
+ if (style != widget->style)
+ gtk_widget_set_style_internal (widget, style);
+ }
+
+ if (GTK_IS_CONTAINER (widget))
+ gtk_container_foreach (GTK_CONTAINER (widget),
+ gtk_widget_set_style_recurse,
+ NULL);
+ }
+}
+
+/*****************************************
+ * gtk_widget_set_style:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_set_style (GtkWidget *widget,
+ GtkStyle *style)
+{
+ g_return_if_fail (widget != NULL);
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_USER_STYLE);
+ gtk_widget_set_style_internal (widget, style);
+}
+
+/*****************************************
+ * gtk_widget_set_uposition:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_set_uposition (GtkWidget *widget,
+ gint x,
+ gint y)
+{
+ GtkWidgetAuxInfo *aux_info;
+
+ g_return_if_fail (widget != NULL);
+
+ aux_info = gtk_object_get_data (GTK_OBJECT (widget), aux_info_key);
+ if (!aux_info)
+ {
+ aux_info = gtk_widget_aux_info_new ();
+ gtk_object_set_data (GTK_OBJECT (widget), aux_info_key, aux_info);
+ }
+
+ if (x > -2)
+ aux_info->x = x;
+ if (y > -2)
+ aux_info->y = y;
+
+ if (GTK_WIDGET_REALIZED (widget) && GTK_IS_WINDOW (widget) &&
+ (aux_info->x != -1) && (aux_info->y != -1))
+ {
+ gdk_window_set_hints (widget->window, aux_info->x, aux_info->y, 0, 0, 0, 0, GDK_HINT_POS);
+ gdk_window_move (widget->window, aux_info->x, aux_info->y);
+ }
+
+ if (GTK_WIDGET_VISIBLE (widget) && widget->parent)
+ gtk_widget_size_allocate (widget, &widget->allocation);
+}
+
+/*****************************************
+ * gtk_widget_set_usize:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_set_usize (GtkWidget *widget,
+ gint width,
+ gint height)
+{
+ GtkWidgetAuxInfo *aux_info;
+
+ g_return_if_fail (widget != NULL);
+
+ aux_info = gtk_object_get_data (GTK_OBJECT (widget), aux_info_key);
+ if (!aux_info)
+ {
+ aux_info = gtk_widget_aux_info_new ();
+ gtk_object_set_data (GTK_OBJECT (widget), aux_info_key, aux_info);
+ }
+
+ if (width > -1)
+ aux_info->width = width;
+ if (height > -1)
+ aux_info->height = height;
+
+ if (GTK_WIDGET_VISIBLE (widget))
+ gtk_widget_queue_resize (widget);
+}
+
+/*****************************************
+ * gtk_widget_set_events:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_set_events (GtkWidget *widget,
+ gint events)
+{
+ gint *eventp;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (!GTK_WIDGET_NO_WINDOW (widget));
+ g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
+
+ eventp = gtk_object_get_data (GTK_OBJECT (widget), event_key);
+
+ if (events)
+ {
+ if (!eventp)
+ eventp = g_new (gint, 1);
+
+ *eventp = events;
+ gtk_object_set_data (GTK_OBJECT (widget), event_key, eventp);
+ }
+ else
+ {
+ if (eventp)
+ g_free (eventp);
+
+ gtk_object_remove_data (GTK_OBJECT (widget), event_key);
+ }
+}
+
+/*****************************************
+ * gtk_widget_set_extension_events:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_set_extension_events (GtkWidget *widget,
+ GdkExtensionMode mode)
+{
+ GdkExtensionMode *modep;
+
+ g_return_if_fail (widget != NULL);
+
+ modep = gtk_object_get_data (GTK_OBJECT (widget), extension_event_key);
+
+ if (!modep)
+ modep = g_new (GdkExtensionMode, 1);
+
+ *modep = mode;
+ gtk_object_set_data (GTK_OBJECT (widget), extension_event_key, modep);
+}
+
+
+/*****************************************
+ * gtk_widget_get_toplevel:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+GtkWidget*
+gtk_widget_get_toplevel (GtkWidget *widget)
+{
+ g_return_val_if_fail (widget != NULL, NULL);
+
+ while (widget->parent)
+ widget = widget->parent;
+
+ return widget;
+}
+
+/*****************************************
+ * gtk_widget_get_ancestor:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+GtkWidget*
+gtk_widget_get_ancestor (GtkWidget *widget,
+ gint type)
+{
+ g_return_val_if_fail (widget != NULL, NULL);
+
+ while (widget && !gtk_type_is_a (GTK_WIDGET_TYPE (widget), type))
+ widget = widget->parent;
+
+ if (!(widget && gtk_type_is_a (GTK_WIDGET_TYPE (widget), type)))
+ return NULL;
+
+ return widget;
+}
+
+/*****************************************
+ * gtk_widget_get_colormap:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+GdkColormap*
+gtk_widget_get_colormap (GtkWidget *widget)
+{
+ GdkColormap *colormap;
+
+ g_return_val_if_fail (widget != NULL, NULL);
+
+ if (!widget->window)
+ {
+ colormap = gtk_object_get_data (GTK_OBJECT (widget), colormap_key);
+ if (colormap)
+ return colormap;
+ return gtk_widget_get_default_colormap ();
+ }
+
+ return gdk_window_get_colormap (widget->window);
+}
+
+/*****************************************
+ * gtk_widget_get_visual:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+GdkVisual*
+gtk_widget_get_visual (GtkWidget *widget)
+{
+ GdkVisual *visual;
+
+ g_return_val_if_fail (widget != NULL, NULL);
+
+ if (!widget->window)
+ {
+ visual = gtk_object_get_data (GTK_OBJECT (widget), visual_key);
+ if (visual)
+ return visual;
+ return gtk_widget_get_default_visual ();
+ }
+
+ return gdk_window_get_visual (widget->window);
+}
+
+/*****************************************
+ * gtk_widget_get_style:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+GtkStyle*
+gtk_widget_get_style (GtkWidget *widget)
+{
+ g_return_val_if_fail (widget != NULL, NULL);
+
+ return widget->style;
+}
+
+/*****************************************
+ * gtk_widget_get_events:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+gint
+gtk_widget_get_events (GtkWidget *widget)
+{
+ gint *events;
+
+ g_return_val_if_fail (widget != NULL, 0);
+
+ events = gtk_object_get_data (GTK_OBJECT (widget), event_key);
+ if (events)
+ return *events;
+
+ return 0;
+}
+
+/*****************************************
+ * gtk_widget_get_extension_events:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+GdkExtensionMode
+gtk_widget_get_extension_events (GtkWidget *widget)
+{
+ GdkExtensionMode *mode;
+
+ g_return_val_if_fail (widget != NULL, 0);
+
+ mode = gtk_object_get_data (GTK_OBJECT (widget), extension_event_key);
+ if (mode)
+ return *mode;
+
+ return 0;
+}
+
+/*****************************************
+ * gtk_widget_get_pointer:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_get_pointer (GtkWidget *widget,
+ gint *x,
+ gint *y)
+{
+ g_return_if_fail (widget != NULL);
+
+ if (x)
+ *x = -1;
+ if (y)
+ *y = -1;
+
+ if (GTK_WIDGET_REALIZED (widget))
+ {
+ gdk_window_get_pointer (widget->window, x, y, NULL);
+
+ if (GTK_WIDGET_NO_WINDOW (widget))
+ {
+ if (x)
+ *x -= widget->allocation.x;
+ if (y)
+ *y -= widget->allocation.y;
+ }
+ }
+}
+
+/*****************************************
+ * gtk_widget_is_ancestor:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+gint
+gtk_widget_is_ancestor (GtkWidget *widget,
+ GtkWidget *ancestor)
+{
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (ancestor != NULL, FALSE);
+
+ while (widget)
+ {
+ if (widget->parent == ancestor)
+ return TRUE;
+ widget = widget->parent;
+ }
+
+ return FALSE;
+}
+
+/*****************************************
+ * gtk_widget_is_child:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+gint
+gtk_widget_is_child (GtkWidget *widget,
+ GtkWidget *child)
+{
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (child != NULL, FALSE);
+
+ return (child->parent == widget);
+}
+
+/*****************************************
+ * gtk_widget_push_colormap:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_push_colormap (GdkColormap *cmap)
+{
+ colormap_stack = g_slist_prepend (colormap_stack, cmap);
+}
+
+/*****************************************
+ * gtk_widget_push_visual:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_push_visual (GdkVisual *visual)
+{
+ visual_stack = g_slist_prepend (visual_stack, visual);
+}
+
+/*****************************************
+ * gtk_widget_push_style:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_push_style (GtkStyle *style)
+{
+ gtk_style_ref (style);
+ style_stack = g_slist_prepend (style_stack, style);
+}
+
+/*****************************************
+ * gtk_widget_pop_colormap:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_pop_colormap ()
+{
+ GSList *tmp;
+
+ if (colormap_stack)
+ {
+ tmp = colormap_stack;
+ colormap_stack = colormap_stack->next;
+ g_slist_free_1 (tmp);
+ }
+}
+
+/*****************************************
+ * gtk_widget_pop_visual:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_pop_visual ()
+{
+ GSList *tmp;
+
+ if (visual_stack)
+ {
+ tmp = visual_stack;
+ visual_stack = visual_stack->next;
+ g_slist_free_1 (tmp);
+ }
+}
+
+/*****************************************
+ * gtk_widget_pop_style:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_pop_style ()
+{
+ GSList *tmp;
+
+ if (style_stack)
+ {
+ tmp = style_stack;
+ style_stack = style_stack->next;
+ gtk_style_unref ((GtkStyle*) tmp->data);
+ g_slist_free_1 (tmp);
+ }
+}
+
+/*****************************************
+ * gtk_widget_set_default_colormap:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_set_default_colormap (GdkColormap *colormap)
+{
+ if (default_colormap && (default_colormap != colormap))
+ gdk_colormap_destroy (default_colormap);
+ default_colormap = colormap;
+}
+
+/*****************************************
+ * gtk_widget_set_default_visual:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_set_default_visual (GdkVisual *visual)
+{
+ default_visual = visual;
+}
+
+/*****************************************
+ * gtk_widget_set_default_style:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+void
+gtk_widget_set_default_style (GtkStyle *style)
+{
+ if (default_style)
+ gtk_style_unref (default_style);
+
+ default_style = style;
+ gtk_style_ref (default_style);
+}
+
+/* Basically, send a message to all toplevel windows telling them
+ that a new _GTK_STYLE_COLORS property is available on the root
+ window */
+void
+gtk_widget_propagate_default_style(void)
+{
+ GdkEventClient sev;
+ int i;
+
+ /* Set the property on the root window */
+ gdk_property_change(GDK_ROOT_PARENT(),
+ gdk_atom_intern("_GTK_DEFAULT_COLORS", FALSE),
+ GDK_NONE, sizeof(gushort),
+ GDK_PROP_MODE_REPLACE,
+ gtk_widget_get_default_style(),
+ GTK_STYLE_NUM_STYLECOLORS() * sizeof(GdkColor));
+
+ for(i = 0; i < 5; i++) sev.data.l[i] = 0;
+ sev.data_format = 32;
+ sev.message_type = gdk_atom_intern("_GTK_STYLE_CHANGED", FALSE);
+ gdk_event_send_clientmessage_toall(&sev);
+}
+
+/*****************************************
+ * gtk_widget_get_default_colormap:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+GdkColormap*
+gtk_widget_get_default_colormap ()
+{
+ if (!default_colormap)
+ default_colormap = gdk_colormap_get_system ();
+
+ return default_colormap;
+}
+
+/*****************************************
+ * gtk_widget_get_default_visual:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+GdkVisual*
+gtk_widget_get_default_visual ()
+{
+ if (!default_visual)
+ default_visual = gdk_visual_get_system ();
+
+ return default_visual;
+}
+
+/*****************************************
+ * gtk_widget_get_default_style:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+GtkStyle*
+gtk_widget_get_default_style ()
+{
+ if (!default_style)
+ {
+ default_style = gtk_style_new ();
+ gtk_style_ref (default_style);
+ }
+
+ return default_style;
+}
+
+
+/*****************************************
+ * gtk_widget_marshal_signal_1:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+static void
+gtk_widget_marshal_signal_1 (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args)
+{
+ GtkWidgetSignal1 rfunc;
+
+ rfunc = (GtkWidgetSignal1) func;
+
+ (* rfunc) (object, GTK_VALUE_POINTER (args[0]), func_data);
+}
+
+/*****************************************
+ * gtk_widget_marshal_signal_2:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+static void
+gtk_widget_marshal_signal_2 (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args)
+{
+ GtkWidgetSignal2 rfunc;
+ gint *return_val;
+
+ rfunc = (GtkWidgetSignal2) func;
+ return_val = GTK_RETLOC_BOOL (args[3]);
+
+ *return_val = (* rfunc) (object, GTK_VALUE_STRING (args[0]),
+ GTK_VALUE_CHAR (args[1]), GTK_VALUE_INT (args[2]),
+ func_data);
+}
+
+/*****************************************
+ * gtk_widget_marshal_signal_3:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+static void
+gtk_widget_marshal_signal_3 (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args)
+{
+ GtkWidgetSignal3 rfunc;
+
+ rfunc = (GtkWidgetSignal3) func;
+
+ (* rfunc) (object, GTK_VALUE_STRING (args[0]), func_data);
+}
+
+/*****************************************
+ * gtk_widget_marshal_signal_4:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+static void
+gtk_widget_marshal_signal_4 (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args)
+{
+ GtkWidgetSignal4 rfunc;
+ gint *return_val;
+
+ rfunc = (GtkWidgetSignal4) func;
+ return_val = GTK_RETLOC_BOOL (args[1]);
+
+ *return_val = (* rfunc) (object, GTK_VALUE_BOXED (args[0]), func_data);
+}
+
+/*****************************************
+ * gtk_real_widget_destroy:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+static void
+gtk_real_widget_destroy (GtkObject *object)
+{
+ GtkWidget *widget;
+ GtkWidgetAuxInfo *aux_info;
+ gint *events;
+ GdkExtensionMode *mode;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_WIDGET (object));
+
+ widget = GTK_WIDGET (object);
+
+ if (GTK_WIDGET_REDRAW_PENDING (widget))
+ g_warning ("redraw pending\n");
+ if (GTK_WIDGET_RESIZE_PENDING (widget))
+ g_warning ("resize pending\n");
+ if (GTK_WIDGET_RESIZE_NEEDED (widget))
+ g_warning ("resize needed\n");
+
+ gtk_grab_remove (widget);
+
+ gtk_selection_remove_all (widget);
+
+ if (widget->name)
+ g_free (widget->name);
+
+ aux_info = gtk_object_get_data (GTK_OBJECT (widget), aux_info_key);
+ if (aux_info)
+ {
+ gtk_widget_aux_info_destroy (aux_info);
+ gtk_object_remove_data (GTK_OBJECT (widget), aux_info_key);
+ }
+
+ events = gtk_object_get_data (GTK_OBJECT (object), event_key);
+ if (events)
+ g_free (events);
+
+ mode = gtk_object_get_data (GTK_OBJECT (object), extension_event_key);
+ if (mode)
+ g_free (mode);
+
+ if (GTK_WIDGET_REALIZED (widget))
+ gtk_widget_unrealize (widget);
+ gtk_style_unref (widget->style);
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+/*****************************************
+ * gtk_real_widget_show:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+static void
+gtk_real_widget_show (GtkWidget *widget)
+{
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ if (!GTK_WIDGET_VISIBLE (widget))
+ {
+ GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
+
+ if (widget->parent)
+ {
+ gtk_widget_queue_resize (widget);
+
+ if (GTK_WIDGET_MAPPED (widget->parent))
+ gtk_widget_map (widget);
+ }
+ }
+}
+
+/*****************************************
+ * gtk_real_widget_hide:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+static void
+gtk_real_widget_hide (GtkWidget *widget)
+{
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ if (GTK_WIDGET_VISIBLE (widget))
+ {
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
+
+ if (GTK_WIDGET_MAPPED (widget))
+ gtk_widget_unmap (widget);
+
+ if (widget->parent)
+ gtk_widget_queue_resize (widget);
+ }
+}
+
+/*****************************************
+ * gtk_real_widget_map:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+static void
+gtk_real_widget_map (GtkWidget *widget)
+{
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ if (GTK_WIDGET_REALIZED (widget) && !GTK_WIDGET_MAPPED (widget))
+ {
+ GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
+
+ if (!GTK_WIDGET_NO_WINDOW (widget))
+ gdk_window_show (widget->window);
+ else
+ gtk_widget_queue_draw (widget);
+ }
+}
+
+/*****************************************
+ * gtk_real_widget_unmap:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+static void
+gtk_real_widget_unmap (GtkWidget *widget)
+{
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ if (GTK_WIDGET_MAPPED (widget))
+ {
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
+
+ if (GTK_WIDGET_NO_WINDOW (widget))
+ gdk_window_clear_area (widget->window,
+ widget->allocation.x,
+ widget->allocation.y,
+ widget->allocation.width,
+ widget->allocation.height);
+ else
+ gdk_window_hide (widget->window);
+ }
+}
+
+/*****************************************
+ * gtk_real_widget_realize:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+static void
+gtk_real_widget_realize (GtkWidget *widget)
+{
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+ if(widget->parent)
+ widget->window = widget->parent->window;
+ widget->style = gtk_style_attach (widget->style, widget->window);
+}
+
+/*****************************************
+ * gtk_real_widget_unrealize:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+static void
+gtk_real_widget_unrealize (GtkWidget *widget)
+{
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_REALIZED | GTK_MAPPED);
+
+ gtk_style_detach (widget->style);
+ if (!GTK_WIDGET_NO_WINDOW (widget))
+ {
+ gdk_window_set_user_data (widget->window, NULL);
+ gdk_window_destroy (widget->window);
+ }
+ widget->window = NULL;
+}
+
+/*****************************************
+ * gtk_real_widget_draw:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+static void
+gtk_real_widget_draw (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ GdkEventExpose event;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+ g_return_if_fail (area != NULL);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ event.type = GDK_EXPOSE;
+ event.window = widget->window;
+ event.area = *area;
+
+ gtk_widget_event (widget, (GdkEvent*) &event);
+ }
+}
+
+/*****************************************
+ * gtk_real_widget_queue_draw:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+static gint
+gtk_real_widget_queue_draw (GtkWidget *widget)
+{
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_REDRAW_PENDING);
+
+ gtk_object_unref (GTK_OBJECT (widget));
+ if (GTK_OBJECT_NEED_DESTROY (widget) &&
+ (GTK_OBJECT (widget)->ref_count == 0))
+ gtk_widget_destroy (widget);
+ else
+ gtk_widget_draw (widget, NULL);
+
+ return FALSE;
+}
+
+/*****************************************
+ * gtk_real_widget_queue_resize:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+static gint
+gtk_real_widget_queue_resize (GtkWidget *widget)
+{
+ GSList *resize_widgets;
+ GSList *tmp_list;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_RESIZE_PENDING);
+
+ gtk_object_unref (GTK_OBJECT (widget));
+ if (GTK_OBJECT_NEED_DESTROY (widget) &&
+ (GTK_OBJECT (widget)->ref_count == 0))
+ {
+ gtk_widget_destroy (widget);
+ }
+ else
+ {
+ gtk_container_need_resize (GTK_CONTAINER (widget));
+
+ if (!GTK_WIDGET_RESIZE_PENDING (widget))
+ {
+ resize_widgets = gtk_object_get_data (GTK_OBJECT (widget), resize_widgets_key);
+
+ tmp_list = resize_widgets;
+ while (tmp_list)
+ {
+ GtkWidget *child;
+
+ child = tmp_list->data;
+ tmp_list = tmp_list->next;
+
+ /* referencing needed? */
+ GTK_WIDGET_UNSET_FLAGS (child, GTK_RESIZE_NEEDED);
+ gtk_object_unref (GTK_OBJECT (child));
+ }
+
+ if (resize_widgets)
+ {
+ gtk_object_set_data (GTK_OBJECT (widget), resize_widgets_key, NULL);
+ g_slist_free (resize_widgets);
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+/*****************************************
+ * gtk_real_widget_size_allocate:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+static void
+gtk_real_widget_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ if (GTK_WIDGET_NO_WINDOW (widget) &&
+ GTK_WIDGET_MAPPED (widget) &&
+ ((widget->allocation.x != allocation->x) ||
+ (widget->allocation.y != allocation->y) ||
+ (widget->allocation.width != allocation->width) ||
+ (widget->allocation.height != allocation->height)) &&
+ (widget->allocation.width != 0) &&
+ (widget->allocation.height != 0))
+ gdk_window_clear_area (widget->window,
+ widget->allocation.x,
+ widget->allocation.y,
+ widget->allocation.width,
+ widget->allocation.height);
+
+ widget->allocation = *allocation;
+
+ if (GTK_WIDGET_REALIZED (widget) &&
+ !GTK_WIDGET_NO_WINDOW (widget))
+ gdk_window_move_resize (widget->window,
+ allocation->x, allocation->y,
+ allocation->width, allocation->height);
+}
+
+/*****************************************
+ * gtk_widget_peek_colormap:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+static GdkColormap*
+gtk_widget_peek_colormap ()
+{
+ if (colormap_stack)
+ return (GdkColormap*) colormap_stack->data;
+ return gtk_widget_get_default_colormap ();
+}
+
+/*****************************************
+ * gtk_widget_peek_visual:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+static GdkVisual*
+gtk_widget_peek_visual ()
+{
+ if (visual_stack)
+ return (GdkVisual*) visual_stack->data;
+ return gtk_widget_get_default_visual ();
+}
+
+/*****************************************
+ * gtk_widget_peek_style:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+static GtkStyle*
+gtk_widget_peek_style ()
+{
+ if (style_stack)
+ return (GtkStyle*) style_stack->data;
+ return gtk_widget_get_default_style ();
+}
+
+
+/*****************************************
+ * gtk_widget_set_parent_sensitive:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+static void
+gtk_widget_set_parent_sensitive (GtkWidget *widget,
+ gpointer client_data)
+{
+ GtkWidget *window;
+ gint *sensitive;
+
+ sensitive = client_data;
+ if (*sensitive)
+ {
+ GTK_WIDGET_SET_FLAGS (widget, GTK_PARENT_SENSITIVE);
+
+ if (GTK_IS_CONTAINER (widget) && GTK_WIDGET_SENSITIVE (widget))
+ gtk_container_foreach (GTK_CONTAINER (widget),
+ gtk_widget_set_parent_sensitive,
+ client_data);
+ }
+ else
+ {
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_PARENT_SENSITIVE);
+
+ if (GTK_WIDGET_HAS_FOCUS (widget))
+ {
+ window = gtk_widget_get_ancestor (widget, gtk_window_get_type ());
+ if (window)
+ gtk_window_set_focus (GTK_WINDOW (window), NULL);
+ }
+
+ if (GTK_IS_CONTAINER (widget))
+ gtk_container_foreach (GTK_CONTAINER (widget),
+ gtk_widget_set_parent_sensitive,
+ client_data);
+ }
+}
+
+/*****************************************
+ * gtk_widget_propagate_restore:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+static void
+gtk_widget_propagate_restore (GtkWidget *widget,
+ gpointer client_data)
+{
+ gtk_widget_restore_state (widget);
+}
+
+/*****************************************
+ * gtk_widget_propagate_state:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+static void
+gtk_widget_propagate_state (GtkWidget *widget,
+ gpointer client_data)
+{
+ GtkStateType *state;
+
+ state = (GtkStateType*) client_data;
+ gtk_widget_set_state (widget, *state);
+}
+
+/*****************************************
+ * gtk_widget_draw_children_recurse:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+static void
+gtk_widget_draw_children_recurse (GtkWidget *widget,
+ gpointer client_data)
+{
+ gtk_widget_draw (widget, NULL);
+ gtk_widget_draw_children (widget);
+}
+
+/*****************************************
+ * gtk_widget_set_style_internal:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+static void
+gtk_widget_set_style_internal (GtkWidget *widget,
+ GtkStyle *style)
+{
+ GtkRequisition old_requisition;
+
+ g_return_if_fail (widget != NULL);
+
+ if (widget->style != style)
+ {
+ if (GTK_WIDGET_REALIZED (widget))
+ gtk_style_detach (widget->style);
+
+ gtk_style_unref (widget->style);
+
+ widget->style = style;
+ gtk_style_ref (widget->style);
+
+ if (GTK_WIDGET_REALIZED (widget))
+ widget->style = gtk_style_attach (widget->style, widget->window);
+
+ if (widget->parent)
+ {
+ old_requisition = widget->requisition;
+ gtk_widget_size_request (widget, &widget->requisition);
+
+ if ((old_requisition.width != widget->requisition.width) ||
+ (old_requisition.height != widget->requisition.height))
+ gtk_widget_queue_resize (widget);
+ else if (GTK_WIDGET_DRAWABLE (widget))
+ gtk_widget_queue_draw (widget);
+ }
+ }
+}
+
+/*****************************************
+ * gtk_widget_set_style_recurse:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+static void
+gtk_widget_set_style_recurse (GtkWidget *widget,
+ gpointer client_data)
+{
+ GtkStyle *style;
+
+ style = gtk_rc_get_style (widget);
+ if (style != widget->style)
+ gtk_widget_set_style_internal (widget, style);
+
+ if (GTK_IS_CONTAINER (widget))
+ gtk_container_foreach (GTK_CONTAINER (widget),
+ gtk_widget_set_style_recurse,
+ NULL);
+}
+
+/*****************************************
+ * gtk_widget_aux_info_new:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+static GtkWidgetAuxInfo*
+gtk_widget_aux_info_new ()
+{
+ GtkWidgetAuxInfo *aux_info;
+
+ if (!aux_info_mem_chunk)
+ aux_info_mem_chunk = g_mem_chunk_new ("widget aux info mem chunk",
+ sizeof (GtkWidgetAuxInfo),
+ 1024, G_ALLOC_AND_FREE);
+
+ aux_info = g_chunk_new (GtkWidgetAuxInfo, aux_info_mem_chunk);
+
+ aux_info->x = -1;
+ aux_info->y = -1;
+ aux_info->width = 0;
+ aux_info->height = 0;
+
+ return aux_info;
+}
+
+/*****************************************
+ * gtk_widget_aux_info_destroy:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+
+static void
+gtk_widget_aux_info_destroy (GtkWidgetAuxInfo *aux_info)
+{
+ g_return_if_fail (aux_info != NULL);
+
+ g_mem_chunk_free (aux_info_mem_chunk, aux_info);
+}
+
+/*****************************************
+ * gtk_widget_shape_combine_mask:
+ * set a shape for this widgets' gdk window, this allows for
+ * transparent windows etc., see gdk_window_shape_combine_mask
+ * for more information
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+void
+gtk_widget_shape_combine_mask (GtkWidget *widget,
+ GdkBitmap *shape_mask,
+ gint offset_x,
+ gint offset_y)
+{
+ GtkWidgetShapeInfo* shape_info;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (shape_mask != NULL);
+ /* set_shape doesn't work on widgets without gdk window */
+ g_return_if_fail (!GTK_WIDGET_NO_WINDOW (widget));
+
+ /*
+ * remember shape mask for later gtk_widget_realize's
+ */
+ shape_info = gtk_object_get_data (GTK_OBJECT (widget), shape_info_key);
+ if (!shape_info)
+ {
+ shape_info = g_new (GtkWidgetShapeInfo, 1);
+ gtk_object_set_data (GTK_OBJECT (widget), shape_info_key, shape_info);
+ }
+ shape_info->shape_mask = shape_mask;
+ shape_info->offset_x = offset_x;
+ shape_info->offset_y = offset_y;
+ GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_SHAPE_MASK);
+
+ /*
+ * set shape if widget has a gdk window allready.
+ * otherwise the shape is scheduled to be set by gtk_widget_realize.
+ */
+ if (widget->window)
+ gdk_window_shape_combine_mask (widget->window, shape_mask,
+ offset_x, offset_y);
+
+}
+
+/*****************************************
+ * gtk_widget_dnd_drag_add:
+ * when you get a DRAG_ENTER event, you can use this
+ * to tell Gtk ofother widgets that are to be dragged as well
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+void
+gtk_widget_dnd_drag_add (GtkWidget *widget)
+{
+}
+
+/*****************************************
+ * gtk_widget_dnd_drag_set:
+ * these two functions enable drag and/or drop on a
+ * widget and also let Gtk know what data types will be accepted
+ * use MIME type naming,plus tacking "URL:" on the front for link
+ * dragging
+ *
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+void
+gtk_widget_dnd_drag_set (GtkWidget *widget,
+ guint8 drag_enable,
+ gchar **type_accept_list,
+ guint numtypes)
+{
+ g_return_if_fail(widget != NULL);
+
+ if (!widget->window)
+ gtk_widget_realize (widget);
+
+ g_return_if_fail (widget->window != NULL);
+ gdk_window_dnd_drag_set (widget->window,
+ drag_enable,
+ type_accept_list,
+ numtypes);
+}
+
+/*****************************************
+ * gtk_widget_dnd_drop_set:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+void
+gtk_widget_dnd_drop_set (GtkWidget *widget,
+ guint8 drop_enable,
+ gchar **type_accept_list,
+ guint numtypes,
+ guint8 is_destructive_operation)
+{
+ g_return_if_fail(widget != NULL);
+
+ if (!widget->window)
+ gtk_widget_realize (widget);
+
+ g_return_if_fail (widget->window != NULL);
+ gdk_window_dnd_drop_set (widget->window,
+ drop_enable,
+ type_accept_list,
+ numtypes,
+ is_destructive_operation);
+}
+
+/*****************************************
+ * gtk_widget_dnd_data_set:
+ *
+ * arguments:
+ *
+ * results:
+ *****************************************/
+void
+gtk_widget_dnd_data_set (GtkWidget *widget,
+ GdkEvent *event,
+ gpointer data,
+ gulong data_numbytes)
+{
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (widget->window != NULL);
+
+ gdk_window_dnd_data_set (widget->window, event, data, data_numbytes);
+}
+
diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h
new file mode 100644
index 000000000..51ea9940c
--- /dev/null
+++ b/gtk/gtkwidget.h
@@ -0,0 +1,505 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_WIDGET_H__
+#define __GTK_WIDGET_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkaccelerator.h>
+#include <gtk/gtkobject.h>
+#include <gtk/gtkstyle.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* The flags that are used in the flags member of the GtkObject
+ * structure.
+ */
+enum
+{
+ GTK_VISIBLE = 1 << 3,
+ GTK_MAPPED = 1 << 4,
+ GTK_UNMAPPED = 1 << 5,
+ GTK_REALIZED = 1 << 6,
+ GTK_SENSITIVE = 1 << 7,
+ GTK_PARENT_SENSITIVE = 1 << 8,
+ GTK_NO_WINDOW = 1 << 9,
+ GTK_HAS_FOCUS = 1 << 10,
+ GTK_CAN_FOCUS = 1 << 11,
+ GTK_HAS_DEFAULT = 1 << 12,
+ GTK_CAN_DEFAULT = 1 << 13,
+ GTK_PROPAGATE_STATE = 1 << 14,
+ GTK_ANCHORED = 1 << 15,
+ GTK_BASIC = 1 << 16,
+ GTK_USER_STYLE = 1 << 17,
+ GTK_GRAB_ALL = 1 << 18,
+ GTK_REDRAW_PENDING = 1 << 19,
+ GTK_RESIZE_PENDING = 1 << 20,
+ GTK_RESIZE_NEEDED = 1 << 21,
+ GTK_HAS_SHAPE_MASK = 1 << 22
+};
+
+
+/* Macro for casting a pointer to a GtkWidget pointer.
+ */
+#define GTK_WIDGET(obj) GTK_CHECK_CAST (obj, gtk_widget_get_type (), GtkWidget)
+
+/* Macro for casting the "class" field of an object to
+ * a GtkWidgetClass pointer.
+ */
+#define GTK_WIDGET_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_widget_get_type (), GtkWidgetClass)
+
+/* Macros for extracting various fields from GtkWidget and
+ * GtkWidgetClass structures.
+ */
+#define GTK_WIDGET_TYPE(obj) (GTK_OBJECT_TYPE (obj))
+#define GTK_WIDGET_STATE(obj) (GTK_WIDGET (obj)->state)
+#define GTK_WIDGET_SAVED_STATE(obj) (GTK_WIDGET (obj)->saved_state)
+#define GTK_WIDGET_VISIBLE(obj) (GTK_OBJECT_FLAGS (obj) & GTK_VISIBLE)
+#define GTK_WIDGET_MAPPED(obj) (GTK_OBJECT_FLAGS (obj) & GTK_MAPPED)
+#define GTK_WIDGET_UNMAPPED(obj) (GTK_OBJECT_FLAGS (obj) & GTK_UNMAPPED)
+#define GTK_WIDGET_REALIZED(obj) (GTK_OBJECT_FLAGS (obj) & GTK_REALIZED)
+#define GTK_WIDGET_SENSITIVE(obj) (GTK_OBJECT_FLAGS (obj) & GTK_SENSITIVE)
+#define GTK_WIDGET_PARENT_SENSITIVE(obj) (GTK_OBJECT_FLAGS (obj) & GTK_PARENT_SENSITIVE)
+#define GTK_WIDGET_IS_SENSITIVE(obj) ((GTK_WIDGET_SENSITIVE (obj) && \
+ GTK_WIDGET_PARENT_SENSITIVE (obj)) != 0)
+#define GTK_WIDGET_NO_WINDOW(obj) (GTK_OBJECT_FLAGS (obj) & GTK_NO_WINDOW)
+#define GTK_WIDGET_HAS_FOCUS(obj) (GTK_OBJECT_FLAGS (obj) & GTK_HAS_FOCUS)
+#define GTK_WIDGET_CAN_FOCUS(obj) (GTK_OBJECT_FLAGS (obj) & GTK_CAN_FOCUS)
+#define GTK_WIDGET_HAS_DEFAULT(obj) (GTK_OBJECT_FLAGS (obj) & GTK_HAS_DEFAULT)
+#define GTK_WIDGET_CAN_DEFAULT(obj) (GTK_OBJECT_FLAGS (obj) & GTK_CAN_DEFAULT)
+#define GTK_WIDGET_PROPAGATE_STATE(obj) (GTK_OBJECT_FLAGS (obj) & GTK_PROPAGATE_STATE)
+#define GTK_WIDGET_DRAWABLE(obj) (GTK_WIDGET_VISIBLE (obj) && GTK_WIDGET_MAPPED (obj))
+#define GTK_WIDGET_ANCHORED(obj) (GTK_OBJECT_FLAGS (obj) & GTK_ANCHORED)
+#define GTK_WIDGET_BASIC(obj) (GTK_OBJECT_FLAGS (obj) & GTK_BASIC)
+#define GTK_WIDGET_USER_STYLE(obj) (GTK_OBJECT_FLAGS (obj) & GTK_USER_STYLE)
+#define GTK_WIDGET_GRAB_ALL(obj) (GTK_OBJECT_FLAGS (obj) & GTK_GRAB_ALL)
+#define GTK_WIDGET_REDRAW_PENDING(obj) (GTK_OBJECT_FLAGS (obj) & GTK_REDRAW_PENDING)
+#define GTK_WIDGET_RESIZE_PENDING(obj) (GTK_OBJECT_FLAGS (obj) & GTK_RESIZE_PENDING)
+#define GTK_WIDGET_RESIZE_NEEDED(obj) (GTK_OBJECT_FLAGS (obj) & GTK_RESIZE_NEEDED)
+#define GTK_WIDGET_HAS_SHAPE_MASK(obj) (GTK_OBJECT_FLAGS (obj) & GTK_HAS_SHAPE_MASK)
+
+#define GTK_TYPE_WIDGET (gtk_widget_get_type ())
+
+/* Macro for testing whether "obj" is of type GtkWidget.
+ */
+#define GTK_IS_WIDGET(obj) GTK_CHECK_TYPE (obj, GTK_TYPE_WIDGET)
+
+/* Macros for setting and clearing widget flags. Notice
+ * that these are only wrappers for the macros which
+ * set and clear the flags in the GtkObject structure.
+ */
+#define GTK_WIDGET_SET_FLAGS(obj,flag) (GTK_OBJECT_SET_FLAGS (obj, flag))
+#define GTK_WIDGET_UNSET_FLAGS(obj,flag) (GTK_OBJECT_UNSET_FLAGS (obj, flag))
+
+
+
+typedef struct _GtkRequisition GtkRequisition;
+typedef struct _GtkAllocation GtkAllocation;
+typedef struct _GtkSelectionData GtkSelectionData;
+typedef struct _GtkWidget GtkWidget;
+typedef struct _GtkWidgetClass GtkWidgetClass;
+typedef struct _GtkWidgetAuxInfo GtkWidgetAuxInfo;
+typedef struct _GtkWidgetShapeInfo GtkWidgetShapeInfo;
+
+typedef void (*GtkCallback) (GtkWidget *widget,
+ gpointer data);
+
+/* A requisition is a desired amount of space which a
+ * widget may request.
+ */
+struct _GtkRequisition
+{
+ guint16 width;
+ guint16 height;
+};
+
+/* An allocation is a size and position. Where a widget
+ * can ask for a desired size, it is actually given
+ * this amount of space at the specified position.
+ */
+struct _GtkAllocation
+{
+ gint16 x;
+ gint16 y;
+ guint16 width;
+ guint16 height;
+};
+
+/* The contents of a selection are returned in a GtkSelectionData
+ structure. selection/target identify the request.
+ type specifies the type of the return; if length < 0, and
+ the data should be ignored. This structure has object semantics -
+ no fields should be modified directly, they should not be created
+ directly, and pointers to them should not be stored beyond the duration of
+ a callback. (If the last is changed, we'll need to add reference
+ counting) */
+
+struct _GtkSelectionData
+{
+ GdkAtom selection;
+ GdkAtom target;
+ GdkAtom type;
+ gint format;
+ guchar *data;
+ gint length;
+};
+
+/* The widget is the base of the tree for displayable objects.
+ * (A displayable object is one which takes up some amount
+ * of screen real estate). It provides a common base and interface
+ * which actual widgets must adhere to.
+ */
+struct _GtkWidget
+{
+ /* The object structure needs to be the first
+ * element in the widget structure in order for
+ * the object mechanism to work correctly. This
+ * allows a GtkWidget pointer to be cast to a
+ * GtkObject pointer.
+ */
+ GtkObject object;
+
+ /* The state of the widget. There are actually only
+ * 5 widget states (defined in "gtkenums.h").
+ */
+ guint8 state;
+
+ /* The saved state of the widget. When a widgets state
+ * is changed via "gtk_widget_set_state" the old state
+ * is kept around in this field. The state may be
+ * restored using "gtk_widget_restore_state".
+ */
+ guint8 saved_state;
+
+ /* The widgets name. If the widget does not have a name
+ * (the name is NULL), then its name (as returned by
+ * "gtk_widget_get_name") is its classes name.
+ * The widget name is used to determine the style to
+ * use for a widget.
+ */
+ gchar *name;
+
+ /* The style for the widget. The style contains the
+ * colors the widget should be drawn in for each state
+ * along with graphics contexts used to draw with and
+ * the font to use for text.
+ */
+ GtkStyle *style;
+
+ /* The widgets desired size.
+ */
+ GtkRequisition requisition;
+
+ /* The widgets allocated size.
+ */
+ GtkAllocation allocation;
+
+ /* The widgets window or its parent window if it does
+ * not have a window. (Which will be indicated by the
+ * GTK_NO_WINDOW flag being set).
+ */
+ GdkWindow *window;
+
+ /* The widgets parent.
+ */
+ GtkWidget *parent;
+};
+
+struct _GtkWidgetClass
+{
+ /* The object class structure needs to be the first
+ * element in the widget class structure in order for
+ * the class mechanism to work correctly. This allows a
+ * GtkWidgetClass pointer to be cast to a GtkObjectClass
+ * pointer.
+ */
+ GtkObjectClass parent_class;
+
+ /* The signal to emit when an object of this class is activated.
+ * This is used when activating the current focus widget and
+ * the default widget.
+ */
+ gint activate_signal;
+
+ /* basics */
+ void (* show) (GtkWidget *widget);
+ void (* hide) (GtkWidget *widget);
+ void (* map) (GtkWidget *widget);
+ void (* unmap) (GtkWidget *widget);
+ void (* realize) (GtkWidget *widget);
+ void (* unrealize) (GtkWidget *widget);
+ void (* draw) (GtkWidget *widget,
+ GdkRectangle *area);
+ void (* draw_focus) (GtkWidget *widget);
+ void (* draw_default) (GtkWidget *widget);
+ void (* size_request) (GtkWidget *widget,
+ GtkRequisition *requisition);
+ void (* size_allocate) (GtkWidget *widget,
+ GtkAllocation *allocation);
+ void (* state_changed) (GtkWidget *widget);
+
+ /* accelerators */
+ gint (* install_accelerator) (GtkWidget *widget,
+ const gchar *signal_name,
+ gchar key,
+ guint8 modifiers);
+ void (* remove_accelerator) (GtkWidget *widget,
+ const gchar *signal_name);
+
+ /* events */
+ gint (* event) (GtkWidget *widget,
+ GdkEvent *event);
+ gint (* button_press_event) (GtkWidget *widget,
+ GdkEventButton *event);
+ gint (* button_release_event) (GtkWidget *widget,
+ GdkEventButton *event);
+ gint (* motion_notify_event) (GtkWidget *widget,
+ GdkEventMotion *event);
+ gint (* delete_event) (GtkWidget *widget,
+ GdkEventAny *event);
+ gint (* destroy_event) (GtkWidget *widget,
+ GdkEventAny *event);
+ gint (* expose_event) (GtkWidget *widget,
+ GdkEventExpose *event);
+ gint (* key_press_event) (GtkWidget *widget,
+ GdkEventKey *event);
+ gint (* key_release_event) (GtkWidget *widget,
+ GdkEventKey *event);
+ gint (* enter_notify_event) (GtkWidget *widget,
+ GdkEventCrossing *event);
+ gint (* leave_notify_event) (GtkWidget *widget,
+ GdkEventCrossing *event);
+ gint (* configure_event) (GtkWidget *widget,
+ GdkEventConfigure *event);
+ gint (* focus_in_event) (GtkWidget *widget,
+ GdkEventFocus *event);
+ gint (* focus_out_event) (GtkWidget *widget,
+ GdkEventFocus *event);
+ gint (* map_event) (GtkWidget *widget,
+ GdkEventAny *event);
+ gint (* unmap_event) (GtkWidget *widget,
+ GdkEventAny *event);
+ gint (* property_notify_event) (GtkWidget *widget,
+ GdkEventProperty *event);
+ gint (* selection_clear_event) (GtkWidget *widget,
+ GdkEventSelection *event);
+ gint (* selection_request_event) (GtkWidget *widget,
+ GdkEventSelection *event);
+ gint (* selection_notify_event) (GtkWidget *widget,
+ GdkEventSelection *event);
+ gint (* proximity_in_event) (GtkWidget *widget,
+ GdkEventProximity *event);
+ gint (* proximity_out_event) (GtkWidget *widget,
+ GdkEventProximity *event);
+ gint (* drag_begin_event) (GtkWidget *widget,
+ GdkEventDragBegin *event);
+ gint (* drag_request_event) (GtkWidget *widget,
+ GdkEventDragRequest *event);
+ gint (* drop_enter_event) (GtkWidget *widget,
+ GdkEventDropEnter *event);
+ gint (* drop_leave_event) (GtkWidget *widget,
+ GdkEventDropLeave *event);
+ gint (* drop_data_available_event) (GtkWidget *widget,
+ GdkEventDropDataAvailable *event);
+ gint (* other_event) (GtkWidget *widget,
+ GdkEventOther *event);
+
+ /* selection */
+ void (* selection_received) (GtkWidget *widget,
+ GtkSelectionData *selection_data);
+
+ gint (* client_event) (GtkWidget *widget,
+ GdkEventClient *event);
+};
+
+struct _GtkWidgetAuxInfo
+{
+ gint16 x;
+ gint16 y;
+ guint16 width;
+ guint16 height;
+};
+
+struct _GtkWidgetShapeInfo
+{
+ gint16 offset_x;
+ gint16 offset_y;
+ GdkBitmap *shape_mask;
+};
+
+
+guint gtk_widget_get_type (void);
+GtkWidget* gtk_widget_new (guint type,
+ ...);
+GtkWidget* gtk_widget_newv (guint type,
+ gint nargs,
+ GtkArg *args);
+void gtk_widget_set (GtkWidget *widget,
+ ...);
+void gtk_widget_setv (GtkWidget *widget,
+ gint nargs,
+ GtkArg *args);
+void gtk_widget_destroy (GtkWidget *widget);
+void gtk_widget_unparent (GtkWidget *widget);
+void gtk_widget_show (GtkWidget *widget);
+void gtk_widget_hide (GtkWidget *widget);
+void gtk_widget_map (GtkWidget *widget);
+void gtk_widget_unmap (GtkWidget *widget);
+void gtk_widget_realize (GtkWidget *widget);
+void gtk_widget_unrealize (GtkWidget *widget);
+void gtk_widget_queue_draw (GtkWidget *widget);
+void gtk_widget_queue_resize (GtkWidget *widget);
+void gtk_widget_draw (GtkWidget *widget,
+ GdkRectangle *area);
+void gtk_widget_draw_focus (GtkWidget *widget);
+void gtk_widget_draw_default (GtkWidget *widget);
+void gtk_widget_draw_children (GtkWidget *widget);
+void gtk_widget_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+void gtk_widget_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+void gtk_widget_install_accelerator (GtkWidget *widget,
+ GtkAcceleratorTable *table,
+ const gchar *signal_name,
+ gchar key,
+ guint8 modifiers);
+void gtk_widget_remove_accelerator (GtkWidget *widget,
+ GtkAcceleratorTable *table,
+ const gchar *signal_name);
+gint gtk_widget_event (GtkWidget *widget,
+ GdkEvent *event);
+
+void gtk_widget_activate (GtkWidget *widget);
+void gtk_widget_reparent (GtkWidget *widget,
+ GtkWidget *new_parent);
+void gtk_widget_popup (GtkWidget *widget,
+ gint x,
+ gint y);
+gint gtk_widget_intersect (GtkWidget *widget,
+ GdkRectangle *area,
+ GdkRectangle *intersection);
+gint gtk_widget_basic (GtkWidget *widget);
+
+void gtk_widget_grab_focus (GtkWidget *widget);
+void gtk_widget_grab_default (GtkWidget *widget);
+
+void gtk_widget_restore_state (GtkWidget *widget);
+void gtk_widget_set_name (GtkWidget *widget,
+ const gchar *name);
+gchar* gtk_widget_get_name (GtkWidget *widget);
+void gtk_widget_set_state (GtkWidget *widget,
+ GtkStateType state);
+void gtk_widget_set_sensitive (GtkWidget *widget,
+ gint sensitive);
+void gtk_widget_set_parent (GtkWidget *widget,
+ GtkWidget *parent);
+void gtk_widget_set_style (GtkWidget *widget,
+ GtkStyle *style);
+void gtk_widget_set_uposition (GtkWidget *widget,
+ gint x,
+ gint y);
+void gtk_widget_set_usize (GtkWidget *widget,
+ gint width,
+ gint height);
+void gtk_widget_set_events (GtkWidget *widget,
+ gint events);
+void gtk_widget_set_extension_events (GtkWidget *widget,
+ GdkExtensionMode mode);
+
+GtkWidget* gtk_widget_get_toplevel (GtkWidget *widget);
+GtkWidget* gtk_widget_get_ancestor (GtkWidget *widget,
+ gint type);
+GdkColormap* gtk_widget_get_colormap (GtkWidget *widget);
+GdkVisual* gtk_widget_get_visual (GtkWidget *widget);
+GtkStyle* gtk_widget_get_style (GtkWidget *widget);
+gint gtk_widget_get_events (GtkWidget *widget);
+GdkExtensionMode gtk_widget_get_extension_events (GtkWidget *widget);
+void gtk_widget_get_pointer (GtkWidget *widget,
+ gint *x,
+ gint *y);
+
+gint gtk_widget_is_ancestor (GtkWidget *widget,
+ GtkWidget *ancestor);
+gint gtk_widget_is_child (GtkWidget *widget,
+ GtkWidget *child);
+
+void gtk_widget_push_colormap (GdkColormap *cmap);
+void gtk_widget_push_visual (GdkVisual *visual);
+void gtk_widget_push_style (GtkStyle *style);
+
+void gtk_widget_pop_colormap (void);
+void gtk_widget_pop_visual (void);
+void gtk_widget_pop_style (void);
+
+void gtk_widget_set_default_colormap (GdkColormap *colormap);
+void gtk_widget_set_default_visual (GdkVisual *visual);
+void gtk_widget_set_default_style (GtkStyle *style);
+/* Tells other Gtk applications to use the same default style */
+void gtk_widget_propagate_default_style(void);
+GdkColormap* gtk_widget_get_default_colormap (void);
+GdkVisual* gtk_widget_get_default_visual (void);
+GtkStyle* gtk_widget_get_default_style (void);
+
+/*
+ * see gdk_window_shape_combine_mask
+ */
+void gtk_widget_shape_combine_mask (GtkWidget *widget,
+ GdkBitmap *shape_mask,
+ gint offset_x,
+ gint offset_y);
+
+/*
+ * When you get a drag_enter event, you can use this to tell Gtk of other
+ * items that are to be dragged as well...
+ */
+void gtk_widget_dnd_drag_add (GtkWidget *widget);
+
+/*
+ * These two functions enable drag and/or drop on a widget,
+ * and also let Gtk know what data types will be accepted (use MIME type
+ * naming, plus tacking "URL:" on the front for link dragging)
+ */
+void gtk_widget_dnd_drag_set (GtkWidget *widget,
+ guint8 drag_enable,
+ gchar **type_accept_list,
+ guint numtypes);
+void gtk_widget_dnd_drop_set (GtkWidget *widget,
+ guint8 drop_enable,
+ gchar **type_accept_list,
+ guint numtypes,
+ guint8 is_destructive_operation);
+
+/*
+ * used to reply to a DRAG_REQUEST event - if you don't want to
+ * give the data then pass in NULL for it
+ */
+void gtk_widget_dnd_data_set (GtkWidget *widget,
+ GdkEvent *event,
+ gpointer data,
+ gulong data_numbytes);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_WIDGET_H__ */
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
new file mode 100644
index 000000000..e97708a96
--- /dev/null
+++ b/gtk/gtkwindow.c
@@ -0,0 +1,1195 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <string.h>
+#include <limits.h>
+#include "gdk/gdk.h"
+#include "gdk/gdkkeysyms.h"
+#include "gdk/gdkx.h"
+#include "gtksignal.h"
+#include "gtkwindow.h"
+
+enum {
+ MOVE_RESIZE,
+ LAST_SIGNAL
+};
+
+
+typedef gint (*GtkWindowSignal1) (GtkObject *object,
+ gpointer arg1,
+ gpointer arg2,
+ gint arg3,
+ gint arg4,
+ gpointer data);
+
+
+static void gtk_window_marshal_signal_1 (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args);
+
+static void gtk_window_class_init (GtkWindowClass *klass);
+static void gtk_window_init (GtkWindow *window);
+static void gtk_window_arg (GtkWindow *window,
+ GtkArg *arg);
+static void gtk_window_destroy (GtkObject *object);
+static void gtk_window_show (GtkWidget *widget);
+static void gtk_window_hide (GtkWidget *widget);
+static void gtk_window_map (GtkWidget *widget);
+static void gtk_window_unmap (GtkWidget *widget);
+static void gtk_window_realize (GtkWidget *widget);
+static void gtk_window_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void gtk_window_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static gint gtk_window_expose_event (GtkWidget *widget,
+ GdkEventExpose *event);
+static gint gtk_window_configure_event (GtkWidget *widget,
+ GdkEventConfigure *event);
+static gint gtk_window_key_press_event (GtkWidget *widget,
+ GdkEventKey *event);
+static gint gtk_window_key_release_event (GtkWidget *widget,
+ GdkEventKey *event);
+static gint gtk_window_enter_notify_event (GtkWidget *widget,
+ GdkEventCrossing *event);
+static gint gtk_window_leave_notify_event (GtkWidget *widget,
+ GdkEventCrossing *event);
+static gint gtk_window_focus_in_event (GtkWidget *widget,
+ GdkEventFocus *event);
+static gint gtk_window_focus_out_event (GtkWidget *widget,
+ GdkEventFocus *event);
+static gint gtk_window_client_event (GtkWidget *widget,
+ GdkEvent *event);
+static gint gtk_window_need_resize (GtkContainer *container);
+static gint gtk_real_window_move_resize (GtkWindow *window,
+ gint *x,
+ gint *y,
+ gint width,
+ gint height);
+static gint gtk_window_move_resize (GtkWidget *widget);
+static void gtk_window_set_hints (GtkWidget *widget,
+ GtkRequisition *requisition);
+static gint gtk_window_check_accelerator (GtkWindow *window,
+ gint key,
+ guint mods);
+
+
+static GtkBinClass *parent_class = NULL;
+static gint window_signals[LAST_SIGNAL] = { 0 };
+
+
+guint
+gtk_window_get_type ()
+{
+ static guint window_type = 0;
+
+ if (!window_type)
+ {
+ GtkTypeInfo window_info =
+ {
+ "GtkWindow",
+ sizeof (GtkWindow),
+ sizeof (GtkWindowClass),
+ (GtkClassInitFunc) gtk_window_class_init,
+ (GtkObjectInitFunc) gtk_window_init,
+ (GtkArgFunc) gtk_window_arg,
+ };
+
+ window_type = gtk_type_unique (gtk_bin_get_type (), &window_info);
+ }
+
+ return window_type;
+}
+
+static void
+gtk_window_class_init (GtkWindowClass *klass)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+ GtkContainerClass *container_class;
+
+ object_class = (GtkObjectClass*) klass;
+ widget_class = (GtkWidgetClass*) klass;
+ container_class = (GtkContainerClass*) klass;
+
+ parent_class = gtk_type_class (gtk_bin_get_type ());
+
+ gtk_object_add_arg_type ("GtkWindow::type", GTK_TYPE_WINDOW_TYPE);
+ gtk_object_add_arg_type ("GtkWindow::title", GTK_TYPE_STRING);
+ gtk_object_add_arg_type ("GtkWindow::auto_shrink", GTK_TYPE_BOOL);
+ gtk_object_add_arg_type ("GtkWindow::allow_shrink", GTK_TYPE_BOOL);
+ gtk_object_add_arg_type ("GtkWindow::allow_grow", GTK_TYPE_BOOL);
+
+ window_signals[MOVE_RESIZE] =
+ gtk_signal_new ("move_resize",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWindowClass, move_resize),
+ gtk_window_marshal_signal_1,
+ GTK_TYPE_BOOL, 4,
+ GTK_TYPE_POINTER, GTK_TYPE_POINTER,
+ GTK_TYPE_INT, GTK_TYPE_INT);
+
+ gtk_object_class_add_signals (object_class, window_signals, LAST_SIGNAL);
+
+ object_class->destroy = gtk_window_destroy;
+
+ widget_class->show = gtk_window_show;
+ widget_class->hide = gtk_window_hide;
+ widget_class->map = gtk_window_map;
+ widget_class->unmap = gtk_window_unmap;
+ widget_class->realize = gtk_window_realize;
+ widget_class->size_request = gtk_window_size_request;
+ widget_class->size_allocate = gtk_window_size_allocate;
+ widget_class->expose_event = gtk_window_expose_event;
+ widget_class->configure_event = gtk_window_configure_event;
+ widget_class->key_press_event = gtk_window_key_press_event;
+ widget_class->key_release_event = gtk_window_key_release_event;
+ widget_class->enter_notify_event = gtk_window_enter_notify_event;
+ widget_class->leave_notify_event = gtk_window_leave_notify_event;
+ widget_class->focus_in_event = gtk_window_focus_in_event;
+ widget_class->focus_out_event = gtk_window_focus_out_event;
+ widget_class->client_event = gtk_window_client_event;
+
+ container_class->need_resize = gtk_window_need_resize;
+
+ klass->move_resize = gtk_real_window_move_resize;
+}
+
+static void
+gtk_window_init (GtkWindow *window)
+{
+ GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
+ GTK_WIDGET_SET_FLAGS (window, GTK_ANCHORED);
+
+ window->title = NULL;
+ window->wmclass_name = NULL;
+ window->wmclass_class = NULL;
+ window->type = GTK_WINDOW_TOPLEVEL;
+ window->accelerator_tables = NULL;
+ window->focus_widget = NULL;
+ window->default_widget = NULL;
+ window->resize_count = 0;
+ window->need_resize = FALSE;
+ window->allow_shrink = FALSE;
+ window->allow_grow = TRUE;
+ window->auto_shrink = FALSE;
+ window->handling_resize = FALSE;
+ window->position = GTK_WIN_POS_NONE;
+ window->use_uposition = TRUE;
+}
+
+static void
+gtk_window_arg (GtkWindow *window,
+ GtkArg *arg)
+{
+ if (strcmp (arg->name, "type") == 0)
+ {
+ window->type = GTK_VALUE_ENUM(*arg);
+ }
+ else if (strcmp (arg->name, "title") == 0)
+ {
+ gtk_window_set_title (window, GTK_VALUE_STRING(*arg));
+ }
+ else if (strcmp (arg->name, "auto_shrink") == 0)
+ {
+ window->auto_shrink = (GTK_VALUE_BOOL(*arg) != FALSE);
+ }
+ else if (strcmp (arg->name, "allow_shrink") == 0)
+ {
+ window->allow_shrink = (GTK_VALUE_BOOL(*arg) != FALSE);
+ }
+ else if (strcmp (arg->name, "allow_grow") == 0)
+ {
+ window->allow_grow = (GTK_VALUE_BOOL(*arg) != FALSE);
+ }
+}
+
+GtkWidget*
+gtk_window_new (GtkWindowType type)
+{
+ GtkWindow *window;
+
+ window = gtk_type_new (gtk_window_get_type ());
+
+ window->type = type;
+
+ return GTK_WIDGET (window);
+}
+
+void
+gtk_window_set_title (GtkWindow *window,
+ const gchar *title)
+{
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (GTK_IS_WINDOW (window));
+
+ if (window->title)
+ g_free (window->title);
+ window->title = g_strdup (title);
+
+ if (GTK_WIDGET_REALIZED (window))
+ gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
+}
+
+void
+gtk_window_set_wmclass (GtkWindow *window,
+ gchar *wmclass_name,
+ gchar *wmclass_class)
+{
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (GTK_IS_WINDOW (window));
+
+ if (window->wmclass_name)
+ g_free (window->wmclass_name);
+ window->wmclass_name = g_strdup (wmclass_name);
+
+ if (window->wmclass_class)
+ g_free (window->wmclass_class);
+ window->wmclass_class = g_strdup (wmclass_class);
+
+ if (GTK_WIDGET_REALIZED (window))
+ g_warning ("shouldn't set wmclass after window is realized!\n");
+}
+
+void
+gtk_window_set_focus (GtkWindow *window,
+ GtkWidget *focus)
+{
+ GdkEventFocus event;
+
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (GTK_IS_WINDOW (window));
+
+ if (focus && !GTK_WIDGET_CAN_FOCUS (focus))
+ return;
+
+ if (window->focus_widget != focus)
+ {
+ if (window->focus_widget)
+ {
+ event.type = GDK_FOCUS_CHANGE;
+ event.window = window->focus_widget->window;
+ event.in = FALSE;
+
+ gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
+ }
+
+ window->focus_widget = focus;
+
+ if (window->focus_widget)
+ {
+ event.type = GDK_FOCUS_CHANGE;
+ event.window = window->focus_widget->window;
+ event.in = TRUE;
+
+ gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
+ }
+ }
+}
+
+void
+gtk_window_set_default (GtkWindow *window,
+ GtkWidget *defaultw)
+{
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (GTK_IS_WINDOW (window));
+ g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (defaultw));
+
+ if (window->default_widget != defaultw)
+ {
+ if (window->default_widget)
+ {
+ GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
+ gtk_widget_draw_default (window->default_widget);
+ }
+
+ window->default_widget = defaultw;
+
+ if (window->default_widget)
+ {
+ GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
+ gtk_widget_draw_default (window->default_widget);
+ }
+ }
+}
+
+void
+gtk_window_set_policy (GtkWindow *window,
+ gint allow_shrink,
+ gint allow_grow,
+ gint auto_shrink)
+{
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (GTK_IS_WINDOW (window));
+
+ window->allow_shrink = (allow_shrink != FALSE);
+ window->allow_grow = (allow_grow != FALSE);
+ window->auto_shrink = (auto_shrink != FALSE);
+}
+
+void
+gtk_window_add_accelerator_table (GtkWindow *window,
+ GtkAcceleratorTable *table)
+{
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (GTK_IS_WINDOW (window));
+
+ gtk_accelerator_table_ref (table);
+ window->accelerator_tables = g_list_prepend (window->accelerator_tables, table);
+}
+
+void
+gtk_window_remove_accelerator_table (GtkWindow *window,
+ GtkAcceleratorTable *table)
+{
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (GTK_IS_WINDOW (window));
+
+ window->accelerator_tables = g_list_remove (window->accelerator_tables, table);
+ gtk_accelerator_table_unref (table);
+}
+
+void
+gtk_window_position (GtkWindow *window,
+ GtkWindowPosition position)
+{
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (GTK_IS_WINDOW (window));
+
+ window->position = position;
+}
+
+static void
+gtk_window_marshal_signal_1 (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args)
+{
+ GtkWindowSignal1 rfunc;
+ gint *return_val;
+
+ rfunc = (GtkWindowSignal1) func;
+ return_val = GTK_RETLOC_BOOL (args[4]);
+
+ *return_val = (* rfunc) (object,
+ GTK_VALUE_POINTER (args[0]),
+ GTK_VALUE_POINTER (args[1]),
+ GTK_VALUE_INT (args[2]),
+ GTK_VALUE_INT (args[3]),
+ func_data);
+}
+
+static void
+gtk_window_destroy (GtkObject *object)
+{
+ GtkWindow *window;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_WINDOW (object));
+
+ window = GTK_WINDOW (object);
+ g_free (window->title);
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+static void
+gtk_window_show (GtkWidget *widget)
+{
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_WINDOW (widget));
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
+ gtk_widget_map (widget);
+}
+
+static void
+gtk_window_hide (GtkWidget *widget)
+{
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_WINDOW (widget));
+
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
+ gtk_widget_unmap (widget);
+}
+
+static void
+gtk_window_map (GtkWidget *widget)
+{
+ GtkWindow *window;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_WINDOW (widget));
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_UNMAPPED);
+
+ gtk_window_move_resize (widget);
+ window = GTK_WINDOW (widget);
+
+ if (window->bin.child &&
+ GTK_WIDGET_VISIBLE (window->bin.child) &&
+ !GTK_WIDGET_MAPPED (window->bin.child))
+ gtk_widget_map (window->bin.child);
+
+ gtk_window_set_hints (widget, &widget->requisition);
+ gdk_window_show (widget->window);
+}
+
+static void
+gtk_window_unmap (GtkWidget *widget)
+{
+ GtkWindow *window;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_WINDOW (widget));
+
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
+ GTK_WIDGET_SET_FLAGS (widget, GTK_UNMAPPED);
+ gdk_window_hide (widget->window);
+
+ window = GTK_WINDOW (widget);
+ window->use_uposition = TRUE;
+}
+
+static void
+gtk_window_realize (GtkWidget *widget)
+{
+ GtkWindow *window;
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_WINDOW (widget));
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+ window = GTK_WINDOW (widget);
+
+ switch (window->type)
+ {
+ case GTK_WINDOW_TOPLEVEL:
+ attributes.window_type = GDK_WINDOW_TOPLEVEL;
+ break;
+ case GTK_WINDOW_DIALOG:
+ attributes.window_type = GDK_WINDOW_DIALOG;
+ break;
+ case GTK_WINDOW_POPUP:
+ attributes.window_type = GDK_WINDOW_TEMP;
+ break;
+ }
+
+ attributes.title = window->title;
+ attributes.wmclass_name = window->wmclass_name;
+ attributes.wmclass_class = window->wmclass_class;
+ attributes.width = widget->allocation.width;
+ attributes.height = widget->allocation.height;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
+ attributes.event_mask = gtk_widget_get_events (widget);
+ attributes.event_mask |= (GDK_EXPOSURE_MASK |
+ GDK_KEY_PRESS_MASK |
+ GDK_ENTER_NOTIFY_MASK |
+ GDK_LEAVE_NOTIFY_MASK |
+ GDK_FOCUS_CHANGE_MASK |
+ GDK_STRUCTURE_MASK);
+
+ attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
+ attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
+ attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
+
+ widget->window = gdk_window_new (NULL, &attributes, attributes_mask);
+ gdk_window_set_user_data (widget->window, window);
+
+ widget->style = gtk_style_attach (widget->style, widget->window);
+ gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
+}
+
+static void
+gtk_window_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkWindow *window;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_WINDOW (widget));
+ g_return_if_fail (requisition != NULL);
+
+ window = GTK_WINDOW (widget);
+
+ if (window->bin.child)
+ {
+ requisition->width = GTK_CONTAINER (window)->border_width * 2;
+ requisition->height = GTK_CONTAINER (window)->border_width * 2;
+
+ gtk_widget_size_request (window->bin.child, &window->bin.child->requisition);
+
+ requisition->width += window->bin.child->requisition.width;
+ requisition->height += window->bin.child->requisition.height;
+ }
+ else
+ {
+ if (!GTK_WIDGET_VISIBLE (window))
+ window->need_resize = TRUE;
+ }
+}
+
+static void
+gtk_window_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkWindow *window;
+ GtkAllocation child_allocation;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_WINDOW (widget));
+ g_return_if_fail (allocation != NULL);
+
+ window = GTK_WINDOW (widget);
+ widget->allocation = *allocation;
+
+ if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
+ {
+ child_allocation.x = GTK_CONTAINER (window)->border_width;
+ child_allocation.y = GTK_CONTAINER (window)->border_width;
+ child_allocation.width = allocation->width - child_allocation.x * 2;
+ child_allocation.height = allocation->height - child_allocation.y * 2;
+
+ gtk_widget_size_allocate (window->bin.child, &child_allocation);
+ }
+}
+
+static gint
+gtk_window_expose_event (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (!GTK_WIDGET_UNMAPPED (widget))
+ GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ if (GTK_WIDGET_CLASS (parent_class)->expose_event)
+ return (* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event);
+
+ return FALSE;
+}
+
+static gint
+gtk_window_configure_event (GtkWidget *widget,
+ GdkEventConfigure *event)
+{
+ GtkWindow *window;
+ GtkAllocation allocation;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ window = GTK_WINDOW (widget);
+ window->handling_resize = TRUE;
+
+ allocation.x = 0;
+ allocation.y = 0;
+ allocation.width = event->width;
+ allocation.height = event->height;
+
+ gtk_widget_size_allocate (widget, &allocation);
+
+ if (window->bin.child &&
+ GTK_WIDGET_VISIBLE (window->bin.child) &&
+ !GTK_WIDGET_MAPPED (window->bin.child))
+ gtk_widget_map (window->bin.child);
+
+ window->resize_count -= 1;
+ if (window->resize_count == 0)
+ {
+ if ((event->width != widget->requisition.width) ||
+ (event->height != widget->requisition.height))
+ {
+ window->resize_count += 1;
+ gdk_window_resize (widget->window,
+ widget->requisition.width,
+ widget->requisition.height);
+ }
+ }
+ else if (window->resize_count < 0)
+ {
+ window->resize_count = 0;
+ }
+
+ window->handling_resize = FALSE;
+
+ return FALSE;
+}
+
+static gint
+gtk_window_key_press_event (GtkWidget *widget,
+ GdkEventKey *event)
+{
+ GtkWindow *window;
+ GtkDirectionType direction = 0;
+ gint return_val;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ window = GTK_WINDOW (widget);
+
+ return_val = FALSE;
+ if (window->focus_widget)
+ return_val = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
+
+ if (!return_val && gtk_window_check_accelerator (window, event->keyval, event->state))
+ return_val = TRUE;
+
+ if (!return_val)
+ {
+ switch (event->keyval)
+ {
+ case GDK_space:
+ if (window->focus_widget)
+ {
+ gtk_widget_activate (window->focus_widget);
+ return_val = TRUE;
+ }
+ break;
+ case GDK_Return:
+ case GDK_KP_Enter:
+ if (window->default_widget)
+ {
+ gtk_widget_activate (window->default_widget);
+ return_val = TRUE;
+ }
+ else if (window->focus_widget)
+ {
+ gtk_widget_activate (window->focus_widget);
+ return_val = TRUE;
+ }
+ break;
+ case GDK_Up:
+ case GDK_Down:
+ case GDK_Left:
+ case GDK_Right:
+ case GDK_Tab:
+ switch (event->keyval)
+ {
+ case GDK_Up:
+ direction = GTK_DIR_UP;
+ break;
+ case GDK_Down:
+ direction = GTK_DIR_DOWN;
+ break;
+ case GDK_Left:
+ direction = GTK_DIR_LEFT;
+ break;
+ case GDK_Right:
+ direction = GTK_DIR_RIGHT;
+ break;
+ case GDK_Tab:
+ if (event->state & GDK_SHIFT_MASK)
+ direction = GTK_DIR_TAB_BACKWARD;
+ else
+ direction = GTK_DIR_TAB_FORWARD;
+ break;
+ default :
+ direction = GTK_DIR_UP; /* never reached, but makes compiler happy */
+ }
+
+ gtk_container_focus (GTK_CONTAINER (widget), direction);
+
+ if (!GTK_CONTAINER (window)->focus_child)
+ gtk_window_set_focus (GTK_WINDOW (widget), NULL);
+ else
+ return_val = TRUE;
+ break;
+ }
+ }
+
+ return return_val;
+}
+
+static gint
+gtk_window_key_release_event (GtkWidget *widget,
+ GdkEventKey *event)
+{
+ GtkWindow *window;
+ gint return_val;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ window = GTK_WINDOW (widget);
+ if (window->focus_widget)
+ return_val = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
+
+ return return_val;
+}
+
+static gint
+gtk_window_enter_notify_event (GtkWidget *widget,
+ GdkEventCrossing *event)
+{
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ return FALSE;
+}
+
+static gint
+gtk_window_leave_notify_event (GtkWidget *widget,
+ GdkEventCrossing *event)
+{
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ return FALSE;
+}
+
+static gint
+gtk_window_focus_in_event (GtkWidget *widget,
+ GdkEventFocus *event)
+{
+ GtkWindow *window;
+ GdkEventFocus fevent;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ /* It appears spurious focus in events can occur when
+ * the window is hidden. So we'll just check to see if
+ * the window is visible before actually handling the
+ * event
+ */
+ if (GTK_WIDGET_VISIBLE (widget))
+ {
+ window = GTK_WINDOW (widget);
+ if (window->focus_widget && !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
+ {
+ fevent.type = GDK_FOCUS_CHANGE;
+ fevent.window = window->focus_widget->window;
+ fevent.in = TRUE;
+
+ gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
+ }
+ }
+
+ return FALSE;
+}
+
+static gint
+gtk_window_focus_out_event (GtkWidget *widget,
+ GdkEventFocus *event)
+{
+ GtkWindow *window;
+ GdkEventFocus fevent;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ window = GTK_WINDOW (widget);
+ if (window->focus_widget && GTK_WIDGET_HAS_FOCUS (window->focus_widget))
+ {
+ fevent.type = GDK_FOCUS_CHANGE;
+ fevent.window = window->focus_widget->window;
+ fevent.in = FALSE;
+
+ gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
+ }
+
+ return FALSE;
+}
+
+static void
+gtk_window_style_set_event (GtkWidget *widget,
+ GdkEventClient *event)
+{
+ GdkAtom atom_default_colors;
+ GtkStyle *style_newdefault;
+ GdkAtom realtype;
+ gint retfmt, retlen;
+ GdkColor *data, *stylecolors;
+ int i = 0, j;
+ GdkColormap *widget_cmap;
+
+ atom_default_colors = gdk_atom_intern("_GTK_DEFAULT_COLORS", FALSE);
+
+ if(gdk_property_get (GDK_ROOT_PARENT(),
+ atom_default_colors,
+ GDK_NONE,
+ 0,
+ sizeof(GdkColor) * GTK_STYLE_NUM_STYLECOLORS(),
+ FALSE,
+ &realtype,
+ &retfmt,
+ &retlen,
+ (guchar *)&data) != TRUE
+ || retfmt != sizeof(gushort)) {
+ g_warning("gdk_property_get() failed in _GTK_STYLE_CHANGED\n");
+ return;
+ }
+ /* We have the color data, now let's interpret it */
+ style_newdefault = gtk_widget_get_default_style();
+ gtk_style_ref(style_newdefault);
+ stylecolors = (GdkColor *) style_newdefault;
+
+ widget_cmap = gtk_widget_get_colormap(widget);
+ for(i = 0; i < GTK_STYLE_NUM_STYLECOLORS(); i++) {
+ stylecolors[i] = data[i];
+ gdk_color_alloc(widget_cmap, &stylecolors[i]);
+ }
+
+ gtk_widget_set_default_style(style_newdefault);
+ gtk_style_unref(style_newdefault);
+
+ /* Now we need to redraw everything */
+ gtk_widget_draw(widget, NULL);
+ gtk_widget_draw_children(widget);
+}
+
+static gint
+gtk_window_client_event (GtkWidget *widget,
+ GdkEvent *event)
+{
+ GdkAtom atom_styleset;
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ atom_styleset = gdk_atom_intern("_GTK_STYLE_CHANGED", FALSE);
+
+ if(event->client.message_type == atom_styleset) {
+ gtk_window_style_set_event(widget, event);
+ }
+ return FALSE;
+}
+
+static gint
+gtk_window_need_resize (GtkContainer *container)
+{
+ GtkWindow *window;
+ gint return_val;
+
+ g_return_val_if_fail (container != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_WINDOW (container), FALSE);
+
+ return_val = FALSE;
+
+ window = GTK_WINDOW (container);
+ if (window->handling_resize)
+ return return_val;
+
+ if (GTK_WIDGET_VISIBLE (container))
+ {
+ window->need_resize = TRUE;
+ return_val = gtk_window_move_resize (GTK_WIDGET (window));
+ window->need_resize = FALSE;
+ }
+
+ return return_val;
+}
+
+static gint
+gtk_real_window_move_resize (GtkWindow *window,
+ gint *x,
+ gint *y,
+ gint width,
+ gint height)
+{
+ GtkWidget *widget;
+ GtkWidget *resize_container;
+ GSList *resize_widgets;
+ GSList *resize_containers;
+ GSList *tmp_list;
+ gint return_val;
+
+ g_return_val_if_fail (window != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
+ g_return_val_if_fail ((x != NULL) || (y != NULL), FALSE);
+
+ return_val = FALSE;
+
+ widget = GTK_WIDGET (window);
+
+ if ((*x != -1) && (*y != -1))
+ gdk_window_move (widget->window, *x, *y);
+
+ if ((widget->requisition.width == 0) ||
+ (widget->requisition.height == 0))
+ {
+ widget->requisition.width = 200;
+ widget->requisition.height = 200;
+ }
+
+ gdk_window_get_geometry (widget->window, NULL, NULL, &width, &height, NULL);
+
+ resize_containers = NULL;
+
+ if ((window->auto_shrink &&
+ ((width != widget->requisition.width) ||
+ (height != widget->requisition.height))) ||
+ (width < widget->requisition.width) ||
+ (height < widget->requisition.height))
+ {
+ if (window->resize_count == 0)
+ {
+ window->resize_count += 1;
+ gdk_window_resize (widget->window,
+ widget->requisition.width,
+ widget->requisition.height);
+ }
+ }
+ else
+ {
+ /* The window hasn't changed size but one of its children
+ * queued a resize request. Which means that the allocation
+ * is not sufficient for the requisition of some child.
+ * We've already performed a size request at this point,
+ * so we simply need to run through the list of resize
+ * widgets and reallocate their sizes appropriately. We
+ * make the optimization of not performing reallocation
+ * for a widget who also has a parent in the resize widgets
+ * list.
+ */
+ resize_widgets = gtk_object_get_data (GTK_OBJECT (window), "resize_widgets");
+ gtk_object_set_data (GTK_OBJECT (window), "resize_widgets", NULL);
+
+ tmp_list = resize_widgets;
+ while (tmp_list)
+ {
+ widget = tmp_list->data;
+ tmp_list = tmp_list->next;
+
+ /* referencing needed? */
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_RESIZE_NEEDED);
+ gtk_object_unref (GTK_OBJECT (widget));
+
+ widget = widget->parent;
+
+ while (widget &&
+ ((widget->allocation.width < widget->requisition.width) ||
+ (widget->allocation.height < widget->requisition.height)))
+ widget = widget->parent;
+
+ if (widget)
+ GTK_WIDGET_SET_FLAGS (widget, GTK_RESIZE_NEEDED);
+ }
+
+ tmp_list = resize_widgets;
+ while (tmp_list)
+ {
+ widget = tmp_list->data;
+ tmp_list = tmp_list->next;
+
+ resize_container = widget->parent;
+ while (resize_container &&
+ !GTK_WIDGET_RESIZE_NEEDED (resize_container))
+ resize_container = resize_container->parent;
+
+ if (resize_container)
+ widget = resize_container->parent;
+ else
+ widget = NULL;
+
+ while (widget)
+ {
+ if (GTK_WIDGET_RESIZE_NEEDED (widget))
+ {
+ GTK_WIDGET_UNSET_FLAGS (resize_container, GTK_RESIZE_NEEDED);
+ resize_container = widget;
+ }
+ widget = widget->parent;
+ }
+
+ if (resize_container &&
+ !g_slist_find (resize_containers, resize_container))
+ resize_containers = g_slist_prepend (resize_containers, resize_container);
+ }
+
+ g_slist_free (resize_widgets);
+
+ tmp_list = resize_containers;
+ while (tmp_list)
+ {
+ widget = tmp_list->data;
+ tmp_list = tmp_list->next;
+
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_RESIZE_NEEDED);
+ gtk_widget_size_allocate (widget, &widget->allocation);
+ gtk_widget_queue_draw (widget);
+ }
+
+ g_slist_free (resize_containers);
+ }
+
+ return return_val;
+}
+
+static gint
+gtk_window_move_resize (GtkWidget *widget)
+{
+ GtkWindow *window;
+ gint x, y;
+ gint width, height;
+ gint screen_width;
+ gint screen_height;
+ gint return_val;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
+
+ return_val = FALSE;
+
+ if (GTK_WIDGET_REALIZED (widget))
+ {
+ window = GTK_WINDOW (widget);
+
+ /* Remember old size, to know if we have to reset hints */
+ width = widget->requisition.width;
+ height = widget->requisition.height;
+ gtk_widget_size_request (widget, &widget->requisition);
+
+ if (GTK_WIDGET_MAPPED (widget) &&
+ (width != widget->requisition.width ||
+ height != widget->requisition.height))
+ gtk_window_set_hints (widget, &widget->requisition);
+
+ x = -1;
+ y = -1;
+ width = widget->requisition.width;
+ height = widget->requisition.height;
+
+ if (window->use_uposition)
+ switch (window->position)
+ {
+ case GTK_WIN_POS_CENTER:
+ x = (gdk_screen_width () - width) / 2;
+ y = (gdk_screen_height () - height) / 2;
+ gtk_widget_set_uposition (widget, x, y);
+ break;
+ case GTK_WIN_POS_MOUSE:
+ gdk_window_get_pointer (NULL, &x, &y, NULL);
+
+ x -= width / 2;
+ y -= height / 2;
+
+ screen_width = gdk_screen_width ();
+ screen_height = gdk_screen_height ();
+
+ if (x < 0)
+ x = 0;
+ else if (x > (screen_width - width))
+ x = screen_width - width;
+
+ if (y < 0)
+ y = 0;
+ else if (y > (screen_height - height))
+ y = screen_height - height;
+
+ gtk_widget_set_uposition (widget, x, y);
+ break;
+ }
+
+ gtk_signal_emit (GTK_OBJECT (widget), window_signals[MOVE_RESIZE],
+ &x, &y, width, height, &return_val);
+ }
+
+ return return_val;
+}
+
+static void
+gtk_window_set_hints (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkWindow *window;
+ GtkWidgetAuxInfo *aux_info;
+ gint flags;
+ gint ux, uy;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_WINDOW (widget));
+ g_return_if_fail (requisition != NULL);
+
+ if (GTK_WIDGET_REALIZED (widget))
+ {
+ window = GTK_WINDOW (widget);
+
+ flags = 0;
+ ux = 0;
+ uy = 0;
+
+ aux_info = gtk_object_get_data (GTK_OBJECT (widget), "aux_info");
+ if (aux_info && (aux_info->x != -1) && (aux_info->y != -1))
+ {
+ ux = aux_info->x;
+ uy = aux_info->y;
+ flags |= GDK_HINT_POS;
+ }
+ if (!window->allow_shrink)
+ flags |= GDK_HINT_MIN_SIZE;
+ if (!window->allow_grow)
+ flags |= GDK_HINT_MAX_SIZE;
+
+ gdk_window_set_hints (widget->window, ux, uy,
+ requisition->width, requisition->height,
+ requisition->width, requisition->height,
+ flags);
+
+ if (window->use_uposition && (flags & GDK_HINT_POS))
+ {
+ window->use_uposition = FALSE;
+ gdk_window_move (widget->window, ux, uy);
+ }
+ }
+}
+
+static gint
+gtk_window_check_accelerator (GtkWindow *window,
+ gint key,
+ guint mods)
+{
+ GtkAcceleratorTable *table;
+ GList *tmp;
+
+ if ((key >= 0x20) && (key <= 0xFF))
+ {
+ tmp = window->accelerator_tables;
+ while (tmp)
+ {
+ table = tmp->data;
+ tmp = tmp->next;
+
+ if (gtk_accelerator_table_check (table, key, mods))
+ return TRUE;
+ }
+
+ if (gtk_accelerator_table_check (NULL, key, mods))
+ return TRUE;
+ }
+
+ return FALSE;
+}
diff --git a/gtk/gtkwindow.h b/gtk/gtkwindow.h
new file mode 100644
index 000000000..ff2252731
--- /dev/null
+++ b/gtk/gtkwindow.h
@@ -0,0 +1,105 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_WINDOW_H__
+#define __GTK_WINDOW_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkaccelerator.h>
+#include <gtk/gtkbin.h>
+#include <gtk/gtkenums.h>
+#include <gtk/gtkwidget.h>
+
+
+#define GTK_WINDOW(obj) GTK_CHECK_CAST (obj, gtk_window_get_type (), GtkWindow)
+#define GTK_WINDOW_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_window_get_type (), GtkWindowClass)
+#define GTK_IS_WINDOW(obj) GTK_CHECK_TYPE (obj, gtk_window_get_type ())
+
+
+typedef struct _GtkWindow GtkWindow;
+typedef struct _GtkWindowClass GtkWindowClass;
+
+struct _GtkWindow
+{
+ GtkBin bin;
+
+ gchar *title;
+ gchar *wmclass_name;
+ gchar *wmclass_class;
+ GtkWindowType type;
+ GList *accelerator_tables;
+
+ GtkWidget *focus_widget;
+ GtkWidget *default_widget;
+
+ gshort resize_count;
+ guint need_resize : 1;
+ guint allow_shrink : 1;
+ guint allow_grow : 1;
+ guint auto_shrink : 1;
+ guint handling_resize : 1;
+ guint position : 2;
+ guint use_uposition : 1;
+};
+
+struct _GtkWindowClass
+{
+ GtkBinClass parent_class;
+
+ gint (* move_resize) (GtkWindow *window,
+ gint *x,
+ gint *y,
+ gint width,
+ gint height);
+};
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+guint gtk_window_get_type (void);
+GtkWidget* gtk_window_new (GtkWindowType type);
+void gtk_window_set_title (GtkWindow *window,
+ const gchar *title);
+void gtk_window_set_wmclass (GtkWindow *window,
+ gchar *wmclass_name,
+ gchar *wmclass_class);
+void gtk_window_set_focus (GtkWindow *window,
+ GtkWidget *focus);
+void gtk_window_set_default (GtkWindow *window,
+ GtkWidget *defaultw);
+void gtk_window_set_policy (GtkWindow *window,
+ gint allow_shrink,
+ gint allow_grow,
+ gint auto_shrink);
+void gtk_window_add_accelerator_table (GtkWindow *window,
+ GtkAcceleratorTable *table);
+void gtk_window_remove_accelerator_table (GtkWindow *window,
+ GtkAcceleratorTable *table);
+void gtk_window_position (GtkWindow *window,
+ GtkWindowPosition position);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_WINDOW_H__ */
diff --git a/gtk/line-arrow.xbm b/gtk/line-arrow.xbm
new file mode 100644
index 000000000..493ecf325
--- /dev/null
+++ b/gtk/line-arrow.xbm
@@ -0,0 +1,4 @@
+#define line_arrow_width 6
+#define line_arrow_height 9
+static unsigned char line_arrow_bits[] = {
+ 0x00, 0x00, 0x04, 0x0c, 0x18, 0x3f, 0x18, 0x0c, 0x04};
diff --git a/gtk/line-wrap.xbm b/gtk/line-wrap.xbm
new file mode 100644
index 000000000..82428037d
--- /dev/null
+++ b/gtk/line-wrap.xbm
@@ -0,0 +1,4 @@
+#define line_wrap_width 6
+#define line_wrap_height 9
+static unsigned char line_wrap_bits[] = {
+ 0x1e, 0x3e, 0x30, 0x30, 0x39, 0x1f, 0x0f, 0x0f, 0x1f, };
diff --git a/gtk/marble.xpm b/gtk/marble.xpm
new file mode 100644
index 000000000..1ef260761
--- /dev/null
+++ b/gtk/marble.xpm
@@ -0,0 +1,408 @@
+/* XPM */
+static char *granite07[] = {
+/* width height num_colors chars_per_pixel */
+" 384 384 16 1",
+/* colors */
+". c #000000",
+"# c #111111",
+"a c #222222",
+"b c #333333",
+"c c #444444",
+"d c #555555",
+"e c #666666",
+"f c #777777",
+"g c #888888",
+"h c #999999",
+"i c #aaaaaa",
+"j c #bbbbbb",
+"k c #cccccc",
+"l c #dddddd",
+"m c #eeeeee",
+"n c #ffffff",
+/* pixels */
+"aacfedbbcbbaaaaaaaaabaabaaaaabcbcbbbabbchfdcccbbabbbaaabaabcbaa#aa#######a#aaaabcddeefhec##dgbabbaaadabbcfbaa##########aaabbaaa#a#####a#aa###a#aaabbbbcbbbccdedaaaaa#aaaaa#a#abaaabbabbbeddbbaaaaaca##a#aaaba########aaaadcababbabdehd.##.a######.cgdcb###b##.##.##aaaaa####abcba######a##aac#a##a####aa#aa##babbbcfccbbbcdccccecbbbcbbbcdccddcbcdfeecbhhjihhgffc.aaa####.#######aaaaaaaabbaaaaa",
+"aaacedccbbcbaaaaaa#bbaabbbaaaabcaabbbbbbafhfccbbbbbbabacbacbaaaaa##########a###abbcdeghhhcagb#ababaaccbacdfca#a####aa###aaaaabaaa#####aca#aabaababbcccccccbcdfdaaaa###aaaaaaaaaaabbbbbbccccccbbcbcaaa##aaaaabaaaa###abdaccceebaaaabehja####a######..#aeec#bb##########aa#####abba#########aaca########aa#aa###aaaabddbbbbbbbbbbccbbabbbbabbabbabcbcbcefhfeddccefhhijheecb#...a####aaaaaaaabaaaaa",
+"aaabccccccdbabcbaaa#aaaaaaaaaaabbabbbbbccabefdccabcbbabacccbaaabaa######a######aaabceiiiihije#bbabbaaeaabcedcaabaa########aaaabaa##a###ab#aabcababbccccccdeeeecc#a##a##aaaaaaaaaabbbbbbbcccbbbdcbbcdaa#a#aabbaaaaa###acbaa#bccaa#abcfig.#######.#######acddgefdda#######a########a#######aaaaaa#a######aaaa#####aaacdcbabbaaabbbcaaaaaaaaabbbaaabbaabbbcbcbabbabcdeefghjkjgc#..####aaaaaaaaaaaa#",
+"#aaaaaacbccbcabbbaaaaaabcaaaaabbbbbbabbbcbaabffccbccbccbbcbaaaabaaaa#aa#aa##a#aaaaabbikkjhijicabbbcc#faaacdebcbda#########aaaaaaaaa####aa##cacccabcccdccccdddfdcbaa##a##abbbabccbbcbbbccccaaa#abbaaba#a##abbbbbaaaaaaaaaaccaaca##aabcfic.###aa#######a####bddeeddb####.##.###aaa#########aaaa###aa####aaaa#######aabdbbbbcabbbaaaa#aaaaaaaaabaaabbbaabbbbdbbaaabccccccdcefhhkhda##aaaa#a#aaaaa##",
+"#aaabaabcecbaa##bcaaaaaaaababbabaaabbabbaabb#chhfdccccbcbecaaabaaaaaaaaaa####aaaaaaabdgjkkijijdabbdcabfaabcecbbec###########a#aaaabaa#######abbaaaadddedddeeefeccaa###a#aabcccdcbcbbbbccbbbbaaaaa#aabbaaaabbbbbbaaaaaaabbbbbaaa####acegha##a#aabbb####a##adccdedbcc#######.###a###a#######aaa#a#aa##..#aa#########abdbaabbabbbaa###aaaaaaaaaaaaacbaaababbdbabbabcbbcbcbccbbdegjkgb#aa#aa#aaaaaaa",
+"##aa#aabccccaaaaaaaa#aaaaaabbaabbbaaaaabbbcbbcfhhgfcccbbbbccbaabbaaaaaaabaa#aaaabaaaabbcehkljjdabacccbgbaaccdb#adea#########aa#abaaaaa#####ac#ba##accdedddefffeaba##a#aaaaacccccccbbbcccaabaaaaaaaaa#aaaaabcbbaaa#bbbbaaefccdbaaa#aaacdei##aa##aabbbaaa#a#cdcccccbcea.#########bbaaa######a###a#aaaa.#aaba####.###abcbaaabaabbbaa###aaaaaaaaaaaabbaaaaaaaaaaababcbbcbbaabbbdddeghheba##ab#abaa##",
+"#####bbaaaaabaaaaa##aa#adccaabaaabbbbabbabbbabccbccfdbccbbbbbcaabcaabaaabbaaaaaaaaaaaabbbcglli#accbbbddgabcddbbaacea#a##########aaa#aaa##aaaa####aabcddeeefffgdbbaaaa###baabbbbbbcdabdcbcaaabaaaaaaa#aaaaaabcbbbbadfbbbaejhhebbccaaaaaccfi.aba##abaaaba####ecbbccba#fc.####.##.bba#a#######aaaaaaaaaaa##aaaa######abcdaa#aaaabaaa###aaaaabaaabbbaaba##aaababcbbcbbbbbcbaaabbccccddgggeb#aadca###",
+"#####bcaaaaaabcbaaa#aaaabcccaaaaaaabaaabbbbbbbaacbabeeddddccbcbbcccbabaaaabaabaaaaaaaaabbbbglmdbcbaabebdgdbcecbbaabdbaa#########aabbaaaa#aa#a##a#aabbdceeedccdcbbaaaaa##aaabbcbbbabaaabbababbaaaa#aaaaaaaabcdccbbbabcbbbcfijfbcdcabb#abcbif#abb##aaabaaaa##fcccbbcaa#db#..##.##.aaa#########ab#aaaaaa#aabaaaaa#####abdbbaaaabbaaaa###b#a#aaaabaaaaaaaaaaaaaabbabbbbaabbbaaaabbbbbbbceffecccbaa##",
+"#####abaaaaa#accbbbbaaabaaaaaaaaaaadcbaabbabbbabbdcaacgfddddcdddcadfcaaaabcbbabaaaaaabcabbbdjliacbababcbdfcdeeaaaaaabba########a##aa#aabaa##a######abddeggca#bcbaaaaaa####aaaaaabbbbbcbbbbbaaa##a#aaaaaaaabcbccbbaaaabaabfgfiecccccbbaaaccicbbbcbaaabaaabb#ceccccdca##aacdb######aaa###a###aabaaaaaa#aabca#abba#####abca##aaaaaaaaa##a##aaaaaaabaaaaaaabaaaacbcbacdbaaabaaaaaabaaaaabbcddccbaa##",
+"####aa#aaaaaaabccbabbaaaaaaaaaaaaabfaaabbcbbbbbabdebaabdffddedefedccecccdcbbbbbccbccbbbbbbccekldaabaaabccbfaaaaaaaaaaaba########aaaaaaaaba##aaa###aabbccfgfaababbbaaaaa#aabbaabaaccaabcccbcbaa##aaaaaabaabbbccbbbaabbbbbbdddghdbbbcccb#abcdebcccbaabbbabbcbaecddddbaa##.#acdeca#######a#aaaaaaaaaaaaaaabba##abba####aacba##aaaaaaaaaaaaa##aba#abaaaaaaabaaaabbbbbbcbabbaabbaaaaabaaaaaaaaccbaa##",
+".####aa#aabaa##bccbaabbbba#aaaaabbaefdaabbbbccbbbaddaaabadeeffhhhffdedddeecbbbbcccbbabcbabbcfjjlkeaaaaacdadcaa#aaaaaaa#ab######ba#aaabbabcaa#aa###babcddcedba##acbaaaaaa#ababbbacbbbcccdfffbaa#aaaacbaabcbabccbbcbbbbbbcbbccedbbbccdccbaabcgb#bccbbbababbbcccdededcb#a####...addcba##aabbbbbbbbaaaaabba#aaa##abba####abbaa###a#aa#aa##aaa#a##abaaaaaaaaabababbcdbcb#baaaaaaaaaaaaaaaaaa#aaaaa###",
+"######a##aaaaaa#accbaaabbbaaa#aaababdcaaabbbbcccbbbdbabbbacdccgecadbbbcdccddeddcccccbaabcbbcgjhhjgeb#aacdcccaa#aa#aaa#a#aaa##aaaaa#aaabbaabb#aa###aabccddeccbbbaabcbbbcbbb#aacbbadbabcccddbaaa#aaaaabbbbabbbbcdbbbabbcddcbbbccaabbbccbbaaaadi##abbbbbbbaabbbacdeedbd######aa####bceda#aabbabaaaaaaaaba#aaaaa#aabaaa###acaaaa####aa##aaaaaaaa#aaaaaaaaaaababaaaaabcaaaaaaabbcbaaaaaaaaa###aaaa###",
+"##########aabaa#accbbabbbbbba##aaaabbcbbbbbbbbcbaaabdbbbbbbddccbbbbaaaabbabbbbcefefdcbaadbcddje#debgfbabecdc####aa##a###a#aa#aa##a##aaabbcabbaa###aabbcceedbcbaaaabdcccbabaaabbbbabbccbbaaaaaa#aaaaaaaabbbbbcbccabcccccdcccbbbbabbababbba#abfe#aaaaaaaabccbbaaaedddc######adcaaaa##dfcaaaaaaaaaa#aaaaa##aabcaaabbaa#aaab###aa###aaaaaaaaaaaa##aaaaaaaaaabaaabaaabcabaaaaaaabcbaabaaa##a###aa####",
+"#########aaaaaaabbcbbbbabcbaacbaa##aaabaaabccccccbaabecabbbcddbacdeba#aaaaabaaabbdfgedcbaccdcgica#aadghdbddd#aa#aaa#a###aaaabaa#####aaaaabbbbbba#aaabccceecbddbaa#bbccabcbbbbbacccdbbdabbaaaaaaa#aaaa#aabbbbcccdcbcbbccccccbcaababbdbabbba#bbgaabaaa#aaacccdcddbeedba#a##a#aba#aaaa##decbaaba#aaa###a#a###abba#bba###aaba####a####aaaaaaaaaaaa#aaabbbaaabbaabbaabbaaa#aa#a#abbaabbbaaa#aaaa#####",
+"############aaaaaaacbbbbbbbaa#aaa#a##aaaaaaaacbbbbbbabdcabbbcdbaccdba#aaaaaababbcbbdddedccddefihaa#aaahiiiffd#aaaa#abaa##aaaaacaa##a#bcaaaabbbcaaaabccdddecabaaaaacbbbabbccccccbbdbdfdaabbaaa###a#aaaaaaaabbbbbbbaaabdcddccbbbbabbbccaabbbaabfdaaabaa#aa##aabbbbbddba##aa#a#aa##aaaaaabcdbbaaa##aa#####a#aaabbaaaaa##abb######aa###aaaaaaaaaaaaaaaaabaaaaaaaabbbbaaabaaa#aaaaaaabbbaaaaaaaaa####",
+"###########aa#aa#aaaccabbaaaaaaabb#######a#aaabcbbbabbaeebbccbcbacdaaa##a#aabbbbccbbcbcdegifdfgifba##aaaagigha#aaaaabbaaaaaaaaabaaa##acaaaaabbbbbbabcdddefeba####abbaabccccbbbcbadcbcbaabba#aaaa#aaaaaababacccbaadbabbccedcccbbccbbabaaaaa##ade###abba#aa##abbba#cebb.#a####.#a#aaaaaaaaacfca#aaa###aa###abaabaaaaaaaabbaa#######aaaaa#aa#aaaaaaaaaaababdaaabbbbbababaaaaaa#aaaaaabbaaabaaaaa###",
+"##########a#aaabaaaaccaaaaaaabaaaaaaba###a##abaaabbababaccbcbbcccaaba#a###aaabbccdccccccdeegggfigaabb#aaa#fffcba#abbaaaaaaaaaaa#abba##aaa##aabbbcbbbbcdeegfeb####aabaabacbbbcbccaabbabaaaaaaa##aa#aaaaababbabbcbcdbbcccbddcdcccabcbbababba###afba#aabba#acaaabbbbaddb##aa####.####aabbaaaabffcaaaaaa##a##bcabbaaaaaaabbbc#a#a#######aaaaa#####a##ababbbbbaaaabbcbaaaaaaaaaaa#aaaaaabaaababaaaaa#",
+"#######a#####a#aaaaabcbaaaaaa#aabaaaaaa###abbabaaaaaccaaabdbccbccbaaca#####accddcccccccddeeefikjeabcca#a#abfifbaa#abbbbbaaaaaaaaa#bbba#bcaaaaaaaccbcccceffeccaa##aaabbbcabbacbddbbaabdbaaaaaaaaaaaaaaabbbaabbbbbbbbbcbbccccdcdcccabbbbbaaba###dcaaaabbaaabaabcbccaadba#aaa########aaaa##aaaacgdbaaaa####cfffda#a#aaaabbdbaa#aaa########aaaa#aa##aaabbabbbaaabbbaaaaaabaaaaaaaa#aaaaabaaaaaaaaa#a",
+"a###########aaaaaaaabbaabaaa###abaaa#a##a###a#aaaaabacaaabccbbbcbbbcbb####a#bdfbbccccccdefecdgiiddaabbaaaabacfeaaaaaabcccbaaaaaaabaaacaa##aaaaaaabccddcfgfgbabaaa#aaabbcccbccbcddbbacabbbbbbbbaaacbaaaabcbabbbbbcbbcbccbccdccdccdcbaabbbaabaaade#aa#baaabaa##abbcbacdb#.#abbccc#.##aaa####aa#aeeaaaaaaabbabddfgfba#aabcd#aaaa########aa##a##aaaaaababbaabbbbbabccbababaaaaaaa##a#aaaabbaaaaaaaa#",
+"#a###a######aaaaaaaacdaaaaaaaa#aaaaaaaaaa#####a###abbbbaaaaccbbbcbbbbaa#aaaaaeecabcccbccdedcdfgigeaaaacbaaabaacbaaaaaaabcbbbaaaaaaaaabccaaaaaaaaaacccceffffbabb#a####aaaabcccccddcdedbbbbaabcabbbccbccbcbcbbbbbbbbbcecbccccceccccdccbbaaaaaaabce#bbaaa###aaa##ababcacda#abb##a#######a#########bfdca#abcbaabaabcffddbabdc#aaaaa##########aa####aaaaaaabbabbbbbbbcbbbcbaaaaaaaa#aa#aaaaaabaa##b##",
+"##a#########aabaaaabcdbabaaaaa##aaaaabaaba######a##ababbbbbabbbbcbcdddbbaa#abceecabccccccdddfedgjgdbaaabaaabbbaaba#aabaabaccaaaaaaaabbccbbbaaabaaabcddefgfebbbb#aa####aaaabbcccccbbfeccbbbaaababbbbbbbccba#abbbabbcdccdcbddcddcccdcddcbaaaaaabcfbadaa#######a#abbacbbcc###a#a########a######a##aabdcabccbbababaaaacdfededbbaa#aa##aa######ba#aa#aaabbabaababcbbcbcbbbabbaaaaaaaa##aaabaaacba#a##",
+"##########a#abaaaaabbbcbbbcaa###a#aaaaa##aba#######aaaaaabbdccbaabccdddecaaaabccdbbacccddcdefdfgiifcba#bbaaabbaaaababbbbbbbabbaabaaaacbbbcbbaaaaaaaceeeefffbaaaa###a##aaaabbcbbbddcddddcbcbbaaabbbbababbabaaabababbbbcccdccddcddccccdecaaaa#abccfbbaaa#######aabbaacabe###a#aa#a#a##.aa#######a#aa#cfeecdcccccabbbabacggcabbaaabbaaaa####aabb#aaaabbababbbbbbcccbbbbbcccbbbaaaa#aaaaaababbaaaa##",
+"######a####abcbaaaaabbccbcbaa###a##aaa##a###aa######aaaaaabdgebaaabbbccacbaaaaabbbaaabccddcdeeffgigbaaaaaabaabcaaababbbbaabbacbaaabbaaaababccbabbabbdffefhdcaaa###aaabba#aababcbdeeccceccccbababbbbabbabbaaaaaabbaabbcbcccccdcddddccccdcaaaababcdeaba#####.###aaabaab#b####a####a##aa#b########aaaaabedddcccccaaaabbcabeaaaabbccbaaa#abbaaabbbaaaabbbaaacbcbcbbdccbaabbacbbbbbaaaaaaaaabbaa#####",
+"######aaa#abbcbaaaaabdccbbaaa#######aaa#####aaa##a#a##aaaababcbbaaaaabdebbbaaa##aaaaaaaabccddeefggieaaaaaaaacabaabbbabbbbaaaabbaaaaaaabbbabbccbaabbbdfgghebbbaa#####abba#aabbbcbccdcbbbcddcccbbbabbabbbabbabaaaaaaacbbabcbbccccddddccbcccaaaaaabbdcbc##########aaacbbaa####a####aa###a#aa###aaa###abbceddedcccbaaaacccdca##a#abbbabaaaabaaabbba#aabbbbbbccbbbbaaacccbbcbbaaabbbbbbabaaabaaaa####",
+"#######aa#aaccabbabaabdecbb#a########aaaa####aaa#aba##a#aaaaaaabbdcaabdcbcaacb####abb#abaabccdeffghfdabaaaa#acbbbbcbabcabcbaaaabbbabaaaabbbbbcccbbbccdfedccbbb#########aaaababbacccbcbbbddbdcccccbbbbaaaabbaabbaaaaabaabbbbccdcceedccccacbaaaabbbbddb####aa######aabbaa####a####aa#aa###a#####aa#aabbddeccddccbbbabbbbceb###aa#aaaaaa##aa####aaaa#abbbbbccacccbaa#accbbbbbaaababbabaaaaaaaaa####",
+"##a#####aaaaaabbbbabacdddccaa########aa#a#####aaa#aa#aaaaaaaaaaaabcabbcbbbbababa###baaaaaaabccdeeehifbabaaa###abbcbbcaccbcbbbaabbbbabaaabbbbbbbbcccccddbccbbbbba#######aaabbbaabbcccbdcbbdbbddcdcccbabaabaaaaaaaaaaaaaaaabbcccddecccbbacccbbbaabbbceca############aaaaa#############a#############aaaaabccddcbbbabbbbbbba#####a##a####aaa#######aaa#babaabbcbaaa##abbbaabbcbbbbaaaaaaaabbaaa####",
+"#########abaaabbabbbbbddeccca##aa######a#aa####bbaaaaaaaaaaaaaaaaaabccbcccebacfdb#####aaaaaaabcdddcfgfccbaa##a##abcbbcbbdcccccabbabaababbbbbbbbbbcdccddbabbbbbba########aaababbbacdccccaabcbbcabddddbbaaabbabbbaaaaaaaaabbbddcddecbccbbbdcbabbbaabbcda#############abaaaa############a####bb##a####aaaaabcffdcccbbbbbbbb#######aaa###aaaa#######aabaaaabbcbaaaaaaaa#aaaaaabbccbbaaaaaabbbaaa####",
+"#########aaabbabcbbbbbdddcbaaaaa###############aabaaaa#aaaaaaaaaaabbabbdefffccbba###aa##aaaaaabcdceecggdcbbaa##aa#aacbb#bcdddddabbbbbabbbabbbbbbbccfeedbbbbbbcbba#a#####a#acababbbdcbcbabbabaabaabeedcaaaaaaaabcbbaaaaaaabbcdfdddccbbbbcbccbabbbaaabcda########a#aaaaaaa#aa#####aaabaaaaaaacb##aaa#aaababbcdefddbbcbccbaa#####aaaaaaaab##a########aa#abbcccbaaaaaa###aaaaabaabccbbbaaaaaaaaa####",
+"########aaaaaaabbbbbbcdedbbbbabaa##########aa###bbb###a##aaaaaaabbaabbbdfeedb##a#a##aa###aaabbbbccdefbfecbbbaaa####a#adb#acdecdfcbaabcbbbbcbbbbbbcdeffbcccabbcdbbba#a###a#aabaaaaaccccbaaaaabbbbaabdfedaaaababbbbbaaaaaaababbcedcccbbbbaccccbaaaccbbabeb######aaaaa#aaa###a######aaaaaaabacbca#aaaaaabbbbccdegfeccccccbcbaaa#####aaaa#aaaaa###a###aaaabbbcccb##a#aaa#aaaaaaaabbdeddcbabaaaaa####",
+"#########a#aabbbbbbbbdddccbbba#aaaa##aa##a####a#bba#a#a#aaaabaabbbabbeedeeefdaaaa#####bb##aaabbabcddehgifffdcbaaaa#aa#aaaaaccdeddcabbbcbbbccbabbccdceeecdcaaaabbcccaaaaaaaaaaaaaabacdddbaabaabbbbcccccfdbaabbaabbcaaaaaaababbcccccbbbbbbbccbcca#acbbbbbda#####aaaa####ab##a######aaaaaaabaccbaaaaabbbbbbccceffcdeedcbbbbaaaa#aaaaaaaaa#aaabaaaaaa##aaaabbbcbbcbaa#####aaaaaabbbcccddcbbaaaaa####",
+"##########a#aabbcbcbbcecccbbbabaaaaaa#####a#aaaabbaa##ba#acaaababbbbbbbcdcfgdbbbaa####aba##aaaabbbccdfefhfgedecaaa##abaaaaacbabebbbbbbbbcccbcbbbbddbedbddcaaaaaabdccaaba#aaaaaa#bbbbbaddccaaabcbbdcbbcbddabbbbbbbccaaaaaaaaabcddcbbbbbbbbbbbbbbaaaabbaabe#########a####bb#aa#####aa#aaaabccdbbbbabbcbbbccccdccbaaeffdbca#aaaa#aaaaaaa#aaaaabaaaa#aaaabaabbccbbcceb#bcaaaaaaaabbbbcdcbbbaaaaa####",
+"#######aa#aaaaabbccbbcdccddcabaaaaaaaaa###aaa#aabcaaa#bba#aabaabbbbbbabcccdfedcaa##aaa######aaaabbbbcdddghhgfedcbaaaa#aaaaabcbbbccbbbbbbbcbccdcccccbeebccbbbaaaaaccccccba#aaaaaaabaaabbbddbbbbcccbcccbaceeacbbbcbccbaaabbabbbbceccbbbbbabbbbbbbab#aabbbbcc#.######a####.bcbcba####aaaa#bedccbbbbbbbaabccddedaaaaa##beeda#aaaaaaaaaaaaaaaaaaaaabba##babbabbbbcbbbccccbbaaaaabbabaabddcbbbaaaa####",
+"##########aaaabbbbccccbcddddbaaaa##a#a#a###aaaa#baabbaaaaaaaabbbabcbaabccbddfebaaba#ba######aaaabbbbbcddfiiigggedbaaaaaaaaaabcbabccbbbbbbbcccddddccceecccccbbaaaabccddbbba#aaaaaaaaabcbbbcccdccbcbabcbabceecbabbbbbbaaaabaabbbcddbbbbbbbbaabbbcbbbbaaabcbdc########..####ccccba#abbaaaabddbabbbcabbbbcccceeca###aaa##aaa##a#aaaaaaaaaaaaaaaaaaaaa##aabcbbbbbbbccbbbbcddaaaaacbaaaabddbbaaaaaa###",
+"############aaabbabcddccdbcdcbcbbbaaaaa##a##aaaa##abaaabaaaaaaabbaacaabddabcefc#aabaaa###a####aaabbbbbbddgihhfffgeaaaaaaaaaaaaabbbcbbbbbbbbbcddeeedceccdcccccaaaaabcbddbaa#a#ab#aaacbbbbbbddebbbbccbbbabbbedbaaaaaaaaaaaabbabbccecbbbbccbbbbaabbbbcc#aaabbcc######a#####.bccabbacbababaabdcabbbabbabbbcbdecabaa##aaaa####aaaaba##aaaaabaaababa##aa#aaabbbbbbbbcbbbbacbedbaaa#bbaaaabcbbbbaaaa#aa",
+"#######a####aaaaabaabbcccbabbbbbbbcbaaa######a#aa######aaaa#aaa#acbbbabeeebabddbaaabaa####aa#a#aababbbbbcehhgeeffdca##aaaaaaaaaabbbbabbbbbbcdcdddfgfhcbbcbbbcbaaaaabcccdbba###baaaabcbbaabcdeecaaabbbbbbaabddecaaaaaaaabbbbbbbccfcbcbbbbbbbaaaaabbbcca#aabacc#######a####acdcbbbbbbaaaabbccaabbbbbbbabbceecabb#aa#aaaa#######aaa##aaaaaaabbaaaaaaaaaaaabbbaabccbbcbaaacgdaaaa#aababbbabbbbaaaaa#",
+"###a#####a#aaaaaabcbacbbddcaaabbbbbbbaaaaaa##a#####a####aaaaa#aaabdbcbbedefcaaabaaaaabaaa#a##abaaaaababbbcfgggfeefea##aaaaaaaaaaabcbbbbbbbbcdcdddefgeabbbbaabccaabaaceddeeaaa##aaaaaabbbabbcdedbabbbaaaaaaaacfecaaaaabaabbbbbbcdfdbccbbbbbaaaaaabbbcdbaa#aabdb#########a#acdcccbaaab#aabccbbbbbbabbbceedccbcbbaaaa#baa#a###a#a##aa###aaaabaaaaaaaa##aaaabbaaabcbbbbbabbdfeaaaa#ababbcbbaabaaaaaa",
+"#####a#####aaaaaabbbbbbbcddcbabccaaabbaaaaa#a##a##a######aaaaaabaaaaacbbbffeaaaababbabbbbbaa##bbaaaabbbbcccghghgeffbaaabbaaaaaabbabccbbbbbbcdddefggecccbabaaabbbacbabbdddecbaa####aabaababbcccdcabaa#aaa###abceedcaaaaabbbbccddefdccdccbcbbaaaaabbccdccdb#abbd###a#####a#a#cddcccaaaaaaaaabccbbbbdeefbba##aabaaa#aaaaaa#aa###aaa##a####aaaaaaaaaaaa##aaaabacbabbbbbcbbbbcfgbaaa#aa#abbab#aaaabba",
+"##########abaaabbbbbcbcdcccdcbbbcbbbbbba#aaaaa#a############aa#aaaaaaababbdeaaaacbbbbbddcbaaa##abaaaabbbbcccghhhedecababcbaaaaaababcbbbbbccbddceggffecccbbbaaabca#aaaadddedcb#a##aaaabbbabbbbcccdd###aaaa#aa##bcefeddcddccefdddfdcccccccccbbaaaaaabccccdddaabbda########ab##bbbddcbbaa#aaaabcbbbcdddccaaaaa#abaaaaaaaaaa#aa#aaaabaa#####aaaaaaaa#######aabaacbabbbbbbcbbbbdfbbaaaa###baabaabaaba",
+"###########aaaabbcbbbcccbddbcdccbbbbcabbaaaaaaaaa###a##aa###aaaabaaababbccbbdb#abccabddbbbba#aaaabdbbaabbbbcdehihbaabbbbcdcbbbbaababbedcbbaccdddeeefedabbabaaa#aaa#aa#beeeeffca###aaabbbcbbbbbbcced#a###a##aaa#abffgfedcccfhcbdebcbccdccccbbaaaaaabbcccccddbaabdcb#.#aa#aaa##abdddcbbbaaababbbbbcbdbabbbbbb##ababbbaaaaa#aa#aa##aaa######ababaaa#####a#aabcbbbabbbbbbcccbbbeabcbba###aaaaaaaaaab",
+"b#########aaaaababbbbabbbbdebcccccbbbabaaaaaaaaaaaa########aa#abbaaabbabbdbcbbbaaadcbcbdbabba##aa##abcb#aaabcdcfhgdabbbccdcbcbbbbbbabcgdcbdbbdedeeehfgdbbbbbaaaa#aaa#abddddgeedcaaaaaabbbdccccccbceeaa###a###aaaacfghhgedccggefbccccccccccbbbbbbaabbcccccccdaabaaccb#aaa###a##adedccbcbaaabbbbcbbcddbaaabbbbaadbbaabbaaa##abaaa#aaaaaaaa#aaabaa########abbadccaaabbbcccccbbdcbcbbba###aaaaaaaabb",
+"aa##########aaabbbbbbbaabbaccbceeebbaabbaabaaabbbbaaa###aaaba#aabaaaaababbccggcbaabccbbbccbca##aaaabdbbabbabbcdddghbabbccddcbbbcbbbbbccgfcbccceddddeddedddcbababaaaaaa#accdeffedbaaaaaaaacccccbbbccffb#a#####aaaaabfhgghhhhgghecbccbccccccccbbbbaaabbbbcbbbcdcbbabbcb#####abca#abccccccabbbbbbbbbdddbaaaaabab#cdba#aabaaaaaaaa#aaa#a#aa#####aaaa#######aabbbbccbbbabbdeddcbbeaabbcb###aaaaaaaaab",
+"baaa######a#aaabaabdbbcbabbaccccedaaaaaaaaaaaaaaadbaa#aaaa##aaaaaaaaabbbcbcccdbaaaaabdcbacbcdcaaaaaaaabaaccbbccdddhgcabcccdecbcbbcbbabadedbbcdedcddeeccdddeeedcbbcbaabbbabbcddddec#aaaaaabbcccccbccdffc##a##a#aaaaaafheffhgeccefcbbcbcccccccbbbbaaabbbbccbbddedbabbcc.##a##abc###cdcccbcbbbabbbaddccababbbaaabaddba##aaaaaa#aaa#a#aaaaa##aa##aaaa#######abbbbccbcbbbbdefeeccecaaaaa####aabaaaaaa",
+"bb#a########aabbbaaababcccdaacdbbaba#aaaaaa#aaa##acaa###aa#aaaaaaaaaaabcdcccaaaaaaaaadbcbbbbacc###aaaaaaaacbbccdcdfggbbbcccdecccddcbbbacdfdbcdebbbcccdcccccdcbefccbaaaaabcbbccabdfcaaaaaaabbdddccccccefe##a##aaaaaaaadfghhhdbbcccccbcbbccdccbbbcaaaabbbbdccddeeba#bbda######.acabbddccabcbbbbbbbddccaaaaaaaaaaabdca#a#aaa#aaaaa##a#aaaaa##aa##aaa#a##a##abbbbccbbdbbccefffeccd#a########abaaaaaa",
+"aa##########aaaaabaabbaaccdcaacbbaab####aaaa#aaaaaa#a####abaaaaaaabcaaabddcacda#aaabacbbbbddddcbaaa##aaaaa#abbdcccdegfbbcdcdefccddccccbcbbfdccecabccbcbbbcdddcbffdcccb#aacbaabcbbeecaa#aaaabcedddccccddfeb#####aaaaaabbehhfcccbcccccbbccccccbcbcbbaaabbbcdcceddcbbabba########bcbbcdcbbbbbbbbaacccccaaaaaaaaaaaabcba####aba##aaaaaa#aaaaaa##a#aaaaaaa#aaabaabbcbbbbbbbdffffeeeaa########aabcaaaa",
+"aba#a#aa####aaaaabbabbabbaccaaabaaaa#######a####aaaaa####aaa#bbaaaabaaacbddcbccaaaaaaaaaaacdeabcbba#a###a#aaabccccdeegfcbcdddeedcdccddccccfedddcbbccbbbbbbccddedecccdca#aaaaaaabacedcddcbabaabccccccccceccd####aaaaaabaacdghhfecccccbbccccccccbcbbbaabbbcccccddcddceaca########cdccdccbbbbbbbbbccbcdcaaaaaaaaaaaaaaba#####aaaaaaa###aaaaa##a####aaaa###aabbbbbbccbdbbbcdefffgaa#a#######aabaaaaa",
+"aa#####aa###aaababbccccbbbbcbaaababa#######a#aabaaaaaa####aa#abbaaaabbaabbdcbbcdbbbbaaaaaabcddbcbba#####a#aaabcdccceefhgbbdcceeeeccccccddeefeeecccacccbcbabbccdefdbcebaaaabaababbbcdcdfffdabbbbbcccccccecade#aa#aabaaaabaackijkidbbbcbccccccccbcbbbbaabbccccccccddegfdaa#######ceedcbbcaacccccbcccccbaaaaaaaaaabaaaaaaaaa####aaa.baa######aaaa####baaa#aaaabbbbbccdcbbcddedfgfb##########abbaaa#",
+"#a########aaaaaaccbbcdcccbbbba#aaaaaa#####aa#aaab#aaaa#.###aa#aabababcbabaccbccdedaaaa#aaaaabccacbaa#a######aacbcccdffhigeccccdeedddccbcddffdefcbabbbcdecbabbbbcddecddbbaaabbabbbcccddeeffabbabbbbcccccdecdedb#a#aaabbaaaaahifgikfcbcccccccccccbbaaabbcbbbccbbbbcccdhea#a#####aedfebccccbbcbcccccccbaaaaaabaa#aaaaaaaaaba#b###aaa#b#######a####aa##abbbabaaabbbbbcdecbbcdedefghc#########abcedcb",
+"a############a#abcbbbcddccbbbcaaaaaa#a####a#a###ba#aa#######aaba#bbbbbccaabcccddeebaaaa##aaaabaaabaaaa#####a#aaaabcbdeggihfccccdddffdcbcccdfcbcbbbbbbccbbbbabaabcdfebcbbca##aabbbbcdcdfffeeaabbbccbbcccdeeddeed##aaabaaaaachgcccfijebbcccccccccbbaaaaabbbaabbaabbcbbcfecaaa#aaadcddbbdcccabbcccbbbabbaaaa#aaa###aaaaaaaaaaaaa##aaaaba######a######a#abbbbbbabbcbbbddcabcddddefgfa########aacedcc",
+"#######aaa#####aaaccccddcdcccbbaaaaa####a####a#aaaa#aa#######abaaabbccacdaadccdddccba#aa#bbaaabaaabaaaaaa#aaaaaababbbdeffiiebcccdddeedcccdcfbcbbbbaabcbbbbbbaaaabcdeefeeddedbaaabcbdccefffffabbbbbbbbbcdcdddddefbaabbbbabaeidccddcejgbbccccccccbbbbaaabaaaaabaaabccccdffebaabbaaddcc#cdccabcccccbbbbbaaaaa#aaaa##aa#aaaaaaaaabaaaba#b##a####a#a#a##a#aabbabbaabbbbddecbbdcccddeega.##.#a##aab###",
+"#########a#####ababccbbbdcccccabbb##aaaaaa#aaaaa##aaaaaa#..###aaaaaaccbbdcbbccdbccdaa##a#a#aaaaaa#ba###a#a#aaaaaaabbbcdeefhgeccedbbcdedeedgebbbbbbbbcdcbbbaabaaabacccddccccbdcaabbadddeefffgfbabbbbccccccccdddbggbaabbbbabhefcccddddihdccccccccbbbababaaa###aa#aabbbcdeeffa.##abcfedabccbcccabcbbbbbbabaaaaa###aaaaaaaabaaaaaaaaaaaaba#######aaab#####aaabaaaabbbaceffecbccddccdec#####.##aa#aa#",
+"#aa########a####abbccbbccdcccbbbbba#a##aaaaabaa#aa####aaba#.##baaaabccdabdbabbbbbcccbaa####aaaaaaa#aaaa######aaaabbabccdfeehihfggfdbceedddeddfdccbbcbbbbbbbbbbaaabaccccbbccdddecababedefffffhgdaaabccbcccccdddbfhfbbbcbbackdeeccdddccfhgbccccbbbaabaaabba#####a#aabbbdeddeda.###aeddcbaaccccccccbbbbbabaaaaaaaaaa##aba##abbaaaaaaaaaab######aa##aa###aaabbbaaaaabbbeffffdcdcdeffda######.###aaa#",
+"#aaa############aabcdcbcdcfedeecbbaba##aaaaabaa###b#a##aaaa####abaaacdcaacdaacbcaaaaaaaabc##aaaabaaaaaa######aaaaabbbdddeddfhhhhhhfcccffffdbaabcbdbabbbbbbbbbbaaaaabbcccbbbbcfdedbbadeddeefdefhffecbbcbcccccceddgibbbbbbdecccbbccccddddhidccccbbaacaaabba########aabccedddeda####cdcecbccccddddcbbbbbabbaaa#a#####a#######abaaaaaaa#aaaa#a##aaaa#a####aabaaaaaaaaabccddfgfddefge################",
+"##aaaaa#aa######aaabdccbccdeefebbaccb###aaabcbaa########aa######aaba#bdbbbcabbbbbbaaba##aba#####ababaaa##a#a##aaaabbcddedddeeefhghfddccdhecbbbaaaababbbabbabcbaaaaaabbccbbbbbbeefdbbbddbddffdggihiebbbcbbcccccedeicbcbbcdccccccccddddddcfifccbbbbabbabbbaaa####aa#aabcedddefeb##.bdcdeccbcccdddcbabbbbaaaaaa#aa############abaa#aaaaa#aaaaaaaaaa#######aabaaaaaaaabbabbcefgecbcc############a#a#",
+"##aaaa####aa##a##aaabcdcbbccdcdccbcaba##aaaabbbaa#aa#a####a######aabaaabaaaaaaaabbba#aa###a##a###abbbaa#aaaa#a##aabbcededddddeghggcdfedffddcbbbaaabbbbbccabbbbbcaaaaabccbbbbbbeccefdbcdbcbcefefhgghdbbcbcccccccdcefedbadccbbcccccddddddddeggcbbbaacaabbbaaa######aaaabdcdeedefbaa#deddcdcbbcdedccbbbcbaaaaaa##################aaaaa#aa##abaaaa#aaa#aa##aaaaaaaaaabaabbacdbacbaaba###############",
+"##a#aaa####aa##a##aaabbbbbcdeccbbaaaaabbaaabbaabaa###aaaa#########aaab#aaaaaaaaabbaaaa#a#a#aa#a#aabaaaa###abb##aaaaabcdeeddefghhhebbbfebbdddccbbbbbaaabdcbcbcbacbaaabbabcbbcccddbbcefecdcbbbcddehgggcbbcbcccccccdddffbbdbbbbbccccddddddddddegcbbaabaaabbbaaa######aaabbbcdefdeca#ddedcdddbacadedccbbbbbabaaaa###############.####aaa##a###a##aaa#aaa#abaabaaaaaaaaaaaaabcdbaaaa#a########a##a###",
+"a##a#aaaa#####aaaaaaabcccbbcdebbaaba#a#bbaaabbaaaa####aaa#####aa#abaaaaaaaabaaaaaabbbaaaaaa#aaaaaababaaa####aaaaaaaabcddddefedhhgbbbbcefbcdedcedabbbababbbcbbbbbbaaabbaabbbbbcbcddbbbcdcebbbbdcabehhebbbbcccccccceddhfddbbbbbccccddddddddddcdfdaaaaaababbaaaaaaaaaaabbbbccddcdfededffddddcbcabcddccbbcbbaaaaa#####################aa##a#a#######aa###aaaaaa###aaaaaaaaaabbccaabaaaa######a######",
+"aaaabaa##aa####aaaaaabbccccbcccaabbba#a##aaaabbb######aaaaba##aaaaababb##aaaaaa#aabaaaa#aaa#aabaaaaaacbaa####aaaaaaabcdeddefefhheabbbbbdfgfgedcfaaabbbbbbaaaaaacabaa#baaabbabaabbdeeeccabdccbbbcaachifbbbcccccbcccddejkeabbbbccccddddddddddccceebabbaabaaaaaaa#aaaabbbcbbcccddefgedfedddcccbaabcdcccbcbcaabaaaa########.##.########aa###a########aaaaa#a###a###aaaaaaaaababccaabaa#########aa#a#",
+"##aaaacb########aaaaabbbbcccbdcddbbcbc#aaaca##a#aba######abca#aaaa#aa###aa###aaaaaabbaaa#a###aaaaaaa##bcbba###a#aaaabbceedddehgfdaaabaccbfhiihffcaaaaccbaaaaaaacabaaabbaabcbbbbbbbcbdeffedfdb#acaabafjgbbcbcccbccccdefiicbbbbacccddddddddccccbbcfbbbbbabaaaaaaaaaabbbcbbbbccccdegfecfdbaabdabbbbcccdcccbbbbaaaa###################a#aa##a#a##a####a#aaaaa###########aaaaaabbbbbaabaa#######aa###",
+"###aaacba#######abaabbdcbbcdcbbefcbabcbbaaaaa####aa#a#a#a#a##aaab###a#aa####abb#a#aacbaa####aaaaaaa#aaabdcbaaaaaaaaabaceefeeffffbaaabbabccehigfeeddefdbabaaaaabbbabaabaaaaabbbbbbabccbabdedda##aaabbachhbbcbccccbbcccdeghebbbaccddddddddddccccbacecbabaaaaaa#aaaaabbbccbbbbcccdcdgfdfebbbbbcccbcbcddccccccbbaaaaa################aabbaaaa####aa###a##aba#############aaaaabbbddbbaba##########.#",
+"####aaaba#######aaaaabdfdbbcccbbdebbaaaab#aaa#a###aa###aaa###aba#####aaa#####aba#aaa#baaa#####aaaaa###aabcccaabbbbbcbbbdfffgeccebaaabbbbcbbeffedccfghhebaaaaaabbaaaaaaaabaabbabbbbbacbbbbcbdda####abbabghabbbccccbbccddddghdaabcddddeedddddcccbbabdfdaaaaa##aaaaaabccccccbbccddcbefdffdcbbbcdccbbccddcccccbbbaaaa################bbccbaabaa#aaaaaa#aabba##a#########a#aaaaabbccbcabaa###########",
+"#####aaaba#######aaacccefcccbcdccbcbbaaaaa#abcba#########aaaaaaa######aaaa####aa##aaa#aaaaaaa##aaaaa##aaaccddcccdddddcceeffdccdccbaaaaabbbbcfggdddfffggfebaaaaaaaaaabaaabccbbbbbbbabccbbbbbcbdb###aabbbbghbacccccccccccdddfigdbcddddddeddddcccbbbabbfeabaa#####aaaabcccccbcbdddecegfffcccabbccccbbccdcccccbbbbaaaa############a#aaaababaaaaaaa#aaa##aaaa#aaa##########aaaaaabbcccbbdba#########.",
+"#####aaaaa######aaabddefcccbabdccccbaaaaaa###aaa######aaabaabbba#######aaaa####a###aaaaaa#a##a#aaaaaaaaaabcddddcdeeedefgfefecdaabbaaaaabbbbbadfebcfdfgffeeecaaaaaaabaaacabdbaaabbbcdcbbbbbbbbccb#a###abbaegcabccccdcccccdddcfihfdccdddddddddcccbaaaaaddbaa######aaabccccbcbccdddhfcfgecccbbbbcbccbccbccbcccbbbbaaaa#a##########aaaaaabccbcba#aa#aa#aaaaa#aaaaa###########aaaabbaddedaa##a#.#####",
+"####aaaaaa#######cffdabcbcdcbbadfbcbbaa###a#aaa#aaaaaaabaaaababaa#######a##a#########aaa##aa##aa#aaaaaaaaabdeddccddddddffeeeec#a#aaabbbaaabbbcggdcfeeeeegfdccbabccbbaaabbbcaaaaabbbcdbbbbccbbbdbaaa###abbccebabbccccbcccccddcdfhjhedddddddddccbbaaaaaabdda#######aaabbddccbbdddedccdgeeedccbbccdccbccbcbccccbbbaaaaa#########.##aaabbaabbbcbaaa###aaaaaaa#a#a#a########aaaaabbaccddeb###########",
+"########aaa######acddbabcbbcccabcddcaabbaaa##aaaaaabbbcaaaabbaaaaaba########aaa#aa###aaa###aa##abaaaaaacbbbcdffeddeccdffffeddbaaaa#abbaaaabaabegebdfeddeffeddddcdddcabbacbcbccbaabbacccbcdbbbcdb#aa##aabbbbbffbbccccbccccccdddedfkkidddddddcccbbaaaaabbabdb#a#####abcccdbccccddfcccdfgeedccbbbcbccccbbabbcccbbbbbbaaa############a#a#aaaacacbaaa####aaa#aa###a##a######aaabaabbbbbbdfa##########",
+"#################abbcbaacccccbccaacbcaaaaaaaaaaaaaaabccabbbbaaab##bb######a#aba##aa##aaaaa##a#a#acabbbacdcbcddffffdgeefefeddcb#a##aaaaabaaaaaaddfdcfdccccccdcbcbcccecbbabccdddddcbbbbccccccbbbceb#aa###aaaabbfgbacccbcccdcdddeedgjkihccddcccccbbaaaabaabaadca####aabbcccbcddccefdcdeeeedddcacbccccccbabaaabbbbbbbaaaa###########.#####aaaabacbba##aaaaaaa####a####a######abbabbcbcbcdb###a##.##.",
+"###########aa#####bdbaaaaccddbbdcba#bbaa##aa#aaaabbbbbbaaabaaaaba##aa.####aaa##a#aaaaaabbbaa#####abaabbbbbccdddeefeffddefdccaa####aaaaaaaaaabaeefdedeccbabbbdddbbccccabbbbbbbbcdcccbcccccccccbaaaa#a####aaaabacgcabbcccdddefffedgijfehdcccccccbbbaa#aaaaaaabcbaaaaaabbccdcdddefgecddeefedccbbbabccbbbbaaaaaabbbbaaaaaa################aaabcbabbaa#aaaaa#aaa###a####a####aaabaabcbbbcbba###aa####",
+"############a#####abaaaaaabddccbcdddbaaaa###aaaabaaabbbaaaabbabba###b######aa######a##aacbcbba##a##babbccccdddddeeefgfeedccdb####a#aaaaaaaaaaadefedecbabbbbbcddddbcddcaabaaaaaabbbbbaabbccdcccbbbcb#a##aa#aaabbbfdbbccddddeffffefggeedjhedcdcccbbaaaaaaaaaaabbcaaaaabbcdcccdeefgdcccdefeccbbbbbbbccbbbbaaaaaaabbbaaaaa#######aa######aaabbbcab#a#aaaaaaaa#a##a#####abaaa#abaabbbbbbdccc####aa#.#",
+"###aaa###a#a#a####aabaaaaaabdbbbcecdcbaaaaaaaa#aaaaaaaaaaaaabccbb###a########a#a#aaaaa##aaaabca#a##aabbccccccdcccbbbbcbcabbbb#a#a#a#aaaabaaaabbeffddeabcbbbbcccccdccbbbaaaaa#abaaaaaaaaaababbbbbcbb#a##a##a#aaaabefcbdeeddeffffffeddfbchjieccccbbbaaaaaaaaaaaacfcabbbbcdddcdehggffeeddgfecbbccbbbccbcbbaaaaaaaaabaaa######a##aaa####aaaaaaabbaa##aaaaaaa#aaaa#####aabbaaaabbbbbbccccddbaaaa####.",
+"####aaaaa#aaaa#aaaaaaabbaaabccbbbcddbbdcbaaaaaabaaaaaabbbbaaaaabaaa###############aaaaa##a#aaaaaaaaaaabbccccdcbbbaaaaaaaabaaa#######aaaaabbbabaacffffbbbbbbbbbbbbccccbaaaaaaaaaaaa##aaaaaaabbccca#######aa###aaaabcgfcdeeefgggggggeffcbbehkjebbcbbaa##aaaa#aaaadheabbbcdddcegfbccdfffgggedccccbbbbbabbbaaaaaaaaabaaaaaa######aaaaa#aa##aaaabaaaaaaaaaaaaa##aaa##aaa#acbaaabababbcccdecbaaaa###a#",
+"#######a###abaaaaaaaaaaabbdccccbbbceefebcaaaaaa#aaaaaabbbcccaabaaa###aaa#######a###aaaba##aaaaaaa#aaaabccccccbbbaaaaaaaaabaa###a###a#aaaaacbababa#eeedbbbbcddbcbccbccccaaaaaaaa#a#aaaaaaaabbbbcba########aa####aabbbghdeeegggggghggfedbbbcdikgbbbbbaa#aaaaaaaaaabheaabccddegdccccdddccfffddbbabbbcbbbbbbbbbbbaaaaaaaa########a###aaaa#a#abaaaaaaaaaaabbabaaaaaaa#a##ccaaaaaaaaaabcccbacaaabaa###",
+"##a#aa#####aaaaaaaaaa#aabbbabbcbbabcdeedcbbbaaaaaaabbbccdddccccbbccbdcbcca########aa####aa##a#aaa###aabbccdccbbbaaaaaabaaaaa#########aaaaabcaaabaa#dfcccbcccbcccccdccccdbbaaaaaa###aaaaaaabbbcb######aa###aaaa###abbcfheeffghhghhijifcbbbbbehjhcbbba##aaaa##aaa##afgdbbcefecdcdccddddddeedcbabbcbbabbcbbbaaaaaaaabaa######a#a#a###aaaa#aaabaaaaa#aaaaaaaaaaaaaaaa#a#bcaaaaabaaaaabbcccbcabbbaaa#",
+"aaaaaaaaaa#aaaaaaaaaaaa#abaa#aaaaaaaaabcbbaabbbabbbbccddddddefdbcdccdecddcaa##aab######baaaa##ab###aaaabbbcccbbaaaaaaaaaaaaaa########aaaaaacdbaabaa#dcabccdddcccccdeeddddddbaaaaaa###aaaaabbbca#a#########a###a##aaabcegefgfhhggiiihddbbccbbfegihfb###aaaaa#aaaa##adgfefecbddccccddcedccefdcbabcdcaabbbbbbbaaaaaaaaaa#a####aaa#aa###aaaabaaaa#aaaaaaa#aaa##aaabaa##abcbaaa#aaaaaaabbbbdddbbbaaaa",
+"aaaabbabaaaaabaaaaa#a#aaa#abaaaaabaaaaaaaaababbbbccdddeeefdfffedccbbbbcccccaaaaacb#abaab#aaba#aaa###a#aaaabccbaaaa##aaa#abaa###a##a#aa#aaaaacca#abaaadbabddddfededcbbcaaabcddcaaaaaa###aabbbcdca######a####aa##aaaaabbcdkgghhhhhgiigecabbbccffedgiida#aaaaaaa#aaaaaabfecbccccbbbabbbddddddccbaaacdcbbcbbbbbbbaaaaaaaaa##################baaaaaaaa######aa#aaaaa#a##abbbbaaaaabbaaaababbddcbbbbaa",
+"aaaaabcccbbbaabaaaaa#aaaaa#aaaaaaaaaaaaabaaabaaabbbcdffefgffdcccdddcccccbaabaaacbab#aa##aaabb#a#a##aaaaaaabbbcaaa###aaaa#aaa#a###aaa#abaaaaaacccbaaaabcbaaccbbdccbbbababba#abccbaaaaaaaaaabdeabaa##########aa####aaaabbceghghhihiihhgcbbbbbbegdcdedhhdd#aaaaaaaaaaaaabdccccccaaabbbbcddddfeffdbbabcbbbbbbbbbaaaaaa###a#########aa#######acbaaa#####aaaa##aaaaaaaaa#a#aaaaaaaaaabbbbaabbccddbbbba",
+"aaaababbbccbbcbaaaaaa#aaabba#aaaaabaaaaababbbbbaaaaaa#aabbcaaabbbbbbbbbcbaaaaaabaaaa####a##aaaa######aaaaaabbbbb#######a#aaa#a###a##a#aaa#aaacbbcbabbabcabbbcddbaaabbaaaa##aaaabbaaaaaaaabbcdbaaa###########a####aaaaabbbcfihghhhihhhdabbbbbbeeccccbdehfaa##aaaa#aaaaaabedccbaaaabcdcddcbfeffddeedccbbbbbbabbaaaaa#############aa########ababaa###aaaaa###aaaaaaaaa##abaaaaabbbbbbbbbbbbcdffabaa",
+"aaaaabbacbbbabaaaa#aaa#aaaacba###aaabaaaaaababaaaaaaaaaa##aaaaaaaaababbccc###aabaaaa##a##aaaaa#aa##aa#abaaaacccb##a#a#a#aaaaa####aaaa###a#aa#ababdbbbabcbabbbbbbbbbcbbaaaaaaaaaaba#a###aaacbcdaaaa#########.#####aaaaaabbccfkjgfhhifdfdaaababbffcbbbbbacgda#aaaaaaaaaaaaaddcba#aabccccdbbdeefeddfdfecbbacaaaabbaa##############aaaaa#######a#aa###aaa####aaaaaabaaaaaaaba#aaababbbcccddddgihcabb",
+"baaaaababccccbbaaa##aaaaaaa#cddb#####aabbbbaaaaaaaaaaa#####aaa##aa#aabadedca#abbaaaaaa####aaaa#a#aaaaa##aababcbca#aaaa#####aa###a#aa##aaaaa#a#aaacbaabbbcbabcccbbbbcbabba#aaaaaaaa#bbaaaaabbadb###################aaaaaabacbgkkihhggfedaaaaaaaceecbaaaaabffgeca#aaaaaa###acdca#aaacbbccbcbeeefffdabdfecabaaababbaa#a##########aaaaaa#######abaa##aaaa#####aaaaaaaaaaaaaabaaabaabbbbbcdegghffdabb",
+"bbaaaaaabbcccccbbaaaaaaabaaaabccca###aabcceebaaaaaaaaaaa#a##a#####aa#aaaddbbaaabaaaaaaaaaaaaabb##abb#aaaaaaabcbba##aaa###aaa#########a#aaaaaaaaaaaaaabbbccbaabccbcbbbbbaaaaaaaaa##aaabaaaaccbed#################.##aaa#aaaaacekljihhhdbaaaaaaabdeedbaaaaaabceffdaaaaa#####abdd##abbbbccccbcedfeddbbbbdddbbaaababaaa#################aa#aa.###aa##ba##aa###aaaaaaabaaaaabaaaaababbabbbdfhjifeecba",
+"bbbaaababaabbcccbaaaaaa#aaaaa#aaba##aaabcbbccbaaaaaaaaaaaaa#aa####aaaaaabccbaaa#aaaabaabaaaa#abdca#acaaaaabaabbaba#aaaaaaabba##aaaaaaaaaaaa##a#aabbbbbbbccbbbacbcbabbbbbaaa#aaa##aaaaaacbccccdbbba#a########a#.####aaaaabaaaaafklljhfcaaaaaaaa#dcgfcbbaaabccccdggcbaaaaa#aaaacdaabbbbbbbbcbddeeddccccbbcecbaaaaaaaa#a##############aaa##a####aa##b###aa#aaaaaaaaaaaaaa#aabaaaaaabaabbdggghhfbdeb",
+"bbabbaaaaaabbcbccbabba#aaaa##a#aaa#a#aaabbabbbaaaaaabbabaaaa#a#####aaaaaadcba###aaaaaaaaaaaaaaabbaa#abaaaabbbcbaa#aaaaaaaaaaaa#aaaaaaaaaa#aaaaaaaabbbbbbbcbababbbcbbbbaaaa###a###aaaaaaaccddcddbaaba#aaaa####a#.#.#aaaaabbaaa##djlljc#aaaaaaaa#afdfebaaaabccccddegfdbaabbbbbbabddbbbbbbbbbadceedcdcccbbabdebaaaa#aaa#############aaaaaa#ab####a##ba#####aaaaaaaaaaaaaaaaaaaaaaaaaabcdfebbbabbbcc",
+"ecabbaaaaababcdcccbbbcdbaaaabbaa#aaaa##aabcbbbaabaaabbaabaaa#aa###aaaaaabecbaa#a#a#aaaaaaaaaa#aaaaaaaaaaaabbcbaa###aaaaabaaaaaaa#a####aaa#aabaaaaaabbbbbbdcbbabbbcbbaaaaa####aaa#aa###aaabcccccbaabbba##a####aa#####aaaabaaaaa##ahlkfa#aaaaaaa##fbbecaaaabccbcdddceghecbbccccbbbccddbbabaa#ccedddddccbbaaacfbaa#a##a############a##aaaaaaaaa##a###ca#aa###aaaaaaaaabaaaacabbaaabbbbddea###aaaabc",
+"abbcbbbbaaaabbccbbbbaaaa#a#aaaabcaaaaaa#aabbbbaabaaccbbabaaaaaaaaaaaabbabdcbaaaaa###aaaaaaaa#aaaaaabbbaabbbabaa#aaaaaa#aaacbbaaa##aa##aaaaabcbaaaaabacbccccabaabaacbcbaaa####aaaaa####aaaabdccdba#abbaaa#######a######aaaaaba#####dljfa#aaaaaaa#ddaadcbccbbbbccccdccehihfddccccccbbdfaaaabbbceefedddcbbbbaaaecaaaaa##a###a####a##a##aaaaaa####a###ba#aa###aaaaaaaaabbbbacbbbbbaaacccdd#####aaaab",
+"babbbcccbbbaacdbccbbbaaaaa######aaaaaaaa##abbbbabaaabbaaaaaaaaaaaa##abbbdcccbaa#aa#####aa#aaaaaaaaaaabcbabbabaa##aaaaaab#accbaaaaa#aaaaaaabcddbaaaaabbbccccbaabbbbaabbbbaa###aaaaa#####a#abceeeaaa#aaaaba#######a#######aaaaaaa###.cgjgb#aaaaaaaafcaacdcdcbcbbcbbccdeefeeghfeccccbcddc#aabaaaeffeccccbbbbbaaacdcaaba##aa##a#aa#aaaa#aa###a####a####b#a##aaaaaaaaaaaaabbbbcababbbbcdddeb#a#####aa",
+"bacbbcddcbbbbacddccbabbaaaaaa#a##aaaaaa####aabbaaaaaaabaaaaabaaaaaaaaabbcccbbabaaaaa#a#aaaaaaaaaaaaaaaabbccbbba##aaa#aaaaaabbbaaaa#aaa##abbaabbcbaabbcccccbbbbbabbbabbbbaa#############aaabbcedbaaaaaa#aaa######a########a#aaaa##a##adhjc#aaaaaaacdb##bddcbbbbaabbccefgecceffgfcbceccedabbaaacffdccbbbbbbbbbaabccbbaaa#aa####a###aaaaa#a##bb##a###ab##a###aaaaaaaaaaabaaabbbcbcbbbcefeb#####aa#a",
+"aaccbcddcbbabcbcddcbbbcbaaaaaaaa#aaaabaa##a#aaaa##aaaaaaaaaaaaaa#aaaaaaaaabbccaaaaaaa#aaabbaaaaaaaaaa##aabccccbaa#aaaa#abaaaaaaaaaaaaaabbbbaabbaccbddedcbbbbbabbbcbcbbcaaaa############a#aacbcba##aaaaaa#aaa#a###########a###aaaaa####adid#aaaaa##eca##addcbbaaaabbcddefddefddgiedccccffbaaaaaefeccbbbbbbbbbaabacdbbba####aa#a##a##aaaaaaccbba###.aa#aa#ba#a#aa#aaaaabbabcbccbcbcccegc######ba#a",
+"abcbbccdedcbbbabdddcbabbbbbaa##aa#aaabaa######aaaaaaaaaaaaaaa#aa#######aa#aabcbbaaaaaaaaabcaaa###abaaa#aaabcbcb#aa##aa#abbaaaaaaaabbcaaaaaabbgecbbbbccbbbbbabcabbcbbbbaaaaa##############aaabaaaa#aaba#######a###########ba#aaa#aaa###aabffcaaaaaabeb####cdcbaaaaaaabbccdeffeeegihfddddffcaaaabefeccaabbbbbbbaaaabdba#aa####aaaaa###aaaacccbbba#######aaaa#aa#a##aabbbbbbbccccccccddgf#aa##a#aaa",
+"aabcdddddddbbbccabcdccbaaaaaa#####bbaaaa#######aaaaaaa###a#####a#########aaaacbbbaaaa#accdddba#a#aaaaaaaaabbbcbaaaaa#aaaabaaaaabba#bdaaaaabeecbbcbcbccbbbbabbbbbbbabbbbaa#aa####a########aaaaacaabaabaa#######aa########abbbbaa##aaaa###aaegfb#aa##dcaaaabddbaaa##a##aaabcdfgffgiggfffedefea#aabffccbaaabbaaabaaaaacbaaaaaaa####a##aaaaaabbabaaa##aa##aaaaa######aabcbaabbccccbbddedeeaaaaa#baaa",
+"aabbdeedeedddaccbbbcbcccbaaaaaabbaccaaa#a#aa###aa#aaaa#########aa#a#####a##babbbbbcbbcfdccccbbaabaaaaabaabbbccbbaaaaaaaaaabaaaaaaaaacfcaaabcbbaaababbcaabbbabbbbbaaacbabaaa####a##.########a#abd##baaaaaa##.###aa#######abbadb#a#########aaeiib####bca#aabadcba########aabccdgghgfeddddeedegdaaabdedbbaaabbabbaaaaa#cbaaaaaaaa#a##a#aaa#abbbbaaa#aa##aaaaaaa#####aaabaabbbbccbbbcdecef######acaa",
+"baabcccddedddbacccbccdcbbbbaa####aa##aaa###a###aaaa#a#####aaaa#a#aaa###aaaaabbbbbabcgjfdccbbbaaaaaaaaaaaabbacccba###aaaaaaab##aaaabbbdfdbaabdecbbbabaabbbbbbbbbbbbababbaaaaaa######.########a#acdb#aaaaaaa######aa######abbccb####aa######afiifa###bca#aaaabcbba#a######aaabcdeefcbcedccccceffaaaaacdbaaabbbaabbabaaabcbbaaaaaaaaa##a#a##abbaaaa#ba##aaa###a####aaaaaaaaaaccbbbcccdeff.######aaa",
+"a#aabbbcdeddcccbcccccdcbbabaaaa##a###aa#a#a#####aa##a###a##aaa####aa#a#a#aaabbaabbbbbffdccbbbabbaaaabbbbbabcbbbaaa##aaaaaaaaa###aabcbbcdfdaacebbbbbaaabbbbbbbbbaaaaabbabaaaa###aa############abcdcaaaabbaaa######aa#####abbbdc#############adghf###cdaa##aaaabbaa##.##.##aaabcdecedbbcdecbbbccebaabacdaaaaabbbbbbbaaaaabdcbaaabaaaaa##aa#aaabaaa#bcaaaaaa###aa#a#a#aaaaaaaaababccdceec##########",
+"###bbbbcdeddddcccccbccbccbbbaaa#####.#a##aa######a##aaaa###aaaaa##a###aaaaaabbbbbbbccddcdcbbbbbcdbbbadecccccbcb###a###aaaabaaaa###accbbccfhcacbbbabbabbbbbbbbaaabbbaabbbaa####aa#########.####aabcbaaaabbaaaa#####a#####aabacfb###############dhhc.ddb###a###bbca#.#....##aaabcdccecbbccedbbcccedbabbdcbaaaaaaaabaaabaaaacccaabaaaaaaaaaaa#abaaabbcaaaaaa###########aaaaaaababbbceeda.#####a###a",
+"#baaabbcdeddddddddbbcccbcbbbbaaaa################aaababba####aaaaaa###aaaaaaabbaabbdecbccccccbbbccccbcbbbcbbddeeca###aaaabccaaaaaa##abbbbcdedbbabbaaaaabbbbbbbbaaaaaaabbaa#######aaa##########aabbbaaabbaabaaa########aaaaaabdfb####aa#########cghhceba###a##aabaa#.....###aaabcdceebbbbbddcbccbcdcabcedbbaaaaaaaabaaaaaa#cddbbbaaaaaaaaaaaaaaaaccbaaaaaba#a#a######a##a#aaaaaaccdeed####aa####a",
+"aaabaabccceeddeedcabbbcbbcbbbbbbaaaaa#########a##aaaaabbcbaa#aa#aaaaa#aaaaaaaaaaabbcddcbbbbbbbbbbbbbabbbbbbaabbdgfba#aaaaabbaaa##aaaaaabbbcceedaaaaabbabbbabbbbbbaaaaaabba#######aba#########a##abbcaabcbaabbba########aabbaabddca#aaaaa#########adjhaaa#aa#####aaa#...####aaabbcccfdabbbbbddcccbbccacffccbaaaaaaaaababaaa##bccccbabaaaaaa#aaaaabdcaabbaaaaa#########a#a#aaa###bcddhga####aa####",
+"##aabbbbcdffeddeebdcbbbbbcbbcbcbaaaaaa##.##aa######aabbbbaaaa#aaaaaaa##aaabb#aaaaacddfbcbabbccbccbbbaabbaaba#abadfdbbaaaabcaaaaaaaaabbbababbceedaaaabbabbbbbbbbbbaaaaaaaaa##.#####aa#########aaa#aacdabbbaaaaaaaa#######bbbbccdcddbaabbaaa####aa###bhgea#######.##aaa#####aaaababbbcebababbabdeccbbbceffeecbaaaaaaaaabaaaaaaa#bcccbbbbaaaaaaababbbbbaaaabaaa#######a##a#aa#aaaaabddhg###########",
+"#a#aaabcdddffdddeeedbbbbbcbbbbcbbbaabaaa#a##a##aacaaaaaaaaaa#a##aaaaacdaaaabaaaa#accdeaaaaabbbbccbbbbaaaaabbbababcdddcccbbaaaa#aaaabbbaaaaaabdeeeaaaaaababbbbbbaaaaaaaaaaaa###a####ba####a####aaaaaabecaa######aaa#####a#ababccccbcbabaaaaaaa###a####dijdb########a#a###aa##a#abbbbddbaaaaabbabdddcfeffffeccbbaaaaa#aaaaaaaaaa#abccbcabaaaaaaaabbaaababaaaaa#aaaa###aaa#aaaaaaaaabchga#####aaa##",
+"#a#a###abccdddefdeeecbbbbbbaabbbbbbbbba#########abaa#aaaaaaa##a#aaaaaccbaaabbabbcbbccfbcaaaababbbbbaaaaaaaaaaaabbbabbabaabaaa#aaaaaabbabaaa#abcdfea#aaaabbbbaaaaaaaaaaaaaaaa#######bba##########aaaabcedbb#######aa#####a##abdcbbccbaaaaaa#aaaaa#aa###bgjjga#######aba#aadba##aabbbccbaaaaabbaaabedffeffffdcbbaaaaaaaaaaaaaaaa#aaaccbbbaaaaaaaaaaaababbbaaaa#aaa#####aaaaaaaaaaabbbghc#####aaaaa",
+"a##a#aa#aabccbdfgeefeccababbbaabaabbbaa#a##.######aaaaaaabba##aa##abbbcbcbbccacbbdedgheccbbabbaaaaaaaaabbaaaaaaaaaaaaaaaaaacbbba#ababbbbaaaaaaabdeeca#aabcbaaaaaaaa#aaabaaaaa####.##ba###########aaabbceeba########a#########cbbbabbbaaa#aa#aaaaaaaaa###djkjb#b#..#abbcaaabcba##aaabbcaaa#aaaaabaacfffffedffccbaaaaaaaaaaaaaaaaaaaabcbbaaaaaa##aaaaabaaabaa#aaaaaaa#a#a#a#aaaabbbbccgc######aaa#",
+"##aaaaaa##aaccbaeihfgggcbabbbaaaaacbbceceeca########aaaaaabaaaaaaaabbbdcccdebbcbbabacedecbbbabaa#aaaaaabbbbaaaaaaaaaa#aaaaa#abbbbacbbbbbbaaaaaaaccddbbbbbbbaaaaaaaaa##aaa#a##a#####aa#############aaabbceeea########a########aaaaaaaabbaa###a###aaa######agjkhgfb.#aabddaaaaaaa###aabdb##b###aaaaa#cffffeeeeeccbaaaaa#aaaaaaaaaaaaaabcbaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaabbbbbdfeba####aaa#",
+"#a#aaaaa###aacca#cjjhhjebcbaa##a##acegebdcbdb#.#cbcaaaaaaaaaaaaaaaaaabbcdgiecbbaaabbbcbcdcbbbbbaaaa#aabaabcbaaaaa#aa#aa#aaa###aaaaaa####a###aaaabcddbcbbbaaaaaaa#aaaa#aaaaa##a#####baa#.#######a##aabbcdddffa##.####aa##.####aaaaaaaaaabaaa###########a####chhiihc..ceffbabaaabaaaaabccaacc###aaccbbegfffededdccbaa#a#aaaaaaaaaaaaaaaabcbbaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaabcccefeaaa###aa#a",
+"aaa#abaaaa##aaba##eiiikhccbddefeeffgecccdccdeffefddc#aaaba#aaabaabbaaaabcdhfbbbbaaacdecbbaabbbcbbbbaaaabbbbbbaaaaaa#######a###aaa#aaaaa######aaaaaccbcbaaaaaaa####aa##aaaaa#####a##############a##aaabcccccdfb##.#####a######aaa#aaaaaaaaaaa##########aaa##.#aejjifb#cffacbbbaaa#acbbcc##ddda##cddeefgfffeedddcabbaa#aaaaaaaaaaaaaaaaaaacbbaaaaaaabbabbbcaabaaaabbabbbbabbbbbbbbbbbdfc####a##aa#",
+"#aaa#a#a##a####b###dgkkjgccfiifdfdeeccddddcdcccccbca#aa##aa#aaaaabbbaababeggdbaaaaadfcbbbbbbcccbabcbaaaaabcabbbcbaaaaaa##########a#a########aa##a#accbbaaa#########aa###aaaa###aaa####.#########b##aabcbbcddfb###############aaaa###abbaaba#aaa#########aa#####djjjifbcebccdcba#bbacbcb##addccdcdeeefgfffeecbccbbbaaaaaaaa#aaaaaaaaaaaaaabbaaaaaaabaabbbbbaabababbbbbbbbbccccbbbbcced####a###aa#",
+"a##aaaaaaaaa#a#ba..#agkgfecfikgddcccdcccbcccbcbcbbdba##bccaaa#bbccccbaabbefffcaaaabdfbbbbbbbbccaaabaaaaaaabcbbbabbbbaaaa#######aaa############aa###abbaaa####a############a####a#######.#####a##aaa####aaaacfa#######..######aaaa###a#cdcbbbabcbaa#aab#########.chiiihfcddeghhgdccdabdaa#addcddceefeeffeeeedbbcccbbaaaaa#aaaaaaaaaaaaaaaaabbbbaaaaaaabaabbaaaababbbbbbbcccdccdcbbceea####aa###aa",
+"a####aaaabaaabbab#.#aaeecdhfijfcccddcccbbbbccbbbccaaa###.a#abccccbcbcbbbbbff#a###abcebabbbbccbcaabbaaaaabccbbbbbbbbbbbaaa#aa####aa##############aaaa#ababaa##############a#a######a####################aabbcacaaab#####.#.##abbaa###aaabcacbcaaaaaaa#aa#########.bgihiifcdgijjjiidaaabe#a#bdcbccccddddddecdecbbbccbbaaaaa##aabbaaaaaaaaaaabbbbbabbbaaaabbbbbaaabbbbbbbccdddedddefeffa####a#####a",
+"#######aaaaaaaaaa#.#abcdaahkkjgbbcccbbbbbcbbcbbbbaaaa#a######abddedccccbbacffcbb##acccacdcabbdccdbabaaaa#abbbbbaabbbbcba###a############.##.###########ababaa##################a##a###.################aaabcbcdbbbaa##.#.#.#aabaa###abcdcaabaa####aa#aabbb###a###.#bgjhacegijjjjjjhedfgea##cbbbccbbbcccccdcccbbbccaabaaaaaaaaaaaaaaaaaaaaaabcbabaaabaaabbbbbaababbbbbbccddddedffceedb######aa###",
+"aaa#a####a##aaa##a.##acda#cejjfdbbbbbabcbaabbcbbaa#aaa##a#a###baecbdfedddefhhgefea#cedbafecbbcbecbbccbbbbabbbbbbbccabbcdcaa####################.#######aaaaca##########################.########a######aaaaccccbbca#a########aaaa####bedcaabaa##aaaabaaabc########..#figefhikjihhhhiijiihd##bbcdbcccbcccddebcbbbbcdbaaaaaaaaaaaaaaaa#aaaaaabbcbbbbbbbabbbbbbbabbbbbccddedeedffa###a#####aaaaaaa#",
+"###aa############a#.##bccbbbbehhaabbbaaabbabbcbaba#aaa#######becdda#fgecddeehghegdabdecaabedbcaacbbddbbbbbbcbbbbbbdbaaccccba#########a################aaaaabcaba###############################a#####.###aaaabccbcb##a######aab##a###accbca#b#####aaaaaaaaa###.####...diihiiihfgeffeffhijid##ddcdccccccddddccbbaabddcaaaaaaabaaaaaaaaaaaaaaabbcbbabbababbbbbbbabbcbccdddedefc.##########aa#aaaa#",
+"#aaaaa#aaa##a######.#abbccaaaabgfb#ababa#aaaacbaaaaabbbab####edeefeccgedcddehhfacebadecaaaabcccbbbbcbabbbbbcbbcbccccccabccdb#######abb###a##############aaaacbccba##########a######.########a###a#########aabcceccb###a#####aaaa##aaaaacbb##ac######aaaaa##aaa#######..diihffffffdeddddefiigaaeddddbbcdddccdccbaaabcedbbbaababaaaaaaaaaaaaaaaabdcbaabbababbbbbbbbbbbbcceeegc.#############aaaaaa",
+"aabcbbaaaaaaaa########bbcdbaaaaaffa#aaaaa#aaabbaaaabcdeddabaefcdddefcgfddddeghcccffddbaaabbbbbccbccdbcbabbbbbbcbbbbbdcabbbddb########bca#a#######a##a###aaaaaaabdbaa#aaa####aca##...###aa####a##a########aaabbbdecc##aaa############aa#abba##a#########aa#aaaaa########.bgiedcccdccccccccdhigdeeeeedcdddccbcebaaaaaaceebbbbbbbababaaaaaaaaaaaabcccccfedcbbbbbbbbbbbbabcfffe############a###aaaaa",
+"a#aaedbbbbaaa#a#######abddca#aaaadcaa##aa####aabababbbccccfggcbcccccfgeccccdddffedfecddcbbbbccbbccdcddbbbbbbcbbbaabbcc#abaacba########aa##..#######aa####aaaaa###bbaaa#aaaaa#cc###a.####aa##aaa#########aaabbbbadcdaaabba##########a#aa#bbaa##a#######a#aa#aaaaaa#######.ageccbbbbbbbbbbbcbehigffeedddddccbcccbbaaa#accdcbbbbbbaaaaaaaaaaaaaabbcbccdbaadfdcbbbbbbbcbcefccba#################aaa#",
+"#aaacbaabbcbbbaa#######abcca##aaabbcba########abbaaabaabccdcbabbbccbcedccccccccccccedbbcdbbbccbcbbcbcbbbbbbbbbbabbbbcccbbaaaaaa##a####a#aa####.#####aa##a#aaaaa##abbcaaaabbbabcaaa#.#.###aa#a##a########aaabccabbddbaabaa####.##.aaaaaa##bba##############aaaa##a########.#bddbbbbbbbbbaaaaabfhhgfeedddccbccbdabaaabbbccddcbbbbbbaaaaaaaaaaabacbbcceb#a#babcbbbbbbcbce##.####################aa#",
+"aaaaaa#aaaababba#######abcccb#a#aaacddb######aaaaa#aaaaabbbbbbbcbbbbcdcbcbccbccccddbababcccccccccbbbbaaabbbbccbdcbbbbabcbbaa######aa#aaa############aa#####aaaaa#acbabaa#baabbcb#a##.#####baaa#########aaaabcdcccccbaaaa##########abaaa###aa##############a####aaa########.##dcbbbbbbbaaaaaaaabghgffedccccccbbcabbaaabbcbdedbbbbbbaaaaaaaaaabaaabccdecbcabbbcbbbbbcbeea###aa####################",
+"aaaaaaaaaaaaaa##########acceeba###bbbcda#######a####aaaaabbbabbabbbbbcccccccccbcbbcdcbaabbcbcccccbbbbbcabbbbddegebbbbbbbcaaaaa#########a######aba#####aa#####abaaaabcbb#aa##abaaba#####a##aaaaa######aaaaaaacccccbccaa##a#######aa#aabaa##aaa####aa########a#aaaaaa###########addcbbbaaaaaaaaaa#fieeeddcccbbbbbaaabaabbaaabdedcccbaaaabaaaaabbaabbbcdebaaccbbdddcbbcdc#aaaa###########.########b",
+"aaaaa#aaa#aa#############abcdfdaaaabcdf###aaaa##a#####aaaaabbccabbaaaabbbcccccbcbabbccbbbbbbbbbbbccbbcccbbbcdcdedecabbbbaaaaaaa########abb##aa#aaabaa#aba###a#aa#aabcccbabb###aa#aaa######aa##aa######aaaaaaaccccdaba###########aaa#aaba#aaaa#aa##a########aca##aaa######a######cffaaaaaaaaaaaaa#ehfeeedcbbbbbbcbaabbbbbbbaadeeefedcbaabbabbccbabbdcbcaabdcccccceedffb##aa####################a#",
+"aaaaa###aaaaaa#####.####aabccfgbaabbcfeda##aaabaaaaaa#aaaaaaaccbccbaaabcccbbccbbbbbbcbbbbbbbcbbbbbcabcccbababccdeccbabbbbaaaaa#aa########aaaaaaaabedaa##a#aaabaaaaabaccbaaaca###aaaaaa#####a###aa###a##aaa#aaaccbbabaa############aaaaaaaaaaaaa#########a##acdaabaaaa############acecaaaaaaaaaaaaafhffeddcbbabbcbbabbbbbbbbaabbdeddfeddbabbbdcabbabbababbbcbcbccddffcdaaaa##a###################",
+"aa#a#####aa#aaaa#########abcdcfeaaacbdccfcbbbdddbbbbbaaaaa#aaaabcbaabbbcccbbbcbbcccccccccbbcbcccbbbbbcccbbabbacddedcaabbabaaaaa##aa########cb##aa#cfdaa##aaababbbbaaaabbbbaabaaa#abaaa#####a#bbaaaa##a##aaaaaabbccdaaaaa#####bb#####aa##aaaaaaaa############aabbbbaaaa##aa##########deaaa###aaaaabcgiggddccccccccabbbbbabbaba#aabcaacccccbbcdbaacbbabbbbabcbcdddd####abaa#a##a#a#aa############a",
+"aaa#####aa#a#aaaaaaa######abccdfa#bbcddbcccdcdaaccdecbbbbbbbaabccbaaabbcccbbbccbccccddccccccddccbbbbbbcccbbbbbcccdddbabbbabaaaa########.####bba##a#aca###aaaaaaaaaaaaaabbbaabaabaaabba#######ababba.##aaaaaaaaabcdcb#aaaa#####a##########aaaaaa#a####aaaa##.##abbba#aab#aba#aa#a#####cgeaa####aa#aabfiigdccccbccccbbbbaabbbbaaaaaabccbbccccdabcbccaaaaabbbccdebdbaaaaaaaaa#a######aaaaa#########",
+"#aa#a###aaa####aa##a#####aabbbbeb#abbceeba#a####aaaba##cdbbbcccdccbbbbbbccbbabcbbbcbcddccccccddddddccdcabbbcbccbbbddcbbbbbbbaaaa#########.####aaa####a#a#aaaaaaaaaaaaaabbbbaaabaaaaaaba####a#.a##ab##.a##a##aaaabbddb##aa#####aa######.##aaaaaa#aa####a#aaa###abbb###acaacaaaa##a#####bff###a##aaa#aacghhfccbcbcbbcbbbbbbbcaaaabababbdccccddbbccccaaaaaabbccee##aaaabbacaaaa######aaa#aaaaaaa###",
+"#aaa##########aaaaa########bbbbbea#babcea#a######aaa####bccddcddedcccccccccbcbccbbbcbcddddcccbbbcccdefedcbaacbbcbbbbbbbbababaaaa############.###aa#a##aaa#aaaaaacbba##abbcbaaa#aaa#aa#########a#######a##aa#a#abbcbcc#a############aa####aaaaaaaaaa#######aa###aabaa##bbaaaa#a##aa######dea#####aaaaaa#behhdccbccacbbbbbbbcbbbaabbabbbcdcccdddbbbba#aaaaabbddb#######bcaaaaaa######aaaabbbaaaaaa",
+"aa#aa##########aaa########aabbbbbedbaabddcb#aaaa#aaaa####cccaacdeeggecccccccbbabbbbbbbbccddcccbbbbcbcddeedcbaaabbabbbbcbbbabaaaa###########.#####aba#######aaaaaabbba#aabbbbaa###aa##a#####.#a#.#.####aa##aa#aaabccbca#aa#..########a######aaa##aaa#########aaa#aaaaaabcaaaa##a##a###a#a#bdb#aaaaaaaaaaabcfhfccccabbcbbbbcbcbbbaabaabbabcddcdcccbba##a#a#abddb########aaaaa#aaa####aaaaaaaabbaaa",
+"aaa#aa##########aa#a#a#######abbabgebaabacca#ba#aaabaa#########a##bdeddeedddcbbbbbbbcbabacdddcccccbbbcdcdcdcabbbbbbababbbccbabaa###############aaabb####aa##aaaaabbbaaaa#abbbaa###aaaa###a###a##....###a##aa##aaabbbca##aa#.#######aaa##aa######aaa#########abaabaaaaaacbaaaaaa##a###a##a#afb##a##aabbbaaaaeggecebcbbbabbbcbbabaabbbbbbabbdddccccccabaaaaaaccc#####a#aaaa#a#####aaaaaaabbbaaabaa",
+"aaaaa############aa#a########.#abbcffcabbceccaaaaaaaaa###a###aa#######aaeebccccccbbbbcbbccbdddccccccbbbccbbbbbbbcbbabbbbbccbbbbaaa########.#aaa#a##aba#aa##aaabbbabbbaaa###abaaa#########aa##a############aa###aabcc#aa#aaa#######.##aaba#aaaaaa##aaaaa######baaaaaaa#aaaaaaaaaa###aaaaaa###ebaaaaaaaaaaaaabbfhgedbbbbbcbbbbbbabbbbbbbabbbbddecbcbbbbbbcbbbceaa#####aabca#a#a#a##a#aaaaaabbbbbaa",
+"aaaaaaa####aaaa#aa###########..#aabdddbbcccccaaaaaaaaaa##a##aaa###aa#####eddedddcddccbccbccccbbcbbcedbbcccccbbbbbbbbababbbcbbcbaaaaa############a#a#aa#aaaaabbaabaabaaa#aaa#abaaa#######aaaa#a###########.#aab##aacc#aa####a######..##aa#aaabbaaa##aaaaaaabbaabaccbaa###aaaaaaaaaa##aaaaa##a#ccbaaaaaa###aaaadgggfeababbcbcbcbbaabbbbaaabbbccddbcbbbbbcdccccca#a#a###aaaaaaaaaaaa#aaaaaaababccba",
+"aaabaaa#a#######a#aaa####aa###.###bcdcbcbabddbaacbbababaa#a##aaaa#aa#aacdccbddddddbbbbbaa#aaa######bfggfdcccbabbbbabaaabcbccabbaaaa#########a#aaaaa#######aabaaabbabbaa####aaaabaaa##aa##aaa#b####.#########abb#aaee##a###.##.##.###..####abccccbaaaaaaaaabcdaabbccba##a#aa#aaaaa#a#aa#aaaaaaaabebaaaaa#a##aabbfghhgedaaabbbccababcccbbbaabccbcccbbcbbcdcdcaaa########aaaaaaaaaaa#aaaaaaababbccb",
+"abaaaaaaaaaa######aaa########aa####bbccbbaabceaa#cbbbbbba#a##aaaa#aa###debacb#aacabaa##aa###########.#afhgeecbccbbbabaacbcccbbbbbbaa#a#########aa#aaaa####aaaaaabbbbbbbaa###aaabbba###a##aaa###.#######ba##aaadbaabeaa##aa#..###.##########abaaabdbaaababababbaabddbaa##aaaaaaaaaaa#aaaaaaaaaaa#aecaaaaa#aa#aaabdghhhfecccbcbbabbacccccbbbbbcbbbbbcbabbdcbcba########aaabaaaa##a###aaaaaaaaaabbb",
+"baaabbaaaaaaaaaaaa###########aaa####acccbaaaabcbcabbbbbbba#####aaaba#acbcaa#aaaa#abaa############.#####.dhihgeefccbbbbaabccbbbbbbaaaa##########a#aa#aa####aaa#aabaabcbbaa####a#aaaa###a#aaa################abbeebbbdd##a#######..####.######aaaaabcbbbbbbbbbbb#abcccbaaa#aaa#aaaaaa###aaabaaaaaaa#bcbaaaaaaaaaaaabehhhfedaaabaaabbccccbabbbbccbbabccbbbdcbbaaa#######a#aabaaaaa#aabaaaaaaaaaaabb",
+"bbaaaaaaaaaaaaaaaaaaa#########a#a####bbcbaaaaabeecbbaaabbaba###a#aaa##cedb#aaabaaaaa##a#########.##.###a#bfgedeffdccccbaaacdccccbbaa###########aaa######aaba###aabaabbbaaaa#####aa#a##abbaa####.##.####aaa#acbddddfega#a#######.######.##a#aaaa#aaaaaaaabccddebaba#bcba##aaaaaaaaab#aaaaabbbcaabaaaaccaaaaaaaabaabbehhfgebaaaaaaacdcccaabbcbbcbbbbbcdcbbcaaa#a######aa#abbaaaaaa#abbaaaaa#aaaaab",
+"bbbaaaaabbbaaabaa#aaaa###.#######a####abb#aa#a#cfecaabbaaaba#######aaa#bddcdaaabaaaa#a#aa######.########ba.a####bfddcccbbacdccccccaa############aaa######adb###aaaaaaabaaaaaa###aaaa##abaaa#####..#####aaaaabbcdeedfgd#aa########.#######a##aa#aaaa#a###a#abeedecc##aaba#aaaaaaaa#bbaaaaabbbbaaaaaaaaaccbaabaaababbadgggfdb#aaaaaabcbbbbbbccccdcaabbcdcccbaaa#######aaaaaaaa##aa###aaaaaaaaaaaba",
+"bbbbaa#aaaabaaaaaaaaaba#a######.#######abbbca##acdedcaabca#a#.###a######bddcfcaabaaa##a##a#####...##aa####a####a#abbccddcbbddedccccbaa####a######aaa#####acb###aaaaaaaaaaaaaa###########aaa####.####a##aaaaacdeceeeedc##aa########..#########aaaaa##a###aaaaaabcdedcb##aa#aaaaaaaaacbaaaaabbbbaaaaaaaaadfdaabaaaabbbbcdggfebaaaaaaacccbbbbbbccdcccbbbdcecba#####a####abbaaa#######a#aaabbaabaabb",
+"bbaacbabaabaaaabbaaabbaabb#.####.#######abbcba#aabecdbaccaa#a#.##aa##a###acacecbaaaaaa##########..######..abaa#aa####aceeddceggeddccbaa##########a#aaaa##aaa##a##aaaaaaaaaaaaa#########aaa####a#aaa####aaaabbdffffgebca#ab#######.#..#aa######aa###aa####aaaa#baabbdcc##b##aaaaaaaaabaaaaaabbbbaaaaaaaabcegcabaababbbbabgfgfdaaaaaabbabbbabbbcdddbcbccccdbaaa#a##a###aaaaaaa#########abbbbccbaab",
+"baaabbaaababaabbaaaaaaaaaaa##############abbaa##aadd##abbaaaa#.##aaa##a####aabcbaaa#aaa###a######..####.#..cdcbbbaa###abdcdedfghffddcbba###########aaaaaaaaaaaaaaaaaaaaaaa#aaaa########a#aaa#####aaa#a#aabbccddghhhfcca#aa##########...##########aa#aa###aaa##aaaa#a#bb####aaaaba#a#aaaaaaaabbcbbaaabaaabbefdabaabbbbbbbbfgggfdcaaaaabbbbbbbccdbdbcbcccbcbba##aaaaaa###aa#aaaa########bbabbbbaaa",
+"aa#a#aaaaaaaaaaaaaaaaaabbabaa#######.#.####aaaaaaabdeb#aababaa####aaa#abba#####aaaaa###a##bdba##a######....acdbabbaaaa#####cddaeggffedcba##########aaaa###aaa#abaaaababaaaaaaaaa##a###abaaaa###.#bbaaaaabdcddeefhhifdda#bb#aa##aa######..########ab##a###a##a#aaaa#abaabaaa#aaaaaaaaaaaa#aaaababbbbaaaaaaabcffbbbabaabbbaacefggdba#aabbbbcbacddccecbbbcccbba##aaaaaaaaaaa#a##a#a#######aaaabaa#a",
+"ba###aaaaa#cbaaaaa#abababa#a################aabbbbbbbea#aaabbaa#####a##adc##aaaaaaba##a####a########.#####...aca###########.####cffdcdecaaa#######aaabaa##aaaaaaa#aaabbbaaaaaabaaaba##babba######accbbbbbfccdeegdgfggeb#dc#####aaa#####...#######aaaa#aa##a#aaabaaa#bbaaaaa##aaaaaaaaaaaaaaabaabbbbbaaaaababbegdbbaaababbaabffffecb#aabbbbcbbcdddecbaabcbaaba#aaaaaaaaaaaaa###a########a#abbaabc",
+"a#######a###aa#abaaaabbccba###.##############abcbcbbcbea#aaaaaaa#######.##ba#a#aa#a#a#a##a####.###########..###ba##############a#aeedbadfcdddcbb##aaaaaaa#aa#aaaa#aaccbbbaabbbbbabcbbcdccb######abcdbddeeefddddb#afdcfebdca#####aaa######.#####aaca####abaa#aa#abcb#accaaaa##aa#aabbaaaaaaaaaaaabbbaaaaaaabbbbbgdbaaabbbbaaaccffgfdcaabbccccccddddfcbaaaaaaaaa#aaabbaaaaaa#a#aab####aa##aaa#bcc#",
+"aa###########aa#aaaaabbabbaaaa##..###########abdcccccbcdcaaaaaa#a##########aabb#abaa##########...#.########.######################.bfdaaccefddddbaaaaaaaaaaaaaa#aaababcccbbbbbccbbcddcabca####aaacdcabeggfdda.##.#cc#aefdbaaa###aaa###.##.####aaaaa#a###abd##a###ababbdc#aa#aaaaaaaabaaaaaaaaaaabbcbbaaaaaaabbbbgfbaaabbbbaabbbcefffddbabbcdccccedcabaaaaaaaaaaaaaaaaaaaaaaaaaaa#####aaa#aaaaaaa",
+"aaaa##########a######.#a#abbaa##########a####abdedcccccccba##########a######aaaa#abaaaaa#######..################aa#aa###############ddabedcgededbbbaabbabaaaaaaaaaaabbccccccbccdddba###abacbbcccba####aaaaaaaa##.###acfcaaa##aa#a############aa#####a#a##aea#aaa#aabbcda##aaa#aa#aaaaaaabaaaaaaababcbaaaaaaaabbbgfbabbbabaabcdcbdefffdbbcccccccdda#aaaaaaa##abaabbaaaaaaaabbbaaaa####a##aaaabaa",
+"aaaaabaa#######a###a##.###abbaa###############acdeccbbccdga##########a######.#aabaaaaaaaaa#a############.###aa###aaaaa###############.cdbbdefhhhfdccccbbbaaabaaaabbbbbccccdddcdccdb#####bbcbcddba####aa####a#a#####.##aedaaaa###aaa#######..#########a###a#bbbbbaaabbbbaba#aaaaaaa#aa#aaaabbaaababbabccbaaaabaabbbggdabbbbcbbbddcbcbdffdcaccccacccd#aaaaaaaaaa#abbbaaaaaaaabbabbabaa#aa####aabaa",
+"aaaa#aaa##########a###.##aaaaaaa####.##aa#####abccdcaabccffa##########a###aa####aabaaabaa#aaa####a######..###a#####aaa############aa###bdddeeddfgfeeeddcabaaabbbbbbbbbbcdddddeeeecaa####abbaaaa#######a#a########.###aaadaaaa#####aa########.#..##.##a######aaabbba#bbca##a###aaaaaaaaaaaabbaaaabbbaabddcaaaaaaaaabfgdaaabbbabdacdbcbdfffdbbdccbc#cbaa##aaaaaaa#aaaaaababaaaa#abbaaaaa#aaaaaaa#a",
+"###a#aaaaaaa######accbaaab#####aaaa####a#######accccabacccfe##.############aa####aa###aaa#aa####.#########.##########a############abca##bfcfabbbcaafffffdbbbbbbbbbabbcccdeeedefcaaaaaa##aaaaaaaa################a#.###abbcaa#aa#aaaaa#######....########aa####a#abba#bbbbaaaaaaaaaaaaaaaaaaabcabbbbbbabeedaaaaaaaaacfgecaabbabbacdbabcffffccccdda##aaaaaaaaababaaaaaaabaaaaaaaaaabaabaa##abb####",
+"a########aaa#######cddebba########aaaaaa#######abccccbabcdefea#.########aaaaabb##aaa#####aaa##.....#.##.##############a#####.#####aabcbaabfc######.afggggcbbbcbcccbbbccceeeeffhgccbaaa#aaabbaa#a######aaa########a#.##aacdba##ab#aabb##.#.####...########aa#####aaaaaaaabbaaaaaaaaaaaaaaaaaaccbabbbbbbabefdaaaaaaaaabeffabaaababdedabbcfffecccddaaaaaaaaababaaaa#aaaabbbaaaaaaaabbaaa#aa##ba###b",
+"#####aa#####aaaabbaaaacdb.#a#########aaa########abcbbbbbcdeeeefc.######aaaabaacbaaaaa##########..#..#....##############a###########abbbba#bd#a######aabbcfedccdddccccdddeeeeefgiedeebaaaaaabaaaa#aaaaa#aaaa###########aabcca##aabaaabba#....#....##.###.#aaa#######a#abaabbaaaaaaaaaaaaaaaaaaddbbbabaabbbddaaaaaaaa##adfecbbbbacddedbbccdffdccddaaa#aaa#bbaabca##a#aaabbaaaaaaaaaaaabb#aaaa###a#",
+"####aaba######aa#abbaaaba###aa#############.####aabcabcbbdegfebc.########abbbaaaaaaaaaa#########.....#.#.######.#######aa#####.#.##aaabbbbbc##a#######..##ehfeeeedddcedeffeeeeehf#abcecccbabbbbbaabaaaaaaaa########a###aacdba#aaaabaaaaa#..##..##.#..####aaa##a####aa#aaaabaaaaaaaaaaa#aaaaaabeeccbababbbbbaaaaaaaaaaaabcffbbbbcdccdcbbbcdfgfedcabaaaa##bbababa#####abbaaaaaaaaaaaaaaaa#aaaaaa##",
+"#a###aabaaaa###ba###ab##ba###a#############..###aaabcaabbdedefgb####aaa###aaaaaaaaabaaaa###########...#.############################aabbbadcaaa#####.######bfhhgggffffffffeeeefhhcaa##acfffeedddbaabaaaabaa########a####abebaaaa#a#a#aa############.###..#aa##a###aba##aaaaba#aaaaaaaaaaaaaaaaccdcdcbbbbabbbaaaaaaaaaaaaacfeaabbbbccdabccbdfffed#aaaaabaaaaaa#aa###aaaaabaaaaaaaaaaaaaaaaaaaaa##",
+"###aaa#aaaa#a##.a##a#aba#aa###########.#.#....####abcbbbbccdffegb...##aa###abaaaaaaaa#a#aa#######aaa###.####.#####################a##abbcfda#aaa###########.#acfhihhhijiiiihgfhhgcaaaa#..acccddccecccbaaabcb#######aa###abcdbaaaaa#aaa#aa##########.##########aa##aaa#aaaa########aaaaaabaaabbaaababaacbbabbbaaaaaabaaaaa#cefdabbbabbcbbbccdfggeb#aaaaaa###aaa#a###aabbaaaaaaaaa#aaaaaaaaaaaaaa#",
+"#aaaaaaaaaa##aaaaaaaa#aaaaaa##.###aa###.###...####aabdbbabbcfeced.#########aaaba#aaaaaa##ca#######aaaa######.########.########a#####aaabdhgfeaaaa#############.#aaba#addfghiiiiheb###aaaa###.####bdbcdcdcbbca##a##a##a##aabbdbaa####aaaaaaa#############a#.##aaaaaaaaa##aaa##a#a#acbaabbabbbaaaaaaaabbbbbaabbbaaaabaaaaa#a#bfgebaaababbbbbbbcggfeaaaaaaaaaaaaaaaa####aabaaaba###aaaabaaaaaaaaaaa",
+"a##ba#abaaaaaaaa####aa###bbaa##.#######b#####.#.###aacbbaabcdeccc##.########aabbba#a##aaa#bba######aaaaa#################.######aa##aabbfhhihdabaa##############aa######.##a#bgfb###aaaaaa########cbacccdfeecaa###aa##a#aaabcdbab##ababaaaaa##########aaa#####aaaaaaaa#a#aaba##aabfdaa#aaaaabbbabaaababdbbbbbbbbbbbbbaaaaaaa#dffcbaabbbbbbbbbcefgdba#abaaaaaaaaa#aa##abbbaaacba##a###aaaaaa##aaa",
+"aaaaaaaaaaaaaaaaaa#####a##aaaa########ab##.####..###aadccbbacdcaa###.######aabaaabb#aaaa###############aa#####a#####.##############aabbbehhhfcaaaa#####.########aaaa##aaa##a#.#caa####aa##########cdbbbbbcedefdcbbaa##aaaababbdbaaaaaaaaa#aba#########aa######aaaaaa#a#aa##aaa##addbbaaaaa#aaaaabaaaaaaccccdcbbabbbcbaabaaaaa#cfgdbabbbbabbbbbcfgedda#aaaaaaaaaab#a##aabbbaaaba#aa###a#aaaaaa#aa",
+"aaaaaabaaaaaaaa#accb#########babaa###aaa##.##a##.####abcbccabdeaaab#..######aaaaaaa#####################aaa####a#####.############aaaabdgihgcbaaa################aaaaaaaaa#aa###a######a##########dbaaaaaaaacbcefgfddcccddegdcbdbaabaaaaaaaaaaa######aaa####aaaaaaaaa#############aaaaaaaaaaaacaaaaaaaaabbbbdeccdccbbbbaabaaaaabefecbbbabbbbcbcegededcaabaaaabaaaaaa##aabbbaaaa#aa#aaa#bbaaaaa#a",
+"a##a#aaaaaa###aa#bbcbaa##aaa#aaaca##abb########a#####aacbbccbdeaaaba#########aaa##a#a####.################ba#########.##..######.bbabaaehhhgbaaaa#################aab#aabaa#aa###a##########a.###.ab#aa#abababbbcbcdcaacecccdefdc##abaaaaa##aa########aaba#aaa#a#aaaaba#a#aa#a##.##abaaaaaaaaabbabbaaaaaaaaaaccbbbcdbbbbaaabbbabbdgfdbbbabcbcccdddeeedcaaaaaaaabaaaaa##aabbaaaaa##aa####aaaaaaa#",
+"####aaaaaaa######abbcca##aaaaa##abbabba#a#####aaa######aabccedfaaaab#########aaa###.#######################b########.#ba#...##.#acbccccfgggebaaaa##a###############aababaaaa#a##a#a####a##a########c#aaaaaaaabbaaaaabccdebabbbdgeaaabbbaaaaa##a#######aaab##a##aaaaaabaaa###aaaa####ba#a##aaaaaabbaaaaabbaaaaacbbbcbbbcbbaaabbbbcbcfgecbcbbbccddccceddccaaaaaa#bbaaaaaaaaaaaa#aaa##a#aa#a#aa####",
+"##a###aaaaa#######aaaaaaaaaaaaa#aabbcaaaaa#a###aa########aabeeea###aaa#######aabb#####a######.#######aa##.######aaaabedccbbb##bbbbaabbbbccdeaa##a##a########aaa#####aabbbba#a#aaa#a####a###########caba###ababbbaabbabcdcddcbabehcaaaaaaaaaa############ab##aaaaaaaaaaaaaa#baaaaa###bb#a##aaaabbbbbaaaaabbbaabbbbcccbabbbaaaabbccccbfffcccbccccbccccddeedaab#aaaabaaabaaabaaa###aaa###bb##a#####",
+"aaaa##aaaaa#aa#######a#abbaaaab######aaaaa#aaaa#aa#######aabdefb#aaa#bc#######abcb#####a#################aa#a..###aabcdfffggfdcbbbbbaaaaaabdeaaa###########aaaa#####aabbbbbaaa#aaa#####aa#a##.#####aaaaaa##abaabcbbbaaabaabbbbcdefaaaabaaaaaa##a######aaa######aaaaa#aaaaaa##aaaa###aa#aaabbbabbaabbaaaaaaaabbbbbacccbaaaaaabbccdccdefegffdccecbccccdeeddcbaaaaaaabbbcbaaabaaaaaa#######aa######",
+"#aaaa##aaaa#############abaaaaaba##aaaaaaaabaaaaaba#####a##abdgca#aaadeb########bba#####aa#aaaaaa###aaa#ab#aa#.###.#acfhfddgccbaa#aaaaaa#abcfaaaa#######aaabbaaa#####aaaaaaaaa#aaaaa#aaaa##########aaaa#aa##aaa#acccabaaba#a###acdbaaaaaaaaaaa###a##.##aaaa###a###aaaaaaaaa###aaaa#abb#aaaabbbbbbbabaaaaaaaaaacbbbccbbbbaabaaacccccdfdbdfgeefcddabccbcedddccbbaaaaaabbbababbaa#aaaa#a##ab##a####",
+"##aaaa#############aa#####abaaabda##abaaaababbaaaaba####aa#abbdeaaaaaadf###############a#aaabbbbba#aa#aaaa#baba.#accbffffgddcbbaa#####aa##acfeabaaaaa###aabcdcbba######aaaaaaaaaaaaaaa#aaa##########dbaa########bbdcaab#abaaa##abceaaaa#a#aaaaaa#a###.######a#####aabaabb#aa#####a#bcbaaaaa#aaaabbbbbaaaaaaaaaaccccbccabacaaaabceeeeggdcdfffccccca#bbcbddeccccca#abbbbbbbaaabaaa#a#aaaaab#######",
+"##aaaa####.##########baaa##aaaaabda#aaaabbaaccbaaaa#####aaaaabbcbbaaabdgfe###aaa#######a##aaabbabbb#a#a#aabdceeedcabcaeddcfhecdb#########aacdhcbccbbbbbbbbdehhedba##aaaabbbbbaaaaaabbaaaaaaa########cba#######a#abbda#aabcbaa##aabceaaa######aaa##aa########aaa##aaaaaa#aaa###.###aabaaa#aaa#aa##abbbaa#baaaaaaabbbbbbdbbabaaaacaddacbbbbddccccbbda#cbbcdcddeccccbaabbbbca#aabaaaaaaaaaaaaa#####",
+"#aa###a####.##########aa#a##aaabaccaba#aabbaccbaaaaaaaaaaaaaabbccabaabeffeebbcb#.####.#aaabbaabbccccccccdddcec.#aaaaaaadccbbcccca.#######aabdhecdddeeeddeefecbbeedcaaaaabbbbbbabbbbcbbaaaaaaaaaba##aba####a####aacdccaa#ccbbaa##aabcdaa########a##aa########aaaa##aaaaa##aaa#########aaa##aa#aba#aabbbaaaaaa#aaaaaabaaaccbaaaaabccababbbb###bcbcbbecabbccdcddcdcccaaababbbbaaaaaaaa#aaaaaaaaa###",
+"#aa#aa##########a######a#####aaaaabc#abaaaabbcbbaa#a##aa#baaabbbbbabbcfffgghebdcbbacacbbbbbbbcbccdccfdaaabdedcaaabaaaaacccbbbbbbcb########abcfgedeffeeeegfcbbcbadgdddaabbbbbbbbbbcccccbbaabababbbaacbaa#########abcccbabccbbbaa##aabcb#a#######aa######a#a##abbbbabaa###a#aa########.bbaaa#aaaaaa#aaabbbccbaaaaabbbbbbbaaaaaaaaabbbccccaaa###bcdbabcbbbabcdddcbddccbbaaaabcccabaaaa#aabaaaaaaba#",
+"#aaaaa#######a####a###aa##.###aaaaabc#abaaabbcbba###aa####a#aaabbbaabcdcdeccdecccccba##aaabbaaaaaa##beaaabacfdeaabdecb#bdcbbbbbbaca#######abcdegeeeeffgfdabbccddeehhhfdbbbddeeccdcccdccbbbbbbcccbcca##a###a########aa#.aceccbbaa#aa#acb###.#####aa#####aba###abcdcbcbaaaaaaa#####a###bc#abaaaa#aaa#ababbbbccbaaaaabbcccbcbaaaaaabccdacccb#a###abddbbbbbbabbcebcbbdcccbbaabbabcabaaaaabcbaaaa#aaa",
+"aaaaaaaaaaa####aa#####aaaaa.###a#aaaccaaabaabccaa##aa#######aaaaaaaaadc##abaaaaa###a#######a#########cb#aaaacdddb#bbdda#becbbbbbbac#######abceffhffffda##babcccdeeddbddeecdcdebdeeccdddeddcccdeba#b###aa##a#########a###bedbbbbaa#a##aca###.#####aa####aaa####bbcdddbaaaaaaaaa#######adbbabaaa##aaaaaaacbabbccbaabaabbccccaaabbcbdcbcecccaa#a#a#adcabbbbbcbbcbccaabccdcbbbbcacbaabbaabcbaaaabaab",
+"bdbaaaabbaaaa#aa##a#aba#############abcaabababcba##aa#########aaaaaaabdb##aaaaaa###a##################b####aaccdeaabcbbaaeddbabbbabb#######bdfhghhgda###aabbcccecbbbdcccefdbbcbcb#eefgghggfeegdaa##a###aa#######aaa#####bedcabbaa#####acb##########a##aaaa####acbccccaaabaabbbba####a##dbba#aaaaa##aaaabdababbccbabaabbcddcbacbbccdacdbba#####aaaabcbbbbbbbccbbababbcddcbabbbabaaabcaaabaaacabaa",
+"aacdbaa##.##a##aa#aa#aba###.#########abca##aabbbca#..###########aaa##aab######aaaa#########aaa#a###aa#######aaccdfbabbaaaeeddbbcbbbdbaa#abcdfhjigca######abccbadb###cfbcbbecabbba#begfhggddcggdbbaaa##############a#aa#.cddccbaaaa#####ab##########aaaaaba####accbbbbaaabaabbbabb#######aba###aaa#aa#aaabcaaaaabccbabbcccdedcbdbbacdcdccaa##a#aaaaabcbbbbbacccbaaaabaccccbaaaaaaaabbbbaaaaababba",
+"aababbaa#####a##a##a###a####.##########aba###abbbbba####.#.#######a###aab######aa#a#########aaa#####aaaaa#####bbceebbbba#ceedccedcegdcbcddedbcbed#######aabccdbdda##adeeb##abbaaaaacbadeddfdghdcbbbaaa###########abbbcdbbdcbbca##aa#####bd###.#.###aaaaaaaba##abbbbbbbaaaaaaaabbaaa#######aa###aaa#aaaaaabcaabb##abcbbaabcedccdcbaaccccba####a#aaababcbaaaabbccbbaaababccbaa##aa##aaabaaaaaaabaa",
+"aabaaaaa#a#####a###aa##########..######aaba####aaaabb#.###############aaab##.###a#a#######aaaaaaaaa#a#aa###a##aacdceddfgfcfffgdccdeeefggdbaabbbbdcaa###aaabbcddeb##a#adfeaaaaaaaaa#bbaaccbeedhecbabbaaa#########.adccbcdbdbbcbba#######a#cda########abbaaaba##abbacbbaabaaaaabaaaaaa########aba##aaaaaaaaabcaaa#a##abca#aaabdefecbaadbbbaa##aa#aaaaaabdcbaaaaabcbaa#aaaabbbaaaaaaaaaaaaaaaaaaaaa",
+"aaabbaaa#########a##aaa###########.##.##aaaa#####aa#cba################abcb.####aaaaaa##aaaabbabaabbbaaa##aaaaaccgghggecdfihhg#a####a#a#abbccccacdcabbbbbacccdfeba#####aaaaaaa###a#ababbccadcgedccbaaa############ccbabccbcacabaa#####a#bacd###.####aaaaaaa###aaabbccaaaaaabbabbaaaa###.##..#bbb###aaaa#aaaaaaa########a#aabccceecbbdbbbbaa#aaaaaabbaadccbaabaabba#####aaaabaabaaa##aaba#aaa#aaa",
+"aaaa#aa##############bba##########..#.############aaaaaa#####.##########abca..####abaaaaabbbcccbbccddbbabbbbbcdefebdfd##a#.bedaa#########aabbbcbcddddcbbbcdeffd#########aaaaaaaa#aa#baaabcbacegedbbaaa##########bcdbaabbcccbbbaaaaa#####abbcca####.##aaa####aaabbcccdbaaaaaaabaaaaaaaa####.###abba##aaaa#aa##a############aaaa##cfebdcabcb###a##aaaabbabacbaaaaaba#a####aaa#aaaaaaa####aaaaaaaaa",
+"abbaaaa####a##########aa###################aaa####abaa#a################aabc#.#####aaaabbbcdddcdfffefgffeddfgdcdcb####aaaa###bb#######a##aabacdcddbdccacdefecc#a##a#####aaaaaaaaaa##aaaaabbbabfgdcbaa########aaacbbbbabbbbcdaba##a#####a#abccda####aaaaa#aaa#abaaaccbbbaaaababbaa##aaa#########bbba##abaa#####aa#a##aaa#a###aaa##defdcabbbaa##aa#aaaabbbaaccaaaaab######aaba#aaaaab####abaaaaaaa",
+"aaabaaa#################abba###############aaaaa##aaaaa#a###############aacaca.#####aabbbbccddfda#adeca#####b###aa#aa#aaaa##aaba#a####aa#aabccdccedebaacccb####aaaa###a###abaaabaaaaa#aaaaaababdgdbb##########cabbdbbbaaaaaccaaaaaaa##aaa##acdc#.#aaaaa##a##aabaa#ccaaabaabbaaacbb##abaa######..abca##aaaa#####aa#aaaaaa######abaabdggcaaa#aaaaaaaaaaacba##bbaaaabba#aa#aaaaa##aaaba###aa#aaaaa#",
+"#########.#################aaaa#.#.##aaa###aaa##aaa##a##aa###############abbbba#.##.#aabbbbcefc####...#####aa#####aa###aa####aa#######a#aaacbacbbdddbbccdfecbcc###aa####aa#aaaaaa###aaaaaaa##aaacfdaaa#####aaaabbabbbbaaabbabbaaa###aaaaaaa#abce..##ababc####aaaaabdaabbbbbbaaabbbaaa#a##.#######abaa#aaaba##aaaaa#a##aaa###aaa##ababehcaaaa##aaaaaaaadc####abaaaaaba###aaaaaaa###aaaaa#aaa#####",
+"####a######################aab#....##aacaaa#aabbaaaaa#####a##############aabbbcb##.###abbcceca###################aaaaaa#a#aa##a#aaaaaabaabbbbbacaaabbabaafddcbcb###aaa#aab##aaaa######a#######a##cfeaaa#####abcbbbbaaaaaabbabba###aaaaa#aaaabaaee#.##ddaaa####aaaaacaaabdcbbbbaabaaba#aa##.#######aaaa#aaabaaaaaaa##aaa#a##a#aaaaaaabbcgebbba#aaaaabaabbaba###aaaaabbaaaaaaaa#aaa##aa#a##baa#a##",
+"####a##aa##################aabda#.#####bcaa#abaabaaaaaa###################aaabcdb.####bbbdea##########.###########aaaaa##aaaaa##aaabbbbcbccbbaaaaaaaabbbaaaacdcbbbaaaaaaaabaa#aaa################abecaa####aadcabcaaaaaaabbaab#####aab#aaaaabaaade#..#ca.#a####abcbbb#abbccaaabbbabbbb#a############aa#aaaaaaaaaacaa##aaa##a#aaaaaacabccfebbbbaaaaabbbbaaba####ababacbaaabaaaa##a#aaaaaa##aaa###",
+"#####aaaa###.#a######a#######aab##..####abbbbbbbbaaa#aaa####aaaaa##########aabddea.###abda#################a#########a#####aaa###aaabbcdcbdbbaaaaaaaaabbbaaaaacddcbaaaa###abaa######..############abeda###ababbbccbaa#aaaaaabaa##a###ab#aa#aaaaaacec##ab.########babbaaaabbababababbcda###############a#aa###aaabcbbaaaaa###aaaa#ababbcdcdecaabaaababbaaa#######aaabbbbaaaaaabaaaa######a#aaaaa#",
+"a#######aa#a######aa#a#aaa###aaac#########abddccbbaaaaaaa####aa#aa########.abehghhc##abca##aaa##################################a#aabccb#aabaaaaaabbbaaaaaabaaabbbdba#aa###aaa##################aa#abefccaabbbcbabbaaaa#aaaaaaaa#aa###abaa##aaaabbcfdaba.#a######bacc##aaaabaababaabcbca##.#####a#####a#aaa#####aaaaab##aa##aaaa#aaaabccebbffbaaaaaabcaa###a#####bbbbbbbaaaaabaa#aa######aa#aa#a",
+"#baa#aaaaa###a#a#aaaaaaa####b#aaba#########aacbdcccaaa##a###aaa#aa##########bbfikjicacc###aa#aaaa#############a###################aaabccca##aaaaaabbaaaaabbbbaa#aabcbbaa####a#################a#aabaabdfbdcccbbbbbbbbaaaaaaaabbaaaaa#a#aaa#aaaaaabbcfdbb#######a#aaac##a#ababaaaabbcdaaaa##########a#aaaa#a#aa##a#aaaaaa#aaaaaaaaaaabbccdcaaegcbaaaaacaa#####a####bbbbbbbaaaabba##a###aaaaaa####",
+"####aa#aaaa##a#aaaaaaaaa##a#####aba##########aadcbbba####a####a#aa##########abcdfhiigc#a##aaaaaaaa#aa#####################a#######aadccccaba##aa#abaaaabbbcaabaaba#aaaaaa####a###a#a###.#####acbbcbaabcehfdccccbbbbbbbaaaaaaabaaaaaabaaaa###a#aaaabbcddca####.#####aa##aaacbabbbbaabcba#bc############aaa##aa##aaaaa#baaaaaa#aaaaaaaabccdeba#cgfbaaabca#a###aa#a###bcbbbbbbaabbba##b###aaaa#a###",
+"###a#aaaaa#aa######aaaaaaaa######aaaa#######a##aaaa####.###aaaaa#a###########abacdhiiga##abbaaaaaaaa##############a########a##a##abbcabc#abbaaaaaaaaaaaaaacaaabaa###a###aa###a###aaa########bbbbcbbbbddceihebbcbbbbbabbaaaaaaaa#aaaaaab#a#####aaaabbcccfb#.########aa##abaaaaaaabbaaaabbcbc#####a######ba##aaa###aa###aa##abbaa#aaaabbbdcccbbabdhebcbaaaaa####a#####accbbbbcbaacba#aa###a#aaa###",
+"#a####a#aaaaa#aaaaaaaaaaaaaa#######aba#######a####ab########aaaa##a#a##.#..#####aehhjihb#abacba#aaaaaa############a#a########aa#aabdcc####abaa##a##aaaaaa#ababa#a##aaaa#######a#aaaaaaaa##aacaabcccbcbabbcghgdbbabbbccba##aaaaaaaaaaaabaaa####aaaabcbcdccaa#########.##aaaaaaaaabababbabaa#######a#a##abbba#a######a###aa#aaaaaabbaabbcdbbbbabbadffbbaaaaaa#a##a####aabcbbbccabbabaaaba##baaaa##",
+"##aa###a#aaa#a##aaabbaaaaaaaaa##aa###a#############bba#.###aa#aaaaaa#######.####adfehjif###aaaaaaaabbaaa#a########aaa###a######abbbbcca.###a###########a###aa###a#############aaabbbbbaaceb#aaabbbccbaaabbbdggdcbbabbbbaa###aaaaaaaaaaba#aa#a###aabbbbcdc#####aa#######aaaabbbaaabbbbbbba#aa#######a##aabbaa#######aa###aa#aaaaaabbbbbccaaccbbbccdfgedaaaaaaaaaaaa##aaaccbcccbbccba##aa##abaaa##",
+"########a#aaaaa#aaaaaaaaaaaaa#aa#ba###########a####aaaaa#.##aaaaaaa##a#a########bbceeijfc####bbababaaaaaaa#########aa##a#aaaaabbadcccba####.############aaa#aa#############a##abbabbbaa##ceaaa#aaaabbbaaaaabbdgfbbbbbabba####aaaaaa#aaaaa#####a#aabbbccdccca#aaaa######aaaaababbaaabcabba##ba##a##a#aaaaaaaaa#######a#a##aaaaaaaabbbcccaabbddcaabbabdffdbbbaaa#aa####aabbccbbcbbddbaaa####acbaa#",
+"#######aa#a#aabbaaaaabaaaaaaaaaa##aa#a#############abaaaa####abb###aaa#a########babcfhiiea###acbbabbaaaaaaaaa####aaba#aaaaa#aaabaccbcbaa###############aaaa###a##############aabaaaaaa####bbbabaaaabbbbaaaabbbcffbbbbbbbbaa##aa##a###aaaa####aa##aabccefcadda##aaaabb#aaaaaaaaaabbbbbbbba##abb######aaaabbba###############aa#aabbcccbabbaabdccccaabacfggccbaaaaaa##a#aabccbbcaabdbacba####bbaaa",
+"aaa####aaaaaaaaaaaaababaaaaaaaaaaa#aa##############abbbbaaaaa##bbbaaaaaaa######ab#bccehiic###abcaabbbaaaa#aaaaaaaa#aaaaaaaaabcbccacba########.##########aa###############a#aaa#aa#a##a#####acbddcbaaabbbbbaaaabbefcbbbabaaaaaaaa######aaa###aa#####abcdghedcbbbbbcccdcbbaaaaaaaabbbbbbabaa#.acca#a###aaaaaaa########a##a###aaabbcdcaaaaaabbaccddaaaaacaadggfdbaaaaa#aaaaaabccbbaacbaababaaaabbaa",
+"aaa#a#####aaaaaabaaaabbbaaa#aaaaaaa###aa#######.#a###abbbaabbbbaaaaaaaaaaaa####a##ababchie###aabbbaaaaaa#aaaaa#aaaaaaaaaaaabccccbccb####a#############aa######.###########aa###aa#aaaa#a###abcccdbbbbaaaabbaaaabbceebbaabbaaaaa#########aaa##aa#####acdfdefebcddcbbdffdcbaabbaabbbbbcdbbaaa##abca#####aaaa#a##a#aa####a#a##aabbdedaaaaaa#aaccbeda#aabbaaaacefgfdbaaaa#aaaaabcccbccabaaabbaaaacc#",
+"##a##aa###aaabbbaaaaabcbaaa#aaaaaaa#a##########a#####aabbaaabaabaaaaaabcccca########aaacfhc##aaabccba#aaaaaabbaaa##abbababbcccbeecba#####a########a####a#a#####.##########b######a##a##aa###aababaaabbaaaaabaaaaaabdfcababbaaaa##############.#######bddcbdeffcbbba##dihdcbaaaaacaabbbdcaaabaa#aba#####aaa######aa##a###aa#abcdccdb#aa###aaaccdcbaaaaaaabbaaabehhebaaaaaaabaccbcbbbaaaaaaaaaaacb",
+"a##aa#####aaaabbbaaaaaababaaa#abaaa#############.###aaaabcaabaaaabbbbacdedaaaa######a##bccdccaaaaaacdcaaababbbaababbbccbcbbcdcceedc####a##a###########a#aaa######..####.####.###aa######abbaaaabaaaaaaaaaaaaaaaaaaaacfeedbbaa############.######aaaa#abbaaaaccbabaaa###igdccbbbaaaaaaabcbabcbcb##a######a####a#aaaaa####aaaacb#abdcaaa#a###a#acddcbaabaaaaaaaaadfhhedaaabbabbcccbbaaaaaaaaaaaaaa",
+"ba##a##a#aaaaa#aaabaaaaaaacaabcbaaaa#aa#########.#########aaaaaa##ababdefcab#aa########aabdfgbaaaaaacdcaaabaaaaabbbbabbcbbbcccddaaaa####aa#aa########a#aa#########..##.##..###.###aaba###aaaaa#abaaaaaaa#aa#aaaaaa#aaaegdcbbbaa###########.######aaa##aaaaab#abaaaaaa#.febaaabcccbcbbcbbaaadbcecbaa#####a#aaaaa###aaa#aaaaabaaaabccaaaaaa#aa###adbbbcbbaaaabaaaabbchifbabcccabbccaacbaaa##a#aaba",
+"#ba########a###aaaaaaa#a#aaa#abaaaaabaa##a#aa###############aab####aaaaabccaaa##a#.#####abcdfb#aaaaaaaaabaabbbcbbbbbababbcdddfedcb#a##aaa#aaaaa###aaaa##aaa##.######.###.###########a#########aaaabbaaaaaaa###aaa##a###bfedcbbaaa############a####a######a#aaabcbbbaaa#gdaaa###bcddcecccca#addefgfddca###a##aaaaaaa##aabaacb####bbdcaaaaaa#aa###ccbbbccbaaaaaaaaabaadhieabaabbccdcbabbaa#####aaa",
+"#aab####aa###aaaaaaaaaaaaaaaa#aaaaaaa#####aaa#a##.############aa#abaaaaaaabaaaaa########abccdfcaaaaaaabbbaa#abbcbbaacabbbbcddecdcc####aaa#aaaaa#aaaaaaa##aaaa###..######.#####a########aaa#a####aaaaa#aaaaa########aa####dedbbbaaa##############a###a#####ababccbaaaaa#gcaaaa####bdebbbbbca#bddcbaabccaa##a##aa#aaaaaaabbaca####abdbaaaaaaaaaa#a#ccbbbbbbbaaabbaabba#adhgcbaccccccdccba######aaa",
+"a##aa#a###aaaaaaaaaaaaaaaaaaaaaaaaa#aa###aaaaa###.#############a##abababbaaaaaba######aaabbcddhcaaab##baaababaabaaabbabbbbcdddffeeb###aaabcaaaaaaaa###aaa#aa####.######a#######b#####aaacb#######ababaa#aaa##aa########a#aaeecbbbaa##################a##a##bbaabb#aaaa#cd#aaaaaaaace.aaa#bdccdcaaabcacbaba###aaaaaaaabaabccaa#aaabbd#aaaaaaaaaaa#bcccbbbcbbaaaaaaabbaabbhidbbcccbdeddaaa#aa#aa#a",
+"aaaa#aaaa##aaaaaaaaaa#aaaaaaaaaaa######aa#aaa####..#########.###aaabbbcbbbaaaaaaba#####aabbcccegcbaaaaaaaacbaabbaaabaaaabcccdeeffddaaaaabcbbbcfffecdcba#abb#############aa#a##acbbcba#bbaa########aabba###a##########aa#aaa#eedccbaaa#####a#a###########aaa#aaa#bcaaaaaafaaaaaaaaacfa##a#aaaba#abaaccbcbbccbaaaaaaabbbbbbaaaa#a#abccc#aaaaabaaaaaadcbbbcbcabbbbaaaaabaaccfjgbccbcccccaa##aabaa#a",
+"#a#aa#aabbaa#aaaaaa##abaaaaaaaaa##aaabaa##aa#a###.#.##############aabbbcacbaca#aaca#####aabbccdeedbaabbaaaabbabababaaaabbccdddffedffb###bbccefebccbdeda#aaabbaaa#######aaaaa###aabcca#adaaa#####aba#aaaa##aa################.cedcbbbbaaaaaaaaa##a######aa####aa#bbaaaaaadc#aaaaaabbee####abaaa#aa##abaaabbabdcccdcbbaccbcb##aaaaabbcdbaaaaababaaaacbccbbccbaaabbbbaabababadjiedccccbbbaaaa#aa#a#",
+"aaaaa###aaaa##aaaaa####abaa#aaa#a###aaaa######aa#################a##abbbcccbbbaaabba##.#aabbbbddedd#aacb#aaaaaaaaaaaaabbbccdddggffghecbbaabbbddabaa#aaaabaaa#bbbaaaaa##a##aba###aaabb##bbaa####aaaa###########a########.#####aaeecbaabbaaaaaaaaaaaaaa###aaa##a##aa###aaabeabaaaaaabchca###a#aa#a###a##aa####bca#abdecbcdbaaba#aaabbdcaaaaaaaabbaaaaccbbbccdbabaaabbbabbbabacjkjgfdccbaaaabbaaa##",
+"#a#aaaa###caa#####aaadb#aaa#aaaa#aaa##aaa###aaaa#a####a##a######a#a##aabbbbabba##aabaa##aaaabacdececaaaba#aaaabaaaa#aaaaccdeeefgeeefbcbbbcbbbcbaaaaaaabaaaaaa##abba##a#####aaa###aaaa##.#ba##.###aa############.##.#############dedcbaabbaaaaaaabaa###a###aa##aa#aaaaaaa#dbbbbbbbaacgg#b####a####a##aaabaaabbcaa#abacdcaaaabaaaaabbccaaaaaaaabbbbcbabcacccccbabbaabbbabcbbaaejklhfcbcbbaaaa#aaaa",
+"####aaaaa##aaaaabaaaaabbaaa##aaaa###aabbaa###aa#aaaa###aa#######aa#a##bcccaaabbaa#acaa###aaaabbcdcdcbaabaaaaaabaa##aaaabbccdfffghffdaabbaabccddbabaaaaaaaaaaaaaaaaa##a#######a####aaa###.aba######a#################a############bfedbaabbbbbaaaaabaa##a#########abbbba##dcbabbbaaabcgdc#####aabaa###a#bbbbbbbbbbaaabbcbbabbbaaaabbbdebaabbbaabcbbbbacbabbabbbbabbbaababbbbbghillgcbbbbbaabbaaa#",
+"###aaaaaaccdcaaaaaaba##aaaaa##aabaabaaab########aaaba####a###a##aaaaaabccbba##bbba#bca###aaaaabdcddcda#abaaabaaaaccaaabbbccefgfghffaaaabbaaabefbcbaaaaaaaaaaaabaaaa##aa#########a########aaa###a##############.##.#.############a#abdebabcdcbbcbaabba############acdea#abecbaabbbaabbdfc##aaaa#a#aaa##abbbcaba#adebaecabbaccdcbbabbcbdddbabbbabccccbbacbbbbbabccbbbbbaaaabcbcfijjkjfddcbabdebaaa",
+"db#bdccbbcb##aabbbbaa###aaabbbbaccaaaabca####.#####baba##a#aaaaa#aba#accbbbbaaaaaaaacbaaaaaaaaacccdccc##abaabbaaabdbabbcccdffffhggbaaaaabdbaaaababbaaaaa#a#a#aaaaba#a#a################aabaaaaa###########.#####...#####.##.####aaaa#bedcccaaaaabbaaaaa##a#####aaaaddaabdebabbbbbabbbbgcaa#a#aaaa###aaabdaddabaadcfdfgdacbaabcbbbcccbdcdffdacdcedccbbbacbbbbcccccbbbbabacabbdgigbbgjjedcbbbccaaa",
+"#bbbaaaaaabaaabbbea#aaa#abbbbabaaaaaaaaba#############b####aaaaaabaa###abbbbbaaaaaaaacbaaaaaaabbcccccdd##cbcbcaaaaaaabcdeffgggiigabbbbbaabcaaaaaaaaaaaaaa#aaa##aaaaaaa################aaba###baaaa#######.#####....#########.#a##aa##a#adfca###abbaaaaaaa#####a####bdbacfdaaaaaabbaacedfa#aa#########abefeddcccdebccfggfedaaccbacddecdccdeddccefddcccccccabaabbabaabbaabacbbhijgdbacfkjeedcba#a#",
+"###aaaaa#abbaaaaaaa#a####bcaaaba###a#aaaa######a####aa######aaababaaaa##aabbaaaaaaaaabcaabbaaaaabcbccccbcbaaaaababbcccdefgfgghkgbaabbcbccbaaaaaabaaaaaaaa#aaaa#aaaaaaaaa####a########aaabba#aaaa#####a#.###.######.#####.####.##a#abaaa#aaddaaabbaaaaaaaa#########aabgggfbaaaaaabbbabbcfea#a#####aa##afghhfggghhgccddffhfffcccbccdfgeeeceec#aabcddcdddccebaaabaaabaaacbbbb#ejhjgbbceceikibbceba#",
+"aaa##a#aabbabbaaaaaaab####bc#aaaa#aaaaaa#ab##aaaa##a#aa######aa#baaaaaaaaaaaaaaaa#aaaaacbaabaaaabbcccccdbaaaabbbbccddeeefeegjheb#a#aabaccdcaaaaaaabbabaa#aa##aaaaaaaaaaaa#######a###aaaabba#abaa####..###.###.####..#####.#######aa##ba#####bcbaaabbaaaaaa########abdfggebabaaaaaabbbbbchfaaa######abbfegggefgghgffeecefggfhheecdddeeefdcefcabaabccbaabcbcbaaaaaaabbabbbbbbfghggdbcbcbbgkjfbbecb",
+"#aa#a###aababbbaaaaaaac###.acaaaba#aba####ac#aba###aaaaaaa#aa##a#a########aaaaa#aaaaabbbbbaabbaaabbbccccebaaaabbccddddedegggfhbaaa##aaabcccaaa#aaabbbbcbaaa#####aaaaaa#aaaaa#####a###aaaaaabbdaaa########...##.###..########.#####aa#aba###a#accbaaaaaaa#######aaaaabccdeeccbbaabaabbbbegfgeca#####adefffefgggfghggfeeccegihijigedbccfeceddfeaaabcacbbaaabbaaabaaaabbbbbcbchgghfgdabbaa#bgkjgcdd",
+"d#a#a####aaaabbbabaaaaaa####abaabaaaaaaa###acdbaa#a###aaaaaaaa###########aa#a####aaa#abbbbbaabaaaaaabcbccdaaaaabccddeefefhgefgbaaaaaaabaabbaa##ababbaaabcca#aa#aaaaaa##aabaaa####a####aacba#bcb#aa#.####.#...##.##..################a########a#adbaaaabaa#aa##aaaaabbbcdeddddcbabebbcbbffeefdec##adeeefeffefghgghghhgfedfheabfghhfdcegecbbbbccaaaabcaaaaaabaaabaabbbbabbcdfffgffffabbbbbcabgkjec",
+"cdaa##aa#aaababbbaabbaaaa####bbabcaaaaaaa##.acaaaaaaaa#aaaaa#ba###########aaa#a###aaaababbaabaaaaaaaabcccdgbbbccccddeffefgfeffbaa###a#aaaaaa#aaaaaaabbbccaaabaaaaa##a###aaabfd#####aaaabbaba#aa########.###.##.###############################bacedcbbbbabaaaaaaaaabcccccddedddbbdeecdefeededdeeffdegffeddefgfgggggcb##abbca###bbefeefeddcdcbeeaaaaab#a###babbbbbababcbccfgfeeefegcbaaabbca#afkh",
+"gdcbaaaaaabbbaaabaaabbbbaaa###bbcbaa#aaaa#####a###aaaaaa#aaa#aaaaa##a#####a#aa#aa#a#aaaabbaaacaaabaaaabccdfgddddddccdfhhffddfbaaa####aaaaaaa##a#aaaaaabbdb#aaaaba#a#######aacegdbaa#aaabaabbb########.#.##.##..#...####.#######################babedededcbaaaaaaaaabccddeedefecfffeeffddddddeddeeeddeggfddeeffbaaaaaaaabdb#baa#a##cbdfeaaabbcdfbaaaaa####a##abbbbaabbbbdcgfgeeedeefabba#aaaaaabg",
+"gjgccbaaaaabbbbbbbbaacbaaaaa###aaaaaaaaaaa####aaa#####aaa##aaa#a#a#######aaaaaa##aaaaaaaabba#acaacbaaa#acccfgdefefcdecfhhddbcaaa#a#####aaa#aa###aaaaaaabbeebaaaaaaa####.###aaacdcbaaaa#aaabba#############.#.#.#...###########..###############aacddeeededceeedccefggfgggfedggghfdfecdddccccddeeeeefddfffddddbabbbaaaaabefcdb#aa##aaabcaaaaa#bdgb#abaa#######ba#bbaabaaeegfgfeeeecfcaaa#aa#aaaa#",
+"#bgifcbaaabbbcbbbbaabbbaba#a#aa##aaaaaaaa######aaaa##a#aabaaaaaaaaabaaaba##aaba###aaaaaaaaabbabbabaa#a#abcceffeecb#cddeeggcdb##a##aa##aa#########aaaaaaa#bedaaaaaa##########abaa#aaaaaa#aaabaa#####a####################..######.#a##.#########aabcccbcda##afgggffdbbbabdhheghifedddeecbccdcdefffeeffdfggfdbaaaaa#aababbacdddb#bb#aaa#a####ababbdebbbaaa####a#babbaaacddfgffeefeeddcbabbaaaa#aaa",
+"a##ehiecbbbccdccbbbbaabbaaa#aaa##aabaaaaaaa####aaaa#####aaba#aabcbbbaabbba##abaaa######aa#abbacbaaaaaaaaabcccdfcaa##bbbbceabaa######aa##a##aa####aaaaaaaa#abaaaaaa###a######abbbaba##aaa#a####aaa###a############.########################a####aa#dcddcdb#a#dedeedcaa#baacgegiifedddddddcdddefeffggfgeedbba#aaaabbaabaaaaabceebbdaaaaa######aaaaabdddb#aaaaaabacbbbaabdfffgfgfeeeeddgcbaaaaa####",
+"#b##adiifdbcefedccccbaabaaaa#aaaaaaaaaaaaaaaa##abaa######aabbaabbcbbaaaaaaa#abaaa#######aaaaabcca#aaa##aaaabbccc#########a###aa##a###aa########aaa##aaa#aaa#aa#aba##a#######aabbabcaa#ababbca##aa####a#####a.#########################a###a##acba.ddeecccba#cfeeedcaaaaabccbaigfeeeddddcbcdcddfeffggeedaabaaaabaaabbabaaaaa##cffedeaa#a#aaa#aaaaaa#abfebabaaaaaacadcaaffecffffgfffeeggaaabaa####",
+"#caaa#.ahjgffefgggffecbbbabaaaaaaaa#aaaaaaaaababaa#aa#a#aaaabaaaacccaaaaaa#a#aaabaa######aaababaaaaaaaaa#aaaabccb####aaa##ab###aa#####a#a####.#aabaaaa########a##aba########acbbaaaaaaaaaabbbaaa################a###a####aa############aaccb#adcbbdddccbcdebdedccba#a#aabdcbaggeeddedcbbbccdeeffffhggfcbaaaabbbcaabaaaba####a#debceea#aaabaaaaaba#aaa#cfgcaa##aabcbcbdffedfeeeefefeedhcaaaa#a###",
+"####aa##.behhgfeeeddefedbbbbaaabaaaaabaaaaaaaabaaaa#aaaa#a#abbaaabbcbbaaaaaaaaaaaba####aa#aaabaaaa##a#aa#a#aaabbcc.##ab##aabca##aaaa############aabaaaaa#a#a#####aaa#bb#.####bccbaa##aaaa###aaaaa######a#######bbabba####bb###a#a###a###bcccccdcdccddcbbabcdcddccba####bdddb#bdcecdedcbbbbbcceeeeehhcdaaaababcbcaaaaabaaa#####ab#aabb###bb##abcaa###a##adfeba###aabaaefefffedddeedefefhbaaa###.#",
+"#####aaaa###chikjiigedcegcccbabbaaaaaabbaaaaabaa#aaa#a#a##aaaaaaaaabaa#aaaaaaabbbaa######aaaaabaaaaaa##aaba##aaabab.###aaaaaabaa#aa#a#############a###aaba########aa#cbb####abcbaaa##aaa#a######a#.####aa###bbccbbdccbaaabb###a#aaaaa###cbbbaccccbbcccaaaabbccccbbaaa#accdcb##bacgeeedccccbccdeeefggebdaaaaabbbbbbaaabaa#####a#a#aa#####aaaa##ca#####a####beeca#b#abadgefffedeedfdcffeff#a#a###.",
+"..######a#aaadd#acdhihecdgecbcaa#aa####ba#aaa##aa##aaa###aaaaaaa##ababaaa#aaaaabbbaa######aaaaaaaabaaaa##baa##a#a#b######aaaaaaaaa#################a#aa#bcb#####aba##a######bbbcbaabcaa#################a#abcdbdefededcbcbaa##aaa#a###bcbababbccbbbbbcaaaaabcccbaabaaaabcdbba###bhhfhgeddccbccddfhhhfbbaaaaaabbbccaaaabaa####aa#a#####b####aa#aa#ab###a##aaabefd#a#abbfgfeeeeeedeeddefggbaaa####",
+"##.######aaba#abaaaabeiiebceddcbaaaaa###aaba#########a##aaaaaaaa###aaaaaaaaabaabbbbaaa###aaaaabbbaaabbaaaaa###a###bb#####aa###########a######a#####aa#baaaba##abcedcbaa##a##bcccbaaaddccaa##############a##bbceffgfededdedcbaa#a#aaa#bcabaaabbbccbbbbbbaaaabbcbbbbaaaaabbcda#a##ehgfeeeeecddbcddfhhgcbbbbbbaaaabcbbbaaaaa###.#a#a#a####aaa###aa##a########aabbbedbacfegggfeeefeddccddgihdaaa####",
+"##.###a####aaaa#bacbaa#chidccdfdbbabaaa#ababaaa###a###aa#aaaaaaaaaba#aaaabccccbcccccabb###aabaabbbcbaabaa########aaab.####aaa##################a####b##aaaabb#aacdddcbb#######bccaaaabdbba#####aa#a#########abccccccddcffhigcbaaa#aa#acaabaabbbbaaabbbbbaaaabbbbaaaaaabcccdda#a#higheddefedeecdffffeeaaabbbbaaabcbaabaaaa#########a####aaaa######a#######aaabdcbadgfdeddegfgfeedcccccehigaaa####",
+"###########aa#####aacdb##ejgcbbfedcaaaaaacbabaa#####aaaa#aaaaaaaaaaa##abbbbbbaaabbcddddbccdcccbababaaaaaab#########aba..####aa###################aa########aa##aaaabbbba##a####ccaababdaa#aa#####aa##########aaaaabbccdfgjjihdcaa#aaaacbaabbababbaabbbabaabbbbbbbbbbbbbcccddebadhggfffeeffffeeeffdccddaaaabaaabbabbbbaaaa######..######aaaaaa#a###a#aaa###aaaccc#ceggedddcffffedcbabccdfgebaa###",
+"#########aabaaa####a#aabbachjgbacdedcccbabaaaaaaa#####aa#######aaaaaa#aaaaaaabaaaabbccdccddcbbbabaaaaaabbaa########aabb.#######a##################aaa##########aa##abaaaaa######bbaaaaba#a#a#.##.#a#aa###aa###aaaaaabcddgijijjigeba#abdcbbcdcabbbbaabbabaaabbbbaaabbbbbcacddee#dfeeeffeccdghhfffebccccaaaaababbbbaaabba#a########.###a##aaaa##aa##aaaaa####aababbddceggfedcdffedcbaabcdeeffaaaa#",
+"#######a#aaaaaa#a#####aaaabcdiibaaacecddcbaaaaaaaaaa##aaa########a#aa###aaaaaaaaaaaaabcccbbaaaaaaaaabaabbaaa######aaaaca.###.##a#a####a########aaaaaaa##...###a###a##a#aaaa#####bdaaaaaa########a########a##a##aaaaabbbbegfeedeghgeccddeeefgcbbaaaabbbbaaaabbbaababbbbcccbceeebegdddeffedbdeiihecbcbdbaabaaababcbbaaabaaa#a#.############aaaa##b#a##aaaaa##aabbbbccdceghgeddefedcaaaaccdedfaaaa#",
+"########bcaaaaa##########aaaa#gidaaabedcccbbbaabdbaa####aba#a#############aaaa###aaaaaaacbbaaaaabbabbbbbcbbabaa######aabb..##.####aa#aaa######aaaaaaa####a#.####aa##ba#aaaba#####dbaaaaa######aaa#aa######aa###aaa#aaabccebabaabbdfhhhgfghggdbaaabbcaaabbaaabaaaaaaabccccccedchigdcdddcedccabghdbaaabcaaabaaaaabbbbcbbaa##a########a##.#aaaaaaaaa#aaaaaaaca#acbbbbbcccdefeddeecdcbaababcfdfeaa##",
+"########baaaaba#aaaa#####a####aciib#aacdddbabbaabbb#aa#####aa#############aaaa##aaaabaaaabaa##aabababbbbccbbbcb#######aaaa#...##.#####aa########aaaaa######a############a#aaaab##abbaaaa#######cb############aa#aa#aaaaabaaa#######bfhigihhfbaabaaaaaabaaaabbaaaabaaaccbccdcchiihhdbcddcddccbbeeaaaabbbaaaababaabbbeeeaa#####.###.aaaa#aaaaaa#aaa#aaaaaa#bbadccbbbbccccbcddddcbcccbaaaaddddge###",
+"########a##abbaaa#########a#aaabcfjhaaabcdecaabaaaaaaa#######a########a#aa#abaa#####aaabaabaa##ba#abbccbaccaaca########abcb..######################aa###ceb#######aaa#####a#aaa###acaa#aa#######b############a#a##aaaaaabaa########abacfhhfcbbaaaabaaabaaaaccaaaaaaaacbcbbcffgfgcegeddeddcdccbcd#aaababbbaaababcaabaaccba########a#abaa##aaaa##aaaaaaaaaababcbbbaccbbcbccdddcbbbcbbcbbadcdeehd##",
+"########bb####aaba#########a####aabfjfbbcbcfdbabaaaaaaba######aa######aaaaaaaaa##a#####aaa######aaaabacbbaaabaa#########aadc...#######.##########aaaaaa#ddeb#a####aaaabeb######a###bbaaaa##b####aa#.##########a#a#a#aaaabaaa##b###.adbaabeecbaaaaaababaaaaabcabaaaabbbbbcdcfgeddgbbggeedddcccccc####aabaaaaabbaabaaa#acda############aaaaaa#aaabaaaaaaaaaabcbabbbabcbbbbcddccbcbbbabbbbccdfggf#a",
+"aaaa####bc##a#aaaaaaa###.#####.####aciiecccbceebaabbabbb######a#a####a##aaaaaaa########aaa#######aaabcbbabbaaaaa#########acfc..####.#.###.###aa###a#a#aaabcaaaa###aaaa##########a##bdcaaaa#ba###baa##########aaa####aaa#bbababdcbaacbbbaaaabbaaa##aaaaaaa#aabbbaaabbbbbbcdcccddcdec#adfedddcccbe#####aaaaaaaaaabbbaaa#bdb##.#######.####aaaaa###aaaaa##aaabccbbbaababbbbbcdccccbcbbbcbbbdcefghc#",
+"########a#####aa#bbaaaba######...####adhifegfddfdcabccbaa###aaaaaaa######aaaa##aa##a###b##########aa#aaaaaabaaa######a###abdfb..#######.##.#####aaa#a###baaa####aaa#########a####a#bddcbaaaa####aaaa####ad##aaaaaa#######abadddccccdcba##a#ababa###aaaaaaaaabaaabbbbbcbbcbbccdccbaba##afedddccbfa######a#aaaaaabbabaaaaab#####.##..#..a###aaaaa#aabbaaaaaabcccbbbabbbbbbbbddccbbcbbbcbbcfdeeffha",
+"##############aababaaaa##########.##.#..chjjhjifffdeccdbaa#aaa###aa#####.##aa#######.#######a#########aaaaaaaaaac########acchc.....#..###########aa##aa#abaaa##aba##a######aaaa##a##bdcbaaaa#####a#aa###bd###aaaa#aa##a####adgdcbbcddbb###aaa#a#####aaa##aaa##abbaabbbbcbbbcccddeccc#a#bhggfedaec##########aa#aaababaaaaaa#####.##.##.####aaaaaaaaaaaaaaaabdcbbbababbabbbabddcbbbbbbccbbdifdefge",
+"a###a##########abb#aaab#a#######...#####.##a#acgkigfeefdcaaa##aa#aaba####..######.#a###a#aa#aa##.#######aaaaaa##ba#####aaabbeha...###.###.#######a##aaa#aaa#a#aaaa###aa#a###aa###a###cdcaaa######a#####abb####aaaaa####a####deebbbccdbba##aaa#aa####aabaa#a#aabbbaaaaabcbcbbccbcedbba###cdffffeefba###########aaaaaabcaba#####.####.#######a#aaaaaaaaaaaaacdccabbababbabbaabcccbbbbbbbccdeeedefh",
+"f#######aa##a##aaa#aa#bba#########..############afkjgfgfeeeba#aaa##a#######.####.#.#####abbbaa##########aaaa##a#a#######abbcdhe#...######.##a####aa#a###aa#a#aaaaa######aaa###########bdbbaaa####a######aa##.##aaab####aabdecdcbaabbbaba##aaa#########abaaa##abbbaaaaabbbcdbaccbcebaa####adghfedeeba#############aaaaabbcb##########.######aa#aaaaaaa###bcdccbbabbbacbaabbbbbbdcccbbbbbcccccddeh",
+"hc#####aa######aa####aaaa#####a###.......##aa##a###gijhhhggeb##baaaa####...#####.#..a###acccaaa##########aa#####aaa####aacdddhf#..###.#..####aaaaaaaaaa###a#aa#aaaaa#####aabb##########cecaaa####a##############aabb##aabacddbcbbabbbaaaaaaaa##a#######baaaaa#abbaaa#abbbabcbbbcdgd####a##adcgfecdeb######a########aaaa#baaba########.######aaaaabbbbbbcbccbbbbbbbbbaaaaabbbbbbccbcbbbbcccccdeed",
+"egb##baaaaa####a##aa#aaa#a#######.#..###.###########adfilkhfca#abaaa#####..##....#....###bbccaa##a##aa####aaaaa##a##a##abbcfhjfb#..#####.######aaaaaaa######aa##a#abbbba###aba#aa#######cecaaaa###a#.#######aa##aa#aa###aaabcbcbbcbbaaabb##aaaaa#######abaaaaaabbaaa#abbbbbabbabdfeaaaa##a#ca#eecccfcaaaaaaaaa#a#a######aaaaabca########a####aaaabababbbbbbbbbbbbbbbaaaaaaabababccccbcccdccbdffd",
+"cfhd#acaaaa##a#######a#a##a###a##.....######.##########bddjkidca#########..###....######acaacbbb#a###ab##aaaaaaaaaaaaa#aabcfgejfa#.###a######a##aaaa#aaa#a###aa##a#abbcba#####aa####a###aeedbaaa##aa####...#aaaa#bcaccbaaaabcdccabcbbbaaca#aaaaa#########aaaaaaabaaaaabbbbbbbaaabbecbbcaaaaaa#adecccedcaaaaaaaaa##a###########abaa######a####aaaabdbbbbbbbaabbbbbabbaaaaaaaabbaabccbccbccdccdefg",
+"fedfea#a####a##a#a#######a####a#.##..#.####...########aaaaaeikhea#####################aaacbabbdfdbbaa#aaabbcbbaabaaaaaaabcdfbbeica..#a########aabaaaaaba#a###aa#######aaa#####aaa#.aa###adffdbaaa##ca####.#########abbcdeeeefcdcbabbbbbaacbbaaaaaa##a##a##baa##aa###aaaabbabbaabaadfb#bbbbbaa###feccbeecbbabaabaaaaaaa#aa###a####a########a##aaaaabbbbbbcbabbaaaaaabbbaaaaaaabbbabccccccddddeeee",
+"fggehdaaa######a##########aaaaa#.##.####..#..##.#######aabbaadjljgda.#################aaaccbccddcccccccccccccdcbbccbcbaabbcfdcbgf#...#aa######abcbaaaaabaaaaa############.##aa##a########dffedcbaa#cc##########a####bbbbcdffeedaaabbbbbcbabbaaaaaaa#######abaaaaaaaaaaaabbabbaa#a#bdcbbbaaaaa###cfeeehhecabbbbbbaaaaaa##aaa##a###a########aa#aaaa#bbcbbbabbbbaaaaabbbbbabaaaaaaaabbbbbcccddddeee",
+"edehhg#aaa######a#a#####a##abbaa###.###################aaabbcaacjllkhbaa#######a######bbaefddddcbbbaaaababefeedddccffdccdfgeeeefec#...#ab#.####abccbbba#aaaaaa###########..###a##########bfdfdccaaacfb.######aababaaaccccbdffebbbbcbbaacccbabbabaaaa######aaaaaaaaab#aaabaaaabaaaabbeffcaaaa####aeeeefiihfcabbbbbbabaaaaaaaa##a######aaaa####abbabbabcbaaaaccbbbbbbbbcbcaaaaaaaaaaaacbbcdddddede",
+"eefgghcaa#######a##aa######abbbcc#.############.###a#aaaaaaaaccbafjllkjecbaaaaaaaa##aabcccgefeecccbba#aaaa.acffffffcacdccbbbfffefda#.##########aabcedba##aa#a#####a#####..#####aa###.####bceecccbaabdfa##aabbbaabbbbdcbbccdcceebabbbaaabcdcbbbbbaaaa######a##aaaaaaacaaaaabbaba###acdeegcbbb#####aeffgfgijkgcbbbbbbbbabbaaaaa##a#aaa#abaaaa##aacdbabbccbaaa#bbbbaabaabccbaaaabbaaaaabbbccdeedddd",
+"deeffdfd#####a######a#######aaaca#a############bdca###aca##aaaceddfijjnligdcbbcbaaaaabcddchgedddbccaaa#aaaaa##accfbbbaa####bdhfedhd#.###########bbcccdba###aaa#####a##a#.#####a####.####.#abedebdcbbcfe#####adcbcddbbdbaaacbcbccbbbaaa#bbcbbbbbbaba#a############aaaaaaaaaabaaaaaaabdfcccbbba#####aceffgiijihedccbbbbbabbaaaaaaaaaaaaaaaaa#####aabaaabbbaaaaaabbaabbbbbcabaaaaaaaaabbbbcccdddddd",
+"ddddecbdca###a###a##baa#aa##abaaba#a###.#####.#aabaaa#aaa##aa#acdhilmklmlmkheegecbbbbccbcefgedcdcbbbbaaaaa#aba#a#cdabcbaaa#achihggfa############abdb#bcaa##aaa#########a###.######..########beddecbcdffc###.#acdfffdabcca#aabacbbbbbaa#abbbbbbbbbaa#############a#aaa#baaaaaba###aaadfd#babacababbbcegfhhiihgfdddcccbbbaabbaaaaaaaaaaba#aaa###a#aaaaaaaaaaaabbabbaabaaabcbbbaaaaaaababbccdddddcd",
+"deddddcacaba###a####aaaaaa#aaaa#aaa###aa#########a##aa#aaa##aba#.cfehhjkjllmllihfedcccbbdefgdcccecbbbccbaaaaaaaaabdbbbcbaaaabhjjhggea#.####a##a#accaa#cdaa#aaa#.#############a##a##.###a####.cedccccefbbaa#####deffeaacdaaaa#aabbbbbaaaaaabbaaabbaba#####a.###a###a#a#aaaaaaa#a##aaacdecaaaabaa#aa#bdgfeeefhhfdccccddcbbaaababaaa##aaaaaaaaa###aaaaaaaaaaaaaaaabbaaababbbbabbbaaaaaabbbbcdcdccdd",
+"dddcccdbbbcba#bb#aa###aa##a##a####a##.####aaa##a#aa##a#a#ba######.fffkjlhkkljmmmlieeddccefaeeeccdedbcdccbcbaaaaaabaccbccaaaabeijjigieba.#######aacbaa#accaaaaa##########a#a###aaa#############decabdeeeaba###..adeddcaabcbba##aabbbaaaaaaaaaaaaaaaaa#####a###########aa#abaaaa##a#abbcdeba#b#aa#####cefedcbbdeedcccdddcbbbaabbaaaaaaaaaaabaaa###aaaa#aaaaa###aaaaaaaaaabbbaabbcbaaaaaabcccccccdd",
+"ddccbcccbcedaddaaaaaaaaaa#aa#a######...###########aaaaaaaaaa####..cfhjjkmlmklkklmnjfeedeefebdeddegheeedddccbbbaaabbccbcbbaabbbgjkjjhifda.#######aaaaa###abaaaa####aaa###########aa##########..adccaddcecbabbaa##dedddcbabcbca#aaaabbaaaaaaaaaaaaaaaaaa###############aabaa##a####aacbcddebaaa########cffecdcbceeefdddddcbbbaabbbaaaabaaaaaaaaaa###aaa#a#aaaaaaaaaaaaaaaabbbaaaacbbaaabbbbcdcdccb",
+"cdcccccbbcdbaacbbbbbbaaa#aa#aaaa#####..#..##.#####a#aaa####aa######eigfcfgijjjlmmmmnlhfhiggdddeefgegfgffdeddcdcbaaccccbcbaaabbcfjkkkijgfb#######a#aa######a#############a###aaaaaba############abcc#ddcccbdecdcaddddddecbbbccaa###aabaaabaaaaaa#aaa#########.####a##a##a#aa#a######abccdgbb#ba#a######cffgfdefffehgdddeccccbaabbbaaabbabaaaaaaaaa###aa##aaaaaaaaaaaaaaaaaaaaaaaabbba#aabbacddccc",
+"cddcccbbcccaabbabaacbaaaaa#aa#aa#.#...#...#..###a###a#########aa##adeaaa#abedefijlkmnnlkkjdddfdcebb#degfaefgfeddcbdcddbacbbbbbbdjjklkkihgc#aa#####aa################aaa##a#aaabaaaaa###########aabdbedcabdddeeddddedcccddccbbbca###aaaaabba#a#####a#a###aaa###.###a#######aaaaa###aabbbbcdaaabaa##a####aeghhhggghhhfedddcccccbbbbbbbbbbbbbbaaaaaa####aaba#aca#aaaaaaaaaaaaaaaaaaaaabaaaaabbbcddd",
+"dddcccbbdedaabdaaaabbabbbbaaaaaa#.##.##.#.#####################aaaddbbaa#aa##a##aceejnllkkhfhfccfbbaaaabafabdeffgfcdddcabbbbabacgjkkllkhjhbaa#####aa############a##aaaa###aaa#aa#a#####.####a##aa#deedcabdeeeedeeddeedbccdcccdcb####aaabbbaaa#####a##a##a####################aa####aabbbcdea##a########aaabehiiiiiihfedfdccccccbacbbabbbcbbbbaaaaaaaa##ab##bbaaaaaaaaaabaaaaaaaabbbaaaaaabbbbbdd",
+"ddccdbcbedcaabbbbaaaaaabbababbaa#################a##########a###a#ecbaababaaaa#####abkllllljgbaaccbababbabaaaa#cedfheedcabbbbbbbchkkkklkhggeba###aba####.####a####a##aa##aaaaaaa##aa####.####a####dfdcba#bdeeeeeefedddcbbcdbbadcba###abaaacaaa###a##a###aa#####.####a######.##a####abbbbccbbc#ab##a#aa#ca###cfggihhihffffedcccccbbabccccdccbbbaaaaaaa#aa#aa#aaababaaabbaaaaaaaaaaaaaa#aa#abbcccc",
+"dedcccbcecaaacbababbbaabbbbbcbaaa#..###.#########a##############.cdabbbbbbbba###aabcddilmmljeaaabcbbbbbbbbbbbabaabcefgfecbbbbbbcdfjjkkkmkhfgecbaaabb########a######aaaaa####aaa###################befcbaabbadfeeeeffededcbbccabccccaa#aaa#abaa#######a########...###########.##..###abbbbcbbf#aa###abaa#a#####acfgffgfggefddcccccbbabcecbbbcbbaaaaaaaa##aa#aaaaababbbabbbbbcbbabaaaaa##aaaaabbcc",
+"cddecccccdcaaaaaabbbbaaaabbbbaaaa########.####################..aaababaaacbba#abddbcdfeejmllf#aabbbaabbbbbbaaaaaaa#afffdedcbbbddffjfijjkkkhgfed####aba#######a####aaaa#aa#####a######a############adffddcaa#befefedeeddccccbcbaacbaabbaa###aba####a###############.###########.######aabcddcefbb###bbaaaaaabba#cffffghhgfffedccccccbcbbebbbbbbbaaaaaaaa####aaba#aaaabbbbbbcbaaaaabbcbaaaaaaaabcc",
+"dddddfebdfeba##aaaaaaabbbbabaaaa####.#########################.abbaaaaaaaaabbaaabba##aceeilmme#aaaaaaaabbbbaaaaabbbbbefgeddcddddegiighiiggjggfdba##aaaa##############ba#b###aaaa#######a##a#aaa####dfgffgcaabefeeededccccdddcbbbbbaaacbab###aaaaaa########a#a########.#########..####aaabdcdecbdc#aa###aabbcccaacegggfgghggfeeeddddcccbccbbbbaaaaaaaaaaba#aaaabaaaaaaaaaaaaaaaaaaabbaaaaabbabbbc",
+"bcdeeeeedeeda##aaaaaaaccbbaaaaaaa####..##.#########a##########aaaaaaaaaaaaababba#aa####abbdhkmgbbbaaaaabbabaaaaababbbaehfcdeeeegghkkjjigdeehfeccaaaabcba########a####aaa#####aa####a####aa###baba##adfgfffdeeffdcddddddbcccdccbbbbbbb##bdb###aadb#a##############.##.######.##########abcdcedecegdb#a#aaabbcddaa#adfghfghgffefeefeeddcccccbbcbaaaaaaaaaaa#aa###aaaaaa#aaaab##aaaabbbabaaaabaaabb",
+"cbceeeefffffd#aaaaaaaaaddbaaaaaaaa#############.#############cbbaabaaaaaaabaaaaaaaaa###aaa#achlkigdaabbabbbbaabcaacaababccdbbdedcdfehkkjgeceheccda#aabbba###.######a#aaa#####aa######.#a#aa##aa#aa##adgggfeeggffdcccddcccbbcbccbbbaaa####ca##abcba#aa##########.#####a######.#.#######abbcbddbdfhgeaaa##abbcdcaaa##aaceghdfgffffffeeddddcccbbbaaaaaaaaaaaa##aa#aaaaaaaaaaab##a#baabbabbbaaaababb",
+"ccddefgfefffd#a##aaaaaabccbabaabaaa##########...############acbaabaabaaaaaaa#aaa#aabaaaa#aaaabgkjiifbabbabbaaaabaaabbabaaaaaaabcc#####cgkmjgfhfcbcaaaabcbaa########a#aa###a###########.####a######aa##bghfefgeddeccbbbccccccbcdcaaa#a##a#aa#a#aaaacbaa##.############aa########.#######bbbccddddggfbaa###abbcbaaaa#aaabeeeeggghgggffeedcccbbbbbcbaaaaaaaaaa###aaaba#aaaabbaa#a#abbbbbbabdbbaaaab",
+"bcceddefhgfcbaa#a#aaa###aaabbbaaaaa#######################aababaaaaa#aaaaaaaaaaa#aaaaaaaa#aa###cefllgabaaaaabbbaaaaabaaabbabaaa#ba######bfjljhghcac##aaacaa########a###############aa#.##a#############afgfgfedcccccbbccccccddcccaa##a####aa#aaaaaabaa#################a#a##.#########aaabccccddeegfbaa###abbaaa#aaaaaabdfceghhhhhhgfedddcbbbbbbbbaaaaaaaaaa###a##aaaaaaabbbaaacbbabbbbbcccdaaaa",
+"bbcccdefhiea###a##aaa######aaaa#aacb##############a####aaabcbbabbaaaaabaaaaaaaaa##a#aaabaaaaaaaaabekljbaaabbaabaabaaaaaaaabbaaaa#a#aa#####aekkhhiba###aabbbb#####a.#########a#a#####a#######aa####.#aba##gggfeedccbbbbbbcbaabccbcbaa##a###aa##abaaa#aa###..###########.###a##.#######aaaabbbcdddcefgaaaaa##abaabaaaabbaabdeffghighhgfffeeccbababbbbbaaaaa#aaaa#a####aaaaaabbaabbbbbbbcccbcccdbaa",
+"bcccccdefgeaaaaaaaaa#a#a#a##aaa#a#aba#######a#.###aa######bcaaaaaaaaaaabaaaaaaaa###aaaaaabbaa#aaabbchkkc#aaaaaaaaaaaaaaaaaaaaa#a#aaa#a#######dkklibca#aaabcdca#a#aa#################a######aaaa######aab#cghhgfddcbbbbaabaaaaabbca##a##abaaa##abaaba#a#aa############...##.###.#..####aaacbbcdccdcdedbaaa#a#acbaaa#aaaaaaabcffffghhhfggfeddbcbbbaaaabbaaaaaaaaaaa#aa#aa#aaabbbcccbbbbbbbbbbcdccb",
+"bbbccccdfcec##aaaaaa####a####aa#aa#aca##a####baa#######a##bbbaaaaaaaabbbbbaaaa#aaaa##aaaaabbba#aaaaaadijgaabaabbaaaaaa###aaaaaaaaaaaaaa#######behlidcdbaaabbcecaa######a###aaa###########a####a#######aaacghihgfedcbaaaaaaaaaababbbaa###aaa####a#aba##a#a#####..######......#...#.#.####aaccbcccdcdehhdaa####bcba###aaaaaaabaaadfeeegihgecdedcbcbaaaabbaaabaaaaaaa##aaaa#aaabcbbbccbbbbbbbbbcbbb",
+"babbcdddddde######aaa###########aaaabda##a####abaaa#####abbaaaaaaaaaaaaaaabbbaaa#aa##aaaaaaaaabaaaaaabcdkib#aaaabbaaaaaa####aaaaa#aaaaaa##a##a##acgjhfgefcbbacccbaa####a######aaaa########a#############bfffhjigedddbaaaaaabaabbbbccaa####aa###a##aa#################a##.....#..#########aabbbbcccddfheaaa####bba####abba#aaaa##bca.#bghfedecbccbbbaaaaaabaaaaaaaaa#a#aaaaabbbbbbbbbbbbbbbbbbaba",
+"bbabbdcdddcec#####aaaa#a####a###abaaaaaa##bda##aaa######aaaaa#######aabbbaaaaaa##a##aa#a#aaaaaaaabaabacbdjjbaaaaaabaaaaaa##########a#aa##aaa##a#a##cfhhededabbdcbcca##########aaaaa############a######a##dffgjiiheedcbaa###bbaabbbddba#########aaa####################a###..###..##..###aaaabbbbcbcfffebaaaa#aabaa##a#aaaaaaa#####aa#.bdegfeccbbaabbaaaaaaaaaaaaaa#aaaaaaaababccbcbaabbbbbbcbbab",
+"dbbbbcdcdcdcea###a####a#aab#aaaa##aaaaaaa##a####aaa###.##aa###########aaaabaa#aaaaaaaaaaaaa#aaaaaaabbaabbbhkfcaaaaabbaaaaa##########aaa###aaba######.ekjgddbabbaabccbba########aaa####.#######aa##aaa#####dgfgghgggedcbbaaa#aabbbcbedba#######aaa#a####################aa#.......##..####aabbbbcbcdefeebb#aaa#aaa##ab###aaa#######a###.##cgefdccbbabbbaaaaaaa#aaaa#a#aaaabbccbbcbbbaabbbbcbccbbb",
+"bcabbcceffabbc########aaa#aaaaaaba#aaaaaaaa########.#####aa######aa####aabbbaaaaaaa##aaaaaa###aa#aa#aaaaabbfkjhdaaaabaaa#aa##aa#####aa#a#a#aaaa######aikjjhbaaabbaacbaaa###############.###################bfhggggggfedcabaaaaabbcdeccaa########aa##########aa######a#a##a##..#.#...#####aabbbbbcccecdgccb##a####a##a############aaa######agfedccccbbaaaababaaaaaaa####aabbaaaaabbababbbccccbbcb",
+"ababbccdffdbbbba###aa#aaaaaaa#baaaaaaaaaaaa#########.####ab###########aaaaaaabcbbbaa###aaaa#ba###aaa###abbbbflljeaaaaaaaaa###########aa##aaaaa#######.afikkiba#abbaaba##########a############################ehffgggfeedcccbaabababcccbaa######aa##aa###.###aa####...#########...########abbbbcbbbcdecfgdaa#######################aa##a####bfeeddccbbbbbaaaaaabaaa#abaaaaaaaaabaaaabbbbbbccccccc",
+"adbbbbcdddecbaba#a#######a#a##aaaaaaaaa#aa##########.###aac##########a##aa#aaaabcbbaaaa##aaa####aa#aaba#abbbbdillhcaaaaa####aa####aa#aaaa##aa#########.#chkli#aaaaabbaaa########a#aa###a###############.###aa#fggffgffedeecbbbaaabbbbcbaaa#####aa###a############################.######aababbcbbbccedcfccaaaaaaaa###############.####a#####bffeddccbbaaaaaaaabaaa###aabaaaaaaaaaaababbbbbbbcccc",
+"ccbbccddeeeccaaca##a####aaaaaa##aaaaa#a#aaaa#########.###ab####.#a###aaa##aaa#aaaabbaaaaaaaaaaba#abaaaaaaaaaaachkklfbaaaa##########a##abaaa############..#bimiaaaaaabaaba##########aa#babaa##############.##a##aegfcbdeedfedbbbabbabbcbbbaa#####a#####aa######################.#########aabbbbbcbbacddddccaaa#aaaaaa###a#####################afgeecdccbaaaaaaa#abccbaaaaaaa#aaaaaaaaaaaabbbccbcc",
+"ccedcdddeeeccbbbcba#a###aaa#a#a#aaa#####aa#a#############ab#####.#####aa#a#aabaaaabbbbabbba##aa###acb#aaaaaaaaacfihkida##a#a###.####aaaaaaaa##a###aa######.ahljc#abaaaaaaa###.####a######abaaa############.#####.bababeedegdcbccbcbabaaabba#a##aa####aba#aba#a###################.####a##ababbbcbbbcdddedea#aaa#a####aa#######.###.######a##a##fgfedddbbaaaa#bcdccbbba####aaaaaaaabbabbbbbbbcbbc",
+"cddeddddeefddcbbcc#a#aa#aaaaaaa#aaaa####aaa######aa######ab#a########aa#a#aaaaaaaaaaabbaabba#aab###abb######aaabbcfheihc######a#####aa#aaaaaaa####aaaaaa###.aikjcaaaaaaaa#################aaccbaa#a################aaaaaaabdddcbccbaaaaaaaaaaa##b####abbcccb##.###a#############..###aaaaaabbbbbccbbccccddecaaa#aaaa###a########################effedccaabbaccbbaaaacc####a#aaaa#aabbbbbbbbbbbcc",
+"dcdcdcdeddfecdcbcdaa#aaa##a###a###aa##############aaaa###aba#############aaaabaaabaaaabbabbaaa#aba####a##a###aaabccefadhhb##aaa#####aaaaa#aa#a##aaa#aaa#####.aflkcaaaabaa####################ddcbaaa#################a#aaa#bdddbbcbaaaabaaaaaaa#a####a#baa####a###a###aa#############aaaabccccbcccbbcdcdedefb##a###aa##aa###############a##aa####efddcbcecbccabbaa#aacc###a##aa#aaaabbababbbbccc",
+"ccdddcbcfhfddcdcbbc#####a#aaa##a########a#a#aaa#####aaa##abaaa##.#######aabbaabbaaaaaaaababbaaa#aaaaa###a#a#a#aaabccdha#diga##aba#####ca##aa####aaaaa#a#######acildaababbaa###########a#######abccbaa#########.#########a###cdedbbdcbbabba#aaa###a####aaaa#aab###a##a#aa######aaa######aabbccccccccccddddeddfca#aa##aaa#aaa#####a####.###aa#a##a#cfeddedacaaabcaa###aacc###########aaaaaabbbbbcc",
+"ccccddccdeffdcccdccb########aa##########a#aaabaa#####aa##ab#aa###########aaaaaaababaaaaaaaabaabcabba############aaabcffb.afjfa#aba####a#a########a#a########aa#abhjb#aaaba#a##########a#######aabcccbb####.#..###aba#########abddbcecbbcbba#aaa########aaaa#a#a###aaa########aaaaa#####aabccdcddccccccccddedcec###ba#a####a#a##########.######aa#adedcbbaabaaabbaa###aabca##aaa#a##aaaaaaabbbbbc",
+"cccccdcedcddfebbdcbdb#######################abcbba#######bbaa######.######aaaaaabbabaaaa##aaabababaaaaa########aaaabbcfiea#bgjeaaa######aa#a#############a####a#acgigaaabb##########.##a#######aaa#adcba##########ba#a#a#####a#adfcddbcccbaa#aaa######aaaaaa##aa#aabbab#aa####aaaa#####aaabbccdddcdcbbbbcccddegd##baaaaa#########a################abbcccbbbbabbbba#####abca##aaa####aa#aaabbbbbb",
+"bbbccddcdcddefdbcdadcaaa#####################aabbbba#a#aabba#aa##########aaaaaabbaaaaaaaaa#a#aaabbbbbaaaa###a#aaaaaaaabfifa##ejgbaaa########a##################acbcfigba#aa###########a#########a#aaabbbba#######.#a#a#######aaaaffddccbccba##aaa##########a######aabaaa#.####aa######aaabbbccdeeefggecdedcdfedcbaacbaaaa##a#a####a############a##aa#accdcbcbbbbbba#####aaca#aaaaaaa###a#aaabaab",
+"bbbbcccccddddfecbccbdc#a############a###aaaa#aaa#aa##aabcccc###########aa#aaaaaabaaaaaaaaaa#aaa#aaabbbbbbaa###a#aabaaabbbhie#.bfhfbaaaa###aaaaaaaaa#######a####aaabdhifbaa########aabaa###a######aa#####bccaa#####.#####a########afgeddccdcba###aa########a#a#######aa######.##########aabcbcccdffghihgdcddcbacbbeabaaaaaa#a###################a##aaaa#bcddcdcbbbab##a##aaaba#aabcaa####a#aaaaba",
+"bbbbbbcccccdefedbbcacdc####aa##a#.##a#.##abb######a##aabbccc###########aa#aaaabbbbaaabaaaaaaaaaaaaaaabbbccbaa##aaabaabba##diic##adhebaaaa#aaa#aa##aa##########aabaaagjjf#a######a#aaaaaaa#a#######aa#a###bdddaa#a###.#a###########adcdddddcba#aaaaa#a###a##a##ba#b###aa####.###aa#####a#abcdcbbcdghihhgdcaaaaaabcfdccaaaaa#aa###################a##a#a##acbcdcbbcba#a#####aaba##abaaaa###aaaaaaa",
+"aaaaabbbbbcddeedccebaccb###a####a####a#..aba##########aaaaccb.############aaaabbaabbaabbaaaaaaaaaa#baaaccbbaaaa#aaaaaaaa####fjfb###egebaabcb##aaa##############aaa#achkjbaa######aaaaaba#a#aa###a###########abba###################abaceddcbaaaaaaaa#####a#####a####a##a######.###a##abaaccddedeeffdghfaaaaaaaabbdfcabbaaaaa###############.#########a###bccbedcbdaa######a#abaaaba########a#aaa",
+"#a#aaaabbbbbbcdedcccbabbb##aa######.######ba#############abcc##############aaaaababaaaaabbaaaaaaaaaaaaabbcbbccba#aaaaaaaaaaa#beihb##afgdbbcba#aaaaa######a######aa#abcilheba#####aaaaabaaaaaa#########a####a##a#aaa###############a#aaadedbbaaaaaaaaa##aa##a#######a##aab######.##aaaababceefcddcb#.#gfaaa#aaaaabcfgcaaaaaba########.#####################aabddcbcabaa##a##aaabaaaa######a######",
+"##a#aaaabbaabbccdcbcbbbacb###a###########.aba#######aa###aacf#######.#######aaaaaabcaaa#acaabbaaaaaaaaabababbbcdcbaabba#abaaaaabfje#a#aehdaaaaaaaaba#####ab#a####aabaabijiebaa##aaaaaabaaaba##aa#####a#a###########a###a###########aaaaaabbbaaaaaabaaa#aaaaa#####a##abaaaaaa########abbabcdgeba##.##.bdaaa#a#aaaacfgcaaaaaa########.a########.#######a#aa###abccbbbaaaa#aa#abbab#abaa####aa#####",
+"#####aaabbaaaabcbccccbbbcca###a############a#########aa##aaacb###.#.########aaaaaaaaabcbaaabaaaaaaaabaaaaaaaaaabcaaaaabaaaaabaabaejhbaa#aggcaaaaaaaaa####abb#a###aa##aabhigddbababba#acbabaaa###aa####a#c#a#############a#a########aaaaaaaabbaaaaaaaaaa#aa##a#####aaaaaa###aaa######aabbabege##b#######aa#a##aaaaaceecbaaa############################aaaa##aaacbbbaaa##aaa#aaaaa##aa#####a#####",
+"####aaaaaaaabbabbdcbcdccbbba#aa####a##a####a######..##aaaaabab###.###########aaaaaaabbbbbbaaaaa#aaaabcbaabaaabbaaaaaaabbaaabbabab#bghcaba#dhfaabaaaaaa#aa###aa##aaaaaaaabeegbccbaaabcbbbaababa######aa#aaaaa##aa#.######aaa#########b#aaaaaabaaaaaaaaaaa#a##aa#aaa#aaabbab##a####ab#aabbbbcfhaaca##############abbabddbbaa####################.###a##a#aaaaa#aabbbbbaaaaaa###aaaaaaaa#######a###",
+"#####aaaaaabbbbbccdbccdcbcca##########a#####aa##a######a#aaaabc###############aaacaabbabbbbbaaaaaaabccbbaaaaaaababcaa#bbaaaaaaaa#ba#eiebabaafhb#aaa###a#a####aaabbaa#baabbbigcebaaabcbbcdbbbcca#a##a###acbbaa#ab##########aaaa########aababbbaaaaabaaaaa##a###a#aa###aaaca##a#aa.bc#abbdccbdga#####.###########abbbbcdebaa##a##a##########a####.###a#aa###aaa##aabbabbba#a#####aaaaaa########aa#",
+"#####bbbabbbabbcddddcccbbbcca#a##aa###a#################aaaaabb#a####.########aaaacaaaaaacaaaaabcaaabbcdcbbbcbabbbabbaaaaaaaaa####aa#cijdbababhfa#aa###aa##a##a#aaaaa#aabbbflggfaabacbaabbbaacbba##aa#abccbbaa###aaa#####a#aaaba###a#aaaaabbacbaaaaaaaaaaaa###aaaaaaaaaacaaaa#bbab#abbcccccbdc#################aabdceedebaa#########################b#####aa#####bbbabbaa#a####a#aa##ba########a",
+"aa##aaabbbbccbbcccddcdccabbdfa####a###########aa######a#a#aacc#######.#########aaabababbaaaabbaaaaaaaabbbbaaaaaaabaabbbaaabaaaaacba#a#beijbaaaaehfa###########aa#abaaaabbbbdhjghffedccaaabaabaabbaaaacbcbcccbaa#aaaaaaaa#aaaaaaaa####aaaabbaadebbaaaaaaaaaaa###aaabaa#a#aaaaabbbbbbbabcdcccefe####.##.#######.##a#aacccccaa#aa#####.###############aaa###.#a###a##bbbbbaa#a########aaaaa##a#####",
+"###ab#ababbccbcbccdddccccbbbeda##aaa######aa###abaa####a###abdb#a###.######aaa#aaabbbaaaaaa#abbbaa#aaaaabdaabbcbabb#aaaaaaaabaaacbcba####ejdbbbacgjd##aa#aa#####aaabbaabaabbejiiiihhggfbaabbbaabcba#bcdcdddddcaabbbbcbaaaaabaaaaaaa##aaabbbbcdedbcbaaaaabbaa#aa#aabbaaaaaaabccbbbbbcdccddffebb####################aabccccca###########.#########a####aaa####a##aa#abbaaaaaa########aaa####a#####",
+"#aaaaabbbabbcccccdedccccedccdebabaa#aa###########baa##.##aaa#aca#######.#####aaa#aaabaaaaaabaaaacbaaaaaaabaaaabcbaabaa##aaabaaaaabaaaa###.cjgcbbbadiib##aaaaa####aaabbaaaaabdhlijjiiihfefcbaabbbbbbababdedfddedccbccdccbccdccccbaa#aaaaababcccdddcccbaaabbaaba#aaaabbaabbaccdddcdefffedeeed..################.######abcbdfbab#a###########################a#a#####aaaaaaaa##aaaa######a##.#a####",
+"###aaaaabcbabccccdcddcccccbbccebaaaa##############a#a####aaa##abb##############aabaaababaaabaaaabbaaaaaaaaaaaaaabbcbabbaabaaaaaaaaaaaa####.afhdbbaabfihb.#aa###aa###aaba#aaacclljjiijigddecbaabccbabbbdbadcbeffffeffgghhhighgfhgffcaaababdbbbbcfddddcbbbbbccabaaaaaaababddehggfegjiedaaaa#a####a##############.######bcdcddbaaa##a###################a#a#####aa####aaaa#aaa#a########a#######aaa",
+"aa##aaaabaaabbbdddccdbcddcccccdd##a#aa##aa########a######aaba###ab##############abaaaaacbaaaabaaaaaaaaaaaaaabbaabbaccbaaaaaaaaaaaaaa#########bfgbaabbdije.######aa#abbaaaaaaabellkkkkllkiiigfdcdcbabbcbcdcbcgijkjhhhhijjic#dcbcbddghffeeeihiggfgddedcccbcdcdcbcbcbabadeeffghhhebegdddb#########a#a####################babbbcbbb##a##################aa##a####aa#a###aa#a#aaa##a#######aaaaa##aa#",
+"a#aaaaabaaaaaabcdcceccefcadgeceebba###a#aaa########a#####aabaa#aabda########a####aaaaaaabbaaaabaaaaaabbaaaabbbbaaaaaabbcbaaaabaaaaaaa#aa######.eiebbbbcfihc#.###abaaa#aa##aaaabellkjlkjklmnnmlkgfccbbdddeefghjijkkllkhd#cfeabcbbcbbdgjjhgecccehieeededccceeedddddefcdffcedbacdec#bbaba#########aaaba#########.#######aaaacccdbbaa####################aa##a####aaaaa#aaaaa#a####aa######aa#aa##aa",
+"a#aaaabaaaaaaaabcccdddggedbdfccecaaa###aaba#a#######aa#.##aabba#aabc###########aaaaabcbaaaabaabaabbbabaaaaaabbcccaaaabbbbbbaaabaaaaaa#aa#aba###.bigbbbccdilid.##aaaaaa####aabbbcekmljgdfiijikmlmnkgdeefeeegieeddgdcghgdbabcfdebcccceffggfcbbbbbcefgedddcceeefdedcbccefgb####babedcaa##aa#######aabcda##.#############aaaaabcdcdbaa#########a########a###a###aabbbbaa#aa#aaaaa##aa######aaa##aaa#",
+"##aaaaabbaaaaaaabcdceeffedccfgedcaaa##aaaa###a#a#####aa..##abaaaabbd#########aaaaa#a#bbbbbbaaaaaaabbbbbaaaaaabccbbaaabaabbbbab#aaaaaaaaa#aaaaa###ahibbcdccgjkg####a#aa####aabbcddegkhddgihhghiibdilmljjjjiiihfaaa##aeeedcbbdghfdbbdfedfedccbbbbdbffhfededeefhhfc#####cea#####aaabdfda.a######.##abdfb##########.###a##aaaabadefecb#a##########aaa####a##aa####acbbbaa##aaaaaaaaaaa#####a######a#",
+"a##aaaaaabaaaaaabacddeddfdccefffd#aaaaabbaa#a#####a#.aaa###aaaa#abbdb########aaaaba#aaaaababbaabbbbbbbbbaaaaaaa#abcbaaababbbbcb#aa#abaaa###########fhdcccdcehihb###aa######a#bccdefggiglkjjhiihba#cglkjhiihgebcaaaaaa#aacdbbdefhfdbbeedbccbbbabdcbgjifefedeggfgfa#aa#a.aa######aaaacffba####.###abdeca######a###########aabbegffgedaaa##########aa####a##aaa#####aaaab#aaa##aaa#aa######a#######",
+"##aaaaa#aaaaaaaaabbcdddceddeeecdfbaaaaabbbaa#####ab#########aaaaaabbc########aababbaaaaaaaabbbaaaabcbbabbaaabaaaaaaabbbbaaabaabbbcaaaaaaa##########.bhfcccdddefigc#abaa#aaaaaacccdegeiihkihhjhbbaa#.#a##a#..##aaaaaaaaaaaacaabaacefedefbbedcbaccdbcfgiihhfdec.addb#ba###aa######aaaaadgeca#######aceaaa#################aaabdgeeghffb########a######aa####abaa#####a#aaaaaaa#aa###a#.######aaaa#",
+"a##a####aa#aaaaaaabccbccdedefebbef#baaaaaabaa#####a#aaa####aaa##aaaada########aaabbbaaaaabbaaaaccbbcabbbbaaaabaaaaaaaabbbbabbbbaabcb#a##a#########a##bifdccdddefgjeaaabaaaa##accbbcddfhehijhdb#aaaaa#a####a#abaa#aa##aa#aaaaaabbbaabefigffefdbcccdcbaacbbdhhfeaacbabb##a##########aaaaadhgb#####aabecaa########a###########baegfefgfeca##a#######a##aaaaa#aaaaa####aa#aabbaa#aaa###a#.#####a#aaa",
+"#aa#####a#a#aaaaaaacccbbccdcdedbcfcaaabbbaaaaa####a###a###abdb####aaeda######a#aa#aabbbabbaaaaacddbaaaaabaaaaaaabcbaabbbaabbbbbbababa####aa###aaa#####dihecccdedeejgaabcbaaaaabcbbbcdeheggeabaaa####aa########aa###aaaaaaaaaaaaaaccbaabdegedddddddccbbbba#abaabcbbaaaa##a##.#.#####a#a#abefb#####abdfaaa#####aaaa#a########aaadfeeffffc#######a######aa#aaaaaaa#aa##aa#aaabaaaaaa#######.###a#aa",
+"aaaaaa#aaaaaabaaaaabbcbbabbbcceedffdbaabcaaaa##abaa##aa###acefa####abdaa###.####a##aabbbcbcbaaaaabba##aaabaaaabaabbbaabbbaabbbbabbcbba#a##aa###aaa#####bhjgccdddefdhheabbaaababcbbabcdehfcaaaaaaaaa#aaaa#######aa###a##aaaaaabcdaabbbbabbbefedeccddcbbbaababbbcccca#a####aa#############aaceda###aabfebaa####aaaaa##########aaadefedegca########aaa##aaa#aaaaaaa##aaa##aaaaaaa#bcba#########aa##",
+"#aaa#aaa#aaaababcbbbbccbaaabbbbdgffgbaabbbaaaa#aaa####a##abbgea##aa##bca#########a#a#bcbabbbbaaaaaaaa##aabaababbbaabaabbbbbbbbbaaaabbaa##a#####aaa######adhidddddfhdfigbcba#aaaaaaaacbcfdabaaaaaa#aaaaaaa#######bb#####aaa##aabccaaabdcaaaeeefeddefcbbbbaaaabcbbbcdba#####a####..#######a##abdb#aabcefdaa####a#aaaaa#######aaaaaabacefc#########a###aaaaaa##aaaaaaaaaaaaabaaaa##aaaa###.#####aa#",
+"#############aabaaaabcbbaaaabbcceeeeeaaabbaa##a###ab#####abddb#####a##cb#######aa#a##aabbbbbbbaaaaabaaa##bbabbbaaabaabbbacbcbbbcbbbbaaa###a######aa##a#baaagkecdeegfeehfcbba##aaaaaaaaccdcbaccbaaaa#aaa##aaa#########a##a###aaabcaaaadeddbbdcdeigfdbcccbaa##cbabcbcdaaa####aaa######.######aa#debaacfdcaa#####aaaabaa########a##aabccdd#############aaaaaaa###aaaaaaaaaaaaaa###aaaaaa#########aa",
+"#############aabbbcbbccbaaaabbccddeedca#abaaa#aa###a##.##aaaa#######aaaca############aaaaaabaabaaaaaa##a#aaaaabbaaaaabbbabbbcbbccbccbaba##########a##aaabaabejfddddehddhgdbbba##aaaaabbbcccaabaaaaa#a#a##a#aaa###############aabcaaaaaegeddcecacdghfdccbaaa#cbabcbac#######bba#################bcdcbeebaaa###aaaa#aa#a###a####abaabdcdcba#a##a####aa###aaaaa##aaaa#aaaaaaaaaaa#aaa##aa#########a",
+"aca##########a#aaabdbcccbaaaabbccddeedbaaaaaa#aa#########abca#######a#aca############aaaaaaaaaaaaaaaaaaaaaaaaabbabaabbbbbabbbcbbbbcabbbba##########aa###aabbbeidbbccehefhhcbbaaa#aaabbaaabbcaaa#abcaaaaaaaaaaaaa#####.########aaabaacbedfdbbbdccccfhebaabaaa##a#acaba######daa###.######a####aa##acfdfdaa####aaaaaaaa###aca#aaaabaabccdeaaa###aa#aaaa##a#aaaaaa#abaaaaaaaabaaa##############.aab",
+"aa#bb#####.######aaabcccbbaaaabbbcddeebaaaa########.#####abca##########abaa####a#####aaaaaaaaaaaaaa#aaaaaaaaabcbbaaaaaaaabbbbbbbbbccabbaa#a#########a#####aaaachdbccdefehgiebbbaaaaabaaabccacbaaaacbaaaaaaa#aaaaaa#############a#baaaaceddbaabcbebbefdcaaaaa###ba#baa#####.aba##############a#a##aacfghdcaaaa#abaaaaaa######acbababbbdbaa###aaa#aaaa#a#aa#aa#aa##abaaaaaaabaaaaa##############ba",
+"a#aa#a#####.###a#aaabbcccbbbaabbbccccge#aa#######.#######abbba#######aaabbaa####bba###aaaaaaaaaaaaa#######aaaaabbbbabaabbaabbbbcbbbcbabbbaaa#a##a##########aaaabeccccddfgefhgaccaa#abbabbbbabbbba#aa#aaaaaaaaaaaaa#######a#####aaaaaabacdccabbbcecaacdfecbbaaaa#aaabaaa#####aa########aaab####a###aabeggbaaaaaaaaaaaaa#a##a###aaaabcccccaa###aaaaaaa#aa#aaaaaaaa#abaaaabaaaaaaa#a###########a#aa",
+"###aaaa###a######aaaacccbbbbbbbabccccehb#a########..#####abbca#######aaaacaa####cca###aaaaaaaaaaaaa#######aaaabaaaacdbaaabbbbbbbaabbbbcbccaa############a#aaaaabaccbdccegeccffbbaa######.#abaabbbaaaaaaaa#aaa#aaaaaaa#a##########aaaabbcc#abbabaabaddcbceebbba#aaaaaba######a############aba###a##aaaccggbaaaaaaabaaaaabaaaaa#a#bbabbccdb#aa###aa#aa#aaa#a#aaabaaaaab###abbabaaa###a#a########aa",
+"###aa#a######.######aacccbbbbbabbbccccfheaaaa#############bbcaa#######aaabcaa#####aa####aaaaaabaaaaa#aaa##aaabaaaaaacdcbaabcbbcbbbabbaabbbbca#a######aaa##a##a#aaacabccdeggacge.#aa####a#baaaabbabaaaaababbaaaaaaaaaaaa#########aaaaaaabda#aaabbbacbcdbbcdeca#a#aaaaa#a#aa#aa#############aa#####a#aaabcfgcabaaaaabaaaa#aaa#####babbbcccc##aa#a#aa#aaaa###aa#aaaaaaaaaaa#aabbaaaa###a#a#####abba",
+"###aa##aa##########a#acbcccbbbbbbbbbcceffebaa#############accbaaa######a#bdcaaa####aa##aaaaaaaaabaaaaaaaa#abbbaaaababcddccbcccccbaabaaabbbbbca####a######aaaaa##a##bbabcbdgefeed########a#a###ab#aabbbaaaaaaaaaaabaaabba#####a#.#a##aaaabca##abbbaccbbdcbcdedb#aaaaabaaa###aaa#########aa#aaaaaaaaaaaaabceecc##aaaaaa#a#aa########abbacccc##aaa#aa##aaaa###aabaaaaabaaaaaaabaaaa####aa#####a#a#a",
+"b###aaaaa#######.##a##abbdcbaabbbbaabccdegea########a#####abcbba###aa####acccaa######a#####aaaacbbbabbccbbaaccaaaaabbbcccbcbccbbaaaababaaaaabc###a#aa#####a#aa#a#aabdaaacbbafhgbfa.#####aaaaaaaaa#aabaaaaaaaaaaaabbbaaba###a###########baba##aaaabacaabccbccdeeaaaa#aaab####.########.##aabbbaaaaaaaaaaabccaccba##abbaa###a##a###a#aabbccca#aaa#a#abaaaaaaaaacaaaa#aaaabbaaaaa#aaaa#a#######a##a",
+"baabaa#######aaa#####aabbccbbaaabbaaabccdfeba#######aaa###abcabbaa##aaa####ddbaa######a###aaaaaaaaaabbcbbbbbccaaaaaabbbbbcccccbbbaaaaaaaaaa#abca##a#aaaaaa##aaaaaaabcaaaabaabgicce##.#a##aa#a#aaaaabaccbaabaaaaaaaaabbbaaa#aabb##########aa#aaaaaaaaaaabccccddfebaaaaabbaa################bbbbbbaaaaaaaabbbc##acbbaaaaaa####a#####aabbbcccb###aaaaaabbaaaa#a##aa####aba#bbaaaaaaabaaa#######a##a",
+"baaaaa#######aa#######aabccbabaabbbaabbbcdgdb#a########a##abdbbaaaa##aaa##abdcbaa#############aaaabbbbbbbbbabccaaaaaaaacbbbcccbccccbbaaaaaaaabbca#aaa#a#aaaaaacbabaa#aaaaaccbbjgabc###bb######abaaabbcccbabbbaaaaaaaaaaaaa##aaaaaa#######aa###aabcbaaaabbbccdeeefebaccbbbbb#.####a####.###abaabbbbbcbaa#aaabca.##acccbaaaa########aaababbcba##abaaaaaaaaaaaaaaaa#aaa#baaababa#bbaaaaaaa#######aa",
+"aa##aaa###############a#abcbabbaaaabaabbbcffcaa##aa##aaaa#abbbbaaaaaaa##a##abdbaa##############aaaaabbaacbabbbcaaaaaaaabbbaaabacbccbbbaaa#aaa#aabb#aaaaaaaaaaabbbbaaaa##aabbbadiabbc.##c#######aaaaaabbccbbabbaaababaaaaaaaaaa##aa#######a#####aabbaaaabcbbbcddcefhgceeaabba##############abbbbbbcbaa###.###aca####aacdba#a#a######aaaabbcbbaa##aaaaaaaaaaaa#aaaaaaaaaaaaaa#bababaaaabaaaaaaa#ab",
+"cb####aa################abcbbbaaaaabbaabbbdgdb##a#aa#aaaaa#abaabaaa#bba####aaddba#######a#########a#abbaaccccccbaaaaabaabccbbabaabcbbbbaaa#aa###acda####aaaabaaabbcbbaaaaa#bcbcebbccd#.aba######aaa#a#acbaaabbbbbaaabbdbbca##ba###abc.#.####.##a#bbaaaaaaccccdecdefghgfccccb#.####.#...###aaaabbabddba###...##bb#####a#bcba##########aaabbccaa###aaaaaaaaaaaaa##a#aa#aaaaaaaa##ababbaabaaaaaaaab",
+"ec##########a##aa#.#####abbcbbaaa#aa#ababccfffcaaa#aabaaaaaabbaaaaa#aba###aabbfdaa###.#############a#aaabbccbbccaabbaabbbbbbbbabaaabbbbbaaa#a###aacdba##aa#abbacbbcbbbaabaaabbceabccde.#c#aa######aaa#aaa#aaababbabaabbdefecd#aaaaaaec#.#########aaaaaa#aacdcbdbabdfegddffdba##.#.###.###aabbbbabbccbba###.#.##bc#######abbba########aaabbbddcaa##aaa##aaaaaaaaaa#aaa#aaaa#aaaaaababaabbaaaa##ab",
+"bca######.#####aa#######abbbbac#a##aa##abcdcehfaaaabbbaa#abcbbbaaa#aaba#####acegdaa####.############aaaaabbbbccccbabababcbbbbbaabbcbbabaa##aaa###aacebba###bffcdbcbbcbbcaaaabbbhbabbcee.##aa##aaa#acaabbaaaaaaabccaaaaaabdefge##aaaacea###########a######abdfdabaaaaababaceeb###.#...#.##aaabbbabbbaabaaa###..##bea###a##a#aca#a#a#####aaababb####aaaa##aaaaaaaaaaaabaaaaa#aaaaaababaaaaaaa###ab",
+".#a###########.b########aacaaaacaaaaaaa##acdffgbaaabaaa##aaehdbaaaa#aaaa#####acfgbaa#########.########aaaabbabcdecbaabbabbbbbbbaaababaaaa######a##aaddbaaaaab##a##abccccccbbaabfhaababgd.######aa#aaaaaaaaaaaaabacdddbaaaaaaddeda#aa#ba######..##a########abdcaaaaababcabbbcddb#a###..#.##aaabccbbaaaaa#########abed#########cb#a#a####a#aaaaacb###a#aaa##aaaaaaaaaaaabaa#aaaaabaaaababaaa######",
+"#########aaa###a########abbaaaaaaa#a#aaaaaacdegeaabaaccbaa#acefcaa###aabba###aadfdbbaa####.#############ababaaabcccaaaaabbbbbbbabaaabbbbaaa#####aaaabdeaabbba########aabdedcbabbffaababhd########a#aaaaaaaaaaaaaaacedbabaaba#bfggcaaa#########..#.########aabcb#aaaaaabaababccddba#..##.####aaabbaaaaaa##...#####acecb########abba#aa#a#aaaaabbca##aa#aa#aabbaaaaaaaaaaaaaaaaaaabaaaaaabaaa#aa##",
+"##########aa###a#####aaaaaaa##aaaacc#a###aabbcefbabbcfcddddbabgfa#a#aaaadbaa##abdedcaaaaaa#############a#aaaabbbbaacbbabbaabbaaababbaabababa##a##aaaaaccbbbb########.###abbacdcccgbabbbcida####aa#a#baaaaaaaa##aaabccaaaaaacbbabggb#a#####aa##..##aa######aabbcbaaaaaaaba#aabbcccca#.########aaaaaaaaa###...#######abdec########abb#aaaaaaaaaaabcbaaa#####aabbbb#aaaaaa#abba#aaaaaabaaaaaaaaabb#",
+"###########aaaaba###aaaaaa####aaabdebca###aabbcfgfbacdccdeheaadgea###a##dcabaaaabdedcbaa##################aaaaabbbccbaabcbaabbbbabbabbbaaabaa#####aa#abddbcb##a########a##.##accdeedbcccejcbaa####aaaaaa#a#aaaa###aabbbbaa#bdbb#chfa####a########.###########babbaaaaaabaa#aaaaabbcdc#..######aa#aaaaaa###.#..#####a#abdeba#######bbbbaaa#aaaaaabcca#aaaa#aaaabbbaabaaaaaaaba#aa#bbaabbaaaa#####",
+"######a##a###a#aaaaa#aabaaa##aaacddbbcaa##aaaabdifdadeeddfffaabdddbaaaaabd#aaaaaacfedcaa#################aa###aaaacccbbabbbbaaabbbbbbbbbaaaaa######a#aaacdddaaa#########a######aabbicceedghcbb##aa#aaaaaa#aaa#a####aaabbaa#adffbafgd####aa###################aaaaaaaaaaaaa#ababaaabbbcb#.####aaaa#a#a#a##..########a#aabbcdd#.###a##bbaaaaaaaaabbbbba######aaaacbb#abaaabaa#a#aaaabaabbbabaa####",
+"######aaaaa####aaaaba#abaaa###a#bddccaaa######abcfgghhhfdfffcacbabdecca#bca#aba##aeffeba##############.########aaaaccbbbabcbbbaaaababbbbbbbaaaa######aaaabeeaa#aaa######a###a#aaaabfgdbbddhhccb###aaaaaabaaa###aa##aaaaaaaa#bffgd#cda##a#a######a#a###########aaaa#aaaaabb#abaaaa#aaaabbca####aa#aaaa####.#############aaabcdc#####a#abba###aaabababc#aaa##aaabcaaaaabaaaaaaacaaaabaabbbbbaaa###",
+"a######aaaa##a#aabbaaaaacba##a##acccddbaa#a##aaaaacccdefefefdacaaaacgebcdb#a##aacbbegfdba#aba##############aa###aaabcdbccbbabcbbbbbbbaabbabaaa###a###aaaabcdb#baa#a###########aaabddgcdcbbcfidbcb#aaaaabaaa#a#a#abaa###a#aa##dfffeaa#####a#####aa##b.######.###aaaaaaaaaacbacaabaaaa#aaaacccaa####################a########abceca###aa#abaa#aaabaaaacda#aa###aacaaaaaabaaa#aaabaaaacbbbbacaaaaaa",
+"aa##a###aaaa#a##aaaaabbbbbbba####bbbacbaaaa##aaaaaabccbdedcefaccaaa#accccaa##aaabcddfgefeeffea################aaaaaabbcbcbbcbabbbaabbaacaaaa#a#######a#aaaacfcaaa##a############aacdee#a####eifccc#aaa#ccaa###aaa#ba###a###a#befffd######aaab###aa############aaaaaaaaaabbcbcdbbaa###abbaaabccdca...#######aa#a####a######aaaabcdc######aaaaaaaaaaabbcdbaaa##aababaa##aabaaaaaabaa#abbbbaaba#aaa",
+"#aaaaa##a#.###a#aaaaaceccbbbab##aaaaaaaaaba#aaaa#aaabccbcdddgfdaaaa######aa##a#aaaeggihgeefeddeca###############aaaaababcbbbbaabaaaaabacbaaa##a#####ba#aaabadgeaa#a##a####a##a##aabbeeaa#####bhibaca##aadbaaaaaca###########aadfddfda###abaabb#aaba#####a######baa#aaaa#abdc#bccbaaaa###ba#aaabdfeec#########aa#aaaa####aa#aaaaabde###a###aaaaba#aaaabbccbaaaaaaaaaa#a#aaabaaabbaaaababbbbaabaaa",
+"##aa####a#####aaaaabcccbbbcbbaa##aaaaaaaaabb#baa##aaabbcccdefgiecbaaa##aabba###a#affghihfccdddddeca################aaabaaaabaaaaaaaaa#aaaabaa########aaaabaabcgcaaaadda#aa#######aacdde#######aegbbdbaa#adbbaabcaa#aa#########acfeeecaaaaaaaabbaaaba###########aaaaaaaaabddfbaaababaaaaaaa##aba#acefgca###aa#####abb######aaaaaaabcfa##a###aaaabdaaaabbbbdb###aa#aaaaaaaaaabcbbbbbbabaabbbbbbaa#",
+"####aaaa#a#####aaabccccbaabcbcca##aaababbabbabaaaaaabcccbacddefffdccabccdedaaaabdeeffgggeccddccdcdca#a##############aaacaaaabaabaaaaaaaaaaaaaaaa###aa###aaaaacdgcaaabaaa#######a##abdchaa######.cfcbcb#a.bffcbbbab###aaaa###a###ceedddabcbaaaabbabbaaaa##..#####aa##aaaa#acecbbcbaaaaabaaaa##aba#aecbccdcabaaa##abbaa#a##aaaa##aaaabdd##aa##aaa#aaababbbbbdb#a##aabaaaaaaaaaaaaabbbbbbcbbbbcbbaa",
+"aaabaaaa####aaaacccbbcbbbaaaabdaaaaabcaabcbbbbbaa##abcddcbcdefedffedbdccdeec#aafffdddeffcccbcdcccccccaa#############aaaab##aacaaaaaaaaaaaaaaaaaaa###aba#aaababdefaaaaaaa##a###aaaaabccgcaa#######bgcdeca##bhgbabaac##a#aaa##a###befddfdddbddbaacabbbbaa####.#######a#aaaaaacbaabbbaa##ababa##aa##acaaaabbcb#aa#a#aaa##aa#####a#a#aaaabeca#aaaaaaaaabaabbbbbdb#aaa#abaaaaaaaaaaaaaaaaaabcbaababaa",
+"aaaaaa#aa#####abbbcbbabcccbbaaabbccccdbabccbbbbbaaabbcddcbceeeddeggddfbcdeec###dffedddeddcccedccccbbcdb#################aa#aaabaaaa#baabaaa#aaa######aaaaaaaabbcdfaaaaaaa#a####a#aaaabge##########bhcbccaabdeeaaaa###a###aaaaaabceedefeeedeeccabbabcbbaaaaa##.#.#######aaaabbb#aaaaaaaaaabaa##a##aaa#acbcabca###aa####aa#########a##aaaedb#abaaaaaaabbabababccb#aaaaba#aaaaaaaaaaaaaaaaabbbbbaaa",
+"aaabaaaaaa###aaabbbbbaaaacbbbbbcccddefdaabbbbccbbbbabbccbcdddddeeeffefcedffedbabeeecddcbcccbdbbbabbbabba#aaaaa##a######aa#a##aaaaa#a##aaaaaaaaa###aa##aa###aaabbdedaaaaab#a####aaaaabbgha#a########becaccdfgddda#aa#aaaabaaa#a#addeecdcdfeeeddcacbbbcbbaaaaaa###########aabacbaaaaabaaba#baba#aa##bbbdbacaabcb##aaaaaaaaaa#########a#aaabddbaaaaababbbbbaaabcccbabaaaabaaaaaaaaaabaaabaaaabbbbaa",
+"abbabbaaaaaaaaaaaabbabaaaaabbcbbcdedfggccbaaabbbbccccbccddeddccdddcddecddeffddecddccacbaacbbbbaabaabaaaaaaaaaaaaaba####a###ba#ba#aa#####aa#aaaaa############aabbcdebbbaaaa########ababdhf#a#########afecfffebceaa###aaa#aaaaa##abeeddddeegffdcfdbbabcccbaaaaba###########aaaabaaaabbaaabbbaabbaaaaacdcaacaaaabca##aaa#aa#aa#aa#######aaaaacee#bbaababbbbbbbbbccdcaaaabbaaaabbbaaaaaaaaaabaaaaaab",
+"babbaaabaaa#aaa#aaaaaaaaaaaabbbbcdbadccdbbbaabbbbbcbbccdeeedeabcccccccccdeedfddcccdbcbaaaaaaabbbaaaaaaaaaccaaa#aa##aaaabbaab#a####aa####aa##aaa###############abcdedbcba#####aaaa#aabbdhie.#####a#####fgffececeda###aaa#aaaaaa#cddecddcddefeegefeccbccccbaa##aaa#.#####.##aaaabaa#aaaaa#aab#bcccbbccbbaab#aaaabcbbaa#aaaa#a#a######aaa##aaabdfdbbbbabbbbbbbbbbccccaaaaaaaaaaabbbbbaaaaaaaaaaba#b",
+"bbaaabbaaaaaaaaaaabaabbbaaaabbabcedcbbabccaaaaabbbaabbceffcccbbcbbbbbbbbddcdddbbbabbbbaa####aaabaaaaa##aacfeaa######a##aaabbbaaa##aa#a#####bcca#a##aab##aaa#aaaacccgdbbb#######aaaaabbbdhhb###########aeifddbbceda#aaa##aaabaabefffcdddccdeeeedeffefeddccbaa##aaa###.###..aa##aba##aaa#aaabaaabccddcccaabaababaabcca###aa#aaaaa####aa#####aaacffbbbbbbbbbbbbbbbbcdcaaaabbaaaaaabbaacbaaaaaabbbab",
+"babbbabbaaaaaaaaaaaaabbbaaaaabbbceddcbaaabbbbbaaaaaaabcdffdcabbccbbaaaabbbbbbbbaaaaaabaaa#a##aaaaaaa####aadd######a########abbaaaa##a#####a#aa########aaaaaa#aabbbbdgcaaa###aa##aaaaabadfgb######aa###aadidcdbaceca#aaaaaa#abcdeeeccdeddccddeadeefffffffecbaba#######.###.##aa#abaaaaaaaaabcaaabaabcbd#abaabbbbaaabdba#a#a##a###aaaa#########aacefdbbbbbbbbbbbbcbcccaaaabaaabbaabaaccaaabbaabbaa",
+"baababbbbabaaaa#a##aaabbbaaaaabccehdbaaaaaaabbaaaa##aabdgieccccbcbaaaaabaaaaaaaaaabaaaaaaaaabaaaaa###a###aaa################aaaaaacba######a#a##########aaaa#abbbbbcdhb##a####aaaaaaaacbfe.##aaaaa#####aadhcbbaaefbdb##aaccddfgedbddccccbbcdedceceggfeefefdcbaaaa#####.###.###aaaaaaaaa##aba#aaaaababdb#aa#aaabaa###bcbaa#######aa#############abdffcabbbabbcbbcbcbcdcbbaaabbbbbbbaacabaaaaaaaaa",
+"bbbbabbbbbbbaaaaabdcabdcaaaaaabbcdffcbaabaaabbbaaaaa##bcgjfbbbcdddcbbbbbbbbbaaabaabbbaaaaaaaaaaaba#########a#a###############aaaaaabaa#######a######aa#a##aaaabcbabbcceda#aaaaaaaaaaabbbec.a#aaaaaaa####aadhcabbbeecbaaadefggfeddcddcccccbccdccdddeghggeeeddcbaaaaa############abbaabaa#aaaaaaaaba#ba#aaaa#abaaaaa##aabbb###aa#a#a##a##########abbcffdcabbcbbbcccbbccccbaaaaaabbbbaabbabaaaaabba",
+"bbbbbbbbbbbbbbaaabfdcccbcbaaaaacdceebaa####aaabbbbaa##bdghfcbaaacdddccccccccccbbababbbaaaaaaabbbaa#a##aa#a#b##a#aa###a#######abaa###aaaa##a################aaaaabbbcbbcffaaa#cbaaaaaaaacec.#####aadea##a#aabgdababdfda#adfggeddccccbbbaccbbcbcddddgghigffffbabbaaaa##########ab#aaaaaaaaaaaaa####aaaabaaaaaaaaaa####a##aaca##a######a#########acbbbbcdefdabbaabccbbbbccccbcbaaabbbaaaababaaaabcc",
+"bcbbbbbbbbbcbbbbbcecccbaccedaaabddcaaa#######aabcbbbaabdfhfdcaa###acdcabdfeeedcccccbbcbbaaaaaaacbaa###aaaa#aaa#####a#aa##aa###ba###aaaaaaaba############aa#aaaaaaaaaabbbfgaa#adbaaa#aaaaehaa###aa#adea#a#aaabgbabacefdb#dfffedccbbaaaaaaccbbcdecdggihihhfdffcbbaaaa###aa###..#aa####baaabaaaaaa#####aaaaaaaa#aba#a###abaa#cbaa##.##aa####aa##aa#baaaacccefdbbabbcccbbbdccdbaabbbbbbbaaabbaaaaabc",
+"cabaabbbbbbcbcccccddb##abaccbabbdbcaa#a##a####aabdcdbbcdddghcbaaa####bcacigggecbbbcbcbbabcaaaaaabaaa#a##abb#########a##aaaaaaaaaa###aaaaaaa########aa##aaaa#####aaaaa#acegfaaa#aac##aaaachfc###aa###aabb###a#bbabccddefdceffedbcaaaaa#aaabbbbcdegihhhhgggdcffecabaaaa##a##.###abca#aaa##aaaaaaaa######a###b###baa####aaaaaaaaabca###############aaaabbbbbbdfebbabcccbcdcbbdcbbaababbabaabaaaabbb",
+"febaaaabbbbcdcccccb#####abbabbcccbbaaa####aa#a#abdeccbddeeehgcaa#a#aa#addhifdddbbccbcccbbbbaaaaaababaaa#aaba####a##a#a##aaaa#aaaaa#a##baaaaaaa#####b###aaaaaa##a##aaaabcefihefc##aaaaaabbdha####aaaa#ab######aaaabbccdefegffdcccaa#a##aaaaaabbehhhhffffcddbdcdbbba#ac######..###bb###a#abaaaaaabba#####aaa######a#aa#####a#####bbca###########a##aaabbbaaaabdfdbaccbccbcbbccdcbbbbaaaabaaaaaaabb",
+"dedbbbbbbccbcdccddb#####bbbaacccacbaaaa###aaaaaaacfdcbcdegghigbaa#aaaaaadfhgedcccccbbbbbbbbbbbbbbbbaaaaaabbba########aa#aaaa#abaaa####aaaaaa############aaaaaaa###aaaabcfghgihfbcb#abaaabbge####aaaaab######a#aaaaaaccdeeddfdbcbaaa##a##aabaafhgggfedccccdccbaaabaaaaaa#########a#####a##aabaabcaa#aaa#a#####.####a###########a#aaaba##a####a#aba#aaaabbaaaaabdeecccbbcbbccccdcbabaaabbbaaaabbba",
+"bccdcbbbcccccbcdfda#####acbabcbaabaaa#a###aa#aabbbefedcdffiihhcaaaaaaaabacfffefedcbbbbbaaaabbbbbbbbcaaaaaabaaa####a###a##aaaaaaaaba#####aabaa###########a#a####a###baabccghfhiieaa##aaaaabdga##a#a#aaaa######aabbaaabbbcddegdcbbaa##aaaaaaabbfedfddecbbbbbbaabbabbaaaaaaaaaa####aa####a#a#aaaabcbaaaaaaaa##############.######a#a#aabbba#a####a#aaaabaaabaaabbabcfedcbbbcbccccccbabbabaaaaabbccb",
+"bbccccbbcccccdddeca####aabbccca##aaaa##a#####abbbbeeffeeccfjjifbaabaaabbbcdecdeffdbcbbbaabbbccccbbdcbaaaaa###########a#a#aaaaaba#a######aaabcaaabaa###aa#aaa######acedbcdfihfhifba####aaaadhc###aaa###########a#bbaaabbccccfecaaacca##aaaaaccffdfccedbbab#a#aaaabbaaabababaa###########aaa###bbaa#aaa#abaa##########.########aa####a#aabba#a###a###aaaaabaabaaabbbcdfedbcccbcccccabbbbbbabbbbbbc",
+"bcdcbbcccccddddddba####abbbbdca#a###a###aa####aaabcededcbbgiijjhcabbaaaaaccddddcceedddddddeeefedbbcbcccbbbbaaa#a###aaaaa###aaaacaaa##a###a##acca############acaaaaa#abbccdghccggfcaba#aaaacggdaaa###############abbbaabbdeefedbaaaadda##aabbchedeefedbaaab#####aabbaabacbabaaaa########aa#a###aa####aaabba##a##.#############a#a####aaa##abdba#########aabbaabbabbaabdeddcbbbcccccbbbbaabbbccbba",
+"bbddccbccdccdcebcbb#####abccbcd######aa##a######abcddcdddeggiihhhdaaaabcccceedccbbcbbccbccdeeeggfeddccdeccbbaaaaaaa#a##aaa###aaaba#a##aa######a#####a######aaaaaaabaaababcehb#adcbdbba#aaabdceaa#################abbbbbacgeeecca###bedcaa#adfhccdffbbbba###a####aaaaabbbbaaaba###aaaa##########aa#.##aaaaa#aa#b######a#######aaaa##aaaa###abcdb######a#aabcbaabaabbaaabcdedbbbcddcbbbbcabbbccbbb",
+"bcdfdddcccdddcecbb####a#aabccabaa#####aaaaa#####abbccdedeedcijfggfabaabbbbccddccbbbabaaaaaaaaabbbgihihffedccbbbbbbbba#a#aa####aaaaaaa##aa#######a###aaaa########abaabbbbaccega#cdaaabaaaaabbfea#a#################abbbbbaeedddcbaaabacceccefihdccedcbaa##########aaaaaaabbbaaaa#####aaa##a############aa####aaaa######a#####aa##a##aaa###aaa#a#abc#aa###aabcaaaabbbbbbbbbbcddcbccddcbbbbabcccdcc",
+"ccbcffhfdddddccadbaa#####aabbaaba##########a##aaabbaacdddfeehjifgha#aabcbacddccbbbbbabbaaa#aabcccefgdddeffeecdedbbbbcba###aa####a##aaaaa##a###aa###aba#aa######a#aaabbba#abbfcbcccccbaaa#abbfjg#aa###########aaabbaaabbcbdedcdbbaaabbbcceghhiiedcedbbaa######a###aaaa#abaaaaaaaa##aaa##a##############aa####aaaaa#####ab#####aa##a###aa#aa#a#####aaaa##aaaaabbbbabbbbbbbbbbbbdddccddccbcbbbcccdd",
+"eecbdggfdddedcacda####a###abbaaca######aa##aaa#aabcababcdeeedgigdfgbbcbbbbbcccbbbbbaaaaaaaaaccddddefdecccbbcbbddcbccddedcaaa#a#aa##########a########adbaa#########aabbbcbcabbdcdcbbbcbaa##abbfiaaa##############baaabbbbccedcccbaa#abbbbbefgihfdcccbaaaa###a######aaba#abaaaaaabaa#aaaaaa######...#a#.#####aa#aaaa########a##aaa###a###aa#aa#aaaa#aabbabaaaaabcbbbbbbbbbbbbbbbccdeddcccbdccccdde",
+"eedfhhfcba#abb##a#####a#aabcaaccbc#####a#aa#aa###ccbbbabcdfffhgifehfebbbabbcccbbbbbbbbaaaa#ccdcddfghfeccccbbbbabcddegcbccdcaaaaaa###a###a######a#a##accba#########aaaabbccbbcbcehb###cbba##bdehe###############aa##aabbbccdcbccba##aacccbcceffedcbbaaa#####a######aaba##aaaa#ababcbbbbcbaa########.#.##a####a####aa######aaa###aa####a###a##a#aaa####aaadbbaaacccbbbbbbccbcbcccbcceeeeededcdbccd",
+"dgghigdb##a#a########baaa#abbcbdbbb#####aa#aaaaaaabaababcdegiihdggffdcbaabbbbabbbbbabaaaaa#ccdccdegedccbbbbbbcbbbbaadbabaacdb###aa###############aaaab#aa##a#######aaaaababbbabbfieaaaa#aaa#chke.#########..#aaaaaaaaababbccbbcbaa#aabbcbabcdeedcba###a#####a#a##.###baabbaaaaaaaabbaaba#########....#.#######ab#a#######a######a#########a##aabba###aaabbbbbbacdcbbbbcbcccccbdddeededegeddddcdc",
+"dhghhfa##a######a######aabaacccedaaa#######aaaaaaaababbbccdghgfedgfgcabaaaaaaabababaabaaaaabdcceeeecdbbbababbbbccbbbbbabdbabcba#a############aa##aaaaab#aa###########aababcbbaabeggh######aaagj##############aa#####abbaabbbbbabbbabcabbaaaabcddccba#######.###########ccaaa###aa##aaaa###a###..##....#.aa##a############aaa#####a#####a###aaa#aaaa#aaacaabbbbbbeccccbbccddccdegghhgfeegd#bddccc",
+"ffhhhe###########a#####b#bcadddcbaaaa#####abcca#aaaaaaaaabdhihgddfgfgcaaaaaaabbbabbbaabaaaabedcefecbbbbbbabbbaaabbacdca#aaa#bbdb#aaa#########aa####aa#a###a#####.###aaaaadbbaabaddcggbaaaa#bbdia#a##########aaa###aaabaaaabbbbbbaacefebaa#aaaabcccbaaaa###########.#.##ad#####.##aaa#aa#aa#####...#...###ab#ba######a###a##ab#####a###aaa##aa#aaaaaaaabbbbbbbbbbceddeeccbccccddfhijjhggghb#bba##",
+"#afhgcaa###########a#a##aabcddca###aa######abbbabaaaaabaaaeiiihgbbgeddaaaaaaaaabbaabbbaaaaabdcccddddccabbbbacaaaaabbbaaabaa##acdd###a######..a#a#####a#aa##a########a##aaecb#abbbcccfgaaaaaaaeia#a#a##############aabbaaaababbababdgeca####aaaaabcbbba#####a####.#######da##############aaaa#######.##.#.#ba########.#a#aa##abba##aa#aa#aa###aaaaaaaaaabbbbbcbccccefgeeccbccbbbbdfiihgggeb#aaaa#",
+"##bhgd###############ab#ababcdd###aaaa####aaaaaaaaababaaaadhhigebabfddcaaaaaaaaaaaabaaaaaaabcbbbcbbcecbbbabbbaaaabbaaaaaba###abadea#########.#a##########aa#a###a###a####aabbabbaadccghbbbaaabfi#a##a###aa####a##a#aaabaaaaaaaabbacfdba##a#aaa#aaaabbb######a######.##a#######aa#a##a#a####aa#####a#.#a####aa#########aaaaa##aaa###aa#aaaaa#aaaaabaaaabcbbbbccccceeceeeefedddcbbceeffhgfebaa####",
+"##.dhdb#########ab###bdababaddc######a###.#a######aabacaaaadghfdbbabecdba###aaa#aaaaccabaaacababbbbbbbcbcbbcbaaaaababaaaba####abbcfbaa#aaa###.###ab#####aaaa##a######aa#ba#aabbbabdcabefbcaababhe#a##aa##aa###a#####aabba#aaaaabbbefcba###aaaa#aaaaaaaa#########a#.##############aa#bb#aaa##a####.###########aaaaa#######aaaa###a####a##aabaabaaaaaaaaaabbbcccddebbbbdedefdcccccbceeghgfdaaba#aa",
+"aa#aeea##########c####ba###aca#####aba#############abcabaa#acdefccbacdbdc##aaaaa###aabdbaaabbcccbbbbbbbccbabcabaabbabbaaaaa###addbcdba#a################a####aaaa#aaaaaaaa#aaacbabdcbbbehca#abbeh#aa######aa######aa#aacfbaaaaaabbdgdbaa###aaaa#aaaa########.###aa#a.###########aaa#bbaaaaaa####a#.##.#######aba#####a#############a#aaaaabbba#bbbbaaaaabbcddddddbaabcedccbaadfdcceeggdbaaaaaaa#",
+"aa##ada#a########aaaa###a###a######abaa#########aa#abbbaaaabbcddeeebcdbabb#aaaaaa####aaaabcccbccbaabbbabccbaaaaaaaabbaaaaaaa##aabcccfeb##############a####ab#aaa##aaabbaacababaaaabcdbccffc##abeh.##aa###a#########aaaaacbabaaaccddfgdbaaa##aaaaaaa#######.##.#######.#########aaabaab########a#a##.#########aaa#####aa##a#aa###bdaaba#aa#aabaaaabbbabbbbcddefecbcbaabbdcbaabcecccefgcaaaaaaaaa#",
+"aaa#aaaa#aaaaa#####aaaaaa###########a#####a##ab#a##aacabaaabcccbdhedfdbbabc#aaaaaaaba##aaaeheaaaaaaabbbacddbbaaabbbaaaaaaabc#aa#a###cfgb#a#########aa###aaaccaaaaaaaacbabcdaacbaaabcddcccgfcaabeg.#a#aa#a###aaaa####aaaaabaaaaaaceefhfdbaa###aaaaaa########.####.###.####.####aa#abcbaaa####aaa#############aaaaaaaa#aaaa#ba#babffb#acb#aaaabaaabbccabbcccfgdaa##bcbbaaacbcbacebbbcddbbaaa#a####",
+"accccedaa#aa#aaa##a#aabda#################a#a#a##aaaabbbabbcccdcccfcfecbaaceca#aacdbcccba#ahgabaaaaababbbccccbaabbbbbbbaaabcb###aca#aabcc##a##########a###a#abaaa#aaabbddddbbbcbaaaaabcdddhecccg######ba#a##.#a###aaceca#cbaaaaacdefhgfcaaa#aaaabba#########..#####...#.#######aaabccbaaa####aa########.####abb##aa#aaa#a#ba#abbefba##bbbaaaaaabbccc#ccddeffcaaaa#baaaaabebbbbcbbbbcbbbbbaa##a##",
+"#abeeebaaa###aa###aa###aaa###################aa###a#aabbbbcddddccefegfcca#adhbaacccaaabcbcdecaaa##aaacabdabdcbaabbabbaaababbcb#aabb#aa##dea##aa#######aaa##a##aabaaaacacdfebbbbbbabccccfeddfgfed...#a##aa###########acdbabbb#aa#acddegfecbaaaaaaabaa#########...#####.#########a#abbbabba##aa#####.##....#####a##aaaaaaaa#baaaceeebaaaaeedbbbabbbccb#cedddcccbaaaaaaabaa#bebbbbbbbbbbbbbaaaa####",
+"##aadba#aa##a#######abbda################a#######aaaa#ababccdeeddffhhgccbaabefdbbaaa#aabcbbabca#aaaababbbbcccbaaacaabaaabaaaabbaaaab#aaaaefaaaaaaa#.###a#a#a######bbbaabccabbdcbabbcbcdbbaaaefeiiffa####a#######a##aaaaabbcba#baabdddefffdcaaaaaaaaaa##########...##############aabbbbbdabaaa###.....########aaaaaaaaaaaaabcccbdfebaaaaaacfdccbcddc##baabcbabaaaaaaaaabaaaedbcbcccccbbccbaaaaaaa",
+"a##aba#a####.######a##bgb#######a########aa#######aaa##aabbcceedddeghiebaaabccebaaaaaaaabaabaaabbaaabbaaabbbbbaaabbaaaaaaaaabbccbbcba#####cfebbabbbacaaaaaa#aaaa###acbbbbbbbbcbaabbbccbaaab#.aceffdfghfa#a####aa#aa##acbacbbbaaaaabcedcddedbaaabaaaaaa#######..#.################aabccccdbbb####.#..#..#.#..########aa#aaa#aaabdddbcababbbdeddedeeb####aaaaaa#ba#aababcbbbaeccbcbcbcbbbbaaaa###a",
+"ba#a#####a#############cb#########aa##a###a####ab#aabaaaabbbbedcdccehihcbbbbbbccaaa#a#aaaaabbaaaabbbcbbaaabbbccaaabbaaaaaaaaaabbbbacda####aaedbaaabddba#aaab###aa####aaddcceebabbbcbcdca#aaba#aaabaabfmka##aabaaaaaa#abbabbbbaaa#acccdddccedbbbbaaaaaaaa##a####.#.###############aabddcbbcaaa####.#......aa###aa####aaaa#aa##aacccccbbbabbcdedddea####a##aa#a#bccbccbcbbaaaadddccbbbbbbaa#aa####",
+"ab##aaaa######a##########aa###b##aaaaa##a#a#####ababbbaababbbccccdcdgjifbbabbcccca#aaaaaaaaacaaaaabcccbaaa#bbbcaaaaaaaaaaaaaaaaccbaabbaa#a#a#bcbbaa##a###aaba######aaaaaaddfhgccddddacacaaaaa#aaaaaaabhnk.aabbb##aa####aa#acaabb#aabccddeecccbbbabaa##aa###aa#######.######a###aaaabdddcdedda#########...#####aaaaaaaaa##a###aabcbbccbbbbcddeeefc##a####aaaaaacdccbbaababaaabccdccccbbbbaa#a####",
+"#####a#aaaaa###aaa######ba###aa#bba#aa#abca##bb#abaabbbbbbaabbbbdccceihgecbcdccbcd#ababa##aaabaaaaaabccbaabbddbbaa#aaaaaaaaaaaaaccbaaa#a######aabdcb##aaa##a#a#####aaaa##aabffebccddcb#aa#######aaaaaadlnd#aabbabaaaaa##aaaa####aaaabccdeedbb#aa##a###############.##..#.#####aaaaabccdeecdaa#####.########.###aaa#aa###aaaa#aaabcbccccbbccddeef##aaaaa####aaaccbaabaaaaaaaaba#bcddcbbbbbb#aaa#a",
+"abaa###aaaaa##a#a##a#############a#a#ababda#aaaaaaaabbaabbbbcbbbddbddgifhedbcccbbcc##aabbaa#aaaaaaabaabbbccccdebaa##aa#aaaaaaaaaabedaaaa##########becaaaaa#a#########aaa##abceffdccb##aa########a#abbabilk#a#a######ab#aa#aa#####aaabbcddedbaa#a######a#####################a#aaaaaabdddfgfc##########...a#a###aaa#a#aa##a###aaaabbbbbcbbbcceghfaaaaaaaabbabccbbbaaaaaaaa#abba#aacedcccbaaaaa#aa",
+"bbaa##aa#aaaa#aaaaaaaaa#aaa##########abaaaa#baaaaabbbbbabbbbccccddbddggghhfdbbcaabbbbbaabbaaaa#aaabbaaabbb#bbbaaa#####a#aaaaaaaaaabb##aa##########aabdcbabaaaa####aa###aa#abbcdhhcaba#baaa#######aaaaabhlmc#a#####aaaaa#a##abba#aabaaabcdgfbb################################aabbaabbccdhigca#########.########aaa########aa#a##aaabbbbccbccdgfha#caaa.##fedbbcbaaaaaaaaa#aaa###aaadecccbbaaaaaa",
+"#aa###aaa#a#aaabbbbbcbaa##a#######aaabaababaa#aaaaabbbbbaaababccdecdfhhiihgfdbccbbcbabaaaaaadca##abbaaaaaaa#bb##aaa####aa#aaa#aaaabbda.##########aaaabddcbbaa#a##aa#aaa##aaabbdecca#a#aa#a########aaaaaeili##a######abaa###aaaaaacfeaabddcdbaa##############################aaabbbbbbcdfgjieba####.#####aa#aa############aaaaa###aaabcbbcbbcefggcbbfeedbedbcbabbaaaaaaaaaaaaaaa#aaa#cdcddcbbaaaa",
+"aa#a###aa#a##a#aaaabbccaa#aaa########bacbaaaaaaaaaaaabcbbbbbbcedcdccfhfhkhggfdbbccbbabaabaabdda###aaa#aaaaaaacb#########aaaaaa#aaaabec##########aaaaaaabddcbaaaaaaaaaaaa##aabacbaaaba#####a##a######aaabgklbaaa#####aaaaaaaaaaabbbfdaacddeddcbaaa#########aaab##########a##aaaabbcbbbbeffhjifdcb#####.##acbb#aaaa###########aaaa#aaacbcbbcbcegfaccgghgffdcbbaabbbaaa#aaaaaaaaaba#aaaabeecccbaaaa",
+"aaaa########aaaabbabbbbcbbbaaaa#####.##aaaaaaaaaaaaabbbbaaaaadedcdccegijkifddebccbbccaabaaa##aa######aaaaaaba#aa#########aaaaaaaaa#bccda#######aaaaabbaaabddcba#aaaaaaaaaaaaabcdaaaaa##abaaa#a#a#a##aaaafhlg.aa#a#a###ba##b#acaabcdfaaaccdccedba##########adcbca#########a#aaabbcddccbdefggiigecb########aaaa#abba###########aaaaaa#bdbccbccef#abdeddeeddccba#bbbbbaaaaaaaaaaabcaaaaaa#eedccbbba",
+"aa#aaaaa###aaaaaaaaabbbbbbbbaaaa#######aabaaaaaaaaaabbaaaaabbbfeccccdfiljigcdeccccbccbccbbaaaa#######a#aa##aaa#####..#..#aaabaaaaaaabacb######aaaaaaabbaaaacddcbaaa##cbabaaaaabcbaaaaa###a##a####a##aababchl#.###a#####aaaaaa#aabbdeaaacbbbbdfdccbabb####a#ddbbbba##########abbbccdcccddefghhfcaaa######aab#abaaddaa########ab###aaaacccccdefd#dbgebcccdcaabbbaaaaaaababbbaaabacaaaaaba#eeddcbba",
+"aa#aaaaba#a#a##aaababbccbabbbbba########aa#a#aaaaaaaababbaaaaadcccaddfhkjigdcdecccbbcdcecbaaaa######aca####aa#####a#####.#aaaaa#aabababb######aaaaaabbabaaaaabcdcbaaaaaaaaaabbbcaaaa#a####aa####a#aaaaaababjh.####a#####aaa##aaaabdabaaaabbabdeeeddddcb#.##debaaabaaaba####aaabbccdcccddeffgfgcaa##aa###aaaaaccaddca########a#a###aaaccbbceffbaacgeaabbbbabaaaaaaaaaaabaaaabbcaaabaaaabbbccdedcb",
+"ba#a#aaaaa####aaaaaaaaaaccbcbbaa#######aaaa###aa##aaaaaaaabbbabbcbbefffhjihfcbfcbcbbbcfhgcaaa#####a#deaa##aaaa###############a##a###aaaaa###aaaabbaaaababbbbbbbbedcbaa#abbbbbcccaa##a######aa##aaa##abaa#aabja##.#######a#a###aaabecaaaaaaacccbcaaaabbdddefedcbaa###aaaa#aaaabbbcccccccddfggghdba####aababababcbbddba###a###a#aaa##aabbcccegfbaabcaaaaaaabbaaaaabbaabaacaabbbabbadbaaaaabba#aefc",
+"ba#a#aa#######aaaaaaabaabbebdbbb######aa####a###a####aaaabbaabcabcccddffjhfdbaefcdbbbbdjkjebaa#####bccb##baba#####aa######a###a#a####aaaaa##a##aabaaaaaaabbbbbbabefdbbcbbbcbbbcbaa####aa#######aaaaadaaaaabbdg###a#a####a#aa#aabccccaaaaaabcdbccaaaaabbdeeedcdcba###aa#aabaaabbbcbcccddddeffffdbaa####abccbb#bbccdbccaa###a#aaaa#a#aabbdcdfgdaaaccaaaaaa#aaaaababbaaabbbbbabbbbbcbcbaaaabaa###be",
+"fcb#############aa#aaaaaaadegdacbaa###aa####aaa#a####aaaabbaaabaabddccehieabaabecccbbbbbikkgca####acbb###baba#####aa####aaaaaaaa######aa###aaaaaaabaaaaaaaacbbbbbbeffedccbcddddbaaa##aaaa###a##aaa#adba#aaabbie.#.#aa##aaaaaaacecaaaba###a##aabdb#a#aaccccccccbbba###aaa###aaabbbbcccdddedegcddcbbaaaabbabbabbaabbaaddbaa#####aa##aaabbddefgcabagbaaaaaaaaaaaabbaaacabaaaaabbbbabbaaaaaaaaaaaa#a",
+"bdeba#########aaaaa###aaaaacfebbbbaa###aa#####aa########aaababaacbdeccehhbaaaaaddcbbbbbcgijhea####acb########a##aa#a##a#aaaaabaaaa####aaab###aaaaaaaaaababbccbbbbacbedffedcdeeaaaab#aaa#aa##a##aa#a###aa#aabackc.#.##aaaaaabdefb#a#aaaaa#a####abc####abcbbeecbbaaabb#aaaaaaaabbbbcbcdededdefdcaccbca##aaaa###aaaaabaaeccaaa###aaa#aaabcccdffbbacfc#a#a#aaaaaaabbaaaaeabcbbabbbbcbbabb#aaaaaaa#aa",
+"##aba######aaaaaaaa##a#aaa#fdaabbccb###################a#aaaabbabccccdehibabbbbcfdcbbbabgihc#a####abbaa##a###aa##a#aaaa##aaa##aaaaba###daaa###abcaaabaaabbbbbccbcbcdcdddggfedbcbaaaaa##a#####aaaa#aa#####abbbbdjb.a##aaaaabeecabba##aabda######aa####aaabbdcdcbaa#bcbbaaaaaaaabbbcccddedefffdcbccbab####a#####a#aaabaabeeba######aaacbcddegebbacccba##a#aaaaaaaaaaaaccbbbbbabaaa#aaabbaaaaaaaaaa",
+"aa##baa####aaabaaaaa#####aacaababbccbaa##################aaaaaaaabbccbegifaaaabbcecbbbbaadgb#####aeeabc#.######aa##aaaaa#aaaaa###abaa##edaaaa##aabbaaaabbbbbbbccbbdccccdddehhdabbaaaaaa##a###aaaabb######cebcbcgj#aa##abdfggcbbbaaaabdfea####aaaaa##aa###aaa#aaaa#aaabbaaaaaaaabbccddeeddeffeeeefcabaa#aa#####aa#aabbbacccbaaaaaaaabcccdegfbbbceaacb#####aaaaaaaaaaaacccabaaaaa#a#abbccaabbaaaa#",
+"#aaa#daaaaaaaabbbaaaa####abbaabaabcbbbbb##aa################aaaaabbbddehecacbaaaabecbbbbabaa#####adcca#########a#a##daaaaacaaaaaa###aa#aca#aa##aaaabbbaabccbbbbcddaccdeddecfhgcabaaa#ab#a####a####aaa#aaaabbbcbcijdchihgighedbcbbcdfdabbbbccaaaaaa###caa#aaaa#a#a##aaaaaaaaaaaaabcccdddddeeedeeeffbaaaaaa##aa###aaabbbabcdeabaaaabbbbcdegibabbfaabca####a#acca#aaaaaaababbbaaaa##aaababbaaabaaaa",
+"#####adcbbbaabbbaaaa#a#a#####aaaabbaaabcbaa#################aa#aaaaabddgeadbcaaaaabccbbbbba#####a#a##aaaaa###aa#aa#bccaabaac#aaa#####a#..#####aaaaaabcbaaabbbbcdccdcddedceefgfccbaaaaaa#aa###aa##accaaaaaaaabbbbdjkfdfgjjhgfeeeeeedcaabaabaaaaa#####ab#a#aaaa###a####aaaaaaaaaaabbccddccccdccdeeegfbcbcaaa#aaba#aaabdcbbbababbbaabbcccdghg#aadbaabbaa###a##acdaaa#a#aa#baaaaaaaaa#a#aaaccbaabaaa",
+"a##a#aaedbbcbabaaaa##a##aa####aaaababbaabacaaa###a#######a####aaaaaaaccehbbbbcbaaaaacdbbbcb#a#a#a#.####aaa##a#aaaaaaabaaaaab##aaaaaaaa#####aaa##aa##abbaaabbbccbccbcdcdcddeffcaabaaaabba#aa####a##bcbaaaabababbbbejib#abccdcbbccba##a##aaaa##a######a##aaaaa#a###a#####aaaaaaaaabbccccccccccccdeegfcdabbaaaaaaa#aaaabccbbbaccbabbbcddefedea#cd##a#aaab#aaa##bcb###aaa##abaaaa#####aaaaabbcbaabbb",
+"aa##aa#bhgccbbccbbaaaaa########aaaaabcbaaaabbaaaa###aa#####a#a#aaaabbbbcega##acbabababecccdabaa##########aaaaaaaaaaaaaabaaa####aaaaaaaa##.##abaaa#aaaaabbbbbbbbcdbbccddcdcegeaaaab#aaaaaaaaa####aabbabbcbbbcaaabbcegiaaaaaa##abbcbca##.###aaaaa####aaa##abbaa#aaaaa####aaaabbaaabbbbccccbcccdddedfddcaaaaaaaaaaaaabbccdbbbcecbbccdefged#a###fa######aaaaaaaabaa#######aab#aaaa#aa#aaaaaabcccabaa",
+"aa##aadafhhfeccbbbaa#aaa##a####a#aaaaaaaaaaaaaaaaabaaaabaa#aa###aaaaaabbcfd#a#acbaaaaabeecdcc#############abbaaaaaaaababbba###aaaaaaa#a#####aa#aaaaaa#aaaabbbabcccehgeecdegebaaaaaaaaa#aaa#aa###aaaaababccbbaa#aabceggaaaaaa#aaaabcb####a###aaba######a#a#####aaaaba#####aabbaaaabcbbbbcbbacceeddeebabdbabbaaaaaababcdccdccdcbbccefecb#####cc#########aaaaaaaaaa##ba#aaaaabbbbaaa#aaaaaabcccdgdb",
+"##aaacdggggghgdbbbbbaaaaa#aa###a###aa##aaaaaaaaaaaaabcbbaaaaaa#aaaaaaabbbdfd#aaacdaaaaaadgefc#######a#a###abb##a#aaabaaaaaa#######aaa#a########aaaaa##aabbbbbbbbccefhfeeegfbbba#aaaaaaaaaaaa####aa##abbcdacbaa##aabcehfaaaa###aaababa##.##a#aaaca#a#aaaaaa#aaaa#aabcc#####aaaabbbbbadcabbbbbbceedefcaabcecaaabaaababccdcdddccbbcceda#####baeaa#aaa#####ab##aaaaa##aaa##abbbbbbbbaaaaaaaaabbbagig",
+"f#aaaehhfffeffhfbccbbaaaaaaa####a#aaaaa###aaa#a#abaabccabcbabbbbabbaabbbbcehdaaaaaaaaaab#dgeaa##a###########aa####aaaaaaa######a####aaaa###a###aaaaa###aabbbbbacccdedddfgebcbaaaaabbbaabaaba#########abcbdabaaa#aabcdeibaaa######aaaca######aabbb####aaaaaaaaaaa##bbdb####aabbbbaaaacdcaabbbbcceddeccccaba#aaabaaaabccddddddceddeec#aca#aabebaaa#######aaaba#######aaaaabbbabbbbbaaaaaaaaaba#dii",
+"hd#aaejiedefeeddedccbaaaaaa########aaa#######a#a#aaaabbaacbbababccbbabbbbbceidbaaaaaaaacbcgeca#############aaaaaaaaaaaba######.a############a##aaaaaaaaaaaacbbbccccedbcfcbbbbaaabbbbaaaaaaababaaa#baaaabababbabaaaaabdfhaaaaa#aa##b#bbaa#####abb##a##aaaabbba#aaaaaacda#####abbbbaa####a#abaabccbdecdbbaaaaaaaaaaaabccceeedcdfgffeba#aa#aa#bcaaa##########aa##a####aaaaa#aaabbbbaaaaabbbcbbbeefh",
+"ggecdhjkiefeeddcdefdababaaa########aa##a########abaabaabcdabbcdccbcbabbbbccchiecaa#abbbaaaadeca#####a#######aabaaaaaabba###a##.#############a##aaaaaaaaaaabbbccdddbbeccdbbcbbbabbbbbbcbbaaaabccaaaabaabcabbabaaaabaabcefeabaaaaa####aaccb####aaa###a###aabbab#a#aaa##aaa#####acbba#a######aaaabbbbfefdaaaacaaaaaaaabbbcefffeefbed########a##dbaaa#######a#############a########aaaaaaaaaccfgfhdf",
+"efddegijmkfeeeddccdgdbcccbaaa####a#aaa#####a####a###aabbcbabacccdccbbbbbcbbdfijhbaaaaabb###cedbaa###aaa#####aabbccbaaaaa###accb###a##########aaaaaaaaaaaabcbbccddddcddaaaabbbabbbbbbcbaabbbbbaaaabbaaaaabbbbaaa#ccaabbddheabaaaaa####abca#####ba##a####abcaaaaaaaaaa#aaaa#####bbaaa##aaaa##aaabbaaadfdbaabcbaaaaaaabbacehhhhcaaaa#####a#ab##ccaa########aa#############ba#a#aaaa#aaabdaaeffghgff",
+"eddcbcdefijgeedcccbbdeccccbaaaaaaaaaa#a#########aaa##a#abcaacccccccbcbbccccdefikibaaaaaaaabbdddca#a#a#aa####aaabbbaaaa##a##aaaba##aa##a######aaaaaaaaaaabbbbbccccddddaabbaabcdbbbccbacbabcbbccbaa#aaaa###baaaaa#a#aaabcdfjb#aaaaaa####abaa.####a##aa####bcbbaaaaaaaa#####aa##abaaa#a##aaaaaaaaaaaaabecbaababaaaaabbbcbcehhcaaa##aaa#######b#.cbabaa#####aa##a#####a#########aa#a#aaabdefffggfefe",
+"ddcaaabdefhihecdbbbbacdecccbbaaaaaaaa############aa##aa#ababbcbcbbbababccdceeegijgaaaaaba###bfcdc##aaaaa######aaaaaaaaa#aaaaaacba#aaa#a#ba#aa#aaaaaaaababcbbbbbcedabbaabbaaabbbabbdccbbbaabbbbbaaa#aaaaa##aaaaaa#####abcehka##aaa#####aaaa###..a#aba#####abcaaaaaaa#a##a##a###ba########aaaa####aa#deaaa#aaaaaaabbbbbccefcbaba##abaaaa.#a#ba##dc#a#a####abaabb#a##aa##a###a###aaaaabaceecddhhedd",
+"cccbabbcdfffhheccbbbbbcdfccbbbbaaaaaa###############a##aaaabacbbbbaaaacccddcdefhjjhbaaaabaa##dfbbc###aa#aa######aabaabaabbbbbabdb#aa#a###bba#a##aaaabbabbbbbcbbcedbaaaaaaaaabbbbbcbccbcebbbbaaaaaaaaaa#####aaa####aa#aabdegj.############a##a##a#aba####a##baaaaaa#a###aa#aa########a##a#aaaa####a#eeaa###aaaaaaaaabbcdgfdbaa####aabbcb#aabc###cda#aa##aababcbb#a#aa###a##aab#aaaaababdecbcdheed",
+"cbbaccbcddeffeedcbbbbbbccffdbbcbabbaaa#aa########a###ca#abaabbbabaaaaabcccddcdgiikjgbaaaaba##afcacba###aa########abbbbaabbbbbbbcbbbb#aa#a###aa##aaaaababbbbcbccdca#a##aaaaabaaabcccbbcbcbaabba##aaaaaba#####aa####aabbbddcdjd.#########.#..#######aba######aaaaaba########aa#######aaa#aba#aaa###aacaaaa##aabaaaaaaabbcefcbbaaaaa##aaacabaaaa###bca#####aaaaacaa#a###a##a#aaa#a#aabbbbcddcccegdd",
+"cbbabbbbccddeedddcbbbbbbbbdfheccccbaaaa###########aa#bd##baaaabaaaaaababcddcccggijjjbaaabbaa##bcbabba##aa#######aaaaaaabbbbbbbbbcccaaaa##a##aaa##aaaabbbdbcbbcdfbaaa#aaabbbbbbbbbcccbccdedaaa#aaaabbaaaa#a#aa####a#abcccdccfi###########....#######aa##aaaaaaaaaaa##########a###a##aa#aa#aaa#####aaa#aaaa##abbbaaaaabcdefbbaaaaabaa####aa####a#a#dba#####bb##b###########aaaaa#aaabbaabbbccddede",
+"baabbbbbccccdeedcccbbccbcbbcdiheccbbbaaaaa#aab##aa###aa###aaaacbaaaaaababccccdfhjjjl#abbbaaba#abeaabb######a#####bbaa#aaaabbbcbbabbaa###aa####a###aaaabacdcccdceaaaaaaaaaababbbbbbbcbbbcbdba###aabbbaaa#aa##########aabbabccgb.###.#########.########a#aaaa#abaa#########a##aa#####bcaabaaba###aaaaaaaa#####aaaaaabbbdhidabaaaaaaaa###########a###ebbb###aaa####a###aa#aabcaabbaaababaaabbbbbdcb",
+"abcbbbbbbbccbbcddbcbbbbbbbbbcfeghfccbbabaaaaabaaaa####a#b##aaaabbaa#aaaaabccbceefhegdedaaaaaaa#abdaaba#aa##a#####aaaabaaaaaaabbbaacc###aa#aa####a#aaaaaaabcccddfbba#aaaaaabbbbabbccccccbcbdaa#####ac#####a##########aa#aabcbdh..#########.#####.####aaa#aaa###abb###########accaa###a##aaabbbba#a##a#abba####aaaaaccegcbbaaaaaaa#aa###.##a########aeaaaa###a#a######aaa##aaaaaaaabbaabbaacaacced",
+"cadbbbbbbcbccbbacbbbbbbbbabccdeehgffccbcbaaabaaaaaa###a####aaa#aaaaaaaaaaabccbdeeffeehgcaabaaa##adb#aca##aaa#####aaabaaaaaaaaaabaacdb##aaaaaaa#abbaaabbbabbdecffbaaaaaaaaaaaaaabbaccbcbcccdcaa#############aabb######aaaaabbbehd..###d#.#.######.####adbaaaa##abba########aaaaaaaaaaaaa#aaaaaaa#a#aa#abaaa####aaacdeheaaaaaaaaa##aa#aa#####a####a#.cdaa######a##a###########aa##aabb#aabaaabbadf",
+"cabdabbbabcccdccbccbbbbbbaabdcdefdcfgccbbbbaabcbaaa###aa##aca####aaa##aabbbccccddffhihhfbaba#c###bdaaagaaa#a######aabaabaaaaaaaa#a#aa####aaaa#aabbaaaabbbbbcddfeca###aaaaabbaabbabbcbccbbbccdada###aa######aaba####a###abaabcafjlf..defe##...#########bbaaa###aab#a#######aaabcb#aaaaaca##aaaa####a##aab###a##aabdfiida###aaaaa##ca#aa#####a####a###ecaaa########a##a#####a####a###aaaaaaaaaabab",
+"ccbbbbabbaaabccdcbbbbbbaaaabcdbbbeeadgeccbbbbabbbaaa##aa#abedbaa####a####bbbcbccddehhhfdaa###da#a#ddaabhaa###########a#abaabbaa######a####aaaaaaaaaabbbbbbcbdeefcb###aaaaaaaaaabbbbccccbbaabbcaaa############aacbaabaaaaaaabccbdejkbd..bgccdcba########aa######aaa#a#######aaaccaba#bcaaba#a##aaa#####abba#aa#aabdgkjkihgdb#.cedcbb#.###dc########b##ebaaaa#########################aaa#aaaaaaba",
+"abeecbbaababbbabbdbabbbbbaaabcccbdcb#ehedccbbaabbbaaa#abaaaedba###########acbbbcceeeggdaaa#bacaa#aadabbdf#######.#######aaaaaa######bca###aaaaaaaaaabbbbbbbccfffbaaaa#aaaaa#aaaabbccabbcccbbbbaaaaa#######a#aa#acaaaaaaaaaaaabccceglh.#....#baacca..####ab########aaa####a##ababbbba#ceaaaaaa###a######aa##acbbbbchgcddfgjihddigefegfffba#affeecbbaaabda#aa######a#a################aaaa#aaaaaab",
+"babfdcbcbabaabababbbaaaaaaaabcccdbaaaacifddcbbbbbbbabaabaacecabaaaaa######aaabbcdeeedifba#adcbaaba#bcabbfe#aa####aaa###a#abaaaa######aaaac#aaaaaaaabbbdbbbbcceebbba##aaaaaaa#aaabbbbbbcccdcabaaaaab##a#aaaaaaa######abaaaaa#abbbbddei#####a####.#ee######aa######aaaba######abaaaa#a##bc##aa#a####a###a#aaaabcbbbceecbbcbdeffgfdccccdefeefgffedcefeb##cdbcba########a###########a###aaaabaaaaaaa"
+};
+SIMPLE = T BITPIX = 8 NAXIS = 2 NAXIS1 = 384 NAXIS2 = 384 HISTORY Written by XV 3.10a END 3"3wUD3D3"3""3"3"333""""""""3DDDU3""""DªwUUD3333333"3""3""DfD"3""""""""33DUfffUªw3""UD3""3"3D"33wf"""""""3""""""""D""""""""333U3333DDff333"""""""""""333333DDDUD"3"""""3"""""""""3""""""3333UUfª"
diff --git a/gtk/parent b/gtk/parent
new file mode 100644
index 000000000..94fee6123
--- /dev/null
+++ b/gtk/parent
@@ -0,0 +1,10 @@
+ gdk_window_show (widget->window);
+ gdk_window_clear_area (widget->window,
+ widget->allocation.x,
+ widget->allocation.y,
+ widget->allocation.width,
+ widget->allocation.height);
+ gdk_window_hide (widget->window);
+ if (GTK_WIDGET_VISIBLE (widget->parent))
+ if (GTK_WIDGET_REALIZED (widget->parent) &&
+ if (GTK_WIDGET_MAPPED (widget->parent) &&
diff --git a/gtk/runelisp b/gtk/runelisp
new file mode 100644
index 000000000..115080cf0
--- /dev/null
+++ b/gtk/runelisp
@@ -0,0 +1,6 @@
+#! /bin/sh
+if test $# -lt 1; then
+ echo >&2 "usage: $0 file.el"
+ exit 1
+fi
+exec emacs --no-init-file --no-site-file --batch --load $*
diff --git a/gtk/simple.c b/gtk/simple.c
new file mode 100644
index 000000000..47893772f
--- /dev/null
+++ b/gtk/simple.c
@@ -0,0 +1,39 @@
+#include <gtk/gtk.h>
+#include <gdk/gdkprivate.h>
+
+
+void
+hello ()
+{
+ g_print ("hello world\n");
+}
+
+int
+main (int argc, char *argv[])
+{
+ GtkWidget *window;
+ GtkWidget *button;
+
+ gdk_progclass = g_strdup ("XTerm");
+ gtk_init (&argc, &argv);
+
+ window = gtk_widget_new (gtk_window_get_type (),
+ "GtkObject::user_data", NULL,
+ "GtkWindow::type", GTK_WINDOW_TOPLEVEL,
+ "GtkWindow::title", "hello world",
+ "GtkWindow::allow_grow", FALSE,
+ "GtkWindow::allow_shrink", FALSE,
+ "GtkContainer::border_width", 10,
+ NULL);
+ button = gtk_widget_new (gtk_button_get_type (),
+ "GtkButton::label", "hello world",
+ "GtkObject::signal::clicked", hello, NULL,
+ "GtkWidget::parent", window,
+ "GtkWidget::visible", TRUE,
+ NULL);
+ gtk_widget_show (window);
+
+ gtk_main ();
+
+ return 0;
+}
diff --git a/gtk/test.xpm b/gtk/test.xpm
new file mode 100644
index 000000000..9b0d2efdb
--- /dev/null
+++ b/gtk/test.xpm
@@ -0,0 +1,92 @@
+/* XPM */
+static char *openfile[] = {
+/* width height num_colors chars_per_pixel */
+" 20 19 66 2",
+/* colors */
+".. c None",
+".# c #000000",
+".a c #dfdfdf",
+".b c #7f7f7f",
+".c c #006f6f",
+".d c #00efef",
+".e c #009f9f",
+".f c #004040",
+".g c #00bfbf",
+".h c #ff0000",
+".i c #ffffff",
+".j c #7f0000",
+".k c #007070",
+".l c #00ffff",
+".m c #00a0a0",
+".n c #004f4f",
+".o c #00cfcf",
+".p c #8f8f8f",
+".q c #6f6f6f",
+".r c #a0a0a0",
+".s c #7f7f00",
+".t c #007f7f",
+".u c #5f5f5f",
+".v c #707070",
+".w c #00f0f0",
+".x c #009090",
+".y c #ffff00",
+".z c #0000ff",
+".A c #00afaf",
+".B c #00d0d0",
+".C c #00dfdf",
+".D c #005f5f",
+".E c #00b0b0",
+".F c #001010",
+".G c #00c0c0",
+".H c #000f0f",
+".I c #00007f",
+".J c #005050",
+".K c #002f2f",
+".L c #dfcfcf",
+".M c #dfd0d0",
+".N c #006060",
+".O c #00e0e0",
+".P c #00ff00",
+".Q c #002020",
+".R c #dfc0c0",
+".S c #008080",
+".T c #001f1f",
+".U c #003f3f",
+".V c #007f00",
+".W c #00000f",
+".X c #000010",
+".Y c #00001f",
+".Z c #000020",
+".0 c #00002f",
+".1 c #000030",
+".2 c #00003f",
+".3 c #000040",
+".4 c #00004f",
+".5 c #000050",
+".6 c #00005f",
+".7 c #000060",
+".8 c #00006f",
+".9 c #000070",
+"#. c #7f7f80",
+"## c #9f9f9f",
+/* pixels */
+"........................................",
+"........................................",
+"........................................",
+".......................#.#.#............",
+".....................#.......#...#......",
+"...............................#.#......",
+".......#.#.#.................#.#.#......",
+".....#.y.i.y.#.#.#.#.#.#.#..............",
+".....#.i.y.i.y.i.y.i.y.i.#..............",
+".....#.y.i.y.i.y.i.y.i.y.#..............",
+".....#.i.y.i.y.#.#.#.#.#.#.#.#.#.#.#....",
+".....#.y.i.y.#.s.s.s.s.s.s.s.s.s.#......",
+".....#.i.y.#.s.s.s.s.s.s.s.s.s.#........",
+".....#.y.#.s.s.s.s.s.s.s.s.s.#..........",
+".....#.#.s.s.s.s.s.s.s.s.s.#............",
+".....#.#.#.#.#.#.#.#.#.#.#..............",
+"........................................",
+"........................................",
+"........................................"
+};
diff --git a/gtk/testgtk.c b/gtk/testgtk.c
new file mode 100644
index 000000000..b1d698a08
--- /dev/null
+++ b/gtk/testgtk.c
@@ -0,0 +1,3110 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include "gtk.h"
+#include "../gdk/gdk.h"
+#include "../gdk/gdkx.h"
+
+
+void
+destroy_window (GtkWidget *widget,
+ GtkWidget **window)
+{
+ *window = NULL;
+}
+
+void
+button_window (GtkWidget *widget,
+ GtkWidget *button)
+{
+ if (!GTK_WIDGET_VISIBLE (button))
+ gtk_widget_show (button);
+ else
+ gtk_widget_hide (button);
+}
+
+void
+create_buttons ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *box1;
+ GtkWidget *box2;
+ GtkWidget *table;
+ GtkWidget *button[10];
+ GtkWidget *separator;
+
+ if (!window)
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "buttons");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+ box1 = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), box1);
+ gtk_widget_show (box1);
+
+
+ table = gtk_table_new (3, 3, FALSE);
+ gtk_table_set_row_spacings (GTK_TABLE (table), 5);
+ gtk_table_set_col_spacings (GTK_TABLE (table), 5);
+ gtk_container_border_width (GTK_CONTAINER (table), 10);
+ gtk_box_pack_start (GTK_BOX (box1), table, TRUE, TRUE, 0);
+ gtk_widget_show (table);
+
+
+ button[0] = gtk_button_new_with_label ("button1");
+ button[1] = gtk_button_new_with_label ("button2");
+ button[2] = gtk_button_new_with_label ("button3");
+ button[3] = gtk_button_new_with_label ("button4");
+ button[4] = gtk_button_new_with_label ("button5");
+ button[5] = gtk_button_new_with_label ("button6");
+ button[6] = gtk_button_new_with_label ("button7");
+ button[7] = gtk_button_new_with_label ("button8");
+ button[8] = gtk_button_new_with_label ("button9");
+
+ gtk_signal_connect (GTK_OBJECT (button[0]), "clicked",
+ (GtkSignalFunc) button_window,
+ button[1]);
+
+ gtk_table_attach (GTK_TABLE (table), button[0], 0, 1, 0, 1,
+ GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+ gtk_widget_show (button[0]);
+
+ gtk_signal_connect (GTK_OBJECT (button[1]), "clicked",
+ (GtkSignalFunc) button_window,
+ button[2]);
+
+ gtk_table_attach (GTK_TABLE (table), button[1], 1, 2, 1, 2,
+ GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+ gtk_widget_show (button[1]);
+
+ gtk_signal_connect (GTK_OBJECT (button[2]), "clicked",
+ (GtkSignalFunc) button_window,
+ button[3]);
+ gtk_table_attach (GTK_TABLE (table), button[2], 2, 3, 2, 3,
+ GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+ gtk_widget_show (button[2]);
+
+ gtk_signal_connect (GTK_OBJECT (button[3]), "clicked",
+ (GtkSignalFunc) button_window,
+ button[4]);
+ gtk_table_attach (GTK_TABLE (table), button[3], 0, 1, 2, 3,
+ GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+ gtk_widget_show (button[3]);
+
+ gtk_signal_connect (GTK_OBJECT (button[4]), "clicked",
+ (GtkSignalFunc) button_window,
+ button[5]);
+ gtk_table_attach (GTK_TABLE (table), button[4], 2, 3, 0, 1,
+ GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+ gtk_widget_show (button[4]);
+
+ gtk_signal_connect (GTK_OBJECT (button[5]), "clicked",
+ (GtkSignalFunc) button_window,
+ button[6]);
+ gtk_table_attach (GTK_TABLE (table), button[5], 1, 2, 2, 3,
+ GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+ gtk_widget_show (button[5]);
+
+ gtk_signal_connect (GTK_OBJECT (button[6]), "clicked",
+ (GtkSignalFunc) button_window,
+ button[7]);
+ gtk_table_attach (GTK_TABLE (table), button[6], 1, 2, 0, 1,
+ GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+ gtk_widget_show (button[6]);
+
+ gtk_signal_connect (GTK_OBJECT (button[7]), "clicked",
+ (GtkSignalFunc) button_window,
+ button[8]);
+ gtk_table_attach (GTK_TABLE (table), button[7], 2, 3, 1, 2,
+ GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+ gtk_widget_show (button[7]);
+
+ gtk_signal_connect (GTK_OBJECT (button[8]), "clicked",
+ (GtkSignalFunc) button_window,
+ button[0]);
+ gtk_table_attach (GTK_TABLE (table), button[8], 0, 1, 1, 2,
+ GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+ gtk_widget_show (button[8]);
+
+
+ separator = gtk_hseparator_new ();
+ gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
+ gtk_widget_show (separator);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ button[9] = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button[9]), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+ gtk_box_pack_start (GTK_BOX (box2), button[9], TRUE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS (button[9], GTK_CAN_DEFAULT);
+ gtk_widget_grab_default (button[9]);
+ gtk_widget_show (button[9]);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+void
+create_toggle_buttons ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *box1;
+ GtkWidget *box2;
+ GtkWidget *button;
+ GtkWidget *separator;
+
+ if (!window)
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "toggle buttons");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+
+ box1 = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), box1);
+ gtk_widget_show (box1);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ button = gtk_toggle_button_new_with_label ("button1");
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+ button = gtk_toggle_button_new_with_label ("button2");
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+ button = gtk_toggle_button_new_with_label ("button3");
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+
+ separator = gtk_hseparator_new ();
+ gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
+ gtk_widget_show (separator);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+void
+create_check_buttons ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *box1;
+ GtkWidget *box2;
+ GtkWidget *button;
+ GtkWidget *separator;
+
+ if (!window)
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "check buttons");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+
+ box1 = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), box1);
+ gtk_widget_show (box1);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ button = gtk_check_button_new_with_label ("button1");
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+ button = gtk_check_button_new_with_label ("button2");
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+ button = gtk_check_button_new_with_label ("button3");
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+
+ separator = gtk_hseparator_new ();
+ gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
+ gtk_widget_show (separator);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+void
+create_radio_buttons ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *box1;
+ GtkWidget *box2;
+ GtkWidget *button;
+ GtkWidget *separator;
+
+ if (!window)
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "radio buttons");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+
+ box1 = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), box1);
+ gtk_widget_show (box1);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ button = gtk_radio_button_new_with_label (NULL, "button1");
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+ button = gtk_radio_button_new_with_label (
+ gtk_radio_button_group (GTK_RADIO_BUTTON (button)),
+ "button2");
+ gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE);
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+ button = gtk_radio_button_new_with_label (
+ gtk_radio_button_group (GTK_RADIO_BUTTON (button)),
+ "button3");
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+
+ separator = gtk_hseparator_new ();
+ gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
+ gtk_widget_show (separator);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+void
+bbox_widget_destroy (GtkWidget* widget, GtkWidget* todestroy)
+{
+}
+
+void
+create_bbox_window (gint horizontal,
+ char* title,
+ gint pos,
+ gint spacing,
+ gint child_w,
+ gint child_h,
+ gint layout)
+{
+ GtkWidget* window;
+ GtkWidget* box1;
+ GtkWidget* bbox;
+ GtkWidget* button;
+
+ /* create a new window */
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title (GTK_WINDOW (window), title);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) bbox_widget_destroy, window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) bbox_widget_destroy, window);
+
+ if (horizontal)
+ {
+ gtk_widget_set_usize (window, 550, 60);
+ gtk_widget_set_uposition (window, 150, pos);
+ box1 = gtk_vbox_new (FALSE, 0);
+ }
+ else
+ {
+ gtk_widget_set_usize (window, 150, 400);
+ gtk_widget_set_uposition (window, pos, 200);
+ box1 = gtk_vbox_new (FALSE, 0);
+ }
+
+ gtk_container_add (GTK_CONTAINER (window), box1);
+ gtk_widget_show (box1);
+
+ if (horizontal)
+ bbox = gtk_hbutton_box_new();
+ else
+ bbox = gtk_vbutton_box_new();
+ gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), layout);
+ gtk_button_box_set_spacing (GTK_BUTTON_BOX (bbox), spacing);
+ gtk_button_box_set_child_size (GTK_BUTTON_BOX (bbox), child_w, child_h);
+ gtk_widget_show (bbox);
+
+ gtk_container_border_width (GTK_CONTAINER(box1), 25);
+ gtk_box_pack_start (GTK_BOX (box1), bbox, TRUE, TRUE, 0);
+
+ button = gtk_button_new_with_label ("OK");
+ gtk_container_add (GTK_CONTAINER(bbox), button);
+
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) bbox_widget_destroy, window);
+
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("Cancel");
+ gtk_container_add (GTK_CONTAINER(bbox), button);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("Help");
+ gtk_container_add (GTK_CONTAINER(bbox), button);
+ gtk_widget_show (button);
+
+ gtk_widget_show (window);
+}
+
+void
+test_hbbox ()
+{
+ create_bbox_window (TRUE, "Spread", 50, 40, 85, 28, GTK_BUTTONBOX_SPREAD);
+ create_bbox_window (TRUE, "Edge", 200, 40, 85, 25, GTK_BUTTONBOX_EDGE);
+ create_bbox_window (TRUE, "Start", 350, 40, 85, 25, GTK_BUTTONBOX_START);
+ create_bbox_window (TRUE, "End", 500, 15, 30, 25, GTK_BUTTONBOX_END);
+}
+
+void
+test_vbbox ()
+{
+ create_bbox_window (FALSE, "Spread", 50, 40, 85, 25, GTK_BUTTONBOX_SPREAD);
+ create_bbox_window (FALSE, "Edge", 250, 40, 85, 28, GTK_BUTTONBOX_EDGE);
+ create_bbox_window (FALSE, "Start", 450, 40, 85, 25, GTK_BUTTONBOX_START);
+ create_bbox_window (FALSE, "End", 650, 15, 30, 25, GTK_BUTTONBOX_END);
+}
+
+void
+create_button_box ()
+{
+ static GtkWidget* window = NULL;
+ GtkWidget* bbox;
+ GtkWidget* button;
+
+ if (!window)
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title (GTK_WINDOW (window),
+ "Button Box Test");
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window, &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window, &window);
+
+ gtk_container_border_width (GTK_CONTAINER (window), 20);
+
+ /*
+ *these 15 lines are a nice and easy example for GtkHButtonBox
+ */
+ bbox = gtk_hbutton_box_new ();
+ gtk_container_add (GTK_CONTAINER (window), bbox);
+ gtk_widget_show (bbox);
+
+ button = gtk_button_new_with_label ("Horizontal");
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) test_hbbox, 0);
+ gtk_container_add (GTK_CONTAINER (bbox), button);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("Vertical");
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) test_vbbox, 0);
+ gtk_container_add (GTK_CONTAINER (bbox), button);
+ gtk_widget_show (button);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+
+void
+reparent_label (GtkWidget *widget,
+ GtkWidget *new_parent)
+{
+ GtkWidget *label;
+
+ label = gtk_object_get_user_data (GTK_OBJECT (widget));
+
+ gtk_widget_reparent (label, new_parent);
+}
+
+void
+create_reparent ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *box1;
+ GtkWidget *box2;
+ GtkWidget *box3;
+ GtkWidget *frame;
+ GtkWidget *button;
+ GtkWidget *label;
+ GtkWidget *separator;
+
+ if (!window)
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "buttons");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+
+ box1 = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), box1);
+ gtk_widget_show (box1);
+
+
+ box2 = gtk_hbox_new (FALSE, 5);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ label = gtk_label_new ("Hello World");
+
+ frame = gtk_frame_new ("Frame 1");
+ gtk_box_pack_start (GTK_BOX (box2), frame, TRUE, TRUE, 0);
+ gtk_widget_show (frame);
+
+ box3 = gtk_vbox_new (FALSE, 5);
+ gtk_container_border_width (GTK_CONTAINER (box3), 5);
+ gtk_container_add (GTK_CONTAINER (frame), box3);
+ gtk_widget_show (box3);
+
+ button = gtk_button_new_with_label ("switch");
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) reparent_label,
+ box3);
+ gtk_object_set_user_data (GTK_OBJECT (button), label);
+ gtk_box_pack_start (GTK_BOX (box3), button, FALSE, TRUE, 0);
+ gtk_widget_show (button);
+
+ gtk_box_pack_start (GTK_BOX (box3), label, FALSE, TRUE, 0);
+ gtk_widget_show (label);
+
+
+ frame = gtk_frame_new ("Frame 2");
+ gtk_box_pack_start (GTK_BOX (box2), frame, TRUE, TRUE, 0);
+ gtk_widget_show (frame);
+
+ box3 = gtk_vbox_new (FALSE, 5);
+ gtk_container_border_width (GTK_CONTAINER (box3), 5);
+ gtk_container_add (GTK_CONTAINER (frame), box3);
+ gtk_widget_show (box3);
+
+ button = gtk_button_new_with_label ("switch");
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) reparent_label,
+ box3);
+ gtk_object_set_user_data (GTK_OBJECT (button), label);
+ gtk_box_pack_start (GTK_BOX (box3), button, FALSE, TRUE, 0);
+ gtk_widget_show (button);
+
+
+ separator = gtk_hseparator_new ();
+ gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
+ gtk_widget_show (separator);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+void
+create_pixmap ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *box1;
+ GtkWidget *box2;
+ GtkWidget *box3;
+ GtkWidget *button;
+ GtkWidget *label;
+ GtkWidget *separator;
+ GtkWidget *pixmapwid;
+ GdkPixmap *pixmap;
+ GdkBitmap *mask;
+ GtkStyle *style;
+
+ if (!window)
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "pixmap");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+ gtk_widget_realize(window);
+
+ box1 = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), box1);
+ gtk_widget_show (box1);
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
+ gtk_widget_show (box2);
+
+ button = gtk_button_new ();
+ gtk_box_pack_start (GTK_BOX (box2), button, FALSE, FALSE, 0);
+ gtk_widget_show (button);
+
+ style=gtk_widget_get_style(button);
+
+ pixmap = gdk_pixmap_create_from_xpm (window->window, &mask,
+ &style->bg[GTK_STATE_NORMAL],
+ "test.xpm");
+ pixmapwid = gtk_pixmap_new (pixmap, mask);
+
+ label = gtk_label_new ("Pixmap\ntest");
+ box3 = gtk_hbox_new (FALSE, 0);
+ gtk_container_border_width (GTK_CONTAINER (box3), 2);
+ gtk_container_add (GTK_CONTAINER (box3), pixmapwid);
+ gtk_container_add (GTK_CONTAINER (box3), label);
+ gtk_container_add (GTK_CONTAINER (button), box3);
+ gtk_widget_show (pixmapwid);
+ gtk_widget_show (label);
+ gtk_widget_show (box3);
+
+ separator = gtk_hseparator_new ();
+ gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
+ gtk_widget_show (separator);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+void
+create_tooltips ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *box1;
+ GtkWidget *box2;
+ GtkWidget *button;
+ GtkWidget *separator;
+ GtkTooltips *tooltips;
+
+ if (!window)
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "tooltips");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+ tooltips=gtk_tooltips_new();
+
+ box1 = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), box1);
+ gtk_widget_show (box1);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ button = gtk_toggle_button_new_with_label ("button1");
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+ gtk_tooltips_set_tips(tooltips,button,"This is button 1");
+
+ button = gtk_toggle_button_new_with_label ("button2");
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+ gtk_tooltips_set_tips(tooltips,button,"This is button 2");
+
+ button = gtk_toggle_button_new_with_label ("button3");
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+ gtk_tooltips_set_tips (tooltips, button, "This is button 3. This is also a really long tooltip which probably won't fit on a single line and will therefore need to be wrapped. Hopefully the wrapping will work correctly.");
+
+ separator = gtk_hseparator_new ();
+ gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
+ gtk_widget_show (separator);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+
+ gtk_tooltips_set_tips (tooltips, button, "Push this button to close window");
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+GtkWidget*
+create_menu (int depth)
+{
+ GtkWidget *menu;
+ GtkWidget *submenu;
+ GtkWidget *menuitem;
+ GSList *group;
+ char buf[32];
+ int i, j;
+
+ if (depth < 1)
+ return NULL;
+
+ menu = gtk_menu_new ();
+ submenu = NULL;
+ group = NULL;
+
+ for (i = 0, j = 1; i < 5; i++, j++)
+ {
+ sprintf (buf, "item %2d - %d", depth, j);
+ menuitem = gtk_radio_menu_item_new_with_label (group, buf);
+ group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem));
+ gtk_menu_append (GTK_MENU (menu), menuitem);
+ gtk_widget_show (menuitem);
+
+ if (depth > 0)
+ {
+ if (!submenu)
+ submenu = create_menu (depth - 1);
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
+ }
+ }
+
+ return menu;
+}
+
+void
+create_menus ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *box1;
+ GtkWidget *box2;
+ GtkWidget *button;
+ GtkWidget *menu;
+ GtkWidget *menubar;
+ GtkWidget *menuitem;
+ GtkWidget *optionmenu;
+ GtkWidget *separator;
+
+ if (!window)
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "menus");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+
+ box1 = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), box1);
+ gtk_widget_show (box1);
+
+
+ menubar = gtk_menu_bar_new ();
+ gtk_box_pack_start (GTK_BOX (box1), menubar, FALSE, TRUE, 0);
+ gtk_widget_show (menubar);
+
+ menu = create_menu (2);
+
+ menuitem = gtk_menu_item_new_with_label ("test\nline2");
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
+ gtk_menu_bar_append (GTK_MENU_BAR (menubar), menuitem);
+ gtk_widget_show (menuitem);
+
+ menuitem = gtk_menu_item_new_with_label ("foo");
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
+ gtk_menu_bar_append (GTK_MENU_BAR (menubar), menuitem);
+ gtk_widget_show (menuitem);
+
+ menuitem = gtk_menu_item_new_with_label ("bar");
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
+ gtk_menu_item_right_justify (GTK_MENU_ITEM (menuitem));
+ gtk_menu_bar_append (GTK_MENU_BAR (menubar), menuitem);
+ gtk_widget_show (menuitem);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ optionmenu = gtk_option_menu_new ();
+ gtk_option_menu_set_menu (GTK_OPTION_MENU (optionmenu), create_menu (1));
+ gtk_option_menu_set_history (GTK_OPTION_MENU (optionmenu), 4);
+ gtk_box_pack_start (GTK_BOX (box2), optionmenu, TRUE, TRUE, 0);
+ gtk_widget_show (optionmenu);
+
+
+ separator = gtk_hseparator_new ();
+ gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
+ gtk_widget_show (separator);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+void
+create_scrolled_windows ()
+{
+ static GtkWidget *window;
+ GtkWidget *scrolled_window;
+ GtkWidget *table;
+ GtkWidget *button;
+ char buffer[32];
+ int i, j;
+
+ if (!window)
+ {
+ window = gtk_dialog_new ();
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "dialog");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+
+ scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+ gtk_container_border_width (GTK_CONTAINER (scrolled_window), 10);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox),
+ scrolled_window, TRUE, TRUE, 0);
+ gtk_widget_show (scrolled_window);
+
+ table = gtk_table_new (20, 20, FALSE);
+ gtk_table_set_row_spacings (GTK_TABLE (table), 10);
+ gtk_table_set_col_spacings (GTK_TABLE (table), 10);
+ gtk_container_add (GTK_CONTAINER (scrolled_window), table);
+ gtk_widget_show (table);
+
+ for (i = 0; i < 20; i++)
+ for (j = 0; j < 20; j++)
+ {
+ sprintf (buffer, "button (%d,%d)\n", i, j);
+ button = gtk_toggle_button_new_with_label (buffer);
+ gtk_table_attach_defaults (GTK_TABLE (table), button,
+ i, i+1, j, j+1);
+ gtk_widget_show (button);
+ }
+
+
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
+ button, TRUE, TRUE, 0);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+void
+create_entry ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *box1;
+ GtkWidget *box2;
+ GtkWidget *entry;
+ GtkWidget *button;
+ GtkWidget *separator;
+
+ /* if (!window) */
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "entry");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+
+ box1 = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), box1);
+ gtk_widget_show (box1);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ entry = gtk_entry_new ();
+ /* gtk_widget_set_usize (entry, 0, 25); */
+ gtk_entry_set_text (GTK_ENTRY (entry), "hello world");
+ gtk_box_pack_start (GTK_BOX (box2), entry, TRUE, TRUE, 0);
+ gtk_widget_show (entry);
+
+
+ separator = gtk_hseparator_new ();
+ gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
+ gtk_widget_show (separator);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ /* else
+ gtk_widget_destroy (window); */
+}
+
+void
+list_add (GtkWidget *widget,
+ GtkWidget *list)
+{
+ static int i = 1;
+ gchar buffer[64];
+ GtkWidget *list_item;
+
+ sprintf (buffer, "added item %d", i++);
+ list_item = gtk_list_item_new_with_label (buffer);
+ gtk_widget_show (list_item);
+ gtk_container_add (GTK_CONTAINER (list), list_item);
+}
+
+void
+list_remove (GtkWidget *widget,
+ GtkWidget *list)
+{
+ GList *tmp_list;
+ GList *clear_list;
+
+ tmp_list = GTK_LIST (list)->selection;
+ clear_list = NULL;
+
+ while (tmp_list)
+ {
+ clear_list = g_list_prepend (clear_list, tmp_list->data);
+ tmp_list = tmp_list->next;
+ }
+
+ clear_list = g_list_reverse (clear_list);
+
+ gtk_list_remove_items (GTK_LIST (list), clear_list);
+
+ tmp_list = clear_list;
+
+ while (tmp_list)
+ {
+ gtk_widget_destroy (GTK_WIDGET (tmp_list->data));
+ tmp_list = tmp_list->next;
+ }
+
+ g_list_free (clear_list);
+}
+
+void
+create_list ()
+{
+ static GtkWidget *window = NULL;
+ static char *list_items[] =
+ {
+ "hello",
+ "world",
+ "blah",
+ "foo",
+ "bar",
+ "argh",
+ "spencer",
+ "is a",
+ "wussy",
+ "programmer",
+ };
+ static int nlist_items = sizeof (list_items) / sizeof (list_items[0]);
+
+ GtkWidget *box1;
+ GtkWidget *box2;
+ GtkWidget *scrolled_win;
+ GtkWidget *list;
+ GtkWidget *list_item;
+ GtkWidget *button;
+ GtkWidget *separator;
+ int i;
+
+ if (!window)
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "list");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+
+ box1 = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), box1);
+ gtk_widget_show (box1);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ scrolled_win = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+ gtk_box_pack_start (GTK_BOX (box2), scrolled_win, TRUE, TRUE, 0);
+ gtk_widget_show (scrolled_win);
+
+ list = gtk_list_new ();
+ gtk_list_set_selection_mode (GTK_LIST (list), GTK_SELECTION_MULTIPLE);
+ gtk_list_set_selection_mode (GTK_LIST (list), GTK_SELECTION_BROWSE);
+ gtk_container_add (GTK_CONTAINER (scrolled_win), list);
+ gtk_widget_show (list);
+
+ for (i = 0; i < nlist_items; i++)
+ {
+ list_item = gtk_list_item_new_with_label (list_items[i]);
+ gtk_container_add (GTK_CONTAINER (list), list_item);
+ gtk_widget_show (list_item);
+ }
+
+ button = gtk_button_new_with_label ("add");
+ GTK_WIDGET_UNSET_FLAGS (button, GTK_CAN_FOCUS);
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) list_add,
+ list);
+ gtk_box_pack_start (GTK_BOX (box2), button, FALSE, TRUE, 0);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("remove");
+ GTK_WIDGET_UNSET_FLAGS (button, GTK_CAN_FOCUS);
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) list_remove,
+ list);
+ gtk_box_pack_start (GTK_BOX (box2), button, FALSE, TRUE, 0);
+ gtk_widget_show (button);
+
+
+ separator = gtk_hseparator_new ();
+ gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
+ gtk_widget_show (separator);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+void
+color_selection_ok (GtkWidget *w,
+ GtkColorSelectionDialog *cs)
+{
+ GtkColorSelection *colorsel;
+ gdouble color[4];
+
+ colorsel=GTK_COLOR_SELECTION(cs->colorsel);
+
+ gtk_color_selection_get_color(colorsel,color);
+ gtk_color_selection_set_color(colorsel,color);
+}
+
+void
+color_selection_changed (GtkWidget *w,
+ GtkColorSelectionDialog *cs)
+{
+ GtkColorSelection *colorsel;
+ gdouble color[4];
+
+ colorsel=GTK_COLOR_SELECTION(cs->colorsel);
+ gtk_color_selection_get_color(colorsel,color);
+}
+
+void
+create_color_selection ()
+{
+ static GtkWidget *window = NULL;
+
+ if (!window)
+ {
+ gtk_preview_set_install_cmap (TRUE);
+ gtk_widget_push_visual (gtk_preview_get_visual ());
+ gtk_widget_push_colormap (gtk_preview_get_cmap ());
+
+ window = gtk_color_selection_dialog_new ("color selection dialog");
+
+ gtk_color_selection_set_opacity (
+ GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (window)->colorsel),
+ TRUE);
+
+ gtk_color_selection_set_update_policy(
+ GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (window)->colorsel),
+ GTK_UPDATE_CONTINUOUS);
+
+ gtk_window_position (GTK_WINDOW (window), GTK_WIN_POS_MOUSE);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_signal_connect (
+ GTK_OBJECT (GTK_COLOR_SELECTION_DIALOG (window)->colorsel),
+ "color_changed",
+ (GtkSignalFunc) color_selection_changed,
+ window);
+
+ gtk_signal_connect (
+ GTK_OBJECT (GTK_COLOR_SELECTION_DIALOG (window)->ok_button),
+ "clicked",
+ (GtkSignalFunc) color_selection_ok,
+ window);
+
+ gtk_signal_connect_object (
+ GTK_OBJECT (GTK_COLOR_SELECTION_DIALOG (window)->cancel_button),
+ "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+
+ gtk_widget_pop_colormap ();
+ gtk_widget_pop_visual ();
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+
+void
+file_selection_ok (GtkWidget *w,
+ GtkFileSelection *fs)
+{
+ g_print ("%s\n", gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs)));
+}
+
+void
+create_file_selection ()
+{
+ static GtkWidget *window = NULL;
+
+ if (!window)
+ {
+ window = gtk_file_selection_new ("file selection dialog");
+ gtk_window_position (GTK_WINDOW (window), GTK_WIN_POS_MOUSE);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (window)->ok_button),
+ "clicked", (GtkSignalFunc) file_selection_ok,
+ window);
+ gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION (window)->cancel_button),
+ "clicked", (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+
+/*
+ * GtkDialog
+ */
+static GtkWidget *dialog_window = NULL;
+
+void
+label_toggle (GtkWidget *widget,
+ GtkWidget **label)
+{
+ if (!(*label))
+ {
+ *label = gtk_label_new ("Dialog Test");
+ gtk_misc_set_padding (GTK_MISC (*label), 10, 10);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->vbox),
+ *label, TRUE, TRUE, 0);
+ gtk_widget_show (*label);
+ }
+ else
+ {
+ gtk_widget_destroy (*label);
+ *label = NULL;
+ }
+}
+
+void
+create_dialog ()
+{
+ static GtkWidget *label;
+ GtkWidget *button;
+
+ if (!dialog_window)
+ {
+ dialog_window = gtk_dialog_new ();
+
+ gtk_signal_connect (GTK_OBJECT (dialog_window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &dialog_window);
+ gtk_signal_connect (GTK_OBJECT (dialog_window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &dialog_window);
+
+ gtk_window_set_title (GTK_WINDOW (dialog_window), "dialog");
+ gtk_container_border_width (GTK_CONTAINER (dialog_window), 0);
+
+ button = gtk_button_new_with_label ("OK");
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->action_area),
+ button, TRUE, TRUE, 0);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("Toggle");
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) label_toggle,
+ &label);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->action_area),
+ button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+ label = NULL;
+ }
+
+ if (!GTK_WIDGET_VISIBLE (dialog_window))
+ gtk_widget_show (dialog_window);
+ else
+ gtk_widget_destroy (dialog_window);
+}
+
+
+/*
+ * GtkRange
+ */
+void
+create_range_controls ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *box1;
+ GtkWidget *box2;
+ GtkWidget *button;
+ GtkWidget *scrollbar;
+ GtkWidget *scale;
+ GtkWidget *separator;
+ GtkObject *adjustment;
+
+ if (!window)
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "range controls");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+
+ box1 = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), box1);
+ gtk_widget_show (box1);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ adjustment = gtk_adjustment_new (0.0, 0.0, 101.0, 0.1, 1.0, 1.0);
+
+ scale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
+ gtk_widget_set_usize (GTK_WIDGET (scale), 150, 30);
+ gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
+ gtk_scale_set_digits (GTK_SCALE (scale), 1);
+ gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
+ gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
+ gtk_widget_show (scale);
+
+ scrollbar = gtk_hscrollbar_new (GTK_ADJUSTMENT (adjustment));
+ gtk_range_set_update_policy (GTK_RANGE (scrollbar),
+ GTK_UPDATE_CONTINUOUS);
+ gtk_box_pack_start (GTK_BOX (box2), scrollbar, TRUE, TRUE, 0);
+ gtk_widget_show (scrollbar);
+
+
+ separator = gtk_hseparator_new ();
+ gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
+ gtk_widget_show (separator);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+
+/*
+ * GtkRulers
+ */
+void
+create_rulers ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *table;
+ GtkWidget *ruler;
+
+ if (!window)
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "rulers");
+ gtk_widget_set_usize (window, 300, 300);
+ gtk_widget_set_events (window,
+ GDK_POINTER_MOTION_MASK
+ | GDK_POINTER_MOTION_HINT_MASK);
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+ table = gtk_table_new (2, 2, FALSE);
+ gtk_container_add (GTK_CONTAINER (window), table);
+ gtk_widget_show (table);
+
+ ruler = gtk_hruler_new ();
+ gtk_ruler_set_range (GTK_RULER (ruler), 5, 15, 0, 20);
+
+ gtk_signal_connect_object (
+ GTK_OBJECT (window),
+ "motion_notify_event",
+ (GtkSignalFunc)
+ GTK_WIDGET_CLASS (GTK_OBJECT (ruler)->klass)->motion_notify_event,
+ GTK_OBJECT (ruler));
+
+ gtk_table_attach (GTK_TABLE (table), ruler, 1, 2, 0, 1,
+ GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
+ gtk_widget_show (ruler);
+
+
+ ruler = gtk_vruler_new ();
+ gtk_ruler_set_range (GTK_RULER (ruler), 5, 15, 0, 20);
+
+ gtk_signal_connect_object (
+ GTK_OBJECT (window),
+ "motion_notify_event",
+ (GtkSignalFunc)
+ GTK_WIDGET_CLASS (GTK_OBJECT (ruler)->klass)->motion_notify_event,
+ GTK_OBJECT (ruler));
+
+ gtk_table_attach (GTK_TABLE (table), ruler, 0, 1, 1, 2,
+ GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+ gtk_widget_show (ruler);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+
+/*
+ * GtkText
+ */
+void
+create_text ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *box1;
+ GtkWidget *box2;
+ GtkWidget *button;
+ GtkWidget *separator;
+ GtkWidget *table;
+ GtkWidget *hscrollbar;
+ GtkWidget *vscrollbar;
+ GtkWidget *text;
+
+ if (!window)
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_widget_set_name (window, "text window");
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "test");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+
+ box1 = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), box1);
+ gtk_widget_show (box1);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ table = gtk_table_new (2, 2, FALSE);
+ gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2);
+ gtk_table_set_col_spacing (GTK_TABLE (table), 0, 2);
+ gtk_box_pack_start (GTK_BOX (box2), table, TRUE, TRUE, 0);
+ gtk_widget_show (table);
+
+ text = gtk_text_new (NULL, NULL);
+ gtk_table_attach_defaults (GTK_TABLE (table), text, 0, 1, 0, 1);
+ gtk_widget_show (text);
+
+ hscrollbar = gtk_hscrollbar_new (GTK_TEXT (text)->hadj);
+ gtk_table_attach (GTK_TABLE (table), hscrollbar, 0, 1, 1, 2,
+ GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
+ gtk_widget_show (hscrollbar);
+
+ vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
+ gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
+ GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+ gtk_widget_show (vscrollbar);
+
+ gtk_text_freeze (GTK_TEXT (text));
+
+ gtk_widget_realize (text);
+
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "spencer blah blah blah\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "kimball\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "is\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "a\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "wuss.\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "but\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "josephine\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "(his\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "girlfriend\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "is\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "not).\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "why?\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "because\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "spencer\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "puked\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "last\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "night\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "but\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "josephine\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "did\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "not", -1);
+
+ gtk_text_thaw (GTK_TEXT (text));
+
+ separator = gtk_hseparator_new ();
+ gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
+ gtk_widget_show (separator);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+
+/*
+ * GtkNotebook
+ */
+void
+rotate_notebook (GtkButton *button,
+ GtkNotebook *notebook)
+{
+ gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos + 1) % 4);
+}
+
+void
+create_notebook ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *box1;
+ GtkWidget *box2;
+ GtkWidget *button;
+ GtkWidget *separator;
+ GtkWidget *notebook;
+ GtkWidget *frame;
+ GtkWidget *label;
+ char buffer[32];
+ int i;
+
+ if (!window)
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "notebook");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+
+ box1 = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), box1);
+ gtk_widget_show (box1);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ notebook = gtk_notebook_new ();
+ gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP);
+ gtk_box_pack_start (GTK_BOX (box2), notebook, TRUE, TRUE, 0);
+ gtk_widget_show (notebook);
+
+
+ for (i = 0; i < 5; i++)
+ {
+ sprintf (buffer, "Page %d", i+1);
+
+ frame = gtk_frame_new (buffer);
+ gtk_container_border_width (GTK_CONTAINER (frame), 10);
+ gtk_widget_set_usize (frame, 200, 150);
+ gtk_widget_show (frame);
+
+ label = gtk_label_new (buffer);
+ gtk_container_add (GTK_CONTAINER (frame), label);
+ gtk_widget_show (label);
+
+ label = gtk_label_new (buffer);
+ gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, label);
+ }
+
+
+ separator = gtk_hseparator_new ();
+ gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
+ gtk_widget_show (separator);
+
+
+ box2 = gtk_hbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("next");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_notebook_next_page,
+ GTK_OBJECT (notebook));
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("prev");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_notebook_prev_page,
+ GTK_OBJECT (notebook));
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("rotate");
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) rotate_notebook,
+ notebook);
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+
+/*
+ * GtkPanes
+ */
+void
+create_panes ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *frame;
+ GtkWidget *hpaned;
+ GtkWidget *vpaned;
+
+ if (!window)
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "Panes");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+ vpaned = gtk_vpaned_new ();
+ gtk_container_add (GTK_CONTAINER (window), vpaned);
+ gtk_container_border_width (GTK_CONTAINER(vpaned), 5);
+ gtk_widget_show (vpaned);
+
+ hpaned = gtk_hpaned_new ();
+ gtk_paned_add1 (GTK_PANED (vpaned), hpaned);
+
+ frame = gtk_frame_new (NULL);
+ gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
+ gtk_widget_set_usize (frame, 60, 60);
+ gtk_paned_add1 (GTK_PANED (hpaned), frame);
+ gtk_widget_show (frame);
+
+ frame = gtk_frame_new (NULL);
+ gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
+ gtk_widget_set_usize (frame, 80, 60);
+ gtk_paned_add2 (GTK_PANED (hpaned), frame);
+ gtk_widget_show (frame);
+
+ gtk_widget_show (hpaned);
+
+ frame = gtk_frame_new (NULL);
+ gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
+ gtk_widget_set_usize (frame, 60, 80);
+ gtk_paned_add2 (GTK_PANED (vpaned), frame);
+ gtk_widget_show (frame);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+
+/*
+ * Drag -N- Drop
+ */
+void
+dnd_drop (GtkWidget *button, GdkEvent *event)
+{
+ g_print ("Got drop of type |%s| with data of:\n%s\n",
+ event->dropdataavailable.data_type,
+ event->dropdataavailable.data);
+ g_free (event->dropdataavailable.data);
+ g_free (event->dropdataavailable.data_type);
+}
+
+void
+dnd_drag_request (GtkWidget *button, GdkEvent *event)
+{
+ g_print ("Button |%s| got drag request %d\n",
+ gtk_widget_get_name (button), event->type);
+
+ gtk_widget_dnd_data_set (button, event, "Hello world!!!",
+ strlen("Hello world!!!") + 1);
+}
+
+void
+create_dnd ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *box1;
+ GtkWidget *box2;
+ GtkWidget *box3;
+ GtkWidget *entry;
+ GtkWidget *frame;
+ GtkWidget *button;
+ GtkWidget *separator;
+ char *foo = "testing";
+
+ if (!window)
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "Drag -N- Drop");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+ box1 = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), box1);
+ gtk_widget_show (box1);
+
+ box2 = gtk_hbox_new (FALSE, 5);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
+ gtk_widget_show (box2);
+
+ frame = gtk_frame_new ("Drag");
+ gtk_box_pack_start (GTK_BOX (box2), frame, TRUE, TRUE, 0);
+ gtk_widget_show (frame);
+
+ box3 = gtk_vbox_new (FALSE, 5);
+ gtk_container_border_width (GTK_CONTAINER (box3), 5);
+ gtk_container_add (GTK_CONTAINER (frame), box3);
+ gtk_widget_show (box3);
+
+ /*
+ * FROM Button
+ */
+ button = gtk_button_new_with_label ("From");
+ gtk_box_pack_start (GTK_BOX (box3), button, FALSE, TRUE, 0);
+ gtk_widget_show (button);
+
+ /*
+ * currently, the widget has to be realized to
+ * set dnd on it, this needs to change
+ */
+ gtk_widget_realize (button);
+ gtk_signal_connect (GTK_OBJECT (button),
+ "drag_request_event",
+ (GtkSignalFunc) dnd_drag_request,
+ button);
+
+ gtk_widget_dnd_drag_set (button, TRUE, &foo, 1);
+
+
+ frame = gtk_frame_new ("Drop");
+ gtk_box_pack_start (GTK_BOX (box2), frame, TRUE, TRUE, 0);
+ gtk_widget_show (frame);
+
+ box3 = gtk_vbox_new (FALSE, 5);
+ gtk_container_border_width (GTK_CONTAINER (box3), 5);
+ gtk_container_add (GTK_CONTAINER (frame), box3);
+ gtk_widget_show (box3);
+
+
+ /*
+ * TO Button
+ */
+ button = gtk_button_new_with_label ("To");
+ gtk_box_pack_start (GTK_BOX (box3), button, FALSE, TRUE, 0);
+ gtk_widget_show (button);
+
+ gtk_widget_realize (button);
+ gtk_signal_connect (GTK_OBJECT (button),
+ "drop_data_available_event",
+ (GtkSignalFunc) dnd_drop,
+ button);
+
+ gtk_widget_dnd_drop_set (button, TRUE, &foo, 1, FALSE);
+
+
+ separator = gtk_hseparator_new ();
+ gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
+ gtk_widget_show (separator);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ button = gtk_button_new_with_label ("close");
+
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+/*
+ * Shaped Windows
+ */
+static GdkWindow *root_win = NULL;
+static GtkWidget *modeller = NULL;
+static GtkWidget *sheets = NULL;
+static GtkWidget *rings = NULL;
+
+typedef struct _cursoroffset {gint x,y;} CursorOffset;
+
+static void
+shape_pressed (GtkWidget *widget)
+{
+ CursorOffset *p;
+
+ p = gtk_object_get_user_data (GTK_OBJECT(widget));
+ gtk_widget_get_pointer (widget, &(p->x), &(p->y));
+
+ gtk_grab_add (widget);
+ gdk_pointer_grab (widget->window, TRUE,
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_BUTTON_MOTION_MASK,
+ NULL, NULL, 0);
+}
+
+
+static void
+shape_released (GtkWidget *widget)
+{
+ gtk_grab_remove (widget);
+ gdk_pointer_ungrab (0);
+}
+
+static void
+shape_motion (GtkWidget *widget,
+ GdkEventMotion *event)
+{
+ gint xp, yp;
+ CursorOffset * p;
+ GdkModifierType mask;
+
+ p = gtk_object_get_user_data (GTK_OBJECT (widget));
+
+ gdk_window_get_pointer (root_win, &xp, &yp, &mask);
+ gtk_widget_set_uposition (widget, xp - p->x, yp - p->y);
+}
+
+GtkWidget *
+shape_create_icon (char *xpm_file,
+ gint x,
+ gint y,
+ gint px,
+ gint py,
+ gint window_type)
+{
+ GtkWidget *window;
+ GtkWidget *pixmap;
+ GtkWidget *fixed;
+ CursorOffset* icon_pos;
+ GdkGC* gc;
+ GdkBitmap *gdk_pixmap_mask;
+ GdkPixmap *gdk_pixmap;
+ GtkStyle *style;
+
+ style = gtk_widget_get_default_style ();
+ gc = style->black_gc;
+
+ /*
+ * GDK_WINDOW_TOPLEVEL works also, giving you a title border
+ */
+ window = gtk_window_new (window_type);
+
+ fixed = gtk_fixed_new ();
+ gtk_widget_set_usize (fixed, 100,100);
+ gtk_container_add (GTK_CONTAINER (window), fixed);
+ gtk_widget_show (fixed);
+
+ gdk_pixmap = gdk_pixmap_create_from_xpm (window->window, &gdk_pixmap_mask,
+ &style->bg[GTK_STATE_NORMAL],
+ xpm_file);
+
+ pixmap = gtk_pixmap_new (gdk_pixmap, gdk_pixmap_mask);
+ gtk_fixed_put (GTK_FIXED (fixed), pixmap, px,py);
+ gtk_widget_show (pixmap);
+
+ gtk_widget_shape_combine_mask (window, gdk_pixmap_mask, px,py);
+
+ gtk_widget_set_events (window,
+ gtk_widget_get_events (window) |
+ GDK_BUTTON_MOTION_MASK |
+ GDK_BUTTON_PRESS_MASK);
+
+ gtk_signal_connect (GTK_OBJECT (window), "button_press_event",
+ GTK_SIGNAL_FUNC (shape_pressed),NULL);
+ gtk_signal_connect (GTK_OBJECT (window), "button_release_event",
+ GTK_SIGNAL_FUNC (shape_released),NULL);
+ gtk_signal_connect (GTK_OBJECT (window), "motion_notify_event",
+ GTK_SIGNAL_FUNC (shape_motion),NULL);
+
+ icon_pos = g_new (CursorOffset, 1);
+ gtk_object_set_user_data(GTK_OBJECT(window), icon_pos);
+
+ gtk_widget_set_uposition (window, x, y);
+ gtk_widget_show (window);
+
+ return window;
+}
+
+void
+create_shapes ()
+{
+ root_win = gdk_window_foreign_new (GDK_ROOT_WINDOW ());
+
+ if (!modeller)
+ {
+ modeller = shape_create_icon ("Modeller.xpm",
+ 440, 140, 0,0, GTK_WINDOW_POPUP);
+
+ gtk_signal_connect (GTK_OBJECT (modeller), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &modeller);
+ gtk_signal_connect (GTK_OBJECT (modeller), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &modeller);
+ }
+ else
+ gtk_widget_destroy (modeller);
+
+ if (!sheets)
+ {
+ sheets = shape_create_icon ("FilesQueue.xpm",
+ 580, 170, 0,0, GTK_WINDOW_POPUP);
+
+ gtk_signal_connect (GTK_OBJECT (sheets), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &sheets);
+ gtk_signal_connect (GTK_OBJECT (sheets), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &sheets);
+
+ }
+ else
+ gtk_widget_destroy (sheets);
+
+ if (!rings)
+ {
+ rings = shape_create_icon ("3DRings.xpm",
+ 460, 270, 25,25, GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (rings), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &rings);
+ gtk_signal_connect (GTK_OBJECT (rings), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &rings);
+ }
+ else
+ gtk_widget_destroy (rings);
+}
+
+
+/*
+ * Progress Bar
+ */
+static int progress_timer = 0;
+
+gint
+progress_timeout (gpointer data)
+{
+ gfloat new_val;
+
+ new_val = GTK_PROGRESS_BAR (data)->percentage;
+ if (new_val >= 1.0)
+ new_val = 0.0;
+ new_val += 0.02;
+
+ gtk_progress_bar_update (GTK_PROGRESS_BAR (data), new_val);
+
+ return TRUE;
+}
+
+void
+destroy_progress (GtkWidget *widget,
+ GtkWidget **window)
+{
+ destroy_window (widget, window);
+ gtk_timeout_remove (progress_timer);
+ progress_timer = 0;
+}
+
+void
+create_progress_bar ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *button;
+ GtkWidget *vbox;
+ GtkWidget *pbar;
+ GtkWidget *label;
+
+ if (!window)
+ {
+ window = gtk_dialog_new ();
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_progress,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_progress,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "dialog");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+
+ vbox = gtk_vbox_new (FALSE, 5);
+ gtk_container_border_width (GTK_CONTAINER (vbox), 10);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox),
+ vbox, TRUE, TRUE, 0);
+ gtk_widget_show (vbox);
+
+ label = gtk_label_new ("progress...");
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+ gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0);
+ gtk_widget_show (label);
+
+ pbar = gtk_progress_bar_new ();
+ gtk_widget_set_usize (pbar, 200, 20);
+ gtk_box_pack_start (GTK_BOX (vbox), pbar, TRUE, TRUE, 0);
+ gtk_widget_show (pbar);
+
+ progress_timer = gtk_timeout_add (100, progress_timeout, pbar);
+
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
+ button, TRUE, TRUE, 0);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+
+/*
+ * Color Preview
+ */
+static int color_idle = 0;
+
+gint
+color_idle_func (GtkWidget *preview)
+{
+ static int count = 1;
+ guchar buf[768];
+ int i, j, k;
+
+ for (i = 0; i < 256; i++)
+ {
+ for (j = 0, k = 0; j < 256; j++)
+ {
+ buf[k+0] = i + count;
+ buf[k+1] = 0;
+ buf[k+2] = j + count;
+ k += 3;
+ }
+
+ gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, i, 256);
+ }
+
+ count += 1;
+
+ gtk_widget_draw (preview, NULL);
+
+ return TRUE;
+}
+
+void
+color_preview_destroy (GtkWidget *widget,
+ GtkWidget **window)
+{
+ gtk_idle_remove (color_idle);
+ color_idle = 0;
+
+ destroy_window (widget, window);
+}
+
+void
+create_color_preview ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *preview;
+ guchar buf[768];
+ int i, j, k;
+
+ if (!window)
+ {
+ gtk_widget_push_visual (gtk_preview_get_visual ());
+ gtk_widget_push_colormap (gtk_preview_get_cmap ());
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) color_preview_destroy,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) color_preview_destroy,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "test");
+ gtk_container_border_width (GTK_CONTAINER (window), 10);
+
+ preview = gtk_preview_new (GTK_PREVIEW_COLOR);
+ gtk_preview_size (GTK_PREVIEW (preview), 256, 256);
+ gtk_container_add (GTK_CONTAINER (window), preview);
+ gtk_widget_show (preview);
+
+ for (i = 0; i < 256; i++)
+ {
+ for (j = 0, k = 0; j < 256; j++)
+ {
+ buf[k+0] = i;
+ buf[k+1] = 0;
+ buf[k+2] = j;
+ k += 3;
+ }
+
+ gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, i, 256);
+ }
+
+ color_idle = gtk_idle_add ((GtkFunction) color_idle_func, preview);
+
+ gtk_widget_pop_colormap ();
+ gtk_widget_pop_visual ();
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+
+/*
+ * Gray Preview
+ */
+static int gray_idle = 0;
+
+gint
+gray_idle_func (GtkWidget *preview)
+{
+ static int count = 1;
+ guchar buf[256];
+ int i, j;
+
+ for (i = 0; i < 256; i++)
+ {
+ for (j = 0; j < 256; j++)
+ buf[j] = i + j + count;
+
+ gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, i, 256);
+ }
+
+ count += 1;
+
+ gtk_widget_draw (preview, NULL);
+
+ return TRUE;
+}
+
+void
+gray_preview_destroy (GtkWidget *widget,
+ GtkWidget **window)
+{
+ gtk_idle_remove (gray_idle);
+ gray_idle = 0;
+
+ destroy_window (widget, window);
+}
+
+void
+create_gray_preview ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *preview;
+ guchar buf[256];
+ int i, j;
+
+ if (!window)
+ {
+ gtk_widget_push_visual (gtk_preview_get_visual ());
+ gtk_widget_push_colormap (gtk_preview_get_cmap ());
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) gray_preview_destroy,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) gray_preview_destroy,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "test");
+ gtk_container_border_width (GTK_CONTAINER (window), 10);
+
+ preview = gtk_preview_new (GTK_PREVIEW_GRAYSCALE);
+ gtk_preview_size (GTK_PREVIEW (preview), 256, 256);
+ gtk_container_add (GTK_CONTAINER (window), preview);
+ gtk_widget_show (preview);
+
+ for (i = 0; i < 256; i++)
+ {
+ for (j = 0; j < 256; j++)
+ buf[j] = i + j;
+
+ gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, i, 256);
+ }
+
+ gray_idle = gtk_idle_add ((GtkFunction) gray_idle_func, preview);
+
+ gtk_widget_pop_colormap ();
+ gtk_widget_pop_visual ();
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+
+/*
+ * Selection Test
+ */
+void
+selection_test_received (GtkWidget *list, GtkSelectionData *data)
+{
+ GdkAtom *atoms;
+ GtkWidget *list_item;
+ GList *item_list;
+ int i, l;
+
+ if (data->length < 0)
+ {
+ g_print ("Selection retrieval failed\n");
+ return;
+ }
+ if (data->type != GDK_SELECTION_TYPE_ATOM)
+ {
+ g_print ("Selection \"TARGETS\" was not returned as atoms!\n");
+ return;
+ }
+
+ /* Clear out any current list items */
+
+ gtk_list_clear_items (GTK_LIST(list), 0, -1);
+
+ /* Add new items to list */
+
+ atoms = (GdkAtom *)data->data;
+
+ item_list = NULL;
+ l = data->length / sizeof (GdkAtom);
+ for (i = 0; i < l; i++)
+ {
+ char *name;
+ name = gdk_atom_name (atoms[i]);
+ if (name != NULL)
+ {
+ list_item = gtk_list_item_new_with_label (name);
+ g_free (name);
+ }
+ else
+ list_item = gtk_list_item_new_with_label ("(bad atom)");
+
+ gtk_widget_show (list_item);
+ item_list = g_list_append (item_list, list_item);
+ }
+
+ gtk_list_append_items (GTK_LIST (list), item_list);
+
+ return;
+}
+
+void
+selection_test_get_targets (GtkWidget *widget, GtkWidget *list)
+{
+ static GdkAtom targets_atom = GDK_NONE;
+
+ if (targets_atom == GDK_NONE)
+ targets_atom = gdk_atom_intern ("TARGETS", FALSE);
+
+ gtk_selection_convert (list, GDK_SELECTION_PRIMARY, targets_atom,
+ GDK_CURRENT_TIME);
+}
+
+void
+create_selection_test ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *button;
+ GtkWidget *vbox;
+ GtkWidget *scrolled_win;
+ GtkWidget *list;
+ GtkWidget *label;
+
+ if (!window)
+ {
+ window = gtk_dialog_new ();
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "Selection Test");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+ /* Create the list */
+
+ vbox = gtk_vbox_new (FALSE, 5);
+ gtk_container_border_width (GTK_CONTAINER (vbox), 10);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox,
+ TRUE, TRUE, 0);
+ gtk_widget_show (vbox);
+
+ label = gtk_label_new ("Gets available targets for current selection");
+ gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
+ gtk_widget_show (label);
+
+ scrolled_win = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+ gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
+ gtk_widget_set_usize (scrolled_win, 100, 200);
+ gtk_widget_show (scrolled_win);
+
+ list = gtk_list_new ();
+ gtk_container_add (GTK_CONTAINER (scrolled_win), list);
+
+ gtk_signal_connect (GTK_OBJECT(list), "selection_received",
+ GTK_SIGNAL_FUNC (selection_test_received), NULL);
+ gtk_widget_show (list);
+
+ /* .. And create some buttons */
+ button = gtk_button_new_with_label ("Get Targets");
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
+ button, TRUE, TRUE, 0);
+
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ GTK_SIGNAL_FUNC (selection_test_get_targets), list);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("Quit");
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
+ button, TRUE, TRUE, 0);
+
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ GTK_SIGNAL_FUNC (gtk_widget_destroy),
+ GTK_OBJECT (window));
+ gtk_widget_show (button);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+
+/*
+ * Gamma Curve
+ */
+void
+create_gamma_curve ()
+{
+ static GtkWidget *window = NULL, *curve;
+ static int count = 0;
+ gfloat vec[256];
+ gint max;
+ gint i;
+
+ if (!window)
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title (GTK_WINDOW (window), "test");
+ gtk_container_border_width (GTK_CONTAINER (window), 10);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ curve = gtk_gamma_curve_new ();
+ gtk_container_add (GTK_CONTAINER (window), curve);
+ gtk_widget_show (curve);
+ }
+
+ max = 127 + (count % 2)*128;
+ gtk_curve_set_range (GTK_CURVE (GTK_GAMMA_CURVE (curve)->curve),
+ 0, max, 0, max);
+ for (i = 0; i < max; ++i)
+ vec[i] = (127 / sqrt (max)) * sqrt (i);
+ gtk_curve_set_vector (GTK_CURVE (GTK_GAMMA_CURVE (curve)->curve),
+ max, vec);
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else if (count % 4 == 3)
+ {
+ gtk_widget_destroy (window);
+ window = NULL;
+ }
+
+ ++count;
+}
+
+
+/*
+ * Timeout Test
+ */
+static int timer = 0;
+
+void
+timeout_test (GtkWidget *label)
+{
+ static int count = 0;
+ static char buffer[32];
+
+ sprintf (buffer, "count: %d", ++count);
+ gtk_label_set (GTK_LABEL (label), buffer);
+}
+
+void
+start_timeout_test (GtkWidget *widget,
+ GtkWidget *label)
+{
+ if (!timer)
+ {
+ timer = gtk_timeout_add (100, (GtkFunction) timeout_test, label);
+ }
+}
+
+void
+stop_timeout_test (GtkWidget *widget,
+ gpointer data)
+{
+ if (timer)
+ {
+ gtk_timeout_remove (timer);
+ timer = 0;
+ }
+}
+
+void
+destroy_timeout_test (GtkWidget *widget,
+ GtkWidget **window)
+{
+ destroy_window (widget, window);
+ stop_timeout_test (NULL, NULL);
+}
+
+void
+create_timeout_test ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *button;
+ GtkWidget *label;
+
+ if (!window)
+ {
+ window = gtk_dialog_new ();
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_timeout_test,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_timeout_test,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "Timeout Test");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+ label = gtk_label_new ("count: 0");
+ gtk_misc_set_padding (GTK_MISC (label), 10, 10);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox),
+ label, TRUE, TRUE, 0);
+ gtk_widget_show (label);
+
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
+ button, TRUE, TRUE, 0);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("start");
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) start_timeout_test,
+ label);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
+ button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("stop");
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) stop_timeout_test,
+ NULL);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
+ button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+
+/*
+ * Idle Test
+ */
+static int idle = 0;
+
+gint
+idle_test (GtkWidget *label)
+{
+ static int count = 0;
+ static char buffer[32];
+
+ sprintf (buffer, "count: %d", ++count);
+ gtk_label_set (GTK_LABEL (label), buffer);
+
+ return TRUE;
+}
+
+void
+start_idle_test (GtkWidget *widget,
+ GtkWidget *label)
+{
+ if (!idle)
+ {
+ idle = gtk_idle_add ((GtkFunction) idle_test, label);
+ }
+}
+
+void
+stop_idle_test (GtkWidget *widget,
+ gpointer data)
+{
+ if (idle)
+ {
+ gtk_idle_remove (idle);
+ idle = 0;
+ }
+}
+
+void
+destroy_idle_test (GtkWidget *widget,
+ GtkWidget **window)
+{
+ destroy_window (widget, window);
+ stop_idle_test (NULL, NULL);
+}
+
+void
+create_idle_test ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *button;
+ GtkWidget *label;
+
+ if (!window)
+ {
+ window = gtk_dialog_new ();
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_idle_test,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_idle_test,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "Idle Test");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+ label = gtk_label_new ("count: 0");
+ gtk_misc_set_padding (GTK_MISC (label), 10, 10);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox),
+ label, TRUE, TRUE, 0);
+ gtk_widget_show (label);
+
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
+ button, TRUE, TRUE, 0);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("start");
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) start_idle_test,
+ label);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
+ button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("stop");
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) stop_idle_test,
+ NULL);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
+ button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+void
+test_destroy (GtkWidget *widget,
+ GtkWidget **window)
+{
+ destroy_window (widget, window);
+ gtk_main_quit ();
+}
+
+/*
+ * Basic Test
+ */
+void
+create_test ()
+{
+ static GtkWidget *window = NULL;
+
+ if (!window)
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) test_destroy,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) test_destroy,
+ &window);
+
+
+ gtk_window_set_title (GTK_WINDOW (window), "test");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ {
+ gtk_widget_show (window);
+
+ g_print ("create_test: start\n");
+ gtk_main ();
+ g_print ("create_test: done\n");
+ }
+ else
+ gtk_widget_destroy (window);
+}
+
+
+/*
+ * Main Window and Exit
+ */
+void
+do_exit ()
+{
+ gtk_exit (0);
+}
+
+void
+create_main_window ()
+{
+ struct {
+ char *label;
+ void (*func) ();
+ } buttons[] =
+ {
+ { "buttons", create_buttons },
+ { "toggle buttons", create_toggle_buttons },
+ { "check buttons", create_check_buttons },
+ { "radio buttons", create_radio_buttons },
+ { "button box", create_button_box },
+ { "reparent", create_reparent },
+ { "pixmap", create_pixmap },
+ { "tooltips", create_tooltips },
+ { "menus", create_menus },
+ { "scrolled windows", create_scrolled_windows },
+ { "drawing areas", NULL },
+ { "entry", create_entry },
+ { "list", create_list },
+ { "color selection", create_color_selection },
+ { "file selection", create_file_selection },
+ { "dialog", create_dialog },
+ { "miscellaneous", NULL },
+ { "range controls", create_range_controls },
+ { "rulers", create_rulers },
+ { "text", create_text },
+ { "notebook", create_notebook },
+ { "panes", create_panes },
+ { "shapes", create_shapes },
+ { "dnd", create_dnd },
+ { "progress bar", create_progress_bar },
+ { "preview color", create_color_preview },
+ { "preview gray", create_gray_preview },
+ { "gamma curve", create_gamma_curve },
+ { "test selection", create_selection_test },
+ { "test timeout", create_timeout_test },
+ { "test idle", create_idle_test },
+ { "test", create_test },
+ };
+ int nbuttons = sizeof (buttons) / sizeof (buttons[0]);
+ GtkWidget *window;
+ GtkWidget *box1;
+ GtkWidget *box2;
+ GtkWidget *scrolled_window;
+ GtkWidget *button;
+ GtkWidget *separator;
+ int i;
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_widget_set_name (window, "main window");
+ gtk_widget_set_usize (window, 200, 400);
+ gtk_widget_set_uposition (window, 20, 20);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) gtk_exit,
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) gtk_exit,
+ NULL);
+
+ box1 = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), box1);
+ gtk_widget_show (box1);
+
+ scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+ gtk_container_border_width (GTK_CONTAINER (scrolled_window), 10);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+ gtk_box_pack_start (GTK_BOX (box1), scrolled_window, TRUE, TRUE, 0);
+ gtk_widget_show (scrolled_window);
+
+ box2 = gtk_vbox_new (FALSE, 0);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_container_add (GTK_CONTAINER (scrolled_window), box2);
+ gtk_widget_show (box2);
+
+ for (i = 0; i < nbuttons; i++)
+ {
+ button = gtk_button_new_with_label (buttons[i].label);
+ if (buttons[i].func)
+ gtk_signal_connect (GTK_OBJECT (button),
+ "clicked",
+ (GtkSignalFunc)
+ buttons[i].func, NULL);
+ else
+ gtk_widget_set_sensitive (button, FALSE);
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+ }
+
+ separator = gtk_hseparator_new ();
+ gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
+ gtk_widget_show (separator);
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
+ gtk_widget_show (box2);
+
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) do_exit, NULL);
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+
+ gtk_widget_show (window);
+}
+
+int
+main (int argc, char *argv[])
+{
+ gtk_set_locale ();
+
+ gtk_init (&argc, &argv);
+ gtk_rc_parse ("testgtkrc");
+
+ create_main_window ();
+
+ gtk_main ();
+
+ return 0;
+}
diff --git a/gtk/testgtkrc b/gtk/testgtkrc
new file mode 100644
index 000000000..e909e314b
--- /dev/null
+++ b/gtk/testgtkrc
@@ -0,0 +1,69 @@
+# pixmap_path "<dir 1>:<dir 2>:<dir 3>:..."
+#
+# style <name> [= <name>]
+# {
+# <option>
+# }
+#
+# widget <widget_set> style <style_name>
+# widget_class <widget_class_set> style <style_name>
+
+pixmap_path "."
+
+style "window"
+{
+# bg_pixmap[NORMAL] = "warning.xpm"
+}
+
+style "scale"
+{
+ fg[NORMAL] = { 1.0, 0, 0 }
+ bg_pixmap[NORMAL] = "<parent>"
+}
+
+style "button"
+{
+ fg[PRELIGHT] = { 1.0, 1.0, 1.0 }
+ bg[PRELIGHT] = { 0, 0, 0.75 }
+}
+
+style "main_button" = "button"
+{
+ font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*"
+ bg[PRELIGHT] = { 0.75, 0, 0 }
+}
+
+style "toggle_button" = "button"
+{
+ fg[NORMAL] = { 1.0, 0, 0 }
+ fg[ACTIVE] = { 1.0, 0, 0 }
+ bg_pixmap[NORMAL] = "<parent>"
+}
+
+style "text"
+{
+ bg_pixmap[NORMAL] = "marble.xpm"
+ fg[NORMAL] = { 1.0, 1.0, 1.0 }
+}
+
+style "ruler"
+{
+ font = "-adobe-helvetica-medium-r-normal--*-80-*-*-*-*-*-*"
+}
+
+style "curve"
+{
+ fg[NORMAL] = { 58000, 0, 0 } # red
+}
+
+widget_class "GtkWindow" style "window"
+widget_class "GtkDialog" style "window"
+widget_class "GtkFileSelection" style "window"
+widget_class "*Gtk*Scale" style "scale"
+widget_class "*GtkCheckButton*" style "toggle_button"
+widget_class "*GtkRadioButton*" style "toggle_button"
+widget_class "*GtkButton*" style "button"
+widget_class "*Ruler" style "ruler"
+widget_class "*GtkText" style "text"
+widget "main window.*GtkButton*" style "main_button"
+widget "*GtkCurve" style "curve"
diff --git a/gtk/testinput.c b/gtk/testinput.c
new file mode 100644
index 000000000..1c6dae0e1
--- /dev/null
+++ b/gtk/testinput.c
@@ -0,0 +1,379 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "gtk.h"
+
+/* Backing pixmap for drawing area */
+
+static GdkPixmap *pixmap = NULL;
+
+/* Information about cursor */
+
+static gint need_cursor = FALSE;
+static gint cursor_proximity = TRUE;
+static gdouble cursor_x;
+static gdouble cursor_y;
+
+/* Unique ID of current device */
+static guint32 current_device = GDK_CORE_POINTER;
+
+/* Check to see if we need to draw a cursor for current device */
+static void
+check_cursor ()
+{
+ GList *tmp_list;
+
+ /* gdk_input_list_devices returns an internal list, so we shouldn't
+ free it afterwards */
+ tmp_list = gdk_input_list_devices();
+
+ while (tmp_list)
+ {
+ GdkDeviceInfo *info = (GdkDeviceInfo *)tmp_list->data;
+
+ if (info->deviceid == current_device)
+ {
+ need_cursor = !info->has_cursor;
+ break;
+ }
+
+ tmp_list = tmp_list->next;
+ }
+}
+
+/* Erase the old cursor, and/or draw a new one, if necessary */
+static void
+update_cursor (GtkWidget *widget, gdouble x, gdouble y)
+{
+ static gint cursor_present = 0;
+ gint state = need_cursor && cursor_proximity;
+
+ if (pixmap != NULL)
+ {
+ if (cursor_present && (cursor_present != state ||
+ x != cursor_x || y != cursor_y))
+ {
+ gdk_draw_pixmap(widget->window,
+ widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ pixmap,
+ cursor_x - 5, cursor_y - 5,
+ cursor_x - 5, cursor_y - 5,
+ 10, 10);
+ }
+
+ cursor_present = state;
+ cursor_x = x;
+ cursor_y = y;
+
+ if (cursor_present)
+ {
+ gdk_draw_rectangle (widget->window,
+ widget->style->black_gc,
+ TRUE,
+ cursor_x - 5, cursor_y -5,
+ 10, 10);
+ }
+ }
+}
+
+/* Create a new backing pixmap of the appropriate size */
+static gint
+configure_event (GtkWidget *widget, GdkEventConfigure *event)
+{
+ if (pixmap)
+ {
+ gdk_pixmap_destroy(pixmap);
+ }
+ pixmap = gdk_pixmap_new(widget->window,
+ widget->allocation.width,
+ widget->allocation.height,
+ -1);
+ gdk_draw_rectangle (pixmap,
+ widget->style->white_gc,
+ TRUE,
+ 0, 0,
+ widget->allocation.width,
+ widget->allocation.height);
+
+ return TRUE;
+}
+
+/* Refill the screen from the backing pixmap */
+static gint
+expose_event (GtkWidget *widget, GdkEventExpose *event)
+{
+ gdk_draw_pixmap(widget->window,
+ widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ pixmap,
+ event->area.x, event->area.y,
+ event->area.x, event->area.y,
+ event->area.width, event->area.height);
+
+ return FALSE;
+}
+
+/* Draw a rectangle on the screen, size depending on pressure,
+ and color on the type of device */
+static void
+draw_brush (GtkWidget *widget, GdkInputSource source,
+ gdouble x, gdouble y, gdouble pressure)
+{
+ GdkGC *gc;
+ GdkRectangle update_rect;
+
+ switch (source)
+ {
+ case GDK_SOURCE_MOUSE:
+ gc = widget->style->dark_gc[GTK_WIDGET_STATE (widget)];
+ break;
+ case GDK_SOURCE_PEN:
+ gc = widget->style->black_gc;
+ break;
+ case GDK_SOURCE_ERASER:
+ gc = widget->style->white_gc;
+ break;
+ default:
+ gc = widget->style->light_gc[GTK_WIDGET_STATE (widget)];
+ }
+
+ update_rect.x = x - 10 * pressure;
+ update_rect.y = y - 10 * pressure;
+ update_rect.width = 20 * pressure;
+ update_rect.height = 20 * pressure;
+ gdk_draw_rectangle (pixmap, gc, TRUE,
+ update_rect.x, update_rect.y,
+ update_rect.width, update_rect.height);
+ gtk_widget_draw (widget, &update_rect);
+}
+
+static guint32 motion_time;
+
+static gint
+button_press_event (GtkWidget *widget, GdkEventButton *event)
+{
+ if (event->deviceid != current_device)
+ {
+ current_device = event->deviceid;
+ check_cursor ();
+ }
+
+ cursor_proximity = TRUE;
+
+ if (event->button == 1 && pixmap != NULL)
+ {
+ draw_brush (widget, event->source, event->x, event->y,
+ event->pressure);
+ motion_time = event->time;
+ }
+
+ update_cursor (widget, event->x, event->y);
+
+ return TRUE;
+}
+
+static gint
+motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
+{
+ GdkTimeCoord *coords;
+ int nevents;
+ int i;
+
+ if (event->deviceid != current_device)
+ {
+ current_device = event->deviceid;
+ check_cursor ();
+ }
+
+ cursor_proximity = TRUE;
+
+ if (event->state & GDK_BUTTON1_MASK && pixmap != NULL)
+ {
+ coords = gdk_input_motion_events (event->window, event->deviceid,
+ motion_time, event->time,
+ &nevents);
+ motion_time = event->time;
+ if (coords)
+ {
+ for (i=0; i<nevents; i++)
+ draw_brush (widget, event->source, coords[i].x, coords[i].y,
+ coords[i].pressure);
+ g_free (coords);
+ }
+ else
+ {
+ if (event->is_hint)
+ gdk_input_window_get_pointer (event->window, event->deviceid,
+ NULL, NULL, NULL, NULL, NULL, NULL);
+ draw_brush (widget, event->source, event->x, event->y,
+ event->pressure);
+ }
+ }
+ else
+ {
+ gdk_input_window_get_pointer (event->window, event->deviceid,
+ &event->x, &event->y,
+ NULL, NULL, NULL, NULL);
+ }
+
+ update_cursor (widget, event->x, event->y);
+
+ return TRUE;
+}
+
+/* We track the next two events to know when we need to draw a
+ cursor */
+
+static gint
+proximity_out_event (GtkWidget *widget, GdkEventProximity *event)
+{
+ cursor_proximity = FALSE;
+ update_cursor (widget, cursor_x, cursor_y);
+ return TRUE;
+}
+
+static gint
+leave_notify_event (GtkWidget *widget, GdkEventCrossing *event)
+{
+ cursor_proximity = FALSE;
+ update_cursor (widget, cursor_x, cursor_y);
+ return TRUE;
+}
+
+void
+input_dialog_destroy (GtkWidget *w, gpointer data)
+{
+ *((GtkWidget **)data) = NULL;
+}
+
+void
+create_input_dialog ()
+{
+ static GtkWidget *inputd = NULL;
+
+ if (!inputd)
+ {
+ inputd = gtk_input_dialog_new();
+
+ gtk_signal_connect (GTK_OBJECT(inputd), "destroy",
+ (GtkSignalFunc)input_dialog_destroy, &inputd);
+ gtk_signal_connect_object (GTK_OBJECT(GTK_INPUT_DIALOG(inputd)->close_button),
+ "clicked",
+ (GtkSignalFunc)gtk_widget_hide,
+ GTK_OBJECT(inputd));
+ gtk_widget_hide ( GTK_INPUT_DIALOG(inputd)->save_button);
+
+ gtk_signal_connect (GTK_OBJECT(inputd), "enable_device",
+ (GtkSignalFunc)check_cursor, NULL);
+ gtk_widget_show (inputd);
+ }
+ else
+ {
+ if (!GTK_WIDGET_MAPPED(inputd))
+ gtk_widget_show(inputd);
+ else
+ gdk_window_raise(inputd->window);
+ }
+}
+
+void
+quit ()
+{
+ gtk_exit (0);
+}
+
+int
+main (int argc, char *argv[])
+{
+ GtkWidget *window;
+ GtkWidget *drawing_area;
+ GtkWidget *vbox;
+
+ GtkWidget *button;
+
+ gtk_init (&argc, &argv);
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_widget_set_name (window, "Test Input");
+
+ vbox = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), vbox);
+ gtk_widget_show (vbox);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ GTK_SIGNAL_FUNC (quit), NULL);
+
+ /* Create the drawing area */
+
+ drawing_area = gtk_drawing_area_new ();
+ gtk_drawing_area_size (GTK_DRAWING_AREA (drawing_area), 200, 200);
+ gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
+
+ gtk_widget_show (drawing_area);
+
+ /* Signals used to handle backing pixmap */
+
+ gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
+ (GtkSignalFunc) expose_event, NULL);
+ gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
+ (GtkSignalFunc) configure_event, NULL);
+
+ /* Event signals */
+
+ gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
+ (GtkSignalFunc) motion_notify_event, NULL);
+ gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
+ (GtkSignalFunc) button_press_event, NULL);
+
+ gtk_signal_connect (GTK_OBJECT (drawing_area), "leave_notify_event",
+ (GtkSignalFunc) leave_notify_event, NULL);
+ gtk_signal_connect (GTK_OBJECT (drawing_area), "proximity_out_event",
+ (GtkSignalFunc) proximity_out_event, NULL);
+
+ gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
+ | GDK_LEAVE_NOTIFY_MASK
+ | GDK_BUTTON_PRESS_MASK
+ | GDK_POINTER_MOTION_MASK
+ | GDK_POINTER_MOTION_HINT_MASK
+ | GDK_PROXIMITY_OUT_MASK);
+
+ /* The following call enables tracking and processing of extension
+ events for the drawing area */
+ gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_ALL);
+
+ /* .. And create some buttons */
+ button = gtk_button_new_with_label ("Input Dialog");
+ gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ GTK_SIGNAL_FUNC (create_input_dialog), NULL);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("Quit");
+ gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ GTK_SIGNAL_FUNC (gtk_widget_destroy),
+ GTK_OBJECT (window));
+ gtk_widget_show (button);
+
+ gtk_widget_show (window);
+
+ gtk_main ();
+
+ return 0;
+}
diff --git a/gtk/testselection.c b/gtk/testselection.c
new file mode 100644
index 000000000..3377cc623
--- /dev/null
+++ b/gtk/testselection.c
@@ -0,0 +1,466 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "gtk.h"
+
+typedef enum {
+ SEL_TYPE_NONE,
+ APPLE_PICT,
+ ATOM,
+ ATOM_PAIR,
+ BITMAP,
+ C_STRING,
+ COLORMAP,
+ COMPOUND_TEXT,
+ DRAWABLE,
+ INTEGER,
+ PIXEL,
+ PIXMAP,
+ SPAN,
+ STRING,
+ TEXT,
+ WINDOW,
+ LAST_SEL_TYPE,
+} SelType;
+
+GdkAtom seltypes[LAST_SEL_TYPE];
+
+typedef struct _Target {
+ gchar *target_name;
+ SelType type;
+ GdkAtom target;
+ gint format;
+ GtkSelectionFunction *handler;
+} Target;
+
+/* The following is a list of all the selection targets defined
+ in the ICCCM */
+
+static Target targets[] = {
+ { "ADOBE_PORTABLE_DOCUMENT_FORMAT", STRING, 0, 8, NULL },
+ { "APPLE_PICT", APPLE_PICT, 0, 8, NULL },
+ { "BACKGROUND", PIXEL, 0, 32, NULL },
+ { "BITMAP", BITMAP, 0, 32, NULL },
+ { "CHARACTER_POSITION", SPAN, 0, 32, NULL },
+ { "CLASS", TEXT, 0, 8, NULL },
+ { "CLIENT_WINDOW", WINDOW, 0, 32, NULL },
+ { "COLORMAP", COLORMAP, 0, 32, NULL },
+ { "COLUMN_NUMBER", SPAN, 0, 32, NULL },
+ { "COMPOUND_TEXT", COMPOUND_TEXT, 0, 8, NULL },
+ /* { "DELETE", "NULL", 0, ?, NULL }, */
+ { "DRAWABLE", DRAWABLE, 0, 32, NULL },
+ { "ENCAPSULATED_POSTSCRIPT", STRING, 0, 8, NULL },
+ { "ENCAPSULATED_POSTSCRIPT_INTERCHANGE", STRING, 0, 8, NULL },
+ { "FILE_NAME", TEXT, 0, 8, NULL },
+ { "FOREGROUND", PIXEL, 0, 32, NULL },
+ { "HOST_NAME", TEXT, 0, 8, NULL },
+ /* { "INSERT_PROPERTY", "NULL", 0, ? NULL }, */
+ /* { "INSERT_SELECTION", "NULL", 0, ? NULL }, */
+ { "LENGTH", INTEGER, 0, 32, NULL },
+ { "LINE_NUMBER", SPAN, 0, 32, NULL },
+ { "LIST_LENGTH", INTEGER, 0, 32, NULL },
+ { "MODULE", TEXT, 0, 8, NULL },
+ /* { "MULTIPLE", "ATOM_PAIR", 0, 32, NULL }, */
+ { "NAME", TEXT, 0, 8, NULL },
+ { "ODIF", TEXT, 0, 8, NULL },
+ { "OWNER_OS", TEXT, 0, 8, NULL },
+ { "PIXMAP", PIXMAP, 0, 32, NULL },
+ { "POSTSCRIPT", STRING, 0, 8, NULL },
+ { "PROCEDURE", TEXT, 0, 8, NULL },
+ { "PROCESS", INTEGER, 0, 32, NULL },
+ { "STRING", STRING, 0, 8, NULL },
+ { "TARGETS", ATOM, 0, 32, NULL },
+ { "TASK", INTEGER, 0, 32, NULL },
+ { "TEXT", TEXT, 0, 8 , NULL },
+ { "TIMESTAMP", INTEGER, 0, 32, NULL },
+ { "USER", TEXT, 0, 8, NULL },
+};
+
+static int num_targets = sizeof(targets)/sizeof(Target);
+
+static int have_selection = FALSE;
+
+GtkWidget *selection_text;
+GtkWidget *selection_button;
+GString *selection_string = NULL;
+
+static void
+init_atoms ()
+{
+ int i;
+
+ seltypes[SEL_TYPE_NONE] = GDK_NONE;
+ seltypes[APPLE_PICT] = gdk_atom_intern ("APPLE_PICT",FALSE);
+ seltypes[ATOM] = gdk_atom_intern ("ATOM",FALSE);
+ seltypes[ATOM_PAIR] = gdk_atom_intern ("ATOM_PAIR",FALSE);
+ seltypes[BITMAP] = gdk_atom_intern ("BITMAP",FALSE);
+ seltypes[C_STRING] = gdk_atom_intern ("C_STRING",FALSE);
+ seltypes[COLORMAP] = gdk_atom_intern ("COLORMAP",FALSE);
+ seltypes[COMPOUND_TEXT] = gdk_atom_intern ("COMPOUND_TEXT",FALSE);
+ seltypes[DRAWABLE] = gdk_atom_intern ("DRAWABLE",FALSE);
+ seltypes[INTEGER] = gdk_atom_intern ("INTEGER",FALSE);
+ seltypes[PIXEL] = gdk_atom_intern ("PIXEL",FALSE);
+ seltypes[PIXMAP] = gdk_atom_intern ("PIXMAP",FALSE);
+ seltypes[SPAN] = gdk_atom_intern ("SPAN",FALSE);
+ seltypes[STRING] = gdk_atom_intern ("STRING",FALSE);
+ seltypes[TEXT] = gdk_atom_intern ("TEXT",FALSE);
+ seltypes[WINDOW] = gdk_atom_intern ("WINDOW",FALSE);
+
+ for (i=0; i<num_targets; i++)
+ targets[i].target = gdk_atom_intern (targets[i].target_name, FALSE);
+}
+
+void
+selection_toggled (GtkWidget *widget)
+{
+ if (GTK_TOGGLE_BUTTON(widget)->active)
+ {
+ have_selection = gtk_selection_owner_set (widget,
+ GDK_SELECTION_PRIMARY,
+ GDK_CURRENT_TIME);
+ if (!have_selection)
+ gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON(widget), FALSE);
+ }
+ else
+ {
+ if (have_selection)
+ {
+ if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window)
+ gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY,
+ GDK_CURRENT_TIME);
+ have_selection = FALSE;
+ }
+ }
+}
+
+void
+selection_handle (GtkWidget *widget,
+ GtkSelectionData *selection_data, gpointer data)
+{
+ guchar *buffer;
+ gint len;
+
+ if (!selection_string)
+ {
+ buffer = NULL;
+ len = 0;
+ }
+ else
+ {
+ buffer = selection_string->str;
+ len = selection_string->len;
+ }
+
+ gtk_selection_data_set (selection_data,
+ selection_data->target == seltypes[COMPOUND_TEXT] ?
+ seltypes[COMPOUND_TEXT] : seltypes[STRING],
+ 8, buffer, len);
+}
+
+gint
+selection_clear (GtkWidget *widget, GdkEventSelection *event)
+{
+ have_selection = FALSE;
+ gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON(widget), FALSE);
+
+ return TRUE;
+}
+
+gchar *
+stringify_atom (guchar *data, gint *position)
+{
+ gchar *str = gdk_atom_name (*(GdkAtom *)(data+*position));
+ *position += sizeof(GdkAtom);
+
+ return str;
+}
+
+gchar *
+stringify_text (guchar *data, gint *position)
+{
+ gchar *str = g_strdup ((gchar *)(data+*position));
+ *position += strlen (str) + 1;
+
+ return str;
+}
+
+gchar *
+stringify_xid (guchar *data, gint *position)
+{
+ gchar buffer[20];
+ gchar *str;
+
+ sprintf(buffer,"0x%x",*(guint32 *)(data+*position));
+ str = g_strdup (buffer);
+
+ *position += sizeof(guint32);
+
+ return str;
+}
+
+gchar *
+stringify_integer (guchar *data, gint *position)
+{
+ gchar buffer[20];
+ gchar *str;
+
+ sprintf(buffer,"%d",*(int *)(data+*position));
+ str = g_strdup (buffer);
+
+ *position += sizeof(int);
+
+ return str;
+}
+
+gchar *
+stringify_span (guchar *data, gint *position)
+{
+ gchar buffer[42];
+ gchar *str;
+
+ sprintf(buffer,"%d - %d",((int *)(data+*position))[0],
+ ((int *)(data+*position))[1]);
+ str = g_strdup (buffer);
+
+ *position += 2*sizeof(int);
+
+ return str;
+}
+
+void
+selection_received (GtkWidget *widget, GtkSelectionData *data)
+{
+ int position;
+ int i;
+ SelType seltype;
+ char *str;
+
+ if (data->length < 0)
+ {
+ g_print("Error retrieving selection\n");
+ return;
+ }
+
+ seltype = SEL_TYPE_NONE;
+ for (i=0; i<LAST_SEL_TYPE; i++)
+ {
+ if (seltypes[i] == data->type)
+ {
+ seltype = i;
+ break;
+ }
+ }
+
+ if (seltype == SEL_TYPE_NONE)
+ {
+ char *name = gdk_atom_name (data->type);
+ g_print("Don't know how to handle type: %s (%ld)\n",
+ name?name:"<unknown>",
+ data->type);
+ return;
+ }
+
+ if (selection_string != NULL)
+ g_string_free (selection_string, TRUE);
+
+ selection_string = g_string_new (NULL);
+
+ gtk_text_freeze (GTK_TEXT (selection_text));
+ gtk_text_set_point (GTK_TEXT (selection_text), 0);
+ gtk_text_foreward_delete (GTK_TEXT (selection_text),
+ gtk_text_get_length (GTK_TEXT (selection_text)));
+
+ position = 0;
+ while (position < data->length)
+ {
+ switch (seltype)
+ {
+ case ATOM:
+ str = stringify_atom (data->data, &position);
+ break;
+ case COMPOUND_TEXT:
+ case STRING:
+ case TEXT:
+ str = stringify_text (data->data, &position);
+ break;
+ case BITMAP:
+ case DRAWABLE:
+ case PIXMAP:
+ case WINDOW:
+ case COLORMAP:
+ str = stringify_xid (data->data, &position);
+ break;
+ case INTEGER:
+ case PIXEL:
+ str = stringify_integer (data->data, &position);
+ break;
+ case SPAN:
+ str = stringify_span (data->data, &position);
+ break;
+ default:
+ {
+ char *name = gdk_atom_name (data->type);
+ g_print("Can't convert type %s (%ld) to string\n",
+ name?name:"<unknown>",
+ data->type);
+ position = data->length;
+ }
+ }
+ gtk_text_insert (GTK_TEXT (selection_text), NULL,
+ &selection_text->style->black,
+ NULL, str, -1);
+ gtk_text_insert (GTK_TEXT (selection_text), NULL,
+ &selection_text->style->black,
+ NULL, "\n", -1);
+ g_string_append (selection_string, str);
+ g_free (str);
+ }
+ gtk_text_thaw (GTK_TEXT (selection_text));
+}
+
+void
+paste (GtkWidget *widget, GtkWidget *entry)
+{
+ char *name;
+ GdkAtom atom;
+
+ name = gtk_entry_get_text (GTK_ENTRY(entry));
+ atom = gdk_atom_intern (name, FALSE);
+
+ if (atom == GDK_NONE)
+ {
+ g_print("Could not create atom: \"%s\"\n",name);
+ return;
+ }
+
+ gtk_selection_convert (selection_button, GDK_SELECTION_PRIMARY, atom,
+ GDK_CURRENT_TIME);
+}
+
+void
+quit ()
+{
+ gtk_exit (0);
+}
+
+int
+main (int argc, char *argv[])
+{
+ GtkWidget *dialog;
+ GtkWidget *button;
+ GtkWidget *table;
+ GtkWidget *label;
+ GtkWidget *entry;
+ GtkWidget *hscrollbar;
+ GtkWidget *vscrollbar;
+ GtkWidget *hbox;
+
+ gtk_init (&argc, &argv);
+
+ init_atoms();
+
+ dialog = gtk_dialog_new ();
+ gtk_widget_set_name (dialog, "Test Input");
+ gtk_container_border_width (GTK_CONTAINER(dialog), 0);
+
+ gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
+ GTK_SIGNAL_FUNC (quit), NULL);
+
+ table = gtk_table_new (4, 2, FALSE);
+ gtk_container_border_width (GTK_CONTAINER(table), 10);
+
+ gtk_table_set_row_spacing (GTK_TABLE (table), 0, 5);
+ gtk_table_set_row_spacing (GTK_TABLE (table), 1, 2);
+ gtk_table_set_row_spacing (GTK_TABLE (table), 2, 2);
+ gtk_table_set_col_spacing (GTK_TABLE (table), 0, 2);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG(dialog)->vbox),
+ table, TRUE, TRUE, 0);
+ gtk_widget_show (table);
+
+ selection_button = gtk_toggle_button_new_with_label ("Claim Selection");
+ gtk_table_attach (GTK_TABLE (table), selection_button, 0, 2, 0, 1,
+ GTK_EXPAND | GTK_FILL, 0, 0, 0);
+ gtk_widget_show (selection_button);
+
+ gtk_signal_connect (GTK_OBJECT(selection_button), "toggled",
+ GTK_SIGNAL_FUNC (selection_toggled), NULL);
+ gtk_signal_connect (GTK_OBJECT(selection_button), "selection_clear_event",
+ GTK_SIGNAL_FUNC (selection_clear), NULL);
+ gtk_signal_connect (GTK_OBJECT(selection_button), "selection_received",
+ GTK_SIGNAL_FUNC (selection_received), NULL);
+
+ gtk_selection_add_handler (selection_button, GDK_SELECTION_PRIMARY,
+ seltypes[STRING], selection_handle, NULL, NULL);
+
+ gtk_selection_add_handler (selection_button, GDK_SELECTION_PRIMARY,
+ seltypes[TEXT], selection_handle, NULL, NULL);
+
+ gtk_selection_add_handler (selection_button, GDK_SELECTION_PRIMARY,
+ seltypes[COMPOUND_TEXT],
+ selection_handle, NULL, NULL);
+
+ selection_text = gtk_text_new (NULL, NULL);
+ gtk_table_attach_defaults (GTK_TABLE (table), selection_text, 0, 1, 1, 2);
+ gtk_widget_show (selection_text);
+
+ hscrollbar = gtk_hscrollbar_new (GTK_TEXT (selection_text)->hadj);
+ gtk_table_attach (GTK_TABLE (table), hscrollbar, 0, 1, 2, 3,
+ GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
+ gtk_widget_show (hscrollbar);
+
+ vscrollbar = gtk_vscrollbar_new (GTK_TEXT (selection_text)->vadj);
+ gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 1, 2,
+ GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+ gtk_widget_show (vscrollbar);
+
+ hbox = gtk_hbox_new (FALSE, 2);
+ gtk_table_attach (GTK_TABLE (table), hbox, 0, 2, 3, 4,
+ GTK_EXPAND | GTK_FILL, 0, 0, 0);
+ gtk_widget_show (hbox);
+
+ label = gtk_label_new ("Target:");
+ gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, FALSE, 0);
+ gtk_widget_show (label);
+
+ entry = gtk_entry_new ();
+ gtk_box_pack_start (GTK_BOX(hbox), entry, TRUE, TRUE, 0);
+ gtk_widget_show (entry);
+
+ /* .. And create some buttons */
+ button = gtk_button_new_with_label ("Paste");
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG(dialog)->action_area),
+ button, TRUE, TRUE, 0);
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ GTK_SIGNAL_FUNC (paste), entry);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("Quit");
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG(dialog)->action_area),
+ button, TRUE, TRUE, 0);
+
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ GTK_SIGNAL_FUNC (gtk_widget_destroy),
+ GTK_OBJECT (dialog));
+ gtk_widget_show (button);
+
+ gtk_widget_show (dialog);
+
+ gtk_main ();
+
+ return 0;
+}
diff --git a/install-sh b/install-sh
new file mode 100755
index 000000000..89fc9b098
--- /dev/null
+++ b/install-sh
@@ -0,0 +1,238 @@
+#! /bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+#
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+tranformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ true
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ else
+ instcmd=mkdir
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ true
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ true
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ true
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ true
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ true
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
diff --git a/ltconfig b/ltconfig
new file mode 100755
index 000000000..e9d3a8379
--- /dev/null
+++ b/ltconfig
@@ -0,0 +1,1415 @@
+#! /bin/sh
+
+# ltconfig - Create a system-specific libtool.
+# Generated automatically from ltconfig.in by configure.
+# Copyright (C) 1996, 1997, Free Software Foundation, Inc.
+# Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# A lot of this script is taken from autoconf-2.10.
+
+# The name of this program.
+progname=`echo "$0" | sed 's%^.*/%%'`
+
+# Constants:
+PROGRAM=ltconfig
+PACKAGE=libtool
+VERSION=1.0f
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.c 1>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.c $LIBS 1>&5'
+rm="rm -f"
+
+help="Try \`$progname --help' for more information."
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+sed_quote_subst='s/\([\\"$\\\\]\)/\\\1/g'
+
+# Same as above, but don't quote variable references.
+double_quote_subst='s/\([\\"\\\\]\)/\\\1/g'
+
+# Global variables:
+can_build_shared=yes
+enable_shared=yes
+# All known linkers require a `.a' archive for static linking.
+enable_static=yes
+ltmain=
+silent=
+srcdir=
+ac_config_guess=
+ac_config_sub=
+host=
+nonopt=
+verify_host=yes
+with_gcc=no
+with_gnu_ld=no
+
+old_AR="$AR"
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+old_CPPFLAGS="$CPPFLAGS"
+old_LD="$LD"
+old_LN_S="$LN_S"
+old_NM="$NM"
+old_RANLIB="$RANLIB"
+
+# Parse the command line options.
+args=
+prev=
+for option
+do
+ case "$option" in
+ -*=*) optarg=`echo "$option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) optarg= ;;
+ esac
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$prev"; then
+ eval "$prev=\$option"
+ prev=
+ continue
+ fi
+
+ case "$option" in
+ --help) cat <<EOM
+Usage: $progname [OPTION]... LTMAIN [HOST]
+
+Generate a system-specific libtool script.
+
+ --disable-shared do not build shared libraries
+ --disable-static do not build static libraries
+ --help display this help and exit
+ --no-verify do not verify that HOST is a valid host type
+ --quiet same as \`--silent'
+ --silent don't print informational messages
+ --srcdir=DIR find \`config.guess' in DIR
+ --version output version information and exit
+ --with-gcc assume that the GNU C compiler will be used
+ --with-gnu-ld assume that the C compiler uses the GNU linker
+
+LTMAIN is the \`ltmain.sh' shell script fragment that provides basic libtool
+functionality.
+
+HOST is the canonical host system name [default=guessed].
+EOM
+ exit 0
+ ;;
+
+ --disable-shared) enable_shared=no ;;
+
+ --disable-static) enable_static=no ;;
+
+ --quiet | --silent) silent=yes ;;
+
+ --srcdir) prev=srcdir ;;
+ --srcdir=*) srcdir="$optarg" ;;
+
+ --no-verify) verify_host=no ;;
+
+ --version) echo "$PROGRAM (GNU $PACKAGE) $VERSION"; exit 0 ;;
+
+ --with-gcc) with_gcc=yes ;;
+ --with-gnu-ld) with_gnu_ld=yes ;;
+
+ -*)
+ echo "$progname: unrecognized option \`$option'" 1>&2
+ echo "$help" 1>&2
+ exit 1
+ ;;
+
+ *)
+ if test -z "$ltmain"; then
+ ltmain="$option"
+ elif test -z "$host"; then
+# FIXME This generates an unnecessary warning for sparc-sun-solaris4.1.3_U1
+# if test -n "`echo $option| sed 's/[-a-z0-9.]//g'`"; then
+# echo "$progname: warning \`$option' is not a valid host type" 1>&2
+# fi
+ host="$option"
+ else
+ echo "$progname: too many arguments" 1>&2
+ echo "$help" 1>&2
+ exit 1
+ fi ;;
+ esac
+done
+
+if test -z "$ltmain"; then
+ echo "$progname: you must specify a LTMAIN file" 1>&2
+ echo "$help" 1>&2
+ exit 1
+fi
+
+if test -f "$ltmain"; then :
+else
+ echo "$progname: warning: \`$ltmain' does not exist" 1>&2
+fi
+
+# Quote any args containing shell metacharacters.
+ltconfig_args=
+for arg
+do
+ case "$arg" in
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ltconfig_args="$ltconfig_args '$arg'" ;;
+ *) ltconfig_args="$ltconfig_args $arg" ;;
+ esac
+done
+
+# A relevant subset of AC_INIT.
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 5 compiler messages saved in config.log
+# 6 checking for... messages and results
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>>./config.log
+
+# NLS nuisances.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+if test -z "$srcdir"; then
+ # Assume the source directory is the same one as the path to ltmain.sh.
+ srcdir=`echo "$ltmain" | sed 's%/[^/]*$%%'`
+ test "$srcdir" = "$ltmain" && srcdir=.
+fi
+
+trap "$rm conftest*; exit 1" 1 2 15
+if test "$verify_host" = yes; then
+ # Check for config.guess and config.sub.
+ ac_aux_dir=
+ for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+ if test -f $ac_dir/config.guess; then
+ ac_aux_dir=$ac_dir
+ break
+ fi
+ done
+ if test -z "$ac_aux_dir"; then
+ echo "$progname: cannot find config.guess in $srcdir $srcdir/.. $srcdir/../.." 1>&2
+ echo "$help" 1>&2
+ exit 1
+ fi
+ ac_config_guess=$ac_aux_dir/config.guess
+ ac_config_sub=$ac_aux_dir/config.sub
+
+ # Make sure we can run config.sub.
+ if $ac_config_sub sun4 >/dev/null 2>&1; then :
+ else
+ echo "$progname: cannot run $ac_config_sub" 1>&2
+ echo "$help" 1>&2
+ exit 1
+ fi
+
+ echo $ac_n "checking host system type""... $ac_c" 1>&6
+
+ host_alias=$host
+ case "$host_alias" in
+ "")
+ if host_alias=`$ac_config_guess`; then :
+ else
+ echo "$progname: cannot guess host type; you must specify one" 1>&2
+ echo "$help" 1>&2
+ exit 1
+ fi ;;
+ esac
+ host=`$ac_config_sub $host_alias`
+ echo "$ac_t$host" 1>&6
+
+ # Make sure the host verified.
+ test -z "$host" && exit 1
+
+elif test -z "$host"; then
+ echo "$progname: you must specify a host type if you use \`--no-verify'" 1>&2
+ echo "$help" 1>&2
+ exit 1
+else
+ host_alias=$host
+fi
+
+# Transform *-*-linux* to *-*-linux-gnu*, to support old configure scripts.
+case "$host" in
+*-*-linux-gnu*) ;;
+*-*-linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'`
+esac
+
+host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+case "$host_os" in
+aix*)
+ # AIX sometimes has problems with the GCC collect2 program. For some
+ # reason, if we set the COLLECT_NAMES environment variable, the problems
+ # vanish in a puff of smoke.
+ if test "${COLLECT_NAMES+set}" != set; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+ fi
+ ;;
+esac
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR cru $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+
+# Set a sane default for `AR'.
+test -z "$AR" && AR=ar
+
+# If RANLIB is not set, then run the test.
+if test "${RANLIB+set}" != "set"; then
+ result=no
+
+ echo $ac_n "checking for ranlib... $ac_c" 1>&6
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}:"
+ for dir in $PATH; do
+ test -z "$dir" && dir=.
+ if test -f $dir/ranlib; then
+ RANLIB="ranlib"
+ result="ranlib"
+ break
+ fi
+ done
+ IFS="$save_ifs"
+
+ echo "$ac_t$result" 1>&6
+fi
+
+if test -n "$RANLIB"; then
+ old_archive_cmds="$old_archive_cmds;\$RANLIB \$oldlib"
+ old_postinstall_cmds="$old_postinstall_cmds;\$RANLIB \$oldlib"
+fi
+
+# Check to see if we are using GCC.
+if test "$with_gcc" != yes || test -z "$CC"; then
+ # If CC is not set, then try to find GCC or a usable CC.
+ if test -z "$CC"; then
+ echo $ac_n "checking for gcc... $ac_c" 1>&6
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}:"
+ for dir in $PATH; do
+ IFS="$save_ifs"
+ test -z "$dir" && dir=.
+ if test -f $dir/gcc; then
+ CC="gcc"
+ break
+ fi
+ done
+ IFS="$save_ifs"
+
+ if test -n "$CC"; then
+ echo "$ac_t$CC" 1>&6
+ else
+ echo "$ac_t"no 1>&6
+ fi
+ fi
+
+ # Not "gcc", so try "cc", rejecting "/usr/ucb/cc".
+ if test -z "$CC"; then
+ echo $ac_n "checking for cc... $ac_c" 1>&6
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}:"
+ cc_rejected=no
+ for dir in $PATH; do
+ test -z "$dir" && dir=.
+ if test -f $dir/cc; then
+ if test "$dir/cc" = "/usr/ucb/cc"; then
+ cc_rejected=yes
+ continue
+ fi
+ CC="cc"
+ break
+ fi
+ done
+ IFS="$save_ifs"
+ if test $cc_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $CC
+ shift
+ if test $# -gt 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same name, so the bogon will be chosen
+ # first if we set CC to just the name; use the full file name.
+ shift
+ set dummy "$dir/cc" "$@"
+ shift
+ CC="$@"
+ fi
+ fi
+
+ if test -n "$CC"; then
+ echo "$ac_t$CC" 1>&6
+ else
+ echo "$ac_t"no 1>&6
+ fi
+
+ if test -z "$CC"; then
+ echo "$progname: error: no acceptable cc found in \$PATH" 1>&2
+ exit 1
+ fi
+ fi
+
+ # Now see if the compiler is really GCC.
+ with_gcc=no
+ echo $ac_n "checking whether we are using GNU C... $ac_c" 1>&6
+ echo "$progname:394: checking whether we are using GNU C" >&5
+
+ $rm conftest.c
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+ if { ac_try='${CC-cc} -E conftest.c'; { (eval echo $progname:402: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ with_gcc=yes
+ fi
+ $rm conftest.c
+ echo "$ac_t$with_gcc" 1>&6
+fi
+
+# Allow CC to be a program name with arguments.
+set dummy $CC
+compiler="$2"
+
+echo $ac_n "checking for $compiler option to produce PIC... $ac_c" 1>&6
+pic_flag=
+profile_flag_pattern=
+special_shlib_compile_flags=
+wl=
+link_static_flag=
+no_builtin_flag=
+
+if test "$with_gcc" = yes; then
+ profile_flag_pattern='-pg?'
+ wl='-Wl,'
+ link_static_flag='-static'
+ no_builtin_flag=' -fno-builtin'
+
+ case "$host_os" in
+ aix3* | aix4* | irix5* | irix6* | osf3* | osf4*)
+ # PIC is the default for these OSes.
+ ;;
+ os2*)
+ # We can build DLLs from non-PIC.
+ ;;
+ *)
+ pic_flag='-fPIC'
+ ;;
+ esac
+else
+ # PORTME Check for PIC flags for the system compiler.
+ case "$host_os" in
+ aix3* | aix4*)
+ # All AIX code is PIC.
+ link_static_flag='-bnso -bI:/lib/syscalls.exp'
+ ;;
+
+ hpux9* | hpux10*)
+ # Is there a better link_static_flag that works with the bundled CC?
+ wl='-Wl,'
+ link_static_flag='${wl}-a ${wl}archive'
+ pic_flag='+Z'
+ ;;
+
+ irix5* | irix6*)
+ wl='-Wl,'
+ link_static_flag='-non_shared'
+ # PIC (with -KPIC) is the default.
+ ;;
+
+ os2*)
+ # We can build DLLs from non-PIC.
+ ;;
+
+ osf3* | osf4*)
+ # All OSF/1 code is PIC.
+ wl='-Wl,'
+ link_static_flag='-non_shared'
+ ;;
+
+ sco3.2v5*)
+ pic_flag='-Kpic'
+ link_static_flag='-dn'
+ special_shlib_compile_flags='-belf'
+ ;;
+
+ solaris2*)
+ pic_flag='-KPIC'
+ link_static_flag='-Bstatic'
+ wl='-Wl,'
+ ;;
+
+ sunos4*)
+ pic_flag='-PIC'
+ link_static_flag='-Bstatic'
+ wl='-Qoption ld '
+ ;;
+
+ uts4*)
+ pic_flag='-pic'
+ link_static_flag='-Bstatic'
+ ;;
+
+ *)
+ can_build_shared=no
+ ;;
+ esac
+fi
+
+if test -n "$pic_flag"; then
+ echo "$ac_t$pic_flag" 1>&6
+
+ # Check to make sure the pic_flag actually works.
+ echo $ac_n "checking if $compiler PIC flag $pic_flag works... $ac_c" 1>&6
+ $rm conftest*
+ echo > conftest.c
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $pic_flag -DPIC"
+ echo "$progname:507: checking if $compiler PIC flag $pic_flag works" >&5
+ if { (eval echo $progname:508: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.o; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+
+ # On HP-UX, the stripped-down bundled CC doesn't accept +Z, but also
+ # reports no error. So, we need to grep stderr for (Bundled).
+ if grep '(Bundled)' conftest.err >/dev/null; then
+ echo "$ac_t"no 1>&6
+ can_build_shared=no
+ pic_flag=
+ else
+ echo "$ac_t"yes 1>&6
+ pic_flag=" $pic_flag"
+ fi
+ else
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ can_build_shared=no
+ pic_flag=
+ echo "$ac_t"no 1>&6
+ fi
+ CFLAGS="$save_CFLAGS"
+ $rm conftest*
+else
+ echo "$ac_t"none 1>&6
+fi
+
+# Check for any special shared library compilation flags.
+if test -n "$special_shlib_compile_flags"; then
+ echo "$progname: warning: \`$CC' requires \`$special_shlib_compile_flags' to build shared libraries" 1>&2
+ if echo "$old_CC $old_CFLAGS " | egrep -e "[ ]$special_shlib_compile_flags[ ]" >/dev/null; then :
+ else
+ echo "$progname: add \`$special_shlib_compile_flags' to the CC or CFLAGS env variable and reconfigure" 1>&2
+ can_build_shared=no
+ fi
+fi
+
+echo $ac_n "checking if $compiler static flag $link_static_flag works... $ac_c" 1>&6
+$rm conftest*
+echo 'main(){return(0);}' > conftest.c
+save_LDFLAGS="$LDFLAGS"
+LDFLAGS="$LDFLAGS $link_static_flag"
+echo "$progname:550: checking if $compiler static flag $link_static_flag works" >&5
+if { (eval echo $progname:551: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ echo "$ac_t$link_static_flag" 1>&6
+else
+ echo "$ac_t"none 1>&6
+ link_static_flag=
+fi
+LDFLAGS="$save_LDFLAGS"
+$rm conftest*
+
+if test -z "$LN_S"; then
+ # Check to see if we can use ln -s, or we need hard links.
+ echo $ac_n "checking whether ln -s works... $ac_c" 1>&6
+ $rm conftestdata
+ if ln -s X conftestdata 2>/dev/null; then
+ $rm conftestdata
+ LN_S="ln -s"
+ else
+ LN_S=ln
+ fi
+ if test "$LN_S" = "ln -s"; then
+ echo "$ac_t"yes 1>&6
+ else
+ echo "$ac_t"no 1>&6
+ fi
+fi
+
+# Make sure LD is an absolute path.
+if test -z "$LD"; then
+ ac_prog=ld
+ if test "$with_gcc" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ echo $ac_n "checking for ld used by GCC... $ac_c" 1>&6
+ echo "$progname:583: checking for ld used by GCC" >&5
+ ac_prog=`($CC -print-prog-name=ld) 2>&5`
+ case "$ac_prog" in
+ # Accept absolute paths.
+ /*)
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+ elif test "$with_gnu_ld" = yes; then
+ echo $ac_n "checking for GNU ld... $ac_c" 1>&6
+ echo "$progname:601: checking for GNU ld" >&5
+ else
+ echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6
+ echo "$progname:604: checking for non-GNU ld" >&5
+ fi
+
+ if test -z "$LD"; then
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog"; then
+ LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some GNU ld's only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ if "$LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
+ test "$with_gnu_ld" != no && break
+ else
+ test "$with_gnu_ld" != yes && break
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+ fi
+
+ if test -n "$LD"; then
+ echo "$ac_t$LD" 1>&6
+ else
+ echo "$ac_t"no 1>&6
+ fi
+
+ if test -z "$LD"; then
+ echo "$progname: error: no acceptable ld found in \$PATH" 1>&2
+ exit 1
+ fi
+fi
+
+# Check to see if it really is or isn't GNU ld.
+echo $ac_n "checking if the linker ($LD) is GNU ld... $ac_c" 1>&6
+# I'd rather use --version here, but apparently some GNU ld's only accept -v.
+if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+ with_gnu_ld=yes
+else
+ with_gnu_ld=no
+fi
+echo "$ac_t$with_gnu_ld" 1>&6
+
+# See if the linker supports building shared libraries.
+echo $ac_n "checking whether the linker ($LD) supports shared libraries... $ac_c" 1>&6
+
+allow_undefined_flag=
+archive_cmds=
+old_archive_from_new_cmds=
+export_dynamic_flag_spec=
+hardcode_libdir_flag_spec=
+hardcode_libdir_separator=
+hardcode_direct=no
+hardcode_minus_L=no
+hardcode_runpath_var=no
+hardcode_shlibpath_var=unsupported
+runpath_var=
+
+ld_shlibs=yes
+if test "$with_gnu_ld" = yes; then
+ # See if GNU ld supports shared libraries.
+
+ case "$host_os" in
+ sunos4*)
+ ld_shlibs=yes
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ *)
+ if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ ld_shlibs=yes
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ esac
+
+ if test "$ld_shlibs" = yes; then
+ archive_cmds='$CC -shared ${wl}-soname $wl$soname -o $lib$libobjs$deplibs'
+ hardcode_libdir_flag_spec='${wl}-rpath $wl$libdir'
+ export_dynamic_flag_spec='${wl}-export-dynamic'
+ fi
+else
+ # PORTME fill in a description of your system's linker (not GNU ld)
+ case "$host_os" in
+ aix3*)
+ allow_undefined_flag=unsupported
+ archive_cmds='$NM$libobjs | $global_symbol_pipe | sed '"'s/.* //'"' > $lib.exp;$LD -o $objdir/$soname$libobjs -bE:$lib.exp -T512 -H512 -bM:SRE$deplibs;$AR cru $lib $objdir/$soname'
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ hardcode_minus_L=yes
+ if test "$with_gcc" = yes && test -z "$link_static_flag"; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ hardcode_direct=unsupported
+ fi
+ ;;
+
+ aix4*)
+ allow_undefined_flag=unsupported
+ archive_cmds='$NM$libobjs | $global_symbol_pipe | sed '"'s/.* //'"' > $lib.exp;$CC -o $objdir/$soname$libobjs ${wl}-bE:$lib.exp ${wl}-bM:SRE ${wl}-bnoentry$deplibs;$AR cru $lib $objdir/$soname'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ ;;
+
+ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+ # support. Future versions do this automatically, but an explicit c++rt0.o
+ # doesn't break anything, and helps significantly (at the cost of a little
+ # extra space).
+ freebsd2.2*)
+ archive_cmds='$LD -Bshareable -o $lib$libobjs$deplibs /usr/lib/c++rt0.o'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ # Unfortunately, older versions of FreeBSD 2 don't have this feature.
+ freebsd2*)
+ archive_cmds='$LD -Bshareable -o $lib$libobjs$deplibs'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ # FreeBSD 3, at last, uses gcc -shared to do shared libraries.
+ freebsd3*)
+ archive_cmds='$CC -shared -o $lib$libobjs$deplibs'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ hpux9*)
+ archive_cmds='$rm $objdir/$soname;$LD -b +s +b $install_libdir -o $objdir/$soname$libobjs$deplibs;mv $objdir/$soname $lib'
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ ;;
+
+ hpux10*)
+ archive_cmds='$LD -b +h $soname +s +b $install_libdir -o $lib$libobjs$deplibs'
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ ;;
+
+ irix5* | irix6*)
+ archive_cmds='$LD -shared -o $lib -soname $soname -set_version $verstring$libobjs$deplibs'
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ ;;
+
+ netbsd*)
+ # Tested with NetBSD 1.2 ld
+ archive_cmds='$LD -Bshareable -o $lib$libobjs'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ openbsd*)
+ archive_cmds='$LD -Bshareable -o $lib$libobjs$deplibs'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ os2*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ allow_undefined_flag=unsupported
+ archive_cmds='echo "LIBRARY $libname INITINSTANCE" > $objdir/$libname.def;echo "DESCRIPTION \"$libname\"" >> $objdir/$libname.def;echo DATA >> $objdir/$libname.def;echo " SINGLE NONSHARED" >> $objdir/$libname.def;echo EXPORTS >> $objdir/$libname.def;emxexp$libobjs >> $objdir/$libname.def;$CC -Zdll -Zcrtdll -o $lib$libobjs $objdir/$libname.def'
+ old_archive_from_new_cmds='emximp -o $objdir/$libname.a $objdir/$libname.def'
+ ;;
+
+ osf3* | osf4*)
+ allow_undefined_flag=' -expect_unresolved \*'
+ archive_cmds='$LD -shared${allow_undefined_flag} -o $lib -soname $soname -set_version $verstring$libobjs$deplibs'
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ ;;
+
+ sco3.2v5*)
+ archive_cmds='$LD -G -o $lib$libobjs$deplibs'
+ hardcode_direct=yes
+ ;;
+
+ solaris2*)
+ archive_cmds='$LD -G -z text -h $soname -o $lib$libobjs$deplibs'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_shlibpath_var=no
+ ;;
+
+ sunos4*)
+ archive_cmds='$LD -assert pure-text -Bstatic -o $lib$libobjs'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ uts4*)
+ archive_cmds='$LD -G -h $soname -o $lib$libobjs$deplibs'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_direct=no
+ hardcode_minus_L=no
+ hardcode_shlibpath_var=no
+ ;;
+
+ *)
+ ld_shlibs=no
+ can_build_shared=no
+ ;;
+ esac
+fi
+echo "$ac_t$ld_shlibs" 1>&6
+
+if test -z "$NM"; then
+ echo $ac_n "checking for BSD-compatible nm... $ac_c" 1>&6
+ case "$NM" in
+ /*) ;; # Let the user override the test with a path.
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in /usr/ucb $PATH /bin; do
+ test -z "$ac_dir" && dir=.
+ if test -f $ac_dir/nm; then
+ # Check to see if the nm accepts a BSD-compat flag.
+ if ($ac_dir/nm -B /dev/null 2>&1; exit 0) | grep /dev/null >/dev/null; then
+ NM="$ac_dir/nm -B"
+ elif ($ac_dir/nm -p /dev/null 2>&1; exit 0) | grep /dev/null >/dev/null; then
+ NM="$ac_dir/nm -p"
+ else
+ NM="$ac_dir/nm"
+ fi
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$NM" && NM=nm
+ ;;
+ esac
+ echo "$ac_t$NM" 1>&6
+fi
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+echo $ac_n "checking command to parse $NM output... $ac_c" 1>&6
+
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix. What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[BCDEGRSTU]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
+
+# Transform the above into a raw symbol and a C symbol.
+symxfrm='\1 \1'
+
+# Define system-specific variables.
+case "$host_os" in
+aix*)
+ symcode='[BCDTU]'
+ ;;
+solaris2*)
+ symcode='[BDTU]'
+ ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then
+ symcode='[ABCDGISTUW]'
+fi
+
+# Write the raw and C identifiers.
+global_symbol_pipe="sed -n -e 's/^.* $symcode $sympat$/$symxfrm/p'"
+
+# Check to see that the pipe works correctly.
+pipe_works=no
+$rm conftest*
+cat > conftest.c <<EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(){}
+#ifdef __cplusplus
+}
+#endif
+main(){nm_test_var='a';nm_test_func();return(0);}
+EOF
+
+echo "$progname:900: checking if global_symbol_pipe works" >&5
+if { (eval echo $progname:901: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; } && test -s conftest.o; then
+ # Now try to grab the symbols.
+ nlist=conftest.nm
+ if { echo "$progname:904: eval \"$NM conftest.o | $global_symbol_pipe > $nlist\"" >&5; eval "$NM conftest.o | $global_symbol_pipe > $nlist 2>&5"; } && test -s "$nlist"; then
+
+ # Try sorting and uniquifying the output.
+ if sort "$nlist" | uniq > "$nlist"T; then
+ mv -f "$nlist"T "$nlist"
+ wcout=`wc "$nlist" 2>/dev/null`
+ count=`echo "$wcout" | sed 's/^[ ]*\([0-9][0-9]*\).*$/\1/'`
+ (test "$count" -ge 0) 2>/dev/null || count=-1
+ else
+ rm -f "$nlist"T
+ count=-1
+ fi
+
+ # Make sure that we snagged all the symbols we need.
+ if egrep ' nm_test_var$' "$nlist" >/dev/null; then
+ if egrep ' nm_test_func$' "$nlist" >/dev/null; then
+ cat <<EOF > conftest.c
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EOF
+ # Now generate the symbol file.
+ sed 's/^.* \(.*\)$/extern char \1;/' < "$nlist" >> conftest.c
+
+ cat <<EOF >> conftest.c
+#if defined (__STDC__) && __STDC__
+# define __ptr_t void *
+#else
+# define __ptr_t char *
+#endif
+
+/* The number of symbols in dld_preloaded_symbols, -1 if unsorted. */
+int dld_preloaded_symbol_count = $count;
+
+/* The mapping between symbol names and symbols. */
+struct {
+ char *name;
+ __ptr_t address;
+}
+dld_preloaded_symbols[] =
+{
+EOF
+ sed 's/^\(.*\) \(.*\)$/ {"\1", \&\2},/' < "$nlist" >> conftest.c
+ cat <<\EOF >> conftest.c
+ {0},
+};
+
+#ifdef __cplusplus
+}
+#endif
+EOF
+ # Now try linking the two files.
+ mv conftest.o conftestm.o
+ save_LIBS="$LIBS"
+ save_CFLAGS="$CFLAGS"
+ LIBS='conftestm.o'
+ CFLAGS="$CFLAGS$no_builtin_flag"
+ if { (eval echo $progname:962: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ pipe_works=yes
+ else
+ echo "$progname: failed program was:" >&5
+ cat conftest.c >&5
+ fi
+ LIBS="$save_LIBS"
+ else
+ echo "cannot find nm_test_func in $nlist" >&5
+ fi
+ else
+ echo "cannot find nm_test_var in $nlist" >&5
+ fi
+ else
+ echo "cannot run $global_symbol_pipe" >&5
+ fi
+else
+ echo "$progname: failed program was:" >&5
+ cat conftest.c >&5
+fi
+$rm conftest*
+
+# Don't use the global_symbol_pipe unless it works.
+echo "$ac_t$pipe_works" 1>&6
+test "$pipe_works" = yes || global_symbol_pipe=
+
+# Check hardcoding attributes.
+echo $ac_n "checking how to hardcode library paths into programs... $ac_c" 1>&6
+hardcode_action=
+if test -n "$hardcode_libdir_flag_spec" || \
+ test "$hardcode_runpath_var" = yes; then
+
+ # We can hardcode non-existant directories.
+ if test "$hardcode_direct" != no && \
+ test "$hardcode_minus_L" != no && \
+ test "$hardcode_shlibpath_var" != no; then
+
+ # Linking always hardcodes the temporary library directory.
+ hardcode_action=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ hardcode_action=immediate
+ fi
+elif test "$hardcode_direct" != yes && \
+ test "$hardcode_minus_L" != yes && \
+ test "$hardcode_shlibpath_var" != yes; then
+ # We can't hardcode anything.
+ hardcode_action=unsupported
+else
+ # We can only hardcode existing directories.
+ hardcode_action=relink
+fi
+echo "$ac_t$hardcode_action" 1>&6
+test "$hardcode_action" = unsupported && can_build_shared=no
+
+
+reload_flag=
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+echo $ac_n "checking for $LD option to reload object files... $ac_c" 1>&6
+# PORTME Some linker may need a different reload flag.
+reload_flag='-r'
+echo "$ac_t$reload_flag"
+test -n "$reload_flag" && reload_flag=" $reload_flag"
+
+# PORTME Fill in your ld.so characteristics
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+postinstall_cmds=
+finish_cmds=
+shlibpath_var=
+version_type=none
+dynamic_linker="$host_os ld.so"
+
+echo $ac_n "checking dynamic linker characteristics... $ac_c" 1>&6
+case "$host_os" in
+aix3* | aix4*)
+ version_type=linux
+ library_names_spec='$libname.so.$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX has no versioning support, so we append a major version to the name.
+ soname_spec='$libname.so.$major'
+ ;;
+
+freebsd2* | freebsd3*)
+ version_type=sunos
+ library_names_spec='$libname.so.$versuffix $libname.so'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+gnu*)
+ version_type=sunos
+ library_names_spec='$libname.so.$versuffix'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+hpux9* | hpux10*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ dynamic_linker="$host_os dld.sl"
+ version_type=sunos
+ shlibpath_var=SHLIB_PATH
+ library_names_spec='$libname.sl.$versuffix $libname.sl.$major $libname.sl'
+ soname_spec='$libname.sl.$major'
+ # HP-UX runs *really* slowly unless shared libraries are mode 555.
+ postinstall_cmds='chmod 555 $lib'
+ ;;
+
+irix5* | irix6*)
+ version_type=osf
+ soname_spec='$libname.so'
+ library_names_spec='$libname.so.$versuffix $libname.so'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*)
+ dynamic_linker=no
+ ;;
+
+# This must be Linux ELF.
+linux-gnu*)
+ version_type=linux
+ library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so'
+ soname_spec='$libname.so.$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+
+ if test -f /lib/ld.so.1; then
+ dynamic_linker='GNU ld.so'
+ else
+ # Only the GNU ld.so supports shared libraries on MkLinux.
+ case "$host_cpu" in
+ powerpc*) dynamic_linker=no ;;
+ *) dynamic_linker='Linux ld.so' ;;
+ esac
+ fi
+ ;;
+
+netbsd* | openbsd*)
+ version_type=sunos
+ library_names_spec='$libname.so.$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+os2*)
+ version_type=none
+ libname_spec='$name'
+ library_names_spec='$libname.dll $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+osf3* | osf4*)
+ version_type=osf
+ soname_spec='$libname.so'
+ library_names_spec='$libname.so.$versuffix $libname.so'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+sco3.2v5*)
+ version_type=osf
+ soname_spec='$libname.so.$major'
+ library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+solaris2*)
+ version_type=linux
+ library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so'
+ soname_spec='$libname.so.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='$libname.so.$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+uts4*)
+ version_type=linux
+ library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so'
+ soname_spec='$libname.so.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+echo "$ac_t$dynamic_linker"
+test "$dynamic_linker" = no && can_build_shared=no
+
+# FIXME add checks for striplib and old_striplib here.
+# strip -x works for most platforms, though not for static libraries on NetBSD
+# HP-UX requires "-r" for library stripping
+striplib=
+old_striplib=
+
+# Report the final consequences.
+echo "checking if libtool supports shared libraries... $can_build_shared" 1>&6
+
+echo $ac_n "checking whether to build shared libraries... $ac_c" 1>&6
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case "$host_os" in
+aix*)
+ test "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds;\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+esac
+
+echo "$ac_t$enable_shared" 1>&6
+
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+
+echo "checking whether to build static libraries... $enable_static" 1>&6
+
+echo $ac_n "checking for objdir... $ac_c" 1>&6
+rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+ objdir=.libs
+else
+ # MS-DOS does not allow filenames that begin with a dot.
+ objdir=_libs
+fi
+rmdir .libs 2>/dev/null
+echo "$ac_t$objdir" 1>&6
+
+# Now quote all the things that may contain metacharacters.
+for var in old_CC old_CFLAGS old_CPPFLAGS old_LD old_NM old_RANLIB \
+ old_LN_S AR CC LD LN_S NM reload_flag reload_cmds wl pic_flag \
+ link_static_flag no_builtin_flag export_dynamic_flag_spec \
+ profile_flag_pattern libname_spec library_names_spec soname_spec RANLIB \
+ old_archive_cmds old_archive_from_new_cmds old_postinstall_cmds \
+ archive_cmds postinstall_cmds \
+ allow_undefined_flag finish_cmds global_symbol_pipe \
+ striplib old_striplib \
+ hardcode_libdir_flag_spec hardcode_libdir_separator; do
+
+ case "$var" in
+ reload_cmds | old_archive_cmds | old_archive_from_new_cmds | \
+ old_postinstall_cmds | archive_cmds | postinstall_cmds | finish_cmds)
+ # Double-quote double-evaled strings.
+ eval "$var=\`echo \"\$$var\" | sed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\"\`"
+ ;;
+ *)
+ eval "$var=\`echo \"\$$var\" | sed \"\$sed_quote_subst\"\`"
+ ;;
+ esac
+done
+
+ofile=libtool
+trap "$rm $ofile; exit 1" 1 2 15
+echo creating $ofile
+$rm $ofile
+cat <<EOF > $ofile
+#! /bin/sh
+
+# libtool - Provide generalized library-building support services.
+#
+# Generated automatically by $PROGRAM - GNU $PACKAGE $VERSION
+# This program was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# CC="$old_CC" CFLAGS="$old_CFLAGS" CPPFLAGS="$old_CPPFLAGS" \\
+# LD="$old_LD" NM="$old_NM" RANLIB="$old_RANLIB" LN_S="$old_LN_S" \\
+# $0$ltconfig_args
+#
+# Compiler and other test output produced by $progname, useful for
+# debugging $progname, is in ./config.log if it exists.
+
+# The version of $progname that generated this script.
+LTCONFIG_VERSION="$VERSION"
+
+# Shell to use when invoking shell scripts.
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Whether or not to build libtool libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build old-style libraries.
+build_old_libs=$enable_static
+
+# The host system.
+host_alias="$host_alias"
+host="$host"
+
+# The archiver.
+AR="$AR"
+
+# The default C compiler.
+CC="$CC"
+
+# The linker used to build libraries.
+LD="$LD"
+
+# Whether we need hard or soft links.
+LN_S="$LN_S"
+
+# A BSD-compatible nm program.
+NM="$NM"
+
+# The name of the directory that contains temporary libtool files.
+objdir="$objdir"
+
+# How to create reloadable object files.
+reload_flag="$reload_flag"
+reload_cmds="$reload_cmds"
+
+# How to pass a linker flag through the compiler.
+wl="$wl"
+
+# Additional compiler flags for building library objects.
+pic_flag="$pic_flag"
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag="$link_static_flag"
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag="$no_builtin_flag"
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec="$export_dynamic_flag_spec"
+
+# Pattern to match compiler flags for creating libNAME_p libraries:
+profile_flag_pattern="$profile_flag_pattern"
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec="$libname_spec"
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec="$library_names_spec"
+
+# The coded name of the library, if different from the real name.
+soname_spec="$soname_spec"
+
+# Commands used to build and install an old-style archive.
+RANLIB="$RANLIB"
+old_archive_cmds="$old_archive_cmds"
+old_postinstall_cmds="$old_postinstall_cmds"
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds="$old_archive_from_new_cmds"
+
+# Commands used to build and install a shared archive.
+archive_cmds="$archive_cmds"
+postinstall_cmds="$postinstall_cmds"
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag="$allow_undefined_flag"
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds="$finish_cmds"
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe="$global_symbol_pipe"
+
+# How to strip a library file.
+striplib="$striplib"
+old_striplib="$old_striplib"
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec="$hardcode_libdir_flag_spec"
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator="$hardcode_libdir_separator"
+
+# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L
+
+# Set to yes if using RUNPATH_VAR=DIR during linking hardcodes DIR into the
+# resulting binary.
+hardcode_runpath_var=$hardcode_runpath_var
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var
+
+EOF
+
+case "$host_os" in
+aix*)
+ cat <<\EOF >> $ofile
+# AIX sometimes has problems with the GCC collect2 program. For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "${COLLECT_NAMES+set}" != set; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+fi
+
+EOF
+ ;;
+esac
+
+# Detect if we are using a relative or absolute path to ltmain.sh.
+case "$ltmain" in
+/*) cat <<EOF >> $ofile
+# Execute the libtool backend.
+. $ltmain
+EOF
+ ;;
+*) cat <<EOF >> $ofile
+# Find the path to this script.
+thisdir=\`echo "\$0" | sed -e 's%/[^/]*\$%%'\`
+test "X\$0" = "X\$thisdir" && thisdir=.
+
+# Execute the libtool backend.
+. \$thisdir/$ltmain
+EOF
+ ;;
+esac
+
+echo 'exit 1' >> $ofile
+
+chmod +x $ofile
+exit 0
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
diff --git a/ltmain.sh b/ltmain.sh
new file mode 100644
index 000000000..cb46c8498
--- /dev/null
+++ b/ltmain.sh
@@ -0,0 +1,2372 @@
+# ltmain.sh - Provide generalized library-building support services.
+# Generated automatically from ltmain.in by configure.
+# Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+# Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+#FIXME: echo=echo
+echo='printf %s\n'
+if test "X`$echo '\t'`" = 'X\t'; then :
+else
+ # The Solaris and AIX default echo program unquotes backslashes.
+ # This makes it impossible to quote backslashes using
+ # echo "$something" | sed 's/\\/\\\\/g'
+ # So, we emulate echo with printf '%s\n'
+ echo='printf %s\n'
+ if test "X`$echo '\t'`" = 'X\t'; then :
+ else
+ # Oops. We have no working printf. Try to find a not-so-buggy echo.
+ echo=echo
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}:"
+ save_PATH="$PATH"
+ PATH="$PATH":/usr/ucb
+ for dir in $PATH; do
+ if test -f $dir/echo && test "X`$dir/echo '\t'`" = 'X\t'; then
+ echo="$dir/echo"
+ break
+ fi
+ done
+ IFS="$save_ifs"
+ PATH="$save_PATH"
+ fi
+fi
+
+# The name of this program.
+progname=`$echo "$0" | sed 's%^.*/%%'`
+
+# Constants.
+PROGRAM=ltmain.sh
+PACKAGE=libtool
+VERSION=1.0f
+
+default_mode=
+help="Try \`$progname --help' for more information."
+magic="%%%MAGIC variable%%%"
+mkdir="mkdir"
+mv="mv -f"
+rm="rm -f"
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+sed_quote_subst='s/\([\\"$\\\\]\)/\\\1/g'
+
+# NLS nuisances.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+
+if test "$LTCONFIG_VERSION" != "$VERSION"; then
+ $echo "$progname: ltconfig version \`$LTCONFIG_VERSION' does not match $PROGRAM version \`$VERSION'" 1>&2
+ $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
+ exit 1
+fi
+
+if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
+ $echo "$progname: not configured to build any kind of library" 1>&2
+ $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
+ exit 1
+fi
+
+# Global variables.
+mode=$default_mode
+nonopt=
+prev=
+prevopt=
+run=
+show="$echo"
+show_help=
+execute_dlfiles=
+
+# Parse our command line options once, thoroughly.
+while test $# -gt 0
+do
+ arg="$1"
+ shift
+
+ case "$arg" in
+ -*=*) optarg=`$echo "$arg" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) optarg= ;;
+ esac
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$prev"; then
+ case "$prev" in
+ execute_dlfiles)
+ eval "$prev=\"\$$prev \$arg\""
+ ;;
+ *)
+ eval "$prev=\$arg"
+ ;;
+ esac
+
+ prev=
+ prevopt=
+ continue
+ fi
+
+ # Have we seen a non-optional argument yet?
+ case "$arg" in
+ --help)
+ show_help=yes
+ ;;
+
+ --version)
+ $echo "$PROGRAM (GNU $PACKAGE) $VERSION"
+ exit 0
+ ;;
+
+ --dry-run | -n)
+ run=:
+ ;;
+
+ --features)
+ $echo "host: $host"
+ if test "$build_libtool_libs" = yes; then
+ $echo "enable shared libraries"
+ else
+ $echo "disable shared libraries"
+ fi
+ if test "$build_old_libs" = yes; then
+ $echo "enable static libraries"
+ else
+ $echo "disable static libraries"
+ fi
+ exit 0
+ ;;
+
+ --finish) mode="finish" ;;
+
+ --mode) prevopt="--mode" prev=mode ;;
+ --mode=*) mode="$optarg" ;;
+
+ --quiet | --silent)
+ show=:
+ ;;
+
+ -dlopen)
+ prevopt="-dlopen"
+ prev=execute_dlfiles
+ ;;
+
+ -*)
+ $echo "$progname: unrecognized option \`$arg'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+
+ *)
+ nonopt="$arg"
+ break
+ ;;
+ esac
+done
+
+if test -n "$prevopt"; then
+ $echo "$progname: option \`$prevopt' requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+fi
+
+if test -z "$show_help"; then
+
+ # Infer the operation mode.
+ if test -z "$mode"; then
+ case "$nonopt" in
+ *cc | *++)
+ mode=link
+ for arg
+ do
+ case "$arg" in
+ -c)
+ mode=compile
+ break
+ ;;
+ esac
+ done
+ ;;
+ *db | *dbx)
+ mode=execute
+ ;;
+ *install*|cp)
+ mode=install
+ ;;
+ *rm)
+ mode=uninstall
+ ;;
+ *)
+ # If we have no mode, but dlfiles were specified, then do execute mode.
+ test -n "$execute_dlfiles" && mode=execute
+
+ # Just use the default operation mode.
+ if test -z "$mode"; then
+ if test -n "$nonopt"; then
+ $echo "$progname: warning: cannot infer operation mode from \`$nonopt'" 1>&2
+ else
+ $echo "$progname: warning: cannot infer operation mode without MODE-ARGS" 1>&2
+ fi
+ fi
+ ;;
+ esac
+ fi
+
+ # Only execute mode is allowed to have -dlopen flags.
+ if test -n "$execute_dlfiles" && test "$mode" != execute; then
+ $echo "$progname: unrecognized option \`-dlopen'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ # Change the help message to a mode-specific one.
+ generic_help="$help"
+ help="Try \`$progname --help --mode=$mode' for more information."
+
+ # These modes are in order of execution frequency so that they run quickly.
+ case "$mode" in
+ # libtool compile mode
+ compile)
+ progname="$progname: compile"
+ # Get the compilation command and the source file.
+ base_compile=
+ lastarg=
+ srcfile="$nonopt"
+ suppress_output=
+
+ for arg
+ do
+ # The only flag that cannot be specified is the output filename.
+ if test "X$arg" = "X-o"; then
+ $echo "$progname: you cannot specify the output filename with \`-o'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ # Accept the current argument as the source file.
+ lastarg="$srcfile"
+ srcfile="$arg"
+
+ # Aesthetically quote the previous argument.
+
+ # Backslashify any backslashes, double quotes, and dollar signs.
+ # These are the only characters that are still specially
+ # interpreted inside of double-quoted scrings.
+ lastarg=`$echo "$lastarg" | sed "$sed_quote_subst"`
+
+ # Double-quote args containing other shell metacharacters.
+ # Many Bourne shells cannot handle close brackets correctly in scan
+ # sets, so we specify it separately.
+ case "$lastarg" in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ lastarg="\"$lastarg\""
+ ;;
+ esac
+
+ # Add the previous argument to base_compile.
+ if test -z "$base_compile"; then
+ base_compile="$lastarg"
+ else
+ base_compile="$base_compile $lastarg"
+ fi
+ done
+
+ # Get the name of the library object.
+ libobj=`$echo "$srcfile" | sed -e 's%^.*/%%'`
+
+ # Recognize several different file suffixes.
+ xform='[cCFSfm]'
+ case "$libobj" in
+ *.c++) xform=c++ ;;
+ *.cc) xform=cc ;;
+ *.cpp) xform=cpp ;;
+ *.cxx) xform=cxx ;;
+ *.f90) xform=f90 ;;
+ *.for) xform=for ;;
+ esac
+
+ libobj=`$echo "$libobj" | sed -e "s/\.$xform$/.lo/"`
+
+ case "$libobj" in
+ *.lo) obj=`$echo "$libobj" | sed -e 's/\.lo$/.o/'` ;;
+ *)
+ $echo "$progname: cannot determine name of library object from \`$srcfile'" 1>&2
+ exit 1
+ ;;
+ esac
+
+ if test -z "$base_compile"; then
+ $echo "$progname: you must specify a compilation command" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ # Delete any leftover library objects.
+ if test "$build_old_libs" = yes; then
+ $run $rm $obj $libobj
+ trap "$run $rm $obj $libobj; exit 1" 1 2 15
+ else
+ $run $rm $libobj
+ trap "$run $rm $libobj; exit 1" 1 2 15
+ fi
+
+ # Only build a PIC object if we are building libtool libraries.
+ if test "$build_libtool_libs" = yes; then
+ # Without this assignment, base_compile gets emptied.
+ fbsd_hideous_sh_bug=$base_compile
+
+ # All platforms use -DPIC, to notify preprocessed assembler code.
+ $show "$base_compile$pic_flag -DPIC $srcfile"
+ if $run eval "$base_compile\$pic_flag -DPIC \$srcfile"; then :
+ else
+ test -n "$obj" && $run $rm $obj
+ exit 1
+ fi
+
+ # If we have no pic_flag, then copy the object into place and finish.
+ if test -z "$pic_flag"; then
+ $show "$LN_S $obj $libobj"
+ $run $LN_S $obj $libobj
+ exit $?
+ fi
+
+ # Just move the object, then go on to compile the next one
+ $show "$mv $obj $libobj"
+ $run $mv $obj $libobj || exit 1
+
+ # Allow error messages only from the first compilation.
+ suppress_output=' >/dev/null 2>&1'
+ fi
+
+ # Only build a position-dependent object if we build old libraries.
+ if test "$build_old_libs" = yes; then
+ # Suppress compiler output if we already did a PIC compilation.
+ $show "$base_compile $srcfile$suppress_output"
+ if $run eval "$base_compile \$srcfile$suppress_output"; then :
+ else
+ $run $rm $obj $libobj
+ exit 1
+ fi
+ fi
+
+ # Create an invalid libtool object if no PIC, so that we don't accidentally
+ # link it into a program.
+ if test "$build_libtool_libs" != yes; then
+ $show "$echo timestamp > $libobj"
+ $run eval "\$echo timestamp > \$libobj" || exit $?
+ fi
+
+ exit 0
+ ;;
+
+ # libtool link mode
+ link)
+ progname="$progname: link"
+ CC="$nonopt"
+ allow_undefined=no
+ compile_command="$CC"
+ finalize_command="$CC"
+
+ compile_shlibpath=
+ finalize_shlibpath=
+ deplibs=
+ dlfiles=
+ dlprefiles=
+ export_dynamic=no
+ hardcode_libdirs=
+ libobjs=
+ link_against_libtool_libs=
+ ltlibs=
+ objs=
+ prev=
+ prevarg=
+ rpath=
+ perm_rpath=
+ temp_rpath=
+ vinfo=
+
+ # We need to know -static, to get the right output filenames.
+ for arg
+ do
+ case "$arg" in
+ -all-static | -static)
+ if test "X$arg" = "X-all-static" && test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
+ $echo "$progname: warning: complete static linking is impossible in this configuration" 1>&2
+ fi
+ build_libtool_libs=no
+ build_old_libs=yes
+ break
+ ;;
+ esac
+ done
+
+ # See if our shared archives depend on static archives.
+ test -n "$old_archive_from_new_cmds" && build_old_libs=yes
+
+ # Go through the arguments, transforming them on the way.
+ for arg
+ do
+ # If the previous option needs an argument, assign it.
+ if test -n "$prev"; then
+ case "$prev" in
+ output)
+ compile_command="$compile_command @OUTPUT@"
+ finalize_command="$finalize_command @OUTPUT@"
+ ;;
+ esac
+
+ case "$prev" in
+ dlfiles|dlprefiles)
+ case "$arg" in
+ *.la | *.lo) ;; # We handle these cases below.
+ *)
+ dlprefiles="$dlprefiles $arg"
+ test "$prev" = dlfiles && dlfiles="$dlfiles $arg"
+ prev=
+ ;;
+ esac
+ ;;
+ rpath)
+ rpath="$rpath $arg"
+ prev=
+ continue
+ ;;
+ *)
+ eval "$prev=\"\$arg\""
+ prev=
+ continue
+ ;;
+ esac
+ fi
+
+ prevarg="$arg"
+
+ case "$arg" in
+ -all-static)
+ if test -n "$link_static_flag"; then
+ compile_command="$compile_command $link_static_flag"
+ finalize_command="$finalize_command $link_static_flag"
+ fi
+ continue
+ ;;
+
+ -allow-undefined)
+ allow_undefined=yes
+ continue
+ ;;
+
+ -dlopen)
+ prev=dlfiles
+ continue
+ ;;
+
+ -dlpreopen)
+ prev=dlprefiles
+ continue
+ ;;
+
+ -export-dynamic)
+ if test "$export_dynamic" != yes; then
+ export_dynamic=yes
+ if test -n "$export_dynamic_flag_spec"; then
+ arg=`eval \\$echo "$export_dynamic_flag_spec"`
+ else
+ arg=
+ fi
+
+ # Add the symbol object into the linking commands.
+ compile_command="$compile_command @SYMFILE@"
+ finalize_command="$finalize_command @SYMFILE@"
+ fi
+ ;;
+
+ -L*)
+ dir=`$echo "$arg" | sed 's%^-L\(.*\)$%\1%'`
+ case "$dir" in
+ /*)
+ # Add the corresponding hardcode_libdir_flag, if it is not identical.
+ ;;
+ *)
+ $echo "$progname: \`-L$dir' cannot specify a relative directory" 1>&2
+ exit 1
+ ;;
+ esac
+ deplibs="$deplibs $arg"
+ ;;
+
+ -l*) deplibs="$deplibs $arg" ;;
+
+ -o) prev=output ;;
+
+ -rpath)
+ prev=rpath
+ continue
+ ;;
+
+ -static)
+ # If we have no pic_flag, then this is the same as -all-static.
+ if test -z "$pic_flag" && test -n "$link_static_flag"; then
+ compile_command="$compile_command $link_static_flag"
+ finalize_command="$finalize_command $link_static_flag"
+ fi
+ continue
+ ;;
+
+ -version-info)
+ prev=vinfo
+ continue
+ ;;
+
+ # Some other compiler flag.
+ -* | +*)
+ # Unknown arguments in both finalize_command and compile_command need
+ # to be aesthetically quoted because they are evaled later.
+ arg=`$echo "$arg" | sed "$sed_quote_subst"`
+ case "$arg" in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ arg="\"$arg\""
+ ;;
+ esac
+ ;;
+
+ *.o | *.a)
+ # A standard object.
+ objs="$objs $arg"
+ ;;
+
+ *.lo)
+ # A library object.
+ if test "$prev" = dlfiles; then
+ dlfiles="$dlfiles $arg"
+ if test "$build_libtool_libs" = yes; then
+ prev=
+ continue
+ else
+ # If libtool objects are unsupported, then we need to preload.
+ prev=dlprefiles
+ fi
+ fi
+
+ if test "$prev" = dlprefiles; then
+ # Preload the old-style object.
+ dlprefiles="$dlprefiles "`$echo "$arg" | sed 's/\.lo$/\.o/'`
+ prev=
+ fi
+ libobjs="$libobjs $arg"
+ ;;
+
+ *.la)
+ # A libtool-controlled library.
+
+ dlname=
+ libdir=
+ library_names=
+ old_library=
+
+ # Check to see that this really is a libtool archive.
+ if egrep '^# Generated by ltmain.sh' $arg >/dev/null 2>&1; then :
+ else
+ $echo "$progname: \`$arg' is not a valid libtool archive" 1>&2
+ exit 1
+ fi
+
+ # If there is no directory component, then add one.
+ case "$arg" in
+ */*) . $arg ;;
+ *) . ./$arg ;;
+ esac
+
+ if test -z "$libdir"; then
+ $echo "$progname: \`$arg' contains no -rpath information" 1>&2
+ exit 1
+ fi
+
+ # Get the name of the library we link against.
+ linklib=
+ for l in $old_library $library_names; do
+ linklib="$l"
+ done
+
+ if test -z "$linklib"; then
+ $echo "$progname: cannot find name of link library for \`$arg'" 1>&2
+ exit 1
+ fi
+
+ # Find the relevant object directory and library name.
+ name=`$echo "$arg" | sed -e 's%^.*/%%' -e 's/\.la$//' -e 's/^lib//'`
+ dir=`$echo "$arg" | sed 's%/[^/]*$%%'`
+ if test "X$dir" = "X$arg"; then
+ dir="$objdir"
+ else
+ dir="$dir/$objdir"
+ fi
+
+ # This library was specified with -dlopen.
+ if test "$prev" = dlfiles; then
+ dlfiles="$dlfiles $arg"
+ if test -z "$dlname"; then
+ # If there is no dlname, we need to preload.
+ prev=dlprefiles
+ else
+ # We should not create a dependency on this library.
+ prev=
+ continue
+ fi
+ fi
+
+ # The library was specified with -dlpreopen.
+ if test "$prev" = dlprefiles; then
+ # Prefer using a static library (so that no silly _DYNAMIC symbols
+ # are required to link).
+ if test -n "$old_library"; then
+ dlprefiles="$dlprefiles $dir/$old_library"
+ else
+ dlprefiles="$dlprefiles $dir/$linklib"
+ fi
+ prev=
+ fi
+
+ if test "$build_libtool_libs" = yes && test -n "$library_names"; then
+ link_against_libtool_libs="$link_against_libtool_libs $arg"
+ if test -n "$shlibpath_var"; then
+ # Make sure the rpath contains only unique directories.
+ case "$temp_rpath " in
+ *" $dir "*) ;;
+ *) temp_rpath="$temp_rpath $dir" ;;
+ esac
+ fi
+
+ # This is the magic to use -rpath.
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ # Put the magic libdir with the hardcode flag.
+ hardcode_libdirs="$libdir"
+ libdir="@HARDCODE_LIBDIRS@"
+ else
+ # Just accumulate the unique libdirs.
+ case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ libdir=
+ fi
+ fi
+
+ if test -n "$libdir"; then
+ flag=`eval \\$echo \"$hardcode_libdir_flag_spec\"`
+
+ compile_command="$compile_command $flag"
+ finalize_command="$finalize_command $flag"
+ fi
+ elif test "$hardcode_runpath_var" = yes; then
+ # Do the same for the permanent run path.
+ case "$perm_rpath " in
+ *" $libdir "*) ;;
+ *) perm_rpath="$perm_rpath $libdir" ;;
+ esac
+ fi
+
+
+ case "$hardcode_action" in
+ immediate)
+ if test "$hardcode_direct" = no; then
+ compile_command="$compile_command $dir/$linklib"
+ elif test "$hardcode_minus_L" = no; then
+ compile_command="$compile_command -L$dir -l$name"
+ elif test "$hardcode_shlibpath_var" = no; then
+ compile_shlibpath="$compile_shlibpath$dir:"
+ compile_command="$compile_command -l$name"
+ fi
+ ;;
+
+ relink)
+ # We need an absolute path.
+ case "$dir" in
+ /*) ;;
+ *)
+ absdir=`cd "$dir" && pwd`
+ if test -z "$absdir"; then
+ $echo "$progname: cannot determine absolute directory name of \`$dir'" 1>&2
+ exit 1
+ fi
+ dir="$absdir"
+ ;;
+ esac
+
+ if test "$hardcode_direct" = yes; then
+ compile_command="$compile_command $dir/$linklib"
+ elif test "$hardcode_minus_L" = yes; then
+ compile_command="$compile_command -L$dir -l$name"
+ elif test "$hardcode_shlibpath_var" = yes; then
+ compile_shlibpath="$compile_shlibpath$dir:"
+ compile_command="$compile_command -l$name"
+ fi
+ ;;
+
+ *)
+ $echo "$progname: \`$hardcode_action' is an unknown hardcode action" 1>&2
+ exit 1
+ ;;
+ esac
+
+ # Finalize command for both is simple: just hardcode it.
+ if test "$hardcode_direct" = yes; then
+ finalize_command="$finalize_command $libdir/$linklib"
+ elif test "$hardcode_minus_L" = yes; then
+ finalize_command="$finalize_command -L$libdir -l$name"
+ elif test "$hardcode_shlibpath_var" = yes; then
+ finalize_shlibpath="$finalize_shlibpath$libdir:"
+ finalize_command="$finalize_command -l$name"
+ else
+ # We can't seem to hardcode it, guess we'll fake it.
+ finalize_command="$finalize_command -L$libdir -l$name"
+ fi
+ else
+ # Transform directly to old archives if we don't build new libraries.
+ if test -n "$pic_flag" && test -z "$old_library"; then
+ $echo "$progname: cannot find static library for \`$arg'" 1>&2
+ exit 1
+ fi
+
+ # Here we assume that one of hardcode_direct or hardcode_minus_L
+ # is not unsupported. This is valid on all known static and
+ # shared platforms.
+ if test "$hardcode_direct" != unsupported; then
+ test -n "$old_library" && linklib="$old_library"
+ compile_command="$compile_command $dir/$linklib"
+ finalize_command="$finalize_command $dir/$linklib"
+ else
+ compile_command="$compile_command -L$dir -l$name"
+ finalize_command="$finalize_command -L$dir -l$name"
+ fi
+ fi
+ continue
+ ;;
+
+ # Some other compiler argument.
+ *)
+ # Unknown arguments in both finalize_command and compile_command need
+ # to be aesthetically quoted because they are evaled later.
+ arg=`$echo "$arg" | sed "$sed_quote_subst"`
+ case "$arg" in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ arg="\"$arg\""
+ ;;
+ esac
+ ;;
+ esac
+
+ # Now actually substitute the argument into the commands.
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ done
+
+ if test -n "$prev"; then
+ $echo "$progname: the \`$prevarg' option requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ oldlib=
+ oldobjs=
+ case "$output" in
+ "")
+ $echo "$progname: you must specify an output file" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+
+ */*)
+ $echo "$progname: output file \`$output' must have no directory components" 1>&2
+ exit 1
+ ;;
+
+ *.la)
+ # Make sure we only generate libraries of the form `libNAME.la'.
+ case "$output" in
+ lib*) ;;
+ *)
+ $echo "$progname: libtool library \`$arg' must begin with \`lib'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+ esac
+
+ name=`$echo "$output" | sed -e 's/\.la$//' -e 's/^lib//'`
+ libname=`eval \\$echo \"$libname_spec\"`
+
+ # All the library-specific variables (install_libdir is set above).
+ library_names=
+ old_library=
+ dlname=
+ current=0
+ revision=0
+ age=0
+
+ if test -n "$objs"; then
+ $echo "$progname: cannot build libtool library \`$output' from non-libtool objects:$objs" 2>&1
+ exit 1
+ fi
+
+ # How the heck are we supposed to write a wrapper for a shared library?
+ if test -n "$link_against_libtool_libs"; then
+ $echo "$progname: libtool library \`$output' may not depend on uninstalled libraries:$link_against_libtool_libs" 1>&2
+ exit 1
+ fi
+
+ # Add libc to deplibs on all systems.
+ deplibs="$deplibs -lc"
+
+ if test -n "$dlfiles$dlprefiles"; then
+ $echo "$progname: warning: \`-dlopen' is ignored while creating libtool libraries" 1>&2
+ # Nullify the symbol file.
+ compile_command=`$echo "$compile_command" | sed "s% @SYMFILE@%%"`
+ finalize_command=`$echo "$finalize_command" | sed "s% @SYMFILE@%%"`
+ fi
+
+ if test -z "$rpath"; then
+ $echo "$progname: you must specify an installation directory with \`-rpath'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ set dummy $rpath
+ if test $# -gt 2; then
+ $echo "$progname: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2
+ fi
+ install_libdir="$2"
+
+ # Parse the version information argument.
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS=':'
+ set dummy $vinfo
+ IFS="$save_ifs"
+
+ if test -n "$5"; then
+ $echo "$progname: too many parameters to \`-version-info'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ test -n "$2" && current="$2"
+ test -n "$3" && revision="$3"
+ test -n "$4" && age="$4"
+
+ # Check that each of the things are valid numbers.
+ case "$current" in
+ 0 | [1-9] | [1-9][0-9]*) ;;
+ *)
+ $echo "$progname: CURRENT \`$current' is not a nonnegative integer" 1>&2
+ $echo "$progname: \`$vinfo' is not valid version information" 1>&2
+ exit 1
+ ;;
+ esac
+
+ case "$revision" in
+ 0 | [1-9] | [1-9][0-9]*) ;;
+ *)
+ $echo "$progname: REVISION \`$revision' is not a nonnegative integer" 1>&2
+ $echo "$progname: \`$vinfo' is not valid version information" 1>&2
+ exit 1
+ ;;
+ esac
+
+ case "$age" in
+ 0 | [1-9] | [1-9][0-9]*) ;;
+ *)
+ $echo "$progname: AGE \`$age' is not a nonnegative integer" 1>&2
+ $echo "$progname: \`$vinfo' is not valid version information" 1>&2
+ exit 1
+ ;;
+ esac
+
+ if test $age -gt $current; then
+ $echo "$progname: AGE \`$age' is greater than the current interface number \`$current'" 1>&2
+ $echo "$progname: \`$vinfo' is not valid version information" 1>&2
+ exit 1
+ fi
+
+ # Calculate the version variables.
+ version_vars="version_type current age revision"
+ case "$version_type" in
+ none) ;;
+
+ linux)
+ version_vars="$version_vars major versuffix"
+ major=`expr $current - $age`
+ versuffix="$major.$age.$revision"
+ ;;
+
+ osf)
+ version_vars="$version_vars versuffix verstring"
+ major=`expr $current - $age`
+ versuffix="$current.$age.$revision"
+ verstring="$versuffix"
+
+ # Add in all the interfaces that we are compatible with.
+ loop=$age
+ while test $loop != 0; do
+ iface=`expr $current - $loop`
+ loop=`expr $loop - 1`
+ verstring="$verstring:${iface}.0"
+ done
+
+ # Make executables depend on our current version.
+ verstring="$verstring:${current}.0"
+ ;;
+
+ sunos)
+ version_vars="$version_vars major versuffix"
+ major="$current"
+ versuffix="$current.$revision"
+ ;;
+
+ *)
+ $echo "$progname: unknown library version type \`$version_type'" 1>&2
+ $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
+ exit 1
+ ;;
+ esac
+
+ # Create the output directory, or remove our outputs if we need to.
+ if test -d $objdir; then
+ $show "$rm $objdir/$output $objdir/$libname.*"
+ $run $rm $objdir/$output $objdir/$libname.*
+ else
+ $show "$mkdir $objdir"
+ $run $mkdir $objdir
+ status=$?
+ if test $status -eq 0 || test -d $objdir; then :
+ else
+ exit $status
+ fi
+ fi
+
+ # Check to see if the archive will have undefined symbols.
+ if test "$allow_undefined" = yes; then
+ if test "$allow_undefined_flag" = unsupported; then
+ $echo "$progname: warning: undefined symbols not allowed in $host shared libraries" 1>&2
+ build_libtool_libs=no
+ build_old_libs=yes
+ fi
+ else
+ # Clear the flag.
+ allow_undefined_flag=
+ fi
+
+ if test "$build_libtool_libs" = yes; then
+ # Get the real and link names of the library.
+ library_names=`eval \\$echo \"$library_names_spec\"`
+ set dummy $library_names
+ realname="$2"
+ shift; shift
+
+ if test -n "$soname_spec"; then
+ soname=`eval \\$echo \"$soname_spec\"`
+ else
+ soname="$realname"
+ fi
+
+ lib="$objdir/$realname"
+ for link
+ do
+ linknames="$linknames $link"
+ done
+
+ # Use standard objects if they are PIC.
+ test -z "$pic_flag" && libobjs=`$echo "$libobjs " | sed -e 's/\.lo /.o /g' -e 's/ $//g'`
+
+ # Do each of the archive commands.
+ cmds=`eval \\$echo \"$archive_cmds\"`
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS=';'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+
+ # Create links to the real library.
+ for link in $linknames; do
+ $show "(cd $objdir && $LN_S $realname $link)"
+ $run eval '(cd $objdir && $LN_S $realname $link)' || exit $?
+ done
+
+ # If -export-dynamic was specified, set the dlname.
+ if test "$export_dynamic" = yes; then
+ # On all known operating systems, these are identical.
+ dlname="$soname"
+ fi
+ fi
+ ;;
+
+ *.lo | *.o)
+ if test -n "$link_against_libtool_libs"; then
+ $echo "$progname: error: cannot link libtool libraries into reloadable objects" 1>&2
+ exit 1
+ fi
+
+ if test -n "$deplibs"; then
+ $echo "$progname: warning: \`-l' and \`-L' are ignored while creating objects" 1>&2
+ fi
+
+ if test -n "$dlfiles$dlprefiles"; then
+ $echo "$progname: warning: \`-dlopen' is ignored while creating objects" 1>&2
+ # Nullify the symbol file.
+ compile_command=`$echo "$compile_command" | sed "s% @SYMFILE@%%"`
+ finalize_command=`$echo "$finalize_command" | sed "s% @SYMFILE@%%"`
+ fi
+
+ if test -n "$rpath"; then
+ $echo "$progname: warning: \`-rpath' is ignored while creating objects" 1>&2
+ fi
+
+ if test -n "$vinfo"; then
+ $echo "$progname: warning: \`-version-info' is ignored while creating objects" 1>&2
+ fi
+
+ case "$output" in
+ *.lo)
+ if test -n "$objs"; then
+ $echo "$progname: cannot build library object \`$output' from non-libtool objects" 1>&2
+ exit 1
+ fi
+ libobj="$output"
+ obj=`$echo "$output" | sed 's/\.lo$/.o/'`
+ ;;
+ *)
+ libobj=
+ obj="$output"
+ ;;
+ esac
+
+ # Delete the old objects.
+ $run $rm $obj $libobj
+
+ # Create the old-style object.
+ reload_objs="$objs"`$echo "$libobjs " | sed -e 's/[^ ]*\.a //g' -e 's/\.lo /.o /g' -e 's/ $//g'`
+
+ output="$obj"
+ cmds=`eval \\$echo \"$reload_cmds\"`
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS=';'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+
+ # Exit if we aren't doing a library object file.
+ test -z "$libobj" && exit 0
+
+ if test "$build_libtool_libs" != yes; then
+ # Create an invalid libtool object if no PIC, so that we don't
+ # accidentally link it into a program.
+ $show "$echo timestamp > $libobj"
+ $run eval "\$echo timestamp > $libobj" || exit $?
+ exit 0
+ fi
+
+ if test -n "$pic_flag"; then
+ # Only do commands if we really have different PIC objects.
+ reload_objs="$libobjs"
+ output="$libobj"
+ cmds=`eval \\$echo \"$reload_cmds\"`
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS=';'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ else
+ # Just create a symlink.
+ $show "$LN_S $obj $libobj"
+ $run $LN_S $obj $libobj || exit 1
+ fi
+
+ exit 0
+ ;;
+
+ *)
+ if test -n "$vinfo"; then
+ $echo "$progname: warning: \`-version-info' is ignored while linking programs" 1>&2
+ fi
+
+ if test -n "$rpath"; then
+ # If the user specified any rpath flags, then add them.
+ for libdir in $rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ # Put the magic libdir with the hardcode flag.
+ hardcode_libdirs="$libdir"
+ libdir="@HARDCODE_LIBDIRS@"
+ else
+ # Just accumulate the unique libdirs.
+ case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ libdir=
+ fi
+ fi
+
+ if test -n "$libdir"; then
+ flag=`eval \\$echo \"$hardcode_libdir_flag_spec\"`
+
+ compile_command="$compile_command $flag"
+ finalize_command="$finalize_command $flag"
+ fi
+ elif test "$hardcode_runpath_var" = yes; then
+ case "$perm_rpath " in
+ *" $libdir "*) ;;
+ *) perm_rpath="$perm_rpath $libdir" ;;
+ esac
+ fi
+ done
+ fi
+
+ # Substitute the hardcoded libdirs into the compile commands.
+ if test -n "$hardcode_libdir_separator"; then
+ compile_command=`$echo "$compile_command" | sed "s%@HARDCODE_LIBDIRS@%$hardcode_libdirs%g"`
+ finalize_command=`$echo "$finalize_command" | sed "s%@HARDCODE_LIBDIRS@%$hardcode_libdirs%g"`
+ fi
+
+ if test -n "$libobjs" && test "$build_old_libs" = yes; then
+ # Transform all the library objects into standard objects.
+ compile_command=`$echo "$compile_command " | sed -e 's/\.lo /.o /g' -e 's/ $//'`
+ finalize_command=`$echo "$finalize_command " | sed -e 's/\.lo /.o /g' -e 's/ $//'`
+ fi
+
+ if test "$export_dynamic" = yes && test -n "$NM" && test -n "$global_symbol_pipe"; then
+ dlsyms="${output}S.c"
+ else
+ dlsyms=
+ fi
+
+ if test -n "$dlsyms"; then
+ # Add our own program objects to the preloaded list.
+ dlprefiles=`$echo "$objs$dlprefiles " | sed -e 's/\.lo /.o /g' -e 's/ $//'`
+
+ # Discover the nlist of each of the dlfiles.
+ nlist="$objdir/${output}.nm"
+
+ if test -d $objdir; then
+ $show "$rm $nlist ${nlist}T"
+ $run $rm "$nlist" "${nlist}T"
+ else
+ $show "$mkdir $objdir"
+ $run $mkdir $objdir
+ status=$?
+ if test $status -eq 0 || test -d $objdir; then :
+ else
+ exit $status
+ fi
+ fi
+
+ for arg in $dlprefiles; do
+ $show "extracting global C symbols from \`$arg'"
+ $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
+ done
+
+ # Parse the name list into a source file.
+ $show "creating $objdir/$dlsyms"
+ if test -z "$run"; then
+ # Make sure we at least have an empty file.
+ test -f "$nlist" || : > "$nlist"
+
+ # Try sorting and uniquifying the output.
+ if sort "$nlist" | uniq > "$nlist"T; then
+ mv -f "$nlist"T "$nlist"
+ wcout=`wc "$nlist" 2>/dev/null`
+ count=`$echo "$wcout" | sed 's/^[ ]*\([0-9][0-9]*\).*$/\1/'`
+ (test "$count" -ge 0) 2>/dev/null || count=-1
+ else
+ $rm "$nlist"T
+ count=-1
+ fi
+
+ case "$dlsyms" in
+ "") ;;
+ *.c)
+ cat <<EOF > "$objdir/$dlsyms"
+/* $dlsyms - symbol resolution table for \`$output' dlsym emulation. */
+/* Generated by $PROGRAM - GNU $PACKAGE $VERSION */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Prevent the only kind of declaration conflicts we can make. */
+#define dld_preloaded_symbol_count some_other_symbol
+#define dld_preloaded_symbols some_other_symbol
+
+/* External symbol declarations for the compiler. */
+EOF
+ if test -f "$nlist"; then
+ sed -e 's/^.* \(.*\)$/extern char \1;/' < "$nlist" >> "$objdir/$dlsyms"
+ else
+ $echo '/* NONE */' >> "$objdir/$dlsyms"
+EOF
+ fi
+
+ cat <<EOF >> "$objdir/$dlsyms"
+
+#undef dld_preloaded_symbol_count
+#undef dld_preloaded_symbols
+
+#if defined (__STDC__) && __STDC__
+# define __ptr_t void *
+#else
+# define __ptr_t char *
+#endif
+
+/* The number of symbols in dld_preloaded_symbols, -1 if unsorted. */
+int dld_preloaded_symbol_count = $count;
+
+/* The mapping between symbol names and symbols. */
+struct {
+ char *name;
+ __ptr_t address;
+}
+dld_preloaded_symbols[] =
+{
+EOF
+
+ if test -f "$nlist"; then
+ sed 's/^\(.*\) \(.*\)$/ {"\1", \&\2},/' < "$nlist" >> "$objdir/$dlsyms"
+ fi
+
+ cat <<\EOF >> "$objdir/$dlsyms"
+ {0},
+};
+
+#ifdef __cplusplus
+}
+#endif
+EOF
+ ;;
+
+ *)
+ echo "$progname: unknown suffix for \`$dlsyms'" 1>&2
+ exit 1
+ ;;
+ esac
+ fi
+
+ # Now compile the dynamic symbol file.
+ $show "(cd $objdir && $CC -c$no_builtin_flag \"$dlsyms\")"
+ $run eval '(cd $objdir && $CC -c$no_builtin_flag "$dlsyms")' || exit $?
+
+ # Transform the symbol file into the correct name.
+ compile_command=`$echo "$compile_command" | sed "s%@SYMFILE@%$objdir/${output}S.o%"`
+ finalize_command=`$echo "$finalize_command" | sed "s%@SYMFILE@%$objdir/${output}S.o%"`
+ elif test "$export_dynamic" != yes; then
+ test -n "$dlfiles$dlprefiles" && $echo "$progname: warning: \`-dlopen' and \`-dlpreopen' are ignored without \`-export-dynamic'" 1>&2
+ else
+ # We keep going just in case the user didn't refer to
+ # dld_preloaded_symbols. The linker will fail if global_symbol_pipe
+ # really was required.
+ $echo "$progname: not configured to extract global symbols from dlpreopened files" 1>&2
+
+ # Nullify the symbol file.
+ compile_command=`$echo "$compile_command" | sed "s% @SYMFILE@%%"`
+ finalize_command=`$echo "$finalize_command" | sed "s% @SYMFILE@%%"`
+ fi
+
+ if test -z "$link_against_libtool_libs" || test "$build_libtool_libs" != yes; then
+ # Replace the output file specification.
+ compile_command=`$echo "$compile_command" | sed 's%@OUTPUT@%'"$output"'%g'`
+ finalize_command=`$echo "$finalize_command" | sed 's%@OUTPUT@%'"$output"'%g'`
+
+ # We have no uninstalled library dependencies, so finalize right now.
+ $show "$compile_command"
+ $run eval "$compile_command"
+ exit $?
+ fi
+
+ # Replace the output file specification.
+ compile_command=`$echo "$compile_command" | sed 's%@OUTPUT@%'"$objdir/$output"'%g'`
+ finalize_command=`$echo "$finalize_command" | sed 's%@OUTPUT@%'"$objdir/$output"'T%g'`
+
+ # Create the binary in the object directory, then wrap it.
+ if test -d $objdir; then :
+ else
+ $show "$mkdir $objdir"
+ $run $mkdir $objdir || exit $?
+ fi
+
+ if test -n "$shlibpath_var"; then
+ # We should set the shlibpath_var
+ rpath=
+ for dir in $temp_rpath; do
+ case "$dir" in
+ /*)
+ # Absolute path.
+ rpath="$rpath$dir:"
+ ;;
+ *)
+ # Relative path: add a thisdir entry.
+ rpath="$rpath\$thisdir/$dir:"
+ ;;
+ esac
+ done
+ temp_rpath="$rpath"
+ fi
+
+ # Delete the old output file.
+ $run $rm $output
+
+ if test -n "$compile_shlibpath"; then
+ compile_command="$shlibpath_var=\"$compile_shlibpath\$$shlibpath_var\" $compile_command"
+ fi
+ if test -n "$finalize_shlibpath"; then
+ finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
+ fi
+
+ if test -n "$perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $perm_rpath; do
+ rpath="$rpath$dir:"
+ done
+ compile_command="$runpath_var=\"$rpath\$$runpath_var\" $compile_command"
+ finalize_command="$runpath_var=\"$rpath\$$runpath_var\" $finalize_command"
+ fi
+
+ case "$hardcode_action" in
+ relink)
+ # AGH! Flame the AIX and HP-UX people for me, will ya?
+ $echo "$progname: warning: using a buggy system linker" 1>&2
+ $echo "$progname: relinking will be required before \`$output' can be installed" 1>&2
+ ;;
+ esac
+
+ $show "$compile_command"
+ $run eval "$compile_command" || exit $?
+
+ # Now create the wrapper script.
+ $show "creating $output"
+
+ # Quote the finalize command for shipping.
+ finalize_command=`$echo "$finalize_command" | sed "$sed_quote_subst"`
+
+ # Only actually do things if our run command is non-null.
+ if test -z "$run"; then
+ $rm $output
+ trap "$rm $output; exit 1" 1 2 15
+
+ cat > $output <<EOF
+#! /bin/sh
+
+# $output - temporary wrapper script for $objdir/$output
+# Generated by ltmain.sh - GNU $PACKAGE $VERSION
+#
+# The $output program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of \``pwd`'.
+# If it is, it will not operate correctly.
+
+# This environment variable determines our operation mode.
+if test "\$libtool_install_magic" = "$magic"; then
+ # install mode needs the following variables:
+ link_against_libtool_libs='$link_against_libtool_libs'
+ finalize_command="$finalize_command"
+else
+ # When we are sourced in execute mode, \$file and \$echo are already set.
+ if test "\$libtool_execute_magic" = "$magic"; then :
+ else
+ echo='$echo'
+ file="\$0"
+ fi
+
+ # Find the directory that this script lives in.
+ thisdir=\`\$echo "\$file" | sed 's%/[^/]*$%%'\`
+ test "x\$thisdir" = "x\$file" && thisdir=.
+
+ # Follow symbolic links until we get to the real thisdir.
+ file=\`ls -ld "\$file" | sed -n 's/.*-> //p'\`
+ while test -n "\$file"; do
+ destdir=\`\$echo "\$file" | sed 's%/[^/]*\$%%'\`
+
+ # If there was a directory component, then change thisdir.
+ if test "x\$destdir" != "x\$file"; then
+ case "\$destdir" in
+ /*) thisdir="\$destdir" ;;
+ *) thisdir="\$thisdir/\$destdir" ;;
+ esac
+ fi
+
+ file=\`\$echo "\$file" | sed 's%^.*/%%'\`
+ file=\`ls -ld "\$thisdir/\$file" | sed -n 's/.*-> //p'\`
+ done
+
+ # Try to get the absolute directory name.
+ absdir=\`cd "\$thisdir" && pwd\`
+ test -n "\$absdir" && thisdir="\$absdir"
+
+ progdir="\$thisdir/$objdir"
+ program='$output'
+
+ if test -f "\$progdir/\$program"; then
+EOF
+
+ # Export our shlibpath_var if we have one.
+ if test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+ cat >> $output <<EOF
+ # Add our own library path to $shlibpath_var
+ $shlibpath_var="$temp_rpath\$$shlibpath_var"
+
+ # Some systems cannot cope with colon-terminated $shlibpath_var
+ $shlibpath_var=\`\$echo \$$shlibpath_var | sed -e 's/:*\$//'\`
+
+ export $shlibpath_var
+
+EOF
+ fi
+
+ cat >> $output <<EOF
+ if test "\$libtool_execute_magic" != "$magic"; then
+ # Run the actual program with our arguments.
+ args=
+ for arg
+ do
+ # Quote arguments (to preserve shell metacharacters).
+ sed_quote_subst='$sed_quote_subst'
+ arg=\`\$echo "\$arg" | sed "\$sed_quote_subst"\`
+ args="\$args \\"\$arg\\""
+ done
+
+ # Export the path to the program.
+ PATH="\$progdir:\$PATH"
+ export PATH
+
+ eval "exec \$program \$args"
+
+ \$echo "\$0: cannot exec \$program \$args"
+ exit 1
+ fi
+ else
+ # The program doesn't exist.
+ \$echo "\$0: error: \$progdir/\$program does not exist" 1>&2
+ \$echo "This script is just a wrapper for \$program." 1>&2
+ \$echo "See the $PACKAGE documentation for more information." 1>&2
+ exit 1
+ fi
+fi
+EOF
+ chmod +x $output
+ fi
+ exit 0
+ ;;
+ esac
+
+
+ # See if we need to build an old-fashioned archive.
+ if test "$build_old_libs" = "yes"; then
+ # Now set the variables for building old libraries.
+ oldlib="$objdir/$libname.a"
+
+ # Transform .lo files to .o files.
+ oldobjs="$objs"`$echo "$libobjs " | sed -e 's/[^ ]*\.a //g' -e 's/\.lo /.o /g' -e 's/ $//g'`
+
+ if test -d "$objdir"; then
+ $show "$rm $oldlib"
+ $run $rm $oldlib
+ else
+ $show "$mkdir $objdir"
+ $run $mkdir $objdir
+ fi
+
+ # Do each command in the archive commands.
+ if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
+ cmds=`eval \\$echo \"$old_archive_from_new_cmds\"`
+ else
+ cmds=`eval \\$echo \"$old_archive_cmds\"`
+ fi
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS=';'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ fi
+
+ # Now create the libtool archive.
+ case "$output" in
+ *.la)
+ old_library=
+ test "$build_old_libs" = yes && old_library="$libname.a"
+
+ $show "creating $output"
+
+ # Only create the output if not a dry run.
+ if test -z "$run"; then
+ cat > $output <<EOF
+# $output - a libtool library file
+# Generated by ltmain.sh - GNU $PACKAGE $VERSION
+
+# The name that we can dlopen(3).
+dlname='$dlname'
+
+# Names of this library.
+library_names='$library_names'
+
+# The name of the static archive.
+old_library='$old_library'
+
+# Version information for $libname.
+current=$current
+age=$age
+revision=$revision
+
+# Directory that this library needs to be installed in:
+libdir='$install_libdir'
+EOF
+ fi
+
+ # Do a symbolic link so that the libtool archive can be found in
+ # LD_LIBRARY_PATH before the program is installed.
+ $show "(cd $objdir && $LN_S ../$output $output)"
+ $run eval "(cd $objdir && $LN_S ../$output $output)" || exit 1
+ ;;
+ esac
+ exit 0
+ ;;
+
+ # libtool install mode
+ install)
+ progname="$progname: install"
+
+ # There may be an optional /bin/sh argument at the beginning of
+ # install_prog (especially on Windows NT).
+ if test "$nonopt" = "$SHELL"; then
+ # Aesthetically quote it.
+ arg=`$echo "$nonopt" | sed "$sed_quote_subst"`
+ case "$arg" in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$arg "
+ arg="$1"
+ shift
+ else
+ install_prog=
+ arg="$nonopt"
+ fi
+
+ # The real first argument should be the name of the installation program.
+ # Aesthetically quote it.
+ arg=`$echo "$arg" | sed "$sed_quote_subst"`
+ case "$arg" in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$install_prog$arg"
+
+ # We need to accept at least all the BSD install flags.
+ dest=
+ files=
+ opts=
+ prev=
+ install_type=
+ isdir=
+ stripme=
+ for arg
+ do
+ if test -n "$dest"; then
+ files="$files $dest"
+ dest="$arg"
+ continue
+ fi
+
+ case "$arg" in
+ -d) isdir=yes ;;
+ -f) prev="-f" ;;
+ -g) prev="-g" ;;
+ -m) prev="-m" ;;
+ -o) prev="-o" ;;
+ -s)
+ stripme=" -s"
+ continue
+ ;;
+ -*) ;;
+
+ *)
+ # If the previous option needed an argument, then skip it.
+ if test -n "$prev"; then
+ prev=
+ else
+ dest="$arg"
+ continue
+ fi
+ ;;
+ esac
+
+ # Aesthetically quote the argument.
+ arg=`$echo "$arg" | sed "$sed_quote_subst"`
+ case "$arg" in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$install_prog $arg"
+ done
+
+ if test -z "$install_prog"; then
+ $echo "$progname: you must specify an install program" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ if test -n "$prev"; then
+ $echo "$progname: the \`$prev' option requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ if test -z "$files"; then
+ if test -z "$dest"; then
+ $echo "$progname: no file or destination specified" 1>&2
+ else
+ $echo "$progname: you must specify a destination" 1>&2
+ fi
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ # Strip any trailing slash from the destination.
+ dest=`$echo "$dest" | sed 's%/$%%'`
+
+ # Check to see that the destination is a directory.
+ test -d "$dest" && isdir=yes
+ if test -n "$isdir"; then
+ destdir="$dest"
+ destname=
+ else
+ destdir=`$echo "$dest" | sed 's%/[^/]*$%%'`
+ test "X$destdir" = "X$dest" && destdir=.
+ destname=`$echo "$dest" | sed 's%^.*/%%'`
+
+ # Not a directory, so check to see that there is only one file specified.
+ set dummy $files
+ if test $# -gt 2; then
+ $echo "$progname: \`$dest' is not a directory" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+ fi
+ case "$destdir" in
+ /*) ;;
+ *)
+ for file in $files; do
+ case "$file" in
+ *.lo) ;;
+ *)
+ $echo "$progname: \`$destdir' must be an absolute directory name" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+ esac
+ done
+ ;;
+ esac
+
+ # This variable tells wrapper scripts just to set variables rather
+ # than running their programs.
+ libtool_install_magic="$magic"
+
+ staticlibs=
+ future_libdirs=
+ current_libdirs=
+ for file in $files; do
+
+ # Do each installation.
+ case "$file" in
+ *.a)
+ # Do the static libraries later.
+ staticlibs="$staticlibs $file"
+ ;;
+
+ *.la)
+ # Check to see that this really is a libtool archive.
+ if egrep '^# Generated by ltmain.sh' $file >/dev/null 2>&1; then :
+ else
+ $echo "$progname: \`$file' is not a valid libtool archive" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ library_names=
+ old_library=
+ # If there is no directory component, then add one.
+ case "$file" in
+ */*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Add the libdir to current_libdirs if it is the destination.
+ if test "X$destdir" = "X$libdir"; then
+ case "$current_libdirs " in
+ *" $libdir "*) ;;
+ *) current_libdirs="$current_libdirs $libdir" ;;
+ esac
+ else
+ # Note the libdir as a future libdir.
+ case "$future_libdirs " in
+ *" $libdir "*) ;;
+ *) future_libdirs="$future_libdirs $libdir" ;;
+ esac
+ fi
+
+ dir="`$echo "$file" | sed 's%/[^/]*$%%'`/"
+ test "X$dir" = "X$file/" && dir=
+ dir="$dir$objdir"
+
+ # See the names of the shared library.
+ set dummy $library_names
+ if test -n "$2"; then
+ realname="$2"
+ shift
+ shift
+
+ # Install the shared library and build the symlinks.
+ $show "$install_prog $dir/$realname $destdir/$realname"
+ $run eval "$install_prog $dir/$realname $destdir/$realname" || exit $?
+ test "X$dlname" = "X$realname" && dlname=
+
+ # Support stripping libraries.
+ if test -n "$stripme"; then
+ if test -n "$striplib"; then
+ $show "$striplib $destdir/$realname"
+ $run $striplib $destdir/$realname || exit $?
+ else
+ $echo "$progname: warning: no library stripping program" 1>&2
+ fi
+ fi
+
+ if test $# -gt 0; then
+ # Delete the old symlinks.
+ rmcmd="$rm"
+ for linkname
+ do
+ rmcmd="$rmcmd $destdir/$linkname"
+ done
+ $show "$rmcmd"
+ $run $rmcmd
+
+ # ... and create new ones.
+ for linkname
+ do
+ test "X$dlname" = "X$linkname" && dlname=
+ $show "(cd $destdir && $LN_S $realname $linkname)"
+ $run eval "(cd $destdir && $LN_S $realname $linkname)"
+ done
+ fi
+
+ if test -n "$dlname"; then
+ # Install the dynamically-loadable library.
+ $show "$install_prog $dir/$dlname $destdir/$dlname"
+ $run eval "$install_prog $dir/$dlname $destdir/$dlname" || exit $?
+ fi
+
+ # Do each command in the postinstall commands.
+ lib="$destdir/$realname"
+ cmds=`eval \\$echo \"$postinstall_cmds\"`
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS=';'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ fi
+
+ # Install the pseudo-library for information purposes.
+ name=`$echo "$file" | sed 's%^.*/%%'`
+ $show "$install_prog $file $destdir/$name"
+ $run eval "$install_prog $file $destdir/$name" || exit $?
+
+ # Maybe install the static library, too.
+ test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library"
+ ;;
+
+ *.lo)
+ # Install (i.e. copy) a libtool object.
+
+ # Figure out destination file name, if it wasn't already specified.
+ if test -n "$destname"; then
+ destfile="$destdir/$destname"
+ else
+ destfile=`$echo "$file" | sed 's%^.*/%%'`
+ destfile="$destdir/$destfile"
+ fi
+
+ # Deduce the name of the destination old-style object file.
+ case "$destfile" in
+ *.lo)
+ staticdest=`$echo "$destfile" | sed 's/\.lo$/\.o/'`
+ ;;
+ *.o)
+ staticdest="$destfile"
+ destfile=
+ ;;
+ *)
+ $echo "$progname: cannot copy a libtool object to \`$destfile'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+ esac
+
+ # Install the libtool object if requested.
+ if test -n "$destfile"; then
+ $show "$install_prog $file $destfile"
+ $run eval "$install_prog $file $destfile" || exit $?
+ fi
+
+ # Install the old object if enabled.
+ if test "$build_old_libs" = yes; then
+ # Deduce the name of the old-style object file.
+ staticobj=`$echo "$file" | sed 's/\.lo$/\.o/'`
+
+ $show "$install_prog $staticobj $staticdest"
+ $run eval "$install_prog \$staticobj \$staticdest" || exit $?
+ fi
+ exit 0
+ ;;
+
+ *)
+ # Do a test to see if this is really a libtool program.
+ if egrep '^# Generated by ltmain.sh' $file >/dev/null 2>&1; then
+ link_against_libtool_libs=
+ finalize_command=
+
+ # If there is no directory component, then add one.
+ case "$file" in
+ */*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Check the variables that should have been set.
+ if test -z "$link_against_libtool_libs" || test -z "$finalize_command"; then
+ $echo "$progname: invalid libtool wrapper script \`$file'" 1>&2
+ exit 1
+ fi
+
+ finalize=yes
+ for lib in $link_against_libtool_libs; do
+ # Check to see that each library is installed.
+ libdir=
+ if test -f "$lib"; then
+ # If there is no directory component, then add one.
+ case "$lib" in
+ */*) . $lib ;;
+ *) . ./$lib ;;
+ esac
+ fi
+ libfile="$libdir/`$echo "$lib" | sed 's%^.*/%%g'`"
+ if test -z "$libdir"; then
+ $echo "$progname: warning: \`$lib' contains no -rpath information" 1>&2
+ elif test -f "$libfile"; then :
+ else
+ $echo "$progname: warning: \`$lib' has not been installed in \`$libdir'" 1>&2
+ finalize=no
+ fi
+ done
+
+ if test "$hardcode_action" = relink; then
+ if test "$finalize" = yes; then
+ $echo "$progname: warning: relinking \`$file' on behalf of your buggy system linker" 1>&2
+ $show "$finalize_command"
+ if $run eval "$finalize_command"; then :
+ else
+ $echo "$progname: error: relink \`$file' with the above command before installing it" 1>&2
+ continue
+ fi
+ file="$objdir/$file"T
+ else
+ $echo "$progname: warning: cannot relink \`$file' on behalf of your buggy system linker" 1>&2
+ fi
+ else
+ # Install the binary that we compiled earlier.
+ file=`$echo "$file" | sed "s%\([^/]*\)$%$objdir/\1%"`
+ fi
+ fi
+
+ $show "$install_prog$stripme $file $dest"
+ $run eval "$install_prog\$stripme \$file \$dest" || exit $?
+ ;;
+ esac
+ done
+
+ for file in $staticlibs; do
+ name=`$echo "$file" | sed 's%^.*/%%'`
+
+ # Set up the ranlib parameters.
+ oldlib="$destdir/$name"
+
+ $show "$install_prog $file $oldlib"
+ $run eval "$install_prog \$file \$oldlib" || exit $?
+
+ # Support stripping libraries.
+ if test -n "$stripme"; then
+ if test -n "$old_striplib"; then
+ $show "$old_striplib $oldlib"
+ $run $old_striplib $oldlib || exit $?
+ else
+ $echo "$progname: warning: no static library stripping program" 1>&2
+ fi
+ fi
+
+ # Do each command in the postinstall commands.
+ cmds=`eval \\$echo \"$old_postinstall_cmds\"`
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS=';'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ done
+
+ if test -n "$future_libdirs"; then
+ $echo "$progname: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2
+ fi
+
+ if test -n "$current_libdirs"; then
+ # Maybe just do a dry run.
+ test -n "$run" && current_libdirs=" -n$current_libdirs"
+ exec $SHELL $0 --finish$current_libdirs
+ exit 1
+ fi
+
+ exit 0
+ ;;
+
+ # libtool finish mode
+ finish)
+ progname="$progname: finish"
+ libdirs="$nonopt"
+
+ if test -n "$finish_cmds" && test -n "$libdirs"; then
+ for dir
+ do
+ libdirs="$libdirs $dir"
+ done
+
+ for libdir in $libdirs; do
+ # Do each command in the postinstall commands.
+ cmds=`eval \\$echo \"$finish_cmds\"`
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS=';'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd"
+ done
+ IFS="$save_ifs"
+ done
+ fi
+
+ $echo "To link against installed libraries in LIBDIR, users may have to:"
+ if test -n "$shlibpath_var"; then
+ $echo " - add LIBDIR to their \`$shlibpath_var' environment variable"
+ fi
+ $echo " - use the \`-LLIBDIR' linker flag"
+ exit 0
+ ;;
+
+ # libtool execute mode
+ execute)
+ progname="$progname: execute"
+
+ # The first argument is the command name.
+ cmd="$nonopt"
+ if test -z "$cmd"; then
+ $echo "$progname: you must specify a COMMAND" 1>&2
+ $echo "$help"
+ exit 1
+ fi
+
+ # Handle -dlopen flags immediately.
+ for file in $execute_dlfiles; do
+ if test -f "$file"; then :
+ else
+ $echo "$progname: \`$file' is not a file" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ dir=
+ case "$file" in
+ *.la)
+ # Check to see that this really is a libtool archive.
+ if egrep '^# Generated by ltmain.sh' $file >/dev/null 2>&1; then :
+ else
+ $echo "$progname: \`$lib' is not a valid libtool archive" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ # Read the libtool library.
+ dlname=
+ library_names=
+
+ # If there is no directory component, then add one.
+ case "$file" in
+ */*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Skip this library if it cannot be dlopened.
+ if test -z "$dlname"; then
+ # Warn if it was a shared library.
+ test -n "$library_names" && $echo "$progname: warning: \`$file' was not linked with \`-export-dynamic'"
+ continue
+ fi
+
+ dir=`$echo "$file" | sed 's%/[^/]*$%%'`
+ test "X$dir" = "X$file" && dir=.
+
+ if test -f "$dir/$objdir/$dlname"; then
+ dir="$dir/$objdir"
+ else
+ $echo "$progname: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2
+ exit 1
+ fi
+ ;;
+
+ *.lo)
+ # Just add the directory containing the .lo file.
+ dir=`$echo "$file" | sed 's%/[^/]*$%%'`
+ test "X$dir" = "X$file" && dir=.
+ ;;
+
+ *)
+ $echo "$progname: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2
+ continue
+ ;;
+ esac
+
+ # Get the absolute pathname.
+ absdir=`cd "$dir" && pwd`
+ test -n "$absdir" && dir="$absdir"
+
+ # Now add the directory to shlibpath_var.
+ if eval "test -z \"\$$shlibpath_var\""; then
+ eval "$shlibpath_var=\"\$dir\""
+ else
+ eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
+ fi
+ done
+
+ # This variable tells wrapper scripts just to set shlibpath_var
+ # rather than running their programs.
+ libtool_execute_magic="$magic"
+
+ # Check if any of the arguments is a wrapper script.
+ args=
+ for file
+ do
+ case "$file" in
+ -*) ;;
+ *)
+ if egrep '^# Generated by ltmain.sh' $file >/dev/null 2>&1; then
+ # If there is no directory component, then add one.
+ case "$file" in
+ */*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Transform arg to wrapped name.
+ file="$progdir/$program"
+ fi
+ ;;
+ esac
+ # Quote arguments (to preserve shell metacharacters).
+ file=`$echo "$file" | sed "$sed_quote_subst"`
+ args="$args \"$file\""
+ done
+
+ if test -z "$run"; then
+ # Export the shlibpath_var.
+ eval "export $shlibpath_var"
+
+ # Now actually exec the command.
+ eval "exec \$cmd$args"
+
+ $echo "$progname: cannot exec \$cmd$args"
+ exit 1
+ else
+ # Display what would be done.
+ eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\""
+ $echo "export $shlibpath_var"
+ $echo "$cmd$args"
+ exit 0
+ fi
+ ;;
+
+ # libtool uninstall mode
+ uninstall)
+ progname="$progname: uninstall"
+ rm="$nonopt"
+ files=
+
+ for arg
+ do
+ case "$arg" in
+ -*) rm="$rm $arg" ;;
+ *) files="$files $arg" ;;
+ esac
+ done
+
+ if test -z "$rm"; then
+ $echo "$progname: you must specify an RM program" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ for file in $files; do
+ dir=`$echo "$file" | sed -e 's%/[^/]*$%%'`
+ test "X$dir" = "X$file" && dir=.
+ name=`$echo "$file" | sed -e 's%^.*/%%'`
+
+ rmfiles="$file"
+
+ case "$name" in
+ *.la)
+ # Possibly a libtool archive, so verify it.
+ if egrep '^# Generated by ltmain.sh' $file >/dev/null 2>&1; then
+ . $dir/$name
+
+ # Delete the libtool libraries and symlinks.
+ for n in $library_names; do
+ rmfiles="$rmfiles $dir/$n"
+ test "X$n" = "X$dlname" && dlname=
+ done
+ test -n "$dlname" && rmfiles="$rmfiles $dir/$dlname"
+ test -n "$old_library" && rmfiles="$rmfiles $dir/$old_library"
+
+ # FIXME: should reinstall the best remaining shared library.
+ fi
+ ;;
+
+ *.lo)
+ if test "$build_old_libs" = yes; then
+ oldobj=`$echo "$name" | sed 's/\.lo$/\.o/'`
+ rmfiles="$rmfiles $dir/$oldobj"
+ fi
+ ;;
+ esac
+
+ $show "$rm $rmfiles"
+ $run $rm $rmfiles
+ done
+ exit 0
+ ;;
+
+ "")
+ $echo "$progname: you must specify a MODE" 1>&2
+ $echo "$generic_help" 1>&2
+ exit 1
+ ;;
+ esac
+
+ $echo "$progname: invalid operation mode \`$mode'" 1>&2
+ $echo "$generic_help" 1>&2
+ exit 1
+fi # test -z "$show_help"
+
+# We need to display help for each of the modes.
+case "$mode" in
+"") cat <<EOF
+Usage: $progname [OPTION]... [MODE-ARG]...
+
+Provide generalized library-building support services.
+
+-n, --dry-run display commands without modifying any files
+ --features display configuration information and exit
+ --finish same as \`--mode=finish'
+ --help display this help message and exit
+ --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS]
+ --quiet same as \`--silent'
+ --silent don't print informational messages
+ --version print version information
+
+MODE must be one of the following:
+
+ compile compile a source file into a libtool object
+ execute automatically set library path, then run a program
+ finish complete the installation of libtool libraries
+ install install libraries or executables
+ link create a library or an executable
+ uninstall remove libraries from an installed directory
+
+MODE-ARGS vary depending on the MODE. Try \`$progname --help --mode=MODE' for
+a more detailed description of MODE.
+EOF
+ ;;
+
+compile)
+ cat <<EOF
+Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
+
+Compile a source file into a libtool library object.
+
+COMPILE-COMMAND is a command to be used in creating a \`standard' object file
+from the given SOURCEFILE.
+
+The output file name is determined by removing the directory component from
+SOURCEFILE, then substituting the C source code suffix \`.c' with the
+library object suffix, \`.lo'.
+EOF
+ ;;
+
+execute)
+ cat <<EOF
+Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]...
+
+Automatically set library path, then run a program.
+
+This mode accepts the following additional options:
+
+ -dlopen FILE add the directory containing FILE to the library path
+
+This mode sets the library path environment variable according to \`-dlopen'
+flags.
+
+If any of the ARGS are libtool executable wrappers, then they are translated
+into their corresponding uninstalled binary, and any of their required library
+directories are added to the library path.
+
+Then, COMMAND is executed, with ARGS as arguments.
+EOF
+ ;;
+
+finish)
+ cat <<EOF
+Usage: $progname [OPTION]... --mode=finish [LIBDIR]...
+
+Complete the installation of libtool libraries.
+
+Each LIBDIR is a directory that contains libtool libraries.
+
+The commands that this mode executes may require superuser privileges. Use
+the \`--dry-run' option if you just want to see what would be executed.
+EOF
+ ;;
+
+install)
+ cat <<EOF
+Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND...
+
+Install executables or libraries.
+
+INSTALL-COMMAND is the installation command. The first component should be
+either the \`install' or \`cp' program.
+
+The rest of the components are interpreted as arguments to that command (only
+BSD-compatible install options are recognized).
+EOF
+ ;;
+
+link)
+ cat <<EOF
+Usage: $progname [OPTION]... --mode=link LINK-COMMAND...
+
+Link object files or libraries together to form another library, or to
+create an executable program.
+
+LINK-COMMAND is a command using the C compiler that you would use to create
+a program from several object files.
+
+The following components of LINK-COMMAND are treated specially:
+
+ -all-static do not do any dynamic linking at all
+ -allow-undefined allow a libtool library to reference undefined symbols
+ -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime
+ -dlpreopen FILE link in FILE and add its symbols to dld_preloaded_symbols
+ -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
+ -LLIBDIR search LIBDIR for required installed libraries
+ -lNAME OUTPUT-FILE requires the installed library libNAME
+ -o OUTPUT-FILE create OUTPUT-FILE from the specified objects
+ -rpath LIBDIR the created library will eventually be installed in LIBDIR
+ -static do not do any dynamic linking of libtool libraries
+ -version-info CURRENT[:REVISION[:AGE]]
+ specify library version info [each variable defaults to 0]
+
+All other options (arguments beginning with \`-') are ignored.
+
+Every other argument is treated as a filename. Files ending in \`.la' are
+treated as uninstalled libtool libraries, other files are standard or library
+object files.
+
+If the OUTPUT-FILE ends in \`.la', then a libtool library is created, only
+library objects (\`.lo' files) may be specified, and \`-rpath' is required.
+
+If OUTPUT-FILE ends in \`.a', then a standard library is created using \`ar'
+and \`ranlib'.
+
+If OUTPUT-FILE ends in \`.lo' or \`.o', then a reloadable object file is
+created, otherwise an executable program is created.
+EOF
+ ;;
+
+uninstall)
+ cat <<EOF
+Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
+
+Remove libraries from an installation directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, all the files associated with it are deleted.
+Otherwise, only FILE itself is deleted using RM.
+EOF
+ ;;
+
+*)
+ $echo "$progname: invalid operation mode \`$mode'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+esac
+
+$echo
+$echo "Try \`$progname --help' for more information about other modes."
+
+exit 0
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
diff --git a/makecopyright b/makecopyright
new file mode 100755
index 000000000..5e17fd329
--- /dev/null
+++ b/makecopyright
@@ -0,0 +1,124 @@
+#!/bin/sh
+
+
+copyright_glib ()
+{
+ cat << EOF
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+EOF
+}
+
+copyright_gdk ()
+{
+ cat << EOF
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+EOF
+}
+
+copyright_gtk ()
+{
+ cat << EOF
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+EOF
+}
+
+copyright_interp ()
+{
+ cat << EOF
+/* GTK Interp - The GTK Interpreter
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+EOF
+}
+
+
+exclude_files="./glib/gconfig.h"
+
+for file in `find . -name "*.[ch]" -print`; do
+ exclude=`echo $exclude_files | grep $file`
+
+ if test "x$exclude" = "x"; then
+ dir=`dirname $file`
+ if test "x$dir" != "x."; then
+ subdir=`basename $dir`
+
+ grepout=`grep Copyright $file`
+ if test "x$grepout" = "x"; then
+ backup_dir="$dir/bak"
+ if test ! -d $backup_dir; then
+ echo "making directory: $backup_dir"
+ mkdir $backup_dir
+ fi
+
+ echo $file
+
+ filename=`basename $file`
+ cp $file $backup_dir/$filename
+ copyright_$subdir > $file
+ cat $backup_dir/$filename >> $file
+ fi
+ fi
+ fi
+done
diff --git a/missing b/missing
new file mode 100755
index 000000000..e4b838ca9
--- /dev/null
+++ b/missing
@@ -0,0 +1,134 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+# Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+# Franc,ois Pinard <pinard@iro.umontreal.ca>, 1996.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program 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 General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+if test $# -eq 0; then
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+fi
+
+case "$1" in
+
+ -h|--h|--he|--hel|--help)
+ echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+ -h, --help display this help and exit
+ -v, --version output version information and exit
+
+Supported PROGRAM values:
+ aclocal touch file \`aclocal.m4'
+ autoconf touch file \`configure'
+ autoheader touch file \`config.h.in'
+ automake touch all \`Makefile.in' files
+ bison touch file \`y.tab.c'
+ makeinfo touch the output file
+ yacc touch file \`y.tab.c'"
+ ;;
+
+ -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+ echo "missing - GNU libit 0.0"
+ ;;
+
+ -*)
+ echo 1>&2 "$0: Unknown \`$1' option"
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+ ;;
+
+ aclocal)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. It should be needed only if
+ you modified \`acinclude.m4' or \`configure.in'. You might want
+ to install the \`Automake' and \`Perl' packages. Grab them from
+ any GNU archive site."
+ touch aclocal.m4
+ ;;
+
+ autoconf)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. It should be needed only if
+ you modified \`configure.in'. You might want to install the
+ \`Autoconf' and \`GNU m4' packages. Grab them from any GNU
+ archive site."
+ touch configure
+ ;;
+
+ autoheader)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. It should be needed only if
+ you modified \`acconfig.h' or \`configure.in'. You might want
+ to install the \`Autoconf' and \`GNU m4' packages. Grab them
+ from any GNU archive site."
+ touch config.h.in
+ ;;
+
+ automake)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. It should be needed only if
+ you modified \`Makefile.am', \`acinclude.m4' or \`configure.in'.
+ You might want to install the \`Automake' and \`Perl' packages.
+ Grab them from any GNU archive site."
+ find . -type f -name Makefile.am -print \
+ | sed 's/^\(.*\).am$/touch \1.in/' \
+ | sh
+ ;;
+
+ bison|yacc)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. It should be needed only if
+ your modified any \`.y' file. For being effective, your
+ modifications might require the \`Bison' package. Grab it from
+ any GNU archive site."
+ touch y.tab.c
+ ;;
+
+ makeinfo)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. It should be needed only if
+ you modified a \`.texi' or \`.texinfo' file, or any other file
+ indirectly affecting the aspect of the manual. The spurious
+ call might also be the consequence of using a buggy \`make' (AIX,
+ DU, IRIX). You might want to install the \`Texinfo' package or
+ the \`GNU make' package. Grab either from any GNU archive site."
+ file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
+ if test -z "$file"; then
+ file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+ file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
+ fi
+ touch $file
+ ;;
+
+ *)
+ echo 1>&2 "\
+WARNING: \`$1' is needed, and you do not seem to have it handy on your
+ system. You might have modified some files without having the
+ proper tools for further handling them. Check the \`README' file,
+ it often tells you about the needed prerequirements for installing
+ this package. You may also peek at any GNU archive site, in case
+ some other package would contain this missing \`$1' program."
+ exit 1
+ ;;
+esac
+
+exit 0
diff --git a/mkinstalldirs b/mkinstalldirs
new file mode 100755
index 000000000..fef1eb941
--- /dev/null
+++ b/mkinstalldirs
@@ -0,0 +1,36 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Last modified: 1994-03-25
+# Public domain
+
+errstatus=0
+
+for file in ${1+"$@"} ; do
+ set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+ shift
+
+ pathcomp=
+ for d in ${1+"$@"} ; do
+ pathcomp="$pathcomp$d"
+ case "$pathcomp" in
+ -* ) pathcomp=./$pathcomp ;;
+ esac
+
+ if test ! -d "$pathcomp"; then
+ echo "mkdir $pathcomp" 1>&2
+ mkdir "$pathcomp" > /dev/null 2>&1 || lasterr=$?
+ fi
+
+ if test ! -d "$pathcomp"; then
+ errstatus=$lasterr
+ fi
+
+ pathcomp="$pathcomp/"
+ done
+done
+
+exit $errstatus
+
+# mkinstalldirs ends here
diff --git a/stamp-h.in b/stamp-h.in
new file mode 100644
index 000000000..9788f7023
--- /dev/null
+++ b/stamp-h.in
@@ -0,0 +1 @@
+timestamp
diff --git a/tests/3DRings.xpm b/tests/3DRings.xpm
new file mode 100644
index 000000000..1ca75da75
--- /dev/null
+++ b/tests/3DRings.xpm
@@ -0,0 +1,116 @@
+/* XPM */
+static char * DRings_xpm[] = {
+"48 48 65 1",
+" c None",
+". c #104010404103",
+"X c #1040208130C2",
+"o c #104014515144",
+"O c #000010402081",
+"+ c #1040104030C2",
+"@ c #208120815144",
+"# c #28A241035965",
+"$ c #30C230C26185",
+"% c #208130C24103",
+"& c #104010402081",
+"* c #104000002081",
+"= c #000010401040",
+"- c #492441036185",
+"; c #596559659E79",
+": c #30C220815144",
+"> c #0820186128A2",
+", c #000000001040",
+"< c #2081104030C2",
+"1 c #514459659658",
+"2 c #514455556185",
+"3 c #104000001040",
+"4 c #000008200000",
+"5 c #618569A6AEBA",
+"6 c #618569A69658",
+"7 c #410345148E38",
+"8 c #104020814103",
+"9 c #79E782079658",
+"0 c #208120814103",
+"q c #596571C69E79",
+"w c #4103514471C6",
+"e c #2081208130C2",
+"r c #6185618571C6",
+"t c #28A228A25965",
+"y c #596561858617",
+"u c #96589E79BEFB",
+"i c #28A230C271C6",
+"p c #38E345145144",
+"a c #79E78207A699",
+"s c #30C2492469A6",
+"d c #410330C25965",
+"f c #410351446185",
+"g c #AEBAAAAAD75C",
+"h c #38E338E34103",
+"j c #EFBEEBADEFBE",
+"k c #208130C25144",
+"l c #9658A289DF7D",
+"z c #208110404103",
+"x c #28A228A26185",
+"c c #8E388A28BEFB",
+"v c #208118612081",
+"b c #38E3451479E7",
+"n c #4924618579E7",
+"m c #86178617B6DA",
+"M c #30C220814103",
+"N c #104030C25144",
+"B c #4103410371C6",
+"V c #86178A28D75C",
+"C c #DF7DDB6CE79D",
+"Z c #BEFBC30BD75C",
+"A c #410330C271C6",
+"S c #30C228A230C2",
+"D c #082008201861",
+"F c #186130C238E3",
+"G c #0000208130C2",
+" .Xo ",
+" O+O@#$% ",
+" &*=+X-;: ",
+" >&=,=<11#2 ",
+" +O34,X567& ",
+" 8X+=,90q9w. ",
+" +e<>3r tyu-& ",
+" Xi%.= paus+ ",
+" Od-@= fga$h ",
+" @y7X, Xrjak ",
+" 2:eaw+ $ag;@ ",
+" .X@8@k@o@X+ +pl9tO ",
+" +zX@x$$isikt8o02crv ",
+" 8@%ip7757ywbs$Ohn6#. ",
+" &0%$p7r215ybw1pzp2-0= ",
+" 8tk$#yw21665n;1+%-p$O ",
+" O<e7pbryq5am9ay6XMpM>3& ",
+" 9.NtpBw16amclVcm1t%kX*88 ",
+" +&etd7r6y9ulgglm6>e>3s@83 ",
+" +0k$y-y69cgCCCZVam%+#ik8X ",
+" O&oi$d725amgCjCZu962ybtx8+p ",
+" &X0x$sBym9VZCCCZca;yBbi%08& ",
+" =++@sApMy5muZZgum6y2wds:>+& ",
+" #tp;1;yB#i25cVucma5;w-pti@8& ",
+" .#2alumnBp:@1r59y9y6ywBS$%0X+= ",
+" %$wmZVu;#tX8X07r1656y2wbp$k@%@OD ",
+" 0Byc9a;h%0>&D&hBrr2r1bwB-AF:0<&*= ",
+" kBf;yr#@X+&<%MkhsBwBwpsB#Bktkt8+Oh ",
+" xt7B-t8*,3O.X00:$i#dBd#bptFek0X.+* ",
+" Xt#b#@=, =&O+X0Ft%ibsp$p$ki%l5sX&= ",
+" &<kvX&4 +O*&<X0e:%$pAti%:edugn0= ",
+" +X@&+, V,O&>+Xt>tktktv0%@k;Cls+ ",
+" =+O*4*X:p;9cy3&&8ve0FMtt$ee0>z7cZ6k ",
+" D=D4,=.k$sBs$ee=+X0Fk%-#t%0X&O0nu9bG ",
+" ,,434*&ze@F<eeeeee><tdhdSMe<&&XAaawx ",
+" 4,4,=+><peeeeee&=<%M%$hSF0X&O&kw5r%Z ",
+" D&vSFMF<>&D =0S-2i& ",
+" +>puB> >0h7s. ",
+" SM5VqM &0t#$8 ",
+" XpVV70 &0kMk. ",
+" XdyB%z *X<%@+ ",
+" &k$b0X+=8X08o ",
+" &e:e+=*X.X+& ",
+" +X.O+X0O.=, ",
+" +>&+0>3&* ",
+" &X0k+O, ",
+" >v,3 ",
+" "};
diff --git a/tests/FilesQueue.xpm b/tests/FilesQueue.xpm
new file mode 100644
index 000000000..586d27ec4
--- /dev/null
+++ b/tests/FilesQueue.xpm
@@ -0,0 +1,98 @@
+/* XPM */
+static char * FilesQueue_xpm[] = {
+"44 31 64 1",
+" c None",
+". c #E79DE38DDF7D",
+"X c #CF3CC71BCF3C",
+"o c #71C675D671C6",
+"O c #B6DAB2CAB6DA",
+"+ c #CF3CD34CCF3C",
+"@ c #DF7DE38DE79D",
+"# c #FFFFFBEEFFFF",
+"$ c #EFBEEFBEEFBE",
+"% c #DF7DDB6CDF7D",
+"& c #BEFBBAEAC71B",
+"* c #BEFBBAEABEFB",
+"= c #BEFBC30BC71B",
+"- c #71C66DB671C6",
+"; c #D75CD34CD75C",
+": c #9E799A699E79",
+"> c #E79DE38DE79D",
+", c #CF3CCB2BC71B",
+"< c #B6DAB2CABEFB",
+"1 c #BEFBBAEAB6DA",
+"2 c #B6DAB6DAB6DA",
+"3 c #618561856185",
+"4 c #C71BBAEABEFB",
+"5 c #AEBAAAAAAEBA",
+"6 c #965892488E38",
+"7 c #A699A699A699",
+"8 c #38E338E338E3",
+"9 c #F7DEF7DEF7DE",
+"0 c #E79DEFBEEFBE",
+"q c #DF7DE38DDF7D",
+"w c #C71BC71BC71B",
+"e c #C71BC30BBEFB",
+"r c #BEFBC30BBEFB",
+"t c #B6DAAAAAAEBA",
+"y c #410345144103",
+"u c #D75CDB6CD75C",
+"i c #C71BCB2BC71B",
+"p c #BEFBCB2BBEFB",
+"a c #9E79A289A699",
+"s c #86178E388E38",
+"d c #CF3CCF3CD75C",
+"f c #CF3CD75CCF3C",
+"g c #C71BC30BCF3C",
+"h c #28A22CB228A2",
+"j c #000000000000",
+"k c #D75CD34CDF7D",
+"l c #10400C300820",
+"z c #E79DEBADEFBE",
+"x c #DF7DDB6CD75C",
+"c c #514459655965",
+"v c #8617861779E7",
+"b c #DF7DD34CD75C",
+"n c #CF3CCB2BCF3C",
+"m c #618555555965",
+"M c #861786178617",
+"N c #30C234D330C2",
+"B c #EFBEEBADE79D",
+"V c #DF7DDB6CE79D",
+"C c #D75CE38DD75C",
+"Z c #514449245144",
+"A c #186120812081",
+"S c #79E77DF779E7",
+"D c #6185659569A6",
+"F c #9E7992489E79",
+" .XoOX+ ",
+" @#$%&*=-o;: ",
+" @>,=O<12*&:-<3X ",
+" >%&1*4*2*OO**56758790 ",
+" 9qX+we=r*&e<<<251t5555yu9 ",
+" $qu++;ipi=p*=p**2tOOO27a5s<- ",
+" #9udfXi;,gi&**4**4r*Ot5t55tehj ",
+" 0qku+u;+d,gg=*=r*&**&<255t<*yl1 ",
+" $$zq@%xk%uf;,w,i=i=e**r=12tO1=8cvj ",
+" $@%>.%.%%%xbkx,w+ni,wwrwe*4*1=;8mMNj ",
+" zz@Bz>>>V%%%C+u;;dfnnfwggi&=&X+yZsNll ",
+" af#9@B0>q>qqq>xk.;;;kfX+XnXw=g,fycMhhN5 ",
+" al5#9$$>qzBV.%x%%b;x+fnf+,X,iiqym6NAo-j ",
+" #roS%#$zz>>V%%xkk%f;;+df,XnwnVZD:8AS-j* ",
+" D-9Oy*9$Bz>q%qx%%u;x;;dknX+d>Zm:hhSDjr ",
+" a3o+>S3z#90@@z.%>qCC%uu;ff%@Zm:NhMoj= ",
+" wlvvo#:3599$>B>q>%%%%+f;fk$ymaalMvjr ",
+" 0.a--S49mct9$z@.qkkqC;xu%@Zm5AlvSj* ",
+" ohu%3:Z:9@y609q@@>..>Cx>$Zm5NhMvjr ",
+" -j797Zv5705y=#$0>>V.%>#Z378AMMj* ",
+" Zj9Xo-McBXDv%90.%%#9cc78AsMj* ",
+" 8hM#M-DSF96cvz0>z#c35Nhs6j1 ",
+" jl9#o63vx#-D###mmt8N66j* ",
+" 5jc@fZF3o%+ZFDm<8A6FjO ",
+" :j50sSay<$ss2Nh:FjO ",
+" 6880&SDMF.rNNFFj1 ",
+" 8jr#:SFScA6ajO ",
+" Alr$DSysajO ",
+" >jy#51:jO ",
+" %Dy*gjO ",
+" alla "};
diff --git a/tests/Modeller.xpm b/tests/Modeller.xpm
new file mode 100644
index 000000000..62e27f985
--- /dev/null
+++ b/tests/Modeller.xpm
@@ -0,0 +1,117 @@
+/* XPM */
+static char * InterfaceModeller_app_2_Tile_xpm[] = {
+"48 48 66 1",
+" c None",
+". c #86174D344103",
+"X c #69A651445144",
+"o c #8617410330C2",
+"O c #69A6410338E3",
+"+ c #30C218611861",
+"@ c #AEBA6DB66185",
+"# c #71C638E328A2",
+"$ c #69A634D328A2",
+"% c #30C228A228A2",
+"& c #79E73CF330C2",
+"* c #BEFB9E799E79",
+"= c #8E3869A66185",
+"- c #514424921861",
+"; c #A699A289B6DA",
+": c #A6999E79A699",
+"> c #71C65D756185",
+", c #9E799A69A699",
+"< c #8E3882078E38",
+"1 c #861779E78617",
+"2 c #A6999A69AEBA",
+"3 c #8E388A289658",
+"4 c #71C675D679E7",
+"5 c #96588A289E79",
+"6 c #30C230C238E3",
+"7 c #C71BC71BC71B",
+"8 c #9E79A289AEBA",
+"9 c #AEBAAAAABEFB",
+"0 c #96589248A699",
+"q c #A699AAAAB6DA",
+"w c #AEBAAAAAB6DA",
+"e c #D75CD34CD75C",
+"r c #EFBEE79DEFBE",
+"t c #BEFBB6DABEFB",
+"y c #B6DABAEAC71B",
+"u c #AEBAAEBAB6DA",
+"i c #E79DDB6CDF7D",
+"p c #96588E389658",
+"a c #596559656185",
+"s c #AEBA8E388E38",
+"d c #CF3CCB2BCF3C",
+"f c #9E799A699E79",
+"g c #86177DF78E38",
+"h c #69A6659571C6",
+"j c #AEBAAEBABEFB",
+"k c #96589E799E79",
+"l c #B6DAA699A699",
+"z c #E79DC71BC71B",
+"x c #B6DAB6DAB6DA",
+"c c #861786179658",
+"v c #B6DAB2CABEFB",
+"b c #BEFBAAAAAEBA",
+"n c #C71BBEFBC71B",
+"m c #514441034103",
+"M c #41033CF34103",
+"N c #492428A228A2",
+"B c #AEBAA289B6DA",
+"V c #618530C22081",
+"C c #69A630C228A2",
+"Z c #69A630C22081",
+"A c #596528A22081",
+"S c #492428A22081",
+"D c #618528A22081",
+"F c #596520811861",
+"G c #69A628A22081",
+"H c #FFFF14514103",
+" .X ",
+" .oO+ ",
+" @.o#++ ",
+" @.o$%+ ",
+" @.&#++ ",
+" @.o#++ ",
+" @.o$++ ",
+" @.&#++ ",
+" .O#++ ",
+" *=-$++ ",
+" ;:>+++ ",
+" ;,<1% ",
+" 2,34 ",
+" 2;,51 ",
+" 2,,,,6 ",
+" 7777 28888,6 ",
+" 77777777 2829,,,06 ",
+" 9qwwe7rrrrr77rr 828,9tyt,6 ",
+" uuwriirrieiiieii77pa< 82,8,,,8,06 ",
+" s=1ttiieeeeded77eufgh>j,8,8,k,0,6 ",
+" =@lzieeeeee77eeex:fpcg4>9,,,,qjv6 ",
+" =O=blt7eeee7deenw:ffp<gha:t979;06 ",
+" =OO@=@zieeee7ex:::fffff0,v72444h6 ",
+" =OOo&Osst7iee7wkf:f:ff;t721444ham ",
+" =#&&&&OO@di7eu:ff:fferiv114444hmMX ",
+" =O&&&..o.sdp33fff:errrii7cc1hhh6mmNX= ",
+" =O&&&@.o.@sberrrrrriiuxuxnB;44aMmVCO#OX ",
+" =O&&o@..o.zrrrie777nnxtuxx:x;n:>mV##&&O$mX ",
+" =O&&o....zrrieieuxunx7txx:nnfwpMmVZ#$ZZZVVN ",
+" =O&oooo.*rrde77ewxnxxtnw:f4M%M%+NA#$Z$ZZVmN> ",
+" =Oo&ooo@iree7inxn7nnuuff4h%M>m%S-AZ$CCZDZmSX ",
+" =O&o.o.@rrn7eulun7xxuwp4mm6ahM%--AZCCZDDDANX ",
+" =Ooooo.*rixenuwwn7nxupph%M>>h6mAADVVZVVDDANX ",
+" =O&o.o.zrexwwnwuxxnughX%mahhmMN-AZCCVVDDAAN> ",
+" *XOoo.*iin7n777xxxtphaM+ama>MSNFVCZZVVDAAAS> ",
+" 1O..izewxux7nuuux4%++%hha>%N-DDCZZVDAAAASX ",
+" 1.=ituu:uButnxxuX%>hh>M%++NADZZZVDADAA--X ",
+" :e7f::lnn7*ppnx6ahm6++mNN-ADCZVDDAAAA-SX ",
+" 7nupp:wxxg%MMau6%++NmmmADADVVVVVDAA---NX ",
+" 7uBgh1wwxg6h>m%:MmmVNAVDZVZCVZZDAAAAF-S+X ",
+" nfgaM%pnwhX6%mXb6$DVVZC$C#C$ZZDVAAA---+NX ",
+" 27a%MaM47:mN.OoolmODGZ####$$ZZVDDA-----SSX ",
+" 2gmg<m6p7wmmOo...O$GZ####$$CZVVDAAA----++X ",
+" qBcaM <gxgmXmo.@.o&$$##$$$CZZZDADA-A-++-NX ",
+" M6> paMa HX.@@@oZ$###$$CZVDDAAAA---SS+X ",
+" 43 p=&@@&&$##$CCCVVVAAA--+S+S+%X ",
+" k =o@.##$VVmmmNNNSSSSSS%XXXX ",
+" s>OSSNmN>>aaa177777 "};
diff --git a/tests/marble.xpm b/tests/marble.xpm
new file mode 100644
index 000000000..1ef260761
--- /dev/null
+++ b/tests/marble.xpm
@@ -0,0 +1,408 @@
+/* XPM */
+static char *granite07[] = {
+/* width height num_colors chars_per_pixel */
+" 384 384 16 1",
+/* colors */
+". c #000000",
+"# c #111111",
+"a c #222222",
+"b c #333333",
+"c c #444444",
+"d c #555555",
+"e c #666666",
+"f c #777777",
+"g c #888888",
+"h c #999999",
+"i c #aaaaaa",
+"j c #bbbbbb",
+"k c #cccccc",
+"l c #dddddd",
+"m c #eeeeee",
+"n c #ffffff",
+/* pixels */
+"aacfedbbcbbaaaaaaaaabaabaaaaabcbcbbbabbchfdcccbbabbbaaabaabcbaa#aa#######a#aaaabcddeefhec##dgbabbaaadabbcfbaa##########aaabbaaa#a#####a#aa###a#aaabbbbcbbbccdedaaaaa#aaaaa#a#abaaabbabbbeddbbaaaaaca##a#aaaba########aaaadcababbabdehd.##.a######.cgdcb###b##.##.##aaaaa####abcba######a##aac#a##a####aa#aa##babbbcfccbbbcdccccecbbbcbbbcdccddcbcdfeecbhhjihhgffc.aaa####.#######aaaaaaaabbaaaaa",
+"aaacedccbbcbaaaaaa#bbaabbbaaaabcaabbbbbbafhfccbbbbbbabacbacbaaaaa##########a###abbcdeghhhcagb#ababaaccbacdfca#a####aa###aaaaabaaa#####aca#aabaababbcccccccbcdfdaaaa###aaaaaaaaaaabbbbbbccccccbbcbcaaa##aaaaabaaaa###abdaccceebaaaabehja####a######..#aeec#bb##########aa#####abba#########aaca########aa#aa###aaaabddbbbbbbbbbbccbbabbbbabbabbabcbcbcefhfeddccefhhijheecb#...a####aaaaaaaabaaaaa",
+"aaabccccccdbabcbaaa#aaaaaaaaaaabbabbbbbccabefdccabcbbabacccbaaabaa######a######aaabceiiiihije#bbabbaaeaabcedcaabaa########aaaabaa##a###ab#aabcababbccccccdeeeecc#a##a##aaaaaaaaaabbbbbbbcccbbbdcbbcdaa#a#aabbaaaaa###acbaa#bccaa#abcfig.#######.#######acddgefdda#######a########a#######aaaaaa#a######aaaa#####aaacdcbabbaaabbbcaaaaaaaaabbbaaabbaabbbcbcbabbabcdeefghjkjgc#..####aaaaaaaaaaaa#",
+"#aaaaaacbccbcabbbaaaaaabcaaaaabbbbbbabbbcbaabffccbccbccbbcbaaaabaaaa#aa#aa##a#aaaaabbikkjhijicabbbcc#faaacdebcbda#########aaaaaaaaa####aa##cacccabcccdccccdddfdcbaa##a##abbbabccbbcbbbccccaaa#abbaaba#a##abbbbbaaaaaaaaaaccaaca##aabcfic.###aa#######a####bddeeddb####.##.###aaa#########aaaa###aa####aaaa#######aabdbbbbcabbbaaaa#aaaaaaaaabaaabbbaabbbbdbbaaabccccccdcefhhkhda##aaaa#a#aaaaa##",
+"#aaabaabcecbaa##bcaaaaaaaababbabaaabbabbaabb#chhfdccccbcbecaaabaaaaaaaaaa####aaaaaaabdgjkkijijdabbdcabfaabcecbbec###########a#aaaabaa#######abbaaaadddedddeeefeccaa###a#aabcccdcbcbbbbccbbbbaaaaa#aabbaaaabbbbbbaaaaaaabbbbbaaa####acegha##a#aabbb####a##adccdedbcc#######.###a###a#######aaa#a#aa##..#aa#########abdbaabbabbbaa###aaaaaaaaaaaaacbaaababbdbabbabcbbcbcbccbbdegjkgb#aa#aa#aaaaaaa",
+"##aa#aabccccaaaaaaaa#aaaaaabbaabbbaaaaabbbcbbcfhhgfcccbbbbccbaabbaaaaaaabaa#aaaabaaaabbcehkljjdabacccbgbaaccdb#adea#########aa#abaaaaa#####ac#ba##accdedddefffeaba##a#aaaaacccccccbbbcccaabaaaaaaaaa#aaaaabcbbaaa#bbbbaaefccdbaaa#aaacdei##aa##aabbbaaa#a#cdcccccbcea.#########bbaaa######a###a#aaaa.#aaba####.###abcbaaabaabbbaa###aaaaaaaaaaaabbaaaaaaaaaaababcbbcbbaabbbdddeghheba##ab#abaa##",
+"#####bbaaaaabaaaaa##aa#adccaabaaabbbbabbabbbabccbccfdbccbbbbbcaabcaabaaabbaaaaaaaaaaaabbbcglli#accbbbddgabcddbbaacea#a##########aaa#aaa##aaaa####aabcddeeefffgdbbaaaa###baabbbbbbcdabdcbcaaabaaaaaaa#aaaaaabcbbbbadfbbbaejhhebbccaaaaaccfi.aba##abaaaba####ecbbccba#fc.####.##.bba#a#######aaaaaaaaaaa##aaaa######abcdaa#aaaabaaa###aaaaabaaabbbaaba##aaababcbbcbbbbbcbaaabbccccddgggeb#aadca###",
+"#####bcaaaaaabcbaaa#aaaabcccaaaaaaabaaabbbbbbbaacbabeeddddccbcbbcccbabaaaabaabaaaaaaaaabbbbglmdbcbaabebdgdbcecbbaabdbaa#########aabbaaaa#aa#a##a#aabbdceeedccdcbbaaaaa##aaabbcbbbabaaabbababbaaaa#aaaaaaaabcdccbbbabcbbbcfijfbcdcabb#abcbif#abb##aaabaaaa##fcccbbcaa#db#..##.##.aaa#########ab#aaaaaa#aabaaaaa#####abdbbaaaabbaaaa###b#a#aaaabaaaaaaaaaaaaaabbabbbbaabbbaaaabbbbbbbceffecccbaa##",
+"#####abaaaaa#accbbbbaaabaaaaaaaaaaadcbaabbabbbabbdcaacgfddddcdddcadfcaaaabcbbabaaaaaabcabbbdjliacbababcbdfcdeeaaaaaabba########a##aa#aabaa##a######abddeggca#bcbaaaaaa####aaaaaabbbbbcbbbbbaaa##a#aaaaaaaabcbccbbaaaabaabfgfiecccccbbaaaccicbbbcbaaabaaabb#ceccccdca##aacdb######aaa###a###aabaaaaaa#aabca#abba#####abca##aaaaaaaaa##a##aaaaaaabaaaaaaabaaaacbcbacdbaaabaaaaaabaaaaabbcddccbaa##",
+"####aa#aaaaaaabccbabbaaaaaaaaaaaaabfaaabbcbbbbbabdebaabdffddedefedccecccdcbbbbbccbccbbbbbbccekldaabaaabccbfaaaaaaaaaaaba########aaaaaaaaba##aaa###aabbccfgfaababbbaaaaa#aabbaabaaccaabcccbcbaa##aaaaaabaabbbccbbbaabbbbbbdddghdbbbcccb#abcdebcccbaabbbabbcbaecddddbaa##.#acdeca#######a#aaaaaaaaaaaaaaabba##abba####aacba##aaaaaaaaaaaaa##aba#abaaaaaaabaaaabbbbbbcbabbaabbaaaaabaaaaaaaaccbaa##",
+".####aa#aabaa##bccbaabbbba#aaaaabbaefdaabbbbccbbbaddaaabadeeffhhhffdedddeecbbbbcccbbabcbabbcfjjlkeaaaaacdadcaa#aaaaaaa#ab######ba#aaabbabcaa#aa###babcddcedba##acbaaaaaa#ababbbacbbbcccdfffbaa#aaaacbaabcbabccbbcbbbbbbcbbccedbbbccdccbaabcgb#bccbbbababbbcccdededcb#a####...addcba##aabbbbbbbbaaaaabba#aaa##abba####abbaa###a#aa#aa##aaa#a##abaaaaaaaaabababbcdbcb#baaaaaaaaaaaaaaaaaa#aaaaa###",
+"######a##aaaaaa#accbaaabbbaaa#aaababdcaaabbbbcccbbbdbabbbacdccgecadbbbcdccddeddcccccbaabcbbcgjhhjgeb#aacdcccaa#aa#aaa#a#aaa##aaaaa#aaabbaabb#aa###aabccddeccbbbaabcbbbcbbb#aacbbadbabcccddbaaa#aaaaabbbbabbbbcdbbbabbcddcbbbccaabbbccbbaaaadi##abbbbbbbaabbbacdeedbd######aa####bceda#aabbabaaaaaaaaba#aaaaa#aabaaa###acaaaa####aa##aaaaaaaa#aaaaaaaaaaababaaaaabcaaaaaaabbcbaaaaaaaaa###aaaa###",
+"##########aabaa#accbbabbbbbba##aaaabbcbbbbbbbbcbaaabdbbbbbbddccbbbbaaaabbabbbbcefefdcbaadbcddje#debgfbabecdc####aa##a###a#aa#aa##a##aaabbcabbaa###aabbcceedbcbaaaabdcccbabaaabbbbabbccbbaaaaaa#aaaaaaaabbbbbcbccabcccccdcccbbbbabbababbba#abfe#aaaaaaaabccbbaaaedddc######adcaaaa##dfcaaaaaaaaaa#aaaaa##aabcaaabbaa#aaab###aa###aaaaaaaaaaaa##aaaaaaaaaabaaabaaabcabaaaaaaabcbaabaaa##a###aa####",
+"#########aaaaaaabbcbbbbabcbaacbaa##aaabaaabccccccbaabecabbbcddbacdeba#aaaaabaaabbdfgedcbaccdcgica#aadghdbddd#aa#aaa#a###aaaabaa#####aaaaabbbbbba#aaabccceecbddbaa#bbccabcbbbbbacccdbbdabbaaaaaaa#aaaa#aabbbbcccdcbcbbccccccbcaababbdbabbba#bbgaabaaa#aaacccdcddbeedba#a##a#aba#aaaa##decbaaba#aaa###a#a###abba#bba###aaba####a####aaaaaaaaaaaa#aaabbbaaabbaabbaabbaaa#aa#a#abbaabbbaaa#aaaa#####",
+"############aaaaaaacbbbbbbbaa#aaa#a##aaaaaaaacbbbbbbabdcabbbcdbaccdba#aaaaaababbcbbdddedccddefihaa#aaahiiiffd#aaaa#abaa##aaaaacaa##a#bcaaaabbbcaaaabccdddecabaaaaacbbbabbccccccbbdbdfdaabbaaa###a#aaaaaaaabbbbbbbaaabdcddccbbbbabbbccaabbbaabfdaaabaa#aa##aabbbbbddba##aa#a#aa##aaaaaabcdbbaaa##aa#####a#aaabbaaaaa##abb######aa###aaaaaaaaaaaaaaaaabaaaaaaaabbbbaaabaaa#aaaaaaabbbaaaaaaaaa####",
+"###########aa#aa#aaaccabbaaaaaaabb#######a#aaabcbbbabbaeebbccbcbacdaaa##a#aabbbbccbbcbcdegifdfgifba##aaaagigha#aaaaabbaaaaaaaaabaaa##acaaaaabbbbbbabcdddefeba####abbaabccccbbbcbadcbcbaabba#aaaa#aaaaaababacccbaadbabbccedcccbbccbbabaaaaa##ade###abba#aa##abbba#cebb.#a####.#a#aaaaaaaaacfca#aaa###aa###abaabaaaaaaaabbaa#######aaaaa#aa#aaaaaaaaaaababdaaabbbbbababaaaaaa#aaaaaabbaaabaaaaa###",
+"##########a#aaabaaaaccaaaaaaabaaaaaaba###a##abaaabbababaccbcbbcccaaba#a###aaabbccdccccccdeegggfigaabb#aaa#fffcba#abbaaaaaaaaaaa#abba##aaa##aabbbcbbbbcdeegfeb####aabaabacbbbcbccaabbabaaaaaaa##aa#aaaaababbabbcbcdbbcccbddcdcccabcbbababba###afba#aabba#acaaabbbbaddb##aa####.####aabbaaaabffcaaaaaa##a##bcabbaaaaaaabbbc#a#a#######aaaaa#####a##ababbbbbaaaabbcbaaaaaaaaaaa#aaaaaabaaababaaaaa#",
+"#######a#####a#aaaaabcbaaaaaa#aabaaaaaa###abbabaaaaaccaaabdbccbccbaaca#####accddcccccccddeeefikjeabcca#a#abfifbaa#abbbbbaaaaaaaaa#bbba#bcaaaaaaaccbcccceffeccaa##aaabbbcabbacbddbbaabdbaaaaaaaaaaaaaaabbbaabbbbbbbbbcbbccccdcdcccabbbbbaaba###dcaaaabbaaabaabcbccaadba#aaa########aaaa##aaaacgdbaaaa####cfffda#a#aaaabbdbaa#aaa########aaaa#aa##aaabbabbbaaabbbaaaaaabaaaaaaaa#aaaaabaaaaaaaaa#a",
+"a###########aaaaaaaabbaabaaa###abaaa#a##a###a#aaaaabacaaabccbbbcbbbcbb####a#bdfbbccccccdefecdgiiddaabbaaaabacfeaaaaaabcccbaaaaaaabaaacaa##aaaaaaabccddcfgfgbabaaa#aaabbcccbccbcddbbacabbbbbbbbaaacbaaaabcbabbbbbcbbcbccbccdccdccdcbaabbbaabaaade#aa#baaabaa##abbcbacdb#.#abbccc#.##aaa####aa#aeeaaaaaaabbabddfgfba#aabcd#aaaa########aa##a##aaaaaababbaabbbbbabccbababaaaaaaa##a#aaaabbaaaaaaaa#",
+"#a###a######aaaaaaaacdaaaaaaaa#aaaaaaaaaa#####a###abbbbaaaaccbbbcbbbbaa#aaaaaeecabcccbccdedcdfgigeaaaacbaaabaacbaaaaaaabcbbbaaaaaaaaabccaaaaaaaaaacccceffffbabb#a####aaaabcccccddcdedbbbbaabcabbbccbccbcbcbbbbbbbbbcecbccccceccccdccbbaaaaaaabce#bbaaa###aaa##ababcacda#abb##a#######a#########bfdca#abcbaabaabcffddbabdc#aaaaa##########aa####aaaaaaabbabbbbbbbcbbbcbaaaaaaaa#aa#aaaaaabaa##b##",
+"##a#########aabaaaabcdbabaaaaa##aaaaabaaba######a##ababbbbbabbbbcbcdddbbaa#abceecabccccccdddfedgjgdbaaabaaabbbaaba#aabaabaccaaaaaaaabbccbbbaaabaaabcddefgfebbbb#aa####aaaabbcccccbbfeccbbbaaababbbbbbbccba#abbbabbcdccdcbddcddcccdcddcbaaaaaabcfbadaa#######a#abbacbbcc###a#a########a######a##aabdcabccbbababaaaacdfededbbaa#aa##aa######ba#aa#aaabbabaababcbbcbcbbbabbaaaaaaaa##aaabaaacba#a##",
+"##########a#abaaaaabbbcbbbcaa###a#aaaaa##aba#######aaaaaabbdccbaabccdddecaaaabccdbbacccddcdefdfgiifcba#bbaaabbaaaababbbbbbbabbaabaaaacbbbcbbaaaaaaaceeeefffbaaaa###a##aaaabbcbbbddcddddcbcbbaaabbbbababbabaaabababbbbcccdccddcddccccdecaaaa#abccfbbaaa#######aabbaacabe###a#aa#a#a##.aa#######a#aa#cfeecdcccccabbbabacggcabbaaabbaaaa####aabb#aaaabbababbbbbbcccbbbbbcccbbbaaaa#aaaaaababbaaaa##",
+"######a####abcbaaaaabbccbcbaa###a##aaa##a###aa######aaaaaabdgebaaabbbccacbaaaaabbbaaabccddcdeeffgigbaaaaaabaabcaaababbbbaabbacbaaabbaaaababccbabbabbdffefhdcaaa###aaabba#aababcbdeeccceccccbababbbbabbabbaaaaaabbaabbcbcccccdcddddccccdcaaaababcdeaba#####.###aaabaab#b####a####a##aa#b########aaaaabedddcccccaaaabbcabeaaaabbccbaaa#abbaaabbbaaaabbbaaacbcbcbbdccbaabbacbbbbbaaaaaaaaabbaa#####",
+"######aaa#abbcbaaaaabdccbbaaa#######aaa#####aaa##a#a##aaaababcbbaaaaabdebbbaaa##aaaaaaaabccddeefggieaaaaaaaacabaabbbabbbbaaaabbaaaaaaabbbabbccbaabbbdfgghebbbaa#####abba#aabbbcbccdcbbbcddcccbbbabbabbbabbabaaaaaaacbbabcbbccccddddccbcccaaaaaabbdcbc##########aaacbbaa####a####aa###a#aa###aaa###abbceddedcccbaaaacccdca##a#abbbabaaaabaaabbba#aabbbbbbccbbbbaaacccbbcbbaaabbbbbbabaaabaaaa####",
+"#######aa#aaccabbabaabdecbb#a########aaaa####aaa#aba##a#aaaaaaabbdcaabdcbcaacb####abb#abaabccdeffghfdabaaaa#acbbbbcbabcabcbaaaabbbabaaaabbbbbcccbbbccdfedccbbb#########aaaababbacccbcbbbddbdcccccbbbbaaaabbaabbaaaaabaabbbbccdcceedccccacbaaaabbbbddb####aa######aabbaa####a####aa#aa###a#####aa#aabbddeccddccbbbabbbbceb###aa#aaaaaa##aa####aaaa#abbbbbccacccbaa#accbbbbbaaababbabaaaaaaaaa####",
+"##a#####aaaaaabbbbabacdddccaa########aa#a#####aaa#aa#aaaaaaaaaaaabcabbcbbbbababa###baaaaaaabccdeeehifbabaaa###abbcbbcaccbcbbbaabbbbabaaabbbbbbbbcccccddbccbbbbba#######aaabbbaabbcccbdcbbdbbddcdcccbabaabaaaaaaaaaaaaaaaabbcccddecccbbacccbbbaabbbceca############aaaaa#############a#############aaaaabccddcbbbabbbbbbba#####a##a####aaa#######aaa#babaabbcbaaa##abbbaabbcbbbbaaaaaaaabbaaa####",
+"#########abaaabbabbbbbddeccca##aa######a#aa####bbaaaaaaaaaaaaaaaaaabccbcccebacfdb#####aaaaaaabcdddcfgfccbaa##a##abcbbcbbdcccccabbabaababbbbbbbbbbcdccddbabbbbbba########aaababbbacdccccaabcbbcabddddbbaaabbabbbaaaaaaaaabbbddcddecbccbbbdcbabbbaabbcda#############abaaaa############a####bb##a####aaaaabcffdcccbbbbbbbb#######aaa###aaaa#######aabaaaabbcbaaaaaaaa#aaaaaabbccbbaaaaaabbbaaa####",
+"#########aaabbabcbbbbbdddcbaaaaa###############aabaaaa#aaaaaaaaaaabbabbdefffccbba###aa##aaaaaabcdceecggdcbbaa##aa#aacbb#bcdddddabbbbbabbbabbbbbbbccfeedbbbbbbcbba#a#####a#acababbbdcbcbabbabaabaabeedcaaaaaaaabcbbaaaaaaabbcdfdddccbbbbcbccbabbbaaabcda########a#aaaaaaa#aa#####aaabaaaaaaacb##aaa#aaababbcdefddbbcbccbaa#####aaaaaaaab##a########aa#abbcccbaaaaaa###aaaaabaabccbbbaaaaaaaaa####",
+"########aaaaaaabbbbbbcdedbbbbabaa##########aa###bbb###a##aaaaaaabbaabbbdfeedb##a#a##aa###aaabbbbccdefbfecbbbaaa####a#adb#acdecdfcbaabcbbbbcbbbbbbcdeffbcccabbcdbbba#a###a#aabaaaaaccccbaaaaabbbbaabdfedaaaababbbbbaaaaaaababbcedcccbbbbaccccbaaaccbbabeb######aaaaa#aaa###a######aaaaaaabacbca#aaaaaabbbbccdegfeccccccbcbaaa#####aaaa#aaaaa###a###aaaabbbcccb##a#aaa#aaaaaaaabbdeddcbabaaaaa####",
+"#########a#aabbbbbbbbdddccbbba#aaaa##aa##a####a#bba#a#a#aaaabaabbbabbeedeeefdaaaa#####bb##aaabbabcddehgifffdcbaaaa#aa#aaaaaccdeddcabbbcbbbccbabbccdceeecdcaaaabbcccaaaaaaaaaaaaaabacdddbaabaabbbbcccccfdbaabbaabbcaaaaaaababbcccccbbbbbbbccbcca#acbbbbbda#####aaaa####ab##a######aaaaaaabaccbaaaaabbbbbbccceffcdeedcbbbbaaaa#aaaaaaaaa#aaabaaaaaa##aaaabbbcbbcbaa#####aaaaaabbbcccddcbbaaaaa####",
+"##########a#aabbcbcbbcecccbbbabaaaaaa#####a#aaaabbaa##ba#acaaababbbbbbbcdcfgdbbbaa####aba##aaaabbbccdfefhfgedecaaa##abaaaaacbabebbbbbbbbcccbcbbbbddbedbddcaaaaaabdccaaba#aaaaaa#bbbbbaddccaaabcbbdcbbcbddabbbbbbbccaaaaaaaaabcddcbbbbbbbbbbbbbbaaaabbaabe#########a####bb#aa#####aa#aaaabccdbbbbabbcbbbccccdccbaaeffdbca#aaaa#aaaaaaa#aaaaabaaaa#aaaabaabbccbbcceb#bcaaaaaaaabbbbcdcbbbaaaaa####",
+"#######aa#aaaaabbccbbcdccddcabaaaaaaaaa###aaa#aabcaaa#bba#aabaabbbbbbabcccdfedcaa##aaa######aaaabbbbcdddghhgfedcbaaaa#aaaaabcbbbccbbbbbbbcbccdcccccbeebccbbbaaaaaccccccba#aaaaaaabaaabbbddbbbbcccbcccbaceeacbbbcbccbaaabbabbbbceccbbbbbabbbbbbbab#aabbbbcc#.######a####.bcbcba####aaaa#bedccbbbbbbbaabccddedaaaaa##beeda#aaaaaaaaaaaaaaaaaaaaabba##babbabbbbcbbbccccbbaaaaabbabaabddcbbbaaaa####",
+"##########aaaabbbbccccbcddddbaaaa##a#a#a###aaaa#baabbaaaaaaaabbbabcbaabccbddfebaaba#ba######aaaabbbbbcddfiiigggedbaaaaaaaaaabcbabccbbbbbbbcccddddccceecccccbbaaaabccddbbba#aaaaaaaaabcbbbcccdccbcbabcbabceecbabbbbbbaaaabaabbbcddbbbbbbbbaabbbcbbbbaaabcbdc########..####ccccba#abbaaaabddbabbbcabbbbcccceeca###aaa##aaa##a#aaaaaaaaaaaaaaaaaaaaa##aabcbbbbbbbccbbbbcddaaaaacbaaaabddbbaaaaaa###",
+"############aaabbabcddccdbcdcbcbbbaaaaa##a##aaaa##abaaabaaaaaaabbaacaabddabcefc#aabaaa###a####aaabbbbbbddgihhfffgeaaaaaaaaaaaaabbbcbbbbbbbbbcddeeedceccdcccccaaaaabcbddbaa#a#ab#aaacbbbbbbddebbbbccbbbabbbedbaaaaaaaaaaaabbabbccecbbbbccbbbbaabbbbcc#aaabbcc######a#####.bccabbacbababaabdcabbbabbabbbcbdecabaa##aaaa####aaaaba##aaaaabaaababa##aa#aaabbbbbbbbcbbbbacbedbaaa#bbaaaabcbbbbaaaa#aa",
+"#######a####aaaaabaabbcccbabbbbbbbcbaaa######a#aa######aaaa#aaa#acbbbabeeebabddbaaabaa####aa#a#aababbbbbcehhgeeffdca##aaaaaaaaaabbbbabbbbbbcdcdddfgfhcbbcbbbcbaaaaabcccdbba###baaaabcbbaabcdeecaaabbbbbbaabddecaaaaaaaabbbbbbbccfcbcbbbbbbbaaaaabbbcca#aabacc#######a####acdcbbbbbbaaaabbccaabbbbbbbabbceecabb#aa#aaaa#######aaa##aaaaaaabbaaaaaaaaaaaabbbaabccbbcbaaacgdaaaa#aababbbabbbbaaaaa#",
+"###a#####a#aaaaaabcbacbbddcaaabbbbbbbaaaaaa##a#####a####aaaaa#aaabdbcbbedefcaaabaaaaabaaa#a##abaaaaababbbcfgggfeefea##aaaaaaaaaaabcbbbbbbbbcdcdddefgeabbbbaabccaabaaceddeeaaa##aaaaaabbbabbcdedbabbbaaaaaaaacfecaaaaabaabbbbbbcdfdbccbbbbbaaaaaabbbcdbaa#aabdb#########a#acdcccbaaab#aabccbbbbbbabbbceedccbcbbaaaa#baa#a###a#a##aa###aaaabaaaaaaaa##aaaabbaaabcbbbbbabbdfeaaaa#ababbcbbaabaaaaaa",
+"#####a#####aaaaaabbbbbbbcddcbabccaaabbaaaaa#a##a##a######aaaaaabaaaaacbbbffeaaaababbabbbbbaa##bbaaaabbbbcccghghgeffbaaabbaaaaaabbabccbbbbbbcdddefggecccbabaaabbbacbabbdddecbaa####aabaababbcccdcabaa#aaa###abceedcaaaaabbbbccddefdccdccbcbbaaaaabbccdccdb#abbd###a#####a#a#cddcccaaaaaaaaabccbbbbdeefbba##aabaaa#aaaaaa#aa###aaa##a####aaaaaaaaaaaa##aaaabacbabbbbbcbbbbcfgbaaa#aa#abbab#aaaabba",
+"##########abaaabbbbbcbcdcccdcbbbcbbbbbba#aaaaa#a############aa#aaaaaaababbdeaaaacbbbbbddcbaaa##abaaaabbbbcccghhhedecababcbaaaaaababcbbbbbccbddceggffecccbbbaaabca#aaaadddedcb#a##aaaabbbabbbbcccdd###aaaa#aa##bcefeddcddccefdddfdcccccccccbbaaaaaabccccdddaabbda########ab##bbbddcbbaa#aaaabcbbbcdddccaaaaa#abaaaaaaaaaa#aa#aaaabaa#####aaaaaaaa#######aabaacbabbbbbbcbbbbdfbbaaaa###baabaabaaba",
+"###########aaaabbcbbbcccbddbcdccbbbbcabbaaaaaaaaa###a##aa###aaaabaaababbccbbdb#abccabddbbbba#aaaabdbbaabbbbcdehihbaabbbbcdcbbbbaababbedcbbaccdddeeefedabbabaaa#aaa#aa#beeeeffca###aaabbbcbbbbbbcced#a###a##aaa#abffgfedcccfhcbdebcbccdccccbbaaaaaabbcccccddbaabdcb#.#aa#aaa##abdddcbbbaaababbbbbcbdbabbbbbb##ababbbaaaaa#aa#aa##aaa######ababaaa#####a#aabcbbbabbbbbbcccbbbeabcbba###aaaaaaaaaab",
+"b#########aaaaababbbbabbbbdebcccccbbbabaaaaaaaaaaaa########aa#abbaaabbabbdbcbbbaaadcbcbdbabba##aa##abcb#aaabcdcfhgdabbbccdcbcbbbbbbabcgdcbdbbdedeeehfgdbbbbbaaaa#aaa#abddddgeedcaaaaaabbbdccccccbceeaa###a###aaaacfghhgedccggefbccccccccccbbbbbbaabbcccccccdaabaaccb#aaa###a##adedccbcbaaabbbbcbbcddbaaabbbbaadbbaabbaaa##abaaa#aaaaaaaa#aaabaa########abbadccaaabbbcccccbbdcbcbbba###aaaaaaaabb",
+"aa##########aaabbbbbbbaabbaccbceeebbaabbaabaaabbbbaaa###aaaba#aabaaaaababbccggcbaabccbbbccbca##aaaabdbbabbabbcdddghbabbccddcbbbcbbbbbccgfcbccceddddeddedddcbababaaaaaa#accdeffedbaaaaaaaacccccbbbccffb#a#####aaaaabfhgghhhhgghecbccbccccccccbbbbaaabbbbcbbbcdcbbabbcb#####abca#abccccccabbbbbbbbbdddbaaaaabab#cdba#aabaaaaaaaa#aaa#a#aa#####aaaa#######aabbbbccbbbabbdeddcbbeaabbcb###aaaaaaaaab",
+"baaa######a#aaabaabdbbcbabbaccccedaaaaaaaaaaaaaaadbaa#aaaa##aaaaaaaaabbbcbcccdbaaaaabdcbacbcdcaaaaaaaabaaccbbccdddhgcabcccdecbcbbcbbabadedbbcdedcddeeccdddeeedcbbcbaabbbabbcddddec#aaaaaabbcccccbccdffc##a##a#aaaaaafheffhgeccefcbbcbcccccccbbbbaaabbbbccbbddedbabbcc.##a##abc###cdcccbcbbbabbbaddccababbbaaabaddba##aaaaaa#aaa#a#aaaaa##aa##aaaa#######abbbbccbcbbbbdefeeccecaaaaa####aabaaaaaa",
+"bb#a########aabbbaaababcccdaacdbbaba#aaaaaa#aaa##acaa###aa#aaaaaaaaaaabcdcccaaaaaaaaadbcbbbbacc###aaaaaaaacbbccdcdfggbbbcccdecccddcbbbacdfdbcdebbbcccdcccccdcbefccbaaaaabcbbccabdfcaaaaaaabbdddccccccefe##a##aaaaaaaadfghhhdbbcccccbcbbccdccbbbcaaaabbbbdccddeeba#bbda######.acabbddccabcbbbbbbbddccaaaaaaaaaaabdca#a#aaa#aaaaa##a#aaaaa##aa##aaa#a##a##abbbbccbbdbbccefffeccd#a########abaaaaaa",
+"aa##########aaaaabaabbaaccdcaacbbaab####aaaa#aaaaaa#a####abaaaaaaabcaaabddcacda#aaabacbbbbddddcbaaa##aaaaa#abbdcccdegfbbcdcdefccddccccbcbbfdccecabccbcbbbcdddcbffdcccb#aacbaabcbbeecaa#aaaabcedddccccddfeb#####aaaaaabbehhfcccbcccccbbccccccbcbcbbaaabbbcdcceddcbbabba########bcbbcdcbbbbbbbbaacccccaaaaaaaaaaaabcba####aba##aaaaaa#aaaaaa##a#aaaaaaa#aaabaabbcbbbbbbbdffffeeeaa########aabcaaaa",
+"aba#a#aa####aaaaabbabbabbaccaaabaaaa#######a####aaaaa####aaa#bbaaaabaaacbddcbccaaaaaaaaaaacdeabcbba#a###a#aaabccccdeegfcbcdddeedcdccddccccfedddcbbccbbbbbbccddedecccdca#aaaaaaabacedcddcbabaabccccccccceccd####aaaaaabaacdghhfecccccbbccccccccbcbbbaabbbcccccddcddceaca########cdccdccbbbbbbbbbccbcdcaaaaaaaaaaaaaaba#####aaaaaaa###aaaaa##a####aaaa###aabbbbbbccbdbbbcdefffgaa#a#######aabaaaaa",
+"aa#####aa###aaababbccccbbbbcbaaababa#######a#aabaaaaaa####aa#abbaaaabbaabbdcbbcdbbbbaaaaaabcddbcbba#####a#aaabcdccceefhgbbdcceeeeccccccddeefeeecccacccbcbabbccdefdbcebaaaabaababbbcdcdfffdabbbbbcccccccecade#aa#aabaaaabaackijkidbbbcbccccccccbcbbbbaabbccccccccddegfdaa#######ceedcbbcaacccccbcccccbaaaaaaaaaabaaaaaaaaa####aaa.baa######aaaa####baaa#aaaabbbbbccdcbbcddedfgfb##########abbaaa#",
+"#a########aaaaaaccbbcdcccbbbba#aaaaaa#####aa#aaab#aaaa#.###aa#aabababcbabaccbccdedaaaa#aaaaabccacbaa#a######aacbcccdffhigeccccdeedddccbcddffdefcbabbbcdecbabbbbcddecddbbaaabbabbbcccddeeffabbabbbbcccccdecdedb#a#aaabbaaaaahifgikfcbcccccccccccbbaaabbcbbbccbbbbcccdhea#a#####aedfebccccbbcbcccccccbaaaaaabaa#aaaaaaaaaba#b###aaa#b#######a####aa##abbbabaaabbbbbcdecbbcdedefghc#########abcedcb",
+"a############a#abcbbbcddccbbbcaaaaaa#a####a#a###ba#aa#######aaba#bbbbbccaabcccddeebaaaa##aaaabaaabaaaa#####a#aaaabcbdeggihfccccdddffdcbcccdfcbcbbbbbbccbbbbabaabcdfebcbbca##aabbbbcdcdfffeeaabbbccbbcccdeeddeed##aaabaaaaachgcccfijebbcccccccccbbaaaaabbbaabbaabbcbbcfecaaa#aaadcddbbdcccabbcccbbbabbaaaa#aaa###aaaaaaaaaaaaa##aaaaba######a######a#abbbbbbabbcbbbddcabcddddefgfa########aacedcc",
+"#######aaa#####aaaccccddcdcccbbaaaaa####a####a#aaaa#aa#######abaaabbccacdaadccdddccba#aa#bbaaabaaabaaaaaa#aaaaaababbbdeffiiebcccdddeedcccdcfbcbbbbaabcbbbbbbaaaabcdeefeeddedbaaabcbdccefffffabbbbbbbbbcdcdddddefbaabbbbabaeidccddcejgbbccccccccbbbbaaabaaaaabaaabccccdffebaabbaaddcc#cdccabcccccbbbbbaaaaa#aaaa##aa#aaaaaaaaabaaaba#b##a####a#a#a##a#aabbabbaabbbbddecbbdcccddeega.##.#a##aab###",
+"#########a#####ababccbbbdcccccabbb##aaaaaa#aaaaa##aaaaaa#..###aaaaaaccbbdcbbccdbccdaa##a#a#aaaaaa#ba###a#a#aaaaaaabbbcdeefhgeccedbbcdedeedgebbbbbbbbcdcbbbaabaaabacccddccccbdcaabbadddeefffgfbabbbbccccccccdddbggbaabbbbabhefcccddddihdccccccccbbbababaaa###aa#aabbbcdeeffa.##abcfedabccbcccabcbbbbbbabaaaaa###aaaaaaaabaaaaaaaaaaaaba#######aaab#####aaabaaaabbbaceffecbccddccdec#####.##aa#aa#",
+"#aa########a####abbccbbccdcccbbbbba#a##aaaaabaa#aa####aaba#.##baaaabccdabdbabbbbbcccbaa####aaaaaaa#aaaa######aaaabbabccdfeehihfggfdbceedddeddfdccbbcbbbbbbbbbbaaabaccccbbccdddecababedefffffhgdaaabccbcccccdddbfhfbbbcbbackdeeccdddccfhgbccccbbbaabaaabba#####a#aabbbdeddeda.###aeddcbaaccccccccbbbbbabaaaaaaaaaa##aba##abbaaaaaaaaaab######aa##aa###aaabbbaaaaabbbeffffdcdcdeffda######.###aaa#",
+"#aaa############aabcdcbcdcfedeecbbaba##aaaaabaa###b#a##aaaa####abaaacdcaacdaacbcaaaaaaaabc##aaaabaaaaaa######aaaaabbbdddeddfhhhhhhfcccffffdbaabcbdbabbbbbbbbbbaaaaabbcccbbbbcfdedbbadeddeefdefhffecbbcbcccccceddgibbbbbbdecccbbccccddddhidccccbbaacaaabba########aabccedddeda####cdcecbccccddddcbbbbbabbaaa#a#####a#######abaaaaaaa#aaaa#a##aaaa#a####aabaaaaaaaaabccddfgfddefge################",
+"##aaaaa#aa######aaabdccbccdeefebbaccb###aaabcbaa########aa######aaba#bdbbbcabbbbbbaaba##aba#####ababaaa##a#a##aaaabbcddedddeeefhghfddccdhecbbbaaaababbbabbabcbaaaaaabbccbbbbbbeefdbbbddbddffdggihiebbbcbbcccccedeicbcbbcdccccccccddddddcfifccbbbbabbabbbaaa####aa#aabcedddefeb##.bdcdeccbcccdddcbabbbbaaaaaa#aa############abaa#aaaaa#aaaaaaaaaa#######aabaaaaaaaabbabbcefgecbcc############a#a#",
+"##aaaa####aa##a##aaabcdcbbccdcdccbcaba##aaaabbbaa#aa#a####a######aabaaabaaaaaaaabbba#aa###a##a###abbbaa#aaaa#a##aabbcededddddeghggcdfedffddcbbbaaabbbbbccabbbbbcaaaaabccbbbbbbeccefdbcdbcbcefefhgghdbbcbcccccccdcefedbadccbbcccccddddddddeggcbbbaacaabbbaaa######aaaabdcdeedefbaa#deddcdcbbcdedccbbbcbaaaaaa##################aaaaa#aa##abaaaa#aaa#aa##aaaaaaaaaabaabbacdbacbaaba###############",
+"##a#aaa####aa##a##aaabbbbbcdeccbbaaaaabbaaabbaabaa###aaaa#########aaab#aaaaaaaaabbaaaa#a#a#aa#a#aabaaaa###abb##aaaaabcdeeddefghhhebbbfebbdddccbbbbbaaabdcbcbcbacbaaabbabcbbcccddbbcefecdcbbbcddehgggcbbcbcccccccdddffbbdbbbbbccccddddddddddegcbbaabaaabbbaaa######aaabbbcdefdeca#ddedcdddbacadedccbbbbbabaaaa###############.####aaa##a###a##aaa#aaa#abaabaaaaaaaaaaaaabcdbaaaa#a########a##a###",
+"a##a#aaaa#####aaaaaaabcccbbcdebbaaba#a#bbaaabbaaaa####aaa#####aa#abaaaaaaaabaaaaaabbbaaaaaa#aaaaaababaaa####aaaaaaaabcddddefedhhgbbbbcefbcdedcedabbbababbbcbbbbbbaaabbaabbbbbcbcddbbbcdcebbbbdcabehhebbbbcccccccceddhfddbbbbbccccddddddddddcdfdaaaaaababbaaaaaaaaaaabbbbccddcdfededffddddcbcabcddccbbcbbaaaaa#####################aa##a#a#######aa###aaaaaa###aaaaaaaaaabbccaabaaaa######a######",
+"aaaabaa##aa####aaaaaabbccccbcccaabbba#a##aaaabbb######aaaaba##aaaaababb##aaaaaa#aabaaaa#aaa#aabaaaaaacbaa####aaaaaaabcdeddefefhheabbbbbdfgfgedcfaaabbbbbbaaaaaacabaa#baaabbabaabbdeeeccabdccbbbcaachifbbbcccccbcccddejkeabbbbccccddddddddddccceebabbaabaaaaaaa#aaaabbbcbbcccddefgedfedddcccbaabcdcccbcbcaabaaaa########.##.########aa###a########aaaaa#a###a###aaaaaaaaababccaabaa#########aa#a#",
+"##aaaacb########aaaaabbbbcccbdcddbbcbc#aaaca##a#aba######abca#aaaa#aa###aa###aaaaaabbaaa#a###aaaaaaa##bcbba###a#aaaabbceedddehgfdaaabaccbfhiihffcaaaaccbaaaaaaacabaaabbaabcbbbbbbbcbdeffedfdb#acaabafjgbbcbcccbccccdefiicbbbbacccddddddddccccbbcfbbbbbabaaaaaaaaaabbbcbbbbccccdegfecfdbaabdabbbbcccdcccbbbbaaaa###################a#aa##a#a##a####a#aaaaa###########aaaaaabbbbbaabaa#######aa###",
+"###aaacba#######abaabbdcbbcdcbbefcbabcbbaaaaa####aa#a#a#a#a##aaab###a#aa####abb#a#aacbaa####aaaaaaa#aaabdcbaaaaaaaaabaceefeeffffbaaabbabccehigfeeddefdbabaaaaabbbabaabaaaaabbbbbbabccbabdedda##aaabbachhbbcbccccbbcccdeghebbbaccddddddddddccccbacecbabaaaaaa#aaaaabbbccbbbbcccdcdgfdfebbbbbcccbcbcddccccccbbaaaaa################aabbaaaa####aa###a##aba#############aaaaabbbddbbaba##########.#",
+"####aaaba#######aaaaabdfdbbcccbbdebbaaaab#aaa#a###aa###aaa###aba#####aaa#####aba#aaa#baaa#####aaaaa###aabcccaabbbbbcbbbdfffgeccebaaabbbbcbbeffedccfghhebaaaaaabbaaaaaaaabaabbabbbbbacbbbbcbdda####abbabghabbbccccbbccddddghdaabcddddeedddddcccbbabdfdaaaaa##aaaaaabccccccbbccddcbefdffdcbbbcdccbbccddcccccbbbaaaa################bbccbaabaa#aaaaaa#aabba##a#########a#aaaaabbccbcabaa###########",
+"#####aaaba#######aaacccefcccbcdccbcbbaaaaa#abcba#########aaaaaaa######aaaa####aa##aaa#aaaaaaa##aaaaa##aaaccddcccdddddcceeffdccdccbaaaaabbbbcfggdddfffggfebaaaaaaaaaabaaabccbbbbbbbabccbbbbbcbdb###aabbbbghbacccccccccccdddfigdbcddddddeddddcccbbbabbfeabaa#####aaaabcccccbcbdddecegfffcccabbccccbbccdcccccbbbbaaaa############a#aaaababaaaaaaa#aaa##aaaa#aaa##########aaaaaabbcccbbdba#########.",
+"#####aaaaa######aaabddefcccbabdccccbaaaaaa###aaa######aaabaabbba#######aaaa####a###aaaaaa#a##a#aaaaaaaaaabcddddcdeeedefgfefecdaabbaaaaabbbbbadfebcfdfgffeeecaaaaaaabaaacabdbaaabbbcdcbbbbbbbbccb#a###abbaegcabccccdcccccdddcfihfdccdddddddddcccbaaaaaddbaa######aaabccccbcbccdddhfcfgecccbbbbcbccbccbccbcccbbbbaaaa#a##########aaaaaabccbcba#aa#aa#aaaaa#aaaaa###########aaaabbaddedaa##a#.#####",
+"####aaaaaa#######cffdabcbcdcbbadfbcbbaa###a#aaa#aaaaaaabaaaababaa#######a##a#########aaa##aa##aa#aaaaaaaaabdeddccddddddffeeeec#a#aaabbbaaabbbcggdcfeeeeegfdccbabccbbaaabbbcaaaaabbbcdbbbbccbbbdbaaa###abbccebabbccccbcccccddcdfhjhedddddddddccbbaaaaaabdda#######aaabbddccbbdddedccdgeeedccbbccdccbccbcbccccbbbaaaaa#########.##aaabbaabbbcbaaa###aaaaaaa#a#a#a########aaaaabbaccddeb###########",
+"########aaa######acddbabcbbcccabcddcaabbaaa##aaaaaabbbcaaaabbaaaaaba########aaa#aa###aaa###aa##abaaaaaacbbbcdffeddeccdffffeddbaaaa#abbaaaabaabegebdfeddeffeddddcdddcabbacbcbccbaabbacccbcdbbbcdb#aa##aabbbbbffbbccccbccccccdddedfkkidddddddcccbbaaaaabbabdb#a#####abcccdbccccddfcccdfgeedccbbbcbccccbbabbcccbbbbbbaaa############a#a#aaaacacbaaa####aaa#aa###a##a######aaabaabbbbbbdfa##########",
+"#################abbcbaacccccbccaacbcaaaaaaaaaaaaaaabccabbbbaaab##bb######a#aba##aa##aaaaa##a#a#acabbbacdcbcddffffdgeefefeddcb#a##aaaaabaaaaaaddfdcfdccccccdcbcbcccecbbabccdddddcbbbbccccccbbbceb#aa###aaaabbfgbacccbcccdcdddeedgjkihccddcccccbbaaaabaabaadca####aabbcccbcddccefdcdeeeedddcacbccccccbabaaabbbbbbbaaaa###########.#####aaaabacbba##aaaaaaa####a####a######abbabbcbcbcdb###a##.##.",
+"###########aa#####bdbaaaaccddbbdcba#bbaa##aa#aaaabbbbbbaaabaaaaba##aa.####aaa##a#aaaaaabbbaa#####abaabbbbbccdddeefeffddefdccaa####aaaaaaaaaabaeefdedeccbabbbdddbbccccabbbbbbbbcdcccbcccccccccbaaaa#a####aaaabacgcabbcccdddefffedgijfehdcccccccbbbaa#aaaaaaabcbaaaaaabbccdcdddefgecddeefedccbbbabccbbbbaaaaaabbbbaaaaaa################aaabcbabbaa#aaaaa#aaa###a####a####aaabaabcbbbcbba###aa####",
+"############a#####abaaaaaabddccbcdddbaaaa###aaaabaaabbbaaaabbabba###b######aa######a##aacbcbba##a##babbccccdddddeeefgfeedccdb####a#aaaaaaaaaaadefedecbabbbbbcddddbcddcaabaaaaaabbbbbaabbccdcccbbbcb#a##aa#aaabbbfdbbccddddeffffefggeedjhedcdcccbbaaaaaaaaaaabbcaaaaabbcdcccdeefgdcccdefeccbbbbbbbccbbbbaaaaaaabbbaaaaa#######aa######aaabbbcab#a#aaaaaaaa#a##a#####abaaa#abaabbbbbbdccc####aa#.#",
+"###aaa###a#a#a####aabaaaaaabdbbbcecdcbaaaaaaaa#aaaaaaaaaaaaabccbb###a########a#a#aaaaa##aaaabca#a##aabbccccccdcccbbbbcbcabbbb#a#a#a#aaaabaaaabbeffddeabcbbbbcccccdccbbbaaaaa#abaaaaaaaaaababbbbbcbb#a##a##a#aaaabefcbdeeddeffffffeddfbchjieccccbbbaaaaaaaaaaaacfcabbbbcdddcdehggffeeddgfecbbccbbbccbcbbaaaaaaaaabaaa######a##aaa####aaaaaaabbaa##aaaaaaa#aaaa#####aabbaaaabbbbbbccccddbaaaa####.",
+"####aaaaa#aaaa#aaaaaaabbaaabccbbbcddbbdcbaaaaaabaaaaaabbbbaaaaabaaa###############aaaaa##a#aaaaaaaaaaabbccccdcbbbaaaaaaaabaaa#######aaaaabbbabaacffffbbbbbbbbbbbbccccbaaaaaaaaaaaa##aaaaaaabbccca#######aa###aaaabcgfcdeeefgggggggeffcbbehkjebbcbbaa##aaaa#aaaadheabbbcdddcegfbccdfffgggedccccbbbbbabbbaaaaaaaaabaaaaaa######aaaaa#aa##aaaabaaaaaaaaaaaaa##aaa##aaa#acbaaabababbcccdecbaaaa###a#",
+"#######a###abaaaaaaaaaaabbdccccbbbceefebcaaaaaa#aaaaaabbbcccaabaaa###aaa#######a###aaaba##aaaaaaa#aaaabccccccbbbaaaaaaaaabaa###a###a#aaaaacbababa#eeedbbbbcddbcbccbccccaaaaaaaa#a#aaaaaaaabbbbcba########aa####aabbbghdeeegggggghggfedbbbcdikgbbbbbaa#aaaaaaaaaabheaabccddegdccccdddccfffddbbabbbcbbbbbbbbbbbaaaaaaaa########a###aaaa#a#abaaaaaaaaaaabbabaaaaaaa#a##ccaaaaaaaaaabcccbacaaabaa###",
+"##a#aa#####aaaaaaaaaa#aabbbabbcbbabcdeedcbbbaaaaaaabbbccdddccccbbccbdcbcca########aa####aa##a#aaa###aabbccdccbbbaaaaaabaaaaa#########aaaaabcaaabaa#dfcccbcccbcccccdccccdbbaaaaaa###aaaaaaabbbcb######aa###aaaa###abbcfheeffghhghhijifcbbbbbehjhcbbba##aaaa##aaa##afgdbbcefecdcdccddddddeedcbabbcbbabbcbbbaaaaaaaabaa######a#a#a###aaaa#aaabaaaaa#aaaaaaaaaaaaaaaa#a#bcaaaaabaaaaabbcccbcabbbaaa#",
+"aaaaaaaaaa#aaaaaaaaaaaa#abaa#aaaaaaaaabcbbaabbbabbbbccddddddefdbcdccdecddcaa##aab######baaaa##ab###aaaabbbcccbbaaaaaaaaaaaaaa########aaaaaacdbaabaa#dcabccdddcccccdeeddddddbaaaaaa###aaaaabbbca#a#########a###a##aaabcegefgfhhggiiihddbbccbbfegihfb###aaaaa#aaaa##adgfefecbddccccddcedccefdcbabcdcaabbbbbbbaaaaaaaaaa#a####aaa#aa###aaaabaaaa#aaaaaaa#aaa##aaabaa##abcbaaa#aaaaaaabbbbdddbbbaaaa",
+"aaaabbabaaaaabaaaaa#a#aaa#abaaaaabaaaaaaaaababbbbccdddeeefdfffedccbbbbcccccaaaaacb#abaab#aaba#aaa###a#aaaabccbaaaa##aaa#abaa###a##a#aa#aaaaacca#abaaadbabddddfededcbbcaaabcddcaaaaaa###aabbbcdca######a####aa##aaaaabbcdkgghhhhhgiigecabbbccffedgiida#aaaaaaa#aaaaaabfecbccccbbbabbbddddddccbaaacdcbbcbbbbbbbaaaaaaaaa##################baaaaaaaa######aa#aaaaa#a##abbbbaaaaabbaaaababbddcbbbbaa",
+"aaaaabcccbbbaabaaaaa#aaaaa#aaaaaaaaaaaaabaaabaaabbbcdffefgffdcccdddcccccbaabaaacbab#aa##aaabb#a#a##aaaaaaabbbcaaa###aaaa#aaa#a###aaa#abaaaaaacccbaaaabcbaaccbbdccbbbababba#abccbaaaaaaaaaabdeabaa##########aa####aaaabbceghghhihiihhgcbbbbbbegdcdedhhdd#aaaaaaaaaaaaabdccccccaaabbbbcddddfeffdbbabcbbbbbbbbbaaaaaa###a#########aa#######acbaaa#####aaaa##aaaaaaaaa#a#aaaaaaaaaabbbbaabbccddbbbba",
+"aaaababbbccbbcbaaaaaa#aaabba#aaaaabaaaaababbbbbaaaaaa#aabbcaaabbbbbbbbbcbaaaaaabaaaa####a##aaaa######aaaaaabbbbb#######a#aaa#a###a##a#aaa#aaacbbcbabbabcabbbcddbaaabbaaaa##aaaabbaaaaaaaabbcdbaaa###########a####aaaaabbbcfihghhhihhhdabbbbbbeeccccbdehfaa##aaaa#aaaaaabedccbaaaabcdcddcbfeffddeedccbbbbbbabbaaaaa#############aa########ababaa###aaaaa###aaaaaaaaa##abaaaaabbbbbbbbbbbbcdffabaa",
+"aaaaabbacbbbabaaaa#aaa#aaaacba###aaabaaaaaababaaaaaaaaaa##aaaaaaaaababbccc###aabaaaa##a##aaaaa#aa##aa#abaaaacccb##a#a#a#aaaaa####aaaa###a#aa#ababdbbbabcbabbbbbbbbbcbbaaaaaaaaaaba#a###aaacbcdaaaa#########.#####aaaaaabbccfkjgfhhifdfdaaababbffcbbbbbacgda#aaaaaaaaaaaaaddcba#aabccccdbbdeefeddfdfecbbacaaaabbaa##############aaaaa#######a#aa###aaa####aaaaaabaaaaaaaba#aaababbbcccddddgihcabb",
+"baaaaababccccbbaaa##aaaaaaa#cddb#####aabbbbaaaaaaaaaaa#####aaa##aa#aabadedca#abbaaaaaa####aaaa#a#aaaaa##aababcbca#aaaa#####aa###a#aa##aaaaa#a#aaacbaabbbcbabcccbbbbcbabba#aaaaaaaa#bbaaaaabbadb###################aaaaaabacbgkkihhggfedaaaaaaaceecbaaaaabffgeca#aaaaaa###acdca#aaacbbccbcbeeefffdabdfecabaaababbaa#a##########aaaaaa#######abaa##aaaa#####aaaaaaaaaaaaaabaaabaabbbbbcdegghffdabb",
+"bbaaaaaabbcccccbbaaaaaaabaaaabccca###aabcceebaaaaaaaaaaa#a##a#####aa#aaaddbbaaabaaaaaaaaaaaaabb##abb#aaaaaaabcbba##aaa###aaa#########a#aaaaaaaaaaaaaabbbccbaabccbcbbbbbaaaaaaaaa##aaabaaaaccbed#################.##aaa#aaaaacekljihhhdbaaaaaaabdeedbaaaaaabceffdaaaaa#####abdd##abbbbccccbcedfeddbbbbdddbbaaababaaa#################aa#aa.###aa##ba##aa###aaaaaaabaaaaabaaaaababbabbbdfhjifeecba",
+"bbbaaababaabbcccbaaaaaa#aaaaa#aaba##aaabcbbccbaaaaaaaaaaaaa#aa####aaaaaabccbaaa#aaaabaabaaaa#abdca#acaaaaabaabbaba#aaaaaaabba##aaaaaaaaaaaa##a#aabbbbbbbccbbbacbcbabbbbbaaa#aaa##aaaaaacbccccdbbba#a########a#.####aaaaabaaaaafklljhfcaaaaaaaa#dcgfcbbaaabccccdggcbaaaaa#aaaacdaabbbbbbbbcbddeeddccccbbcecbaaaaaaaa#a##############aaa##a####aa##b###aa#aaaaaaaaaaaaaa#aabaaaaaabaabbdggghhfbdeb",
+"bbabbaaaaaabbcbccbabba#aaaa##a#aaa#a#aaabbabbbaaaaaabbabaaaa#a#####aaaaaadcba###aaaaaaaaaaaaaaabbaa#abaaaabbbcbaa#aaaaaaaaaaaa#aaaaaaaaaa#aaaaaaaabbbbbbbcbababbbcbbbbaaaa###a###aaaaaaaccddcddbaaba#aaaa####a#.#.#aaaaabbaaa##djlljc#aaaaaaaa#afdfebaaaabccccddegfdbaabbbbbbabddbbbbbbbbbadceedcdcccbbabdebaaaa#aaa#############aaaaaa#ab####a##ba#####aaaaaaaaaaaaaaaaaaaaaaaaaabcdfebbbabbbcc",
+"ecabbaaaaababcdcccbbbcdbaaaabbaa#aaaa##aabcbbbaabaaabbaabaaa#aa###aaaaaabecbaa#a#a#aaaaaaaaaa#aaaaaaaaaaaabbcbaa###aaaaabaaaaaaa#a####aaa#aabaaaaaabbbbbbdcbbabbbcbbaaaaa####aaa#aa###aaabcccccbaabbba##a####aa#####aaaabaaaaa##ahlkfa#aaaaaaa##fbbecaaaabccbcdddceghecbbccccbbbccddbbabaa#ccedddddccbbaaacfbaa#a##a############a##aaaaaaaaa##a###ca#aa###aaaaaaaaabaaaacabbaaabbbbddea###aaaabc",
+"abbcbbbbaaaabbccbbbbaaaa#a#aaaabcaaaaaa#aabbbbaabaaccbbabaaaaaaaaaaaabbabdcbaaaaa###aaaaaaaa#aaaaaabbbaabbbabaa#aaaaaa#aaacbbaaa##aa##aaaaabcbaaaaabacbccccabaabaacbcbaaa####aaaaa####aaaabdccdba#abbaaa#######a######aaaaaba#####dljfa#aaaaaaa#ddaadcbccbbbbccccdccehihfddccccccbbdfaaaabbbceefedddcbbbbaaaecaaaaa##a###a####a##a##aaaaaa####a###ba#aa###aaaaaaaaabbbbacbbbbbaaacccdd#####aaaab",
+"babbbcccbbbaacdbccbbbaaaaa######aaaaaaaa##abbbbabaaabbaaaaaaaaaaaa##abbbdcccbaa#aa#####aa#aaaaaaaaaaabcbabbabaa##aaaaaab#accbaaaaa#aaaaaaabcddbaaaaabbbccccbaabbbbaabbbbaa###aaaaa#####a#abceeeaaa#aaaaba#######a#######aaaaaaa###.cgjgb#aaaaaaaafcaacdcdcbcbbcbbccdeefeeghfeccccbcddc#aabaaaeffeccccbbbbbaaacdcaaba##aa##a#aa#aaaa#aa###a####a####b#a##aaaaaaaaaaaaabbbbcababbbbcdddeb#a#####aa",
+"bacbbcddcbbbbacddccbabbaaaaaa#a##aaaaaa####aabbaaaaaaabaaaaabaaaaaaaaabbcccbbabaaaaa#a#aaaaaaaaaaaaaaaabbccbbba##aaa#aaaaaabbbaaaa#aaa##abbaabbcbaabbcccccbbbbbabbbabbbbaa#############aaabbcedbaaaaaa#aaa######a########a#aaaa##a##adhjc#aaaaaaacdb##bddcbbbbaabbccefgecceffgfcbceccedabbaaacffdccbbbbbbbbbaabccbbaaa#aa####a###aaaaa#a##bb##a###ab##a###aaaaaaaaaaabaaabbbcbcbbbcefeb#####aa#a",
+"aaccbcddcbbabcbcddcbbbcbaaaaaaaa#aaaabaa##a#aaaa##aaaaaaaaaaaaaa#aaaaaaaaabbccaaaaaaa#aaabbaaaaaaaaaa##aabccccbaa#aaaa#abaaaaaaaaaaaaaabbbbaabbaccbddedcbbbbbabbbcbcbbcaaaa############a#aacbcba##aaaaaa#aaa#a###########a###aaaaa####adid#aaaaa##eca##addcbbaaaabbcddefddefddgiedccccffbaaaaaefeccbbbbbbbbbaabacdbbba####aa#a##a##aaaaaaccbba###.aa#aa#ba#a#aa#aaaaabbabcbccbcbcccegc######ba#a",
+"abcbbccdedcbbbabdddcbabbbbbaa##aa#aaabaa######aaaaaaaaaaaaaaa#aa#######aa#aabcbbaaaaaaaaabcaaa###abaaa#aaabcbcb#aa##aa#abbaaaaaaaabbcaaaaaabbgecbbbbccbbbbbabcabbcbbbbaaaaa##############aaabaaaa#aaba#######a###########ba#aaa#aaa###aabffcaaaaaabeb####cdcbaaaaaaabbccdeffeeegihfddddffcaaaabefeccaabbbbbbbaaaabdba#aa####aaaaa###aaaacccbbba#######aaaa#aa#a##aabbbbbbbccccccccddgf#aa##a#aaa",
+"aabcdddddddbbbccabcdccbaaaaaa#####bbaaaa#######aaaaaaa###a#####a#########aaaacbbbaaaa#accdddba#a#aaaaaaaaabbbcbaaaaa#aaaabaaaaabba#bdaaaaabeecbbcbcbccbbbbabbbbbbbabbbbaa#aa####a########aaaaacaabaabaa#######aa########abbbbaa##aaaa###aaegfb#aa##dcaaaabddbaaa##a##aaabcdfgffgiggfffedefea#aabffccbaaabbaaabaaaaacbaaaaaaa####a##aaaaaabbabaaa##aa##aaaaa######aabcbaabbccccbbddedeeaaaaa#baaa",
+"aabbdeedeedddaccbbbcbcccbaaaaaabbaccaaa#a#aa###aa#aaaa#########aa#a#####a##babbbbbcbbcfdccccbbaabaaaaabaabbbccbbaaaaaaaaaabaaaaaaaaacfcaaabcbbaaababbcaabbbabbbbbaaacbabaaa####a##.########a#abd##baaaaaa##.###aa#######abbadb#a#########aaeiib####bca#aabadcba########aabccdgghgfeddddeedegdaaabdedbbaaabbabbaaaaa#cbaaaaaaaa#a##a#aaa#abbbbaaa#aa##aaaaaaa#####aaabaabbbbccbbbcdecef######acaa",
+"baabcccddedddbacccbccdcbbbbaa####aa##aaa###a###aaaa#a#####aaaa#a#aaa###aaaaabbbbbabcgjfdccbbbaaaaaaaaaaaabbacccba###aaaaaaab##aaaabbbdfdbaabdecbbbabaabbbbbbbbbbbbababbaaaaaa######.########a#acdb#aaaaaaa######aa######abbccb####aa######afiifa###bca#aaaabcbba#a######aaabcdeefcbcedccccceffaaaaacdbaaabbbaabbabaaabcbbaaaaaaaaa##a#a##abbaaaa#ba##aaa###a####aaaaaaaaaaccbbbcccdeff.######aaa",
+"a#aabbbcdeddcccbcccccdcbbabaaaa##a###aa#a#a#####aa##a###a##aaa####aa#a#a#aaabbaabbbbbffdccbbbabbaaaabbbbbabcbbbaaa##aaaaaaaaa###aabcbbcdfdaacebbbbbaaabbbbbbbbbaaaaabbabaaaa###aa############abcdcaaaabbaaa######aa#####abbbdc#############adghf###cdaa##aaaabbaa##.##.##aaabcdecedbbcdecbbbccebaabacdaaaaabbbbbbbaaaaabdcbaaabaaaaa##aa#aaabaaa#bcaaaaaa###aa#a#a#aaaaaaaaababccdceec##########",
+"###bbbbcdeddddcccccbccbccbbbaaa#####.#a##aa######a##aaaa###aaaaa##a###aaaaaabbbbbbbccddcdcbbbbbcdbbbadecccccbcb###a###aaaabaaaa###accbbccfhcacbbbabbabbbbbbbbaaabbbaabbbaa####aa#########.####aabcbaaaabbaaaa#####a#####aabacfb###############dhhc.ddb###a###bbca#.#....##aaabcdccecbbccedbbcccedbabbdcbaaaaaaaabaaabaaaacccaabaaaaaaaaaaa#abaaabbcaaaaaa###########aaaaaaababbbceeda.#####a###a",
+"#baaabbcdeddddddddbbcccbcbbbbaaaa################aaababba####aaaaaa###aaaaaaabbaabbdecbccccccbbbccccbcbbbcbbddeeca###aaaabccaaaaaa##abbbbcdedbbabbaaaaabbbbbbbbaaaaaaabbaa#######aaa##########aabbbaaabbaabaaa########aaaaaabdfb####aa#########cghhceba###a##aabaa#.....###aaabcdceebbbbbddcbccbcdcabcedbbaaaaaaaabaaaaaa#cddbbbaaaaaaaaaaaaaaaaccbaaaaaba#a#a######a##a#aaaaaaccdeed####aa####a",
+"aaabaabccceeddeedcabbbcbbcbbbbbbaaaaa#########a##aaaaabbcbaa#aa#aaaaa#aaaaaaaaaaabbcddcbbbbbbbbbbbbbabbbbbbaabbdgfba#aaaaabbaaa##aaaaaabbbcceedaaaaabbabbbabbbbbbaaaaaabba#######aba#########a##abbcaabcbaabbba########aabbaabddca#aaaaa#########adjhaaa#aa#####aaa#...####aaabbcccfdabbbbbddcccbbccacffccbaaaaaaaaababaaa##bccccbabaaaaaa#aaaaabdcaabbaaaaa#########a#a#aaa###bcddhga####aa####",
+"##aabbbbcdffeddeebdcbbbbbcbbcbcbaaaaaa##.##aa######aabbbbaaaa#aaaaaaa##aaabb#aaaaacddfbcbabbccbccbbbaabbaaba#abadfdbbaaaabcaaaaaaaaabbbababbceedaaaabbabbbbbbbbbbaaaaaaaaa##.#####aa#########aaa#aacdabbbaaaaaaaa#######bbbbccdcddbaabbaaa####aa###bhgea#######.##aaa#####aaaababbbcebababbabdeccbbbceffeecbaaaaaaaaabaaaaaaa#bcccbbbbaaaaaaababbbbbaaaabaaa#######a##a#aa#aaaaabddhg###########",
+"#a#aaabcdddffdddeeedbbbbbcbbbbcbbbaabaaa#a##a##aacaaaaaaaaaa#a##aaaaacdaaaabaaaa#accdeaaaaabbbbccbbbbaaaaabbbababcdddcccbbaaaa#aaaabbbaaaaaabdeeeaaaaaababbbbbbaaaaaaaaaaaa###a####ba####a####aaaaaabecaa######aaa#####a#ababccccbcbabaaaaaaa###a####dijdb########a#a###aa##a#abbbbddbaaaaabbabdddcfeffffeccbbaaaaa#aaaaaaaaaa#abccbcabaaaaaaaabbaaababaaaaa#aaaa###aaa#aaaaaaaaabchga#####aaa##",
+"#a#a###abccdddefdeeecbbbbbbaabbbbbbbbba#########abaa#aaaaaaa##a#aaaaaccbaaabbabbcbbccfbcaaaababbbbbaaaaaaaaaaaabbbabbabaabaaa#aaaaaabbabaaa#abcdfea#aaaabbbbaaaaaaaaaaaaaaaa#######bba##########aaaabcedbb#######aa#####a##abdcbbccbaaaaaa#aaaaa#aa###bgjjga#######aba#aadba##aabbbccbaaaaabbaaabedffeffffdcbbaaaaaaaaaaaaaaaa#aaaccbbbaaaaaaaaaaaababbbaaaa#aaa#####aaaaaaaaaaabbbghc#####aaaaa",
+"a##a#aa#aabccbdfgeefeccababbbaabaabbbaa#a##.######aaaaaaabba##aa##abbbcbcbbccacbbdedgheccbbabbaaaaaaaaabbaaaaaaaaaaaaaaaaaacbbba#ababbbbaaaaaaabdeeca#aabcbaaaaaaaa#aaabaaaaa####.##ba###########aaabbceeba########a#########cbbbabbbaaa#aa#aaaaaaaaa###djkjb#b#..#abbcaaabcba##aaabbcaaa#aaaaabaacfffffedffccbaaaaaaaaaaaaaaaaaaaabcbbaaaaaa##aaaaabaaabaa#aaaaaaa#a#a#a#aaaabbbbccgc######aaa#",
+"##aaaaaa##aaccbaeihfgggcbabbbaaaaacbbceceeca########aaaaaabaaaaaaaabbbdcccdebbcbbabacedecbbbabaa#aaaaaabbbbaaaaaaaaaa#aaaaa#abbbbacbbbbbbaaaaaaaccddbbbbbbbaaaaaaaaa##aaa#a##a#####aa#############aaabbceeea########a########aaaaaaaabbaa###a###aaa######agjkhgfb.#aabddaaaaaaa###aabdb##b###aaaaa#cffffeeeeeccbaaaaa#aaaaaaaaaaaaaabcbaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaabbbbbdfeba####aaa#",
+"#a#aaaaa###aacca#cjjhhjebcbaa##a##acegebdcbdb#.#cbcaaaaaaaaaaaaaaaaaabbcdgiecbbaaabbbcbcdcbbbbbaaaa#aabaabcbaaaaa#aa#aa#aaa###aaaaaa####a###aaaabcddbcbbbaaaaaaa#aaaa#aaaaa##a#####baa#.#######a##aabbcdddffa##.####aa##.####aaaaaaaaaabaaa###########a####chhiihc..ceffbabaaabaaaaabccaacc###aaccbbegfffededdccbaa#a#aaaaaaaaaaaaaaaabcbbaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaabcccefeaaa###aa#a",
+"aaa#abaaaa##aaba##eiiikhccbddefeeffgecccdccdeffefddc#aaaba#aaabaabbaaaabcdhfbbbbaaacdecbbaabbbcbbbbaaaabbbbbbaaaaaa#######a###aaa#aaaaa######aaaaaccbcbaaaaaaa####aa##aaaaa#####a##############a##aaabcccccdfb##.#####a######aaa#aaaaaaaaaaa##########aaa##.#aejjifb#cffacbbbaaa#acbbcc##ddda##cddeefgfffeedddcabbaa#aaaaaaaaaaaaaaaaaaacbbaaaaaaabbabbbcaabaaaabbabbbbabbbbbbbbbbbdfc####a##aa#",
+"#aaa#a#a##a####b###dgkkjgccfiifdfdeeccddddcdcccccbca#aa##aa#aaaaabbbaababeggdbaaaaadfcbbbbbbcccbabcbaaaaabcabbbcbaaaaaa##########a#a########aa##a#accbbaaa#########aa###aaaa###aaa####.#########b##aabcbbcddfb###############aaaa###abbaaba#aaa#########aa#####djjjifbcebccdcba#bbacbcb##addccdcdeeefgfffeecbccbbbaaaaaaaa#aaaaaaaaaaaaaabbaaaaaaabaabbbbbaabababbbbbbbbbccccbbbbcced####a###aa#",
+"a##aaaaaaaaa#a#ba..#agkgfecfikgddcccdcccbcccbcbcbbdba##bccaaa#bbccccbaabbefffcaaaabdfbbbbbbbbccaaabaaaaaaabcbbbabbbbaaaa#######aaa############aa###abbaaa####a############a####a#######.#####a##aaa####aaaacfa#######..######aaaa###a#cdcbbbabcbaa#aab#########.chiiihfcddeghhgdccdabdaa#addcddceefeeffeeeedbbcccbbaaaaa#aaaaaaaaaaaaaaaaabbbbaaaaaaabaabbaaaababbbbbbbcccdccdcbbceea####aa###aa",
+"a####aaaabaaabbab#.#aaeecdhfijfcccddcccbbbbccbbbccaaa###.a#abccccbcbcbbbbbff#a###abcebabbbbccbcaabbaaaaabccbbbbbbbbbbbaaa#aa####aa##############aaaa#ababaa##############a#a######a####################aabbcacaaab#####.#.##abbaa###aaabcacbcaaaaaaa#aa#########.bgihiifcdgijjjiidaaabe#a#bdcbccccddddddecdecbbbccbbaaaaa##aabbaaaaaaaaaaabbbbbabbbaaaabbbbbaaabbbbbbbccdddedddefeffa####a#####a",
+"#######aaaaaaaaaa#.#abcdaahkkjgbbcccbbbbbcbbcbbbbaaaa#a######abddedccccbbacffcbb##acccacdcabbdccdbabaaaa#abbbbbaabbbbcba###a############.##.###########ababaa##################a##a###.################aaabcbcdbbbaa##.#.#.#aabaa###abcdcaabaa####aa#aabbb###a###.#bgjhacegijjjjjjhedfgea##cbbbccbbbcccccdcccbbbccaabaaaaaaaaaaaaaaaaaaaaaabcbabaaabaaabbbbbaababbbbbbccddddedffceedb######aa###",
+"aaa#a####a##aaa##a.##acda#cejjfdbbbbbabcbaabbcbbaa#aaa##a#a###baecbdfedddefhhgefea#cedbafecbbcbecbbccbbbbabbbbbbbccabbcdcaa####################.#######aaaaca##########################.########a######aaaaccccbbca#a########aaaa####bedcaabaa##aaaabaaabc########..#figefhikjihhhhiijiihd##bbcdbcccbcccddebcbbbbcdbaaaaaaaaaaaaaaaa#aaaaaabbcbbbbbbbabbbbbbbabbbbbccddedeedffa###a#####aaaaaaa#",
+"###aa############a#.##bccbbbbehhaabbbaaabbabbcbaba#aaa#######becdda#fgecddeehghegdabdecaabedbcaacbbddbbbbbbcbbbbbbdbaaccccba#########a################aaaaabcaba###############################a#####.###aaaabccbcb##a######aab##a###accbca#b#####aaaaaaaaa###.####...diihiiihfgeffeffhijid##ddcdccccccddddccbbaabddcaaaaaaabaaaaaaaaaaaaaaabbcbbabbababbbbbbbabbcbccdddedefc.##########aa#aaaa#",
+"#aaaaa#aaa##a######.#abbccaaaabgfb#ababa#aaaacbaaaaabbbab####edeefeccgedcddehhfacebadecaaaabcccbbbbcbabbbbbcbbcbccccccabccdb#######abb###a##############aaaacbccba##########a######.########a###a#########aabcceccb###a#####aaaa##aaaaacbb##ac######aaaaa##aaa#######..diihffffffdeddddefiigaaeddddbbcdddccdccbaaabcedbbbaababaaaaaaaaaaaaaaaabdcbaabbababbbbbbbbbbbbcceeegc.#############aaaaaa",
+"aabcbbaaaaaaaa########bbcdbaaaaaffa#aaaaa#aaabbaaaabcdeddabaefcdddefcgfddddeghcccffddbaaabbbbbccbccdbcbabbbbbbcbbbbbdcabbbddb########bca#a#######a##a###aaaaaaabdbaa#aaa####aca##...###aa####a##a########aaabbbdecc##aaa############aa#abba##a#########aa#aaaaa########.bgiedcccdccccccccdhigdeeeeedcdddccbcebaaaaaaceebbbbbbbababaaaaaaaaaaaabcccccfedcbbbbbbbbbbbbabcfffe############a###aaaaa",
+"a#aaedbbbbaaa#a#######abddca#aaaadcaa##aa####aabababbbccccfggcbcccccfgeccccdddffedfecddcbbbbccbbccdcddbbbbbbcbbbaabbcc#abaacba########aa##..#######aa####aaaaa###bbaaa#aaaaa#cc###a.####aa##aaa#########aaabbbbadcdaaabba##########a#aa#bbaa##a#######a#aa#aaaaaa#######.ageccbbbbbbbbbbbcbehigffeedddddccbcccbbaaa#accdcbbbbbbaaaaaaaaaaaaaabbcbccdbaadfdcbbbbbbbcbcefccba#################aaa#",
+"#aaacbaabbcbbbaa#######abcca##aaabbcba########abbaaabaabccdcbabbbccbcedccccccccccccedbbcdbbbccbcbbcbcbbbbbbbbbbabbbbcccbbaaaaaa##a####a#aa####.#####aa##a#aaaaa##abbcaaaabbbabcaaa#.#.###aa#a##a########aaabccabbddbaabaa####.##.aaaaaa##bba##############aaaa##a########.#bddbbbbbbbbbaaaaabfhhgfeedddccbccbdabaaabbbccddcbbbbbbaaaaaaaaaaabacbbcceb#a#babcbbbbbbcbce##.####################aa#",
+"aaaaaa#aaaababba#######abcccb#a#aaacddb######aaaaa#aaaaabbbbbbbcbbbbcdcbcbccbccccddbababcccccccccbbbbaaabbbbccbdcbbbbabcbbaa######aa#aaa############aa#####aaaaa#acbabaa#baabbcb#a##.#####baaa#########aaaabcdcccccbaaaa##########abaaa###aa##############a####aaa########.##dcbbbbbbbaaaaaaaabghgffedccccccbbcabbaaabbcbdedbbbbbbaaaaaaaaaabaaabccdecbcabbbcbbbbbcbeea###aa####################",
+"aaaaaaaaaaaaaa##########acceeba###bbbcda#######a####aaaaabbbabbabbbbbcccccccccbcbbcdcbaabbcbcccccbbbbbcabbbbddegebbbbbbbcaaaaa#########a######aba#####aa#####abaaaabcbb#aa##abaaba#####a##aaaaa######aaaaaaacccccbccaa##a#######aa#aabaa##aaa####aa########a#aaaaaa###########addcbbbaaaaaaaaaa#fieeeddcccbbbbbaaabaabbaaabdedcccbaaaabaaaaabbaabbbcdebaaccbbdddcbbcdc#aaaa###########.########b",
+"aaaaa#aaa#aa#############abcdfdaaaabcdf###aaaa##a#####aaaaabbccabbaaaabbbcccccbcbabbccbbbbbbbbbbbccbbcccbbbcdcdedecabbbbaaaaaaa########abb##aa#aaabaa#aba###a#aa#aabcccbabb###aa#aaa######aa##aa######aaaaaaaccccdaba###########aaa#aaba#aaaa#aa##a########aca##aaa######a######cffaaaaaaaaaaaaa#ehfeeedcbbbbbbcbaabbbbbbbaadeeefedcbaabbabbccbabbdcbcaabdcccccceedffb##aa####################a#",
+"aaaaa###aaaaaa#####.####aabccfgbaabbcfeda##aaabaaaaaa#aaaaaaaccbccbaaabcccbbccbbbbbbcbbbbbbbcbbbbbcabcccbababccdeccbabbbbaaaaa#aa########aaaaaaaabedaa##a#aaabaaaaabaccbaaaca###aaaaaa#####a###aa###a##aaa#aaaccbbabaa############aaaaaaaaaaaaa#########a##acdaabaaaa############acecaaaaaaaaaaaaafhffeddcbbabbcbbabbbbbbbbaabbdeddfeddbabbbdcabbabbababbbcbcbccddffcdaaaa##a###################",
+"aa#a#####aa#aaaa#########abcdcfeaaacbdccfcbbbdddbbbbbaaaaa#aaaabcbaabbbcccbbbcbbcccccccccbbcbcccbbbbbcccbbabbacddedcaabbabaaaaa##aa########cb##aa#cfdaa##aaababbbbaaaabbbbaabaaa#abaaa#####a#bbaaaa##a##aaaaaabbccdaaaaa#####bb#####aa##aaaaaaaa############aabbbbaaaa##aa##########deaaa###aaaaabcgiggddccccccccabbbbbabbaba#aabcaacccccbbcdbaacbbabbbbabcbcdddd####abaa#a##a#a#aa############a",
+"aaa#####aa#a#aaaaaaa######abccdfa#bbcddbcccdcdaaccdecbbbbbbbaabccbaaabbcccbbbccbccccddccccccddccbbbbbbcccbbbbbcccdddbabbbabaaaa########.####bba##a#aca###aaaaaaaaaaaaaabbbaabaabaaabba#######ababba.##aaaaaaaaabcdcb#aaaa#####a##########aaaaaa#a####aaaa##.##abbba#aab#aba#aa#a#####cgeaa####aa#aabfiigdccccbccccbbbbaabbbbaaaaaabccbbccccdabcbccaaaaabbbccdebdbaaaaaaaaa#a######aaaaa#########",
+"#aa#a###aaa####aa##a#####aabbbbeb#abbceeba#a####aaaba##cdbbbcccdccbbbbbbccbbabcbbbcbcddccccccddddddccdcabbbcbccbbbddcbbbbbbbaaaa#########.####aaa####a#a#aaaaaaaaaaaaaabbbbaaabaaaaaaba####a#.a##ab##.a##a##aaaabbddb##aa#####aa######.##aaaaaa#aa####a#aaa###abbb###acaacaaaa##a#####bff###a##aaa#aacghhfccbcbcbbcbbbbbbbcaaaabababbdccccddbbccccaaaaaabbccee##aaaabbacaaaa######aaa#aaaaaaa###",
+"#aaa##########aaaaa########bbbbbea#babcea#a######aaa####bccddcddedcccccccccbcbccbbbcbcddddcccbbbcccdefedcbaacbbcbbbbbbbbababaaaa############.###aa#a##aaa#aaaaaacbba##abbcbaaa#aaa#aa#########a#######a##aa#a#abbcbcc#a############aa####aaaaaaaaaa#######aa###aabaa##bbaaaa#a##aa######dea#####aaaaaa#behhdccbccacbbbbbbbcbbbaabbabbbcdcccdddbbbba#aaaaabbddb#######bcaaaaaa######aaaabbbaaaaaa",
+"aa#aa##########aaa########aabbbbbedbaabddcb#aaaa#aaaa####cccaacdeeggecccccccbbabbbbbbbbccddcccbbbbcbcddeedcbaaabbabbbbcbbbabaaaa###########.#####aba#######aaaaaabbba#aabbbbaa###aa##a#####.#a#.#.####aa##aa#aaabccbca#aa#..########a######aaa##aaa#########aaa#aaaaaabcaaaa##a##a###a#a#bdb#aaaaaaaaaaabcfhfccccabbcbbbbcbcbbbaabaabbabcddcdcccbba##a#a#abddb########aaaaa#aaa####aaaaaaaabbaaa",
+"aaa#aa##########aa#a#a#######abbabgebaabacca#ba#aaabaa#########a##bdeddeedddcbbbbbbbcbabacdddcccccbbbcdcdcdcabbbbbbababbbccbabaa###############aaabb####aa##aaaaabbbaaaa#abbbaa###aaaa###a###a##....###a##aa##aaabbbca##aa#.#######aaa##aa######aaa#########abaabaaaaaacbaaaaaa##a###a##a#afb##a##aabbbaaaaeggecebcbbbabbbcbbabaabbbbbbabbdddccccccabaaaaaaccc#####a#aaaa#a#####aaaaaaabbbaaabaa",
+"aaaaa############aa#a########.#abbcffcabbceccaaaaaaaaa###a###aa#######aaeebccccccbbbbcbbccbdddccccccbbbccbbbbbbbcbbabbbbbccbbbbaaa########.#aaa#a##aba#aa##aaabbbabbbaaa###abaaa#########aa##a############aa###aabcc#aa#aaa#######.##aaba#aaaaaa##aaaaa######baaaaaaa#aaaaaaaaaa###aaaaaa###ebaaaaaaaaaaaaabbfhgedbbbbbcbbbbbbabbbbbbbabbbbddecbcbbbbbbcbbbceaa#####aabca#a#a#a##a#aaaaaabbbbbaa",
+"aaaaaaa####aaaa#aa###########..#aabdddbbcccccaaaaaaaaaa##a##aaa###aa#####eddedddcddccbccbccccbbcbbcedbbcccccbbbbbbbbababbbcbbcbaaaaa############a#a#aa#aaaaabbaabaabaaa#aaa#abaaa#######aaaa#a###########.#aab##aacc#aa####a######..##aa#aaabbaaa##aaaaaaabbaabaccbaa###aaaaaaaaaa##aaaaa##a#ccbaaaaaa###aaaadgggfeababbcbcbcbbaabbbbaaabbbccddbcbbbbbcdccccca#a#a###aaaaaaaaaaaa#aaaaaaababccba",
+"aaabaaa#a#######a#aaa####aa###.###bcdcbcbabddbaacbbababaa#a##aaaa#aa#aacdccbddddddbbbbbaa#aaa######bfggfdcccbabbbbabaaabcbccabbaaaa#########a#aaaaa#######aabaaabbabbaa####aaaabaaa##aa##aaa#b####.#########abb#aaee##a###.##.##.###..####abccccbaaaaaaaaabcdaabbccba##a#aa#aaaaa#a#aa#aaaaaaaabebaaaaa#a##aabbfghhgedaaabbbccababcccbbbaabccbcccbbcbbcdcdcaaa########aaaaaaaaaaa#aaaaaaababbccb",
+"abaaaaaaaaaa######aaa########aa####bbccbbaabceaa#cbbbbbba#a##aaaa#aa###debacb#aacabaa##aa###########.#afhgeecbccbbbabaacbcccbbbbbbaa#a#########aa#aaaa####aaaaaabbbbbbbaa###aaabbba###a##aaa###.#######ba##aaadbaabeaa##aa#..###.##########abaaabdbaaababababbaabddbaa##aaaaaaaaaaa#aaaaaaaaaaa#aecaaaaa#aa#aaabdghhhfecccbcbbabbacccccbbbbbcbbbbbcbabbdcbcba########aaabaaaa##a###aaaaaaaaaabbb",
+"baaabbaaaaaaaaaaaa###########aaa####acccbaaaabcbcabbbbbbba#####aaaba#acbcaa#aaaa#abaa############.#####.dhihgeefccbbbbaabccbbbbbbaaaa##########a#aa#aa####aaa#aabaabcbbaa####a#aaaa###a#aaa################abbeebbbdd##a#######..####.######aaaaabcbbbbbbbbbbb#abcccbaaa#aaa#aaaaaa###aaabaaaaaaa#bcbaaaaaaaaaaaabehhhfedaaabaaabbccccbabbbbccbbabccbbbdcbbaaa#######a#aabaaaaa#aabaaaaaaaaaaabb",
+"bbaaaaaaaaaaaaaaaaaaa#########a#a####bbcbaaaaabeecbbaaabbaba###a#aaa##cedb#aaabaaaaa##a#########.##.###a#bfgedeffdccccbaaacdccccbbaa###########aaa######aaba###aabaabbbaaaa#####aa#a##abbaa####.##.####aaa#acbddddfega#a#######.######.##a#aaaa#aaaaaaaabccddebaba#bcba##aaaaaaaaab#aaaaabbbcaabaaaaccaaaaaaaabaabbehhfgebaaaaaaacdcccaabbcbbcbbbbbcdcbbcaaa#a######aa#abbaaaaaa#abbaaaaa#aaaaab",
+"bbbaaaaabbbaaabaa#aaaa###.#######a####abb#aa#a#cfecaabbaaaba#######aaa#bddcdaaabaaaa#a#aa######.########ba.a####bfddcccbbacdccccccaa############aaa######adb###aaaaaaabaaaaaa###aaaa##abaaa#####..#####aaaaabbcdeedfgd#aa########.#######a##aa#aaaa#a###a#abeedecc##aaba#aaaaaaaa#bbaaaaabbbbaaaaaaaaaccbaabaaababbadgggfdb#aaaaaabcbbbbbbccccdcaabbcdcccbaaa#######aaaaaaaa##aa###aaaaaaaaaaaba",
+"bbbbaa#aaaabaaaaaaaaaba#a######.#######abbbca##acdedcaabca#a#.###a######bddcfcaabaaa##a##a#####...##aa####a####a#abbccddcbbddedccccbaa####a######aaa#####acb###aaaaaaaaaaaaaa###########aaa####.####a##aaaaacdeceeeedc##aa########..#########aaaaa##a###aaaaaabcdedcb##aa#aaaaaaaaacbaaaaabbbbaaaaaaaaadfdaabaaaabbbbcdggfebaaaaaaacccbbbbbbccdcccbbbdcecba#####a####abbaaa#######a#aaabbaabaabb",
+"bbaacbabaabaaaabbaaabbaabb#.####.#######abbcba#aabecdbaccaa#a#.##aa##a###acacecbaaaaaa##########..######..abaa#aa####aceeddceggeddccbaa##########a#aaaa##aaa##a##aaaaaaaaaaaaa#########aaa####a#aaa####aaaabbdffffgebca#ab#######.#..#aa######aa###aa####aaaa#baabbdcc##b##aaaaaaaaabaaaaaabbbbaaaaaaaabcegcabaababbbbabgfgfdaaaaaabbabbbabbbcdddbcbccccdbaaa#a##a###aaaaaaa#########abbbbccbaab",
+"baaabbaaababaabbaaaaaaaaaaa##############abbaa##aadd##abbaaaa#.##aaa##a####aabcbaaa#aaa###a######..####.#..cdcbbbaa###abdcdedfghffddcbba###########aaaaaaaaaaaaaaaaaaaaaaa#aaaa########a#aaa#####aaa#a#aabbccddghhhfcca#aa##########...##########aa#aa###aaa##aaaa#a#bb####aaaaba#a#aaaaaaaabbcbbaaabaaabbefdabaabbbbbbbbfgggfdcaaaaabbbbbbbccdbdbcbcccbcbba##aaaaaa###aa#aaaa########bbabbbbaaa",
+"aa#a#aaaaaaaaaaaaaaaaaabbabaa#######.#.####aaaaaaabdeb#aababaa####aaa#abba#####aaaaa###a##bdba##a######....acdbabbaaaa#####cddaeggffedcba##########aaaa###aaa#abaaaababaaaaaaaaa##a###abaaaa###.#bbaaaaabdcddeefhhifdda#bb#aa##aa######..########ab##a###a##a#aaaa#abaabaaa#aaaaaaaaaaaa#aaaababbbbaaaaaaabcffbbbabaabbbaacefggdba#aabbbbcbacddccecbbbcccbba##aaaaaaaaaaa#a##a#a#######aaaabaa#a",
+"ba###aaaaa#cbaaaaa#abababa#a################aabbbbbbbea#aaabbaa#####a##adc##aaaaaaba##a####a########.#####...aca###########.####cffdcdecaaa#######aaabaa##aaaaaaa#aaabbbaaaaaabaaaba##babba######accbbbbbfccdeegdgfggeb#dc#####aaa#####...#######aaaa#aa##a#aaabaaa#bbaaaaa##aaaaaaaaaaaaaaabaabbbbbaaaaababbegdbbaaababbaabffffecb#aabbbbcbbcdddecbaabcbaaba#aaaaaaaaaaaaa###a########a#abbaabc",
+"a#######a###aa#abaaaabbccba###.##############abcbcbbcbea#aaaaaaa#######.##ba#a#aa#a#a#a##a####.###########..###ba##############a#aeedbadfcdddcbb##aaaaaaa#aa#aaaa#aaccbbbaabbbbbabcbbcdccb######abcdbddeeefddddb#afdcfebdca#####aaa######.#####aaca####abaa#aa#abcb#accaaaa##aa#aabbaaaaaaaaaaaabbbaaaaaaabbbbbgdbaaabbbbaaaccffgfdcaabbccccccddddfcbaaaaaaaaa#aaabbaaaaaa#a#aab####aa##aaa#bcc#",
+"aa###########aa#aaaaabbabbaaaa##..###########abdcccccbcdcaaaaaa#a##########aabb#abaa##########...#.########.######################.bfdaaccefddddbaaaaaaaaaaaaaa#aaababcccbbbbbccbbcddcabca####aaacdcabeggfdda.##.#cc#aefdbaaa###aaa###.##.####aaaaa#a###abd##a###ababbdc#aa#aaaaaaaabaaaaaaaaaaabbcbbaaaaaaabbbbgfbaaabbbbaabbbcefffddbabbcdccccedcabaaaaaaaaaaaaaaaaaaaaaaaaaaa#####aaa#aaaaaaa",
+"aaaa##########a######.#a#abbaa##########a####abdedcccccccba##########a######aaaa#abaaaaa#######..################aa#aa###############ddabedcgededbbbaabbabaaaaaaaaaaabbccccccbccdddba###abacbbcccba####aaaaaaaa##.###acfcaaa##aa#a############aa#####a#a##aea#aaa#aabbcda##aaa#aa#aaaaaaabaaaaaaababcbaaaaaaaabbbgfbabbbabaabcdcbdefffdbbcccccccdda#aaaaaaa##abaabbaaaaaaaabbbaaaa####a##aaaabaa",
+"aaaaabaa#######a###a##.###abbaa###############acdeccbbccdga##########a######.#aabaaaaaaaaa#a############.###aa###aaaaa###############.cdbbdefhhhfdccccbbbaaabaaaabbbbbccccdddcdccdb#####bbcbcddba####aa####a#a#####.##aedaaaa###aaa#######..#########a###a#bbbbbaaabbbbaba#aaaaaaa#aa#aaaabbaaababbabccbaaaabaabbbggdabbbbcbbbddcbcbdffdcaccccacccd#aaaaaaaaaa#abbbaaaaaaaabbabbabaa#aa####aabaa",
+"aaaa#aaa##########a###.##aaaaaaa####.##aa#####abccdcaabccffa##########a###aa####aabaaabaa#aaa####a######..###a#####aaa############aa###bdddeeddfgfeeeddcabaaabbbbbbbbbbcdddddeeeecaa####abbaaaa#######a#a########.###aaadaaaa#####aa########.#..##.##a######aaabbba#bbca##a###aaaaaaaaaaaabbaaaabbbaabddcaaaaaaaaabfgdaaabbbabdacdbcbdfffdbbdccbc#cbaa##aaaaaaa#aaaaaababaaaa#abbaaaaa#aaaaaaa#a",
+"###a#aaaaaaa######accbaaab#####aaaa####a#######accccabacccfe##.############aa####aa###aaa#aa####.#########.##########a############abca##bfcfabbbcaafffffdbbbbbbbbbabbcccdeeedefcaaaaaa##aaaaaaaa################a#.###abbcaa#aa#aaaaa#######....########aa####a#abba#bbbbaaaaaaaaaaaaaaaaaaabcabbbbbbabeedaaaaaaaaacfgecaabbabbacdbabcffffccccdda##aaaaaaaaababaaaaaaabaaaaaaaaaabaabaa##abb####",
+"a########aaa#######cddebba########aaaaaa#######abccccbabcdefea#.########aaaaabb##aaa#####aaa##.....#.##.##############a#####.#####aabcbaabfc######.afggggcbbbcbcccbbbccceeeeffhgccbaaa#aaabbaa#a######aaa########a#.##aacdba##ab#aabb##.#.####...########aa#####aaaaaaaabbaaaaaaaaaaaaaaaaaaccbabbbbbbabefdaaaaaaaaabeffabaaababdedabbcfffecccddaaaaaaaaababaaaa#aaaabbbaaaaaaaabbaaa#aa##ba###b",
+"#####aa#####aaaabbaaaacdb.#a#########aaa########abcbbbbbcdeeeefc.######aaaabaacbaaaaa##########..#..#....##############a###########abbbba#bd#a######aabbcfedccdddccccdddeeeeefgiedeebaaaaaabaaaa#aaaaa#aaaa###########aabcca##aabaaabba#....#....##.###.#aaa#######a#abaabbaaaaaaaaaaaaaaaaaaddbbbabaabbbddaaaaaaaa##adfecbbbbacddedbbccdffdccddaaa#aaa#bbaabca##a#aaabbaaaaaaaaaaaabb#aaaa###a#",
+"####aaba######aa#abbaaaba###aa#############.####aabcabcbbdegfebc.########abbbaaaaaaaaaa#########.....#.#.######.#######aa#####.#.##aaabbbbbc##a#######..##ehfeeeedddcedeffeeeeehf#abcecccbabbbbbaabaaaaaaaa########a###aacdba#aaaabaaaaa#..##..##.#..####aaa##a####aa#aaaabaaaaaaaaaaa#aaaaaabeeccbababbbbbaaaaaaaaaaaabcffbbbbcdccdcbbbcdfgfedcabaaaa##bbababa#####abbaaaaaaaaaaaaaaaa#aaaaaa##",
+"#a###aabaaaa###ba###ab##ba###a#############..###aaabcaabbdedefgb####aaa###aaaaaaaaabaaaa###########...#.############################aabbbadcaaa#####.######bfhhgggffffffffeeeefhhcaa##acfffeedddbaabaaaabaa########a####abebaaaa#a#a#aa############.###..#aa##a###aba##aaaaba#aaaaaaaaaaaaaaaaccdcdcbbbbabbbaaaaaaaaaaaaacfeaabbbbccdabccbdfffed#aaaaabaaaaaa#aa###aaaaabaaaaaaaaaaaaaaaaaaaaa##",
+"###aaa#aaaa#a##.a##a#aba#aa###########.#.#....####abcbbbbccdffegb...##aa###abaaaaaaaa#a#aa#######aaa###.####.#####################a##abbcfda#aaa###########.#acfhihhhijiiiihgfhhgcaaaa#..acccddccecccbaaabcb#######aa###abcdbaaaaa#aaa#aa##########.##########aa##aaa#aaaa########aaaaaabaaabbaaababaacbbabbbaaaaaabaaaaa#cefdabbbabbcbbbccdfggeb#aaaaaa###aaa#a###aabbaaaaaaaaa#aaaaaaaaaaaaaa#",
+"#aaaaaaaaaa##aaaaaaaa#aaaaaa##.###aa###.###...####aabdbbabbcfeced.#########aaaba#aaaaaa##ca#######aaaa######.########.########a#####aaabdhgfeaaaa#############.#aaba#addfghiiiiheb###aaaa###.####bdbcdcdcbbca##a##a##a##aabbdbaa####aaaaaaa#############a#.##aaaaaaaaa##aaa##a#a#acbaabbabbbaaaaaaaabbbbbaabbbaaaabaaaaa#a#bfgebaaababbbbbbbcggfeaaaaaaaaaaaaaaaa####aabaaaba###aaaabaaaaaaaaaaa",
+"a##ba#abaaaaaaaa####aa###bbaa##.#######b#####.#.###aacbbaabcdeccc##.########aabbba#a##aaa#bba######aaaaa#################.######aa##aabbfhhihdabaa##############aa######.##a#bgfb###aaaaaa########cbacccdfeecaa###aa##a#aaabcdbab##ababaaaaa##########aaa#####aaaaaaaa#a#aaba##aabfdaa#aaaaabbbabaaababdbbbbbbbbbbbbbaaaaaaa#dffcbaabbbbbbbbbcefgdba#abaaaaaaaaa#aa##abbbaaacba##a###aaaaaa##aaa",
+"aaaaaaaaaaaaaaaaaa#####a##aaaa########ab##.####..###aadccbbacdcaa###.######aabaaabb#aaaa###############aa#####a#####.##############aabbbehhhfcaaaa#####.########aaaa##aaa##a#.#caa####aa##########cdbbbbbcedefdcbbaa##aaaababbdbaaaaaaaaa#aba#########aa######aaaaaa#a#aa##aaa##addbbaaaaa#aaaaabaaaaaaccccdcbbabbbcbaabaaaaa#cfgdbabbbbabbbbbcfgedda#aaaaaaaaaab#a##aabbbaaaba#aa###a#aaaaaa#aa",
+"aaaaaabaaaaaaaa#accb#########babaa###aaa##.##a##.####abcbccabdeaaab#..######aaaaaaa#####################aaa####a#####.############aaaabdgihgcbaaa################aaaaaaaaa#aa###a######a##########dbaaaaaaaacbcefgfddcccddegdcbdbaabaaaaaaaaaaa######aaa####aaaaaaaaa#############aaaaaaaaaaaacaaaaaaaaabbbbdeccdccbbbbaabaaaaabefecbbbabbbbcbcegededcaabaaaabaaaaaa##aabbbaaaa#aa#aaa#bbaaaaa#a",
+"a##a#aaaaaa###aa#bbcbaa##aaa#aaaca##abb########a#####aacbbccbdeaaaba#########aaa##a#a####.################ba#########.##..######.bbabaaehhhgbaaaa#################aab#aabaa#aa###a##########a.###.ab#aa#abababbbcbcdcaacecccdefdc##abaaaaa##aa########aaba#aaa#a#aaaaba#a#aa#a##.##abaaaaaaaaabbabbaaaaaaaaaaccbbbcdbbbbaaabbbabbdgfdbbbabcbcccdddeeedcaaaaaaaabaaaaa##aabbaaaaa##aa####aaaaaaa#",
+"####aaaaaaa######abbcca##aaaaa##abbabba#a#####aaa######aabccedfaaaab#########aaa###.#######################b########.#ba#...##.#acbccccfgggebaaaa##a###############aababaaaa#a##a#a####a##a########c#aaaaaaaabbaaaaabccdebabbbdgeaaabbbaaaaa##a#######aaab##a##aaaaaabaaa###aaaa####ba#a##aaaaaabbaaaaabbaaaaacbbbcbbbcbbaaabbbbcbcfgecbcbbbccddccceddccaaaaaa#bbaaaaaaaaaaaa#aaa##a#aa#a#aa####",
+"##a###aaaaa#######aaaaaaaaaaaaa#aabbcaaaaa#a###aa########aabeeea###aaa#######aabb#####a######.#######aa##.######aaaabedccbbb##bbbbaabbbbccdeaa##a##a########aaa#####aabbbba#a#aaa#a####a###########caba###ababbbaabbabcdcddcbabehcaaaaaaaaaa############ab##aaaaaaaaaaaaaa#baaaaa###bb#a##aaaabbbbbaaaaabbbaabbbbcccbabbbaaaabbccccbfffcccbccccbccccddeedaab#aaaabaaabaaabaaa###aaa###bb##a#####",
+"aaaa##aaaaa#aa#######a#abbaaaab######aaaaa#aaaa#aa#######aabdefb#aaa#bc#######abcb#####a#################aa#a..###aabcdfffggfdcbbbbbaaaaaabdeaaa###########aaaa#####aabbbbbaaa#aaa#####aa#a##.#####aaaaaa##abaabcbbbaaabaabbbbcdefaaaabaaaaaa##a######aaa######aaaaa#aaaaaa##aaaa###aa#aaabbbabbaabbaaaaaaaabbbbbacccbaaaaaabbccdccdefegffdccecbccccdeeddcbaaaaaaabbbcbaaabaaaaaa#######aa######",
+"#aaaa##aaaa#############abaaaaaba##aaaaaaaabaaaaaba#####a##abdgca#aaadeb########bba#####aa#aaaaaa###aaa#ab#aa#.###.#acfhfddgccbaa#aaaaaa#abcfaaaa#######aaabbaaa#####aaaaaaaaa#aaaaa#aaaa##########aaaa#aa##aaa#acccabaaba#a###acdbaaaaaaaaaaa###a##.##aaaa###a###aaaaaaaaa###aaaa#abb#aaaabbbbbbbabaaaaaaaaaacbbbccbbbbaabaaacccccdfdbdfgeefcddabccbcedddccbbaaaaaabbbababbaa#aaaa#a##ab##a####",
+"##aaaa#############aa#####abaaabda##abaaaababbaaaaba####aa#abbdeaaaaaadf###############a#aaabbbbba#aa#aaaa#baba.#accbffffgddcbbaa#####aa##acfeabaaaaa###aabcdcbba######aaaaaaaaaaaaaaa#aaa##########dbaa########bbdcaab#abaaa##abceaaaa#a#aaaaaa#a###.######a#####aabaabb#aa#####a#bcbaaaaa#aaaabbbbbaaaaaaaaaaccccbccabacaaaabceeeeggdcdfffccccca#bbcbddeccccca#abbbbbbbaaabaaa#a#aaaaab#######",
+"##aaaa####.##########baaa##aaaaabda#aaaabbaaccbaaaa#####aaaaabbcbbaaabdgfe###aaa#######a##aaabbabbb#a#a#aabdceeedcabcaeddcfhecdb#########aacdhcbccbbbbbbbbdehhedba##aaaabbbbbaaaaaabbaaaaaaa########cba#######a#abbda#aabcbaa##aabceaaa######aaa##aa########aaa##aaaaaa#aaa###.###aabaaa#aaa#aa##abbbaa#baaaaaaabbbbbbdbbabaaaacaddacbbbbddccccbbda#cbbcdcddeccccbaabbbbca#aabaaaaaaaaaaaaa#####",
+"#aa###a####.##########aa#a##aaabaccaba#aabbaccbaaaaaaaaaaaaaabbccabaabeffeebbcb#.####.#aaabbaabbccccccccdddcec.#aaaaaaadccbbcccca.#######aabdhecdddeeeddeefecbbeedcaaaaabbbbbbabbbbcbbaaaaaaaaaba##aba####a####aacdccaa#ccbbaa##aabcdaa########a##aa########aaaa##aaaaa##aaa#########aaa##aa#aba#aabbbaaaaaa#aaaaaabaaaccbaaaaabccababbbb###bcbcbbecabbccdcddcdcccaaababbbbaaaaaaaa#aaaaaaaaa###",
+"#aa#aa##########a######a#####aaaaabc#abaaaabbcbbaa#a##aa#baaabbbbbabbcfffgghebdcbbacacbbbbbbbcbccdccfdaaabdedcaaabaaaaacccbbbbbbcb########abcfgedeffeeeegfcbbcbadgdddaabbbbbbbbbbcccccbbaabababbbaacbaa#########abcccbabccbbbaa##aabcb#a#######aa######a#a##abbbbabaa###a#aa########.bbaaa#aaaaaa#aaabbbccbaaaaabbbbbbbaaaaaaaaabbbccccaaa###bcdbabcbbbabcdddcbddccbbaaaabcccabaaaa#aabaaaaaaba#",
+"#aaaaa#######a####a###aa##.###aaaaabc#abaaabbcbba###aa####a#aaabbbaabcdcdeccdecccccba##aaabbaaaaaa##beaaabacfdeaabdecb#bdcbbbbbbaca#######abcdegeeeeffgfdabbccddeehhhfdbbbddeeccdcccdccbbbbbbcccbcca##a###a########aa#.aceccbbaa#aa#acb###.#####aa#####aba###abcdcbcbaaaaaaa#####a###bc#abaaaa#aaa#ababbbbccbaaaaabbcccbcbaaaaaabccdacccb#a###abddbbbbbbabbcebcbbdcccbbaabbabcabaaaaabcbaaaa#aaa",
+"aaaaaaaaaaa####aa#####aaaaa.###a#aaaccaaabaabccaa##aa#######aaaaaaaaadc##abaaaaa###a#######a#########cb#aaaacdddb#bbdda#becbbbbbbac#######abceffhffffda##babcccdeeddbddeecdcdebdeeccdddeddcccdeba#b###aa##a#########a###bedbbbbaa#a##aca###.#####aa####aaa####bbcdddbaaaaaaaaa#######adbbabaaa##aaaaaaacbabbccbaabaabbccccaaabbcbdcbcecccaa#a#a#adcabbbbbcbbcbccaabccdcbbbbcacbaabbaabcbaaaabaab",
+"bdbaaaabbaaaa#aa##a#aba#############abcaabababcba##aa#########aaaaaaabdb##aaaaaa###a##################b####aaccdeaabcbbaaeddbabbbabb#######bdfhghhgda###aabbcccecbbbdcccefdbbcbcb#eefgghggfeegdaa##a###aa#######aaa#####bedcabbaa#####acb##########a##aaaa####acbccccaaabaabbbba####a##dbba#aaaaa##aaaabdababbccbabaabbcddcbacbbccdacdbba#####aaaabcbbbbbbbccbbababbcddcbabbbabaaabcaaabaaacabaa",
+"aacdbaa##.##a##aa#aa#aba###.#########abca##aabbbca#..###########aaa##aab######aaaa#########aaa#a###aa#######aaccdfbabbaaaeeddbbcbbbdbaa#abcdfhjigca######abccbadb###cfbcbbecabbba#begfhggddcggdbbaaa##############a#aa#.cddccbaaaa#####ab##########aaaaaba####accbbbbaaabaabbbabb#######aba###aaa#aa#aaabcaaaaabccbabbcccdedcbdbbacdcdccaa##a#aaaaabcbbbbbacccbaaaabaccccbaaaaaaaabbbbaaaaababba",
+"aababbaa#####a##a##a###a####.##########aba###abbbbba####.#.#######a###aab######aa#a#########aaa#####aaaaa#####bbceebbbba#ceedccedcegdcbcddedbcbed#######aabccdbdda##adeeb##abbaaaaacbadeddfdghdcbbbaaa###########abbbcdbbdcbbca##aa#####bd###.#.###aaaaaaaba##abbbbbbbaaaaaaaabbaaa#######aa###aaa#aaaaaabcaabb##abcbbaabcedccdcbaaccccba####a#aaababcbaaaabbccbbaaababccbaa##aa##aaabaaaaaaabaa",
+"aabaaaaa#a#####a###aa##########..######aaba####aaaabb#.###############aaab##.###a#a#######aaaaaaaaa#a#aa###a##aacdceddfgfcfffgdccdeeefggdbaabbbbdcaa###aaabbcddeb##a#adfeaaaaaaaaa#bbaaccbeedhecbabbaaa#########.adccbcdbdbbcbba#######a#cda########abbaaaba##abbacbbaabaaaaabaaaaaa########aba##aaaaaaaaabcaaa#a##abca#aaabdefecbaadbbbaa##aa#aaaaaabdcbaaaaabcbaa#aaaabbbaaaaaaaaaaaaaaaaaaaaa",
+"aaabbaaa#########a##aaa###########.##.##aaaa#####aa#cba################abcb.####aaaaaa##aaaabbabaabbbaaa##aaaaaccgghggecdfihhg#a####a#a#abbccccacdcabbbbbacccdfeba#####aaaaaaa###a#ababbccadcgedccbaaa############ccbabccbcacabaa#####a#bacd###.####aaaaaaa###aaabbccaaaaaabbabbaaaa###.##..#bbb###aaaa#aaaaaaa########a#aabccceecbbdbbbbaa#aaaaaabbaadccbaabaabba#####aaaabaabaaa##aaba#aaa#aaa",
+"aaaa#aa##############bba##########..#.############aaaaaa#####.##########abca..####abaaaaabbbcccbbccddbbabbbbbcdefebdfd##a#.bedaa#########aabbbcbcddddcbbbcdeffd#########aaaaaaaa#aa#baaabcbacegedbbaaa##########bcdbaabbcccbbbaaaaa#####abbcca####.##aaa####aaabbcccdbaaaaaaabaaaaaaaa####.###abba##aaaa#aa##a############aaaa##cfebdcabcb###a##aaaabbabacbaaaaaba#a####aaa#aaaaaaa####aaaaaaaaa",
+"abbaaaa####a##########aa###################aaa####abaa#a################aabc#.#####aaaabbbcdddcdfffefgffeddfgdcdcb####aaaa###bb#######a##aabacdcddbdccacdefecc#a##a#####aaaaaaaaaa##aaaaabbbabfgdcbaa########aaacbbbbabbbbcdaba##a#####a#abccda####aaaaa#aaa#abaaaccbbbaaaababbaa##aaa#########bbba##abaa#####aa#a##aaa#a###aaa##defdcabbbaa##aa#aaaabbbaaccaaaaab######aaba#aaaaab####abaaaaaaa",
+"aaabaaa#################abba###############aaaaa##aaaaa#a###############aacaca.#####aabbbbccddfda#adeca#####b###aa#aa#aaaa##aaba#a####aa#aabccdccedebaacccb####aaaa###a###abaaabaaaaa#aaaaaababdgdbb##########cabbdbbbaaaaaccaaaaaaa##aaa##acdc#.#aaaaa##a##aabaa#ccaaabaabbaaacbb##abaa######..abca##aaaa#####aa#aaaaaa######abaabdggcaaa#aaaaaaaaaaacba##bbaaaabba#aa#aaaaa##aaaba###aa#aaaaa#",
+"#########.#################aaaa#.#.##aaa###aaa##aaa##a##aa###############abbbba#.##.#aabbbbcefc####...#####aa#####aa###aa####aa#######a#aaacbacbbdddbbccdfecbcc###aa####aa#aaaaaa###aaaaaaa##aaacfdaaa#####aaaabbabbbbaaabbabbaaa###aaaaaaa#abce..##ababc####aaaaabdaabbbbbbaaabbbaaa#a##.#######abaa#aaaba##aaaaa#a##aaa###aaa##ababehcaaaa##aaaaaaaadc####abaaaaaba###aaaaaaa###aaaaa#aaa#####",
+"####a######################aab#....##aacaaa#aabbaaaaa#####a##############aabbbcb##.###abbcceca###################aaaaaa#a#aa##a#aaaaaabaabbbbbacaaabbabaafddcbcb###aaa#aab##aaaa######a#######a##cfeaaa#####abcbbbbaaaaaabbabba###aaaaa#aaaabaaee#.##ddaaa####aaaaacaaabdcbbbbaabaaba#aa##.#######aaaa#aaabaaaaaaa##aaa#a##a#aaaaaaabbcgebbba#aaaaabaabbaba###aaaaabbaaaaaaaa#aaa##aa#a##baa#a##",
+"####a##aa##################aabda#.#####bcaa#abaabaaaaaa###################aaabcdb.####bbbdea##########.###########aaaaa##aaaaa##aaabbbbcbccbbaaaaaaaabbbaaaacdcbbbaaaaaaaabaa#aaa################abecaa####aadcabcaaaaaaabbaab#####aab#aaaaabaaade#..#ca.#a####abcbbb#abbccaaabbbabbbb#a############aa#aaaaaaaaaacaa##aaa##a#aaaaaacabccfebbbbaaaaabbbbaaba####ababacbaaabaaaa##a#aaaaaa##aaa###",
+"#####aaaa###.#a######a#######aab##..####abbbbbbbbaaa#aaa####aaaaa##########aabddea.###abda#################a#########a#####aaa###aaabbcdcbdbbaaaaaaaaabbbaaaaacddcbaaaa###abaa######..############abeda###ababbbccbaa#aaaaaabaa##a###ab#aa#aaaaaacec##ab.########babbaaaabbababababbcda###############a#aa###aaabcbbaaaaa###aaaa#ababbcdcdecaabaaababbaaa#######aaabbbbaaaaaabaaaa######a#aaaaa#",
+"a#######aa#a######aa#a#aaa###aaac#########abddccbbaaaaaaa####aa#aa########.abehghhc##abca##aaa##################################a#aabccb#aabaaaaaabbbaaaaaabaaabbbdba#aa###aaa##################aa#abefccaabbbcbabbaaaa#aaaaaaaa#aa###abaa##aaaabbcfdaba.#a######bacc##aaaabaababaabcbca##.#####a#####a#aaa#####aaaaab##aa##aaaa#aaaabccebbffbaaaaaabcaa###a#####bbbbbbbaaaaabaa#aa######aa#aa#a",
+"#baa#aaaaa###a#a#aaaaaaa####b#aaba#########aacbdcccaaa##a###aaa#aa##########bbfikjicacc###aa#aaaa#############a###################aaabccca##aaaaaabbaaaaabbbbaa#aabcbbaa####a#################a#aabaabdfbdcccbbbbbbbbaaaaaaaabbaaaaa#a#aaa#aaaaaabbcfdbb#######a#aaac##a#ababaaaabbcdaaaa##########a#aaaa#a#aa##a#aaaaaa#aaaaaaaaaaabbccdcaaegcbaaaaacaa#####a####bbbbbbbaaaabba##a###aaaaaa####",
+"####aa#aaaa##a#aaaaaaaaa##a#####aba##########aadcbbba####a####a#aa##########abcdfhiigc#a##aaaaaaaa#aa#####################a#######aadccccaba##aa#abaaaabbbcaabaaba#aaaaaa####a###a#a###.#####acbbcbaabcehfdccccbbbbbbbaaaaaaabaaaaaabaaaa###a#aaaabbcddca####.#####aa##aaacbabbbbaabcba#bc############aaa##aa##aaaaa#baaaaaa#aaaaaaaabccdeba#cgfbaaabca#a###aa#a###bcbbbbbbaabbba##b###aaaa#a###",
+"###a#aaaaa#aa######aaaaaaaa######aaaa#######a##aaaa####.###aaaaa#a###########abacdhiiga##abbaaaaaaaa##############a########a##a##abbcabc#abbaaaaaaaaaaaaaacaaabaa###a###aa###a###aaa########bbbbcbbbbddceihebbcbbbbbabbaaaaaaaa#aaaaaab#a#####aaaabbcccfb#.########aa##abaaaaaaabbaaaabbcbc#####a######ba##aaa###aa###aa##abbaa#aaaabbbdcccbbabdhebcbaaaaa####a#####accbbbbcbaacba#aa###a#aaa###",
+"#a####a#aaaaa#aaaaaaaaaaaaaa#######aba#######a####ab########aaaa##a#a##.#..#####aehhjihb#abacba#aaaaaa############a#a########aa#aabdcc####abaa##a##aaaaaa#ababa#a##aaaa#######a#aaaaaaaa##aacaabcccbcbabbcghgdbbabbbccba##aaaaaaaaaaaabaaa####aaaabcbcdccaa#########.##aaaaaaaaabababbabaa#######a#a##abbba#a######a###aa#aaaaaabbaabbcdbbbbabbadffbbaaaaaa#a##a####aabcbbbccabbabaaaba##baaaa##",
+"##aa###a#aaa#a##aaabbaaaaaaaaa##aa###a#############bba#.###aa#aaaaaa#######.####adfehjif###aaaaaaaabbaaa#a########aaa###a######abbbbcca.###a###########a###aa###a#############aaabbbbbaaceb#aaabbbccbaaabbbdggdcbbabbbbaa###aaaaaaaaaaba#aa#a###aabbbbcdc#####aa#######aaaabbbaaabbbbbbba#aa#######a##aabbaa#######aa###aa#aaaaaabbbbbccaaccbbbccdfgedaaaaaaaaaaaa##aaaccbcccbbccba##aa##abaaa##",
+"########a#aaaaa#aaaaaaaaaaaaa#aa#ba###########a####aaaaa#.##aaaaaaa##a#a########bbceeijfc####bbababaaaaaaa#########aa##a#aaaaabbadcccba####.############aaa#aa#############a##abbabbbaa##ceaaa#aaaabbbaaaaabbdgfbbbbbabba####aaaaaa#aaaaa#####a#aabbbccdccca#aaaa######aaaaababbaaabcabba##ba##a##a#aaaaaaaaa#######a#a##aaaaaaaabbbcccaabbddcaabbabdffdbbbaaa#aa####aabbccbbcbbddbaaa####acbaa#",
+"#######aa#a#aabbaaaaabaaaaaaaaaa##aa#a#############abaaaa####abb###aaa#a########babcfhiiea###acbbabbaaaaaaaaa####aaba#aaaaa#aaabaccbcbaa###############aaaa###a##############aabaaaaaa####bbbabaaaabbbbaaaabbbcffbbbbbbbbaa##aa##a###aaaa####aa##aabccefcadda##aaaabb#aaaaaaaaaabbbbbbbba##abb######aaaabbba###############aa#aabbcccbabbaabdccccaabacfggccbaaaaaa##a#aabccbbcaabdbacba####bbaaa",
+"aaa####aaaaaaaaaaaaababaaaaaaaaaaa#aa##############abbbbaaaaa##bbbaaaaaaa######ab#bccehiic###abcaabbbaaaa#aaaaaaaa#aaaaaaaaabcbccacba########.##########aa###############a#aaa#aa#a##a#####acbddcbaaabbbbbaaaabbefcbbbabaaaaaaaa######aaa###aa#####abcdghedcbbbbbcccdcbbaaaaaaaabbbbbbabaa#.acca#a###aaaaaaa########a##a###aaabbcdcaaaaaabbaccddaaaaacaadggfdbaaaaa#aaaaaabccbbaacbaababaaaabbaa",
+"aaa#a#####aaaaaabaaaabbbaaa#aaaaaaa###aa#######.#a###abbbaabbbbaaaaaaaaaaaa####a##ababchie###aabbbaaaaaa#aaaaa#aaaaaaaaaaaabccccbccb####a#############aa######.###########aa###aa#aaaa#a###abcccdbbbbaaaabbaaaabbceebbaabbaaaaa#########aaa##aa#####acdfdefebcddcbbdffdcbaabbaabbbbbcdbbaaa##abca#####aaaa#a##a#aa####a#a##aabbdedaaaaaa#aaccbeda#aabbaaaacefgfdbaaaa#aaaaabcccbccabaaabbaaaacc#",
+"##a##aa###aaabbbaaaaabcbaaa#aaaaaaa#a##########a#####aabbaaabaabaaaaaabcccca########aaacfhc##aaabccba#aaaaaabbaaa##abbababbcccbeecba#####a########a####a#a#####.##########b######a##a##aa###aababaaabbaaaaabaaaaaabdfcababbaaaa##############.#######bddcbdeffcbbba##dihdcbaaaaacaabbbdcaaabaa#aba#####aaa######aa##a###aa#abcdccdb#aa###aaaccdcbaaaaaaabbaaabehhebaaaaaaabaccbcbbbaaaaaaaaaaacb",
+"a##aa#####aaaabbbaaaaaababaaa#abaaa#############.###aaaabcaabaaaabbbbacdedaaaa######a##bccdccaaaaaacdcaaababbbaababbbccbcbbcdcceedc####a##a###########a#aaa######..####.####.###aa######abbaaaabaaaaaaaaaaaaaaaaaaaacfeedbbaa############.######aaaa#abbaaaaccbabaaa###igdccbbbaaaaaaabcbabcbcb##a######a####a#aaaaa####aaaacb#abdcaaa#a###a#acddcbaabaaaaaaaaadfhhedaaabbabbcccbbaaaaaaaaaaaaaa",
+"ba##a##a#aaaaa#aaabaaaaaaacaabcbaaaa#aa#########.#########aaaaaa##ababdefcab#aa########aabdfgbaaaaaacdcaaabaaaaabbbbabbcbbbcccddaaaa####aa#aa########a#aa#########..##.##..###.###aaba###aaaaa#abaaaaaaa#aa#aaaaaa#aaaegdcbbbaa###########.######aaa##aaaaab#abaaaaaa#.febaaabcccbcbbcbbaaadbcecbaa#####a#aaaaa###aaa#aaaaabaaaabccaaaaaa#aa###adbbbcbbaaaabaaaabbchifbabcccabbccaacbaaa##a#aaba",
+"#ba########a###aaaaaaa#a#aaa#abaaaaabaa##a#aa###############aab####aaaaabccaaa##a#.#####abcdfb#aaaaaaaaabaabbbcbbbbbababbcdddfedcb#a##aaa#aaaaa###aaaa##aaa##.######.###.###########a#########aaaabbaaaaaaa###aaa##a###bfedcbbaaa############a####a######a#aaabcbbbaaa#gdaaa###bcddcecccca#addefgfddca###a##aaaaaaa##aabaacb####bbdcaaaaaa#aa###ccbbbccbaaaaaaaaabaadhieabaabbccdcbabbaa#####aaa",
+"#aab####aa###aaaaaaaaaaaaaaaa#aaaaaaa#####aaa#a##.############aa#abaaaaaaabaaaaa########abccdfcaaaaaaabbbaa#abbcbbaacabbbbcddecdcc####aaa#aaaaa#aaaaaaa##aaaa###..######.#####a########aaa#a####aaaaa#aaaaa########aa####dedbbbaaa##############a###a#####ababccbaaaaa#gcaaaa####bdebbbbbca#bddcbaabccaa##a##aa#aaaaaaabbaca####abdbaaaaaaaaaa#a#ccbbbbbbbaaabbaabba#adhgcbaccccccdccba######aaa",
+"a##aa#a###aaaaaaaaaaaaaaaaaaaaaaaaa#aa###aaaaa###.#############a##abababbaaaaaba######aaabbcddhcaaab##baaababaabaaabbabbbbcdddffeeb###aaabcaaaaaaaa###aaa#aa####.######a#######b#####aaacb#######ababaa#aaa##aa########a#aaeecbbbaa##################a##a##bbaabb#aaaa#cd#aaaaaaaace.aaa#bdccdcaaabcacbaba###aaaaaaaabaabccaa#aaabbd#aaaaaaaaaaa#bcccbbbcbbaaaaaaabbaabbhidbbcccbdeddaaa#aa#aa#a",
+"aaaa#aaaa##aaaaaaaaaa#aaaaaaaaaaa######aa#aaa####..#########.###aaabbbcbbbaaaaaaba#####aabbcccegcbaaaaaaaacbaabbaaabaaaabcccdeeffddaaaaabcbbbcfffecdcba#abb#############aa#a##acbbcba#bbaa########aabba###a##########aa#aaa#eedccbaaa#####a#a###########aaa#aaa#bcaaaaaafaaaaaaaaacfa##a#aaaba#abaaccbcbbccbaaaaaaabbbbbbaaaa#a#abccc#aaaaabaaaaaadcbbbcbcabbbbaaaaabaaccfjgbccbcccccaa##aabaa#a",
+"#a#aa#aabbaa#aaaaaa##abaaaaaaaaa##aaabaa##aa#a###.#.##############aabbbcacbaca#aaca#####aabbccdeedbaabbaaaabbabababaaaabbccdddffedffb###bbccefebccbdeda#aaabbaaa#######aaaaa###aabcca#adaaa#####aba#aaaa##aa################.cedcbbbbaaaaaaaaa##a######aa####aa#bbaaaaaadc#aaaaaabbee####abaaa#aa##abaaabbabdcccdcbbaccbcb##aaaaabbcdbaaaaababaaaacbccbbccbaaabbbbaabababadjiedccccbbbaaaa#aa#a#",
+"aaaaa###aaaa##aaaaa####abaa#aaa#a###aaaa######aa#################a##abbbcccbbbaaabba##.#aabbbbddedd#aacb#aaaaaaaaaaaaabbbccdddggffghecbbaabbbddabaa#aaaabaaa#bbbaaaaa##a##aba###aaabb##bbaa####aaaa###########a########.#####aaeecbaabbaaaaaaaaaaaaaa###aaa##a##aa###aaabeabaaaaaabchca###a#aa#a###a##aa####bca#abdecbcdbaaba#aaabbdcaaaaaaaabbaaaaccbbbccdbabaaabbbabbbabacjkjgfdccbaaaabbaaa##",
+"#a#aaaa###caa#####aaadb#aaa#aaaa#aaa##aaa###aaaa#a####a##a######a#a##aabbbbabba##aabaa##aaaabacdececaaaba#aaaabaaaa#aaaaccdeeefgeeefbcbbbcbbbcbaaaaaaabaaaaaa##abba##a#####aaa###aaaa##.#ba##.###aa############.##.#############dedcbaabbaaaaaaabaa###a###aa##aa#aaaaaaa#dbbbbbbbaacgg#b####a####a##aaabaaabbcaa#abacdcaaaabaaaaabbccaaaaaaaabbbbcbabcacccccbabbaabbbabcbbaaejklhfcbcbbaaaa#aaaa",
+"####aaaaa##aaaaabaaaaabbaaa##aaaa###aabbaa###aa#aaaa###aa#######aa#a##bcccaaabbaa#acaa###aaaabbcdcdcbaabaaaaaabaa##aaaabbccdfffghffdaabbaabccddbabaaaaaaaaaaaaaaaaa##a#######a####aaa###.aba######a#################a############bfedbaabbbbbaaaaabaa##a#########abbbba##dcbabbbaaabcgdc#####aabaa###a#bbbbbbbbbbaaabbcbbabbbaaaabbbdebaabbbaabcbbbbacbabbabbbbabbbaababbbbbghillgcbbbbbaabbaaa#",
+"###aaaaaaccdcaaaaaaba##aaaaa##aabaabaaab########aaaba####a###a##aaaaaabccbba##bbba#bca###aaaaabdcddcda#abaaabaaaaccaaabbbccefgfghffaaaabbaaabefbcbaaaaaaaaaaaabaaaa##aa#########a########aaa###a##############.##.#.############a#abdebabcdcbbcbaabba############acdea#abecbaabbbaabbdfc##aaaa#a#aaa##abbbcaba#adebaecabbaccdcbbabbcbdddbabbbabccccbbacbbbbbabccbbbbbaaaabcbcfijjkjfddcbabdebaaa",
+"db#bdccbbcb##aabbbbaa###aaabbbbaccaaaabca####.#####baba##a#aaaaa#aba#accbbbbaaaaaaaacbaaaaaaaaacccdccc##abaabbaaabdbabbcccdffffhggbaaaaabdbaaaababbaaaaa#a#a#aaaaba#a#a################aabaaaaa###########.#####...#####.##.####aaaa#bedcccaaaaabbaaaaa##a#####aaaaddaabdebabbbbbabbbbgcaa#a#aaaa###aaabdaddabaadcfdfgdacbaabcbbbcccbdcdffdacdcedccbbbacbbbbcccccbbbbabacabbdgigbbgjjedcbbbccaaa",
+"#bbbaaaaaabaaabbbea#aaa#abbbbabaaaaaaaaba#############b####aaaaaabaa###abbbbbaaaaaaaacbaaaaaaabbcccccdd##cbcbcaaaaaaabcdeffgggiigabbbbbaabcaaaaaaaaaaaaaa#aaa##aaaaaaa################aaba###baaaa#######.#####....#########.#a##aa##a#adfca###abbaaaaaaa#####a####bdbacfdaaaaaabbaacedfa#aa#########abefeddcccdebccfggfedaaccbacddecdccdeddccefddcccccccabaabbabaabbaabacbbhijgdbacfkjeedcba#a#",
+"###aaaaa#abbaaaaaaa#a####bcaaaba###a#aaaa######a####aa######aaababaaaa##aabbaaaaaaaaabcaabbaaaaabcbccccbcbaaaaababbcccdefgfgghkgbaabbcbccbaaaaaabaaaaaaaa#aaaa#aaaaaaaaa####a########aaabba#aaaa#####a#.###.######.#####.####.##a#abaaa#aaddaaabbaaaaaaaa#########aabgggfbaaaaaabbbabbcfea#a#####aa##afghhfggghhgccddffhfffcccbccdfgeeeceec#aabcddcdddccebaaabaaabaaacbbbb#ejhjgbbceceikibbceba#",
+"aaa##a#aabbabbaaaaaaab####bc#aaaa#aaaaaa#ab##aaaa##a#aa######aa#baaaaaaaaaaaaaaaa#aaaaacbaabaaaabbcccccdbaaaabbbbccddeeefeegjheb#a#aabaccdcaaaaaaabbabaa#aa##aaaaaaaaaaaa#######a###aaaabba#abaa####..###.###.####..#####.#######aa##ba#####bcbaaabbaaaaaa########abdfggebabaaaaaabbbbbchfaaa######abbfegggefgghgffeecefggfhheecdddeeefdcefcabaabccbaabcbcbaaaaaaabbabbbbbbfghggdbcbcbbgkjfbbecb",
+"#aa#a###aababbbaaaaaaac###.acaaaba#aba####ac#aba###aaaaaaa#aa##a#a########aaaaa#aaaaabbbbbaabbaaabbbccccebaaaabbccddddedegggfhbaaa##aaabcccaaa#aaabbbbcbaaa#####aaaaaa#aaaaa#####a###aaaaaabbdaaa########...##.###..########.#####aa#aba###a#accbaaaaaaa#######aaaaabccdeeccbbaabaabbbbegfgeca#####adefffefgggfghggfeeccegihijigedbccfeceddfeaaabcacbbaaabbaaabaaaabbbbbcbchgghfgdabbaa#bgkjgcdd",
+"d#a#a####aaaabbbabaaaaaa####abaabaaaaaaa###acdbaa#a###aaaaaaaa###########aa#a####aaa#abbbbbaabaaaaaabcbccdaaaaabccddeefefhgefgbaaaaaaabaabbaa##ababbaaabcca#aa#aaaaaa##aabaaa####a####aacba#bcb#aa#.####.#...##.##..################a########a#adbaaaabaa#aa##aaaaabbbcdeddddcbabebbcbbffeefdec##adeeefeffefghgghghhgfedfheabfghhfdcegecbbbbccaaaabcaaaaaabaaabaabbbbabbcdfffgffffabbbbbcabgkjec",
+"cdaa##aa#aaababbbaabbaaaa####bbabcaaaaaaa##.acaaaaaaaa#aaaaa#ba###########aaa#a###aaaababbaabaaaaaaaabcccdgbbbccccddeffefgfeffbaa###a#aaaaaa#aaaaaaabbbccaaabaaaaa##a###aaabfd#####aaaabbaba#aa########.###.##.###############################bacedcbbbbabaaaaaaaaabcccccddedddbbdeecdefeededdeeffdegffeddefgfgggggcb##abbca###bbefeefeddcdcbeeaaaaab#a###babbbbbababcbccfgfeeefegcbaaabbca#afkh",
+"gdcbaaaaaabbbaaabaaabbbbaaa###bbcbaa#aaaa#####a###aaaaaa#aaa#aaaaa##a#####a#aa#aa#a#aaaabbaaacaaabaaaabccdfgddddddccdfhhffddfbaaa####aaaaaaa##a#aaaaaabbdb#aaaaba#a#######aacegdbaa#aaabaabbb########.#.##.##..#...####.#######################babedededcbaaaaaaaaabccddeedefecfffeeffddddddeddeeeddeggfddeeffbaaaaaaaabdb#baa#a##cbdfeaaabbcdfbaaaaa####a##abbbbaabbbbdcgfgeeedeefabba#aaaaaabg",
+"gjgccbaaaaabbbbbbbbaacbaaaaa###aaaaaaaaaaa####aaa#####aaa##aaa#a#a#######aaaaaa##aaaaaaaabba#acaacbaaa#acccfgdefefcdecfhhddbcaaa#a#####aaa#aa###aaaaaaabbeebaaaaaaa####.###aaacdcbaaaa#aaabba#############.#.#.#...###########..###############aacddeeededceeedccefggfgggfedggghfdfecdddccccddeeeeefddfffddddbabbbaaaaabefcdb#aa##aaabcaaaaa#bdgb#abaa#######ba#bbaabaaeegfgfeeeecfcaaa#aa#aaaa#",
+"#bgifcbaaabbbcbbbbaabbbaba#a#aa##aaaaaaaa######aaaa##a#aabaaaaaaaaabaaaba##aaba###aaaaaaaaabbabbabaa#a#abcceffeecb#cddeeggcdb##a##aa##aa#########aaaaaaa#bedaaaaaa##########abaa#aaaaaa#aaabaa#####a####################..######.#a##.#########aabcccbcda##afgggffdbbbabdhheghifedddeecbccdcdefffeeffdfggfdbaaaaa#aababbacdddb#bb#aaa#a####ababbdebbbaaa####a#babbaaacddfgffeefeeddcbabbaaaa#aaa",
+"a##ehiecbbbccdccbbbbaabbaaa#aaa##aabaaaaaaa####aaaa#####aaba#aabcbbbaabbba##abaaa######aa#abbacbaaaaaaaaabcccdfcaa##bbbbceabaa######aa##a##aa####aaaaaaaa#abaaaaaa###a######abbbaba##aaa#a####aaa###a############.########################a####aa#dcddcdb#a#dedeedcaa#baacgegiifedddddddcdddefeffggfgeedbba#aaaabbaabaaaaabceebbdaaaaa######aaaaabdddb#aaaaaabacbbbaabdfffgfgfeeeeddgcbaaaaa####",
+"#b##adiifdbcefedccccbaabaaaa#aaaaaaaaaaaaaaaa##abaa######aabbaabbcbbaaaaaaa#abaaa#######aaaaabcca#aaa##aaaabbccc#########a###aa##a###aa########aaa##aaa#aaa#aa#aba##a#######aabbabcaa#ababbca##aa####a#####a.#########################a###a##acba.ddeecccba#cfeeedcaaaaabccbaigfeeeddddcbcdcddfeffggeedaabaaaabaaabbabaaaaa##cffedeaa#a#aaa#aaaaaa#abfebabaaaaaacadcaaffecffffgfffeeggaaabaa####",
+"#caaa#.ahjgffefgggffecbbbabaaaaaaaa#aaaaaaaaababaa#aa#a#aaaabaaaacccaaaaaa#a#aaabaa######aaababaaaaaaaaa#aaaabccb####aaa##ab###aa#####a#a####.#aabaaaa########a##aba########acbbaaaaaaaaaabbbaaa################a###a####aa############aaccb#adcbbdddccbcdebdedccba#a#aabdcbaggeeddedcbbbccdeeffffhggfcbaaaabbbcaabaaaba####a#debceea#aaabaaaaaba#aaa#cfgcaa##aabcbcbdffedfeeeefefeedhcaaaa#a###",
+"####aa##.behhgfeeeddefedbbbbaaabaaaaabaaaaaaaabaaaa#aaaa#a#abbaaabbcbbaaaaaaaaaaaba####aa#aaabaaaa##a#aa#a#aaabbcc.##ab##aabca##aaaa############aabaaaaa#a#a#####aaa#bb#.####bccbaa##aaaa###aaaaa######a#######bbabba####bb###a#a###a###bcccccdcdccddcbbabcdcddccba####bdddb#bdcecdedcbbbbbcceeeeehhcdaaaababcbcaaaaabaaa#####ab#aabb###bb##abcaa###a##adfeba###aabaaefefffedddeedefefhbaaa###.#",
+"#####aaaa###chikjiigedcegcccbabbaaaaaabbaaaaabaa#aaa#a#a##aaaaaaaaabaa#aaaaaaabbbaa######aaaaabaaaaaa##aaba##aaabab.###aaaaaabaa#aa#a#############a###aaba########aa#cbb####abcbaaa##aaa#a######a#.####aa###bbccbbdccbaaabb###a#aaaaa###cbbbaccccbbcccaaaabbccccbbaaa#accdcb##bacgeeedccccbccdeeefggebdaaaaabbbbbbaaabaa#####a#a#aa#####aaaa##ca#####a####beeca#b#abadgefffedeedfdcffeff#a#a###.",
+"..######a#aaadd#acdhihecdgecbcaa#aa####ba#aaa##aa##aaa###aaaaaaa##ababaaa#aaaaabbbaa######aaaaaaaabaaaa##baa##a#a#b######aaaaaaaaa#################a#aa#bcb#####aba##a######bbbcbaabcaa#################a#abcdbdefededcbcbaa##aaa#a###bcbababbccbbbbbcaaaaabcccbaabaaaabcdbba###bhhfhgeddccbccddfhhhfbbaaaaaabbbccaaaabaa####aa#a#####b####aa#aa#ab###a##aaabefd#a#abbfgfeeeeeedeeddefggbaaa####",
+"##.######aaba#abaaaabeiiebceddcbaaaaa###aaba#########a##aaaaaaaa###aaaaaaaaabaabbbbaaa###aaaaabbbaaabbaaaaa###a###bb#####aa###########a######a#####aa#baaaba##abcedcbaa##a##bcccbaaaddccaa##############a##bbceffgfededdedcbaa#a#aaa#bcabaaabbbccbbbbbbaaaabbcbbbbaaaaabbcda#a##ehgfeeeeecddbcddfhhgcbbbbbbaaaabcbbbaaaaa###.#a#a#a####aaa###aa##a########aabbbedbacfegggfeeefeddccddgihdaaa####",
+"##.###a####aaaa#bacbaa#chidccdfdbbabaaa#ababaaa###a###aa#aaaaaaaaaba#aaaabccccbcccccabb###aabaabbbcbaabaa########aaab.####aaa##################a####b##aaaabb#aacdddcbb#######bccaaaabdbba#####aa#a#########abccccccddcffhigcbaaa#aa#acaabaabbbbaaabbbbbaaaabbbbaaaaaabcccdda#a#higheddefedeecdffffeeaaabbbbaaabcbaabaaaa#########a####aaaa######a#######aaabdcbadgfdeddegfgfeedcccccehigaaa####",
+"###########aa#####aacdb##ejgcbbfedcaaaaaacbabaa#####aaaa#aaaaaaaaaaa##abbbbbbaaabbcddddbccdcccbababaaaaaab#########aba..####aa###################aa########aa##aaaabbbba##a####ccaababdaa#aa#####aa##########aaaaabbccdfgjjihdcaa#aaaacbaabbababbaabbbabaabbbbbbbbbbbbbcccddebadhggfffeeffffeeeffdccddaaaabaaabbabbbbaaaa######..######aaaaaa#a###a#aaa###aaaccc#ceggedddcffffedcbabccdfgebaa###",
+"#########aabaaa####a#aabbachjgbacdedcccbabaaaaaaa#####aa#######aaaaaa#aaaaaaabaaaabbccdccddcbbbabaaaaaabbaa########aabb.#######a##################aaa##########aa##abaaaaa######bbaaaaba#a#a#.##.#a#aa###aa###aaaaaabcddgijijjigeba#abdcbbcdcabbbbaabbabaaabbbbaaabbbbbcacddee#dfeeeffeccdghhfffebccccaaaaababbbbaaabba#a########.###a##aaaa##aa##aaaaa####aababbddceggfedcdffedcbaabcdeeffaaaa#",
+"#######a#aaaaaa#a#####aaaabcdiibaaacecddcbaaaaaaaaaa##aaa########a#aa###aaaaaaaaaaaaabcccbbaaaaaaaaabaabbaaa######aaaaca.###.##a#a####a########aaaaaaa##...###a###a##a#aaaa#####bdaaaaaa########a########a##a##aaaaabbbbegfeedeghgeccddeeefgcbbaaaabbbbaaaabbbaababbbbcccbceeebegdddeffedbdeiihecbcbdbaabaaababcbbaaabaaa#a#.############aaaa##b#a##aaaaa##aabbbbccdceghgeddefedcaaaaccdedfaaaa#",
+"########bcaaaaa##########aaaa#gidaaabedcccbbbaabdbaa####aba#a#############aaaa###aaaaaaacbbaaaaabbabbbbbcbbabaa######aabb..##.####aa#aaa######aaaaaaa####a#.####aa##ba#aaaba#####dbaaaaa######aaa#aa######aa###aaa#aaabccebabaabbdfhhhgfghggdbaaabbcaaabbaaabaaaaaaabccccccedchigdcdddcedccabghdbaaabcaaabaaaaabbbbcbbaa##a########a##.#aaaaaaaaa#aaaaaaaca#acbbbbbcccdefeddeecdcbaababcfdfeaa##",
+"########baaaaba#aaaa#####a####aciib#aacdddbabbaabbb#aa#####aa#############aaaa##aaaabaaaabaa##aabababbbbccbbbcb#######aaaa#...##.#####aa########aaaaa######a############a#aaaab##abbaaaa#######cb############aa#aa#aaaaabaaa#######bfhigihhfbaabaaaaaabaaaabbaaaabaaaccbccdcchiihhdbcddcddccbbeeaaaabbbaaaababaabbbeeeaa#####.###.aaaa#aaaaaa#aaa#aaaaaa#bbadccbbbbccccbcddddcbcccbaaaaddddge###",
+"########a##abbaaa#########a#aaabcfjhaaabcdecaabaaaaaaa#######a########a#aa#abaa#####aaabaabaa##ba#abbccbaccaaca########abcb..######################aa###ceb#######aaa#####a#aaa###acaa#aa#######b############a#a##aaaaaabaa########abacfhhfcbbaaaabaaabaaaaccaaaaaaaacbcbbcffgfgcegeddeddcdccbcd#aaababbbaaababcaabaaccba########a#abaa##aaaa##aaaaaaaaaababcbbbaccbbcbccdddcbbbcbbcbbadcdeehd##",
+"########bb####aaba#########a####aabfjfbbcbcfdbabaaaaaaba######aa######aaaaaaaaa##a#####aaa######aaaabacbbaaabaa#########aadc...#######.##########aaaaaa#ddeb#a####aaaabeb######a###bbaaaa##b####aa#.##########a#a#a#aaaabaaa##b###.adbaabeecbaaaaaababaaaaabcabaaaabbbbbcdcfgeddgbbggeedddcccccc####aabaaaaabbaabaaa#acda############aaaaaa#aaabaaaaaaaaaabcbabbbabcbbbbcddccbcbbbabbbbccdfggf#a",
+"aaaa####bc##a#aaaaaaa###.#####.####aciiecccbceebaabbabbb######a#a####a##aaaaaaa########aaa#######aaabcbbabbaaaaa#########acfc..####.#.###.###aa###a#a#aaabcaaaa###aaaa##########a##bdcaaaa#ba###baa##########aaa####aaa#bbababdcbaacbbbaaaabbaaa##aaaaaaa#aabbbaaabbbbbbcdcccddcdec#adfedddcccbe#####aaaaaaaaaabbbaaa#bdb##.#######.####aaaaa###aaaaa##aaabccbbbaababbbbbcdccccbcbbbcbbbdcefghc#",
+"########a#####aa#bbaaaba######...####adhifegfddfdcabccbaa###aaaaaaa######aaaa##aa##a###b##########aa#aaaaaabaaa######a###abdfb..#######.##.#####aaa#a###baaa####aaa#########a####a#bddcbaaaa####aaaa####ad##aaaaaa#######abadddccccdcba##a#ababa###aaaaaaaaabaaabbbbbcbbcbbccdccbaba##afedddccbfa######a#aaaaaabbabaaaaab#####.##..#..a###aaaaa#aabbaaaaaabcccbbbabbbbbbbbddccbbcbbbcbbcfdeeffha",
+"##############aababaaaa##########.##.#..chjjhjifffdeccdbaa#aaa###aa#####.##aa#######.#######a#########aaaaaaaaaac########acchc.....#..###########aa##aa#abaaa##aba##a######aaaa##a##bdcbaaaa#####a#aa###bd###aaaa#aa##a####adgdcbbcddbb###aaa#a#####aaa##aaa##abbaabbbbcbbbcccddeccc#a#bhggfedaec##########aa#aaababaaaaaa#####.##.##.####aaaaaaaaaaaaaaaabdcbbbababbabbbabddcbbbbbbccbbdifdefge",
+"a###a##########abb#aaab#a#######...#####.##a#acgkigfeefdcaaa##aa#aaba####..######.#a###a#aa#aa##.#######aaaaaa##ba#####aaabbeha...###.###.#######a##aaa#aaa#a#aaaa###aa#a###aa###a###cdcaaa######a#####abb####aaaaa####a####deebbbccdbba##aaa#aa####aabaa#a#aabbbaaaaabcbcbbccbcedbba###cdffffeefba###########aaaaaabcaba#####.####.#######a#aaaaaaaaaaaaacdccabbababbabbaabcccbbbbbbbccdeeedefh",
+"f#######aa##a##aaa#aa#bba#########..############afkjgfgfeeeba#aaa##a#######.####.#.#####abbbaa##########aaaa##a#a#######abbcdhe#...######.##a####aa#a###aa#a#aaaaa######aaa###########bdbbaaa####a######aa##.##aaab####aabdecdcbaabbbaba##aaa#########abaaa##abbbaaaaabbbcdbaccbcebaa####adghfedeeba#############aaaaabbcb##########.######aa#aaaaaaa###bcdccbbabbbacbaabbbbbbdcccbbbbbcccccddeh",
+"hc#####aa######aa####aaaa#####a###.......##aa##a###gijhhhggeb##baaaa####...#####.#..a###acccaaa##########aa#####aaa####aacdddhf#..###.#..####aaaaaaaaaa###a#aa#aaaaa#####aabb##########cecaaa####a##############aabb##aabacddbcbbabbbaaaaaaaa##a#######baaaaa#abbaaa#abbbabcbbbcdgd####a##adcgfecdeb######a########aaaa#baaba########.######aaaaabbbbbbcbccbbbbbbbbbaaaaabbbbbbccbcbbbbcccccdeed",
+"egb##baaaaa####a##aa#aaa#a#######.#..###.###########adfilkhfca#abaaa#####..##....#....###bbccaa##a##aa####aaaaa##a##a##abbcfhjfb#..#####.######aaaaaaa######aa##a#abbbba###aba#aa#######cecaaaa###a#.#######aa##aa#aa###aaabcbcbbcbbaaabb##aaaaa#######abaaaaaabbaaa#abbbbbabbabdfeaaaa##a#ca#eecccfcaaaaaaaaa#a#a######aaaaabca########a####aaaabababbbbbbbbbbbbbbbaaaaaaabababccccbcccdccbdffd",
+"cfhd#acaaaa##a#######a#a##a###a##.....######.##########bddjkidca#########..###....######acaacbbb#a###ab##aaaaaaaaaaaaa#aabcfgejfa#.###a######a##aaaa#aaa#a###aa##a#abbcba#####aa####a###aeedbaaa##aa####...#aaaa#bcaccbaaaabcdccabcbbbaaca#aaaaa#########aaaaaaabaaaaabbbbbbbaaabbecbbcaaaaaa#adecccedcaaaaaaaaa##a###########abaa######a####aaaabdbbbbbbbaabbbbbabbaaaaaaaabbaabccbccbccdccdefg",
+"fedfea#a####a##a#a#######a####a#.##..#.####...########aaaaaeikhea#####################aaacbabbdfdbbaa#aaabbcbbaabaaaaaaabcdfbbeica..#a########aabaaaaaba#a###aa#######aaa#####aaa#.aa###adffdbaaa##ca####.#########abbcdeeeefcdcbabbbbbaacbbaaaaaa##a##a##baa##aa###aaaabbabbaabaadfb#bbbbbaa###feccbeecbbabaabaaaaaaa#aa###a####a########a##aaaaabbbbbbcbabbaaaaaabbbaaaaaaabbbabccccccddddeeee",
+"fggehdaaa######a##########aaaaa#.##.####..#..##.#######aabbaadjljgda.#################aaaccbccddcccccccccccccdcbbccbcbaabbcfdcbgf#...#aa######abcbaaaaabaaaaa############.##aa##a########dffedcbaa#cc##########a####bbbbcdffeedaaabbbbbcbabbaaaaaaa#######abaaaaaaaaaaaabbabbaa#a#bdcbbbaaaaa###cfeeehhecabbbbbbaaaaaa##aaa##a###a########aa#aaaa#bbcbbbabbbbaaaaabbbbbabaaaaaaaabbbbbcccddddeee",
+"edehhg#aaa######a#a#####a##abbaa###.###################aaabbcaacjllkhbaa#######a######bbaefddddcbbbaaaababefeedddccffdccdfgeeeefec#...#ab#.####abccbbba#aaaaaa###########..###a##########bfdfdccaaacfb.######aababaaaccccbdffebbbbcbbaacccbabbabaaaa######aaaaaaaaab#aaabaaaabaaaabbeffcaaaa####aeeeefiihfcabbbbbbabaaaaaaaa##a######aaaa####abbabbabcbaaaaccbbbbbbbbcbcaaaaaaaaaaaacbbcdddddede",
+"eefgghcaa#######a##aa######abbbcc#.############.###a#aaaaaaaaccbafjllkjecbaaaaaaaa##aabcccgefeecccbba#aaaa.acffffffcacdccbbbfffefda#.##########aabcedba##aa#a#####a#####..#####aa###.####bceecccbaabdfa##aabbbaabbbbdcbbccdcceebabbbaaabcdcbbbbbaaaa######a##aaaaaaacaaaaabbaba###acdeegcbbb#####aeffgfgijkgcbbbbbbbbabbaaaaa##a#aaa#abaaaa##aacdbabbccbaaa#bbbbaabaabccbaaaabbaaaaabbbccdeedddd",
+"deeffdfd#####a######a#######aaaca#a############bdca###aca##aaaceddfijjnligdcbbcbaaaaabcddchgedddbccaaa#aaaaa##accfbbbaa####bdhfedhd#.###########bbcccdba###aaa#####a##a#.#####a####.####.#abedebdcbbcfe#####adcbcddbbdbaaacbcbccbbbaaa#bbcbbbbbbaba#a############aaaaaaaaaabaaaaaaabdfcccbbba#####aceffgiijihedccbbbbbabbaaaaaaaaaaaaaaaaa#####aabaaabbbaaaaaabbaabbbbbcabaaaaaaaaabbbbcccdddddd",
+"ddddecbdca###a###a##baa#aa##abaaba#a###.#####.#aabaaa#aaa##aa#acdhilmklmlmkheegecbbbbccbcefgedcdcbbbbaaaaa#aba#a#cdabcbaaa#achihggfa############abdb#bcaa##aaa#########a###.######..########beddecbcdffc###.#acdfffdabcca#aabacbbbbbaa#abbbbbbbbbaa#############a#aaa#baaaaaba###aaadfd#babacababbbcegfhhiihgfdddcccbbbaabbaaaaaaaaaaba#aaa###a#aaaaaaaaaaaabbabbaabaaabcbbbaaaaaaababbccdddddcd",
+"deddddcacaba###a####aaaaaa#aaaa#aaa###aa#########a##aa#aaa##aba#.cfehhjkjllmllihfedcccbbdefgdcccecbbbccbaaaaaaaaabdbbbcbaaaabhjjhggea#.####a##a#accaa#cdaa#aaa#.#############a##a##.###a####.cedccccefbbaa#####deffeaacdaaaa#aabbbbbaaaaaabbaaabbaba#####a.###a###a#a#aaaaaaa#a##aaacdecaaaabaa#aa#bdgfeeefhhfdccccddcbbaaababaaa##aaaaaaaaa###aaaaaaaaaaaaaaaabbaaababbbbabbbaaaaaabbbbcdcdccdd",
+"dddcccdbbbcba#bb#aa###aa##a##a####a##.####aaa##a#aa##a#a#ba######.fffkjlhkkljmmmlieeddccefaeeeccdedbcdccbcbaaaaaabaccbccaaaabeijjigieba.#######aacbaa#accaaaaa##########a#a###aaa#############decabdeeeaba###..adeddcaabcbba##aabbbaaaaaaaaaaaaaaaaa#####a###########aa#abaaaa##a#abbcdeba#b#aa#####cefedcbbdeedcccdddcbbbaabbaaaaaaaaaaabaaa###aaaa#aaaaa###aaaaaaaaaabbbaabbcbaaaaaabcccccccdd",
+"ddccbcccbcedaddaaaaaaaaaa#aa#a######...###########aaaaaaaaaa####..cfhjjkmlmklkklmnjfeedeefebdeddegheeedddccbbbaaabbccbcbbaabbbgjkjjhifda.#######aaaaa###abaaaa####aaa###########aa##########..adccaddcecbabbaa##dedddcbabcbca#aaaabbaaaaaaaaaaaaaaaaaa###############aabaa##a####aacbcddebaaa########cffecdcbceeefdddddcbbbaabbbaaaabaaaaaaaaaa###aaa#a#aaaaaaaaaaaaaaaabbbaaaacbbaaabbbbcdcdccb",
+"cdcccccbbcdbaacbbbbbbaaa#aa#aaaa#####..#..##.#####a#aaa####aa######eigfcfgijjjlmmmmnlhfhiggdddeefgegfgffdeddcdcbaaccccbcbaaabbcfjkkkijgfb#######a#aa######a#############a###aaaaaba############abcc#ddcccbdecdcaddddddecbbbccaa###aabaaabaaaaaa#aaa#########.####a##a##a#aa#a######abccdgbb#ba#a######cffgfdefffehgdddeccccbaabbbaaabbabaaaaaaaaa###aa##aaaaaaaaaaaaaaaaaaaaaaaabbba#aabbacddccc",
+"cddcccbbcccaabbabaacbaaaaa#aa#aa#.#...#...#..###a###a#########aa##adeaaa#abedefijlkmnnlkkjdddfdcebb#degfaefgfeddcbdcddbacbbbbbbdjjklkkihgc#aa#####aa################aaa##a#aaabaaaaa###########aabdbedcabdddeeddddedcccddccbbbca###aaaaabba#a#####a#a###aaa###.###a#######aaaaa###aabbbbcdaaabaa##a####aeghhhggghhhfedddcccccbbbbbbbbbbbbbbaaaaaa####aaba#aca#aaaaaaaaaaaaaaaaaaaaabaaaaabbbcddd",
+"dddcccbbdedaabdaaaabbabbbbaaaaaa#.##.##.#.#####################aaaddbbaa#aa##a##aceejnllkkhfhfccfbbaaaabafabdeffgfcdddcabbbbabacgjkkllkhjhbaa#####aa############a##aaaa###aaa#aa#a#####.####a##aa#deedcabdeeeedeeddeedbccdcccdcb####aaabbbaaa#####a##a##a####################aa####aabbbcdea##a########aaabehiiiiiihfedfdccccccbacbbabbbcbbbbaaaaaaaa##ab##bbaaaaaaaaaabaaaaaaaabbbaaaaaabbbbbdd",
+"ddccdbcbedcaabbbbaaaaaabbababbaa#################a##########a###a#ecbaababaaaa#####abkllllljgbaaccbababbabaaaa#cedfheedcabbbbbbbchkkkklkhggeba###aba####.####a####a##aa##aaaaaaa##aa####.####a####dfdcba#bdeeeeeefedddcbbcdbbadcba###abaaacaaa###a##a###aa#####.####a######.##a####abbbbccbbc#ab##a#aa#ca###cfggihhihffffedcccccbbabccccdccbbbaaaaaaa#aa#aa#aaababaaabbaaaaaaaaaaaaaa#aa#abbcccc",
+"dedcccbcecaaacbababbbaabbbbbcbaaa#..###.#########a##############.cdabbbbbbbba###aabcddilmmljeaaabcbbbbbbbbbbbabaabcefgfecbbbbbbcdfjjkkkmkhfgecbaaabb########a######aaaaa####aaa###################befcbaabbadfeeeeffededcbbccabccccaa#aaa#abaa#######a########...###########.##..###abbbbcbbf#aa###abaa#a#####acfgffgfggefddcccccbbabcecbbbcbbaaaaaaaa##aa#aaaaababbbabbbbbcbbabaaaaa##aaaaabbcc",
+"cddecccccdcaaaaaabbbbaaaabbbbaaaa########.####################..aaababaaacbba#abddbcdfeejmllf#aabbbaabbbbbbaaaaaaa#afffdedcbbbddffjfijjkkkhgfed####aba#######a####aaaa#aa#####a######a############adffddcaa#befefedeeddccccbcbaacbaabbaa###aba####a###############.###########.######aabcddcefbb###bbaaaaaabba#cffffghhgfffedccccccbcbbebbbbbbbaaaaaaaa####aaba#aaaabbbbbbcbaaaaabbcbaaaaaaaabcc",
+"dddddfebdfeba##aaaaaaabbbbabaaaa####.#########################.abbaaaaaaaaabbaaabba##aceeilmme#aaaaaaaabbbbaaaaabbbbbefgeddcddddegiighiiggjggfdba##aaaa##############ba#b###aaaa#######a##a#aaa####dfgffgcaabefeeededccccdddcbbbbbaaacbab###aaaaaa########a#a########.#########..####aaabdcdecbdc#aa###aabbcccaacegggfgghggfeeeddddcccbccbbbbaaaaaaaaaaba#aaaabaaaaaaaaaaaaaaaaaaabbaaaaabbabbbc",
+"bcdeeeeedeeda##aaaaaaaccbbaaaaaaa####..##.#########a##########aaaaaaaaaaaaababba#aa####abbdhkmgbbbaaaaabbabaaaaababbbaehfcdeeeegghkkjjigdeehfeccaaaabcba########a####aaa#####aa####a####aa###baba##adfgfffdeeffdcddddddbcccdccbbbbbbb##bdb###aadb#a##############.##.######.##########abcdcedecegdb#a#aaabbcddaa#adfghfghgffefeefeeddcccccbbcbaaaaaaaaaaa#aa###aaaaaa#aaaab##aaaabbbabaaaabaaabb",
+"cbceeeefffffd#aaaaaaaaaddbaaaaaaaa#############.#############cbbaabaaaaaaabaaaaaaaaa###aaa#achlkigdaabbabbbbaabcaacaababccdbbdedcdfehkkjgeceheccda#aabbba###.######a#aaa#####aa######.#a#aa##aa#aa##adgggfeeggffdcccddcccbbcbccbbbaaa####ca##abcba#aa##########.#####a######.#.#######abbcbddbdfhgeaaa##abbcdcaaa##aaceghdfgffffffeeddddcccbbbaaaaaaaaaaaa##aa#aaaaaaaaaaab##a#baabbabbbaaaababb",
+"ccddefgfefffd#a##aaaaaabccbabaabaaa##########...############acbaabaabaaaaaaa#aaa#aabaaaa#aaaabgkjiifbabbabbaaaabaaabbabaaaaaaabcc#####cgkmjgfhfcbcaaaabcbaa########a#aa###a###########.####a######aa##bghfefgeddeccbbbccccccbcdcaaa#a##a#aa#a#aaaacbaa##.############aa########.#######bbbccddddggfbaa###abbcbaaaa#aaabeeeeggghgggffeedcccbbbbbcbaaaaaaaaaa###aaaba#aaaabbaa#a#abbbbbbabdbbaaaab",
+"bcceddefhgfcbaa#a#aaa###aaabbbaaaaa#######################aababaaaaa#aaaaaaaaaaa#aaaaaaaa#aa###cefllgabaaaaabbbaaaaabaaabbabaaa#ba######bfjljhghcac##aaacaa########a###############aa#.##a#############afgfgfedcccccbbccccccddcccaa##a####aa#aaaaaabaa#################a#a##.#########aaabccccddeegfbaa###abbaaa#aaaaaabdfceghhhhhhgfedddcbbbbbbbbaaaaaaaaaa###a##aaaaaaabbbaaacbbabbbbbcccdaaaa",
+"bbcccdefhiea###a##aaa######aaaa#aacb##############a####aaabcbbabbaaaaabaaaaaaaaa##a#aaabaaaaaaaaabekljbaaabbaabaabaaaaaaaabbaaaa#a#aa#####aekkhhiba###aabbbb#####a.#########a#a#####a#######aa####.#aba##gggfeedccbbbbbbcbaabccbcbaa##a###aa##abaaa#aa###..###########.###a##.#######aaaabbbcdddcefgaaaaa##abaabaaaabbaabdeffghighhgfffeeccbababbbbbaaaaa#aaaa#a####aaaaaabbaabbbbbbbcccbcccdbaa",
+"bcccccdefgeaaaaaaaaa#a#a#a##aaa#a#aba#######a#.###aa######bcaaaaaaaaaaabaaaaaaaa###aaaaaabbaa#aaabbchkkc#aaaaaaaaaaaaaaaaaaaaa#a#aaa#a#######dkklibca#aaabcdca#a#aa#################a######aaaa######aab#cghhgfddcbbbbaabaaaaabbca##a##abaaa##abaaba#a#aa############...##.###.#..####aaacbbcdccdcdedbaaa#a#acbaaa#aaaaaaabcffffghhhfggfeddbcbbbaaaabbaaaaaaaaaaa#aa#aa#aaabbbcccbbbbbbbbbbcdccb",
+"bbbccccdfcec##aaaaaa####a####aa#aa#aca##a####baa#######a##bbbaaaaaaaabbbbbaaaa#aaaa##aaaaabbba#aaaaaadijgaabaabbaaaaaa###aaaaaaaaaaaaaa#######behlidcdbaaabbcecaa######a###aaa###########a####a#######aaacghihgfedcbaaaaaaaaaababbbaa###aaa####a#aba##a#a#####..######......#...#.#.####aaccbcccdcdehhdaa####bcba###aaaaaaabaaadfeeegihgecdedcbcbaaaabbaaabaaaaaaa##aaaa#aaabcbbbccbbbbbbbbbcbbb",
+"babbcdddddde######aaa###########aaaabda##a####abaaa#####abbaaaaaaaaaaaaaaabbbaaa#aa##aaaaaaaaabaaaaaabcdkib#aaaabbaaaaaa####aaaaa#aaaaaa##a##a##acgjhfgefcbbacccbaa####a######aaaa########a#############bfffhjigedddbaaaaaabaabbbbccaa####aa###a##aa#################a##.....#..#########aabbbbcccddfheaaa####bba####abba#aaaa##bca.#bghfedecbccbbbaaaaaabaaaaaaaaa#a#aaaaabbbbbbbbbbbbbbbbbbaba",
+"bbabbdcdddcec#####aaaa#a####a###abaaaaaa##bda##aaa######aaaaa#######aabbbaaaaaa##a##aa#a#aaaaaaaabaabacbdjjbaaaaaabaaaaaa##########a#aa##aaa##a#a##cfhhededabbdcbcca##########aaaaa############a######a##dffgjiiheedcbaa###bbaabbbddba#########aaa####################a###..###..##..###aaaabbbbcbcfffebaaaa#aabaa##a#aaaaaaa#####aa#.bdegfeccbbaabbaaaaaaaaaaaaaa#aaaaaaaababccbcbaabbbbbbcbbab",
+"dbbbbcdcdcdcea###a####a#aab#aaaa##aaaaaaa##a####aaa###.##aa###########aaaabaa#aaaaaaaaaaaaa#aaaaaaabbaabbbhkfcaaaaabbaaaaa##########aaa###aaba######.ekjgddbabbaabccbba########aaa####.#######aa##aaa#####dgfgghgggedcbbaaa#aabbbcbedba#######aaa#a####################aa#.......##..####aabbbbcbcdefeebb#aaa#aaa##ab###aaa#######a###.##cgefdccbbabbbaaaaaaa#aaaa#a#aaaabbccbbcbbbaabbbbcbccbbb",
+"bcabbcceffabbc########aaa#aaaaaaba#aaaaaaaa########.#####aa######aa####aabbbaaaaaaa##aaaaaa###aa#aa#aaaaabbfkjhdaaaabaaa#aa##aa#####aa#a#a#aaaa######aikjjhbaaabbaacbaaa###############.###################bfhggggggfedcabaaaaabbcdeccaa########aa##########aa######a#a##a##..#.#...#####aabbbbbcccecdgccb##a####a##a############aaa######agfedccccbbaaaababaaaaaaa####aabbaaaaabbababbbccccbbcb",
+"ababbccdffdbbbba###aa#aaaaaaa#baaaaaaaaaaaa#########.####ab###########aaaaaaabcbbbaa###aaaa#ba###aaa###abbbbflljeaaaaaaaaa###########aa##aaaaa#######.afikkiba#abbaaba##########a############################ehffgggfeedcccbaabababcccbaa######aa##aa###.###aa####...#########...########abbbbcbbbcdecfgdaa#######################aa##a####bfeeddccbbbbbaaaaaabaaa#abaaaaaaaaabaaaabbbbbbccccccc",
+"adbbbbcdddecbaba#a#######a#a##aaaaaaaaa#aa##########.###aac##########a##aa#aaaabcbbaaaa##aaa####aa#aaba#abbbbdillhcaaaaa####aa####aa#aaaa##aa#########.#chkli#aaaaabbaaa########a#aa###a###############.###aa#fggffgffedeecbbbaaabbbbcbaaa#####aa###a############################.######aababbcbbbccedcfccaaaaaaaa###############.####a#####bffeddccbbaaaaaaaabaaa###aabaaaaaaaaaaababbbbbbbcccc",
+"ccbbccddeeeccaaca##a####aaaaaa##aaaaa#a#aaaa#########.###ab####.#a###aaa##aaa#aaaabbaaaaaaaaaaba#abaaaaaaaaaaachkklfbaaaa##########a##abaaa############..#bimiaaaaaabaaba##########aa#babaa##############.##a##aegfcbdeedfedbbbabbabbcbbbaa#####a#####aa######################.#########aabbbbbcbbacddddccaaa#aaaaaa###a#####################afgeecdccbaaaaaaa#abccbaaaaaaa#aaaaaaaaaaaabbbccbcc",
+"ccedcdddeeeccbbbcba#a###aaa#a#a#aaa#####aa#a#############ab#####.#####aa#a#aabaaaabbbbabbba##aa###acb#aaaaaaaaacfihkida##a#a###.####aaaaaaaa##a###aa######.ahljc#abaaaaaaa###.####a######abaaa############.#####.bababeedegdcbccbcbabaaabba#a##aa####aba#aba#a###################.####a##ababbbcbbbcdddedea#aaa#a####aa#######.###.######a##a##fgfedddbbaaaa#bcdccbbba####aaaaaaaabbabbbbbbbcbbc",
+"cddeddddeefddcbbcc#a#aa#aaaaaaa#aaaa####aaa######aa######ab#a########aa#a#aaaaaaaaaaabbaabba#aab###abb######aaabbcfheihc######a#####aa#aaaaaaa####aaaaaa###.aikjcaaaaaaaa#################aaccbaa#a################aaaaaaabdddcbccbaaaaaaaaaaa##b####abbcccb##.###a#############..###aaaaaabbbbbccbbccccddecaaa#aaaa###a########################effedccaabbaccbbaaaacc####a#aaaa#aabbbbbbbbbbbcc",
+"dcdcdcdeddfecdcbcdaa#aaa##a###a###aa##############aaaa###aba#############aaaabaaabaaaabbabbaaa#aba####a##a###aaabccefadhhb##aaa#####aaaaa#aa#a##aaa#aaa#####.aflkcaaaabaa####################ddcbaaa#################a#aaa#bdddbbcbaaaabaaaaaaa#a####a#baa####a###a###aa#############aaaabccccbcccbbcdcdedefb##a###aa##aa###############a##aa####efddcbcecbccabbaa#aacc###a##aa#aaaabbababbbbccc",
+"ccdddcbcfhfddcdcbbc#####a#aaa##a########a#a#aaa#####aaa##abaaa##.#######aabbaabbaaaaaaaababbaaa#aaaaa###a#a#a#aaabccdha#diga##aba#####ca##aa####aaaaa#a#######acildaababbaa###########a#######abccbaa#########.#########a###cdedbbdcbbabba#aaa###a####aaaa#aab###a##a#aa######aaa######aabbccccccccccddddeddfca#aa##aaa#aaa#####a####.###aa#a##a#cfeddedacaaabcaa###aacc###########aaaaaabbbbbcc",
+"ccccddccdeffdcccdccb########aa##########a#aaabaa#####aa##ab#aa###########aaaaaaababaaaaaaaabaabcabba############aaabcffb.afjfa#aba####a#a########a#a########aa#abhjb#aaaba#a##########a#######aabcccbb####.#..###aba#########abddbcecbbcbba#aaa########aaaa#a#a###aaa########aaaaa#####aabccdcddccccccccddedcec###ba#a####a#a##########.######aa#adedcbbaabaaabbaa###aabca##aaa#a##aaaaaaabbbbbc",
+"cccccdcedcddfebbdcbdb#######################abcbba#######bbaa######.######aaaaaabbabaaaa##aaabababaaaaa########aaaabbcfiea#bgjeaaa######aa#a#############a####a#acgigaaabb##########.##a#######aaa#adcba##########ba#a#a#####a#adfcddbcccbaa#aaa######aaaaaa##aa#aabbab#aa####aaaa#####aaabbccdddcdcbbbbcccddegd##baaaaa#########a################abbcccbbbbabbbba#####abca##aaa####aa#aaabbbbbb",
+"bbbccddcdcddefdbcdadcaaa#####################aabbbba#a#aabba#aa##########aaaaaabbaaaaaaaaa#a#aaabbbbbaaaa###a#aaaaaaaabfifa##ejgbaaa########a##################acbcfigba#aa###########a#########a#aaabbbba#######.#a#a#######aaaaffddccbccba##aaa##########a######aabaaa#.####aa######aaabbbccdeeefggecdedcdfedcbaacbaaaa##a#a####a############a##aa#accdcbcbbbbbba#####aaca#aaaaaaa###a#aaabaab",
+"bbbbcccccddddfecbccbdc#a############a###aaaa#aaa#aa##aabcccc###########aa#aaaaaabaaaaaaaaaa#aaa#aaabbbbbbaa###a#aabaaabbbhie#.bfhfbaaaa###aaaaaaaaa#######a####aaabdhifbaa########aabaa###a######aa#####bccaa#####.#####a########afgeddccdcba###aa########a#a#######aa######.##########aabcbcccdffghihgdcddcbacbbeabaaaaaa#a###################a##aaaa#bcddcdcbbbab##a##aaaba#aabcaa####a#aaaaba",
+"bbbbbbcccccdefedbbcacdc####aa##a#.##a#.##abb######a##aabbccc###########aa#aaaabbbbaaabaaaaaaaaaaaaaaabbbccbaa##aaabaabba##diic##adhebaaaa#aaa#aa##aa##########aabaaagjjf#a######a#aaaaaaa#a#######aa#a###bdddaa#a###.#a###########adcdddddcba#aaaaa#a###a##a##ba#b###aa####.###aa#####a#abcdcbbcdghihhgdcaaaaaabcfdccaaaaa#aa###################a##a#a##acbcdcbbcba#a#####aaba##abaaaa###aaaaaaa",
+"aaaaabbbbbcddeedccebaccb###a####a####a#..aba##########aaaaccb.############aaaabbaabbaabbaaaaaaaaaa#baaaccbbaaaa#aaaaaaaa####fjfb###egebaabcb##aaa##############aaa#achkjbaa######aaaaaba#a#aa###a###########abba###################abaceddcbaaaaaaaa#####a#####a####a##a######.###a##abaaccddedeeffdghfaaaaaaaabbdfcabbaaaaa###############.#########a###bccbedcbdaa######a#abaaaba########a#aaa",
+"#a#aaaabbbbbbcdedcccbabbb##aa######.######ba#############abcc##############aaaaababaaaaabbaaaaaaaaaaaaabbcbbccba#aaaaaaaaaaa#beihb##afgdbbcba#aaaaa######a######aa#abcilheba#####aaaaabaaaaaa#########a####a##a#aaa###############a#aaadedbbaaaaaaaaa##aa##a#######a##aab######.##aaaababceefcddcb#.#gfaaa#aaaaabcfgcaaaaaba########.#####################aabddcbcabaa##a##aaabaaaa######a######",
+"##a#aaaabbaabbccdcbcbbbacb###a###########.aba#######aa###aacf#######.#######aaaaaabcaaa#acaabbaaaaaaaaabababbbcdcbaabba#abaaaaabfje#a#aehdaaaaaaaaba#####ab#a####aabaabijiebaa##aaaaaabaaaba##aa#####a#a###########a###a###########aaaaaabbbaaaaaabaaa#aaaaa#####a##abaaaaaa########abbabcdgeba##.##.bdaaa#a#aaaacfgcaaaaaa########.a########.#######a#aa###abccbbbaaaa#aa#abbab#abaa####aa#####",
+"#####aaabbaaaabcbccccbbbcca###a############a#########aa##aaacb###.#.########aaaaaaaaabcbaaabaaaaaaaabaaaaaaaaaabcaaaaabaaaaabaabaejhbaa#aggcaaaaaaaaa####abb#a###aa##aabhigddbababba#acbabaaa###aa####a#c#a#############a#a########aaaaaaaabbaaaaaaaaaa#aa##a#####aaaaaa###aaa######aabbabege##b#######aa#a##aaaaaceecbaaa############################aaaa##aaacbbbaaa##aaa#aaaaa##aa#####a#####",
+"####aaaaaaaabbabbdcbcdccbbba#aa####a##a####a######..##aaaaabab###.###########aaaaaaabbbbbbaaaaa#aaaabcbaabaaabbaaaaaaabbaaabbabab#bghcaba#dhfaabaaaaaa#aa###aa##aaaaaaaabeegbccbaaabcbbbaababa######aa#aaaaa##aa#.######aaa#########b#aaaaaabaaaaaaaaaaa#a##aa#aaa#aaabbab##a####ab#aabbbbcfhaaca##############abbabddbbaa####################.###a##a#aaaaa#aabbbbbaaaaaa###aaaaaaaa#######a###",
+"#####aaaaaabbbbbccdbccdcbcca##########a#####aa##a######a#aaaabc###############aaacaabbabbbbbaaaaaaabccbbaaaaaaababcaa#bbaaaaaaaa#ba#eiebabaafhb#aaa###a#a####aaabbaa#baabbbigcebaaabcbbcdbbbcca#a##a###acbbaa#ab##########aaaa########aababbbaaaaabaaaaa##a###a#aa###aaaca##a#aa.bc#abbdccbdga#####.###########abbbbcdebaa##a##a##########a####.###a#aa###aaa##aabbabbba#a#####aaaaaa########aa#",
+"#####bbbabbbabbcddddcccbbbcca#a##aa###a#################aaaaabb#a####.########aaaacaaaaaacaaaaabcaaabbcdcbbbcbabbbabbaaaaaaaaa####aa#cijdbababhfa#aa###aa##a##a#aaaaa#aabbbflggfaabacbaabbbaacbba##aa#abccbbaa###aaa#####a#aaaba###a#aaaaabbacbaaaaaaaaaaaa###aaaaaaaaaacaaaa#bbab#abbcccccbdc#################aabdceedebaa#########################b#####aa#####bbbabbaa#a####a#aa##ba########a",
+"aa##aaabbbbccbbcccddcdccabbdfa####a###########aa######a#a#aacc#######.#########aaabababbaaaabbaaaaaaaabbbbaaaaaaabaabbbaaabaaaaacba#a#beijbaaaaehfa###########aa#abaaaabbbbdhjghffedccaaabaabaabbaaaacbcbcccbaa#aaaaaaaa#aaaaaaaa####aaaabbaadebbaaaaaaaaaaa###aaabaa#a#aaaaabbbbbbbabcdcccefe####.##.#######.##a#aacccccaa#aa#####.###############aaa###.#a###a##bbbbbaa#a########aaaaa##a#####",
+"###ab#ababbccbcbccdddccccbbbeda##aaa######aa###abaa####a###abdb#a###.######aaa#aaabbbaaaaaa#abbbaa#aaaaabdaabbcbabb#aaaaaaaabaaacbcba####ejdbbbacgjd##aa#aa#####aaabbaabaabbejiiiihhggfbaabbbaabcba#bcdcdddddcaabbbbcbaaaaabaaaaaaa##aaabbbbcdedbcbaaaaabbaa#aa#aabbaaaaaaabccbbbbbcdccddffebb####################aabccccca###########.#########a####aaa####a##aa#abbaaaaaa########aaa####a#####",
+"#aaaaabbbabbcccccdedccccedccdebabaa#aa###########baa##.##aaa#aca#######.#####aaa#aaabaaaaaabaaaacbaaaaaaabaaaabcbaabaa##aaabaaaaabaaaa###.cjgcbbbadiib##aaaaa####aaabbaaaaabdhlijjiiihfefcbaabbbbbbababdedfddedccbccdccbccdccccbaa#aaaaababcccdddcccbaaabbaaba#aaaabbaabbaccdddcdefffedeeed..################.######abcbdfbab#a###########################a#a#####aaaaaaaa##aaaa######a##.#a####",
+"###aaaaabcbabccccdcddcccccbbccebaaaa##############a#a####aaa##abb##############aabaaababaaabaaaabbaaaaaaaaaaaaaabbcbabbaabaaaaaaaaaaaa####.afhdbbaabfihb.#aa###aa###aaba#aaacclljjiijigddecbaabccbabbbdbadcbeffffeffgghhhighgfhgffcaaababdbbbbcfddddcbbbbbccabaaaaaaababddehggfegjiedaaaa#a####a##############.######bcdcddbaaa##a###################a#a#####aa####aaaa#aaa#a########a#######aaa",
+"aa##aaaabaaabbbdddccdbcddcccccdd##a#aa##aa########a######aaba###ab##############abaaaaacbaaaabaaaaaaaaaaaaaabbaabbaccbaaaaaaaaaaaaaa#########bfgbaabbdije.######aa#abbaaaaaaabellkkkkllkiiigfdcdcbabbcbcdcbcgijkjhhhhijjic#dcbcbddghffeeeihiggfgddedcccbcdcdcbcbcbabadeeffghhhebegdddb#########a#a####################babbbcbbb##a##################aa##a####aa#a###aa#a#aaa##a#######aaaaa##aa#",
+"a#aaaaabaaaaaabcdcceccefcadgeceebba###a#aaa########a#####aabaa#aabda########a####aaaaaaabbaaaabaaaaaabbaaaabbbbaaaaaabbcbaaaabaaaaaaa#aa######.eiebbbbcfihc#.###abaaa#aa##aaaabellkjlkjklmnnmlkgfccbbdddeefghjijkkllkhd#cfeabcbbcbbdgjjhgecccehieeededccceeedddddefcdffcedbacdec#bbaba#########aaaba#########.#######aaaacccdbbaa####################aa##a####aaaaa#aaaaa#a####aa######aa#aa##aa",
+"a#aaaabaaaaaaaabcccdddggedbdfccecaaa###aaba#a#######aa#.##aabba#aabc###########aaaaabcbaaaabaabaabbbabaaaaaabbcccaaaabbbbbbaaabaaaaaa#aa#aba###.bigbbbccdilid.##aaaaaa####aabbbcekmljgdfiijikmlmnkgdeefeeegieeddgdcghgdbabcfdebcccceffggfcbbbbbcefgedddcceeefdedcbccefgb####babedcaa##aa#######aabcda##.#############aaaaabcdcdbaa#########a########a###a###aabbbbaa#aa#aaaaa##aa######aaa##aaa#",
+"##aaaaabbaaaaaaabcdceeffedccfgedcaaa##aaaa###a#a#####aa..##abaaaabbd#########aaaaa#a#bbbbbbaaaaaaabbbbbaaaaaabccbbaaabaabbbbab#aaaaaaaaa#aaaaa###ahibbcdccgjkg####a#aa####aabbcddegkhddgihhghiibdilmljjjjiiihfaaa##aeeedcbbdghfdbbdfedfedccbbbbdbffhfededeefhhfc#####cea#####aaabdfda.a######.##abdfb##########.###a##aaaabadefecb#a##########aaa####a##aa####acbbbaa##aaaaaaaaaaa#####a######a#",
+"a##aaaaaabaaaaaabacddeddfdccefffd#aaaaabbaa#a#####a#.aaa###aaaa#abbdb########aaaaba#aaaaababbaabbbbbbbbbaaaaaaa#abcbaaababbbbcb#aa#abaaa###########fhdcccdcehihb###aa######a#bccdefggiglkjjhiihba#cglkjhiihgebcaaaaaa#aacdbbdefhfdbbeedbccbbbabdcbgjifefedeggfgfa#aa#a.aa######aaaacffba####.###abdeca######a###########aabbegffgedaaa##########aa####a##aaa#####aaaab#aaa##aaa#aa######a#######",
+"##aaaaa#aaaaaaaaabbcdddceddeeecdfbaaaaabbbaa#####ab#########aaaaaabbc########aababbaaaaaaaabbbaaaabcbbabbaaabaaaaaaabbbbaaabaabbbcaaaaaaa##########.bhfcccdddefigc#abaa#aaaaaacccdegeiihkihhjhbbaa#.#a##a#..##aaaaaaaaaaaacaabaacefedefbbedcbaccdbcfgiihhfdec.addb#ba###aa######aaaaadgeca#######aceaaa#################aaabdgeeghffb########a######aa####abaa#####a#aaaaaaa#aa###a#.######aaaa#",
+"a##a####aa#aaaaaaabccbccdedefebbef#baaaaaabaa#####a#aaa####aaa##aaaada########aaabbbaaaaabbaaaaccbbcabbbbaaaabaaaaaaaabbbbabbbbaabcb#a##a#########a##bifdccdddefgjeaaabaaaa##accbbcddfhehijhdb#aaaaa#a####a#abaa#aa##aa#aaaaaabbbaabefigffefdbcccdcbaacbbdhhfeaacbabb##a##########aaaaadhgb#####aabecaa########a###########baegfefgfeca##a#######a##aaaaa#aaaaa####aa#aabbaa#aaa###a#.#####a#aaa",
+"#aa#####a#a#aaaaaaacccbbccdcdedbcfcaaabbbaaaaa####a###a###abdb####aaeda######a#aa#aabbbabbaaaaacddbaaaaabaaaaaaabcbaabbbaabbbbbbababa####aa###aaa#####dihecccdedeejgaabcbaaaaabcbbbcdeheggeabaaa####aa########aa###aaaaaaaaaaaaaaccbaabdegedddddddccbbbba#abaabcbbaaaa##a##.#.#####a#a#abefb#####abdfaaa#####aaaa#a########aaadfeeffffc#######a######aa#aaaaaaa#aa##aa#aaabaaaaaa#######.###a#aa",
+"aaaaaa#aaaaaabaaaaabbcbbabbbcceedffdbaabcaaaa##abaa##aa###acefa####abdaa###.####a##aabbbcbcbaaaaabba##aaabaaaabaabbbaabbbaabbbbabbcbba#a##aa###aaa#####bhjgccdddefdhheabbaaababcbbabcdehfcaaaaaaaaa#aaaa#######aa###a##aaaaaabcdaabbbbabbbefedeccddcbbbaababbbcccca#a####aa#############aaceda###aabfebaa####aaaaa##########aaadefedegca########aaa##aaa#aaaaaaa##aaa##aaaaaaa#bcba#########aa##",
+"#aaa#aaa#aaaababcbbbbccbaaabbbbdgffgbaabbbaaaa#aaa####a##abbgea##aa##bca#########a#a#bcbabbbbaaaaaaaa##aabaababbbaabaabbbbbbbbbaaaabbaa##a#####aaa######adhidddddfhdfigbcba#aaaaaaaacbcfdabaaaaaa#aaaaaaa#######bb#####aaa##aabccaaabdcaaaeeefeddefcbbbbaaaabcbbbcdba#####a####..#######a##abdb#aabcefdaa####a#aaaaa#######aaaaaabacefc#########a###aaaaaa##aaaaaaaaaaaaabaaaa##aaaa###.#####aa#",
+"#############aabaaaabcbbaaaabbcceeeeeaaabbaa##a###ab#####abddb#####a##cb#######aa#a##aabbbbbbbaaaaabaaa##bbabbbaaabaabbbacbcbbbcbbbbaaa###a######aa##a#baaagkecdeegfeehfcbba##aaaaaaaaccdcbaccbaaaa#aaa##aaa#########a##a###aaabcaaaadeddbbdcdeigfdbcccbaa##cbabcbcdaaa####aaa######.######aa#debaacfdcaa#####aaaabaa########a##aabccdd#############aaaaaaa###aaaaaaaaaaaaaa###aaaaaa#########aa",
+"#############aabbbcbbccbaaaabbccddeedca#abaaa#aa###a##.##aaaa#######aaaca############aaaaaabaabaaaaaa##a#aaaaabbaaaaabbbabbbcbbccbccbaba##########a##aaabaabejfddddehddhgdbbba##aaaaabbbcccaabaaaaa#a#a##a#aaa###############aabcaaaaaegeddcecacdghfdccbaaa#cbabcbac#######bba#################bcdcbeebaaa###aaaa#aa#a###a####abaabdcdcba#a##a####aa###aaaaa##aaaa#aaaaaaaaaaa#aaa##aa#########a",
+"aca##########a#aaabdbcccbaaaabbccddeedbaaaaaa#aa#########abca#######a#aca############aaaaaaaaaaaaaaaaaaaaaaaaabbabaabbbbbabbbcbbbbcabbbba##########aa###aabbbeidbbccehefhhcbbaaa#aaabbaaabbcaaa#abcaaaaaaaaaaaaa#####.########aaabaacbedfdbbbdccccfhebaabaaa##a#acaba######daa###.######a####aa##acfdfdaa####aaaaaaaa###aca#aaaabaabccdeaaa###aa#aaaa##a#aaaaaa#abaaaaaaaabaaa##############.aab",
+"aa#bb#####.######aaabcccbbaaaabbbcddeebaaaa########.#####abca##########abaa####a#####aaaaaaaaaaaaaa#aaaaaaaaabcbbaaaaaaaabbbbbbbbbccabbaa#a#########a#####aaaachdbccdefehgiebbbaaaaabaaabccacbaaaacbaaaaaaa#aaaaaa#############a#baaaaceddbaabcbebbefdcaaaaa###ba#baa#####.aba##############a#a##aacfghdcaaaa#abaaaaaa######acbababbbdbaa###aaa#aaaa#a#aa#aa#aa##abaaaaaaabaaaaa##############ba",
+"a#aa#a#####.###a#aaabbcccbbbaabbbccccge#aa#######.#######abbba#######aaabbaa####bba###aaaaaaaaaaaaa#######aaaaabbbbabaabbaabbbbcbbbcbabbbaaa#a##a##########aaaabeccccddfgefhgaccaa#abbabbbbabbbba#aa#aaaaaaaaaaaaa#######a#####aaaaaabacdccabbbcecaacdfecbbaaaa#aaabaaa#####aa########aaab####a###aabeggbaaaaaaaaaaaaa#a##a###aaaabcccccaa###aaaaaaa#aa#aaaaaaaa#abaaaabaaaaaaa#a###########a#aa",
+"###aaaa###a######aaaacccbbbbbbbabccccehb#a########..#####abbca#######aaaacaa####cca###aaaaaaaaaaaaa#######aaaabaaaacdbaaabbbbbbbaabbbbcbccaa############a#aaaaabaccbdccegeccffbbaa######.#abaabbbaaaaaaaa#aaa#aaaaaaa#a##########aaaabbcc#abbabaabaddcbceebbba#aaaaaba######a############aba###a##aaaccggbaaaaaaabaaaaabaaaaa#a#bbabbccdb#aa###aa#aa#aaa#a#aaabaaaaab###abbabaaa###a#a########aa",
+"###aa#a######.######aacccbbbbbabbbccccfheaaaa#############bbcaa#######aaabcaa#####aa####aaaaaabaaaaa#aaa##aaabaaaaaacdcbaabcbbcbbbabbaabbbbca#a######aaa##a##a#aaacabccdeggacge.#aa####a#baaaabbabaaaaababbaaaaaaaaaaaa#########aaaaaaabda#aaabbbacbcdbbcdeca#a#aaaaa#a#aa#aa#############aa#####a#aaabcfgcabaaaaabaaaa#aaa#####babbbcccc##aa#a#aa#aaaa###aa#aaaaaaaaaaa#aabbaaaa###a#a#####abba",
+"###aa##aa##########a#acbcccbbbbbbbbbcceffebaa#############accbaaa######a#bdcaaa####aa##aaaaaaaaabaaaaaaaa#abbbaaaababcddccbcccccbaabaaabbbbbca####a######aaaaa##a##bbabcbdgefeed########a#a###ab#aabbbaaaaaaaaaaabaaabba#####a#.#a##aaaabca##abbbaccbbdcbcdedb#aaaaabaaa###aaa#########aa#aaaaaaaaaaaaabceecc##aaaaaa#a#aa########abbacccc##aaa#aa##aaaa###aabaaaaabaaaaaaabaaaa####aa#####a#a#a",
+"b###aaaaa#######.##a##abbdcbaabbbbaabccdegea########a#####abcbba###aa####acccaa######a#####aaaacbbbabbccbbaaccaaaaabbbcccbcbccbbaaaababaaaaabc###a#aa#####a#aa#a#aabdaaacbbafhgbfa.#####aaaaaaaaa#aabaaaaaaaaaaaabbbaaba###a###########baba##aaaabacaabccbccdeeaaaa#aaab####.########.##aabbbaaaaaaaaaaabccaccba##abbaa###a##a###a#aabbccca#aaa#a#abaaaaaaaaacaaaa#aaaabbaaaaa#aaaa#a#######a##a",
+"baabaa#######aaa#####aabbccbbaaabbaaabccdfeba#######aaa###abcabbaa##aaa####ddbaa######a###aaaaaaaaaabbcbbbbbccaaaaaabbbbbcccccbbbaaaaaaaaaa#abca##a#aaaaaa##aaaaaaabcaaaabaabgicce##.#a##aa#a#aaaaabaccbaabaaaaaaaaabbbaaa#aabb##########aa#aaaaaaaaaaabccccddfebaaaaabbaa################bbbbbbaaaaaaaabbbc##acbbaaaaaa####a#####aabbbcccb###aaaaaabbaaaa#a##aa####aba#bbaaaaaaabaaa#######a##a",
+"baaaaa#######aa#######aabccbabaabbbaabbbcdgdb#a########a##abdbbaaaa##aaa##abdcbaa#############aaaabbbbbbbbbabccaaaaaaaacbbbcccbccccbbaaaaaaaabbca#aaa#a#aaaaaacbabaa#aaaaaccbbjgabc###bb######abaaabbcccbabbbaaaaaaaaaaaaa##aaaaaa#######aa###aabcbaaaabbbccdeeefebaccbbbbb#.####a####.###abaabbbbbcbaa#aaabca.##acccbaaaa########aaababbcba##abaaaaaaaaaaaaaaaa#aaa#baaababa#bbaaaaaaa#######aa",
+"aa##aaa###############a#abcbabbaaaabaabbbcffcaa##aa##aaaa#abbbbaaaaaaa##a##abdbaa##############aaaaabbaacbabbbcaaaaaaaabbbaaabacbccbbbaaa#aaa#aabb#aaaaaaaaaaabbbbaaaa##aabbbadiabbc.##c#######aaaaaabbccbbabbaaababaaaaaaaaaa##aa#######a#####aabbaaaabcbbbcddcefhgceeaabba##############abbbbbbcbaa###.###aca####aacdba#a#a######aaaabbcbbaa##aaaaaaaaaaaa#aaaaaaaaaaaaaa#bababaaaabaaaaaaa#ab",
+"cb####aa################abcbbbaaaaabbaabbbdgdb##a#aa#aaaaa#abaabaaa#bba####aaddba#######a#########a#abbaaccccccbaaaaabaabccbbabaabcbbbbaaa#aa###acda####aaaabaaabbcbbaaaaa#bcbcebbccd#.aba######aaa#a#acbaaabbbbbaaabbdbbca##ba###abc.#.####.##a#bbaaaaaaccccdecdefghgfccccb#.####.#...###aaaabbabddba###...##bb#####a#bcba##########aaabbccaa###aaaaaaaaaaaaa##a#aa#aaaaaaaa##ababbaabaaaaaaaab",
+"ec##########a##aa#.#####abbcbbaaa#aa#ababccfffcaaa#aabaaaaaabbaaaaa#aba###aabbfdaa###.#############a#aaabbccbbccaabbaabbbbbbbbabaaabbbbbaaa#a###aacdba##aa#abbacbbcbbbaabaaabbceabccde.#c#aa######aaa#aaa#aaababbabaabbdefecd#aaaaaaec#.#########aaaaaa#aacdcbdbabdfegddffdba##.#.###.###aabbbbabbccbba###.#.##bc#######abbba########aaabbbddcaa##aaa##aaaaaaaaaa#aaa#aaaa#aaaaaababaabbaaaa##ab",
+"bca######.#####aa#######abbbbac#a##aa##abcdcehfaaaabbbaa#abcbbbaaa#aaba#####acegdaa####.############aaaaabbbbccccbabababcbbbbbaabbcbbabaa##aaa###aacebba###bffcdbcbbcbbcaaaabbbhbabbcee.##aa##aaa#acaabbaaaaaaabccaaaaaabdefge##aaaacea###########a######abdfdabaaaaababaceeb###.#...#.##aaabbbabbbaabaaa###..##bea###a##a#aca#a#a#####aaababb####aaaa##aaaaaaaaaaaabaaaaa#aaaaaababaaaaaaa###ab",
+".#a###########.b########aacaaaacaaaaaaa##acdffgbaaabaaa##aaehdbaaaa#aaaa#####acfgbaa#########.########aaaabbabcdecbaabbabbbbbbbaaababaaaa######a##aaddbaaaaab##a##abccccccbbaabfhaababgd.######aa#aaaaaaaaaaaaabacdddbaaaaaaddeda#aa#ba######..##a########abdcaaaaababcabbbcddb#a###..#.##aaabccbbaaaaa#########abed#########cb#a#a####a#aaaaacb###a#aaa##aaaaaaaaaaaabaa#aaaaabaaaababaaa######",
+"#########aaa###a########abbaaaaaaa#a#aaaaaacdegeaabaaccbaa#acefcaa###aabba###aadfdbbaa####.#############ababaaabcccaaaaabbbbbbbabaaabbbbaaa#####aaaabdeaabbba########aabdedcbabbffaababhd########a#aaaaaaaaaaaaaaacedbabaaba#bfggcaaa#########..#.########aabcb#aaaaaabaababccddba#..##.####aaabbaaaaaa##...#####acecb########abba#aa#a#aaaaabbca##aa#aa#aabbaaaaaaaaaaaaaaaaaaabaaaaaabaaa#aa##",
+"##########aa###a#####aaaaaaa##aaaacc#a###aabbcefbabbcfcddddbabgfa#a#aaaadbaa##abdedcaaaaaa#############a#aaaabbbbaacbbabbaabbaaababbaabababa##a##aaaaaccbbbb########.###abbacdcccgbabbbcida####aa#a#baaaaaaaa##aaabccaaaaaacbbabggb#a#####aa##..##aa######aabbcbaaaaaaaba#aabbcccca#.########aaaaaaaaa###...#######abdec########abb#aaaaaaaaaaabcbaaa#####aabbbb#aaaaaa#abba#aaaaaabaaaaaaaaabb#",
+"###########aaaaba###aaaaaa####aaabdebca###aabbcfgfbacdccdeheaadgea###a##dcabaaaabdedcbaa##################aaaaabbbccbaabcbaabbbbabbabbbaaabaa#####aa#abddbcb##a########a##.##accdeedbcccejcbaa####aaaaaa#a#aaaa###aabbbbaa#bdbb#chfa####a########.###########babbaaaaaabaa#aaaaabbcdc#..######aa#aaaaaa###.#..#####a#abdeba#######bbbbaaa#aaaaaabcca#aaaa#aaaabbbaabaaaaaaaba#aa#bbaabbaaaa#####",
+"######a##a###a#aaaaa#aabaaa##aaacddbbcaa##aaaabdifdadeeddfffaabdddbaaaaabd#aaaaaacfedcaa#################aa###aaaacccbbabbbbaaabbbbbbbbbaaaaa######a#aaacdddaaa#########a######aabbicceedghcbb##aa#aaaaaa#aaa#a####aaabbaa#adffbafgd####aa###################aaaaaaaaaaaaa#ababaaabbbcb#.####aaaa#a#a#a##..########a#aabbcdd#.###a##bbaaaaaaaaabbbbba######aaaacbb#abaaabaa#a#aaaabaabbbabaa####",
+"######aaaaa####aaaaba#abaaa###a#bddccaaa######abcfgghhhfdfffcacbabdecca#bca#aba##aeffeba##############.########aaaaccbbbabcbbbaaaababbbbbbbaaaa######aaaabeeaa#aaa######a###a#aaaabfgdbbddhhccb###aaaaaabaaa###aa##aaaaaaaa#bffgd#cda##a#a######a#a###########aaaa#aaaaabb#abaaaa#aaaabbca####aa#aaaa####.#############aaabcdc#####a#abba###aaabababc#aaa##aaabcaaaaabaaaaaaacaaaabaabbbbbaaa###",
+"a######aaaa##a#aabbaaaaacba##a##acccddbaa#a##aaaaacccdefefefdacaaaacgebcdb#a##aacbbegfdba#aba##############aa###aaabcdbccbbabcbbbbbbbaabbabaaa###a###aaaabcdb#baa#a###########aaabddgcdcbbcfidbcb#aaaaabaaa#a#a#abaa###a#aa##dfffeaa#####a#####aa##b.######.###aaaaaaaaaacbacaabaaaa#aaaacccaa####################a########abceca###aa#abaa#aaabaaaacda#aa###aacaaaaaabaaa#aaabaaaacbbbbacaaaaaa",
+"aa##a###aaaa#a##aaaaabbbbbbba####bbbacbaaaa##aaaaaabccbdedcefaccaaa#accccaa##aaabcddfgefeeffea################aaaaaabbcbcbbcbabbbaabbaacaaaa#a#######a#aaaacfcaaa##a############aacdee#a####eifccc#aaa#ccaa###aaa#ba###a###a#befffd######aaab###aa############aaaaaaaaaabbcbcdbbaa###abbaaabccdca...#######aa#a####a######aaaabcdc######aaaaaaaaaaabbcdbaaa##aababaa##aabaaaaaabaa#abbbbaaba#aaa",
+"#aaaaa##a#.###a#aaaaaceccbbbab##aaaaaaaaaba#aaaa#aaabccbcdddgfdaaaa######aa##a#aaaeggihgeefeddeca###############aaaaababcbbbbaabaaaaabacbaaa##a#####ba#aaabadgeaa#a##a####a##a##aabbeeaa#####bhibaca##aadbaaaaaca###########aadfddfda###abaabb#aaba#####a######baa#aaaa#abdc#bccbaaaa###ba#aaabdfeec#########aa#aaaa####aa#aaaaabde###a###aaaaba#aaaabbccbaaaaaaaaaa#a#aaabaaabbaaaababbbbaabaaa",
+"##aa####a#####aaaaabcccbbbcbbaa##aaaaaaaaabb#baa##aaabbcccdefgiecbaaa##aabba###a#affghihfccdddddeca################aaabaaaabaaaaaaaaa#aaaabaa########aaaabaabcgcaaaadda#aa#######aacdde#######aegbbdbaa#adbbaabcaa#aa#########acfeeecaaaaaaaabbaaaba###########aaaaaaaaabddfbaaababaaaaaaa##aba#acefgca###aa#####abb######aaaaaaabcfa##a###aaaabdaaaabbbbdb###aa#aaaaaaaaaabcbbbbbbabaabbbbbbaa#",
+"####aaaa#a#####aaabccccbaabcbcca##aaababbabbabaaaaaabcccbacddefffdccabccdedaaaabdeeffgggeccddccdcdca#a##############aaacaaaabaabaaaaaaaaaaaaaaaa###aa###aaaaacdgcaaabaaa#######a##abdchaa######.cfcbcb#a.bffcbbbab###aaaa###a###ceedddabcbaaaabbabbaaaa##..#####aa##aaaa#acecbbcbaaaaabaaaa##aba#aecbccdcabaaa##abbaa#a##aaaa##aaaabdd##aa##aaa#aaababbbbbdb#a##aabaaaaaaaaaaaaabbbbbbcbbbbcbbaa",
+"aaabaaaa####aaaacccbbcbbbaaaabdaaaaabcaabcbbbbbaa##abcddcbcdefedffedbdccdeec#aafffdddeffcccbcdcccccccaa#############aaaab##aacaaaaaaaaaaaaaaaaaaa###aba#aaababdefaaaaaaa##a###aaaaabccgcaa#######bgcdeca##bhgbabaac##a#aaa##a###befddfdddbddbaacabbbbaa####.#######a#aaaaaacbaabbbaa##ababa##aa##acaaaabbcb#aa#a#aaa##aa#####a#a#aaaabeca#aaaaaaaaabaabbbbbdb#aaa#abaaaaaaaaaaaaaaaaaabcbaababaa",
+"aaaaaa#aa#####abbbcbbabcccbbaaabbccccdbabccbbbbbaaabbcddcbceeeddeggddfbcdeec###dffedddeddcccedccccbbcdb#################aa#aaabaaaa#baabaaa#aaa######aaaaaaaabbcdfaaaaaaa#a####a#aaaabge##########bhcbccaabdeeaaaa###a###aaaaaabceedefeeedeeccabbabcbbaaaaa##.#.#######aaaabbb#aaaaaaaaaabaa##a##aaa#acbcabca###aa####aa#########a##aaaedb#abaaaaaaabbabababccb#aaaaba#aaaaaaaaaaaaaaaaabbbbbaaa",
+"aaabaaaaaa###aaabbbbbaaaacbbbbbcccddefdaabbbbccbbbbabbccbcdddddeeeffefcedffedbabeeecddcbcccbdbbbabbbabba#aaaaa##a######aa#a##aaaaa#a##aaaaaaaaa###aa##aa###aaabbdedaaaaab#a####aaaaabbgha#a########becaccdfgddda#aa#aaaabaaa#a#addeecdcdfeeeddcacbbbcbbaaaaaa###########aabacbaaaaabaaba#baba#aa##bbbdbacaabcb##aaaaaaaaaa#########a#aaabddbaaaaababbbbbaaabcccbabaaaabaaaaaaaaaabaaabaaaabbbbaa",
+"abbabbaaaaaaaaaaaabbabaaaaabbcbbcdedfggccbaaabbbbccccbccddeddccdddcddecddeffddecddccacbaacbbbbaabaabaaaaaaaaaaaaaba####a###ba#ba#aa#####aa#aaaaa############aabbcdebbbaaaa########ababdhf#a#########afecfffebceaa###aaa#aaaaa##abeeddddeegffdcfdbbabcccbaaaaba###########aaaabaaaabbaaabbbaabbaaaaacdcaacaaaabca##aaa#aa#aa#aa#######aaaaacee#bbaababbbbbbbbbccdcaaaabbaaaabbbaaaaaaaaaabaaaaaab",
+"babbaaabaaa#aaa#aaaaaaaaaaaabbbbcdbadccdbbbaabbbbbcbbccdeeedeabcccccccccdeedfddcccdbcbaaaaaaabbbaaaaaaaaaccaaa#aa##aaaabbaab#a####aa####aa##aaa###############abcdedbcba#####aaaa#aabbdhie.#####a#####fgffececeda###aaa#aaaaaa#cddecddcddefeegefeccbccccbaa##aaa#.#####.##aaaabaa#aaaaa#aab#bcccbbccbbaab#aaaabcbbaa#aaaa#a#a######aaa##aaabdfdbbbbabbbbbbbbbbccccaaaaaaaaaaabbbbbaaaaaaaaaaba#b",
+"bbaaabbaaaaaaaaaaabaabbbaaaabbabcedcbbabccaaaaabbbaabbceffcccbbcbbbbbbbbddcdddbbbabbbbaa####aaabaaaaa##aacfeaa######a##aaabbbaaa##aa#a#####bcca#a##aab##aaa#aaaacccgdbbb#######aaaaabbbdhhb###########aeifddbbceda#aaa##aaabaabefffcdddccdeeeedeffefeddccbaa##aaa###.###..aa##aba##aaa#aaabaaabccddcccaabaababaabcca###aa#aaaaa####aa#####aaacffbbbbbbbbbbbbbbbbcdcaaaabbaaaaaabbaacbaaaaaabbbab",
+"babbbabbaaaaaaaaaaaaabbbaaaaabbbceddcbaaabbbbbaaaaaaabcdffdcabbccbbaaaabbbbbbbbaaaaaabaaa#a##aaaaaaa####aadd######a########abbaaaa##a#####a#aa########aaaaaa#aabbbbdgcaaa###aa##aaaaabadfgb######aa###aadidcdbaceca#aaaaaa#abcdeeeccdeddccddeadeefffffffecbaba#######.###.##aa#abaaaaaaaaabcaaabaabcbd#abaabbbbaaabdba#a#a##a###aaaa#########aacefdbbbbbbbbbbbbcbcccaaaabaaabbaabaaccaaabbaabbaa",
+"baababbbbabaaaa#a##aaabbbaaaaabccehdbaaaaaaabbaaaa##aabdgieccccbcbaaaaabaaaaaaaaaabaaaaaaaaabaaaaa###a###aaa################aaaaaacba######a#a##########aaaa#abbbbbcdhb##a####aaaaaaaacbfe.##aaaaa#####aadhcbbaaefbdb##aaccddfgedbddccccbbcdedceceggfeefefdcbaaaa#####.###.###aaaaaaaaa##aba#aaaaababdb#aa#aaabaa###bcbaa#######aa#############abdffcabbbabbcbbcbcbcdcbbaaabbbbbbbaacabaaaaaaaaa",
+"bbbbabbbbbbbaaaaabdcabdcaaaaaabbcdffcbaabaaabbbaaaaa##bcgjfbbbcdddcbbbbbbbbbaaabaabbbaaaaaaaaaaaba#########a#a###############aaaaaabaa#######a######aa#a##aaaabcbabbcceda#aaaaaaaaaaabbbec.a#aaaaaaa####aadhcabbbeecbaaadefggfeddcddcccccbccdccdddeghggeeeddcbaaaaa############abbaabaa#aaaaaaaaba#ba#aaaa#abaaaaa##aabbb###aa#a#a##a##########abbcffdcabbcbbbcccbbccccbaaaaaabbbbaabbabaaaaabba",
+"bbbbbbbbbbbbbbaaabfdcccbcbaaaaacdceebaa####aaabbbbaa##bdghfcbaaacdddccccccccccbbababbbaaaaaaabbbaa#a##aa#a#b##a#aa###a#######abaa###aaaa##a################aaaaabbbcbbcffaaa#cbaaaaaaaacec.#####aadea##a#aabgdababdfda#adfggeddccccbbbaccbbcbcddddgghigffffbabbaaaa##########ab#aaaaaaaaaaaaa####aaaabaaaaaaaaaa####a##aaca##a######a#########acbbbbcdefdabbaabccbbbbccccbcbaaabbbaaaababaaaabcc",
+"bcbbbbbbbbbcbbbbbcecccbaccedaaabddcaaa#######aabcbbbaabdfhfdcaa###acdcabdfeeedcccccbbcbbaaaaaaacbaa###aaaa#aaa#####a#aa##aa###ba###aaaaaaaba############aa#aaaaaaaaaabbbfgaa#adbaaa#aaaaehaa###aa#adea#a#aaabgbabacefdb#dfffedccbbaaaaaaccbbcdecdggihihhfdffcbbaaaa###aa###..#aa####baaabaaaaaa#####aaaaaaaa#aba#a###abaa#cbaa##.##aa####aa##aa#baaaacccefdbbabbcccbbbdccdbaabbbbbbbaaabbaaaaabc",
+"cabaabbbbbbcbcccccddb##abaccbabbdbcaa#a##a####aabdcdbbcdddghcbaaa####bcacigggecbbbcbcbbabcaaaaaabaaa#a##abb#########a##aaaaaaaaaa###aaaaaaa########aa##aaaa#####aaaaa#acegfaaa#aac##aaaachfc###aa###aabb###a#bbabccddefdceffedbcaaaaa#aaabbbbcdegihhhhgggdcffecabaaaa##a##.###abca#aaa##aaaaaaaa######a###b###baa####aaaaaaaaabca###############aaaabbbbbbdfebbabcccbcdcbbdcbbaababbabaabaaaabbb",
+"febaaaabbbbcdcccccb#####abbabbcccbbaaa####aa#a#abdeccbddeeehgcaa#a#aa#addhifdddbbccbcccbbbbaaaaaababaaa#aaba####a##a#a##aaaa#aaaaa#a##baaaaaaa#####b###aaaaaa##a##aaaabcefihefc##aaaaaabbdha####aaaa#ab######aaaabbccdefegffdcccaa#a##aaaaaabbehhhhffffcddbdcdbbba#ac######..###bb###a#abaaaaaabba#####aaa######a#aa#####a#####bbca###########a##aaabbbaaaabdfdbaccbccbcbbccdcbbbbaaaabaaaaaaabb",
+"dedbbbbbbccbcdccddb#####bbbaacccacbaaaa###aaaaaaacfdcbcdegghigbaa#aaaaaadfhgedcccccbbbbbbbbbbbbbbbbaaaaaabbba########aa#aaaa#abaaa####aaaaaa############aaaaaaa###aaaabcfghgihfbcb#abaaabbge####aaaaab######a#aaaaaaccdeeddfdbcbaaa##a##aabaafhgggfedccccdccbaaabaaaaaa#########a#####a##aabaabcaa#aaa#a#####.####a###########a#aaaba##a####a#aba#aaaabbaaaaabdeecccbbcbbccccdcbabaaabbbaaaabbba",
+"bccdcbbbcccccbcdfda#####acbabcbaabaaa#a###aa#aabbbefedcdffiihhcaaaaaaaabacfffefedcbbbbbaaaabbbbbbbbcaaaaaabaaa####a###a##aaaaaaaaba#####aabaa###########a#a####a###baabccghfhiieaa##aaaaabdga##a#a#aaaa######aabbaaabbbcddegdcbbaa##aaaaaaabbfedfddecbbbbbbaabbabbaaaaaaaaaa####aa####a#a#aaaabcbaaaaaaaa##############.######a#a#aabbba#a####a#aaaabaaabaaabbabcfedcbbbcbccccccbabbabaaaaabbccb",
+"bbccccbbcccccdddeca####aabbccca##aaaa##a#####abbbbeeffeeccfjjifbaabaaabbbcdecdeffdbcbbbaabbbccccbbdcbaaaaa###########a#a#aaaaaba#a######aaabcaaabaa###aa#aaa######acedbcdfihfhifba####aaaadhc###aaa###########a#bbaaabbccccfecaaacca##aaaaaccffdfccedbbab#a#aaaabbaaabababaa###########aaa###bbaa#aaa#abaa##########.########aa####a#aabba#a###a###aaaaabaabaaabbbcdfedbcccbcccccabbbbbbabbbbbbc",
+"bcdcbbcccccddddddba####abbbbdca#a###a###aa####aaabcededcbbgiijjhcabbaaaaaccddddcceedddddddeeefedbbcbcccbbbbaaa#a###aaaaa###aaaacaaa##a###a##acca############acaaaaa#abbccdghccggfcaba#aaaacggdaaa###############abbbaabbdeefedbaaaadda##aabbchedeefedbaaab#####aabbaabacbabaaaa########aa#a###aa####aaabba##a##.#############a#a####aaa##abdba#########aabbaabbabbaabdeddcbbbcccccbbbbaabbbccbba",
+"bbddccbccdccdcebcbb#####abccbcd######aa##a######abcddcdddeggiihhhdaaaabcccceedccbbcbbccbccdeeeggfeddccdeccbbaaaaaaa#a##aaa###aaaba#a##aa######a#####a######aaaaaaabaaababcehb#adcbdbba#aaabdceaa#################abbbbbacgeeecca###bedcaa#adfhccdffbbbba###a####aaaaabbbbaaaba###aaaa##########aa#.##aaaaa#aa#b######a#######aaaa##aaaa###abcdb######a#aabcbaabaabbaaabcdedbbbcddcbbbbcabbbccbbb",
+"bcdfdddcccdddcecbb####a#aabccabaa#####aaaaa#####abbccdedeedcijfggfabaabbbbccddccbbbabaaaaaaaaabbbgihihffedccbbbbbbbba#a#aa####aaaaaaa##aa#######a###aaaa########abaabbbbaccega#cdaaabaaaaabbfea#a#################abbbbbaeedddcbaaabacceccefihdccedcbaa##########aaaaaaabbbaaaa#####aaa##a############aa####aaaa######a#####aa##a##aaa###aaa#a#abc#aa###aabcaaaabbbbbbbbbbcddcbccddcbbbbabcccdcc",
+"ccbcffhfdddddccadbaa#####aabbaaba##########a##aaabbaacdddfeehjifgha#aabcbacddccbbbbbabbaaa#aabcccefgdddeffeecdedbbbbcba###aa####a##aaaaa##a###aa###aba#aa######a#aaabbba#abbfcbcccccbaaa#abbfjg#aa###########aaabbaaabbcbdedcdbbaaabbbcceghhiiedcedbbaa######a###aaaa#abaaaaaaaa##aaa##a##############aa####aaaaa#####ab#####aa##a###aa#aa#a#####aaaa##aaaaabbbbabbbbbbbbbbbbdddccddccbcbbbcccdd",
+"eecbdggfdddedcacda####a###abbaaca######aa##aaa#aabcababcdeeedgigdfgbbcbbbbbcccbbbbbaaaaaaaaaccddddefdecccbbcbbddcbccddedcaaa#a#aa##########a########adbaa#########aabbbcbcabbdcdcbbbcbaa##abbfiaaa##############baaabbbbccedcccbaa#abbbbbefgihfdcccbaaaa###a######aaba#abaaaaaabaa#aaaaaa######...#a#.#####aa#aaaa########a##aaa###a###aa#aa#aaaa#aabbabaaaaabcbbbbbbbbbbbbbbbccdeddcccbdccccdde",
+"eedfhhfcba#abb##a#####a#aabcaaccbc#####a#aa#aa###ccbbbabcdfffhgifehfebbbabbcccbbbbbbbbaaaa#ccdcddfghfeccccbbbbabcddegcbccdcaaaaaa###a###a######a#a##accba#########aaaabbccbbcbcehb###cbba##bdehe###############aa##aabbbccdcbccba##aacccbcceffedcbbaaa#####a######aaba##aaaa#ababcbbbbcbaa########.#.##a####a####aa######aaa###aa####a###a##a#aaa####aaadbbaaacccbbbbbbccbcbcccbcceeeeededcdbccd",
+"dgghigdb##a#a########baaa#abbcbdbbb#####aa#aaaaaaabaababcdegiihdggffdcbaabbbbabbbbbabaaaaa#ccdccdegedccbbbbbbcbbbbaadbabaacdb###aa###############aaaab#aa##a#######aaaaababbbabbfieaaaa#aaa#chke.#########..#aaaaaaaaababbccbbcbaa#aabbcbabcdeedcba###a#####a#a##.###baabbaaaaaaaabbaaba#########....#.#######ab#a#######a######a#########a##aabba###aaabbbbbbacdcbbbbcbcccccbdddeededegeddddcdc",
+"dhghhfa##a######a######aabaacccedaaa#######aaaaaaaababbbccdghgfedgfgcabaaaaaaabababaabaaaaabdcceeeecdbbbababbbbccbbbbbabdbabcba#a############aa##aaaaab#aa###########aababcbbaabeggh######aaagj##############aa#####abbaabbbbbabbbabcabbaaaabcddccba#######.###########ccaaa###aa##aaaa###a###..##....#.aa##a############aaa#####a#####a###aaa#aaaa#aaacaabbbbbbeccccbbccddccdegghhgfeegd#bddccc",
+"ffhhhe###########a#####b#bcadddcbaaaa#####abcca#aaaaaaaaabdhihgddfgfgcaaaaaaabbbabbbaabaaaabedcefecbbbbbbabbbaaabbacdca#aaa#bbdb#aaa#########aa####aa#a###a#####.###aaaaadbbaabaddcggbaaaa#bbdia#a##########aaa###aaabaaaabbbbbbaacefebaa#aaaabcccbaaaa###########.#.##ad#####.##aaa#aa#aa#####...#...###ab#ba######a###a##ab#####a###aaa##aa#aaaaaaaabbbbbbbbbbceddeeccbccccddfhijjhggghb#bba##",
+"#afhgcaa###########a#a##aabcddca###aa######abbbabaaaaabaaaeiiihgbbgeddaaaaaaaaabbaabbbaaaaabdcccddddccabbbbacaaaaabbbaaabaa##acdd###a######..a#a#####a#aa##a########a##aaecb#abbbcccfgaaaaaaaeia#a#a##############aabbaaaababbababdgeca####aaaaabcbbba#####a####.#######da##############aaaa#######.##.#.#ba########.#a#aa##abba##aa#aa#aa###aaaaaaaaaabbbbbcbccccefgeeccbccbbbbdfiihgggeb#aaaa#",
+"##bhgd###############ab#ababcdd###aaaa####aaaaaaaaababaaaadhhigebabfddcaaaaaaaaaaaabaaaaaaabcbbbcbbcecbbbabbbaaaabbaaaaaba###abadea#########.#a##########aa#a###a###a####aabbabbaadccghbbbaaabfi#a##a###aa####a##a#aaabaaaaaaaabbacfdba##a#aaa#aaaabbb######a######.##a#######aa#a##a#a####aa#####a#.#a####aa#########aaaaa##aaa###aa#aaaaa#aaaaabaaaabcbbbbccccceeceeeefedddcbbceeffhgfebaa####",
+"##.dhdb#########ab###bdababaddc######a###.#a######aabacaaaadghfdbbabecdba###aaa#aaaaccabaaacababbbbbbbcbcbbcbaaaaababaaaba####abbcfbaa#aaa###.###ab#####aaaa##a######aa#ba#aabbbabdcabefbcaababhe#a##aa##aa###a#####aabba#aaaaabbbefcba###aaaa#aaaaaaaa#########a#.##############aa#bb#aaa##a####.###########aaaaa#######aaaa###a####a##aabaabaaaaaaaaaabbbcccddebbbbdedefdcccccbceeghgfdaaba#aa",
+"aa#aeea##########c####ba###aca#####aba#############abcabaa#acdefccbacdbdc##aaaaa###aabdbaaabbcccbbbbbbbccbabcabaabbabbaaaaa###addbcdba#a################a####aaaa#aaaaaaaa#aaacbabdcbbbehca#abbeh#aa######aa######aa#aacfbaaaaaabbdgdbaa###aaaa#aaaa########.###aa#a.###########aaa#bbaaaaaa####a#.##.#######aba#####a#############a#aaaaabbba#bbbbaaaaabbcddddddbaabcedccbaadfdcceeggdbaaaaaaa#",
+"aa##ada#a########aaaa###a###a######abaa#########aa#abbbaaaabbcddeeebcdbabb#aaaaaa####aaaabcccbccbaabbbabccbaaaaaaaabbaaaaaaa##aabcccfeb##############a####ab#aaa##aaabbaacababaaaabcdbccffc##abeh.##aa###a#########aaaaacbabaaaccddfgdbaaa##aaaaaaa#######.##.#######.#########aaabaab########a#a##.#########aaa#####aa##a#aa###bdaaba#aa#aabaaaabbbabbbbcddefecbcbaabbdcbaabcecccefgcaaaaaaaaa#",
+"aaa#aaaa#aaaaa#####aaaaaa###########a#####a##ab#a##aacabaaabcccbdhedfdbbabc#aaaaaaaba##aaaeheaaaaaaabbbacddbbaaabbbaaaaaaabc#aa#a###cfgb#a#########aa###aaaccaaaaaaaacbabcdaacbaaabcddcccgfcaabeg.#a#aa#a###aaaa####aaaaabaaaaaaceefhfdbaa###aaaaaa########.####.###.####.####aa#abcbaaa####aaa#############aaaaaaaa#aaaa#ba#babffb#acb#aaaabaaabbccabbcccfgdaa##bcbbaaacbcbacebbbcddbbaaa#a####",
+"accccedaa#aa#aaa##a#aabda#################a#a#a##aaaabbbabbcccdcccfcfecbaaceca#aacdbcccba#ahgabaaaaababbbccccbaabbbbbbbaaabcb###aca#aabcc##a##########a###a#abaaa#aaabbddddbbbcbaaaaabcdddhecccg######ba#a##.#a###aaceca#cbaaaaacdefhgfcaaa#aaaabba#########..#####...#.#######aaabccbaaa####aa########.####abb##aa#aaa#a#ba#abbefba##bbbaaaaaabbccc#ccddeffcaaaa#baaaaabebbbbcbbbbcbbbbbaa##a##",
+"#abeeebaaa###aa###aa###aaa###################aa###a#aabbbbcddddccefegfcca#adhbaacccaaabcbcdecaaa##aaacabdabdcbaabbabbaaababbcb#aabb#aa##dea##aa#######aaa##a##aabaaaacacdfebbbbbbabccccfeddfgfed...#a##aa###########acdbabbb#aa#acddegfecbaaaaaaabaa#########...#####.#########a#abbbabba##aa#####.##....#####a##aaaaaaaa#baaaceeebaaaaeedbbbabbbccb#cedddcccbaaaaaaabaa#bebbbbbbbbbbbbbaaaa####",
+"##aadba#aa##a#######abbda################a#######aaaa#ababccdeeddffhhgccbaabefdbbaaa#aabcbbabca#aaaababbbbcccbaaacaabaaabaaaabbaaaab#aaaaefaaaaaaa#.###a#a#a######bbbaabccabbdcbabbcbcdbbaaaefeiiffa####a#######a##aaaaabbcba#baabdddefffdcaaaaaaaaaa##########...##############aabbbbbdabaaa###.....########aaaaaaaaaaaaabcccbdfebaaaaaacfdccbcddc##baabcbabaaaaaaaaabaaaedbcbcccccbbccbaaaaaaa",
+"a##aba#a####.######a##bgb#######a########aa#######aaa##aabbcceedddeghiebaaabccebaaaaaaaabaabaaabbaaabbaaabbbbbaaabbaaaaaaaaabbccbbcba#####cfebbabbbacaaaaaa#aaaa###acbbbbbbbbcbaabbbccbaaab#.aceffdfghfa#a####aa#aa##acbacbbbaaaaabcedcddedbaaabaaaaaa#######..#.################aabccccdbbb####.#..#..#.#..########aa#aaa#aaabdddbcababbbdeddedeeb####aaaaaa#ba#aababcbbbaeccbcbcbcbbbbaaaa###a",
+"ba#a#####a#############cb#########aa##a###a####ab#aabaaaabbbbedcdccehihcbbbbbbccaaa#a#aaaaabbaaaabbbcbbaaabbbccaaabbaaaaaaaaaabbbbacda####aaedbaaabddba#aaab###aa####aaddcceebabbbcbcdca#aaba#aaabaabfmka##aabaaaaaa#abbabbbbaaa#acccdddccedbbbbaaaaaaaa##a####.#.###############aabddcbbcaaa####.#......aa###aa####aaaa#aa##aacccccbbbabbcdedddea####a##aa#a#bccbccbcbbaaaadddccbbbbbbaa#aa####",
+"ab##aaaa######a##########aa###b##aaaaa##a#a#####ababbbaababbbccccdcdgjifbbabbcccca#aaaaaaaaacaaaaabcccbaaa#bbbcaaaaaaaaaaaaaaaaccbaabbaa#a#a#bcbbaa##a###aaba######aaaaaaddfhgccddddacacaaaaa#aaaaaaabhnk.aabbb##aa####aa#acaabb#aabccddeecccbbbabaa##aa###aa#######.######a###aaaabdddcdedda#########...#####aaaaaaaaa##a###aabcbbccbbbbcddeeefc##a####aaaaaacdccbbaababaaabccdccccbbbbaa#a####",
+"#####a#aaaaa###aaa######ba###aa#bba#aa#abca##bb#abaabbbbbbaabbbbdccceihgecbcdccbcd#ababa##aaabaaaaaabccbaabbddbbaa#aaaaaaaaaaaaaccbaaa#a######aabdcb##aaa##a#a#####aaaa##aabffebccddcb#aa#######aaaaaadlnd#aabbabaaaaa##aaaa####aaaabccdeedbb#aa##a###############.##..#.#####aaaaabccdeecdaa#####.########.###aaa#aa###aaaa#aaabcbccccbbccddeef##aaaaa####aaaccbaabaaaaaaaaba#bcddcbbbbbb#aaa#a",
+"abaa###aaaaa##a#a##a#############a#a#ababda#aaaaaaaabbaabbbbcbbbddbddgifhedbcccbbcc##aabbaa#aaaaaaabaabbbccccdebaa##aa#aaaaaaaaaabedaaaa##########becaaaaa#a#########aaa##abceffdccb##aa########a#abbabilk#a#a######ab#aa#aa#####aaabbcddedbaa#a######a#####################a#aaaaaabdddfgfc##########...a#a###aaa#a#aa##a###aaaabbbbbcbbbcceghfaaaaaaaabbabccbbbaaaaaaaa#abba#aacedcccbaaaaa#aa",
+"bbaa##aa#aaaa#aaaaaaaaa#aaa##########abaaaa#baaaaabbbbbabbbbccccddbddggghhfdbbcaabbbbbaabbaaaa#aaabbaaabbb#bbbaaa#####a#aaaaaaaaaabb##aa##########aabdcbabaaaa####aa###aa#abbcdhhcaba#baaa#######aaaaabhlmc#a#####aaaaa#a##abba#aabaaabcdgfbb################################aabbaabbccdhigca#########.########aaa########aa#a##aaabbbbccbccdgfha#caaa.##fedbbcbaaaaaaaaa#aaa###aaadecccbbaaaaaa",
+"#aa###aaa#a#aaabbbbbcbaa##a#######aaabaababaa#aaaaabbbbbaaababccdecdfhhiihgfdbccbbcbabaaaaaadca##abbaaaaaaa#bb##aaa####aa#aaa#aaaabbda.##########aaaabddcbbaa#a##aa#aaa##aaabbdecca#a#aa#a########aaaaaeili##a######abaa###aaaaaacfeaabddcdbaa##############################aaabbbbbbcdfgjieba####.#####aa#aa############aaaaa###aaabcbbcbbcefggcbbfeedbedbcbabbaaaaaaaaaaaaaaa#aaa#cdcddcbbaaaa",
+"aa#a###aa#a##a#aaaabbccaa#aaa########bacbaaaaaaaaaaaabcbbbbbbcedcdccfhfhkhggfdbbccbbabaabaabdda###aaa#aaaaaaacb#########aaaaaa#aaaabec##########aaaaaaabddcbaaaaaaaaaaaa##aabacbaaaba#####a##a######aaabgklbaaa#####aaaaaaaaaaabbbfdaacddeddcbaaa#########aaab##########a##aaaabbcbbbbeffhjifdcb#####.##acbb#aaaa###########aaaa#aaacbcbbcbcegfaccgghgffdcbbaabbbaaa#aaaaaaaaaba#aaaabeecccbaaaa",
+"aaaa########aaaabbabbbbcbbbaaaa#####.##aaaaaaaaaaaaabbbbaaaaadedcdccegijkifddebccbbccaabaaa##aa######aaaaaaba#aa#########aaaaaaaaa#bccda#######aaaaabbaaabddcba#aaaaaaaaaaaaabcdaaaaa##abaaa#a#a#a##aaaafhlg.aa#a#a###ba##b#acaabcdfaaaccdccedba##########adcbca#########a#aaabbcddccbdefggiigecb########aaaa#abba###########aaaaaa#bdbccbccef#abdeddeeddccba#bbbbbaaaaaaaaaaabcaaaaaa#eedccbbba",
+"aa#aaaaa###aaaaaaaaabbbbbbbbaaaa#######aabaaaaaaaaaabbaaaaabbbfeccccdfiljigcdeccccbccbccbbaaaa#######a#aa##aaa#####..#..#aaabaaaaaaabacb######aaaaaaabbaaaacddcbaaa##cbabaaaaabcbaaaaa###a##a####a##aababchl#.###a#####aaaaaa#aabbdeaaacbbbbdfdccbabb####a#ddbbbba##########abbbccdcccddefghhfcaaa######aab#abaaddaa########ab###aaaacccccdefd#dbgebcccdcaabbbaaaaaaababbbaaabacaaaaaba#eeddcbba",
+"aa#aaaaba#a#a##aaababbccbabbbbba########aa#a#aaaaaaaababbaaaaadcccaddfhkjigdcdecccbbcdcecbaaaa######aca####aa#####a#####.#aaaaa#aabababb######aaaaaabbabaaaaabcdcbaaaaaaaaaabbbcaaaa#a####aa####a#aaaaaababjh.####a#####aaa##aaaabdabaaaabbabdeeeddddcb#.##debaaabaaaba####aaabbccdcccddeffgfgcaa##aa###aaaaaccaddca########a#a###aaaccbbceffbaacgeaabbbbabaaaaaaaaaaabaaaabbcaaabaaaabbbccdedcb",
+"ba#a#aaaaa####aaaaaaaaaaccbcbbaa#######aaaa###aa##aaaaaaaabbbabbcbbefffhjihfcbfcbcbbbcfhgcaaa#####a#deaa##aaaa###############a##a###aaaaa###aaaabbaaaababbbbbbbbedcbaa#abbbbbcccaa##a######aa##aaa##abaa#aabja##.#######a#a###aaabecaaaaaaacccbcaaaabbdddefedcbaa###aaaa#aaaabbbcccccccddfggghdba####aababababcbbddba###a###a#aaa##aabbcccegfbaabcaaaaaaabbaaaaabbaabaacaabbbabbadbaaaaabba#aefc",
+"ba#a#aa#######aaaaaaabaabbebdbbb######aa####a###a####aaaabbaabcabcccddffjhfdbaefcdbbbbdjkjebaa#####bccb##baba#####aa######a###a#a####aaaaa##a##aabaaaaaaabbbbbbabefdbbcbbbcbbbcbaa####aa#######aaaaadaaaaabbdg###a#a####a#aa#aabccccaaaaaabcdbccaaaaabbdeeedcdcba###aa#aabaaabbbcbcccddddeffffdbaa####abccbb#bbccdbccaa###a#aaaa#a#aabbdcdfgdaaaccaaaaaa#aaaaababbaaabbbbbabbbbbcbcbaaaabaa###be",
+"fcb#############aa#aaaaaaadegdacbaa###aa####aaa#a####aaaabbaaabaabddccehieabaabecccbbbbbikkgca####acbb###baba#####aa####aaaaaaaa######aa###aaaaaaabaaaaaaaacbbbbbbeffedccbcddddbaaa##aaaa###a##aaa#adba#aaabbie.#.#aa##aaaaaaacecaaaba###a##aabdb#a#aaccccccccbbba###aaa###aaabbbbcccdddedegcddcbbaaaabbabbabbaabbaaddbaa#####aa##aaabbddefgcabagbaaaaaaaaaaaabbaaacabaaaaabbbbabbaaaaaaaaaaaa#a",
+"bdeba#########aaaaa###aaaaacfebbbbaa###aa#####aa########aaababaacbdeccehhbaaaaaddcbbbbbcgijhea####acb########a##aa#a##a#aaaaabaaaa####aaab###aaaaaaaaaababbccbbbbacbedffedcdeeaaaab#aaa#aa##a##aa#a###aa#aabackc.#.##aaaaaabdefb#a#aaaaa#a####abc####abcbbeecbbaaabb#aaaaaaaabbbbcbcdededdefdcaccbca##aaaa###aaaaabaaeccaaa###aaa#aaabcccdffbbacfc#a#a#aaaaaaabbaaaaeabcbbabbbbcbbabb#aaaaaaa#aa",
+"##aba######aaaaaaaa##a#aaa#fdaabbccb###################a#aaaabbabccccdehibabbbbcfdcbbbabgihc#a####abbaa##a###aa##a#aaaa##aaa##aaaaba###daaa###abcaaabaaabbbbbccbcbcdcdddggfedbcbaaaaa##a#####aaaa#aa#####abbbbdjb.a##aaaaabeecabba##aabda######aa####aaabbdcdcbaa#bcbbaaaaaaaabbbcccddedefffdcbccbab####a#####a#aaabaabeeba######aaacbcddegebbacccba##a#aaaaaaaaaaaaccbbbbbabaaa#aaabbaaaaaaaaaa",
+"aa##baa####aaabaaaaa#####aacaababbccbaa##################aaaaaaaabbccbegifaaaabbcecbbbbaadgb#####aeeabc#.######aa##aaaaa#aaaaa###abaa##edaaaa##aabbaaaabbbbbbbccbbdccccdddehhdabbaaaaaa##a###aaaabb######cebcbcgj#aa##abdfggcbbbaaaabdfea####aaaaa##aa###aaa#aaaa#aaabbaaaaaaaabbccddeeddeffeeeefcabaa#aa#####aa#aabbbacccbaaaaaaaabcccdegfbbbceaacb#####aaaaaaaaaaaacccabaaaaa#a#abbccaabbaaaa#",
+"#aaa#daaaaaaaabbbaaaa####abbaabaabcbbbbb##aa################aaaaabbbddehecacbaaaabecbbbbabaa#####adcca#########a#a##daaaaacaaaaaa###aa#aca#aa##aaaabbbaabccbbbbcddaccdeddecfhgcabaaa#ab#a####a####aaa#aaaabbbcbcijdchihgighedbcbbcdfdabbbbccaaaaaa###caa#aaaa#a#a##aaaaaaaaaaaaabcccdddddeeedeeeffbaaaaaa##aa###aaabbbabcdeabaaaabbbbcdegibabbfaabca####a#acca#aaaaaaababbbaaaa##aaababbaaabaaaa",
+"#####adcbbbaabbbaaaa#a#a#####aaaabbaaabcbaa#################aa#aaaaabddgeadbcaaaaabccbbbbba#####a#a##aaaaa###aa#aa#bccaabaac#aaa#####a#..#####aaaaaabcbaaabbbbcdccdcddedceefgfccbaaaaaa#aa###aa##accaaaaaaaabbbbdjkfdfgjjhgfeeeeeedcaabaabaaaaa#####ab#a#aaaa###a####aaaaaaaaaaabbccddccccdccdeeegfbcbcaaa#aaba#aaabdcbbbababbbaabbcccdghg#aadbaabbaa###a##acdaaa#a#aa#baaaaaaaaa#a#aaaccbaabaaa",
+"a##a#aaedbbcbabaaaa##a##aa####aaaababbaabacaaa###a#######a####aaaaaaaccehbbbbcbaaaaacdbbbcb#a#a#a#.####aaa##a#aaaaaaabaaaaab##aaaaaaaa#####aaa##aa##abbaaabbbccbccbcdcdcddeffcaabaaaabba#aa####a##bcbaaaabababbbbejib#abccdcbbccba##a##aaaa##a######a##aaaaa#a###a#####aaaaaaaaabbccccccccccccdeegfcdabbaaaaaaa#aaaabccbbbaccbabbbcddefedea#cd##a#aaab#aaa##bcb###aaa##abaaaa#####aaaaabbcbaabbb",
+"aa##aa#bhgccbbccbbaaaaa########aaaaabcbaaaabbaaaa###aa#####a#a#aaaabbbbcega##acbabababecccdabaa##########aaaaaaaaaaaaaabaaa####aaaaaaaa##.##abaaa#aaaaabbbbbbbbcdbbccddcdcegeaaaab#aaaaaaaaa####aabbabbcbbbcaaabbcegiaaaaaa##abbcbca##.###aaaaa####aaa##abbaa#aaaaa####aaaabbaaabbbbccccbcccdddedfddcaaaaaaaaaaaaabbccdbbbcecbbccdefged#a###fa######aaaaaaaabaa#######aab#aaaa#aa#aaaaaabcccabaa",
+"aa##aadafhhfeccbbbaa#aaa##a####a#aaaaaaaaaaaaaaaaabaaaabaa#aa###aaaaaabbcfd#a#acbaaaaabeecdcc#############abbaaaaaaaababbba###aaaaaaa#a#####aa#aaaaaa#aaaabbbabcccehgeecdegebaaaaaaaaa#aaa#aa###aaaaababccbbaa#aabceggaaaaaa#aaaabcb####a###aaba######a#a#####aaaaba#####aabbaaaabcbbbbcbbacceeddeebabdbabbaaaaaababcdccdccdcbbccefecb#####cc#########aaaaaaaaaa##ba#aaaaabbbbaaa#aaaaaabcccdgdb",
+"##aaacdggggghgdbbbbbaaaaa#aa###a###aa##aaaaaaaaaaaaabcbbaaaaaa#aaaaaaabbbdfd#aaacdaaaaaadgefc#######a#a###abb##a#aaabaaaaaa#######aaa#a########aaaaa##aabbbbbbbbccefhfeeegfbbba#aaaaaaaaaaaa####aa##abbcdacbaa##aabcehfaaaa###aaababa##.##a#aaaca#a#aaaaaa#aaaa#aabcc#####aaaabbbbbadcabbbbbbceedefcaabcecaaabaaababccdcdddccbbcceda#####baeaa#aaa#####ab##aaaaa##aaa##abbbbbbbbaaaaaaaaabbbagig",
+"f#aaaehhfffeffhfbccbbaaaaaaa####a#aaaaa###aaa#a#abaabccabcbabbbbabbaabbbbcehdaaaaaaaaaab#dgeaa##a###########aa####aaaaaaa######a####aaaa###a###aaaaa###aabbbbbacccdedddfgebcbaaaaabbbaabaaba#########abcbdabaaa#aabcdeibaaa######aaaca######aabbb####aaaaaaaaaaa##bbdb####aabbbbaaaacdcaabbbbcceddeccccaba#aaabaaaabccddddddceddeec#aca#aabebaaa#######aaaba#######aaaaabbbabbbbbaaaaaaaaaba#dii",
+"hd#aaejiedefeeddedccbaaaaaa########aaa#######a#a#aaaabbaacbbababccbbabbbbbceidbaaaaaaaacbcgeca#############aaaaaaaaaaaba######.a############a##aaaaaaaaaaaacbbbccccedbcfcbbbbaaabbbbaaaaaaababaaa#baaaabababbabaaaaabdfhaaaaa#aa##b#bbaa#####abb##a##aaaabbba#aaaaaacda#####abbbbaa####a#abaabccbdecdbbaaaaaaaaaaaabccceeedcdfgffeba#aa#aa#bcaaa##########aa##a####aaaaa#aaabbbbaaaaabbbcbbbeefh",
+"ggecdhjkiefeeddcdefdababaaa########aa##a########abaabaabcdabbcdccbcbabbbbccchiecaa#abbbaaaadeca#####a#######aabaaaaaabba###a##.#############a##aaaaaaaaaaabbbccdddbbeccdbbcbbbabbbbbbcbbaaaabccaaaabaabcabbabaaaabaabcefeabaaaaa####aaccb####aaa###a###aabbab#a#aaa##aaa#####acbba#a######aaaabbbbfefdaaaacaaaaaaaabbbcefffeefbed########a##dbaaa#######a#############a########aaaaaaaaaccfgfhdf",
+"efddegijmkfeeeddccdgdbcccbaaa####a#aaa#####a####a###aabbcbabacccdccbbbbbcbbdfijhbaaaaabb###cedbaa###aaa#####aabbccbaaaaa###accb###a##########aaaaaaaaaaaabcbbccddddcddaaaabbbabbbbbbcbaabbbbbaaaabbaaaaabbbbaaa#ccaabbddheabaaaaa####abca#####ba##a####abcaaaaaaaaaa#aaaa#####bbaaa##aaaa##aaabbaaadfdbaabcbaaaaaaabbacehhhhcaaaa#####a#ab##ccaa########aa#############ba#a#aaaa#aaabdaaeffghgff",
+"eddcbcdefijgeedcccbbdeccccbaaaaaaaaaa#a#########aaa##a#abcaacccccccbcbbccccdefikibaaaaaaaabbdddca#a#a#aa####aaabbbaaaa##a##aaaba##aa##a######aaaaaaaaaaabbbbbccccddddaabbaabcdbbbccbacbabcbbccbaa#aaaa###baaaaa#a#aaabcdfjb#aaaaaa####abaa.####a##aa####bcbbaaaaaaaa#####aa##abaaa#a##aaaaaaaaaaaaabecbaababaaaaabbbcbcehhcaaa##aaa#######b#.cbabaa#####aa##a#####a#########aa#a#aaabdefffggfefe",
+"ddcaaabdefhihecdbbbbacdecccbbaaaaaaaa############aa##aa#ababbcbcbbbababccdceeegijgaaaaaba###bfcdc##aaaaa######aaaaaaaaa#aaaaaacba#aaa#a#ba#aa#aaaaaaaababcbbbbbcedabbaabbaaabbbabbdccbbbaabbbbbaaa#aaaaa##aaaaaa#####abcehka##aaa#####aaaa###..a#aba#####abcaaaaaaa#a##a##a###ba########aaaa####aa#deaaa#aaaaaaabbbbbccefcbaba##abaaaa.#a#ba##dc#a#a####abaabb#a##aa##a###a###aaaaabaceecddhhedd",
+"cccbabbcdfffhheccbbbbbcdfccbbbbaaaaaa###############a##aaaabacbbbbaaaacccddcdefhjjhbaaaabaa##dfbbc###aa#aa######aabaabaabbbbbabdb#aa#a###bba#a##aaaabbabbbbbcbbcedbaaaaaaaaabbbbbcbccbcebbbbaaaaaaaaaa#####aaa####aa#aabdegj.############a##a##a#aba####a##baaaaaa#a###aa#aa########a##a#aaaa####a#eeaa###aaaaaaaaabbcdgfdbaa####aabbcb#aabc###cda#aa##aababcbb#a#aa###a##aab#aaaaababdecbcdheed",
+"cbbaccbcddeffeedcbbbbbbccffdbbcbabbaaa#aa########a###ca#abaabbbabaaaaabcccddcdgiikjgbaaaaba##afcacba###aa########abbbbaabbbbbbbcbbbb#aa#a###aa##aaaaababbbbcbccdca#a##aaaaabaaabcccbbcbcbaabba##aaaaaba#####aa####aabbbddcdjd.#########.#..#######aba######aaaaaba########aa#######aaa#aba#aaa###aacaaaa##aabaaaaaaabbcefcbbaaaaa##aaacabaaaa###bca#####aaaaacaa#a###a##a#aaa#a#aabbbbcddcccegdd",
+"cbbabbbbccddeedddcbbbbbbbbdfheccccbaaaa###########aa#bd##baaaabaaaaaababcddcccggijjjbaaabbaa##bcbabba##aa#######aaaaaaabbbbbbbbbcccaaaa##a##aaa##aaaabbbdbcbbcdfbaaa#aaabbbbbbbbbcccbccdedaaa#aaaabbaaaa#a#aa####a#abcccdccfi###########....#######aa##aaaaaaaaaaa##########a###a##aa#aa#aaa#####aaa#aaaa##abbbaaaaabcdefbbaaaaabaa####aa####a#a#dba#####bb##b###########aaaaa#aaabbaabbbccddede",
+"baabbbbbccccdeedcccbbccbcbbcdiheccbbbaaaaa#aab##aa###aa###aaaacbaaaaaababccccdfhjjjl#abbbaaba#abeaabb######a#####bbaa#aaaabbbcbbabbaa###aa####a###aaaabacdcccdceaaaaaaaaaababbbbbbbcbbbcbdba###aabbbaaa#aa##########aabbabccgb.###.#########.########a#aaaa#abaa#########a##aa#####bcaabaaba###aaaaaaaa#####aaaaaabbbdhidabaaaaaaaa###########a###ebbb###aaa####a###aa#aabcaabbaaababaaabbbbbdcb",
+"abcbbbbbbbccbbcddbcbbbbbbbbbcfeghfccbbabaaaaabaaaa####a#b##aaaabbaa#aaaaabccbceefhegdedaaaaaaa#abdaaba#aa##a#####aaaabaaaaaaabbbaacc###aa#aa####a#aaaaaaabcccddfbba#aaaaaabbbbabbccccccbcbdaa#####ac#####a##########aa#aabcbdh..#########.#####.####aaa#aaa###abb###########accaa###a##aaabbbba#a##a#abba####aaaaaccegcbbaaaaaaa#aa###.##a########aeaaaa###a#a######aaa##aaaaaaaabbaabbaacaacced",
+"cadbbbbbbcbccbbacbbbbbbbbabccdeehgffccbcbaaabaaaaaa###a####aaa#aaaaaaaaaaabccbdeeffeehgcaabaaa##adb#aca##aaa#####aaabaaaaaaaaaabaacdb##aaaaaaa#abbaaabbbabbdecffbaaaaaaaaaaaaaabbaccbcbcccdcaa#############aabb######aaaaabbbehd..###d#.#.######.####adbaaaa##abba########aaaaaaaaaaaaa#aaaaaaa#a#aa#abaaa####aaacdeheaaaaaaaaa##aa#aa#####a####a#.cdaa######a##a###########aa##aabb#aabaaabbadf",
+"cabdabbbabcccdccbccbbbbbbaabdcdefdcfgccbbbbaabcbaaa###aa##aca####aaa##aabbbccccddffhihhfbaba#c###bdaaagaaa#a######aabaabaaaaaaaa#a#aa####aaaa#aabbaaaabbbbbcddfeca###aaaaabbaabbabbcbccbbbccdada###aa######aaba####a###abaabcafjlf..defe##...#########bbaaa###aab#a#######aaabcb#aaaaaca##aaaa####a##aab###a##aabdfiida###aaaaa##ca#aa#####a####a###ecaaa########a##a#####a####a###aaaaaaaaaabab",
+"ccbbbbabbaaabccdcbbbbbbaaaabcdbbbeeadgeccbbbbabbbaaa##aa#abedbaa####a####bbbcbccddehhhfdaa###da#a#ddaabhaa###########a#abaabbaa######a####aaaaaaaaaabbbbbbcbdeefcb###aaaaaaaaaabbbbccccbbaabbcaaa############aacbaabaaaaaaabccbdejkbd..bgccdcba########aa######aaa#a#######aaaccaba#bcaaba#a##aaa#####abba#aa#aabdgkjkihgdb#.cedcbb#.###dc########b##ebaaaa#########################aaa#aaaaaaba",
+"abeecbbaababbbabbdbabbbbbaaabcccbdcb#ehedccbbaabbbaaa#abaaaedba###########acbbbcceeeggdaaa#bacaa#aadabbdf#######.#######aaaaaa######bca###aaaaaaaaaabbbbbbbccfffbaaaa#aaaaa#aaaabbccabbcccbbbbaaaaa#######a#aa#acaaaaaaaaaaaabccceglh.#....#baacca..####ab########aaa####a##ababbbba#ceaaaaaa###a######aa##acbbbbchgcddfgjihddigefegfffba#affeecbbaaabda#aa######a#a################aaaa#aaaaaab",
+"babfdcbcbabaabababbbaaaaaaaabcccdbaaaacifddcbbbbbbbabaabaacecabaaaaa######aaabbcdeeedifba#adcbaaba#bcabbfe#aa####aaa###a#abaaaa######aaaac#aaaaaaaabbbdbbbbcceebbba##aaaaaaa#aaabbbbbbcccdcabaaaaab##a#aaaaaaa######abaaaaa#abbbbddei#####a####.#ee######aa######aaaba######abaaaa#a##bc##aa#a####a###a#aaaabcbbbceecbbcbdeffgfdccccdefeefgffedcefeb##cdbcba########a###########a###aaaabaaaaaaa"
+};
+SIMPLE = T BITPIX = 8 NAXIS = 2 NAXIS1 = 384 NAXIS2 = 384 HISTORY Written by XV 3.10a END 3"3wUD3D3"3""3"3"333""""""""3DDDU3""""DªwUUD3333333"3""3""DfD"3""""""""33DUfffUªw3""UD3""3"3D"33wf"""""""3""""""""D""""""""333U3333DDff333"""""""""""333333DDDUD"3"""""3"""""""""3""""""3333UUfª"
diff --git a/tests/simple.c b/tests/simple.c
new file mode 100644
index 000000000..47893772f
--- /dev/null
+++ b/tests/simple.c
@@ -0,0 +1,39 @@
+#include <gtk/gtk.h>
+#include <gdk/gdkprivate.h>
+
+
+void
+hello ()
+{
+ g_print ("hello world\n");
+}
+
+int
+main (int argc, char *argv[])
+{
+ GtkWidget *window;
+ GtkWidget *button;
+
+ gdk_progclass = g_strdup ("XTerm");
+ gtk_init (&argc, &argv);
+
+ window = gtk_widget_new (gtk_window_get_type (),
+ "GtkObject::user_data", NULL,
+ "GtkWindow::type", GTK_WINDOW_TOPLEVEL,
+ "GtkWindow::title", "hello world",
+ "GtkWindow::allow_grow", FALSE,
+ "GtkWindow::allow_shrink", FALSE,
+ "GtkContainer::border_width", 10,
+ NULL);
+ button = gtk_widget_new (gtk_button_get_type (),
+ "GtkButton::label", "hello world",
+ "GtkObject::signal::clicked", hello, NULL,
+ "GtkWidget::parent", window,
+ "GtkWidget::visible", TRUE,
+ NULL);
+ gtk_widget_show (window);
+
+ gtk_main ();
+
+ return 0;
+}
diff --git a/tests/test.xpm b/tests/test.xpm
new file mode 100644
index 000000000..9b0d2efdb
--- /dev/null
+++ b/tests/test.xpm
@@ -0,0 +1,92 @@
+/* XPM */
+static char *openfile[] = {
+/* width height num_colors chars_per_pixel */
+" 20 19 66 2",
+/* colors */
+".. c None",
+".# c #000000",
+".a c #dfdfdf",
+".b c #7f7f7f",
+".c c #006f6f",
+".d c #00efef",
+".e c #009f9f",
+".f c #004040",
+".g c #00bfbf",
+".h c #ff0000",
+".i c #ffffff",
+".j c #7f0000",
+".k c #007070",
+".l c #00ffff",
+".m c #00a0a0",
+".n c #004f4f",
+".o c #00cfcf",
+".p c #8f8f8f",
+".q c #6f6f6f",
+".r c #a0a0a0",
+".s c #7f7f00",
+".t c #007f7f",
+".u c #5f5f5f",
+".v c #707070",
+".w c #00f0f0",
+".x c #009090",
+".y c #ffff00",
+".z c #0000ff",
+".A c #00afaf",
+".B c #00d0d0",
+".C c #00dfdf",
+".D c #005f5f",
+".E c #00b0b0",
+".F c #001010",
+".G c #00c0c0",
+".H c #000f0f",
+".I c #00007f",
+".J c #005050",
+".K c #002f2f",
+".L c #dfcfcf",
+".M c #dfd0d0",
+".N c #006060",
+".O c #00e0e0",
+".P c #00ff00",
+".Q c #002020",
+".R c #dfc0c0",
+".S c #008080",
+".T c #001f1f",
+".U c #003f3f",
+".V c #007f00",
+".W c #00000f",
+".X c #000010",
+".Y c #00001f",
+".Z c #000020",
+".0 c #00002f",
+".1 c #000030",
+".2 c #00003f",
+".3 c #000040",
+".4 c #00004f",
+".5 c #000050",
+".6 c #00005f",
+".7 c #000060",
+".8 c #00006f",
+".9 c #000070",
+"#. c #7f7f80",
+"## c #9f9f9f",
+/* pixels */
+"........................................",
+"........................................",
+"........................................",
+".......................#.#.#............",
+".....................#.......#...#......",
+"...............................#.#......",
+".......#.#.#.................#.#.#......",
+".....#.y.i.y.#.#.#.#.#.#.#..............",
+".....#.i.y.i.y.i.y.i.y.i.#..............",
+".....#.y.i.y.i.y.i.y.i.y.#..............",
+".....#.i.y.i.y.#.#.#.#.#.#.#.#.#.#.#....",
+".....#.y.i.y.#.s.s.s.s.s.s.s.s.s.#......",
+".....#.i.y.#.s.s.s.s.s.s.s.s.s.#........",
+".....#.y.#.s.s.s.s.s.s.s.s.s.#..........",
+".....#.#.s.s.s.s.s.s.s.s.s.#............",
+".....#.#.#.#.#.#.#.#.#.#.#..............",
+"........................................",
+"........................................",
+"........................................"
+};
diff --git a/tests/testgtk.c b/tests/testgtk.c
new file mode 100644
index 000000000..b1d698a08
--- /dev/null
+++ b/tests/testgtk.c
@@ -0,0 +1,3110 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include "gtk.h"
+#include "../gdk/gdk.h"
+#include "../gdk/gdkx.h"
+
+
+void
+destroy_window (GtkWidget *widget,
+ GtkWidget **window)
+{
+ *window = NULL;
+}
+
+void
+button_window (GtkWidget *widget,
+ GtkWidget *button)
+{
+ if (!GTK_WIDGET_VISIBLE (button))
+ gtk_widget_show (button);
+ else
+ gtk_widget_hide (button);
+}
+
+void
+create_buttons ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *box1;
+ GtkWidget *box2;
+ GtkWidget *table;
+ GtkWidget *button[10];
+ GtkWidget *separator;
+
+ if (!window)
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "buttons");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+ box1 = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), box1);
+ gtk_widget_show (box1);
+
+
+ table = gtk_table_new (3, 3, FALSE);
+ gtk_table_set_row_spacings (GTK_TABLE (table), 5);
+ gtk_table_set_col_spacings (GTK_TABLE (table), 5);
+ gtk_container_border_width (GTK_CONTAINER (table), 10);
+ gtk_box_pack_start (GTK_BOX (box1), table, TRUE, TRUE, 0);
+ gtk_widget_show (table);
+
+
+ button[0] = gtk_button_new_with_label ("button1");
+ button[1] = gtk_button_new_with_label ("button2");
+ button[2] = gtk_button_new_with_label ("button3");
+ button[3] = gtk_button_new_with_label ("button4");
+ button[4] = gtk_button_new_with_label ("button5");
+ button[5] = gtk_button_new_with_label ("button6");
+ button[6] = gtk_button_new_with_label ("button7");
+ button[7] = gtk_button_new_with_label ("button8");
+ button[8] = gtk_button_new_with_label ("button9");
+
+ gtk_signal_connect (GTK_OBJECT (button[0]), "clicked",
+ (GtkSignalFunc) button_window,
+ button[1]);
+
+ gtk_table_attach (GTK_TABLE (table), button[0], 0, 1, 0, 1,
+ GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+ gtk_widget_show (button[0]);
+
+ gtk_signal_connect (GTK_OBJECT (button[1]), "clicked",
+ (GtkSignalFunc) button_window,
+ button[2]);
+
+ gtk_table_attach (GTK_TABLE (table), button[1], 1, 2, 1, 2,
+ GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+ gtk_widget_show (button[1]);
+
+ gtk_signal_connect (GTK_OBJECT (button[2]), "clicked",
+ (GtkSignalFunc) button_window,
+ button[3]);
+ gtk_table_attach (GTK_TABLE (table), button[2], 2, 3, 2, 3,
+ GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+ gtk_widget_show (button[2]);
+
+ gtk_signal_connect (GTK_OBJECT (button[3]), "clicked",
+ (GtkSignalFunc) button_window,
+ button[4]);
+ gtk_table_attach (GTK_TABLE (table), button[3], 0, 1, 2, 3,
+ GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+ gtk_widget_show (button[3]);
+
+ gtk_signal_connect (GTK_OBJECT (button[4]), "clicked",
+ (GtkSignalFunc) button_window,
+ button[5]);
+ gtk_table_attach (GTK_TABLE (table), button[4], 2, 3, 0, 1,
+ GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+ gtk_widget_show (button[4]);
+
+ gtk_signal_connect (GTK_OBJECT (button[5]), "clicked",
+ (GtkSignalFunc) button_window,
+ button[6]);
+ gtk_table_attach (GTK_TABLE (table), button[5], 1, 2, 2, 3,
+ GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+ gtk_widget_show (button[5]);
+
+ gtk_signal_connect (GTK_OBJECT (button[6]), "clicked",
+ (GtkSignalFunc) button_window,
+ button[7]);
+ gtk_table_attach (GTK_TABLE (table), button[6], 1, 2, 0, 1,
+ GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+ gtk_widget_show (button[6]);
+
+ gtk_signal_connect (GTK_OBJECT (button[7]), "clicked",
+ (GtkSignalFunc) button_window,
+ button[8]);
+ gtk_table_attach (GTK_TABLE (table), button[7], 2, 3, 1, 2,
+ GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+ gtk_widget_show (button[7]);
+
+ gtk_signal_connect (GTK_OBJECT (button[8]), "clicked",
+ (GtkSignalFunc) button_window,
+ button[0]);
+ gtk_table_attach (GTK_TABLE (table), button[8], 0, 1, 1, 2,
+ GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+ gtk_widget_show (button[8]);
+
+
+ separator = gtk_hseparator_new ();
+ gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
+ gtk_widget_show (separator);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ button[9] = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button[9]), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+ gtk_box_pack_start (GTK_BOX (box2), button[9], TRUE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS (button[9], GTK_CAN_DEFAULT);
+ gtk_widget_grab_default (button[9]);
+ gtk_widget_show (button[9]);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+void
+create_toggle_buttons ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *box1;
+ GtkWidget *box2;
+ GtkWidget *button;
+ GtkWidget *separator;
+
+ if (!window)
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "toggle buttons");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+
+ box1 = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), box1);
+ gtk_widget_show (box1);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ button = gtk_toggle_button_new_with_label ("button1");
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+ button = gtk_toggle_button_new_with_label ("button2");
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+ button = gtk_toggle_button_new_with_label ("button3");
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+
+ separator = gtk_hseparator_new ();
+ gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
+ gtk_widget_show (separator);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+void
+create_check_buttons ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *box1;
+ GtkWidget *box2;
+ GtkWidget *button;
+ GtkWidget *separator;
+
+ if (!window)
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "check buttons");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+
+ box1 = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), box1);
+ gtk_widget_show (box1);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ button = gtk_check_button_new_with_label ("button1");
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+ button = gtk_check_button_new_with_label ("button2");
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+ button = gtk_check_button_new_with_label ("button3");
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+
+ separator = gtk_hseparator_new ();
+ gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
+ gtk_widget_show (separator);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+void
+create_radio_buttons ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *box1;
+ GtkWidget *box2;
+ GtkWidget *button;
+ GtkWidget *separator;
+
+ if (!window)
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "radio buttons");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+
+ box1 = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), box1);
+ gtk_widget_show (box1);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ button = gtk_radio_button_new_with_label (NULL, "button1");
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+ button = gtk_radio_button_new_with_label (
+ gtk_radio_button_group (GTK_RADIO_BUTTON (button)),
+ "button2");
+ gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE);
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+ button = gtk_radio_button_new_with_label (
+ gtk_radio_button_group (GTK_RADIO_BUTTON (button)),
+ "button3");
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+
+ separator = gtk_hseparator_new ();
+ gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
+ gtk_widget_show (separator);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+void
+bbox_widget_destroy (GtkWidget* widget, GtkWidget* todestroy)
+{
+}
+
+void
+create_bbox_window (gint horizontal,
+ char* title,
+ gint pos,
+ gint spacing,
+ gint child_w,
+ gint child_h,
+ gint layout)
+{
+ GtkWidget* window;
+ GtkWidget* box1;
+ GtkWidget* bbox;
+ GtkWidget* button;
+
+ /* create a new window */
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title (GTK_WINDOW (window), title);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) bbox_widget_destroy, window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) bbox_widget_destroy, window);
+
+ if (horizontal)
+ {
+ gtk_widget_set_usize (window, 550, 60);
+ gtk_widget_set_uposition (window, 150, pos);
+ box1 = gtk_vbox_new (FALSE, 0);
+ }
+ else
+ {
+ gtk_widget_set_usize (window, 150, 400);
+ gtk_widget_set_uposition (window, pos, 200);
+ box1 = gtk_vbox_new (FALSE, 0);
+ }
+
+ gtk_container_add (GTK_CONTAINER (window), box1);
+ gtk_widget_show (box1);
+
+ if (horizontal)
+ bbox = gtk_hbutton_box_new();
+ else
+ bbox = gtk_vbutton_box_new();
+ gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), layout);
+ gtk_button_box_set_spacing (GTK_BUTTON_BOX (bbox), spacing);
+ gtk_button_box_set_child_size (GTK_BUTTON_BOX (bbox), child_w, child_h);
+ gtk_widget_show (bbox);
+
+ gtk_container_border_width (GTK_CONTAINER(box1), 25);
+ gtk_box_pack_start (GTK_BOX (box1), bbox, TRUE, TRUE, 0);
+
+ button = gtk_button_new_with_label ("OK");
+ gtk_container_add (GTK_CONTAINER(bbox), button);
+
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) bbox_widget_destroy, window);
+
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("Cancel");
+ gtk_container_add (GTK_CONTAINER(bbox), button);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("Help");
+ gtk_container_add (GTK_CONTAINER(bbox), button);
+ gtk_widget_show (button);
+
+ gtk_widget_show (window);
+}
+
+void
+test_hbbox ()
+{
+ create_bbox_window (TRUE, "Spread", 50, 40, 85, 28, GTK_BUTTONBOX_SPREAD);
+ create_bbox_window (TRUE, "Edge", 200, 40, 85, 25, GTK_BUTTONBOX_EDGE);
+ create_bbox_window (TRUE, "Start", 350, 40, 85, 25, GTK_BUTTONBOX_START);
+ create_bbox_window (TRUE, "End", 500, 15, 30, 25, GTK_BUTTONBOX_END);
+}
+
+void
+test_vbbox ()
+{
+ create_bbox_window (FALSE, "Spread", 50, 40, 85, 25, GTK_BUTTONBOX_SPREAD);
+ create_bbox_window (FALSE, "Edge", 250, 40, 85, 28, GTK_BUTTONBOX_EDGE);
+ create_bbox_window (FALSE, "Start", 450, 40, 85, 25, GTK_BUTTONBOX_START);
+ create_bbox_window (FALSE, "End", 650, 15, 30, 25, GTK_BUTTONBOX_END);
+}
+
+void
+create_button_box ()
+{
+ static GtkWidget* window = NULL;
+ GtkWidget* bbox;
+ GtkWidget* button;
+
+ if (!window)
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title (GTK_WINDOW (window),
+ "Button Box Test");
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window, &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window, &window);
+
+ gtk_container_border_width (GTK_CONTAINER (window), 20);
+
+ /*
+ *these 15 lines are a nice and easy example for GtkHButtonBox
+ */
+ bbox = gtk_hbutton_box_new ();
+ gtk_container_add (GTK_CONTAINER (window), bbox);
+ gtk_widget_show (bbox);
+
+ button = gtk_button_new_with_label ("Horizontal");
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) test_hbbox, 0);
+ gtk_container_add (GTK_CONTAINER (bbox), button);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("Vertical");
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) test_vbbox, 0);
+ gtk_container_add (GTK_CONTAINER (bbox), button);
+ gtk_widget_show (button);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+
+void
+reparent_label (GtkWidget *widget,
+ GtkWidget *new_parent)
+{
+ GtkWidget *label;
+
+ label = gtk_object_get_user_data (GTK_OBJECT (widget));
+
+ gtk_widget_reparent (label, new_parent);
+}
+
+void
+create_reparent ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *box1;
+ GtkWidget *box2;
+ GtkWidget *box3;
+ GtkWidget *frame;
+ GtkWidget *button;
+ GtkWidget *label;
+ GtkWidget *separator;
+
+ if (!window)
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "buttons");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+
+ box1 = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), box1);
+ gtk_widget_show (box1);
+
+
+ box2 = gtk_hbox_new (FALSE, 5);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ label = gtk_label_new ("Hello World");
+
+ frame = gtk_frame_new ("Frame 1");
+ gtk_box_pack_start (GTK_BOX (box2), frame, TRUE, TRUE, 0);
+ gtk_widget_show (frame);
+
+ box3 = gtk_vbox_new (FALSE, 5);
+ gtk_container_border_width (GTK_CONTAINER (box3), 5);
+ gtk_container_add (GTK_CONTAINER (frame), box3);
+ gtk_widget_show (box3);
+
+ button = gtk_button_new_with_label ("switch");
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) reparent_label,
+ box3);
+ gtk_object_set_user_data (GTK_OBJECT (button), label);
+ gtk_box_pack_start (GTK_BOX (box3), button, FALSE, TRUE, 0);
+ gtk_widget_show (button);
+
+ gtk_box_pack_start (GTK_BOX (box3), label, FALSE, TRUE, 0);
+ gtk_widget_show (label);
+
+
+ frame = gtk_frame_new ("Frame 2");
+ gtk_box_pack_start (GTK_BOX (box2), frame, TRUE, TRUE, 0);
+ gtk_widget_show (frame);
+
+ box3 = gtk_vbox_new (FALSE, 5);
+ gtk_container_border_width (GTK_CONTAINER (box3), 5);
+ gtk_container_add (GTK_CONTAINER (frame), box3);
+ gtk_widget_show (box3);
+
+ button = gtk_button_new_with_label ("switch");
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) reparent_label,
+ box3);
+ gtk_object_set_user_data (GTK_OBJECT (button), label);
+ gtk_box_pack_start (GTK_BOX (box3), button, FALSE, TRUE, 0);
+ gtk_widget_show (button);
+
+
+ separator = gtk_hseparator_new ();
+ gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
+ gtk_widget_show (separator);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+void
+create_pixmap ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *box1;
+ GtkWidget *box2;
+ GtkWidget *box3;
+ GtkWidget *button;
+ GtkWidget *label;
+ GtkWidget *separator;
+ GtkWidget *pixmapwid;
+ GdkPixmap *pixmap;
+ GdkBitmap *mask;
+ GtkStyle *style;
+
+ if (!window)
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "pixmap");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+ gtk_widget_realize(window);
+
+ box1 = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), box1);
+ gtk_widget_show (box1);
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
+ gtk_widget_show (box2);
+
+ button = gtk_button_new ();
+ gtk_box_pack_start (GTK_BOX (box2), button, FALSE, FALSE, 0);
+ gtk_widget_show (button);
+
+ style=gtk_widget_get_style(button);
+
+ pixmap = gdk_pixmap_create_from_xpm (window->window, &mask,
+ &style->bg[GTK_STATE_NORMAL],
+ "test.xpm");
+ pixmapwid = gtk_pixmap_new (pixmap, mask);
+
+ label = gtk_label_new ("Pixmap\ntest");
+ box3 = gtk_hbox_new (FALSE, 0);
+ gtk_container_border_width (GTK_CONTAINER (box3), 2);
+ gtk_container_add (GTK_CONTAINER (box3), pixmapwid);
+ gtk_container_add (GTK_CONTAINER (box3), label);
+ gtk_container_add (GTK_CONTAINER (button), box3);
+ gtk_widget_show (pixmapwid);
+ gtk_widget_show (label);
+ gtk_widget_show (box3);
+
+ separator = gtk_hseparator_new ();
+ gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
+ gtk_widget_show (separator);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+void
+create_tooltips ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *box1;
+ GtkWidget *box2;
+ GtkWidget *button;
+ GtkWidget *separator;
+ GtkTooltips *tooltips;
+
+ if (!window)
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "tooltips");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+ tooltips=gtk_tooltips_new();
+
+ box1 = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), box1);
+ gtk_widget_show (box1);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ button = gtk_toggle_button_new_with_label ("button1");
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+ gtk_tooltips_set_tips(tooltips,button,"This is button 1");
+
+ button = gtk_toggle_button_new_with_label ("button2");
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+ gtk_tooltips_set_tips(tooltips,button,"This is button 2");
+
+ button = gtk_toggle_button_new_with_label ("button3");
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+ gtk_tooltips_set_tips (tooltips, button, "This is button 3. This is also a really long tooltip which probably won't fit on a single line and will therefore need to be wrapped. Hopefully the wrapping will work correctly.");
+
+ separator = gtk_hseparator_new ();
+ gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
+ gtk_widget_show (separator);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+
+ gtk_tooltips_set_tips (tooltips, button, "Push this button to close window");
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+GtkWidget*
+create_menu (int depth)
+{
+ GtkWidget *menu;
+ GtkWidget *submenu;
+ GtkWidget *menuitem;
+ GSList *group;
+ char buf[32];
+ int i, j;
+
+ if (depth < 1)
+ return NULL;
+
+ menu = gtk_menu_new ();
+ submenu = NULL;
+ group = NULL;
+
+ for (i = 0, j = 1; i < 5; i++, j++)
+ {
+ sprintf (buf, "item %2d - %d", depth, j);
+ menuitem = gtk_radio_menu_item_new_with_label (group, buf);
+ group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem));
+ gtk_menu_append (GTK_MENU (menu), menuitem);
+ gtk_widget_show (menuitem);
+
+ if (depth > 0)
+ {
+ if (!submenu)
+ submenu = create_menu (depth - 1);
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
+ }
+ }
+
+ return menu;
+}
+
+void
+create_menus ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *box1;
+ GtkWidget *box2;
+ GtkWidget *button;
+ GtkWidget *menu;
+ GtkWidget *menubar;
+ GtkWidget *menuitem;
+ GtkWidget *optionmenu;
+ GtkWidget *separator;
+
+ if (!window)
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "menus");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+
+ box1 = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), box1);
+ gtk_widget_show (box1);
+
+
+ menubar = gtk_menu_bar_new ();
+ gtk_box_pack_start (GTK_BOX (box1), menubar, FALSE, TRUE, 0);
+ gtk_widget_show (menubar);
+
+ menu = create_menu (2);
+
+ menuitem = gtk_menu_item_new_with_label ("test\nline2");
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
+ gtk_menu_bar_append (GTK_MENU_BAR (menubar), menuitem);
+ gtk_widget_show (menuitem);
+
+ menuitem = gtk_menu_item_new_with_label ("foo");
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
+ gtk_menu_bar_append (GTK_MENU_BAR (menubar), menuitem);
+ gtk_widget_show (menuitem);
+
+ menuitem = gtk_menu_item_new_with_label ("bar");
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
+ gtk_menu_item_right_justify (GTK_MENU_ITEM (menuitem));
+ gtk_menu_bar_append (GTK_MENU_BAR (menubar), menuitem);
+ gtk_widget_show (menuitem);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ optionmenu = gtk_option_menu_new ();
+ gtk_option_menu_set_menu (GTK_OPTION_MENU (optionmenu), create_menu (1));
+ gtk_option_menu_set_history (GTK_OPTION_MENU (optionmenu), 4);
+ gtk_box_pack_start (GTK_BOX (box2), optionmenu, TRUE, TRUE, 0);
+ gtk_widget_show (optionmenu);
+
+
+ separator = gtk_hseparator_new ();
+ gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
+ gtk_widget_show (separator);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+void
+create_scrolled_windows ()
+{
+ static GtkWidget *window;
+ GtkWidget *scrolled_window;
+ GtkWidget *table;
+ GtkWidget *button;
+ char buffer[32];
+ int i, j;
+
+ if (!window)
+ {
+ window = gtk_dialog_new ();
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "dialog");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+
+ scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+ gtk_container_border_width (GTK_CONTAINER (scrolled_window), 10);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox),
+ scrolled_window, TRUE, TRUE, 0);
+ gtk_widget_show (scrolled_window);
+
+ table = gtk_table_new (20, 20, FALSE);
+ gtk_table_set_row_spacings (GTK_TABLE (table), 10);
+ gtk_table_set_col_spacings (GTK_TABLE (table), 10);
+ gtk_container_add (GTK_CONTAINER (scrolled_window), table);
+ gtk_widget_show (table);
+
+ for (i = 0; i < 20; i++)
+ for (j = 0; j < 20; j++)
+ {
+ sprintf (buffer, "button (%d,%d)\n", i, j);
+ button = gtk_toggle_button_new_with_label (buffer);
+ gtk_table_attach_defaults (GTK_TABLE (table), button,
+ i, i+1, j, j+1);
+ gtk_widget_show (button);
+ }
+
+
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
+ button, TRUE, TRUE, 0);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+void
+create_entry ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *box1;
+ GtkWidget *box2;
+ GtkWidget *entry;
+ GtkWidget *button;
+ GtkWidget *separator;
+
+ /* if (!window) */
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "entry");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+
+ box1 = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), box1);
+ gtk_widget_show (box1);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ entry = gtk_entry_new ();
+ /* gtk_widget_set_usize (entry, 0, 25); */
+ gtk_entry_set_text (GTK_ENTRY (entry), "hello world");
+ gtk_box_pack_start (GTK_BOX (box2), entry, TRUE, TRUE, 0);
+ gtk_widget_show (entry);
+
+
+ separator = gtk_hseparator_new ();
+ gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
+ gtk_widget_show (separator);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ /* else
+ gtk_widget_destroy (window); */
+}
+
+void
+list_add (GtkWidget *widget,
+ GtkWidget *list)
+{
+ static int i = 1;
+ gchar buffer[64];
+ GtkWidget *list_item;
+
+ sprintf (buffer, "added item %d", i++);
+ list_item = gtk_list_item_new_with_label (buffer);
+ gtk_widget_show (list_item);
+ gtk_container_add (GTK_CONTAINER (list), list_item);
+}
+
+void
+list_remove (GtkWidget *widget,
+ GtkWidget *list)
+{
+ GList *tmp_list;
+ GList *clear_list;
+
+ tmp_list = GTK_LIST (list)->selection;
+ clear_list = NULL;
+
+ while (tmp_list)
+ {
+ clear_list = g_list_prepend (clear_list, tmp_list->data);
+ tmp_list = tmp_list->next;
+ }
+
+ clear_list = g_list_reverse (clear_list);
+
+ gtk_list_remove_items (GTK_LIST (list), clear_list);
+
+ tmp_list = clear_list;
+
+ while (tmp_list)
+ {
+ gtk_widget_destroy (GTK_WIDGET (tmp_list->data));
+ tmp_list = tmp_list->next;
+ }
+
+ g_list_free (clear_list);
+}
+
+void
+create_list ()
+{
+ static GtkWidget *window = NULL;
+ static char *list_items[] =
+ {
+ "hello",
+ "world",
+ "blah",
+ "foo",
+ "bar",
+ "argh",
+ "spencer",
+ "is a",
+ "wussy",
+ "programmer",
+ };
+ static int nlist_items = sizeof (list_items) / sizeof (list_items[0]);
+
+ GtkWidget *box1;
+ GtkWidget *box2;
+ GtkWidget *scrolled_win;
+ GtkWidget *list;
+ GtkWidget *list_item;
+ GtkWidget *button;
+ GtkWidget *separator;
+ int i;
+
+ if (!window)
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "list");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+
+ box1 = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), box1);
+ gtk_widget_show (box1);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ scrolled_win = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+ gtk_box_pack_start (GTK_BOX (box2), scrolled_win, TRUE, TRUE, 0);
+ gtk_widget_show (scrolled_win);
+
+ list = gtk_list_new ();
+ gtk_list_set_selection_mode (GTK_LIST (list), GTK_SELECTION_MULTIPLE);
+ gtk_list_set_selection_mode (GTK_LIST (list), GTK_SELECTION_BROWSE);
+ gtk_container_add (GTK_CONTAINER (scrolled_win), list);
+ gtk_widget_show (list);
+
+ for (i = 0; i < nlist_items; i++)
+ {
+ list_item = gtk_list_item_new_with_label (list_items[i]);
+ gtk_container_add (GTK_CONTAINER (list), list_item);
+ gtk_widget_show (list_item);
+ }
+
+ button = gtk_button_new_with_label ("add");
+ GTK_WIDGET_UNSET_FLAGS (button, GTK_CAN_FOCUS);
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) list_add,
+ list);
+ gtk_box_pack_start (GTK_BOX (box2), button, FALSE, TRUE, 0);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("remove");
+ GTK_WIDGET_UNSET_FLAGS (button, GTK_CAN_FOCUS);
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) list_remove,
+ list);
+ gtk_box_pack_start (GTK_BOX (box2), button, FALSE, TRUE, 0);
+ gtk_widget_show (button);
+
+
+ separator = gtk_hseparator_new ();
+ gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
+ gtk_widget_show (separator);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+void
+color_selection_ok (GtkWidget *w,
+ GtkColorSelectionDialog *cs)
+{
+ GtkColorSelection *colorsel;
+ gdouble color[4];
+
+ colorsel=GTK_COLOR_SELECTION(cs->colorsel);
+
+ gtk_color_selection_get_color(colorsel,color);
+ gtk_color_selection_set_color(colorsel,color);
+}
+
+void
+color_selection_changed (GtkWidget *w,
+ GtkColorSelectionDialog *cs)
+{
+ GtkColorSelection *colorsel;
+ gdouble color[4];
+
+ colorsel=GTK_COLOR_SELECTION(cs->colorsel);
+ gtk_color_selection_get_color(colorsel,color);
+}
+
+void
+create_color_selection ()
+{
+ static GtkWidget *window = NULL;
+
+ if (!window)
+ {
+ gtk_preview_set_install_cmap (TRUE);
+ gtk_widget_push_visual (gtk_preview_get_visual ());
+ gtk_widget_push_colormap (gtk_preview_get_cmap ());
+
+ window = gtk_color_selection_dialog_new ("color selection dialog");
+
+ gtk_color_selection_set_opacity (
+ GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (window)->colorsel),
+ TRUE);
+
+ gtk_color_selection_set_update_policy(
+ GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (window)->colorsel),
+ GTK_UPDATE_CONTINUOUS);
+
+ gtk_window_position (GTK_WINDOW (window), GTK_WIN_POS_MOUSE);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_signal_connect (
+ GTK_OBJECT (GTK_COLOR_SELECTION_DIALOG (window)->colorsel),
+ "color_changed",
+ (GtkSignalFunc) color_selection_changed,
+ window);
+
+ gtk_signal_connect (
+ GTK_OBJECT (GTK_COLOR_SELECTION_DIALOG (window)->ok_button),
+ "clicked",
+ (GtkSignalFunc) color_selection_ok,
+ window);
+
+ gtk_signal_connect_object (
+ GTK_OBJECT (GTK_COLOR_SELECTION_DIALOG (window)->cancel_button),
+ "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+
+ gtk_widget_pop_colormap ();
+ gtk_widget_pop_visual ();
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+
+void
+file_selection_ok (GtkWidget *w,
+ GtkFileSelection *fs)
+{
+ g_print ("%s\n", gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs)));
+}
+
+void
+create_file_selection ()
+{
+ static GtkWidget *window = NULL;
+
+ if (!window)
+ {
+ window = gtk_file_selection_new ("file selection dialog");
+ gtk_window_position (GTK_WINDOW (window), GTK_WIN_POS_MOUSE);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (window)->ok_button),
+ "clicked", (GtkSignalFunc) file_selection_ok,
+ window);
+ gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION (window)->cancel_button),
+ "clicked", (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+
+/*
+ * GtkDialog
+ */
+static GtkWidget *dialog_window = NULL;
+
+void
+label_toggle (GtkWidget *widget,
+ GtkWidget **label)
+{
+ if (!(*label))
+ {
+ *label = gtk_label_new ("Dialog Test");
+ gtk_misc_set_padding (GTK_MISC (*label), 10, 10);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->vbox),
+ *label, TRUE, TRUE, 0);
+ gtk_widget_show (*label);
+ }
+ else
+ {
+ gtk_widget_destroy (*label);
+ *label = NULL;
+ }
+}
+
+void
+create_dialog ()
+{
+ static GtkWidget *label;
+ GtkWidget *button;
+
+ if (!dialog_window)
+ {
+ dialog_window = gtk_dialog_new ();
+
+ gtk_signal_connect (GTK_OBJECT (dialog_window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &dialog_window);
+ gtk_signal_connect (GTK_OBJECT (dialog_window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &dialog_window);
+
+ gtk_window_set_title (GTK_WINDOW (dialog_window), "dialog");
+ gtk_container_border_width (GTK_CONTAINER (dialog_window), 0);
+
+ button = gtk_button_new_with_label ("OK");
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->action_area),
+ button, TRUE, TRUE, 0);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("Toggle");
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) label_toggle,
+ &label);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->action_area),
+ button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+ label = NULL;
+ }
+
+ if (!GTK_WIDGET_VISIBLE (dialog_window))
+ gtk_widget_show (dialog_window);
+ else
+ gtk_widget_destroy (dialog_window);
+}
+
+
+/*
+ * GtkRange
+ */
+void
+create_range_controls ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *box1;
+ GtkWidget *box2;
+ GtkWidget *button;
+ GtkWidget *scrollbar;
+ GtkWidget *scale;
+ GtkWidget *separator;
+ GtkObject *adjustment;
+
+ if (!window)
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "range controls");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+
+ box1 = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), box1);
+ gtk_widget_show (box1);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ adjustment = gtk_adjustment_new (0.0, 0.0, 101.0, 0.1, 1.0, 1.0);
+
+ scale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
+ gtk_widget_set_usize (GTK_WIDGET (scale), 150, 30);
+ gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
+ gtk_scale_set_digits (GTK_SCALE (scale), 1);
+ gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
+ gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
+ gtk_widget_show (scale);
+
+ scrollbar = gtk_hscrollbar_new (GTK_ADJUSTMENT (adjustment));
+ gtk_range_set_update_policy (GTK_RANGE (scrollbar),
+ GTK_UPDATE_CONTINUOUS);
+ gtk_box_pack_start (GTK_BOX (box2), scrollbar, TRUE, TRUE, 0);
+ gtk_widget_show (scrollbar);
+
+
+ separator = gtk_hseparator_new ();
+ gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
+ gtk_widget_show (separator);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+
+/*
+ * GtkRulers
+ */
+void
+create_rulers ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *table;
+ GtkWidget *ruler;
+
+ if (!window)
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "rulers");
+ gtk_widget_set_usize (window, 300, 300);
+ gtk_widget_set_events (window,
+ GDK_POINTER_MOTION_MASK
+ | GDK_POINTER_MOTION_HINT_MASK);
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+ table = gtk_table_new (2, 2, FALSE);
+ gtk_container_add (GTK_CONTAINER (window), table);
+ gtk_widget_show (table);
+
+ ruler = gtk_hruler_new ();
+ gtk_ruler_set_range (GTK_RULER (ruler), 5, 15, 0, 20);
+
+ gtk_signal_connect_object (
+ GTK_OBJECT (window),
+ "motion_notify_event",
+ (GtkSignalFunc)
+ GTK_WIDGET_CLASS (GTK_OBJECT (ruler)->klass)->motion_notify_event,
+ GTK_OBJECT (ruler));
+
+ gtk_table_attach (GTK_TABLE (table), ruler, 1, 2, 0, 1,
+ GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
+ gtk_widget_show (ruler);
+
+
+ ruler = gtk_vruler_new ();
+ gtk_ruler_set_range (GTK_RULER (ruler), 5, 15, 0, 20);
+
+ gtk_signal_connect_object (
+ GTK_OBJECT (window),
+ "motion_notify_event",
+ (GtkSignalFunc)
+ GTK_WIDGET_CLASS (GTK_OBJECT (ruler)->klass)->motion_notify_event,
+ GTK_OBJECT (ruler));
+
+ gtk_table_attach (GTK_TABLE (table), ruler, 0, 1, 1, 2,
+ GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+ gtk_widget_show (ruler);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+
+/*
+ * GtkText
+ */
+void
+create_text ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *box1;
+ GtkWidget *box2;
+ GtkWidget *button;
+ GtkWidget *separator;
+ GtkWidget *table;
+ GtkWidget *hscrollbar;
+ GtkWidget *vscrollbar;
+ GtkWidget *text;
+
+ if (!window)
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_widget_set_name (window, "text window");
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "test");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+
+ box1 = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), box1);
+ gtk_widget_show (box1);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ table = gtk_table_new (2, 2, FALSE);
+ gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2);
+ gtk_table_set_col_spacing (GTK_TABLE (table), 0, 2);
+ gtk_box_pack_start (GTK_BOX (box2), table, TRUE, TRUE, 0);
+ gtk_widget_show (table);
+
+ text = gtk_text_new (NULL, NULL);
+ gtk_table_attach_defaults (GTK_TABLE (table), text, 0, 1, 0, 1);
+ gtk_widget_show (text);
+
+ hscrollbar = gtk_hscrollbar_new (GTK_TEXT (text)->hadj);
+ gtk_table_attach (GTK_TABLE (table), hscrollbar, 0, 1, 1, 2,
+ GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
+ gtk_widget_show (hscrollbar);
+
+ vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
+ gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
+ GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+ gtk_widget_show (vscrollbar);
+
+ gtk_text_freeze (GTK_TEXT (text));
+
+ gtk_widget_realize (text);
+
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "spencer blah blah blah\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "kimball\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "is\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "a\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "wuss.\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "but\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "josephine\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "(his\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "girlfriend\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "is\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "not).\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "why?\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "because\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "spencer\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "puked\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "last\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "night\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "but\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "josephine\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "did\n", -1);
+ gtk_text_insert (GTK_TEXT (text), NULL, &text->style->white, NULL,
+ "not", -1);
+
+ gtk_text_thaw (GTK_TEXT (text));
+
+ separator = gtk_hseparator_new ();
+ gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
+ gtk_widget_show (separator);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+
+/*
+ * GtkNotebook
+ */
+void
+rotate_notebook (GtkButton *button,
+ GtkNotebook *notebook)
+{
+ gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos + 1) % 4);
+}
+
+void
+create_notebook ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *box1;
+ GtkWidget *box2;
+ GtkWidget *button;
+ GtkWidget *separator;
+ GtkWidget *notebook;
+ GtkWidget *frame;
+ GtkWidget *label;
+ char buffer[32];
+ int i;
+
+ if (!window)
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "notebook");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+
+ box1 = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), box1);
+ gtk_widget_show (box1);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ notebook = gtk_notebook_new ();
+ gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP);
+ gtk_box_pack_start (GTK_BOX (box2), notebook, TRUE, TRUE, 0);
+ gtk_widget_show (notebook);
+
+
+ for (i = 0; i < 5; i++)
+ {
+ sprintf (buffer, "Page %d", i+1);
+
+ frame = gtk_frame_new (buffer);
+ gtk_container_border_width (GTK_CONTAINER (frame), 10);
+ gtk_widget_set_usize (frame, 200, 150);
+ gtk_widget_show (frame);
+
+ label = gtk_label_new (buffer);
+ gtk_container_add (GTK_CONTAINER (frame), label);
+ gtk_widget_show (label);
+
+ label = gtk_label_new (buffer);
+ gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, label);
+ }
+
+
+ separator = gtk_hseparator_new ();
+ gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
+ gtk_widget_show (separator);
+
+
+ box2 = gtk_hbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("next");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_notebook_next_page,
+ GTK_OBJECT (notebook));
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("prev");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_notebook_prev_page,
+ GTK_OBJECT (notebook));
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("rotate");
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) rotate_notebook,
+ notebook);
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+
+/*
+ * GtkPanes
+ */
+void
+create_panes ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *frame;
+ GtkWidget *hpaned;
+ GtkWidget *vpaned;
+
+ if (!window)
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "Panes");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+ vpaned = gtk_vpaned_new ();
+ gtk_container_add (GTK_CONTAINER (window), vpaned);
+ gtk_container_border_width (GTK_CONTAINER(vpaned), 5);
+ gtk_widget_show (vpaned);
+
+ hpaned = gtk_hpaned_new ();
+ gtk_paned_add1 (GTK_PANED (vpaned), hpaned);
+
+ frame = gtk_frame_new (NULL);
+ gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
+ gtk_widget_set_usize (frame, 60, 60);
+ gtk_paned_add1 (GTK_PANED (hpaned), frame);
+ gtk_widget_show (frame);
+
+ frame = gtk_frame_new (NULL);
+ gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
+ gtk_widget_set_usize (frame, 80, 60);
+ gtk_paned_add2 (GTK_PANED (hpaned), frame);
+ gtk_widget_show (frame);
+
+ gtk_widget_show (hpaned);
+
+ frame = gtk_frame_new (NULL);
+ gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
+ gtk_widget_set_usize (frame, 60, 80);
+ gtk_paned_add2 (GTK_PANED (vpaned), frame);
+ gtk_widget_show (frame);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+
+/*
+ * Drag -N- Drop
+ */
+void
+dnd_drop (GtkWidget *button, GdkEvent *event)
+{
+ g_print ("Got drop of type |%s| with data of:\n%s\n",
+ event->dropdataavailable.data_type,
+ event->dropdataavailable.data);
+ g_free (event->dropdataavailable.data);
+ g_free (event->dropdataavailable.data_type);
+}
+
+void
+dnd_drag_request (GtkWidget *button, GdkEvent *event)
+{
+ g_print ("Button |%s| got drag request %d\n",
+ gtk_widget_get_name (button), event->type);
+
+ gtk_widget_dnd_data_set (button, event, "Hello world!!!",
+ strlen("Hello world!!!") + 1);
+}
+
+void
+create_dnd ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *box1;
+ GtkWidget *box2;
+ GtkWidget *box3;
+ GtkWidget *entry;
+ GtkWidget *frame;
+ GtkWidget *button;
+ GtkWidget *separator;
+ char *foo = "testing";
+
+ if (!window)
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "Drag -N- Drop");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+ box1 = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), box1);
+ gtk_widget_show (box1);
+
+ box2 = gtk_hbox_new (FALSE, 5);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
+ gtk_widget_show (box2);
+
+ frame = gtk_frame_new ("Drag");
+ gtk_box_pack_start (GTK_BOX (box2), frame, TRUE, TRUE, 0);
+ gtk_widget_show (frame);
+
+ box3 = gtk_vbox_new (FALSE, 5);
+ gtk_container_border_width (GTK_CONTAINER (box3), 5);
+ gtk_container_add (GTK_CONTAINER (frame), box3);
+ gtk_widget_show (box3);
+
+ /*
+ * FROM Button
+ */
+ button = gtk_button_new_with_label ("From");
+ gtk_box_pack_start (GTK_BOX (box3), button, FALSE, TRUE, 0);
+ gtk_widget_show (button);
+
+ /*
+ * currently, the widget has to be realized to
+ * set dnd on it, this needs to change
+ */
+ gtk_widget_realize (button);
+ gtk_signal_connect (GTK_OBJECT (button),
+ "drag_request_event",
+ (GtkSignalFunc) dnd_drag_request,
+ button);
+
+ gtk_widget_dnd_drag_set (button, TRUE, &foo, 1);
+
+
+ frame = gtk_frame_new ("Drop");
+ gtk_box_pack_start (GTK_BOX (box2), frame, TRUE, TRUE, 0);
+ gtk_widget_show (frame);
+
+ box3 = gtk_vbox_new (FALSE, 5);
+ gtk_container_border_width (GTK_CONTAINER (box3), 5);
+ gtk_container_add (GTK_CONTAINER (frame), box3);
+ gtk_widget_show (box3);
+
+
+ /*
+ * TO Button
+ */
+ button = gtk_button_new_with_label ("To");
+ gtk_box_pack_start (GTK_BOX (box3), button, FALSE, TRUE, 0);
+ gtk_widget_show (button);
+
+ gtk_widget_realize (button);
+ gtk_signal_connect (GTK_OBJECT (button),
+ "drop_data_available_event",
+ (GtkSignalFunc) dnd_drop,
+ button);
+
+ gtk_widget_dnd_drop_set (button, TRUE, &foo, 1, FALSE);
+
+
+ separator = gtk_hseparator_new ();
+ gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
+ gtk_widget_show (separator);
+
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
+ gtk_widget_show (box2);
+
+
+ button = gtk_button_new_with_label ("close");
+
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+/*
+ * Shaped Windows
+ */
+static GdkWindow *root_win = NULL;
+static GtkWidget *modeller = NULL;
+static GtkWidget *sheets = NULL;
+static GtkWidget *rings = NULL;
+
+typedef struct _cursoroffset {gint x,y;} CursorOffset;
+
+static void
+shape_pressed (GtkWidget *widget)
+{
+ CursorOffset *p;
+
+ p = gtk_object_get_user_data (GTK_OBJECT(widget));
+ gtk_widget_get_pointer (widget, &(p->x), &(p->y));
+
+ gtk_grab_add (widget);
+ gdk_pointer_grab (widget->window, TRUE,
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_BUTTON_MOTION_MASK,
+ NULL, NULL, 0);
+}
+
+
+static void
+shape_released (GtkWidget *widget)
+{
+ gtk_grab_remove (widget);
+ gdk_pointer_ungrab (0);
+}
+
+static void
+shape_motion (GtkWidget *widget,
+ GdkEventMotion *event)
+{
+ gint xp, yp;
+ CursorOffset * p;
+ GdkModifierType mask;
+
+ p = gtk_object_get_user_data (GTK_OBJECT (widget));
+
+ gdk_window_get_pointer (root_win, &xp, &yp, &mask);
+ gtk_widget_set_uposition (widget, xp - p->x, yp - p->y);
+}
+
+GtkWidget *
+shape_create_icon (char *xpm_file,
+ gint x,
+ gint y,
+ gint px,
+ gint py,
+ gint window_type)
+{
+ GtkWidget *window;
+ GtkWidget *pixmap;
+ GtkWidget *fixed;
+ CursorOffset* icon_pos;
+ GdkGC* gc;
+ GdkBitmap *gdk_pixmap_mask;
+ GdkPixmap *gdk_pixmap;
+ GtkStyle *style;
+
+ style = gtk_widget_get_default_style ();
+ gc = style->black_gc;
+
+ /*
+ * GDK_WINDOW_TOPLEVEL works also, giving you a title border
+ */
+ window = gtk_window_new (window_type);
+
+ fixed = gtk_fixed_new ();
+ gtk_widget_set_usize (fixed, 100,100);
+ gtk_container_add (GTK_CONTAINER (window), fixed);
+ gtk_widget_show (fixed);
+
+ gdk_pixmap = gdk_pixmap_create_from_xpm (window->window, &gdk_pixmap_mask,
+ &style->bg[GTK_STATE_NORMAL],
+ xpm_file);
+
+ pixmap = gtk_pixmap_new (gdk_pixmap, gdk_pixmap_mask);
+ gtk_fixed_put (GTK_FIXED (fixed), pixmap, px,py);
+ gtk_widget_show (pixmap);
+
+ gtk_widget_shape_combine_mask (window, gdk_pixmap_mask, px,py);
+
+ gtk_widget_set_events (window,
+ gtk_widget_get_events (window) |
+ GDK_BUTTON_MOTION_MASK |
+ GDK_BUTTON_PRESS_MASK);
+
+ gtk_signal_connect (GTK_OBJECT (window), "button_press_event",
+ GTK_SIGNAL_FUNC (shape_pressed),NULL);
+ gtk_signal_connect (GTK_OBJECT (window), "button_release_event",
+ GTK_SIGNAL_FUNC (shape_released),NULL);
+ gtk_signal_connect (GTK_OBJECT (window), "motion_notify_event",
+ GTK_SIGNAL_FUNC (shape_motion),NULL);
+
+ icon_pos = g_new (CursorOffset, 1);
+ gtk_object_set_user_data(GTK_OBJECT(window), icon_pos);
+
+ gtk_widget_set_uposition (window, x, y);
+ gtk_widget_show (window);
+
+ return window;
+}
+
+void
+create_shapes ()
+{
+ root_win = gdk_window_foreign_new (GDK_ROOT_WINDOW ());
+
+ if (!modeller)
+ {
+ modeller = shape_create_icon ("Modeller.xpm",
+ 440, 140, 0,0, GTK_WINDOW_POPUP);
+
+ gtk_signal_connect (GTK_OBJECT (modeller), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &modeller);
+ gtk_signal_connect (GTK_OBJECT (modeller), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &modeller);
+ }
+ else
+ gtk_widget_destroy (modeller);
+
+ if (!sheets)
+ {
+ sheets = shape_create_icon ("FilesQueue.xpm",
+ 580, 170, 0,0, GTK_WINDOW_POPUP);
+
+ gtk_signal_connect (GTK_OBJECT (sheets), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &sheets);
+ gtk_signal_connect (GTK_OBJECT (sheets), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &sheets);
+
+ }
+ else
+ gtk_widget_destroy (sheets);
+
+ if (!rings)
+ {
+ rings = shape_create_icon ("3DRings.xpm",
+ 460, 270, 25,25, GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (rings), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &rings);
+ gtk_signal_connect (GTK_OBJECT (rings), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &rings);
+ }
+ else
+ gtk_widget_destroy (rings);
+}
+
+
+/*
+ * Progress Bar
+ */
+static int progress_timer = 0;
+
+gint
+progress_timeout (gpointer data)
+{
+ gfloat new_val;
+
+ new_val = GTK_PROGRESS_BAR (data)->percentage;
+ if (new_val >= 1.0)
+ new_val = 0.0;
+ new_val += 0.02;
+
+ gtk_progress_bar_update (GTK_PROGRESS_BAR (data), new_val);
+
+ return TRUE;
+}
+
+void
+destroy_progress (GtkWidget *widget,
+ GtkWidget **window)
+{
+ destroy_window (widget, window);
+ gtk_timeout_remove (progress_timer);
+ progress_timer = 0;
+}
+
+void
+create_progress_bar ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *button;
+ GtkWidget *vbox;
+ GtkWidget *pbar;
+ GtkWidget *label;
+
+ if (!window)
+ {
+ window = gtk_dialog_new ();
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_progress,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_progress,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "dialog");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+
+ vbox = gtk_vbox_new (FALSE, 5);
+ gtk_container_border_width (GTK_CONTAINER (vbox), 10);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox),
+ vbox, TRUE, TRUE, 0);
+ gtk_widget_show (vbox);
+
+ label = gtk_label_new ("progress...");
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+ gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0);
+ gtk_widget_show (label);
+
+ pbar = gtk_progress_bar_new ();
+ gtk_widget_set_usize (pbar, 200, 20);
+ gtk_box_pack_start (GTK_BOX (vbox), pbar, TRUE, TRUE, 0);
+ gtk_widget_show (pbar);
+
+ progress_timer = gtk_timeout_add (100, progress_timeout, pbar);
+
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
+ button, TRUE, TRUE, 0);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+
+/*
+ * Color Preview
+ */
+static int color_idle = 0;
+
+gint
+color_idle_func (GtkWidget *preview)
+{
+ static int count = 1;
+ guchar buf[768];
+ int i, j, k;
+
+ for (i = 0; i < 256; i++)
+ {
+ for (j = 0, k = 0; j < 256; j++)
+ {
+ buf[k+0] = i + count;
+ buf[k+1] = 0;
+ buf[k+2] = j + count;
+ k += 3;
+ }
+
+ gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, i, 256);
+ }
+
+ count += 1;
+
+ gtk_widget_draw (preview, NULL);
+
+ return TRUE;
+}
+
+void
+color_preview_destroy (GtkWidget *widget,
+ GtkWidget **window)
+{
+ gtk_idle_remove (color_idle);
+ color_idle = 0;
+
+ destroy_window (widget, window);
+}
+
+void
+create_color_preview ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *preview;
+ guchar buf[768];
+ int i, j, k;
+
+ if (!window)
+ {
+ gtk_widget_push_visual (gtk_preview_get_visual ());
+ gtk_widget_push_colormap (gtk_preview_get_cmap ());
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) color_preview_destroy,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) color_preview_destroy,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "test");
+ gtk_container_border_width (GTK_CONTAINER (window), 10);
+
+ preview = gtk_preview_new (GTK_PREVIEW_COLOR);
+ gtk_preview_size (GTK_PREVIEW (preview), 256, 256);
+ gtk_container_add (GTK_CONTAINER (window), preview);
+ gtk_widget_show (preview);
+
+ for (i = 0; i < 256; i++)
+ {
+ for (j = 0, k = 0; j < 256; j++)
+ {
+ buf[k+0] = i;
+ buf[k+1] = 0;
+ buf[k+2] = j;
+ k += 3;
+ }
+
+ gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, i, 256);
+ }
+
+ color_idle = gtk_idle_add ((GtkFunction) color_idle_func, preview);
+
+ gtk_widget_pop_colormap ();
+ gtk_widget_pop_visual ();
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+
+/*
+ * Gray Preview
+ */
+static int gray_idle = 0;
+
+gint
+gray_idle_func (GtkWidget *preview)
+{
+ static int count = 1;
+ guchar buf[256];
+ int i, j;
+
+ for (i = 0; i < 256; i++)
+ {
+ for (j = 0; j < 256; j++)
+ buf[j] = i + j + count;
+
+ gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, i, 256);
+ }
+
+ count += 1;
+
+ gtk_widget_draw (preview, NULL);
+
+ return TRUE;
+}
+
+void
+gray_preview_destroy (GtkWidget *widget,
+ GtkWidget **window)
+{
+ gtk_idle_remove (gray_idle);
+ gray_idle = 0;
+
+ destroy_window (widget, window);
+}
+
+void
+create_gray_preview ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *preview;
+ guchar buf[256];
+ int i, j;
+
+ if (!window)
+ {
+ gtk_widget_push_visual (gtk_preview_get_visual ());
+ gtk_widget_push_colormap (gtk_preview_get_cmap ());
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) gray_preview_destroy,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) gray_preview_destroy,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "test");
+ gtk_container_border_width (GTK_CONTAINER (window), 10);
+
+ preview = gtk_preview_new (GTK_PREVIEW_GRAYSCALE);
+ gtk_preview_size (GTK_PREVIEW (preview), 256, 256);
+ gtk_container_add (GTK_CONTAINER (window), preview);
+ gtk_widget_show (preview);
+
+ for (i = 0; i < 256; i++)
+ {
+ for (j = 0; j < 256; j++)
+ buf[j] = i + j;
+
+ gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, i, 256);
+ }
+
+ gray_idle = gtk_idle_add ((GtkFunction) gray_idle_func, preview);
+
+ gtk_widget_pop_colormap ();
+ gtk_widget_pop_visual ();
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+
+/*
+ * Selection Test
+ */
+void
+selection_test_received (GtkWidget *list, GtkSelectionData *data)
+{
+ GdkAtom *atoms;
+ GtkWidget *list_item;
+ GList *item_list;
+ int i, l;
+
+ if (data->length < 0)
+ {
+ g_print ("Selection retrieval failed\n");
+ return;
+ }
+ if (data->type != GDK_SELECTION_TYPE_ATOM)
+ {
+ g_print ("Selection \"TARGETS\" was not returned as atoms!\n");
+ return;
+ }
+
+ /* Clear out any current list items */
+
+ gtk_list_clear_items (GTK_LIST(list), 0, -1);
+
+ /* Add new items to list */
+
+ atoms = (GdkAtom *)data->data;
+
+ item_list = NULL;
+ l = data->length / sizeof (GdkAtom);
+ for (i = 0; i < l; i++)
+ {
+ char *name;
+ name = gdk_atom_name (atoms[i]);
+ if (name != NULL)
+ {
+ list_item = gtk_list_item_new_with_label (name);
+ g_free (name);
+ }
+ else
+ list_item = gtk_list_item_new_with_label ("(bad atom)");
+
+ gtk_widget_show (list_item);
+ item_list = g_list_append (item_list, list_item);
+ }
+
+ gtk_list_append_items (GTK_LIST (list), item_list);
+
+ return;
+}
+
+void
+selection_test_get_targets (GtkWidget *widget, GtkWidget *list)
+{
+ static GdkAtom targets_atom = GDK_NONE;
+
+ if (targets_atom == GDK_NONE)
+ targets_atom = gdk_atom_intern ("TARGETS", FALSE);
+
+ gtk_selection_convert (list, GDK_SELECTION_PRIMARY, targets_atom,
+ GDK_CURRENT_TIME);
+}
+
+void
+create_selection_test ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *button;
+ GtkWidget *vbox;
+ GtkWidget *scrolled_win;
+ GtkWidget *list;
+ GtkWidget *label;
+
+ if (!window)
+ {
+ window = gtk_dialog_new ();
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "Selection Test");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+ /* Create the list */
+
+ vbox = gtk_vbox_new (FALSE, 5);
+ gtk_container_border_width (GTK_CONTAINER (vbox), 10);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox,
+ TRUE, TRUE, 0);
+ gtk_widget_show (vbox);
+
+ label = gtk_label_new ("Gets available targets for current selection");
+ gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
+ gtk_widget_show (label);
+
+ scrolled_win = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+ gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
+ gtk_widget_set_usize (scrolled_win, 100, 200);
+ gtk_widget_show (scrolled_win);
+
+ list = gtk_list_new ();
+ gtk_container_add (GTK_CONTAINER (scrolled_win), list);
+
+ gtk_signal_connect (GTK_OBJECT(list), "selection_received",
+ GTK_SIGNAL_FUNC (selection_test_received), NULL);
+ gtk_widget_show (list);
+
+ /* .. And create some buttons */
+ button = gtk_button_new_with_label ("Get Targets");
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
+ button, TRUE, TRUE, 0);
+
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ GTK_SIGNAL_FUNC (selection_test_get_targets), list);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("Quit");
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
+ button, TRUE, TRUE, 0);
+
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ GTK_SIGNAL_FUNC (gtk_widget_destroy),
+ GTK_OBJECT (window));
+ gtk_widget_show (button);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+
+/*
+ * Gamma Curve
+ */
+void
+create_gamma_curve ()
+{
+ static GtkWidget *window = NULL, *curve;
+ static int count = 0;
+ gfloat vec[256];
+ gint max;
+ gint i;
+
+ if (!window)
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title (GTK_WINDOW (window), "test");
+ gtk_container_border_width (GTK_CONTAINER (window), 10);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_window,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_window,
+ &window);
+
+ curve = gtk_gamma_curve_new ();
+ gtk_container_add (GTK_CONTAINER (window), curve);
+ gtk_widget_show (curve);
+ }
+
+ max = 127 + (count % 2)*128;
+ gtk_curve_set_range (GTK_CURVE (GTK_GAMMA_CURVE (curve)->curve),
+ 0, max, 0, max);
+ for (i = 0; i < max; ++i)
+ vec[i] = (127 / sqrt (max)) * sqrt (i);
+ gtk_curve_set_vector (GTK_CURVE (GTK_GAMMA_CURVE (curve)->curve),
+ max, vec);
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else if (count % 4 == 3)
+ {
+ gtk_widget_destroy (window);
+ window = NULL;
+ }
+
+ ++count;
+}
+
+
+/*
+ * Timeout Test
+ */
+static int timer = 0;
+
+void
+timeout_test (GtkWidget *label)
+{
+ static int count = 0;
+ static char buffer[32];
+
+ sprintf (buffer, "count: %d", ++count);
+ gtk_label_set (GTK_LABEL (label), buffer);
+}
+
+void
+start_timeout_test (GtkWidget *widget,
+ GtkWidget *label)
+{
+ if (!timer)
+ {
+ timer = gtk_timeout_add (100, (GtkFunction) timeout_test, label);
+ }
+}
+
+void
+stop_timeout_test (GtkWidget *widget,
+ gpointer data)
+{
+ if (timer)
+ {
+ gtk_timeout_remove (timer);
+ timer = 0;
+ }
+}
+
+void
+destroy_timeout_test (GtkWidget *widget,
+ GtkWidget **window)
+{
+ destroy_window (widget, window);
+ stop_timeout_test (NULL, NULL);
+}
+
+void
+create_timeout_test ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *button;
+ GtkWidget *label;
+
+ if (!window)
+ {
+ window = gtk_dialog_new ();
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_timeout_test,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_timeout_test,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "Timeout Test");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+ label = gtk_label_new ("count: 0");
+ gtk_misc_set_padding (GTK_MISC (label), 10, 10);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox),
+ label, TRUE, TRUE, 0);
+ gtk_widget_show (label);
+
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
+ button, TRUE, TRUE, 0);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("start");
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) start_timeout_test,
+ label);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
+ button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("stop");
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) stop_timeout_test,
+ NULL);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
+ button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+
+/*
+ * Idle Test
+ */
+static int idle = 0;
+
+gint
+idle_test (GtkWidget *label)
+{
+ static int count = 0;
+ static char buffer[32];
+
+ sprintf (buffer, "count: %d", ++count);
+ gtk_label_set (GTK_LABEL (label), buffer);
+
+ return TRUE;
+}
+
+void
+start_idle_test (GtkWidget *widget,
+ GtkWidget *label)
+{
+ if (!idle)
+ {
+ idle = gtk_idle_add ((GtkFunction) idle_test, label);
+ }
+}
+
+void
+stop_idle_test (GtkWidget *widget,
+ gpointer data)
+{
+ if (idle)
+ {
+ gtk_idle_remove (idle);
+ idle = 0;
+ }
+}
+
+void
+destroy_idle_test (GtkWidget *widget,
+ GtkWidget **window)
+{
+ destroy_window (widget, window);
+ stop_idle_test (NULL, NULL);
+}
+
+void
+create_idle_test ()
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *button;
+ GtkWidget *label;
+
+ if (!window)
+ {
+ window = gtk_dialog_new ();
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy_idle_test,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) destroy_idle_test,
+ &window);
+
+ gtk_window_set_title (GTK_WINDOW (window), "Idle Test");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+
+ label = gtk_label_new ("count: 0");
+ gtk_misc_set_padding (GTK_MISC (label), 10, 10);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox),
+ label, TRUE, TRUE, 0);
+ gtk_widget_show (label);
+
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
+ button, TRUE, TRUE, 0);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("start");
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) start_idle_test,
+ label);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
+ button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("stop");
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) stop_idle_test,
+ NULL);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
+ button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+void
+test_destroy (GtkWidget *widget,
+ GtkWidget **window)
+{
+ destroy_window (widget, window);
+ gtk_main_quit ();
+}
+
+/*
+ * Basic Test
+ */
+void
+create_test ()
+{
+ static GtkWidget *window = NULL;
+
+ if (!window)
+ {
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) test_destroy,
+ &window);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) test_destroy,
+ &window);
+
+
+ gtk_window_set_title (GTK_WINDOW (window), "test");
+ gtk_container_border_width (GTK_CONTAINER (window), 0);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ {
+ gtk_widget_show (window);
+
+ g_print ("create_test: start\n");
+ gtk_main ();
+ g_print ("create_test: done\n");
+ }
+ else
+ gtk_widget_destroy (window);
+}
+
+
+/*
+ * Main Window and Exit
+ */
+void
+do_exit ()
+{
+ gtk_exit (0);
+}
+
+void
+create_main_window ()
+{
+ struct {
+ char *label;
+ void (*func) ();
+ } buttons[] =
+ {
+ { "buttons", create_buttons },
+ { "toggle buttons", create_toggle_buttons },
+ { "check buttons", create_check_buttons },
+ { "radio buttons", create_radio_buttons },
+ { "button box", create_button_box },
+ { "reparent", create_reparent },
+ { "pixmap", create_pixmap },
+ { "tooltips", create_tooltips },
+ { "menus", create_menus },
+ { "scrolled windows", create_scrolled_windows },
+ { "drawing areas", NULL },
+ { "entry", create_entry },
+ { "list", create_list },
+ { "color selection", create_color_selection },
+ { "file selection", create_file_selection },
+ { "dialog", create_dialog },
+ { "miscellaneous", NULL },
+ { "range controls", create_range_controls },
+ { "rulers", create_rulers },
+ { "text", create_text },
+ { "notebook", create_notebook },
+ { "panes", create_panes },
+ { "shapes", create_shapes },
+ { "dnd", create_dnd },
+ { "progress bar", create_progress_bar },
+ { "preview color", create_color_preview },
+ { "preview gray", create_gray_preview },
+ { "gamma curve", create_gamma_curve },
+ { "test selection", create_selection_test },
+ { "test timeout", create_timeout_test },
+ { "test idle", create_idle_test },
+ { "test", create_test },
+ };
+ int nbuttons = sizeof (buttons) / sizeof (buttons[0]);
+ GtkWidget *window;
+ GtkWidget *box1;
+ GtkWidget *box2;
+ GtkWidget *scrolled_window;
+ GtkWidget *button;
+ GtkWidget *separator;
+ int i;
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_widget_set_name (window, "main window");
+ gtk_widget_set_usize (window, 200, 400);
+ gtk_widget_set_uposition (window, 20, 20);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) gtk_exit,
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ (GtkSignalFunc) gtk_exit,
+ NULL);
+
+ box1 = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), box1);
+ gtk_widget_show (box1);
+
+ scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+ gtk_container_border_width (GTK_CONTAINER (scrolled_window), 10);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+ gtk_box_pack_start (GTK_BOX (box1), scrolled_window, TRUE, TRUE, 0);
+ gtk_widget_show (scrolled_window);
+
+ box2 = gtk_vbox_new (FALSE, 0);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_container_add (GTK_CONTAINER (scrolled_window), box2);
+ gtk_widget_show (box2);
+
+ for (i = 0; i < nbuttons; i++)
+ {
+ button = gtk_button_new_with_label (buttons[i].label);
+ if (buttons[i].func)
+ gtk_signal_connect (GTK_OBJECT (button),
+ "clicked",
+ (GtkSignalFunc)
+ buttons[i].func, NULL);
+ else
+ gtk_widget_set_sensitive (button, FALSE);
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+ }
+
+ separator = gtk_hseparator_new ();
+ gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
+ gtk_widget_show (separator);
+
+ box2 = gtk_vbox_new (FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (box2), 10);
+ gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
+ gtk_widget_show (box2);
+
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) do_exit, NULL);
+ gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+
+ gtk_widget_show (window);
+}
+
+int
+main (int argc, char *argv[])
+{
+ gtk_set_locale ();
+
+ gtk_init (&argc, &argv);
+ gtk_rc_parse ("testgtkrc");
+
+ create_main_window ();
+
+ gtk_main ();
+
+ return 0;
+}
diff --git a/tests/testgtkrc b/tests/testgtkrc
new file mode 100644
index 000000000..e909e314b
--- /dev/null
+++ b/tests/testgtkrc
@@ -0,0 +1,69 @@
+# pixmap_path "<dir 1>:<dir 2>:<dir 3>:..."
+#
+# style <name> [= <name>]
+# {
+# <option>
+# }
+#
+# widget <widget_set> style <style_name>
+# widget_class <widget_class_set> style <style_name>
+
+pixmap_path "."
+
+style "window"
+{
+# bg_pixmap[NORMAL] = "warning.xpm"
+}
+
+style "scale"
+{
+ fg[NORMAL] = { 1.0, 0, 0 }
+ bg_pixmap[NORMAL] = "<parent>"
+}
+
+style "button"
+{
+ fg[PRELIGHT] = { 1.0, 1.0, 1.0 }
+ bg[PRELIGHT] = { 0, 0, 0.75 }
+}
+
+style "main_button" = "button"
+{
+ font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*"
+ bg[PRELIGHT] = { 0.75, 0, 0 }
+}
+
+style "toggle_button" = "button"
+{
+ fg[NORMAL] = { 1.0, 0, 0 }
+ fg[ACTIVE] = { 1.0, 0, 0 }
+ bg_pixmap[NORMAL] = "<parent>"
+}
+
+style "text"
+{
+ bg_pixmap[NORMAL] = "marble.xpm"
+ fg[NORMAL] = { 1.0, 1.0, 1.0 }
+}
+
+style "ruler"
+{
+ font = "-adobe-helvetica-medium-r-normal--*-80-*-*-*-*-*-*"
+}
+
+style "curve"
+{
+ fg[NORMAL] = { 58000, 0, 0 } # red
+}
+
+widget_class "GtkWindow" style "window"
+widget_class "GtkDialog" style "window"
+widget_class "GtkFileSelection" style "window"
+widget_class "*Gtk*Scale" style "scale"
+widget_class "*GtkCheckButton*" style "toggle_button"
+widget_class "*GtkRadioButton*" style "toggle_button"
+widget_class "*GtkButton*" style "button"
+widget_class "*Ruler" style "ruler"
+widget_class "*GtkText" style "text"
+widget "main window.*GtkButton*" style "main_button"
+widget "*GtkCurve" style "curve"
diff --git a/tests/testinput.c b/tests/testinput.c
new file mode 100644
index 000000000..1c6dae0e1
--- /dev/null
+++ b/tests/testinput.c
@@ -0,0 +1,379 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "gtk.h"
+
+/* Backing pixmap for drawing area */
+
+static GdkPixmap *pixmap = NULL;
+
+/* Information about cursor */
+
+static gint need_cursor = FALSE;
+static gint cursor_proximity = TRUE;
+static gdouble cursor_x;
+static gdouble cursor_y;
+
+/* Unique ID of current device */
+static guint32 current_device = GDK_CORE_POINTER;
+
+/* Check to see if we need to draw a cursor for current device */
+static void
+check_cursor ()
+{
+ GList *tmp_list;
+
+ /* gdk_input_list_devices returns an internal list, so we shouldn't
+ free it afterwards */
+ tmp_list = gdk_input_list_devices();
+
+ while (tmp_list)
+ {
+ GdkDeviceInfo *info = (GdkDeviceInfo *)tmp_list->data;
+
+ if (info->deviceid == current_device)
+ {
+ need_cursor = !info->has_cursor;
+ break;
+ }
+
+ tmp_list = tmp_list->next;
+ }
+}
+
+/* Erase the old cursor, and/or draw a new one, if necessary */
+static void
+update_cursor (GtkWidget *widget, gdouble x, gdouble y)
+{
+ static gint cursor_present = 0;
+ gint state = need_cursor && cursor_proximity;
+
+ if (pixmap != NULL)
+ {
+ if (cursor_present && (cursor_present != state ||
+ x != cursor_x || y != cursor_y))
+ {
+ gdk_draw_pixmap(widget->window,
+ widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ pixmap,
+ cursor_x - 5, cursor_y - 5,
+ cursor_x - 5, cursor_y - 5,
+ 10, 10);
+ }
+
+ cursor_present = state;
+ cursor_x = x;
+ cursor_y = y;
+
+ if (cursor_present)
+ {
+ gdk_draw_rectangle (widget->window,
+ widget->style->black_gc,
+ TRUE,
+ cursor_x - 5, cursor_y -5,
+ 10, 10);
+ }
+ }
+}
+
+/* Create a new backing pixmap of the appropriate size */
+static gint
+configure_event (GtkWidget *widget, GdkEventConfigure *event)
+{
+ if (pixmap)
+ {
+ gdk_pixmap_destroy(pixmap);
+ }
+ pixmap = gdk_pixmap_new(widget->window,
+ widget->allocation.width,
+ widget->allocation.height,
+ -1);
+ gdk_draw_rectangle (pixmap,
+ widget->style->white_gc,
+ TRUE,
+ 0, 0,
+ widget->allocation.width,
+ widget->allocation.height);
+
+ return TRUE;
+}
+
+/* Refill the screen from the backing pixmap */
+static gint
+expose_event (GtkWidget *widget, GdkEventExpose *event)
+{
+ gdk_draw_pixmap(widget->window,
+ widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ pixmap,
+ event->area.x, event->area.y,
+ event->area.x, event->area.y,
+ event->area.width, event->area.height);
+
+ return FALSE;
+}
+
+/* Draw a rectangle on the screen, size depending on pressure,
+ and color on the type of device */
+static void
+draw_brush (GtkWidget *widget, GdkInputSource source,
+ gdouble x, gdouble y, gdouble pressure)
+{
+ GdkGC *gc;
+ GdkRectangle update_rect;
+
+ switch (source)
+ {
+ case GDK_SOURCE_MOUSE:
+ gc = widget->style->dark_gc[GTK_WIDGET_STATE (widget)];
+ break;
+ case GDK_SOURCE_PEN:
+ gc = widget->style->black_gc;
+ break;
+ case GDK_SOURCE_ERASER:
+ gc = widget->style->white_gc;
+ break;
+ default:
+ gc = widget->style->light_gc[GTK_WIDGET_STATE (widget)];
+ }
+
+ update_rect.x = x - 10 * pressure;
+ update_rect.y = y - 10 * pressure;
+ update_rect.width = 20 * pressure;
+ update_rect.height = 20 * pressure;
+ gdk_draw_rectangle (pixmap, gc, TRUE,
+ update_rect.x, update_rect.y,
+ update_rect.width, update_rect.height);
+ gtk_widget_draw (widget, &update_rect);
+}
+
+static guint32 motion_time;
+
+static gint
+button_press_event (GtkWidget *widget, GdkEventButton *event)
+{
+ if (event->deviceid != current_device)
+ {
+ current_device = event->deviceid;
+ check_cursor ();
+ }
+
+ cursor_proximity = TRUE;
+
+ if (event->button == 1 && pixmap != NULL)
+ {
+ draw_brush (widget, event->source, event->x, event->y,
+ event->pressure);
+ motion_time = event->time;
+ }
+
+ update_cursor (widget, event->x, event->y);
+
+ return TRUE;
+}
+
+static gint
+motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
+{
+ GdkTimeCoord *coords;
+ int nevents;
+ int i;
+
+ if (event->deviceid != current_device)
+ {
+ current_device = event->deviceid;
+ check_cursor ();
+ }
+
+ cursor_proximity = TRUE;
+
+ if (event->state & GDK_BUTTON1_MASK && pixmap != NULL)
+ {
+ coords = gdk_input_motion_events (event->window, event->deviceid,
+ motion_time, event->time,
+ &nevents);
+ motion_time = event->time;
+ if (coords)
+ {
+ for (i=0; i<nevents; i++)
+ draw_brush (widget, event->source, coords[i].x, coords[i].y,
+ coords[i].pressure);
+ g_free (coords);
+ }
+ else
+ {
+ if (event->is_hint)
+ gdk_input_window_get_pointer (event->window, event->deviceid,
+ NULL, NULL, NULL, NULL, NULL, NULL);
+ draw_brush (widget, event->source, event->x, event->y,
+ event->pressure);
+ }
+ }
+ else
+ {
+ gdk_input_window_get_pointer (event->window, event->deviceid,
+ &event->x, &event->y,
+ NULL, NULL, NULL, NULL);
+ }
+
+ update_cursor (widget, event->x, event->y);
+
+ return TRUE;
+}
+
+/* We track the next two events to know when we need to draw a
+ cursor */
+
+static gint
+proximity_out_event (GtkWidget *widget, GdkEventProximity *event)
+{
+ cursor_proximity = FALSE;
+ update_cursor (widget, cursor_x, cursor_y);
+ return TRUE;
+}
+
+static gint
+leave_notify_event (GtkWidget *widget, GdkEventCrossing *event)
+{
+ cursor_proximity = FALSE;
+ update_cursor (widget, cursor_x, cursor_y);
+ return TRUE;
+}
+
+void
+input_dialog_destroy (GtkWidget *w, gpointer data)
+{
+ *((GtkWidget **)data) = NULL;
+}
+
+void
+create_input_dialog ()
+{
+ static GtkWidget *inputd = NULL;
+
+ if (!inputd)
+ {
+ inputd = gtk_input_dialog_new();
+
+ gtk_signal_connect (GTK_OBJECT(inputd), "destroy",
+ (GtkSignalFunc)input_dialog_destroy, &inputd);
+ gtk_signal_connect_object (GTK_OBJECT(GTK_INPUT_DIALOG(inputd)->close_button),
+ "clicked",
+ (GtkSignalFunc)gtk_widget_hide,
+ GTK_OBJECT(inputd));
+ gtk_widget_hide ( GTK_INPUT_DIALOG(inputd)->save_button);
+
+ gtk_signal_connect (GTK_OBJECT(inputd), "enable_device",
+ (GtkSignalFunc)check_cursor, NULL);
+ gtk_widget_show (inputd);
+ }
+ else
+ {
+ if (!GTK_WIDGET_MAPPED(inputd))
+ gtk_widget_show(inputd);
+ else
+ gdk_window_raise(inputd->window);
+ }
+}
+
+void
+quit ()
+{
+ gtk_exit (0);
+}
+
+int
+main (int argc, char *argv[])
+{
+ GtkWidget *window;
+ GtkWidget *drawing_area;
+ GtkWidget *vbox;
+
+ GtkWidget *button;
+
+ gtk_init (&argc, &argv);
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_widget_set_name (window, "Test Input");
+
+ vbox = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), vbox);
+ gtk_widget_show (vbox);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ GTK_SIGNAL_FUNC (quit), NULL);
+
+ /* Create the drawing area */
+
+ drawing_area = gtk_drawing_area_new ();
+ gtk_drawing_area_size (GTK_DRAWING_AREA (drawing_area), 200, 200);
+ gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
+
+ gtk_widget_show (drawing_area);
+
+ /* Signals used to handle backing pixmap */
+
+ gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
+ (GtkSignalFunc) expose_event, NULL);
+ gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
+ (GtkSignalFunc) configure_event, NULL);
+
+ /* Event signals */
+
+ gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
+ (GtkSignalFunc) motion_notify_event, NULL);
+ gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
+ (GtkSignalFunc) button_press_event, NULL);
+
+ gtk_signal_connect (GTK_OBJECT (drawing_area), "leave_notify_event",
+ (GtkSignalFunc) leave_notify_event, NULL);
+ gtk_signal_connect (GTK_OBJECT (drawing_area), "proximity_out_event",
+ (GtkSignalFunc) proximity_out_event, NULL);
+
+ gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
+ | GDK_LEAVE_NOTIFY_MASK
+ | GDK_BUTTON_PRESS_MASK
+ | GDK_POINTER_MOTION_MASK
+ | GDK_POINTER_MOTION_HINT_MASK
+ | GDK_PROXIMITY_OUT_MASK);
+
+ /* The following call enables tracking and processing of extension
+ events for the drawing area */
+ gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_ALL);
+
+ /* .. And create some buttons */
+ button = gtk_button_new_with_label ("Input Dialog");
+ gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ GTK_SIGNAL_FUNC (create_input_dialog), NULL);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("Quit");
+ gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ GTK_SIGNAL_FUNC (gtk_widget_destroy),
+ GTK_OBJECT (window));
+ gtk_widget_show (button);
+
+ gtk_widget_show (window);
+
+ gtk_main ();
+
+ return 0;
+}
diff --git a/tests/testselection.c b/tests/testselection.c
new file mode 100644
index 000000000..3377cc623
--- /dev/null
+++ b/tests/testselection.c
@@ -0,0 +1,466 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "gtk.h"
+
+typedef enum {
+ SEL_TYPE_NONE,
+ APPLE_PICT,
+ ATOM,
+ ATOM_PAIR,
+ BITMAP,
+ C_STRING,
+ COLORMAP,
+ COMPOUND_TEXT,
+ DRAWABLE,
+ INTEGER,
+ PIXEL,
+ PIXMAP,
+ SPAN,
+ STRING,
+ TEXT,
+ WINDOW,
+ LAST_SEL_TYPE,
+} SelType;
+
+GdkAtom seltypes[LAST_SEL_TYPE];
+
+typedef struct _Target {
+ gchar *target_name;
+ SelType type;
+ GdkAtom target;
+ gint format;
+ GtkSelectionFunction *handler;
+} Target;
+
+/* The following is a list of all the selection targets defined
+ in the ICCCM */
+
+static Target targets[] = {
+ { "ADOBE_PORTABLE_DOCUMENT_FORMAT", STRING, 0, 8, NULL },
+ { "APPLE_PICT", APPLE_PICT, 0, 8, NULL },
+ { "BACKGROUND", PIXEL, 0, 32, NULL },
+ { "BITMAP", BITMAP, 0, 32, NULL },
+ { "CHARACTER_POSITION", SPAN, 0, 32, NULL },
+ { "CLASS", TEXT, 0, 8, NULL },
+ { "CLIENT_WINDOW", WINDOW, 0, 32, NULL },
+ { "COLORMAP", COLORMAP, 0, 32, NULL },
+ { "COLUMN_NUMBER", SPAN, 0, 32, NULL },
+ { "COMPOUND_TEXT", COMPOUND_TEXT, 0, 8, NULL },
+ /* { "DELETE", "NULL", 0, ?, NULL }, */
+ { "DRAWABLE", DRAWABLE, 0, 32, NULL },
+ { "ENCAPSULATED_POSTSCRIPT", STRING, 0, 8, NULL },
+ { "ENCAPSULATED_POSTSCRIPT_INTERCHANGE", STRING, 0, 8, NULL },
+ { "FILE_NAME", TEXT, 0, 8, NULL },
+ { "FOREGROUND", PIXEL, 0, 32, NULL },
+ { "HOST_NAME", TEXT, 0, 8, NULL },
+ /* { "INSERT_PROPERTY", "NULL", 0, ? NULL }, */
+ /* { "INSERT_SELECTION", "NULL", 0, ? NULL }, */
+ { "LENGTH", INTEGER, 0, 32, NULL },
+ { "LINE_NUMBER", SPAN, 0, 32, NULL },
+ { "LIST_LENGTH", INTEGER, 0, 32, NULL },
+ { "MODULE", TEXT, 0, 8, NULL },
+ /* { "MULTIPLE", "ATOM_PAIR", 0, 32, NULL }, */
+ { "NAME", TEXT, 0, 8, NULL },
+ { "ODIF", TEXT, 0, 8, NULL },
+ { "OWNER_OS", TEXT, 0, 8, NULL },
+ { "PIXMAP", PIXMAP, 0, 32, NULL },
+ { "POSTSCRIPT", STRING, 0, 8, NULL },
+ { "PROCEDURE", TEXT, 0, 8, NULL },
+ { "PROCESS", INTEGER, 0, 32, NULL },
+ { "STRING", STRING, 0, 8, NULL },
+ { "TARGETS", ATOM, 0, 32, NULL },
+ { "TASK", INTEGER, 0, 32, NULL },
+ { "TEXT", TEXT, 0, 8 , NULL },
+ { "TIMESTAMP", INTEGER, 0, 32, NULL },
+ { "USER", TEXT, 0, 8, NULL },
+};
+
+static int num_targets = sizeof(targets)/sizeof(Target);
+
+static int have_selection = FALSE;
+
+GtkWidget *selection_text;
+GtkWidget *selection_button;
+GString *selection_string = NULL;
+
+static void
+init_atoms ()
+{
+ int i;
+
+ seltypes[SEL_TYPE_NONE] = GDK_NONE;
+ seltypes[APPLE_PICT] = gdk_atom_intern ("APPLE_PICT",FALSE);
+ seltypes[ATOM] = gdk_atom_intern ("ATOM",FALSE);
+ seltypes[ATOM_PAIR] = gdk_atom_intern ("ATOM_PAIR",FALSE);
+ seltypes[BITMAP] = gdk_atom_intern ("BITMAP",FALSE);
+ seltypes[C_STRING] = gdk_atom_intern ("C_STRING",FALSE);
+ seltypes[COLORMAP] = gdk_atom_intern ("COLORMAP",FALSE);
+ seltypes[COMPOUND_TEXT] = gdk_atom_intern ("COMPOUND_TEXT",FALSE);
+ seltypes[DRAWABLE] = gdk_atom_intern ("DRAWABLE",FALSE);
+ seltypes[INTEGER] = gdk_atom_intern ("INTEGER",FALSE);
+ seltypes[PIXEL] = gdk_atom_intern ("PIXEL",FALSE);
+ seltypes[PIXMAP] = gdk_atom_intern ("PIXMAP",FALSE);
+ seltypes[SPAN] = gdk_atom_intern ("SPAN",FALSE);
+ seltypes[STRING] = gdk_atom_intern ("STRING",FALSE);
+ seltypes[TEXT] = gdk_atom_intern ("TEXT",FALSE);
+ seltypes[WINDOW] = gdk_atom_intern ("WINDOW",FALSE);
+
+ for (i=0; i<num_targets; i++)
+ targets[i].target = gdk_atom_intern (targets[i].target_name, FALSE);
+}
+
+void
+selection_toggled (GtkWidget *widget)
+{
+ if (GTK_TOGGLE_BUTTON(widget)->active)
+ {
+ have_selection = gtk_selection_owner_set (widget,
+ GDK_SELECTION_PRIMARY,
+ GDK_CURRENT_TIME);
+ if (!have_selection)
+ gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON(widget), FALSE);
+ }
+ else
+ {
+ if (have_selection)
+ {
+ if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window)
+ gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY,
+ GDK_CURRENT_TIME);
+ have_selection = FALSE;
+ }
+ }
+}
+
+void
+selection_handle (GtkWidget *widget,
+ GtkSelectionData *selection_data, gpointer data)
+{
+ guchar *buffer;
+ gint len;
+
+ if (!selection_string)
+ {
+ buffer = NULL;
+ len = 0;
+ }
+ else
+ {
+ buffer = selection_string->str;
+ len = selection_string->len;
+ }
+
+ gtk_selection_data_set (selection_data,
+ selection_data->target == seltypes[COMPOUND_TEXT] ?
+ seltypes[COMPOUND_TEXT] : seltypes[STRING],
+ 8, buffer, len);
+}
+
+gint
+selection_clear (GtkWidget *widget, GdkEventSelection *event)
+{
+ have_selection = FALSE;
+ gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON(widget), FALSE);
+
+ return TRUE;
+}
+
+gchar *
+stringify_atom (guchar *data, gint *position)
+{
+ gchar *str = gdk_atom_name (*(GdkAtom *)(data+*position));
+ *position += sizeof(GdkAtom);
+
+ return str;
+}
+
+gchar *
+stringify_text (guchar *data, gint *position)
+{
+ gchar *str = g_strdup ((gchar *)(data+*position));
+ *position += strlen (str) + 1;
+
+ return str;
+}
+
+gchar *
+stringify_xid (guchar *data, gint *position)
+{
+ gchar buffer[20];
+ gchar *str;
+
+ sprintf(buffer,"0x%x",*(guint32 *)(data+*position));
+ str = g_strdup (buffer);
+
+ *position += sizeof(guint32);
+
+ return str;
+}
+
+gchar *
+stringify_integer (guchar *data, gint *position)
+{
+ gchar buffer[20];
+ gchar *str;
+
+ sprintf(buffer,"%d",*(int *)(data+*position));
+ str = g_strdup (buffer);
+
+ *position += sizeof(int);
+
+ return str;
+}
+
+gchar *
+stringify_span (guchar *data, gint *position)
+{
+ gchar buffer[42];
+ gchar *str;
+
+ sprintf(buffer,"%d - %d",((int *)(data+*position))[0],
+ ((int *)(data+*position))[1]);
+ str = g_strdup (buffer);
+
+ *position += 2*sizeof(int);
+
+ return str;
+}
+
+void
+selection_received (GtkWidget *widget, GtkSelectionData *data)
+{
+ int position;
+ int i;
+ SelType seltype;
+ char *str;
+
+ if (data->length < 0)
+ {
+ g_print("Error retrieving selection\n");
+ return;
+ }
+
+ seltype = SEL_TYPE_NONE;
+ for (i=0; i<LAST_SEL_TYPE; i++)
+ {
+ if (seltypes[i] == data->type)
+ {
+ seltype = i;
+ break;
+ }
+ }
+
+ if (seltype == SEL_TYPE_NONE)
+ {
+ char *name = gdk_atom_name (data->type);
+ g_print("Don't know how to handle type: %s (%ld)\n",
+ name?name:"<unknown>",
+ data->type);
+ return;
+ }
+
+ if (selection_string != NULL)
+ g_string_free (selection_string, TRUE);
+
+ selection_string = g_string_new (NULL);
+
+ gtk_text_freeze (GTK_TEXT (selection_text));
+ gtk_text_set_point (GTK_TEXT (selection_text), 0);
+ gtk_text_foreward_delete (GTK_TEXT (selection_text),
+ gtk_text_get_length (GTK_TEXT (selection_text)));
+
+ position = 0;
+ while (position < data->length)
+ {
+ switch (seltype)
+ {
+ case ATOM:
+ str = stringify_atom (data->data, &position);
+ break;
+ case COMPOUND_TEXT:
+ case STRING:
+ case TEXT:
+ str = stringify_text (data->data, &position);
+ break;
+ case BITMAP:
+ case DRAWABLE:
+ case PIXMAP:
+ case WINDOW:
+ case COLORMAP:
+ str = stringify_xid (data->data, &position);
+ break;
+ case INTEGER:
+ case PIXEL:
+ str = stringify_integer (data->data, &position);
+ break;
+ case SPAN:
+ str = stringify_span (data->data, &position);
+ break;
+ default:
+ {
+ char *name = gdk_atom_name (data->type);
+ g_print("Can't convert type %s (%ld) to string\n",
+ name?name:"<unknown>",
+ data->type);
+ position = data->length;
+ }
+ }
+ gtk_text_insert (GTK_TEXT (selection_text), NULL,
+ &selection_text->style->black,
+ NULL, str, -1);
+ gtk_text_insert (GTK_TEXT (selection_text), NULL,
+ &selection_text->style->black,
+ NULL, "\n", -1);
+ g_string_append (selection_string, str);
+ g_free (str);
+ }
+ gtk_text_thaw (GTK_TEXT (selection_text));
+}
+
+void
+paste (GtkWidget *widget, GtkWidget *entry)
+{
+ char *name;
+ GdkAtom atom;
+
+ name = gtk_entry_get_text (GTK_ENTRY(entry));
+ atom = gdk_atom_intern (name, FALSE);
+
+ if (atom == GDK_NONE)
+ {
+ g_print("Could not create atom: \"%s\"\n",name);
+ return;
+ }
+
+ gtk_selection_convert (selection_button, GDK_SELECTION_PRIMARY, atom,
+ GDK_CURRENT_TIME);
+}
+
+void
+quit ()
+{
+ gtk_exit (0);
+}
+
+int
+main (int argc, char *argv[])
+{
+ GtkWidget *dialog;
+ GtkWidget *button;
+ GtkWidget *table;
+ GtkWidget *label;
+ GtkWidget *entry;
+ GtkWidget *hscrollbar;
+ GtkWidget *vscrollbar;
+ GtkWidget *hbox;
+
+ gtk_init (&argc, &argv);
+
+ init_atoms();
+
+ dialog = gtk_dialog_new ();
+ gtk_widget_set_name (dialog, "Test Input");
+ gtk_container_border_width (GTK_CONTAINER(dialog), 0);
+
+ gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
+ GTK_SIGNAL_FUNC (quit), NULL);
+
+ table = gtk_table_new (4, 2, FALSE);
+ gtk_container_border_width (GTK_CONTAINER(table), 10);
+
+ gtk_table_set_row_spacing (GTK_TABLE (table), 0, 5);
+ gtk_table_set_row_spacing (GTK_TABLE (table), 1, 2);
+ gtk_table_set_row_spacing (GTK_TABLE (table), 2, 2);
+ gtk_table_set_col_spacing (GTK_TABLE (table), 0, 2);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG(dialog)->vbox),
+ table, TRUE, TRUE, 0);
+ gtk_widget_show (table);
+
+ selection_button = gtk_toggle_button_new_with_label ("Claim Selection");
+ gtk_table_attach (GTK_TABLE (table), selection_button, 0, 2, 0, 1,
+ GTK_EXPAND | GTK_FILL, 0, 0, 0);
+ gtk_widget_show (selection_button);
+
+ gtk_signal_connect (GTK_OBJECT(selection_button), "toggled",
+ GTK_SIGNAL_FUNC (selection_toggled), NULL);
+ gtk_signal_connect (GTK_OBJECT(selection_button), "selection_clear_event",
+ GTK_SIGNAL_FUNC (selection_clear), NULL);
+ gtk_signal_connect (GTK_OBJECT(selection_button), "selection_received",
+ GTK_SIGNAL_FUNC (selection_received), NULL);
+
+ gtk_selection_add_handler (selection_button, GDK_SELECTION_PRIMARY,
+ seltypes[STRING], selection_handle, NULL, NULL);
+
+ gtk_selection_add_handler (selection_button, GDK_SELECTION_PRIMARY,
+ seltypes[TEXT], selection_handle, NULL, NULL);
+
+ gtk_selection_add_handler (selection_button, GDK_SELECTION_PRIMARY,
+ seltypes[COMPOUND_TEXT],
+ selection_handle, NULL, NULL);
+
+ selection_text = gtk_text_new (NULL, NULL);
+ gtk_table_attach_defaults (GTK_TABLE (table), selection_text, 0, 1, 1, 2);
+ gtk_widget_show (selection_text);
+
+ hscrollbar = gtk_hscrollbar_new (GTK_TEXT (selection_text)->hadj);
+ gtk_table_attach (GTK_TABLE (table), hscrollbar, 0, 1, 2, 3,
+ GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
+ gtk_widget_show (hscrollbar);
+
+ vscrollbar = gtk_vscrollbar_new (GTK_TEXT (selection_text)->vadj);
+ gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 1, 2,
+ GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+ gtk_widget_show (vscrollbar);
+
+ hbox = gtk_hbox_new (FALSE, 2);
+ gtk_table_attach (GTK_TABLE (table), hbox, 0, 2, 3, 4,
+ GTK_EXPAND | GTK_FILL, 0, 0, 0);
+ gtk_widget_show (hbox);
+
+ label = gtk_label_new ("Target:");
+ gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, FALSE, 0);
+ gtk_widget_show (label);
+
+ entry = gtk_entry_new ();
+ gtk_box_pack_start (GTK_BOX(hbox), entry, TRUE, TRUE, 0);
+ gtk_widget_show (entry);
+
+ /* .. And create some buttons */
+ button = gtk_button_new_with_label ("Paste");
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG(dialog)->action_area),
+ button, TRUE, TRUE, 0);
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ GTK_SIGNAL_FUNC (paste), entry);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("Quit");
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG(dialog)->action_area),
+ button, TRUE, TRUE, 0);
+
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ GTK_SIGNAL_FUNC (gtk_widget_destroy),
+ GTK_OBJECT (dialog));
+ gtk_widget_show (button);
+
+ gtk_widget_show (dialog);
+
+ gtk_main ();
+
+ return 0;
+}