1 <!doctype book PUBLIC "-//OASIS//DTD DocBook V3.1//EN" []>
5 <date>June 25th 2003</date>
6 <title>GTK+ FAQ</title>
9 <firstname>Tony</firstname>
10 <surname>Gale</surname>
13 <firstname>Shawn</firstname>
14 <surname>Amundson</surname>
17 <firstname>Emmanuel</firstname>
18 <surname>Deloget</surname>
22 <para> This document is intended to answer questions that are
23 likely to be frequently asked by programmers using GTK+ or
24 people who are just looking at using GTK+. </para>
25 <para><emphasis>Note: </emphasis> This FAQ mainly covers GTK+ 1.2.
26 Where the text covers GTK+ 2.x this will be indicated</para>
32 <!-- ***************************************************************** -->
34 <title>General Information</title>
36 <!-- ----------------------------------------------------------------- -->
39 <title>Note: This FAQ mainly covers GTK+ 1.2</title>
40 <para>This FAQ mainly covers GTK+ 1.2.
41 Where the text covers GTK+ 2.x this will be indicated by prefixing the
42 text with: <emphasis>[GTK+ 2.x]</emphasis>
46 <!-- ----------------------------------------------------------------- -->
49 <title>Before anything else: the greetings</title>
50 <para>The FAQ authors want to thank:</para>
51 <itemizedlist spacing=Compact>
53 <simpara>Havoc Pennington</simpara>
56 <simpara>Erik Mouw</simpara>
59 <simpara>Owen Taylor</simpara>
62 <simpara>Tim Janik</simpara>
65 <simpara>Thomas Mailund Jensen</simpara>
68 <simpara>Joe Pfeiffer</simpara>
71 <simpara>Andy Kahn</simpara>
74 <simpara>Federico Mena Quntero</simpara>
77 <simpara>Damon Chaplin</simpara>
80 <simpara>and all the members of the GTK+ lists</simpara>
81 </listitem></itemizedlist>
82 <para> If we forgot you, please email us! Thanks again (I know,
83 it's really short :) </para>
86 <!-- ----------------------------------------------------------------- -->
89 <title>Authors</title>
91 <para>The original authors of GTK+ were:</para>
93 <itemizedlist spacing=Compact>
95 <simpara>Peter Mattis</simpara>
98 <simpara>Spencer Kimball</simpara>
101 <simpara>Josh MacDonald</simpara>
105 <para>Since then, much has been added by others. Please see the
106 AUTHORS file in the distribution for the GTK+ Team.</para>
110 <!-- ----------------------------------------------------------------- -->
113 <title>What is GTK+?</title>
115 <para>GTK+ is a small and efficient widget set designed with
116 the general look and feel of Motif. In reality, it looks much
117 better than Motif. It contains common widgets and some more
118 complex widgets such as a file selection, and color selection
121 <para>GTK+ provides some unique features. (At least, I know of
122 no other widget library which provides them). For example, a
123 button does not contain a label, it contains a child widget,
124 which in most instances will be a label. However, the child
125 widget can also be a pixmap, image or any combination possible
126 the programmer desires. This flexibility is adhered to
127 throughout the library.</para>
131 <!-- ----------------------------------------------------------------- -->
134 <title>What is the + in GTK+?</title>
136 <para>Peter Mattis informed the gtk mailing list that:</para>
138 <para><quote>I originally wrote gtk which included the three
139 libraries, libglib, libgdk and libgtk. It featured a flat
140 widget hierarchy. That is, you couldn't derive a new widget
141 from an existing one. And it contained a more standard
142 callback mechanism instead of the signal mechanism now present
143 in gtk+. The + was added to distinguish between the original
144 version of gtk and the new version. You can think of it as
145 being an enhancement to the original gtk that adds object
146 oriented features.</quote></para>
150 <!-- ----------------------------------------------------------------- -->
153 <title>Does the G in GTK+, GDK and GLib stand for?</title>
155 <para>GTK+ == Gimp Toolkit</para>
156 <para>GDK == GTK+ Drawing Kit</para>
157 <para>GLib == G Library</para>
161 <!-- ----------------------------------------------------------------- -->
164 <title>Where is the documentation for GTK+?</title>
166 <para>In the GTK+ distribution's doc/ directory you will find
167 the reference material for both GTK and GDK, this FAQ and the
170 <para>In addition, you can find links to HTML versions of
171 these documents by going to <ulink url="http://www.gtk.org/">
172 http://www.gtk.org/</ulink>. A
173 packaged version of the GTK Tutorial, with SGML, HTML,
174 Postscript, DVI and text versions can be found in <ulink
175 url="ftp://ftp.gtk.org/pub/gtk/tutorial">
176 ftp://ftp.gtk.org/pub/gtk/tutorial
179 <para>There are now a couple of books available that deal with
180 programming GTK+, GDK and GNOME:</para>
183 <listitem><simpara>Eric Harlows book entitled "Developing
184 Linux Applications with GTK+ and GDK". The ISBN is
185 0-7357-0021-4</simpara>
187 <listitem><simpara>The example code from Eric's book is
188 available on-line at <ulink
189 url="http://www.bcpl.net/~eharlow/book">
190 http://www.bcpl.net/~eharlow/book</ulink></simpara>
192 <listitem><simpara>Havoc Pennington has released a book called
193 "GTK+/GNOME Application Development". The ISBN is
194 0-7357-0078-8</simpara>
195 <simpara>The free version of the book lives here: <ulink
196 url="http://developer.gnome.org/doc/GGAD/">
197 http://developer.gnome.org/doc/GGAD/
199 <simpara>And Havoc maintains information about it and
201 url="http://pobox.com/~hp/gnome-app-devel.html">
202 http://pobox.com/~hp/gnome-app-devel.html
209 <!-- ----------------------------------------------------------------- -->
212 <title>Is there a mailing list (or mailing list archive) for
215 <para>Information on mailing lists relating to GTK+ can be
217 url="http://www.gtk.org/mailinglists.html">
218 http://www.gtk.org/mailinglists.html
223 <!-- ----------------------------------------------------------------- -->
226 <title>How to get help with GTK+</title>
228 <para>First, make sure your question isn't answered in the
229 documentation, this FAQ or the tutorial. Done that? You're
230 sure you've done that, right? In that case, the best place to
231 post questions is to the GTK+ mailing list.</para>
235 <!-- ----------------------------------------------------------------- -->
238 <title>How to report bugs in GTK+</title>
240 <para>Bugs should be reported to the GNOME bug tracking system
241 (<ulink url="http://bugzilla.gnome.org">http://bugzilla.gnome.org</ulink>).
242 You will need to enter your email address and receive a password before
243 you can use the system to register a new bug report.</para>
245 <para>There are a number of options to select and boxes to fill in when
246 submitting a bug report. Please remember that the more information you
247 give, the easier it will be to track the problem down. Extra information
248 that may prove useful includes:</para>
251 <listitem><simpara> How to reproduce the bug.</simpara>
252 <simpara>If you can reproduce it with the testgtk program
253 that is built in the gtk/ subdirectory, that will be most
254 convenient. Otherwise, please include a short test program
255 that exhibits the behavior. As a last resort, you can also
256 provide a pointer to a larger piece of software that can
257 be downloaded.</simpara>
258 <simpara>(Bugs that can be reproduced within the GIMP are
259 almost as good as bugs that can be reproduced in
260 testgtk. If you are reporting a bug found with the GIMP,
261 please include the version number of the GIMP you are
265 <listitem><simpara> If the bug was a crash, the exact text that was
266 printed out when the crash occurred.</simpara>
269 <listitem><simpara> Further information such as stack traces
270 may be useful, but are not necessary. If you do send a stack trace,
271 and the error is an X error, it will be more useful if the stacktrace is
272 produced running the test program with the <literal>--sync</literal>
273 command line option.</simpara>
279 <!-- ----------------------------------------------------------------- -->
282 <title>Is there a Windows version of GTK+?</title>
284 <para>There is an on going port of GTK+ to the Windows
285 platform which is making impressive progress.</para>
288 url="http://www.iki.fi/tml/gimp/win32">
289 http://www.iki.fi/tml/gimp/win32</ulink>
290 for more information.</para>
294 <!-- ----------------------------------------------------------------- -->
297 <title>What applications have been written with GTK+?</title>
299 <para>A list of some GTK+ based application can be found on
300 the GTK+ web server at <ulink
301 url="http://www.gtk.org/apps/">http://www.gtk.org/apps/</ulink>
302 and contains more than 350 applications.</para>
304 <para>Failing that, look for a project to work on for the
305 GNOME project, <ulink
306 url="http://www.gnome.org/">http://www.gnome.org/</ulink>
307 Write a game. Write something that is useful.</para>
308 <para>Some of these are:</para>
311 <listitem><simpara> GIMP (<ulink
312 url="http://www.gimp.org/">http://www.gimp.org/</ulink>), an
313 image manipulation program</simpara>
315 <listitem><simpara> AbiWord (<ulink
316 url="http://www.abisource.com/">http://www.abisource.com/</ulink>),
317 a professional word processor</simpara>
319 <listitem><simpara> Gzilla (<ulink
320 url="http://www.levien.com/gzilla/">http://www.levien.com/gzilla/</ulink>),
321 a web browser</simpara>
323 <listitem><simpara> XQF (<ulink
324 url="http://www.botik.ru/~roma/quake/">
325 http://www.botik.ru/~roma/quake/</ulink>),
326 a QuakeWorld/Quake2 server browser and launcher</simpara>
328 <listitem><simpara> GDK Imlib (<ulink
329 url="http://www.rasterman.com/imlib.html">
330 http://www.rasterman.com/imlib.html</ulink>),
331 a fast image loading and manipulation library for GDK</simpara>
333 <listitem><simpara> Glade (<ulink
334 url="http://glade.pn.org/">http://glade.pn.org/</ulink>), a
335 GTK+ based RAD tool which produces GTK+ applications</simpara>
340 <!-- ----------------------------------------------------------------- -->
343 <title>I'm looking for an application to write in GTK+. How
344 about an IRC client?</title>
346 <para>Ask on gtk-list for suggestions. There are at least
347 three IRC clients already under development (probably more in fact. The
348 server at <ulink url="http://www.forcix.cx/irc-clients.html">
349 http://www.forcix.cx/irc-clients.html</ulink> list a bunch of
352 <itemizedlist spacing=compact>
353 <listitem><simpara> X-Chat.</simpara>
355 <listitem><simpara> girc. (Included with GNOME)</simpara>
357 <listitem><simpara> gsirc. (In the gnome CVS tree)</simpara>
365 <!-- ***************************************************************** -->
367 <title>How to find, configure, install, and troubleshoot GTK+</title>
369 <!-- ----------------------------------------------------------------- -->
372 <title>What do I need to run GTK+?</title>
374 <para>To compile GTK+, all you need is a C compiler (gcc) and
375 the X Window System and associated libraries on your system.</para>
379 <!-- ----------------------------------------------------------------- -->
382 <title>Where can I get GTK+?</title>
384 <para>The canonical site is <ulink
385 url="ftp://ftp.gtk.org/pub/gtk">ftp://ftp.gtk.org/pub/gtk</ulink>.</para>
387 <para>This site tends to get busy around the time of a new
388 GTK+ release so try and use one of the mirror sites that are
390 url="ftp://ftp.gtk.org/etc/mirrors">ftp://ftp.gtk.org/etc/mirrors
393 <para>Here's a few mirror sites to get you started:</para>
395 <itemizedlist spacing=compact>
396 <listitem><simpara> Africa -
397 <ulink url="ftp://ftp.is.co.za/applications/gimp">
398 ftp://ftp.is.co.za/applications/gimp</ulink></simpara>
400 <listitem><simpara> Australia -
402 url="ftp://ftp.au.gimp.org/pub/gimp">
403 ftp://ftp.au.gimp.org/pub/gimp</ulink></simpara>
405 <listitem><simpara> Finland -
406 <ulink url="ftp://ftp.funet.fi/pub/sci/graphics/packages/gimp">
407 ftp://ftp.funet.fi/pub/sci/graphics/packages/gimp</ulink></simpara>
409 <listitem><simpara> Germany -
410 <ulink url="ftp://infosoc.uni-koeln.de/pub/ftp.gimp.org">
411 ftp://infosoc.uni-koeln.de/pub/ftp.gimp.org"</ulink></simpara>
413 <listitem><simpara> Japan -
414 <ulink url="ftp://SunSITE.sut.ac.jp/pub/archives/packages/gimp">
415 ftp://SunSITE.sut.ac.jp/pub/archives/packages/gimp</ulink></simpara>
417 <listitem><simpara> UK -
418 <ulink url="ftp://ftp.flirble.org/pub/X/gimp">
419 ftp://ftp.flirble.org/pub/X/gimp</ulink></simpara>
421 <listitem><simpara> US -
422 <ulink url="ftp://ftp.insync.net/pub/mirrors/ftp.gimp.org">
423 ftp://ftp.insync.net/pub/mirrors/ftp.gimp.org</ulink></simpara>
428 <!-- ----------------------------------------------------------------- -->
431 <title>How do I configure/compile GTK+?</title>
433 <para>Generally, all you will need to do is issue the commands:</para>
435 <para><literallayout><literal>./configure</literal>
436 <literal>make</literal></literallayout></para>
438 <para>in the gtk+-version/ directory.</para>
441 <!-- ----------------------------------------------------------------- -->
444 <title>When compiling GTK+ I get an error like: <literal>make:
445 file `Makefile' line 456: Syntax error</literal></title>
447 <para>Make sure that you are using GNU make
448 (use <literal>make -v</literal>
449 to check). There are many weird and wonderful versions of make
450 out there, and not all of them handle the automatically
451 generated Makefiles.</para>
455 <!-- ----------------------------------------------------------------- -->
458 <title>I've compiled and installed GTK+, but I can't get any
459 programs to link with it! <emphasis>[GTK 2.x]</emphasis></title>
461 <para>This problem is most often encountered when the GTK+
462 libraries can't be found or are the wrong version. Generally,
463 the compiler will complain about an 'unresolved symbol'.</para>
465 <para>Make sure that the libraries can be
466 found. You want to edit <filename>/etc/ld.so.conf</filename> to
467 include the directories which contain the GTK libraries,
468 so it looks something like:</para>
470 <para><literallayout><literal>/usr/X11R6/lib</literal>
471 <literal>/usr/local/lib</literal></literallayout></para>
473 <para>Then you need to run /sbin/ldconfig as root. You can
474 find what libraries GTK requires using</para>
476 <para><literallayout><literal>pkg-config gtk+-2.0 --libs</literal>
477 </literallayout></para>
479 <para>If your system doesn't use ld.so to find libraries
480 (such as Solaris), then you will have to use the LD_LIBRARY_PATH
481 environment variable (or compile the path into your program, which I'm
482 not going to cover here). So, with a Bourne type shell you can do (if
483 your GTK libraries are in /usr/local/lib):</para>
485 <para><literallayout>
486 <literal>export LD_LIBRARY_PATH=/usr/local/lib</literal>
487 </literallayout></para>
489 <para>and in a csh, you can do:</para>
491 <para><literallayout>
492 <literal>setenv LD_LIBRARY_PATH /usr/local/lib</literal>
493 </literallayout></para>
497 <!-- ----------------------------------------------------------------- -->
500 <title>When installing a GTK+ application, configure reports
501 that it can't find GTK. <emphasis>[GTK 2.x]</emphasis></title>
503 <para>There are several common reasons for this:</para>
506 <listitem><simpara>You have an old version of GTK installed
507 somewhere. You should remove this old copy, but note that
508 this may break applications that have been compiled against
509 the old version.</simpara>
512 <listitem><simpara><literal>pkg-config</literal> (or another
513 component of GTK) isn't in your path, or there is an old
514 version on your system. Type:</simpara>
516 <para><literallayout>
517 <literal>pkg-config gtk+-2.0 --version</literal>
518 </literallayout></para>
520 <para>to check for both of these. If it returns a value
521 different from what you expect, then you have an old
522 version of GTK on your system.</para>
525 <listitem><simpara>The ./configure script can't find the GTK
526 libraries. As ./configure compiles various test programs, it needs to be
527 able to find the GTK libraries. See the question above
528 for help on this. </simpara></listitem>
531 <para>If none of the above help, then have a look in
532 config.log, which is generated by ./configure as it runs. At the
533 bottom will be the last action it took before failing. If it is a
534 section of source code, copy the source code to a file and compile it
535 with the line just above it in config.log. If the compilation is
536 successful, try executing it.</para>
542 <!-- ***************************************************************** -->
544 <title>Development of GTK+</title>
546 <!-- ----------------------------------------------------------------- -->
549 <title>Whats this CVS thing that everyone keeps talking about,
550 and how do I access it?</title>
552 <para>CVS is the Concurrent Version System and is a very
553 popular means of version control for software projects. It is
554 designed to allow multiple authors to be able to
555 simultanously operate on the same source tree. This source
556 tree is centrally maintained, but each developer has a local
557 mirror of this repository that they make their changes to.</para>
559 <para>The GTK+ developers use a CVS repository to store the
560 master copy of the current development version of GTK+. As
561 such, people wishing to contribute patches to GTK+ should
562 generate them against the CVS version. Normal people should
563 use the packaged releases.</para>
565 <para>The CVS toolset is available as RPM packages from the
566 usual RedHat sites. The latest version is available at <ulink
567 url="http://download.cyclic.com/pub/">http://download.cyclic.com/pub/
570 <para>Anyone can download the latest CVS version of GTK+ by
571 using anonymous access using the following steps:</para>
574 <listitem><simpara> In a bourne shell descendant (e.g. bash) type:</simpara>
575 <para><literallayout>
576 <literal>CVSROOT=':pserver:anonymous@anoncvs.gnome.org:/cvs/gnome'</literal>
577 <literal>export CVSROOT</literal>
578 </literallayout></para>
581 <listitem><simpara>Next, the first time the source tree is
582 checked out, a cvs login is needed. </simpara>
583 <para><literallayout>
584 <literal>cvs login</literal>
585 </literallayout></para>
586 <para>This will ask you for a password. There is no
587 password for cvs.gimp.org, so just enter a carriage return.</para>
590 <listitem><simpara>To get the tree and place it in a subdir of your
591 current working directory, issue the command:</simpara>
592 <para><literallayout>
593 <literal>cvs -z3 get gtk+</literal>
594 </literallayout></para>
595 <para>Note that with the GTK+ 1.1 tree, glib has been moved to
596 a separate CVS module, so if you don't have glib installed you will
597 need to get that as well:</para>
598 <para><literallayout>
599 <literal>cvs -z3 get glib</literal>
600 </literallayout></para>
606 <!-- ----------------------------------------------------------------- -->
609 <title>How can I contribute to GTK+?</title>
611 <para>It's simple. If something doesn't work like you think it
612 should in a program, check the documentation to make sure
613 you're not missing something. If it is a true bug or missing
614 feature, track it down in the GTK+ source, change it, and
615 then generate a patch in the form of a 'context diff'. This
616 can be done using a command such as <literal>diff -ru
617 <oldfile> <newfile></literal>. Then upload the patchfile
620 <para><literallayout>
621 <literal>ftp://ftp.gtk.org/incoming</literal>
622 </literallayout></para>
624 <para>along with a README file. Make sure you follow the
625 naming conventions or your patch will just be deleted! The
626 filenames should be of this form:</para>
628 <para><literallayout>
629 <literal>gtk<username>-<date yymmdd-n>.patch.gz</literal>
630 <literal>gtk-<username>-<date yymmdd-n>.patch.README</literal>
631 </literallayout></para>
633 <para>The "n" in the date indicates a unique number (starting
634 from 0) of patches you uploaded that day. It should be 0,
635 unless you upload more than one patch in the same day.</para>
637 <para>Example:</para>
639 <para><literallayout>
640 <literal>gtk-gale-982701-0.patch.gz</literal>
641 <literal>gtk-gale-982701-0.patch.README</literal>
642 </literallayout></para>
644 <para>Once you upload <emphasis>anything</emphasis>, send the README to
645 ftp-admin@gtk.org</para>
649 <!-- ----------------------------------------------------------------- -->
652 <title>How do I know if my patch got applied, and if not, why
655 <para>Uploaded patches will be moved to
656 <filename>ftp://ftp.gtk.org/pub/gtk/patches</filename> where one of the
657 GTK+ development team will pick them up. If applied, they will be moved
658 to <filename>/pub/gtk/patches/old</filename>.</para>
660 <para>Patches that aren't applied, for whatever reason, are
661 moved to <filename>/pub/gtk/patches/unapplied</filename> or
662 <filename>/pub/gtk/patches/outdated</filename>. At this point you can ask
663 on the <literal>gtk-list</literal> mailing list why your patch wasn't
664 applied. There are many possible reasons why patches may not
665 be applied, ranging from it doesn't apply cleanly, to it isn't
666 right. Don't be put off if your patch didn't make it first
671 <!-- ----------------------------------------------------------------- -->
674 <title>What is the policy on incorporating new widgets into
677 <para>This is up to the authors, so you will have to ask them
678 once you are done with your widget. As a general guideline,
679 widgets that are generally useful, work, and are not a
680 disgrace to the widget set will gladly be included.</para>
684 <!-- ----------------------------------------------------------------- -->
687 <title>Is anyone working on bindings for languages other than
690 <para>The GTK+ home page (<ulink
691 url="http://www.gtk.org/">http://www.gtk.org/</ulink>)
692 presents a list of GTK+ bindings.</para>
695 <listitem><simpara>There are several C++ wrappers for GTK+.</simpara>
698 <listitem><simpara>the gtkmm package, which is a wrapper for
699 GTK+. You can find the home page at <ulink
700 url="http://www.gtkmm.org">
701 http://www.gtkmm.org/</ulink>.</simpara>
704 <listitem><simpara>the VDK package, which was built as
705 the base package of a GTK+ application Borland-like
706 builder. The home page can be found at <ulink
707 url="http://vdkbuilder.sourceforge.net/">
708 http://vdkbuilder.sourceforge.net/</ulink>.</simpara>
711 <listitem><simpara>The wxWindows/Gtk package, a free C++ library for
712 cross-platform GUI development. The home page of this package is
713 <ulink url="http://www.wxwindows.org/">
714 http://www.wxwindows.org/</ulink>.</simpara>
720 <listitem><simpara>There are three known Objective-c
721 bindings currently in development:</simpara>
724 <listitem><simpara>The <ulink
725 url="http://www.gnome.org/">http://www.gnome.org/</ulink>
726 package of choice is objgtk. Objgtk is based on the Object class and
727 is maintained by <ulink url="mailto:sopwith@cuc.edu">Elliot
728 Lee</ulink>. Apparently, objgtk is being accepted as the `standard'
729 Objective-C binding for GTK+.</simpara>
732 <listitem><simpara>If you are more inclined towards the
733 <ulink url="http://www.gnustep.org/">GNUstep project</ulink>,
734 you may want to check out GTKKit by
735 <ulink url="mailto:helge@mdlink.de">Helge Heß</ulink>.
736 The intention is to setup a GTK+ binding using the FoundationKit.
737 GTKKit includes nicities like writing a XML-type template file to
738 construct a GTK+ interface.</simpara>
741 <listitem><simpara>The GToolKit package, which can be found at
742 <ulink url="ftp://ftp.gtk.org/pub/gtk/objc-gtoolkit/">
743 ftp://ftp.gtk.org/pub/gtk/objc-gtoolkit/</ulink>.</simpara>
749 <listitem><simpara>Perl bindings <ulink
750 url="ftp://ftp.gtk.org/pub/gtk/perl">
751 ftp://ftp.gtk.org/pub/gtk/perl</ulink></simpara>
754 <listitem><simpara>Guile bindings. The home page is at
755 <ulink url="http://www.ping.de/sites/zagadka/guile-gtk">
756 http://www.ping.de/sites/zagadka/guile-gtk</ulink>.
757 By the way, Guile is the GNU Project's implemention of R4RS Scheme (the
758 standard). If you like Scheme, you may want to take a look at
762 <listitem><simpara>David Monniaux reports:
763 <quote>I've started a gtk-O'Caml binding system.
764 The basics of the system, including callbacks, work fine.
766 The current development is in
767 <ulink url="http://www.ens-lyon.fr/~dmonniau/arcs">
768 http://www.ens-lyon.fr/~dmonniau/arcs</ulink>
772 <listitem><simpara>Several python bindings have been done:</simpara>
775 <listitem><simpara>pygtk is at
776 <ulink url="http://www.daa.com.au/~james/pygtk">
777 http://www.daa.com.au/~james/pygtk</ulink> and
778 <ulink url="ftp://ftp.gtk.org/pub/gtk/python">
779 ftp://ftp.gtk.org/pub/gtk/python</ulink></simpara>
782 <listitem><simpara>python-gtk is at
783 <ulink url="http://www.ucalgary.ca/~nascheme/python-gtk">
784 http://www.ucalgary.ca/~nascheme/python-gtk</ulink></simpara>
790 <listitem><simpara>There's are a couple of OpenGL/Mesa
791 widgets available for GTK+. I suggest you start at
792 <ulink url="http://www.student.oulu.fi/~jlof/gtkglarea/index.html">
793 http://www.student.oulu.fi/~jlof/gtkglarea/index.html</ulink></simpara>
795 <listitem><simpara>Last, there are a lot of other language
796 bindings for languages such as Eiffel, TOM, Pascal, Pike, etc.</simpara>
804 <!-- ***************************************************************** -->
806 <title>Development with GTK+: the begining</title>
808 <!-- ----------------------------------------------------------------- -->
811 <title>How do I get started?</title>
813 <para>So, after you have installed GTK+ there are a couple of
814 things that can ease you into developing applications with
815 it. There is the GTK+ Tutorial <ulink
816 url="http://www.gtk.org/tutorial/">
817 http://www.gtk.org/tutorial/</ulink>, which is undergoing
818 development. This will introduce you to writing applications
821 <para>The Tutorial doesn't (yet) contain information on all of
822 the widgets that are in GTK+. For example code on how to use
823 the basics of all the GTK+ widgets you should look at the file
824 gtk/testgtk.c (and associated source files) within the GTK+
825 distribution. Looking at these examples will give you a good
826 grounding on what the widgets can do.</para>
830 <!-- ----------------------------------------------------------------- -->
833 <title>How do I use the Glade GUI builder with GTK+? <emphasis>[GTK 2.x]</emphasis></title>
835 <para>There are two ways to use Glade. The first way is to use
836 Glade's facilities for generating code; the second
837 way is to use the libglade library which directly loads
838 the XML user interface description files that Glade
839 generates into a running program.</para>
841 Experienced GTK+ programmers generally strongly recommend
842 using libglade; you don't have to worry about the interaction
843 between Glade generating the source and you editing it,
844 and its been shown to be a method that works better
845 for large projects, so there is a lot of example code
846 out there you can look at.</para>
848 <para>An introduction to using libglade can be found in the
850 (<ulink url="http://developer.gnome.org/doc/API/2.0/libglade/libglade-notes.html#libglade-basics">
851 http://developer.gnome.org/doc/API/2.0/libglade/libglade-notes.html#libglade-basics</ulink>)
856 <!-- ----------------------------------------------------------------- -->
859 <title>How do I write security sensitive/SUID/SGID programs with GTK+?
860 Is GTK+ secure? What's this GTK_MODULES security hole I heard about?</title>
862 <para>The short answer to this question is: Don't write SUID/SGID
863 programs with GTK+</para>
865 <para>For a more thorough explanation of the GTK+ Developers position on
866 this issue see <ulink
867 url="http://www.gtk.org/setuid.html">http://www.gtk.org/setuid.html</ulink>.</para>
871 <!-- ----------------------------------------------------------------- -->
874 <title>I tried to compile a small <command>Hello World</command> of mine,
875 but it failed. Any clue? <emphasis>[GTK 2.x]</emphasis></title>
877 <para>Since you are good at coding, we will not deal with
878 compile time error here :)</para>
880 <para>The classic command line to compile a GTK+ based program is</para>
881 <para><literallayout>
882 <literal>gcc -o myprog [c files] `pkg-config gtk+-2.0 --cflags --libs`</literal>
883 </literallayout></para>
885 <para>You should notice the backquote character which is used
886 in this command line. A common mistake when you start a GTK+
887 based development is to use quote instead of backquotes. If
888 you do so, the compiler will complain about an unknown file
889 called <filename>pkg-config gtk+-2.0 --cflags --libs</filename>. The
890 text in backquotes is an instruction to your shell to
891 substitute the output of executing this command into the
894 <para>The command line above ensures that:</para>
897 <listitem><simpara>the correct C compiler flags will be used
898 to compile the program (including the complete C header
899 directory list)</simpara>
902 <listitem><simpara>your program will be linked with the
903 needed libraries.</simpara>
909 <!-- ----------------------------------------------------------------- -->
912 <title>What about using the <command>make</command>
913 utility? <emphasis>[GTK 2.x]</emphasis></title>
915 <para>This is a sample makefile which compile a GTK+ based
918 <programlisting role="C">
919 # basic GTK+ app makefile
920 SOURCES = myprg.c foo.c bar.c
921 OBJS = ${SOURCES:.c=.o}
922 CFLAGS = `pkg-config gtk+-2.0 --cflags`
923 LDADD = `pkg-config gtk+-2.0 --libs`
928 ${CC} -o ${PACKAGE} ${OBJS} ${LDADD}
931 ${CC} ${CFLAGS} -c $<
936 <para>For more information about the <command>make</command> utility, you
937 should read either the related man page or the relevant info file.</para>
941 <!-- ----------------------------------------------------------------- -->
944 <title>I use the backquote stuff in my makefiles, but my make
945 process failed.</title>
947 <para>The backquote construction seems to not be accepted by
948 some old <command>make</command> utilities. If you use one of these, the
949 make process will probably fail. In order to have the
950 backquote syntax working again, you should use the GNU make
951 utility (get it on the GNU ftp server at <ulink
952 url="ftp://ftp.gnu.org/">ftp://ftp.gnu.org/</ulink>).</para>
956 <!-- ----------------------------------------------------------------- -->
959 <title>I want to add some configure stuff, how could I do
962 <para>To use autoconf/automake, you must first install the
963 relevant packages. These are:</para>
965 <itemizedlist spacing=Compact>
966 <listitem><simpara>the m4 preprocessor v1.4 or better</simpara>
969 <listitem><simpara>autoconf v2.13 or better</simpara>
972 <listitem><simpara>automake v1.4 or better</simpara>
976 <para>You'll find these packages on the GNU main ftp server
977 (<ulink url="ftp://ftp.gnu.org/">ftp://ftp.gnu.org/</ulink>)
978 or on any GNU mirror.</para>
980 <para>In order to use the powerful autoconf/automake scheme,
981 you must create a configure.in which may look like:</para>
983 <programlisting role="C">
984 dnl Process this file with autoconf to produce a configure script.
985 dnl configure.in for a GTK+ based program
988 AM_INIT_AUTOMAKE(mypkgname,0.0.1)dnl
989 AM_CONFIG_HEADER(config.h)dnl
991 dnl Checks for programs.
992 AC_PROG_CC dnl check for the c compiler
993 dnl you should add CFLAGS="" here, 'cos it is set to -g by PROG_CC
995 dnl Checks for libraries.
996 AM_PATH_GTK(1.2.0,,AC_MSG_ERROR(mypkgname 0.1 needs GTK))dnl
1003 <para>You must add a Makefile.am file:</para>
1005 <programlisting role="C">
1006 bin_PROGRAMS = myprg
1007 myprg_SOURCES = myprg.c foo.c bar.c
1008 INCLUDES = @GTK_CFLAGS@
1011 DISTCLEANFILES = .deps/*.P
1014 <para>If your project contains more than one subdirectory,
1015 you'll have to create one Makefile.am in each directory plus a
1016 master Makefile.am which will look like:</para>
1018 <programlisting role="C">
1019 SUBDIRS = mydir1 mydir2 mydir3
1022 <para>then, to use these, simply type the following
1025 <programlisting role="C">
1029 automake --add-missing --include-deps --foreign
1032 <para>For further information, you should look at the autoconf
1033 and the automake documentation (the shipped info files are
1034 really easy to understand, and there are plenty of web
1035 resources that deal with autoconf and automake).</para>
1039 <!-- ----------------------------------------------------------------- -->
1042 <title>I try to debug my GTK+ application with gdb, but it
1043 hangs my X server when I hit some breakpoint. Any
1046 <para>From Federico Mena Quintero:</para>
1048 <para><quote>X is not locked up. It is likely that you are hitting a
1049 breakpoint inside a callback that is called from a place in Gtk that has
1050 a mouse grab.</quote></para>
1052 <para><quote>Run your program with the <literal>--sync</literal>
1053 option; it will make it easier to debug. Also, you may want to
1054 use the console for running the debugger, and just let the
1055 program run in another console with the X server.</quote></para>
1057 <para>Eric Mouw had another solution:</para>
1059 <para><quote>An old terminal connected to an otherwise unused serial
1060 port is also great for debugging X programs. Old vt100/vt220
1061 terminals are dirt cheap but a bit hard to get (here in The
1062 Netherlands, YMMV).</quote></para>
1067 <!-- ***************************************************************** -->
1069 <title>Development with GTK+: general questions</title>
1071 <!-- ----------------------------------------------------------------- -->
1074 <title>What widgets are in GTK?</title>
1076 <para>The GTK+ Tutorial lists the following widgets:</para>
1078 <programlisting role="C">
1089 | | | `GtkAspectFrame
1094 | | | | `GtkCheckMenuItem
1095 | | | | `GtkRadioMenuItem
1099 | | +GtkColorSelectionDialog
1101 | | | `GtkInputDialog
1102 | | `GtkFileSelection
1105 | | | +GtkHButtonBox
1106 | | | `GtkVButtonBox
1111 | | +GtkColorSelection
1115 | | `GtkToggleButton
1129 | +GtkScrolledWindow
1163 <!-- ----------------------------------------------------------------- -->
1166 <title>Is GTK+ thread safe? How do I write multi-threaded GTK+
1167 applications? <emphasis>[GTK 2.x]</emphasis></title>
1169 <para>The GLib library can be used in a thread-safe mode by
1170 calling g_thread_init() before making any other GLib
1171 calls. In this mode GLib automatically locks all internal
1172 data structures as needed. This does not mean that two
1173 threads can simultaneously access, for example, a single hash
1174 table, but they can access two different hash tables
1175 simultaneously. If two different threads need to access the
1176 same hash table, the application is responsible for locking
1179 <para>In order to make GDK thread aware, you also need to
1180 call gdk_threads_init() in conjunction with the above call.
1181 There is a single global
1182 lock that you must acquire with gdk_threads_enter() before
1183 making any GDK calls, and release with gdk_threads_leave()
1184 afterwards throughout your code.</para>
1186 <para>A minimal main program for a threaded GTK+ application
1189 <programlisting role="C">
1191 main (int argc, char *argv[])
1196 g_thread_init(NULL);
1200 gtk_init(&argc, &argv);
1202 window = create_window();
1203 gtk_widget_show(window);
1205 gdk_threads_enter();
1207 gdk_threads_leave();
1213 <para>Callbacks require a bit of attention. Callbacks from
1214 GTK+ (signals) are made within the GTK+ lock. However
1215 callbacks from GLib (timeouts, IO callbacks, and idle
1216 functions) are made outside of the GTK+ lock. So, within a
1217 signal handler you do not need to call gdk_threads_enter(),
1218 but within the other types of callbacks, you do.</para>
1220 <para>Erik Mouw contributed the following code example to
1221 illustrate how to use threads within GTK+ programs.</para>
1223 <programlisting role="C">
1224 /*-------------------------------------------------------------------------
1225 * Filename: gtk-thread.c
1227 * Copyright: Copyright (C) 1999, Erik Mouw
1228 * Author: Erik Mouw <J.A.K.Mouw@its.tudelft.nl>
1229 * Description: GTK threads example.
1230 * Created at: Sun Oct 17 21:27:09 1999
1231 * Modified by: Owen Taylor <otaylor@gtk.org>
1232 * Modified at: Wed May 28 10:43:00 2003
1233 *-----------------------------------------------------------------------*/
1237 * cc -o gtk-thread gtk-thread.c `pkg-config --cflags --libs gtk+-2.0 gthread`
1239 * Thanks to Sebastian Wilhelmi for pointing out some bugs in earlier versions.
1243 #include <unistd.h>
1244 #include <gtk/gtk.h>
1246 #define YES_IT_IS (1)
1247 #define NO_IT_IS_NOT (0)
1255 G_LOCK_DEFINE_STATIC (yes_or_no);
1256 static volatile int yes_or_no = YES_IT_IS;
1258 void destroy(GtkWidget *widget, gpointer data)
1263 void *argument_thread(void *args)
1265 yes_or_no_args *data = (yes_or_no_args *)args;
1266 gboolean say_something;
1271 sleep(g_random_int_range (1, 4));
1273 /* lock the yes_or_no_variable */
1276 /* do we have to say something? */
1277 say_something = (yes_or_no != data->what);
1281 /* set the variable */
1282 yes_or_no = data->what;
1285 /* Unlock the yes_or_no variable */
1286 G_UNLOCK(yes_or_no);
1290 /* get GTK thread lock */
1291 gdk_threads_enter();
1293 /* set label text */
1294 if(data->what == YES_IT_IS)
1295 gtk_label_set_text(GTK_LABEL(data->label), "O yes, it is!");
1297 gtk_label_set_text(GTK_LABEL(data->label), "O no, it isn't!");
1299 /* Make sure all X commands are sent to the X server; not strictly
1300 * necessary here, but always a good idea when you do anything
1301 * from a thread other than the one where the main loop is running.
1305 /* release GTK thread lock */
1306 gdk_threads_leave();
1313 int main(int argc, char *argv[])
1317 GError *error = NULL;
1318 yes_or_no_args yes_args, no_args;
1321 g_thread_init(NULL);
1325 gtk_init(&argc, &argv);
1327 /* create a window */
1328 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1330 g_signal_connect(window, "destroy",
1331 G_CALLBACK(destroy), NULL);
1333 gtk_container_set_border_width(GTK_CONTAINER (window), 10);
1335 /* create a label */
1336 label = gtk_label_new("And now for something completely different ...");
1337 gtk_container_add(GTK_CONTAINER(window), label);
1339 /* show everything */
1340 gtk_widget_show(label);
1341 gtk_widget_show (window);
1343 /* create the threads */
1344 yes_args.label = label;
1345 yes_args.what = YES_IT_IS;
1346 if (!g_thread_create(argument_thread, &yes_args, FALSE, &error))
1348 g_printerr ("Failed to create YES thread: %s\n", error->message);
1352 no_args.label = label;
1353 no_args.what = NO_IT_IS_NOT;
1354 if (!g_thread_create(argument_thread, &no_args, FALSE, &error))
1356 g_printerr ("Failed to create NO thread: %s\n", error->message);
1360 /* enter the GTK main loop */
1361 gdk_threads_enter();
1363 gdk_threads_leave();
1370 <!-- ----------------------------------------------------------------- -->
1373 <title>I'm doing some stuff with GTK+ in a separate thread, and
1374 properly locking with gdk_threads_enter/gdk_threads_leave()
1375 but the display doesn't update properly. <emphasis>[GTK 2.x]</emphasis>
1378 <para>For efficiency, the X window system batches up commands
1379 and sends them to the X server in batches instead of sending
1380 out immediately.</para>
1382 <para>In a non-multithreaded program, you don't have to worry about
1383 this, since the first thing that happens when control returns
1384 to the main loop is that any outstanding X requests are
1385 sent to the X server.</para>
1387 <para>However, if you are making GTK+ calls from a thread other
1388 than the main loop, then GTK+ doesn't know when to send batched
1389 commands out. For that reason, after making GTK+ calls
1390 in a separate thread, it is usually a good idea to call
1391 gdk_flush() before gdk_thread_leave().</para>
1393 <para>Actually, gdk_flush() is more expensive than is necessary here,
1394 since it waits for the X server to finish outstanding commands
1395 as well; if performance is an issue, you may want to call
1396 XFlush() directly:</para>
1398 <programlisting role="C">
1400 #include <gdk/gdkx.h>
1402 void my_flush_commands (void)
1404 GdkDisplay *display = gdk_display_get_default ();
1405 XFlush (GDK_DISPLAY_XDISPLAY (display);
1411 <!-- ----------------------------------------------------------------- -->
1414 <title>What's an easy way to run a function in the thread with
1415 the main loop? <emphasis>[GTK 2.x]</emphasis></title>
1417 <para>Sometimes the simplest way to set up a threaded program
1418 is to make all the GTK+ calls in a single thread. In such
1419 a program, you should still call g_threads_init(), but
1420 don't need to call gdk_threads_init(), gkd_threads_enter(),
1421 and gdk_threads_leave().</para>
1423 <para>If you set your program up this way, how then do you get
1424 the thread making GTK+ calls and running the main loop
1425 to do something in response to another thread?</para>
1427 <para>An easy way to do it is to take advantage of the fact that
1428 the GLib main loop functions are all thread safe, and can
1429 be called from any thread by adding an idle function
1430 with g_idle_add(). The function provided will be called
1431 at the next opportunity by the main thread. If you want
1432 your function to take priority over event handling and
1433 drawing, you can instead use g_idle_add_full() and pass
1434 in a priority of G_PRIORITY_HIGH.</para>
1438 <!-- ----------------------------------------------------------------- -->
1441 <title>Why does this strange 'x io error' occur when I
1442 <literal>fork()</literal> in my GTK+ app?</title>
1444 <para>This is not really a GTK+ problem, and the problem is
1445 not related to <literal>fork()</literal> either. If the 'x io
1446 error' occurs then you probably use the <literal>exit()</literal> function
1447 in order to exit from the child process.</para>
1449 <para>When GDK opens an X display, it creates a socket file
1450 descriptor. When you use the <literal>exit()</literal>
1451 function, you implicitly close all the open file descriptors,
1452 and the underlying X library really doesn't like this.</para>
1454 <para>The right function to use here is
1455 <literal>_exit()</literal>.</para>
1457 <para>Erik Mouw contributed the following code example to
1458 illustrate handling fork() and exit().</para>
1460 <programlisting role="C">
1461 /*-------------------------------------------------------------------------
1462 * Filename: gtk-fork.c
1464 * Copyright: Copyright (C) 1999, Erik Mouw
1465 * Author: Erik Mouw <J.A.K.Mouw@its.tudelft.nl>
1466 * Description: GTK+ fork example
1467 * Created at: Thu Sep 23 21:37:55 1999
1468 * Modified by: Erik Mouw <J.A.K.Mouw@its.tudelft.nl>
1469 * Modified at: Thu Sep 23 22:39:39 1999
1470 *-----------------------------------------------------------------------*/
1474 * cc -o gtk-fork gtk-fork.c `pkg-config gtk+-2.0 --cflags --libs`
1478 #include <stdio.h>
1479 #include <stdlib.h>
1480 #include <signal.h>
1481 #include <sys/types.h>
1482 #include <sys/wait.h>
1483 #include <unistd.h>
1484 #include <gtk/gtk.h>
1486 void sigchld_handler(int num)
1488 sigset_t set, oldset;
1490 int status, exitstatus;
1492 /* block other incoming SIGCHLD signals */
1493 sigemptyset(&set);
1494 sigaddset(&set, SIGCHLD);
1495 sigprocmask(SIG_BLOCK, &set, &oldset);
1497 /* wait for child */
1498 while((pid = waitpid((pid_t)-1, &status, WNOHANG)) > 0)
1500 if(WIFEXITED(status))
1502 exitstatus = WEXITSTATUS(status);
1505 "Parent: child exited, pid = %d, exit status = %d\n",
1506 (int)pid, exitstatus);
1508 else if(WIFSIGNALED(status))
1510 exitstatus = WTERMSIG(status);
1513 "Parent: child terminated by signal %d, pid = %d\n",
1514 exitstatus, (int)pid);
1516 else if(WIFSTOPPED(status))
1518 exitstatus = WSTOPSIG(status);
1521 "Parent: child stopped by signal %d, pid = %d\n",
1522 exitstatus, (int)pid);
1527 "Parent: child exited magically, pid = %d\n",
1532 /* re-install the signal handler (some systems need this) */
1533 signal(SIGCHLD, sigchld_handler);
1535 /* and unblock it */
1536 sigemptyset(&set);
1537 sigaddset(&set, SIGCHLD);
1538 sigprocmask(SIG_UNBLOCK, &set, &oldset);
1541 gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
1546 void destroy(GtkWidget *widget, gpointer data)
1551 void fork_me(GtkWidget *widget, gpointer data)
1559 /* ouch, fork() failed */
1566 fprintf(stderr, "Child: pid = %d\n", (int)getpid());
1568 execlp("ls", "ls", "-CF", "/", NULL);
1570 /* if exec() returns, there is something wrong */
1573 /* exit child. note the use of _exit() instead of exit() */
1579 fprintf(stderr, "Parent: forked a child with pid = %d\n", (int)pid);
1583 int main(int argc, char *argv[])
1588 gtk_init(&argc, &argv);
1590 /* the basic stuff: make a window and set callbacks for destroy and
1593 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1595 gtk_signal_connect(GTK_OBJECT (window), "delete_event",
1596 GTK_SIGNAL_FUNC(delete_event), NULL);
1598 gtk_signal_connect(GTK_OBJECT (window), "destroy",
1599 GTK_SIGNAL_FUNC(destroy), NULL);
1601 #if (GTK_MAJOR_VERSION == 1) && (GTK_MINOR_VERSION == 0)
1602 gtk_container_border_width(GTK_CONTAINER (window), 10);
1604 gtk_container_set_border_width(GTK_CONTAINER (window), 10);
1607 /* add a button to do something usefull */
1608 button = gtk_button_new_with_label("Fork me!");
1610 gtk_signal_connect(GTK_OBJECT (button), "clicked",
1611 GTK_SIGNAL_FUNC(fork_me), NULL);
1613 gtk_container_add(GTK_CONTAINER(window), button);
1615 /* show everything */
1616 gtk_widget_show (button);
1617 gtk_widget_show (window);
1620 /* install a signal handler for SIGCHLD signals */
1621 signal(SIGCHLD, sigchld_handler);
1632 <!-- ----------------------------------------------------------------- -->
1635 <title>Why don't the contents of a button move when the button
1636 is pressed? Here's a patch to make it work that way...</title>
1638 <para>From: Peter Mattis</para>
1640 <para><quote>The reason buttons don't move their child down and to
1641 the right when they are depressed is because I don't think
1642 that's what is happening visually. My view of buttons is
1643 that you are looking at them straight on. That is, the user
1644 interface lies in a plane and you're above it looking
1645 straight at it. When a button gets pressed it moves directly
1646 away from you. To be absolutely correct I guess the child
1647 should actually shrink a tiny amount. But I don't see why
1648 the child should shift down and to the left. Remember, the
1649 child is supposed to be attached to the buttons surface. Its
1650 not good for it to appear like the child is slipping on the
1651 surface of the button.</quote></para>
1653 <para><quote>On a more practical note, I did implement this at one point
1654 and determined it didn't look good and removed it.</quote></para>
1658 <!-- ----------------------------------------------------------------- -->
1661 <title>How do I identifiy a widgets top level window or other
1664 <para>There are a couple of ways to find the top level parent
1665 of a widget. The easier way is to call the
1666 <literal>gtk_widget_get_toplevel()</literal> function that
1667 returns pointer to a GtkWidget that is the top level
1670 <para>A more complicated way to do this (but less limited, as
1671 it allows the user to get the closest ancestor of a known type) is to use
1672 <literal>gtk_widget_get_ancestor()</literal> as in:</para>
1674 <programlisting role="C">
1676 widget = gtk_widget_get_ancestor(w, GTK_TYPE_WINDOW);
1679 <para>Since virtually all the GTK_TYPEs can be used as the
1680 second parameter of this function, you can get any parent
1681 widget of a particular widget. Suppose you have an hbox which
1682 contains a vbox, which in turn contains some other atomic
1683 widget (entry, label, etc. To find the master hbox using the
1684 <literal>entry</literal> widget simply use:</para>
1686 <programlisting role="C">
1688 hbox = gtk_widget_get_ancestor(w, GTK_TYPE_HBOX);
1693 <!-- ----------------------------------------------------------------- -->
1696 <title>How do I get the Window ID of a GtkWindow?</title>
1698 <para>The actual Gdk/X window will be created when the widget
1699 gets realized. You can get the Window ID with:</para>
1701 <programlisting role="C">
1702 #include <gdk/gdkx.h>
1704 Window xwin = GDK_WINDOW_XWINDOW (GTK_WIDGET (my_window)->window);
1708 <!-- ----------------------------------------------------------------- -->
1711 <title>How do I catch a double click event (in a list widget,
1712 for example)?</title>
1714 <para>Tim Janik wrote to gtk-list (slightly modified):</para>
1716 <para>Define a signal handler:</para>
1718 <programlisting role="C">
1720 signal_handler_event(GtkWidget *widget, GdkEventButton *event, gpointer func_data)
1722 if (GTK_IS_LIST_ITEM(widget) &&
1723 (event->type==GDK_2BUTTON_PRESS ||
1724 event->type==GDK_3BUTTON_PRESS) ) {
1725 printf("I feel %s clicked on button %d\n",
1726 event->type==GDK_2BUTTON_PRESS ? "double" : "triple",
1733 <para>And connect the handler to your object:</para>
1735 <programlisting role="C">
1737 /* list, list item init stuff */
1739 gtk_signal_connect(GTK_OBJECT(list_item),
1740 "button_press_event",
1741 GTK_SIGNAL_FUNC(signal_handler_event),
1746 gtk_signal_connect(GTK_OBJECT(list_item),
1747 "button_release_event",
1748 GTK_SIGNAL_FUNC(signal_handler_event),
1751 /* something else */
1755 <para>and, Owen Taylor wrote:</para>
1757 <para><quote>Note that a single button press will be received
1758 beforehand, and if you are doing this for a button, you will
1759 therefore also get a "clicked" signal for the button. (This
1760 is going to be true for any toolkit, since computers aren't
1761 good at reading one's mind.)</quote></para>
1765 <!-- ----------------------------------------------------------------- -->
1768 <title>By the way, what are the differences between signals
1771 <para>First of all, Havoc Pennington gives a rather complete
1772 description of the differences between events and signals in
1773 his free book (two chapters can be found at <ulink
1774 url="http://www106.pair.com/rhp/sample_chapters.html">
1775 http://www106.pair.com/rhp/sample_chapters.html</ulink>).</para>
1777 <para>Moreover, Havoc posted this to the <literal>gtk-list</literal>
1778 <quote>Events are a stream of messages received from the X
1779 server. They drive the Gtk main loop; which more or less
1780 amounts to "wait for events, process them" (not exactly, it
1781 is really more general than that and can wait on many
1782 different input streams at once). Events are a Gdk/Xlib
1783 concept.</quote></para>
1785 <para><quote>Signals are a feature of GtkObject and its subclasses. They
1786 have nothing to do with any input stream; really a signal is just a way
1787 to keep a list of callbacks around and invoke them ("emit" the
1788 signal). There are lots of details and extra features of
1789 course. Signals are emitted by object instances, and are entirely
1790 unrelated to the Gtk main loop. Conventionally, signals are emitted
1791 "when something changes" about the object emitting the
1792 signal.</quote></para>
1794 <para><quote>Signals and events only come together because GtkWidget
1795 happens to emit signals when it gets events. This is purely a
1796 convenience, so you can connect callbacks to be invoked when a
1797 particular widget receives a particular event. There is nothing about
1798 this that makes signals and events inherently related concepts, any more
1799 than emitting a signal when you click a button makes button clicking and
1800 signals related concepts.</quote></para>
1804 <!-- ----------------------------------------------------------------- -->
1807 <title>Data I pass to the <literal>delete_event</literal> (or other event)
1808 handler gets corrupted.</title>
1810 <para>All event handlers take an additional argument which
1811 contains information about the event that triggered the
1812 handler. So, a <literal>delete_event</literal> handler must
1813 be declared as:</para>
1816 <programlisting role="C">
1817 gint delete_event_handler (GtkWidget *widget,
1824 <!-- ----------------------------------------------------------------- -->
1827 <title>I have my signal connected to the the (whatever) event,
1828 but it seems I don't catch it. What's wrong?</title>
1830 <para>There is some special initialisation to do in order to
1831 catch some particular events. In fact, you must set the
1832 correct event mask bit of your widget before getting some
1833 particular events.</para>
1835 <para>For example,</para>
1837 <programlisting role="C">
1838 gtk_widget_add_events(window, GDK_KEY_RELEASE_MASK);
1841 <para>lets you catch the key release events. If you want to
1842 catch every events, simply us the GDK_ALL_EVENTS_MASK event
1845 <para>All the event masks are defined in the
1846 <filename>gdktypes.h</filename> file.</para>
1850 <!-- ----------------------------------------------------------------- -->
1853 <title>I need to add a new signal to a GTK+ widget. Any
1856 <para>If the signal you want to add may be beneficial for
1857 other GTK+ users, you may want to submit a patch that
1858 presents your changes. Check the tutorial for more
1859 information about adding signals to a widget class.</para>
1861 <para>If you don't think it is the case or if your patch is
1862 not applied you'll have to use the
1863 <literal>gtk_object_class_user_signal_new</literal>
1864 function. <literal>gtk_object_class_user_signal_new</literal> allows you
1865 to add a new signal to a predefined GTK+ widget without any
1866 modification of the GTK+ source code. The new signal can be
1867 emited with <literal>gtk_signal_emit</literal> and can be
1868 handled in the same way as other signals.</para>
1870 <para>Tim Janik posted this code snippet:</para>
1872 <programlisting role="C">
1873 static guint signal_user_action = 0;
1875 signal_user_action =
1876 gtk_object_class_user_signal_new (gtk_type_class (GTK_TYPE_WIDGET),
1878 GTK_RUN_LAST | GTK_RUN_ACTION,
1879 gtk_marshal_NONE__POINTER,
1884 gtk_widget_user_action (GtkWidget *widget,
1887 g_return_if_fail (GTK_IS_WIDGET (widget));
1889 gtk_signal_emit (GTK_OBJECT (widget), signal_user_action, act_data);
1893 <para>If you want your new signal to have more than the
1894 classical gpointer parameter, you'll have to play with GTK+
1899 <!-- ----------------------------------------------------------------- -->
1902 <title>Is it possible to get some text displayed which is
1903 truncated to fit inside its allocation?</title>
1905 <para>GTK's behavior (no clipping) is a consequence of its
1906 attempts to conserve X resources. Label widgets (among
1907 others) don't get their own X window - they just draw their
1908 contents on their parent's window. While it might be possible
1909 to have clipping occur by setting the clip mask before
1910 drawing the text, this would probably cause a substantial
1911 performance penalty.</para>
1913 <para>Its possible that, in the long term, the best solution
1914 to such problems might be just to change gtk to give labels X
1915 windows. A short term workaround is to put the label widget
1916 inside another widget that does get its own window - one
1917 possible candidate would be the viewport widget.</para>
1919 <programlisting role="C">
1920 viewport = gtk_viewport (NULL, NULL);
1921 gtk_widget_set_usize (viewport, 50, 25);
1922 gtk_viewport_set_shadow_type (GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1923 gtk_widget_show(viewport);
1925 label = gtk_label ("a really long label that won't fit");
1926 gtk_container_add (GTK_CONTAINER(viewport), label);
1927 gtk_widget_show (label);
1930 <para>If you were doing this for a bunch of widgets, you might
1931 want to copy gtkviewport.c and strip out the adjustment and
1932 shadow functionality (perhaps you could call it
1936 <!-- ----------------------------------------------------------------- -->
1939 <title>How do I make my window modal? / How do I make a single
1940 window active?</title>
1942 <para>After you create your window, do
1943 <literal>gtk_grab_add(my_window)</literal>. And after closing the window
1944 do <literal>gtk_grab_remove(my_window)</literal>.</para>
1948 <!-- ----------------------------------------------------------------- -->
1951 <title>Why doesn't my widget (e.g. progressbar)
1954 <para>You are probably doing all the changes within a function without
1955 returning control to <literal>gtk_main()</literal>. This may
1956 be the case if you do some lengthy calculation in your
1957 code. Most drawing updates are only placed on a queue, which
1958 is processed within <literal>gtk_main()</literal>. You can force the
1959 drawing queue to be processed using something like:</para>
1962 <programlisting role="C">
1963 while (g_main_iteration(FALSE));
1966 <para>inside you're function that changes the widget.</para>
1968 <para>What the above snippet does is run all pending events
1969 and high priority idle functions, then return immediately
1970 (the drawing is done in a high priority idle function).</para>
1974 <!-- ----------------------------------------------------------------- -->
1977 <title>How do I attach data to some GTK+ object/widget?
1978 <emphasis>[GTK 2.x]</emphasis></title>
1980 <para>First of all, the attached data is stored in the
1981 object_data field of a GtkObject. The type of this field is
1982 GData, which is defined in glib.h. So you should read the
1983 gdataset.c file in your glib source directory very
1986 <para>There are two (easy) ways to attach some data to a gtk
1987 object. Using <literal>g_object_set_data()</literal> and
1988 <literal>g_object_get_data()</literal> seems to be the most
1989 common way to do this, as it provides a powerful interface to
1990 connect objects and data.</para>
1992 <programlisting role="C">
1993 void g_object_set_data(GObject *object, const gchar *key, gpointer data);
1995 gpointer g_object_get_data(GObject *object, const gchar *key);
1998 <para>Since a short example is better than any lengthy speech:</para>
2000 <programlisting role="C">
2001 struct my_struct p1,p2,*result;
2004 g_object_set_data(G_OBJECT(w),"p1 data",(gpointer)&p1);
2005 g_object_set_data(G_OBJECT(w),"p2 data",(gpointer)&p2);
2007 result = g_object_get_data(G_OBJECT(w),"p1 data");
2010 <para>The <literal>gtk_object_set_user_data()</literal> and
2011 <literal>gtk_object_get_user_data()</literal> functions does
2012 exactly the same thing as the functions above, but does not
2013 let you specify the "key" parameter.Instead, it uses a
2014 standard "user_data" key. Note that the use of these functions
2015 is deprecated in 1.2. They only provide a compatibility mode
2016 with some old gtk packages.</para>
2020 <!-- ----------------------------------------------------------------- -->
2023 <title>How do I remove the data I have attached to an
2026 <para>When attaching the data to the object, you can use the
2027 <literal>gtk_object_set_data_full()</literal> function. The three
2028 first arguments of the function are the same as in
2029 <literal>gtk_object_set_data()</literal>. The fourth one is a
2030 pointer to a callback function which is called when the data
2031 is destroyed. The data is destroyed when you:</para>
2034 <listitem><simpara> destroy the object</simpara>
2037 <listitem><simpara> replace the data with a new one (with
2038 the same key)</simpara>
2041 <listitem><simpara> replace the data with NULL (with the
2049 <!-- ----------------------------------------------------------------- -->
2052 <title>How do I reparent a widget?</title>
2054 <para>The normal way to reparent (ie change the owner) of a
2055 widget should be to use the function:</para>
2057 <programlisting role="C">
2058 void gtk_widget_reparent (GtkWidget *widget,
2059 GtkWidget *new_parent)
2062 <para>But this is only a "should be" since this function does
2063 not correctly do its job on some specific widgets. The main
2064 goal of gtk_widget_reparent() is to avoid unrealizing widget
2065 if both widget and new_parent are realized (in this case,
2066 widget->window is successfully reparented). The problem here
2067 is that some widgets in the GTK+ hierarchy have multiple
2068 attached X subwindows and this is notably the case for the
2069 GtkSpinButton widget. For those, gtk_widget_reparent() will
2070 fail by leaving an unrealized child window where it should
2073 <para>To avoid this problem, simply use the following code
2076 <programlisting role="C">
2077 gtk_widget_ref(widget);
2078 gtk_container_remove(GTK_CONTAINER(old_parent), widget);
2079 gtk_container_add(GTK_CONTAINER(new_parent), widget);
2080 gtk_widget_unref(widget);
2085 <!-- ----------------------------------------------------------------- -->
2088 <title>How could I get any widgets position?</title>
2090 <para>As Tim Janik pointed out, there are different cases, and
2091 each case requires a different solution.</para>
2094 <listitem><simpara> If you want the position of a widget
2095 relative to its parent, you should use
2096 <literal>widget->allocation.x</literal> and
2097 <literal>widget->allocation.y</literal>.</simpara>
2100 <listitem><simpara> If you want the position of a window
2101 relative to the X root window, you should use
2102 <literal>gdk_window_get_geometry()</literal>
2103 <literal>gdk_window_get_position()</literal> or
2104 <literal>gdk_window_get_origin()</literal>.</simpara>
2107 <listitem><simpara> If you want to get the position of the
2108 window (including the WM decorations), you should use
2109 <literal>gdk_window_get_root_origin()</literal>.</simpara>
2112 <listitem><simpara> Last but not least, if you want to get a Window
2113 Manager frame position, you should use
2114 <literal>gdk_window_get_deskrelative_origin()</literal>.</simpara>
2118 <para>Your choice of Window Manager will have an effect of the
2119 results of the above functions. You should keep this in mind
2120 when writing your application. This is dependant upon how the
2121 Window Managers manage the decorations that they add around
2126 <!-- ----------------------------------------------------------------- -->
2129 <title>How do I set the size of a widget/window? How do I
2130 prevent the user resizing my window? <emphasis>[GTK 2.x]</emphasis></title>
2132 <para>The <literal>gtk_widget_set_size_request()</literal> function
2133 is used to set the size of a widget to a specific size.
2136 <literal>gtk_window_set_resizable()</literal> function sets whether
2137 the user can resize a window, which they can by default. The
2138 definition of these functions are:</para>
2140 <programlisting role="C">
2141 void gtk_widget_set_size_request (GtkWidget *widget,
2145 void gtk_window_set_resizable (GtkWindow *window,
2146 gboolean resizable);
2152 <!-- ----------------------------------------------------------------- -->
2155 <title>How do I add a popup menu to my GTK+ application?</title>
2157 <para>The <literal>menu</literal> example in the examples/menu
2158 directory of the GTK+ distribution implements a popup menu
2159 with this technique:</para>
2161 <programlisting role="C">
2162 static gint button_press (GtkWidget *widget, GdkEvent *event)
2165 if (event->type == GDK_BUTTON_PRESS) {
2166 GdkEventButton *bevent = (GdkEventButton *) event;
2167 gtk_menu_popup (GTK_MENU(widget), NULL, NULL, NULL, NULL,
2168 bevent->button, bevent->time);
2169 /* Tell calling code that we have handled this event; the buck
2174 /* Tell calling code that we have not handled this event; pass it on. */
2181 <!-- ----------------------------------------------------------------- -->
2184 <title>How do I disable or enable a widget, such as a
2187 <para>To disable (or to enable) a widget, use the
2188 <literal>gtk_widget_set_sensitive()</literal> function. The
2189 first parameter is you widget pointer. The second parameter is
2190 a boolean value: when this value is TRUE, the widget is
2194 <!-- ----------------------------------------------------------------- -->
2197 <title>Shouldn't the text argument in the gtk_clist_*
2198 functions be declared const?</title>
2200 <para>For example:</para>
2202 <programlisting role="C">
2203 gint gtk_clist_prepend (GtkCList *clist,
2207 <para>Answer: No, while a type "gchar*" (pointer to char) can
2208 automatically be cast into "const gchar*" (pointer to const
2209 char), this does not apply for "gchar *[]" (array of an
2210 unspecified number of pointers to char) into "const gchar *[]"
2211 (array of an unspecified number of pointers to const char).</para>
2213 <para>The type qualifier "const" may be subject to automatic
2214 casting, but in the array case, it is not the array itself
2215 that needs the (const) qualified cast, but its members, thus
2216 changing the whole type.</para>
2219 <!-- ----------------------------------------------------------------- -->
2222 <title>How do I render pixels (image data) to the
2225 <para>There are several ways to approach this. The simplest
2226 way is to use GdkRGB, see gdk/gdkrgb.h. You create an RGB
2227 buffer, render to your RGB buffer, then use GdkRGB routines to
2228 copy your RGB buffer to a drawing area or custom widget. The
2229 book "GTK+/Gnome Application Development" gives some details;
2230 GdkRGB is also documented in the GTK+ reference
2231 documentation.</para>
2233 <para>If you're writing a game or other graphics-intensive
2234 application, you might consider a more elaborate
2235 solution. OpenGL is the graphics standard that will let you
2236 access hardware accelaration in future versions of XFree86; so
2237 for maximum speed, you probably want to use OpenGL. A
2238 GtkGLArea widget is available for using OpenGL with GTK+ (but
2239 GtkGLArea does not come with GTK+ itself). There are also
2240 several open source game libraries, such as ClanLib and Loki's
2241 Simple DirectMedia Layer library (SDL).</para>
2243 <para>You do NOT want to use
2244 <literal>gdk_draw_point()</literal>, that will be extremely
2248 <!-- ----------------------------------------------------------------- -->
2251 <title>How do I create a pixmap without having my window being
2252 realized/shown?</title>
2254 <para>Functions such as
2255 <literal>gdk_pixmap_create_from_xpm()</literal> require a
2256 valid window as a parameter. During the initialisation phase
2257 of an application, a valid window may not be available without
2258 showing a window, which may be inappropriate. In order to
2259 avoid this, a function such as
2260 <literal>gdk_pixmap_colormap_create_from_xpm</literal> can be
2263 <programlisting role="C">
2264 char *pixfile = "foo.xpm";
2265 GtkWidget *top, *box, *pixw;
2266 GdkPixmap *pixmap, *pixmap_mask;
2268 top = gtk_window_new (GKT_WINDOW_TOPLEVEL);
2269 box = gtk_hbox_new (FALSE, 4);
2270 gtk_conainer_add (GTK_CONTAINER(top), box);
2272 pixmap = gdk_pixmap_colormap_create_from_xpm (
2273 NULL, gtk_widget_get_colormap(top),
2274 &pixmap_mask, NULL, pixfile);
2275 pixw = gtk_pixmap_new (pixmap, pixmap_mask);
2276 gdk_pixmap_unref (pixmap);
2277 gdk_pixmap_unref (pixmap_mask);
2282 <!-- ----------------------------------------------------------------- -->
2285 <title>How do I do drag-and-drop?</title>
2287 <para>GTK+ has a high level set of functions for doing inter-process
2288 communication via the drag-and-drop system. GTK+ can perform
2289 drag-and-drop on top of the low level Xdnd and Motif drag-and-drop
2292 <para>The documentation on GTK+ drag-and-drop isn't complete, but there
2293 is some information in the <ulink
2294 url="http://www.gtk.org/tutorial/">Tutorial</ulink>. You should also
2295 look at the drag-and-drop example code that is part of the GTK+ source
2296 distribution, in the file <filename>gtk/testdnd.c</filename>.</para>
2300 <!-- ----------------------------------------------------------------- -->
2303 <title>Why does GTK+/GLib leak memory?</title>
2305 <para>It doesn't. Both GLib and the C library (malloc implementation)
2306 will cache allocated memory on occasion, even if you free it with
2309 <para>So you can't generally use tools such as top to see if you are
2310 using free() properly (aside from the very roughest of estimations, i.e.
2311 if you are really, really screwing up top will show that, but you can't
2312 distinguish small mistakes from the GLib/malloc caches).</para>
2314 <para>In order to find memory leaks, use proper memory profiling
2321 <!-- ***************************************************************** -->
2323 <title>Development with GTK+: widget specific questions</title>
2325 <!-- ----------------------------------------------------------------- -->
2328 <title>How do I find out about the selection of a GtkList?</title>
2330 <para>Get the selection something like this:</para>
2332 <programlisting role="C">
2334 sel = GTK_LIST(list)->selection;
2337 <para>This is how GList is defined (quoting glist.h):</para>
2339 <programlisting role="C">
2340 typedef struct _GList GList;
2350 <para>A GList structure is just a simple structure for doubly
2351 linked lists. There exist several g_list_*() functions to
2352 modify a linked list in glib.h. However the
2353 GTK_LIST(MyGtkList)->selection is maintained by the
2354 gtk_list_*() functions and should not be modified.</para>
2357 <para>The selection_mode of the GtkList determines the
2358 selection facilities of a GtkList and therefore the contents
2359 of GTK_LIST(AnyGtkList)->selection:</para>
2361 <informaltable frame="all">
2365 <entry><literal>selection_mode</literal></entry>
2366 <entry><literal> GTK_LIST()->selection</literal>
2373 <entry><literal>GTK_SELECTION_SINGLE</literal></entry>
2374 <entry>selection is either NULL or contains a GList*
2375 pointer for a single selected item.</entry>
2379 <entry><literal>GTK_SELECTION_BROWSE</literal></entry>
2380 <entry>selection is NULL if the list contains no
2381 widgets, otherwise it contains a GList*
2382 pointer for one GList structure.</entry>
2386 <entry><literal>GTK_SELECTION_MULTIPLE</literal></entry>
2387 <entry>selection is NULL if no listitems are selected
2388 or a a GList* pointer for the first selected
2389 item. that in turn points to a GList structure
2390 for the second selected item and so
2395 <entry><literal>GTK_SELECTION_EXTENDED</literal></entry>
2396 <entry>selection is NULL.</entry>
2403 <para>The data field of the GList structure
2404 GTK_LIST(MyGtkList)->selection points to the first
2405 GtkListItem that is selected. So if you would like to
2406 determine which listitems are selected you should go like
2409 <programlisting role="C">
2411 gchar *list_items[]={
2417 guint nlist_items=sizeof(list_items)/sizeof(list_items[0]);
2418 GtkWidget *list_item;
2421 list=gtk_list_new();
2422 gtk_list_set_selection_mode(GTK_LIST(list), GTK_SELECTION_MULTIPLE);
2423 gtk_container_add(GTK_CONTAINER(AnyGtkContainer), list);
2424 gtk_widget_show (list);
2426 for (i = 0; i < nlist_items; i++)
2428 list_item=gtk_list_item_new_with_label(list_items[i]);
2429 gtk_object_set_user_data(GTK_OBJECT(list_item), (gpointer)i);
2430 gtk_container_add(GTK_CONTAINER(list), list_item);
2431 gtk_widget_show(list_item);
2436 <para>To get known about the selection:</para>
2438 <programlisting role="C">
2442 items=GTK_LIST(list)->selection;
2444 printf("Selected Items: ");
2446 if (GTK_IS_LIST_ITEM(items->data))
2447 printf("%d ", (guint)
2448 gtk_object_get_user_data(items->data));
2457 <!-- ----------------------------------------------------------------- -->
2460 <title>How do I stop the column headings of a GtkCList
2461 disappearing when the list is scrolled?</title>
2463 <para>This happens when a GtkCList is packed into a
2464 GtkScrolledWindow using the function
2465 <literal>gtk_scroll_window_add_with_viewport()</literal>. The prefered
2466 method of adding a CList to a scrolled window is to use the
2467 function <literal>gtk_container_add</literal>, as in:</para>
2469 <programlisting role="C">
2470 GtkWidget *scrolled, *clist;
2471 char *titles[] = { "Title1" , "Title2" };
2473 scrolled = gtk_scrolled_window_new(NULL, NULL);
2475 clist = gtk_clist_new_with_titles(2, titles);
2476 gtk_container_add(GTK_CONTAINER(scrolled), clist);
2481 <!-- ----------------------------------------------------------------- -->
2484 <title>I don't want the user of my applications to enter text
2485 into a GtkCombo. Any idea?</title>
2487 <para>A GtkCombo has an associated entry which can be accessed
2488 using the following expression:</para>
2490 <programlisting role="C">
2491 GTK_COMBO(combo_widget)->entry
2494 <para>If you don't want the user to be able to modify the
2495 content of this entry, you can use the
2496 gtk_entry_set_editable() function:</para>
2499 <programlisting role="C">
2500 void gtk_entry_set_editable(GtkEntry *entry,
2504 <para>Set the editable parameter to FALSE to disable typing
2505 into the entry.</para>
2508 <!-- ----------------------------------------------------------------- -->
2511 <title>How do I catch a combo box change?</title>
2513 <para>The entry which is associated to your GtkCombo send a
2514 "changed" signal when:</para>
2517 <listitem><simpara>some text is typed in</simpara>
2520 <listitem><simpara>the selection of the combo box is changed</simpara>
2524 <para>To catch any combo box change, simply connect your
2525 signal handler with</para>
2527 <programlisting role="C">
2528 gtk_signal_connect(GTK_COMBO(cb)->entry,
2530 GTK_SIGNAL_FUNC(my_cb_change_handler),
2536 <!-- ----------------------------------------------------------------- -->
2539 <title>How can I define a separation line in a menu?</title>
2541 <para>See the <ulink
2542 url="http://www.gtk.org/tutorial/">Tutorial</ulink> for
2543 information on how to create menus. However, to create a
2544 separation line in a menu, just insert an empty menu item:</para>
2546 <programlisting role="C">
2547 menuitem = gtk_menu_item_new();
2548 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
2549 gtk_widget_show(menuitem);
2554 <!-- ----------------------------------------------------------------- -->
2557 <title>How can I right justify a menu, such as Help?</title>
2559 <para>Depending on if you use the MenuFactory or not, there
2560 are two ways to proceed. With the MenuFactory, use something
2561 like the following:</para>
2563 <programlisting role="C">
2564 menu_path = gtk_menu_factory_find (factory, "<MyApp>/Help");
2565 gtk_menu_item_right_justify(menu_path->widget);
2568 <para>If you do not use the MenuFactory, you should simply
2572 <programlisting role="C">
2573 gtk_menu_item_right_justify(my_menu_item);
2578 <!-- ----------------------------------------------------------------- -->
2581 <title>How do I add some underlined accelerators to menu
2584 <para>Damon Chaplin, the technical force behind the Glade
2585 project, provided the following code sample (this code is an
2586 output from Glade). It creates a small <GUIMenu>File</guimenu> menu item
2587 with only one child (<guimenu>New</guimenu>). The F in
2588 <guimenu>File</guimenu> and the N in <guimenu>New</guimenu> are
2589 underlined, and the relevant accelerators are created.</para>
2591 <programlisting role="C">
2592 menubar1 = gtk_menu_bar_new ();
2593 gtk_object_set_data (GTK_OBJECT (window1), "menubar1", menubar1);
2594 gtk_widget_show (menubar1);
2595 gtk_box_pack_start (GTK_BOX (vbox1), menubar1, FALSE, FALSE, 0);
2597 file1 = gtk_menu_item_new_with_label ("");
2598 tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (file1)->child),
2600 gtk_widget_add_accelerator (file1, "activate_item", accel_group,
2601 tmp_key, GDK_MOD1_MASK, 0);
2602 gtk_object_set_data (GTK_OBJECT (window1), "file1", file1);
2603 gtk_widget_show (file1);
2604 gtk_container_add (GTK_CONTAINER (menubar1), file1);
2606 file1_menu = gtk_menu_new ();
2607 file1_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (file1_menu));
2608 gtk_object_set_data (GTK_OBJECT (window1), "file1_menu", file1_menu);
2609 gtk_menu_item_set_submenu (GTK_MENU_ITEM (file1), file1_menu);
2611 new1 = gtk_menu_item_new_with_label ("");
2612 tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (new1)->child),
2614 gtk_widget_add_accelerator (new1, "activate_item", file1_menu_accels,
2616 gtk_object_set_data (GTK_OBJECT (window1), "new1", new1);
2617 gtk_widget_show (new1);
2618 gtk_container_add (GTK_CONTAINER (file1_menu), new1);
2623 <!-- ----------------------------------------------------------------- -->
2626 <title>How can I retrieve the text from a GtkMenuItem?</title>
2628 <para>You can usually retrieve the label of a specific
2629 GtkMenuItem with:</para>
2631 <programlisting role="C">
2632 if (GTK_BIN (menu_item)->child)
2634 GtkWidget *child = GTK_BIN (menu_item)->child;
2636 /* do stuff with child */
2637 if (GTK_IS_LABEL (child))
2641 gtk_label_get (GTK_LABEL (child), &text);
2642 g_print ("menu item text: %s\n", text);
2647 <para>To get the active menu item from a GtkOptionMenu you can
2650 <programlisting role="C">
2651 if (GTK_OPTION_MENU (option_menu)->menu_item)
2653 GtkWidget *menu_item = GTK_OPTION_MENU (option_menu)->menu_item;
2657 <para>But, there's a catch. For this specific case, you can
2658 <emphasis>not</emphasis> get the label widget from
2659 <literal>menu_item</literal> with the above code, because the
2660 option menu reparents the menu_item's child temporarily to
2661 display the currently active contents. So to retrive the child
2662 of the currently active menu_item of an option menu, you'll
2665 <programlisting role="C">
2666 if (GTK_BIN (option_menu)->child)
2668 GtkWidget *child = GTK_BIN (option_menu)->child;
2670 /* do stuff with child */
2676 <!-- ----------------------------------------------------------------- -->
2679 <title>How do I right (or otherwise) justify a
2682 <para>Are you sure you want to <emphasis>justify</emphasis>
2683 the labels? The label class contains the
2684 <literal>gtk_label_set_justify()</literal> function that is
2685 used to control the justification of a multi-line
2688 <para>What you probably want is to set the <emphasis>alignment</emphasis>
2689 of the label, ie right align it, center it or left align
2690 it. If you want to do this, you should use:</para>
2692 <programlisting role="C">
2693 void gtk_misc_set_alignment (GtkMisc *misc,
2698 <para>where the <literal>xalign</literal> and
2699 <literal>yalign</literal> values are floats in
2702 <programlisting role="C">
2705 /* horizontal : left align, vertical : top */
2706 gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.0f);
2708 /* horizontal : centered, vertical : centered */
2709 gtk_misc_set_alignment(GTK_MISC(label), 0.5f, 0.5f);
2711 /* horizontal : right align, vertical : bottom */
2712 gtk_misc_set_alignment(GTK_MISC(label), 1.0f, 1.0f);
2717 <!-- ----------------------------------------------------------------- -->
2720 <title>How do I set the background color of a GtkLabel
2723 <para>The GtkLabel widget is one of a few GTK+ widgets that
2724 don't create their own window to render themselves
2725 into. Instead, they draw themselves directly onto their
2726 parents window.</para>
2728 <para>This means that in order to set the background color for
2729 a GtkLabel widget, you need to change the background color of
2730 its parent, i.e. the object that you pack it into.</para>
2734 <!-- ----------------------------------------------------------------- -->
2737 <title>How do I set the color and font of a GtkLabel using a
2738 Resource File?</title>
2740 <para>The widget name path constructed for a Label consists of
2741 the widget names of its object hierarchy as well, e.g.</para>
2743 <para><literallayout>
2744 <literal>window (name: humphrey)</literal>
2745 <literal> hbox</literal>
2746 <literal> label (name: mylabel)</literal>
2747 </literallayout></para>
2749 <para>The widget path your pattern needs to match would be:
2750 <literal>humphrey.GtkHBox.mylabel</literal></para>
2752 <para>The resource file may look something like:</para>
2754 <programlisting role="C">
2757 fg[NORMAL] = {1.0, 0.0, 0.0}
2758 font = "-adobe-helvetica-bold-r-normal--*-140-*-*-*-*-*-*"
2760 widget "*mylabel" style "title"
2763 <para>In your program, you would also need to give a name to
2764 the Label widget, which can be done using:</para>
2766 <programlisting role="C">
2767 label = gtk_label_new("Some Label Text");
2768 gtk_widget_set_name(label, "mylabel");
2769 gtk_widget_show(label);
2774 <!-- ----------------------------------------------------------------- -->
2777 <title>How do I configure Tooltips in a Resource File?</title>
2779 <para>The tooltip's window is named "gtk-tooltips",
2780 GtkTooltips in itself is not a GtkWidget (though a GtkObject)
2781 and as such is not attempted to match any widget styles.</para>
2783 <para>So, you resource file should look something like:</para>
2785 <programlisting role="C">
2788 bg[NORMAL] = {1.0, 1.0, 0.0}
2790 widget "gtk-tooltips*" style "postie"
2795 <!-- ----------------------------------------------------------------- -->
2798 <title>I can't add more than (something like) 2000 chars in a
2799 GtkEntry. What's wrong?</title>
2801 <para>There is now a known problem in the GtkEntry widget. In
2802 the <literal>gtk_entry_insert_text()</literal> function, the
2803 following lines limit the number of chars in the entry to
2806 <programlisting role="C">
2807 /* The algorithms here will work as long as, the text size (a
2808 * multiple of 2), fits into a guint16 but we specify a shorter
2809 * maximum length so that if the user pastes a very long text, there
2810 * is not a long hang from the slow X_LOCALE functions. */
2812 if (entry->text_max_length == 0)
2815 max_length = MIN (2047, entry->text_max_length);
2820 <!-- ----------------------------------------------------------------- -->
2823 <title>How do I make a GtkEntry widget activate on pressing
2824 the Return key?</title>
2826 <para>The Entry widget emits an 'activate' signal when you
2827 press return in it. Just attach to the activate signal on the
2828 entry and do whatever you want to do. Typical code would
2831 <programlisting role="C">
2832 entry = gtk_entry_new();
2833 gtk_signal_connect (GTK_OBJECT(entry), "activate",
2834 GTK_SIGNAL_FUNC(entry_callback),
2840 <!-- ----------------------------------------------------------------- -->
2843 <title>How do I validate/limit/filter the input to a GtkEntry?</title>
2845 <para>If you want to validate the text that a user enters into
2846 a GtkEntry widget you can attach to the "insert_text" signal
2847 of the entry, and modify the text within the callback
2848 function. The example below forces all characters to
2849 uppercase, and limits the range of characters to A-Z. Note
2850 that the entry is cast to an object of type GtkEditable, from
2851 which GtkEntry is derived.</para>
2853 <programlisting role="C">
2854 #include <ctype.h>
2855 #include <gtk/gtk.h>
2857 void insert_text_handler (GtkEntry *entry,
2863 GtkEditable *editable = GTK_EDITABLE(entry);
2865 gchar *result = g_new (gchar, length);
2867 for (i=0; i < length; i++) {
2868 if (!isalpha(text[i]))
2870 result[count++] = islower(text[i]) ? toupper(text[i]) : text[i];
2874 gtk_signal_handler_block_by_func (GTK_OBJECT (editable),
2875 GTK_SIGNAL_FUNC (insert_text_handler),
2877 gtk_editable_insert_text (editable, result, count, position);
2878 gtk_signal_handler_unblock_by_func (GTK_OBJECT (editable),
2879 GTK_SIGNAL_FUNC (insert_text_handler),
2882 gtk_signal_emit_stop_by_name (GTK_OBJECT (editable), "insert_text");
2893 gtk_init (&argc, &argv);
2895 /* create a new window */
2896 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
2897 gtk_window_set_title(GTK_WINDOW (window), "GTK Entry");
2898 gtk_signal_connect(GTK_OBJECT (window), "delete_event",
2899 (GtkSignalFunc) gtk_exit, NULL);
2901 entry = gtk_entry_new();
2902 gtk_signal_connect(GTK_OBJECT(entry), "insert_text",
2903 GTK_SIGNAL_FUNC(insert_text_handler),
2905 gtk_container_add(GTK_CONTAINER (window), entry);
2906 gtk_widget_show(entry);
2908 gtk_widget_show(window);
2917 <!-- ----------------------------------------------------------------- -->
2920 <title>How do I use horizontal scrollbars with a GtkText widget?</title>
2922 <para>The short answer is that you can't. The current version
2923 of the GtkText widget does not support horizontal
2924 scrolling. There is an intention to completely rewrite the
2925 GtkText widget, at which time this limitation will be
2930 <!-- ----------------------------------------------------------------- -->
2933 <title>How do I change the font of a GtkText widget?</title>
2935 <para>There are a couple of ways of doing this. As GTK+ allows
2936 the appearance of applications to be changed at run time using
2937 resources you can use something like the following in the
2938 appropriate file:</para>
2940 <programlisting role="C">
2943 font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*"
2947 <para>Another way to do this is to load a font within your
2948 program, and then use this in the functions for adding text to
2949 the text widget. You can load a font using, for example:</para>
2951 <programlisting role="C">
2953 font = gdk_font_load("-adobe-helvetica-medium-r-normal--*-140-*-*-*-*-*-*");
2958 <!-- ----------------------------------------------------------------- -->
2961 <title>How do I set the cursor position in a GtkText
2964 <para>Notice that the response is valid for any object that
2965 inherits from the GtkEditable class.</para>
2967 <para>Are you sure that you want to move the cursor position?
2968 Most of the time, while the cursor position is good, the
2969 insertion point does not match the cursor position. If this
2970 apply to what you really want, then you should use the
2971 <literal>gtk_text_set_point()</literal> function. If you want
2972 to set the insertion point at the current cursor position, use
2973 the following:</para>
2975 <programlisting role="C">
2976 gtk_text_set_point(GTK_TEXT(text),
2977 gtk_editable_get_position(GTK_EDITABLE(text)));
2980 <para>If you want the insertion point to follow the cursor at
2981 all time, you should probably catch the button press event,
2982 and then move the insertion point. Be careful : you'll have to
2983 catch it after the widget has changed the cursor position
2984 though. Thomas Mailund Jensen proposed the following
2987 <programlisting role="C">
2989 insert_bar (GtkWidget *text)
2991 /* jump to cursor mark */
2992 gtk_text_set_point (GTK_TEXT (text),
2993 gtk_editable_get_position (GTK_EDITABLE (text)));
2995 gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL,
2996 "bar", strlen ("bar"));
3000 main (int argc, char *argv[])
3002 GtkWidget *window, *text;
3004 gtk_init (&argc, &argv);
3006 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3007 text = gtk_text_new (NULL, NULL);
3008 gtk_text_set_editable (GTK_TEXT (text), TRUE);
3009 gtk_container_add (GTK_CONTAINER (window), text);
3011 /* connect after everything else */
3012 gtk_signal_connect_after (GTK_OBJECT(text), "button_press_event",
3013 GTK_SIGNAL_FUNC (insert_bar), NULL);
3015 gtk_widget_show_all(window);
3022 <para>Now, if you really want to change the cursor position,
3024 <literal>gtk_editable_set_position()</literal>
3031 <!-- ***************************************************************** -->
3033 <title>About GDK</title>
3035 <!-- ----------------------------------------------------------------- -->
3038 <title>What is GDK?</title>
3040 <para>GDK is basically a wrapper around the standard Xlib
3041 function calls. If you are at all familiar with Xlib, a lot of
3042 the functions in GDK will require little or no getting used
3043 to. All functions are written to provide an way to access Xlib
3044 functions in an easier and slightly more intuitive manner. In
3045 addition, since GDK uses GLib (see below), it will be more
3046 portable and safer to use on multiple platforms.</para>
3048 <!-- Examples, anybody? I've been mulling some over. NF -->
3052 <!-- ----------------------------------------------------------------- -->
3055 <title>How do I use color allocation?</title>
3057 <para>One of the nice things about GDK is that it's based on
3058 top of Xlib; this is also a problem, especially in the area of
3059 color management. If you want to use color in your program
3060 (drawing a rectangle or such, your code should look something
3063 <programlisting role="C">
3072 /* first, create a GC to draw on */
3073 gc = gdk_gc_new(widget->window);
3075 /* find proper dimensions for rectangle */
3076 gdk_window_get_size(widget->window, &width, &height);
3078 /* the color we want to use */
3079 color = (GdkColor *)malloc(sizeof(GdkColor));
3081 /* red, green, and blue are passed values, indicating the RGB triple
3082 * of the color we want to draw. Note that the values of the RGB components
3083 * within the GdkColor are taken from 0 to 65535, not 0 to 255.
3085 color->red = red * (65535/255);
3086 color->green = green * (65535/255);
3087 color->blue = blue * (65535/255);
3089 /* the pixel value indicates the index in the colormap of the color.
3090 * it is simply a combination of the RGB values we set earlier
3092 color->pixel = (gulong)(red*65536 + green*256 + blue);
3094 /* However, the pixel valule is only truly valid on 24-bit (TrueColor)
3095 * displays. Therefore, this call is required so that GDK and X can
3096 * give us the closest color available in the colormap
3098 gdk_color_alloc(gtk_widget_get_colormap(widget), color);
3100 /* set the foreground to our color */
3101 gdk_gc_set_foreground(gc, color);
3103 /* draw the rectangle */
3104 gdk_draw_rectangle(widget->window, gc, 1, 0, 0, width, height);
3114 <!-- ***************************************************************** -->
3116 <title>About GLib</title>
3118 <!-- ----------------------------------------------------------------- -->
3121 <title>What is GLib?</title>
3123 <para>GLib is a library of useful functions and definitions
3124 available for use when creating GDK and GTK applications. It
3125 provides replacements for some standard libc functions, such
3126 as malloc, which are buggy on some systems.</para>
3128 <para>It also provides routines for handling:</para>
3130 <itemizedlist spacing=compact>
3131 <listitem><simpara>Doubly Linked Lists</simpara>
3134 <listitem><simpara>Singly Linked Lists</simpara>
3137 <listitem><simpara>Timers</simpara>
3140 <listitem><simpara>String Handling</simpara>
3143 <listitem><simpara>A Lexical Scanner</simpara>
3146 <listitem><simpara>Error Functions</simpara>
3152 <!-- ----------------------------------------------------------------- -->
3155 <title>How can I use the doubly linked lists?</title>
3157 <para>The GList object is defined as:</para>
3159 <programlisting role="C">
3160 typedef struct _GList GList;
3170 <para>To use the GList objects, simply:</para>
3172 <programlisting role="C">
3175 gint array[] = { 1, 2, 3, 4, 5, 6 };
3179 /* add data to the list */
3180 for (pos=0;pos < sizeof array; pos++) {
3181 list = g_list_append(list, (gpointer)&array[pos]);
3184 /* run through the list */
3185 listrunner = g_list_first(list);
3186 while (listrunner) {
3187 value = (gint *)listrunner->data;
3188 printf("%d\n", *value);
3189 listrunner = g_list_next(listrunner);
3192 /* removing datas from the list */
3193 listrunner = g_list_first(list);
3194 list = g_list_remove_link(list, listrunner);
3195 list = g_list_remove(list, &array[4]);
3198 <para>The same code is usable with singly linked lists (GSList
3199 objects) by replacing g_list_* functions with the relevant
3200 g_slist_* ones (g_slist_append, g_slist_remove, ...). Just
3201 remember that since you can't go backward in a singly linked
3202 list, there is no g_slist_first function - you'll need to keep
3203 a reference on the first node of the list.</para>
3205 <!-- Some Examples might be useful here! NF -->
3206 <!-- I believe it should be better :) ED -->
3207 <!-- Linked lists are pretty standard data structures - don't want to
3208 over do it - TRG -->
3212 <!-- ----------------------------------------------------------------- -->
3215 <title>Memory does not seem to be released when I free the
3216 list nodes I've allocated</title>
3218 <para>GLib tries to be "intelligent" on this special issue: it
3219 assumes that you are likely to reuse the objects, so caches
3220 the allocated memory. If you do not want to use this behavior,
3221 you'll probably want to set up a special allocator.</para>
3223 <para>To quote Tim Janik:</para>
3224 <para><quote>If you have a certain portion of code that uses *lots*
3225 of GLists or GNodes, and you know you'd better want to release
3226 all of them after a short while, you'd want to use a
3227 GAllocator. Pushing an allocator into g_list will make all
3228 subsequent glist operations private to that allocator's memory
3229 pool (and thus you have to take care to pop the allocator
3230 again, before making any external calls): </quote></para>
3232 <programlisting role="C">
3233 GAllocator *allocator;
3237 /* set a new allocation pool for GList nodes */
3238 allocator = g_allocator_new ("list heap", 1024);
3239 g_list_push_allocator (allocator);
3241 /* do some list operations */
3242 for (i = 0; i < 4096; i++)
3243 list = g_list_prepend (list, NULL);
3244 list = g_list_reverse (list);
3246 /* beware to pop allocator befor calling external functions */
3247 g_list_pop_allocator ();
3248 gtk_label_set_text (GTK_LABEL (some_label), "some text");
3250 /* and set our private glist pool again */
3251 g_list_push_allocator (allocator);
3253 /* do some list operations */
3256 for (i = 0; i < 4096; i++)
3257 list = g_list_prepend (list, NULL);
3259 /* and back out (while freeing all of the list nodes in our pool) */
3260 g_list_pop_allocator ();
3261 g_allocator_free (allocator);
3266 <!-- ----------------------------------------------------------------- -->
3269 <title>Why use g_print, g_malloc, g_strdup and fellow glib
3272 <para>Thanks to Tim Janik who wrote to gtk-list: (slightly
3275 <para><quote>Regarding g_malloc(), g_free() and siblings, these
3276 functions are much safer than their libc equivalents. For
3277 example, g_free() just returns if called with NULL. Also, if
3278 USE_DMALLOC is defined, the definition for these functions
3279 changes (in glib.h) to use MALLOC(), FREE() etc... If
3280 MEM_PROFILE or MEM_CHECK are defined, there are even small
3281 statistics made counting the used block sizes (shown by
3282 g_mem_profile() / g_mem_check()).</quote></para>
3284 <para><quote>Considering the fact that glib provides an interface for
3285 memory chunks to save space if you have lots of blocks that
3286 are always the same size and to mark them ALLOC_ONLY if
3287 needed, it is just straight forward to create a small saver
3288 (debug able) wrapper around the normal malloc/free stuff as
3289 well - just like gdk covers Xlib. ;)</quote></para>
3291 <para><quote>Using g_error() and g_warning() inside of applications
3292 like the GIMP that fully rely on gtk even gives the
3293 opportunity to pop up a window showing the messages inside of
3294 a gtk window with your own handler (by using
3295 g_set_error_handler()) along the lines of
3296 <literal>gtk_print()</literal> (inside of
3297 gtkmain.c).</quote></para>
3301 <!-- ----------------------------------------------------------------- -->
3304 <title>What's a GScanner and how do I use one?</title>
3306 <para>A GScanner will tokenize your text, that is, it'll return
3307 an integer for every word or number that appears in its input
3308 stream, following certain (customizable) rules to perform this
3309 translation. You still need to write the parsing functions on
3310 your own though.</para>
3312 <para>Here's a little test program supplied by Tim Janik that
3315 <para><literallayout>
3316 <literal><SYMBOL> = <OPTIONAL-MINUS> <NUMBER> ;</literal>
3317 </literallayout></para>
3319 <para>constructs, while skipping "#\n" and "/**/" style
3322 <programlisting role="C">
3323 #include <glib.h>
3325 /* some test text to be fed into the scanner */
3326 static const gchar *test_text =
3328 "/* slide in some \n"
3329 " * comments, just for the\n"
3334 "# the next value is a float\n"
3337 "ping = - 0.5;\n" );
3339 /* define enumeration values to be returned for specific symbols */
3341 SYMBOL_PING = G_TOKEN_LAST + 1,
3342 SYMBOL_PONG = G_TOKEN_LAST + 2,
3343 SYMBOL_ZONK = G_TOKEN_LAST + 3
3347 static const struct {
3351 { "ping", SYMBOL_PING, },
3352 { "pong", SYMBOL_PONG, },
3353 { "zonk", SYMBOL_ZONK, },
3355 }, *symbol_p = symbols;
3357 static gfloat ping = 0;
3358 static gfloat pong = 0;
3359 static gfloat zonk = 0;
3362 parse_symbol (GScanner *scanner)
3365 gboolean negate = FALSE;
3367 /* expect a valid symbol */
3368 g_scanner_get_next_token (scanner);
3369 symbol = scanner->token;
3370 if (symbol < SYMBOL_PING ||
3371 symbol > SYMBOL_ZONK)
3372 return G_TOKEN_SYMBOL;
3375 g_scanner_get_next_token (scanner);
3376 if (scanner->token != '=')
3379 /* feature optional '-' */
3380 g_scanner_peek_next_token (scanner);
3381 if (scanner->next_token == '-')
3383 g_scanner_get_next_token (scanner);
3387 /* expect a float (ints are converted to floats on the fly) */
3388 g_scanner_get_next_token (scanner);
3389 if (scanner->token != G_TOKEN_FLOAT)
3390 return G_TOKEN_FLOAT;
3392 /* make sure the next token is a ';' */
3393 if (g_scanner_peek_next_token (scanner) != ';')
3395 /* not so, eat up the non-semicolon and error out */
3396 g_scanner_get_next_token (scanner);
3400 /* assign value, eat the semicolon and exit successfully */
3404 ping = negate ? - scanner->value.v_float : scanner->value.v_float;
3407 pong = negate ? - scanner->value.v_float : scanner->value.v_float;
3410 zonk = negate ? - scanner->value.v_float : scanner->value.v_float;
3413 g_scanner_get_next_token (scanner);
3415 return G_TOKEN_NONE;
3419 main (int argc, char *argv[])
3422 guint expected_token;
3424 scanner = g_scanner_new (NULL);
3426 /* adjust lexing behaviour to suit our needs
3428 /* convert non-floats (octal values, hex values...) to G_TOKEN_INT */
3429 scanner->config->numbers_2_int = TRUE;
3430 /* convert G_TOKEN_INT to G_TOKEN_FLOAT */
3431 scanner->config->int_2_float = TRUE;
3432 /* don't return G_TOKEN_SYMBOL, but the symbol's value */
3433 scanner->config->symbol_2_token = TRUE;
3435 /* load symbols into the scanner */
3436 while (symbol_p->symbol_name)
3438 g_scanner_add_symbol (scanner,
3439 symbol_p->symbol_name,
3440 GINT_TO_POINTER (symbol_p->symbol_token));
3444 /* feed in the text */
3445 g_scanner_input_text (scanner, test_text, strlen (test_text));
3447 /* give the error handler an idea on how the input is named */
3448 scanner->input_name = "test text";
3450 /* scanning loop, we parse the input until its end is reached,
3451 * the scanner encountered a lexing error, or our sub routine came
3452 * across invalid syntax
3456 expected_token = parse_symbol (scanner);
3458 g_scanner_peek_next_token (scanner);
3460 while (expected_token == G_TOKEN_NONE &&
3461 scanner->next_token != G_TOKEN_EOF &&
3462 scanner->next_token != G_TOKEN_ERROR);
3464 /* give an error message upon syntax errors */
3465 if (expected_token != G_TOKEN_NONE)
3466 g_scanner_unexp_token (scanner, expected_token, NULL, "symbol", NULL, NULL, TRUE);
3468 /* finsish parsing */
3469 g_scanner_destroy (scanner);
3472 g_print ("ping: %f\n", ping);
3473 g_print ("pong: %f\n", pong);
3474 g_print ("zonk: %f\n", zonk);
3480 <para>You need to understand that the scanner will parse its
3481 input and tokenize it, it is up to you to interpret these
3482 tokens, not define their types before they get parsed,
3483 e.g. watch gscanner parse a string:</para>
3485 <para><literallayout>
3486 <literal>"hi i am 17"</literal>
3487 <literal> | | | |</literal>
3488 <literal> | | | v</literal>
3489 <literal> | | v TOKEN_INT, value: 17</literal>
3490 <literal> | v TOKEN_IDENTIFIER, value: "am"</literal>
3491 <literal> v TOKEN_CHAR, value: 'i'</literal>
3492 <literal>TOKEN_IDENTIFIER, value: "hi"</literal>
3493 </literallayout></para>
3495 <para>If you configure the scanner with:</para>
3497 <programlisting role="C">
3498 scanner->config->int_2_float = TRUE;
3499 scanner->config->char_2_token = TRUE;
3500 scanner->config->scan_symbols = TRUE;
3503 <para>and add "am" as a symbol with</para>
3505 <programlisting role="C">
3506 g_scanner_add_symbol (scanner, "am", "symbol value");
3509 <para>GScanner will parse it as</para>
3511 <para><literallayout>
3512 <literal>"hi i am 17"</literal>
3513 <literal> | | | |</literal>
3514 <literal> | | | v</literal>
3515 <literal> | | v TOKEN_FLOAT, value: 17.0 (automatic int->float conversion)</literal>
3516 <literal> | | TOKEN_SYMBOL, value: "symbol value" (a successfull hash table lookup</literal>
3517 <literal> | | turned a TOKEN_IDENTIFIER into a</literal>
3518 <literal> | | TOKEN_SYMBOL and took over the</literal>
3519 <literal> | v symbol's value)</literal>
3520 <literal> v 'i' ('i' can be a valid token as well, as all chars >0 and <256)</literal>
3521 <literal>TOKEN_IDENTIFIER, value: "hi"</literal>
3522 </literallayout></para>
3524 <para>You need to match the token sequence with your code, and
3525 if you encounter something that you don't want, you error
3528 <programlisting role="C">
3529 /* expect an identifier ("hi") */
3530 g_scanner_get_next_token (scanner);
3531 if (scanner->token != G_TOKEN_IDENTIFIER)
3532 return G_TOKEN_IDENTIFIER;
3533 /* expect a token 'i' */
3534 g_scanner_get_next_token (scanner);
3535 if (scanner->token != 'i')
3537 /* expect a symbol ("am") */
3538 g_scanner_get_next_token (scanner);
3539 if (scanner->token != G_TOKEN_SYMBOL)
3540 return G_TOKEN_SYMBOL;
3541 /* expect a float (17.0) */
3542 g_scanner_get_next_token (scanner);
3543 if (scanner->token != G_TOKEN_FLOAT)
3544 return G_TOKEN_FLOAT;
3547 <para>If you got past here, you have parsed "hi i am 17" and
3548 would have accepted "dooh i am 42" and "bah i am 0.75" as
3549 well, but you would have not accepted "hi 7 am 17" or "hi i hi
3556 <!-- ***************************************************************** -->
3559 <title>GTK+ FAQ Contributions, Maintainers and Copyright</title>
3561 <para>If you would like to make a contribution to the FAQ, send either one
3562 of us an e-mail message with the exact text you think should be
3563 included (question and answer). With your help, this document can grow
3564 and become more useful!</para>
3566 <para>This document is maintained by
3568 <ulink url="mailto:gale@gtk.org"><gale@gtk.org></ulink>
3571 <ulink url="mailto:maestrox@geocities.com">
3572 <maestrox@geocities.com></ulink>,
3575 <ulink url="mailto:logout@free.fr"><logout@free.fr></ulink>.
3577 This FAQ was created by Shawn T. Amundson
3578 <ulink url="mailto:amundson@gimp.org">
3579 <amundson@gimp.org></ulink> who continues to provide support.
3581 Contributions should be sent to Tony Gale <ulink
3582 url="mailto:gale@gtk.org"><gale@gtk.org></ulink></para>
3584 <para>The GTK+ FAQ is Copyright (C) 1997-2000 by Shawn T. Amundson,
3585 Tony Gale, Emmanuel Deloget and Nathan Froyd.</para>
3587 <para>Permission is granted to make and distribute verbatim copies of this
3588 manual provided the copyright notice and this permission notice are
3589 preserved on all copies.</para>
3591 <para>Permission is granted to copy and distribute modified versions of this
3592 document under the conditions for verbatim copying, provided that this
3593 copyright notice is included exactly as in the original, and that the
3594 entire resulting derived work is distributed under the terms of a
3595 permission notice identical to this one.</para>
3597 <para>Permission is granted to copy and distribute translations of this
3598 document into another language, under the above conditions for
3599 modified versions.</para>
3601 <para>If you are intending to incorporate this document into a published
3602 work, please contact one of the maintainers, and we will make an
3603 effort to ensure that you have the most up to date information
3606 <para>There is no guarentee that this document lives up to its intended
3607 purpose. This is simply provided as a free resource. As such, the
3608 authors and maintainers of the information provided within can not
3609 make any guarentee that the information is even accurate.</para>
3613 <!-- ----------------------------------------------------------------- -->