commit 3d4331ba3b413b608742d0c5b81cd31e0fbd0ddf
Author: Brian C. Lane <bcl@brianlane.com>
Date:   Tue, 11 Jan 2022 07:52:39 -0800
Initial commit: xfreecd v0.7.8
Diffstat:
86 files changed, 11605 insertions(+), 0 deletions(-)
diff --git a/COPYING b/COPYING
@@ -0,0 +1,340 @@
+
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 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.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, 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 software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, 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 show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, 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 redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+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 give any other recipients of the Program a copy of this License
+along with the Program.
+
+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 Program or any portion
+of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+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 Program, 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 Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) 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; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, 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 executable.  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.
+
+If distribution of executable or 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 counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program 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.
+
+  5. 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 Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program 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.
+
+  7. 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 Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program 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 Program.
+
+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.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program 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.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the 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 Program
+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 Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, 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
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), 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 Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  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 program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/HISTORY b/HISTORY
@@ -0,0 +1,64 @@
+0.7.8   Attempt to fix a bug that some people report happens 100% and that
+	happens about 5% for me. sigsegv after retrieving the cddb data. I
+	added some code to make sure displat.plabel was equal to NULL after
+	the progress box is destroyed (this didn't fix it, but cannot hurt)
+	And I removed a write to the progress box just before it is deleted.
+	At the moment this 'appears' to have fixed the problem. Tell me if
+	it hasn't!
+
+0.7.7	Small bugfix. In cddbd.c I had a small string that was a holdover
+	from the old way of ding things. It was catted onto the end of each
+	frame request sent to the server. Depending on the state of memory
+	it may have done nothing, or may have scrambled the request string.
+	It has now been fixed.
+
+0.7.6	Just a few minor bugfixes. I wasn't calculating the length of track
+	1 correctly (because of the change from 1-99 ot 0-98 internally).
+	Fixed a problem with the first original submission to CDDB being
+	revision 2 instead of revision 1.
+	XfreeCD v0.7.6 and later are now certified to submit CD info to
+	the CDDB database. Thanks Steve!
+	Added real cddb submission email address.
+	Added RPM building to the Makefile. Thanks to Vincent Cautaerts
+	for creating the RPM version of 0.7.5 that I based this on.
+
+0.7.5	Massive Changes Again:
+	I removed all the static string storage used for the title
+	and track names and replaced with dynamic storage using the
+	GTK+ GString. Works pretty good.
+	Added support for extended CD information. This was required
+	to meet the standards for being able to submit CD information
+	the the CDDB database. You cannot edit this data in the
+	program, but it is preserved on disk, and can be edited with
+	a text editor if necisary
+	Fixed problems relating to 99 track CDs (NIN-Broken broke
+	things).
+	Added support for the Revision # downloaded from the cddb
+	database. When the CD is sent to the database for an updte
+        the Revision # is incremented by 1
+	Changing the category of a CD now automatically erases the
+	old copy of the data in the old category.
+	Added support for multiple DTITLE, TTITLE, EXTD, EXTT, etc.
+	lines in the cddb support routines.
+
+0.7.4	Added sending CDDB updates to the server via email
+	Fixed a bug where changing categories would leave the entry in the
+	old category directory.
+	Fixed a bug that would display the previous CDs info in the Track
+	window while retrieving new CD data from the server.
+	Fixed a problem with editing. It wasn't initalizing the title or
+	the category, so if these weren't edited it could have ended up
+	in the wrong place.
+	Added support for multiple TITLEx lines in the CDDB file.
+	Fixed a bug when editing CD tracks with > 8 tracks. The clist was
+	popping back to the top after selecting the track to edit. This
+	now works right (I changed the way I update the list).
+
+0.7.3   Added titlebar control using different class names for the different
+	windows.
+
+0.7.2	Added -geometry support
+
+
+0.7	Added CDDB support, rewrote low level controls. Split into 3
+	processes.
diff --git a/Makefile b/Makefile
@@ -0,0 +1,45 @@
+#
+# Makefile for XfreeCD
+# Copyright 1998 by Brian C. Lane
+#
+ifeq ($(strip $(CC)),)
+  CC = gcc
+else
+  CC:=${CC}
+endif
+
+VERSION = 0.7.8
+CFLAGS = -O2 -Wall -pipe `gtk-config --cflags` -DVERSION=\"$(VERSION)\"
+LDFLAGS = `gtk-config --libs`
+
+OBJS = xfreecd.o cd_control.o cddbd.o cddb.o child_sync.o xpm_button.o
+
+all:		xfreecd
+
+xfreecd:	$(OBJS)
+		$(CC) $(OBJS) -o xfreecd $(LDFLAGS)
+
+clean:
+	rm -f *.o *~ xfreecd xfreecd-$(VERSION).tar.gz core
+	rm -rf xfreecd-$(VERSION)
+	rm -f xfreecd-$(VERSION)-1.spec
+	rm -f xfreecd-$(VERSION).lsm
+
+# Build the tarball
+dist:	xfreecd
+#	gpg --detach-sig xfreecd
+	rm -rf xfreecd-$(VERSION)
+	mkdir xfreecd-$(VERSION)
+	mkdir xfreecd-$(VERSION)/bitmaps
+	cp bitmaps/* xfreecd-$(VERSION)/bitmaps
+	cp {Makefile,*.c,*.h,xfreecd,README,HISTORY,COPYING,xfreecd.xpm,xfreecd.gif,xfreecd.wmconfig,xfreecd.spec,xfreecd.lsm,xfreecd.sig} xfreecd-$(VERSION)/
+	tar cvzf xfreecd-$(VERSION).tar.gz xfreecd-$(VERSION)/*
+	ln -s xfreecd.lsm xfreecd-$(VERSION).lsm
+
+# Build RedHat binary and source RPMs
+rpm:	dist
+	cp xfreecd-$(VERSION).tar.gz /usr/src/redhat/SOURCES
+	cp xfreecd.gif /usr/src/redhat/SOURCES
+	rm -f xfreecd-$(VERSION)-1.spec
+	ln -s xfreecd.spec xfreecd-$(VERSION)-1.spec
+	rpm -ba -vv xfreecd-$(VERSION)-1.spec
diff --git a/README b/README
@@ -0,0 +1,225 @@
+
+  XfreeCD v0.7.8 (c) 1998 by Brian C. Lane	   http://www.tatoosh.com/nexus
+===============================================================================
+
+
+  Hello!
+
+  Thanks for trying out XfreeCD. The first thing is that you need to have a
+copy of GTK+ v1.0.2 or later installed. This is the Gimp Toolkit, so if you
+have a recent version of Gimp installed you are ready to compile XfreeCD by
+typing make. If you don't have GTK+ then you need to download and install it.
+It is available from http://www.gimp.org/gtk/ and the install is pretty easy.
+Sorry about this (I know I hate having to install other stuff just to run
+a program), but GTK+ is well worth it (as is Gimp) -- you will be seeing
+many more programs using GTK+ in the future.
+
+  Ok, so if you have GTK+ installed you can type make in the xfreecd directory
+to build xfreecd. Then copy the xfreecd binary it to your favorite location and
+run it. The standard place is in /usr/local/bin
+
+  The program initially uses /dev/cdrom to access the CD device. This can be
+changed in the setup dialog box (click on the question mark). It does not
+work with SCSI devices yet, but that's on ly list of things to find other
+people to do <G>.
+
+  You also have to make sure you have read permission for the CD device. You
+can do this by executing chmod ugo+r /dev/sbpcd (or whatever your device
+is). Make sure you change the device itself, not a symlink like /dev/cdrom
+since that won't work.
+
+  Please read over the rest of this document!
+
+
+
+
+  What is xfreecd?
+  ----------------
+
+  XfreeCD is a X windows program that looks like the frontpanel of a cd
+player. I stole the images from the win95 freeCD program. My thanks to Nate
+Smith for making his code freely available.
+
+  You can play CDs, move between tracks, adjust volume -- clicking the left
+button on the speaker icon increases the volume. Clicking the right button
+will decrease the volume. You can display 4 different times on the display:
+
+  1. Time elapsed on the track (icon has a plus and a 1/4 cdrom on it)
+  2. Time remaining on the track (icon has a minus and 1/4 cdrom on it)
+  3. Time elapsed on cdrom (icon has a plus and a full cdrom)
+  4. Time remaining on cdrom (icon has a minus and a full cdrom)
+
+  The repeat key causes the cdrom to keep playing when it reaches the end of
+the cdrom. The question mark key opens a setup dialog box with 3 tabs for
+the different setup screens. The 'Setup' tab allows you to set the CD device
+to use and 3 other buttons:
+
+  1. AutoPlay            When this is selected XfreeCD will start playing
+                         the CD if there is one in the drive. If a CD is
+                         already playing it doesn't disturb it.
+
+  2. Eject when done     When selected this will eject the CD when it is done
+                         playing it if the repeat button on the front panel
+                         is not selected.
+
+  4. Eject on exit       When this is selected and you exit XfreeCD with
+                         the CD stopped or paused it will eject the CD.
+
+
+  A new feature for this version is support for the internet CD database CDDB
+created by Ti Kan and Steve Scherf (Thanks Guys!). Select the CDDB tab from
+the setup menu to setup this option. The Local CDDB path is where it will
+store the CD info when it is downloaded from the internet or entered locally.
+A number of directories are created under this directory for the different
+categories of CDs (this is handles automatically, you don't need to create
+any directories yourself, just make sure you have the right permissions for
+the location you select).
+
+  The CDDB server is the internet site that you want to use to retrieve CD
+track names from. This should probably be geographicly near you for the
+best performance. Initially only cddb.cddb.com is selected. A list of the
+current sites can be downloaded by pressing the Refresh Servers button.
+
+  The CDDB Submit email address is the email address of the CDDB server to
+submit new CDs to. The default is xmcd-cddb@amb.org and the test address
+is test-cddb@cddb.cddb.com -- The test address will tell you if the submission
+would have been accepted or not. You can submit CD info from the Track Edit
+window by pressing the 'Send to Server' button. This uses the 'cat' and 'mail'
+programs, and they should be in your current PATH for it to work.
+
+  As of version 0.7.6 XfreeCD submissions to the cddb database are accepted!
+Now you can add that obscure CD of yours to the worldwide database.
+
+  If the CDDB support button is selected XfreeCD will first search the local
+database (it does this even if CDDB is not selected) for the current CD's
+unique discid. If that fails then it will attempt to connect to the CDDB
+server that you have selected and download the CD info. It will then store
+that data locally. CDDB submission is available even when CDDB download
+support is turned off.
+
+  To use the CDDB download feature you will need to have your internet
+connection online or be using a program like diald to automatically connect
+to the internet.
+
+  The track names are displayed by doing a left click in the main display
+window (the one showing the time and track #). Doing a right click in
+this window allows you to drag the XfreeCD window anywhere on your desktop.
+
+
+  At the bottom of the track list window is a button labeled 'edit tracks'
+Click on it and another window similar to the first will be opened. Here
+you can edit the track names and save the changes to the local database.
+You don't need to have the internet CDDB support enabled.
+  
+
+  Version 0.7 is a complete rewrite of the code. The old code didn't run
+as well as I liked, the user interface was sometimes slow because it was
+waiting for a response from the low-level CD routines which can sometimes
+take a noticeable amount of time. And I wanted to add CDDB support without
+the 'freezing' of alot of X programs.
+
+  Some people requested track seeking (skipping forward a few seconds
+within the track). I tried to implement this, but it seems that the
+low level CD device drivers don't implement this function very well and
+I removed the option (It would crash often and leave the cd_control
+process with no way to kill it since it was frozen waiting for a kernel
+call to finish). I have tested other players and none of them implement
+this feature any better. If you want to add it yourself and can get it
+to work, I'd be happy to integrate it into the next release of XfreeCD.
+
+  If you do a 'ps' while running xfreecd you will notice 3 processes
+running. This is perfectly normal. One process handles the GTK+ user
+interface, another handles the low-level CD control and the third is the
+cddb internet interface.
+
+  In version 0.7.5 I have reduced the amount of static memory storage used
+for strings, so you should notice a slightly smaller memory foorprint. On
+my system a 'ps xm | grep xfreecd' shows:
+
+
+v0.7.4
+  PID TTY MAJFLT MINFLT   TRS   DRS  SIZE  SWAP   RSS  SHRD   LIB  DT COMMAND
+ 3183  p3      0      3    44   532   576     0   576   552     0  50 xfreecd 
+ 3182  p3     14      7    48   588   636     0   636   592     0  52 xfreecd 
+ 3181  p3    389    198    76  1500  1576     0  1576  1184     0 119 xfreecd 
+
+v0.7.5
+  PID TTY MAJFLT MINFLT   TRS   DRS  SIZE  SWAP   RSS  SHRD   LIB  DT COMMAND
+ 3189  p3      0      3    40   500   540     0   540   516     0  43 ./xfreecd
+ 3188  p3     14      5    48   532   580     0   580   556     0  43 ./xfreecd
+ 3187  p3    408    169    80  1404  1484     0  1484  1184     0  96 ./xfreecd
+
+
+  Not a huge difference, but an improvement.
+
+
+  -geometry
+  ---------
+
+  XfreeCD now recognizes the -geometry command for x/y placement on the
+screen. Use the standard X geometry placement parameters. Width and Height
+are ignored. I use 'xfreecd -geometry +580-80' to place it at the end of my
+AfterStep Wharf bar.
+
+  The only small glitch with this is if you have titlebars on and use geometry
+the placement will be relative to the main XfreeCD window, without respect to
+the size of the titlebars.
+
+  Title Bars
+  ----------
+
+  If you want to modify the way the XfreeCD windows look (I like the main
+window to have no title bar and no resize bars) you can tell your window
+manager to remove them. This depends on what manager you are running. There
+are 5 types of windows associated with XfreeCD, but usually you will only be
+concerned with the main window.
+
+  XfreeCD is the main window.
+  XfreeCDt is the Track List window.
+  XfreeCDet is the Edit Track list window.
+  XfreeCDp is the progress window while connecting to the internet CDDB server.
+  XfreeCDs is the setup window.
+
+  I run AfterStep, and to setup the main window without title bar or resize
+handles you add a line like this to the database file:
+
+  Style   "XfreeCD"       NoTitle, NoHandles
+
+
+SCSI Support:
+
+  I don't have a SCSI CD drive, so it would be difficult for me to test
+any code I wrote. But it is possible for someone to modify the cd_control
+module to support SCSI drives, preferably through a user selectable
+button in the setup menu, not via compile time (I'm trying to make it
+easy to distribute this as a binary for those who don't have gcc
+installed on their system).
+
+  This is beta software and it may have memory leaks and other problems.
+Please report any problems or ideas to me for inclusion in future versions.
+
+  Brian Lane
+  Nexus Computing
+  nexus@tatoosh.com
+  http://www.tatoosh.com/nexus
+
+
+Hall of Thanks
+--------------
+
+I would like to thank all of the beta testers for their help, bug reports,
+and suggestions. If I have forgotten anyone, please let me know and I'll add
+you to the list.
+
+Vincent Cautaerts (vincent@comf5.comm.eng.osaka-u.ac.jp) did the
+RPM package for RedHat users for v0.7.5 (I have taken over the rpm
+generation as of v0.7.6, so send any errors to me).
+
+The guys at www.cddb.com for their strict requirements for submission to
+the database. They revealed several bug that have now been squashed.
+
+Users of v0.7.6 for reporting the error 500 problem and forcing me to
+look over the code once again. I found the bug and squashed it!
+
+Users of v0.7.7 who kept insisting that it was sigsegving after a cddb
+retrieval. I believed you! Really!
diff --git a/bitmaps/a0.xpm b/bitmaps/a0.xpm
@@ -0,0 +1,28 @@
+/* XPM */
+static char * a0_xpm[] = {
+"11 22 3 1",
+" 	c #000000000000",
+".	c #861782078617",
+"X	c #FFFFFFFFFFFF",
+" .XXXXXXX. ",
+". .XXXXX. .",
+"X.       .X",
+"XX       XX",
+"XX       XX",
+"XX       XX",
+"XX       XX",
+"XX       XX",
+"XX       XX",
+"X.       .X",
+".         .",
+".         .",
+"X.       .X",
+"XX       XX",
+"XX       XX",
+"XX       XX",
+"XX       XX",
+"XX       XX",
+"XX       XX",
+"X.       .X",
+". .XXXXX. .",
+" .XXXXXXX. "};
diff --git a/bitmaps/a1.xpm b/bitmaps/a1.xpm
@@ -0,0 +1,28 @@
+/* XPM */
+static char * a1_xpm[] = {
+"11 22 3 1",
+" 	c #000000000000",
+".	c #861782078617",
+"X	c #FFFFFFFFFFFF",
+"           ",
+"          .",
+"         .X",
+"         XX",
+"         XX",
+"         XX",
+"         XX",
+"         XX",
+"         XX",
+"         .X",
+"          .",
+"          .",
+"         .X",
+"         XX",
+"         XX",
+"         XX",
+"         XX",
+"         XX",
+"         XX",
+"         .X",
+"          .",
+"           "};
diff --git a/bitmaps/a2.xpm b/bitmaps/a2.xpm
@@ -0,0 +1,28 @@
+/* XPM */
+static char * a2_xpm[] = {
+"11 22 3 1",
+" 	c #000000000000",
+".	c #861782078617",
+"X	c #FFFFFFFFFFFF",
+" .XXXXXXX. ",
+"  .XXXXX. .",
+"         .X",
+"         XX",
+"         XX",
+"         XX",
+"         XX",
+"         XX",
+"         XX",
+"         .X",
+"  .XXXXX. .",
+". .XXXXX.  ",
+"X.         ",
+"XX         ",
+"XX         ",
+"XX         ",
+"XX         ",
+"XX         ",
+"XX         ",
+"X.         ",
+". .XXXXX.  ",
+" .XXXXXXX. "};
diff --git a/bitmaps/a3.xpm b/bitmaps/a3.xpm
@@ -0,0 +1,28 @@
+/* XPM */
+static char * a3_xpm[] = {
+"11 22 3 1",
+" 	c #000000000000",
+".	c #861782078617",
+"X	c #FFFFFFFFFFFF",
+" .XXXXXXX. ",
+"  .XXXXX. .",
+"         .X",
+"         XX",
+"         XX",
+"         XX",
+"         XX",
+"         XX",
+"         XX",
+"         .X",
+"  .XXXXX. .",
+"  .XXXXX. .",
+"         .X",
+"         XX",
+"         XX",
+"         XX",
+"         XX",
+"         XX",
+"         XX",
+"         .X",
+"  .XXXXX. .",
+" .XXXXXXX. "};
diff --git a/bitmaps/a4.xpm b/bitmaps/a4.xpm
@@ -0,0 +1,28 @@
+/* XPM */
+static char * a4_xpm[] = {
+"11 22 3 1",
+" 	c #000000000000",
+".	c #861782078617",
+"X	c #FFFFFFFFFFFF",
+"           ",
+".         .",
+"X.       .X",
+"XX       XX",
+"XX       XX",
+"XX       XX",
+"XX       XX",
+"XX       XX",
+"XX       XX",
+"X.       .X",
+". .XXXXX. .",
+"  .XXXXX. .",
+"         .X",
+"         XX",
+"         XX",
+"         XX",
+"         XX",
+"         XX",
+"         XX",
+"         .X",
+"          .",
+"           "};
diff --git a/bitmaps/a5.xpm b/bitmaps/a5.xpm
@@ -0,0 +1,28 @@
+/* XPM */
+static char * a5_xpm[] = {
+"11 22 3 1",
+" 	c #000000000000",
+".	c #861782078617",
+"X	c #FFFFFFFFFFFF",
+" .XXXXXXX. ",
+". .XXXXX.  ",
+"X.         ",
+"XX         ",
+"XX         ",
+"XX         ",
+"XX         ",
+"XX         ",
+"XX         ",
+"X.         ",
+". .XXXXX.  ",
+"  .XXXXX. .",
+"         .X",
+"         XX",
+"         XX",
+"         XX",
+"         XX",
+"         XX",
+"         XX",
+"         .X",
+"  .XXXXX. .",
+" .XXXXXXX. "};
diff --git a/bitmaps/a6.xpm b/bitmaps/a6.xpm
@@ -0,0 +1,28 @@
+/* XPM */
+static char * a6_xpm[] = {
+"11 22 3 1",
+" 	c #000000000000",
+".	c #861782078617",
+"X	c #FFFFFFFFFFFF",
+" .XXXXXXX. ",
+". .XXXXX.  ",
+"X.         ",
+"XX         ",
+"XX         ",
+"XX         ",
+"XX         ",
+"XX         ",
+"XX         ",
+"X.         ",
+". .XXXXX.  ",
+". .XXXXX. .",
+"X.       .X",
+"XX       XX",
+"XX       XX",
+"XX       XX",
+"XX       XX",
+"XX       XX",
+"XX       XX",
+"X.       .X",
+". .XXXXX. .",
+" .XXXXXXX. "};
diff --git a/bitmaps/a7.xpm b/bitmaps/a7.xpm
@@ -0,0 +1,28 @@
+/* XPM */
+static char * a7_xpm[] = {
+"11 22 3 1",
+" 	c #000000000000",
+".	c #861782078617",
+"X	c #FFFFFFFFFFFF",
+" .XXXXXXX. ",
+"  .XXXXX. .",
+"         .X",
+"         XX",
+"         XX",
+"         XX",
+"         XX",
+"         XX",
+"         XX",
+"         .X",
+"          .",
+"          .",
+"         .X",
+"         XX",
+"         XX",
+"         XX",
+"         XX",
+"         XX",
+"         XX",
+"         .X",
+"          .",
+"           "};
diff --git a/bitmaps/a8.xpm b/bitmaps/a8.xpm
@@ -0,0 +1,28 @@
+/* XPM */
+static char * a8_xpm[] = {
+"11 22 3 1",
+" 	c #000000000000",
+".	c #861782078617",
+"X	c #FFFFFFFFFFFF",
+" .XXXXXXX. ",
+". .XXXXX. .",
+"X.       .X",
+"XX       XX",
+"XX       XX",
+"XX       XX",
+"XX       XX",
+"XX       XX",
+"XX       XX",
+"X.       .X",
+". .XXXXX. .",
+". .XXXXX. .",
+"X.       .X",
+"XX       XX",
+"XX       XX",
+"XX       XX",
+"XX       XX",
+"XX       XX",
+"XX       XX",
+"X.       .X",
+". .XXXXX. .",
+" .XXXXXXX. "};
diff --git a/bitmaps/a9.xpm b/bitmaps/a9.xpm
@@ -0,0 +1,28 @@
+/* XPM */
+static char * a9_xpm[] = {
+"11 22 3 1",
+" 	c #000000000000",
+".	c #861782078617",
+"X	c #FFFFFFFFFFFF",
+" .XXXXXXX. ",
+". .XXXXX. .",
+"X.       .X",
+"XX       XX",
+"XX       XX",
+"XX       XX",
+"XX       XX",
+"XX       XX",
+"XX       XX",
+"X.       .X",
+". .XXXXX. .",
+"  .XXXXX. .",
+"         .X",
+"         XX",
+"         XX",
+"         XX",
+"         XX",
+"         XX",
+"         XX",
+"         .X",
+"  .XXXXX. .",
+" .XXXXXXX. "};
diff --git a/bitmaps/an.xpm b/bitmaps/an.xpm
@@ -0,0 +1,26 @@
+/* XPM */
+static char * an_xpm[] = {
+"11 22 1 1",
+" 	c #000000000000",
+"           ",
+"           ",
+"           ",
+"           ",
+"           ",
+"           ",
+"           ",
+"           ",
+"           ",
+"           ",
+"           ",
+"           ",
+"           ",
+"           ",
+"           ",
+"           ",
+"           ",
+"           ",
+"           ",
+"           ",
+"           ",
+"           "};
diff --git a/bitmaps/b0.xpm b/bitmaps/b0.xpm
@@ -0,0 +1,35 @@
+/* XPM */
+static char * b0_xpm[] = {
+"8 16 16 1",
+" 	c #30C230C230C2",
+".	c #DF7DDF7DDF7D",
+"X	c #FFFFFFFFFFFF",
+"o	c #EFBEEFBEEFBE",
+"O	c #B6DAAEBAB6DA",
+"+	c #000000000000",
+"@	c #79E775D679E7",
+"#	c #492441034924",
+"$	c #A6999E79A699",
+"%	c #965896589658",
+"&	c #38E338E338E3",
+"*	c #410341034103",
+"=	c #104008200820",
+"-	c #208118612081",
+";	c #514451445144",
+":	c #F7DEF7DEF7DE",
+" .XXXoO+",
+"@#$%$% O",
+"o&++++%X",
+"X&++++$X",
+"X*++++$X",
+"X*++++$X",
+"o&++++%X",
+"@=++++-O",
+";++++++@",
+". ++++@X",
+"X*++=+$X",
+":*++++$X",
+"X*++++$X",
+"X&++++$X",
+"O ***&*.",
+"&OXXXo@ "};
diff --git a/bitmaps/b1.xpm b/bitmaps/b1.xpm
@@ -0,0 +1,31 @@
+/* XPM */
+static char * b1_xpm[] = {
+"8 16 12 1",
+" 	c #000000000000",
+".	c #208118612081",
+"X	c #B6DAAEBAB6DA",
+"o	c #410338E34103",
+"O	c #FFFFFFFFFFFF",
+"+	c #28A228A228A2",
+"@	c #E79DE79DE79D",
+"#	c #514451445144",
+"$	c #104008200820",
+"%	c #861779E779E7",
+"&	c #38E330C238E3",
+"*	c #F7DEF7DEF7DE",
+"       .",
+"      .X",
+"      oO",
+"      oO",
+"      oO",
+"      oO",
+"      +@",
+"       #",
+"      $%",
+"      &@",
+"      oO",
+"      oO",
+"      oO",
+"      &*",
+"      $%",
+"        "};
diff --git a/bitmaps/b2.xpm b/bitmaps/b2.xpm
@@ -0,0 +1,31 @@
+/* XPM */
+static char * b2_xpm[] = {
+"8 16 12 1",
+" 	c #000000000000",
+".	c #9E799E799E79",
+"X	c #EFBEE79DEFBE",
+"o	c #FFFFF7DEFFFF",
+"O	c #FFFFFFFFFFFF",
+"+	c #AEBAA699AEBA",
+"@	c #38E338E338E3",
+"#	c #082008200820",
+"$	c #38E330C238E3",
+"%	c #410338E338E3",
+"&	c #28A22CB228A2",
+"*	c #618559656185",
+" .XoOO+@",
+" #$@%@$+",
+"   # #%O",
+"    # %O",
+"  # # %O",
+" #    %O",
+"    # &X",
+" $XoOo*%",
+"+@....@ ",
+"O.   #  ",
+"O.     #",
+"O.      ",
+"o.      ",
+"O.  ####",
+"+@....@ ",
+" +XOOoX&"};
diff --git a/bitmaps/b3.xpm b/bitmaps/b3.xpm
@@ -0,0 +1,31 @@
+/* XPM */
+static char * b3_xpm[] = {
+"8 16 12 1",
+" 	c #000000000000",
+".	c #8E388A288E38",
+"X	c #F7DEEFBEEFBE",
+"o	c #FFFFF7DEFFFF",
+"O	c #FFFFFFFFFFFF",
+"+	c #AEBAA699AEBA",
+"@	c #38E334D338E3",
+"#	c #082008200820",
+"$	c #410338E34103",
+"%	c #28A228A228A2",
+"&	c #514451445144",
+"*	c #208118612081",
+" .XoOO+@",
+" #@@$@@+",
+"   # #$O",
+"      $O",
+"  # # $O",
+"      $O",
+"      %X",
+" @XoOo&&",
+" *..++$.",
+"      @X",
+"      $O",
+"   #  $O",
+"      $O",
+"      @X",
+" *.+++$.",
+" +OOOoX*"};
diff --git a/bitmaps/b4.xpm b/bitmaps/b4.xpm
@@ -0,0 +1,31 @@
+/* XPM */
+static char * b4_xpm[] = {
+"8 16 12 1",
+" 	c #38E330C230C2",
+".	c #000000000000",
+"X	c #208118612081",
+"o	c #DF7DD75CDF7D",
+"O	c #38E338E338E3",
+"+	c #9E799E799E79",
+"@	c #FFFFFFFFFFFF",
+"#	c #410338E34103",
+"$	c #082008200820",
+"%	c #69A669A669A6",
+"&	c #28A228A228A2",
+"*	c #F7DEF7DEF7DE",
+" ......X",
+"oO....X+",
+"@+....#@",
+"@+....#@",
+"@+.$..#@",
+"@+....#@",
+"@%...$&o",
+"%Oo@@*%#",
+".X++++#+",
+"......O*",
+"......#*",
+"......#@",
+"......#@",
+"......O*",
+"......$%",
+"......$."};
diff --git a/bitmaps/b5.xpm b/bitmaps/b5.xpm
@@ -0,0 +1,33 @@
+/* XPM */
+static char * b5_xpm[] = {
+"8 16 14 1",
+" 	c #30C230C230C2",
+".	c #861782078617",
+"X	c #F7DEF3CEF7DE",
+"o	c #FFFFF7DEF7DE",
+"O	c #B6DAAEBAB6DA",
+"+	c #208118612081",
+"@	c #E79DDF7DDF7D",
+"#	c #410338E34103",
+"$	c #410338E338E3",
+"%	c #186110401861",
+"&	c #000000000000",
+"*	c #9E799E799E79",
+"=	c #082000000000",
+"-	c #596555555965",
+" .XoooO+",
+"@#$###%&",
+"o*&&&&&&",
+"o*&&==&&",
+"o*&&&&&&",
+"o*&=&&&&",
+"o-%&&=&&",
+". @ooo-=",
+"&+.***-.",
+"&&&&&& X",
+"&&&=&&#o",
+"&&&&&&#o",
+"&&&=&&#o",
+"&&&&=&$X",
+"&+****#.",
+"&OXooo@ "};
diff --git a/bitmaps/b6.xpm b/bitmaps/b6.xpm
@@ -0,0 +1,32 @@
+/* XPM */
+static char * b6_xpm[] = {
+"8 16 13 1",
+" 	c #30C230C230C2",
+".	c #96588E388E38",
+"X	c #F7DEEFBEEFBE",
+"o	c #FFFFF7DEFFFF",
+"O	c #AEBAA699AEBA",
+"+	c #208118612081",
+"@	c #38E338E338E3",
+"#	c #41033CF338E3",
+"$	c #186110401861",
+"%	c #000000000000",
+"&	c #A6999E799E79",
+"*	c #082000000000",
+"=	c #69A665956185",
+" .XoooO+",
+"X@@@##$%",
+"o&%%%%%%",
+"o&%%**%%",
+"o&%%*%%%",
+"o&%*%*%%",
+"o=%%*%%%",
+". Xooo=%",
+"O@.&&&#.",
+"o.%%%%@X",
+"o&%%%%#o",
+"o&%%%%#o",
+"o&%%%%#o",
+"o.%%%*@X",
+"O@.&&&#.",
+"%OooooX "};
diff --git a/bitmaps/b7.xpm b/bitmaps/b7.xpm
@@ -0,0 +1,30 @@
+/* XPM */
+static char * b7_xpm[] = {
+"8 16 11 1",
+" 	c #000000000000",
+".	c #71C675D671C6",
+"X	c #F7DEF3CEF7DE",
+"o	c #FFFFF7DEFFFF",
+"O	c #DF7DDF7DDF7D",
+"+	c #28A228A228A2",
+"@	c #082008200820",
+"#	c #104008200820",
+"$	c #38E338E338E3",
+"%	c #410338E34103",
+"&	c #082000000820",
+" .XoooO+",
+"@#$%$$+O",
+"   @ @$X",
+"      %o",
+"  & & %o",
+"      %o",
+"      +O",
+"       %",
+"      #.",
+"      $X",
+"      %o",
+"      %o",
+"      %o",
+"      $X",
+"      @.",
+"        "};
diff --git a/bitmaps/b8.xpm b/bitmaps/b8.xpm
@@ -0,0 +1,31 @@
+/* XPM */
+static char * b8_xpm[] = {
+"8 16 12 1",
+" 	c #30C230C230C2",
+".	c #8E388A288E38",
+"X	c #F7DEEFBEEFBE",
+"o	c #FFFFF7DEFFFF",
+"O	c #AEBAAAAAAEBA",
+"+	c #38E338E338E3",
+"@	c #DF7DDF7DDF7D",
+"#	c #41033CF338E3",
+"$	c #A6999E799E79",
+"%	c #000000000000",
+"&	c #082000000000",
+"*	c #61855D756185",
+" .XoooO+",
+"@#+### O",
+"o$%%%%#o",
+"o$%%&&#o",
+"o$%%%%#o",
+"o$%&%%#o",
+"o*&%&% @",
+". @ooo**",
+"O+.$$$#.",
+"o.%%%%+X",
+"o$%%%%#o",
+"o$%%%%#o",
+"o$%%%%#o",
+"o.%%%&+X",
+"O#.$$$#.",
+"%Ooooo@ "};
diff --git a/bitmaps/b9.xpm b/bitmaps/b9.xpm
@@ -0,0 +1,34 @@
+/* XPM */
+static char * b9_xpm[] = {
+"8 16 15 1",
+" 	c #30C230C230C2",
+".	c #71C671C671C6",
+"X	c #F7DEF3CEF7DE",
+"o	c #FFFFFFFFFFFF",
+"O	c #AEBAAAAAAEBA",
+"+	c #38E33CF338E3",
+"@	c #DF7DDF7DDF7D",
+"#	c #492441034924",
+"$	c #A6999E799E79",
+"%	c #000000000000",
+"&	c #082000000000",
+"*	c #28A228A228A2",
+"=	c #FFFFF7DEF7DE",
+"-	c #208118612081",
+";	c #965896589658",
+" .XoooO+",
+"@#++++ O",
+"o$%%%%+o",
+"o$%%&&+o",
+"o$%%&%+o",
+"o$%&%&+o",
+"o.%%%&*@",
+". @o=X.#",
+"%-;$$$+.",
+"%%%%%%+X",
+"%%%&%%+=",
+"%%%%%%+o",
+"%%%&%%+o",
+"%%%%&%+X",
+"%-;$$;#.",
+"%Ooooo@ "};
diff --git a/bitmaps/bar.xpm b/bitmaps/bar.xpm
@@ -0,0 +1,18 @@
+/* XPM */
+static char * bar_xpm[] = {
+"4 7 8 1",
+" 	c #000000000000",
+".	c #208118612081",
+"X	c #B6DAAEBAB6DA",
+"o	c #410338E34103",
+"O	c #FFFFFFFFFFFF",
+"+	c #28A228A228A2",
+"@	c #E79DE79DE79D",
+"#	c #514451445144",
+" .X ",
+" oO ",
+" oO ",
+" oO ",
+" oO ",
+" +@ ",
+"  # "};
diff --git a/bitmaps/bn.xpm b/bitmaps/bn.xpm
@@ -0,0 +1,20 @@
+/* XPM */
+static char * bn_xpm[] = {
+"8 16 1 1",
+" 	c #000000000000",
+"        ",
+"        ",
+"        ",
+"        ",
+"        ",
+"        ",
+"        ",
+"        ",
+"        ",
+"        ",
+"        ",
+"        ",
+"        ",
+"        ",
+"        ",
+"        "};
diff --git a/bitmaps/cdrom.xpm b/bitmaps/cdrom.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static char * cdrom_xpm[] = {
+"15 15 4 1",
+" 	c #965896589658",
+".	c #000000000000",
+"X	c #492449244924",
+"o	c #CF3CCF3CCF3C",
+"              .",
+" XXXXXXXXXXXXX.",
+" XXXXXXXXXXXXX.",
+" XXXXXoooooXXX.",
+" XXXXoooooooXX.",
+" XXXXooooooo.X.",
+" XXXXoooXooo.X.",
+" XXXXooooooo.X.",
+" XXXXooooooo.X.",
+" XXXXXooooo..X.",
+" XXXXXX.....XX.",
+" XXXXXXXXXXXXX.",
+" XXXXXXXXXXXXX.",
+" XXXXXXXXXXXXX.",
+"..............."};
diff --git a/bitmaps/concept1.xpm b/bitmaps/concept1.xpm
@@ -0,0 +1,294 @@
+/* XPM */
+static char * concept1_xpm[] = {
+"256 256 35 1",
+" 	c #FFFFFFFFFFFF",
+".	c #000000000000",
+"X	c #965896589658",
+"o	c #492449244924",
+"O	c #CF3CCF3CCF3C",
+"+	c #514451445144",
+"@	c #BEFBBAEABEFB",
+"#	c #186118611861",
+"$	c #69A66DB669A6",
+"%	c #EFBEEFBEEFBE",
+"&	c #596559655965",
+"*	c #38E338E338E3",
+"=	c #DF7DDF7DDF7D",
+"-	c #28A228A228A2",
+";	c #D75CD75CD75C",
+":	c #082008200820",
+">	c #C71BC30BC71B",
+",	c #CF3CCB2BCF3C",
+"<	c #B6DAB6DAB6DA",
+"1	c #AEBAAEBAAEBA",
+"2	c #A699A699A699",
+"3	c #9E799E799E79",
+"4	c #965892489658",
+"5	c #8E388A288E38",
+"6	c #861782078617",
+"7	c #79E779E779E7",
+"8	c #618565956185",
+"9	c #59655D755965",
+"0	c #514455555144",
+"q	c #410341034103",
+"w	c #30C230C230C2",
+"e	c #208124922081",
+"r	c #18611C711861",
+"t	c #104014511040",
+"y	c #08200C300820",
+"                                                                                                                                                                                                                                                                ",
+" .......................................................................................................................................                                                                                                                        ",
+" ..........................................................................................XXXXXXXXXXXXXX.XXXXXXXXXXXXXX.XXXXXXXXXXXXXX.                                                                                                                        ",
+" ..........................................................................................Xooooooooooooo.Xooooooooooooo.Xooooooooooooo.                                                                                                                        ",
+" ..........................................................................................XooooooOooOooo.Xooooooooooooo.XoOOooooooOOoo.                                                                                                                        ",
+" ..........................................................................................XoooooOO.ooOoo.Xooooooooooooo.XoOOOooooOOO.o.                                                                                                                        ",
+" ..........................................................................................XooooOOO.OoO.o.Xooooooooooooo.XooOOOooOOO..o.                                                                                                                        ",
+" ..........................................................................................XoooOOOO.O.O.o.XoOOOOOOOOOOoo.XoooOOOOOO..oo.                                                                                                                        ",
+" ..........................................................................................XoOOOOOO.O.O.o.XooOOOOOOOO..o.XooooOOOO..ooo.                                                                                                                        ",
+" ..........................................................................................XoOOOOOO.O.O.o.XoooOOOOOO..oo.XooooOOOO.oooo.                                                                                                                        ",
+" ..........................................................................................Xoo.OOOO.O.O.o.XooooOOOO..ooo.XoooOOOOOOoooo.                                                                                                                        ",
+" ..........................................................................................XooooOOO.O.O.o.XoooooOO..oooo.XooOOO..OOOooo.                                                                                                                        ",
+" ..........................................................................................XoooooOO.o.O.o.Xoooooo..ooooo.XoOOO..ooOOOoo.                                                                                                                        ",
+" ..........................................................................................XooooooO.oOo.o.Xooooooooooooo.XoOO..ooooOO.o.                                                                                                                        ",
+" ..........................................................................................Xooooooo.oo.oo.Xooooooooooooo.Xoo..oooooo..o.                                                                                                                        ",
+" ..........................................................................................Xooooooooooooo.Xooooooooooooo.Xooooooooooooo.                                                                                                                        ",
+" .......................................................................................................................................                                                                                                                        ",
+" ....... +.....@@....#$@  %@&.............@     @&....* *...*@  =@&#.....*@=  @$...........XXXXXXXXXXXXXX.XXXXXXXXXXXXXX.XXXXXXXXXXXXXX.                                                                                                                        ",
+" ....... %-....@@...-= ;$$X= O#...........@=$$$$; ;#..* *..o =X$X= =:...@ =X$$; ;#.........Xooooooooooooo.Xooooooooooooo.Xooooooooooooo.                                                                                                                        ",
+" .......  =-...@@..#=%*.....$ @...........@@.....+ X..* *..@=.....*$...$ @.....o%$.........XooooooooOoooo.Xooooooooooooo.XooooOOOOOoooo.                                                                                                                        ",
+" ....... @%=-..@@..$ -.......$ -..........@@......X #.* *..@%*.........%@.......:..........XooooooooOOooo.Xooooooooooooo.XoooOOOOOOOooo.                                                                                                                        ",
+" ....... $-%;#.@@..@;........# $..........@@......* *.* *..-%    =@*..* o..................XoooOOOOOOOOoo.XoooooOOoooooo.XoooOO..oOO.oo.                                                                                                                        ",
+" ....... $.-%O#@@..@@......... $..........@@......* *.* *....*$$$X= *.* *..................XooOOOOOOOOO.o.XooooOOOOooooo.Xoooo..ooOO.oo.                                                                                                                        ",
+" ....... $..+ ;@@..X #.......o o..........@@......X #.* *.........#=@.# X.......-#.........XoOOO....OO..o.XoooOOOOOOoooo.XoooooooOOO.oo.                                                                                                                        ",
+" ....... $...+  @..#%;#.....-%=...........@@.....o X..* *..$*......=@..X +.....-%@.........XoOO..oooO..oo.XooOOOOOOOOooo.XooooooOOO..oo.                                                                                                                        ",
+" ....... $....+ @...+ =X**oX =-...........@=$$$$; ;#..* *.:% ;$**&; o..#; X&*oX %-.........XoOO.ooooo.ooo.XoOOOOOOOOOOoo.XooooooOO..ooo.                                                                                                                        ",
+" ....... $.....@@....-@    %X#............@     ;$#...* *..#$;    =o....#$%    X#..........XoOOOooooooooo.Xoo..........o.Xooooooo..oooo.                                                                                                                        ",
+" .......................**-...................................#**-.........-**.............XooOOOOOOOOOoo.XoOOOOOOOOOOoo.XooooooOOooooo.                                                                                                                        ",
+" ..........................................................................................XoooOOOOOOO..o.Xoo..........o.XooooooOO.oooo.                                                                                                                        ",
+" ..........................................................................................Xoooo.......oo.Xooooooooooooo.Xooooooo..oooo.                                                                                                                        ",
+" ..........................................................................................Xooooooooooooo.Xooooooooooooo.Xooooooooooooo.                                                                                                                        ",
+" .......................................................................................................................................                                                                                                                        ",
+"O>>>>>>>>>>>>>>>>>>>>>>>>>>O.O>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>O.O>>>>>>>>>>>>>>>>>>>>>>>>>>O.                                                                                                                       ",
+"O,,,,,,,,,,,,,,,,,,,,,,,,,,O.O,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,O.O,,,,,,,,,,,,,,,,,,,,,,,,,,O.                                                                                                                       ",
+"O<<<<<<<<<<<<<<<<<<<<<<<<<<O.O<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<O.O<<<<<<<<<<<<<<<<<<<<<<<<<<O.                                                                                                                       ",
+"O11111111111111111111111111O.O1111111111111111111111111111111111111111111111111111111111111111111111111111O.O11111111111111111111111111O.                                                                                                                       ",
+"O22222222222222222222222222O.O2222222222222222222222222222222222222222222222222222222222222222222222222222O.O22222222222222222222222222O.                                                                                                                       ",
+"O33333333333333333333333333O.O3333333333333333333333333333333333333333333333333333333333333333333333333333O.O33333333333333333333333333O.                                                                                                                       ",
+"O44444444444444444444444444O.O4444444444444444444444444444444444444444444444444444444444444444444444444444O.O44444444444444444444444444O.                                                                                                                       ",
+"O55555555555555555555555555O.O5555555555555555555555555555555555555555555555555555555555555555555555555555O.O55555555555555555555555555O.                                                                                                                       ",
+"O6666OO666666OO666666OO6666O.O66666666666666666666666  66666666666666666666OOO66OOO66666666666666666666666O.O6666OO666666OO666666OO6666O.                                                                                                                       ",
+"O7777OO77777OOO77777OOO7777O.O77777777777777777777777     77777777777777777OOO77OOO77777777777777777777777O.O7777OOO77777OOO77777OO7777O.                                                                                                                       ",
+"O$$$$OO$$$$OOOO$$$$OOOO$$$$O.O$$$$$$$$$$$$$$$$$$$$$$$        $$$$$$$$$$$$$$OOO$$OOO$$$$$$$$$$$$$$$$$$$$$$$O.O$$$$OOOO$$$$OOOO$$$$OO$$$$O.                                                                                                                       ",
+"O8888OO888OOOOO888OOOOO8888O.O88888888888888888888888           88888888888OOO88OOO88888888888888888888888O.O8888OOOOO888OOOOO888OO8888O.                                                                                                                       ",
+"O9999OO99OOOOOO99OOOOOO9999O.O99999999999999999999999              99999999OOO99OOO99999999999999999999999O.O9999OOOOOO99OOOOOO99OO9999O.                                                                                                                       ",
+"O0000OO0OOOOOOO0OOOOOOO0000O.O00000000000000000000000                 00000OOO00OOO00000000000000000000000O.O0000OOOOOOO0OOOOOOO0OO0000O.                                                                                                                       ",
+",ooooOOOOOOOOOOOOOOOOOOoooo,.,ooooooooooooooooooooooo                    ooOOOooOOOooooooooooooooooooooooo,.,ooooOOOOOOOOOOOOOOOOOOoooo,.                                                                                                                       ",
+"<qqqqOOOOOOOOOOOOOOOOOOqqqq<.<qqqqqqqqqqqqqqqqqqqqqqq                    qqOOOqqOOOqqqqqqqqqqqqqqqqqqqqqqq<.<qqqqOOOOOOOOOOOOOOOOOOqqqq<.                                                                                                                       ",
+"2****OO*OOOOOOO*OOOOOOO****2.2***********************                 *****OOO**OOO***********************2.2****OOOOOOO*OOOOOOO*OO****2.                                                                                                                       ",
+"4wwwwOOwwOOOOOOwwOOOOOOwwww4.4wwwwwwwwwwwwwwwwwwwwwww              wwwwwwwwOOOwwOOOwwwwwwwwwwwwwwwwwwwwwww4.4wwwwOOOOOOwwOOOOOOwwOOwwww4.                                                                                                                       ",
+"6eeeeOOeeeOOOOOeeeOOOOOeeee6.6eeeeeeeeeeeeeeeeeeeeeee           eeeeeeeeeeeOOOeeOOOeeeeeeeeeeeeeeeeeeeeeee6.6eeeeOOOOOeeeOOOOOeeeOOeeee6.                                                                                                                       ",
+"$rrrrOOrrrrOOOOrrrrOOOOrrrr$.$rrrrrrrrrrrrrrrrrrrrrrr        rrrrrrrrrrrrrrOOOrrOOOrrrrrrrrrrrrrrrrrrrrrrr$.$rrrrOOOOrrrrOOOOrrrrOOrrrr$.                                                                                                                       ",
+"9ttttOOtttttOOOtttttOOOtttt9.9ttttttttttttttttttttttt     tttttttttttttttttOOOttOOOttttttttttttttttttttttt9.9ttttOOOtttttOOOtttttOOtttt9.                                                                                                                       ",
+"oyyyyOOyyyyyyOOyyyyyyOOyyyyo.oyyyyyyyyyyyyyyyyyyyyyyy  yyyyyyyyyyyyyyyyyyyyOOOyyOOOyyyyyyyyyyyyyyyyyyyyyyyo.oyyyyOOyyyyyyOOyyyyyyOOyyyyo.                                                                                                                       ",
+"*..........................*.*............................................................................*.*..........................*.                                                                                                                       ",
+"e..........................e.e............................................................................e.e..........................e.                                                                                                                       ",
+"t..........................t.t............................................................................t.t..........................t.                                                                                                                       ",
+".........................................................................................................................................                                                                                                                       ",
+".........................................................................................................................................                                                                                                                       ",
+".........................................................................................................................................                                                                                                                       ",
+".........................................................................................................................................                                                                                                                       ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                ",
+"                                                                                                                                                                                                                                                                "};
diff --git a/bitmaps/ejdn.xpm b/bitmaps/ejdn.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static char * ejdn_xpm[] = {
+"15 15 4 1",
+" 	c #000000000000",
+".	c #965896589658",
+"X	c #492449244924",
+"o	c #FFFFFFFFFFFF",
+"               ",
+" ..............",
+" .XXXXXXXXXXXXX",
+" .XXXXXXXXXXXXX",
+" .XXXXXXXXXXXXX",
+" .XXXXXooXXXXXX",
+" .XXXXooooXXXXX",
+" .XXXooooooXXXX",
+" .XXooooooooXXX",
+" .XooooooooooXX",
+" .XX          X",
+" .XooooooooooXX",
+" .XX          X",
+" .XXXXXXXXXXXXX",
+" .XXXXXXXXXXXXX"};
diff --git a/bitmaps/ejup.xpm b/bitmaps/ejup.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static char * ejup_xpm[] = {
+"15 15 4 1",
+" 	c #965896589658",
+".	c #000000000000",
+"X	c #492449244924",
+"o	c #CF3CCF3CCF3C",
+"              .",
+" XXXXXXXXXXXXX.",
+" XXXXXXXXXXXXX.",
+" XXXXXXXXXXXXX.",
+" XXXXXooXXXXXX.",
+" XXXXooooXXXXX.",
+" XXXooooooXXXX.",
+" XXooooooooXXX.",
+" XooooooooooXX.",
+" XX..........X.",
+" XooooooooooXX.",
+" XX..........X.",
+" XXXXXXXXXXXXX.",
+" XXXXXXXXXXXXX.",
+"..............."};
diff --git a/bitmaps/exitdn.xpm b/bitmaps/exitdn.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static char * exitdn_xpm[] = {
+"15 15 4 1",
+" 	c #000000000000",
+".	c #965896589658",
+"X	c #492449244924",
+"o	c #FFFFFFFFFFFF",
+"               ",
+" ..............",
+" .XXXXXXXXXXXXX",
+" .XooXXXXXXooXX",
+" .XoooXXXXooo X",
+" .XXoooXXooo  X",
+" .XXXoooooo  XX",
+" .XXXXoooo  XXX",
+" .XXXXoooo XXXX",
+" .XXXooooooXXXX",
+" .XXooo  oooXXX",
+" .Xooo  XXoooXX",
+" .Xoo  XXXXoo X",
+" .XX  XXXXXX  X",
+" .XXXXXXXXXXXXX"};
diff --git a/bitmaps/exitup.xpm b/bitmaps/exitup.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static char * exitup_xpm[] = {
+"15 15 4 1",
+" 	c #965896589658",
+".	c #000000000000",
+"X	c #492449244924",
+"o	c #CF3CCF3CCF3C",
+"              .",
+" XXXXXXXXXXXXX.",
+" XooXXXXXXooXX.",
+" XoooXXXXooo.X.",
+" XXoooXXooo..X.",
+" XXXoooooo..XX.",
+" XXXXoooo..XXX.",
+" XXXXoooo.XXXX.",
+" XXXooooooXXXX.",
+" XXooo..oooXXX.",
+" Xooo..XXoooXX.",
+" Xoo..XXXXoo.X.",
+" XX..XXXXXX..X.",
+" XXXXXXXXXXXXX.",
+"..............."};
diff --git a/bitmaps/ffdn.xpm b/bitmaps/ffdn.xpm
@@ -0,0 +1,59 @@
+/* XPM */
+static char * ffdn_xpm[] = {
+"29 30 26 1",
+" 	c None",
+".	c #000000",
+"+	c #CFCFCF",
+"@	c #C7C3C7",
+"#	c #CFCBCF",
+"$	c #B6B6B6",
+"%	c #AEAEAE",
+"&	c #A6A6A6",
+"*	c #9E9E9E",
+"=	c #969296",
+"-	c #8E8A8E",
+";	c #868286",
+">	c #FFFFFF",
+",	c #797979",
+"'	c #696D69",
+")	c #616561",
+"!	c #595D59",
+"~	c #515551",
+"{	c #494949",
+"]	c #414141",
+"^	c #383838",
+"/	c #303030",
+"(	c #202420",
+"_	c #181C18",
+":	c #101410",
+"<	c #080C08",
+".............................",
+".+@@@@@@@@@@@@@@@@@@@@@@@@@@+",
+".+##########################+",
+".+$$$$$$$$$$$$$$$$$$$$$$$$$$+",
+".+%%%%%%%%%%%%%%%%%%%%%%%%%%+",
+".+&&&&&&&&&&&&&&&&&&&&&&&&&&+",
+".+**************************+",
+".+==========================+",
+".+--------------------------+",
+".+;;;;;;;;;;;;>>;;;;;;>>;;;;+",
+".+,,,,,,,,,,,,>>>,,,,,>>,,,,+",
+".+''''''''''''>>>>''''>>''''+",
+".+))))))))))))>>>>>)))>>))))+",
+".+!!!!!!!!!!!!>>>>>>!!>>!!!!+",
+".+~~~~~~~~~~~~>>>>>>>~>>~~~~+",
+".#{{{{{{{{{{{{>>>>>>>>>>{{{{#",
+".$]]]]]]]]]]]]>>>>>>>>>>]]]]$",
+".&^^^^^^^^^^^^>>>>>>>^>>^^^^&",
+".=////////////>>>>>>//>>////=",
+".;((((((((((((>>>>>(((>>((((;",
+".'____________>>>>____>>____'",
+".!::::::::::::>>>:::::>>::::!",
+".{<<<<<<<<<<<<>><<<<<<>><<<<{",
+".^..........................^",
+".(..........................(",
+".:..........................:",
+".............................",
+".............................",
+".............................",
+"............................."};
diff --git a/bitmaps/ffup.xpm b/bitmaps/ffup.xpm
@@ -0,0 +1,57 @@
+/* XPM */
+static char * ffup_xpm[] = {
+"29 30 24 1",
+" 	c #CF3CCF3CCF3C",
+".	c #C71BC30BC71B",
+"X	c #000000000000",
+"o	c #CF3CCB2BCF3C",
+"O	c #B6DAB6DAB6DA",
+"+	c #AEBAAEBAAEBA",
+"@	c #A699A699A699",
+"#	c #9E799E799E79",
+"$	c #965892489658",
+"%	c #8E388A288E38",
+"&	c #861782078617",
+"*	c #79E779E779E7",
+"=	c #69A66DB669A6",
+"-	c #618565956185",
+";	c #59655D755965",
+":	c #514455555144",
+">	c #492449244924",
+",	c #410341034103",
+"<	c #38E338E338E3",
+"1	c #30C230C230C2",
+"2	c #208124922081",
+"3	c #18611C711861",
+"4	c #104014511040",
+"5	c #08200C300820",
+" .......................... X",
+" oooooooooooooooooooooooooo X",
+" OOOOOOOOOOOOOOOOOOOOOOOOOO X",
+" ++++++++++++++++++++++++++ X",
+" @@@@@@@@@@@@@@@@@@@@@@@@@@ X",
+" ########################## X",
+" $$$$$$$$$$$$$$$$$$$$$$$$$$ X",
+" %%%%%%%%%%%%%%%%%%%%%%%%%% X",
+" &&&&  &&&&&&  &&&&&&  &&&& X",
+" ****   *****   *****  **** X",
+" ====    ====    ====  ==== X",
+" ----     ---     ---  ---- X",
+" ;;;;      ;;      ;;  ;;;; X",
+" ::::       :       :  :::: X",
+"o>>>>                  >>>>oX",
+"O,,,,                  ,,,,OX",
+"@<<<<       <       <  <<<<@X",
+"$1111      11      11  1111$X",
+"&2222     222     222  2222&X",
+"=3333    3333    3333  3333=X",
+";4444   44444   44444  4444;X",
+">5555  555555  555555  5555>X",
+"<XXXXXXXXXXXXXXXXXXXXXXXXXX<X",
+"2XXXXXXXXXXXXXXXXXXXXXXXXXX2X",
+"4XXXXXXXXXXXXXXXXXXXXXXXXXX4X",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXX"};
diff --git a/bitmaps/freecd.xpm b/bitmaps/freecd.xpm
@@ -0,0 +1,153 @@
+/* XPM */
+static char * freecd_xpm[] = {
+"26 94 56 1",
+" 	c #FFFFFFFFFFFF",
+".	c #FFFFFBEEFFFF",
+"X	c #F7DEF7DEF7DE",
+"o	c #EFBEEFBEEFBE",
+"O	c #EFBEEBADEFBE",
+"+	c #E79DE79DE79D",
+"@	c #E79DE38DE79D",
+"#	c #DF7DDF7DDF7D",
+"$	c #DF7DDB6CDF7D",
+"%	c #D75CD75CD75C",
+"&	c #D75CD34CD75C",
+"*	c #CF3CCB2BCF3C",
+"=	c #C71BC71BC71B",
+"-	c #C71BC30BC71B",
+";	c #BEFBBEFBBEFB",
+":	c #BEFBBAEABEFB",
+">	c #B6DAB6DAB6DA",
+",	c #B6DAB2CAB6DA",
+"<	c #AEBAAEBAAEBA",
+"1	c #AEBAAAAAAEBA",
+"2	c #A699A289A699",
+"3	c #9E799E799E79",
+"4	c #A699A699A699",
+"5	c #9E799A699E79",
+"6	c #965896589658",
+"7	c #965892489658",
+"8	c #514451445144",
+"9	c #18611C711861",
+"0	c #208124922081",
+"q	c #28A228A228A2",
+"w	c #30C230C230C2",
+"e	c #30C234D330C2",
+"r	c #410345144103",
+"t	c #492449244924",
+"y	c #618561856185",
+"u	c #69A66DB669A6",
+"i	c #49244D344924",
+"p	c #71C671C671C6",
+"a	c #79E77DF779E7",
+"s	c #38E33CF338E3",
+"d	c #208120812081",
+"f	c #861782078617",
+"g	c #71C675D671C6",
+"h	c #69A669A669A6",
+"j	c #618565956185",
+"k	c #410341034103",
+"l	c #38E338E338E3",
+"z	c #CF3CCF3CCF3C",
+"x	c #8E388A288E38",
+"c	c #79E779E779E7",
+"v	c #8E388E388E38",
+"b	c #28A22CB228A2",
+"n	c #596559655965",
+"m	c #514455555144",
+"M	c #861786178617",
+"N	c #59655D755965",
+"     .XoO+@#$%&*=-;:>,<123",
+"     .XoO+@#$%&*=-;:>,<123",
+"     .XoO+@#$%&*=-;:>,<123",
+"     .XoO+@#$%&*=-;:>,<123",
+"     .X*44233356667:>,<123",
+"     .890qqqqqqqqqqw3,<123",
+"     59erttttttttttty,<123",
+"     uqr888888888888i,<123",
+"     pwi8888888888888,<123",
+"     pea:,<<<114443i8,<123",
+"     pe,O+@#$%&*=-;si,<123",
+"     pe<O+@#$%&*=-;0r,<123",
+"     pe<O+@#$%&*=-;dr,<123",
+"     pe<O+@#$%&*=-;dr,<123",
+"     pe<O+@#$%&*=-;dr,<123",
+"     pef6guuuuhhhhj0r,<123",
+"     petkeeeeeeeeeeli,<123",
+"     pei8iiiiiiiiiii8,<123",
+"     pei8888888888888,<123",
+"     pei8888888888888,<123",
+"     <;*z*=--;;:>>,<4,<123",
+"     &x2O+@#$%&*=-<cv,<123",
+"     udgO+@#$%&*=-1dw,<123",
+"     pb4O+@#$%&*=-;0k,<123",
+"     pe<O+@#$%&*=-;dr,<123",
+"     pe<O+@#$%&*=-;dr,<123",
+"     pe<O+@#$%&*=-;dr,<123",
+"     pe<O+@#$%&*=-;dr,<123",
+"     pe<O+@#$%&*=-;dr,<123",
+"     penuirrkkkkkkeqt,<123",
+"     pettsssssssssski,<123",
+"     pei8888888888888,<123",
+"     ;wi8888888888887,<123",
+"     .3j888888888886,,<123",
+"     .XoO+@#$%&*=-;:>,<123",
+"     .XoO+@=,<<1--;<>,<123",
+"     .XoO+gdeskk1-;kq,<123",
+"     .XoO*dipaaa;-;tm,<123",
+"     .XoO<epv777--;ij,<123",
+"     .XoO<sa7777--;ij,<123",
+"     .XoO<k1&*,M--;ij,<123",
+"     .XoO<k:$%6h;-;ij,<123",
+"     .XoO<k>$%am;-;ij,<123",
+"     .XoO<k>$%c8;-;ij,<123",
+"     .XoO<k<$%c8;-;rj,<123",
+"     .XoO<kgyllyg8wsp,<123",
+"     .XoO<kcMccMxfccx,<123",
+"     .XoO:sa777777775,<123",
+"     .XoO+yg77777777;,<123",
+"     .XoO+@>;-;;;::;>,<123",
+"     .XoO+@#$%&*=-;:>,<123",
+"     .XoO+3wwlss1-;mi,<123",
+"     .XoO%qkjggg:-;ti,<123",
+"     .XoO<bhx777--;iy,<123",
+"     .XoO<sc7777--;ij,<123",
+"     .XoO<k5*-1x--;ij,<123",
+"     .XoO<k:$%2p--;ij,<123",
+"     .XoO<k>$%fn;-;ij,<123",
+"     .XoO<k>$%c8;-;ij,<123",
+"     .XoO<k>$%c8;-;ij,<123",
+"     .XoO<kaMNrN7pmlu,<123",
+"     .XoO<kcahhcMgjuM,<123",
+"     .XoO<kavvxv7vxv7,<123",
+"     .XoO+8c77777777:,<123",
+"     .XoO+*31<<<<<<:>,<123",
+"     .XoO:tu*%&*=-;:>,<123",
+"     .XoO<wN&%&*=-;:>,<123",
+"     .XoO<sc$%&*=-;:>,<123",
+"     .XoO<ka$%&*=-;:>,<123",
+"     .XoO<ka$%&*=-;:>,<123",
+"     .XoO+rc>xcggggpN,<123",
+"     .XoO<egMy888888m,<123",
+"     .XoO<scvxMMMMMMM,<123",
+"     .XoO<ka777777777,<123",
+"     .XoO<ka777777777,<123",
+"     .XoO$%#$%&*=-;:>,<123",
+"     ,8gO+@#,<;*=-;:>,<123",
+"     ce5O+@#9ex*=-;:>,<123",
+"     ai;O+@#8y-*=-;:>,<123",
+"     f8-O+@#8h=*=-;:>,<123",
+"     f8-O+@#8j=*=-;:>,<123",
+"     f8-O+@#8j=*=-;:>,<123",
+"     f8-O+@#8j=*=-;:>,<123",
+"     f8-O+@#8j=*=-;:>,<123",
+"     f87MN88ku5gm8iiw,<123",
+"     f8achjjufxgjjjjj,<123",
+"     f8fvxxxvv7vxxxxv,<123",
+"     f8M7777777777777,<123",
+"     f8M7777777777777,<123",
+"     %OoO+@#$%&*=-;:>,<123",
+"     .XoO+@#$%&*=-;:>,<123",
+"     .XoO+@#$%&*=-;:>,<123",
+"     .XoO+@#$%&*=-;:>,<123",
+"     .XoO+@#$%&*=-;:>,<123"};
diff --git a/bitmaps/freecdbase.xpm b/bitmaps/freecdbase.xpm
@@ -0,0 +1,26 @@
+/* XPM */
+static char * freecdbase_xpm[] = {
+"26 1 22 1",
+" 	c #FFFFFFFFFFFF",
+".	c #FFFFFBEEFFFF",
+"X	c #F7DEF7DEF7DE",
+"o	c #EFBEEFBEEFBE",
+"O	c #EFBEEBADEFBE",
+"+	c #E79DE79DE79D",
+"@	c #E79DE38DE79D",
+"#	c #DF7DDF7DDF7D",
+"$	c #DF7DDB6CDF7D",
+"%	c #D75CD75CD75C",
+"&	c #D75CD34CD75C",
+"*	c #CF3CCB2BCF3C",
+"=	c #C71BC71BC71B",
+"-	c #C71BC30BC71B",
+";	c #BEFBBEFBBEFB",
+":	c #BEFBBAEABEFB",
+">	c #B6DAB6DAB6DA",
+",	c #B6DAB2CAB6DA",
+"<	c #AEBAAEBAAEBA",
+"1	c #AEBAAAAAAEBA",
+"2	c #A699A289A699",
+"3	c #9E799E799E79",
+"     .XoO+@#$%&*=-;:>,<123"};
diff --git a/bitmaps/helpdn.xpm b/bitmaps/helpdn.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static char * helpdn_xpm[] = {
+"15 15 4 1",
+" 	c #000000000000",
+".	c #965896589658",
+"X	c #492449244924",
+"o	c #FFFFFFFFFFFF",
+"               ",
+" ..............",
+" .XXXXXXXXXXXXX",
+" .XXXXoooooXXXX",
+" .XXXoooooooXXX",
+" .XXXoo  Xoo XX",
+" .XXXX  XXoo XX",
+" .XXXXXXXooo XX",
+" .XXXXXXooo  XX",
+" .XXXXXXoo  XXX",
+" .XXXXXXX  XXXX",
+" .XXXXXXooXXXXX",
+" .XXXXXXoo XXXX",
+" .XXXXXXX  XXXX",
+" .XXXXXXXXXXXXX"};
diff --git a/bitmaps/helpup.xpm b/bitmaps/helpup.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static char * helpup_xpm[] = {
+"15 15 4 1",
+" 	c #965896589658",
+".	c #000000000000",
+"X	c #492449244924",
+"o	c #CF3CCF3CCF3C",
+"              .",
+" XXXXXXXXXXXXX.",
+" XXXXoooooXXXX.",
+" XXXoooooooXXX.",
+" XXXoo..Xoo.XX.",
+" XXXX..XXoo.XX.",
+" XXXXXXXooo.XX.",
+" XXXXXXooo..XX.",
+" XXXXXXoo..XXX.",
+" XXXXXXX..XXXX.",
+" XXXXXXooXXXXX.",
+" XXXXXXoo.XXXX.",
+" XXXXXXX..XXXX.",
+" XXXXXXXXXXXXX.",
+"..............."};
diff --git a/bitmaps/mindn.xpm b/bitmaps/mindn.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static char * mindn_xpm[] = {
+"15 15 4 1",
+" 	c #000000000000",
+".	c #965896589658",
+"X	c #492449244924",
+"o	c #FFFFFFFFFFFF",
+"               ",
+" ..............",
+" .XXXXXXXXXXXXX",
+" .XXXXXXXXXXXXX",
+" .XXXXXXXXXXXXX",
+" .XXXXXXXXXXXXX",
+" .XooooooooooXX",
+" .XXoooooooo  X",
+" .XXXoooooo  XX",
+" .XXXXoooo  XXX",
+" .XXXXXoo  XXXX",
+" .XXXXXX  XXXXX",
+" .XXXXXXXXXXXXX",
+" .XXXXXXXXXXXXX",
+" .XXXXXXXXXXXXX"};
diff --git a/bitmaps/minup.xpm b/bitmaps/minup.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static char * minup_xpm[] = {
+"15 15 4 1",
+" 	c #965896589658",
+".	c #000000000000",
+"X	c #492449244924",
+"o	c #CF3CCF3CCF3C",
+"              .",
+" XXXXXXXXXXXXX.",
+" XXXXXXXXXXXXX.",
+" XXXXXXXXXXXXX.",
+" XXXXXXXXXXXXX.",
+" XooooooooooXX.",
+" XXoooooooo..X.",
+" XXXoooooo..XX.",
+" XXXXoooo..XXX.",
+" XXXXXoo..XXXX.",
+" XXXXXX..XXXXX.",
+" XXXXXXXXXXXXX.",
+" XXXXXXXXXXXXX.",
+" XXXXXXXXXXXXX.",
+"..............."};
diff --git a/bitmaps/minus.xpm b/bitmaps/minus.xpm
@@ -0,0 +1,29 @@
+/* XPM */
+static char * minus_xpm[] = {
+"8 16 10 1",
+" 	c #000000000000",
+".	c #38E330C238E3",
+"X	c #F7DEEFBEEFBE",
+"o	c #FFFFF7DEFFFF",
+"O	c #FFFFFFFFFFFF",
+"+	c #514451445144",
+"@	c #208118612081",
+"#	c #8E388E388E38",
+"$	c #AEBAA699AEBA",
+"%	c #410338E34103",
+"        ",
+"        ",
+"        ",
+"        ",
+"        ",
+"        ",
+"        ",
+".XoOo+  ",
+"@##$$%  ",
+"        ",
+"        ",
+"        ",
+"        ",
+"        ",
+"        ",
+"        "};
diff --git a/bitmaps/mnscddn.xpm b/bitmaps/mnscddn.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static char * mnscddn_xpm[] = {
+"15 15 4 1",
+" 	c #000000000000",
+".	c #965896589658",
+"X	c #492449244924",
+"o	c #FFFFFFFFFFFF",
+"               ",
+" ..............",
+" .XXXXXXXXXXXXX",
+" .XXXXXXXXXXXXX",
+" .XXXXXoooooXXX",
+" .XXXXoooooooXX",
+" .XXXXooooooo X",
+" .XXXXoooXooo X",
+" .XXXXooooooo X",
+" .XXXXooooooo X",
+" .Xoooooo.oo  X",
+" .Xoooooo    XX",
+" .XX      XXXXX",
+" .XXXXXXXXXXXXX",
+" .XXXXXXXXXXXXX"};
diff --git a/bitmaps/mnscdup.xpm b/bitmaps/mnscdup.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static char * mnscdup_xpm[] = {
+"15 15 4 1",
+" 	c #965896589658",
+".	c #000000000000",
+"X	c #492449244924",
+"o	c #CF3CCF3CCF3C",
+"              .",
+" XXXXXXXXXXXXX.",
+" XXXXXXXXXXXXX.",
+" XXXXXoooooXXX.",
+" XXXXoooooooXX.",
+" XXXXooooooo.X.",
+" XXXXoooXooo.X.",
+" XXXXooooooo.X.",
+" XXXXooooooo.X.",
+" Xoooooo oo..X.",
+" Xoooooo....XX.",
+" XX......XXXXX.",
+" XXXXXXXXXXXXX.",
+" XXXXXXXXXXXXX.",
+"..............."};
diff --git a/bitmaps/mnstrkdn.xpm b/bitmaps/mnstrkdn.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static char * mnstrkdn_xpm[] = {
+"15 15 4 1",
+" 	c #000000000000",
+".	c #965896589658",
+"X	c #492449244924",
+"o	c #FFFFFFFFFFFF",
+"               ",
+" ..............",
+" .XXXXXXXXXXXXX",
+" .XXXXXXXXXXXXX",
+" .XXXXXXXoooXXX",
+" .XXXXXXXooooXX",
+" .XXXXXXXoooo X",
+" .XXXXXXXoooo X",
+" .XXXXXXXX    X",
+" .XXXXXXXXXXXXX",
+" .XooooooXXXXXX",
+" .Xoooooo XXXXX",
+" .XX      XXXXX",
+" .XXXXXXXXXXXXX",
+" .XXXXXXXXXXXXX"};
diff --git a/bitmaps/mnstrkup.xpm b/bitmaps/mnstrkup.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static char * mnstrkup_xpm[] = {
+"15 15 4 1",
+" 	c #965896589658",
+".	c #000000000000",
+"X	c #492449244924",
+"o	c #CF3CCF3CCF3C",
+"              .",
+" XXXXXXXXXXXXX.",
+" XXXXXXXXXXXXX.",
+" XXXXXXXoooXXX.",
+" XXXXXXXooooXX.",
+" XXXXXXXoooo.X.",
+" XXXXXXXoooo.X.",
+" XXXXXXXX....X.",
+" XXXXXXXXXXXXX.",
+" XooooooXXXXXX.",
+" Xoooooo.XXXXX.",
+" XX......XXXXX.",
+" XXXXXXXXXXXXX.",
+" XXXXXXXXXXXXX.",
+"..............."};
diff --git a/bitmaps/nobar.xpm b/bitmaps/nobar.xpm
@@ -0,0 +1,11 @@
+/* XPM */
+static char * nobar_xpm[] = {
+"4 7 1 1",
+" 	c #000000000000",
+"    ",
+"    ",
+"    ",
+"    ",
+"    ",
+"    ",
+"    "};
diff --git a/bitmaps/nodisc.xpm b/bitmaps/nodisc.xpm
@@ -0,0 +1,49 @@
+/* XPM */
+static char * nodisc_xpm[] = {
+"92 30 16 1",
+" 	c #000000000000",
+".	c #FFFFFFFFFFFF",
+"X	c #514451445144",
+"o	c #BEFBBAEABEFB",
+"O	c #186118611861",
+"+	c #69A66DB669A6",
+"@	c #EFBEEFBEEFBE",
+"#	c #596559655965",
+"$	c #38E338E338E3",
+"%	c #DF7DDF7DDF7D",
+"&	c #28A228A228A2",
+"*	c #D75CD75CD75C",
+"=	c #965896589658",
+"-	c #CF3CCF3CCF3C",
+";	c #492449244924",
+":	c #082008200820",
+"                                                                                            ",
+"                                                                                            ",
+"                                                                                            ",
+"                                                                                            ",
+"                                                                                            ",
+"                                                                                            ",
+"                                                                                            ",
+"                                                                                            ",
+"                                                                                            ",
+"                                                                                            ",
+"                                                                                            ",
+"                                                                                            ",
+"                                                                                            ",
+"                                                                                            ",
+"                                                                                            ",
+"       .X     oo    O+o..@o#             o.....o#    $.$   $o..%o#O     $o%..o+             ",
+"       .@&    oo   &%.*++=%.-O           o%++++*.*O  $.$  ;.%=+=%.%:   o.%=++*.*O           ",
+"       ..%&   oo  O%@$     +.o           oo     X.=  $.$  o%     $+   +.o     ;@+           ",
+"       .o@%&  oo  +.&       +.&          oo      =.O $.$  o@$         @o       :            ",
+"       .+&@*O oo  o*        O.+          oo      $.$ $.$  &@....%o$  $.;                    ",
+"       .+ &@-Ooo  oo         .+          oo      $.$ $.$    $+++=%.$ $.$                    ",
+"       .+  X.*oo  =.O       ;.;          oo      =.O $.$         O%o O.=       &O           ",
+"       .+   X..o  O@*O     &@%           oo     ;.=  $.$  +$      %o  =.X     &@o           ",
+"       .+    X.o   X.%=$$;=.%&           o%++++*.*O  $.$ :@.*+$$#*.;  O*.=#$;=.@&           ",
+"       .+     oo    &o....@=O            o.....*+O   $.$  O+*....%;    O+@....=O            ",
+"                       $$&                                   O$$&         &$$               ",
+"                                                                                            ",
+"                                                                                            ",
+"                                                                                            ",
+"                                                                                            "};
diff --git a/bitmaps/null.xpm b/bitmaps/null.xpm
@@ -0,0 +1,35 @@
+/* XPM */
+static char * null_xpm[] = {
+"92 30 2 1",
+" 	c #000000000000",
+".	c #FFFFFFFFFFFF",
+"                                                                                            ",
+"                                                                                            ",
+"                                                                                            ",
+"                                                                                            ",
+"                                                                                            ",
+"                                                                                            ",
+"                                                                                            ",
+"                                                                                            ",
+"                                                                                            ",
+"                                                                                            ",
+"                                                                                            ",
+"                                                                                            ",
+"                                                                                            ",
+"                                                                                            ",
+"                                                                .                           ",
+"                                                                .                           ",
+"                                                                                            ",
+"                                                                                            ",
+"                                                                                            ",
+"                                                                                            ",
+"                                                                .                           ",
+"                                                                .                           ",
+"                                                                                            ",
+"                                                                                            ",
+"                                                                                            ",
+"                                                                                            ",
+"                                                                                            ",
+"                                                                                            ",
+"                                                                                            ",
+"                                                                                            "};
diff --git a/bitmaps/pauseup.xpm b/bitmaps/pauseup.xpm
@@ -0,0 +1,58 @@
+/* XPM */
+static char * pauseup_xpm[] = {
+"79 30 25 1",
+" 	c #CF3CCF3CCF3C",
+".	c #C71BC30BC71B",
+"X	c #000000000000",
+"o	c #CF3CCB2BCF3C",
+"O	c #B6DAB6DAB6DA",
+"+	c #AEBAAEBAAEBA",
+"@	c #A699A699A699",
+"#	c #9E799E799E79",
+"$	c #965892489658",
+"%	c #8E388A288E38",
+"&	c #861782078617",
+"*	c #FFFFFFFFFFFF",
+"=	c #79E779E779E7",
+"-	c #69A66DB669A6",
+";	c #618565956185",
+":	c #59655D755965",
+">	c #514455555144",
+",	c #492449244924",
+"<	c #410341034103",
+"1	c #38E338E338E3",
+"2	c #30C230C230C2",
+"3	c #208124922081",
+"4	c #18611C711861",
+"5	c #104014511040",
+"6	c #08200C300820",
+" ............................................................................ X",
+" oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo X",
+" OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO X",
+" ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ X",
+" @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ X",
+" ############################################################################ X",
+" $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ X",
+" %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% X",
+" &&&&&&&&&&&&&&&&&&&&&&&  &&&&&&&&&&&&&&&&&&&&***&&***&&&&&&&&&&&&&&&&&&&&&&& X",
+" =======================     =================***==***======================= X",
+" -----------------------        --------------***--***----------------------- X",
+" ;;;;;;;;;;;;;;;;;;;;;;;           ;;;;;;;;;;;***;;***;;;;;;;;;;;;;;;;;;;;;;; X",
+" :::::::::::::::::::::::              ::::::::***::***::::::::::::::::::::::: X",
+" >>>>>>>>>>>>>>>>>>>>>>>                 >>>>>***>>***>>>>>>>>>>>>>>>>>>>>>>> X",
+"o,,,,,,,,,,,,,,,,,,,,,,,                    ,,***,,***,,,,,,,,,,,,,,,,,,,,,,,oX",
+"O<<<<<<<<<<<<<<<<<<<<<<<                    <<***<<***<<<<<<<<<<<<<<<<<<<<<<<OX",
+"@11111111111111111111111                 11111***11***11111111111111111111111@X",
+"$22222222222222222222222              22222222***22***22222222222222222222222$X",
+"&33333333333333333333333           33333333333***33***33333333333333333333333&X",
+"-44444444444444444444444        44444444444444***44***44444444444444444444444-X",
+":55555555555555555555555     55555555555555555***55***55555555555555555555555:X",
+",66666666666666666666666  66666666666666666666***66***66666666666666666666666,X",
+"1XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX1X",
+"3XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX3X",
+"5XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX5X",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"};
diff --git a/bitmaps/playdn.xpm b/bitmaps/playdn.xpm
@@ -0,0 +1,58 @@
+/* XPM */
+static char * playdn_xpm[] = {
+"79 30 25 1",
+" 	c #000000000000",
+".	c #CF3CCF3CCF3C",
+"X	c #C71BC30BC71B",
+"o	c #CF3CCB2BCF3C",
+"O	c #B6DAB6DAB6DA",
+"+	c #AEBAAEBAAEBA",
+"@	c #A699A699A699",
+"#	c #9E799E799E79",
+"$	c #965892489658",
+"%	c #8E388A288E38",
+"&	c #861782078617",
+"*	c #FFFFFFFFFFFF",
+"=	c #79E779E779E7",
+"-	c #69A66DB669A6",
+";	c #618565956185",
+":	c #59655D755965",
+">	c #514455555144",
+",	c #492449244924",
+"<	c #410341034103",
+"1	c #38E338E338E3",
+"2	c #30C230C230C2",
+"3	c #208124922081",
+"4	c #18611C711861",
+"5	c #104014511040",
+"6	c #08200C300820",
+"                                                                               ",
+" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.",
+" .oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo.",
+" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO.",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.",
+" .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@.",
+" .############################################################################.",
+" .$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$.",
+" .%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%.",
+" .&&&&&&&&&&&&&&&&&&&&&&&**&&&&&&&&&&&&&&&&&&&&***&&***&&&&&&&&&&&&&&&&&&&&&&&.",
+" .=======================*****=================***==***=======================.",
+" .-----------------------********--------------***--***-----------------------.",
+" .;;;;;;;;;;;;;;;;;;;;;;;***********;;;;;;;;;;;***;;***;;;;;;;;;;;;;;;;;;;;;;;.",
+" .:::::::::::::::::::::::**************::::::::***::***:::::::::::::::::::::::.",
+" .>>>>>>>>>>>>>>>>>>>>>>>*****************>>>>>***>>***>>>>>>>>>>>>>>>>>>>>>>>.",
+" o,,,,,,,,,,,,,,,,,,,,,,,********************,,***,,***,,,,,,,,,,,,,,,,,,,,,,,o",
+" O<<<<<<<<<<<<<<<<<<<<<<<********************<<***<<***<<<<<<<<<<<<<<<<<<<<<<<O",
+" @11111111111111111111111*****************11111***11***11111111111111111111111@",
+" $22222222222222222222222**************22222222***22***22222222222222222222222$",
+" &33333333333333333333333***********33333333333***33***33333333333333333333333&",
+" -44444444444444444444444********44444444444444***44***44444444444444444444444-",
+" :55555555555555555555555*****55555555555555555***55***55555555555555555555555:",
+" ,66666666666666666666666**66666666666666666666***66***66666666666666666666666,",
+" 1                                                                            1",
+" 3                                                                            3",
+" 5                                                                            5",
+"                                                                               ",
+"                                                                               ",
+"                                                                               ",
+"                                                                               "};
diff --git a/bitmaps/playup.xpm b/bitmaps/playup.xpm
@@ -0,0 +1,58 @@
+/* XPM */
+static char * playup_xpm[] = {
+"79 30 25 1",
+" 	c #CF3CCF3CCF3C",
+".	c #C71BC30BC71B",
+"X	c #000000000000",
+"o	c #CF3CCB2BCF3C",
+"O	c #B6DAB6DAB6DA",
+"+	c #AEBAAEBAAEBA",
+"@	c #A699A699A699",
+"#	c #9E799E799E79",
+"$	c #965892489658",
+"%	c #8E388A288E38",
+"&	c #861782078617",
+"*	c #FFFFFFFFFFFF",
+"=	c #79E779E779E7",
+"-	c #69A66DB669A6",
+";	c #618565956185",
+":	c #59655D755965",
+">	c #514455555144",
+",	c #492449244924",
+"<	c #410341034103",
+"1	c #38E338E338E3",
+"2	c #30C230C230C2",
+"3	c #208124922081",
+"4	c #18611C711861",
+"5	c #104014511040",
+"6	c #08200C300820",
+" ............................................................................ X",
+" oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo X",
+" OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO X",
+" ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ X",
+" @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ X",
+" ############################################################################ X",
+" $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ X",
+" %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% X",
+" &&&&&&&&&&&&&&&&&&&&&&&**&&&&&&&&&&&&&&&&&&&&   &&   &&&&&&&&&&&&&&&&&&&&&&& X",
+" =======================*****=================   ==   ======================= X",
+" -----------------------********--------------   --   ----------------------- X",
+" ;;;;;;;;;;;;;;;;;;;;;;;***********;;;;;;;;;;;   ;;   ;;;;;;;;;;;;;;;;;;;;;;; X",
+" :::::::::::::::::::::::**************::::::::   ::   ::::::::::::::::::::::: X",
+" >>>>>>>>>>>>>>>>>>>>>>>*****************>>>>>   >>   >>>>>>>>>>>>>>>>>>>>>>> X",
+"o,,,,,,,,,,,,,,,,,,,,,,,********************,,   ,,   ,,,,,,,,,,,,,,,,,,,,,,,oX",
+"O<<<<<<<<<<<<<<<<<<<<<<<********************<<   <<   <<<<<<<<<<<<<<<<<<<<<<<OX",
+"@11111111111111111111111*****************11111   11   11111111111111111111111@X",
+"$22222222222222222222222**************22222222   22   22222222222222222222222$X",
+"&33333333333333333333333***********33333333333   33   33333333333333333333333&X",
+"-44444444444444444444444********44444444444444   44   44444444444444444444444-X",
+":55555555555555555555555*****55555555555555555   55   55555555555555555555555:X",
+",66666666666666666666666**66666666666666666666   66   66666666666666666666666,X",
+"1XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX1X",
+"3XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX3X",
+"5XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX5X",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"};
diff --git a/bitmaps/plscddn.xpm b/bitmaps/plscddn.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static char * plscddn_xpm[] = {
+"15 15 4 1",
+" 	c #000000000000",
+".	c #965896589658",
+"X	c #492449244924",
+"o	c #FFFFFFFFFFFF",
+"               ",
+" ..............",
+" .XXXXXXXXXXXXX",
+" .XXXXXXXXXXXXX",
+" .XXXXXoooooXXX",
+" .XXXXoooooooXX",
+" .XXXXooooooo X",
+" .XXXXoooXooo X",
+" .XXXoo.ooooo X",
+" .XXXoo ooooo X",
+" .Xoooooo.oo  X",
+" .Xoooooo    XX",
+" .XX oo   XXXXX",
+" .XXXoo XXXXXXX",
+" .XXXX  XXXXXXX"};
diff --git a/bitmaps/plscdup.xpm b/bitmaps/plscdup.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static char * plscdup_xpm[] = {
+"15 15 4 1",
+" 	c #965896589658",
+".	c #000000000000",
+"X	c #492449244924",
+"o	c #CF3CCF3CCF3C",
+"              .",
+" XXXXXXXXXXXXX.",
+" XXXXXXXXXXXXX.",
+" XXXXXoooooXXX.",
+" XXXXoooooooXX.",
+" XXXXooooooo.X.",
+" XXXXoooXooo.X.",
+" XXXoo ooooo.X.",
+" XXXoo.ooooo.X.",
+" Xoooooo oo..X.",
+" Xoooooo....XX.",
+" XX.oo...XXXXX.",
+" XXXoo.XXXXXXX.",
+" XXXX..XXXXXXX.",
+"..............."};
diff --git a/bitmaps/plstrkdn.xpm b/bitmaps/plstrkdn.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static char * plstrkdn_xpm[] = {
+"15 15 4 1",
+" 	c #000000000000",
+".	c #965896589658",
+"X	c #492449244924",
+"o	c #FFFFFFFFFFFF",
+"               ",
+" ..............",
+" .XXXXXXXXXXXXX",
+" .XXXXXXXXXXXXX",
+" .XXXXXXXoooXXX",
+" .XXXXXXXooooXX",
+" .XXXXXXXoooo X",
+" .XXXXXXXoooo X",
+" .XXXooXXX    X",
+" .XXXoo XXXXXXX",
+" .XooooooXXXXXX",
+" .Xoooooo XXXXX",
+" .XX oo   XXXXX",
+" .XXXoo XXXXXXX",
+" .XXXX  XXXXXXX"};
diff --git a/bitmaps/plstrkup.xpm b/bitmaps/plstrkup.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static char * plstrkup_xpm[] = {
+"15 15 4 1",
+" 	c #965896589658",
+".	c #000000000000",
+"X	c #492449244924",
+"o	c #CF3CCF3CCF3C",
+"              .",
+" XXXXXXXXXXXXX.",
+" XXXXXXXXXXXXX.",
+" XXXXXXXoooXXX.",
+" XXXXXXXooooXX.",
+" XXXXXXXoooo.X.",
+" XXXXXXXoooo.X.",
+" XXXooXXX....X.",
+" XXXoo.XXXXXXX.",
+" XooooooXXXXXX.",
+" Xoooooo.XXXXX.",
+" XX.oo...XXXXX.",
+" XXXoo.XXXXXXX.",
+" XXXX..XXXXXXX.",
+"..............."};
diff --git a/bitmaps/redbar.xpm b/bitmaps/redbar.xpm
@@ -0,0 +1,16 @@
+/* XPM */
+static char * redbar_xpm[] = {
+"4 7 6 1",
+" 	c #000000000000",
+".	c #79E700000000",
+"X	c #CF3C00000000",
+"o	c #AEBA00000000",
+"O	c #FFFF00000000",
+"+	c #DF7D00000000",
+" .X ",
+" oO ",
+" oO ",
+" oO ",
+" oO ",
+" .+ ",
+"  o "};
diff --git a/bitmaps/rewdn.xpm b/bitmaps/rewdn.xpm
@@ -0,0 +1,59 @@
+/* XPM */
+static char * rewdn_xpm[] = {
+"29 30 26 1",
+" 	c None",
+".	c #000000",
+"+	c #CFCFCF",
+"@	c #C7C3C7",
+"#	c #CFCBCF",
+"$	c #B6B6B6",
+"%	c #AEAEAE",
+"&	c #A6A6A6",
+"*	c #9E9E9E",
+"=	c #969296",
+"-	c #8E8A8E",
+";	c #868286",
+">	c #FFFFFF",
+",	c #797979",
+"'	c #696D69",
+")	c #616561",
+"!	c #595D59",
+"~	c #515551",
+"{	c #494949",
+"]	c #414141",
+"^	c #383838",
+"/	c #303030",
+"(	c #202420",
+"_	c #181C18",
+":	c #101410",
+"<	c #080C08",
+".............................",
+".+@@@@@@@@@@@@@@@@@@@@@@@@@@+",
+".+##########################+",
+".+$$$$$$$$$$$$$$$$$$$$$$$$$$+",
+".+%%%%%%%%%%%%%%%%%%%%%%%%%%+",
+".+&&&&&&&&&&&&&&&&&&&&&&&&&&+",
+".+**************************+",
+".+==========================+",
+".+--------------------------+",
+".+;;;;>>;;;;;;>>;;;;;;;;;;;;+",
+".+,,,,>>,,,,,>>>,,,,,,,,,,,,+",
+".+''''>>''''>>>>''''''''''''+",
+".+))))>>)))>>>>>))))))))))))+",
+".+!!!!>>!!>>>>>>!!!!!!!!!!!!+",
+".+~~~~>>~>>>>>>>~~~~~~~~~~~~+",
+".#{{{{>>>>>>>>>>{{{{{{{{{{{{#",
+".$]]]]>>>>>>>>>>]]]]]]]]]]]]$",
+".&^^^^>>^>>>>>>>^^^^^^^^^^^^&",
+".=////>>//>>>>>>////////////=",
+".;((((>>(((>>>>>((((((((((((;",
+".'____>>____>>>>____________'",
+".!::::>>:::::>>>::::::::::::!",
+".{<<<<>><<<<<<>><<<<<<<<<<<<{",
+".^..........................^",
+".(..........................(",
+".:..........................:",
+".............................",
+".............................",
+".............................",
+"............................."};
diff --git a/bitmaps/rewup.xpm b/bitmaps/rewup.xpm
@@ -0,0 +1,57 @@
+/* XPM */
+static char * rewup_xpm[] = {
+"29 30 24 1",
+" 	c #CF3CCF3CCF3C",
+".	c #C71BC30BC71B",
+"X	c #000000000000",
+"o	c #CF3CCB2BCF3C",
+"O	c #B6DAB6DAB6DA",
+"+	c #AEBAAEBAAEBA",
+"@	c #A699A699A699",
+"#	c #9E799E799E79",
+"$	c #965892489658",
+"%	c #8E388A288E38",
+"&	c #861782078617",
+"*	c #79E779E779E7",
+"=	c #69A66DB669A6",
+"-	c #618565956185",
+";	c #59655D755965",
+":	c #514455555144",
+">	c #492449244924",
+",	c #410341034103",
+"<	c #38E338E338E3",
+"1	c #30C230C230C2",
+"2	c #208124922081",
+"3	c #18611C711861",
+"4	c #104014511040",
+"5	c #08200C300820",
+" .......................... X",
+" oooooooooooooooooooooooooo X",
+" OOOOOOOOOOOOOOOOOOOOOOOOOO X",
+" ++++++++++++++++++++++++++ X",
+" @@@@@@@@@@@@@@@@@@@@@@@@@@ X",
+" ########################## X",
+" $$$$$$$$$$$$$$$$$$$$$$$$$$ X",
+" %%%%%%%%%%%%%%%%%%%%%%%%%% X",
+" &&&&  &&&&&&  &&&&&&  &&&& X",
+" ****  *****   *****   **** X",
+" ====  ====    ====    ==== X",
+" ----  ---     ---     ---- X",
+" ;;;;  ;;      ;;      ;;;; X",
+" ::::  :       :       :::: X",
+"o>>>>                  >>>>oX",
+"O,,,,                  ,,,,OX",
+"@<<<<  <       <       <<<<@X",
+"$1111  11      11      1111$X",
+"&2222  222     222     2222&X",
+"=3333  3333    3333    3333=X",
+";4444  44444   44444   4444;X",
+">5555  555555  555555  5555>X",
+"<XXXXXXXXXXXXXXXXXXXXXXXXXX<X",
+"2XXXXXXXXXXXXXXXXXXXXXXXXXX2X",
+"4XXXXXXXXXXXXXXXXXXXXXXXXXX4X",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXX"};
diff --git a/bitmaps/rptdn.xpm b/bitmaps/rptdn.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static char * rptdn_xpm[] = {
+"15 15 4 1",
+" 	c #000000000000",
+".	c #965896589658",
+"X	c #492449244924",
+"o	c #FFFFFFFFFFFF",
+"               ",
+" ..............",
+" .XXXXXXXXXXXXX",
+" .XXXXXXXXoXXXX",
+" .XXXXXXXXooXXX",
+" .XXXooooooooXX",
+" .XXooooooooo X",
+" .Xooo    oo  X",
+" .Xoo  XXXo  XX",
+" .Xoo XXXXX XXX",
+" .XoooXXXXXXXXX",
+" .XXoooooooooXX",
+" .XXXooooooo  X",
+" .XXXX       XX",
+" .XXXXXXXXXXXXX"};
diff --git a/bitmaps/rptup.xpm b/bitmaps/rptup.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static char * rptup_xpm[] = {
+"15 15 4 1",
+" 	c #965896589658",
+".	c #000000000000",
+"X	c #492449244924",
+"o	c #CF3CCF3CCF3C",
+"              .",
+" XXXXXXXXXXXXX.",
+" XXXXXXXXoXXXX.",
+" XXXXXXXXooXXX.",
+" XXXooooooooXX.",
+" XXooooooooo.X.",
+" Xooo....oo..X.",
+" Xoo..XXXo..XX.",
+" Xoo.XXXXX.XXX.",
+" XoooXXXXXXXXX.",
+" XXoooooooooXX.",
+" XXXooooooo..X.",
+" XXXX.......XX.",
+" XXXXXXXXXXXXX.",
+"..............."};
diff --git a/bitmaps/rptupact.xpm b/bitmaps/rptupact.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static char * rptupact_xpm[] = {
+"15 15 4 1",
+" 	c #965896589658",
+".	c #000000000000",
+"X	c #492449244924",
+"o	c #FFFFFFFFFFFF",
+"              .",
+" XXXXXXXXXXXXX.",
+" XXXXXXXXoXXXX.",
+" XXXXXXXXooXXX.",
+" XXXooooooooXX.",
+" XXooooooooo.X.",
+" Xooo....oo..X.",
+" Xoo..XXXo..XX.",
+" Xoo.XXXXX.XXX.",
+" XoooXXXXXXXXX.",
+" XXoooooooooXX.",
+" XXXooooooo..X.",
+" XXXX.......XX.",
+" XXXXXXXXXXXXX.",
+"..............."};
diff --git a/bitmaps/sfwddn.xpm b/bitmaps/sfwddn.xpm
@@ -0,0 +1,59 @@
+/* XPM */
+static char * sfwddn_xpm[] = {
+"29 30 26 1",
+" 	c None",
+".	c #000000",
+"+	c #CFCFCF",
+"@	c #C7C3C7",
+"#	c #CFCBCF",
+"$	c #B6B6B6",
+"%	c #AEAEAE",
+"&	c #A6A6A6",
+"*	c #9E9E9E",
+"=	c #969296",
+"-	c #8E8A8E",
+";	c #868286",
+">	c #FFFFFF",
+",	c #797979",
+"'	c #696D69",
+")	c #616561",
+"!	c #595D59",
+"~	c #515551",
+"{	c #494949",
+"]	c #414141",
+"^	c #383838",
+"/	c #303030",
+"(	c #202420",
+"_	c #181C18",
+":	c #101410",
+"<	c #080C08",
+".............................",
+".+@@@@@@@@@@@@@@@@@@@@@@@@@@+",
+".+##########################+",
+".+$$$$$$$$$$$$$$$$$$$$$$$$$$+",
+".+%%%%%%%%%%%%%%%%%%%%%%%%%%+",
+".+&&&&&&&&&&&&&&&&&&&&&&&&&&+",
+".+**************************+",
+".+==========================+",
+".+--------------------------+",
+".+;;;;>>;;;;;;>>;;;;;;;;;;;;+",
+".+,,,,>>>,,,,,>>>,,,,,,,,,,,+",
+".+''''>>>>''''>>>>''''''''''+",
+".+))))>>>>>)))>>>>>)))))))))+",
+".+!!!!>>>>>>!!>>>>>>!!!!!!!!+",
+".+~~~~>>>>>>>~>>>>>>>~~~~~~~+",
+".#{{{{>>>>>>>>>>>>>>>>{{{{{{#",
+".$]]]]>>>>>>>>>>>>>>>>]]]]]]$",
+".&^^^^>>>>>>>^>>>>>>>^^^^^^^&",
+".=////>>>>>>//>>>>>>////////=",
+".;((((>>>>>(((>>>>>(((((((((;",
+".'____>>>>____>>>>__________'",
+".!::::>>>:::::>>>:::::::::::!",
+".{<<<<>><<<<<<>><<<<<<<<<<<<{",
+".^..........................^",
+".(..........................(",
+".:..........................:",
+".............................",
+".............................",
+".............................",
+"............................."};
diff --git a/bitmaps/slice.xpm b/bitmaps/slice.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static char * slice_xpm[] = {
+"15 15 4 1",
+" 	c #965896589658",
+".	c #000000000000",
+"X	c #492449244924",
+"o	c #CF3CCF3CCF3C",
+"              .",
+" XXXXXXXXXXXXX.",
+" XXXXXXXXXXXXX.",
+" XXXXXXXoooXXX.",
+" XXXXXXXooooXX.",
+" XXXXXXXoooo.X.",
+" XXXXXXXoooo.X.",
+" XXXXXXXX....X.",
+" XXXXXXXXXXXXX.",
+" XXXXXXXXXXXXX.",
+" XXXXXXXXXXXXX.",
+" XXXXXXXXXXXXX.",
+" XXXXXXXXXXXXX.",
+" XXXXXXXXXXXXX.",
+"..............."};
diff --git a/bitmaps/srevdn.xpm b/bitmaps/srevdn.xpm
@@ -0,0 +1,59 @@
+/* XPM */
+static char * srevdn_xpm[] = {
+"29 30 26 1",
+" 	c None",
+".	c #000000",
+"+	c #CFCFCF",
+"@	c #C7C3C7",
+"#	c #CFCBCF",
+"$	c #B6B6B6",
+"%	c #AEAEAE",
+"&	c #A6A6A6",
+"*	c #9E9E9E",
+"=	c #969296",
+"-	c #8E8A8E",
+";	c #868286",
+">	c #FFFFFF",
+",	c #797979",
+"'	c #696D69",
+")	c #616561",
+"!	c #595D59",
+"~	c #515551",
+"{	c #494949",
+"]	c #414141",
+"^	c #383838",
+"/	c #303030",
+"(	c #202420",
+"_	c #181C18",
+":	c #101410",
+"<	c #080C08",
+".............................",
+".+@@@@@@@@@@@@@@@@@@@@@@@@@@+",
+".+##########################+",
+".+$$$$$$$$$$$$$$$$$$$$$$$$$$+",
+".+%%%%%%%%%%%%%%%%%%%%%%%%%%+",
+".+&&&&&&&&&&&&&&&&&&&&&&&&&&+",
+".+**************************+",
+".+==========================+",
+".+--------------------------+",
+".+;;;;;;;;;;;;>>;;;;;;>>;;;;+",
+".+,,,,,,,,,,,>>>,,,,,>>>,,,,+",
+".+''''''''''>>>>''''>>>>''''+",
+".+)))))))))>>>>>)))>>>>>))))+",
+".+!!!!!!!!>>>>>>!!>>>>>>!!!!+",
+".+~~~~~~~>>>>>>>~>>>>>>>~~~~+",
+".#{{{{{{>>>>>>>>>>>>>>>>{{{{#",
+".$]]]]]]>>>>>>>>>>>>>>>>]]]]$",
+".&^^^^^^^>>>>>>>^>>>>>>>^^^^&",
+".=////////>>>>>>//>>>>>>////=",
+".;(((((((((>>>>>(((>>>>>((((;",
+".'__________>>>>____>>>>____'",
+".!:::::::::::>>>:::::>>>::::!",
+".{<<<<<<<<<<<<>><<<<<<>><<<<{",
+".^..........................^",
+".(..........................(",
+".:..........................:",
+".............................",
+".............................",
+".............................",
+"............................."};
diff --git a/bitmaps/stopup.xpm b/bitmaps/stopup.xpm
@@ -0,0 +1,57 @@
+/* XPM */
+static char * stopup_xpm[] = {
+"79 30 24 1",
+" 	c #CF3CCF3CCF3C",
+".	c #C71BC30BC71B",
+"X	c #000000000000",
+"o	c #CF3CCB2BCF3C",
+"O	c #B6DAB6DAB6DA",
+"+	c #AEBAAEBAAEBA",
+"@	c #A699A699A699",
+"#	c #9E799E799E79",
+"$	c #965892489658",
+"%	c #8E388A288E38",
+"&	c #861782078617",
+"*	c #79E779E779E7",
+"=	c #69A66DB669A6",
+"-	c #618565956185",
+";	c #59655D755965",
+":	c #514455555144",
+">	c #492449244924",
+",	c #410341034103",
+"<	c #38E338E338E3",
+"1	c #30C230C230C2",
+"2	c #208124922081",
+"3	c #18611C711861",
+"4	c #104014511040",
+"5	c #08200C300820",
+" ............................................................................ X",
+" oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo X",
+" OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO X",
+" ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ X",
+" @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ X",
+" ############################################################################ X",
+" $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ X",
+" %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% X",
+" &&&&&&&&&&&&&&&&&&&&&&&  &&&&&&&&&&&&&&&&&&&&   &&   &&&&&&&&&&&&&&&&&&&&&&& X",
+" ***********************     *****************   **   *********************** X",
+" =======================        ==============   ==   ======================= X",
+" -----------------------           -----------   --   ----------------------- X",
+" ;;;;;;;;;;;;;;;;;;;;;;;              ;;;;;;;;   ;;   ;;;;;;;;;;;;;;;;;;;;;;; X",
+" :::::::::::::::::::::::                 :::::   ::   ::::::::::::::::::::::: X",
+"o>>>>>>>>>>>>>>>>>>>>>>>                    >>   >>   >>>>>>>>>>>>>>>>>>>>>>>oX",
+"O,,,,,,,,,,,,,,,,,,,,,,,                    ,,   ,,   ,,,,,,,,,,,,,,,,,,,,,,,OX",
+"@<<<<<<<<<<<<<<<<<<<<<<<                 <<<<<   <<   <<<<<<<<<<<<<<<<<<<<<<<@X",
+"$11111111111111111111111              11111111   11   11111111111111111111111$X",
+"&22222222222222222222222           22222222222   22   22222222222222222222222&X",
+"=33333333333333333333333        33333333333333   33   33333333333333333333333=X",
+";44444444444444444444444     44444444444444444   44   44444444444444444444444;X",
+">55555555555555555555555  55555555555555555555   55   55555555555555555555555>X",
+"<XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX<X",
+"2XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX2X",
+"4XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX4X",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"};
diff --git a/bitmaps/voldn.xpm b/bitmaps/voldn.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static char * voldn_xpm[] = {
+"15 15 4 1",
+" 	c #000000000000",
+".	c #965896589658",
+"X	c #492449244924",
+"o	c #FFFFFFFFFFFF",
+"               ",
+" ..............",
+" .XXXXXXXXXXXXX",
+" .XXXXXXoXXoXXX",
+" .XXXXXoo XXoXX",
+" .XXXXooo oXo X",
+" .XXXoooo o o X",
+" .Xoooooo o o X",
+" .Xoooooo o o X",
+" .XX oooo o o X",
+" .XXXXooo o o X",
+" .XXXXXoo X o X",
+" .XXXXXXo XoX X",
+" .XXXXXXX XX XX",
+" .XXXXXXXXXXXXX"};
diff --git a/bitmaps/volup.xpm b/bitmaps/volup.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static char * volup_xpm[] = {
+"15 15 4 1",
+" 	c #965896589658",
+".	c #000000000000",
+"X	c #492449244924",
+"o	c #CF3CCF3CCF3C",
+"              .",
+" XXXXXXXXXXXXX.",
+" XXXXXXoXXoXXX.",
+" XXXXXoo.XXoXX.",
+" XXXXooo.oXo.X.",
+" XXXoooo.o.o.X.",
+" Xoooooo.o.o.X.",
+" Xoooooo.o.o.X.",
+" XX.oooo.o.o.X.",
+" XXXXooo.o.o.X.",
+" XXXXXoo.X.o.X.",
+" XXXXXXo.XoX.X.",
+" XXXXXXX.XX.XX.",
+" XXXXXXXXXXXXX.",
+"..............."};
diff --git a/cd_control.c b/cd_control.c
@@ -0,0 +1,415 @@
+/* -----------------------------------------------------------------------
+   cd_control process
+
+   part of XfreeCD
+
+   Copyright (C) 1998 Brian C. Lane
+   nexus@tatoosh.com
+   http://www.tatoosh.com/nexus
+
+   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.
+   
+   ==========================[ HISTORY ]==================================
+   06/22/98   Bug in track length calculation. It was waiting until track
+              #2 before calculating the lengths (holdover from the change
+	      to 0 offset from 1 offset). FIXED.
+
+   05/08/98   Added the control and init code from old version of xfreecd
+              Added software control of the EJECT on CLOSE state - using
+	      the CD_SET_EJECT command and an argument of 0 to disable
+	      eject on exit and 1 to enable eject on exit.
+
+   05/03/98   Wrote the synchronization code and basic switch statment.
+              Testing different shutdown situations. No hungup child
+	      processes yet.
+
+	      Things this process needs to do:
+	      x 1. Get the data on the current CD and send it to the
+	           parent, in response to a request by the parent.
+	      x 2. Play a CD
+	      x 3. Pause a CD
+	      x 4. Resume a CD
+	      x 5. Go to next track
+	      x 6. Go to Previous track
+	      x 8. Eject a CD
+	      x 9. Close the CD tray
+	     10. Switch CDs for a CD changer
+	     11. Seek forward (may need a kernel patch?)
+	     12. Seek backwards (may need a kernel patch?)
+	     13. Return error/status codes (like if a play is tried and
+	         there is no CD in the player).
+	     14. Shuffle play (on one Cd or among multiple CDs)
+	     15. Repeat Song
+	     16. Repeat whole CD, repeat group of CDs
+
+
+   ----------------------------------------------------------------------- */
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <gtk/gtk.h>
+#include "child_sync.h"
+#include "cd_control.h"
+#include "cddb.h"
+
+int cd_control( int );
+int readline( register int, register char *, register int );
+
+#undef DEBUG1
+#undef DEBUG3
+
+/*
+   Fire up the cd_control process.
+   Create a socket pair.
+   Fork a child process
+   Return the parent's file descriptor for the socket or -1 + errno
+   fill in childpid with the child's PID
+   Child calls cd_control 
+*/
+int start_cd_control( int *childpid )
+{
+  int  fd[2];
+
+  if( socketpair( AF_UNIX, SOCK_STREAM, 0, fd ) < 0 )
+    return(-1);
+
+  if( ( *childpid = fork() ) < 0 )
+  {
+    perror("start_cd_control, cannot fork");
+    return(-1);
+  } else if( *childpid == 0 ) {
+    close( fd[0] );
+
+    /* Synchronize with the parent, exit if it fails */
+    if( parent_sync( fd[1] ) == 0 )
+      cd_control( fd[1] );
+    
+    close( fd[1] );
+    exit(0);
+  } 
+  close( fd[1] );
+
+  if( child_sync( fd[0] ) == 0 )
+    return(fd[0]);  
+
+  return(-1);
+}
+
+
+/*
+   Load a new CD, read all of its info into the cdinfo array
+*/
+int cdrom_init( struct CDINFO *cdinfo, struct cdrom_volctrl *volctrl, char *cd_device )
+{
+  int  fd;
+  int  x;
+
+  /* Try and open the /dev/cdrom device */
+  if( ( fd = open( cd_device, O_RDONLY ) ) < 0 )
+    {
+#ifdef DEBUG3
+      g_print( "device = %s\n", cd_device);
+#endif
+
+      perror("CDROM device" );
+      return -1;
+    }
+  
+  /* Read the cdrom's header information */
+  if( ioctl( fd, CDROMREADTOCHDR, &cdinfo->tochdr ) != 0 )
+    {
+      perror("cdrom_init(CDROMREADTOCHDR-2)" );
+      return -1;
+    }
+
+  /* Get the time on the end of the last track */
+  cdinfo->leadout.cdte_track  = CDROM_LEADOUT;
+  cdinfo->leadout.cdte_format = CDROM_MSF;
+
+  if( ioctl( fd, CDROMREADTOCENTRY, &cdinfo->leadout ) != 0 )
+    {
+      perror( "cdrom_init(CDROMREADTOCENTRY-2)" );
+      return -1;
+    }
+
+  /* Calculate the total length of the CD */
+  cdinfo->cd_length = cdinfo->leadout.cdte_addr.msf.second \
+                     + (cdinfo->leadout.cdte_addr.msf.minute * 60);
+
+  /* Read the current CD volume level - different from soundcard volume */
+  if( ioctl( fd, CDROMVOLREAD, volctrl ) == 0 )
+    { 
+      cdinfo->volume = volctrl->channel0;
+    } else {
+      perror( "cdrom_init(CDROMVOLREAD-2)" );
+      return -1;
+    }
+
+  /* Fill in the tracks[] array with info on all the tracks */
+  for( x = 0; x < cdinfo->tochdr.cdth_trk1; x++ )
+    {
+      /* Read the info for the current track */
+      cdinfo->track[x].te.cdte_track  = x+1;
+      cdinfo->track[x].te.cdte_format = CDROM_MSF;
+      if( ioctl( fd, CDROMREADTOCENTRY, &cdinfo->track[x].te ) != 0 )
+	{
+	  perror( "set_track_length(CDROMREADTOCENTRY)" );
+	  return -1;
+	}
+
+      cdinfo->track[x].frame_offset = cdinfo->track[x].te.cdte_addr.msf.minute * 60 + cdinfo->track[x].te.cdte_addr.msf.second;
+
+      /* Convert seconds to frames */
+      cdinfo->track[x].frame_offset *= 75;
+      cdinfo->track[x].frame_offset += cdinfo->track[x].te.cdte_addr.msf.frame;
+
+      /* 
+       * Set the length of the previous track
+       *  Accomplished by taking the start of the current track - start
+       *  of the previous track.
+       */
+      if( x > 0 )
+	{
+	  /* Set length to the start of the current one */
+	  cdinfo->track[x-1].length = (cdinfo->track[x].te.cdte_addr.msf.minute * 60) + cdinfo->track[x].te.cdte_addr.msf.second;
+
+	  /* Subtract the start of the previous track */
+	  cdinfo->track[x-1].length = cdinfo->track[x-1].length - ((cdinfo->track[x-1].te.cdte_addr.msf.minute * 60) + cdinfo->track[x-1].te.cdte_addr.msf.second);
+
+#ifdef DEBUG1
+	  /* Show some debug data on the tracks we find */
+	  g_print("track %d - length = %d seconds\n", x-1, cdinfo->track[x-1].length );
+#endif
+	}
+    }
+
+  /* 
+   * Set the length of the last track
+   * This is accomplished by subtracting the last track start from the
+   * length of the CD.
+   */
+  x--;
+  cdinfo->track[x].length = cdinfo->cd_length - ((cdinfo->track[x].te.cdte_addr.msf.minute * 60) + cdinfo->track[x].te.cdte_addr.msf.second );
+
+#ifdef DEBUG1
+  /* Show debug data on the last track */
+  g_print("track %d - length = %d seconds\n", x, cdinfo->track[x].length );
+  
+  g_print("New CD loaded: ");
+  g_print("%d tracks, cd_length = %d, ", cdinfo->tochdr.cdth_trk1, cdinfo->cd_length );
+  g_print("volume = %d\n", cdinfo->volume );
+#endif		
+
+  /* Calculate the discid for this CD */
+  cdinfo->discid = cddb_discid( cdinfo );
+
+  cdinfo->revision = -1;
+  cdinfo->extd = NULL;
+
+
+  /* All is well */
+  return fd;
+}
+
+
+/* ----------------------------------------------------------------------
+   Control the low-level audio CD player
+
+   Wait for commands from the parent, execute the command and send back
+   a response if one is needed
+
+   A command is 2 bytes of data - a command and an optional argument.
+   The Commands are defined in cd_control.h as CD_*
+
+   To init the cd, if status is called the first time it will try to init
+   the CD. If this fails it sets cd_fd to -1, so status won't repeatedly
+   try the CD. After the initial failure only a play will try.
+
+   ----------------------------------------------------------------------- */
+int cd_control( int control_fd )
+{
+  char   cmnd[2],
+         cd_device[80];                 /* Device to talk to */
+  struct cdrom_volctrl volctrl;  	/* Volume control 		 */
+  struct CDINFO cdinfo;                 /* All the info on the CD        */
+  int  fd_cd=0;
+
+  /* Default cdrom device */
+  strcpy( cd_device, "/dev/cdrom" );
+
+  for(;;)
+  {
+    /* Get the command from the parent process */
+    if( read( control_fd, &cmnd, 2 ) != 2 )
+      return(-1);
+
+    switch( cmnd[0] )
+      {
+      case CD_DIAG :
+	puts("cd_control diagnostic\n");
+	break;
+
+      case CD_STATUS :
+	if( fd_cd > 0 )
+	  {
+	    cdinfo.sc.cdsc_format = CDROM_MSF;     /* Info in MM:SS:FF format*/
+	    if( ioctl( fd_cd, CDROMSUBCHNL, &cdinfo.sc ) != 0 )
+	      {
+		/* perror( "cd_control(CDROMSUBCHNL-2)" ); */
+		cdinfo.sc.cdsc_audiostatus = CDROM_AUDIO_NO_STATUS;
+	      }
+  	  } else {
+	    cdinfo.sc.cdsc_audiostatus = CDROM_AUDIO_NO_STATUS;
+	  }
+
+	/* Send the new data back to the main process */
+	write( control_fd, &cdinfo, sizeof( struct CDINFO ) );
+	break;
+
+
+      case CD_PLAY :
+	/* If we are not open yet, try to open it first */
+	if( fd_cd < 1 )
+	  {
+	    fd_cd = cdrom_init( &cdinfo, &volctrl, cd_device );
+	    
+	    /* Start playing at the beginning*/
+	    cmnd[1] = cdinfo.tochdr.cdth_trk0;
+	  }
+
+	if( fd_cd > 0 )
+	  {
+	    /* Setup the CD to play the indicated track */
+	    cdinfo.ti.cdti_trk0 = cmnd[1];
+	    cdinfo.ti.cdti_trk1 = cdinfo.tochdr.cdth_trk1;
+	    cdinfo.ti.cdti_ind0 = cdinfo.ti.cdti_ind1 = 0;
+
+	    /* Stop playing previous track and start playing the next */
+	    /* Try this without the stop and see what happens... */
+	    if( ioctl( fd_cd, CDROMSTOP ) != 0 )
+	      {
+		perror( "cd_control(CDROMSTOP-1)" );
+	      } else if( ioctl( fd_cd, CDROMPLAYTRKIND, &cdinfo.ti ) != 0 ) {
+		perror( "cd_control(CDROMPLAYTRKIND-1)" );
+	      }
+	  }
+	break;
+
+      case CD_PAUSE :
+	if( fd_cd > 0 )
+	  {
+	    if( ioctl( fd_cd, CDROMPAUSE ) != 0 )
+	      perror( "cd_control(CDROMPAUSE)" );
+	  }
+	break;
+
+      case CD_RESUME :
+	if( fd_cd > 0 )
+	  {
+	    if( ioctl( fd_cd, CDROMRESUME ) != 0 )
+	      perror( "cd_control(CDROMRESUME)" );
+	  }
+	break;
+
+      case CD_STOP :
+	if( fd_cd > 0 )
+	  {
+	    if( ioctl( fd_cd, CDROMSTOP ) != 0 )
+	      perror( "cd_control(CDROMSTOP-2)" );
+
+	    close( fd_cd );
+	    fd_cd = 0;
+	  }
+	break;
+
+      case CD_VOLUME :
+	if( fd_cd > 0 )
+	  {
+	    cdinfo.volume = (unsigned char) cmnd[1];
+
+	    volctrl.channel0 = cdinfo.volume;
+	    volctrl.channel1 = cdinfo.volume;
+	    if( ioctl( fd_cd, CDROMVOLCTRL, &volctrl ) != 0 )
+	      perror( "cd_control(CDROMVOLCTRL-3)" );
+	  }
+	break;
+
+      case CD_EJECT :
+	if( (fd_cd > 0) )
+	  {
+	    /* Stop playing, then eject the CD */
+	    if( ioctl( fd_cd, CDROMSTOP ) != 0 )
+	      {
+		perror( "cd_control(CDROMSTOP-3)" );
+	      } else  if( ioctl( fd_cd, CDROMEJECT ) != 0 ) {
+		perror( "cd_control(CDROMEJECT)" );
+	      }
+	    close( fd_cd );
+	    fd_cd = 0;
+	  }
+	break;
+
+      case CD_SET_EJECT :
+	if( fd_cd > 0 )
+	  {
+	    /* Set the software configurable eject on close state */
+	    if( ioctl( fd_cd, CDROMEJECT_SW, cmnd[1] ) != 0 )
+	      perror("cd_control(CDROMEJECT_SW)");
+	  }
+	break;
+
+	/* Set the default device, close the current device and open the
+	   new one */
+      case CD_SET_DEVICE :
+
+#ifdef DEBUG3
+	printf("got CD_SET_DEVICE\n");
+#endif
+
+	/*
+	   This routine is different from the others, it reads a string from
+	   the sending process after receiving the 2 byte command
+	*/
+	if( readline( control_fd, cd_device, 80 ) < 0 )
+	  {
+	    perror("readline - 2");	    
+	  }
+
+	/* Strip trailing CR */
+	if( cd_device[strlen(cd_device)-1] == '\n' )
+	  cd_device[strlen(cd_device)-1] = 0;
+
+#ifdef DEBUG3
+	printf("Setting cd_control cd_device = %s\n", cd_device );
+#endif
+	/* If a device isn't open, then open one */
+	if( fd_cd < 1 )
+	  fd_cd = cdrom_init( &cdinfo, &volctrl, cd_device );
+
+	break;
+
+
+      case CD_QUIT :
+	if( fd_cd )
+	  close( fd_cd );
+	return(0);
+	break;
+      }
+  }
+  return(0);
+}
diff --git a/cd_control.h b/cd_control.h
@@ -0,0 +1,85 @@
+/* ------------------------------------------------------------------------
+   cd_control include file for XfreeCD
+
+   Copyright 1998 by Brian C. Lane
+   nexus@tatoosh.com
+   http://www.tatoosh.com/nexus
+
+   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.
+
+   ------------------------------------------------------------------------ */
+#include <linux/cdrom.h>
+
+#define CD_DIAG         0x00
+#define CD_PLAY         0x01
+#define CD_PAUSE        0x02
+#define CD_STOP         0x03
+#define CD_EJECT        0x04
+#define CD_SEEK_FWD     0x05
+#define CD_SEEK_REV     0x06
+#define CD_RESUME       0x07
+#define CD_VOLUME       0x08
+#define CD_STATUS       0x09
+#define CD_TOC          0x0A
+#define CD_QUIT         0x0B
+#define CD_SET_EJECT    0x0C
+#define CD_SET_DEVICE   0x0D
+
+
+int start_cd_control( int * );
+
+
+struct song_info {
+  struct cdrom_tocentry te;             /* TOC entry data               */
+  int                   length;         /* Length of this track in sec  */
+  long                  frame_offset;   /* Frame Offset in 1/75 frames  */
+};
+
+struct CDINFO {
+  unsigned long discid;                 /* cddb disc ID                 */
+  int		disc;			/* disc # being played, for
+  					   future support for jukeboxes
+  					 */
+  int		track_length;		/* Length of current track	*/
+  int		cd_length;		/* Length of the CD		*/
+  int		cd_remaining;		/* Remaining # of seconds on CD	*/
+  int           volume;                 /* Volume setting               */
+
+  /* Info on the current cdrom in the drive */
+  struct cdrom_tochdr tochdr;  		/* TOC Headers			*/
+  struct cdrom_tocentry leadout;	/* Last track info		*/
+  struct cdrom_ti ti;          		/* Track(s) to play 
+					   Track indexing 
+					 */
+  struct cdrom_subchnl sc;     		/* Drive status 		*/
+  struct song_info track[99];           /* Info on songs on this CD     */
+
+  GString          *title;              /* Title of this CD             */
+  GString          *category;           /* CDDBD category               */
+  GString          *name[99];           /* Name of the track            */
+  GString          *extd;               /* Extended data for the CD     */
+  GString          *extt[99];           /* Extended Track info          */
+  int              revision;            /* CDDB entry  revision #       */   
+
+
+  /* Data used for talking to the other processes */
+  int              cddbd_cmnd,          /* Command for cddbd            */
+                   cddbd_stat;          /* Status of process            */
+  char             server[80];          /* Server to connect to         */
+  int              port;                /* Port on server               */
+  char             line[255];           /* Text from MOTD or SITES      */
+  char             local_cddb[1024];    /* Path to local CDDB database  */
+  char             device[80];          /* CDROM device                 */
+};
diff --git a/cddb.c b/cddb.c
@@ -0,0 +1,888 @@
+/* ---------------------------------------------------------------------
+   basic cddb functions for XfreeCD
+
+   Copyright 1998 by Brian C. Lane
+   nexus@tatoosh.com
+   http://www.tatoosh.com/nexus
+
+   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.
+
+   =============================[ HISTORY ]=============================
+   06/19/98     Adding write extended data to the database. DONE.
+                Switching to using g_malloc, g_free, g_realloc -- they're
+		safer than libc and can provide usage stats.
+
+   06/16/98     Need to add support for extended data lines. Split lines
+                too of course. This data needs to make it into the
+		database, and be able to send it to the server when
+		the CD is edited.
+
+		Revision # support needs to be added to. Read it and
+		increment it when the CD is submitted to the server.
+		FIXED.
+
+   06/06/98     I need to support split TTITLE lines, and get the
+                track # from the TTITLE line instead of assuming they
+		just go in order.
+		I found my garbage at the end of the file problem. If
+		A long file was written then it was shortened it
+		wouldn't erase it first, it would just write over
+		the top and leave the old stuff hanging off the end.
+		So I added an unlink to delete it first.
+
+   05/27/98     Adding creation of the cddb database directories if
+                they don't exist (only creates the ones that don't
+		exist). Added to write_cddb(). Only creates what it
+		needs to. This way it isn't limited to a static list of
+		categories. Works.
+		Found a bug. CDDB read/write don't handle multiple
+		DTITLEs very well.
+
+   05/16/98     Added expansion of ~/ to $HOME enviornmental variable
+                Added a local_cddb path in the cdinfo structure to point
+		to the local storage location for writing and reading
+		cd information.
+
+   05/11/98     Split off reading code to read_cddb_file so it can be
+                used to read a specific temporary file after the data
+		is downloaded from the server.
+
+   05/09/98     Started this part of the XfreeCD code. 
+                Correct operation confirmed for discid using
+		Bryan Adams / Waking up the Neighbors id 0xce118c0f
+		Writing database entries works well so far, frames,
+		length, and discid are correct. Default track and title
+		strings are saved ok too.
+		find_discid works.
+
+   ---------------------------------------------------------------------
+   This file includes support for saving and loading local database
+   information.
+   --------------------------------------------------------------------- */
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <gtk/gtk.h>
+#include "xfreecd.h"
+#include "cd_control.h"
+#include "cddb.h"
+
+#undef DEBUG1
+#undef DEBUG2
+#undef DEBUG3
+#undef DEBUG6
+#undef DEBUG9
+
+int
+cddb_sum(int n)
+{
+	char	buf[12],
+		*p;
+	int	ret = 0;
+
+	/* For backward compatibility this algorithm must not change */
+	sprintf(buf, "%lu", n);
+	for (p = buf; *p != '\0'; p++)
+		ret += (*p - '0');
+
+	return (ret);
+}
+
+unsigned long cddb_discid( struct CDINFO *cdinfo )
+{
+  int	i,
+        t = 0,
+        n = 0,
+        tot_trks;
+
+  tot_trks = cdinfo->tochdr.cdth_trk1;
+
+  /* For backward compatibility this algorithm must not change */
+  for (i = 0; i < tot_trks; i++)
+    n += cddb_sum((cdinfo->track[i].te.cdte_addr.msf.minute * 60) + cdinfo->track[i].te.cdte_addr.msf.second);
+  
+  t = ((cdinfo->leadout.cdte_addr.msf.minute * 60) + cdinfo->leadout.cdte_addr.msf.second) - ((cdinfo->track[0].te.cdte_addr.msf.minute * 60) + cdinfo->track[0].te.cdte_addr.msf.second);
+  
+  return ((n % 0xff) << 24 | t << 8 | tot_trks);
+}
+
+
+/* -------------------------------------------------------------------------
+   Write the data from cdinfo structure to the correct file in the selected
+   category.
+
+   The master database directory is in cdinfo->local_cddb
+
+   How do I check for the same CD with a different ID so I can symlink?
+
+   if over is 0 then check to make sure the file doesn't already exist
+   if over is 1 then go ahead and overwrite it.
+
+   return -2 if the file already exists.
+   return -3 if the HOME variable cannot be found
+   return -4 if we had trouble creating the local cddb directories
+   ------------------------------------------------------------------------- */
+int write_cddb( struct CDINFO *cdinfo, int over )
+{
+  char  fname[1024],
+        tmp_fname[1024],
+        tmpstr[255],
+        idstr[9],
+        *p;
+  int   fd,
+        x,
+        i;
+  struct stat   sbuf;
+
+  /* Copy the path to the local datbase to a temporary variable */
+  strncpy( fname, cdinfo->local_cddb, 1023 );
+
+  /* Convert a leading ~ into the user's HOME directory */
+  if( fname[0] == '~' )
+    {
+      /* Copy the reset of the path/filename to tmp_fname */
+      strncpy( tmp_fname, &fname[1], 1023 );
+
+      if( ( p = getenv("HOME") ) == NULL )
+	{
+	  return(-3);
+	}
+      strncpy( fname, p, 1023 );
+
+      /* Make sure there is a slash inbetween */
+      if( (fname[strlen(fname)-1] != '/') && (tmp_fname[0] != '/') )
+	{
+	  strcat( fname, "/" );
+	}
+
+      strncat( fname, tmp_fname, 1023-strlen( p ) );
+    }
+
+#ifdef DEBUG1
+  g_print("write_cddb( %s )\n", fname );
+#endif
+
+  /* 
+     See if we have the top level directory. If not, try to create it.
+  */
+  if( stat( fname, &sbuf ) < 0 )
+    {
+      /* If the top level directory doesn't exist, create it */
+      if( errno == ENOENT )
+	{
+	  /* Try to make the top level directory, if it fails, quit */
+	  if( mkdir( fname, S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH | S_IROTH ) < 0 )
+	    {
+	      return(-4);
+	    }
+	} else {
+	  return(-4);
+	}
+    }
+
+
+  /* Make sure we have slashes between the path and category directory */
+  if( fname[strlen(fname)] != '/' )
+    strcat( fname, "/" );
+  strcat( fname, cdinfo->category->str );
+  if( fname[strlen(fname)] != '/' )
+    strcat( fname, "/" );
+
+  /*
+    See if the category directory exists. If not, create it.
+  */
+  if( stat( fname, &sbuf ) < 0 )
+    {
+      /* If the top level directory doesn't exist, create it */
+      if( errno == ENOENT )
+	{
+	  /* Try to make the category directory, if it fails, quit with an error*/
+	  if( mkdir( fname, S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH | S_IROTH ) < 0 )
+	    {
+	      return(-4);
+	    }
+	} else {
+	  return(-4);
+	}
+    }
+
+  sprintf( idstr, "%08lx", cdinfo->discid );
+  strcat( fname, idstr );
+
+  /* Should we check for prior existance? */  
+  if( !over )
+    {
+      if( ( fd = open( fname, O_RDONLY ) ) != -1 )
+	{
+	  close( fd );
+	  return(-2);
+	}
+    }
+
+  /* Make sure it is deleted */
+  unlink( fname );
+
+  if( ( fd = open( fname, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ) ) < 0 )
+    {
+      return(-1);
+    }
+
+  /* Write the cddb entry from the info in the cdinfostructure */
+  sprintf( tmpstr, "# xmcd CD database file generated by XfreeCD %s\n", VERSION );
+
+  if( write( fd, tmpstr, strlen( tmpstr) ) < 0 )
+    {
+      close( fd );
+      return(-1);
+    }
+
+  sprintf( tmpstr, "#\n# Track frame offsets:\n" );
+  if( write( fd, tmpstr, strlen( tmpstr ) ) < 0 )
+    {
+      close( fd );
+      return(-1);
+    }
+
+  /* Write the frame offset for each track */
+  for( x = 0; x < cdinfo->tochdr.cdth_trk1; x++ )
+    {
+      sprintf( tmpstr, "#\t%ld\n", cdinfo->track[x].frame_offset );
+      if( write( fd, tmpstr, strlen( tmpstr ) ) < 0 )
+	{
+	  close( fd );
+	  return(-1);
+	}
+    }
+
+  strcpy( tmpstr, "#\n" );
+  if( write( fd, tmpstr, strlen( tmpstr ) ) < 0 )
+    {
+      close( fd );
+      return(-1);
+    }
+
+  sprintf( tmpstr, "# Disc length: %d seconds\n#\n", cdinfo->cd_length );
+  if( write( fd, tmpstr, strlen( tmpstr ) ) < 0 )
+    {
+      close( fd );
+      return(-1);
+    }
+ 
+  sprintf( tmpstr, "# Revision: %d\n", cdinfo->revision );
+  if( write( fd, tmpstr, strlen( tmpstr ) ) < 0 )
+    {
+      close( fd );
+      return(-1);
+    }
+
+  sprintf( tmpstr, "# Submitted via: XfreeCD %s\n#\n", VERSION );
+  if( write( fd, tmpstr, strlen( tmpstr ) ) < 0 )
+    {
+      close( fd );
+      return(-1);
+    } 
+
+  sprintf( tmpstr, "DISCID=%08lx\n", cddb_discid( cdinfo ) );
+  if( write( fd, tmpstr, strlen( tmpstr ) ) < 0 )
+    {
+      close( fd );
+      return(-1);
+    } 
+
+  if( (cdinfo->title == NULL) || (cdinfo->title->len == 0) )
+    {
+      if( write( fd, "DTITLE=\n", 8 ) < 0 )
+	{
+	  close( fd );
+	  return(-1);
+	} 
+    } else {
+      /* If the title is too long, split it up into 70 byte chunks */
+      i = 0;
+      p = cdinfo->title->str;
+      while( i < cdinfo->title->len )
+	{
+	  strcpy( tmpstr, "DTITLE=" );
+	  strncat( tmpstr, p, 70 );
+	  strcat( tmpstr, "\n" );
+
+	  if( write( fd, tmpstr, strlen( tmpstr ) ) < 0 )
+	    {
+	      close( fd );
+	      return(-1);
+	    } 
+	  
+	  if( cdinfo->title->len > 70 )
+	    {
+	      p = p + 70;
+	      i += 70;
+	    } else { 
+	      i = cdinfo->title->len;
+	    }
+	}
+    }
+
+  /* Write the titles */
+  for( x = 0; x < cdinfo->tochdr.cdth_trk1; x++ )
+    {
+      if( (cdinfo->name[x] == NULL) || (cdinfo->name[x]->len == 0) )
+	{
+	  sprintf( tmpstr, "TTITLE%d=\n", x );
+	  if( write( fd, tmpstr, strlen( tmpstr ) ) < 0 )
+	    {
+	      close( fd );
+	      return(-1);
+	    } 
+	} else {
+	  
+	  /* If the track name is too long, split it up into 70 byte chunks */
+	  i = 0;
+	  p = cdinfo->name[x]->str;
+	  while( i < cdinfo->name[x]->len )
+	    {
+	      sprintf( tmpstr, "TTITLE%d=", x );
+	      strncat( tmpstr, p, 70 );
+	      strcat( tmpstr, "\n" );
+
+	      if( write( fd, tmpstr, strlen( tmpstr ) ) < 0 )
+		{
+		  close( fd );
+		  return(-1);
+		} 
+
+	      if( cdinfo->name[x]->len > 70 )
+		{
+		  p = p + 70;
+		  i += 70;
+		} else { 
+		  i = cdinfo->name[x]->len;
+		}
+	    }
+	}
+    }
+  
+  /* Check for a null entry first */
+  if( (cdinfo->extd == NULL) || (cdinfo->extd->len == 0) )
+    {
+      if( write( fd, "EXTD=\n", 6 ) < 0 )
+	{
+	  close( fd );
+	  return(-1);
+	} 
+    } else {
+      /* Write the extended disc data to the file. It it is too long, break it
+	 up into 70 byte chuncks
+      */
+      i = 0;
+      p = cdinfo->extd->str;
+      while( i < cdinfo->extd->len )
+	{
+	  strcpy( tmpstr, "EXTD=" );
+	  strncat( tmpstr, p, 70 );
+	  strcat( tmpstr, "\n" );
+	  
+	  if( write( fd, tmpstr, strlen( tmpstr ) ) < 0 )
+	    {
+	      close( fd );
+	      return(-1);
+	    } 
+
+	  if( cdinfo->extd->len > 70 )
+	    {
+	      p = p + 70;
+	      i += 70;
+	    } else { 
+	      i = cdinfo->extd->len;
+	    }
+	}
+    }
+
+  /* Write the extended title information to the database */
+  for( x = 0; x < cdinfo->tochdr.cdth_trk1; x++ )
+    {
+      if( (cdinfo->extt[x] == NULL) || (cdinfo->extt[x]->len == 0) )
+	{
+	  sprintf( tmpstr, "EXTT%d=\n", x );
+	  if( write( fd, tmpstr, strlen( tmpstr ) ) < 0 )
+	    {
+	      close( fd );
+	      return(-1);
+	    } 
+	} else {
+	  /* If the track name is too long, split it up into 70 byte chunks */
+	  i = 0;
+	  p = cdinfo->extt[x]->str;
+	  while( i < cdinfo->extt[x]->len )
+	    {
+	      sprintf( tmpstr, "EXTT%d=", x );
+	      strncat( tmpstr, p, 70 );
+	      strcat( tmpstr, "\n" );
+
+	      if( write( fd, tmpstr, strlen( tmpstr ) ) < 0 )
+		{
+		  close( fd );
+		  return(-1);
+		} 
+
+	      if( cdinfo->extt[x]->len > 70 )
+		{
+		  p = p + 70;
+		  i += 70;
+		} else { 
+		  i = cdinfo->extt[x]->len;
+		}
+	    }
+	}
+    }
+
+  /* XfreeCD doesn't use this at all */
+  if( write( fd, "PLAYORDER=\n", 11 ) < 0 )
+    {
+      close( fd );
+      return(-1);
+    } 
+    
+  close( fd );
+
+  return(0);
+}
+
+
+/* -----------------------------------------------------------------------
+   Search all sub-directories below CDDB_PATH for the file to read
+   Fills in the category with the name of the trailing directory that
+   it is found in.
+
+
+   Return 0 on file found
+   Return -1 on an error
+   Return -2 on no file found
+   ----------------------------------------------------------------------- */
+int find_discid( char *fname,                /* Path to local database */
+		 unsigned long id,           /* discid to search for   */
+		 char *path,                 /* Return full path       */
+		 GString **category )        /* Return category found  */
+{
+  DIR   *dp;
+  struct dirent *dirp;
+  char  idstr[9],
+        tmp_fname[1024],
+        *p;
+  int   fp;
+
+  /* Convert a leading ~ into the user's HOME directory */
+  if( fname[0] == '~' )
+    {
+      /* Copy the reset of the path/filename to tmp_fname */
+      strncpy( tmp_fname, &fname[1], 1023 );
+
+      if( ( p = (char *) getenv("HOME") ) == NULL )
+	{
+	  return(-2);
+	}
+      strncpy( fname, p, 1023 );
+
+      /* Make sure there is a slash inbetween the two */
+      if( (fname[strlen(fname)-1] != '/') && (tmp_fname[0] != '/') )
+	{
+	  strcat( fname, "/" );
+	}
+
+      strncat( fname, tmp_fname, 1023-strlen( p ) );
+    }
+
+#ifdef DEBUG1
+  g_print("find_discid( %s )\n", fname );
+#endif
+
+
+  sprintf( idstr, "%08lx", id );
+
+  if( ( dp = opendir( fname ) ) == NULL )
+    return(-1);
+
+  while( ( dirp = readdir( dp ) ) != NULL )
+    {
+      if( (strcmp(dirp->d_name,"." )==0) || (strcmp(dirp->d_name, "..")==0) )
+	continue;
+
+      strcpy( path, fname );
+      if( path[strlen(path)] != '/' )
+	strcat( path, "/" );
+      strcat( path, dirp->d_name );
+      if( path[strlen(path)] != '/' )
+	strcat( path, "/" );
+      strcat( path, idstr );
+
+      /* Copy the directory name as the category name */
+      if( *category == NULL )
+	*category = g_string_new( dirp->d_name );
+      else
+	*category = g_string_assign( *category, dirp->d_name );
+
+#ifdef DEBUG1
+      g_print("Checking %s\n", path );
+#endif
+
+      /* Does this file exist? */
+      if( ( fp = open( path, O_RDONLY ) ) != -1 )
+	{
+	  close( fp );
+	  closedir( dp );
+	  return(0);
+	}
+    } 
+
+  closedir( dp );
+
+  return(-2);
+}
+
+
+/* -----------------------------------------------------------------------
+   Read the CDDB info from a filename into a cdinfo structure
+   Allocate all needed string storage using gtk's g_string functions
+
+   return -2  = failed to find HOME enviornmental variable
+   ----------------------------------------------------------------------- */
+int read_cddb_file( char *fname, struct CDINFO *tmpinfo )
+{
+  int   gotid,
+        i,
+        x,
+        f;
+  FILE  *fp;
+  char  line[255],
+        discid[9],
+        *p;
+  
+  if( ( fp = fopen( fname, "r" ) ) == NULL )
+    {
+      return(-1);
+    }
+
+  /* Read the cddb file, placing data into tmpinfo */
+  if( fgets( line, 255, fp ) == NULL )
+    {
+      fclose( fp );
+      return(-1);
+    }
+
+  /* Check the file to make sure its a cddb file */
+  if( strncmp( line, "# xmcd", 6 ) != 0 )
+    {
+      fclose( fp );
+      return(-1);
+    }
+
+#ifdef DEBUG1
+  g_print("%s", line );
+#endif
+
+  /* Find the track offsets, abort serarch at the end of comments */
+  while( ( line[0] == '#' ) && ( strncmp( line, "# Track frame offsets:",22 ) != 0 )  )
+    {
+      if( fgets( line, 255, fp ) == NULL )
+	{
+	  fclose( fp );
+	  return(-1);
+	}
+    }
+
+  /* Skip all the reset of the comments up to Revision: */
+  while( line[0] == '#' && (strncmp( line, "# Revision:", 11)!=0) )
+    {
+      if( fgets( line, 255, fp ) == NULL )
+	{
+	  fclose( fp );
+	  return(-1);
+	}
+    }
+
+  /* If we got the Revision line, get the revision # */
+  if( strncmp( line, "# Revision:", 11)==0 )
+    {
+      sscanf( line, "# Revision: %d", &tmpinfo->revision );
+
+      /* Now read the rest of the comments */
+      while( line[0] == '#' )
+	{
+	  if( fgets( line, 255, fp ) == NULL )
+	    {
+	      fclose( fp );
+	      return(-1);
+	    }
+	}
+    }
+
+  /* Read discid lines */
+  /*
+     How should this be handled? check for our id, and discard all others
+     that may be present?
+
+     DISCID= lines are comma seperated and can be multiple lines
+  */
+  gotid = 0;
+  sprintf( discid, "%08lx", tmpinfo->discid );
+  while( strncmp( line, "DISCID=", 7 ) == 0 )
+    {
+      if( strstr( line, discid ) != NULL )
+	gotid = 1;
+      if( fgets( line, 255, fp ) == NULL )
+	{
+	  fclose( fp );
+	  return(-1);
+	}
+    }
+
+  /* Process multiple DTITLE lines and concatanate them */
+  i = 0;
+  f = 0;
+  while( strncmp( line, "DTITLE", 6 ) == 0 )
+  {
+    p = strtok( line, "=\n" );
+    p = strtok( NULL, "=\n" );
+
+    /* Add the title to the tmpinfo.title string */
+    if( f == 0 )
+      {
+	tmpinfo->title = g_string_new( p );
+	f = 1;
+      } else {
+	tmpinfo->title = g_string_append( tmpinfo->title, p );
+      }
+
+    /* Keep reading DTITLE no matter what */
+    if( fgets( line, 255, fp ) == NULL )
+      {
+	fclose( fp );
+	return(-1);
+      }
+  }
+
+#ifdef DEBUG1
+  g_print("title read = %s\n", tmpinfo->title->str );
+#endif
+
+  /*
+     Copy the titles from the TTITLE strings
+
+     This has to:
+       Get the track # from the TTITLEx
+       strcat split title lines up to the limit of storage (255)
+  */
+  x = -1;
+  f = 0;
+  while( strncmp( line, "TTITLE", 6 ) == 0 )
+  {
+    /* Get the track # */
+    p = strtok( &line[6], "=\n" );
+
+    /* Is it a new track? */
+    if( atoi(p) != x )
+      {
+	/* Yes, reset the length counter and track name */
+	i = 0;
+	f = 0;
+	tmpinfo->name[atoi(p)] = NULL;
+      }
+
+    /* Get the track number and make sure its not too big. */
+    if( ( x = atoi( p ) ) < 99 )
+      {
+	/* Get the track name */
+	p = strtok( NULL, "=\n" );
+
+	/* If its blank, then insert default track name */
+	if( p == NULL )
+	  {
+	    tmpinfo->name[x] = NULL;
+	  } else {
+	    if( f == 0 )
+	      {
+		tmpinfo->name[x] = g_string_new( p );
+		f = 1;
+	      } else {
+		tmpinfo->name[x] = g_string_append( tmpinfo->name[x], p );
+	      }
+	  }
+      }
+
+    /* Read the next line */
+    if( fgets( line, 255, fp ) == NULL )
+      {
+	fclose( fp );
+	return(-1);
+      }
+  }
+
+
+  /* Process multiple EXTD lines and concatanate them, dynamically
+     allocating memory at tmpinfo->extd for it
+   */
+  i = 0;
+  f = 0;
+  tmpinfo->extd = NULL;
+  while( strncmp( line, "EXTD", 4 ) == 0 )
+  {
+    /* Add to the data until the end is reached */
+    p = strtok( line, "=\n" );
+    p = strtok( NULL, "=\n" );
+
+    if( p != NULL )
+      {
+	/* Move the pointer and copy the new string */
+	if( f == 0 )
+	  {
+	    tmpinfo->extd = g_string_new( p );
+	    f = 1;
+	  } else {
+	    tmpinfo->extd = g_string_append( tmpinfo->extd, p );
+	  }
+      }
+
+    /* Keep reading lines */
+    if( fgets( line, 255, fp ) == NULL )
+      {
+	fclose( fp );
+	return(-1);
+      }
+  }
+
+
+  /*
+     Copy the extended title data from the EXTTx entries
+
+     This has to:
+       Get the track # from the EXTTx
+       Allocate storage for it and copy it over, and handle multiple lines
+       for each track entry.
+  */
+  x = -1;
+  f = 0;
+  while( strncmp( line, "EXTT", 4 ) == 0 )
+  {
+    /* Get the track # */
+    p = strtok( &line[4], "=\n" );
+
+    /* Is it a new track? */
+    if( atoi(p) != x )
+      {
+	/* Yes, reset the length counter and track name */
+	i = 0;
+        f = 0;
+	tmpinfo->extt[atoi(p)] = NULL;
+      }
+
+    /* Get the track number, make sure it isn't too big */
+    if( ( x = atoi( p ) ) < 99 )
+      {
+	/* Get the extended data from the rest of the line*/
+	p = strtok( NULL, "=\n" );
+
+	/* Process multiple EXTT lines and concatanate them, dynamicly
+	   allocating memory at tmpinfo->extd for it
+	*/
+	if( p != NULL )
+	  {
+	    /* Move the pointer and copy the new string */
+	    if( f == 0 )
+	      {
+		tmpinfo->extt[x] = g_string_new( p );
+		f = 1;
+	      } else {
+		tmpinfo->extt[x] = g_string_append( tmpinfo->extt[x], p );
+	      }
+	  }
+      }
+
+    /* Read the next line */
+    if( fgets( line, 255, fp ) == NULL )
+      {
+	fclose( fp );
+	return(-1);
+      }
+  }
+
+  fclose( fp );
+
+  return(0);
+}
+
+
+/* -----------------------------------------------------------------------
+   Read a cddb entry for the current CD
+
+   This needs to search through the sub-directories in CDDB_PATH to find
+   the discid of the current CD.
+
+   We then read the file, filling in the track names, etc.
+   We should also compare the frame count to make sure it is the
+   correct CD.
+
+   Returns -1 if there was an error
+   Returns -2 if it cannot find the file
+   ----------------------------------------------------------------------- */
+int read_cddb( struct CDINFO *cdinfo )
+{
+  int   x;
+  char  fname[255];
+  struct CDINFO tmpinfo;
+
+  /* Clean out the structure */
+  bzero( &tmpinfo, sizeof( struct CDINFO ) );
+
+  tmpinfo.discid = cdinfo->discid;
+
+  /* Find out where this ID lives and fill in fname with full name */
+  if( find_discid( cdinfo->local_cddb, tmpinfo.discid, fname, &tmpinfo.category ) < 0 )
+    {
+      /* Could not find an entry for this */
+      return(-2);
+    }
+
+  if( read_cddb_file( fname, &tmpinfo ) == 0 )
+    {
+      cdinfo->title = tmpinfo.title;
+      for( x = 0; x < cdinfo->tochdr.cdth_trk1; x++ )
+	{
+	  cdinfo->name[x] = tmpinfo.name[x];
+	}
+
+      /* Copy the category over too */
+      cdinfo->category = tmpinfo.category;
+
+      /* Copy the revision # over if it is valid */
+      if( tmpinfo.revision >= 0 )
+	cdinfo->revision = tmpinfo.revision;
+      else
+	cdinfo->revision = 1;
+
+      /* Copy the extd pointer over */
+      cdinfo->extd = tmpinfo.extd;
+
+      /* Copy all the extended track pointers */
+      for( x = 0; x < 99; x++ )
+	cdinfo->extt[x] = tmpinfo.extt[x];
+    }
+
+  return(0);
+}
diff --git a/cddb.h b/cddb.h
@@ -0,0 +1,27 @@
+/* ------------------------------------------------------------------------
+   cddb include file for XfreeCD
+
+   Copyright 1998 by Brian C. Lane
+   nexus@tatoosh.com
+   http://www.tatoosh.com/nexus
+
+   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.
+
+   ------------------------------------------------------------------------ */
+unsigned long cddb_discid( struct CDINFO * );
+int write_cddb( struct CDINFO *, int );
+int read_cddb( struct CDINFO * );
+int read_cddb_file( char *, struct CDINFO *);
+int find_discid( char *, unsigned long, char *, GString ** );
diff --git a/cddbd.c b/cddbd.c
@@ -0,0 +1,1220 @@
+/* ---------------------------------------------------------------------
+   cddbd interface for XfreeCD
+
+   Copyright 1998 by Brian C. Lane
+   nexus@tatoosh.com
+   http://www.tatoosh.com/nexus
+
+   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.
+
+   =============================[ HISTORY ]=============================
+   07/05/98	Removed the strcat of tmpstr from the track offset loop
+   		when requesting CD info. This was causing the odd
+   		behavior, depending on the state of memory.
+
+   06/19/98     Changed offset in the track loop to be 0 reference
+                instead of 1.
+
+   06/16/98     NIN Broken is living up to its name. It is causing the
+                server to return an error 500. Hmm, I somehow left out
+		the length of the cd. This is fixed. It now downloads
+		NIN correctly (woo hoo, ack, pthhhtttt). Anyone want
+		a copy of NIN Broken? I'll mail it to you in little
+		pieces...
+
+   06/02/98     Sending the full line returned by the server to the
+                caling process in cdinfo.line
+
+   05/24/98     Adding support for inexact matches.
+                Adding a return type of CDDBD_INEX_LINE
+
+   05/11/98     Adding more information from main process. Passes a
+                cdinfo structure.
+
+   05/10/98     Added basic socket open/close/read/write functions.
+
+   05/09/98     Started this part of the XfreeCD code. 
+
+
+   ---------------------------------------------------------------------
+   This implements the internet connection to a cddbd server. Local data
+   is accessed using the functions in ... 
+
+   Hmm, how to implemetn all this?
+   State machine for error responses and link to next command?
+
+   I also need to get more info on the CD than just the CD's discid
+
+   --------------------------------------------------------------------- */
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include "xfreecd.h"
+#include "child_sync.h"
+#include "cd_control.h"
+#include "cddbd.h"
+#include "cddb.h"
+
+
+#undef DEBUG1
+#undef DEBUG3
+
+int cddbd( int );
+
+/*
+   Fire up the cddb process.
+   Create a socket pair.
+   Fork a child process
+   Return the parent's file descriptor for the socket or -1 + errno
+   fill in childpid with the child's PID
+   Child calls cddbd 
+*/
+int start_cddbd( int *childpid )
+{
+  int  fd[2];
+
+  if( socketpair( AF_UNIX, SOCK_STREAM, 0, fd ) < 0 )
+    return(-1);
+
+  if( ( *childpid = fork() ) < 0 )
+  {
+    perror("start_cddbd, cannot fork");
+    return(-1);
+  } else if( *childpid == 0 ) {
+    close( fd[0] );
+
+    /* Synchronize with the parent, exit if it fails */
+    if( parent_sync( fd[1] ) == 0 )
+      cddbd( fd[1] );
+    
+    close( fd[1] );
+    exit(0);
+  } 
+  close( fd[1] );
+
+  if( child_sync( fd[0] ) == 0 )
+    return(fd[0]);  
+
+  return(-1);
+}
+
+/* -----------------------------------------------------------------------
+   Read a line from the socket
+   ----------------------------------------------------------------------- */
+int readn( register int fd, register char *ptr, register int nbytes )
+{
+  int   nleft,
+        nread;
+
+  nleft = nbytes;
+  while( nleft > 0 )
+    {
+      nread = read( fd, ptr, nleft );
+      if( nread < 0 )
+	return( nread );
+      else if( nread == 0 )
+	break;
+
+      nleft -= nread;
+      ptr += nread;
+    }
+  return (nbytes - nleft);
+}
+
+
+/* -----------------------------------------------------------------------
+   Write n bytes of data to the socket
+
+   Loop until all the data is written. 
+   ----------------------------------------------------------------------- */
+int writen( register int fd, register char *ptr, register int nbytes )
+{
+  int   nleft,
+        nwritten;
+
+  nleft = nbytes;
+  while( nleft > 0 )
+    {
+      nwritten = write( fd, ptr, nleft );
+      if( nwritten <= 0 )
+	return( nwritten );
+
+      nleft -= nwritten;
+      ptr += nwritten;
+    }
+
+  return (nbytes - nleft );
+}
+
+
+/* -----------------------------------------------------------------------
+   A VERY inefficent read routine. I need to rewrite this to read as much
+   as possible and scan the buffer read...
+   
+   But then how do you put back characters after the CR that you want to
+   read the next time it is called? Static holding previous spares maybe?
+   ----------------------------------------------------------------------- */
+int readline( register int fd, register char *ptr, register int maxlen )
+{
+  int  n,
+       rc;
+  char c;
+
+  for( n = 1; n < maxlen; n++ )
+    {
+      if( ( rc = read( fd, &c, 1 ) ) == 1 )
+	{
+	  *ptr++ = c;
+	  if( c == '\n' )
+	    break;
+	} else if( rc == 0 ) {
+	  if( n == 1 )
+	    return(0);
+	  else
+	    break;
+	} else {
+	  return(-1);
+	}
+    }
+
+  *ptr = 0;
+  return(n);
+}
+
+
+/* -----------------------------------------------------------------------
+   Open a cddbd connection, return the fd
+
+   This handles the connection and initial login to the server,
+   returns error codes on failure.
+
+   Pass the server name and port
+   ----------------------------------------------------------------------- */
+int open_cddbd( char *server, int port )
+{
+  struct sockaddr_in   tcp_srv_addr;    /* Server's Internet socket addr. */
+  struct hostent       tcp_host_info;   /* from gethostbyname */
+  struct hostent       *hp;
+  unsigned long        inaddr;
+  int                  fd;
+
+
+  bzero( &tcp_srv_addr, sizeof( tcp_srv_addr ) );
+  tcp_srv_addr.sin_family = AF_INET;
+
+
+  /* Setup the port, exit if illegal passed */
+  if( port < 1 )
+    return(-2);
+
+  tcp_srv_addr.sin_port = htons( port );
+
+  /* Try the hostname as a dotted decimal first */
+  if( ( inaddr = inet_addr( server ) ) != INADDR_NONE )
+    {
+      bcopy((char *)&inaddr,(char *)&tcp_srv_addr.sin_addr,sizeof(inaddr));
+      tcp_host_info.h_name = NULL;
+    } else {
+      /* Not dotted decimal, try it as a name */
+      if( ( hp = gethostbyname( server ) ) == NULL )
+	{
+	  return(-3);
+	}
+      tcp_host_info = *hp;    /* Copy the structure */
+      bcopy( hp->h_addr, (char *) &tcp_srv_addr.sin_addr, hp->h_length );
+    }
+
+  /* Create the socket */
+  if( ( fd = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 )
+    {
+      return(-4);
+    }
+
+  /* Connect to the server */
+  if( connect(fd,(struct sockaddr *)&tcp_srv_addr,sizeof(tcp_srv_addr)) < 0 )
+    {
+      close( fd );
+      return(-5);
+    }
+
+  return(fd);
+}
+
+/* -----------------------------------------------------------------------
+   Close down the connection to the server.
+
+   Send quit and close socket
+   ----------------------------------------------------------------------- */
+int close_cddbd( fd )
+{
+  char  line[255];
+
+  writen( fd, "quit\n", strlen( "quit\n" ) );
+
+  /* Read the closing banner from the server */
+  if( readline( fd, line, 255 ) < 0 )
+    {
+      close( fd );
+      return(-2);
+    }
+
+#ifdef DEBUG1
+  g_print("%s", line );
+#endif
+
+  close( fd );
+  return(0);
+}
+
+
+/* -----------------------------------------------------------------------
+   Return the response code
+   ----------------------------------------------------------------------- */
+int cddbd_code( char *line )
+{
+  char *p;
+
+  p = strtok( line, " \n" );
+  return( atoi( p ) );
+}
+
+
+
+/* -----------------------------------------------------------------------
+   Watch for commands from the main process and execute connections to
+   the indicated cddbd internet database server.
+
+   Commands ... DB_*
+   Uses the cddbd_cmnd structure to pass the command, server and port.
+
+   Also need to read the sites listing, and motd.
+
+   Retrieve data for ID from server SERVER using PORT
+
+   returns a CDINFO structure with a status byte? How to keep it updated
+   without returning a full CDINFO every time?   
+
+   As we progress thru the protocol, send back status updates to the parent
+   process.
+
+   ----------------------------------------------------------------------- */
+int cddbd( int control_fd )
+{
+  struct CDINFO  cdinfo;
+  FILE           *fp;
+  int            cddbd_fd;
+  char           line[255],
+                 *tmpfile,
+                 *p;
+  int            x,
+                 code;
+
+
+  for(;;)
+  {
+    /* Get the command from the parent process */
+    if( read( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+      {
+	perror("cddbd read error");
+	return(-1);
+      }
+
+    switch( cdinfo.cddbd_cmnd )
+      {
+      case DB_DIAG :
+	puts("cddbd diagnostic\n");
+	break;
+
+	/* Get the info on a CD from the server */
+      case DB_READ :
+
+#ifdef DEBUG1
+	g_print("Searching for 0x%08x at %s : %d\n", cdinfo.discid, cdinfo.server, cdinfo.port );
+#endif
+
+	if( (cddbd_fd = open_cddbd( cdinfo.server, cdinfo.port )) < 0 )
+	  {
+	    close_cddbd( cddbd_fd );
+
+	    /* Tell the parent the connection failed */
+	    cdinfo.cddbd_stat = CDDBD_OPEN_ERR;
+	    sprintf( cdinfo.line, "err=%d", cddbd_fd );
+	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	      {
+		perror("cddbd write error-1");
+		break;
+	      }
+	    break;
+	  }
+
+	/* Tell the parent we are connected ok */
+	cdinfo.cddbd_stat = CDDBD_OPEN_OK;
+	if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	      {
+		perror("cddbd write error-2");
+		break;
+	      }
+	  	
+	/* Read the opening banner from the server */
+	if( readline( cddbd_fd, line, 255 ) < 0 )
+	  {
+	    close( cddbd_fd );
+	    /* Tell the parent the read failed */
+	    cdinfo.cddbd_stat = CDDBD_READ_ERR;
+	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	      {
+		perror("cddbd write error-3");
+		break;
+	      }
+	    break;
+	  }  
+
+#ifdef DEBUG1
+	g_print( "%s", line );
+#endif
+
+	strncpy( cdinfo.line, line, 254 );
+	code = cddbd_code( line );
+	if( code > 201 )
+	  {
+	    close_cddbd( cddbd_fd );
+	    /* Tell the parent the connect failed */
+	    cdinfo.cddbd_stat = code;
+	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	      {
+		perror("cddbd write error-4");
+		break;
+	      }
+	    break;
+	  }
+
+	/* Identify ourself to the server */
+	sprintf( line, "cddb hello %s %s XfreeCD %s\n", getenv("USER"),
+		                                        getenv("HOSTNAME"),
+		                                        VERSION );
+
+#ifdef DEBUG1
+	g_print("%s", line );
+#endif
+
+	if( writen( cddbd_fd, line, strlen( line ) ) < 0 )
+	  {
+	    close( cddbd_fd );
+
+	    /* Tell the parent the write failed */
+	    cdinfo.cddbd_stat = CDDBD_WRITE_ERR;
+	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	      {
+		perror("cddbd write error-5");
+		break;
+	      }
+	    break;
+	  }
+
+	/* Get the response from the server */
+	if( readline( cddbd_fd, line, 255 ) < 0 )
+	  {
+	    close( cddbd_fd );
+
+	    /* Tell the parent the read failed */
+	    cdinfo.cddbd_stat = CDDBD_READ_ERR;
+	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	      {
+		perror("cddbd write error-6");
+		break;
+	      }
+	    break;
+	  }  
+
+#ifdef DEBUG1
+	g_print( "%s", line );
+#endif
+
+	strncpy( cdinfo.line, line, 254 );
+	code = cddbd_code( line );
+	if( code > 200 )
+	  {
+	    close_cddbd( cddbd_fd );
+
+	    /* Tell the parent the read failed */
+	    cdinfo.cddbd_stat = code;
+	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	      {
+		perror("cddbd write error-7");
+		break;
+	      }
+	    break;
+	  }
+
+	/* Send a Query to the server */
+	/* This can be quite! long (try NIN broken, 99 tracks) so break it up
+	   into smaller chuncks
+	*/
+	sprintf( line, "cddb query %08lx %d ", cdinfo.discid, cdinfo.tochdr.cdth_trk1 );
+
+#ifdef DEBUG1
+	g_print("%s", line );
+#endif
+
+	/* Write the first part of the query to the server */
+	if( writen( cddbd_fd, line, strlen( line ) ) < 0 )
+	  {
+	    close( cddbd_fd );
+
+	    /* Tell the parent the write failed */
+	    cdinfo.cddbd_stat = CDDBD_WRITE_ERR;
+	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	      {
+		perror("cddbd write error-8");
+		break;
+	      }
+	    break;
+	  }
+
+	/* List of offsets, send it one offset at a time */
+	for( x = 0; x < cdinfo.tochdr.cdth_trk1; x++ )
+	  {
+	    sprintf( line, "%ld ", cdinfo.track[x].frame_offset );
+
+#ifdef DEBUG1
+	    g_print("[%d]%s", x, line );
+#endif
+
+	    /* Write this next chunck of the request */
+	    if( writen( cddbd_fd, line, strlen( line ) ) < 0 )
+	      {
+		close( cddbd_fd );
+
+		/* Tell the parent the write failed */
+		cdinfo.cddbd_stat = CDDBD_WRITE_ERR;
+		if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+		  {
+		    perror("cddbd write error-8");
+		    break;
+		  }
+		break;
+	      }
+	  }
+
+	/* End of the query with length in seconds */
+	sprintf(line, "%d\n", cdinfo.cd_length );
+
+#ifdef DEBUG1
+	g_print("%s", line );
+#endif
+
+	if( writen( cddbd_fd, line, strlen( line ) ) < 0 )
+	  {
+	    close( cddbd_fd );
+
+	    /* Tell the parent the write failed */
+	    cdinfo.cddbd_stat = CDDBD_WRITE_ERR;
+	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	      {
+		perror("cddbd write error-8");
+		break;
+	      }
+	    break;
+	  }
+
+        /* Get the response from the server, get the coded response,
+	   and the rest up to the '.'
+	*/
+	/* Get the response from the server */
+	if( readline( cddbd_fd, line, 255 ) < 0 )
+	  {
+	    close( cddbd_fd );
+
+	    /* Tell the parent the read failed */
+	    cdinfo.cddbd_stat = CDDBD_READ_ERR;
+	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	      {
+		perror("cddbd write error-9");
+		break;
+	      }
+	    break;
+	  }  
+
+#ifdef DEBUG1
+	g_print( "%s", line );
+#endif
+
+	strncpy( cdinfo.line, line, 254 );
+	code = cddbd_code( line );
+	if( (code > 211) || (code==202) )
+	  {
+	    close_cddbd( cddbd_fd );
+
+	    /* Tell the parent the read failed */
+	    cdinfo.cddbd_stat = code;
+	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	      {
+		perror("cddbd write error-10");
+		break;
+	      }
+	    break;
+	  }
+
+	/* Inexact match, get the list */
+	if( code == 211 )
+	  {
+	    /* Return the inexact match lines to the sparent process */
+	    while( line[0] != '.' )
+	      {
+		if( readline( cddbd_fd, line, 255 ) < 0 )
+		  {
+		    close( cddbd_fd );
+
+		    /* Tell the parent the read failed */
+		    cdinfo.cddbd_stat = CDDBD_READ_ERR;
+		    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+		      {
+			perror("cddbd write error-11");
+			break;
+		      }
+		    break;
+		  }  
+
+#ifdef DEBUG1
+		g_print( "%s", line );
+#endif
+		/* Send the line to the parent */
+		cdinfo.cddbd_stat = CDDBD_INEX_LINE;
+		strncpy( cdinfo.line, line, 254 );
+		if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+		  {
+		    perror("cddbd write error-11a");
+		    break;
+		  } 
+	      }
+
+	    /* We are finished with the server */
+	    close_cddbd( cddbd_fd );
+	    break;
+	  }
+
+	/* Exact match, get the category ?? and discid ?? */
+	if( code == 200 )
+	  {
+	    /* Tell the parent that we got a match */
+	    cdinfo.cddbd_stat = CDDBD_MATCH_OK;
+	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	      {
+		perror("cddbd write error-11a");
+		break;
+	      }
+	    
+	    /* Get the category (code has already placed a null in line) */
+	    p = strtok( NULL, " \n" );
+	    if( cdinfo.category == NULL )
+	      cdinfo.category = g_string_new( p );
+	    else
+	      cdinfo.category = g_string_assign( cdinfo.category, p );
+
+#ifdef DEBUG3
+	    g_print("category = %s\n", cdinfo.category->str );
+#endif
+	    /* We could also get the discid and title here... */
+	  }
+
+
+	/* Send a read command to the server */
+	sprintf( line, "cddb read %s %08lx\n", cdinfo.category->str, cdinfo.discid );
+
+#ifdef DEBUG1
+		g_print( "%s", line );
+#endif
+
+	if( writen( cddbd_fd, line, strlen( line ) ) < 0 )
+	  {
+	    close( cddbd_fd );
+
+	    /* Tell the parent the read failed */
+	    cdinfo.cddbd_stat = CDDBD_WRITE_ERR;
+	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	      {
+		perror("cddbd write error-12");
+		break;
+	      }
+	    break;
+	  }
+
+	/* Get the response from the server */
+	if( readline( cddbd_fd, line, 255 ) < 0 )
+	  {
+	    close( cddbd_fd );
+
+	    /* Tell the parent the read failed */
+	    cdinfo.cddbd_stat = CDDBD_READ_ERR;
+	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	      {
+		perror("cddbd write error-13");
+		break;
+	      }
+	    break;
+	  }  
+
+#ifdef DEBUG1
+	g_print( "%s", line );
+#endif
+
+	strncpy( cdinfo.line, line, 254 );
+	code = cddbd_code( line );
+	if( code > 210 )
+	  {
+	    close_cddbd( cddbd_fd );
+	    
+	    /* Tell the parent the read failed */
+	    cdinfo.cddbd_stat = code;
+	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	      {
+		perror("cddbd write error-14");
+		break;
+	      }
+	    break;
+	  }
+
+	/* 
+	   Get the database file from the server.
+	   Write the file into a temporary file to be read by cddb_read
+	*/
+	if( ( tmpfile = tmpnam( NULL ) ) == NULL )
+	  {
+	    close_cddbd( cddbd_fd );
+
+	    /* Tell the parent the read failed */
+	    cdinfo.cddbd_stat = CDDBD_TMPF_ERR;
+	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	      {
+		perror("cddbd write error-15");
+		break;
+	      }
+	    break;	    
+	  }
+
+	if( ( fp = fopen( tmpfile, "wb" ) ) == NULL )
+	  {
+	    close_cddbd( cddbd_fd );
+
+	    /* Tell the parent the read failed */
+	    cdinfo.cddbd_stat = CDDBD_FOPEN_ERR;
+	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	      {
+		perror("cddbd write error-16");
+		break;
+	      }
+	    break;
+	  }
+
+	/* Tell the parent we are reading the database entry */
+	cdinfo.cddbd_stat = CDDBD_ENTRY_OK;
+	if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	  {
+	    perror("cddbd write error-14a");
+	    break;
+	  }
+
+	while( line[0] != '.' )
+	  {
+	    /* Get the response from the server */
+	    if( readline( cddbd_fd, line, 255 ) < 0 )
+	      {
+		close( cddbd_fd );
+
+		/* Tell the parent the read failed */
+		cdinfo.cddbd_stat = CDDBD_READ_ERR;
+		if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+		  {
+		    perror("cddbd write error-17");
+		    break;
+		  }
+		break;
+	      }  
+      
+#ifdef DEBUG1
+	    g_print( "%s", line );
+#endif
+	    /* Strip trailing CR -- kludge, may not be there... */
+	    line[strlen(line)-2] = 0;
+	    fprintf(fp, "%s\n", line);
+	  }
+
+	fclose( fp );
+
+	/* We are finished with the server */
+	close_cddbd( cddbd_fd );
+
+
+	/* Read the file into the cdinfo structure, and write it to its
+	   final location in the local database.
+	*/
+	if( read_cddb_file( tmpfile, &cdinfo ) == 0 )
+	  {
+	    /* Make sure it is saved with our discid! */
+	    cdinfo.discid = cddb_discid( &cdinfo );
+
+	    if( write_cddb( &cdinfo, 1 ) == 0 )
+	      cdinfo.cddbd_stat = CDDBD_DONE_OK;
+	    else
+	    cdinfo.cddbd_stat = CDDBD_DONE_ERR;
+	  } else {
+	    cdinfo.cddbd_stat = CDDBD_DONE_ERR;
+	  }
+
+#ifdef DEBUG3
+	    g_print("category = %s\n", cdinfo.category->str );
+#endif
+
+	/* Send the new structure back to the parent process */
+	if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	  {
+	    perror("cddbd write error-18");
+	    break;
+	  }
+
+	/* Delete the temporary file */
+#ifdef DEBUG1
+	g_print( "tmpfile=%s\n", tmpfile );
+#else
+	unlink( tmpfile );
+#endif
+	
+	break;
+
+      /* Get the MOTD from the current server */
+      case DB_MOTD :
+	if( (cddbd_fd = open_cddbd( cdinfo.server, cdinfo.port )) < 0 )
+	  {
+	    close_cddbd( cddbd_fd );
+
+	    /* Tell the parent the connection failed */
+	    cdinfo.cddbd_stat = CDDBD_OPEN_ERR;
+	    sprintf( cdinfo.line, "err=%d", cddbd_fd );
+	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	      {
+		perror("cddbd write error-1");
+		break;
+	      }
+	    break;
+	  }
+
+	/* Read the opening banner from the server */
+	if( readline( cddbd_fd, line, 255 ) < 0 )
+	  {
+	    close( cddbd_fd );
+	    /* Tell the parent the read failed */
+	    cdinfo.cddbd_stat = CDDBD_READ_ERR;
+	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	      {
+		perror("cddbd write error-3");
+		break;
+	      }
+	    break;
+	  }  
+
+#ifdef DEBUG1
+	g_print( "%s", line );
+#endif
+
+	strncpy( cdinfo.line, line, 254 );
+	code = cddbd_code( line );
+	if( code > 201 )
+	  {
+	    close_cddbd( cddbd_fd );
+	    /* Tell the parent the connect failed */
+	    cdinfo.cddbd_stat = code;
+	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	      {
+		perror("cddbd write error-4");
+		break;
+	      }
+	    break;
+	  }
+
+	/* Identify ourself to the server */
+	sprintf( line, "cddb hello %s %s XfreeCD %s\n", getenv("USER"),
+		                                        getenv("HOSTNAME"),
+		                                        VERSION );
+
+#ifdef DEBUG1
+	g_print("%s", line );
+#endif
+
+	if( writen( cddbd_fd, line, strlen( line ) ) < 0 )
+	  {
+	    close( cddbd_fd );
+
+	    /* Tell the parent the write failed */
+	    cdinfo.cddbd_stat = CDDBD_WRITE_ERR;
+	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	      {
+		perror("cddbd write error-5");
+		break;
+	      }
+	    break;
+	  }
+
+	/* Get the response from the server */
+	if( readline( cddbd_fd, line, 255 ) < 0 )
+	  {
+	    close( cddbd_fd );
+
+	    /* Tell the parent the read failed */
+	    cdinfo.cddbd_stat = CDDBD_READ_ERR;
+	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	      {
+		perror("cddbd write error-6");
+		break;
+	      }
+	    break;
+	  }  
+
+#ifdef DEBUG1
+	g_print( "%s", line );
+#endif
+
+	strncpy( cdinfo.line, line, 254 );
+	code = cddbd_code( line );
+	if( code > 200 )
+	  {
+	    close_cddbd( cddbd_fd );
+
+	    /* Tell the parent the read failed */
+	    cdinfo.cddbd_stat = code;
+	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	      {
+		perror("cddbd write error-7");
+		break;
+	      }
+	    break;
+	  }
+
+	/* Tell the server we want the MOTD */
+	strcpy( line, "motd\n" );
+	if( writen( cddbd_fd, line, strlen( line ) ) < 0 )
+	  {
+	    close( cddbd_fd );
+
+	    /* Tell the parent the write failed */
+	    cdinfo.cddbd_stat = CDDBD_WRITE_ERR;
+	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	      {
+		perror("cddbd write error-7");
+		break;
+	      }
+	    break;
+	  }
+
+	/* Get the response from the server */
+	if( readline( cddbd_fd, line, 255 ) < 0 )
+	  {
+	    close( cddbd_fd );
+
+	    /* Tell the parent the read failed */
+	    cdinfo.cddbd_stat = CDDBD_READ_ERR;
+	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	      {
+		perror("cddbd write error-8");
+		break;
+	      }
+	    break;
+	  }
+
+#ifdef DEBUG1
+	g_print( "%s", line );
+#endif
+
+	strncpy( cdinfo.line, line, 254 );
+	code = cddbd_code( line );
+	if( code > 210 )
+	  {
+	    close_cddbd( cddbd_fd );
+
+	    /* Tell the parent the read failed */
+	    cdinfo.cddbd_stat = code;
+	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	      {
+		perror("cddbd write error-7");
+		break;
+	      }
+	    break;
+	  }
+
+	/* Tell the parent about the MOTD date and time */
+	cdinfo.cddbd_stat = CDDBD_MOTD_LINE;
+	strncpy( cdinfo.line, line, 254 );
+	if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	  {
+	    perror("cddbd write error-8");
+	    break;
+	  }
+
+	/* Read the MOTD one line at a time */
+	while( line[0] != '.' )
+	  {
+	    /* Get the response from the server */
+	    if( readline( cddbd_fd, line, 255 ) < 0 )
+	      {
+		close( cddbd_fd );
+
+		/* Tell the parent the read failed */
+		cdinfo.cddbd_stat = CDDBD_READ_ERR;
+		if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+		  {
+		    perror("cddbd write error-8");
+		    break;
+		  }
+		break;
+	      }
+
+#ifdef DEBUG10
+	    g_print( "%s", line );
+#endif
+
+	    /* Send the line to the parent */
+	    cdinfo.cddbd_stat = CDDBD_MOTD_LINE;
+	    strncpy( cdinfo.line, line, 254 );
+	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	      {
+		perror("cddbd write error-8");
+		break;
+	      } 
+	  }
+
+	close_cddbd( cddbd_fd );
+
+	break;
+
+	/* 
+	   Read the list of sites from the server.
+	   Only return sites that we can talk to (cddb, not html)
+	*/
+      case DB_SITES :
+	if( (cddbd_fd = open_cddbd( cdinfo.server, cdinfo.port )) < 0 )
+	  {
+	    close_cddbd( cddbd_fd );
+
+	    /* Tell the parent the connection failed */
+	    cdinfo.cddbd_stat = CDDBD_OPEN_ERR;
+	    sprintf( cdinfo.line, "err=%d", cddbd_fd );
+	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	      {
+		perror("cddbd write error-1");
+		break;
+	      }
+	    break;
+	  }
+
+	/* Read the opening banner from the server */
+	if( readline( cddbd_fd, line, 255 ) < 0 )
+	  {
+	    close( cddbd_fd );
+	    /* Tell the parent the read failed */
+	    cdinfo.cddbd_stat = CDDBD_READ_ERR;
+	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	      {
+		perror("cddbd write error-3");
+		break;
+	      }
+	    break;
+	  }  
+
+#ifdef DEBUG1
+	g_print( "%s", line );
+#endif
+
+	strncpy( cdinfo.line, line, 254 );
+	code = cddbd_code( line );
+	if( code > 201 )
+	  {
+	    close_cddbd( cddbd_fd );
+	    /* Tell the parent the connect failed */
+	    cdinfo.cddbd_stat = code;
+	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	      {
+		perror("cddbd write error-4");
+		break;
+	      }
+	    break;
+	  }
+
+	/* Identify ourself to the server */
+	sprintf( line, "cddb hello %s %s XfreeCD %s\n", getenv("USER"),
+		                                        getenv("HOSTNAME"),
+		                                        VERSION );
+
+#ifdef DEBUG1
+	g_print("%s", line );
+#endif
+
+	if( writen( cddbd_fd, line, strlen( line ) ) < 0 )
+	  {
+	    close( cddbd_fd );
+
+	    /* Tell the parent the write failed */
+	    cdinfo.cddbd_stat = CDDBD_WRITE_ERR;
+	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	      {
+		perror("cddbd write error-5");
+		break;
+	      }
+	    break;
+	  }
+
+	/* Get the response from the server */
+	if( readline( cddbd_fd, line, 255 ) < 0 )
+	  {
+	    close( cddbd_fd );
+
+	    /* Tell the parent the read failed */
+	    cdinfo.cddbd_stat = CDDBD_READ_ERR;
+	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	      {
+		perror("cddbd write error-6");
+		break;
+	      }
+	    break;
+	  }  
+
+#ifdef DEBUG1
+	g_print( "%s", line );
+#endif
+
+	strncpy( cdinfo.line, line, 254 );
+	code = cddbd_code( line );
+	if( code > 200 )
+	  {
+	    close_cddbd( cddbd_fd );
+
+	    /* Tell the parent the read failed */
+	    cdinfo.cddbd_stat = code;
+	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	      {
+		perror("cddbd write error-7");
+		break;
+	      }
+	    break;
+	  }
+
+	/* Tell the server we want the MOTD */
+	strcpy( line, "sites\n" );
+	if( writen( cddbd_fd, line, strlen( line ) ) < 0 )
+	  {
+	    close( cddbd_fd );
+
+	    /* Tell the parent the write failed */
+	    cdinfo.cddbd_stat = CDDBD_WRITE_ERR;
+	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	      {
+		perror("cddbd write error-7");
+		break;
+	      }
+	    break;
+	  }
+
+	/* Get the response from the server */
+	if( readline( cddbd_fd, line, 255 ) < 0 )
+	  {
+	    close( cddbd_fd );
+
+	    /* Tell the parent the read failed */
+	    cdinfo.cddbd_stat = CDDBD_READ_ERR;
+	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	      {
+		perror("cddbd write error-8");
+		break;
+	      }
+	    break;
+	  }
+
+#ifdef DEBUG1
+	g_print( "%s", line );
+#endif
+
+	strncpy( cdinfo.line, line, 254 );
+	code = cddbd_code( line );
+	if( code > 210 )
+	  {
+	    close_cddbd( cddbd_fd );
+
+	    /* Tell the parent the read failed */
+	    cdinfo.cddbd_stat = code;
+	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	      {
+		perror("cddbd write error-7");
+		break;
+	      }
+	    break;
+	  }
+
+	/* Read the MOTD one line at a time */
+	while( line[0] != '.' )
+	  {
+	    /* Get the response from the server */
+	    if( readline( cddbd_fd, line, 255 ) < 0 )
+	      {
+		close( cddbd_fd );
+
+		/* Tell the parent the read failed */
+		cdinfo.cddbd_stat = CDDBD_READ_ERR;
+		if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+		  {
+		    perror("cddbd write error-8");
+		    break;
+		  }
+		break;
+	      }
+
+#ifdef DEBUG10
+	    g_print( "%s", line );
+#endif
+
+	    /*
+	       Here we should check the protocol level and parse the
+	       response and only return sites that we can talk to.
+	    
+	       For the moment, just return the lines to the parent
+	    */
+
+	    /* Send the line to the parent */
+	    cdinfo.cddbd_stat = CDDBD_SITE_LINE;
+	    strncpy( cdinfo.line, line, 254 );
+	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+	      {
+		perror("cddbd write error-8");
+		break;
+	      } 
+	  }
+
+	close_cddbd( cddbd_fd );
+	break;
+
+
+      case DB_QUIT :
+	return(0);
+	break;
+      }
+  }
+  return(0);
+}
diff --git a/cddbd.h b/cddbd.h
@@ -0,0 +1,37 @@
+/* ------------------------------------------------------------------------
+   cddbd include file for XfreeCD
+
+   Copyright 1998 by Brian C. Lane
+   nexus@tatoosh.com
+   http://www.tatoosh.com/nexus
+
+   ------------------------------------------------------------------------ */
+#define DB_DIAG        0x00
+#define DB_READ        0x01
+#define DB_QUIT        0x02
+#define DB_MOTD        0x03
+#define DB_SITES       0x04
+#define DB_WRITE       0x05
+
+#define CDDBD_DONE_OK   0x00
+#define CDDBD_OPEN_ERR  0x01
+#define CDDBD_OPEN_OK   0x02
+#define CDDBD_READ_ERR  0x03
+#define CDDBD_WRITE_ERR 0x04
+#define CDDBD_TMPF_ERR  0x05
+#define CDDBD_FOPEN_ERR 0x06
+#define CDDBD_DONE_ERR  0x07
+#define CDDBD_MATCH_OK  0x08
+#define CDDBD_ENTRY_OK  0x09
+#define CDDBD_MOTD_LINE 0x0A
+#define CDDBD_SITE_LINE 0x0B
+#define CDDBD_INEX_LINE 0x0C
+#define CDDBD_MAX       0x10
+
+
+int start_cddbd( int * );
+
+int readn( register int, register char *, register int );
+int writen( register int, register char *, register int );
+int readline( register int, register char *, register int );
+
diff --git a/child_sync.c b/child_sync.c
@@ -0,0 +1,66 @@
+/* -----------------------------------------------------------------------
+   child process synchronization functions
+
+   part of XfreeCD
+
+   Copyright 1998 by Brian C. Lane
+   nexus@tatoosh.com
+   http://www.tatoosh.com/nexus
+
+   ==========================[ HISTORY ]==================================
+   05/09/98    Moved these functions into this seperate file
+
+   ----------------------------------------------------------------------- */
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+
+
+/*
+   Synchronize with the parent process. Wait until we receive a 'P'
+   from the parent. Send a 'C' to the parent in response
+
+   Return a 0 if all went ok
+   Return a -1 if something went wrong
+*/
+int parent_sync( int fd )
+{
+  char c;
+
+  if( read( fd, &c, 1 ) != 1 )
+    return(-1);
+
+  if( write( fd, "C", 1 ) != 1 )
+    return(-1);
+
+  return(0);
+}
+
+
+
+/*
+   Synchronize with the child process. Send a 'P' to the child and wait
+   until a 'C' is received back.
+
+   Return a 0 if all went ok
+   Return a -1 if something went wrong
+*/
+int child_sync( int fd )
+{
+  char c;
+
+  if( write( fd, "P", 1 ) != 1 )
+    return(-1);
+
+  if( read( fd, &c, 1 ) != 1 )
+    return(-1);
+
+  if( c != 'C' )
+    return(-1);
+
+  return(0);
+}
diff --git a/child_sync.h b/child_sync.h
@@ -0,0 +1,10 @@
+/* ------------------------------------------------------------------------
+   child_sync include file for XfreeCD
+
+   Copyright 1998 by Brian C. Lane
+   nexus@tatoosh.com
+   http://www.tatoosh.com/nexus
+
+   ------------------------------------------------------------------------ */
+int parent_sync( int fd );
+int child_sync( int fd );
diff --git a/xfreecd.c b/xfreecd.c
@@ -0,0 +1,5293 @@
+/* ---------------------------------------------------------------------
+
+   XfreeCD v0.7.8
+
+   Copyright (C) 1998 Brian C. Lane
+   nexus@tatoosh.com
+   http://www.tatoosh.com/nexus
+
+   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.
+
+   ============================[ HISTORY ]==============================
+   12/02/98     Tracking down the crash on CDDB retrieveal bug that people
+                have been reporting. I've finally duplicated it myself
+		and narrowed it down to the code after printing the string
+		"Got the new data ok" and the call to local_cddb();
+		My theory is that display.plabel or display.progress don't
+		get set to a NULL when deleted, so my checks fail and
+		it tries to write to already freed memory.
+		Removed the progress update right before destroying the
+		progress box, no point if its going to get deleted!
+		I cannot be 100% positive, but I think this has fixed the
+		recall problem. Needs testing.
+
+		Another bug. If the progress box is killed, it never opens
+		again until the program is restarted. Fix this in next
+		version.
+
+
+   07/05/98	Fixed intermittant bug with recalling CD info. There was
+   	 	a spare strcat(tmpstr) in the request loop of offsets!
+   	 	Depending on the state of memory this could really hose
+   	 	the requests.
+
+   06/26/98     Fixing Revision # for original submissions. Store them
+                locally as #0 so that the first send to the server will
+		increment it to #1 and the server will get #1.
+		Also added the VERSION number to the makefile to make
+		changing the version easier.
+
+   06/22/98     I just noticed a problem. The Length of track #1 is wrong!
+                Seems to be stuck at 20:36. cd_control.c was waiting until
+		the track was at #2 before calculating the length. FIXED.
+
+   06/20/98     TODO
+                1. Fix EXT problems.
+		   FIXED.
+		2. Reread spec on blank tracks. It refused 'Track 6'
+		   I shouldn't save any default strings to disk or send
+		   them to the database. Only show them when updating
+		   the clist. DONE. Sends a blank ttitle if none is
+		   entered.
+
+		3. Made change, but edit doesn't work and it complains
+		   about lots of g_strings != NULL (means ==) that need
+		   to be fixed (probably in the edit an edit copy). Make
+		   sure the (blank) placeholders are not copied over unless
+		   they are edited.
+		   Writing of blank tracks doesn't work when the user has
+		   deleted everything since it holds a string of zero
+		   length.
+		   FIXED. Check the length for 0.
+
+		4. If the CD is paused when XfreeCD is run it doesn't
+		   show the current track in the display. FIXED.
+
+		5. If the CD is paused when XfreeCD is run and you show
+		   the track names, it is blank. The database has not
+		   been read yet. FIXED.
+
+		6. Main Tracklist display is updated every second...
+		   This is because some of the CDDB entries have a revision
+		   of -1. I convert these into revision 1 now.
+
+   06/19/98     Finishing up the extended data support. Adding free_cdinfo
+                to the appropriate places. Need to make sure its only called
+		when its needed and not in the update loop.
+		Changed Cancel button in edit window to Close
+
+		Shit. Nov I've broken it and I don't know how. Well, then
+		I'll just break it more. Changing all string usage to
+		dynamically allocated GString * from gtk.
+
+		Whew! Okay, I've converted all the static string storage
+		over to GString usage. It appears to be working okay for
+		the moment. Now to stress test it with all the CDDB
+		requirements.
+
+		Testing and making submissions to CDDB test server.
+		1. Inexact doesn't save to disk with my ID, it saves it
+		   with the downloaded id (because I canged the way it
+		   is saved after being received!). Change in cddbd.c
+		   so it save to local, reads it, changes discid and
+		   saves it again <ICK>. FIXED.
+
+		2. There is a problem when reading extended info. It
+		   is writing a blank EXTD and EXT0 then another EXT0
+		   and then up to the end-1 tracks. Fix it tomorrow.
+		   FIXED. 1 - off error.
+
+   06/16/98     Things that need fixing:
+                1. 99 track CD isn't downloaded, causes an error and
+		   it retries the server endlessly.
+		   The track array in cdinfo was 1 short! I should use
+		   0-98 instead of 1-99 for all access.
+		   FIXED.
+
+		2. Server error caused by not sending all the track offsets
+		   (buffer overflow). Fixed by sending it the offsets one
+		   at a time. FIXED.
+
+		3. Edit window coredumps when trying to edit 99 track
+		   NIN-broken. FIXED. display structure had a [99] in it.
+		   
+		4. Main tracklist window flickers every second...
+
+		5. Need to process extended data, save to local database,
+		   resend it to server when tracks change. Don't need
+		   to edit it or display it (most CDs don't use it at all).
+		   Reading works now.
+		   a. Need to write it back to disk. DONE.
+		   b. Need to free the used memory when a CD is ejected
+		      DONE.
+
+		6. Need to read the Revision # correctly
+		   DONE.
+
+   06/06/98     Fixed problem with changing categories. Once the new
+                category has successfully been written it erases the
+		old category.
+		While it is waiting to get new data from the server
+		it is displaying the old track data. Needs to be erased
+		from the cdinfo structure as well as the display.
+		FIXED.
+		I would like to make long title in the track window
+		wrap automatically, but the GTK label doesn't have
+		wrapping, so too bad.
+		Adding a Send to Server option. This just uses the
+		local mail binary (must be in the path). This should
+		work for everyone.
+		Works, Tested successfully.
+		Added support for multiple TITLEx lines. Tested, and it
+		works fine. Sent 5 test of long title and long track
+		names to the cddb-test server.
+		I just noticed a bug with the clist edit window. It
+		is resetting the vertical scroll bar when you select
+                a track that has to be scrolled down to. Probably
+		because I reload the clist when the trackname is
+		edited. FIXED.
+
+   06/05/98     Trying to tidy up all the loose ends.
+                GTK cannot figure out the geometry of the window before
+		it is actually showing, so the negative geometry with
+		titlebar doean't work right. Hardcoded the window size
+		to 137x60
+
+   06/02/98     Adding display of full string returned by server error.
+                Fixed close error, I was returning the wrong thing from
+		delete_event.
+   
+   06/01/98     Adding seperate Window Class names to the different
+                windows so that the user can individually control the
+		title bar, move/resize, etc. As suggested by Michael
+		J. Hammel
+
+   05/31/98     Adding support for -geometry, apparently this has not
+                been added to GTK+ itself yet, so I have to do it
+		myself, using XParseGeometry. Works Great!
+		When geometry is passed a '- it needs to be relative
+		to the other corner of the window, not the upper
+		left. Fixed.
+
+   05/28/98	Bug with eject on exit. It needs to send the current
+   		state to the cd_control process when it reads the
+   		config file. FIXED.
+   		Need to add dropdown list for categories in edit. DONE.
+
+   05/27/98     More finishing touches <G>.
+                Added selection of next track in the track window when
+		it goes to the next track. Looks nicer.
+		Fixed a bug with multiple DTITLE lines.
+
+		NEED TO DO:
+		x 1. Build local cddb directories sometime (either under
+		     the setup menu, or the first time it writes,
+		     or at compile time). The best would be when it
+		     tries to write to a non-existant directory, create
+		     the structure needed.
+		     Works. It creates only the category directory
+		     needed and the root cddb directory if it doesn't
+		     exist yet. This way the categories aren't limited
+		     to a static list.
+		x 2. Editing track names and saving to local database.
+		x 3. Sending edited track info to the database, or just
+		     a new discid for the CD. Requires email. Use the
+		     mail binary, but allow users to spec. it?
+		x 4. Allow user to select local .cddb support or internet
+		     so they can build their own database in the cddb
+		     format even if they have no inet connection.
+		  5. Clean up code. Add comments.
+		     There is a bunch of duplicated code that can be
+		     put into a subroutine with maybe 1 parameter
+		     passed to it. The clist updating routines are
+		     one.
+		x 6. Convert my usage of printf to g_print
+
+   05/26/98     Finishing touches. Got the text window to work, thanks
+                to Owen. I had to add it to the notebook before
+		it is realized, otherwise it doesn't know who its
+		parent is (this is because text windows are changes as
+		you add to them).
+		Changed to main window to be a POPUP so that it has no
+		title bars. Keeps people from resizing it too!
+
+   05/25/98     Problem with using device from main process -- we only
+                send 2 bytes to the cd_control process!! How am I going
+		to pass the new device? A 2 stage send? With the second
+		part being the new device?
+
+		Added CD_SET_DEVICE to cd_control.
+		Adding sending of it to read_config.
+		Switching cd device is now working!
+
+		Adding clear of display.tclist to no disc display points
+
+
+   05/24/98     Adding support for inexact matches. CDDBD_INEX_LINE.
+                Inexact matching works!!! It saves it as the locally
+		calculated discid (recalculated just before the save).
+
+		x 1. Need to update the track list if its already open
+		     when the new data is downloaded from the server or
+		     read from disk.
+		x 2. Clear the track list and title when nodisc info is
+		     available (on change, use Track #, etc).
+		x 3. Click on a track in the track list to jump to
+		     that track directly.
+	       no  5. CD changer support...
+		x 6. Volume update is slow, needs to be called on click.
+
+		I've decided not to include changer support. Too hard to
+		integrate into the current GUI. And there probably isn't
+		a great need.
+
+   05/23/98     The Help/Setup dialog is partially working. It still
+                complains when making the help text box, why?
+		The startup sequence isn't working right. Not playing
+		after closing the tray, or even when already closed.
+
+		I also don't like the startup pause for checking for the
+		current status. That should be handled by a startup
+		state machine in the status callback. May help solve the
+		startup play problem. Fixed. Status returned was NO_STATUS
+		which I was checking for some reason.
+
+		Software selectable eject on exit with no play is now
+		working correctly.
+
+		Server refresh is working as far as updating the internal
+		list but the list in the setup dialog isn't working. Also
+		changes to cddb and device are cross-polinated! It is
+		happening at the realloc in the device_edit and cddb_edit
+		routines. Pointer copied over somehow? realloc wrong?
+		typical bug. Assignment to wrong place.
+
+		Some of th things left to do:
+		x 1. refresh server listing after update from internet
+		     while dialog box is still open.
+		x 2. Status box showing the info while connected to the
+		     server.
+		x 3. Implement Inexact match
+		x    a. receive list of discids and titles from the server
+		        Add a new command to cddbd return value
+		x    b. Show a dialog box with the list of titles and have
+		        the user pick one or Cancel.
+		x    c. re-submit the query using the user selected discid
+		x 4. Saving to disk saves the wrong revision #, -1
+		o 5. Popup window when display is left clicked that shows
+		     and allows editing of title and tracks.
+		     showing title and track is working.
+		  6. Need to switch to using config.device and telling the
+		     cd_control process about it when we change it.
+		  7. Submitting a new disc to the database (via email?)
+
+
+   05/22/98     Need to finish the help/setup menu window.
+                x Device (defaults to /dev/cdrom)
+		x Server List
+		x cddb support
+	       no changer support
+		x Eject at end?
+		x Startup behavior
+
+
+		Since I have the WM set to no titles and bars it makes it
+		hard to manipulate the setup screen! How about if I were
+		to extend the cdplayers window up or down (how to tell?)
+		and include the setup/server/tracklist data that way?
+		How do you delete things once you've packed them? Or can
+		you? 
+
+
+   05/21/98     Right click on display window and dragging now works
+                fine for moving the window around.
+
+
+   05/20/98     Blink isn't working. Fixed. Multiple places calling
+                update_display. FIXED.
+		Also need to add window dragging if right clicked in
+		the display area.
+		Need to add parallel tracklist window popup if right
+		click on either of the track digits (or area).
+
+		At startup we need to know the current state of the
+		CD before we go off and send a play command to it. FIXED.
+		When it has to close the door to play it doesn't start
+		playing automatically.
+		When it tries to play with no CD in the drive it doesn't
+		recover when you insert a disc and hit play.
+		Because fd_cd is < 0. Check for this.
+
+		There is a problem with setting the play button graphic
+		and state at the point where it is sent to control.
+		it it fails then the state/button is wrong! But if I
+		wait until it succeeds/fails then response time is
+		greatly delayed... Added code to make sure the button
+		state matched the display state and to change it if it
+		differs. Seems to work nicely. Shows playup until it
+		fails and then switches to stopup. WORKS WELL.
+
+		Eject doesn't work with status doing an init. Do an
+		initial init when cd_control is started. FIXED.
+
+		Dragging now sortof works. It loses track of the cursor
+		if its moved too fast, and won't ungrab (ick!)
+
+   05/19/98     Read/Write config now works, needs to still be tested
+                with multiple servers though.
+
+   05/18/98     Adding configuration writing and reading
+
+   05/17/98     Found a chunck of startup code that was double-copied,
+                The player actually plays, ejects, etc. OK.
+		The volume display needs to update immediatly as does
+		the time display update when the key is pressed. Eject
+		should eject even when no cd has been opened.
+		At startup we should?
+		  Play automatically
+		  Show no disc and do nothing until play pressed
+		  Show total # of tracks and time remaining
+		All of these should be user selectable.
+		When a CD is opened for the first time (no discid stored
+		in cdinfo) we should query the database.
+		Clicking (right probably) on the display should pop up a
+		list of the tracks (editable).
+		There are some == NULL problems that need to be taken care
+		at starup, probably due to not realizing widgets first?
+		Blink isn't working right (doesn't blink)
+		Remaining on track counts up, not down!
+		Help/Setup dialog needs to be nicer looking, black to match
+		the look of the main box (how do I change the colors of
+		the dialogs?)
+
+   05/16/98     Finishing up the cd control, adding get motd and get
+                server list from cddb.cddb.com
+		I really should add protocol support, but really, it
+		works fine like this...
+		OK, it 'looks like' the low level and server support is
+		now working okay. The code is a bit hard to read and
+		could probably use some macroing or other cleanups,
+		but I'll save that for later.
+
+		Now to start adding the GTK+ GUI stuff again and integrate
+		it with the data returning from the server and the CD
+		control process.
+
+		Well, the UI is sort of running. It complains a little,
+		and puts two 'NO DISC' pixmaps in the window, but it
+		starts at least!
+
+   05/09/98     Added local cddb database support. It successfully reads
+                the disc info from the database.
+
+   05/03/98     Restarted this whole project from the ground up. I am
+                writing the CD control and cddb support code first,
+		and then adding the GUI interface.
+
+		cd_control and cddb will be seperate processes forked
+		from the main process at startup.
+
+   -------------------------------------------------------------------- */
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include "cd_control.h"
+#include "cddbd.h"
+#include "cddb.h"
+#include "xfreecd.h"
+#include "xpm_button.h"
+
+
+/* Include all the bitmaps used (in xpm format) */
+#include "bitmaps/ffup.xpm"
+#include "bitmaps/ffdn.xpm"
+#include "bitmaps/rewup.xpm"
+#include "bitmaps/rewdn.xpm"
+#include "bitmaps/sfwddn.xpm"
+#include "bitmaps/srevdn.xpm"
+#include "bitmaps/stopup.xpm"
+#include "bitmaps/playup.xpm"
+#include "bitmaps/playdn.xpm"
+#include "bitmaps/pauseup.xpm"
+#include "bitmaps/ejup.xpm"
+#include "bitmaps/ejdn.xpm"
+#include "bitmaps/exitup.xpm"
+#include "bitmaps/exitdn.xpm"
+#include "bitmaps/helpup.xpm"
+#include "bitmaps/helpdn.xpm"
+#include "bitmaps/rptup.xpm"
+#include "bitmaps/rptdn.xpm"
+#include "bitmaps/rptupact.xpm"
+#include "bitmaps/volup.xpm"
+#include "bitmaps/voldn.xpm"
+#include "bitmaps/null.xpm"
+#include "bitmaps/nodisc.xpm"
+#include "bitmaps/plstrkup.xpm"
+#include "bitmaps/plstrkdn.xpm"
+#include "bitmaps/mnstrkup.xpm"
+#include "bitmaps/mnstrkdn.xpm"
+#include "bitmaps/plscdup.xpm"
+#include "bitmaps/plscddn.xpm"
+#include "bitmaps/mnscdup.xpm"
+#include "bitmaps/mnscddn.xpm"
+#include "bitmaps/minus.xpm"
+#include "bitmaps/bar.xpm"
+#include "bitmaps/redbar.xpm"
+#include "bitmaps/nobar.xpm"
+#include "bitmaps/a0.xpm"
+#include "bitmaps/a1.xpm"
+#include "bitmaps/a2.xpm"
+#include "bitmaps/a3.xpm"
+#include "bitmaps/a4.xpm"
+#include "bitmaps/a5.xpm"
+#include "bitmaps/a6.xpm"
+#include "bitmaps/a7.xpm"
+#include "bitmaps/a8.xpm"
+#include "bitmaps/a9.xpm"
+#include "bitmaps/an.xpm"
+#include "bitmaps/b0.xpm"
+#include "bitmaps/b1.xpm"
+#include "bitmaps/b2.xpm"
+#include "bitmaps/b3.xpm"
+#include "bitmaps/b4.xpm"
+#include "bitmaps/b5.xpm"
+#include "bitmaps/b6.xpm"
+#include "bitmaps/b7.xpm"
+#include "bitmaps/b8.xpm"
+#include "bitmaps/b9.xpm"
+#include "bitmaps/bn.xpm"
+
+
+#undef DEBUG1
+#undef DEBUG2
+#undef DEBUG3
+#undef DEBUG4
+#undef DEBUG5
+#undef DEBUG6
+#undef DEBUG7
+#undef DEBUG8
+#undef DEBUG9
+#undef MAIL_DEBUG
+
+#define	CDROM_NODISC	0
+#define CDROM_PLAYING	1
+#define CDROM_PAUSED	2
+
+#define TRACK_ELAPSED	0
+#define TRACK_REMAIN	1
+#define CD_ELAPSED	2
+#define CD_REMAIN	3
+
+
+#define HELP_TEXT( x )       gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, x, -1)
+#define COLOR_TEXT( x, y )   gtk_text_insert (GTK_TEXT (text), NULL, y, NULL, x, -1)
+
+int read_config( struct CONFIG * );
+int run_gtk();
+void free_config( struct CONFIG * );
+gint delete_event(GtkWidget *, gpointer);
+void destroy (GtkWidget *, gpointer);
+void cd_fd_read( gpointer, gint, GdkInputCondition);
+void cddbd_fd_read( gpointer, gint, GdkInputCondition);
+void ff_press(GtkWidget *, GdkEventButton *);
+void ff_release(GtkWidget *, GdkEventButton *);
+void rew_press(GtkWidget *, GdkEventButton *);
+void rew_release(GtkWidget *, GdkEventButton *);
+void play_press(GtkWidget *, GdkEventButton *);
+void play_release(GtkWidget *, GdkEventButton *);
+void eject_press(GtkWidget *, GdkEventButton *);
+void eject_release(GtkWidget *, GdkEventButton *);
+void ex_press(GtkWidget *, GdkEventButton *);
+void ex_release(GtkWidget *, GdkEventButton *);
+void help_press(GtkWidget *, GdkEventButton *);
+void help_release(GtkWidget *, GdkEventButton *);
+void tdisp_press(GtkWidget *, GdkEventButton *);
+void tdisp_release(GtkWidget *, GdkEventButton *);
+void rpt_press(GtkWidget *, GdkEventButton *);
+void rpt_release(GtkWidget *, GdkEventButton *);
+void vol_press(GtkWidget *, GdkEventButton *);
+void vol_release(GtkWidget *, GdkEventButton *);
+void set_vol( int amount );
+static int expose_display( GtkWidget *, GdkEventExpose *);
+gint update_cdrom( gpointer );
+void play_next();
+void play_previous();
+void pause_cdrom();
+void resume_cdrom();
+void play_track(int);
+void update_display();
+void stop_cdrom();
+void eject_cdrom();
+int cdrom_status();
+int write_config( struct CONFIG * );
+static void display_released (GtkWidget *);
+static void display_motion (GtkWidget *, GdkEventMotion *);
+static void display_pressed (GtkWidget *, GdkEventButton *);
+void wait_status();
+gint show_tracks();
+void set_eject( int );
+
+
+typedef struct _cursoroffset {gint x,y;} CursorOffset;
+
+/* Global Variables and structures */
+struct CDINFO cdinfo;
+struct CONFIG config;
+ 
+char          cmnd[2];
+int           cd_pid, cd_fd,            /* Communications with the CD control */
+              cddbd_pid, cddbd_fd;      /* Communications with cd database */
+gint          gdk_cd_fd,
+              gdk_cddbd_fd;
+
+
+static GdkWindow *root_win = NULL;
+
+
+struct _pbutton	ff,			/* Fast Forward button		*/
+		rew,			/* Rewind			*/
+		play,			/* Play				*/
+		vol,			/* Volume control		*/
+		eject,			/* Elect			*/
+		tdisp,			/* Time Display			*/
+		rpt,			/* Repeat			*/
+		ex,			/* Exit button			*/
+		help;			/* Help				*/
+
+/* Display pixmaps and current disc status */
+struct _display 
+{
+  GtkWidget	*main_window;           /* The main window              */
+  GtkWidget     *vbox;                  /* Vbox holding everything      */
+  GtkWidget	*wid;			/* Widget for placing pixmaps	*/
+  GtkWidget     *progress;              /* CDDBD progress dialog window */
+  GtkWidget     *plabel;                /* Progress dialog label        */
+  GtkWidget     *twindow;               /* Track Window pointer         */
+  GtkWidget     *tclist;                /* List of tracks               */               
+  GtkWidget     *ttitle;                /* Track list title widget      */
+  GtkWidget     *tewindow;              /* Track Edit Window            */
+  GtkWidget     *teentry;               /* Track Entry Window           */
+  GtkWidget     *teclist;               /* Clist for Track Edit         */
+  GtkWidget     *cb;                    /* ComboBox list of Servers     */
+  GdkPixmap	*image;			/* image to paint onto		*/
+  GdkPixmap	*null_pixmap;		/* Blank with : 		*/
+  GdkBitmap	*null_mask;
+  GdkPixmap	*nodisc_pixmap;		/* NO DISC			*/
+  GdkBitmap	*nodisc_mask;
+  GdkPixmap	*minus_pixmap;		/* Minus sign			*/
+  GdkBitmap	*minus_mask;
+  GdkPixmap	*playup_pixmap;		/* Play in white		*/
+  GdkBitmap	*playup_mask;
+  GdkPixmap	*playdn_pixmap;
+  GdkBitmap	*playdn_mask;
+  GdkPixmap	*pauseup_pixmap;	/* Pause bars in white		*/
+  GdkBitmap	*pauseup_mask;
+  GdkPixmap	*stopup_pixmap;		/* play and pause in gray	*/
+  GdkBitmap	*stopup_mask;
+  GdkPixmap     *sfwddn_pixmap;         /* Seek forward down button     */
+  GdkBitmap     *sfwddn_mask;
+  GdkPixmap     *srevdn_pixmap;         /* Seek reverse down button     */
+  GdkBitmap     *srevdn_mask;
+  GdkPixmap	*rptupact_pixmap;	/* repeat active (white)	*/
+  GdkBitmap	*rptupact_mask;
+  GdkPixmap	*plstrkup_pixmap;	/* Elapsed track time		*/
+  GdkBitmap	*plstrkup_mask;
+  GdkPixmap	*plstrkdn_pixmap;
+  GdkBitmap	*plstrkdn_mask;
+  GdkPixmap	*mnstrkup_pixmap;	/* Remaining track time		*/
+  GdkBitmap	*mnstrkup_mask;
+  GdkPixmap	*mnstrkdn_pixmap;
+  GdkBitmap	*mnstrkdn_mask;
+  GdkPixmap	*plscdup_pixmap;	/* Elapsed CD time		*/
+  GdkBitmap	*plscdup_mask;
+  GdkPixmap	*plscddn_pixmap;
+  GdkBitmap	*plscddn_mask;
+  GdkPixmap	*mnscdup_pixmap;	/* Remaining CD time		*/
+  GdkBitmap	*mnscdup_mask;
+  GdkPixmap	*mnscddn_pixmap;
+  GdkBitmap	*mnscddn_mask;
+  GdkPixmap	*bar_pixmap;		/* Volume Bargraph		*/
+  GdkBitmap	*bar_mask;
+  GdkPixmap	*redbar_pixmap;		/* Volume Bargraph		*/
+  GdkBitmap	*redbar_mask;
+  GdkPixmap	*nobar_pixmap;		/* Volume Bargraph		*/
+  GdkBitmap	*nobar_mask;
+
+  GdkPixmap	*a_pixmap[11];		/* Large digits			*/
+  GdkBitmap	*a_mask[11];
+  GdkPixmap	*b_pixmap[11];		/* Small Digits			*/
+  GdkBitmap	*b_mask[11];
+
+  GString       *tmp_category;          /* New Category entry */
+  GString       *tmp_title;             /* Title storage for edit_tracks*/
+  GString       *tmp_track[99];         /* Song names for editing       */
+  int           tmp_row;                /* Current row in tmp_track     */
+
+  short         startup;                /* Startup State machine        */
+  short         cddb_lock;              /* Lock cddb access while busy  */
+  int		status;			/* Current player status
+  					   0 = no disc in drive
+  					   1 = stopped
+  					   2 = playing
+  					   3 = paused
+  					 */
+  int		playbtn;		/* State of play button, same as
+  					   above (use CDROM_ equates)
+  					 */
+  int		time;			/* Time mode			*/
+  int		track,                  /* track # - 1 to end of CD     */
+                minute,
+                second;                 /* Info for the display		*/
+  int		repeat;			/* Repeat status		*/
+} display;
+
+
+
+/* Signal handling code */
+static int caught_fatal_sig = 0;
+
+static void on_signal (int sig_num)
+{
+  if (caught_fatal_sig)
+/*    raise (sig_num);*/
+    kill (getpid (), sig_num);
+  caught_fatal_sig = 1;
+
+  switch (sig_num)
+    {
+    case SIGHUP:
+      g_print("sighup caught\n");
+      gdk_exit(1);
+      break;
+    case SIGINT:
+      g_print("sigint caught\n");
+      gdk_exit(1);
+      break;
+    case SIGQUIT:
+      g_print("sigquit caught\n");
+      gdk_exit(1);
+      break;
+   case SIGABRT:
+      g_print("sigabrt caught\n");
+      gdk_exit(1);
+      break;
+    case SIGBUS:
+      g_print("sigbus caught\n");
+      destroy(NULL,NULL);
+      break;
+    case SIGSEGV:
+      g_print("sigsegv caught\n");
+      destroy(NULL,NULL);
+      break;
+    case SIGPIPE:
+      g_print("sigpipe caught\n");
+      gdk_exit(1);
+      break;
+    case SIGTERM:
+      g_print("sigterm caught\n");
+      gdk_exit(1);
+      break;
+    case SIGFPE:
+      g_print("sigfpe caught\n");
+      destroy(NULL,NULL);
+      break;
+    default:
+      g_print("unknown signal\n");
+      destroy(NULL,NULL);
+      break;
+    }
+}
+
+static void on_sig_child (int sig_num)
+{
+  int pid;
+  int status;
+
+  while (1)
+    {
+      pid = waitpid (WAIT_ANY, &status, WNOHANG);
+      if (pid <= 0)
+        break;
+    }
+}
+
+
+/* ------------------------------------------------------------------------
+   Where it all begins...
+   ------------------------------------------------------------------------ */
+int main( int argc, char *argv[] )
+{
+  int    x,
+         x_ret,
+         y_ret,
+         w_ret,
+         h_ret,
+         stat=0;
+
+  bzero( &cdinfo, sizeof( struct CDINFO ) );
+
+  /* Start up the CD control process */
+  if( ( cd_fd = start_cd_control( &cd_pid ) ) < 0 )
+    {
+      perror("start_cd_control error");
+      exit(-1);
+    }
+
+  /* Start up the CDDBD control process */
+  if( ( cddbd_fd = start_cddbd( &cddbd_pid ) ) < 0 )
+    {
+      perror("start_cd_dbd error");
+      exit(-1);
+    }
+
+  /* Startup GTK */
+  gtk_init (&argc, &argv);
+
+  /* Tell gdk to watch the cd control and cddb pipes for reading */
+  gdk_cd_fd = gdk_input_add( cd_fd, GDK_INPUT_READ, cd_fd_read, 0 );
+  gdk_cddbd_fd = gdk_input_add( cddbd_fd, GDK_INPUT_READ, cddbd_fd_read, 0 );
+
+  /* Get the -geometry parameters */
+  for( x = 0; x < argc; x++ )
+    {
+      if( (strcasecmp( argv[x], "-geometry" ) == 0) || (strcasecmp( argv[x], "-geom" ) == 0) )
+	{
+	if( argv[x+1] != NULL )
+	  {
+#ifdef DEBUG7
+	    g_print("Passing %s to XParseGeometry\n", argv[x+1]);
+#endif
+
+	    stat = XParseGeometry( argv[x+1], &x_ret, &y_ret, &w_ret, &h_ret );
+
+#ifdef DEBUG7
+	    g_print("%d = XParseGeometry( s, %d, %d, %d, %d )\n",
+                    stat, x_ret, y_ret, w_ret, h_ret );
+#endif
+	  }
+	}
+    }
+
+ /* Handle some signals */
+  signal (SIGHUP, on_signal);
+  signal (SIGINT, on_signal);
+  signal (SIGQUIT, on_signal);
+  signal (SIGABRT, on_signal);
+  signal (SIGBUS, on_signal);
+  signal (SIGSEGV, on_signal);
+  signal (SIGPIPE, on_signal);
+  signal (SIGTERM, on_signal);
+  signal (SIGFPE, on_signal);
+  
+  /* Handle child exits */
+  signal (SIGCHLD, on_sig_child);
+
+  run_gtk( stat, x_ret, y_ret );
+
+  gdk_input_remove( gdk_cd_fd );
+  gdk_input_remove( gdk_cddbd_fd );
+
+  /* Tell cd_control to quit */
+  cmnd[0] = CD_QUIT;
+  cmnd[1] = 0;
+  if( write( cd_fd, &cmnd, 2 ) < 0 )
+    {
+      perror("write to cd_control error");
+      close( cd_fd );
+      exit(-1);
+    }
+
+  /* Tell cddbd to quit */
+  cdinfo.cddbd_cmnd = DB_QUIT;
+  if( write( cddbd_fd, &cdinfo, sizeof( struct CDINFO ) ) < 0 )
+    {
+      perror("write to cddbd error");
+      close( cd_fd );
+      close( cddbd_fd );
+      exit(-1);
+    }
+
+  close( cd_fd );
+  close( cddbd_fd );
+  return(0);
+}
+
+
+
+/* ----- subroutines follow ------ */
+
+
+void send_device()
+{
+  char  buffer[80];
+
+  /* Send the CD device to the cd_control process */
+  buffer[0] = CD_SET_DEVICE;
+  buffer[1] = 0;
+  if( write( cd_fd, buffer, 2 ) < 0 )
+    {
+      perror("write to cd_control error - 1a");
+    }
+
+  sprintf( buffer, "%s\n", config.device );
+  if( write( cd_fd, buffer, strlen(buffer) ) < 0 )
+    {
+      perror("write to cd_control error - 1b");
+    }
+}
+
+
+/* ------------------------------------------------------------------------
+   Read the configuration file from $HOME/.xfreecdrc
+
+   Return -2 if a malloc fails
+   ------------------------------------------------------------------------ */
+int read_config( struct CONFIG *config )
+{
+  FILE  *fp;
+  char  fname[1024],
+        line[80],
+        *p;
+  struct SITE *sp, *sp2;
+
+  if( ( p = getenv( "HOME" ) ) == NULL )
+    {
+      g_print("Cannot find HOME enviornmental variable\n");
+      return(-1);
+    }
+
+  strncpy( fname, p, 1023 );
+  if( fname[strlen(fname)-1] != '/' )
+    strcat( fname, "/" );
+  strcat( fname, ".xfreecdrc" );
+
+  if( ( fp = fopen( fname, "rb" ) ) == NULL )
+    {
+      /* Setup reasonable defaults */
+
+      /* Setup for the default device (/dev/cdrom) */
+      if( ( config->device = (char *) malloc( strlen(DEFAULT_DEVICE)+1 ) ) == NULL )
+	{
+	  return(-2);
+	}
+      strcpy( config->device, DEFAULT_DEVICE );
+
+      /* Get some memory for the path to the local database.
+	 By default I put this in the user's home directory ~/.cddb
+      */
+      if( ( config->local_cddb = (char *) malloc( strlen(DEFAULT_CDDB_PATH)+1 ) ) == NULL )
+	{
+	  return(-2);
+	}
+      strcpy( config->local_cddb, DEFAULT_CDDB_PATH );
+      strcpy( cdinfo.local_cddb, config->local_cddb );
+
+     /* Get some memory for the cddbd email address */
+      if( ( config->to_cddbd = (char *) malloc( strlen(DEFAULT_TO_CDDBD)+1 ) ) == NULL )
+	{
+	  return(-2);
+	}
+      strcpy( config->to_cddbd, DEFAULT_TO_CDDBD );
+
+      /* Get some memory for the SITE */
+      if( ( config->server = (struct SITE *) malloc( sizeof(struct SITE) ) ) == NULL )
+	{
+	  return(-2);
+	}
+
+      bzero( config->server, sizeof(struct SITE) );
+      
+       /* Fill in the site with cddb.cddb.com */
+      if( ( config->server->name = (char *) malloc( strlen(DEFAULT_SERVER)+1 ) ) == NULL )
+	{
+	  return(-2);
+	}
+      strcpy( config->server->name, DEFAULT_SERVER );
+      config->server->port = 888;
+      config->server->next = NULL;
+
+      /* Set current server to the default */
+      if( ( config->current = (char *) malloc( strlen(DEFAULT_SERVER)+1 ) ) == NULL )
+	{
+	  return(-2);
+	}
+      strcpy( config->current, DEFAULT_SERVER );
+
+      config->done_eject = 0;          /* Eject when done playing */
+      config->exit_eject = 0;          /* Eject on exit when not playing */
+      config->startup = 1;             /* Play at startup */
+      config->cddb = 0;
+      config->changer = 0;
+      config->saved = 0;               /* Needs to be saved */
+
+      /* Write this as the default */
+      return( write_config( config ) );
+    }
+
+  /* Process the lines in the file */
+  while( fgets( line, 80, fp ) != NULL )
+    {
+      if( (line[0] == '#') || (line[0] == '\n') )
+	continue;
+
+      p = strtok( line, "= \n" );
+      if( strcmp( p, "DEVICE" ) == 0 )
+	{
+	  p = strtok( NULL, "= \n" );
+	  /* Get some memory for the device */
+	  if( ( config->device = (char *) malloc( strlen(p)+1 ) ) == NULL )
+	    {
+	      fclose( fp );
+	      return(-2);
+	    }
+	  strcpy( config->device, p );
+
+	  continue;
+	}
+
+      if( strcmp( p, "LOCAL_CDDB" ) == 0 )
+	{
+	  p = strtok( NULL, "= \n" );
+	  /* Get some memory for the path to the local database.
+	  */
+	  if( ( config->local_cddb = (char *) malloc( strlen(p)+1 ) ) == NULL )
+	    {
+	      fclose( fp );
+	      return(-2);
+	    }
+	  strcpy( config->local_cddb, p );
+	  strcpy(  cdinfo.local_cddb, p );
+	  continue;
+	}
+
+      if( strcmp( p, "TO_CDDBD" ) == 0 )
+	{
+	  p = strtok( NULL, "= \n" );
+	  /* Get some memory for the path to the local database.
+	  */
+	  if( ( config->to_cddbd = (char *) malloc( strlen(p)+1 ) ) == NULL )
+	    {
+	      fclose( fp );
+	      return(-2);
+	    }
+	  strcpy( config->to_cddbd, p );
+	  continue;
+	}
+
+      if( strcmp( p, "SERVER" ) == 0 )
+	{
+	  p = strtok( NULL, "=: \n" );
+
+	  /* Reserve some space for this server, add it to the end of the list */
+	  if( ( sp = (struct SITE *) malloc( sizeof(struct SITE) ) ) == NULL )
+	    {
+	      return(-2);
+	    }
+	  bzero( sp, sizeof(struct SITE) );
+      
+	  /* Reserve space for the name */
+	  if( ( sp->name = (char *) malloc( strlen(p)+1 ) ) == NULL )
+	    {
+	      return(-2);
+	    }
+	  strcpy( sp->name, p );
+
+	  p = strtok( NULL, "=: \n" );
+	  sp->port = atoi(p);
+	  sp->next = NULL;
+
+	  /* Is it the first in the list? */
+	  if( config->server == NULL )
+	    {
+	      /* Yep, First in the list */
+	      config->server = sp;
+	    } else {
+	      /* Walk to the end of the list (no cuts!!) */
+	      sp2 = config->server;
+	      while( sp2->next != NULL )
+		{
+		  sp2 = sp2->next;
+		}
+
+	      /* Add the new site to the end of the list */
+	      sp2->next = sp;
+	    }
+
+	  continue;
+	}
+
+      if( strcmp( p, "CURRENT" ) == 0 )
+	{
+	  p = strtok( NULL, "= \n" );
+
+	  /* Get some memory for the current server name */
+	  if( ( config->current = (char *) malloc( strlen(p)+1 ) ) == NULL )
+	    {
+	      fclose( fp );
+	      return(-2);
+	    }
+	  strcpy( config->current, p );
+	  continue;
+	}
+
+      if( strcmp( p, "DONE_EJECT" ) == 0 )
+	{
+	  p = strtok( NULL, "= \n" );
+	  config->done_eject = atoi( p );
+	  continue;
+	}
+
+      if( strcmp( p, "EXIT_EJECT" ) == 0 )
+	{
+	  p = strtok( NULL, "= \n" );
+	  config->exit_eject = atoi( p );
+	  set_eject( config->exit_eject );          /* Tell the CD_CONTROL device about state */
+	  continue;
+	}
+
+      if( strcmp( p, "STARTUP" ) == 0 )
+	{
+	  p = strtok( NULL, "= \n" );
+	  config->startup = atoi( p );
+	  continue;
+	}
+
+      if( strcmp( p, "CDDB" ) == 0 )
+	{
+	  p = strtok( NULL, "= \n" );
+	  config->cddb = atoi( p );
+	  continue;
+	}
+
+      if( strcmp( p, "CHANGER" ) == 0 )
+	{
+	  p = strtok( NULL, "= \n" );
+	  config->changer = atoi( p );
+	  continue;
+	}
+
+
+    }
+  fclose( fp );
+
+
+  /* 
+     I've added config->to_cddbd since last release, so if it wasn't read from the
+     rcfile give it a default value so people don't need to erase their old rcfile
+  */
+  if( config->to_cddbd == NULL )
+    {
+      if( ( config->to_cddbd = (char *) malloc( strlen( DEFAULT_TO_CDDBD ) + 1 ) ) == NULL )
+	{
+	  fclose( fp );
+	  return(-2);
+	}
+      strcpy( config->to_cddbd, DEFAULT_TO_CDDBD );
+    }
+  
+  config->saved = 1;            /* Just read it, same as saved file */
+
+  return 0;
+}
+
+
+/* ------------------------------------------------------------------------
+   Write the configuration file to $HOME/.xfreecdrc
+   ------------------------------------------------------------------------ */
+int write_config( struct CONFIG *config )
+{
+  FILE  *fp;
+  char  fname[1024],
+        *p;
+  struct SITE  *sp;
+
+  /* Already saved, no need to save it again */
+  if( config->saved == 1 )
+    return(0);
+
+  if( ( p = getenv( "HOME" ) ) == NULL )
+    {
+      g_print("Cannot find HOME enviornmental variable\n");
+      return(-1);
+    }
+
+  strncpy( fname, p, 1023 );
+  if( fname[strlen(fname)-1] != '/' )
+    strcat( fname, "/" );
+  strcat( fname, ".xfreecdrc" );
+
+  if( ( fp = fopen( fname, "wb" ) ) == NULL )
+    {
+      return(-2);
+    }
+
+  fprintf( fp, "# XfreeCD v%s configuration file\n", VERSION );
+  fprintf( fp, "#\n");
+  fprintf( fp, "DEVICE=%s\n", config->device );
+  fprintf( fp, "LOCAL_CDDB=%s\n", config->local_cddb );
+  fprintf( fp, "TO_CDDBD=%s\n", config->to_cddbd );
+
+  /* Walk down the list of servers */
+  sp = config->server;
+  while( sp != NULL )
+    {
+      fprintf( fp, "SERVER=%s:%d\n", sp->name, sp->port);
+      sp = sp->next;
+    }
+
+  fprintf( fp, "CURRENT=%s\n", config->current );
+  fprintf( fp, "DONE_EJECT=%d\n", config->done_eject );
+  fprintf( fp, "EXIT_EJECT=%d\n", config->exit_eject );
+  fprintf( fp, "STARTUP=%d\n", config->startup );
+  fprintf( fp, "CDDB=%d\n", config->cddb );
+  fprintf( fp, "CHANGER=%d\n", config->changer );
+
+  fclose( fp );
+
+  config->saved = 1;            /* config is now same as saved on disk */
+
+  return 0;
+}
+
+
+
+/* -----------------------------------------------------------------------
+   Free up the info used in the cdinfo structure
+   ----------------------------------------------------------------------- */
+void free_cdinfo()
+{
+  int  x;
+
+#ifdef DEBUG8
+  g_print("Freeing any used extended data\n" );
+#endif
+
+  if( cdinfo.title != NULL )
+    {
+      g_string_free( cdinfo.title, 1 );
+      cdinfo.title = NULL;
+    }
+
+  if( cdinfo.category != NULL )
+    {
+      g_string_free( cdinfo.category, 1 );
+      cdinfo.category = NULL;
+    }
+
+  for( x = 0; x < 99; x++ )
+    {
+      if( cdinfo.name[x] != NULL )
+	{
+	  g_string_free( cdinfo.name[x], 1 );
+	  cdinfo.name[x] = NULL;
+	}
+    }
+
+
+  if( cdinfo.extd != NULL )
+    {
+      g_string_free( cdinfo.extd, 1 );
+      cdinfo.extd = NULL;
+    }
+
+  for( x = 0; x < 99; x++ )
+    {
+      if( cdinfo.extt[x] != NULL )
+	{
+	  g_string_free( cdinfo.extt[x], 1 );
+	  cdinfo.extt[x] = NULL;
+	}
+    }
+
+  /* Clean up the display's temporary storage */
+  if( display.tmp_category != NULL )
+    {
+      g_string_free( display.tmp_category, 1 );
+      display.tmp_category = NULL;
+    }
+
+  if( display.tmp_title != NULL )
+    {
+      g_string_free( display.tmp_title, 1 );
+      display.tmp_title = NULL;
+    }
+
+  for( x = 0; x < 99; x++ )
+    {
+      if( display.tmp_track[x] != NULL )
+	{
+	  g_string_free( display.tmp_track[x], 1 );
+	  display.tmp_track[x] = NULL;
+	}
+    }  
+}
+
+
+/* -----------------------------------------------------------------------
+   Free up any memory used by the config structure to store the paths
+   and site names.
+   ----------------------------------------------------------------------- */
+void free_config( struct CONFIG *config )
+{
+  struct SITE *sp;
+
+  /* Need to free up memory usage */
+  free( config->local_cddb );
+  free( config->device );
+  free( config->to_cddbd );
+
+  /* Walk the server list, freeing up memory */
+  while( config->server != NULL )
+    {
+      sp = config->server;
+      config->server = config->server->next;
+      free( sp->name );
+      free( sp );
+    }
+
+  /* Free up the dynamically allocated strings in cdinfo */
+  free_cdinfo();
+}
+
+
+
+/* -----------------------------------------------------------------------
+   Load the CD info from the local database or set defaults
+   ----------------------------------------------------------------------- */
+void local_cddb()
+{
+
+#ifdef DEBUG1
+  g_print("Loading local Database\n");
+#endif
+
+  /* No internet support, just try and read the local DB */
+  if( read_cddb( &cdinfo ) < 0 )
+    {
+
+#ifdef DEBUG1
+      g_print("Not found on disk, defaulting\n");
+#endif
+
+      /* Unknown title */
+      if( cdinfo.title == NULL )
+	cdinfo.title = g_string_new( "Unknown CD" );
+      else
+	cdinfo.title = g_string_assign( cdinfo.title, "Unknown CD" );
+
+      if( cdinfo.category == NULL )
+	cdinfo.category = g_string_new( "misc" );
+      else
+	cdinfo.category = g_string_assign( cdinfo.category, "misc" );
+
+      /* Set a default revision, so they can edit the list */
+      cdinfo.revision = 0;
+    }	      
+
+#ifdef DEBUG9
+  g_print("local_cddb() revision = %d\n", cdinfo.revision );
+#endif
+
+}
+
+
+/* -----------------------------------------------------------------------
+   The Main GTK setup routine
+   ----------------------------------------------------------------------- */
+int run_gtk( int stat, int x_ret, int y_ret )
+{
+  GtkWidget	*window,
+                *button,
+  	        *hbox1,
+  		*hbox2,
+        	*table;
+  GtkTooltips	*tips;
+  GtkStyle	*style;
+  GdkColor	tip_color;
+  GdkColormap	*colormap;      
+  gint          timer;
+  CursorOffset  *icon_pos;
+  int           x_pos, 
+                y_pos;
+
+  bzero( &config, sizeof( struct CONFIG ) );
+  bzero( &display, sizeof( struct _display ) );
+  bzero( &cdinfo, sizeof( struct CDINFO ) );
+
+  cdinfo.revision = -1;                /* Initalize the revision number */
+
+  /* Copyright info, version info */
+  g_print("XfreeCD v%s\n", VERSION );
+  g_print("Copyright 1998 by Brian C. Lane\n<http://www.tatoosh.com/nexus>\n\n");
+
+  root_win = gdk_window_foreign_new (GDK_ROOT_WINDOW ());
+
+  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  display.main_window = window;
+  gtk_container_border_width( GTK_CONTAINER( window ), 0 );
+
+  /* Give it a name */
+  gtk_window_set_title (GTK_WINDOW (window), "XfreeCD");
+  gtk_window_set_wmclass(GTK_WINDOW(window), "XfreeCD", NULL );
+
+  /* when the window is given the "delete_event" signal (this is given
+   * by the window manager (usually the 'close' option, or on the
+   * titlebar), we ask it to call the delete_event () function
+   * as defined above.  The data passed to the callback
+   * function is NULL and is ignored in the callback. */
+  gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+		      GTK_SIGNAL_FUNC (delete_event), NULL);
+  
+  /* here we connect the "destroy" event to a signal handler.  
+   * This event occurs when we call gtk_widget_destroy() on the window,
+   * or if we return 'FALSE' in the "delete_event" callback. */
+  gtk_signal_connect (GTK_OBJECT (window), "destroy",
+		      GTK_SIGNAL_FUNC (destroy), NULL);
+
+  gtk_widget_realize(window);
+
+  /* Start up a new list of tool tips */
+  tips = gtk_tooltips_new();
+
+  /* Show the tooltips after the cursor has paused for 2 seconds */
+  gtk_tooltips_set_delay( tips, 2000 );
+
+  /*
+   * This section fills in all the data structures used by the xpm_button
+   * subroutine call to create buttons.
+   * Eventually this will be more automatic/cleaner/maybe a widget?
+   */
+   
+  ff.up_xpm = (gchar *) ffup_xpm;
+  ff.dn_xpm = (gchar *) ffdn_xpm;
+  ff.press = &ff_press;
+  ff.release = &ff_release;
+
+  rew.up_xpm = (gchar *) rewup_xpm;
+  rew.dn_xpm = (gchar *) rewdn_xpm;
+  rew.press = &rew_press;
+  rew.release = &rew_release;
+  
+  play.up_xpm = (gchar *) stopup_xpm;
+  play.dn_xpm = (gchar *) playdn_xpm;
+  play.press = &play_press;
+  play.release = &play_release;
+  
+  eject.up_xpm = (gchar *) ejup_xpm;
+  eject.dn_xpm = (gchar *) ejdn_xpm;
+  eject.press = &eject_press;
+  eject.release = &eject_release;
+
+  ex.up_xpm = (gchar *) exitup_xpm;
+  ex.dn_xpm = (gchar *) exitdn_xpm;
+  ex.press = &ex_press;
+  ex.release = &ex_release;
+  
+  help.up_xpm = (gchar *) helpup_xpm;
+  help.dn_xpm = (gchar *) helpdn_xpm;
+  help.press = &help_press;
+  help.release = &help_release;
+
+  tdisp.up_xpm = (gchar *) plstrkup_xpm;
+  tdisp.dn_xpm = (gchar *) plstrkdn_xpm;
+  tdisp.press = &tdisp_press;
+  tdisp.release = &tdisp_release;
+  
+  rpt.up_xpm = (gchar *) rptup_xpm;
+  rpt.dn_xpm = (gchar *) rptdn_xpm;
+  rpt.press = &rpt_press;
+  rpt.release = &rpt_release;
+  
+  vol.up_xpm = (gchar *) volup_xpm;
+  vol.dn_xpm = (gchar *) voldn_xpm;
+  vol.press = &vol_press;
+  vol.release = &vol_release;
+  
+  
+  /* 
+   *  The XfreeCD window consists of:
+   *    one vertical box that contains:
+   *    Two vertical boxes
+   *    The top one with hbox of the display and right justified, a 3x2 table
+   *    The bottom one with a hbox of 3 buttons
+   */
+
+  /* Make a vbox to hold our hboxes */
+  display.vbox = gtk_vbox_new( FALSE, 0 );
+  gtk_container_add( GTK_CONTAINER( window ), display.vbox );
+  gtk_widget_show( display.vbox );
+
+  /* Make a hbox to hold the bottom row of buttons REW/PLAY/FF */    
+  hbox1 = gtk_hbox_new( FALSE, 0 );
+  gtk_box_pack_end( GTK_BOX( display.vbox ), hbox1, FALSE, FALSE, 0 );
+  gtk_widget_show( hbox1 );
+
+  /* Make a hbox to put the table into */
+  hbox2 = gtk_hbox_new( FALSE, 0 );
+  gtk_box_pack_start( GTK_BOX( display.vbox ), hbox2, FALSE, FALSE, 0 );
+  gtk_widget_show( hbox2 );  
+
+  /* Make the xpm_buttons and add the tooltips for each one */
+  button = xpm_button( window, &rew );
+  gtk_box_pack_start( GTK_BOX( hbox1 ), button, FALSE, FALSE, 0 );
+  gtk_widget_show( button );
+  gtk_tooltips_set_tip( tips, button, "Previous Track", "ContextHelp/buttons/Prev" );
+
+  button = xpm_button( window, &play );
+  gtk_box_pack_start( GTK_BOX( hbox1 ), button, FALSE, FALSE, 0 );
+  gtk_widget_show( button );
+  gtk_tooltips_set_tip( tips, button, "Play/Pause", "ContextHelp/buttons/Play" );
+
+  button = xpm_button( window, &ff );
+  gtk_box_pack_start( GTK_BOX( hbox1 ), button, FALSE, FALSE, 0 );
+  gtk_widget_show( button );
+  gtk_tooltips_set_tip( tips, button, "Next Track", "ContextHelp/buttons/Next" );
+  
+  /* Make a table for the 6 control buttons */
+  table = gtk_table_new( 2, 3, TRUE );
+
+  /* Add the table to the end of the hbox (the display goes first) */
+  gtk_box_pack_end( GTK_BOX( hbox2 ), table, FALSE, FALSE, 0 );
+
+  /* Make sure it is showing */
+  gtk_widget_show( table );
+  
+  button = xpm_button( window, &vol );
+  gtk_table_attach( GTK_TABLE( table ), button, 0, 1, 0, 1, 0, 0, 0, 0 );
+  gtk_widget_show( button );
+  gtk_tooltips_set_tip( tips, button, "Volume", "ContextHelp/buttons/Volume" );
+  
+  button = xpm_button( window, &tdisp );
+  gtk_table_attach( GTK_TABLE( table ), button, 1, 2, 0, 1, 0, 0, 0, 0 );
+  gtk_widget_show( button );
+  gtk_tooltips_set_tip( tips, button, "Time Display", "ContextHelp/buttons/Time" );
+  
+  button = xpm_button( window, &ex );
+  gtk_table_attach( GTK_TABLE( table ), button, 2, 3, 0, 1, 0, 0, 0, 0 );
+  gtk_widget_show( button );
+  gtk_tooltips_set_tip( tips, button, "Exit", "ContextHelp/buttons/Exit" );
+  
+  button = xpm_button( window, &rpt );
+  gtk_table_attach( GTK_TABLE( table ), button, 0, 1, 1, 2, 0, 0, 0, 0 );
+  gtk_widget_show( button );
+  gtk_tooltips_set_tip( tips, button, "Repeat", "ContextHelp/buttons/Repeat" );
+  
+  button = xpm_button( window, &eject );
+  gtk_table_attach( GTK_TABLE( table ), button, 1, 2, 1, 2, 0, 0, 0, 0 );
+  gtk_widget_show( button );
+  gtk_tooltips_set_tip( tips, button, "Eject", "ContextHelp/buttons/Eject" );
+  
+  button = xpm_button( window, &help );
+  gtk_table_attach( GTK_TABLE( table ), button, 2, 3, 1, 2, 0, 0, 0, 0 );
+  gtk_widget_show( button );
+  gtk_tooltips_set_tip( tips, button, "Help", "ContextHelp/buttons/Help" );
+  
+
+  /* Get the window's style info */
+  style = gtk_widget_get_style( window );
+
+  /* Load all the other pixmaps (some are duplicates) */
+  display.null_pixmap = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.null_mask,
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) null_xpm );
+  
+  display.nodisc_pixmap = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.nodisc_mask,
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) nodisc_xpm );
+  
+  display.minus_pixmap = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.minus_mask,
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) minus_xpm );
+
+  display.playup_pixmap = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.playup_mask,
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) playup_xpm );
+
+  display.playdn_pixmap = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.playdn_mask,
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) playdn_xpm );
+
+  display.pauseup_pixmap = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.pauseup_mask,
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) pauseup_xpm );
+
+  display.stopup_pixmap = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.stopup_mask,
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) stopup_xpm );
+
+  display.sfwddn_pixmap = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.sfwddn_mask,
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) sfwddn_xpm );
+
+  display.srevdn_pixmap = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.srevdn_mask,
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) srevdn_xpm );
+
+  display.rptupact_pixmap = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.rptupact_mask,
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) rptupact_xpm );
+
+  display.plstrkup_pixmap = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.plstrkup_mask,
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) plstrkup_xpm );
+
+  display.plstrkdn_pixmap = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.plstrkdn_mask,
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) plstrkdn_xpm );
+
+  display.mnstrkup_pixmap = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.mnstrkup_mask,
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) mnstrkup_xpm );
+
+  display.mnstrkdn_pixmap = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.mnstrkdn_mask,
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) mnstrkdn_xpm );
+
+  display.plscdup_pixmap = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.plscdup_mask,
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) plscdup_xpm );
+
+  display.plscddn_pixmap = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.plscddn_mask,
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) plscddn_xpm );
+
+  display.mnscdup_pixmap = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.mnscdup_mask,
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) mnscdup_xpm );
+
+  display.mnscddn_pixmap = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.mnscddn_mask,
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) mnscddn_xpm );
+
+  display.bar_pixmap = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.bar_mask,
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) bar_xpm );
+
+  display.nobar_pixmap = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.nobar_mask,
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) nobar_xpm );
+
+  display.redbar_pixmap = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.redbar_mask,
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) redbar_xpm );
+
+  display.a_pixmap[0] = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.a_mask[0],
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) a0_xpm );
+ 
+  display.a_pixmap[1] = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.a_mask[1],
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) a1_xpm );
+ 
+  display.a_pixmap[2] = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.a_mask[2],
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) a2_xpm );
+ 
+  display.a_pixmap[3] = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.a_mask[3],
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) a3_xpm );
+ 
+  display.a_pixmap[4] = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.a_mask[4],
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) a4_xpm );
+ 
+  display.a_pixmap[5] = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.a_mask[5],
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) a5_xpm );
+ 
+  display.a_pixmap[6] = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.a_mask[6],
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) a6_xpm );
+ 
+  display.a_pixmap[7] = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.a_mask[7],
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) a7_xpm );
+ 
+  display.a_pixmap[8] = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.a_mask[8],
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) a8_xpm );
+ 
+  display.a_pixmap[9] = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.a_mask[9],
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) a9_xpm );
+ 
+  display.a_pixmap[10] = gdk_pixmap_create_from_xpm_d( window->window,
+  		 				    &display.a_mask[10],
+  		 				    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) an_xpm );
+ 
+ 
+  display.b_pixmap[0] = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.b_mask[0],
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) b0_xpm );
+
+  display.b_pixmap[1] = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.b_mask[1],
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) b1_xpm );
+
+  display.b_pixmap[2] = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.b_mask[2],
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) b2_xpm );
+
+  display.b_pixmap[3] = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.b_mask[3],
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) b3_xpm );
+
+  display.b_pixmap[4] = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.b_mask[4],
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) b4_xpm );
+
+  display.b_pixmap[5] = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.b_mask[5],
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) b5_xpm );
+
+  display.b_pixmap[6] = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.b_mask[6],
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) b6_xpm );
+
+  display.b_pixmap[7] = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.b_mask[7],
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) b7_xpm );
+
+  display.b_pixmap[8] = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.b_mask[8],
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) b8_xpm );
+
+  display.b_pixmap[9] = gdk_pixmap_create_from_xpm_d( window->window,
+  						    &display.b_mask[9],
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) b9_xpm );
+
+  display.b_pixmap[10] = gdk_pixmap_create_from_xpm_d( window->window,
+   						    &display.b_mask[10],
+  						    &style->bg[GTK_STATE_NORMAL],
+  						    (gchar **) bn_xpm );
+
+  /*
+   * Create a drawing area for us to show the track and time
+   */
+  display.wid = gtk_drawing_area_new();
+  gtk_box_pack_start( GTK_BOX( hbox2 ), display.wid, FALSE, FALSE, 0 );
+  gtk_widget_show( display.wid );
+
+  /* Make sure it is redrawn when covered and uncovered by others */  
+  gtk_signal_connect( GTK_OBJECT( display.wid ), "expose_event",
+  		      (GtkSignalFunc) expose_display, NULL );
+
+  gtk_drawing_area_size( GTK_DRAWING_AREA(display.wid), 92, 30 );
+  gtk_widget_set_events( display.wid, GDK_EXPOSURE_MASK | 
+                         GDK_BUTTON_MOTION_MASK |
+                         GDK_POINTER_MOTION_HINT_MASK |
+                         GDK_BUTTON_PRESS_MASK);
+
+  /*  gtk_widget_realize (display.wid);*/
+
+  gtk_signal_connect (GTK_OBJECT (display.wid), "button_press_event",
+                      GTK_SIGNAL_FUNC (display_pressed),NULL);
+  gtk_signal_connect (GTK_OBJECT (display.wid), "button_release_event",
+                      GTK_SIGNAL_FUNC (display_released),NULL);
+  gtk_signal_connect (GTK_OBJECT (display.wid), "motion_notify_event",
+                      GTK_SIGNAL_FUNC (display_motion),NULL);
+
+  /* Data area to keep track of the cursor position for moving the window */
+  icon_pos = g_new (CursorOffset, 1);
+  gtk_object_set_user_data(GTK_OBJECT(display.wid), icon_pos);
+
+  x_pos = 0;
+  y_pos = 0;
+  /* Check the retun bits -- we want XValue & YValue */
+  if( stat & XValue )
+    {
+      /* Is the value negative (relative to right side?) */
+      if( stat & XNegative )
+	{
+	  /* Make sure it returned a negative value */
+	  if( x_ret < 0 )
+	    x_pos = (gdk_screen_width()-137) + x_ret;
+	  else
+	    x_pos = (gdk_screen_width()-137) - x_ret;
+	} else {
+	  x_pos = x_ret;
+	}
+    }
+
+  /* Did we get a Y position? */
+  if( stat & YValue )
+    {
+      /* Is the value negative (relative to bottom side?) */
+      if( stat & YNegative )
+	{
+	  /* Make sure it returned a negative value */
+	  if( y_ret < 0 )
+	    y_pos = (gdk_screen_height()-60) + y_ret;
+	  else
+	    y_pos = (gdk_screen_height()-60) - y_ret;
+	} else {
+	  y_pos = y_ret;
+	}
+    }
+
+#ifdef DEBUG7
+  g_print("Setting x=%d  y=%d\n", x_pos, y_pos );
+#endif
+
+  /* Put the window where the user wants it (x_pos,y_pos) */
+  gtk_widget_set_uposition( window, x_pos, y_pos );
+
+  /* Setup the colors for the tooltip windows, postit yellow */
+  colormap = gdk_window_get_colormap (window->window);
+  tip_color.red = 61669;
+  tip_color.green = 59113;
+  tip_color.blue = 35979;
+  gdk_color_alloc (colormap, &tip_color);
+
+  /* Set the foreground/background of the tooltips */
+  gtk_tooltips_set_colors( tips, &tip_color, &window->style->fg[GTK_STATE_NORMAL] );
+
+  /* Showing the window last so everything pops up at once. */
+  gtk_widget_show (window);
+
+  /* Start the 1 second update timer */
+  timer = gtk_timeout_add( 1000, update_cdrom, NULL );
+
+  /*
+     Read some useful info from .xfreecdrc
+     Path to local database
+     server list
+     default server
+  */
+  if( read_config( &config ) < 0 )
+    {
+      g_print("read_config failed\n");
+      g_free( icon_pos );
+      exit(-1);
+    }
+
+  /* Send the device to the cd_control process */
+  send_device();
+
+  /* Tell cd_control about the exit on eject decision */
+  set_eject( config.exit_eject );
+
+  gtk_main ();
+
+  /* Turn off the 1 second timeout */
+  gtk_timeout_remove( timer );
+
+  g_free( icon_pos );
+
+  free_config( &config );        /* Free up config's memory usage */
+
+  return(0);
+}
+
+
+gint delete_event(GtkWidget *widget, gpointer data)
+{
+    /* if you return FALSE in the "delete_event" signal handler,
+     * GTK will emit the "destroy" signal.  Returning TRUE means
+     * you don't want the window to be destroyed.
+     * This is useful for popping up 'are you sure you want to quit ?'
+     * type dialogs. */
+
+    /* Change TRUE to FALSE and the main window will be destroyed with
+     * a "delete_event". */
+
+    return (FALSE);
+}
+
+/* another callback */
+void destroy (GtkWidget *widget, gpointer data)
+{
+  gtk_main_quit ();
+}
+
+
+
+/* --------------------------------------------------------------
+   Copy the edited data over to cdinfo and write to local database
+   --------------------------------------------------------------- */
+void write_tracks()
+{
+  GString      *old_category;
+  int  x;
+  char         *texts[3],
+               *p,
+               text1[255],
+               text2[255],
+               fname[1024],
+               tmp_fname[1024];
+
+
+  /* Sanity checks. We can't save or send if some of the important fields
+     are blank.
+  */
+  if( display.tmp_title == NULL )
+    return;
+
+  if( display.tmp_category == NULL )
+    return;
+
+  if( cdinfo.category == NULL )
+    return;
+
+  /* Save the old category so we can erase it if its changed */
+  old_category = g_string_new( cdinfo.category->str );
+  
+  /* Copy the new title into the cdinfo structure */
+  cdinfo.title = g_string_assign( cdinfo.title, display.tmp_title->str );
+  g_string_free( display.tmp_title, 1 );
+  display.tmp_title = NULL;
+
+  /* Copy the track names if they exist and delete display storage */
+  for( x = 0; x < cdinfo.tochdr.cdth_trk1; x++ )
+    {
+      if( display.tmp_track[x] != NULL )
+	{
+	  if( cdinfo.name[x] == NULL )
+	    cdinfo.name[x] = g_string_new( display.tmp_track[x]->str );
+	  else
+	    cdinfo.name[x] = g_string_assign( cdinfo.name[x], display.tmp_track[x]->str );
+	  g_string_free( display.tmp_track[x], 1 );
+	  display.tmp_track[x] = NULL;
+	}
+    }
+
+  /* Copy the new categry name over */
+  cdinfo.category = g_string_assign( cdinfo.category, display.tmp_category->str );
+
+  /* Update the track window's info if its still open */
+  if( display.twindow != NULL )
+    {
+      gtk_clist_freeze (GTK_CLIST (display.tclist));
+
+      /* Clear out the old list first */
+      gtk_clist_clear( GTK_CLIST( display.tclist ) );
+
+      /* Set the new title */
+      if( cdinfo.title != NULL )
+	sprintf( text1, "%s", cdinfo.title->str );
+      else
+	strcpy( text1, "" );
+
+      gtk_label_set( GTK_LABEL( display.ttitle ), text1 );
+
+      /* Add the track names */
+      for( x = 0; x < cdinfo.tochdr.cdth_trk1; x++ )
+	{
+	  sprintf( text1, "%d", x+1 );
+	  sprintf( text2, "%d:%02d",cdinfo.track[x].length/60,cdinfo.track[x].length%60 );
+	  texts[0] = text1;
+	  texts[2] = text2;
+	  if( cdinfo.name[x] != NULL )
+	    texts[1] = cdinfo.name[x]->str;
+	  else
+	    texts[1] = "(blank)";
+
+	  gtk_clist_append (GTK_CLIST (display.tclist), texts);
+	}
+      gtk_clist_thaw( GTK_CLIST( display.tclist ) );
+      gtk_clist_select_row( GTK_CLIST(display.tclist), display.track-1, -1 );
+    }
+
+  /* Save to database -- overwrite previous */
+  if( write_cddb( &cdinfo, 1 ) < 0 )
+    {
+      perror("write_cddb error");
+    } else {
+#ifdef DEBUG3
+      g_print("Wrote %08lx ok\n", cddb_discid( &cdinfo ) );
+#endif
+
+      /* The write was successful, we can erase the old category if it is different */
+      if( strcmp( cdinfo.category->str, old_category->str ) != 0 )
+	{
+	  /* Build the path to the old entry */
+	  /* Convert a leading ~ into the user's HOME directory */
+	  if( cdinfo.local_cddb[0] == '~' )
+	    {
+	      /* Copy the reset of the path/filename to tmp_fname */
+	      strncpy( tmp_fname, &cdinfo.local_cddb[1], 1023 );
+
+	      if( ( p = (char *) getenv("HOME") ) == NULL )
+		{
+		  return;
+		}
+	      strncpy( fname, p, 1023 );
+
+	      /* Make sure there is a slash inbetween the two */
+	      if( (fname[strlen(fname)-1] != '/') && (tmp_fname[0] != '/') )
+		{
+		  strcat( fname, "/" );
+		}
+
+	      strncat( fname, tmp_fname, 1023-strlen( p ) );
+	    } else {
+	      strncpy( fname, cdinfo.local_cddb, 1023 );
+	    }
+
+	  if( fname[strlen(fname)-1] != '/')
+	    strcat( fname, "/" );
+
+	  /* Add the category name */
+	  strcat( fname, old_category->str );
+	  strcat( fname, "/" );
+	  sprintf( tmp_fname, "%08lx", cdinfo.discid );
+	  strcat( fname, tmp_fname );
+
+	  /* Delete it */
+	  unlink( fname );
+	}
+    }
+
+  g_string_free( old_category, 1 );
+}
+
+
+
+/* --------------------------------------------------------------
+   Send the cdinfo to the database
+
+   Increment the revision and save the new one to disk.
+   Use a system call to mail and cat
+   --------------------------------------------------------------- */
+void send_cddbd( GtkWidget  *widget, GtkWidget *window)
+{
+  char  *p,
+        tmp_fname[1024],
+        fname[1024],
+        buffer[1024];
+
+  /* Close the edit window */
+  gtk_widget_destroy( window );
+
+  /* Increment the revision number */
+  cdinfo.revision++;
+
+  /* Copy all the changes to the cdinfo structure */
+  write_tracks();
+
+  /* Make sure it has a title */
+  if( cdinfo.title != NULL )
+    {
+      /* Convert a leading ~ into the user's HOME directory */
+      if( cdinfo.local_cddb[0] == '~' )
+	{
+	  /* Copy the reset of the path/filename to tmp_fname */
+	  strncpy( tmp_fname, &cdinfo.local_cddb[1], 1023 );
+	
+	  if( ( p = (char *) getenv("HOME") ) == NULL )
+	    {
+	      return;
+	    }
+	  strncpy( fname, p, 1023 );
+
+	  /* Make sure there is a slash inbetween the two */
+	  if( (fname[strlen(fname)-1] != '/') && (tmp_fname[0] != '/') )
+	    {
+	      strcat( fname, "/" );
+	    }
+
+	  strncat( fname, tmp_fname, 1023-strlen( p ) );
+	} else {
+	  strncpy( fname, cdinfo.local_cddb, 1023 );
+	}
+
+      if( fname[strlen(fname)-1] != '/')
+	strcat( fname, "/" );
+
+      /* Add the category name */
+      strcat( fname, cdinfo.category->str );
+      strcat( fname, "/" );
+      sprintf( tmp_fname, "%08lx", cdinfo.discid );
+      strcat( fname, tmp_fname );
+
+      sprintf( buffer, "cat %s | %s -s \"cddb %s %08lx\" %s", fname, MAIL_BINARY, cdinfo.category->str, cdinfo.discid, config.to_cddbd );
+
+#ifdef MAIL_DEBUG
+      g_print( "%s\n", buffer );
+#else      
+      /* Make a system call */
+      system( buffer );
+#endif
+    }
+}
+
+
+/* --------------------------------------------------------------
+   Save the new cd data to the local cd database
+  --------------------------------------------------------------- */
+void save_tracks( GtkWidget  *widget, GtkWidget *window)
+{
+  gtk_widget_destroy( window );
+
+  /* Update cdinfo and write the new data to the local database */
+  write_tracks();
+}
+
+
+/* ----------------------------------------------------------------------
+   The track entry data has changed. Copy it to a temporary location...
+   ---------------------------------------------------------------------- */
+void track_entry(GtkWidget *widget, GtkWidget *entry)
+{
+  gchar *entry_text;
+  char         *texts[3],
+               text1[255],
+               text2[255];
+
+  entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
+
+  if( display.tmp_track[display.tmp_row] == NULL )
+    display.tmp_track[display.tmp_row] = g_string_new( entry_text );
+  else
+    display.tmp_track[display.tmp_row] = g_string_assign( display.tmp_track[display.tmp_row], entry_text );
+
+  /* Update the clist in the edit window */
+  if( display.tewindow != NULL )
+    {
+      gtk_clist_freeze (GTK_CLIST (display.teclist));
+      
+      /* Remove the old entry first */
+      gtk_clist_remove( GTK_CLIST( display.teclist ), display.tmp_row );
+
+      /* Insert the new data */
+      sprintf( text1, "%d", display.tmp_row+1 );
+      sprintf( text2, "%d:%02d",cdinfo.track[display.tmp_row].length/60,cdinfo.track[display.tmp_row].length%60 );
+      texts[0] = text1;
+      texts[2] = text2;
+      if( display.tmp_track[display.tmp_row] != NULL )
+	texts[1] = display.tmp_track[display.tmp_row]->str;
+      else
+	texts[1] = "(blank)";
+      gtk_clist_insert (GTK_CLIST (display.teclist), display.tmp_row, texts);
+
+      /* Select the correct row in the clist */
+      gtk_clist_select_row( GTK_CLIST(display.teclist), display.tmp_row, -1 );
+
+      gtk_clist_thaw( GTK_CLIST( display.teclist ) );
+
+    }
+}
+
+
+/* -------------------------------------------------------------------
+   The Title entry data has changed, copy it to a temporary location
+   ------------------------------------------------------------------- */
+void title_entry(GtkWidget *widget, GtkWidget *entry)
+{
+  gchar *entry_text;
+
+  entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
+
+  if( display.tmp_title == NULL )
+    display.tmp_title = g_string_new( entry_text );
+  else
+    display.tmp_title = g_string_assign( display.tmp_title, entry_text );
+}
+
+
+/* ----------------------------------------------------------------------
+   The user selected a track, copy its data into the edit widget
+   (display.teedit)
+   ---------------------------------------------------------------------- */
+void select_teclist (GtkWidget *widget,
+		     gint row,
+		     gint column,
+		     GdkEventButton * bevent)
+{
+
+#ifdef DEBUG9
+  g_print ("Selection: Track #%d by button %d\n", row, bevent ? bevent->button : 0 );
+#endif
+
+  if( bevent )
+    {
+      if( bevent->button == 1 )
+	{
+	  display.tmp_row = row;
+	  /* Copy the track name into the edit widget */
+	  if( display.tmp_track[display.tmp_row] != NULL )
+	    gtk_entry_set_text( GTK_ENTRY( display.teentry ), display.tmp_track[display.tmp_row]->str);
+	  else
+	    gtk_entry_set_text( GTK_ENTRY( display.teentry ), "(blank)" );
+	}
+    }
+}
+
+
+
+
+/* --------------------------------------------------------------------
+   If the user select a track in the tracklist window, play that
+   track now.
+   -------------------------------------------------------------------- */
+void select_tclist (GtkWidget *widget,
+              gint row,
+              gint column,
+              GdkEventButton * bevent)
+{
+
+#ifdef DEBUG9
+  g_print ("Selection: Track #%d by button %d\n", row, bevent ? bevent->button : 0 );
+#endif
+
+  if( bevent )
+    {
+      if( bevent->button == 1 )
+	{
+	  play_track( row+1 );      
+	}
+    }
+}
+
+
+
+
+/* -----------------------------------------------------------------------
+   Handle the button press events
+
+   Each button has a xx_press and xx_release event where they change their
+   pixmaps to show a up or down state.
+
+   The FF, REW, Eject button also have to update the state of the play
+   button since they can effect the state that the player is in. I'm sure
+   there is a better way to do this...
+   ----------------------------------------------------------------------- */
+
+
+/* -----------------------------------------------------------------------
+   Copy the selected item into the category
+   ----------------------------------------------------------------------- */
+static void menuitem_response (gchar *string)
+{
+  if( display.tmp_category == NULL )
+    display.tmp_category = g_string_new( string );
+  else
+    display.tmp_category = g_string_assign( display.tmp_category, string );
+}
+
+
+/* -----------------------------------------------------------------------
+   Start up the window for editing the track list.
+   Close the normal track list while doing this.
+   Save it to cddb format when close is clicked.
+   Don't save when Cancel is clicked.
+   ----------------------------------------------------------------------- */
+static void edit_tracks(GtkWidget *widget, GtkWidget *data)
+{
+  GtkWidget    *vbox1,
+               *hbox1,
+               *button,
+               *edit,
+               *optionmenu,
+               *menu,
+               *menuitem;
+  int          x,
+               curr_cat;
+  char         *texts[3],
+               text1[255],
+               text2[255];
+  static char  *titles[] =
+  {
+    "Track #",
+    "Title",
+    "Length"
+  };
+  static char  *categories[] =
+  {
+    "blues",
+    "classical",
+    "country",
+    "data",
+    "folk",
+    "jazz",
+    "misc",
+    "newage",
+    "reggae",
+    "rock",
+    "soundtrack"
+  };
+
+
+  /* Don't allow edit if there's no disk */
+  if( display.status == CDROM_NODISC )
+    return;
+
+  if (!display.tewindow)
+    {
+      display.tewindow = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+      gtk_widget_set_usize (display.tewindow, 300, 400);
+      
+      gtk_signal_connect (GTK_OBJECT (display.tewindow), "destroy",
+			  GTK_SIGNAL_FUNC(gtk_widget_destroyed),
+			  &display.tewindow);
+
+      gtk_window_set_title (GTK_WINDOW (display.tewindow), "Edit Track Info" );
+      gtk_container_border_width (GTK_CONTAINER (display.tewindow), 4);
+      gtk_window_set_wmclass(GTK_WINDOW(display.tewindow), "XfreeCDet", NULL );
+
+      /* create a vbox to hold the clist and buttons */
+      vbox1 = gtk_vbox_new (FALSE, 0);
+      gtk_container_add (GTK_CONTAINER (display.tewindow), vbox1);
+      gtk_widget_show (vbox1);
+
+      /* Make a hbox to hold discid and category dropdown */
+      hbox1 = gtk_hbox_new (FALSE, 0);
+      gtk_box_pack_start( GTK_BOX( vbox1 ), hbox1, FALSE, FALSE, 2 );
+      gtk_widget_show (hbox1);
+
+      /* Need to show the disc id and category */
+      /* Maybe category should be a drop-down listing of the standard categories? */
+      sprintf( text1, "Discid: 0x%08lx   Category : ", cdinfo.discid );
+      button = gtk_label_new( text1 );
+      gtk_box_pack_start( GTK_BOX( hbox1 ), button, FALSE, FALSE, 2 );
+      gtk_widget_show( button );
+
+      /* Optionmenu for selecting the category */
+      optionmenu = gtk_option_menu_new();
+      menu = gtk_menu_new();
+
+      curr_cat = 0;
+      /* Add the categories */
+      for( x = 0; x < 11; x++ )
+	{
+	  /* Set the current category */
+	  if( cdinfo.category != NULL )
+	    {
+	      if( strcmp( cdinfo.category->str, categories[x] ) == 0 )
+		{
+		  curr_cat = x;
+		  if( display.tmp_category == NULL )
+		    display.tmp_category = g_string_new( cdinfo.category->str );
+		  else
+		    display.tmp_category = g_string_assign( display.tmp_category, cdinfo.category->str );
+		}
+	    } else {
+	      display.tmp_category= g_string_new( categories[0] );
+	    }
+	  menuitem = gtk_menu_item_new_with_label( categories[x] );
+	  gtk_menu_append (GTK_MENU (menu), menuitem);
+	  gtk_signal_connect_object( GTK_OBJECT(menuitem), "activate",
+	      GTK_SIGNAL_FUNC(menuitem_response), (gpointer) categories[x] );
+	  gtk_widget_show (menuitem);
+	}
+      gtk_option_menu_set_menu (GTK_OPTION_MENU (optionmenu), menu);
+      gtk_option_menu_set_history (GTK_OPTION_MENU (optionmenu), curr_cat );
+      gtk_box_pack_start (GTK_BOX (hbox1), optionmenu, FALSE, FALSE, 0);
+      gtk_widget_show (optionmenu);
+
+
+
+      /* Entry Widget for the title of the CD */
+      edit = gtk_entry_new_with_max_length( 254 );
+      gtk_signal_connect(GTK_OBJECT(edit), "changed",
+			 GTK_SIGNAL_FUNC(title_entry),
+			 edit);
+
+      if( cdinfo.title != NULL )
+	gtk_entry_set_text( GTK_ENTRY( edit ), cdinfo.title->str );
+      gtk_editable_select_region( GTK_EDITABLE( edit ), 0, -1 );
+      gtk_box_pack_start( GTK_BOX( vbox1 ), edit, FALSE, FALSE, 2 );
+      gtk_widget_show( edit );
+
+      /* Initalize the title */
+      if( cdinfo.title != NULL )
+	display.tmp_title = g_string_new( cdinfo.title->str );
+
+      /* Entry Widget for the track name-changed by selecting a diff. track */
+      display.teentry = gtk_entry_new_with_max_length( 254 );
+      gtk_box_pack_start( GTK_BOX( vbox1 ), display.teentry, FALSE, FALSE, 2 );
+      gtk_widget_show( display.teentry );
+
+      /* Create the clist */
+      display.teclist = gtk_clist_new_with_titles (3, titles);
+      gtk_clist_set_row_height (GTK_CLIST (display.teclist), 20);
+      gtk_clist_set_column_width (GTK_CLIST (display.teclist), 0, 45);
+      gtk_clist_set_column_width (GTK_CLIST (display.teclist), 1, 150);
+      gtk_clist_set_column_width (GTK_CLIST (display.teclist), 2, 45);
+      gtk_signal_connect (GTK_OBJECT (display.teclist),
+			  "select_row",
+			  (GtkSignalFunc) select_teclist,
+			  NULL);
+#ifdef GOOBER
+      gtk_clist_set_selection_mode (GTK_CLIST (display.teclist), GTK_SELECTION_BROWSE);
+#endif
+      gtk_clist_set_policy (GTK_CLIST (display.teclist),
+			    GTK_POLICY_AUTOMATIC,
+			    GTK_POLICY_AUTOMATIC);
+
+      gtk_clist_set_column_justification (GTK_CLIST (display.teclist), 0, GTK_JUSTIFY_CENTER);
+      gtk_clist_set_column_justification (GTK_CLIST (display.teclist), 1, GTK_JUSTIFY_LEFT);
+      gtk_clist_set_column_justification (GTK_CLIST (display.teclist), 2, GTK_JUSTIFY_LEFT);
+	  
+      gtk_clist_freeze (GTK_CLIST (display.teclist));
+
+      display.tmp_row = 0;
+      /* Add the track names */
+      for( x = 0; x < cdinfo.tochdr.cdth_trk1; x++ )
+	{
+	  sprintf( text1, "%d", x+1 );
+	  sprintf( text2, "%d:%02d",cdinfo.track[x].length/60,cdinfo.track[x].length%60 );
+	  texts[0] = text1;
+	  texts[2] = text2;
+	  if( cdinfo.name[x] != NULL )
+	    texts[1] = cdinfo.name[x]->str;
+	  else
+	    texts[1] = "(blank)";
+	  gtk_clist_append (GTK_CLIST (display.teclist), texts);
+
+	  /* Initalize the temporary storage */
+	  if( cdinfo.name[x] != NULL )
+	    display.tmp_track[x] = g_string_new( cdinfo.name[x]->str );
+	  else
+	    display.tmp_track[x] = NULL;
+	}
+      gtk_clist_thaw( GTK_CLIST( display.teclist ) );
+	  
+      gtk_container_border_width (GTK_CONTAINER (display.teclist), 5);
+      gtk_box_pack_start (GTK_BOX (vbox1), display.teclist, TRUE, TRUE, 0);
+      gtk_widget_show (display.teclist);
+
+      /* Now we can update the track edit control, since the tclist is setup */
+      gtk_signal_connect(GTK_OBJECT(display.teentry), "changed",
+			 GTK_SIGNAL_FUNC(track_entry),
+			 display.teentry);
+      if( display.tmp_track[0] != NULL )
+	gtk_entry_set_text( GTK_ENTRY( display.teentry ), display.tmp_track[0]->str );
+      gtk_editable_select_region( GTK_EDITABLE( display.teentry ), 0, -1 );
+
+      button = gtk_button_new_with_label ("Send To Server");
+      gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+				 GTK_SIGNAL_FUNC(send_cddbd),
+				 GTK_OBJECT (display.tewindow));
+      gtk_box_pack_start (GTK_BOX (vbox1), button, FALSE, FALSE, 2);
+      gtk_widget_show (button);
+
+      button = gtk_button_new_with_label ("Save");
+      gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+				 GTK_SIGNAL_FUNC(save_tracks),
+				 GTK_OBJECT (display.tewindow));
+      gtk_box_pack_start (GTK_BOX (vbox1), button, FALSE, FALSE, 2);
+      gtk_widget_show (button);
+
+      button = gtk_button_new_with_label ("Close");
+      gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+				 GTK_SIGNAL_FUNC(gtk_widget_destroy),
+				 GTK_OBJECT (display.tewindow));
+      gtk_box_pack_start (GTK_BOX (vbox1), button, FALSE, FALSE, 2);
+      gtk_widget_show (button);
+
+      gtk_widget_show( display.tewindow );
+    }
+}
+
+
+
+/*
+   Handle button press in the display window.
+   Determine if its a click for a track list or a drag to move the window
+*/
+static void display_pressed (GtkWidget *widget, GdkEventButton *event)
+{
+  CursorOffset *p;
+  GtkWidget    *vbox1,
+               *button;
+  int          x;
+  char         *texts[3],
+               text1[255],
+               text2[255];
+  static char  *titles[] =
+  {
+    "Track #",
+    "Title",
+    "Length"
+  };
+
+
+  /* ignore double and triple click */
+  if (event->type != GDK_BUTTON_PRESS)
+    return;
+
+  /* Right button is move window */
+  if( event->button == 3 )
+    {
+      if( ( p = gtk_object_get_user_data (GTK_OBJECT(widget)) ) != NULL )
+	{
+	  p->x = (int) event->x;
+	  p->y = (int) event->y;
+
+	  gtk_grab_add (widget);
+	  gdk_pointer_grab (widget->window, TRUE,
+			    GDK_BUTTON_RELEASE_MASK |
+			    GDK_BUTTON_MOTION_MASK |
+			    GDK_POINTER_MOTION_HINT_MASK,
+			    NULL, NULL, 0);
+	}
+    } else if( event->button == 1 ) {
+      /* Show the title and the tracks, using a clist */
+      if (!display.twindow)
+	{
+	  display.twindow = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+	  gtk_widget_set_usize (display.twindow, 300, 350);
+
+	  gtk_signal_connect (GTK_OBJECT (display.twindow), "destroy",
+			      GTK_SIGNAL_FUNC(gtk_widget_destroyed),
+			      &display.twindow);
+
+	  /*	  gtk_window_set_title (GTK_WINDOW (display.twindow), cdinfo.title); */
+	  gtk_container_border_width (GTK_CONTAINER (display.twindow), 4);
+	  gtk_window_set_wmclass(GTK_WINDOW(display.twindow), "XfreeCDt", NULL );
+
+	  /* create a vbox to hold the clist and buttons */
+	  vbox1 = gtk_vbox_new (FALSE, 0);
+	  gtk_container_add (GTK_CONTAINER (display.twindow), vbox1);
+	  gtk_widget_show (vbox1);
+
+	  if( cdinfo.title != NULL )
+	    sprintf( text1, "%s", cdinfo.title->str );
+	  else
+	    strcpy( text1, "" );
+	  display.ttitle = gtk_label_new( text1 );
+	  gtk_box_pack_start( GTK_BOX( vbox1 ), display.ttitle, FALSE, FALSE, 0 );
+	  gtk_widget_show( display.ttitle );
+
+	  /* Create the clist */
+	  display.tclist = gtk_clist_new_with_titles (3, titles);
+	  gtk_clist_set_row_height (GTK_CLIST (display.tclist), 20);
+	  gtk_clist_set_column_width (GTK_CLIST (display.tclist), 0, 45);
+	  gtk_clist_set_column_width (GTK_CLIST (display.tclist), 1, 150);
+	  gtk_clist_set_column_width (GTK_CLIST (display.tclist), 2, 45);
+	  gtk_signal_connect (GTK_OBJECT (display.tclist),
+			      "select_row",
+			      (GtkSignalFunc) select_tclist,
+			      NULL);
+
+#ifdef GOOBER
+	  gtk_clist_set_selection_mode (GTK_CLIST (display.tclist), GTK_SELECTION_BROWSE);
+#endif
+	  gtk_clist_set_policy (GTK_CLIST (display.tclist),
+				GTK_POLICY_AUTOMATIC,
+				GTK_POLICY_AUTOMATIC);
+
+	  gtk_clist_set_column_justification (GTK_CLIST (display.tclist), 0, GTK_JUSTIFY_CENTER);
+	  gtk_clist_set_column_justification (GTK_CLIST (display.tclist), 1, GTK_JUSTIFY_LEFT);
+	  gtk_clist_set_column_justification (GTK_CLIST (display.tclist), 2, GTK_JUSTIFY_LEFT);
+
+	  if( display.status != CDROM_NODISC )
+	    {
+	      gtk_clist_freeze (GTK_CLIST (display.tclist));
+	      /* Add the track names */
+	      for( x = 0; x < cdinfo.tochdr.cdth_trk1; x++ )
+		{
+		  sprintf( text1, "%d", x+1 );
+		  sprintf( text2, "%d:%02d",cdinfo.track[x].length/60,cdinfo.track[x].length%60 );
+		  texts[0] = text1;
+		  texts[2] = text2;
+		  if( cdinfo.name[x] != NULL )
+		    texts[1] = cdinfo.name[x]->str;
+		  else
+		    texts[1] = "(blank)";
+		  gtk_clist_append (GTK_CLIST (display.tclist), texts);
+		}
+	      gtk_clist_thaw( GTK_CLIST( display.tclist ) );
+	    }
+
+	  gtk_container_border_width (GTK_CONTAINER (display.tclist), 5);
+	  gtk_box_pack_start (GTK_BOX (vbox1), display.tclist, TRUE, TRUE, 0);
+	  gtk_widget_show (display.tclist);
+
+	  button = gtk_button_new_with_label ("Edit Info");
+	  gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+				     GTK_SIGNAL_FUNC(edit_tracks),
+				     GTK_OBJECT (display.twindow));
+	  gtk_box_pack_start (GTK_BOX (vbox1), button, FALSE, FALSE, 2);
+	  gtk_widget_show (button);
+
+	  button = gtk_button_new_with_label ("Close");
+	  gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+				     GTK_SIGNAL_FUNC(gtk_widget_destroy),
+				     GTK_OBJECT (display.twindow));
+
+	  gtk_box_pack_start (GTK_BOX (vbox1), button, FALSE, FALSE, 2);
+	  /*	  GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); */
+	  /*	  gtk_widget_grab_default (button); */
+	  gtk_widget_show (button);
+	  gtk_widget_show( display.twindow );
+	}
+    }
+}
+
+
+static void display_released (GtkWidget *widget)
+{
+  gtk_grab_remove (widget);
+  gdk_pointer_ungrab (0);
+}
+
+
+static void display_motion (GtkWidget *widget, GdkEventMotion *event)
+{
+  gint xp, yp;
+  CursorOffset * p;
+  GdkModifierType mask;
+
+  if( ( p = gtk_object_get_user_data (GTK_OBJECT (widget)) ) != NULL )
+    {
+      /*
+       * Can't use event->x / event->y here 
+       * because I need absolute coordinates.
+       */
+      gdk_window_get_pointer (root_win, &xp, &yp, &mask);
+      gtk_widget_set_uposition (display.main_window, xp  - p->x, yp  - p->y);
+    }
+}
+
+
+
+
+void ff_press (GtkWidget *widget, GdkEventButton *event)
+{
+  /* Left button pressed */
+  if( event->button == 1 )
+  {
+    /* Set the FF down image */
+    gtk_pixmap_set( GTK_PIXMAP( ff.wid ),
+                    ff.image.dn_pixmap,
+                    ff.image.dn_mask );
+
+    /* Tell the CD control to play the next track */
+    play_next();
+     
+
+    /* Update the state of the play button -- Should be a subroutine */
+    if( (display.playbtn != CDROM_PLAYING) && (display.status != CDROM_NODISC))
+      {
+     	gtk_pixmap_set( GTK_PIXMAP( play.wid ),
+     			display.playup_pixmap,
+     			display.playup_mask );
+     	display.playbtn = CDROM_PLAYING;
+      }
+  }
+}
+
+
+void ff_release (GtkWidget *widget, GdkEventButton *event)
+{
+  if( (event->button == 1) )
+  {
+    /* Draw the button up image */
+    gtk_pixmap_set( GTK_PIXMAP( ff.wid ),
+                    ff.image.up_pixmap,
+                    ff.image.up_mask );
+  }
+}
+
+
+void rew_press (GtkWidget *widget, GdkEventButton *event)                              
+{
+  /* Left button pressed */
+  if( event->button == 1 )
+  {
+    /* Draw the down image for REW */
+    gtk_pixmap_set( GTK_PIXMAP( rew.wid ),
+                    rew.image.dn_pixmap,
+                    rew.image.dn_mask );
+
+    /* Tell the CD to play the previous track */
+    play_previous();
+    
+
+    /* Update the state of the Play button -- should be a subroutine */
+    if( (display.playbtn != CDROM_PLAYING) && (display.status != CDROM_NODISC))
+      {
+     	gtk_pixmap_set( GTK_PIXMAP( play.wid ),
+     			display.playup_pixmap,
+     			display.playup_mask );
+     	display.playbtn = CDROM_PLAYING;
+      }
+     
+  }
+}
+
+
+void rew_release (GtkWidget *widget, GdkEventButton *event)
+{
+  if( (event->button == 1) )
+  {
+    /* Draw the up image for the button */
+    gtk_pixmap_set( GTK_PIXMAP( rew.wid ),
+                    rew.image.up_pixmap,
+                    rew.image.up_mask );
+  }
+}
+
+
+void play_press (GtkWidget *widget, GdkEventButton *event)                              
+{
+  int x;
+
+  /* Left button press */
+  if( event->button == 1 )
+  {
+    /* Depending on the current state of the button, display the correct image */
+    switch( display.playbtn )
+    {
+      case CDROM_PLAYING:	gtk_pixmap_set( GTK_PIXMAP( play.wid ),
+                    				display.playdn_pixmap,
+                    				display.playdn_mask );
+                                pause_cdrom();
+				display.playbtn = CDROM_PAUSED;
+      				break;
+
+      case CDROM_PAUSED:	gtk_pixmap_set( GTK_PIXMAP( play.wid ),
+                    				display.playdn_pixmap,
+                    				display.playdn_mask );
+                                resume_cdrom();
+				display.playbtn = CDROM_PLAYING;
+      				break;
+
+      case CDROM_NODISC:	gtk_pixmap_set( GTK_PIXMAP( play.wid ),
+                    				display.playdn_pixmap,
+                    				display.playdn_mask );
+
+                                play_track( 1 );
+				update_display();
+				display.playbtn = CDROM_PLAYING;
+				break;
+    }    
+  } else if( event->button ==3 ) {
+    /* Stop playing without ejecting the CD */
+    switch( display.playbtn )
+      {
+
+      case CDROM_PLAYING :	
+      case CDROM_PAUSED :
+	stop_cdrom();
+	gtk_pixmap_set( GTK_PIXMAP( play.wid ),
+			display.playdn_pixmap,
+			display.playdn_mask );
+	update_display();
+	display.playbtn = CDROM_NODISC;
+
+	/* Clear out the track list */
+	if( display.twindow != NULL )
+	  {
+	  gtk_clist_clear( GTK_CLIST( display.tclist ) );
+
+	  /* Clear the title */
+	  gtk_label_set( GTK_LABEL( display.ttitle ), "" );
+	  }
+
+	/* Erase the title and track names */
+	if( cdinfo.title != NULL )
+	  {
+	    g_string_free( cdinfo.title, 1 );
+	    cdinfo.title = NULL;
+	  }
+
+	for( x = 0; x < cdinfo.tochdr.cdth_trk1; x++ )
+	  {
+	    if( cdinfo.name[x] != NULL )
+	      {
+		g_string_free( cdinfo.name[x], 1 );
+		cdinfo.name[x] = NULL;
+	      }
+	  }
+
+	/* Free up dynamically allocated cdinfo strings */
+	free_cdinfo();
+	break;
+
+      case CDROM_NODISC :
+	break;
+    }
+  }
+}
+
+
+void play_release (GtkWidget *widget, GdkEventButton *event)
+{
+  if( (event->button == 1) || (event->button ==3) )
+  {
+    switch( display.playbtn )
+    {
+      case CDROM_PAUSED:	gtk_pixmap_set( GTK_PIXMAP( play.wid ),
+                    				display.pauseup_pixmap,
+                    				display.pauseup_mask );
+    				break;
+
+      case CDROM_PLAYING:	gtk_pixmap_set( GTK_PIXMAP( play.wid ),
+                    				display.playup_pixmap,
+                    				display.playup_mask );
+    				break;
+
+      case CDROM_NODISC:	gtk_pixmap_set( GTK_PIXMAP( play.wid ),
+                    				display.stopup_pixmap,
+                    				display.stopup_mask );
+    				break;
+
+    }
+  }
+}
+
+
+void eject_press (GtkWidget *widget, GdkEventButton *event)                              
+{
+  int x;
+
+  if( event->button == 1 )
+  {
+    gtk_pixmap_set( GTK_PIXMAP( eject.wid ),
+                    eject.image.dn_pixmap,
+                    eject.image.dn_mask );
+
+
+    /*
+     * If we are playing or paused then we will be stopped, so change
+     * the play button to the stop button
+     */
+    switch( display.status )
+      {
+      case CDROM_PAUSED :
+      case CDROM_PLAYING :
+	gtk_pixmap_set( GTK_PIXMAP( play.wid ),
+			display.stopup_pixmap,
+			display.stopup_mask );
+	display.playbtn = CDROM_NODISC;
+	break;
+      }
+    eject_cdrom();
+    display.playbtn = CDROM_NODISC;
+    gdk_draw_pixmap( display.wid->window,
+		     display.wid->style->black_gc,
+		     display.nodisc_pixmap,
+		     0, 0,
+		     0, 0, 92, 30 );
+
+    /* Clear out the track list */
+    if( display.twindow != NULL )
+      {
+	gtk_clist_clear( GTK_CLIST( display.tclist ) );
+
+	/* Clear the title */
+	gtk_label_set( GTK_LABEL( display.ttitle ), "" );
+      }
+
+
+    /* Erase the title and track names */
+    if( cdinfo.title != NULL )
+      {
+	g_string_free( cdinfo.title, 1 );
+	cdinfo.title = NULL;
+      }
+
+    for( x = 0; x < cdinfo.tochdr.cdth_trk1; x++ )
+      {
+	if( cdinfo.name[x] != NULL )
+	  {
+	    g_string_free( cdinfo.name[x], 1 );
+	    cdinfo.name[x] = NULL;
+	  }
+      }
+
+    /* Free up the dynamically allocated cdinfo strings */
+    free_cdinfo();
+  }
+}
+
+
+void eject_release (GtkWidget *widget, GdkEventButton *event)
+{
+  if( event->button == 1 )
+  {
+    gtk_pixmap_set( GTK_PIXMAP( eject.wid ),
+                    eject.image.up_pixmap,
+                    eject.image.up_mask );
+  }
+}
+
+
+gint ex_timer( gpointer data )
+{
+  gtk_timeout_remove( ex.timer );
+
+  gtk_main_quit();
+
+  return FALSE;
+}
+
+
+void ex_press (GtkWidget *widget, GdkEventButton *event)                              
+{
+  if( event->button == 1 )
+  {
+    gtk_pixmap_set( GTK_PIXMAP( ex.wid ),
+                    ex.image.dn_pixmap,
+                    ex.image.dn_mask );
+
+    /* In 100mS execute the play_next function */
+    ex.timer = gtk_timeout_add( 500, ex_timer, NULL );
+
+  }
+}
+
+
+void ex_release (GtkWidget *widget, GdkEventButton *event)
+{
+  if( event->button == 1 )
+  {
+    gtk_pixmap_set( GTK_PIXMAP( ex.wid ),
+                    ex.image.up_pixmap,
+                    ex.image.up_mask );
+  }
+}
+
+
+void
+destroy_window (GtkWidget  *widget,
+                GtkWidget **window)
+{
+  *window = NULL;
+}
+
+
+void close_setup( GtkWidget  *widget, GtkWidget *window)
+{
+  gtk_widget_destroy( window );
+
+  /* Write configuration */
+  write_config( &config );
+
+  /* Send the new device to the cd_control process */
+  send_device();
+}
+
+
+/* Toggle the state of the cddb button */
+static void toggle_cddb (GtkWidget *checkbutton,
+		       GtkWidget *text)
+{
+  config.cddb = GTK_TOGGLE_BUTTON(checkbutton)->active;
+
+#ifdef DEBUG3
+  g_print("Toggling cddb = %d\n", config.cddb );
+#endif
+
+  config.saved = 0;            /* Needs to be written to disk */
+}
+
+
+#ifdef CHANGER_SUPPORT
+/* Toggle the CD changer support button */
+static void toggle_changer (GtkWidget *checkbutton,
+		       GtkWidget *text)
+{
+  config.changer = GTK_TOGGLE_BUTTON(checkbutton)->active;
+
+#ifdef DEBUG3
+  g_print("Toggling changer = %d\n", config.changer );
+#endif
+
+  config.saved = 0;            /* Needs to be written to disk */
+}
+#endif
+
+
+/* Toggle the Eject when done playing */
+static void toggle_eject_done(GtkWidget *checkbutton,
+		       GtkWidget *text)
+{
+  config.done_eject = GTK_TOGGLE_BUTTON(checkbutton)->active;
+
+#ifdef DEBUG3
+  g_print("Toggling done_eject = %d\n", config.done_eject );
+#endif
+
+  config.saved = 0;            /* Needs to be written to disk */
+}
+
+
+/* Toggle the Eject at Close */
+static void toggle_eject_exit(GtkWidget *checkbutton,
+		       GtkWidget *text)
+{
+  config.exit_eject = GTK_TOGGLE_BUTTON(checkbutton)->active;
+
+#ifdef DEBUG3
+  g_print("Toggling exit_eject = %d\n", config.exit_eject );
+#endif
+
+  set_eject( config.exit_eject );
+  config.saved = 0;            /* Needs to be written to disk */
+}
+
+static void toggle_startup(GtkWidget *checkbutton,
+		       GtkWidget *text)
+{
+  config.startup = GTK_TOGGLE_BUTTON(checkbutton)->active;
+  config.saved = 0;            /* Needs to be written to disk */
+}
+
+
+void cddb_servers()
+{
+
+  /* Placeholder for server listing/editing */
+}
+
+
+static void
+page_switch (GtkWidget *widget, GtkNotebookPage *page, gint page_num)
+{
+  GtkNotebookPage *oldpage;
+
+  oldpage = GTK_NOTEBOOK (widget)->cur_page;
+
+  if (page == oldpage)
+    return;
+
+}
+
+
+void device_entry(GtkWidget *widget, GtkWidget *entry)
+{
+  gchar *entry_text;
+
+  entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
+
+  config.device = realloc( config.device, strlen(entry_text)+1);
+  strcpy( config.device, entry_text );
+  config.saved = 0;            /* Needs to be written to disk */
+}
+
+void cddb_entry(GtkWidget *widget, GtkWidget *entry)
+{
+  gchar *entry_text;
+
+  entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
+
+  config.local_cddb = realloc( config.local_cddb, strlen(entry_text)+1);
+  strcpy( config.local_cddb, entry_text );
+  strcpy( cdinfo.local_cddb, entry_text );
+
+  config.saved = 0;            /* Needs to be written to disk */
+}
+
+void cddb_to_email(GtkWidget *widget, GtkWidget *entry)
+{
+  gchar *entry_text;
+
+  entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
+
+  config.to_cddbd = realloc( config.to_cddbd, strlen(entry_text)+1);
+  strcpy( config.to_cddbd, entry_text );
+
+  config.saved = 0;            /* Needs to be written to disk */
+}
+
+
+void server_entry(GtkWidget *widget, GtkWidget *entry)
+{
+  gchar *entry_text;
+
+  entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
+
+  config.current = realloc( config.current, strlen(entry_text)+1);
+  strcpy( config.current, entry_text );
+  config.saved = 0;            /* Needs to be written to disk */
+}
+
+
+void refresh_servers()
+{
+  char buffer[80];
+
+  /* Need to lock this routine until we complete the last request */
+  if( display.cddb_lock == 0 )
+    {
+      /* Get the server list from cddb.cddb.com - DB_SITES */
+      /* Tell it to print the diagnostic string */
+      cdinfo.cddbd_cmnd = DB_SITES;
+
+      /* Set the server to connect to */
+      strncpy( cdinfo.server, "cddb.cddb.com", 80 );
+      cdinfo.port = 888;
+      if( write( cddbd_fd, &cdinfo, sizeof( struct CDINFO ) ) < 0 )
+	{
+	  perror("write to cddbd error");
+	}
+
+      display.cddb_lock = 1;
+     
+      /* Start up a progress dialog */
+      display.progress = gtk_dialog_new ();
+
+      sprintf( buffer, "Connecting to %s:%d", cdinfo.server, cdinfo.port );
+
+      gtk_signal_connect( GTK_OBJECT( display.progress ), "destroy",
+                          GTK_SIGNAL_FUNC(gtk_widget_destroy),
+                          &display.progress);
+
+      gtk_window_set_title (GTK_WINDOW (display.progress), "CDDBD Status");
+      gtk_container_border_width (GTK_CONTAINER (display.progress), 0);
+      gtk_window_set_wmclass(GTK_WINDOW(display.progress), "XfreeCDp", NULL );
+
+      display.plabel = gtk_label_new (buffer);
+      gtk_misc_set_padding (GTK_MISC (display.plabel), 10, 10);
+      gtk_box_pack_start (GTK_BOX (GTK_DIALOG (display.progress)->vbox),
+                          display.plabel, FALSE, FALSE, 0);
+      gtk_widget_show( display.plabel );
+      gtk_widget_show( display.progress );
+    }
+}
+
+
+/* -----------------------------------------------------------------------
+   Display the help/setup dialog box
+
+   All changed info is saved when this dialog is exited.
+   ----------------------------------------------------------------------- */
+gint help_timer( gpointer data )
+{
+  struct SITE       *sp;
+  static GtkWidget  *window = NULL;
+  GtkWidget         *notebook,
+                    *text,
+                    *vbox1,
+                    *vbox2,
+                    *label,
+                    *button,
+                    *table,
+                    *hscrollbar,
+                    *vscrollbar,
+                    *edit;
+  GList             *cbitems = NULL;
+
+
+  gtk_timeout_remove( help.timer );   
+  help.timer = 0;
+
+  /* Create the main window for the notebook */
+  if( !window )
+    {
+      window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+      gtk_signal_connect (GTK_OBJECT (window), "destroy",
+                          GTK_SIGNAL_FUNC(gtk_widget_destroyed),
+                          &window);
+
+      gtk_window_set_title (GTK_WINDOW (window), "notebook");
+      gtk_container_border_width (GTK_CONTAINER (window), 0);
+      gtk_window_set_title (GTK_WINDOW( window ), "XfreeCD Setup");
+      gtk_widget_set_usize (window, 250, 300);
+      gtk_window_set_wmclass(GTK_WINDOW(window), "XfreeCDs", NULL );
+ 
+      /* Create a vbox to hold the notebook */
+      vbox1 = gtk_vbox_new (FALSE, 0);
+      gtk_container_add (GTK_CONTAINER (window), vbox1);
+
+      /* Create the notebook */
+      notebook = gtk_notebook_new ();
+      gtk_signal_connect (GTK_OBJECT (notebook), "switch_page",
+                          GTK_SIGNAL_FUNC (page_switch), NULL);
+      gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP);
+      gtk_box_pack_start (GTK_BOX (vbox1), notebook, TRUE, TRUE, 0);
+      gtk_container_border_width (GTK_CONTAINER (notebook), 10);
+      gtk_widget_realize (notebook);
+
+      /* Create the about page for the notebook -- Put a text window in it */
+      vbox2 = gtk_vbox_new( FALSE, 0 );
+      gtk_widget_show( vbox2 );
+
+      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 (vbox2), 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 (GTK_TABLE (table), text, 0, 1, 0, 1,
+                        GTK_EXPAND | GTK_SHRINK | GTK_FILL,
+                        GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
+      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_SHRINK, 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_SHRINK | GTK_FILL, 0, 0);
+      gtk_widget_show (vscrollbar);
+
+      /* Create the label box for the About page */
+      label = gtk_label_new ("About");
+      
+      /* Add it to the notebook */
+      gtk_notebook_append_page_menu (GTK_NOTEBOOK(notebook), vbox2, label, label  );
+
+      gtk_text_freeze (GTK_TEXT (text));
+
+      gtk_widget_realize (text);
+
+      /* Add the actual text */
+      HELP_TEXT( "XfreeCD v0.7.8\n" );
+      HELP_TEXT( "Copyright 1998 Brian C. Lane\n" );
+      HELP_TEXT( "<nexus@tatoosh.com>\n" );
+      HELP_TEXT( "http://www.tatoosh.com/nexus\n\n" );
+
+      HELP_TEXT( "Click on the 'SETUP' tab to set the\n" );
+      HELP_TEXT( "CD device and some options:\n\n" );
+      HELP_TEXT( "AutoPlay will start playing the CD\n" );
+      HELP_TEXT( "when XfreeCD is started\n\n" );
+      HELP_TEXT( "Eject when done will eject the CD\n" );
+      HELP_TEXT( "when it is finished playing if repeat\n" );
+      HELP_TEXT( "is not turned on (the button on the\n" );
+      HELP_TEXT( "main panel).\n\n" );
+      HELP_TEXT( "Eject on Exit will eject the CD if it\n");
+      HELP_TEXT( "is not playing when you exit.\n\n" );
+      HELP_TEXT( "Click on the 'CDDB' tab to set up\n" );
+      HELP_TEXT( "the support for online cd database\n" );
+      HELP_TEXT( "support. The Local CDDB Path\n" );
+      HELP_TEXT( "should point to a directory where\n" );
+      HELP_TEXT( "you have read and write\n");
+      HELP_TEXT( "permission. This is where the\n" );
+      HELP_TEXT( "track lists for the CDs will be\n");
+      HELP_TEXT( "saved.\n\n");
+      HELP_TEXT( "The CDDB Submit email field is for\n" );
+      HELP_TEXT( "the email address of the CDDB\n");
+      HELP_TEXT( "server to submit CD information\n" );
+      HELP_TEXT( "to. The send button is located\n" );
+      HELP_TEXT( "in the Track Edit window. Please\n" );
+      HELP_TEXT( "only submit CDs that do not exist\n");
+      HELP_TEXT( "in the database and that have\n" );
+      HELP_TEXT( "complete title and track text\n" );
+      HELP_TEXT( "entered.\n\n" );
+      HELP_TEXT( "The CDDB server is the internet\n" );
+      HELP_TEXT( "site where requests for unknown\n" );
+      HELP_TEXT( "CDs will be sent to. Initially only\n" );
+      HELP_TEXT( "cddb.cddb.com is listed. Click\n");
+      HELP_TEXT( "Refresh Server List to download a\n");
+      HELP_TEXT( "list of the available servers.\n" );
+      HELP_TEXT( "Use the combobox to pick a server\n" );
+      HELP_TEXT( "close to you. If you unselect cddb\n" );
+      HELP_TEXT( "support the internet server will\n" );
+      HELP_TEXT( "not be queried, but the local\n" );
+      HELP_TEXT( "database will be used.\n\n" );
+      HELP_TEXT( "Right click & drag on the main\n");
+      HELP_TEXT( "display window will allow you to\n" );
+      HELP_TEXT( "move XfreeCD even when you\n");
+      HELP_TEXT( "have title bars and handles. Left\n");
+      HELP_TEXT( "Clicking on the display will open\n");
+      HELP_TEXT( "up the Track List window.\n\n" );
+      HELP_TEXT( "In the Track List window you can\n");
+      HELP_TEXT( "click on the title of a track and\n");
+      HELP_TEXT( "XfreeCD will jump directly to\n" );
+      HELP_TEXT( "that track and play it.\n\n" );
+      HELP_TEXT( "Right clicking on the play/pause\n");
+      HELP_TEXT( "button will stop playing and\n");
+      HELP_TEXT( "turn off the CD player.\n\n");
+      HELP_TEXT( "Volume is controlled by left/right\n");
+      HELP_TEXT( "clicking on the volume button.\n\n");
+      HELP_TEXT( "Thanks to Ti Kan and Steve Scherf\n" );
+      HELP_TEXT( "for creating CDDB.\n\n" );
+
+      gtk_text_thaw (GTK_TEXT (text));
+
+      /* Add the general setup page */
+      vbox2 = gtk_vbox_new( FALSE, 0 );
+      gtk_widget_show( vbox2 );
+
+      /* Add an editable field for the device */
+      label = gtk_label_new ("CDROM device:");
+      gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, FALSE, 0);
+      gtk_widget_show (label);
+
+      edit = gtk_entry_new_with_max_length(20);
+      gtk_signal_connect(GTK_OBJECT(edit), "changed",
+			 GTK_SIGNAL_FUNC(device_entry),
+			 edit);
+      gtk_widget_show( edit );
+
+#ifdef DEBUG3
+      g_print("config.device = %s\n", config.device );
+#endif
+
+      if( config.device != NULL )
+	gtk_entry_set_text( GTK_ENTRY( edit ), config.device );
+      gtk_editable_select_region( GTK_EDITABLE( edit ), 0, -1 );
+      gtk_box_pack_start( GTK_BOX( vbox2 ), edit, FALSE, FALSE, 0 );
+      gtk_widget_show( edit );
+
+#ifdef DEBUG3
+      g_print("config.startup = %d\n", config.startup );
+#endif
+      
+      /* Create a check button for Playing at Startup */
+      button = gtk_check_button_new_with_label("AutoPlay");
+      gtk_box_pack_start( GTK_BOX( vbox2 ), button, FALSE, FALSE, 0 );
+      gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), (config.startup == 1));
+      gtk_signal_connect( GTK_OBJECT( button ), "toggled",
+			  GTK_SIGNAL_FUNC( toggle_startup ), NULL );
+      gtk_widget_show( button );
+
+#ifdef DEBUG3
+      g_print("config.changer = %d\n", config.changer );
+#endif
+
+#ifdef CHANGER_SUPPORT
+      /* Create a check button for CD Changer */
+      button = gtk_check_button_new_with_label("CD Changer");
+      gtk_box_pack_start( GTK_BOX( vbox2 ), button, FALSE, FALSE, 0 );
+      gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), (config.changer == 1));
+      gtk_signal_connect( GTK_OBJECT( button ), "toggled",
+			  GTK_SIGNAL_FUNC( toggle_changer ), NULL );
+      gtk_widget_show( button );
+#endif
+
+#ifdef DEBUG3
+      g_print("config.done_eject = %d\n", config.done_eject );
+#endif
+
+      /* Create a check button for Eject on Close */
+      button = gtk_check_button_new_with_label("Eject when done");
+      gtk_box_pack_start( GTK_BOX( vbox2 ), button, FALSE, FALSE, 0 );
+      gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), (config.done_eject==1));
+      gtk_signal_connect( GTK_OBJECT( button ), "toggled",
+			  GTK_SIGNAL_FUNC( toggle_eject_done ), NULL );
+      gtk_widget_show( button );
+
+      /* Create a check button for Eject on Exit (and not playing) */
+      button = gtk_check_button_new_with_label("Eject on Exit");
+      gtk_box_pack_start( GTK_BOX( vbox2 ), button, FALSE, FALSE, 0 );
+      gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), (config.exit_eject==1));
+      gtk_signal_connect( GTK_OBJECT( button ), "toggled",
+			  GTK_SIGNAL_FUNC( toggle_eject_exit ), NULL );
+      gtk_widget_show( button );
+
+      
+      /* Create the label box for the Setup page */
+      label = gtk_label_new ("Setup");
+      
+      /* Add it to the notebook */
+      gtk_notebook_append_page_menu( GTK_NOTEBOOK( notebook ), vbox2, label, label );
+
+
+      /* Create the CDDB page for the notebook */
+      vbox2 = gtk_vbox_new( FALSE, 0 );
+      gtk_widget_show( vbox2 );
+
+       /* Path to the local cddb database */
+      label = gtk_label_new( "Local CDDB Path" );
+      gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, FALSE, 0);
+      gtk_widget_show (label);
+
+     /* Add an editable field for the local CDDBD database */
+      edit = gtk_entry_new_with_max_length( 1023 );
+      gtk_signal_connect(GTK_OBJECT(edit), "changed",
+			 GTK_SIGNAL_FUNC(cddb_entry),
+			 edit);
+      gtk_widget_show( edit );
+
+#ifdef DEBUG3
+      g_print("config.local_cddb = %s\n", config.local_cddb );
+#endif
+
+      if( config.local_cddb != NULL )
+	gtk_entry_set_text( GTK_ENTRY( edit ), config.local_cddb );
+      gtk_editable_select_region( GTK_EDITABLE( edit ), 0, -1 );
+      gtk_box_pack_start( GTK_BOX( vbox2 ), edit, FALSE, FALSE, 0 );
+      gtk_widget_show( edit );
+
+       /* Email address for submitting to the database */
+      label = gtk_label_new( "CDDB Submit Email" );
+      gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, FALSE, 0);
+      gtk_widget_show (label);
+
+      /* Add an editable field for the email address */
+      edit = gtk_entry_new_with_max_length( 1023 );
+      gtk_signal_connect(GTK_OBJECT(edit), "changed",
+			 GTK_SIGNAL_FUNC(cddb_to_email),
+			 edit);
+      gtk_widget_show( edit );
+
+#ifdef DEBUG3
+      g_print("config.local_cddb = %s\n", config.local_cddb );
+#endif
+
+      if( config.to_cddbd != NULL )
+	gtk_entry_set_text( GTK_ENTRY( edit ), config.to_cddbd );
+      gtk_editable_select_region( GTK_EDITABLE( edit ), 0, -1 );
+      gtk_box_pack_start( GTK_BOX( vbox2 ), edit, FALSE, FALSE, 0 );
+      gtk_widget_show( edit );
+
+
+#ifdef DEBUG3
+      g_print("config.cddb = %d\n", config.cddb );
+#endif
+
+      /* Create a check button for CDDB support */
+      button = gtk_check_button_new_with_label("CDDB Support");
+      gtk_box_pack_start( GTK_BOX( vbox2 ), button, FALSE, FALSE, 0 );
+      gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), (config.cddb == 1));
+      gtk_signal_connect( GTK_OBJECT( button ), "toggled",
+			  GTK_SIGNAL_FUNC( toggle_cddb ), NULL );
+      gtk_widget_show( button );
+
+
+      /* Create the list of servers, use a combobox for this */
+      label = gtk_label_new( "CDDB Server" );
+      gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, FALSE, 0);
+      gtk_widget_show (label);
+
+      /* Walk the list */
+      cbitems = NULL;
+      sp = config.server;
+      while( sp != NULL )
+	{
+	  cbitems = g_list_append(cbitems, sp->name);
+	  sp = sp->next;
+	}
+      
+      display.cb = gtk_combo_new ();
+      gtk_combo_set_popdown_strings (GTK_COMBO (display.cb), cbitems);
+
+      /* Here we should put the selected server into the entry box */
+      gtk_entry_set_text (GTK_ENTRY (GTK_COMBO(display.cb)->entry), config.current);
+
+      gtk_signal_connect(GTK_OBJECT(GTK_COMBO(display.cb)->entry), "changed",
+			 GTK_SIGNAL_FUNC(server_entry),
+			 GTK_COMBO(display.cb)->entry);
+      gtk_editable_select_region (GTK_EDITABLE (GTK_COMBO(display.cb)->entry),
+                                  0, -1);
+      gtk_box_pack_start (GTK_BOX (vbox2), display.cb, FALSE, FALSE, 0);
+      gtk_widget_show (display.cb);
+
+
+      /* Add a button to refresh the list with */
+      button = gtk_button_new_with_label("Refresh Server List");
+      gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+                                 GTK_SIGNAL_FUNC (refresh_servers),
+                                 GTK_OBJECT( window ));
+      gtk_box_pack_end (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
+
+      /* Create the label box for the CDDB page */
+      label = gtk_label_new ("CDDB");
+      
+      /* Add it to the notebook */
+      gtk_notebook_append_page_menu( GTK_NOTEBOOK( notebook ), vbox2, label, label );
+
+      /* Add the close button */
+      button = gtk_button_new_with_label ("close");
+      gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+                                 GTK_SIGNAL_FUNC (close_setup),
+                                 GTK_OBJECT( window ));
+      gtk_box_pack_start (GTK_BOX (vbox1), button, FALSE, FALSE, 0);
+      GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+      gtk_widget_grab_default (button);
+    }
+
+  if (!GTK_WIDGET_VISIBLE (window))
+    gtk_widget_show_all (window);
+  else
+    gtk_widget_destroy( window );
+
+  return FALSE;
+}
+
+
+#ifdef GOOBER1
+void old_stuff()
+{
+
+  /* A useful frame with 3 radio buttons in it */
+
+      /* Create a frame with the Startup options as radio buttons */
+      frame = gtk_frame_new("Startup Action");
+      gtk_box_pack_start(GTK_BOX(vbox2), frame, FALSE, FALSE, 0);
+      gtk_widget_show(frame);
+
+      /* Add the general setup page */
+      vbox3 = gtk_vbox_new( FALSE, 0 );
+      gtk_container_add(GTK_CONTAINER(frame), vbox3);
+      gtk_container_border_width(GTK_CONTAINER(vbox3), 0); 
+      gtk_widget_show( vbox3 );
+
+      /* create radio button for Play at startup */
+      button = gtk_radio_button_new_with_label( NULL, "Play CD");
+      if( config.startup == STARTUP_PLAY )
+	gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE);
+      else
+ 	gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), FALSE);
+      gtk_signal_connect( GTK_OBJECT( button ), "toggled",
+			  GTK_SIGNAL_FUNC( play_setup ), NULL );
+      gtk_box_pack_start(GTK_BOX(vbox3), button, FALSE, FALSE, 0);
+      gtk_widget_show(button);
+ 
+      button = gtk_radio_button_new_with_label(
+	      gtk_radio_button_group (GTK_RADIO_BUTTON (button)), "Show Tracks");
+      if( config.startup == STARTUP_TRACKS )
+	gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE);
+      else
+ 	gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), FALSE);
+      gtk_signal_connect( GTK_OBJECT( button ), "toggled",
+			  GTK_SIGNAL_FUNC( tracks_setup ), NULL );
+      gtk_box_pack_start(GTK_BOX(vbox3), button, FALSE, FALSE, 0);
+      gtk_widget_show(button);
+ 
+      button = gtk_radio_button_new_with_label(
+	      gtk_radio_button_group (GTK_RADIO_BUTTON (button)), "No Disc");
+      if( config.startup == STARTUP_NODISC )
+	gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE);
+      else
+ 	gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), FALSE);
+      gtk_signal_connect( GTK_OBJECT( button ), "toggled",
+			  GTK_SIGNAL_FUNC( nothing_setup ), NULL );
+      gtk_box_pack_start(GTK_BOX(vbox3), button, FALSE, FALSE, 0);
+      gtk_widget_show(button);
+ 
+
+
+
+
+
+
+
+
+  GtkWidget *hbox;
+  GtkWidget *button;
+  GtkWidget *check;
+  GtkWidget *separator;
+  GtkWidget *table;
+  GtkWidget *hscrollbar;
+  GtkWidget *vscrollbar;
+  GtkWidget *text;
+
+    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), TRUE);
+    gtk_table_attach (GTK_TABLE (table), text, 0, 1, 0, 1,
+		      GTK_EXPAND | GTK_SHRINK | GTK_FILL,
+		      GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
+    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_SHRINK, 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_SHRINK | GTK_FILL, 0, 0);
+    gtk_widget_show (vscrollbar);
+    
+
+    gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL,
+                     "This program will play CDs using an attached ", -1);
+    gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL,
+                     "IDE or SoundBlaster CD player. It currently ", -1);
+    gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL,
+                     "does not work with SCSI drives.\n\n", -1);
+    gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL,
+                     "The latest version is available from my webpage.", -1);
+    gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL,
+                     "Please email me with any suggestions, problems,", -1);
+    gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL,
+                     "or comments you may have\n\n", -1);
+     
+    hbox = gtk_hbutton_box_new ();
+    gtk_box_pack_start (GTK_BOX (box2), hbox, FALSE, FALSE, 0);
+    gtk_widget_show (hbox);
+
+    /*      check = gtk_check_button_new_with_label("Editable");
+     *      gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, FALSE, 0);
+     *      gtk_signal_connect (GTK_OBJECT(check), "toggled",
+     *			  GTK_SIGNAL_FUNC(text_toggle_editable), text);
+     *      gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(check), TRUE);
+     *      gtk_widget_show (check);
+     */
+
+    /*      check = gtk_check_button_new_with_label("Wrap Words");
+     *      gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, TRUE, 0);
+     *      gtk_signal_connect (GTK_OBJECT(check), "toggled",
+     *			  GTK_SIGNAL_FUNC(text_toggle_word_wrap), text);
+     *      gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(check), FALSE);
+     *      gtk_widget_show (check);
+     */
+
+    /* Checkbox for www.cddb.com support */
+    check = gtk_check_button_new_with_label("www.cddb.com");
+    gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, TRUE, 0);
+    gtk_signal_connect (GTK_OBJECT(check), "toggled",
+			GTK_SIGNAL_FUNC(about_toggle_cddb), text);
+    gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(check), FALSE);
+    gtk_widget_show (check);
+
+    /* Checkbox for CD Changer support */
+    check = gtk_check_button_new_with_label("CD changer");
+    gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, TRUE, 0);
+    gtk_signal_connect (GTK_OBJECT(check), "toggled",
+			GTK_SIGNAL_FUNC(about_toggle_cddb), text);
+    gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(check), FALSE);
+    gtk_widget_show (check);
+
+    gtk_text_set_word_wrap(GTK_TEXT(text), TRUE );
+    
+    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);
+
+}
+#endif
+
+
+void help_press (GtkWidget *widget, GdkEventButton *event)                              
+{
+  if( event->button == 1 )
+  {
+    gtk_pixmap_set( GTK_PIXMAP( help.wid ),
+                    help.image.dn_pixmap,
+                    help.image.dn_mask );
+
+    /* In XXXmS execute the help dialog window function */
+    help.timer = gtk_timeout_add( 500, help_timer, NULL );
+  }
+}
+
+
+void help_release (GtkWidget *widget, GdkEventButton *event)
+{
+  if( event->button == 1 )
+  {
+    gtk_pixmap_set( GTK_PIXMAP( help.wid ),
+                    help.image.up_pixmap,
+                    help.image.up_mask );
+  }
+}
+
+
+void tdisp_press (GtkWidget *widget, GdkEventButton *event)                              
+{
+  if( event->button == 1 )
+  {
+    /* Cycle through the time display options */
+    switch( display.time )
+    {
+      case TRACK_ELAPSED :	display.time = TRACK_REMAIN;
+      				gtk_pixmap_set( GTK_PIXMAP( tdisp.wid ),
+      						display.plstrkdn_pixmap,
+      						display.plstrkdn_mask );
+      				break;
+      				
+      case TRACK_REMAIN :	display.time = CD_ELAPSED;
+      				gtk_pixmap_set( GTK_PIXMAP( tdisp.wid ),
+      						display.mnstrkdn_pixmap,
+      						display.mnstrkdn_mask );
+      				break;
+      				
+      case CD_ELAPSED :		display.time = CD_REMAIN;
+      				gtk_pixmap_set( GTK_PIXMAP( tdisp.wid ),
+      						display.plscddn_pixmap,
+      						display.plscddn_mask );
+      				break;
+      				
+      case CD_REMAIN :		display.time = TRACK_ELAPSED;
+      				gtk_pixmap_set( GTK_PIXMAP( tdisp.wid ),
+      						display.mnscddn_pixmap,
+      						display.mnscddn_mask );
+      				break;
+    }
+  }
+}
+
+
+void tdisp_release (GtkWidget *widget, GdkEventButton *event)
+{
+  if( event->button == 1 )
+  {
+    switch( display.time )
+    {
+      case TRACK_ELAPSED :	gtk_pixmap_set( GTK_PIXMAP( tdisp.wid ),
+      						display.plstrkup_pixmap,
+      						display.plstrkup_mask );
+      				break;
+      				
+      case TRACK_REMAIN :	gtk_pixmap_set( GTK_PIXMAP( tdisp.wid ),
+      						display.mnstrkup_pixmap,
+      						display.mnstrkup_mask );
+      				break;
+      				
+      case CD_ELAPSED :		gtk_pixmap_set( GTK_PIXMAP( tdisp.wid ),
+      						display.plscdup_pixmap,
+      						display.plscdup_mask );
+      				break;
+      				
+      case CD_REMAIN :		gtk_pixmap_set( GTK_PIXMAP( tdisp.wid ),
+      						display.mnscdup_pixmap,
+      						display.mnscdup_mask );
+      				break;
+    }
+  }
+}
+
+
+void rpt_press (GtkWidget *widget, GdkEventButton *event)                              
+{
+  if( event->button == 1 )
+  {
+    gtk_pixmap_set( GTK_PIXMAP( rpt.wid ),
+                    rpt.image.dn_pixmap,
+                    rpt.image.dn_mask );
+
+    if( display.repeat == 0 )
+      display.repeat = 1;
+    else
+      display.repeat = 0;
+  }
+}
+
+
+void rpt_release (GtkWidget *widget, GdkEventButton *event)
+{
+  if( event->button == 1 )
+  {
+    if( display.repeat == 0 )
+    {
+      gtk_pixmap_set( GTK_PIXMAP( rpt.wid ),
+                      rpt.image.up_pixmap,
+                      rpt.image.up_mask );
+    } else {
+      gtk_pixmap_set( GTK_PIXMAP( rpt.wid ),
+                      display.rptupact_pixmap,
+                      display.rptupact_mask );
+    }
+  }
+}
+
+
+void vol_press (GtkWidget *widget, GdkEventButton *event)                              
+{
+  switch( event->button )
+  {
+    case 1 :	gtk_pixmap_set( GTK_PIXMAP( vol.wid ),
+                   	        vol.image.dn_pixmap,
+                    		vol.image.dn_mask );
+    		set_vol( +10 );
+		update_display();
+    		break;
+    		
+    case 3 :	gtk_pixmap_set( GTK_PIXMAP( vol.wid ),
+                   	        vol.image.dn_pixmap,
+                    		vol.image.dn_mask );
+		set_vol( -10 );
+		update_display();
+    		break;
+    	
+  }
+}
+
+void vol_release (GtkWidget *widget, GdkEventButton *event)
+{
+  if( (event->button == 1) || (event->button == 3) )
+  {
+    gtk_pixmap_set( GTK_PIXMAP( vol.wid ),
+                    vol.image.up_pixmap,
+                    vol.image.up_mask );
+  }
+}
+
+/* -----------------------------------------------------------------------------------------
+   Show the track title listbox, allow editing of it. Hilight the current track. Show
+   total time for each track. Show discid for the CD. Allow sending to CDDB.
+   ----------------------------------------------------------------------------------------- */
+gint show_tracks( )
+{
+
+  return FALSE;
+}
+
+
+/* -----------------------------------------------------------------------
+   Redraw the uncovered part of the display
+   ----------------------------------------------------------------------- */
+static int expose_display( GtkWidget *widget, GdkEventExpose *event )
+{
+  switch( display.status )
+  {
+    case CDROM_PLAYING :	gdk_draw_pixmap (widget->window,
+                     				 widget->style->black_gc,
+                     				 display.null_pixmap, 
+                     				 event->area.x, event->area.y,
+                     				 event->area.x, event->area.y,
+                     				 event->area.width, event->area.height);
+  				break;
+
+    case CDROM_NODISC :		gdk_draw_pixmap (widget->window,
+                     				 widget->style->black_gc,
+                     				 display.nodisc_pixmap, 
+                     				 event->area.x, event->area.y,
+                     				 event->area.x, event->area.y,
+                     				 event->area.width, event->area.height);
+  				break;
+  }
+                                                                                                       
+  return FALSE;
+}
+
+
+
+
+
+/* -----------------------------------------------------------------------
+   Update the cdrom status and the display
+   
+   This routine is called once per second to check for the end of the CD
+   and to update the display.
+   ----------------------------------------------------------------------- */
+gint update_cdrom( gpointer data )
+{
+  /* Get the latest info into cdinfo structure */
+  cdrom_status();
+  
+  return TRUE;
+}
+
+
+/* -----------------------------------------------------------------------
+   Draw the current track # onto the null_pixmap and then copy the
+   pixmap to the display
+   ----------------------------------------------------------------------- */
+void draw_track()
+{
+  gdk_draw_pixmap( display.null_pixmap,
+ 		   display.wid->style->black_gc,
+		   display.a_pixmap[display.track/10],
+                   0, 0,
+                   2, 2, 11, 22 );
+
+  gdk_draw_pixmap( display.null_pixmap,
+                   display.wid->style->black_gc,
+                   display.a_pixmap[display.track%10],
+                   0, 0,
+                   15, 2, 11, 22 );
+
+  gdk_draw_pixmap( display.wid->window,
+                   display.wid->style->black_gc,
+                   display.null_pixmap,
+                   0, 0,
+                   0, 0, 92, 30 );
+}		  
+
+
+/* -----------------------------------------------------------------------
+   Draw the minute digits onto the null_pixmap and then copy the
+   pixmap to the display. Also draws the minus sign if needed.
+   ----------------------------------------------------------------------- */
+void draw_minute()
+{
+  /* Show or don't show the minus sign */
+  if((display.minute<0) || (display.second<0))
+    {
+      gdk_draw_pixmap( display.null_pixmap,
+		       display.wid->style->black_gc,
+		       display.minus_pixmap,
+		       0, 0,
+		       32, 10, 8, 16 );
+    } else {
+      gdk_draw_pixmap( display.null_pixmap,
+		       display.wid->style->black_gc,
+		       display.b_pixmap[10],
+		       0, 0,
+		       32, 10, 8, 16 );
+    }
+
+  gdk_draw_pixmap( display.null_pixmap,
+                   display.wid->style->black_gc,
+                   display.b_pixmap[abs(display.minute)/10],
+                   0, 0,
+                   42, 10, 8, 16 );
+
+  gdk_draw_pixmap( display.null_pixmap,
+                   display.wid->style->black_gc,
+                   display.b_pixmap[abs(display.minute)%10],
+                   0, 0,
+                   52, 10, 8, 16 );
+
+  gdk_draw_pixmap( display.wid->window,
+                   display.wid->style->black_gc,
+                   display.null_pixmap,
+                   0, 0,
+                   0, 0, 92, 30 );
+}
+
+
+/* -----------------------------------------------------------------------
+   Draw the second digits onto the null_pixmap and then copy the
+   pixmap to the display.
+   ----------------------------------------------------------------------- */
+void draw_second()
+{
+  /* Show or don't show the minus sign */
+  if((display.minute<0) || (display.second<0))
+    {
+      gdk_draw_pixmap( display.null_pixmap,
+		       display.wid->style->black_gc,
+		       display.minus_pixmap,
+		       0, 0,
+		       32, 10, 8, 16 );
+    } else {
+      gdk_draw_pixmap( display.null_pixmap,
+		       display.wid->style->black_gc,
+		       display.b_pixmap[10],
+		       0, 0,
+		       32, 10, 8, 16 );
+    }
+
+  gdk_draw_pixmap( display.null_pixmap,
+                   display.wid->style->black_gc,
+                   display.b_pixmap[abs(display.second/10)],
+                   0, 0,
+                   68, 10, 8, 16 );
+
+  gdk_draw_pixmap( display.null_pixmap,
+                   display.wid->style->black_gc,
+                   display.b_pixmap[abs(display.second%10)],
+                   0, 0,
+                   78, 10, 8, 16 );
+
+  gdk_draw_pixmap( display.wid->window,
+                   display.wid->style->black_gc,
+                   display.null_pixmap,
+                   0, 0,
+                   0, 0, 92, 30 );
+}
+
+
+/* -----------------------------------------------------------------------
+   Erase the minute digits and the minus sign. This is used by the blink
+   routine.
+   ----------------------------------------------------------------------- */
+void erase_minute()
+{				  
+  gdk_draw_pixmap( display.null_pixmap,
+                   display.wid->style->black_gc,
+                   display.b_pixmap[10],
+                   0, 0,
+                   32, 10, 8, 16 );
+
+  gdk_draw_pixmap( display.null_pixmap,
+                   display.wid->style->black_gc,
+                   display.b_pixmap[10],
+                   0, 0,
+                   42, 10, 8, 16 );
+
+  gdk_draw_pixmap( display.null_pixmap,
+                   display.wid->style->black_gc,
+                   display.b_pixmap[10],
+                   0, 0,
+                   52, 10, 8, 16 );
+
+  gdk_draw_pixmap( display.wid->window,
+                   display.wid->style->black_gc,
+                   display.null_pixmap,
+                   0, 0,
+                   0, 0, 92, 30 );
+}
+
+
+/* -----------------------------------------------------------------------
+   Erase the second digits. This is used by the blink routine.
+   ----------------------------------------------------------------------- */
+void erase_second()
+{
+  gdk_draw_pixmap( display.null_pixmap,
+                   display.wid->style->black_gc,
+                   display.b_pixmap[10],
+                   0, 0,
+                   68, 10, 8, 16 );
+
+  gdk_draw_pixmap( display.null_pixmap,
+                   display.wid->style->black_gc,
+                   display.b_pixmap[10],
+                   0, 0,
+                   78, 10, 8, 16 );
+
+  gdk_draw_pixmap( display.wid->window,
+                   display.wid->style->black_gc,
+                   display.null_pixmap,
+                   0, 0,
+                   0, 0, 92, 30 );
+}
+
+
+/* -----------------------------------------------------------------------
+   Decide what to show on the display
+   If there is no disc, then show NO DISC bitmap
+   If playing then update the display digits
+   If paused then blink the time
+   
+   It keeps track of the previous states of things so only the areas that
+   have changed get updated each time. An improvement would be to only
+   update the digits that change (instead of both minute or both second
+   digits), but it isn't that important.
+   ----------------------------------------------------------------------- */
+void update_display()
+{
+  static int	curr_track=-1,		/* Default to unknown value	*/
+  		curr_minute=-1,
+  		curr_second=-1,
+  		curr_status=-1,
+                curr_volume=-1,
+  		blinking=0,
+                tclist_track=-1;        /* Track selected in tclist */ 
+                
+  int		x;
+
+  /*
+   * If the volume needs updating then we draw a bargraph, one bar for
+   *  every 17 volume units. 15 bars maximum with the last 5 being red
+   */
+  if( curr_volume != cdinfo.volume )
+  {
+    for( x = 0; x < (cdinfo.volume / 17); x++ )
+    {
+      if( x < 10 )
+      {
+        gdk_draw_pixmap( display.null_pixmap,
+                         display.wid->style->black_gc,
+                         display.bar_pixmap,
+                         0, 0,
+                         30+(x*4), 1, 4, 7 );
+      } else {
+        gdk_draw_pixmap( display.null_pixmap,
+                         display.wid->style->black_gc,
+                         display.redbar_pixmap,
+                         0, 0,
+                         30+(x*4), 1, 4, 7 );
+      }
+    }
+    for( ; x < 15; x++ )
+    {
+      gdk_draw_pixmap( display.null_pixmap,
+                       display.wid->style->black_gc,
+                       display.nobar_pixmap,
+                       0, 0,
+                       30+(x*4), 1, 4, 7 );
+    }
+
+    gdk_draw_pixmap( display.wid->window,
+                     display.wid->style->black_gc,
+                     display.null_pixmap,
+                     0, 0,
+                     0, 0, 92, 30 );
+
+    curr_volume = cdinfo.volume;
+  }
+
+  switch( display.time )
+    {
+    case TRACK_ELAPSED :
+      display.minute = cdinfo.sc.cdsc_reladdr.msf.minute;
+      display.second = cdinfo.sc.cdsc_reladdr.msf.second;
+      break;
+
+    case TRACK_REMAIN :
+      display.minute = 0 - ( (cdinfo.track[display.track-1].length/60) - cdinfo.sc.cdsc_reladdr.msf.minute);
+      display.second = 0 - ( (cdinfo.track[display.track-1].length%60) - cdinfo.sc.cdsc_reladdr.msf.second);
+      break;
+      
+    case CD_ELAPSED : 
+      display.minute = cdinfo.sc.cdsc_absaddr.msf.minute;
+      display.second = cdinfo.sc.cdsc_absaddr.msf.second;
+      break;
+      
+    case CD_REMAIN :
+      display.minute = 0-cdinfo.cd_remaining/60;
+      display.second = 0-cdinfo.cd_remaining%60;
+      break;  
+    }
+
+
+  switch( display.status )
+  {
+    case CDROM_PLAYING :       	if( display.track != curr_track )
+    				{
+    				  draw_track();
+    				  
+  				  curr_track = display.track;
+    				}
+    
+    				if( display.minute != curr_minute )
+    				{
+				  draw_minute();
+  				  
+    				  curr_minute = display.minute;
+    				}
+    
+    				if( display.second != curr_second )
+    				{
+				  draw_second();
+				  
+   				  curr_second = display.second;
+   				}
+				curr_status = display.status;
+
+				if( display.playbtn != CDROM_PLAYING )
+				  {
+				    gtk_pixmap_set( GTK_PIXMAP( play.wid ),
+						    display.playup_pixmap,
+						    display.playup_mask );
+
+				    display.playbtn = CDROM_PLAYING;
+				  }
+
+				/* If the track window is open, update selected track */
+				if( display.twindow != NULL )
+				  {
+				    if( tclist_track+1 != curr_track )
+				      {
+					if( curr_track > 0 )
+					  tclist_track = curr_track -1;
+					else
+					  tclist_track = 0;
+					gtk_clist_select_row( GTK_CLIST(display.tclist), tclist_track, -1 );
+				      }
+				  }
+				
+   				break;
+   
+    /* Flash the min/sec digits while paused */
+    case CDROM_PAUSED :		if( display.track != curr_track )
+                                {
+    				  draw_track();
+    				  
+  				  curr_track = display.track;
+    				}
+    
+
+                                if( blinking )
+    				{
+				  draw_second();
+    				  draw_minute();
+    				  blinking=0;  
+    				} else {
+    				  erase_second();
+    				  erase_minute();
+    				  curr_second = -1;
+    				  curr_minute = -1;
+    				  blinking=1;
+    				}
+
+                                if( display.playbtn != CDROM_PAUSED )
+				  {
+				    gtk_pixmap_set( GTK_PIXMAP( play.wid ),
+						    display.pauseup_pixmap,
+						    display.pauseup_mask );
+				    display.playbtn = CDROM_PAUSED;
+				  }
+    				break; 
+    
+    				/* Display NO DISC */
+    case CDROM_NODISC :		if( curr_status != display.status )
+    				{
+    				  gdk_draw_pixmap( display.wid->window,
+    				  		   display.wid->style->black_gc,
+    						   display.nodisc_pixmap,
+    						   0, 0,
+    						   0, 0, 92, 30 );
+
+    				  curr_status = display.status;
+    				}
+
+                                if( display.playbtn != CDROM_NODISC )
+				  {
+				    gtk_pixmap_set( GTK_PIXMAP( play.wid ),
+						    display.stopup_pixmap,
+						    display.stopup_mask );
+				    display.playbtn = CDROM_NODISC;
+				  }
+
+				break;
+  }
+
+#ifdef DEBUG4
+  g_print( "update called. status = %d  remain = %d\n", display.status, cdinfo.cd_remaining );
+  g_print( "        curr  new\n");
+  g_print( "track   %03d : %03d\n", curr_track, display.track );
+  g_print( "minute  %03d : %03d\n", curr_minute, display.minute );
+  g_print( "second  %03d : %03d\n", curr_second, display.second );
+  g_print( "volume  %03d : %03d\n", curr_volume, cdinfo.volume );
+#endif
+
+}
+
+
+/* ------------------------------------------------------------------------
+   Process data coming back from the cd_control process
+
+   This is a stateless process since it only returns a cdinfo structure
+   ------------------------------------------------------------------------ */
+void wait_status()
+{
+  struct CDINFO tmpinfo;
+  struct SITE   *sp;
+  char          buffer[80];
+  int           x;
+  char         *texts[3],
+               text1[255],
+               text2[255];
+
+
+  /* Read the new cdinfo structure from the cd_control process */
+  if( read( cd_fd, &tmpinfo, sizeof(struct CDINFO) ) < 0 )
+    perror("cdrom_status(read)");
+
+  /* Copy the useful bits from tmpinfo  to cdinfo */
+  memcpy( &cdinfo.tochdr, &tmpinfo.tochdr, sizeof(tmpinfo.tochdr) );
+  memcpy( &cdinfo.leadout, &tmpinfo.leadout, sizeof(tmpinfo.leadout) );
+  memcpy( &cdinfo.volume, &tmpinfo.volume, sizeof(tmpinfo.volume) );
+
+  /* Copy track length, but not the track name over from the status */
+  for( x = 0; x < cdinfo.tochdr.cdth_trk1; x++ )
+    {
+      cdinfo.track[x].te = tmpinfo.track[x].te;
+      cdinfo.track[x].length = tmpinfo.track[x].length;
+      cdinfo.track[x].frame_offset = tmpinfo.track[x].frame_offset;
+    }
+
+  memcpy( &cdinfo.sc, &tmpinfo.sc, sizeof(tmpinfo.sc) );
+  memcpy( &cdinfo.ti, &tmpinfo.ti, sizeof(tmpinfo.ti) );
+  cdinfo.cd_length = tmpinfo.cd_length;
+  cdinfo.discid = tmpinfo.discid;
+
+  switch( cdinfo.sc.cdsc_audiostatus )
+    {
+    case CDROM_AUDIO_PLAY :
+    case CDROM_AUDIO_PAUSED :
+      if( cdinfo.sc.cdsc_audiostatus == CDROM_AUDIO_PLAY )
+	display.status = CDROM_PLAYING;
+      else
+	display.status = CDROM_PAUSED;
+
+      /* Update the currently playing track */
+      display.track = cdinfo.sc.cdsc_trk;
+
+      /* Update the number of seconds remaining on the CD */
+      cdinfo.cd_remaining = cdinfo.cd_length - ((cdinfo.sc.cdsc_absaddr.msf.minute*60)+cdinfo.sc.cdsc_absaddr.msf.second);
+
+      /* Do we need track data? Can we request it? */
+      if( (display.cddb_lock == 0) && (cdinfo.revision == -1))
+	{
+	  if( config.cddb == 1 )
+	    {   
+#ifdef DEBUG9
+	      g_print("reading cddb info %d\n", cdinfo.revision );
+#endif
+	      /* Try and find a cddb entry in the local CD database */
+	      if( read_cddb( &cdinfo ) < 0 )
+		{
+		  /* Default server to query */
+		  strcpy( cdinfo.server, "cddb.cddb.com" );
+		  cdinfo.port = 888;
+
+		  /* So here we query the default internet server */
+		  if( config.current != NULL )
+		    {
+		      /* Use the current + 888 even if not found in the list */
+		      strcpy( cdinfo.server, config.current );
+
+		      /* Find the current server in the list */
+		      sp = config.server;
+		      while( sp != NULL )
+			{
+			  if( strcmp( sp->name, config.current ) == 0 )
+			    {
+			      strcpy( cdinfo.server, sp->name );
+			      cdinfo.port = sp->port;
+			      sp = NULL;
+			    }else {
+			      sp = sp->next;
+			    }
+			}
+		    }
+		  /* Send the command to the server - Starts a state machine */
+		  cdinfo.cddbd_cmnd = DB_READ;
+		  if( write( cddbd_fd, &cdinfo, sizeof( struct CDINFO) ) < 0 )
+		    {
+		      perror("write to cddbd_fd error");
+		      if( cdinfo.revision < 0 )
+			cdinfo.revision = -2;     /* Failed, Don't try again */
+		    }
+		  /* Lock the use of the internet database */
+		  display.cddb_lock = 1;
+
+		  /* !!!! This could probably be turned into a subroutine
+		     !!!! */
+
+		  /* Start up a progress dialog */
+		  display.progress = gtk_dialog_new ();
+		  
+		  sprintf(buffer, "Connecting to %s:%d", cdinfo.server,
+			                                 cdinfo.port );
+
+		  gtk_signal_connect( GTK_OBJECT( display.progress ), "destroy",
+				      GTK_SIGNAL_FUNC(gtk_widget_destroy),
+				      &display.progress);
+
+		  gtk_window_set_title (GTK_WINDOW (display.progress), "CDDBD Status");
+		  gtk_container_border_width (GTK_CONTAINER (display.progress), 0);
+		  gtk_window_set_wmclass(GTK_WINDOW(display.progress), "XfreeCDp", NULL );
+
+		  display.plabel = gtk_label_new (buffer);
+		  gtk_misc_set_padding (GTK_MISC (display.plabel), 10, 10);
+		  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (display.progress)->vbox),
+				      display.plabel, FALSE, FALSE, 0);
+		  gtk_widget_show( display.plabel );
+		  gtk_widget_show( display.progress );
+		} else {
+		  /* Read of local database successful */
+#ifdef DEBUG5
+		  g_print("Title : %s\n", cdinfo.title->str );
+		  for( x = 0; x < cdinfo.tochdr.cdth_trk1; x++ )
+		    {
+		      g_print("Track %d : %s\n", x+1, cdinfo.name[x]->str );
+		    }
+#endif
+		}
+	    } else {
+	      /* Read the data from the local database, or set defaults */
+	      local_cddb();
+	    }
+
+	  /* If the track list window is open, update the list */
+	  if( display.twindow != NULL )
+	    {
+#ifdef DEBUG9
+	      g_print("Updating Track Window revision=%d\n", cdinfo.revision);
+#endif
+
+	      gtk_clist_freeze (GTK_CLIST (display.tclist));
+	      
+	      /* Clear out the old list first */
+	      gtk_clist_clear( GTK_CLIST( display.tclist ) );
+	      
+	      /* Set the new title */
+	      if( cdinfo.title != NULL )
+		sprintf( text1, "%s", cdinfo.title->str );
+	      else
+		strcpy( text1, "" );
+	      gtk_label_set( GTK_LABEL( display.ttitle ), text1 );
+	      
+	      /* Add the track names */
+	      for( x = 0; x < cdinfo.tochdr.cdth_trk1; x++ )
+		{
+		  sprintf( text1, "%d", x+1 );
+		  sprintf( text2, "%d:%02d",cdinfo.track[x].length/60,cdinfo.track[x].length%60 );
+		  texts[0] = text1;
+		  texts[2] = text2;
+		  if( cdinfo.name[x] != NULL )
+		    texts[1] = cdinfo.name[x]->str;
+		  else
+		    texts[1] = "(blank)";
+		  gtk_clist_append (GTK_CLIST (display.tclist), texts);
+		}
+	      gtk_clist_thaw( GTK_CLIST( display.tclist ) );
+	      gtk_clist_select_row( GTK_CLIST(display.tclist), display.track-1, -1 );
+	    }
+	}
+      break;
+
+#ifdef OLD_WAY					
+      case CDROM_AUDIO_PAUSED :
+      display.status = CDROM_PAUSED;
+      break;
+#endif
+
+    case CDROM_AUDIO_NO_STATUS :
+      /* Only clean things up once */
+      if( display.status != CDROM_NODISC )
+	{
+	  /* Clear out the track list */
+	  if( display.twindow != NULL )
+	    {
+	      gtk_clist_clear( GTK_CLIST( display.tclist ) );
+	      
+	      /* Clear the title */
+	      gtk_label_set( GTK_LABEL( display.ttitle ), "" );
+	    }
+
+	  /* Free dynamically allocated cdinfo strings */
+	  free_cdinfo();
+
+	  display.status = CDROM_NODISC;
+	  /* Reset the revision # so next will recall from database*/
+	  cdinfo.revision = -1;
+	}
+      break;
+
+    default:
+      /* Only cleanup once */
+      if( display.status != CDROM_NODISC )
+	{
+	  /* Clear out the track list */
+	  if( display.twindow != NULL )
+	    {
+	      gtk_clist_clear( GTK_CLIST( display.tclist ) );
+
+	      /* Clear the title */
+	      gtk_label_set( GTK_LABEL( display.ttitle ), "" );
+	    }
+
+	  /* Free dynamically allocated cdinfo strings */
+	  free_cdinfo();
+
+	  display.status = CDROM_NODISC;
+	  cdinfo.revision = -1;
+	}
+      break;
+  }  
+
+
+  /*
+   * If the CD is over then either restart it, or eject it, or show NO DISC
+   */
+  if( (cdinfo.cd_remaining == 0) && (display.status == CDROM_PLAYING) )
+    {
+      /* If repeat is on, start playing the cd over from the start */
+      if( display.repeat == 1 )
+	{
+	  display.track = cdinfo.tochdr.cdth_trk0;
+	  play_track( cdinfo.tochdr.cdth_trk0 );
+	} else {
+	  /* Clear out the track list */
+	  if( display.twindow != NULL )
+	    {
+	      gtk_clist_clear( GTK_CLIST( display.tclist ) );
+
+	      /* Clear the title */
+	      gtk_label_set( GTK_LABEL( display.ttitle ), "" );
+	    }
+
+	  /* Free up any dynamically allocated cdinfo strings */
+	  free_cdinfo();
+
+	  /* Eject when done Playing - only eject if the user has enabled this */
+	  if( config.done_eject == 1 )
+	    {
+	      /* All done, eject it for the next disc! */
+	      eject_cdrom();
+	    } else {
+	      stop_cdrom();
+	    }
+
+	  gtk_pixmap_set( GTK_PIXMAP( play.wid ),
+			  display.stopup_pixmap,
+			  display.stopup_mask );
+	  display.playbtn = CDROM_NODISC;
+	}
+    }
+}
+
+
+/* -------------------------------------------------------------------------
+   Process data coming back from the cd_control process
+
+   This is a stateless process since it only returns a cdinfo structure
+   ------------------------------------------------------------------------- */
+void cd_fd_read( gpointer data, gint source, GdkInputCondition condition)
+{
+  wait_status();
+
+  if( display.startup == 0 )
+    {
+      if( config.startup == 1 )
+	{
+	  /* If it is already playing, don't restart it */
+	  if( ( cdinfo.sc.cdsc_audiostatus != CDROM_AUDIO_PLAY ) &&
+	      (cdinfo.discid != 0 ) )
+	    {
+#ifdef DEBUG6
+	      g_print("Starting play of cd. audiostatus = %d\n", cdinfo.sc.cdsc_audiostatus );
+#endif
+	      play_track( 1 );
+	    }
+	}
+
+      /* Stop trying after the discid gets set by cd_control process */
+      if( cdinfo.discid != 0 )
+	display.startup = 1;
+    }
+
+  update_display();
+}
+
+
+/* ------------------------------------------------------------------------
+   this is the signal handler that gets called if GtkList
+   emits the "selection_changed" signal
+   ------------------------------------------------------------------------ */
+void inexact_selected( GtkWidget *gtklist, gpointer func_data)
+{
+  char      *p,
+            buffer[80];
+  GList     *dlist;
+  GtkObject *list_item;
+  gchar     *item_data_string;
+
+
+  /* fetch the doubly linked list of selected items
+   * of the GtkList, remember to treat this as read-only!
+   */
+  dlist=GTK_LIST(gtklist)->selection;
+
+  /* if there are no selected items there is nothing more
+   * to do than just telling the user so
+   */
+  if (dlist)
+    {
+      list_item=GTK_OBJECT(dlist->data);
+      item_data_string=gtk_object_get_data(list_item,
+					   "XfreeCDkey");
+      p = strtok( item_data_string, " \n" );
+      p = strtok( NULL, " \n" );
+
+#ifdef DEBUG3
+      g_print("Retrieving data for %s\n", p);
+#endif
+
+      /* Change the discid so the new request will work */
+      sscanf( p, "%lx", &cdinfo.discid );
+      cdinfo.cddbd_cmnd = DB_READ;
+      if( write( cddbd_fd, &cdinfo, sizeof( struct CDINFO) ) < 0 )
+	{
+	  perror("write to cddbd_fd error");
+	  if( cdinfo.revision < 0 )
+	    cdinfo.revision = -2;     /* Failed, Don't try again */
+	}
+      /* Lock use of the CDDB internet server */
+      display.cddb_lock = 1;
+
+      /* Delete the old progress box */
+      gtk_widget_destroy( display.progress );
+      display.plabel = NULL;
+
+      /* Start up a new progress dialog */
+      display.progress = gtk_dialog_new ();
+
+      sprintf(buffer, "Connecting to %s:%d", cdinfo.server, cdinfo.port );
+
+      gtk_signal_connect( GTK_OBJECT( display.progress ), "destroy",
+			  GTK_SIGNAL_FUNC(gtk_widget_destroy),
+			  &display.progress);
+
+      gtk_window_set_title (GTK_WINDOW (display.progress), "CDDBD Status");
+      gtk_container_border_width (GTK_CONTAINER (display.progress), 0);
+      gtk_window_set_wmclass(GTK_WINDOW(display.progress), "XfreeCDp", NULL );
+
+      display.plabel = gtk_label_new (buffer);
+      gtk_misc_set_padding (GTK_MISC (display.plabel), 10, 10);
+      gtk_box_pack_start (GTK_BOX (GTK_DIALOG (display.progress)->vbox),
+			  display.plabel, FALSE, FALSE, 0);
+      gtk_widget_show( display.plabel );
+      gtk_widget_show( display.progress );
+    } else {
+      gtk_widget_destroy( display.progress );
+      display.plabel = NULL;
+    }
+}
+
+
+
+
+/* -------------------------------------------------------------------------
+   Process data coming back from the cddbd process
+
+   This routine processes data from the pipe to the cddbd process. This gets
+   the track names and site list from the server.
+   ------------------------------------------------------------------------- */
+void cddbd_fd_read( gpointer data, gint source, GdkInputCondition condition)
+{
+  struct CDINFO tmpinfo;
+  int           x;
+  static struct SITE   *sp,
+                       *sp_top=NULL,
+                       *sp_end=NULL;
+  char          *p, buffer[80];
+  gchar         *string;
+  GtkWidget     *button,
+                *scrolled_win,
+                *list,
+                *vbox1,
+                *label;
+  static GList  *cbitems=NULL;
+  char         *texts[3],
+               text1[255],
+               text2[255];
+
+
+  /* Read back the status structure */
+  if( read( cddbd_fd, &tmpinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
+    {
+      perror( "CDDBD status read" );
+      close( cd_fd );
+      close( cddbd_fd );
+      exit(-1);
+    }
+
+  switch( tmpinfo.cddbd_stat )
+    {
+    case CDDBD_OPEN_OK :
+#ifdef DEBUG3
+      g_print("Connected to %s ok\n", tmpinfo.server );
+#endif
+
+      if( display.plabel != NULL )
+	{
+	  sprintf (buffer, "Connected to %s:%d", tmpinfo.server, tmpinfo.port);
+	  gtk_label_set (GTK_LABEL (display.plabel), buffer);
+	}
+      break;
+
+    case CDDBD_DONE_OK :
+      display.cddb_lock = 0;
+
+      /* Copy the info from the tmpinfo to cdinfo */
+#ifdef DEBUG3
+      g_print("Got the new data ok\n");
+      g_print("tmpinfo.title->str = 0x%X\n", tmpinfo.title->str );
+#endif
+
+#ifdef DUMB
+      if( display.plabel != NULL )
+	{
+	  sprintf (buffer, "Retrieved %s", tmpinfo.title->str );
+	  gtk_label_set (GTK_LABEL (display.plabel), buffer);
+	}
+#endif
+
+      gtk_widget_destroy( display.progress );
+      display.plabel = NULL;
+
+      /* Read the new data from the database */
+      local_cddb();
+
+      /* If the track list window is open, update the list */
+      if( display.twindow != NULL )
+	{
+	  gtk_clist_freeze (GTK_CLIST (display.tclist));
+	  
+	  /* Clear out the old list first */
+	  gtk_clist_clear( GTK_CLIST( display.tclist ) );
+
+	  /* Set the new title */
+	  if( cdinfo.title != NULL )
+	    sprintf( text1, "%s", cdinfo.title->str );
+	  else
+	    strcpy( text1, "" );
+	  gtk_label_set( GTK_LABEL( display.ttitle ), text1 );
+
+	  /* Add the track names */
+	  for( x = 0; x < cdinfo.tochdr.cdth_trk1; x++ )
+	    {
+	      sprintf( text1, "%d", x+1 );
+	      sprintf( text2, "%d:%02d",cdinfo.track[x].length/60,cdinfo.track[x].length%60 );
+	      texts[0] = text1;
+	      texts[2] = text2;
+	      if( cdinfo.name[x] != NULL )
+		texts[1] = cdinfo.name[x]->str;
+	      else
+		texts[1] = "(blank)";
+	      gtk_clist_append (GTK_CLIST (display.tclist), texts);
+	    }
+	  gtk_clist_thaw( GTK_CLIST( display.tclist ) );
+	  gtk_clist_select_row( GTK_CLIST(display.tclist), display.track-1, -1 );
+	}
+      break;
+      
+      /* Process the line of text */
+    case CDDBD_MOTD_LINE :
+      
+      if( tmpinfo.line[0] == '.' )
+	{
+	  display.cddb_lock = 0;
+#ifdef DEBUG3
+	  g_print("End of MOTD\n");
+#endif
+
+	  gtk_widget_destroy( display.progress );
+	  display.plabel = NULL;
+
+	} else {
+#ifdef DEBUG3
+	  /* Do something with the MOTD, for now print it */
+	  g_print( "%s", tmpinfo.line );
+#endif
+
+	  if( display.plabel != NULL )
+	    {
+	      gtk_label_set (GTK_LABEL (display.plabel), tmpinfo.line);
+	    }
+	}
+      break;
+
+      /* Process the line of text */
+    case CDDBD_SITE_LINE :
+      
+      if( tmpinfo.line[0] == '.' )
+	{
+	  display.cddb_lock = 0;
+#ifdef DEBUG3
+	  g_print("End of Site listing\n");
+#endif
+	  if( display.plabel != NULL )
+	    {
+	      sprintf (buffer, "Retrieved Site Listing ok" );
+	      gtk_label_set (GTK_LABEL (display.plabel), buffer);
+	    }
+
+	  if( sp_top != NULL )
+	    {
+	      /* Everything seems okay, erase the old list and add the new one */
+	      while( config.server != NULL )
+		{
+		  sp = config.server;
+		  config.server = config.server->next;
+		  free( sp->name );
+		  free( sp );
+		}
+
+	      /* Point config to the new list */
+	      config.server = sp_top;
+	      sp_top = sp_end = NULL;
+
+	      config.saved = 0;             /* Need to save this to disk */
+	      write_config( &config );      /* Write new list to disk */
+	      strncpy( cdinfo.device, config.device, 80 );
+
+	      /* Need to let the site list in the dialog box be updated if it is
+		 still being shown (user could close it before we finish).
+	      */
+	      if( display.cb != NULL )
+		{
+
+		  /* Walk the list */
+		  cbitems = NULL;
+		  sp = config.server;
+		  while( sp != NULL )
+		    {
+		      cbitems = g_list_append(cbitems, sp->name);
+		      sp = sp->next;
+		    }
+      
+		  gtk_combo_set_popdown_strings (GTK_COMBO (display.cb), cbitems);
+		  cbitems = NULL;
+		}
+
+	    }
+	  gtk_widget_destroy( display.progress );
+	  display.plabel = NULL;
+
+	} else {
+	  /* Do something with the SITE, for now print it */
+	  /* Need to store in a temp. List until complete, then move to config */
+#ifdef DEBUG3
+	  g_print( "%s", tmpinfo.line );
+#endif
+
+	  if( display.plabel != NULL )
+	    {
+	      gtk_label_set (GTK_LABEL (display.plabel), tmpinfo.line);
+	    }
+
+	  /* Reserve some space for this server, add it to the end of the list */
+	  if( ( sp = (struct SITE *) malloc( sizeof(struct SITE) ) ) == NULL )
+	    {
+	      perror("malloc - 1");
+	    }
+	  bzero( sp, sizeof(struct SITE) );
+      
+	  p = strtok( tmpinfo.line, " \n" );
+
+	  /* Reserve space for the name */
+	  if( ( sp->name = (char *) malloc( strlen(p)+1 ) ) == NULL )
+	    {
+	      perror("malloc - 2");
+	    }
+	  strcpy( sp->name, p );
+
+	  p = strtok( NULL, " \n" );
+	  sp->port = atoi(p);
+	  sp->next = NULL;
+
+	  /* Is it the first in the list? */
+	  if( sp_top == NULL )
+	    {
+	      /* Yep, First in the list */
+	      sp_top = sp;
+	      sp_end = sp;
+	    } else {
+	      /* No, add it to the end of the list */
+	      sp_end->next = sp;
+	      sp_end = sp;
+	    }
+	}
+      break;
+
+
+      /* Process the line of text inexact matches */
+    case CDDBD_INEX_LINE :
+      
+      if( tmpinfo.line[0] == '.' )
+	{
+	  cdinfo.revision = -2;
+	  display.cddb_lock = 0;
+
+#ifdef DEBUG3
+	  g_print("End of Inexact Match listing\n");
+#endif
+
+	  if( display.plabel != NULL )
+	    {
+	      sprintf (buffer, "Retrieved inexact matches for discid 0x%08lx", cdinfo.discid );
+	      gtk_label_set (GTK_LABEL (display.plabel), buffer);
+	    }
+
+	  /* Here we want to add a list of the sites to the progress box,
+	     add a cancel button, and add a signal to use one of the inexact
+	     matches in a new search.
+	  */
+	  if( cbitems != NULL )
+	    {
+	      /* Add a vbox to hold the list and cancel button */
+	      vbox1 = gtk_vbox_new( FALSE, 0 );
+	      gtk_box_pack_start( GTK_BOX (GTK_DIALOG (display.progress)->action_area),
+				  vbox1, FALSE, TRUE, 1 );
+	      gtk_widget_show( vbox1 );
+	      
+	      scrolled_win = gtk_scrolled_window_new (NULL, NULL);
+	      gtk_widget_set_usize( scrolled_win, 250, 100 );
+	      gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
+					      GTK_POLICY_AUTOMATIC,
+					      GTK_POLICY_AUTOMATIC);
+	      gtk_box_pack_start (GTK_BOX( vbox1 ), scrolled_win, FALSE, FALSE, 0);
+	      gtk_widget_show (scrolled_win);
+
+	      /* Put a list into the scrolling window */
+	      list = gtk_list_new ();
+	      gtk_list_set_selection_mode (GTK_LIST (list), GTK_SELECTION_SINGLE);
+	      gtk_container_add (GTK_CONTAINER (scrolled_win), list);
+	      gtk_container_set_focus_vadjustment (GTK_CONTAINER (list),
+	      	   gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_win)));
+	      gtk_signal_connect(GTK_OBJECT(list),
+				 "selection_changed",
+				 GTK_SIGNAL_FUNC(inexact_selected),
+				 NULL);
+	      gtk_widget_show (list);
+
+	      /* Add the list of inexact matches to the list from cbitems */
+	      gtk_list_append_items( GTK_LIST( list ), cbitems );
+
+	      button = gtk_button_new_with_label ("Cancel");
+	      gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+					 GTK_SIGNAL_FUNC(gtk_widget_destroy),
+					 GTK_OBJECT (display.progress));
+	      GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+	      gtk_box_pack_start (GTK_BOX( vbox1 ), button, TRUE, TRUE, 0);
+	      gtk_widget_grab_default (button);
+	      gtk_widget_show (button);
+	      
+	      cbitems = NULL;
+	    } else {
+	      gtk_widget_destroy( display.progress );
+	      display.plabel = NULL;
+	    }
+	} else {
+	  /* Need to store in a temp. List until we receive the last line */
+#ifdef DEBUG3
+	  g_print( "%s", tmpinfo.line );
+#endif
+
+	  /* Show the line in the progress box */
+	  if( display.plabel != NULL )
+	    {
+	      gtk_label_set (GTK_LABEL (display.plabel), tmpinfo.line);
+	    }
+
+	  /* Add it to a list of sites */
+	  /* Need to detect first line of this type and set cbitems to NULL, or else
+	     set it to null when everything else is finished with it.
+	  */
+	  if( tmpinfo.line[strlen(tmpinfo.line)-1] == '\n' )
+	    {
+	      tmpinfo.line[strlen(tmpinfo.line)-1] = 0x00;
+	    }
+
+	  button=gtk_list_item_new();
+	  label=gtk_label_new( tmpinfo.line );
+	  gtk_misc_set_alignment (GTK_MISC(label), 0.0, 0.5);
+	  gtk_container_add (GTK_CONTAINER (button), label);
+	  gtk_widget_show (label);
+	  gtk_widget_show(button);
+	  gtk_label_get(GTK_LABEL(label), &string);
+	  gtk_object_set_data(GTK_OBJECT(button),
+			      "XfreeCDkey",
+			      string);
+	  cbitems = g_list_append(cbitems, button);
+
+	}
+      break;
+
+
+
+    case CDDBD_MATCH_OK :
+#ifdef DEBUG3
+      g_print("Got a match for 0x%08lx\n", tmpinfo.discid );
+#endif
+
+      if( display.plabel != NULL )
+	{
+	  sprintf (buffer, "Retrieving data for id 0x%08lx", tmpinfo.discid);
+	  gtk_label_set (GTK_LABEL (display.plabel), buffer);
+	}
+
+      break;
+      
+    case CDDBD_ENTRY_OK :
+#ifdef DEBUG3
+      g_print("Reading CDDB Database entry from %s\n", tmpinfo.server );
+#endif
+
+      if( display.plabel != NULL )
+	{
+	  sprintf (buffer, "Reading CDDB info from %s", tmpinfo.server);
+	  gtk_label_set (GTK_LABEL (display.plabel), buffer);
+	}
+      break;
+      
+    case CDDBD_DONE_ERR :
+      cdinfo.revision = -2;
+      display.cddb_lock = 0;
+
+
+#ifdef DEBUG3
+      g_print("Error reading temporary file\n");
+#endif
+
+      if( display.plabel != NULL )
+	{
+	  sprintf (buffer, "Error Reading temp. file");
+	  gtk_label_set (GTK_LABEL (display.plabel), buffer);
+	}
+
+      button = gtk_button_new_with_label ("OK");
+      gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+                                 GTK_SIGNAL_FUNC(gtk_widget_destroy),
+                                 GTK_OBJECT (display.progress));
+      GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+      gtk_box_pack_start (GTK_BOX (GTK_DIALOG (display.progress)->action_area),
+                          button, TRUE, TRUE, 0);
+      gtk_widget_grab_default (button);
+      gtk_widget_show (button);
+
+      break;
+      
+    case CDDBD_OPEN_ERR :
+      cdinfo.revision = -2;
+      display.cddb_lock = 0;
+
+#ifdef DEBUG3
+      g_print("Failed to connect to %s\n", tmpinfo.server );
+      g_print("%s\n", tmpinfo.line );
+#endif
+
+      if( display.plabel != NULL )
+	{
+	  sprintf (buffer, "Failed to connect to %s", tmpinfo.server );
+	  gtk_label_set (GTK_LABEL (display.plabel), buffer);
+	}
+
+      button = gtk_button_new_with_label ("OK");
+      gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+                                 GTK_SIGNAL_FUNC(gtk_widget_destroy),
+                                 GTK_OBJECT (display.progress));
+      GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+      gtk_box_pack_start (GTK_BOX (GTK_DIALOG (display.progress)->action_area),
+                          button, TRUE, TRUE, 0);
+      gtk_widget_grab_default (button);
+      gtk_widget_show (button);
+
+      break;
+      
+    case CDDBD_READ_ERR :
+      cdinfo.revision = -2;
+      display.cddb_lock = 0;
+
+#ifdef DEBUG3
+      g_print("Socket read failed\n");
+#endif
+
+      if( display.plabel != NULL )
+	{
+	  sprintf (buffer, "Socket Read Failed");
+	  gtk_label_set (GTK_LABEL (display.plabel), buffer);
+	}
+
+      button = gtk_button_new_with_label ("OK");
+      gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+                                 GTK_SIGNAL_FUNC(gtk_widget_destroy),
+                                 GTK_OBJECT (display.progress));
+      GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+      gtk_box_pack_start (GTK_BOX (GTK_DIALOG (display.progress)->action_area),
+                          button, TRUE, TRUE, 0);
+      gtk_widget_grab_default (button);
+      gtk_widget_show (button);
+
+      break;
+      
+    case CDDBD_WRITE_ERR :
+      cdinfo.revision = -2;
+      display.cddb_lock = 0;
+
+#ifdef DEBUG3
+      g_print("Socket write failed\n");
+#endif
+
+      if( display.plabel != NULL )
+	{
+	  sprintf (buffer, "Socket Write Failed");
+	  gtk_label_set (GTK_LABEL (display.plabel), buffer);
+	}
+
+      button = gtk_button_new_with_label ("OK");
+      gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+                                 GTK_SIGNAL_FUNC(gtk_widget_destroy),
+                                 GTK_OBJECT (display.progress));
+      GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+      gtk_box_pack_start (GTK_BOX (GTK_DIALOG (display.progress)->action_area),
+                          button, TRUE, TRUE, 0);
+      gtk_widget_grab_default (button);
+      gtk_widget_show (button);
+
+      break;
+      
+    case CDDBD_TMPF_ERR :
+      cdinfo.revision = -2;
+      display.cddb_lock = 0;
+
+#ifdef DEBUG3
+      g_print("Error, cannot create a temporary filename\n");
+#endif
+
+      if( display.plabel != NULL )
+	{
+	  sprintf (buffer, "Cannot Create temp. file");
+	  gtk_label_set (GTK_LABEL (display.plabel), buffer);
+	}
+
+      button = gtk_button_new_with_label ("OK");
+      gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+                                 GTK_SIGNAL_FUNC(gtk_widget_destroy),
+                                 GTK_OBJECT (display.progress));
+      GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+      gtk_box_pack_start (GTK_BOX (GTK_DIALOG (display.progress)->action_area),
+                          button, TRUE, TRUE, 0);
+      gtk_widget_grab_default (button);
+      gtk_widget_show (button);
+
+      break;
+      
+    case CDDBD_FOPEN_ERR :
+      cdinfo.revision = -2;
+      display.cddb_lock = 0;
+
+#ifdef DEBUG3
+      g_print("Error opening temporary file\n");
+#endif
+
+      if( display.plabel != NULL )
+	{
+	  sprintf (buffer, "Error opening temp. file");
+	  gtk_label_set (GTK_LABEL (display.plabel), buffer);
+	}
+
+      button = gtk_button_new_with_label ("OK");
+      gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+                                 GTK_SIGNAL_FUNC(gtk_widget_destroy),
+                                 GTK_OBJECT (display.progress));
+      GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+      gtk_box_pack_start (GTK_BOX (GTK_DIALOG (display.progress)->action_area),
+                          button, TRUE, TRUE, 0);
+      gtk_widget_grab_default (button);
+      gtk_widget_show (button);
+
+      break;
+      
+    default:
+      cdinfo.revision = -2;
+      display.cddb_lock = 0;
+
+#ifdef DEBUG3
+      g_print("Server returned %d\n", tmpinfo.cddbd_stat );
+#endif
+
+      if( display.plabel != NULL )
+	{
+	  sprintf( buffer, "Server: %s", tmpinfo.line );
+	  gtk_label_set (GTK_LABEL (display.plabel), buffer );
+	}
+
+      button = gtk_button_new_with_label ("OK");
+      gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+                                 GTK_SIGNAL_FUNC(gtk_widget_destroy),
+                                 GTK_OBJECT (display.progress));
+      GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+      gtk_box_pack_start (GTK_BOX (GTK_DIALOG (display.progress)->action_area),
+                          button, TRUE, TRUE, 0);
+      gtk_widget_grab_default (button);
+      gtk_widget_show (button);
+
+      break;
+    }
+}
+
+
+/* -----------------------------------------------------------------------
+   Get the current status of the cdrom and fill in the display info
+
+   return -1 = error writing
+   ----------------------------------------------------------------------- */
+int cdrom_status()
+{
+  /* Get the status of the cd */
+  cmnd[0] = CD_STATUS;
+  cmnd[1] = 0;
+  if( write( cd_fd, &cmnd, 2 ) < 0 )
+    {
+      perror("write to cd_control error");
+      return(-1);
+    }
+
+  return 0;
+}
+
+
+/* -----------------------------------------------------------------------
+   Play a track
+   ----------------------------------------------------------------------- */
+void play_track( int track )
+{
+  /* Start Playing right away */
+  cmnd[0] = CD_PLAY;
+  cmnd[1] = track;
+  if( write( cd_fd, &cmnd, 2 ) < 0 )
+    {
+      perror("write to cd_control error");
+    }
+}
+
+
+/* -----------------------------------------------------------------------
+   Play the next track
+   ----------------------------------------------------------------------- */
+void play_next()
+{
+  cmnd[0] = CD_PLAY;
+  cmnd[1] = display.track == cdinfo.tochdr.cdth_trk1 ? display.track = cdinfo.tochdr.cdth_trk0 : ++display.track;
+
+  if( write( cd_fd, &cmnd, 2 ) < 0 )
+    {
+      perror("write to cd_control error");
+    }
+}
+
+
+/* -----------------------------------------------------------------------
+   Play the previous track
+   ----------------------------------------------------------------------- */
+void play_previous()
+{
+  cmnd[0] = CD_PLAY;
+  cmnd[1] = display.track == cdinfo.tochdr.cdth_trk0 ? display.track = cdinfo.tochdr.cdth_trk1 : --display.track;
+
+  if( write( cd_fd, &cmnd, 2 ) < 0 )
+    {
+      perror("write to cd_control error");
+    }
+}
+
+
+/* -----------------------------------------------------------------------
+   Eject the cd tray if we are currently playing, otherwise start playing.
+   
+   This should really be seperated into 2 pieces of code for more positive
+   control over the cdrom.
+   ----------------------------------------------------------------------- */
+void eject_cdrom()
+{
+  cmnd[0] = CD_EJECT;
+  cmnd[1] = 0;
+
+  if( write( cd_fd, &cmnd, 2 ) < 0 )
+    {
+      perror("write to cd_control error");
+    }
+}
+
+
+/* -----------------------------------------------------------------------
+   Pause the cdrom
+   ----------------------------------------------------------------------- */
+void pause_cdrom()
+{
+  cmnd[0] = CD_PAUSE;
+  cmnd[1] = 0;  
+
+  if( write( cd_fd, &cmnd, 2 ) < 0 )
+    {
+      perror("write to cd_control error");
+    }
+}
+
+
+/* -----------------------------------------------------------------------
+   Resume playing the cdrom
+   ----------------------------------------------------------------------- */
+void resume_cdrom()
+{
+  cmnd[0] = CD_RESUME;
+  cmnd[1] = 0;
+
+  if( write( cd_fd, &cmnd, 2 ) < 0 )
+    {
+      perror("write to cd_control error");
+    }
+}
+
+
+/* -----------------------------------------------------------------------
+   Change the volume setting
+
+   amount is +/- amount to adjust by
+   ----------------------------------------------------------------------- */
+void set_vol( int amount )
+{
+  /* Limit the volume setting to 0 to 255 */
+  cdinfo.volume += amount;
+  cdinfo.volume = cdinfo.volume < 0 ? 0 : cdinfo.volume > 255 ? 255 : cdinfo.volume;
+
+  cmnd[0] = CD_VOLUME;
+  cmnd[1] = (unsigned char) cdinfo.volume;
+
+  if( write( cd_fd, &cmnd, 2 ) < 0 )
+    {
+      perror("write to cd_control error");
+    }
+}
+
+
+/* -----------------------------------------------------------------------
+   Stop playing the cdrom
+   ----------------------------------------------------------------------- */
+void stop_cdrom()
+{
+  cmnd[0] = CD_STOP;
+  cmnd[1] = 0;
+
+  if( write( cd_fd, &cmnd, 2 ) < 0 )
+    {
+      perror("write to cd_control error");
+    }
+}
+
+
+/* -----------------------------------------------------------------------
+   Set the Eject CD on exit state
+   ----------------------------------------------------------------------- */
+void set_eject( int state )
+{
+  cmnd[0] = CD_SET_EJECT;
+  cmnd[1] = state;
+
+  if( write( cd_fd, &cmnd, 2 ) < 0 )
+    {
+      perror("write to cd_control error");
+    }
+}
diff --git a/xfreecd.gif b/xfreecd.gif
Binary files differ.
diff --git a/xfreecd.h b/xfreecd.h
@@ -0,0 +1,34 @@
+/* ------------------------------------------------------------------------
+   xfreecd include file for XfreeCD
+
+   Copyright 1998 by Brian C. Lane
+   nexus@tatoosh.com
+   http://www.tatoosh.com/nexus
+
+   ------------------------------------------------------------------------ */
+#define DEFAULT_CDDB_PATH "~/.cddb"
+#define DEFAULT_SERVER    "cddb.cddb.com"
+#define DEFAULT_DEVICE    "/dev/cdrom"
+#define DEFAULT_TO_CDDBD  "xmcd-cddb@amb.org"
+#define MAIL_BINARY       "mail"
+
+
+struct SITE {
+  char *name;
+  int  port;
+  struct SITE *next;
+};
+
+struct CONFIG {
+  char   *device;               /* CD device to use */
+  char   *local_cddb;
+  char   *current;              /* Current server name */
+  char   *to_cddbd;             /* Server to send to */
+  struct SITE *server;
+  short  done_eject;            /* Eject when play is finished */
+  short  exit_eject;            /* Eject on Exit when not playing */
+  short  startup;               /* What should we do at startup? See STARTUP_* */
+  short  cddb;                  /* Is cddb support enabled? */
+  short  changer;               /* Is IDE CD changer support enabled? */
+  short  saved;                 /* Saved state. 1 = saved, 0 = needs to be saved */
+};
diff --git a/xfreecd.lsm b/xfreecd.lsm
@@ -0,0 +1,21 @@
+
+Begin3
+Title:          XfreeCD
+Version:        0.7.8
+Entered-date:   02DEC98
+Description:    XfreeCD is a CD player for X written with GTK+
+		It supports CDDB database info, and can submit new CD
+		info to the CDDB database.
+Keywords:       XfreeCD,CD player,Audio,CDROM,sound,X,GTK+
+Author:         nexus@tatoosh.com (Brian Lane)
+Maintained-by:  nexus@tatoosh.com (Brian Lane)
+Primary-site:   ftp.tatoosh.com /linux
+		669 xfreecd-0.7.8.lsm
+		120464 xfreecd-0.7.8.tar.gz
+		54867 xfreecd-0.7.8-1.i386.rpm
+		121588 xfreecd-0.7.8-1.src.rpm
+Alternate-site: sunsite.unc.edu /pub/Linux/X11/utils
+Original-site:  
+Platforms:      GTK+ v1.0.2 or later
+Copying-policy: GPL
+End
diff --git a/xfreecd.sig b/xfreecd.sig
Binary files differ.
diff --git a/xfreecd.spec b/xfreecd.spec
@@ -0,0 +1,36 @@
+Summary: Xfreecd, a CD player with CDDB features
+Name: xfreecd
+Version: 0.7.8
+Release: 1
+Copyright: GPL
+Group: X11/Utilities
+Source: http://www.tatoosh.com/nexus/linux/xfreecd-0.7.8.tar.gz
+URL: http://www.tatoosh.com/nexus/xfreecd.shtml
+Packager: nexus@tatoosh.com
+Icon: xfreecd.gif
+Prefix: /usr/local
+Buildroot: /var/tmp/xfreecd-0.7.8
+Requires: libm.so.5
+
+%description
+  XfreeCD is a X windows program written using GTK+ that looks like the
+frontpanel of a cd player. It also supports the CDDB database of CD track
+information, and is certified for submitting new CD information to the
+database. At 137x90 it takes up a small amount of screen space.
+
+%prep
+%setup
+
+%build
+make
+
+%install
+install -d -m 755 -o 0 -g 0 $RPM_BUILD_ROOT/usr/local/bin/
+install -s -m 755 -o 0 -g 0 xfreecd $RPM_BUILD_ROOT/usr/local/bin/
+install -d -m 755 -o 0 -g 0 $RPM_BUILD_ROOT/etc/X11/wmconfig/
+install -m 644 -o 0 -g 0 xfreecd.wmconfig $RPM_BUILD_ROOT/etc/X11/wmconfig/xfreecd
+
+%files
+%doc COPYING README HISTORY xfreecd.xpm xfreecd.gif
+/usr/local/bin/xfreecd
+/etc/X11/wmconfig/xfreecd
diff --git a/xfreecd.wmconfig b/xfreecd.wmconfig
@@ -0,0 +1,4 @@
+xfreecd name "XFreeCD"
+xfreecd description "CD Player"
+xfreecd exec "xfreecd &"
+xfreecd group Utilities/Sound
diff --git a/xfreecd.xpm b/xfreecd.xpm
@@ -0,0 +1,341 @@
+/* XPM */
+static char * xfreecd_xpm[] = {
+"48 48 290 2",
+"  	c None",
+". 	c #50E5F8",
+"+ 	c #56E5F8",
+"@ 	c #61E6F8",
+"# 	c #65E5F8",
+"$ 	c #6BE5F8",
+"% 	c #6DE5F8",
+"& 	c #64E5F8",
+"* 	c #59E5F8",
+"= 	c #47E4F8",
+"- 	c #3FE4F8",
+"; 	c #3CE4F7",
+"> 	c #38E3F7",
+", 	c #35E3F7",
+"' 	c #24E1F7",
+") 	c #1FE1F7",
+"! 	c #1CE1F7",
+"~ 	c #19E1F7",
+"{ 	c #18E1F7",
+"] 	c #63E6F8",
+"^ 	c #71E6F8",
+"/ 	c #78E6F8",
+"( 	c #9DE7F8",
+"_ 	c #A3E8F8",
+": 	c #76E6F8",
+"< 	c #68E5F8",
+"[ 	c #5BE5F8",
+"} 	c #45E4F8",
+"| 	c #3EE4F8",
+"1 	c #3AE4F7",
+"2 	c #37E3F7",
+"3 	c #33E3F7",
+"4 	c #25E1F7",
+"5 	c #1BE1F7",
+"6 	c #8AE6F8",
+"7 	c #8EE7F8",
+"8 	c #9AE7F8",
+"9 	c #A0E8F8",
+"0 	c #99E7F8",
+"a 	c #8AE7F8",
+"b 	c #86E6F8",
+"c 	c #4BE5F8",
+"d 	c #41E4F8",
+"e 	c #20E1F7",
+"f 	c #A7E8F8",
+"g 	c #BEEBF9",
+"h 	c #C8EDF9",
+"i 	c #BCEBF9",
+"j 	c #A4E8F8",
+"k 	c #74E6F8",
+"l 	c #60E5F8",
+"m 	c #51E5F8",
+"n 	c #44E4F8",
+"o 	c #3DE4F7",
+"p 	c #39E3F7",
+"q 	c #1AE1F7",
+"r 	c #DFF0FA",
+"s 	c #EFF5FB",
+"t 	c #97E7F8",
+"u 	c #66E5F8",
+"v 	c #55E5F8",
+"w 	c #36E3F7",
+"x 	c #32E3F7",
+"y 	c #9FE8F8",
+"z 	c #C7EDF9",
+"A 	c #FFFEFE",
+"B 	c #9DE8F8",
+"C 	c #48E4F8",
+"D 	c #2EE2F7",
+"E 	c #31E3F7",
+"F 	c #2CE2F7",
+"G 	c #26E2F7",
+"H 	c #2FE2F7",
+"I 	c #2AE2F7",
+"J 	c #24E2F7",
+"K 	c #27E2F7",
+"L 	c #22E1F7",
+"M 	c #29E2F7",
+"N 	c #3FE4F7",
+"O 	c #34E3F7",
+"P 	c #2FE3F7",
+"Q 	c #2BE2F7",
+"R 	c #25E2F7",
+"S 	c #21E1F7",
+"T 	c #1DE1F7",
+"U 	c #22E2F7",
+"V 	c #1EE1F7",
+"W 	c #23E2F7",
+"X 	c #2DE2F7",
+"Y 	c #32E2F7",
+"Z 	c #30E3F7",
+"` 	c #28E2F7",
+" .	c #30E2F7",
+"..	c #45E4F7",
+"+.	c #2CE1F7",
+"@.	c #2BE1F7",
+"#.	c #4AF1FA",
+"$.	c #000000",
+"%.	c #17DFF4",
+"&.	c #17DFF5",
+"*.	c #17E0F6",
+"=.	c #14C7DA",
+"-.	c #0A646D",
+";.	c #0C747F",
+">.	c #17DAF0",
+",.	c #17DDF3",
+"'.	c #17DEF4",
+").	c #32E1F5",
+"!.	c #30E0F5",
+"~.	c #1F281B",
+"{.	c #17DDF2",
+"].	c #11AABC",
+"^.	c #17DCF2",
+"/.	c #14C4D8",
+"(.	c #11ACBD",
+"_.	c #77F5F9",
+":.	c #2ADEF3",
+"<.	c #1E8087",
+"[.	c #150B00",
+"}.	c #1A0E00",
+"|.	c #17DBF1",
+"1.	c #109CAB",
+"2.	c #0F909F",
+"3.	c #17D9EF",
+"4.	c #11A9BA",
+"5.	c #02181B",
+"6.	c #074850",
+"7.	c #0F92A0",
+"8.	c #1D1000",
+"9.	c #2297A0",
+"0.	c #37DDF0",
+"a.	c #21281B",
+"b.	c #241500",
+"c.	c #17D9EE",
+"d.	c #16D5EA",
+"e.	c #15CADD",
+"f.	c #042F33",
+"g.	c #16D6EB",
+"h.	c #043034",
+"i.	c #07484F",
+"j.	c #0F909E",
+"k.	c #1C0F00",
+"l.	c #120A00",
+"m.	c #33DAED",
+"n.	c #180E00",
+"o.	c #201200",
+"p.	c #16D4E9",
+"q.	c #16CFE3",
+"r.	c #16D2E7",
+"s.	c #07464D",
+"t.	c #0E8D9B",
+"u.	c #36D7E9",
+"v.	c #372100",
+"w.	c #16D1E5",
+"x.	c #15C6D9",
+"y.	c #010A0B",
+"z.	c #15CDE1",
+"A.	c #07454B",
+"B.	c #16D0E4",
+"C.	c #2ED2E4",
+"D.	c #29D1E3",
+"E.	c #142019",
+"F.	c #1C1706",
+"G.	c #091D13",
+"H.	c #17CCDF",
+"I.	c #15C8DB",
+"J.	c #14C3D6",
+"K.	c #04292D",
+"L.	c #15C5D8",
+"M.	c #074349",
+"N.	c #15CADE",
+"O.	c #12B3C5",
+"P.	c #30CDDE",
+"Q.	c #246462",
+"R.	c #091D17",
+"S.	c #1DCBDA",
+"T.	c #0B6C76",
+"U.	c #08525A",
+"V.	c #14C1D4",
+"W.	c #14BFD2",
+"X.	c #042A2E",
+"Y.	c #063F45",
+"Z.	c #12AEBF",
+"`.	c #042B30",
+" +	c #064148",
+".+	c #11AEC0",
+"++	c #021618",
+"@+	c #02090B",
+"#+	c #09297B",
+"$+	c #16C1D4",
+"%+	c #0D7E8A",
+"&+	c #050100",
+"*+	c #1C7B81",
+"=+	c #08020D",
+"-+	c #06000B",
+";+	c #100C03",
+">+	c #13B7C9",
+",+	c #14BCCF",
+"'+	c #13BACC",
+")+	c #10A4B4",
+"!+	c #021517",
+"~+	c #031F22",
+"{+	c #11A8B9",
+"]+	c #063F46",
+"^+	c #0D7F8C",
+"/+	c #14BED1",
+"(+	c #14BDD0",
+"_+	c #000005",
+":+	c #171C05",
+"<+	c #101608",
+"[+	c #178282",
+"}+	c #114D41",
+"|+	c #070E00",
+"1+	c #040008",
+"2+	c #110E05",
+"3+	c #14BBCE",
+"4+	c #13B8CA",
+"5+	c #13B6C8",
+"6+	c #13B4C6",
+"7+	c #13B4C5",
+"8+	c #10A0AF",
+"9+	c #0D8693",
+"0+	c #11A2B1",
+"a+	c #13B9CB",
+"b+	c #10A5B5",
+"c+	c #0E919F",
+"d+	c #16B5C7",
+"e+	c #28BCC6",
+"f+	c #1CB7C3",
+"g+	c #1AB4C0",
+"h+	c #1AB2BE",
+"i+	c #19A7B0",
+"j+	c #12AFC1",
+"k+	c #13B5C7",
+"l+	c #13B3C4",
+"m+	c #12B0C1",
+"n+	c #12AFC0",
+"o+	c #13B2C3",
+"p+	c #22B6C4",
+"q+	c #1BB5C0",
+"r+	c #19B1BE",
+"s+	c #18AFBC",
+"t+	c #17ACB9",
+"u+	c #17ABB8",
+"v+	c #12ADBE",
+"w+	c #11A5B5",
+"x+	c #11A7B8",
+"y+	c #12B1C2",
+"z+	c #21B2C0",
+"A+	c #1DB3BD",
+"B+	c #1AB1BC",
+"C+	c #18AEBA",
+"D+	c #14AAB9",
+"E+	c #13A7B7",
+"F+	c #14A7B5",
+"G+	c #148A92",
+"H+	c #12ACBD",
+"I+	c #17ADBE",
+"J+	c #16ACBF",
+"K+	c #1CB3BC",
+"L+	c #1AAFBA",
+"M+	c #16ABB9",
+"N+	c #13A8B8",
+"O+	c #11A5B6",
+"P+	c #13A5B4",
+"Q+	c #16A5B2",
+"R+	c #0F95A3",
+"S+	c #11A6B6",
+"T+	c #21B0BE",
+"U+	c #1DB3BC",
+"V+	c #1AB0BB",
+"W+	c #18ADB9",
+"X+	c #17A8B4",
+"Y+	c #148083",
+"Z+	c #14C3D7",
+"`+	c #0F8E9B",
+" @	c #1DB2C3",
+".@	c #19B2BF",
+"+@	c #1BB2BD",
+"@@	c #19B0BC",
+"#@	c #18AEBB",
+"$@	c #18ACB8",
+"%@	c #1AA7AF",
+"&@	c #1AB3C7",
+"*@	c #1EB8C2",
+"=@	c #1AB3BF",
+"-@	c #1AB1BD",
+";@	c #1BB2BC",
+">@	c #1EB3BB",
+",@	c #0C717C",
+"                                                                                                ",
+"                                                                                                ",
+"                                                                                                ",
+"                                                                                                ",
+"                . + @ # $ % $ & * . = - ; > ,         ' ) ! ~ { { { { { { { { {                 ",
+"                  ] ^ / ( _ ( : < [ . } | 1 2 3       4 ) 5 ~ { { { { { { { {                   ",
+"                  % 6 7 8 9 0 a b < * c d ; > ,         e 5 ~ { { { { { { { {                   ",
+"                  / 7 f g h i j a k l m n o p ,         ) q { { { { { { { {                     ",
+"                    8 g r s r i t 8 u v = | 1 w x       e q { { { { { { { {                     ",
+"                    y z s A s z B 9 < + C - 1 w x         ~ { { { { { { { {                     ",
+"                    t i r s r i t 8 u v = | 1 w x D       { { { { { { { {                       ",
+"                      j i z i j a k l m n o p , x D         { { { { { { {                       ",
+"                      a t B t a b < * c d ; > , E F G       { { { { { {                         ",
+"                        8 9 8 k < [ . } | 1 2 3 H I J         { { { { {                         ",
+"                        u < u l * . = - ; > , x F K L         { { { {                           ",
+"                        v + v m c } - ; p w 3 D M J ) 5       { { { {                           ",
+"                          C = n d | N p 2 O P Q R S T ~         { { {                           ",
+"                          - | o ; 1 > w 3 P Q G U V 5 { {       { {                             ",
+"                            1 p > 2 , x P Q K W ) ! ~ { {         {                             ",
+"                            w , , 3 E X I Y W ) ! ~ { { { {                                     ",
+"                              x Z D Q `  ...+.! q { { { { {                                     ",
+"                              F I ` G W e @.! ~ { { { { { {                                     ",
+"                              G J U e ) T 5 ~ { { { { { { { {                                   ",
+"                                ) V ! 5 ~ { { #.{ { { { { { {                                   ",
+"                                5 q ~ { { { { { { { { { { { { {                                 ",
+"                                  { { { { { { { { { { { { { { {                                 ",
+"        $.$.$.                    %.&.&.*.*.*.*.{ { { { { =.-.$.;.$.$.    $.$.$.  $.$.          ",
+"      $.$.$.$.                    >.,.'.'.'.&.&.&.&.&.).!.~.$.$.{.$.$.    $.$.$.  $.$.$.        ",
+"      $.$.$.                        ].^.^.,./.(./.(._.:.<.[.}.$.|.  $.    $.$.$.  $.$.$.$.      ",
+"    $.$.$.$.$.  $.$.  $.$.  1.$.$.  $.2.3.4.5.6.7.8.9.0.a.b.[.8.c.d.      $.$.$.  $.$.$.$.      ",
+"      $.$.      $.$.  $.$.e.f.$.$.  $.$.g.h.$.i.j.k.l.m.n.o.l.k.d.p.      $.$.$.  $.$.$.$.      ",
+"      $.$.      $.$.      q.$.$.$.  $.$.r.$.$.s.t.8.[.u.o.v.[.8.w.q.x.    $.$.$.  $.$.$.$.      ",
+"      $.$.      $.$.      e.$.$.y.      z.$.$.A.q.B.C.D.E.[.F.G.H.e.I.    $.$.$.  $.$.$.$.      ",
+"      $.$.      $.$.    J./.$.$.K.      L.$.$.M.N.N.O.P.Q.8.G.R.S./.T.U.  $.$.$.  $.$.$.$.      ",
+"      $.$.      $.$.    V.W.X.$.Y.    $.Z.`.$. +/./. +/..+++@+#+$+%+&+*+  =+-+=+  ;+&+$.        ",
+"      $.$.      $.$.  >+,+'+)+K.!+~+$.    {+X.!+]+]+^+/+(+{+X._+)+:+<+[+}+|+$.$.$.$.1+2+        ",
+"                      3+4+5+6+7+8+9+      0+a+b+c+'+'+a+4+>+5+d+e+f+g+h+i+                      ",
+"                    j+a+k+l+m+n+n+m+        6+k+k+k+6+6+7+l+o+p+q+r+s+t+u+                      ",
+"                    3+>+l+m+n+v+v+Z.w+      x+o+o+o+y+y+m+n+z+A+B+C+D+E+F+G+                    ",
+"                  v+3+5+l+m+Z.H+H+H+v+        m+m+n+n+n+Z.I+J+K+L+M+N+O+P+Q+                    ",
+"                  V.,+4+7+y+n+Z.v+Z.Z.R+      S+m+n+n+n+Z.T+H+U+V+W+D+E+F+X+Y+                  ",
+"                n+Z+/+'+5+7+o+y+m+m+y+y+      `+o+o+y+m+m+ @n+.@+@@@#@t+t+$@%@                  ",
+"                I.x.V.(+'+>+5+6+6+6+6+k+7.      y+6+6+7+l+&@l+o+*@q+g+=@-@;@>@,@                ",
+"                                                                                                ",
+"                                                                                                ",
+"                                                                                                ",
+"                                                                                                ",
+"                                                                                                "};
diff --git a/xpm_button.c b/xpm_button.c
@@ -0,0 +1,67 @@
+/* -----------------------------------------------------------------------
+   xpm button routines for XfreeCD
+   
+   Copyright 1998 by Brian C. Lane
+   ----------------------------------------------------------------------- */
+#include <gtk/gtk.h>
+#include "xpm_button.h"
+
+/* Create a button with 2 xpm pixmaps for pressed and unpressed states */
+GtkWidget *xpm_button( GtkWidget *parent, struct _pbutton *pb )
+{
+  GtkWidget	*event_box;
+  GtkWidget	*hbox;
+  GtkStyle	*style;
+
+  /* get style of button.. I assume it's to get the background color.
+   * if someone knows the real reason, please enlighten me. */
+  style = gtk_widget_get_style( parent );
+
+  /* Make a hbox to hold the image */
+  hbox = gtk_hbox_new( FALSE, 0 );
+  gtk_container_border_width( GTK_CONTAINER( hbox ), 0 );
+
+  /* now on to the xpm stuff.. load xpm */
+  pb->image.up_pixmap = gdk_pixmap_create_from_xpm_d (parent->window,
+                                       &pb->image.up_mask,
+                                       &style->bg[GTK_STATE_NORMAL],
+                                       (gchar **) pb->up_xpm);
+
+  pb->image.dn_pixmap = gdk_pixmap_create_from_xpm_d (parent->window,
+                                       &pb->image.dn_mask,
+                                       &style->bg[GTK_STATE_NORMAL],
+                                       (gchar **) pb->dn_xpm);
+
+  /* Start with the up image */
+  pb->wid = gtk_pixmap_new (pb->image.up_pixmap, pb->image.up_mask);
+
+  gtk_box_pack_start (GTK_BOX (hbox), pb->wid, FALSE, FALSE, 0);
+
+  gtk_widget_show(pb->wid);
+     
+  /* Create the event box that will hold the image and callbacks */
+  event_box = gtk_event_box_new();
+/*  gtk_container_add (GTK_CONTAINER(parent), event_box);          
+ * gtk_widget_show (event_box);
+ */
+
+  /* Add the box containing the image to the button */
+  gtk_container_add (GTK_CONTAINER (event_box), hbox);  
+
+  /* Make sure that the image is visible */
+  gtk_widget_show( hbox );
+
+  /* Set the clipping size (this should come from the pixmap somehow) */
+/*  gtk_widget_set_usize (hbox, 29, 30); */
+
+  /* Add the callback functions */
+  gtk_widget_set_events( event_box, GDK_BUTTON_PRESS_MASK |
+                                    GDK_BUTTON_RELEASE_MASK );
+
+  gtk_signal_connect (GTK_OBJECT (event_box), "button_press_event",
+                      GTK_SIGNAL_FUNC (pb->press), NULL );
+  gtk_signal_connect (GTK_OBJECT (event_box), "button_release_event",
+                      GTK_SIGNAL_FUNC (pb->release), NULL );
+
+  return( event_box );
+}
diff --git a/xpm_button.h b/xpm_button.h
@@ -0,0 +1,24 @@
+/* XPM Pushbutton structures */
+
+struct _bstate
+{
+  GdkPixmap	*up_pixmap;
+  GdkBitmap	*up_mask;
+  GdkPixmap	*dn_pixmap;
+  GdkBitmap	*dn_mask;
+};
+
+
+struct _pbutton
+{
+  GtkWidget		*wid;		/* Button's Widget ID		*/
+  struct _bstate	image;		/* up and down images		*/
+  int			timer;
+  void (*press)   (GtkWidget *widget, GdkEventButton *event);
+  void (*release) (GtkWidget *widget, GdkEventButton *event);
+  void (*clicked) (GtkWidget *widget, GdkEventButton *event);
+  gchar 		*up_xpm;
+  gchar 		*dn_xpm;
+};
+
+GtkWidget *xpm_button( GtkWidget *parent, struct _pbutton *pb );