diff options
author | Matthias Clasen <mclasen@redhat.com> | 2010-10-18 17:17:24 -0400 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2010-10-19 18:22:08 +0200 |
commit | 921f069269e27bb2505f569b0d655b96aca54cad (patch) | |
tree | 38c86a57b34fb50e52e1e9cf1b91702036383f8a /docs | |
parent | 6e4643de140d07b0470a29e9f28b06634f09f3c1 (diff) | |
download | gtk+-921f069269e27bb2505f569b0d655b96aca54cad.tar.gz |
Remove the outdated faq
It mainly contains information that is already covered in the
API docs, or is outdated, or refers to no longer existing widgets.
Diffstat (limited to 'docs')
-rw-r--r-- | docs/Makefile.am | 2 | ||||
-rw-r--r-- | docs/faq/Makefile.am | 44 | ||||
-rw-r--r-- | docs/faq/gtk-faq.sgml | 3637 |
3 files changed, 1 insertions, 3682 deletions
diff --git a/docs/Makefile.am b/docs/Makefile.am index 41206ac29e..9cbdb39504 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -1,7 +1,7 @@ ## Process this file with automake to produce Makefile.in include $(top_srcdir)/Makefile.decl -SUBDIRS = faq reference tools +SUBDIRS = reference tools EXTRA_DIST += \ CODING-STYLE \ diff --git a/docs/faq/Makefile.am b/docs/faq/Makefile.am deleted file mode 100644 index f53c96c5dd..0000000000 --- a/docs/faq/Makefile.am +++ /dev/null @@ -1,44 +0,0 @@ -include $(top_srcdir)/Makefile.decl - -EXTRA_DIST += \ - gtk-faq.sgml - -if HAVE_DOCBOOK -html: - if test -w $(srcdir); then \ - (cd $(srcdir); \ - db2html gtk-faq.sgml; \ - test -d html && rm -r html; \ - mv gtk-faq html); \ - fi - -pdf: - if test -w $(srcdir); then \ - (cd $(srcdir); db2pdf gtk-faq.sgml); \ - fi - -all-local: html - -dist-hook: html - cp -Rp $(srcdir)/html $(distdir) -else -html: - echo "***" - echo "*** Warning: FAQ not built" - echo "***" - -pdf: - echo "***" - echo "*** Warning: FAQ not built" - echo "***" - -dist-hook: - echo "***" - echo "*** Warning: FAQ not built" - echo "*** DISTRIBUTION IS INCOMPLETE" - echo "***" -endif - -.PHONY: html - --include $(top_srcdir)/git.mk diff --git a/docs/faq/gtk-faq.sgml b/docs/faq/gtk-faq.sgml deleted file mode 100644 index b896e91006..0000000000 --- a/docs/faq/gtk-faq.sgml +++ /dev/null @@ -1,3637 +0,0 @@ -<!doctype book PUBLIC "-//OASIS//DTD DocBook V3.1//EN" []> -<book> - -<bookinfo> - <date>January 14th 2004</date> - <title>GTK+ FAQ</title> - <authorgroup> - <author> -<firstname>Tony</firstname> -<surname>Gale</surname> - </author> - <author> -<firstname>Shawn</firstname> -<surname>Amundson</surname> - </author> - <author> -<firstname>Emmanuel</firstname> -<surname>Deloget</surname> - </author> - </authorgroup> - <abstract> - <para> This document is intended to answer questions that are - likely to be frequently asked by programmers using GTK+ or - people who are just looking at using GTK+. </para> - <para><emphasis>Note: </emphasis> This FAQ mainly covers GTK+ 1.2. - Where the text covers GTK+ 2.x this will be indicated</para> - </abstract> -</bookinfo> - -<toc></toc> - -<!-- ***************************************************************** --> -<chapter> -<title>General Information</title> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>Note: This FAQ is undergoing conversion to GTK+ 2.x</title> -<para>This FAQ is undergoing conversion to GTK+ 2.x. -Where the text covers GTK+ 2.x this will be indicated by prefixing the -text with: <emphasis>[GTK+ 2.x]</emphasis>. Where this is not -indicated, the text has not yet been updated from GTK+ 1.2 and may -not be totally correct. -</para> -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>Before anything else: the greetings <emphasis>[GTK 2.x]</emphasis></title> -<para>The FAQ authors want to thank:</para> -<itemizedlist spacing=Compact> -<listitem> -<simpara>Havoc Pennington</simpara> -</listitem> -<listitem> -<simpara>Erik Mouw</simpara> -</listitem> -<listitem> -<simpara>Owen Taylor</simpara> -</listitem> -<listitem> -<simpara>Tim Janik</simpara> -</listitem> -<listitem> -<simpara>Thomas Mailund Jensen</simpara> -</listitem> -<listitem> -<simpara>Joe Pfeiffer</simpara> -</listitem> -<listitem> -<simpara>Andy Kahn</simpara> -</listitem> -<listitem> -<simpara>Federico Mena Quntero</simpara> -</listitem> -<listitem> -<simpara>Damon Chaplin</simpara> -</listitem> -<listitem> -<simpara>and all the members of the GTK+ lists</simpara> -</listitem></itemizedlist> -<para> If we forgot you, please email us! Thanks again (I know, -it's really short :) </para> -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>Authors <emphasis>[GTK 2.x]</emphasis></title> - -<para>The original authors of GTK+ were:</para> - -<itemizedlist spacing=Compact> -<listitem> -<simpara>Peter Mattis</simpara> -</listitem> -<listitem> -<simpara>Spencer Kimball</simpara> -</listitem> -<listitem> -<simpara>Josh MacDonald</simpara> -</listitem> -</itemizedlist> - -<para>Since then, much has been added by others. Please see the -AUTHORS file in the distribution for the GTK+ Team. The people currently -contributing the most code to GTK+ are (in no particular order):</para> - - -<itemizedlist spacing=Compact> -<listitem> -<simpara>Owen Taylor</simpara> -</listitem> -<listitem> -<simpara>Matthias Clasen</simpara> -</listitem> -<listitem> -<simpara>Federico Mena Quintero</simpara> -</listitem> -<listitem> -<simpara>Soeren Sandmann</simpara> -</listitem> -<listitem> -<simpara>Padraig O'Briain</simpara> -</listitem> -<listitem> -<simpara>Manish Singh</simpara> -</listitem> -<listitem> -<simpara>Kristian Rietveld</simpara> -</listitem> -<listitem> -<simpara>Tor Lillqvist</simpara> -</listitem> -</itemizedlist> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>What is GTK+? <emphasis>[GTK 2.x]</emphasis></title> - -<para>GTK+ is a multi-platform toolkit for creating graphical user -interfaces, originally designed with -the general look and feel of Motif. In reality, it looks much -better than Motif. It contains common and complex widgets, such as -file selection, and color selection widgets.</para> - -<para>GTK+ was initially developed as a widget set for the GIMP (GNU Image -Manipulation Program). It has grown extensively since then, and is today -used by a large number of applications, and is the toolkit used by the -<ulink url="http://www.gnome.org/">GNOME</ulink> desktop project.</para> - -<para>GTK+ is free software and part of the GNU Project. However, the -licensing terms for GTK+, the GNU LGPL, allow it to be used by all developers, -including those developing proprietary software, without any license fees -or royalties.</para> - -<para>GTK+ has been designed from the ground up to support a range of -<ulink url="http://www.gtk.org/bindings.html"> -language bindings</ulink>, not only C/C++. Using GTK+ from languages -such as Perl and Python (especially in combination with the Glade GUI -builder) provides an effective method of rapid application -development..</para> -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>What is the + in GTK+? <emphasis>[GTK 2.x]</emphasis></title> - -<para>Peter Mattis informed the gtk mailing list that:</para> - -<para><quote>I originally wrote gtk which included the three -libraries, libglib, libgdk and libgtk. It featured a flat -widget hierarchy. That is, you couldn't derive a new widget -from an existing one. And it contained a more standard -callback mechanism instead of the signal mechanism now present -in gtk+. The + was added to distinguish between the original -version of gtk and the new version. You can think of it as -being an enhancement to the original gtk that adds object -oriented features.</quote></para> - -<para>Although much has changed with GTK+, and Peter, Spencer and Josh -don't have any direct involvement these days, the name is kept to keep -a link with the heritage of GTK+.</para> - -<para>GTK+ is now additionally based upon the Pango and ATK -libraries, that provide text layout and rendering and accessibility -interfaces.</para> -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>Does the G in GTK+, GDK and GLib stand for? <emphasis>[GTK 2.x]</emphasis></title> - -<para>GTK+ == The GIMP Toolkit</para> -<para>GDK == GTK+ Drawing Kit</para> -<para>GLib == G Library</para> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>Where is the documentation for GTK+? <emphasis>[GTK 2.x]</emphasis></title> - -<para>In the GTK+ distribution's doc/ directory you will find -the API Reference for both GTK and GDK, this FAQ and the -GTK Tutorial.</para> - -<para>In addition, you can find links to HTML versions of -these documents by going to <ulink url="http://www.gtk.org/"> -http://www.gtk.org/</ulink>. A -packaged version of the GTK Tutorial, with SGML, HTML, -Postscript, DVI and text versions can be found in <ulink -url="ftp://ftp.gtk.org/pub/gtk/tutorial"> -ftp://ftp.gtk.org/pub/gtk/tutorial -</ulink></para> - -<para>There are now a few books available that deal with -programming GTK+, GDK and GNOME. Unfortunately, they -currently are all based upon GTK+ 1.x:</para> - -<itemizedlist> -<listitem><simpara>Eric Harlows book entitled "Developing -Linux Applications with GTK+ and GDK". The ISBN is -0-7357-0021-4</simpara> -</listitem> -<listitem><simpara>The example code from Eric's book is -available on-line at <ulink -url="http://www.bcpl.net/~eharlow/book"> -http://www.bcpl.net/~eharlow/book</ulink></simpara> -</listitem> -<listitem><simpara>Havoc Pennington has released a book called -"GTK+/GNOME Application Development". The ISBN is -0-7357-0078-8</simpara> -<simpara>The free version of the book lives here: <ulink -url="http://developer.gnome.org/doc/GGAD/"> -http://developer.gnome.org/doc/GGAD/ -</ulink></simpara> -<simpara>And Havoc maintains information about it and -errata here: <ulink -url="http://pobox.com/~hp/gnome-app-devel.html"> -http://pobox.com/~hp/gnome-app-devel.html -</ulink></simpara> -</listitem> -<listitem><simpara>"GTK+ Programming in C" by -Syd Logan. ISBN: 0-1301-4264-6</simpara> -</listitem> -<listitem><simpara>"Linux GNOME/GTK+ Programming Bible" by -Arthur Griffith. ISBN: 0-7645-4640-6</simpara> -</listitem> -<listitem><simpara>"Beginning GTK+/GNOME Programming" by -Peter Wright. ISBN: 1-8610-0381-1</simpara> -</listitem> -<listitem><simpara>"Sams Teach Yourself GTK+ Programming -in 21 Days" by Donna Martin -. ISBN: 0-6723-1829-6</simpara> -</listitem> -</itemizedlist> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1 id="faq-MailLists"> -<title>Is there a mailing list (or mailing list archive) for -GTK+? <emphasis>[GTK 2.x]</emphasis></title> - -<para>Information on mailing lists relating to GTK+ can be -found at: <ulink -url="http://www.gtk.org/mailinglists.html"> -http://www.gtk.org/mailinglists.html -</ulink></para> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How to get help with GTK+ <emphasis>[GTK 2.x]</emphasis></title> - -<para>First, make sure your question isn't answered in the -documentation, this FAQ or the tutorial. Done that? You're -sure you've done that, right? In that case, the best place to -post questions is to the GTK+ mailing list.</para> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How to report bugs in GTK+ <emphasis>[GTK 2.x]</emphasis></title> - -<para>Bugs should be reported to the GNOME bug tracking system -(<ulink url="http://bugzilla.gnome.org">http://bugzilla.gnome.org</ulink>). -You will need to enter your email address and receive a password before -you can use the system to register a new bug report.</para> - -<para>There are a number of options to select and boxes to fill in when -submitting a bug report. Please remember that the more information you -give, the easier it will be to track the problem down. Extra information -that may prove useful includes:</para> - -<itemizedlist> -<listitem><simpara> How to reproduce the bug.</simpara> -<simpara>If you can reproduce it with the testgtk program -that is built in the gtk/ subdirectory, that will be most -convenient. Otherwise, please include a complete, short test -program that exhibits the behavior. As a last resort, you can also -provide a pointer to a larger piece of software that can -be downloaded.</simpara> - -<simpara>(Bugs that can be reproduced within the GIMP are -almost as good as bugs that can be reproduced in -testgtk. If you are reporting a bug found with the GIMP, -please include the version number of the GIMP you are -using)</simpara> -</listitem> - -<listitem><simpara> If the bug was a crash, the exact text that was -printed out when the crash occurred. If you can easily reproduce this -crash then running the program under a debugger (e.g. gdb) and getting -a backtrace when the crash occurs is very useful.</simpara> -</listitem> - -<listitem><simpara> Further information such as stack traces -may be useful. If you do send a stack trace, -and the error is an X error, it will be more useful if the stacktrace is -produced running the test program with the <literal>--sync</literal> -command line option.</simpara> -</listitem> -</itemizedlist> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>Is there a Windows version of GTK+? <emphasis>[GTK 2.x]</emphasis></title> - -<para>The Win32 port of GTK+ is maintained concurrently with the Xwindows -version in CVS. As such it is a supported architecture.</para> - -<para>The Win32 port has been predominately done by Tor Lillqvist. Tor -maintains some information on <ulink url="http://www.gimp.org/~tml/gimp/win32/"> -GTK+ and GIMP for Windows</ulink>.</para> - -<para>There is a pre-compiled, easy-to-install version of GTK+ for -windows on the <ulink url="http://www.dropline.net/gtk/"> -Dropline GTK+</ulink> site.</para> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>What applications have been written with GTK+? <emphasis>[GTK 2.x]</emphasis></title> - -<para>The GNOME software map contains a catalogue of software that is -built using GNOME and GTK+. The catalogue is searchable and browsable, so -provides easy access.</para> - -<para>Some of the best known projects utilising GTK+ are:</para> - -<itemizedlist> -<listitem><simpara> GIMP (<ulink -url="http://www.gimp.org/">http://www.gimp.org/</ulink>), an -image manipulation program</simpara> -</listitem> -<listitem><simpara> AbiWord (<ulink -url="http://www.abiword.org/">http://www.abiword.com/</ulink>), -a professional word processor</simpara> -</listitem> -<listitem><simpara> Dia (<ulink -url="http://www.lysator.liu.se/~alla/dia/dia.html"> -http://www.lysator.liu.se/~alla/dia/dia.html</ulink>), -a diagram creation program</simpara> -</listitem> -<listitem><simpara> GnuCash (<ulink -url="http://www.gnucash.org/"> -http://www.gnucash.org/</ulink>), -a personal finance manager</simpara> -</listitem> -<listitem><simpara> Gnumeric (<ulink -url="http://www.gnome.org/projects/gnumeric/"> -http://www.gnome.org/projects/gnumeric/</ulink>), -the GNOME spreadsheet application</simpara> -</listitem> -<listitem><simpara> Glade (<ulink -url="http://glade.gnome.org/">http://glade.gnome.org/</ulink>), a -GTK+ based RAD tool which produces GTK+ and GNOME applications</simpara> -</listitem> -<listitem><simpara> Anjuta (<ulink -url="http://anjuta.sourceforge.net/">http://anjuta.sourceforge.net/</ulink>), -a versatile Integrated Development Environment (IDE) using C and C++ for GTK+ -and GIMP.</simpara> -</listitem> -</itemizedlist> -</sect1> - -</chapter> - -<!-- ***************************************************************** --> -<chapter> -<title>How to find, configure, install, and troubleshoot GTK+</title> - -<!-- ----------------------------------------------------------------- --> - -<sect1 id="faq-Compile"> -<title>What do I need to compile GTK+? <emphasis>[GTK 2.x]</emphasis></title> - -<para>GTK+ is a large package that is dependent on a number of other -tools and libraries. It is recommended that you use precompiled -binary packages for your system if possible</para> - -<para>To compile GTK+ from source you need a C compiler (gcc) and -the X Window System and associated development libraries and packages -on your system.</para> - -<para>You will also need to have installed the tools -and libraries that GTK+ depends upon. These are listed below in the order -in which they need to be installed:</para> - -<itemizedlist spacing=compact> -<listitem><simpara> pkg-config -(<ulink url="http://pkg-config.freedesktop.org/wiki"> -pkg-config Site</ulink>)</simpara> -</listitem> - -<listitem><simpara> GNU make -(<ulink url="http://www.gnu.org/software/make/"> -GNU make Site</ulink>)</simpara> -</listitem> - -<listitem><simpara> JPEG, PNG and TIFF image libraries -(<ulink url="ftp://ftp.gtk.org/pub/gtk/v2.2/dependencies/"> -GTK+ Site</ulink>)</simpara> -</listitem> - -<listitem><simpara> FreeType -(<ulink url="http://www.freetype.org/"> -FreeType Site</ulink>)</simpara> -</listitem> - -<listitem><simpara> fontconfig -(<ulink url="http://www.fontconfig.org/"> -fontconfig Site</ulink>)</simpara> -</listitem> - -<listitem><simpara> GNU libiconv library (if your system doesn't have iconv()) -(<ulink url="http://www.gnu.org/software/libiconv/"> -GNU libiconv Site</ulink>)</simpara> -</listitem> - -<listitem><simpara> GNU gettext (if your system doesn't have gettext()) -(<ulink url="http://www.gnu.org/software/gettext/"> -GTK+ Site</ulink>)</simpara> -</listitem> - -<listitem><simpara> GLib -(<ulink url="ftp://ftp.gtk.org/pub/gtk/v2.2/"> -GTK+ Site</ulink>)</simpara> -</listitem> - -<listitem><simpara> Pango -(<ulink url="ftp://ftp.gtk.org/pub/gtk/v2.2/"> -GTK+ Site</ulink>)</simpara> -</listitem> - -<listitem><simpara> ATK -(<ulink url="ftp://ftp.gtk.org/pub/gtk/v2.2/"> -GTK+ Site</ulink>)</simpara> -</listitem> - -<listitem><simpara> GTK+ -(<ulink url="ftp://ftp.gtk.org/pub/gtk/v2.2/"> -GTK+ Site</ulink>)</simpara> -</listitem> -</itemizedlist> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>Where can I get GTK+? <emphasis>[GTK 2.x]</emphasis></title> - -<para>The canonical site is <ulink -url="ftp://ftp.gtk.org/pub/gtk">ftp://ftp.gtk.org/pub/gtk</ulink>.</para> - -<para>This site tends to get busy around the time of a new -GTK+ release so try and use one of the mirror sites that are -listed in <ulink -url="ftp://ftp.gtk.org/etc/mirrors">ftp://ftp.gtk.org/etc/mirrors -</ulink></para> - -<para>Here's a few mirror sites to get you started:</para> - -<itemizedlist spacing=compact> -<listitem><simpara> Africa - -<ulink url="ftp://ftp.is.co.za/applications/gimp"> -ftp://ftp.is.co.za/applications/gimp</ulink></simpara> -</listitem> - -<listitem><simpara> Australia - -<ulink -url="ftp://ftp.planetmirror.com/pub/gimp/gtk"> -ftp://ftp.planetmirror.com/pub/gimp/gtk</ulink></simpara> -</listitem> - -<listitem><simpara> Finland - -<ulink url="ftp://ftp.funet.fi/pub/sci/graphics/packages/gimp/gtk"> -ftp://ftp.funet.fi/pub/sci/graphics/packages/gimp/gtk</ulink></simpara> -</listitem> - -<listitem><simpara> Germany - -<ulink url="ftp://ftp.gwdg.de/pub/misc/grafik/gimp/gtk"> -ftp://ftp.gwdg.de/pub/misc/grafik/gimp/gtk</ulink></simpara> -</listitem> - -<listitem><simpara> Japan - -<ulink url="ftp://sunsite.sut.ac.jp/pub/archives/packages/gimp/gtk"> -ftp://sunsite.sut.ac.jp/pub/archives/packages/gimp/gtk</ulink></simpara> -</listitem> - -<listitem><simpara> UK - -<ulink url="http://www.mirror.ac.uk/sites/ftp.gimp.org/pub/gtk/"> -http://www.mirror.ac.uk/sites/ftp.gimp.org/pub/gtk/</ulink></simpara> -</listitem> -</itemizedlist> -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How do I configure/compile GTK+? <emphasis>[GTK 2.x]</emphasis></title> - -<para>Generally, the minimum you need to do is issue the commands:</para> - -<para><literallayout><literal>./configure</literal> -<literal>make</literal> -<literal>make install</literal></literallayout></para> - -<para>in the GTK+ source directory.</para> - -<para>This generally also holds true for each of the packages that GTK+ -depends upon, listed <link linkend="faq-Compile">above</link>.</para> - -<para>There are various options that you can pass to the configure script -in order to change its default settings. The one that you are most likely -to want to use is the <literal>--prefix</literal> -argument, which defines where the package is to be install, e.g.</para> - -<para> -<literallayout><literal>./configure --prefix=/usr</literal></literallayout> -</para> -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>When compiling GTK+ I get an error like: <literal>make: -file `Makefile' line 456: Syntax error</literal> <emphasis>[GTK 2.x]</emphasis></title> - -<para>Make sure that you are using GNU make -(use <literal>make -v</literal> -to check). There are many weird and wonderful versions of make -out there, and not all of them handle the automatically -generated Makefiles.</para> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>I've compiled and installed GTK+, but I can't get any -programs to link with it! <emphasis>[GTK 2.x]</emphasis></title> - -<para>This problem is most often encountered when the GTK+ -libraries can't be found or are the wrong version. Generally, -the compiler will complain about an 'unresolved symbol'.</para> - -<para>Make sure that the libraries can be -found. You want to edit <filename>/etc/ld.so.conf</filename> to -include the directories which contain the GTK libraries, -so it looks something like:</para> - -<para><literallayout><literal>/usr/X11R6/lib</literal> -<literal>/usr/local/lib</literal></literallayout></para> - -<para>Then you need to run /sbin/ldconfig as root. You can -find what libraries GTK requires using</para> - -<para><literallayout><literal>pkg-config gtk+-2.0 --libs</literal> -</literallayout></para> - -<para>If your system doesn't use ld.so to find libraries -(such as Solaris), then you will have to use the LD_LIBRARY_PATH -environment variable (or compile the path into your program, which I'm -not going to cover here). So, with a Bourne type shell you can do (if -your GTK libraries are in /usr/local/lib):</para> - -<para><literallayout> -<literal>export LD_LIBRARY_PATH=/usr/local/lib</literal> -</literallayout></para> - -<para>and in a csh, you can do:</para> - -<para><literallayout> -<literal>setenv LD_LIBRARY_PATH /usr/local/lib</literal> -</literallayout></para> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>When installing a GTK+ application, configure reports -that it can't find GTK. <emphasis>[GTK 2.x]</emphasis></title> - -<para>There are several common reasons for this:</para> - -<itemizedlist> -<listitem><simpara>You have an old version of GTK installed -somewhere. You should remove this old copy, but note that -this may break applications that have been compiled against -the old version.</simpara> -</listitem> - -<listitem><simpara><literal>pkg-config</literal> (or another -component of GTK) isn't in your path, or there is an old -version on your system. Type:</simpara> - -<para><literallayout> -<literal>pkg-config gtk+-2.0 --modversion</literal> -</literallayout></para> - -<para>to check for both of these. If it returns a value -different from what you expect, then you have an old -version of GTK on your system.</para> -</listitem> - -<listitem><simpara>The ./configure script can't find the GTK -libraries. As ./configure compiles various test programs, it needs to be -able to find the GTK libraries. See the question above -for help on this. </simpara></listitem> -</itemizedlist> - -<para>If none of the above help, then have a look in -config.log, which is generated by ./configure as it runs. At the -bottom will be the last action it took before failing. If it is a -section of source code, copy the source code to a file and compile it -with the line just above it in config.log. If the compilation is -successful, try executing it.</para> - -</sect1> - -</chapter> - -<!-- ***************************************************************** --> -<chapter> -<title>Development of GTK+</title> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>Whats this CVS thing that everyone keeps talking about, -and how do I access it? <emphasis>[GTK 2.x]</emphasis></title> - -<para>CVS is the Concurrent Version System and is a very -popular means of version control for software projects. It is -designed to allow multiple authors to simultanously operate on the same -source tree. This source tree is centrally maintained, but each -developer has a local mirror of this repository that they make -their changes to.</para> - -<para>The GTK+ developers use a CVS repository to store the -master copy of the current development version of GTK+. As -such, people wishing to contribute patches to GTK+ should -generate them against the CVS version. Normal people should -use the packaged releases.</para> - -<para>The CVS toolset is available as RPM packages from the -usual RedHat sites. The latest version is available at <ulink -url="http://download.cyclic.com/pub/">http://download.cyclic.com/pub/ -</ulink></para> - -<para>Anyone can download the latest CVS version of GTK+ by -using anonymous access using the following steps:</para> - -<itemizedlist> -<listitem><simpara> In a bourne shell descendant (e.g. bash) type:</simpara> -<para><literallayout> -<literal>CVSROOT=':pserver:anonymous@anoncvs.gnome.org:/cvs/gnome'</literal> -<literal>export CVSROOT</literal> -</literallayout></para> -</listitem> - -<listitem><simpara>Next, the first time the source tree is -checked out, a cvs login is needed. </simpara> -<para><literallayout> -<literal>cvs login</literal> -</literallayout></para> -<para>This will ask you for a password. There is no -password for cvs.gimp.org, so just enter a carriage return.</para> -</listitem> - -<listitem><simpara>To get the tree and place it in a subdir of your -current working directory, issue the command:</simpara> -<para><literallayout> -<literal>cvs -z3 get gtk+</literal> -</literallayout></para> -<para>Note that with the GTK+ 1.1 tree, glib has been moved to -a separate CVS module, so if you don't have glib installed you will -need to get that as well:</para> -<para><literallayout> -<literal>cvs -z3 get glib</literal> -</literallayout></para> -</listitem> -</itemizedlist> - -<para>The CVS archive stores both the current development version of -GTK+ (the CVS HEAD branch) and all current and past stable versions. -If you want to retrieve a specific version of GTK+ you have to specify -the CVS tag corresponding to the version you want to checkout. If you -want to checkout the current GTK+ 2.2 stable source code, you would need -to use the following command:</para> - -<para><literallayout> -<literal>cvs -z3 get -r gtk-2-2 gtk+</literal> -</literallayout></para> -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1 id="faq-Patches"> -<title>How can I contribute to GTK+? <emphasis>[GTK 2.x]</emphasis></title> - -<para>It's simple. If something doesn't work like you think it -should in a program, check the documentation to make sure -you're not missing something. If it is a true bug or missing -feature, track it down in the GTK+ source, change it, and -then generate a patch in the form of a 'context diff'. This -can be done using a command such as <literal>diff -ru -<oldfile> <newfile></literal>.</para> - -<para>The patch should then be attached to a bug report in -the GNOME bug tracking system, which can also be used to store -general patches -(<ulink url="http://bugzilla.gnome.org">http://bugzilla.gnome.org</ulink>). -</para> - -<para>This method ensures that the patch will not be lost.</para> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How do I know if my patch got applied, and if not, why -not? <emphasis>[GTK 2.x]</emphasis></title> - -<para>If you have used the GNOME bug tracking system (as stated -<link linkend="faq-Patches">above</link>) then the status -of your patch should be reflected in the bug report.</para> - -<para>The GTK+ developers will generally add comments to the bug -report stating what needs to be done to get the patch applied, -or why the patch is not appropriate.</para> -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>What is the policy on incorporating new widgets into -the library? <emphasis>[GTK 2.x]</emphasis></title> - -<para>This is up to the authors, so you will have to ask them -once you are done with your widget. As a general guideline, -widgets that are generally useful, work, and are not a -disgrace to the widget set will gladly be included.</para> - -<para>The new widgets that get added to GTK+ are generally either -replacements for existing widgets that are no longer -deemed to be adequate, or have been developed externally to GTK+ but -have been widely tested.</para> - -<para>Before you spend months of your valuable time implementing your -revolutionary widget, it is highly recommended that you get some -feedback on your idea via the appropriate -<link linkend="faq-MailLists">mailing list</link>.</para> -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>Is anyone working on bindings for languages other than -C? <emphasis>[GTK 2.x]</emphasis></title> - -<para>There is a list of <ulink url="http://www.gtk.org/bindings.html"> -language bindings</ulink> on the GTK+ website.</para> - -<para>The 'official' language bindings are C++, Ada and Python. -However, bindings for many other languages are available.</para> -</sect1> - -</chapter> - -<!-- ***************************************************************** --> -<chapter> -<title>Development with GTK+: the begining</title> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How do I get started? <emphasis>[GTK 2.x]</emphasis></title> - -<para>So, after you have installed GTK+ there are a couple of -things that can ease you into developing applications with -it. There is the GTK+ Tutorial <ulink -url="http://library.gnome.org/devel/gtk-tutorial/stable/"> -http://library.gnome.org/devel/gtk-tutorial/stable/</ulink>, which is undergoing -development. This will introduce you to writing applications -using C.</para> - -<para>The GTK+ Tutorial doesn't contain information on all of -the widgets that are in GTK+. For example code on how to use -the basics of all the GTK+ widgets you should look in the -directory 'tests' (and associated source files) within the GTK+ -distribution. Looking at these examples will give you a good -grounding on what the widgets can do.</para> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How do I use the Glade GUI builder with GTK+? <emphasis>[GTK 2.x]</emphasis></title> - -<para>There are two ways to use Glade. The first way is to use -Glade's facilities for generating code; the second -way is to use the libglade library which directly loads -the XML user interface description files that Glade -generates into a running program.</para> - -<para>Experienced GTK+ programmers generally strongly recommend -using libglade; you don't have to worry about the interaction -between Glade generating the source and you editing it, -and its been shown to be a method that works better -for large projects, so there is a lot of example code -out there you can look at.</para> - -<para>An introduction to using libglade can be found in the -libglade API docs -(<ulink url="http://developer.gnome.org/doc/API/2.0/libglade/libglade-notes.html#libglade-basics"> -http://developer.gnome.org/doc/API/2.0/libglade/libglade-notes.html#libglade-basics</ulink>) -.</para> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How do I write security sensitive/SUID/SGID programs with GTK+? -Is GTK+ secure? What's this GTK_MODULES security hole I heard about? -<emphasis>[GTK 2.x]</emphasis></title> - -<para>The short answer to this question is: you can't, so don't write SUID/SGID -programs with GTK+</para> - -<para>GTK+ will refuse to run with elevated privileges, as it is not designed -to be used in this manner. The only correct way to write a setuid program with -a graphical user interface is to have a setuid backend that communicates with -the non-setuid graphical user interface via a mechanism such as a pipe and that -considers the input it receives to be untrusted.</para> - -<para>For a more thorough explanation of the GTK+ Developers position on -this issue see <ulink -url="http://www.gtk.org/setuid.html">http://www.gtk.org/setuid.html</ulink>.</para> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>I tried to compile a small <command>Hello World</command> of mine, -but it failed. Any clue? <emphasis>[GTK 2.x]</emphasis></title> - -<para>Since you are good at coding, we will not deal with -compile time errors here :)</para> - -<para>The classic command line to compile a GTK+ based program is</para> -<para><literallayout> -<literal>gcc -o myprog [c files] `pkg-config gtk+-2.0 --cflags --libs`</literal> -</literallayout></para> - -<para>You should notice the backquote character which is used -in this command line. A common mistake when you start a GTK+ -based development is to use quotes instead of backquotes. If -you do so, the compiler will complain about an unknown file -called <filename>pkg-config gtk+-2.0 --cflags --libs</filename>. The -text in backquotes is an instruction to your shell to -substitute the output of executing this command into the -commandline.</para> - -<para>The command line above ensures that:</para> - -<itemizedlist> -<listitem><simpara>the correct C compiler flags will be used -to compile the program (including the complete C header -directory list)</simpara> -</listitem> - -<listitem><simpara>your program will be linked with the -needed libraries.</simpara> -</listitem> -</itemizedlist> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>What about using the <command>make</command> -utility? <emphasis>[GTK 2.x]</emphasis></title> - -<para>This is a sample makefile which compiles a GTK+ based -program:</para> - -<programlisting role="C"> -# basic GTK+ app makefile -SOURCES = myprg.c foo.c bar.c -OBJS = ${SOURCES:.c=.o} -CFLAGS = `pkg-config gtk+-2.0 --cflags` -LDADD = `pkg-config gtk+-2.0 --libs` -CC = gcc -PACKAGE = myprg - -all : ${OBJS} - ${CC} -o ${PACKAGE} ${OBJS} ${LDADD} - -.c.o: - ${CC} ${CFLAGS} -c $< - -# end of file -</programlisting> - -<para>For more information about the <command>make</command> utility, you -should read either the related man page or the relevant info file.</para> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>I use the backquote stuff in my makefiles, but my make -process failed. <emphasis>[GTK 2.x]</emphasis></title> - -<para>The backquote construction seems to not be accepted by -some old <command>make</command> utilities. If you use one of these, the -make process will probably fail. In order to have the -backquote syntax working again, you should use the GNU make -utility (get it on the GNU ftp server at <ulink -url="ftp://ftp.gnu.org/gnu/make/">ftp://ftp.gnu.org/gnu/make/</ulink>).</para> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>I want to add some configure stuff, how could I do -this? <emphasis>[GTK 2.x]</emphasis></title> - -<para>To use autoconf/automake, you must first install the -relevant packages. These are:</para> - -<itemizedlist spacing=Compact> -<listitem><simpara>the m4 preprocessor v1.4 or better</simpara> -</listitem> - -<listitem><simpara>autoconf v2.54 or better</simpara> -</listitem> - -<listitem><simpara>automake v1.7 or better suggested</simpara> -</listitem> -</itemizedlist> - -<para>You'll find these packages on the main GNU ftp server -(<ulink url="ftp://ftp.gnu.org/">ftp://ftp.gnu.org/</ulink>) -or on any GNU mirror.</para> - -<para>In order to use the powerful autoconf/automake scheme, -you must create a configure.ac which may look like:</para> - -<programlisting role="C"> -dnl Process this file with autoconf to produce a configure script. -dnl configure.ac for a GTK+ based program - -AC_INIT(myprg.c) -AM_INIT_AUTOMAKE(mypkgname, 0.0.1) -AM_CONFIG_HEADER(config.h) - -dnl Checks for programs. -AC_PROG_CC dnl check for the c compiler -dnl you should add CFLAGS="" here, 'cos it is set to -g by PROG_CC - -dnl Checks for libraries. -AM_PATH_GTK_2_0(2.2.0,,AC_MSG_ERROR(mypkgname 0.1 needs GTK+ 2.2.0)) - -AC_OUTPUT( - Makefile -) -</programlisting> - -<para>You must add a Makefile.am file:</para> - -<programlisting role="C"> -bin_PROGRAMS = myprg -myprg_SOURCES = myprg.c foo.c bar.c -INCLUDES = @GTK_CFLAGS@ -LDADD = @GTK_LIBS@ -CLEANFILES = *~ -DISTCLEANFILES = .deps/*.P -</programlisting> - -<para>If your project contains more than one subdirectory, -you'll have to create one Makefile.am in each directory plus a -master Makefile.am which will look like:</para> - -<programlisting role="C"> -SUBDIRS = mydir1 mydir2 mydir3 -</programlisting> - -<para>then, to use these, simply type the following -commands:</para> - -<programlisting role="C"> -aclocal -autoheader -autoconf -automake --add-missing --include-deps --foreign -</programlisting> - -<para>For further information, you should look at the autoconf -and the automake documentation (the shipped info files are -really easy to understand, and there are plenty of web -resources that deal with autoconf and automake).</para> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>I try to debug my GTK+ application with gdb, but it -hangs my X server when I hit some breakpoint. Any -Idea? <emphasis>[GTK 2.x]</emphasis></title> - -<para>From Federico Mena Quintero:</para> - -<para><quote>X is not locked up. It is likely that you are hitting a -breakpoint inside a callback that is called from a place in Gtk that has -a mouse grab.</quote></para> - -<para><quote>Run your program with the <literal>--sync</literal> -option; it will make it easier to debug. Also, you may want to -use the console for running the debugger, and just let the -program run in another console with the X server.</quote></para> - -<para>Eric Mouw had another solution:</para> - -<para><quote>An old terminal connected to an otherwise unused serial -port is also great for debugging X programs. Old vt100/vt220 -terminals are dirt cheap but a bit hard to get (here in The -Netherlands, YMMV).</quote></para> - -<para> -Another option is to run your application on Xnest. Xnest is an X server -which displays its root window in a regular window of another X server. -A pointer grab on the Xnest display will not affect the GUI of your debugger -running on your regular X server. -<programlisting> -Xnest :1 -twm -display :1 -myapp --display=:1 -</programlisting> -</para> -</sect1> -</chapter> - -<!-- ***************************************************************** --> -<chapter> -<title>Development with GTK+: general questions</title> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>What widgets are in GTK?</title> - -<para>The GTK+ Tutorial lists the following widgets:</para> - -<programlisting role="C"> - GtkObject - +GtkData - | +GtkAdjustment - | `GtkTooltips - `GtkWidget - +GtkContainer - | +GtkBin - | | +GtkAlignment - | | +GtkEventBox - | | +GtkFrame - | | | `GtkAspectFrame - | | +GtkHandleBox - | | +GtkItem - | | | +GtkListItem - | | | +GtkMenuItem - | | | | `GtkCheckMenuItem - | | | | `GtkRadioMenuItem - | | | `GtkTreeItem - | | +GtkViewport - | | `GtkWindow - | | +GtkColorSelectionDialog - | | +GtkDialog - | | | `GtkInputDialog - | | `GtkFileSelection - | +GtkBox - | | +GtkButtonBox - | | | +GtkHButtonBox - | | | `GtkVButtonBox - | | +GtkHBox - | | | +GtkCombo - | | | `GtkStatusbar - | | `GtkVBox - | | `GtkColorSelection - | +GtkButton - | | +GtkOptionMenu - | | `GtkToggleButton - | | `GtkCheckButton - | | `GtkRadioButton - | +GtkCList - | `GtkCTree - | +GtkFixed - | +GtkList - | +GtkMenuShell - | | +GtkMenuBar - | | `GtkMenu - | +GtkNotebook - | +GtkPaned - | | +GtkHPaned - | | `GtkVPaned - | +GtkScrolledWindow - | +GtkTable - | +GtkToolbar - | `GtkTree - +GtkDrawingArea - +GtkEditable - | +GtkEntry - | | `GtkSpinButton - | `GtkText - +GtkMisc - | +GtkArrow - | +GtkImage - | +GtkLabel - | | `GtkTipsQuery - | `GtkPixmap - +GtkPreview - +GtkProgressBar - +GtkRange - | +GtkScale - | | +GtkHScale - | | `GtkVScale - | `GtkScrollbar - | +GtkHScrollbar - | `GtkVScrollbar - +GtkRuler - | +GtkHRuler - | `GtkVRuler - `GtkSeparator - +GtkHSeparator - `GtkVSeparator -</programlisting> -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>Is GTK+ thread safe? How do I write multi-threaded GTK+ -applications? <emphasis>[GTK 2.x]</emphasis></title> - -<para>The GLib library can be used in a thread-safe mode by -calling g_thread_init() before making any other GLib -calls. In this mode GLib automatically locks all internal -data structures as needed. This does not mean that two -threads can simultaneously access, for example, a single hash -table, but they can access two different hash tables -simultaneously. If two different threads need to access the -same hash table, the application is responsible for locking -itself.</para> - -<para>In order to make GDK thread aware, you also need to -call gdk_threads_init() in conjunction with the above call. -There is a single global -lock that you must acquire with gdk_threads_enter() before -making any GDK calls, and release with gdk_threads_leave() -afterwards throughout your code.</para> - -<para>A minimal main program for a threaded GTK+ application -looks like:</para> - -<programlisting role="C"> -int -main (int argc, char *argv[]) -{ - GtkWidget *window; - - /* init threads */ - g_thread_init(NULL); - gdk_threads_init(); - - /* init gtk */ - gtk_init(&argc, &argv); - - window = create_window(); - gtk_widget_show(window); - - gdk_threads_enter(); - gtk_main(); - gdk_threads_leave(); - - return 0; -} -</programlisting> - -<para>Callbacks require a bit of attention. Callbacks from -GTK+ (signals) are made within the GTK+ lock. However -callbacks from GLib (timeouts, IO callbacks, and idle -functions) are made outside of the GTK+ lock. So, within a -signal handler you do not need to call gdk_threads_enter(), -but within the other types of callbacks, you do.</para> - -<para>Erik Mouw contributed the following code example to -illustrate how to use threads within GTK+ programs.</para> - -<programlisting role="C"> -/*------------------------------------------------------------------------- - * Filename: gtk-thread.c - * Version: 1.99.1 - * Copyright: Copyright (C) 1999, Erik Mouw - * Author: Erik Mouw <J.A.K.Mouw@its.tudelft.nl> - * Description: GTK threads example. - * Created at: Sun Oct 17 21:27:09 1999 - * Modified by: Owen Taylor <otaylor@gtk.org> - * Modified at: Wed May 28 10:43:00 2003 - *-----------------------------------------------------------------------*/ -/* - * Compile with: - * - * cc -o gtk-thread gtk-thread.c `pkg-config --cflags --libs gtk+-2.0 gthread-2.0` - * - * Thanks to Sebastian Wilhelmi for pointing out some bugs in earlier versions. - * - */ - -#include <unistd.h> -#include <gtk/gtk.h> - -#define YES_IT_IS (1) -#define NO_IT_IS_NOT (0) - -typedef struct -{ - GtkWidget *label; - int what; -} yes_or_no_args; - -G_LOCK_DEFINE_STATIC (yes_or_no); -static volatile int yes_or_no = YES_IT_IS; - -void destroy(GtkWidget *widget, gpointer data) -{ - gtk_main_quit(); -} - -void *argument_thread(void *args) -{ - yes_or_no_args *data = (yes_or_no_args *)args; - gboolean say_something; - - for(;;) - { - /* sleep a while */ - sleep(g_random_int_range (1, 4)); - - /* lock the yes_or_no_variable */ - G_LOCK(yes_or_no); - - /* do we have to say something? */ - say_something = (yes_or_no != data->what); - - if(say_something) - { - /* set the variable */ - yes_or_no = data->what; - } - - /* Unlock the yes_or_no variable */ - G_UNLOCK(yes_or_no); - - if(say_something) - { - /* get GTK thread lock */ - gdk_threads_enter(); - - /* set label text */ - if(data->what == YES_IT_IS) - gtk_label_set_text(GTK_LABEL(data->label), "O yes, it is!"); - else - gtk_label_set_text(GTK_LABEL(data->label), "O no, it isn't!"); - - /* Make sure all X commands are sent to the X server; not strictly - * necessary here, but always a good idea when you do anything - * from a thread other than the one where the main loop is running. - */ - gdk_flush (); - - /* release GTK thread lock */ - gdk_threads_leave(); - } - } - - return NULL; -} - -int main(int argc, char *argv[]) -{ - GtkWidget *window; - GtkWidget *label; - GError *error = NULL; - yes_or_no_args yes_args, no_args; - - /* init threads */ - g_thread_init(NULL); - gdk_threads_init(); - - /* init gtk */ - gtk_init(&argc, &argv); - - /* create a window */ - window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - - g_signal_connect(window, "destroy", - G_CALLBACK(destroy), NULL); - - gtk_container_set_border_width(GTK_CONTAINER (window), 10); - - /* create a label */ - label = gtk_label_new("And now for something completely different ..."); - gtk_container_add(GTK_CONTAINER(window), label); - - /* show everything */ - gtk_widget_show(label); - gtk_widget_show (window); - - /* create the threads */ - yes_args.label = label; - yes_args.what = YES_IT_IS; - if (!g_thread_create(argument_thread, &yes_args, FALSE, &error)) - { - g_printerr ("Failed to create YES thread: %s\n", error->message); - return 1; - } - - no_args.label = label; - no_args.what = NO_IT_IS_NOT; - if (!g_thread_create(argument_thread, &no_args, FALSE, &error)) - { - g_printerr ("Failed to create NO thread: %s\n", error->message); - return 1; - } - - /* enter the GTK main loop */ - gdk_threads_enter(); - gtk_main(); - gdk_threads_leave(); - - return 0; -} -</programlisting> -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>I'm doing some stuff with GTK+ in a separate thread, and -properly locking with gdk_threads_enter/gdk_threads_leave() -but the display doesn't update properly. <emphasis>[GTK 2.x]</emphasis> -</title> - -<para>For efficiency, the X window system batches up commands -and sends them to the X server in batches instead of sending -out immediately.</para> - -<para>In a non-multithreaded program, you don't have to worry about -this, since the first thing that happens when control returns -to the main loop is that any outstanding X requests are -sent to the X server.</para> - -<para>However, if you are making GTK+ calls from a thread other -than the main loop, then GTK+ doesn't know when to send batched -commands out. For that reason, after making GTK+ calls -in a separate thread, it is usually a good idea to call -gdk_flush() before gdk_thread_leave().</para> - -<para>Actually, gdk_flush() is more expensive than is necessary here, -since it waits for the X server to finish outstanding commands -as well; if performance is an issue, you may want to call -XFlush() directly:</para> - -<programlisting role="C"> - -#include <gdk/gdkx.h> - -void my_flush_commands (void) -{ - GdkDisplay *display = gdk_display_get_default (); - XFlush (GDK_DISPLAY_XDISPLAY (display); -} -</programlisting> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>What's an easy way to run a function in the thread with -the main loop? <emphasis>[GTK 2.x]</emphasis></title> - -<para>Sometimes the simplest way to set up a threaded program -is to make all the GTK+ calls in a single thread. In such -a program, you should still call g_threads_init(), but -don't need to call gdk_threads_init(), gkd_threads_enter(), -and gdk_threads_leave().</para> - -<para>If you set your program up this way, how then do you get -the thread making GTK+ calls and running the main loop -to do something in response to another thread?</para> - -<para>An easy way to do it is to take advantage of the fact that -the GLib main loop functions are all thread safe, and can -be called from any thread by adding an idle function -with g_idle_add(). The function provided will be called -at the next opportunity by the main thread. If you want -your function to take priority over event handling and -drawing, you can instead use g_idle_add_full() and pass -in a priority of G_PRIORITY_HIGH.</para> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>Why does this strange 'x io error' occur when I -<literal>fork()</literal> in my GTK+ app? <emphasis>[GTK 2.x]</emphasis></title> - -<para>This is not really a GTK+ problem, and the problem is -not related to <literal>fork()</literal> either. If the 'x io -error' occurs then you probably use the <literal>exit()</literal> function -in order to exit from the child process.</para> - -<para>When GDK opens an X display, it creates a socket file -descriptor. When you use the <literal>exit()</literal> -function, you implicitly close all the open file descriptors, -and the underlying X library really doesn't like this.</para> - -<para>The right function to use here is -<literal>_exit()</literal>.</para> - -<para>Erik Mouw contributed the following code example to -illustrate handling fork() and exit().</para> - -<programlisting role="C"> -/*------------------------------------------------------------------------- - * Filename: gtk-fork.c - * Version: 0.99.2 - * Copyright: Copyright (C) 1999, Erik Mouw - * Author: Erik Mouw <J.A.K.Mouw@its.tudelft.nl> - * Description: GTK+ fork example - * Created at: Thu Sep 23 21:37:55 1999 - * Modified by: Erik Mouw <J.A.K.Mouw@its.tudelft.nl> - * Modified at: Thu Sep 23 22:39:39 1999 - * Modified by: Tony Gale <gale@gtk.org> - * Modified at: Wed Jan 14 12:38:00 2004 - *-----------------------------------------------------------------------*/ -/* - * Compile with: - * - * cc -o gtk-fork gtk-fork.c `pkg-config gtk+-2.0 --cflags --libs` - * - */ - -#include <stdio.h> -#include <stdlib.h> -#include <signal.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <unistd.h> -#include <gtk/gtk.h> - -void sigchld_handler(int num) -{ - sigset_t set, oldset; - pid_t pid; - int status, exitstatus; - - /* block other incoming SIGCHLD signals */ - sigemptyset(&set); - sigaddset(&set, SIGCHLD); - sigprocmask(SIG_BLOCK, &set, &oldset); - - /* wait for child */ - while((pid = waitpid((pid_t)-1, &status, WNOHANG)) > 0) - { - if(WIFEXITED(status)) - { - exitstatus = WEXITSTATUS(status); - - fprintf(stderr, - "Parent: child exited, pid = %d, exit status = %d\n", - (int)pid, exitstatus); - } - else if(WIFSIGNALED(status)) - { - exitstatus = WTERMSIG(status); - - fprintf(stderr, - "Parent: child terminated by signal %d, pid = %d\n", - exitstatus, (int)pid); - } - else if(WIFSTOPPED(status)) - { - exitstatus = WSTOPSIG(status); - - fprintf(stderr, - "Parent: child stopped by signal %d, pid = %d\n", - exitstatus, (int)pid); - } - else - { - fprintf(stderr, - "Parent: child exited magically, pid = %d\n", - (int)pid); - } - } - - /* re-install the signal handler (some systems need this) */ - signal(SIGCHLD, sigchld_handler); - - /* and unblock it */ - sigemptyset(&set); - sigaddset(&set, SIGCHLD); - sigprocmask(SIG_UNBLOCK, &set, &oldset); -} - -gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data) -{ - return(FALSE); -} - -void destroy(GtkWidget *widget, gpointer data) -{ - gtk_main_quit(); -} - -void fork_me(GtkWidget *widget, gpointer data) -{ - pid_t pid; - - pid = fork(); - - if(pid == -1) - { - /* ouch, fork() failed */ - perror("fork"); - exit(-1); - } - else if(pid == 0) - { - /* child */ - fprintf(stderr, "Child: pid = %d\n", (int)getpid()); - - execlp("ls", "ls", "-CF", "/", NULL); - - /* if exec() returns, there is something wrong */ - perror("execlp"); - - /* exit child. note the use of _exit() instead of exit() */ - _exit(-1); - } - else - { - /* parent */ - fprintf(stderr, "Parent: forked a child with pid = %d\n", (int)pid); - } -} - -int main(int argc, char *argv[]) -{ - GtkWidget *window; - GtkWidget *button; - - gtk_init(&argc, &argv); - - /* the basic stuff: make a window and set callbacks for destroy and - * delete events - */ - window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - - g_signal_connect(G_OBJECT (window), "delete_event", - G_CALLBACK(delete_event), NULL); - - g_signal_connect(G_OBJECT (window), "destroy", - G_CALLBACK(destroy), NULL); - - gtk_container_set_border_width(GTK_CONTAINER (window), 10); - - /* add a button to do something useful */ - button = gtk_button_new_with_label("Fork me!"); - - g_signal_connect(G_OBJECT (button), "clicked", - G_CALLBACK(fork_me), NULL); - - gtk_container_add(GTK_CONTAINER(window), button); - - /* show everything */ - gtk_widget_show (button); - gtk_widget_show (window); - - - /* install a signal handler for SIGCHLD signals */ - signal(SIGCHLD, sigchld_handler); - - - /* main loop */ - gtk_main (); - - exit(0); -} -</programlisting> -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>Why don't the contents of a button move when the button -is pressed? Here's a patch to make it work that way... <emphasis>[GTK 2.x]</emphasis></title> - -<para>From: Peter Mattis</para> - -<para><quote>The reason buttons don't move their child down and to -the right when they are depressed is because I don't think -that's what is happening visually. My view of buttons is -that you are looking at them straight on. That is, the user -interface lies in a plane and you're above it looking -straight at it. When a button gets pressed it moves directly -away from you. To be absolutely correct I guess the child -should actually shrink a tiny amount. But I don't see why -the child should shift down and to the left. Remember, the -child is supposed to be attached to the buttons surface. Its -not good for it to appear like the child is slipping on the -surface of the button.</quote></para> - -<para><quote>On a more practical note, I did implement this at one point -and determined it didn't look good and removed it.</quote></para> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How do I identifiy a widgets top level window or other -ancestor? <emphasis>[GTK 2.x]</emphasis></title> - -<para>There are a couple of ways to find the top level parent -of a widget. The easiest way is to call the -<literal>gtk_widget_get_toplevel()</literal> function that -returns a pointer to a GtkWidget that is the top level -window.</para> - -<para>A more complicated way to do this (but less limited, as -it allows the user to get the closest ancestor of a known type) is to use -<literal>gtk_widget_get_ancestor()</literal> as in:</para> - -<programlisting role="C"> - GtkWidget *widget; - widget = gtk_widget_get_ancestor(w, GTK_TYPE_WINDOW); -</programlisting> - -<para>Since virtually all the GTK_TYPEs can be used as the -second parameter of this function, you can get any parent -widget of a particular widget. Suppose you have an hbox which -contains a vbox, which in turn contains some other atomic -widget (entry, label, etc. To find the master hbox using the -<literal>entry</literal> widget simply use:</para> - -<programlisting role="C"> - GtkWidget *hbox; - hbox = gtk_widget_get_ancestor(w, GTK_TYPE_HBOX); -</programlisting> - -<para>You can also follow the a widgets ancestry by using the function -<literal>gtk_widget_get_parent()</literal> that returns a pointer -to a widgets parent widget.</para> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How do I get the Window ID of a GtkWindow? <emphasis>[GTK 2.x]</emphasis></title> - -<para>The actual Gdk/X window will be created when the widget -gets realized. You can get the Window ID with:</para> - -<programlisting role="C"> -#include <gdk/gdkx.h> - -Window xwin = GDK_WINDOW_XWINDOW (GTK_WIDGET (my_window)->window); -</programlisting> -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How do I catch a double click event? <emphasis>[GTK 2.x]</emphasis></title> - -<para>Tim Janik wrote to gtk-list (slightly modified):</para> - -<para>Define a signal handler:</para> - -<programlisting role="C"> -gint -signal_handler_event(GtkWidget *widget, GdkEventButton *event, gpointer func_data) -{ - if (GTK_IS_BUTTON(widget) && - (event->type==GDK_2BUTTON_PRESS || - event->type==GDK_3BUTTON_PRESS) ) { - printf("I feel %s clicked with button %d\n", - event->type==GDK_2BUTTON_PRESS ? "double" : "triple", - event->button); - } - - return FALSE; -}</programlisting> - -<para>And connect the handler to your object:</para> - -<programlisting role="C"> -{ - /* button init stuff */ - - g_signal_connect(G_OBJECT(button), - "button_press_event", - G_CALLBACK(signal_handler_event), - NULL); - - /* and/or */ - - g_signal_connect(G_OBJECT(button), - "button_release_event", - G_CALLBACK(signal_handler_event), - NULL); - - /* something else */ -} -</programlisting> - -<para>and, Owen Taylor wrote:</para> - -<para><quote>Note that a single button press will be received -beforehand, and if you are doing this for a button, you will -therefore also get a "clicked" signal for the button. (This -is going to be true for any toolkit, since computers aren't -good at reading one's mind.)</quote></para> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>By the way, what are the differences between signals -and events?</title> - -<para>First of all, Havoc Pennington gives a rather complete -description of the differences between events and signals in -his free book (two chapters can be found at <ulink -url="http://www106.pair.com/rhp/sample_chapters.html"> -http://www106.pair.com/rhp/sample_chapters.html</ulink>).</para> - -<para>Moreover, Havoc posted this to the <literal>gtk-list</literal> -<quote>Events are a stream of messages received from the X -server. They drive the Gtk main loop; which more or less -amounts to "wait for events, process them" (not exactly, it -is really more general than that and can wait on many -different input streams at once). Events are a Gdk/Xlib -concept.</quote></para> - -<para><quote>Signals are a feature of GtkObject and its subclasses. They -have nothing to do with any input stream; really a signal is just a way -to keep a list of callbacks around and invoke them ("emit" the -signal). There are lots of details and extra features of -course. Signals are emitted by object instances, and are entirely -unrelated to the Gtk main loop. Conventionally, signals are emitted -"when something changes" about the object emitting the -signal.</quote></para> - -<para><quote>Signals and events only come together because GtkWidget -happens to emit signals when it gets events. This is purely a -convenience, so you can connect callbacks to be invoked when a -particular widget receives a particular event. There is nothing about -this that makes signals and events inherently related concepts, any more -than emitting a signal when you click a button makes button clicking and -signals related concepts.</quote></para> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>Data I pass to the <literal>delete_event</literal> (or other event) -handler gets corrupted.</title> - -<para>All event handlers take an additional argument which -contains information about the event that triggered the -handler. So, a <literal>delete_event</literal> handler must -be declared as:</para> - - -<programlisting role="C"> -gint delete_event_handler (GtkWidget *widget, - GdkEventAny *event, - gpointer data); -</programlisting> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>I have my signal connected to the the (whatever) event, -but it seems I don't catch it. What's wrong?</title> - -<para>There is some special initialisation to do in order to -catch some particular events. In fact, you must set the -correct event mask bit of your widget before getting some -particular events.</para> - -<para>For example,</para> - -<programlisting role="C"> - gtk_widget_add_events(window, GDK_KEY_RELEASE_MASK); -</programlisting> - -<para>lets you catch the key release events. If you want to -catch every events, simply us the GDK_ALL_EVENTS_MASK event -mask.</para> - -<para>All the event masks are defined in the -<filename>gdktypes.h</filename> file.</para> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>I need to add a new signal to a GTK+ widget. Any -idea?</title> - -<para>If the signal you want to add may be beneficial for -other GTK+ users, you may want to submit a patch that -presents your changes. Check the tutorial for more -information about adding signals to a widget class.</para> - -<para>If you don't think it is the case or if your patch is -not applied you'll have to use the -<literal>gtk_object_class_user_signal_new</literal> -function. <literal>gtk_object_class_user_signal_new</literal> allows you -to add a new signal to a predefined GTK+ widget without any -modification of the GTK+ source code. The new signal can be -emited with <literal>g_signal_emit</literal> and can be -handled in the same way as other signals.</para> - -<para>Tim Janik posted this code snippet:</para> - -<programlisting role="C"> -static guint signal_user_action = 0; - -signal_user_action = - gtk_object_class_user_signal_new (gtk_type_class (GTK_TYPE_WIDGET), - "user_action", - GTK_RUN_LAST | GTK_RUN_ACTION, - gtk_marshal_NONE__POINTER, - GTK_TYPE_NONE, 1, - GTK_TYPE_POINTER); - -void -gtk_widget_user_action (GtkWidget *widget, - gpointer act_data) -{ - g_return_if_fail (GTK_IS_WIDGET (widget)); - - g_signal_emit (widget, signal_user_action, act_data); -} -</programlisting> - -<para>If you want your new signal to have more than the -classical gpointer parameter, you'll have to play with GTK+ -marshallers.</para> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>Is it possible to get some text displayed which is -truncated to fit inside its allocation?</title> - -<para>GTK's behavior (no clipping) is a consequence of its -attempts to conserve X resources. Label widgets (among -others) don't get their own X window - they just draw their -contents on their parent's window. While it might be possible -to have clipping occur by setting the clip mask before -drawing the text, this would probably cause a substantial -performance penalty.</para> - -<para>Its possible that, in the long term, the best solution -to such problems might be just to change gtk to give labels X -windows. A short term workaround is to put the label widget -inside another widget that does get its own window - one -possible candidate would be the viewport widget.</para> - -<programlisting role="C"> -viewport = gtk_viewport (NULL, NULL); -gtk_widget_set_usize (viewport, 50, 25); -gtk_viewport_set_shadow_type (GTK_VIEWPORT(viewport), GTK_SHADOW_NONE); -gtk_widget_show(viewport); - -label = gtk_label ("a really long label that won't fit"); -gtk_container_add (GTK_CONTAINER(viewport), label); -gtk_widget_show (label); -</programlisting> - -<para>If you were doing this for a bunch of widgets, you might -want to copy gtkviewport.c and strip out the adjustment and -shadow functionality (perhaps you could call it -GtkClipper).</para> -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How do I make my window modal? / How do I make a single -window active?</title> - -<para>After you create your window, do -<literal>gtk_grab_add(my_window)</literal>. And after closing the window -do <literal>gtk_grab_remove(my_window)</literal>.</para> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>Why doesn't my widget (e.g. progressbar) -update? <emphasis>[GTK 2.x]</emphasis></title> - -<para>You are probably doing all the changes within a function without -returning control to <literal>gtk_main()</literal>. This may -be the case if you do some lengthy calculation in your -code. Most drawing updates are only placed on a queue, which -is processed within <literal>gtk_main()</literal>. You can force the -drawing queue to be processed using something like:</para> - - -<programlisting role="C"> -while (g_main_context_iteration(NULL, FALSE)); -</programlisting> - -<para>inside you're function that changes the widget.</para> - -<para>What the above snippet does is run all pending events -and high priority idle functions, then return immediately -(the drawing is done in a high priority idle function).</para> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How do I attach data to some GTK+ object/widget? -<emphasis>[GTK 2.x]</emphasis></title> - -<para>First of all, the attached data is stored in the -object_data field of a GtkObject. The type of this field is -GData, which is defined in glib.h. So you should read the -gdataset.c file in your glib source directory very -carefully.</para> - -<para>There are two (easy) ways to attach some data to a gtk -object. Using <literal>g_object_set_data()</literal> and -<literal>g_object_get_data()</literal> seems to be the most -common way to do this, as it provides a powerful interface to -connect objects and data.</para> - -<programlisting role="C"> -void g_object_set_data(GObject *object, const gchar *key, gpointer data); - -gpointer g_object_get_data(GObject *object, const gchar *key); -</programlisting> - -<para>Since a short example is better than any lengthy speech:</para> - -<programlisting role="C"> -struct my_struct p1,p2,*result; -GtkWidget *w; - -g_object_set_data(G_OBJECT(w),"p1 data",(gpointer)&p1); -g_object_set_data(G_OBJECT(w),"p2 data",(gpointer)&p2); - -result = g_object_get_data(G_OBJECT(w),"p1 data"); -</programlisting> - -<para>The <literal>gtk_object_set_user_data()</literal> and -<literal>gtk_object_get_user_data()</literal> functions does -exactly the same thing as the functions above, but does not -let you specify the "key" parameter.Instead, it uses a -standard "user_data" key. Note that the use of these functions -is deprecated in 1.2. They only provide a compatibility mode -with some old gtk packages.</para> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How do I remove the data I have attached to an -object?</title> - -<para>When attaching the data to the object, you can use the -<literal>gtk_object_set_data_full()</literal> function. The three -first arguments of the function are the same as in -<literal>gtk_object_set_data()</literal>. The fourth one is a -pointer to a callback function which is called when the data -is destroyed. The data is destroyed when you:</para> - -<itemizedlist> -<listitem><simpara> destroy the object</simpara> -</listitem> - -<listitem><simpara> replace the data with a new one (with -the same key)</simpara> -</listitem> - -<listitem><simpara> replace the data with NULL (with the -same key)</simpara> -</listitem> - -</itemizedlist> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How do I reparent a widget?</title> - -<para>The normal way to reparent (ie change the owner) of a -widget should be to use the function:</para> - -<programlisting role="C"> -void gtk_widget_reparent (GtkWidget *widget, - GtkWidget *new_parent) -</programlisting> - -<para>But this is only a "should be" since this function does -not correctly do its job on some specific widgets. The main -goal of gtk_widget_reparent() is to avoid unrealizing widget -if both widget and new_parent are realized (in this case, -widget->window is successfully reparented). The problem here -is that some widgets in the GTK+ hierarchy have multiple -attached X subwindows and this is notably the case for the -GtkSpinButton widget. For those, gtk_widget_reparent() will -fail by leaving an unrealized child window where it should -not.</para> - -<para>To avoid this problem, simply use the following code -snippet:</para> - -<programlisting role="C"> - g_object_ref(widget); - gtk_container_remove(GTK_CONTAINER(old_parent), widget); - gtk_container_add(GTK_CONTAINER(new_parent), widget); - g_object_unref(widget); -</programlisting> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How could I get any widgets position?</title> - -<para>As Tim Janik pointed out, there are different cases, and -each case requires a different solution.</para> - -<itemizedlist> -<listitem><simpara> If you want the position of a widget -relative to its parent, you should use -<literal>widget->allocation.x</literal> and -<literal>widget->allocation.y</literal>.</simpara> -</listitem> - -<listitem><simpara> If you want the position of a window -relative to the X root window, you should use -<literal>gdk_window_get_geometry()</literal> -<literal>gdk_window_get_position()</literal> or -<literal>gdk_window_get_origin()</literal>.</simpara> -</listitem> - -<listitem><simpara> If you want to get the position of the -window (including the WM decorations), you should use -<literal>gdk_window_get_root_origin()</literal>.</simpara> -</listitem> - -<listitem><simpara> Last but not least, if you want to get a Window -Manager frame position, you should use -<literal>gdk_window_get_deskrelative_origin()</literal>.</simpara> -</listitem> -</itemizedlist> - -<para>Your choice of Window Manager will have an effect of the -results of the above functions. You should keep this in mind -when writing your application. This is dependant upon how the -Window Managers manage the decorations that they add around -windows.</para> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How do I set the size of a widget/window? How do I -prevent the user resizing my window? <emphasis>[GTK 2.x]</emphasis></title> - -<para>The <literal>gtk_widget_set_size_request()</literal> function -is used to set the size of a widget to a specific size. - -The function -<literal>gtk_window_set_resizable()</literal> function sets whether -the user can resize a window, which they can by default. The -definition of these functions are:</para> - -<programlisting role="C"> -void gtk_widget_set_size_request (GtkWidget *widget, - gint width, - gint height); - -void gtk_window_set_resizable (GtkWindow *window, - gboolean resizable); - -</programlisting> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How do I add a popup menu to my GTK+ application?</title> - -<para>The <literal>menu</literal> example in the examples/menu -directory of the GTK+ distribution implements a popup menu -with this technique:</para> - -<programlisting role="C"> -static gint button_press (GtkWidget *widget, GdkEvent *event) -{ - - if (event->type == GDK_BUTTON_PRESS) { - GdkEventButton *bevent = (GdkEventButton *) event; - gtk_menu_popup (GTK_MENU(widget), NULL, NULL, NULL, NULL, - bevent->button, bevent->time); - /* Tell calling code that we have handled this event; the buck - * stops here. */ - return TRUE; - } - - /* Tell calling code that we have not handled this event; pass it on. */ - return FALSE; -} -</programlisting> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How do I disable or enable a widget, such as a -button?</title> - -<para>To disable (or to enable) a widget, use the -<literal>gtk_widget_set_sensitive()</literal> function. The -first parameter is you widget pointer. The second parameter is -a boolean value: when this value is TRUE, the widget is -enabled.</para> -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>Shouldn't the text argument in the gtk_clist_* -functions be declared const?</title> - -<para>For example:</para> - -<programlisting role="C"> -gint gtk_clist_prepend (GtkCList *clist, - gchar *text[]); -</programlisting> - -<para>Answer: No, while a type "gchar*" (pointer to char) can -automatically be cast into "const gchar*" (pointer to const -char), this does not apply for "gchar *[]" (array of an -unspecified number of pointers to char) into "const gchar *[]" -(array of an unspecified number of pointers to const char).</para> - -<para>The type qualifier "const" may be subject to automatic -casting, but in the array case, it is not the array itself -that needs the (const) qualified cast, but its members, thus -changing the whole type.</para> -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How do I render pixels (image data) to the -screen?</title> - -<para>There are several ways to approach this. The simplest -way is to use GdkRGB, see gdk/gdkrgb.h. You create an RGB -buffer, render to your RGB buffer, then use GdkRGB routines to -copy your RGB buffer to a drawing area or custom widget. The -book "GTK+/Gnome Application Development" gives some details; -GdkRGB is also documented in the GTK+ reference -documentation.</para> - -<para>If you're writing a game or other graphics-intensive -application, you might consider a more elaborate -solution. OpenGL is the graphics standard that will let you -access hardware accelaration in future versions of XFree86; so -for maximum speed, you probably want to use OpenGL. A -GtkGLArea widget is available for using OpenGL with GTK+ (but -GtkGLArea does not come with GTK+ itself). There are also -several open source game libraries, such as ClanLib and Loki's -Simple DirectMedia Layer library (SDL).</para> - -<para>You do NOT want to use -<literal>gdk_draw_point()</literal>, that will be extremely -slow.</para> -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How do I create a pixmap without having my window being -realized/shown?</title> - -<para>Functions such as -<literal>gdk_pixmap_create_from_xpm()</literal> require a -valid window as a parameter. During the initialisation phase -of an application, a valid window may not be available without -showing a window, which may be inappropriate. In order to -avoid this, a function such as -<literal>gdk_pixmap_colormap_create_from_xpm</literal> can be -used, as in:</para> - -<programlisting role="C"> - char *pixfile = "foo.xpm"; - GtkWidget *top, *box, *pixw; - GdkPixmap *pixmap, *pixmap_mask; - - top = gtk_window_new (GKT_WINDOW_TOPLEVEL); - box = gtk_hbox_new (FALSE, 4); - gtk_conainer_add (GTK_CONTAINER(top), box); - - pixmap = gdk_pixmap_colormap_create_from_xpm ( - NULL, gtk_widget_get_colormap(top), - &pixmap_mask, NULL, pixfile); - pixw = gtk_pixmap_new (pixmap, pixmap_mask); - g_object_unref (pixmap); - g_object_unref (pixmap_mask); -</programlisting> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How do I do drag-and-drop?</title> - -<para>GTK+ has a high level set of functions for doing inter-process -communication via the drag-and-drop system. GTK+ can perform -drag-and-drop on top of the low level Xdnd and Motif drag-and-drop -protocols.</para> - -<para>The documentation on GTK+ drag-and-drop isn't complete, but there -is some information in the <ulink -url="http://www.gtk.org/tutorial/">Tutorial</ulink>. You should also -look at the drag-and-drop example code that is part of the GTK+ source -distribution, in the file <filename>gtk/testdnd.c</filename>.</para> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>Why does GTK+/GLib leak memory?</title> - -<para>It doesn't. Both GLib and the C library (malloc implementation) -will cache allocated memory on occasion, even if you free it with -free().</para> - -<para>So you can't generally use tools such as top to see if you are -using free() properly (aside from the very roughest of estimations, i.e. -if you are really, really screwing up top will show that, but you can't -distinguish small mistakes from the GLib/malloc caches).</para> - -<para>In order to find memory leaks, use proper memory profiling -tools.</para> - -</sect1> - -</chapter> - -<!-- ***************************************************************** --> -<chapter> -<title>Development with GTK+: widget specific questions</title> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How do I find out about the selection of a GtkList?</title> - -<para>Get the selection something like this:</para> - -<programlisting role="C"> -GList *sel; -sel = GTK_LIST(list)->selection; -</programlisting> - -<para>This is how GList is defined (quoting glist.h):</para> - -<programlisting role="C"> -typedef struct _GList GList; - -struct _GList -{ - gpointer data; - GList *next; - GList *prev; -}; -</programlisting> - -<para>A GList structure is just a simple structure for doubly -linked lists. There exist several g_list_*() functions to -modify a linked list in glib.h. However the -GTK_LIST(MyGtkList)->selection is maintained by the -gtk_list_*() functions and should not be modified.</para> - - -<para>The selection_mode of the GtkList determines the -selection facilities of a GtkList and therefore the contents -of GTK_LIST(AnyGtkList)->selection:</para> - -<informaltable frame="all"> -<tgroup cols="2"> -<thead> -<row> -<entry><literal>selection_mode</literal></entry> -<entry><literal> GTK_LIST()->selection</literal> -contents</entry> -</row> -</thead> - -<tbody> -<row> -<entry><literal>GTK_SELECTION_SINGLE</literal></entry> -<entry>selection is either NULL or contains a GList* -pointer for a single selected item.</entry> -</row> - -<row> -<entry><literal>GTK_SELECTION_BROWSE</literal></entry> -<entry>selection is NULL if the list contains no -widgets, otherwise it contains a GList* -pointer for one GList structure.</entry> -</row> - -<row> -<entry><literal>GTK_SELECTION_MULTIPLE</literal></entry> -<entry>selection is NULL if no listitems are selected -or a a GList* pointer for the first selected -item. that in turn points to a GList structure -for the second selected item and so -on.</entry> -</row> - -<row> -<entry><literal>GTK_SELECTION_EXTENDED</literal></entry> -<entry>selection is NULL.</entry> -</row> - -</tbody> -</tgroup> -</informaltable> - -<para>The data field of the GList structure -GTK_LIST(MyGtkList)->selection points to the first -GtkListItem that is selected. So if you would like to -determine which listitems are selected you should go like -this:</para> - -<programlisting role="C"> -{ - gchar *list_items[]={ - "Item0", - "Item1", - "foo", - "last Item", - }; - guint nlist_items=sizeof(list_items)/sizeof(list_items[0]); - GtkWidget *list_item; - guint i; - - list=gtk_list_new(); - gtk_list_set_selection_mode(GTK_LIST(list), GTK_SELECTION_MULTIPLE); - gtk_container_add(GTK_CONTAINER(AnyGtkContainer), list); - gtk_widget_show (list); - - for (i = 0; i < nlist_items; i++) - { - list_item=gtk_list_item_new_with_label(list_items[i]); - gtk_object_set_user_data(GTK_OBJECT(list_item), (gpointer)i); - gtk_container_add(GTK_CONTAINER(list), list_item); - gtk_widget_show(list_item); - } -} -</programlisting> - -<para>To get known about the selection:</para> - -<programlisting role="C"> -{ - GList *items; - - items=GTK_LIST(list)->selection; - - printf("Selected Items: "); - while (items) { - if (GTK_IS_LIST_ITEM(items->data)) - printf("%d ", (guint) - gtk_object_get_user_data(items->data)); - items=items->next; - } - printf("\n"); -} -</programlisting> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How do I stop the column headings of a GtkCList -disappearing when the list is scrolled?</title> - -<para>This happens when a GtkCList is packed into a -GtkScrolledWindow using the function -<literal>gtk_scroll_window_add_with_viewport()</literal>. The prefered -method of adding a CList to a scrolled window is to use the -function <literal>gtk_container_add</literal>, as in:</para> - -<programlisting role="C"> - GtkWidget *scrolled, *clist; - char *titles[] = { "Title1" , "Title2" }; - - scrolled = gtk_scrolled_window_new(NULL, NULL); - - clist = gtk_clist_new_with_titles(2, titles); - gtk_container_add(GTK_CONTAINER(scrolled), clist); -</programlisting> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>I don't want the user of my applications to enter text -into a GtkCombo. Any idea?</title> - -<para>A GtkCombo has an associated entry which can be accessed -using the following expression:</para> - -<programlisting role="C"> - GTK_COMBO(combo_widget)->entry -</programlisting> - -<para>If you don't want the user to be able to modify the -content of this entry, you can use the -gtk_editable_set_editable() function:</para> - - -<programlisting role="C"> -void gtk_editable_set_editable (GtkEditable *editable, - gboolean is_editable); -</programlisting> - -<para>Set the is_editable parameter to FALSE to disable typing -into the entry.</para> -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How do I catch a combo box change?</title> - -<para>The entry which is associated to your GtkCombo send a -"changed" signal when:</para> - -<itemizedlist> -<listitem><simpara>some text is typed in</simpara> -</listitem> - -<listitem><simpara>the selection of the combo box is changed</simpara> -</listitem> -</itemizedlist> - -<para>To catch any combo box change, simply connect your -signal handler with</para> - -<programlisting role="C"> - g_signal_connect(GTK_COMBO(cb)->entry, - "changed", - G_CALLBACK(my_cb_change_handler), - NULL); -</programlisting> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How can I define a separation line in a menu?</title> - -<para>See the <ulink -url="http://www.gtk.org/tutorial/">Tutorial</ulink> for -information on how to create menus. However, to create a -separation line in a menu, just insert an empty menu item:</para> - -<programlisting role="C"> -menuitem = gtk_menu_item_new(); -gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); -gtk_widget_show(menuitem); -</programlisting> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How can I right justify a menu, such as Help?</title> - -<para>Depending on if you use the MenuFactory or not, there -are two ways to proceed. With the MenuFactory, use something -like the following:</para> - -<programlisting role="C"> -menu_path = gtk_menu_factory_find (factory, "<MyApp>/Help"); -gtk_menu_item_right_justify(menu_path->widget); -</programlisting> - -<para>If you do not use the MenuFactory, you should simply -use:</para> - - -<programlisting role="C"> -gtk_menu_item_right_justify(my_menu_item); -</programlisting> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How do I add some underlined accelerators to menu -items?</title> - -<para>Damon Chaplin, the technical force behind the Glade -project, provided the following code sample (this code is an -output from Glade). It creates a small <GUIMenu>File</guimenu> menu item -with only one child (<guimenu>New</guimenu>). The F in -<guimenu>File</guimenu> and the N in <guimenu>New</guimenu> are -underlined, and the relevant accelerators are created.</para> - -<programlisting role="C"> - menubar1 = gtk_menu_bar_new (); - gtk_object_set_data (GTK_OBJECT (window1), "menubar1", menubar1); - gtk_widget_show (menubar1); - gtk_box_pack_start (GTK_BOX (vbox1), menubar1, FALSE, FALSE, 0); - - file1 = gtk_menu_item_new_with_label (""); - gtk_label_set_use_underline (GTK_LABEL (gtk_bin_get_child (GTK_BIN (file1))), - TRUE); - gtk_widget_add_accelerator (file1, "activate_item", accel_group, - tmp_key, GDK_MOD1_MASK, 0); - gtk_object_set_data (GTK_OBJECT (window1), "file1", file1); - gtk_widget_show (file1); - gtk_container_add (GTK_CONTAINER (menubar1), file1); - - file1_menu = gtk_menu_new (); - file1_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (file1_menu)); - gtk_object_set_data (GTK_OBJECT (window1), "file1_menu", file1_menu); - gtk_menu_item_set_submenu (GTK_MENU_ITEM (file1), file1_menu); - - new1 = gtk_menu_item_new_with_label (""); - gtk_label_set_use_underline (GTK_LABEL (gtk_bin_get_child (GTK_BIN (new1))), - TRUE); - gtk_widget_add_accelerator (new1, "activate_item", file1_menu_accels, - tmp_key, 0, 0); - gtk_object_set_data (GTK_OBJECT (window1), "new1", new1); - gtk_widget_show (new1); - gtk_container_add (GTK_CONTAINER (file1_menu), new1); -</programlisting> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How can I retrieve the text from a GtkMenuItem?</title> - -<para>You can usually retrieve the label of a specific -GtkMenuItem with:</para> - -<programlisting role="C"> - if (GTK_BIN (menu_item)->child) - { - GtkWidget *child = GTK_BIN (menu_item)->child; - - /* do stuff with child */ - if (GTK_IS_LABEL (child)) - { - const gchar *text; - - text = gtk_label_get_text (GTK_LABEL (child)); - g_print ("menu item text: %s\n", text); - } - } -</programlisting> - -<para>To get the active menu item from a GtkOptionMenu you can -do:</para> - -<programlisting role="C"> -if (GTK_OPTION_MENU (option_menu)->menu_item) -{ - GtkWidget *menu_item = GTK_OPTION_MENU (option_menu)->menu_item; -} -</programlisting> - -<para>But, there's a catch. For this specific case, you can -<emphasis>not</emphasis> get the label widget from -<literal>menu_item</literal> with the above code, because the -option menu reparents the menu_item's child temporarily to -display the currently active contents. So to retrive the child -of the currently active menu_item of an option menu, you'll -have to do:</para> - -<programlisting role="C"> - if (GTK_BIN (option_menu)->child) - { - GtkWidget *child = GTK_BIN (option_menu)->child; - - /* do stuff with child */ - } -</programlisting> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How do I right (or otherwise) justify a -GtkLabel?</title> - -<para>Are you sure you want to <emphasis>justify</emphasis> -the labels? The label class contains the -<literal>gtk_label_set_justify()</literal> function that is -used to control the justification of a multi-line -label.</para> - -<para>What you probably want is to set the <emphasis>alignment</emphasis> -of the label, ie right align it, center it or left align -it. If you want to do this, you should use:</para> - -<programlisting role="C"> -void gtk_misc_set_alignment (GtkMisc *misc, - gfloat xalign, - gfloat yalign); -</programlisting> - -<para>where the <literal>xalign</literal> and -<literal>yalign</literal> values are floats in -[0.00;1.00].</para> - -<programlisting role="C"> -GtkWidget *label; - -/* horizontal : left align, vertical : top */ -gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.0f); - -/* horizontal : centered, vertical : centered */ -gtk_misc_set_alignment(GTK_MISC(label), 0.5f, 0.5f); - -/* horizontal : right align, vertical : bottom */ -gtk_misc_set_alignment(GTK_MISC(label), 1.0f, 1.0f); -</programlisting> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How do I set the background color of a GtkLabel -widget?</title> - -<para>The GtkLabel widget is one of a few GTK+ widgets that -don't create their own window to render themselves -into. Instead, they draw themselves directly onto their -parents window.</para> - -<para>This means that in order to set the background color for -a GtkLabel widget, you need to change the background color of -its parent, i.e. the object that you pack it into.</para> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How do I set the color and font of a GtkLabel using a -Resource File?</title> - -<para>The widget name path constructed for a Label consists of -the widget names of its object hierarchy as well, e.g.</para> - -<para><literallayout> -<literal>window (name: humphrey)</literal> -<literal> hbox</literal> -<literal> label (name: mylabel)</literal> -</literallayout></para> - -<para>The widget path your pattern needs to match would be: -<literal>humphrey.GtkHBox.mylabel</literal></para> - -<para>The resource file may look something like:</para> - -<programlisting role="C"> -style "title" -{ - fg[NORMAL] = {1.0, 0.0, 0.0} - font = "-adobe-helvetica-bold-r-normal--*-140-*-*-*-*-*-*" -} -widget "*mylabel" style "title" -</programlisting> - -<para>In your program, you would also need to give a name to -the Label widget, which can be done using:</para> - -<programlisting role="C"> - label = gtk_label_new("Some Label Text"); - gtk_widget_set_name(label, "mylabel"); - gtk_widget_show(label); -</programlisting> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How do I configure Tooltips in a Resource File?</title> - -<para>The tooltip's window is named "gtk-tooltips", -GtkTooltips in itself is not a GtkWidget (though a GtkObject) -and as such is not attempted to match any widget styles.</para> - -<para>So, your resource file should look something like:</para> - -<programlisting role="C"> -style "postie" -{ - bg[NORMAL] = {1.0, 1.0, 0.0} -} -widget "gtk-tooltips*" style "postie" -</programlisting> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>I can't add more than (something like) 2000 chars in a -GtkEntry. What's wrong?</title> - -<para>There is now a known problem in the GtkEntry widget. In -the <literal>gtk_entry_insert_text()</literal> function, the -following lines limit the number of chars in the entry to -2047.</para> - -<programlisting role="C"> - /* The algorithms here will work as long as, the text size (a - * multiple of 2), fits into a guint16 but we specify a shorter - * maximum length so that if the user pastes a very long text, there - * is not a long hang from the slow X_LOCALE functions. */ - - if (entry->text_max_length == 0) - max_length = 2047; - else - max_length = MIN (2047, entry->text_max_length); -</programlisting> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How do I make a GtkEntry widget activate on pressing -the Return key?</title> - -<para>The Entry widget emits an 'activate' signal when you -press return in it. Just attach to the activate signal on the -entry and do whatever you want to do. Typical code would -be:</para> - -<programlisting role="C"> - entry = gtk_entry_new(); - g_signal_connect (entry, "activate", - G_CALLBACK(entry_callback), - NULL); -</programlisting> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How do I validate/limit/filter the input to a GtkEntry? <emphasis>[GTK 2.x]</emphasis></title> - -<para>If you want to validate the text that a user enters into -a GtkEntry widget you can attach to the "insert_text" signal -of the entry, and modify the text within the callback -function. The example below forces all characters to -uppercase, and limits the range of characters to A-Z. Note -that the entry is cast to an object of type GtkEditable, from -which GtkEntry is derived.</para> - -<programlisting role="C"> -#include <ctype.h> -#include <gtk/gtk.h> - -void insert_text_handler (GtkEntry *entry, - const gchar *text, - gint length, - gint *position, - gpointer data) -{ - GtkEditable *editable = GTK_EDITABLE(entry); - int i, count=0; - gchar *result = g_new (gchar, length); - - for (i=0; i < length; i++) { - if (!isalpha(text[i])) - continue; - result[count++] = islower(text[i]) ? toupper(text[i]) : text[i]; - } - - if (count > 0) { - g_signal_handlers_block_by_func (G_OBJECT (editable), - G_CALLBACK (insert_text_handler), - data); - gtk_editable_insert_text (editable, result, count, position); - g_signal_handlers_unblock_by_func (G_OBJECT (editable), - G_CALLBACK (insert_text_handler), - data); - } - g_signal_stop_emission_by_name (G_OBJECT (editable), "insert_text"); - - g_free (result); -} - -int main (int argc, - char *argv[]) -{ - GtkWidget *window; - GtkWidget *entry; - - gtk_init (&argc, &argv); - - /* create a new window */ - window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_title(GTK_WINDOW (window), "GTK Entry"); - g_signal_connect (G_OBJECT (window), "destroy", - G_CALLBACK (gtk_main_quit), - NULL); - - entry = gtk_entry_new(); - g_signal_connect(G_OBJECT(entry), "insert_text", - G_CALLBACK(insert_text_handler), - NULL); - gtk_container_add(GTK_CONTAINER (window), entry); - gtk_widget_show(entry); - - gtk_widget_show(window); - - gtk_main(); - return(0); -} -</programlisting> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How do I use horizontal scrollbars with a GtkText widget?</title> - -<para>The short answer is that you can't. The current version -of the GtkText widget does not support horizontal -scrolling. There is an intention to completely rewrite the -GtkText widget, at which time this limitation will be -removed.</para> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How do I change the font of a GtkText widget?</title> - -<para>There are a couple of ways of doing this. As GTK+ allows -the appearance of applications to be changed at run time using -resources you can use something like the following in the -appropriate file:</para> - -<programlisting role="C"> -style "text" -{ - font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*" -} -</programlisting> - -<para>Another way to do this is to load a font within your -program, and then use this in the functions for adding text to -the text widget. You can load a font using, for example:</para> - -<programlisting role="C"> - GdkFont *font; - font = gdk_font_load("-adobe-helvetica-medium-r-normal--*-140-*-*-*-*-*-*"); -</programlisting> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How do I set the cursor position in a GtkText -object?</title> - -<para>Notice that the response is valid for any object that -inherits from the GtkEditable class.</para> - -<para>Are you sure that you want to move the cursor position? -Most of the time, while the cursor position is good, the -insertion point does not match the cursor position. If this -apply to what you really want, then you should use the -<literal>gtk_text_set_point()</literal> function. If you want -to set the insertion point at the current cursor position, use -the following:</para> - -<programlisting role="C"> - gtk_text_set_point(GTK_TEXT(text), - gtk_editable_get_position(GTK_EDITABLE(text))); -</programlisting> - -<para>If you want the insertion point to follow the cursor at -all time, you should probably catch the button press event, -and then move the insertion point. Be careful : you'll have to -catch it after the widget has changed the cursor position -though. Thomas Mailund Jensen proposed the following -code:</para> - -<programlisting role="C"> -static void -insert_bar (GtkWidget *text) -{ - /* jump to cursor mark */ - gtk_text_set_point (GTK_TEXT (text), - gtk_editable_get_position (GTK_EDITABLE (text))); - - gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, - "bar", strlen ("bar")); -} - -int -main (int argc, char *argv[]) -{ - GtkWidget *window, *text; - - gtk_init (&argc, &argv); - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - text = gtk_text_new (NULL, NULL); - gtk_text_set_editable (GTK_TEXT (text), TRUE); - gtk_container_add (GTK_CONTAINER (window), text); - - /* connect after everything else */ - g_signal_connect_after (text, "button_press_event", - G_CALLBACK (insert_bar), NULL); - - gtk_widget_show_all(window); - gtk_main(); - - return 0; -} -</programlisting> - -<para>Now, if you really want to change the cursor position, -you should use the -<literal>gtk_editable_set_position()</literal> -function.</para> - -</sect1> - -</chapter> - -<!-- ***************************************************************** --> -<chapter> -<title>About GDK</title> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>What is GDK?</title> - -<para>GDK is basically a wrapper around the standard Xlib -function calls. If you are at all familiar with Xlib, a lot of -the functions in GDK will require little or no getting used -to. All functions are written to provide an way to access Xlib -functions in an easier and slightly more intuitive manner. In -addition, since GDK uses GLib (see below), it will be more -portable and safer to use on multiple platforms.</para> - -<!-- Examples, anybody? I've been mulling some over. NF --> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How do I use color allocation?</title> - -<para>One of the nice things about GDK is that it's based on -top of Xlib; this is also a problem, especially in the area of -color management. If you want to use color in your program -(drawing a rectangle or such, your code should look something -like this:</para> - -<programlisting role="C"> -{ - GdkColor *color; - int width, height; - GtkWidget *widget; - GdkGC *gc; - - ... - - /* first, create a GC to draw on */ - gc = gdk_gc_new(widget->window); - - /* find proper dimensions for rectangle */ - gdk_drawable_get_size(widget->window, &width, &height); - - /* the color we want to use */ - color = (GdkColor *)malloc(sizeof(GdkColor)); - - /* red, green, and blue are passed values, indicating the RGB triple - * of the color we want to draw. Note that the values of the RGB components - * within the GdkColor are taken from 0 to 65535, not 0 to 255. - */ - color->red = red * (65535/255); - color->green = green * (65535/255); - color->blue = blue * (65535/255); - - /* the pixel value indicates the index in the colormap of the color. - * it is simply a combination of the RGB values we set earlier - */ - color->pixel = (gulong)(red*65536 + green*256 + blue); - - /* However, the pixel valule is only truly valid on 24-bit (TrueColor) - * displays. Therefore, this call is required so that GDK and X can - * give us the closest color available in the colormap - */ - gdk_colormap_alloc_color(gtk_widget_get_colormap(widget), color, FALSE, TRUE); - - /* set the foreground to our color */ - gdk_gc_set_foreground(gc, color); - - /* draw the rectangle */ - gdk_draw_rectangle(widget->window, gc, 1, 0, 0, width, height); - - ... -} -</programlisting> - -</sect1> - -</chapter> - -<!-- ***************************************************************** --> -<chapter> -<title>About GLib</title> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>What is GLib?</title> - -<para>GLib is a library of useful functions and definitions -available for use when creating GDK and GTK applications. It -provides replacements for some standard libc functions, such -as malloc, which are buggy on some systems.</para> - -<para>It also provides routines for handling:</para> - -<itemizedlist spacing=compact> -<listitem><simpara>Doubly Linked Lists</simpara> -</listitem> - -<listitem><simpara>Singly Linked Lists</simpara> -</listitem> - -<listitem><simpara>Timers</simpara> -</listitem> - -<listitem><simpara>String Handling</simpara> -</listitem> - -<listitem><simpara>A Lexical Scanner</simpara> -</listitem> - -<listitem><simpara>Error Functions</simpara> -</listitem> -</itemizedlist> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>How can I use the doubly linked lists?</title> - -<para>The GList object is defined as:</para> - -<programlisting role="C"> -typedef struct _GList GList; - -struct _GList -{ - gpointer data; - GList *next; - GList *prev; -}; -</programlisting> - -<para>To use the GList objects, simply:</para> - -<programlisting role="C"> -GList *list = NULL; -GList *listrunner; -gint array[] = { 1, 2, 3, 4, 5, 6 }; -gint pos; -gint *value; - -/* add data to the list */ -for (pos=0;pos < sizeof array; pos++) { - list = g_list_append(list, (gpointer)&array[pos]); -} - -/* run through the list */ -listrunner = g_list_first(list); -while (listrunner) { - value = (gint *)listrunner->data; - printf("%d\n", *value); - listrunner = g_list_next(listrunner); -} - -/* removing datas from the list */ -listrunner = g_list_first(list); -list = g_list_remove_link(list, listrunner); -list = g_list_remove(list, &array[4]); -</programlisting> - -<para>The same code is usable with singly linked lists (GSList -objects) by replacing g_list_* functions with the relevant -g_slist_* ones (g_slist_append, g_slist_remove, ...). Just -remember that since you can't go backward in a singly linked -list, there is no g_slist_first function - you'll need to keep -a reference on the first node of the list.</para> - -<!-- Some Examples might be useful here! NF --> -<!-- I believe it should be better :) ED --> -<!-- Linked lists are pretty standard data structures - don't want to -over do it - TRG --> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>Memory does not seem to be released when I free the -list nodes I've allocated</title> - -<para>GLib tries to be "intelligent" on this special issue: it -assumes that you are likely to reuse the objects, so caches -the allocated memory. If you do not want to use this behavior, -you'll probably want to set up a special allocator.</para> - -<para>To quote Tim Janik:</para> -<para><quote>If you have a certain portion of code that uses *lots* -of GLists or GNodes, and you know you'd better want to release -all of them after a short while, you'd want to use a -GAllocator. Pushing an allocator into g_list will make all -subsequent glist operations private to that allocator's memory -pool (and thus you have to take care to pop the allocator -again, before making any external calls): </quote></para> - -<programlisting role="C"> -GAllocator *allocator; -GList *list = NULL; -guint i; - -/* set a new allocation pool for GList nodes */ -allocator = g_allocator_new ("list heap", 1024); -g_list_push_allocator (allocator); - -/* do some list operations */ -for (i = 0; i < 4096; i++) - list = g_list_prepend (list, NULL); -list = g_list_reverse (list); - -/* beware to pop allocator befor calling external functions */ -g_list_pop_allocator (); -gtk_label_set_text (GTK_LABEL (some_label), "some text"); - -/* and set our private glist pool again */ -g_list_push_allocator (allocator); - -/* do some list operations */ -g_list_free (list); -list = NULL; -for (i = 0; i < 4096; i++) - list = g_list_prepend (list, NULL); - -/* and back out (while freeing all of the list nodes in our pool) */ -g_list_pop_allocator (); -g_allocator_free (allocator); -</programlisting> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>Why use g_print, g_malloc, g_strdup and fellow glib -functions?</title> - -<para>Thanks to Tim Janik who wrote to gtk-list: (slightly -modified)</para> - -<para><quote>Regarding g_malloc(), g_free() and siblings, these -functions are much safer than their libc equivalents. For -example, g_free() just returns if called with NULL. Also, if -USE_DMALLOC is defined, the definition for these functions -changes (in glib.h) to use MALLOC(), FREE() etc... If -MEM_PROFILE or MEM_CHECK are defined, there are even small -statistics made counting the used block sizes (shown by -g_mem_profile() / g_mem_check()).</quote></para> - -<para><quote>Considering the fact that glib provides an interface for -memory chunks to save space if you have lots of blocks that -are always the same size and to mark them ALLOC_ONLY if -needed, it is just straight forward to create a small saver -(debug able) wrapper around the normal malloc/free stuff as -well - just like gdk covers Xlib. ;)</quote></para> - -<para><quote>Using g_error() and g_warning() inside of applications -like the GIMP that fully rely on gtk even gives the -opportunity to pop up a window showing the messages inside of -a gtk window with your own handler (by using -g_set_error_handler()) along the lines of -<literal>gtk_print()</literal> (inside of -gtkmain.c).</quote></para> - -</sect1> - -<!-- ----------------------------------------------------------------- --> - -<sect1> -<title>What's a GScanner and how do I use one?</title> - -<para>A GScanner will tokenize your text, that is, it'll return -an integer for every word or number that appears in its input -stream, following certain (customizable) rules to perform this -translation. You still need to write the parsing functions on -your own though.</para> - -<para>Here's a little test program supplied by Tim Janik that -will parse</para> - -<para><literallayout> -<literal><SYMBOL> = <OPTIONAL-MINUS> <NUMBER> ;</literal> -</literallayout></para> - -<para>constructs, while skipping "#\n" and "/**/" style -comments.</para> - -<programlisting role="C"> -#include <glib.h> - -/* some test text to be fed into the scanner */ -static const gchar *test_text = -( "ping = 5;\n" - "/* slide in some \n" - " * comments, just for the\n" - " * fun of it \n" - " */\n" - "pong = -6; \n" - "\n" - "# the next value is a float\n" - "zonk = 0.7;\n" - "# redefine ping\n" - "ping = - 0.5;\n" ); - -/* define enumeration values to be returned for specific symbols */ -enum { - SYMBOL_PING = G_TOKEN_LAST + 1, - SYMBOL_PONG = G_TOKEN_LAST + 2, - SYMBOL_ZONK = G_TOKEN_LAST + 3 -}; - -/* symbol array */ -static const struct { - gchar *symbol_name; - guint symbol_token; -} symbols[] = { - { "ping", SYMBOL_PING, }, - { "pong", SYMBOL_PONG, }, - { "zonk", SYMBOL_ZONK, }, - { NULL, 0, }, -}, *symbol_p = symbols; - -static gfloat ping = 0; -static gfloat pong = 0; -static gfloat zonk = 0; - -static guint -parse_symbol (GScanner *scanner) -{ - guint symbol; - gboolean negate = FALSE; - - /* expect a valid symbol */ - g_scanner_get_next_token (scanner); - symbol = scanner->token; - if (symbol < SYMBOL_PING || - symbol > SYMBOL_ZONK) - return G_TOKEN_SYMBOL; - - /* expect '=' */ - g_scanner_get_next_token (scanner); - if (scanner->token != '=') - return '='; - - /* feature optional '-' */ - g_scanner_peek_next_token (scanner); - if (scanner->next_token == '-') - { - g_scanner_get_next_token (scanner); - negate = !negate; - } - - /* expect a float (ints are converted to floats on the fly) */ - g_scanner_get_next_token (scanner); - if (scanner->token != G_TOKEN_FLOAT) - return G_TOKEN_FLOAT; - - /* make sure the next token is a ';' */ - if (g_scanner_peek_next_token (scanner) != ';') - { - /* not so, eat up the non-semicolon and error out */ - g_scanner_get_next_token (scanner); - return ';'; - } - - /* assign value, eat the semicolon and exit successfully */ - switch (symbol) - { - case SYMBOL_PING: - ping = negate ? - scanner->value.v_float : scanner->value.v_float; - break; - case SYMBOL_PONG: - pong = negate ? - scanner->value.v_float : scanner->value.v_float; - break; - case SYMBOL_ZONK: - zonk = negate ? - scanner->value.v_float : scanner->value.v_float; - break; - } - g_scanner_get_next_token (scanner); - - return G_TOKEN_NONE; -} - -int -main (int argc, char *argv[]) -{ - GScanner *scanner; - guint expected_token; - - scanner = g_scanner_new (NULL); - - /* adjust lexing behaviour to suit our needs - */ - /* convert non-floats (octal values, hex values...) to G_TOKEN_INT */ - scanner->config->numbers_2_int = TRUE; - /* convert G_TOKEN_INT to G_TOKEN_FLOAT */ - scanner->config->int_2_float = TRUE; - /* don't return G_TOKEN_SYMBOL, but the symbol's value */ - scanner->config->symbol_2_token = TRUE; - - /* load symbols into the scanner */ - while (symbol_p->symbol_name) - { - g_scanner_add_symbol (scanner, - symbol_p->symbol_name, - GINT_TO_POINTER (symbol_p->symbol_token)); - symbol_p++; - } - - /* feed in the text */ - g_scanner_input_text (scanner, test_text, strlen (test_text)); - - /* give the error handler an idea on how the input is named */ - scanner->input_name = "test text"; - - /* scanning loop, we parse the input until its end is reached, - * the scanner encountered a lexing error, or our sub routine came - * across invalid syntax - */ - do - { - expected_token = parse_symbol (scanner); - - g_scanner_peek_next_token (scanner); - } - while (expected_token == G_TOKEN_NONE && - scanner->next_token != G_TOKEN_EOF && - scanner->next_token != G_TOKEN_ERROR); - - /* give an error message upon syntax errors */ - if (expected_token != G_TOKEN_NONE) - g_scanner_unexp_token (scanner, expected_token, NULL, "symbol", NULL, NULL, TRUE); - - /* finsish parsing */ - g_scanner_destroy (scanner); - - /* print results */ - g_print ("ping: %f\n", ping); - g_print ("pong: %f\n", pong); - g_print ("zonk: %f\n", zonk); - - return 0; -} -</programlisting> - -<para>You need to understand that the scanner will parse its -input and tokenize it, it is up to you to interpret these -tokens, not define their types before they get parsed, -e.g. watch gscanner parse a string:</para> - -<para><literallayout> -<literal>"hi i am 17"</literal> -<literal> | | | |</literal> -<literal> | | | v</literal> -<literal> | | v TOKEN_INT, value: 17</literal> -<literal> | v TOKEN_IDENTIFIER, value: "am"</literal> -<literal> v TOKEN_CHAR, value: 'i'</literal> -<literal>TOKEN_IDENTIFIER, value: "hi"</literal> -</literallayout></para> - -<para>If you configure the scanner with:</para> - -<programlisting role="C"> -scanner->config->int_2_float = TRUE; -scanner->config->char_2_token = TRUE; -scanner->config->scan_symbols = TRUE; -</programlisting> - -<para>and add "am" as a symbol with</para> - -<programlisting role="C"> -g_scanner_add_symbol (scanner, "am", "symbol value"); -</programlisting> - -<para>GScanner will parse it as</para> - -<para><literallayout> -<literal>"hi i am 17"</literal> -<literal> | | | |</literal> -<literal> | | | v</literal> -<literal> | | v TOKEN_FLOAT, value: 17.0 (automatic int->float conversion)</literal> -<literal> | | TOKEN_SYMBOL, value: "symbol value" (a successfull hash table lookup</literal> -<literal> | | turned a TOKEN_IDENTIFIER into a</literal> -<literal> | | TOKEN_SYMBOL and took over the</literal> -<literal> | v symbol's value)</literal> -<literal> v 'i' ('i' can be a valid token as well, as all chars >0 and <256)</literal> -<literal>TOKEN_IDENTIFIER, value: "hi"</literal> -</literallayout></para> - -<para>You need to match the token sequence with your code, and -if you encounter something that you don't want, you error -out:</para> - -<programlisting role="C"> -/* expect an identifier ("hi") */ -g_scanner_get_next_token (scanner); -if (scanner->token != G_TOKEN_IDENTIFIER) - return G_TOKEN_IDENTIFIER; -/* expect a token 'i' */ -g_scanner_get_next_token (scanner); -if (scanner->token != 'i') - return 'i'; -/* expect a symbol ("am") */ -g_scanner_get_next_token (scanner); -if (scanner->token != G_TOKEN_SYMBOL) - return G_TOKEN_SYMBOL; -/* expect a float (17.0) */ -g_scanner_get_next_token (scanner); -if (scanner->token != G_TOKEN_FLOAT) - return G_TOKEN_FLOAT; -</programlisting> - -<para>If you got past here, you have parsed "hi i am 17" and -would have accepted "dooh i am 42" and "bah i am 0.75" as -well, but you would have not accepted "hi 7 am 17" or "hi i hi -17".</para> - -</sect1> - -</chapter> - -<!-- ***************************************************************** --> - -<chapter> -<title>GTK+ FAQ Contributions, Maintainers and Copyright</title> - -<para>If you would like to make a contribution to the FAQ, send either one -of us an e-mail message with the exact text you think should be -included (question and answer). With your help, this document can grow -and become more useful!</para> - -<para>This document is maintained by -Tony Gale -<ulink url="mailto:gale@gtk.org"><gale@gtk.org></ulink> - -This FAQ was created by Shawn T. Amundson -<ulink url="mailto:amundson@gimp.org"> -<amundson@gimp.org></ulink>. - -Contributions should be sent to Tony Gale <ulink -url="mailto:gale@gtk.org"><gale@gtk.org></ulink></para> - -<para>The GTK+ FAQ is Copyright (C) 1997-2003 by Shawn T. Amundson, -Tony Gale.</para> - -<para>Permission is granted to make and distribute verbatim copies of this -manual provided the copyright notice and this permission notice are -preserved on all copies.</para> - -<para>Permission is granted to copy and distribute modified versions of this -document under the conditions for verbatim copying, provided that this -copyright notice is included exactly as in the original, and that the -entire resulting derived work is distributed under the terms of a -permission notice identical to this one.</para> - -<para>Permission is granted to copy and distribute translations of this -document into another language, under the above conditions for -modified versions.</para> - -<para>If you are intending to incorporate this document into a published -work, please contact one of the maintainers, and we will make an -effort to ensure that you have the most up to date information -available.</para> - -<para>There is no guarentee that this document lives up to its intended -purpose. This is simply provided as a free resource. As such, the -authors and maintainers of the information provided within can not -make any guarentee that the information is even accurate.</para> - -</chapter> - -<!-- ----------------------------------------------------------------- --> - -</book> |