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 <para>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>
1065 Another option is to run your application on Xnest. Xnest is an X server
1066 which displays its root window in a regular window of another X server.
1067 A pointer grab on the Xnest display will not affect the GUI of your debugger
1068 running on your regular X server.
1078 <!-- ***************************************************************** -->
1080 <title>Development with GTK+: general questions</title>
1082 <!-- ----------------------------------------------------------------- -->
1085 <title>What widgets are in GTK?</title>
1087 <para>The GTK+ Tutorial lists the following widgets:</para>
1089 <programlisting role="C">
1100 | | | `GtkAspectFrame
1105 | | | | `GtkCheckMenuItem
1106 | | | | `GtkRadioMenuItem
1110 | | +GtkColorSelectionDialog
1112 | | | `GtkInputDialog
1113 | | `GtkFileSelection
1116 | | | +GtkHButtonBox
1117 | | | `GtkVButtonBox
1122 | | +GtkColorSelection
1126 | | `GtkToggleButton
1140 | +GtkScrolledWindow
1174 <!-- ----------------------------------------------------------------- -->
1177 <title>Is GTK+ thread safe? How do I write multi-threaded GTK+
1178 applications? <emphasis>[GTK 2.x]</emphasis></title>
1180 <para>The GLib library can be used in a thread-safe mode by
1181 calling g_thread_init() before making any other GLib
1182 calls. In this mode GLib automatically locks all internal
1183 data structures as needed. This does not mean that two
1184 threads can simultaneously access, for example, a single hash
1185 table, but they can access two different hash tables
1186 simultaneously. If two different threads need to access the
1187 same hash table, the application is responsible for locking
1190 <para>In order to make GDK thread aware, you also need to
1191 call gdk_threads_init() in conjunction with the above call.
1192 There is a single global
1193 lock that you must acquire with gdk_threads_enter() before
1194 making any GDK calls, and release with gdk_threads_leave()
1195 afterwards throughout your code.</para>
1197 <para>A minimal main program for a threaded GTK+ application
1200 <programlisting role="C">
1202 main (int argc, char *argv[])
1207 g_thread_init(NULL);
1211 gtk_init(&argc, &argv);
1213 window = create_window();
1214 gtk_widget_show(window);
1216 gdk_threads_enter();
1218 gdk_threads_leave();
1224 <para>Callbacks require a bit of attention. Callbacks from
1225 GTK+ (signals) are made within the GTK+ lock. However
1226 callbacks from GLib (timeouts, IO callbacks, and idle
1227 functions) are made outside of the GTK+ lock. So, within a
1228 signal handler you do not need to call gdk_threads_enter(),
1229 but within the other types of callbacks, you do.</para>
1231 <para>Erik Mouw contributed the following code example to
1232 illustrate how to use threads within GTK+ programs.</para>
1234 <programlisting role="C">
1235 /*-------------------------------------------------------------------------
1236 * Filename: gtk-thread.c
1238 * Copyright: Copyright (C) 1999, Erik Mouw
1239 * Author: Erik Mouw <J.A.K.Mouw@its.tudelft.nl>
1240 * Description: GTK threads example.
1241 * Created at: Sun Oct 17 21:27:09 1999
1242 * Modified by: Owen Taylor <otaylor@gtk.org>
1243 * Modified at: Wed May 28 10:43:00 2003
1244 *-----------------------------------------------------------------------*/
1248 * cc -o gtk-thread gtk-thread.c `pkg-config --cflags --libs gtk+-2.0 gthread`
1250 * Thanks to Sebastian Wilhelmi for pointing out some bugs in earlier versions.
1254 #include <unistd.h>
1255 #include <gtk/gtk.h>
1257 #define YES_IT_IS (1)
1258 #define NO_IT_IS_NOT (0)
1266 G_LOCK_DEFINE_STATIC (yes_or_no);
1267 static volatile int yes_or_no = YES_IT_IS;
1269 void destroy(GtkWidget *widget, gpointer data)
1274 void *argument_thread(void *args)
1276 yes_or_no_args *data = (yes_or_no_args *)args;
1277 gboolean say_something;
1282 sleep(g_random_int_range (1, 4));
1284 /* lock the yes_or_no_variable */
1287 /* do we have to say something? */
1288 say_something = (yes_or_no != data->what);
1292 /* set the variable */
1293 yes_or_no = data->what;
1296 /* Unlock the yes_or_no variable */
1297 G_UNLOCK(yes_or_no);
1301 /* get GTK thread lock */
1302 gdk_threads_enter();
1304 /* set label text */
1305 if(data->what == YES_IT_IS)
1306 gtk_label_set_text(GTK_LABEL(data->label), "O yes, it is!");
1308 gtk_label_set_text(GTK_LABEL(data->label), "O no, it isn't!");
1310 /* Make sure all X commands are sent to the X server; not strictly
1311 * necessary here, but always a good idea when you do anything
1312 * from a thread other than the one where the main loop is running.
1316 /* release GTK thread lock */
1317 gdk_threads_leave();
1324 int main(int argc, char *argv[])
1328 GError *error = NULL;
1329 yes_or_no_args yes_args, no_args;
1332 g_thread_init(NULL);
1336 gtk_init(&argc, &argv);
1338 /* create a window */
1339 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1341 g_signal_connect(window, "destroy",
1342 G_CALLBACK(destroy), NULL);
1344 gtk_container_set_border_width(GTK_CONTAINER (window), 10);
1346 /* create a label */
1347 label = gtk_label_new("And now for something completely different ...");
1348 gtk_container_add(GTK_CONTAINER(window), label);
1350 /* show everything */
1351 gtk_widget_show(label);
1352 gtk_widget_show (window);
1354 /* create the threads */
1355 yes_args.label = label;
1356 yes_args.what = YES_IT_IS;
1357 if (!g_thread_create(argument_thread, &yes_args, FALSE, &error))
1359 g_printerr ("Failed to create YES thread: %s\n", error->message);
1363 no_args.label = label;
1364 no_args.what = NO_IT_IS_NOT;
1365 if (!g_thread_create(argument_thread, &no_args, FALSE, &error))
1367 g_printerr ("Failed to create NO thread: %s\n", error->message);
1371 /* enter the GTK main loop */
1372 gdk_threads_enter();
1374 gdk_threads_leave();
1381 <!-- ----------------------------------------------------------------- -->
1384 <title>I'm doing some stuff with GTK+ in a separate thread, and
1385 properly locking with gdk_threads_enter/gdk_threads_leave()
1386 but the display doesn't update properly. <emphasis>[GTK 2.x]</emphasis>
1389 <para>For efficiency, the X window system batches up commands
1390 and sends them to the X server in batches instead of sending
1391 out immediately.</para>
1393 <para>In a non-multithreaded program, you don't have to worry about
1394 this, since the first thing that happens when control returns
1395 to the main loop is that any outstanding X requests are
1396 sent to the X server.</para>
1398 <para>However, if you are making GTK+ calls from a thread other
1399 than the main loop, then GTK+ doesn't know when to send batched
1400 commands out. For that reason, after making GTK+ calls
1401 in a separate thread, it is usually a good idea to call
1402 gdk_flush() before gdk_thread_leave().</para>
1404 <para>Actually, gdk_flush() is more expensive than is necessary here,
1405 since it waits for the X server to finish outstanding commands
1406 as well; if performance is an issue, you may want to call
1407 XFlush() directly:</para>
1409 <programlisting role="C">
1411 #include <gdk/gdkx.h>
1413 void my_flush_commands (void)
1415 GdkDisplay *display = gdk_display_get_default ();
1416 XFlush (GDK_DISPLAY_XDISPLAY (display);
1422 <!-- ----------------------------------------------------------------- -->
1425 <title>What's an easy way to run a function in the thread with
1426 the main loop? <emphasis>[GTK 2.x]</emphasis></title>
1428 <para>Sometimes the simplest way to set up a threaded program
1429 is to make all the GTK+ calls in a single thread. In such
1430 a program, you should still call g_threads_init(), but
1431 don't need to call gdk_threads_init(), gkd_threads_enter(),
1432 and gdk_threads_leave().</para>
1434 <para>If you set your program up this way, how then do you get
1435 the thread making GTK+ calls and running the main loop
1436 to do something in response to another thread?</para>
1438 <para>An easy way to do it is to take advantage of the fact that
1439 the GLib main loop functions are all thread safe, and can
1440 be called from any thread by adding an idle function
1441 with g_idle_add(). The function provided will be called
1442 at the next opportunity by the main thread. If you want
1443 your function to take priority over event handling and
1444 drawing, you can instead use g_idle_add_full() and pass
1445 in a priority of G_PRIORITY_HIGH.</para>
1449 <!-- ----------------------------------------------------------------- -->
1452 <title>Why does this strange 'x io error' occur when I
1453 <literal>fork()</literal> in my GTK+ app?</title>
1455 <para>This is not really a GTK+ problem, and the problem is
1456 not related to <literal>fork()</literal> either. If the 'x io
1457 error' occurs then you probably use the <literal>exit()</literal> function
1458 in order to exit from the child process.</para>
1460 <para>When GDK opens an X display, it creates a socket file
1461 descriptor. When you use the <literal>exit()</literal>
1462 function, you implicitly close all the open file descriptors,
1463 and the underlying X library really doesn't like this.</para>
1465 <para>The right function to use here is
1466 <literal>_exit()</literal>.</para>
1468 <para>Erik Mouw contributed the following code example to
1469 illustrate handling fork() and exit().</para>
1471 <programlisting role="C">
1472 /*-------------------------------------------------------------------------
1473 * Filename: gtk-fork.c
1475 * Copyright: Copyright (C) 1999, Erik Mouw
1476 * Author: Erik Mouw <J.A.K.Mouw@its.tudelft.nl>
1477 * Description: GTK+ fork example
1478 * Created at: Thu Sep 23 21:37:55 1999
1479 * Modified by: Erik Mouw <J.A.K.Mouw@its.tudelft.nl>
1480 * Modified at: Thu Sep 23 22:39:39 1999
1481 *-----------------------------------------------------------------------*/
1485 * cc -o gtk-fork gtk-fork.c `pkg-config gtk+-2.0 --cflags --libs`
1489 #include <stdio.h>
1490 #include <stdlib.h>
1491 #include <signal.h>
1492 #include <sys/types.h>
1493 #include <sys/wait.h>
1494 #include <unistd.h>
1495 #include <gtk/gtk.h>
1497 void sigchld_handler(int num)
1499 sigset_t set, oldset;
1501 int status, exitstatus;
1503 /* block other incoming SIGCHLD signals */
1504 sigemptyset(&set);
1505 sigaddset(&set, SIGCHLD);
1506 sigprocmask(SIG_BLOCK, &set, &oldset);
1508 /* wait for child */
1509 while((pid = waitpid((pid_t)-1, &status, WNOHANG)) > 0)
1511 if(WIFEXITED(status))
1513 exitstatus = WEXITSTATUS(status);
1516 "Parent: child exited, pid = %d, exit status = %d\n",
1517 (int)pid, exitstatus);
1519 else if(WIFSIGNALED(status))
1521 exitstatus = WTERMSIG(status);
1524 "Parent: child terminated by signal %d, pid = %d\n",
1525 exitstatus, (int)pid);
1527 else if(WIFSTOPPED(status))
1529 exitstatus = WSTOPSIG(status);
1532 "Parent: child stopped by signal %d, pid = %d\n",
1533 exitstatus, (int)pid);
1538 "Parent: child exited magically, pid = %d\n",
1543 /* re-install the signal handler (some systems need this) */
1544 signal(SIGCHLD, sigchld_handler);
1546 /* and unblock it */
1547 sigemptyset(&set);
1548 sigaddset(&set, SIGCHLD);
1549 sigprocmask(SIG_UNBLOCK, &set, &oldset);
1552 gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
1557 void destroy(GtkWidget *widget, gpointer data)
1562 void fork_me(GtkWidget *widget, gpointer data)
1570 /* ouch, fork() failed */
1577 fprintf(stderr, "Child: pid = %d\n", (int)getpid());
1579 execlp("ls", "ls", "-CF", "/", NULL);
1581 /* if exec() returns, there is something wrong */
1584 /* exit child. note the use of _exit() instead of exit() */
1590 fprintf(stderr, "Parent: forked a child with pid = %d\n", (int)pid);
1594 int main(int argc, char *argv[])
1599 gtk_init(&argc, &argv);
1601 /* the basic stuff: make a window and set callbacks for destroy and
1604 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1606 gtk_signal_connect(GTK_OBJECT (window), "delete_event",
1607 GTK_SIGNAL_FUNC(delete_event), NULL);
1609 gtk_signal_connect(GTK_OBJECT (window), "destroy",
1610 GTK_SIGNAL_FUNC(destroy), NULL);
1612 #if (GTK_MAJOR_VERSION == 1) && (GTK_MINOR_VERSION == 0)
1613 gtk_container_border_width(GTK_CONTAINER (window), 10);
1615 gtk_container_set_border_width(GTK_CONTAINER (window), 10);
1618 /* add a button to do something usefull */
1619 button = gtk_button_new_with_label("Fork me!");
1621 gtk_signal_connect(GTK_OBJECT (button), "clicked",
1622 GTK_SIGNAL_FUNC(fork_me), NULL);
1624 gtk_container_add(GTK_CONTAINER(window), button);
1626 /* show everything */
1627 gtk_widget_show (button);
1628 gtk_widget_show (window);
1631 /* install a signal handler for SIGCHLD signals */
1632 signal(SIGCHLD, sigchld_handler);
1643 <!-- ----------------------------------------------------------------- -->
1646 <title>Why don't the contents of a button move when the button
1647 is pressed? Here's a patch to make it work that way...</title>
1649 <para>From: Peter Mattis</para>
1651 <para><quote>The reason buttons don't move their child down and to
1652 the right when they are depressed is because I don't think
1653 that's what is happening visually. My view of buttons is
1654 that you are looking at them straight on. That is, the user
1655 interface lies in a plane and you're above it looking
1656 straight at it. When a button gets pressed it moves directly
1657 away from you. To be absolutely correct I guess the child
1658 should actually shrink a tiny amount. But I don't see why
1659 the child should shift down and to the left. Remember, the
1660 child is supposed to be attached to the buttons surface. Its
1661 not good for it to appear like the child is slipping on the
1662 surface of the button.</quote></para>
1664 <para><quote>On a more practical note, I did implement this at one point
1665 and determined it didn't look good and removed it.</quote></para>
1669 <!-- ----------------------------------------------------------------- -->
1672 <title>How do I identifiy a widgets top level window or other
1675 <para>There are a couple of ways to find the top level parent
1676 of a widget. The easier way is to call the
1677 <literal>gtk_widget_get_toplevel()</literal> function that
1678 returns pointer to a GtkWidget that is the top level
1681 <para>A more complicated way to do this (but less limited, as
1682 it allows the user to get the closest ancestor of a known type) is to use
1683 <literal>gtk_widget_get_ancestor()</literal> as in:</para>
1685 <programlisting role="C">
1687 widget = gtk_widget_get_ancestor(w, GTK_TYPE_WINDOW);
1690 <para>Since virtually all the GTK_TYPEs can be used as the
1691 second parameter of this function, you can get any parent
1692 widget of a particular widget. Suppose you have an hbox which
1693 contains a vbox, which in turn contains some other atomic
1694 widget (entry, label, etc. To find the master hbox using the
1695 <literal>entry</literal> widget simply use:</para>
1697 <programlisting role="C">
1699 hbox = gtk_widget_get_ancestor(w, GTK_TYPE_HBOX);
1704 <!-- ----------------------------------------------------------------- -->
1707 <title>How do I get the Window ID of a GtkWindow?</title>
1709 <para>The actual Gdk/X window will be created when the widget
1710 gets realized. You can get the Window ID with:</para>
1712 <programlisting role="C">
1713 #include <gdk/gdkx.h>
1715 Window xwin = GDK_WINDOW_XWINDOW (GTK_WIDGET (my_window)->window);
1719 <!-- ----------------------------------------------------------------- -->
1722 <title>How do I catch a double click event (in a list widget,
1723 for example)?</title>
1725 <para>Tim Janik wrote to gtk-list (slightly modified):</para>
1727 <para>Define a signal handler:</para>
1729 <programlisting role="C">
1731 signal_handler_event(GtkWidget *widget, GdkEventButton *event, gpointer func_data)
1733 if (GTK_IS_LIST_ITEM(widget) &&
1734 (event->type==GDK_2BUTTON_PRESS ||
1735 event->type==GDK_3BUTTON_PRESS) ) {
1736 printf("I feel %s clicked on button %d\n",
1737 event->type==GDK_2BUTTON_PRESS ? "double" : "triple",
1744 <para>And connect the handler to your object:</para>
1746 <programlisting role="C">
1748 /* list, list item init stuff */
1750 gtk_signal_connect(GTK_OBJECT(list_item),
1751 "button_press_event",
1752 GTK_SIGNAL_FUNC(signal_handler_event),
1757 gtk_signal_connect(GTK_OBJECT(list_item),
1758 "button_release_event",
1759 GTK_SIGNAL_FUNC(signal_handler_event),
1762 /* something else */
1766 <para>and, Owen Taylor wrote:</para>
1768 <para><quote>Note that a single button press will be received
1769 beforehand, and if you are doing this for a button, you will
1770 therefore also get a "clicked" signal for the button. (This
1771 is going to be true for any toolkit, since computers aren't
1772 good at reading one's mind.)</quote></para>
1776 <!-- ----------------------------------------------------------------- -->
1779 <title>By the way, what are the differences between signals
1782 <para>First of all, Havoc Pennington gives a rather complete
1783 description of the differences between events and signals in
1784 his free book (two chapters can be found at <ulink
1785 url="http://www106.pair.com/rhp/sample_chapters.html">
1786 http://www106.pair.com/rhp/sample_chapters.html</ulink>).</para>
1788 <para>Moreover, Havoc posted this to the <literal>gtk-list</literal>
1789 <quote>Events are a stream of messages received from the X
1790 server. They drive the Gtk main loop; which more or less
1791 amounts to "wait for events, process them" (not exactly, it
1792 is really more general than that and can wait on many
1793 different input streams at once). Events are a Gdk/Xlib
1794 concept.</quote></para>
1796 <para><quote>Signals are a feature of GtkObject and its subclasses. They
1797 have nothing to do with any input stream; really a signal is just a way
1798 to keep a list of callbacks around and invoke them ("emit" the
1799 signal). There are lots of details and extra features of
1800 course. Signals are emitted by object instances, and are entirely
1801 unrelated to the Gtk main loop. Conventionally, signals are emitted
1802 "when something changes" about the object emitting the
1803 signal.</quote></para>
1805 <para><quote>Signals and events only come together because GtkWidget
1806 happens to emit signals when it gets events. This is purely a
1807 convenience, so you can connect callbacks to be invoked when a
1808 particular widget receives a particular event. There is nothing about
1809 this that makes signals and events inherently related concepts, any more
1810 than emitting a signal when you click a button makes button clicking and
1811 signals related concepts.</quote></para>
1815 <!-- ----------------------------------------------------------------- -->
1818 <title>Data I pass to the <literal>delete_event</literal> (or other event)
1819 handler gets corrupted.</title>
1821 <para>All event handlers take an additional argument which
1822 contains information about the event that triggered the
1823 handler. So, a <literal>delete_event</literal> handler must
1824 be declared as:</para>
1827 <programlisting role="C">
1828 gint delete_event_handler (GtkWidget *widget,
1835 <!-- ----------------------------------------------------------------- -->
1838 <title>I have my signal connected to the the (whatever) event,
1839 but it seems I don't catch it. What's wrong?</title>
1841 <para>There is some special initialisation to do in order to
1842 catch some particular events. In fact, you must set the
1843 correct event mask bit of your widget before getting some
1844 particular events.</para>
1846 <para>For example,</para>
1848 <programlisting role="C">
1849 gtk_widget_add_events(window, GDK_KEY_RELEASE_MASK);
1852 <para>lets you catch the key release events. If you want to
1853 catch every events, simply us the GDK_ALL_EVENTS_MASK event
1856 <para>All the event masks are defined in the
1857 <filename>gdktypes.h</filename> file.</para>
1861 <!-- ----------------------------------------------------------------- -->
1864 <title>I need to add a new signal to a GTK+ widget. Any
1867 <para>If the signal you want to add may be beneficial for
1868 other GTK+ users, you may want to submit a patch that
1869 presents your changes. Check the tutorial for more
1870 information about adding signals to a widget class.</para>
1872 <para>If you don't think it is the case or if your patch is
1873 not applied you'll have to use the
1874 <literal>gtk_object_class_user_signal_new</literal>
1875 function. <literal>gtk_object_class_user_signal_new</literal> allows you
1876 to add a new signal to a predefined GTK+ widget without any
1877 modification of the GTK+ source code. The new signal can be
1878 emited with <literal>gtk_signal_emit</literal> and can be
1879 handled in the same way as other signals.</para>
1881 <para>Tim Janik posted this code snippet:</para>
1883 <programlisting role="C">
1884 static guint signal_user_action = 0;
1886 signal_user_action =
1887 gtk_object_class_user_signal_new (gtk_type_class (GTK_TYPE_WIDGET),
1889 GTK_RUN_LAST | GTK_RUN_ACTION,
1890 gtk_marshal_NONE__POINTER,
1895 gtk_widget_user_action (GtkWidget *widget,
1898 g_return_if_fail (GTK_IS_WIDGET (widget));
1900 gtk_signal_emit (GTK_OBJECT (widget), signal_user_action, act_data);
1904 <para>If you want your new signal to have more than the
1905 classical gpointer parameter, you'll have to play with GTK+
1910 <!-- ----------------------------------------------------------------- -->
1913 <title>Is it possible to get some text displayed which is
1914 truncated to fit inside its allocation?</title>
1916 <para>GTK's behavior (no clipping) is a consequence of its
1917 attempts to conserve X resources. Label widgets (among
1918 others) don't get their own X window - they just draw their
1919 contents on their parent's window. While it might be possible
1920 to have clipping occur by setting the clip mask before
1921 drawing the text, this would probably cause a substantial
1922 performance penalty.</para>
1924 <para>Its possible that, in the long term, the best solution
1925 to such problems might be just to change gtk to give labels X
1926 windows. A short term workaround is to put the label widget
1927 inside another widget that does get its own window - one
1928 possible candidate would be the viewport widget.</para>
1930 <programlisting role="C">
1931 viewport = gtk_viewport (NULL, NULL);
1932 gtk_widget_set_usize (viewport, 50, 25);
1933 gtk_viewport_set_shadow_type (GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1934 gtk_widget_show(viewport);
1936 label = gtk_label ("a really long label that won't fit");
1937 gtk_container_add (GTK_CONTAINER(viewport), label);
1938 gtk_widget_show (label);
1941 <para>If you were doing this for a bunch of widgets, you might
1942 want to copy gtkviewport.c and strip out the adjustment and
1943 shadow functionality (perhaps you could call it
1947 <!-- ----------------------------------------------------------------- -->
1950 <title>How do I make my window modal? / How do I make a single
1951 window active?</title>
1953 <para>After you create your window, do
1954 <literal>gtk_grab_add(my_window)</literal>. And after closing the window
1955 do <literal>gtk_grab_remove(my_window)</literal>.</para>
1959 <!-- ----------------------------------------------------------------- -->
1962 <title>Why doesn't my widget (e.g. progressbar)
1965 <para>You are probably doing all the changes within a function without
1966 returning control to <literal>gtk_main()</literal>. This may
1967 be the case if you do some lengthy calculation in your
1968 code. Most drawing updates are only placed on a queue, which
1969 is processed within <literal>gtk_main()</literal>. You can force the
1970 drawing queue to be processed using something like:</para>
1973 <programlisting role="C">
1974 while (g_main_iteration(FALSE));
1977 <para>inside you're function that changes the widget.</para>
1979 <para>What the above snippet does is run all pending events
1980 and high priority idle functions, then return immediately
1981 (the drawing is done in a high priority idle function).</para>
1985 <!-- ----------------------------------------------------------------- -->
1988 <title>How do I attach data to some GTK+ object/widget?
1989 <emphasis>[GTK 2.x]</emphasis></title>
1991 <para>First of all, the attached data is stored in the
1992 object_data field of a GtkObject. The type of this field is
1993 GData, which is defined in glib.h. So you should read the
1994 gdataset.c file in your glib source directory very
1997 <para>There are two (easy) ways to attach some data to a gtk
1998 object. Using <literal>g_object_set_data()</literal> and
1999 <literal>g_object_get_data()</literal> seems to be the most
2000 common way to do this, as it provides a powerful interface to
2001 connect objects and data.</para>
2003 <programlisting role="C">
2004 void g_object_set_data(GObject *object, const gchar *key, gpointer data);
2006 gpointer g_object_get_data(GObject *object, const gchar *key);
2009 <para>Since a short example is better than any lengthy speech:</para>
2011 <programlisting role="C">
2012 struct my_struct p1,p2,*result;
2015 g_object_set_data(G_OBJECT(w),"p1 data",(gpointer)&p1);
2016 g_object_set_data(G_OBJECT(w),"p2 data",(gpointer)&p2);
2018 result = g_object_get_data(G_OBJECT(w),"p1 data");
2021 <para>The <literal>gtk_object_set_user_data()</literal> and
2022 <literal>gtk_object_get_user_data()</literal> functions does
2023 exactly the same thing as the functions above, but does not
2024 let you specify the "key" parameter.Instead, it uses a
2025 standard "user_data" key. Note that the use of these functions
2026 is deprecated in 1.2. They only provide a compatibility mode
2027 with some old gtk packages.</para>
2031 <!-- ----------------------------------------------------------------- -->
2034 <title>How do I remove the data I have attached to an
2037 <para>When attaching the data to the object, you can use the
2038 <literal>gtk_object_set_data_full()</literal> function. The three
2039 first arguments of the function are the same as in
2040 <literal>gtk_object_set_data()</literal>. The fourth one is a
2041 pointer to a callback function which is called when the data
2042 is destroyed. The data is destroyed when you:</para>
2045 <listitem><simpara> destroy the object</simpara>
2048 <listitem><simpara> replace the data with a new one (with
2049 the same key)</simpara>
2052 <listitem><simpara> replace the data with NULL (with the
2060 <!-- ----------------------------------------------------------------- -->
2063 <title>How do I reparent a widget?</title>
2065 <para>The normal way to reparent (ie change the owner) of a
2066 widget should be to use the function:</para>
2068 <programlisting role="C">
2069 void gtk_widget_reparent (GtkWidget *widget,
2070 GtkWidget *new_parent)
2073 <para>But this is only a "should be" since this function does
2074 not correctly do its job on some specific widgets. The main
2075 goal of gtk_widget_reparent() is to avoid unrealizing widget
2076 if both widget and new_parent are realized (in this case,
2077 widget->window is successfully reparented). The problem here
2078 is that some widgets in the GTK+ hierarchy have multiple
2079 attached X subwindows and this is notably the case for the
2080 GtkSpinButton widget. For those, gtk_widget_reparent() will
2081 fail by leaving an unrealized child window where it should
2084 <para>To avoid this problem, simply use the following code
2087 <programlisting role="C">
2088 gtk_widget_ref(widget);
2089 gtk_container_remove(GTK_CONTAINER(old_parent), widget);
2090 gtk_container_add(GTK_CONTAINER(new_parent), widget);
2091 gtk_widget_unref(widget);
2096 <!-- ----------------------------------------------------------------- -->
2099 <title>How could I get any widgets position?</title>
2101 <para>As Tim Janik pointed out, there are different cases, and
2102 each case requires a different solution.</para>
2105 <listitem><simpara> If you want the position of a widget
2106 relative to its parent, you should use
2107 <literal>widget->allocation.x</literal> and
2108 <literal>widget->allocation.y</literal>.</simpara>
2111 <listitem><simpara> If you want the position of a window
2112 relative to the X root window, you should use
2113 <literal>gdk_window_get_geometry()</literal>
2114 <literal>gdk_window_get_position()</literal> or
2115 <literal>gdk_window_get_origin()</literal>.</simpara>
2118 <listitem><simpara> If you want to get the position of the
2119 window (including the WM decorations), you should use
2120 <literal>gdk_window_get_root_origin()</literal>.</simpara>
2123 <listitem><simpara> Last but not least, if you want to get a Window
2124 Manager frame position, you should use
2125 <literal>gdk_window_get_deskrelative_origin()</literal>.</simpara>
2129 <para>Your choice of Window Manager will have an effect of the
2130 results of the above functions. You should keep this in mind
2131 when writing your application. This is dependant upon how the
2132 Window Managers manage the decorations that they add around
2137 <!-- ----------------------------------------------------------------- -->
2140 <title>How do I set the size of a widget/window? How do I
2141 prevent the user resizing my window? <emphasis>[GTK 2.x]</emphasis></title>
2143 <para>The <literal>gtk_widget_set_size_request()</literal> function
2144 is used to set the size of a widget to a specific size.
2147 <literal>gtk_window_set_resizable()</literal> function sets whether
2148 the user can resize a window, which they can by default. The
2149 definition of these functions are:</para>
2151 <programlisting role="C">
2152 void gtk_widget_set_size_request (GtkWidget *widget,
2156 void gtk_window_set_resizable (GtkWindow *window,
2157 gboolean resizable);
2163 <!-- ----------------------------------------------------------------- -->
2166 <title>How do I add a popup menu to my GTK+ application?</title>
2168 <para>The <literal>menu</literal> example in the examples/menu
2169 directory of the GTK+ distribution implements a popup menu
2170 with this technique:</para>
2172 <programlisting role="C">
2173 static gint button_press (GtkWidget *widget, GdkEvent *event)
2176 if (event->type == GDK_BUTTON_PRESS) {
2177 GdkEventButton *bevent = (GdkEventButton *) event;
2178 gtk_menu_popup (GTK_MENU(widget), NULL, NULL, NULL, NULL,
2179 bevent->button, bevent->time);
2180 /* Tell calling code that we have handled this event; the buck
2185 /* Tell calling code that we have not handled this event; pass it on. */
2192 <!-- ----------------------------------------------------------------- -->
2195 <title>How do I disable or enable a widget, such as a
2198 <para>To disable (or to enable) a widget, use the
2199 <literal>gtk_widget_set_sensitive()</literal> function. The
2200 first parameter is you widget pointer. The second parameter is
2201 a boolean value: when this value is TRUE, the widget is
2205 <!-- ----------------------------------------------------------------- -->
2208 <title>Shouldn't the text argument in the gtk_clist_*
2209 functions be declared const?</title>
2211 <para>For example:</para>
2213 <programlisting role="C">
2214 gint gtk_clist_prepend (GtkCList *clist,
2218 <para>Answer: No, while a type "gchar*" (pointer to char) can
2219 automatically be cast into "const gchar*" (pointer to const
2220 char), this does not apply for "gchar *[]" (array of an
2221 unspecified number of pointers to char) into "const gchar *[]"
2222 (array of an unspecified number of pointers to const char).</para>
2224 <para>The type qualifier "const" may be subject to automatic
2225 casting, but in the array case, it is not the array itself
2226 that needs the (const) qualified cast, but its members, thus
2227 changing the whole type.</para>
2230 <!-- ----------------------------------------------------------------- -->
2233 <title>How do I render pixels (image data) to the
2236 <para>There are several ways to approach this. The simplest
2237 way is to use GdkRGB, see gdk/gdkrgb.h. You create an RGB
2238 buffer, render to your RGB buffer, then use GdkRGB routines to
2239 copy your RGB buffer to a drawing area or custom widget. The
2240 book "GTK+/Gnome Application Development" gives some details;
2241 GdkRGB is also documented in the GTK+ reference
2242 documentation.</para>
2244 <para>If you're writing a game or other graphics-intensive
2245 application, you might consider a more elaborate
2246 solution. OpenGL is the graphics standard that will let you
2247 access hardware accelaration in future versions of XFree86; so
2248 for maximum speed, you probably want to use OpenGL. A
2249 GtkGLArea widget is available for using OpenGL with GTK+ (but
2250 GtkGLArea does not come with GTK+ itself). There are also
2251 several open source game libraries, such as ClanLib and Loki's
2252 Simple DirectMedia Layer library (SDL).</para>
2254 <para>You do NOT want to use
2255 <literal>gdk_draw_point()</literal>, that will be extremely
2259 <!-- ----------------------------------------------------------------- -->
2262 <title>How do I create a pixmap without having my window being
2263 realized/shown?</title>
2265 <para>Functions such as
2266 <literal>gdk_pixmap_create_from_xpm()</literal> require a
2267 valid window as a parameter. During the initialisation phase
2268 of an application, a valid window may not be available without
2269 showing a window, which may be inappropriate. In order to
2270 avoid this, a function such as
2271 <literal>gdk_pixmap_colormap_create_from_xpm</literal> can be
2274 <programlisting role="C">
2275 char *pixfile = "foo.xpm";
2276 GtkWidget *top, *box, *pixw;
2277 GdkPixmap *pixmap, *pixmap_mask;
2279 top = gtk_window_new (GKT_WINDOW_TOPLEVEL);
2280 box = gtk_hbox_new (FALSE, 4);
2281 gtk_conainer_add (GTK_CONTAINER(top), box);
2283 pixmap = gdk_pixmap_colormap_create_from_xpm (
2284 NULL, gtk_widget_get_colormap(top),
2285 &pixmap_mask, NULL, pixfile);
2286 pixw = gtk_pixmap_new (pixmap, pixmap_mask);
2287 gdk_pixmap_unref (pixmap);
2288 gdk_pixmap_unref (pixmap_mask);
2293 <!-- ----------------------------------------------------------------- -->
2296 <title>How do I do drag-and-drop?</title>
2298 <para>GTK+ has a high level set of functions for doing inter-process
2299 communication via the drag-and-drop system. GTK+ can perform
2300 drag-and-drop on top of the low level Xdnd and Motif drag-and-drop
2303 <para>The documentation on GTK+ drag-and-drop isn't complete, but there
2304 is some information in the <ulink
2305 url="http://www.gtk.org/tutorial/">Tutorial</ulink>. You should also
2306 look at the drag-and-drop example code that is part of the GTK+ source
2307 distribution, in the file <filename>gtk/testdnd.c</filename>.</para>
2311 <!-- ----------------------------------------------------------------- -->
2314 <title>Why does GTK+/GLib leak memory?</title>
2316 <para>It doesn't. Both GLib and the C library (malloc implementation)
2317 will cache allocated memory on occasion, even if you free it with
2320 <para>So you can't generally use tools such as top to see if you are
2321 using free() properly (aside from the very roughest of estimations, i.e.
2322 if you are really, really screwing up top will show that, but you can't
2323 distinguish small mistakes from the GLib/malloc caches).</para>
2325 <para>In order to find memory leaks, use proper memory profiling
2332 <!-- ***************************************************************** -->
2334 <title>Development with GTK+: widget specific questions</title>
2336 <!-- ----------------------------------------------------------------- -->
2339 <title>How do I find out about the selection of a GtkList?</title>
2341 <para>Get the selection something like this:</para>
2343 <programlisting role="C">
2345 sel = GTK_LIST(list)->selection;
2348 <para>This is how GList is defined (quoting glist.h):</para>
2350 <programlisting role="C">
2351 typedef struct _GList GList;
2361 <para>A GList structure is just a simple structure for doubly
2362 linked lists. There exist several g_list_*() functions to
2363 modify a linked list in glib.h. However the
2364 GTK_LIST(MyGtkList)->selection is maintained by the
2365 gtk_list_*() functions and should not be modified.</para>
2368 <para>The selection_mode of the GtkList determines the
2369 selection facilities of a GtkList and therefore the contents
2370 of GTK_LIST(AnyGtkList)->selection:</para>
2372 <informaltable frame="all">
2376 <entry><literal>selection_mode</literal></entry>
2377 <entry><literal> GTK_LIST()->selection</literal>
2384 <entry><literal>GTK_SELECTION_SINGLE</literal></entry>
2385 <entry>selection is either NULL or contains a GList*
2386 pointer for a single selected item.</entry>
2390 <entry><literal>GTK_SELECTION_BROWSE</literal></entry>
2391 <entry>selection is NULL if the list contains no
2392 widgets, otherwise it contains a GList*
2393 pointer for one GList structure.</entry>
2397 <entry><literal>GTK_SELECTION_MULTIPLE</literal></entry>
2398 <entry>selection is NULL if no listitems are selected
2399 or a a GList* pointer for the first selected
2400 item. that in turn points to a GList structure
2401 for the second selected item and so
2406 <entry><literal>GTK_SELECTION_EXTENDED</literal></entry>
2407 <entry>selection is NULL.</entry>
2414 <para>The data field of the GList structure
2415 GTK_LIST(MyGtkList)->selection points to the first
2416 GtkListItem that is selected. So if you would like to
2417 determine which listitems are selected you should go like
2420 <programlisting role="C">
2422 gchar *list_items[]={
2428 guint nlist_items=sizeof(list_items)/sizeof(list_items[0]);
2429 GtkWidget *list_item;
2432 list=gtk_list_new();
2433 gtk_list_set_selection_mode(GTK_LIST(list), GTK_SELECTION_MULTIPLE);
2434 gtk_container_add(GTK_CONTAINER(AnyGtkContainer), list);
2435 gtk_widget_show (list);
2437 for (i = 0; i < nlist_items; i++)
2439 list_item=gtk_list_item_new_with_label(list_items[i]);
2440 gtk_object_set_user_data(GTK_OBJECT(list_item), (gpointer)i);
2441 gtk_container_add(GTK_CONTAINER(list), list_item);
2442 gtk_widget_show(list_item);
2447 <para>To get known about the selection:</para>
2449 <programlisting role="C">
2453 items=GTK_LIST(list)->selection;
2455 printf("Selected Items: ");
2457 if (GTK_IS_LIST_ITEM(items->data))
2458 printf("%d ", (guint)
2459 gtk_object_get_user_data(items->data));
2468 <!-- ----------------------------------------------------------------- -->
2471 <title>How do I stop the column headings of a GtkCList
2472 disappearing when the list is scrolled?</title>
2474 <para>This happens when a GtkCList is packed into a
2475 GtkScrolledWindow using the function
2476 <literal>gtk_scroll_window_add_with_viewport()</literal>. The prefered
2477 method of adding a CList to a scrolled window is to use the
2478 function <literal>gtk_container_add</literal>, as in:</para>
2480 <programlisting role="C">
2481 GtkWidget *scrolled, *clist;
2482 char *titles[] = { "Title1" , "Title2" };
2484 scrolled = gtk_scrolled_window_new(NULL, NULL);
2486 clist = gtk_clist_new_with_titles(2, titles);
2487 gtk_container_add(GTK_CONTAINER(scrolled), clist);
2492 <!-- ----------------------------------------------------------------- -->
2495 <title>I don't want the user of my applications to enter text
2496 into a GtkCombo. Any idea?</title>
2498 <para>A GtkCombo has an associated entry which can be accessed
2499 using the following expression:</para>
2501 <programlisting role="C">
2502 GTK_COMBO(combo_widget)->entry
2505 <para>If you don't want the user to be able to modify the
2506 content of this entry, you can use the
2507 gtk_entry_set_editable() function:</para>
2510 <programlisting role="C">
2511 void gtk_entry_set_editable(GtkEntry *entry,
2515 <para>Set the editable parameter to FALSE to disable typing
2516 into the entry.</para>
2519 <!-- ----------------------------------------------------------------- -->
2522 <title>How do I catch a combo box change?</title>
2524 <para>The entry which is associated to your GtkCombo send a
2525 "changed" signal when:</para>
2528 <listitem><simpara>some text is typed in</simpara>
2531 <listitem><simpara>the selection of the combo box is changed</simpara>
2535 <para>To catch any combo box change, simply connect your
2536 signal handler with</para>
2538 <programlisting role="C">
2539 gtk_signal_connect(GTK_COMBO(cb)->entry,
2541 GTK_SIGNAL_FUNC(my_cb_change_handler),
2547 <!-- ----------------------------------------------------------------- -->
2550 <title>How can I define a separation line in a menu?</title>
2552 <para>See the <ulink
2553 url="http://www.gtk.org/tutorial/">Tutorial</ulink> for
2554 information on how to create menus. However, to create a
2555 separation line in a menu, just insert an empty menu item:</para>
2557 <programlisting role="C">
2558 menuitem = gtk_menu_item_new();
2559 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
2560 gtk_widget_show(menuitem);
2565 <!-- ----------------------------------------------------------------- -->
2568 <title>How can I right justify a menu, such as Help?</title>
2570 <para>Depending on if you use the MenuFactory or not, there
2571 are two ways to proceed. With the MenuFactory, use something
2572 like the following:</para>
2574 <programlisting role="C">
2575 menu_path = gtk_menu_factory_find (factory, "<MyApp>/Help");
2576 gtk_menu_item_right_justify(menu_path->widget);
2579 <para>If you do not use the MenuFactory, you should simply
2583 <programlisting role="C">
2584 gtk_menu_item_right_justify(my_menu_item);
2589 <!-- ----------------------------------------------------------------- -->
2592 <title>How do I add some underlined accelerators to menu
2595 <para>Damon Chaplin, the technical force behind the Glade
2596 project, provided the following code sample (this code is an
2597 output from Glade). It creates a small <GUIMenu>File</guimenu> menu item
2598 with only one child (<guimenu>New</guimenu>). The F in
2599 <guimenu>File</guimenu> and the N in <guimenu>New</guimenu> are
2600 underlined, and the relevant accelerators are created.</para>
2602 <programlisting role="C">
2603 menubar1 = gtk_menu_bar_new ();
2604 gtk_object_set_data (GTK_OBJECT (window1), "menubar1", menubar1);
2605 gtk_widget_show (menubar1);
2606 gtk_box_pack_start (GTK_BOX (vbox1), menubar1, FALSE, FALSE, 0);
2608 file1 = gtk_menu_item_new_with_label ("");
2609 tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (file1)->child),
2611 gtk_widget_add_accelerator (file1, "activate_item", accel_group,
2612 tmp_key, GDK_MOD1_MASK, 0);
2613 gtk_object_set_data (GTK_OBJECT (window1), "file1", file1);
2614 gtk_widget_show (file1);
2615 gtk_container_add (GTK_CONTAINER (menubar1), file1);
2617 file1_menu = gtk_menu_new ();
2618 file1_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (file1_menu));
2619 gtk_object_set_data (GTK_OBJECT (window1), "file1_menu", file1_menu);
2620 gtk_menu_item_set_submenu (GTK_MENU_ITEM (file1), file1_menu);
2622 new1 = gtk_menu_item_new_with_label ("");
2623 tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (new1)->child),
2625 gtk_widget_add_accelerator (new1, "activate_item", file1_menu_accels,
2627 gtk_object_set_data (GTK_OBJECT (window1), "new1", new1);
2628 gtk_widget_show (new1);
2629 gtk_container_add (GTK_CONTAINER (file1_menu), new1);
2634 <!-- ----------------------------------------------------------------- -->
2637 <title>How can I retrieve the text from a GtkMenuItem?</title>
2639 <para>You can usually retrieve the label of a specific
2640 GtkMenuItem with:</para>
2642 <programlisting role="C">
2643 if (GTK_BIN (menu_item)->child)
2645 GtkWidget *child = GTK_BIN (menu_item)->child;
2647 /* do stuff with child */
2648 if (GTK_IS_LABEL (child))
2652 gtk_label_get (GTK_LABEL (child), &text);
2653 g_print ("menu item text: %s\n", text);
2658 <para>To get the active menu item from a GtkOptionMenu you can
2661 <programlisting role="C">
2662 if (GTK_OPTION_MENU (option_menu)->menu_item)
2664 GtkWidget *menu_item = GTK_OPTION_MENU (option_menu)->menu_item;
2668 <para>But, there's a catch. For this specific case, you can
2669 <emphasis>not</emphasis> get the label widget from
2670 <literal>menu_item</literal> with the above code, because the
2671 option menu reparents the menu_item's child temporarily to
2672 display the currently active contents. So to retrive the child
2673 of the currently active menu_item of an option menu, you'll
2676 <programlisting role="C">
2677 if (GTK_BIN (option_menu)->child)
2679 GtkWidget *child = GTK_BIN (option_menu)->child;
2681 /* do stuff with child */
2687 <!-- ----------------------------------------------------------------- -->
2690 <title>How do I right (or otherwise) justify a
2693 <para>Are you sure you want to <emphasis>justify</emphasis>
2694 the labels? The label class contains the
2695 <literal>gtk_label_set_justify()</literal> function that is
2696 used to control the justification of a multi-line
2699 <para>What you probably want is to set the <emphasis>alignment</emphasis>
2700 of the label, ie right align it, center it or left align
2701 it. If you want to do this, you should use:</para>
2703 <programlisting role="C">
2704 void gtk_misc_set_alignment (GtkMisc *misc,
2709 <para>where the <literal>xalign</literal> and
2710 <literal>yalign</literal> values are floats in
2713 <programlisting role="C">
2716 /* horizontal : left align, vertical : top */
2717 gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.0f);
2719 /* horizontal : centered, vertical : centered */
2720 gtk_misc_set_alignment(GTK_MISC(label), 0.5f, 0.5f);
2722 /* horizontal : right align, vertical : bottom */
2723 gtk_misc_set_alignment(GTK_MISC(label), 1.0f, 1.0f);
2728 <!-- ----------------------------------------------------------------- -->
2731 <title>How do I set the background color of a GtkLabel
2734 <para>The GtkLabel widget is one of a few GTK+ widgets that
2735 don't create their own window to render themselves
2736 into. Instead, they draw themselves directly onto their
2737 parents window.</para>
2739 <para>This means that in order to set the background color for
2740 a GtkLabel widget, you need to change the background color of
2741 its parent, i.e. the object that you pack it into.</para>
2745 <!-- ----------------------------------------------------------------- -->
2748 <title>How do I set the color and font of a GtkLabel using a
2749 Resource File?</title>
2751 <para>The widget name path constructed for a Label consists of
2752 the widget names of its object hierarchy as well, e.g.</para>
2754 <para><literallayout>
2755 <literal>window (name: humphrey)</literal>
2756 <literal> hbox</literal>
2757 <literal> label (name: mylabel)</literal>
2758 </literallayout></para>
2760 <para>The widget path your pattern needs to match would be:
2761 <literal>humphrey.GtkHBox.mylabel</literal></para>
2763 <para>The resource file may look something like:</para>
2765 <programlisting role="C">
2768 fg[NORMAL] = {1.0, 0.0, 0.0}
2769 font = "-adobe-helvetica-bold-r-normal--*-140-*-*-*-*-*-*"
2771 widget "*mylabel" style "title"
2774 <para>In your program, you would also need to give a name to
2775 the Label widget, which can be done using:</para>
2777 <programlisting role="C">
2778 label = gtk_label_new("Some Label Text");
2779 gtk_widget_set_name(label, "mylabel");
2780 gtk_widget_show(label);
2785 <!-- ----------------------------------------------------------------- -->
2788 <title>How do I configure Tooltips in a Resource File?</title>
2790 <para>The tooltip's window is named "gtk-tooltips",
2791 GtkTooltips in itself is not a GtkWidget (though a GtkObject)
2792 and as such is not attempted to match any widget styles.</para>
2794 <para>So, you resource file should look something like:</para>
2796 <programlisting role="C">
2799 bg[NORMAL] = {1.0, 1.0, 0.0}
2801 widget "gtk-tooltips*" style "postie"
2806 <!-- ----------------------------------------------------------------- -->
2809 <title>I can't add more than (something like) 2000 chars in a
2810 GtkEntry. What's wrong?</title>
2812 <para>There is now a known problem in the GtkEntry widget. In
2813 the <literal>gtk_entry_insert_text()</literal> function, the
2814 following lines limit the number of chars in the entry to
2817 <programlisting role="C">
2818 /* The algorithms here will work as long as, the text size (a
2819 * multiple of 2), fits into a guint16 but we specify a shorter
2820 * maximum length so that if the user pastes a very long text, there
2821 * is not a long hang from the slow X_LOCALE functions. */
2823 if (entry->text_max_length == 0)
2826 max_length = MIN (2047, entry->text_max_length);
2831 <!-- ----------------------------------------------------------------- -->
2834 <title>How do I make a GtkEntry widget activate on pressing
2835 the Return key?</title>
2837 <para>The Entry widget emits an 'activate' signal when you
2838 press return in it. Just attach to the activate signal on the
2839 entry and do whatever you want to do. Typical code would
2842 <programlisting role="C">
2843 entry = gtk_entry_new();
2844 gtk_signal_connect (GTK_OBJECT(entry), "activate",
2845 GTK_SIGNAL_FUNC(entry_callback),
2851 <!-- ----------------------------------------------------------------- -->
2854 <title>How do I validate/limit/filter the input to a GtkEntry?</title>
2856 <para>If you want to validate the text that a user enters into
2857 a GtkEntry widget you can attach to the "insert_text" signal
2858 of the entry, and modify the text within the callback
2859 function. The example below forces all characters to
2860 uppercase, and limits the range of characters to A-Z. Note
2861 that the entry is cast to an object of type GtkEditable, from
2862 which GtkEntry is derived.</para>
2864 <programlisting role="C">
2865 #include <ctype.h>
2866 #include <gtk/gtk.h>
2868 void insert_text_handler (GtkEntry *entry,
2874 GtkEditable *editable = GTK_EDITABLE(entry);
2876 gchar *result = g_new (gchar, length);
2878 for (i=0; i < length; i++) {
2879 if (!isalpha(text[i]))
2881 result[count++] = islower(text[i]) ? toupper(text[i]) : text[i];
2885 gtk_signal_handler_block_by_func (GTK_OBJECT (editable),
2886 GTK_SIGNAL_FUNC (insert_text_handler),
2888 gtk_editable_insert_text (editable, result, count, position);
2889 gtk_signal_handler_unblock_by_func (GTK_OBJECT (editable),
2890 GTK_SIGNAL_FUNC (insert_text_handler),
2893 gtk_signal_emit_stop_by_name (GTK_OBJECT (editable), "insert_text");
2904 gtk_init (&argc, &argv);
2906 /* create a new window */
2907 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
2908 gtk_window_set_title(GTK_WINDOW (window), "GTK Entry");
2909 gtk_signal_connect(GTK_OBJECT (window), "delete_event",
2910 (GtkSignalFunc) gtk_exit, NULL);
2912 entry = gtk_entry_new();
2913 gtk_signal_connect(GTK_OBJECT(entry), "insert_text",
2914 GTK_SIGNAL_FUNC(insert_text_handler),
2916 gtk_container_add(GTK_CONTAINER (window), entry);
2917 gtk_widget_show(entry);
2919 gtk_widget_show(window);
2928 <!-- ----------------------------------------------------------------- -->
2931 <title>How do I use horizontal scrollbars with a GtkText widget?</title>
2933 <para>The short answer is that you can't. The current version
2934 of the GtkText widget does not support horizontal
2935 scrolling. There is an intention to completely rewrite the
2936 GtkText widget, at which time this limitation will be
2941 <!-- ----------------------------------------------------------------- -->
2944 <title>How do I change the font of a GtkText widget?</title>
2946 <para>There are a couple of ways of doing this. As GTK+ allows
2947 the appearance of applications to be changed at run time using
2948 resources you can use something like the following in the
2949 appropriate file:</para>
2951 <programlisting role="C">
2954 font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*"
2958 <para>Another way to do this is to load a font within your
2959 program, and then use this in the functions for adding text to
2960 the text widget. You can load a font using, for example:</para>
2962 <programlisting role="C">
2964 font = gdk_font_load("-adobe-helvetica-medium-r-normal--*-140-*-*-*-*-*-*");
2969 <!-- ----------------------------------------------------------------- -->
2972 <title>How do I set the cursor position in a GtkText
2975 <para>Notice that the response is valid for any object that
2976 inherits from the GtkEditable class.</para>
2978 <para>Are you sure that you want to move the cursor position?
2979 Most of the time, while the cursor position is good, the
2980 insertion point does not match the cursor position. If this
2981 apply to what you really want, then you should use the
2982 <literal>gtk_text_set_point()</literal> function. If you want
2983 to set the insertion point at the current cursor position, use
2984 the following:</para>
2986 <programlisting role="C">
2987 gtk_text_set_point(GTK_TEXT(text),
2988 gtk_editable_get_position(GTK_EDITABLE(text)));
2991 <para>If you want the insertion point to follow the cursor at
2992 all time, you should probably catch the button press event,
2993 and then move the insertion point. Be careful : you'll have to
2994 catch it after the widget has changed the cursor position
2995 though. Thomas Mailund Jensen proposed the following
2998 <programlisting role="C">
3000 insert_bar (GtkWidget *text)
3002 /* jump to cursor mark */
3003 gtk_text_set_point (GTK_TEXT (text),
3004 gtk_editable_get_position (GTK_EDITABLE (text)));
3006 gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL,
3007 "bar", strlen ("bar"));
3011 main (int argc, char *argv[])
3013 GtkWidget *window, *text;
3015 gtk_init (&argc, &argv);
3017 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3018 text = gtk_text_new (NULL, NULL);
3019 gtk_text_set_editable (GTK_TEXT (text), TRUE);
3020 gtk_container_add (GTK_CONTAINER (window), text);
3022 /* connect after everything else */
3023 gtk_signal_connect_after (GTK_OBJECT(text), "button_press_event",
3024 GTK_SIGNAL_FUNC (insert_bar), NULL);
3026 gtk_widget_show_all(window);
3033 <para>Now, if you really want to change the cursor position,
3035 <literal>gtk_editable_set_position()</literal>
3042 <!-- ***************************************************************** -->
3044 <title>About GDK</title>
3046 <!-- ----------------------------------------------------------------- -->
3049 <title>What is GDK?</title>
3051 <para>GDK is basically a wrapper around the standard Xlib
3052 function calls. If you are at all familiar with Xlib, a lot of
3053 the functions in GDK will require little or no getting used
3054 to. All functions are written to provide an way to access Xlib
3055 functions in an easier and slightly more intuitive manner. In
3056 addition, since GDK uses GLib (see below), it will be more
3057 portable and safer to use on multiple platforms.</para>
3059 <!-- Examples, anybody? I've been mulling some over. NF -->
3063 <!-- ----------------------------------------------------------------- -->
3066 <title>How do I use color allocation?</title>
3068 <para>One of the nice things about GDK is that it's based on
3069 top of Xlib; this is also a problem, especially in the area of
3070 color management. If you want to use color in your program
3071 (drawing a rectangle or such, your code should look something
3074 <programlisting role="C">
3083 /* first, create a GC to draw on */
3084 gc = gdk_gc_new(widget->window);
3086 /* find proper dimensions for rectangle */
3087 gdk_window_get_size(widget->window, &width, &height);
3089 /* the color we want to use */
3090 color = (GdkColor *)malloc(sizeof(GdkColor));
3092 /* red, green, and blue are passed values, indicating the RGB triple
3093 * of the color we want to draw. Note that the values of the RGB components
3094 * within the GdkColor are taken from 0 to 65535, not 0 to 255.
3096 color->red = red * (65535/255);
3097 color->green = green * (65535/255);
3098 color->blue = blue * (65535/255);
3100 /* the pixel value indicates the index in the colormap of the color.
3101 * it is simply a combination of the RGB values we set earlier
3103 color->pixel = (gulong)(red*65536 + green*256 + blue);
3105 /* However, the pixel valule is only truly valid on 24-bit (TrueColor)
3106 * displays. Therefore, this call is required so that GDK and X can
3107 * give us the closest color available in the colormap
3109 gdk_color_alloc(gtk_widget_get_colormap(widget), color);
3111 /* set the foreground to our color */
3112 gdk_gc_set_foreground(gc, color);
3114 /* draw the rectangle */
3115 gdk_draw_rectangle(widget->window, gc, 1, 0, 0, width, height);
3125 <!-- ***************************************************************** -->
3127 <title>About GLib</title>
3129 <!-- ----------------------------------------------------------------- -->
3132 <title>What is GLib?</title>
3134 <para>GLib is a library of useful functions and definitions
3135 available for use when creating GDK and GTK applications. It
3136 provides replacements for some standard libc functions, such
3137 as malloc, which are buggy on some systems.</para>
3139 <para>It also provides routines for handling:</para>
3141 <itemizedlist spacing=compact>
3142 <listitem><simpara>Doubly Linked Lists</simpara>
3145 <listitem><simpara>Singly Linked Lists</simpara>
3148 <listitem><simpara>Timers</simpara>
3151 <listitem><simpara>String Handling</simpara>
3154 <listitem><simpara>A Lexical Scanner</simpara>
3157 <listitem><simpara>Error Functions</simpara>
3163 <!-- ----------------------------------------------------------------- -->
3166 <title>How can I use the doubly linked lists?</title>
3168 <para>The GList object is defined as:</para>
3170 <programlisting role="C">
3171 typedef struct _GList GList;
3181 <para>To use the GList objects, simply:</para>
3183 <programlisting role="C">
3186 gint array[] = { 1, 2, 3, 4, 5, 6 };
3190 /* add data to the list */
3191 for (pos=0;pos < sizeof array; pos++) {
3192 list = g_list_append(list, (gpointer)&array[pos]);
3195 /* run through the list */
3196 listrunner = g_list_first(list);
3197 while (listrunner) {
3198 value = (gint *)listrunner->data;
3199 printf("%d\n", *value);
3200 listrunner = g_list_next(listrunner);
3203 /* removing datas from the list */
3204 listrunner = g_list_first(list);
3205 list = g_list_remove_link(list, listrunner);
3206 list = g_list_remove(list, &array[4]);
3209 <para>The same code is usable with singly linked lists (GSList
3210 objects) by replacing g_list_* functions with the relevant
3211 g_slist_* ones (g_slist_append, g_slist_remove, ...). Just
3212 remember that since you can't go backward in a singly linked
3213 list, there is no g_slist_first function - you'll need to keep
3214 a reference on the first node of the list.</para>
3216 <!-- Some Examples might be useful here! NF -->
3217 <!-- I believe it should be better :) ED -->
3218 <!-- Linked lists are pretty standard data structures - don't want to
3219 over do it - TRG -->
3223 <!-- ----------------------------------------------------------------- -->
3226 <title>Memory does not seem to be released when I free the
3227 list nodes I've allocated</title>
3229 <para>GLib tries to be "intelligent" on this special issue: it
3230 assumes that you are likely to reuse the objects, so caches
3231 the allocated memory. If you do not want to use this behavior,
3232 you'll probably want to set up a special allocator.</para>
3234 <para>To quote Tim Janik:</para>
3235 <para><quote>If you have a certain portion of code that uses *lots*
3236 of GLists or GNodes, and you know you'd better want to release
3237 all of them after a short while, you'd want to use a
3238 GAllocator. Pushing an allocator into g_list will make all
3239 subsequent glist operations private to that allocator's memory
3240 pool (and thus you have to take care to pop the allocator
3241 again, before making any external calls): </quote></para>
3243 <programlisting role="C">
3244 GAllocator *allocator;
3248 /* set a new allocation pool for GList nodes */
3249 allocator = g_allocator_new ("list heap", 1024);
3250 g_list_push_allocator (allocator);
3252 /* do some list operations */
3253 for (i = 0; i < 4096; i++)
3254 list = g_list_prepend (list, NULL);
3255 list = g_list_reverse (list);
3257 /* beware to pop allocator befor calling external functions */
3258 g_list_pop_allocator ();
3259 gtk_label_set_text (GTK_LABEL (some_label), "some text");
3261 /* and set our private glist pool again */
3262 g_list_push_allocator (allocator);
3264 /* do some list operations */
3267 for (i = 0; i < 4096; i++)
3268 list = g_list_prepend (list, NULL);
3270 /* and back out (while freeing all of the list nodes in our pool) */
3271 g_list_pop_allocator ();
3272 g_allocator_free (allocator);
3277 <!-- ----------------------------------------------------------------- -->
3280 <title>Why use g_print, g_malloc, g_strdup and fellow glib
3283 <para>Thanks to Tim Janik who wrote to gtk-list: (slightly
3286 <para><quote>Regarding g_malloc(), g_free() and siblings, these
3287 functions are much safer than their libc equivalents. For
3288 example, g_free() just returns if called with NULL. Also, if
3289 USE_DMALLOC is defined, the definition for these functions
3290 changes (in glib.h) to use MALLOC(), FREE() etc... If
3291 MEM_PROFILE or MEM_CHECK are defined, there are even small
3292 statistics made counting the used block sizes (shown by
3293 g_mem_profile() / g_mem_check()).</quote></para>
3295 <para><quote>Considering the fact that glib provides an interface for
3296 memory chunks to save space if you have lots of blocks that
3297 are always the same size and to mark them ALLOC_ONLY if
3298 needed, it is just straight forward to create a small saver
3299 (debug able) wrapper around the normal malloc/free stuff as
3300 well - just like gdk covers Xlib. ;)</quote></para>
3302 <para><quote>Using g_error() and g_warning() inside of applications
3303 like the GIMP that fully rely on gtk even gives the
3304 opportunity to pop up a window showing the messages inside of
3305 a gtk window with your own handler (by using
3306 g_set_error_handler()) along the lines of
3307 <literal>gtk_print()</literal> (inside of
3308 gtkmain.c).</quote></para>
3312 <!-- ----------------------------------------------------------------- -->
3315 <title>What's a GScanner and how do I use one?</title>
3317 <para>A GScanner will tokenize your text, that is, it'll return
3318 an integer for every word or number that appears in its input
3319 stream, following certain (customizable) rules to perform this
3320 translation. You still need to write the parsing functions on
3321 your own though.</para>
3323 <para>Here's a little test program supplied by Tim Janik that
3326 <para><literallayout>
3327 <literal><SYMBOL> = <OPTIONAL-MINUS> <NUMBER> ;</literal>
3328 </literallayout></para>
3330 <para>constructs, while skipping "#\n" and "/**/" style
3333 <programlisting role="C">
3334 #include <glib.h>
3336 /* some test text to be fed into the scanner */
3337 static const gchar *test_text =
3339 "/* slide in some \n"
3340 " * comments, just for the\n"
3345 "# the next value is a float\n"
3348 "ping = - 0.5;\n" );
3350 /* define enumeration values to be returned for specific symbols */
3352 SYMBOL_PING = G_TOKEN_LAST + 1,
3353 SYMBOL_PONG = G_TOKEN_LAST + 2,
3354 SYMBOL_ZONK = G_TOKEN_LAST + 3
3358 static const struct {
3362 { "ping", SYMBOL_PING, },
3363 { "pong", SYMBOL_PONG, },
3364 { "zonk", SYMBOL_ZONK, },
3366 }, *symbol_p = symbols;
3368 static gfloat ping = 0;
3369 static gfloat pong = 0;
3370 static gfloat zonk = 0;
3373 parse_symbol (GScanner *scanner)
3376 gboolean negate = FALSE;
3378 /* expect a valid symbol */
3379 g_scanner_get_next_token (scanner);
3380 symbol = scanner->token;
3381 if (symbol < SYMBOL_PING ||
3382 symbol > SYMBOL_ZONK)
3383 return G_TOKEN_SYMBOL;
3386 g_scanner_get_next_token (scanner);
3387 if (scanner->token != '=')
3390 /* feature optional '-' */
3391 g_scanner_peek_next_token (scanner);
3392 if (scanner->next_token == '-')
3394 g_scanner_get_next_token (scanner);
3398 /* expect a float (ints are converted to floats on the fly) */
3399 g_scanner_get_next_token (scanner);
3400 if (scanner->token != G_TOKEN_FLOAT)
3401 return G_TOKEN_FLOAT;
3403 /* make sure the next token is a ';' */
3404 if (g_scanner_peek_next_token (scanner) != ';')
3406 /* not so, eat up the non-semicolon and error out */
3407 g_scanner_get_next_token (scanner);
3411 /* assign value, eat the semicolon and exit successfully */
3415 ping = negate ? - scanner->value.v_float : scanner->value.v_float;
3418 pong = negate ? - scanner->value.v_float : scanner->value.v_float;
3421 zonk = negate ? - scanner->value.v_float : scanner->value.v_float;
3424 g_scanner_get_next_token (scanner);
3426 return G_TOKEN_NONE;
3430 main (int argc, char *argv[])
3433 guint expected_token;
3435 scanner = g_scanner_new (NULL);
3437 /* adjust lexing behaviour to suit our needs
3439 /* convert non-floats (octal values, hex values...) to G_TOKEN_INT */
3440 scanner->config->numbers_2_int = TRUE;
3441 /* convert G_TOKEN_INT to G_TOKEN_FLOAT */
3442 scanner->config->int_2_float = TRUE;
3443 /* don't return G_TOKEN_SYMBOL, but the symbol's value */
3444 scanner->config->symbol_2_token = TRUE;
3446 /* load symbols into the scanner */
3447 while (symbol_p->symbol_name)
3449 g_scanner_add_symbol (scanner,
3450 symbol_p->symbol_name,
3451 GINT_TO_POINTER (symbol_p->symbol_token));
3455 /* feed in the text */
3456 g_scanner_input_text (scanner, test_text, strlen (test_text));
3458 /* give the error handler an idea on how the input is named */
3459 scanner->input_name = "test text";
3461 /* scanning loop, we parse the input until its end is reached,
3462 * the scanner encountered a lexing error, or our sub routine came
3463 * across invalid syntax
3467 expected_token = parse_symbol (scanner);
3469 g_scanner_peek_next_token (scanner);
3471 while (expected_token == G_TOKEN_NONE &&
3472 scanner->next_token != G_TOKEN_EOF &&
3473 scanner->next_token != G_TOKEN_ERROR);
3475 /* give an error message upon syntax errors */
3476 if (expected_token != G_TOKEN_NONE)
3477 g_scanner_unexp_token (scanner, expected_token, NULL, "symbol", NULL, NULL, TRUE);
3479 /* finsish parsing */
3480 g_scanner_destroy (scanner);
3483 g_print ("ping: %f\n", ping);
3484 g_print ("pong: %f\n", pong);
3485 g_print ("zonk: %f\n", zonk);
3491 <para>You need to understand that the scanner will parse its
3492 input and tokenize it, it is up to you to interpret these
3493 tokens, not define their types before they get parsed,
3494 e.g. watch gscanner parse a string:</para>
3496 <para><literallayout>
3497 <literal>"hi i am 17"</literal>
3498 <literal> | | | |</literal>
3499 <literal> | | | v</literal>
3500 <literal> | | v TOKEN_INT, value: 17</literal>
3501 <literal> | v TOKEN_IDENTIFIER, value: "am"</literal>
3502 <literal> v TOKEN_CHAR, value: 'i'</literal>
3503 <literal>TOKEN_IDENTIFIER, value: "hi"</literal>
3504 </literallayout></para>
3506 <para>If you configure the scanner with:</para>
3508 <programlisting role="C">
3509 scanner->config->int_2_float = TRUE;
3510 scanner->config->char_2_token = TRUE;
3511 scanner->config->scan_symbols = TRUE;
3514 <para>and add "am" as a symbol with</para>
3516 <programlisting role="C">
3517 g_scanner_add_symbol (scanner, "am", "symbol value");
3520 <para>GScanner will parse it as</para>
3522 <para><literallayout>
3523 <literal>"hi i am 17"</literal>
3524 <literal> | | | |</literal>
3525 <literal> | | | v</literal>
3526 <literal> | | v TOKEN_FLOAT, value: 17.0 (automatic int->float conversion)</literal>
3527 <literal> | | TOKEN_SYMBOL, value: "symbol value" (a successfull hash table lookup</literal>
3528 <literal> | | turned a TOKEN_IDENTIFIER into a</literal>
3529 <literal> | | TOKEN_SYMBOL and took over the</literal>
3530 <literal> | v symbol's value)</literal>
3531 <literal> v 'i' ('i' can be a valid token as well, as all chars >0 and <256)</literal>
3532 <literal>TOKEN_IDENTIFIER, value: "hi"</literal>
3533 </literallayout></para>
3535 <para>You need to match the token sequence with your code, and
3536 if you encounter something that you don't want, you error
3539 <programlisting role="C">
3540 /* expect an identifier ("hi") */
3541 g_scanner_get_next_token (scanner);
3542 if (scanner->token != G_TOKEN_IDENTIFIER)
3543 return G_TOKEN_IDENTIFIER;
3544 /* expect a token 'i' */
3545 g_scanner_get_next_token (scanner);
3546 if (scanner->token != 'i')
3548 /* expect a symbol ("am") */
3549 g_scanner_get_next_token (scanner);
3550 if (scanner->token != G_TOKEN_SYMBOL)
3551 return G_TOKEN_SYMBOL;
3552 /* expect a float (17.0) */
3553 g_scanner_get_next_token (scanner);
3554 if (scanner->token != G_TOKEN_FLOAT)
3555 return G_TOKEN_FLOAT;
3558 <para>If you got past here, you have parsed "hi i am 17" and
3559 would have accepted "dooh i am 42" and "bah i am 0.75" as
3560 well, but you would have not accepted "hi 7 am 17" or "hi i hi
3567 <!-- ***************************************************************** -->
3570 <title>GTK+ FAQ Contributions, Maintainers and Copyright</title>
3572 <para>If you would like to make a contribution to the FAQ, send either one
3573 of us an e-mail message with the exact text you think should be
3574 included (question and answer). With your help, this document can grow
3575 and become more useful!</para>
3577 <para>This document is maintained by
3579 <ulink url="mailto:gale@gtk.org"><gale@gtk.org></ulink>
3582 <ulink url="mailto:maestrox@geocities.com">
3583 <maestrox@geocities.com></ulink>,
3586 <ulink url="mailto:logout@free.fr"><logout@free.fr></ulink>.
3588 This FAQ was created by Shawn T. Amundson
3589 <ulink url="mailto:amundson@gimp.org">
3590 <amundson@gimp.org></ulink> who continues to provide support.
3592 Contributions should be sent to Tony Gale <ulink
3593 url="mailto:gale@gtk.org"><gale@gtk.org></ulink></para>
3595 <para>The GTK+ FAQ is Copyright (C) 1997-2000 by Shawn T. Amundson,
3596 Tony Gale, Emmanuel Deloget and Nathan Froyd.</para>
3598 <para>Permission is granted to make and distribute verbatim copies of this
3599 manual provided the copyright notice and this permission notice are
3600 preserved on all copies.</para>
3602 <para>Permission is granted to copy and distribute modified versions of this
3603 document under the conditions for verbatim copying, provided that this
3604 copyright notice is included exactly as in the original, and that the
3605 entire resulting derived work is distributed under the terms of a
3606 permission notice identical to this one.</para>
3608 <para>Permission is granted to copy and distribute translations of this
3609 document into another language, under the above conditions for
3610 modified versions.</para>
3612 <para>If you are intending to incorporate this document into a published
3613 work, please contact one of the maintainers, and we will make an
3614 effort to ensure that you have the most up to date information
3617 <para>There is no guarentee that this document lives up to its intended
3618 purpose. This is simply provided as a free resource. As such, the
3619 authors and maintainers of the information provided within can not
3620 make any guarentee that the information is even accurate.</para>
3624 <!-- ----------------------------------------------------------------- -->