]> Pileus Git - ~andy/gtk/blob - docs/faq/gtk-faq.sgml
minor cleanups, remove refs to gtk_menu_append
[~andy/gtk] / docs / faq / gtk-faq.sgml
1 <!doctype book PUBLIC "-//OASIS//DTD DocBook V3.1//EN" []>
2 <book>
3
4 <bookinfo>
5   <date>October 27th 2002</date>
6   <title>GTK+ FAQ</title>
7   <authorgroup>
8     <author>
9 <firstname>Tony</firstname>
10 <surname>Gale</surname>
11     </author>
12     <author>
13 <firstname>Shawn</firstname>
14 <surname>Amundson</surname>
15     </author>
16     <author>
17 <firstname>Emmanuel</firstname>
18 <surname>Deloget</surname>
19     </author>
20   </authorgroup>
21   <abstract>
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   </abstract>
26 </bookinfo>
27
28 <toc></toc>
29
30 <!-- ***************************************************************** -->
31 <chapter>
32 <title>General Information</title>
33
34 <!-- ----------------------------------------------------------------- -->
35
36 <sect1>
37 <title>Before anything else: the greetings</title>
38 <para>The FAQ authors want to thank:</para>
39 <itemizedlist spacing=Compact>
40 <listitem>
41 <simpara>Havoc Pennington</simpara>
42 </listitem>
43 <listitem>
44 <simpara>Erik Mouw</simpara>
45 </listitem>
46 <listitem>
47 <simpara>Owen Taylor</simpara>
48 </listitem>
49 <listitem>
50 <simpara>Tim Janik</simpara>
51 </listitem>
52 <listitem>
53 <simpara>Thomas Mailund Jensen</simpara>
54 </listitem>
55 <listitem>
56 <simpara>Joe Pfeiffer</simpara>
57 </listitem>
58 <listitem>
59 <simpara>Andy Kahn</simpara>
60 </listitem>
61 <listitem>
62 <simpara>Federico Mena Quntero</simpara>
63 </listitem>
64 <listitem>
65 <simpara>Damon Chaplin</simpara>
66 </listitem>
67 <listitem>
68 <simpara>and all the members of the GTK+ lists</simpara>
69 </listitem></itemizedlist>
70 <para> If we forgot you, please email us! Thanks again (I know,
71 it's really short :) </para>
72 </sect1>
73
74 <!-- ----------------------------------------------------------------- -->
75
76 <sect1>
77 <title>Authors</title>
78
79 <para>The original authors of GTK+ were:</para>
80
81 <itemizedlist spacing=Compact>
82 <listitem>
83 <simpara>Peter Mattis</simpara>
84 </listitem>
85 <listitem>
86 <simpara>Spencer Kimball</simpara>
87 </listitem>
88 <listitem>
89 <simpara>Josh MacDonald</simpara>
90 </listitem>
91 </itemizedlist>
92
93 <para>Since then, much has been added by others. Please see the
94 AUTHORS file in the distribution for the GTK+ Team.</para>
95
96 </sect1>
97
98 <!-- ----------------------------------------------------------------- -->
99
100 <sect1>
101 <title>What is GTK+?</title>
102
103 <para>GTK+ is a small and efficient widget set designed with
104 the general look and feel of Motif.  In reality, it looks much
105 better than Motif.  It contains common widgets and some more
106 complex widgets such as a file selection, and color selection
107 widgets.</para>
108
109 <para>GTK+ provides some unique features. (At least, I know of
110 no other widget library which provides them). For example, a
111 button does not contain a label, it contains a child widget,
112 which in most instances will be a label.  However, the child
113 widget can also be a pixmap, image or any combination possible
114 the programmer desires. This flexibility is adhered to
115 throughout the library.</para>
116
117 </sect1>
118
119 <!-- ----------------------------------------------------------------- -->
120
121 <sect1>
122 <title>What is the + in GTK+?</title>
123
124 <para>Peter Mattis informed the gtk mailing list that:</para>
125
126 <para><quote>I originally wrote gtk which included the three
127 libraries, libglib, libgdk and libgtk. It featured a flat
128 widget hierarchy. That is, you couldn't derive a new widget
129 from an existing one. And it contained a more standard
130 callback mechanism instead of the signal mechanism now present
131 in gtk+. The + was added to distinguish between the original
132 version of gtk and the new version. You can think of it as
133 being an enhancement to the original gtk that adds object
134 oriented features.</quote></para>
135
136 </sect1>
137
138 <!-- ----------------------------------------------------------------- -->
139
140 <sect1>
141 <title>Does the G in GTK+, GDK and GLib stand for?</title>
142
143 <para>GTK+ == Gimp Toolkit</para>
144 <para>GDK == GTK+ Drawing Kit</para>
145 <para>GLib == G Libray</para>
146
147 </sect1>
148
149 <!-- ----------------------------------------------------------------- -->
150
151 <sect1>
152 <title>Where is the documentation for GTK+?</title>
153
154 <para>In the GTK+ distribution's doc/ directory you will find
155 the reference material for both GTK and GDK, this FAQ and the
156 GTK Tutorial.</para>
157
158 <para>In addition, you can find links to HTML versions of
159 these documents  by going to <ulink url="http://www.gtk.org/">
160 http://www.gtk.org/</ulink>. A
161 packaged version of the GTK Tutorial, with SGML, HTML,
162 Postscript, DVI and text versions can be found in <ulink
163 url="ftp://ftp.gtk.org/pub/gtk/tutorial">
164 ftp://ftp.gtk.org/pub/gtk/tutorial
165 </ulink></para>
166
167 <para>There are now a couple of books available that deal with
168 programming GTK+, GDK and GNOME:</para>
169
170 <itemizedlist>
171 <listitem><simpara>Eric Harlows book entitled "Developing
172 Linux Applications with GTK+ and GDK". The ISBN is
173 0-7357-0021-4</simpara>
174 </listitem>
175 <listitem><simpara>The example code from Eric's book is
176 available on-line at <ulink
177 url="http://www.bcpl.net/~eharlow/book">
178 http://www.bcpl.net/~eharlow/book</ulink></simpara>
179 </listitem>
180 <listitem><simpara>Havoc Pennington has released a book called
181 "GTK+/GNOME Application Development". The ISBN is
182 0-7357-0078-8</simpara>
183 <simpara>The free version of the book lives here: <ulink
184 url="http://developer.gnome.org/doc/GGAD/">
185 http://developer.gnome.org/doc/GGAD/
186 </ulink></simpara>
187 <simpara>And Havoc maintains information about it and
188 errata here: <ulink
189 url="http://pobox.com/~hp/gnome-app-devel.html">
190 http://pobox.com/~hp/gnome-app-devel.html
191 </ulink></simpara>
192 </listitem>
193 </itemizedlist>
194
195 </sect1>
196
197 <!-- ----------------------------------------------------------------- -->
198
199 <sect1>
200 <title>Is there a mailing list (or mailing list archive) for
201 GTK+?</title>
202
203 <para>Information on mailing lists relating to GTK+ can be
204 found at: <ulink
205 url="http://www.gtk.org/mailinglists.html">
206 http://www.gtk.org/mailinglists.html
207 </ulink></para>
208
209 </sect1>
210
211 <!-- ----------------------------------------------------------------- -->
212
213 <sect1>
214 <title>How to get help with GTK+</title>
215
216 <para>First, make sure your question isn't answered in the
217 documentation, this FAQ or the tutorial. Done that? You're
218 sure you've done that, right? In that case, the best place to
219 post questions is to the GTK+ mailing list.</para>
220
221 </sect1>
222
223 <!-- ----------------------------------------------------------------- -->
224
225 <sect1>
226 <title>How to report bugs in GTK+</title>
227
228 <para>Bugs should be reported to the GNOME bug tracking system
229 (<ulink url="http://bugzilla.gnome.org">http://bugzilla.gnome.org</ulink>).
230 You will need to enter your email address and receive a password before
231 you can use the system to register a new bug report.</para>
232
233 <para>There are a number of options to select and boxes to fill in when
234 submitting a bug report. Please remember that the more information you
235 give, the easier it will be to track the problem down. Extra information
236 that may prove useful includes:</para>
237
238 <itemizedlist>
239 <listitem><simpara> How to reproduce the bug.</simpara>
240 <simpara>If you can reproduce it with the testgtk program
241 that is built in the gtk/ subdirectory, that will be most
242 convenient. Otherwise, please include a short test program
243 that exhibits the behavior. As a last resort, you can also
244 provide a pointer to a larger piece of software that can
245 be downloaded.</simpara>
246 <simpara>(Bugs that can be reproduced within the GIMP are
247 almost as good as bugs that can be reproduced in
248 testgtk. If you are reporting a bug found with the GIMP,
249 please include the version number of the GIMP you are
250 using)</simpara>
251 </listitem>
252
253 <listitem><simpara> If the bug was a crash, the exact text that was
254 printed out when the crash occurred.</simpara>
255 </listitem>
256
257 <listitem><simpara> Further information such as stack traces
258 may be useful, but are not necessary. If you do send a stack trace,
259 and the error is an X error, it will be more useful if the stacktrace is
260 produced running the test program with the <literal>--sync</literal>
261 command line option.</simpara>
262 </listitem>
263 </itemizedlist>
264
265 </sect1>
266
267 <!-- ----------------------------------------------------------------- -->
268
269 <sect1>
270 <title>Is there a Windows version of GTK+?</title>
271
272 <para>There is an on going port of GTK+ to the Windows
273 platform which is making impressive progress.</para>
274
275 <para>See <ulink
276 url="http://www.iki.fi/tml/gimp/win32">
277 http://www.iki.fi/tml/gimp/win32</ulink>
278 for more information.</para>
279
280 </sect1>
281
282 <!-- ----------------------------------------------------------------- -->
283
284 <sect1>
285 <title>What applications have been written with GTK+?</title>
286
287 <para>A list of some GTK+ based application can be found on
288 the GTK+ web server at <ulink
289 url="http://www.gtk.org/apps/">http://www.gtk.org/apps/</ulink>
290 and contains more than 350 applications.</para>
291
292 <para>Failing that, look for a project to work on for the
293 GNOME project, <ulink
294 url="http://www.gnome.org/">http://www.gnome.org/</ulink>
295 Write a game. Write something that is useful.</para>
296 <para>Some of these are:</para>
297
298 <itemizedlist>
299 <listitem><simpara> GIMP (<ulink
300 url="http://www.gimp.org/">http://www.gimp.org/</ulink>), an
301 image manipulation program</simpara>
302 </listitem>
303 <listitem><simpara> AbiWord (<ulink
304 url="http://www.abisource.com/">http://www.abisource.com/</ulink>),
305 a professional word processor</simpara>
306 </listitem>
307 <listitem><simpara> Gzilla (<ulink
308 url="http://www.levien.com/gzilla/">http://www.levien.com/gzilla/</ulink>),
309 a web browser</simpara>
310 </listitem>
311 <listitem><simpara> XQF (<ulink
312 url="http://www.botik.ru/~roma/quake/">
313 http://www.botik.ru/~roma/quake/</ulink>),
314 a QuakeWorld/Quake2 server browser and launcher</simpara>
315 </listitem>
316 <listitem><simpara> GDK Imlib (<ulink
317 url="http://www.rasterman.com/imlib.html">
318 http://www.rasterman.com/imlib.html</ulink>),
319 a fast image loading and manipulation library for GDK</simpara>
320 </listitem>
321 <listitem><simpara> Glade (<ulink
322 url="http://glade.pn.org/">http://glade.pn.org/</ulink>), a
323 GTK+ based RAD tool which produces GTK+ applications</simpara>
324 </listitem>
325 </itemizedlist>
326 </sect1>
327
328 <!-- ----------------------------------------------------------------- -->
329
330 <sect1>
331 <title>I'm looking for an application to write in GTK+. How
332 about an IRC client?</title>
333
334 <para>Ask on gtk-list for suggestions. There are at least
335 three IRC clients already under development (probably more in fact. The
336 server at <ulink url="http://www.forcix.cx/irc-clients.html">
337 http://www.forcix.cx/irc-clients.html</ulink> list a bunch of
338 them).</para>
339
340 <itemizedlist spacing=compact>
341 <listitem><simpara> X-Chat.</simpara>
342 </listitem>
343 <listitem><simpara> girc. (Included with GNOME)</simpara>
344 </listitem>
345 <listitem><simpara> gsirc. (In the gnome CVS tree)</simpara>
346 </listitem>
347 </itemizedlist>
348
349 </sect1>
350
351 </chapter>
352
353 <!-- ***************************************************************** -->
354 <chapter>
355 <title>How to find, configure, install, and troubleshoot GTK+</title>
356
357 <!-- ----------------------------------------------------------------- -->
358
359 <sect1>
360 <title>What do I need to run GTK+?</title>
361
362 <para>To compile GTK+, all you need is a C compiler (gcc) and
363 the X Window System and associated libraries on your system.</para>
364
365 </sect1>
366
367 <!-- ----------------------------------------------------------------- -->
368
369 <sect1>
370 <title>Where can I get GTK+?</title>
371
372 <para>The canonical site is <ulink
373 url="ftp://ftp.gtk.org/pub/gtk">ftp://ftp.gtk.org/pub/gtk</ulink>.</para>
374
375 <para>This site tends to get busy around the time of a new
376 GTK+ release so try and use one of the mirror sites that are
377 listed in <ulink
378 url="ftp://ftp.gtk.org/etc/mirrors">ftp://ftp.gtk.org/etc/mirrors
379 </ulink></para>
380
381 <para>Here's a few mirror sites to get you started:</para>
382
383 <itemizedlist spacing=compact>
384 <listitem><simpara> Africa -
385 <ulink url="ftp://ftp.is.co.za/applications/gimp">
386 ftp://ftp.is.co.za/applications/gimp</ulink></simpara> 
387 </listitem>
388 <listitem><simpara> Australia -
389 <ulink
390 url="ftp://ftp.au.gimp.org/pub/gimp">
391 ftp://ftp.au.gimp.org/pub/gimp</ulink></simpara> 
392 </listitem>
393 <listitem><simpara> Finland -
394 <ulink url="ftp://ftp.funet.fi/pub/sci/graphics/packages/gimp">
395 ftp://ftp.funet.fi/pub/sci/graphics/packages/gimp</ulink></simpara> 
396 </listitem>
397 <listitem><simpara> Germany -
398 <ulink url="ftp://infosoc.uni-koeln.de/pub/ftp.gimp.org">
399 ftp://infosoc.uni-koeln.de/pub/ftp.gimp.org"</ulink></simpara> 
400 </listitem>
401 <listitem><simpara> Japan -
402 <ulink url="ftp://SunSITE.sut.ac.jp/pub/archives/packages/gimp">
403 ftp://SunSITE.sut.ac.jp/pub/archives/packages/gimp</ulink></simpara> 
404 </listitem>
405 <listitem><simpara> UK - 
406 <ulink url="ftp://ftp.flirble.org/pub/X/gimp">
407 ftp://ftp.flirble.org/pub/X/gimp</ulink></simpara>
408 </listitem>
409 <listitem><simpara> US -
410 <ulink url="ftp://ftp.insync.net/pub/mirrors/ftp.gimp.org">
411 ftp://ftp.insync.net/pub/mirrors/ftp.gimp.org</ulink></simpara> 
412 </listitem>
413 </itemizedlist>
414 </sect1>
415
416 <!-- ----------------------------------------------------------------- -->
417
418 <sect1>
419 <title>How do I configure/compile GTK+?</title>
420
421 <para>Generally, all you will need to do is issue the commands:</para>
422
423 <para><literallayout><literal>./configure</literal>
424 <literal>make</literal></literallayout></para>
425
426 <para>in the gtk+-version/ directory.</para>
427 </sect1>
428
429 <!-- ----------------------------------------------------------------- -->
430
431 <sect1>
432 <title>When compiling GTK+ I get an error like: <literal>make:
433 file `Makefile' line 456: Syntax error</literal></title>
434
435 <para>Make sure that you are using GNU make
436 (use <literal>make -v</literal>
437 to check). There are many weird and wonderful versions of make
438 out there, and not all of them handle the automatically
439 generated Makefiles.</para>
440
441 </sect1>
442
443 <!-- ----------------------------------------------------------------- -->
444
445 <sect1>
446 <title>I've compiled and installed GTK+, but I can't get any
447 programs to link with it!</title>
448
449 <para>This problem is most often encountered when the GTK+
450 libraries can't be  found or are the wrong version. Generally,
451 the compiler will complain about an 'unresolved symbol'.
452 There are two things you need to check:</para>
453
454 <itemizedlist>
455 <listitem><simpara>Make sure that the libraries can be
456 found. You want to edit <filename>/etc/ld.so.conf</filename> to
457 include the directories which contain the GTK libraries,
458 so it looks something like:</simpara>
459
460 <para><literallayout><literal>/usr/X11R6/lib</literal>
461 <literal>/usr/local/lib</literal></literallayout></para>
462
463 <para>Then you need to run /sbin/ldconfig as root. You can
464 find what directory GTK is in using</para>
465
466 <para><literallayout><literal>gtk-config --libs</literal>
467 </literallayout></para>
468
469 <para>If your system doesn't use ld.so to find libraries
470 (such as Solaris), then you will have to use the LD_LIBRARY_PATH
471 environment variable (or compile the path into your program, which I'm
472 not going to cover here). So, with a Bourne type shell you can do (if
473 your GTK libraries are in /usr/local/lib):</para>
474
475 <para><literallayout>
476 <literal>export LD_LIBRARY_PATH=/usr/local/lib</literal>
477 </literallayout></para>
478
479 <para>and in a csh, you can do:</para>
480
481 <para><literallayout>
482 <literal>setenv LD_LIBRARY_PATH /usr/local/lib</literal>
483 </literallayout></para>
484
485 </listitem>
486 <listitem><simpara>Make sure the linker is finding the
487 correct set of libraries. If you have a Linux distribution that
488 installs GTK+ (e.g. RedHat 5.0) then this  older version may be
489 used. Now (assuming you have a RedHat system), issue the
490 command</simpara>
491
492 <para><literallayout>
493 <literal>rpm -e gtk gtk-devel</literal>
494 </literallayout></para>
495
496 <para>You may also want to remove the packages that depend
497 on gtk (rpm will tell you which ones they are).  If you don't have a
498 RedHat Linux system, check to make sure that neither
499 <filename>/usr/lib</filename> or <filename>/usr/local/lib</filename>
500 contain any of the libraries libgtk, libgdk, libglib, or libgck. If
501 they do exist, remove them (and any gtk include files, such as
502 <filename>/usr/include/gtk</filename> and
503 <filename>/usr/include/gdk</filename>) and reinstall gtk+.</para>
504 </listitem>
505 </itemizedlist>
506
507 </sect1>
508
509 <!-- ----------------------------------------------------------------- -->
510
511 <sect1>
512 <title>When compiling programs with GTK+, I get compiler error
513 messages about not being able to find
514 <literal>glibconfig.h</literal>.</title>
515
516 <para>The header file "glibconfig.h" was moved to the
517 directory $exec_prefix/lib/glib/include/. $exec_prefix is the
518 directory that was specified by giving the --exec-prefix flags
519 to ./configure when compiling GTK+. It defaults to  $prefix,
520 (specified with --prefix), which in turn defaults to /usr/local/.</para>
521
522 <para>This was done because "glibconfig.h" includes
523 architecture dependent information, and the rest of the
524 include files are put in $prefix/include, which can be shared
525 between different architectures.</para>
526
527 <para>GTK+ includes a shell script, <literal>/gtk-config/</literal>,
528 that makes it easy to find out the correct include paths. The GTK+
529 Tutorial includes an example of using <literal>/gtk-config/</literal>
530 for simple compilation from the command line. For information about more
531 complicated configuration, see the file docs/gtk-config.txt in the GTK+
532 distribution.</para>
533
534 <para>If you are trying to compile an old program, you may be
535 able to work around the problem by configuring it with a
536 command line like:</para>
537
538 <para><literallayout>
539 <literal>setenv CPPFLAGS "-I/usr/local/include/glib/include"</literal>
540 <literal>./configure</literal>
541 </literallayout></para>
542
543 <para>(Substitute the appropriate value of $exec_prefix for
544 /usr/local.)</para>
545
546 </sect1>
547
548 <!-- ----------------------------------------------------------------- -->
549
550 <sect1>
551 <title>When installing a GTK+ application, configure reports
552 that it can't find GTK.</title>
553
554 <para>There are several common reasons for this:</para>
555
556 <itemizedlist>
557 <listitem><simpara>You have an old version of GTK installed
558 somewhere. RedHat 5.0, for example, installs an older copy of GTK that
559 may not work with the latest applications. You should remove this old
560 copy, but note that in the case of RedHat 5.0 this will
561 break the <literal>control-panel</literal> applications.</simpara>
562 </listitem>
563
564 <listitem><simpara><literal>gtk-config</literal> (or another
565 component of GTK) isn't in your path, or there is an old
566 version on your system. Type:</simpara>
567
568 <para><literallayout>
569 <literal>gtk-config --version</literal>
570 </literallayout></para>
571
572 <para>to check for both of these. If it returns a value
573 different from what you expect, then you have an old
574 version of GTK on your system.</para>
575 </listitem>
576
577 <listitem><simpara>The ./configure script can't find the GTK
578 libraries. As ./configure compiles various test programs, it needs to be
579 able to find the GTK libraries. See the question above
580 for help on this. </simpara></listitem>
581 </itemizedlist>
582
583 <para>If none of the above help, then have a look in
584 config.log, which is generated by ./configure as it runs. At the
585 bottom will be the last action it took before failing. If it is a
586 section of source code, copy the source code to a file and compile it
587 with the line just above it in config.log. If the compilation is
588 successful, try executing it.</para>
589
590 </sect1>
591
592 </chapter>
593
594 <!-- ***************************************************************** -->
595 <chapter>
596 <title>Development of GTK+</title>
597
598 <!-- ----------------------------------------------------------------- -->
599
600 <sect1>
601 <title>Whats this CVS thing that everyone keeps talking about,
602 and how do I access it?</title>
603
604 <para>CVS is the Concurrent Version System and is a very
605 popular means of version control for software projects. It is
606 designed to allow multiple  authors to be able to
607 simultanously operate on the same source tree.  This source
608 tree is centrally maintained, but each developer has a local
609 mirror of this repository that they make their changes to.</para>
610
611 <para>The GTK+ developers use a CVS repository to store the
612 master copy of the current development version of GTK+. As
613 such, people wishing to contribute patches to GTK+ should
614 generate them against the CVS version. Normal people should
615 use the packaged releases.</para>
616
617 <para>The CVS toolset is available as RPM packages from the
618 usual RedHat sites. The latest version is available at <ulink
619 url="http://download.cyclic.com/pub/">http://download.cyclic.com/pub/
620 </ulink></para>
621
622 <para>Anyone can download the latest CVS version of GTK+ by
623 using anonymous access using the following steps:</para>
624
625 <itemizedlist>
626 <listitem><simpara> In a bourne shell descendant (e.g. bash) type:</simpara>
627 <para><literallayout>
628 <literal>CVSROOT=':pserver:anonymous@anoncvs.gnome.org:/cvs/gnome'</literal>
629 <literal>export CVSROOT</literal>
630 </literallayout></para>
631 </listitem>
632
633 <listitem><simpara>Next, the first time the source tree is
634 checked out, a cvs login is needed. </simpara>
635 <para><literallayout>
636 <literal>cvs login</literal>
637 </literallayout></para>
638 <para>This will ask you for a password. There is no
639 password for cvs.gimp.org, so just enter a carriage return.</para>
640 </listitem>
641
642 <listitem><simpara>To get the tree and place it in a subdir of your
643 current working directory, issue the command:</simpara>
644 <para><literallayout>
645 <literal>cvs -z3 get gtk+</literal>
646 </literallayout></para>
647 <para>Note that with the GTK+ 1.1 tree, glib has been moved to
648 a separate CVS module, so if you don't have glib installed you will
649 need to get that as well:</para>
650 <para><literallayout>
651 <literal>cvs -z3 get glib</literal>
652 </literallayout></para>
653 </listitem>
654 </itemizedlist>
655
656 </sect1>
657
658 <!-- ----------------------------------------------------------------- -->
659
660 <sect1>
661 <title>How can I contribute to GTK+?</title>
662
663 <para>It's simple. If something doesn't work like you think it
664 should in a program, check the documentation to make sure
665 you're not missing something. If it is a true bug or missing
666 feature, track it down in the GTK+ source, change it,  and
667 then generate a patch in the form of a 'context diff'. This
668 can be done using a command such as <literal>diff -ru
669 &lt;oldfile&gt; &lt;newfile&gt;</literal>. Then upload the patchfile
670 to:</para>
671
672 <para><literallayout>
673 <literal>ftp://ftp.gtk.org/incoming</literal>
674 </literallayout></para>
675
676 <para>along with a README file. Make sure you follow the
677 naming conventions or your patch will just be deleted! The
678 filenames should be of this form:</para>
679
680 <para><literallayout>
681 <literal>gtk&lt;username&gt;-&lt;date yymmdd-n&gt;.patch.gz</literal>
682 <literal>gtk-&lt;username&gt;-&lt;date yymmdd-n&gt;.patch.README</literal>
683 </literallayout></para>
684
685 <para>The "n" in the date indicates a unique number (starting
686 from 0) of patches you uploaded that day.  It should be 0,
687 unless you upload more than one patch in the same day.</para>
688
689 <para>Example:</para>
690
691 <para><literallayout>
692 <literal>gtk-gale-982701-0.patch.gz</literal>
693 <literal>gtk-gale-982701-0.patch.README</literal>
694 </literallayout></para>
695
696 <para>Once you upload <emphasis>anything</emphasis>, send the README to
697 ftp-admin@gtk.org</para>
698
699 </sect1>
700
701 <!-- ----------------------------------------------------------------- -->
702
703 <sect1>
704 <title>How do I know if my patch got applied, and if not, why
705 not?</title>
706
707 <para>Uploaded patches will be moved to
708 <filename>ftp://ftp.gtk.org/pub/gtk/patches</filename> where one of the
709 GTK+ development team will pick them up. If applied, they will be moved
710 to <filename>/pub/gtk/patches/old</filename>.</para>
711
712 <para>Patches that aren't applied, for whatever reason, are
713 moved to <filename>/pub/gtk/patches/unapplied</filename> or
714 <filename>/pub/gtk/patches/outdated</filename>. At this point you can ask
715 on the <literal>gtk-list</literal> mailing list why your patch wasn't
716 applied. There are many possible reasons why patches may not
717 be applied, ranging from it doesn't apply cleanly, to it isn't
718 right. Don't be put off if your patch didn't make it first
719 time round.</para>
720
721 </sect1>
722
723 <!-- ----------------------------------------------------------------- -->
724
725 <sect1>
726 <title>What is the policy on incorporating new widgets into
727 the library?</title>
728
729 <para>This is up to the authors, so you will have to ask them
730 once you are done with your widget. As a general guideline,
731 widgets that are  generally useful, work, and are not a
732 disgrace to the widget set will gladly be included.</para>
733
734 </sect1>
735
736 <!-- ----------------------------------------------------------------- -->
737
738 <sect1>
739 <title>Is anyone working on bindings for languages other than
740 C?</title>
741
742 <para>The GTK+ home page (<ulink
743 url="http://www.gtk.org/">http://www.gtk.org/</ulink>)
744 presents a list of GTK+ bindings.</para>
745
746 <itemizedlist>
747 <listitem><simpara>There are several C++ wrappers for GTK+.</simpara>
748
749   <itemizedlist> 
750   <listitem><simpara>the gtk-- package, which is a very small wrapper for
751   GTK+. You can find the home page at <ulink
752   url="http://www.cs.tut.fi/~p150650/gtk/gtk--.html">
753   http://www.cs.tut.fi/~p150650/gtk/gtk--.html</ulink>. The FTP site is 
754   <ulink url="ftp://ftp.gtk.org/pub/gtk/gtk--">
755   ftp://ftp.gtk.org/pub/gtk/gtk--</ulink>.</simpara>
756   </listitem>
757
758   <listitem><simpara>the VDK package, which was built as
759   the base package of a GTK+ application Borland-like
760   builder. The home page can be found at <ulink
761   url="http://www.guest.net/homepages/mmotta/VDKHome">
762   http://www.guest.net/homepages/mmotta/VDKHome</ulink>.</simpara>
763   </listitem>
764
765   <listitem><simpara>The wxWindows/Gtk package, a free C++ library for
766   cross-platform GUI development. The home page of this package is
767   <ulink url="http://www.freiburg.linux.de/~wxxt/">
768   http://www.freiburg.linux.de/~wxxt/</ulink>.</simpara>
769   </listitem>
770
771   </itemizedlist>
772 </listitem>
773
774 <listitem><simpara>There are three known Objective-c
775 bindings currently in development:</simpara>
776
777   <itemizedlist> 
778   <listitem><simpara>The <ulink
779   url="http://www.gnome.org/">http://www.gnome.org/</ulink>
780   package of choice is objgtk. Objgtk is based on the Object class and
781   is maintained by <ulink url="mailto:sopwith@cuc.edu">Elliot
782   Lee</ulink>. Apparently, objgtk is being accepted as the `standard'
783   Objective-C binding for GTK+.</simpara>
784   </listitem>
785
786   <listitem><simpara>If you are more inclined towards the 
787   <ulink url="http://www.gnustep.org/">GNUstep project</ulink>,
788   you may want to check out GTKKit by 
789   <ulink url="mailto:helge@mdlink.de">Helge He&szlig;</ulink>.
790   The intention is to setup a GTK+ binding using the FoundationKit. 
791   GTKKit includes nicities like writing a XML-type template file to 
792   construct a GTK+ interface.</simpara>
793   </listitem>
794
795   <listitem><simpara>The GToolKit package, which can be found at
796   <ulink url="ftp://ftp.gtk.org/pub/gtk/objc-gtoolkit/">
797   ftp://ftp.gtk.org/pub/gtk/objc-gtoolkit/</ulink>.</simpara>
798   </listitem>
799   
800   </itemizedlist>
801 </listitem>
802
803 <listitem><simpara>Perl bindings <ulink
804 url="ftp://ftp.gtk.org/pub/gtk/perl">
805 ftp://ftp.gtk.org/pub/gtk/perl</ulink></simpara>
806 </listitem>
807
808 <listitem><simpara>Guile bindings. The home page is at
809 <ulink url="http://www.ping.de/sites/zagadka/guile-gtk">
810 http://www.ping.de/sites/zagadka/guile-gtk</ulink>.
811 By the way, Guile is the GNU Project's implemention of R4RS Scheme (the
812 standard). If you like Scheme, you may want to take a look at
813 this.</simpara>
814 </listitem>
815
816 <listitem><simpara>David Monniaux reports:
817 <quote>I've started a gtk-O'Caml binding system.
818 The basics of the system, including callbacks, work fine.
819
820 The current development is in
821 <ulink url="http://www.ens-lyon.fr/~dmonniau/arcs">
822 http://www.ens-lyon.fr/~dmonniau/arcs</ulink>
823 </quote></simpara>
824 </listitem>
825
826 <listitem><simpara>Several python bindings have been done:</simpara>
827
828   <itemizedlist>
829   <listitem><simpara>pygtk is at 
830   <ulink url="http://www.daa.com.au/~james/pygtk">
831   http://www.daa.com.au/~james/pygtk</ulink> and 
832   <ulink url="ftp://ftp.gtk.org/pub/gtk/python">
833   ftp://ftp.gtk.org/pub/gtk/python</ulink></simpara>
834   </listitem>
835
836   <listitem><simpara>python-gtk is at
837   <ulink url="http://www.ucalgary.ca/~nascheme/python-gtk">
838   http://www.ucalgary.ca/~nascheme/python-gtk</ulink></simpara>
839   </listitem>
840   
841   </itemizedlist>
842 </listitem>
843
844 <listitem><simpara>There's are a couple of OpenGL/Mesa
845 widgets available for GTK+. I suggest you start at
846 <ulink url="http://www.student.oulu.fi/~jlof/gtkglarea/index.html">
847 http://www.student.oulu.fi/~jlof/gtkglarea/index.html</ulink></simpara>
848 </listitem>
849 <listitem><simpara>Last, there are a lot of other language
850 bindings for languages such as Eiffel, TOM, Pascal, Pike, etc.</simpara>
851 </listitem>
852
853 </itemizedlist>
854 </sect1>
855
856 </chapter>
857
858 <!-- ***************************************************************** -->
859 <chapter>
860 <title>Development with GTK+: the begining</title>
861
862 <!-- ----------------------------------------------------------------- -->
863
864 <sect1>
865 <title>How do I get started?</title>
866
867 <para>So, after you have installed GTK+ there are a couple of
868 things that can ease you into developing applications with
869 it. There is the GTK+ Tutorial <ulink
870 url="http://www.gtk.org/tutorial/">
871 http://www.gtk.org/tutorial/</ulink>, which is undergoing
872 development. This will introduce you to writing applications
873 using C.</para>
874
875 <para>The Tutorial doesn't (yet) contain information on all of
876 the widgets that are in GTK+. For example code on how to use
877 the basics of all the GTK+ widgets you should look at the file
878 gtk/testgtk.c (and associated source files) within the GTK+
879 distribution. Looking at these examples will give you a good
880 grounding on what the widgets can do.</para>
881
882 </sect1>
883
884 <!-- ----------------------------------------------------------------- -->
885
886 <sect1>
887 <title>How do I write security sensitive/SUID/SGID programs with GTK+?
888 Is GTK+ secure? What's this GTK_MODULES security hole I heard about?</title>
889
890 <para>The short answer to this question is: Don't write SUID/SGID
891 programs with GTK+</para>
892
893 <para>For a more thorough explanation of the GTK+ Developers position on
894 this issue see <ulink
895 url="http://www.gtk.org/setuid.html">http://www.gtk.org/setuid.html</ulink>.</para>
896
897 </sect1>
898
899 <!-- ----------------------------------------------------------------- -->
900
901 <sect1>
902 <title>I tried to compile a small <command>Hello World</command> of mine,
903 but it failed. Any clue?</title>
904
905 <para>Since you are good at coding, we will not deal with
906 compile time error here :)</para>
907
908 <para>The classic command line to compile a GTK+ based program is</para>
909 <para><literallayout>
910 <literal>gcc -o myprog [c files] `gtk-config --cflags --libs`</literal>
911 </literallayout></para>
912
913 <para>You should notice the backquote character which is used
914 in this command line. A common mistake when you start a GTK+
915 based development is to use quote instead of backquotes. If
916 you do so, the compiler will complain about an unknown file
917 called <filename>gtk-config --cflags --libs</filename>. The
918 text in backquotes is an instruction to your shell to
919 substitute the output of executing this text into the
920 commandline.</para>
921
922 <para>The command line above ensure that:</para>
923
924 <itemizedlist>
925 <listitem><simpara>the correct C compiler flags will be used
926 to compile the program (including the complete C header
927 directory list)</simpara>
928 </listitem>
929
930 <listitem><simpara>your program will be linked with the
931 needed libraries.</simpara>
932 </listitem>
933 </itemizedlist>
934
935 </sect1>
936
937 <!-- ----------------------------------------------------------------- -->
938
939 <sect1>
940 <title>What about using the <command>make</command>
941 utility?</title>
942
943 <para>This is a sample makefile which compile a GTK+ based
944 program:</para>
945
946 <programlisting role="C">
947 # basic GTK+ app makefile
948 SOURCES = myprg.c foo.c bar.c
949 OBJS    = ${SOURCES:.c=.o}
950 CFLAGS  = `gtk-config --cflags`
951 LDADD   = `gtk-config --libs`
952 CC      = gcc
953 PACKAGE = myprg
954
955 all : ${OBJS}
956   ${CC} -o ${PACKAGE} ${OBJS} ${LDADD}
957
958 .c.o:
959   ${CC} ${CFLAGS} -c $<
960
961 # end of file
962 </programlisting>
963
964 <para>For more information about the <command>make</command> utility, you
965 should read either the related man page or the relevant info file.</para>
966
967 </sect1>
968
969 <!-- ----------------------------------------------------------------- -->
970
971 <sect1>
972 <title>I use the backquote stuff in my makefiles, but my make
973 process failed.</title>
974
975 <para>The backquote construction seems to not be accepted by
976 some old <command>make</command> utilities. If you use one of these, the
977 make process will probably fail. In order to have the
978 backquote syntax working again, you should use the GNU make
979 utility (get it on the GNU ftp server at <ulink
980 url="ftp://ftp.gnu.org/">ftp://ftp.gnu.org/</ulink>).</para>
981
982 </sect1>
983
984 <!-- ----------------------------------------------------------------- -->
985
986 <sect1>
987 <title>I want to add some configure stuff, how could I do
988 this?</title>
989
990 <para>To use autoconf/automake, you must first install the
991 relevant packages. These are:</para>
992
993 <itemizedlist spacing=Compact>
994 <listitem><simpara>the m4 preprocessor v1.4 or better</simpara>
995 </listitem>
996
997 <listitem><simpara>autoconf v2.13 or better</simpara>
998 </listitem>
999
1000 <listitem><simpara>automake v1.4 or better</simpara>
1001 </listitem>
1002 </itemizedlist>
1003
1004 <para>You'll find these packages on the GNU main ftp server
1005 (<ulink url="ftp://ftp.gnu.org/">ftp://ftp.gnu.org/</ulink>)
1006 or on any GNU mirror.</para>
1007
1008 <para>In order to use the powerful autoconf/automake scheme,
1009 you must create a configure.in which may look like:</para>
1010
1011 <programlisting role="C">
1012 dnl Process this file with autoconf to produce a configure script.
1013 dnl configure.in for a GTK+ based program
1014
1015 AC_INIT(myprg.c)dnl
1016 AM_INIT_AUTOMAKE(mypkgname,0.0.1)dnl
1017 AM_CONFIG_HEADER(config.h)dnl
1018
1019 dnl Checks for programs.
1020 AC_PROG_CC dnl check for the c compiler
1021 dnl you should add CFLAGS="" here, 'cos it is set to -g by PROG_CC
1022
1023 dnl Checks for libraries.
1024 AM_PATH_GTK(1.2.0,,AC_MSG_ERROR(mypkgname 0.1 needs GTK))dnl
1025
1026 AC_OUTPUT(
1027         Makefile
1028 )dnl
1029 </programlisting>
1030
1031 <para>You must add a Makefile.am file:</para>
1032
1033 <programlisting role="C">
1034 bin_PROGRAMS    = myprg
1035 myprg_SOURCES   = myprg.c foo.c bar.c
1036 INCLUDES        = @GTK_CFLAGS@
1037 LDADD           = @GTK_LIBS@
1038 CLEANFILES      = *~
1039 DISTCLEANFILES  = .deps/*.P
1040 </programlisting>
1041
1042 <para>If your project contains more than one subdirectory,
1043 you'll have to create one Makefile.am in each directory plus a
1044 master Makefile.am which will look like:</para>
1045
1046 <programlisting role="C">
1047 SUBDIRS         = mydir1 mydir2 mydir3
1048 </programlisting>
1049
1050 <para>then, to use these, simply type the following
1051 commands:</para>
1052
1053 <programlisting role="C">
1054 aclocal
1055 autoheader
1056 autoconf
1057 automake --add-missing --include-deps --foreign 
1058 </programlisting>
1059
1060 <para>For further information, you should look at the autoconf
1061 and the automake documentation (the shipped info files are
1062 really easy to understand, and there are plenty of web
1063 resources that deal with autoconf and automake).</para>
1064
1065 </sect1>
1066
1067 <!-- ----------------------------------------------------------------- -->
1068
1069 <sect1>
1070 <title>I try to debug my GTK+ application with gdb, but it
1071 hangs my X server when I hit some breakpoint. Any
1072 Idea?</title>
1073
1074 <para>From Federico Mena Quintero:</para>
1075
1076 <para><quote>X is not locked up.  It is likely that you are hitting a
1077 breakpoint inside a callback that is called from a place in Gtk that has
1078 a mouse grab.</quote></para>
1079
1080 <para><quote>Run your program with the <literal>--sync</literal>
1081 option; it will make it easier to debug. Also, you may want to
1082 use the console for running the debugger, and just let the
1083 program run in another console with the X server.</quote></para>
1084
1085 <para>Eric Mouw had another solution:</para>
1086
1087 <para><quote>An old terminal connected to an otherwise unused serial
1088 port is also great for debugging X programs. Old vt100/vt220
1089 terminals are dirt cheap but a bit hard to get (here in The
1090 Netherlands, YMMV).</quote></para>
1091
1092 </sect1>
1093 </chapter>
1094
1095 <!-- ***************************************************************** -->
1096 <chapter>
1097 <title>Development with GTK+: general questions</title>
1098
1099 <!-- ----------------------------------------------------------------- -->
1100
1101 <sect1>
1102 <title>What widgets are in GTK?</title>
1103
1104 <para>The GTK+ Tutorial lists the following widgets:</para>
1105
1106 <programlisting role="C">
1107   GtkObject
1108    +GtkData
1109    | +GtkAdjustment
1110    | `GtkTooltips
1111    `GtkWidget
1112      +GtkContainer
1113      | +GtkBin
1114      | | +GtkAlignment
1115      | | +GtkEventBox
1116      | | +GtkFrame
1117      | | | `GtkAspectFrame
1118      | | +GtkHandleBox
1119      | | +GtkItem
1120      | | | +GtkListItem
1121      | | | +GtkMenuItem
1122      | | | | `GtkCheckMenuItem
1123      | | | |   `GtkRadioMenuItem
1124      | | | `GtkTreeItem
1125      | | +GtkViewport
1126      | | `GtkWindow
1127      | |   +GtkColorSelectionDialog
1128      | |   +GtkDialog
1129      | |   | `GtkInputDialog
1130      | |   `GtkFileSelection
1131      | +GtkBox
1132      | | +GtkButtonBox
1133      | | | +GtkHButtonBox
1134      | | | `GtkVButtonBox
1135      | | +GtkHBox
1136      | | | +GtkCombo
1137      | | | `GtkStatusbar
1138      | | `GtkVBox
1139      | |   +GtkColorSelection
1140      | |   `GtkGammaCurve
1141      | +GtkButton
1142      | | +GtkOptionMenu
1143      | | `GtkToggleButton
1144      | |   `GtkCheckButton
1145      | |     `GtkRadioButton
1146      | +GtkCList
1147      |   `GtkCTree
1148      | +GtkFixed
1149      | +GtkList
1150      | +GtkMenuShell
1151      | | +GtkMenuBar
1152      | | `GtkMenu
1153      | +GtkNotebook
1154      | +GtkPaned
1155      | | +GtkHPaned
1156      | | `GtkVPaned
1157      | +GtkScrolledWindow
1158      | +GtkTable
1159      | +GtkToolbar
1160      | `GtkTree
1161      +GtkDrawingArea
1162      | `GtkCurve
1163      +GtkEditable
1164      | +GtkEntry
1165      | | `GtkSpinButton
1166      | `GtkText
1167      +GtkMisc
1168      | +GtkArrow
1169      | +GtkImage
1170      | +GtkLabel
1171      | | `GtkTipsQuery
1172      | `GtkPixmap
1173      +GtkPreview
1174      +GtkProgressBar
1175      +GtkRange
1176      | +GtkScale
1177      | | +GtkHScale
1178      | | `GtkVScale
1179      | `GtkScrollbar
1180      |   +GtkHScrollbar
1181      |   `GtkVScrollbar
1182      +GtkRuler
1183      | +GtkHRuler
1184      | `GtkVRuler
1185      `GtkSeparator
1186        +GtkHSeparator
1187        `GtkVSeparator
1188 </programlisting>
1189 </sect1>
1190
1191 <!-- ----------------------------------------------------------------- -->
1192
1193 <sect1>
1194 <title>Is GTK+ thread safe? How do I write multi-threaded GTK+
1195 applications?</title>
1196
1197 <para>The GLib library can be used in a thread-safe mode by
1198 calling g_thread_init() before making any other GLib
1199 calls. In this mode GLib automatically locks all internal
1200 data structures as needed.  This does not mean that two
1201 threads can simultaneously access, for example, a single hash
1202 table, but they can access two different hash tables
1203 simultaneously. If two different threads need to access the
1204 same hash table, the application is responsible for locking
1205 itself.</para>
1206
1207 <para>When GLib is intialized to be thread-safe, GTK+ is
1208 <emphasis>thread aware</emphasis>. There is a single global
1209 lock that you must acquire with gdk_threads_enter() before
1210 making any GDK calls, and release with gdk_threads_leave()
1211 afterwards.</para>
1212
1213 <para>A minimal main program for a threaded GTK+ application
1214 looks like:</para>
1215
1216 <programlisting role="C">
1217 int
1218 main (int argc, char *argv[])
1219 {
1220   GtkWidget *window;
1221
1222   g_thread_init(NULL);
1223   gtk_init(&amp;argc, &amp;argv);
1224
1225   window = create_window();
1226   gtk_widget_show(window);
1227
1228   gdk_threads_enter();
1229   gtk_main();
1230   gdk_threads_leave();
1231
1232   return(0);
1233 }
1234 </programlisting>
1235
1236 <para>Callbacks require a bit of attention. Callbacks from
1237 GTK+ (signals) are made within the GTK+ lock. However
1238 callbacks from GLib (timeouts, IO callbacks, and idle
1239 functions) are made outside of the GTK+ lock. So, within a
1240 signal handler you do not need to call gdk_threads_enter(),
1241 but within the other types of callbacks, you do.</para>
1242
1243 <para>Erik Mouw contributed the following code example to
1244 illustrate how to use threads within GTK+ programs.</para>
1245
1246 <programlisting role="C">
1247 /*-------------------------------------------------------------------------
1248  * Filename:      gtk-thread.c
1249  * Version:       0.99.1
1250  * Copyright:     Copyright (C) 1999, Erik Mouw
1251  * Author:        Erik Mouw &lt;J.A.K.Mouw@its.tudelft.nl&gt;
1252  * Description:   GTK threads example. 
1253  * Created at:    Sun Oct 17 21:27:09 1999
1254  * Modified by:   Erik Mouw &lt;J.A.K.Mouw@its.tudelft.nl&gt;
1255  * Modified at:   Sun Oct 24 17:21:41 1999
1256  *-----------------------------------------------------------------------*/
1257 /*
1258  * Compile with:
1259  *
1260  * cc -o gtk-thread gtk-thread.c `gtk-config --cflags --libs gthread`
1261  *
1262  * Thanks to Sebastian Wilhelmi and Owen Taylor for pointing out some
1263  * bugs.
1264  *
1265  */
1266
1267 #include &lt;stdio.h&gt;
1268 #include &lt;stdlib.h&gt;
1269 #include &lt;unistd.h&gt;
1270 #include &lt;time.h&gt;
1271 #include &lt;gtk/gtk.h&gt;
1272 #include &lt;glib.h&gt;
1273 #include &lt;pthread.h&gt;
1274
1275 #define YES_IT_IS    (1)
1276 #define NO_IT_IS_NOT (0)
1277
1278 typedef struct 
1279 {
1280   GtkWidget *label;
1281   int what;
1282 } yes_or_no_args;
1283
1284 G_LOCK_DEFINE_STATIC (yes_or_no);
1285 static volatile int yes_or_no = YES_IT_IS;
1286
1287 void destroy(GtkWidget *widget, gpointer data)
1288 {
1289   gtk_main_quit();
1290 }
1291
1292 void *argument_thread(void *args)
1293 {
1294   yes_or_no_args *data = (yes_or_no_args *)args;
1295   gboolean say_something;
1296
1297   for(;;)
1298     {
1299       /* sleep a while */
1300       sleep(rand() / (RAND_MAX / 3) + 1);
1301
1302       /* lock the yes_or_no_variable */
1303       G_LOCK(yes_or_no);
1304
1305       /* do we have to say something? */
1306       say_something = (yes_or_no != data->what);
1307
1308       if(say_something)
1309         {
1310           /* set the variable */
1311           yes_or_no = data->what;
1312         }
1313
1314       /* Unlock the yes_or_no variable */
1315       G_UNLOCK(yes_or_no);
1316
1317       if(say_something)
1318         {
1319           /* get GTK thread lock */
1320           gdk_threads_enter();
1321
1322           /* set label text */
1323           if(data->what == YES_IT_IS)
1324             gtk_label_set_text(GTK_LABEL(data->label), "O yes, it is!");
1325           else
1326             gtk_label_set_text(GTK_LABEL(data->label), "O no, it isn't!");
1327
1328           /* release GTK thread lock */
1329           gdk_threads_leave();
1330         }
1331     }
1332
1333   return(NULL);
1334 }
1335
1336 int main(int argc, char *argv[])
1337 {
1338   GtkWidget *window;
1339   GtkWidget *label;
1340   yes_or_no_args yes_args, no_args;
1341   pthread_t no_tid, yes_tid;
1342
1343   /* init threads */
1344   g_thread_init(NULL);
1345
1346   /* init gtk */
1347   gtk_init(&amp;argc, &amp;argv);
1348
1349   /* init random number generator */
1350   srand((unsigned int)time(NULL));
1351
1352   /* create a window */
1353   window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1354
1355   gtk_signal_connect(GTK_OBJECT (window), "destroy",
1356                      GTK_SIGNAL_FUNC(destroy), NULL);
1357
1358   gtk_container_set_border_width(GTK_CONTAINER (window), 10);
1359
1360   /* create a label */
1361   label = gtk_label_new("And now for something completely different ...");
1362   gtk_container_add(GTK_CONTAINER(window), label);
1363   
1364   /* show everything */
1365   gtk_widget_show(label);
1366   gtk_widget_show (window);
1367
1368   /* create the threads */
1369   yes_args.label = label;
1370   yes_args.what = YES_IT_IS;
1371   pthread_create(&amp;yes_tid, NULL, argument_thread, &amp;yes_args);
1372
1373   no_args.label = label;
1374   no_args.what = NO_IT_IS_NOT;
1375   pthread_create(&amp;no_tid, NULL, argument_thread, &amp;no_args);
1376
1377   /* enter the GTK main loop */
1378   gdk_threads_enter();
1379   gtk_main();
1380   gdk_threads_leave();
1381
1382   return(0);
1383 }
1384 </programlisting>
1385 </sect1>
1386
1387 <!-- ----------------------------------------------------------------- -->
1388
1389 <sect1>
1390 <title>Why does this strange 'x io error' occur when I
1391 <literal>fork()</literal> in my GTK+ app?</title>
1392
1393 <para>This is not really a GTK+ problem, and the problem is
1394 not related to <literal>fork()</literal> either. If the 'x io
1395 error' occurs then you probably use the <literal>exit()</literal> function
1396 in order to exit from the child process.</para>
1397
1398 <para>When GDK opens an X display, it creates a socket file
1399 descriptor. When you use the <literal>exit()</literal>
1400 function, you implicitly close all the open file descriptors,
1401 and the underlying X library really doesn't like this.</para>
1402
1403 <para>The right function to use here is
1404 <literal>_exit()</literal>.</para> 
1405
1406 <para>Erik Mouw contributed the following code example to
1407 illustrate handling fork() and exit().</para>
1408
1409 <programlisting role="C">
1410 /*-------------------------------------------------------------------------
1411  * Filename:      gtk-fork.c
1412  * Version:       0.99.1
1413  * Copyright:     Copyright (C) 1999, Erik Mouw
1414  * Author:        Erik Mouw &lt;J.A.K.Mouw@its.tudelft.nl&gt;
1415  * Description:   GTK+ fork example
1416  * Created at:    Thu Sep 23 21:37:55 1999
1417  * Modified by:   Erik Mouw &lt;J.A.K.Mouw@its.tudelft.nl&gt;
1418  * Modified at:   Thu Sep 23 22:39:39 1999
1419  *-----------------------------------------------------------------------*/
1420 /*
1421  * Compile with:
1422  *
1423  * cc -o gtk-fork gtk-fork.c `gtk-config --cflags --libs`
1424  *
1425  */
1426
1427 #include &lt;stdio.h&gt;
1428 #include &lt;stdlib.h&gt;
1429 #include &lt;signal.h&gt;
1430 #include &lt;sys/types.h&gt;
1431 #include &lt;sys/wait.h&gt;
1432 #include &lt;unistd.h&gt;
1433 #include &lt;gtk/gtk.h&gt;
1434
1435 void sigchld_handler(int num)
1436 {
1437   sigset_t set, oldset;
1438   pid_t pid;
1439   int status, exitstatus;
1440
1441   /* block other incoming SIGCHLD signals */
1442   sigemptyset(&amp;set);
1443   sigaddset(&amp;set, SIGCHLD);
1444   sigprocmask(SIG_BLOCK, &amp;set, &amp;oldset);
1445
1446   /* wait for child */
1447   while((pid = waitpid((pid_t)-1, &amp;status, WNOHANG)) > 0)
1448     {
1449       if(WIFEXITED(status))
1450         {
1451           exitstatus = WEXITSTATUS(status);
1452
1453           fprintf(stderr, 
1454                   "Parent: child exited, pid = %d, exit status = %d\n", 
1455                   (int)pid, exitstatus);
1456         }
1457       else if(WIFSIGNALED(status))
1458         {
1459           exitstatus = WTERMSIG(status);
1460
1461           fprintf(stderr,
1462                   "Parent: child terminated by signal %d, pid = %d\n",
1463                   exitstatus, (int)pid);
1464         }
1465       else if(WIFSTOPPED(status))
1466         {
1467           exitstatus = WSTOPSIG(status);
1468
1469           fprintf(stderr,
1470                   "Parent: child stopped by signal %d, pid = %d\n",
1471                   exitstatus, (int)pid);
1472         }
1473       else
1474         {
1475           fprintf(stderr,
1476                   "Parent: child exited magically, pid = %d\n",
1477                   (int)pid);
1478         }
1479     }
1480
1481   /* re-install the signal handler (some systems need this) */
1482   signal(SIGCHLD, sigchld_handler);
1483   
1484   /* and unblock it */
1485   sigemptyset(&amp;set);
1486   sigaddset(&amp;set, SIGCHLD);
1487   sigprocmask(SIG_UNBLOCK, &amp;set, &amp;oldset);
1488 }
1489
1490 gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
1491 {
1492   return(FALSE);
1493 }
1494
1495 void destroy(GtkWidget *widget, gpointer data)
1496 {
1497   gtk_main_quit();
1498 }
1499
1500 void fork_me(GtkWidget *widget, gpointer data)
1501 {
1502   pid_t pid;
1503
1504   pid = fork();
1505
1506   if(pid == -1)
1507     {
1508       /* ouch, fork() failed */
1509       perror("fork");
1510       exit(-1);
1511     }
1512   else if(pid == 0)
1513     {
1514       /* child */
1515       fprintf(stderr, "Child: pid = %d\n", (int)getpid());
1516
1517       execlp("ls", "ls", "-CF", "/", NULL);
1518       
1519       /* if exec() returns, there is something wrong */
1520       perror("execlp");
1521
1522       /* exit child. note the use of _exit() instead of exit() */
1523       _exit(-1);
1524     }
1525   else
1526     {
1527       /* parent */
1528       fprintf(stderr, "Parent: forked a child with pid = %d\n", (int)pid);
1529     }
1530 }
1531
1532 int main(int argc, char *argv[])
1533 {
1534   GtkWidget *window;
1535   GtkWidget *button;
1536
1537   gtk_init(&amp;argc, &amp;argv);
1538
1539   /* the basic stuff: make a window and set callbacks for destroy and
1540    * delete events 
1541    */
1542   window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1543
1544   gtk_signal_connect(GTK_OBJECT (window), "delete_event",
1545                      GTK_SIGNAL_FUNC(delete_event), NULL);
1546           
1547   gtk_signal_connect(GTK_OBJECT (window), "destroy",
1548                      GTK_SIGNAL_FUNC(destroy), NULL);
1549
1550 #if (GTK_MAJOR_VERSION == 1) && (GTK_MINOR_VERSION == 0)
1551   gtk_container_border_width(GTK_CONTAINER (window), 10);
1552 #else  
1553   gtk_container_set_border_width(GTK_CONTAINER (window), 10);
1554 #endif
1555
1556   /* add a button to do something usefull */
1557   button = gtk_button_new_with_label("Fork me!");
1558           
1559   gtk_signal_connect(GTK_OBJECT (button), "clicked",
1560                      GTK_SIGNAL_FUNC(fork_me), NULL);
1561
1562   gtk_container_add(GTK_CONTAINER(window), button);
1563           
1564   /* show everything */
1565   gtk_widget_show (button);
1566   gtk_widget_show (window);
1567
1568
1569   /* install a signal handler for SIGCHLD signals */
1570   signal(SIGCHLD, sigchld_handler);
1571
1572   
1573   /* main loop */
1574   gtk_main ();
1575
1576   exit(0);         
1577 }
1578 </programlisting>
1579 </sect1>
1580
1581 <!-- ----------------------------------------------------------------- -->
1582
1583 <sect1>
1584 <title>Why don't the contents of a button move when the button
1585 is pressed? Here's a patch to make it work that way...</title>
1586
1587 <para>From: Peter Mattis</para>
1588
1589 <para><quote>The reason buttons don't move their child down and to
1590 the right when they are depressed is because I don't think
1591 that's what is happening visually. My view of buttons is
1592 that you are looking at them straight on. That is, the user
1593 interface lies in a plane and you're above it looking
1594 straight at it. When a button gets pressed it moves directly
1595 away from you. To be absolutely correct I guess the child
1596 should actually shrink a tiny amount. But I don't see why
1597 the child should shift down and to the left. Remember, the
1598 child is supposed to be attached to the buttons surface. Its
1599 not good for it to appear like the child is slipping on the
1600 surface of the button.</quote></para>
1601
1602 <para><quote>On a more practical note, I did implement this at one point
1603 and determined it didn't look good and removed it.</quote></para>
1604
1605 </sect1>
1606
1607 <!-- ----------------------------------------------------------------- -->
1608
1609 <sect1>
1610 <title>How do I identifiy a widgets top level window or other
1611 ancestor?</title>
1612
1613 <para>There are a couple of ways to find the top level parent
1614 of a widget. The easier way is to call the
1615 <literal>gtk_widget_top_level()</literal> function that
1616 returns pointer to a GtkWidget that is the top level
1617 window.</para>
1618
1619 <para>A more complicated way to do this (but less limited, as
1620 it allows the user to get the closest ancestor of a known type) is to use
1621 <literal>gtk_widget_get_ancestor()</literal> as in:</para>
1622
1623 <programlisting role="C">
1624       GtkWidget       *widget;
1625       widget = gtk_widget_get_ancestor(w, GTK_TYPE_WINDOW);
1626 </programlisting>
1627
1628 <para>Since virtually all the GTK_TYPEs can be used as the
1629 second parameter of this function, you can get any parent
1630 widget of a particular widget. Suppose you have an hbox which
1631 contains a vbox, which in turn contains some other atomic
1632 widget (entry, label, etc. To find the master hbox using the
1633 <literal>entry</literal> widget simply use:</para>
1634
1635 <programlisting role="C">
1636       GtkWidget       *hbox;
1637       hbox = gtk_widget_get_ancestor(w, GTK_TYPE_HBOX);
1638 </programlisting>
1639
1640 </sect1>
1641
1642 <!-- ----------------------------------------------------------------- -->
1643
1644 <sect1>
1645 <title>How do I get the Window ID of a GtkWindow?</title>
1646
1647 <para>The actual Gdk/X window will be created when the widget
1648 gets realized. You can get the Window ID with:</para>
1649
1650 <programlisting role="C">
1651 #include &lt;gdk/gdkx.h&gt;
1652
1653 Window xwin = GDK_WINDOW_XWINDOW (GTK_WIDGET (my_window)->window);
1654 </programlisting>
1655 </sect1>
1656
1657 <!-- ----------------------------------------------------------------- -->
1658
1659 <sect1>
1660 <title>How do I catch a double click event (in a list widget,
1661 for example)?</title>
1662
1663 <para>Tim Janik wrote to gtk-list (slightly modified):</para>
1664
1665 <para>Define a signal handler:</para>
1666
1667 <programlisting role="C">
1668 gint
1669 signal_handler_event(GtkWidget *widget, GdkEventButton *event, gpointer func_data)
1670 {
1671   if (GTK_IS_LIST_ITEM(widget) &&
1672        (event->type==GDK_2BUTTON_PRESS ||
1673         event->type==GDK_3BUTTON_PRESS) ) {
1674     printf("I feel %s clicked on button %d\n",
1675            event->type==GDK_2BUTTON_PRESS ? "double" : "triple",
1676            event->button);
1677   }
1678
1679   return FALSE;
1680 }</programlisting>
1681
1682 <para>And connect the handler to your object:</para>
1683
1684 <programlisting role="C">
1685 {
1686   /* list, list item init stuff */     
1687
1688   gtk_signal_connect(GTK_OBJECT(list_item),
1689                      "button_press_event",
1690                      GTK_SIGNAL_FUNC(signal_handler_event),
1691                      NULL);
1692
1693   /* and/or */
1694
1695   gtk_signal_connect(GTK_OBJECT(list_item),
1696                      "button_release_event",
1697                      GTK_SIGNAL_FUNC(signal_handler_event),
1698                      NULL);
1699
1700   /* something else */
1701 }
1702 </programlisting>
1703
1704 <para>and, Owen Taylor wrote:</para>
1705
1706 <para><quote>Note that a single button press will be received
1707 beforehand, and if you are doing this for a button, you will
1708 therefore also get a "clicked" signal for the button. (This
1709 is going to be true for any toolkit, since computers aren't
1710 good at reading one's mind.)</quote></para>
1711
1712 </sect1>
1713
1714 <!-- ----------------------------------------------------------------- -->
1715
1716 <sect1>
1717 <title>By the way, what are the differences between signals
1718 and events?</title>
1719
1720 <para>First of all, Havoc Pennington gives a rather complete
1721 description of the differences between events and signals in
1722 his free book (two chapters can be found at <ulink
1723 url="http://www106.pair.com/rhp/sample_chapters.html">
1724 http://www106.pair.com/rhp/sample_chapters.html</ulink>).</para>
1725
1726 <para>Moreover, Havoc posted this to the <literal>gtk-list</literal>
1727 <quote>Events are a stream of messages received from the X
1728 server. They drive the Gtk main loop; which more or less
1729 amounts to "wait for events, process them" (not exactly, it
1730 is really more general than that and can wait on many
1731 different input streams at once). Events are a Gdk/Xlib
1732 concept.</quote></para>
1733
1734 <para><quote>Signals are a feature of GtkObject and its subclasses. They
1735 have nothing to do with any input stream; really a signal is just a way
1736 to keep a list of callbacks around and invoke them ("emit" the
1737 signal). There are lots of details and extra features of
1738 course. Signals are emitted by object instances, and are entirely
1739 unrelated to the Gtk main loop.  Conventionally, signals are emitted
1740 "when something changes" about the object emitting the
1741 signal.</quote></para>
1742
1743 <para><quote>Signals and events only come together because GtkWidget
1744 happens to emit signals when it gets events. This is purely a
1745 convenience, so you can connect callbacks to be invoked when a
1746 particular widget receives a particular event. There is nothing about
1747 this that makes signals and events inherently related concepts, any more
1748 than emitting a signal when you click a button makes button clicking and
1749 signals related concepts.</quote></para>
1750
1751 </sect1>
1752
1753 <!-- ----------------------------------------------------------------- -->
1754
1755 <sect1>
1756 <title>Data I pass to the <literal>delete_event</literal> (or other event)
1757 handler gets corrupted.</title>
1758
1759 <para>All event handlers take an additional argument which
1760 contains information about the event that triggered the
1761 handler. So, a <literal>delete_event</literal> handler must
1762 be declared as:</para>
1763
1764
1765 <programlisting role="C">
1766 gint delete_event_handler (GtkWidget   *widget,
1767                            GdkEventAny *event,
1768                            gpointer     data);
1769 </programlisting>
1770
1771 </sect1>
1772
1773 <!-- ----------------------------------------------------------------- -->
1774
1775 <sect1>
1776 <title>I have my signal connected to the the (whatever) event,
1777 but it seems I don't catch it. What's wrong?</title>
1778
1779 <para>There is some special initialisation to do in order to
1780 catch some particular events. In fact, you must set the
1781 correct event mask bit of your widget before getting some
1782 particular events.</para>
1783
1784 <para>For example,</para>
1785
1786 <programlisting role="C">
1787   gtk_widget_add_events(window, GDK_KEY_RELEASE_MASK);
1788 </programlisting>
1789
1790 <para>lets you catch the key release events. If you want to
1791 catch every events, simply us the GDK_ALL_EVENTS_MASK event
1792 mask.</para>
1793
1794 <para>All the event masks are defined in the
1795 <filename>gdktypes.h</filename> file.</para>
1796
1797 </sect1>
1798
1799 <!-- ----------------------------------------------------------------- -->
1800
1801 <sect1>
1802 <title>I need to add a new signal to a GTK+ widget. Any
1803 idea?</title>
1804
1805 <para>If the signal you want to add may be beneficial for
1806 other GTK+ users, you may want to submit a patch that
1807 presents your changes. Check the tutorial for more
1808 information about adding signals to a widget class.</para>
1809
1810 <para>If you don't think it is the case or if your patch is
1811 not applied you'll have to use the
1812 <literal>gtk_object_class_user_signal_new</literal>
1813 function. <literal>gtk_object_class_user_signal_new</literal> allows you
1814 to add a new signal to a predefined GTK+ widget without any
1815 modification of the GTK+ source code. The new signal can be
1816 emited with <literal>gtk_signal_emit</literal> and can be
1817 handled in the same way as other signals.</para>
1818
1819 <para>Tim Janik posted this code snippet:</para>
1820
1821 <programlisting role="C">
1822 static guint signal_user_action = 0;
1823
1824 signal_user_action =
1825   gtk_object_class_user_signal_new (gtk_type_class (GTK_TYPE_WIDGET),
1826                     "user_action",
1827                     GTK_RUN_LAST | GTK_RUN_ACTION,
1828                     gtk_marshal_NONE__POINTER,
1829                     GTK_TYPE_NONE, 1,
1830                     GTK_TYPE_POINTER);
1831
1832 void
1833 gtk_widget_user_action (GtkWidget *widget,
1834                         gpointer   act_data)
1835 {
1836   g_return_if_fail (GTK_IS_WIDGET (widget));
1837
1838   gtk_signal_emit (GTK_OBJECT (widget), signal_user_action, act_data);
1839 }
1840 </programlisting>
1841
1842 <para>If you want your new signal to have more than the
1843 classical gpointer parameter, you'll have to play with GTK+
1844 marshallers.</para>
1845
1846 </sect1>
1847
1848 <!-- ----------------------------------------------------------------- -->
1849
1850 <sect1>
1851 <title>Is it possible to get some text displayed which is
1852 truncated to fit inside its allocation?</title>
1853
1854 <para>GTK's behavior (no clipping) is a consequence of its
1855 attempts to conserve X resources. Label widgets (among
1856 others) don't get their own X window - they just draw their
1857 contents on their parent's window. While it might be possible
1858 to have clipping occur by setting the clip mask before
1859 drawing the text, this would probably cause a substantial
1860 performance penalty.</para>
1861
1862 <para>Its possible that, in the long term, the best solution
1863 to such problems might be just to change gtk to give labels X
1864 windows. A short term workaround is to put the label widget
1865 inside another widget that does get its own window - one
1866 possible candidate would be the viewport widget.</para>
1867
1868 <programlisting role="C">
1869 viewport = gtk_viewport (NULL, NULL);
1870 gtk_widget_set_usize (viewport, 50, 25);
1871 gtk_viewport_set_shadow_type (GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1872 gtk_widget_show(viewport);
1873
1874 label = gtk_label ("a really long label that won't fit");
1875 gtk_container_add (GTK_CONTAINER(viewport), label);
1876 gtk_widget_show (label);
1877 </programlisting>
1878
1879 <para>If you were doing this for a bunch of widgets, you might
1880 want to copy gtkviewport.c and strip out the adjustment and
1881 shadow functionality (perhaps you could call it
1882 GtkClipper).</para>
1883 </sect1>
1884
1885 <!-- ----------------------------------------------------------------- -->
1886
1887 <sect1>
1888 <title>How do I make my window modal? / How do I make a single
1889 window active?</title>
1890
1891 <para>After you create your window, do
1892 <literal>gtk_grab_add(my_window)</literal>. And after closing the window
1893 do <literal>gtk_grab_remove(my_window)</literal>.</para>
1894
1895 </sect1>
1896
1897 <!-- ----------------------------------------------------------------- -->
1898
1899 <sect1>
1900 <title>Why doesn't my widget (e.g. progressbar)
1901 update?</title>
1902
1903 <para>You are probably doing all the changes within a function without
1904 returning control to <literal>gtk_main()</literal>. This may
1905 be the case if you do some lengthy calculation in your
1906 code. Most drawing updates are only placed on a queue, which
1907 is processed within <literal>gtk_main()</literal>. You can force the
1908 drawing queue to be processed using something like:</para>
1909
1910
1911 <programlisting role="C">
1912 while (g_main_iteration(FALSE));
1913 </programlisting>
1914
1915 <para>inside you're function that changes the widget.</para>
1916
1917 <para>What the above snippet does is run all pending events
1918 and high priority idle functions, then return immediately
1919 (the drawing is done in a high priority idle function).</para>
1920
1921 </sect1>
1922
1923 <!-- ----------------------------------------------------------------- -->
1924
1925 <sect1>
1926 <title>How do I attach data to some GTK+ object/widget?</title>
1927
1928 <para>First of all, the attached data is stored in the
1929 object_data field of a GtkObject. The type of this field is
1930 GData, which is defined in glib.h.  So you should read the
1931 gdataset.c file in your glib source directory very
1932 carefully.</para>
1933
1934 <para>There are two (easy) ways to attach some data to a gtk
1935 object.  Using <literal>gtk_object_set_data()</literal> and
1936 <literal>gtk_object_get_data()</literal> seems to be the most
1937 common way to do this, as it provides a powerful interface to
1938 connect objects and data.</para>
1939
1940 <programlisting role="C">
1941 void gtk_object_set_data(GtkObject *object, const gchar *key, gpointer data);
1942
1943 gpointer gtk_object_get_data(GtkObject *object, const gchar *key);
1944 </programlisting>
1945
1946 <para>Since a short example is better than any lengthy speech:</para>
1947
1948 <programlisting role="C">
1949 struct my_struct        p1,p2,*result;
1950 GtkWidget               *w;
1951
1952 gtk_object_set_data(GTK_OBJECT(w),"p1 data",(gpointer)&amp;p1);
1953 gtk_object_set_data(GTK_OBJECT(w),"p2 data",(gpointer)&amp;p2);
1954
1955 result = gtk_object_get_data(GTK_OBJECT(w),"p1 data");
1956 </programlisting>
1957
1958 <para>The <literal>gtk_object_set_user_data()</literal> and
1959 <literal>gtk_object_get_user_data()</literal> functions does
1960 exactly the same thing as the functions above, but does not
1961 let you specify the "key" parameter.Instead, it uses a
1962 standard "user_data" key. Note that the use of these functions
1963 is deprecated in 1.2. They only provide a compatibility mode
1964 with some old gtk packages.</para>
1965
1966 </sect1>
1967
1968 <!-- ----------------------------------------------------------------- -->
1969
1970 <sect1>
1971 <title>How do I remove the data I have attached to an
1972 object?</title>
1973
1974 <para>When attaching the data to the object, you can use the
1975 <literal>gtk_object_set_data_full()</literal> function. The three
1976 first arguments of the function are the same as in
1977 <literal>gtk_object_set_data()</literal>. The fourth one is a
1978 pointer to a callback function which is called when the data
1979 is destroyed. The data is destroyed when you:</para>
1980
1981 <itemizedlist>
1982 <listitem><simpara> destroy the object</simpara>
1983 </listitem>
1984
1985 <listitem><simpara> replace the data with a new one (with
1986 the same key)</simpara>
1987 </listitem>
1988
1989 <listitem><simpara> replace the data with NULL (with the
1990 same key)</simpara>
1991 </listitem>
1992
1993 </itemizedlist>
1994
1995 </sect1>
1996
1997 <!-- ----------------------------------------------------------------- -->
1998
1999 <sect1>
2000 <title>How do I reparent a widget?</title>
2001
2002 <para>The normal way to reparent (ie change the owner) of a
2003 widget should be to use the function:</para>
2004
2005 <programlisting role="C">
2006 void gtk_widget_reparent (GtkWidget *widget, 
2007                           GtkWidget *new_parent)
2008 </programlisting>
2009
2010 <para>But this is only a "should be" since this function does
2011 not correctly do its job on some specific widgets. The main
2012 goal of gtk_widget_reparent() is to avoid unrealizing widget
2013 if both widget and new_parent are realized (in this case,
2014 widget->window is successfully reparented). The problem here
2015 is that some widgets in the GTK+ hierarchy have multiple
2016 attached X subwindows and this is notably the case for the
2017 GtkSpinButton widget. For those, gtk_widget_reparent() will
2018 fail by leaving an unrealized child window where it should
2019 not.</para>
2020
2021 <para>To avoid this problem, simply use the following code
2022 snippet:</para>
2023
2024 <programlisting role="C">
2025      gtk_widget_ref(widget);
2026      gtk_container_remove(GTK_CONTAINER(old_parent), widget);
2027      gtk_container_add(GTK_CONTAINER(new_parent), widget);
2028      gtk_widget_unref(widget);
2029 </programlisting>
2030
2031 </sect1>
2032
2033 <!-- ----------------------------------------------------------------- -->
2034
2035 <sect1>
2036 <title>How could I get any widgets position?</title>
2037
2038 <para>As Tim Janik pointed out, there are different cases, and
2039 each case requires a different solution.</para>
2040
2041 <itemizedlist>
2042 <listitem><simpara> If you want the position of a widget
2043 relative to its parent, you should use
2044 <literal>widget->allocation.x</literal> and
2045 <literal>widget->allocation.y</literal>.</simpara>
2046 </listitem>
2047
2048 <listitem><simpara> If you want the position of a window
2049 relative to the X root window, you should use
2050 <literal>gdk_window_get_geometry()</literal>
2051 <literal>gdk_window_get_position()</literal> or
2052 <literal>gdk_window_get_origin()</literal>.</simpara>
2053 </listitem>
2054
2055 <listitem><simpara> If you want to get the position of the
2056 window (including the WM decorations), you should use
2057 <literal>gdk_window_get_root_origin()</literal>.</simpara>
2058 </listitem>
2059
2060 <listitem><simpara> Last but not least, if you want to get a Window
2061 Manager frame position, you should use
2062 <literal>gdk_window_get_deskrelative_origin()</literal>.</simpara>
2063 </listitem>
2064 </itemizedlist>
2065
2066 <para>Your choice of Window Manager will have an effect of the
2067 results of the above functions. You should keep this in mind
2068 when writing your application. This is dependant upon how the
2069 Window Managers manage the decorations that they add around
2070 windows.</para>
2071
2072 </sect1>
2073
2074 <!-- ----------------------------------------------------------------- -->
2075
2076 <sect1>
2077 <title>How do I set the size of a widget/window? How do I
2078 prevent the user resizing my window?</title>
2079
2080 <para>The <literal>gtk_widget_set_uposition()</literal>
2081 function is used to set the position of any widget.</para>
2082
2083 <para>The <literal>gtk_widget_set_usize()</literal> function
2084 is used to set the size of a widget. In order to use all the
2085 features that are provided by this function when it acts on a
2086 window, you may want to use the
2087 <literal>gtk_window_set_policy</literal> function. The
2088 definition of these functions are:</para>
2089
2090 <programlisting role="C">
2091 void gtk_widget_set_usize (GtkWidget *widget,
2092                            gint width,
2093                            gint height);
2094
2095 void gtk_window_set_policy (GtkWindow *window,
2096                             gint allow_shrink,
2097                             gint allow_grow,
2098                             gint auto_shrink);
2099 </programlisting>
2100
2101 <para><literal>auto_shrink</literal> will automatically shrink
2102 the window when the requested size of the child widgets goes
2103 below the current size of the
2104 window. <literal>allow_shrink</literal> will give the user the
2105 authorisation to make the window smaller that it should
2106 normally be. <literal>allow_grow</literal> gives the user
2107 the ability to make the window bigger. The default
2108 values for these parameters are:</para>
2109
2110 <programlisting role="C">
2111 allow_shrink = FALSE
2112 allow_grow   = TRUE
2113 auto_shrink  = FALSE
2114 </programlisting>
2115
2116 <para>The <literal>gtk_widget_set_usize()</literal> functions
2117 is not the easiest way to set a window size since you cannot
2118 decrease this window size with another call to this function
2119 unless you call it twice, as in:</para>
2120
2121 <programlisting role="C">
2122      gtk_widget_set_usize(your_widget, -1, -1);
2123      gtk_widget_set_usize(your_widget, new_x_size, new_y_size);
2124 </programlisting>
2125
2126 <para>Another way to set the size of and/or move a window is to use
2127 the <literal>gdk_window_move_resize()</literal> function which
2128 uses to work fine both to grow or to shrink the window:</para>
2129
2130 <programlisting role="C">
2131      gdk_window_move_resize(window->window, 
2132                             x_pos, y_pos, 
2133                             x_size, y_size);
2134 </programlisting>
2135
2136 </sect1>
2137
2138 <!-- ----------------------------------------------------------------- -->
2139
2140 <sect1>
2141 <title>How do I add a popup menu to my GTK+ application?</title>
2142
2143 <para>The <literal>menu</literal> example in the examples/menu
2144 directory of the GTK+ distribution implements a popup menu
2145 with this technique:</para>
2146
2147 <programlisting role="C">
2148 static gint button_press (GtkWidget *widget, GdkEvent *event)
2149 {
2150
2151     if (event->type == GDK_BUTTON_PRESS) {
2152         GdkEventButton *bevent = (GdkEventButton *) event; 
2153         gtk_menu_popup (GTK_MENU(widget), NULL, NULL, NULL, NULL,
2154                         bevent->button, bevent->time);
2155         /* Tell calling code that we have handled this event; the buck
2156          * stops here. */
2157         return TRUE;
2158     }
2159
2160     /* Tell calling code that we have not handled this event; pass it on. */
2161     return FALSE;
2162 }
2163 </programlisting>
2164
2165 </sect1>
2166
2167 <!-- ----------------------------------------------------------------- -->
2168
2169 <sect1>
2170 <title>How do I disable or enable a widget, such as a
2171 button?</title>
2172
2173 <para>To disable (or to enable) a widget, use the
2174 <literal>gtk_widget_set_sensitive()</literal> function. The
2175 first parameter is you widget pointer. The second parameter is
2176 a boolean value: when this value is TRUE, the widget is
2177 enabled.</para>
2178 </sect1>
2179
2180 <!-- ----------------------------------------------------------------- -->
2181
2182 <sect1>
2183 <title>Shouldn't the text argument in the gtk_clist_*
2184 functions be declared const?</title>
2185
2186 <para>For example:</para>
2187
2188 <programlisting role="C">
2189 gint gtk_clist_prepend (GtkCList *clist,
2190                         gchar    *text[]);
2191 </programlisting>
2192
2193 <para>Answer: No, while a type "gchar*" (pointer to char) can
2194 automatically be cast into "const gchar*" (pointer to const
2195 char), this does not apply for "gchar *[]" (array of an
2196 unspecified number of pointers to char) into "const gchar *[]"
2197 (array of an unspecified number of pointers to const char).</para>
2198
2199 <para>The type qualifier "const" may be subject to automatic
2200 casting, but in the array case, it is not the array itself
2201 that needs the (const) qualified cast, but its members, thus
2202 changing the whole type.</para>
2203 </sect1>
2204
2205 <!-- ----------------------------------------------------------------- -->
2206
2207 <sect1>
2208 <title>How do I render pixels (image data) to the
2209 screen?</title>
2210
2211 <para>There are several ways to approach this. The simplest
2212 way is to use GdkRGB, see gdk/gdkrgb.h. You create an RGB
2213 buffer, render to your RGB buffer, then use GdkRGB routines to
2214 copy your RGB buffer to a drawing area or custom widget. The
2215 book "GTK+/Gnome Application Development" gives some details;
2216 GdkRGB is also documented in the GTK+ reference
2217 documentation.</para>
2218
2219 <para>If you're writing a game or other graphics-intensive
2220 application, you might consider a more elaborate
2221 solution. OpenGL is the graphics standard that will let you
2222 access hardware accelaration in future versions of XFree86; so
2223 for maximum speed, you probably want to use OpenGL. A
2224 GtkGLArea widget is available for using OpenGL with GTK+ (but
2225 GtkGLArea does not come with GTK+ itself). There are also
2226 several open source game libraries, such as ClanLib and Loki's
2227 Simple DirectMedia Layer library (SDL).</para>
2228
2229 <para>You do NOT want to use
2230 <literal>gdk_draw_point()</literal>, that will be extremely
2231 slow.</para>
2232 </sect1>
2233
2234 <!-- ----------------------------------------------------------------- -->
2235
2236 <sect1>
2237 <title>How do I create a pixmap without having my window being
2238 realized/shown?</title>
2239
2240 <para>Functions such as
2241 <literal>gdk_pixmap_create_from_xpm()</literal> require a
2242 valid window as a parameter. During the initialisation phase
2243 of an application, a valid window may not be available without
2244 showing a window, which may be inappropriate. In order to
2245 avoid this, a function such as
2246 <literal>gdk_pixmap_colormap_create_from_xpm</literal> can be
2247 used, as in:</para>
2248
2249 <programlisting role="C">
2250   char *pixfile = "foo.xpm";
2251   GtkWidget *top, *box, *pixw;
2252   GdkPixmap *pixmap, *pixmap_mask;
2253
2254   top = gtk_window_new (GKT_WINDOW_TOPLEVEL);
2255   box = gtk_hbox_new (FALSE, 4);
2256   gtk_conainer_add (GTK_CONTAINER(top), box);
2257  
2258   pixmap = gdk_pixmap_colormap_create_from_xpm (
2259                NULL, gtk_widget_get_colormap(top),
2260                &amp;pixmap_mask, NULL, pixfile);
2261   pixw = gtk_pixmap_new (pixmap, pixmap_mask);
2262   gdk_pixmap_unref (pixmap);
2263   gdk_pixmap_unref (pixmap_mask);
2264 </programlisting>
2265
2266 </sect1>
2267
2268 <!-- ----------------------------------------------------------------- -->
2269
2270 <sect1>
2271 <title>How do I do drag-and-drop?</title>
2272
2273 <para>GTK+ has a high level set of functions for doing inter-process
2274 communication via the drag-and-drop system. GTK+ can perform
2275 drag-and-drop on top of the low level Xdnd and Motif drag-and-drop
2276 protocols.</para>
2277
2278 <para>The documentation on GTK+ drag-and-drop isn't complete, but there
2279 is some information in the <ulink
2280 url="http://www.gtk.org/tutorial/">Tutorial</ulink>. You should also
2281 look at the drag-and-drop example code that is part of the GTK+ source
2282 distribution, in the file <filename>gtk/testdnd.c</filename>.</para>
2283
2284 </sect1>
2285
2286 <!-- ----------------------------------------------------------------- -->
2287
2288 <sect1>
2289 <title>Why does GTK+/GLib leak memory?</title>
2290
2291 <para>It doesn't. Both GLib and the C library (malloc implementation)
2292 will cache allocated memory on occasion, even if you free it with
2293 free().</para>
2294
2295 <para>So you can't generally use tools such as top to see if you are
2296 using free() properly (aside from the very roughest of estimations, i.e.
2297 if you are really, really screwing up top will show that, but you can't
2298 distinguish small mistakes from the GLib/malloc caches).</para>
2299
2300 <para>In order to find memory leaks, use proper memory profiling
2301 tools.</para>
2302
2303 </sect1>
2304
2305 </chapter>
2306
2307 <!-- ***************************************************************** -->
2308 <chapter>
2309 <title>Development with GTK+: widget specific questions</title>
2310
2311 <!-- ----------------------------------------------------------------- -->
2312
2313 <sect1>
2314 <title>How do I find out about the selection of a GtkList?</title>
2315
2316 <para>Get the selection something like this:</para>
2317
2318 <programlisting role="C">
2319 GList *sel;
2320 sel = GTK_LIST(list)->selection;
2321 </programlisting>
2322
2323 <para>This is how GList is defined (quoting glist.h):</para>
2324
2325 <programlisting role="C">
2326 typedef struct _GList GList;
2327
2328 struct _GList
2329 {
2330   gpointer data;
2331   GList *next;
2332   GList *prev;
2333 };
2334 </programlisting>
2335
2336 <para>A GList structure is just a simple structure for doubly
2337 linked lists. There exist several g_list_*() functions to
2338 modify a linked list in glib.h.  However the
2339 GTK_LIST(MyGtkList)->selection is maintained by the
2340 gtk_list_*() functions and should not be modified.</para>
2341
2342
2343 <para>The selection_mode of the GtkList determines the
2344 selection facilities of a GtkList and therefore the contents
2345 of GTK_LIST(AnyGtkList)->selection:</para>
2346
2347 <informaltable frame="all">
2348 <tgroup cols="2">
2349 <thead>
2350 <row>
2351 <entry><literal>selection_mode</literal></entry>
2352 <entry><literal> GTK_LIST()->selection</literal>
2353 contents</entry>
2354 </row>
2355 </thead>
2356
2357 <tbody>
2358 <row>
2359 <entry><literal>GTK_SELECTION_SINGLE</literal></entry>
2360 <entry>selection is either NULL or contains a GList*
2361 pointer for a single selected item.</entry>
2362 </row>
2363
2364 <row>
2365 <entry><literal>GTK_SELECTION_BROWSE</literal></entry>
2366 <entry>selection is NULL if the list contains no
2367 widgets, otherwise it contains a GList*
2368 pointer for one GList structure.</entry>
2369 </row>
2370
2371 <row>
2372 <entry><literal>GTK_SELECTION_MULTIPLE</literal></entry>
2373 <entry>selection is NULL if no listitems are selected
2374 or a a GList* pointer for the first selected
2375 item. that in turn points to a GList structure
2376 for the second selected item and so
2377 on.</entry>
2378 </row>
2379
2380 <row>
2381 <entry><literal>GTK_SELECTION_EXTENDED</literal></entry>
2382 <entry>selection is NULL.</entry>
2383 </row>
2384
2385 </tbody>
2386 </tgroup>
2387 </informaltable>
2388
2389 <para>The data field of the GList structure
2390 GTK_LIST(MyGtkList)->selection points to the first
2391 GtkListItem that is selected.  So if you would like to
2392 determine which listitems are selected you should go like
2393 this:</para>
2394
2395 <programlisting role="C">
2396 {
2397         gchar           *list_items[]={
2398                                 "Item0",
2399                                 "Item1",
2400                                 "foo",
2401                                 "last Item",
2402                         };
2403         guint           nlist_items=sizeof(list_items)/sizeof(list_items[0]);
2404         GtkWidget       *list_item;
2405         guint           i;
2406
2407         list=gtk_list_new();
2408         gtk_list_set_selection_mode(GTK_LIST(list), GTK_SELECTION_MULTIPLE);
2409         gtk_container_add(GTK_CONTAINER(AnyGtkContainer), list);
2410         gtk_widget_show (list);
2411
2412         for (i = 0; i < nlist_items; i++)
2413         {
2414                 list_item=gtk_list_item_new_with_label(list_items[i]);
2415                 gtk_object_set_user_data(GTK_OBJECT(list_item), (gpointer)i);
2416                 gtk_container_add(GTK_CONTAINER(list), list_item);
2417                 gtk_widget_show(list_item);
2418         }
2419 }
2420 </programlisting>
2421
2422 <para>To get known about the selection:</para>
2423
2424 <programlisting role="C">
2425 {
2426         GList   *items;
2427
2428         items=GTK_LIST(list)->selection;
2429
2430         printf("Selected Items: ");
2431         while (items) {
2432                 if (GTK_IS_LIST_ITEM(items->data))
2433                         printf("%d ", (guint) 
2434                 gtk_object_get_user_data(items->data));
2435                 items=items->next;
2436         }
2437         printf("\n");
2438 }
2439 </programlisting>
2440
2441 </sect1>
2442
2443 <!-- ----------------------------------------------------------------- -->
2444
2445 <sect1>
2446 <title>How do I stop the column headings of a GtkCList
2447 disappearing when the list is scrolled?</title>
2448
2449 <para>This happens when a GtkCList is packed into a
2450 GtkScrolledWindow using the function
2451 <literal>gtk_scroll_window_add_with_viewport()</literal>. The prefered
2452 method of adding a CList to a scrolled window is to use the
2453 function <literal>gtk_container_add</literal>, as in:</para>
2454
2455 <programlisting role="C">
2456     GtkWidget *scrolled, *clist;
2457     char *titles[] = { "Title1" , "Title2" };
2458
2459     scrolled = gtk_scrolled_window_new(NULL, NULL);
2460
2461     clist = gtk_clist_new_with_titles(2, titles);
2462     gtk_container_add(GTK_CONTAINER(scrolled), clist);
2463 </programlisting>
2464
2465 </sect1>
2466
2467 <!-- ----------------------------------------------------------------- -->
2468
2469 <sect1>
2470 <title>I don't want the user of my applications to enter text
2471 into a GtkCombo. Any idea?</title>
2472
2473 <para>A GtkCombo has an associated entry which can be accessed
2474 using the following expression:</para>
2475
2476 <programlisting role="C">
2477       GTK_COMBO(combo_widget)->entry
2478 </programlisting>
2479
2480 <para>If you don't want the user to be able to modify the
2481 content of this entry, you can use the
2482 gtk_entry_set_editable() function:</para>
2483
2484
2485 <programlisting role="C">
2486       void gtk_entry_set_editable(GtkEntry *entry, 
2487                                   gboolean editable);
2488 </programlisting>
2489
2490 <para>Set the editable parameter to FALSE to disable typing
2491 into the entry.</para>
2492 </sect1>
2493
2494 <!-- ----------------------------------------------------------------- -->
2495
2496 <sect1>
2497 <title>How do I catch a combo box change?</title>
2498
2499 <para>The entry which is associated to your GtkCombo send a
2500 "changed" signal when:</para>
2501
2502 <itemizedlist>
2503 <listitem><simpara>some text is typed in</simpara>
2504 </listitem>
2505
2506 <listitem><simpara>the selection of the combo box is changed</simpara>
2507 </listitem>
2508 </itemizedlist>
2509
2510 <para>To catch any combo box change, simply connect your
2511 signal handler with</para>
2512
2513 <programlisting role="C">
2514       gtk_signal_connect(GTK_COMBO(cb)->entry,
2515                          "changed",
2516                          GTK_SIGNAL_FUNC(my_cb_change_handler),
2517                          NULL);
2518 </programlisting>
2519
2520 </sect1>
2521
2522 <!-- ----------------------------------------------------------------- -->
2523
2524 <sect1>
2525 <title>How can I define a separation line in a menu?</title>
2526
2527 <para>See the <ulink
2528 url="http://www.gtk.org/tutorial/">Tutorial</ulink> for
2529 information on how to create menus. However, to create a
2530 separation line in a menu, just insert an empty menu item:</para>
2531
2532 <programlisting role="C">
2533 menuitem = gtk_menu_item_new();
2534 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
2535 gtk_widget_show(menuitem);
2536 </programlisting>
2537
2538 </sect1>
2539
2540 <!-- ----------------------------------------------------------------- -->
2541
2542 <sect1>
2543 <title>How can I right justify a menu, such as Help?</title>
2544
2545 <para>Depending on if you use the MenuFactory or not, there
2546 are two ways to proceed. With the MenuFactory, use something
2547 like the following:</para>
2548
2549 <programlisting role="C">
2550 menu_path = gtk_menu_factory_find (factory,  "&lt;MyApp&gt;/Help");
2551 gtk_menu_item_right_justify(menu_path->widget);
2552 </programlisting>
2553
2554 <para>If you do not use the MenuFactory, you should simply
2555 use:</para>
2556
2557
2558 <programlisting role="C">
2559 gtk_menu_item_right_justify(my_menu_item);
2560 </programlisting>
2561
2562 </sect1>
2563
2564 <!-- ----------------------------------------------------------------- -->
2565
2566 <sect1>
2567 <title>How do I add some underlined accelerators to menu
2568 items?</title>
2569
2570 <para>Damon Chaplin, the technical force behind the Glade
2571 project, provided the following code sample (this code is an
2572 output from Glade). It creates a small <GUIMenu>File</guimenu> menu item
2573 with only one child (<guimenu>New</guimenu>). The F in
2574 <guimenu>File</guimenu> and the N in <guimenu>New</guimenu> are
2575 underlined, and the relevant accelerators are created.</para>
2576
2577 <programlisting role="C">
2578   menubar1 = gtk_menu_bar_new ();
2579   gtk_object_set_data (GTK_OBJECT (window1), "menubar1", menubar1);
2580   gtk_widget_show (menubar1);
2581   gtk_box_pack_start (GTK_BOX (vbox1), menubar1, FALSE, FALSE, 0);
2582
2583   file1 = gtk_menu_item_new_with_label ("");
2584   tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (file1)->child),
2585                                    _("_File"));
2586   gtk_widget_add_accelerator (file1, "activate_item", accel_group,
2587                               tmp_key, GDK_MOD1_MASK, 0);
2588   gtk_object_set_data (GTK_OBJECT (window1), "file1", file1);
2589   gtk_widget_show (file1);
2590   gtk_container_add (GTK_CONTAINER (menubar1), file1);
2591
2592   file1_menu = gtk_menu_new ();
2593   file1_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (file1_menu));
2594   gtk_object_set_data (GTK_OBJECT (window1), "file1_menu", file1_menu);
2595   gtk_menu_item_set_submenu (GTK_MENU_ITEM (file1), file1_menu);
2596
2597   new1 = gtk_menu_item_new_with_label ("");
2598   tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (new1)->child),
2599                                    _("_New"));
2600   gtk_widget_add_accelerator (new1, "activate_item", file1_menu_accels,
2601                               tmp_key, 0, 0);
2602   gtk_object_set_data (GTK_OBJECT (window1), "new1", new1);
2603   gtk_widget_show (new1);
2604   gtk_container_add (GTK_CONTAINER (file1_menu), new1);
2605 </programlisting>
2606
2607 </sect1>
2608
2609 <!-- ----------------------------------------------------------------- -->
2610
2611 <sect1>
2612 <title>How can I retrieve the text from a GtkMenuItem?</title>
2613
2614 <para>You can usually retrieve the label of a specific
2615 GtkMenuItem with:</para>
2616
2617 <programlisting role="C">
2618     if (GTK_BIN (menu_item)->child)
2619     {
2620       GtkWidget *child = GTK_BIN (menu_item)->child;
2621   
2622       /* do stuff with child */
2623       if (GTK_IS_LABEL (child))
2624       {
2625         gchar *text;
2626     
2627         gtk_label_get (GTK_LABEL (child), &amp;text);
2628         g_print ("menu item text: %s\n", text);
2629       }
2630     }
2631 </programlisting>
2632
2633 <para>To get the active menu item from a GtkOptionMenu you can
2634 do:</para>
2635
2636 <programlisting role="C">
2637 if (GTK_OPTION_MENU (option_menu)->menu_item)
2638 {
2639   GtkWidget *menu_item = GTK_OPTION_MENU (option_menu)->menu_item;
2640 }
2641 </programlisting>
2642
2643 <para>But, there's a catch. For this specific case, you can
2644 <emphasis>not</emphasis> get the label widget from
2645 <literal>menu_item</literal> with the above code, because the
2646 option menu reparents the menu_item's child temporarily to
2647 display the currently active contents. So to retrive the child
2648 of the currently active menu_item of an option menu, you'll
2649 have to do:</para>
2650
2651 <programlisting role="C">
2652     if (GTK_BIN (option_menu)->child)
2653     {
2654       GtkWidget *child = GTK_BIN (option_menu)->child;
2655
2656       /* do stuff with child */
2657     }
2658 </programlisting>
2659
2660 </sect1>
2661
2662 <!-- ----------------------------------------------------------------- -->
2663
2664 <sect1>
2665 <title>How do I right (or otherwise) justify a
2666 GtkLabel?</title>
2667
2668 <para>Are you sure you want to <emphasis>justify</emphasis>
2669 the labels? The label class contains the
2670 <literal>gtk_label_set_justify()</literal> function that is
2671 used to control the justification of a multi-line
2672 label.</para>
2673
2674 <para>What you probably want is to set the <emphasis>alignment</emphasis>
2675 of the label, ie right align it, center it or left align
2676 it. If you want to do this, you should use:</para>
2677
2678 <programlisting role="C">
2679 void gtk_misc_set_alignment (GtkMisc *misc,
2680                              gfloat xalign,
2681                              gfloat yalign);
2682 </programlisting>
2683
2684 <para>where the <literal>xalign</literal> and
2685 <literal>yalign</literal> values are floats in
2686 [0.00;1.00].</para>
2687
2688 <programlisting role="C">
2689 GtkWidget       *label;
2690
2691 /* horizontal : left align, vertical : top */
2692 gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.0f);
2693
2694 /* horizontal : centered, vertical : centered */
2695 gtk_misc_set_alignment(GTK_MISC(label), 0.5f, 0.5f);
2696
2697 /* horizontal : right align, vertical : bottom */
2698 gtk_misc_set_alignment(GTK_MISC(label), 1.0f, 1.0f);
2699 </programlisting>
2700
2701 </sect1>
2702
2703 <!-- ----------------------------------------------------------------- -->
2704
2705 <sect1>
2706 <title>How do I set the background color of a GtkLabel
2707 widget?</title>
2708
2709 <para>The GtkLabel widget is one of a few GTK+ widgets that
2710 don't create their own window to render themselves
2711 into. Instead, they draw themselves directly onto their
2712 parents window.</para>
2713
2714 <para>This means that in order to set the background color for
2715 a GtkLabel widget, you need to change the background color of
2716 its parent, i.e. the object that you pack it into.</para>
2717
2718 </sect1> 
2719
2720 <!-- ----------------------------------------------------------------- -->
2721
2722 <sect1>
2723 <title>How do I set the color and font of a GtkLabel using a
2724 Resource File?</title>
2725
2726 <para>The widget name path constructed for a Label consists of
2727 the widget names of its object hierarchy as well, e.g.</para>
2728
2729 <para><literallayout>
2730 <literal>window (name: humphrey)</literal>
2731 <literal>  hbox</literal>
2732 <literal>     label (name: mylabel)</literal>
2733 </literallayout></para>
2734
2735 <para>The widget path your pattern needs to match would be:
2736 <literal>humphrey.GtkHBox.mylabel</literal></para>
2737
2738 <para>The resource file may look something like:</para>
2739
2740 <programlisting role="C">
2741 style "title"
2742 {
2743       fg[NORMAL] = {1.0, 0.0, 0.0}
2744       font = "-adobe-helvetica-bold-r-normal--*-140-*-*-*-*-*-*"
2745 }
2746 widget "*mylabel" style "title"
2747 </programlisting>
2748
2749 <para>In your program, you would also need to give a name to
2750 the Label widget, which can be done using:</para>
2751
2752 <programlisting role="C">
2753   label = gtk_label_new("Some Label Text");
2754   gtk_widget_set_name(label, "mylabel");
2755   gtk_widget_show(label);
2756 </programlisting>
2757
2758 </sect1>
2759
2760 <!-- ----------------------------------------------------------------- -->
2761
2762 <sect1>
2763 <title>How do I configure Tooltips in a Resource File?</title>
2764
2765 <para>The tooltip's window is named "gtk-tooltips",
2766 GtkTooltips in itself is not a GtkWidget (though a GtkObject)
2767 and as such is not attempted to match any widget styles.</para>
2768
2769 <para>So, you resource file should look something like:</para>
2770
2771 <programlisting role="C">
2772 style "postie"
2773 {
2774       bg[NORMAL] = {1.0, 1.0, 0.0}
2775 }
2776 widget "gtk-tooltips*" style "postie"
2777 </programlisting>
2778
2779 </sect1>
2780
2781 <!-- ----------------------------------------------------------------- -->
2782
2783 <sect1>
2784 <title>I can't add more than (something like) 2000 chars in a
2785 GtkEntry. What's wrong?</title>
2786
2787 <para>There is now a known problem in the GtkEntry widget. In
2788 the <literal>gtk_entry_insert_text()</literal> function, the
2789 following lines limit the number of chars in the entry to
2790 2047.</para>
2791
2792 <programlisting role="C">
2793   /* The algorithms here will work as long as, the text size (a
2794    * multiple of 2), fits into a guint16 but we specify a shorter
2795    * maximum length so that if the user pastes a very long text, there
2796    * is not a long hang from the slow X_LOCALE functions.  */
2797
2798   if (entry->text_max_length == 0)
2799     max_length = 2047;
2800   else
2801     max_length = MIN (2047, entry->text_max_length);
2802 </programlisting>
2803
2804 </sect1>
2805
2806 <!-- ----------------------------------------------------------------- -->
2807
2808 <sect1>
2809 <title>How do I make a GtkEntry widget activate on pressing
2810 the Return key?</title>
2811
2812 <para>The Entry widget emits an 'activate' signal when you
2813 press return in it. Just attach to the activate signal on the
2814 entry and do whatever you want to do. Typical code would
2815 be:</para>
2816
2817 <programlisting role="C">
2818   entry = gtk_entry_new();
2819   gtk_signal_connect (GTK_OBJECT(entry), "activate",
2820                       GTK_SIGNAL_FUNC(entry_callback),
2821                       NULL);
2822 </programlisting>
2823
2824 </sect1>
2825
2826 <!-- ----------------------------------------------------------------- -->
2827
2828 <sect1>
2829 <title>How do I validate/limit/filter the input to a GtkEntry?</title>
2830
2831 <para>If you want to validate the text that a user enters into
2832 a GtkEntry widget you can attach to the "insert_text" signal
2833 of the entry, and modify the text within the callback
2834 function. The example below forces all characters to
2835 uppercase, and limits the range of characters to A-Z. Note
2836 that the entry is cast to an object of type GtkEditable, from
2837 which GtkEntry is derived.</para>
2838
2839 <programlisting role="C">
2840 #include &lt;ctype.h&gt;
2841 #include &lt;gtk/gtk.h&gt;
2842
2843 void insert_text_handler (GtkEntry    *entry,
2844                           const gchar *text,
2845                           gint         length,
2846                           gint        *position,
2847                           gpointer     data)
2848 {
2849   GtkEditable *editable = GTK_EDITABLE(entry);
2850   int i, count=0;
2851   gchar *result = g_new (gchar, length);
2852
2853   for (i=0; i < length; i++) {
2854     if (!isalpha(text[i]))
2855       continue;
2856     result[count++] = islower(text[i]) ? toupper(text[i]) : text[i];
2857   }
2858   
2859   if (count > 0) {
2860     gtk_signal_handler_block_by_func (GTK_OBJECT (editable),
2861                                       GTK_SIGNAL_FUNC (insert_text_handler),
2862                                       data);
2863     gtk_editable_insert_text (editable, result, count, position);
2864     gtk_signal_handler_unblock_by_func (GTK_OBJECT (editable),
2865                                         GTK_SIGNAL_FUNC (insert_text_handler),
2866                                         data);
2867   }
2868   gtk_signal_emit_stop_by_name (GTK_OBJECT (editable), "insert_text");
2869   
2870   g_free (result);
2871 }
2872
2873 int main (int   argc,
2874           char *argv[])
2875 {
2876   GtkWidget *window;
2877   GtkWidget *entry;
2878   
2879   gtk_init (&amp;argc, &amp;argv);
2880   
2881   /* create a new window */
2882   window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
2883   gtk_window_set_title(GTK_WINDOW (window), "GTK Entry");
2884   gtk_signal_connect(GTK_OBJECT (window), "delete_event",
2885                      (GtkSignalFunc) gtk_exit, NULL);
2886   
2887   entry = gtk_entry_new();
2888   gtk_signal_connect(GTK_OBJECT(entry), "insert_text",
2889                      GTK_SIGNAL_FUNC(insert_text_handler),
2890                      NULL);
2891   gtk_container_add(GTK_CONTAINER (window), entry);
2892   gtk_widget_show(entry);
2893   
2894   gtk_widget_show(window);
2895   
2896   gtk_main();
2897   return(0);
2898 }
2899 </programlisting>
2900
2901 </sect1>
2902
2903 <!-- ----------------------------------------------------------------- -->
2904
2905 <sect1>
2906 <title>How do I use horizontal scrollbars with a GtkText widget?</title>
2907
2908 <para>The short answer is that you can't. The current version
2909 of the GtkText widget does not support horizontal
2910 scrolling. There is an intention to completely rewrite the
2911 GtkText widget, at which time this limitation will be
2912 removed.</para>
2913
2914 </sect1>
2915
2916 <!-- ----------------------------------------------------------------- -->
2917
2918 <sect1>
2919 <title>How do I change the font of a GtkText widget?</title>
2920
2921 <para>There are a couple of ways of doing this. As GTK+ allows
2922 the appearance of applications to be changed at run time using
2923 resources you can use something like the following in the
2924 appropriate file:</para>
2925
2926 <programlisting role="C">
2927 style "text"
2928 {
2929   font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*"
2930 }
2931 </programlisting>
2932
2933 <para>Another way to do this is to load a font within your
2934 program, and then use this in the functions for adding text to
2935 the text widget. You can load a font using, for example:</para>
2936
2937 <programlisting role="C">
2938   GdkFont *font;
2939   font = gdk_font_load("-adobe-helvetica-medium-r-normal--*-140-*-*-*-*-*-*");
2940 </programlisting>
2941
2942 </sect1>
2943
2944 <!-- ----------------------------------------------------------------- -->
2945
2946 <sect1>
2947 <title>How do I set the cursor position in a GtkText
2948 object?</title>
2949
2950 <para>Notice that the response is valid for any object that
2951 inherits from the GtkEditable class.</para>
2952
2953 <para>Are you sure that you want to move the cursor position?
2954 Most of the time, while the cursor position is good, the
2955 insertion point does not match the cursor position. If this
2956 apply to what you really want, then you should use the
2957 <literal>gtk_text_set_point()</literal> function. If you want
2958 to set the insertion point at the current cursor position, use
2959 the following:</para>
2960
2961 <programlisting role="C">
2962   gtk_text_set_point(GTK_TEXT(text),
2963   gtk_editable_get_position(GTK_EDITABLE(text)));
2964 </programlisting>
2965
2966 <para>If you want the insertion point to follow the cursor at
2967 all time, you should probably catch the button press event,
2968 and then move the insertion point. Be careful : you'll have to
2969 catch it after the widget has changed the cursor position
2970 though. Thomas Mailund Jensen proposed the following
2971 code:</para>
2972
2973 <programlisting role="C">
2974 static void
2975 insert_bar (GtkWidget *text)
2976 {
2977   /* jump to cursor mark */
2978   gtk_text_set_point (GTK_TEXT (text),
2979   gtk_editable_get_position (GTK_EDITABLE  (text)));
2980
2981   gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL,
2982      "bar", strlen ("bar"));
2983 }
2984
2985 int
2986 main (int argc, char *argv[])
2987 {
2988   GtkWidget *window, *text;
2989
2990   gtk_init (&amp;argc, &amp;argv);
2991
2992   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2993   text = gtk_text_new (NULL, NULL);
2994   gtk_text_set_editable (GTK_TEXT (text), TRUE);
2995   gtk_container_add (GTK_CONTAINER (window), text);
2996
2997   /* connect after everything else */
2998   gtk_signal_connect_after (GTK_OBJECT(text), "button_press_event",
2999     GTK_SIGNAL_FUNC (insert_bar), NULL);
3000
3001   gtk_widget_show_all(window);
3002   gtk_main();
3003
3004   return 0;
3005 }
3006 </programlisting>
3007
3008 <para>Now, if you really want to change the cursor position,
3009 you should use the
3010 <literal>gtk_editable_set_position()</literal>
3011 function.</para>
3012
3013 </sect1>
3014
3015 </chapter>
3016
3017 <!-- ***************************************************************** -->
3018 <chapter>
3019 <title>About GDK</title>
3020
3021 <!-- ----------------------------------------------------------------- -->
3022
3023 <sect1>
3024 <title>What is GDK?</title>
3025
3026 <para>GDK is basically a wrapper around the standard Xlib
3027 function calls. If you are at all familiar with Xlib, a lot of
3028 the functions in GDK will require little or no getting used
3029 to. All functions are written to provide an way to access Xlib
3030 functions in an easier and slightly more intuitive manner. In
3031 addition, since GDK uses GLib (see below), it will be more
3032 portable and safer to use on multiple platforms.</para>
3033
3034 <!-- Examples, anybody? I've been mulling some over. NF -->
3035
3036 </sect1>
3037
3038 <!-- ----------------------------------------------------------------- -->
3039
3040 <sect1>
3041 <title>How do I use color allocation?</title>
3042
3043 <para>One of the nice things about GDK is that it's based on
3044 top of Xlib; this is also a problem, especially in the area of
3045 color management. If you want  to use color in your program
3046 (drawing a rectangle or such, your code  should look something
3047 like this:</para>
3048
3049 <programlisting role="C">
3050 {
3051   GdkColor *color;
3052   int width, height;
3053   GtkWidget *widget;
3054   GdkGC *gc;
3055
3056   ...
3057   
3058   /* first, create a GC to draw on */
3059   gc = gdk_gc_new(widget->window);
3060
3061   /* find proper dimensions for rectangle */
3062   gdk_window_get_size(widget->window, &amp;width, &amp;height);
3063
3064   /* the color we want to use */
3065   color = (GdkColor *)malloc(sizeof(GdkColor));
3066   
3067   /* red, green, and blue are passed values, indicating the RGB triple
3068    * of the color we want to draw. Note that the values of the RGB components
3069    * within the GdkColor are taken from 0 to 65535, not 0 to 255.
3070    */
3071   color->red = red * (65535/255);
3072   color->green = green * (65535/255);
3073   color->blue = blue * (65535/255);
3074   
3075   /* the pixel value indicates the index in the colormap of the color.
3076    * it is simply a combination of the RGB values we set earlier
3077    */
3078   color->pixel = (gulong)(red*65536 + green*256 + blue);
3079
3080   /* However, the pixel valule is only truly valid on 24-bit (TrueColor)
3081    * displays. Therefore, this call is required so that GDK and X can
3082    * give us the closest color available in the colormap
3083    */
3084   gdk_color_alloc(gtk_widget_get_colormap(widget), color);
3085
3086   /* set the foreground to our color */
3087   gdk_gc_set_foreground(gc, color);
3088   
3089   /* draw the rectangle */
3090   gdk_draw_rectangle(widget->window, gc, 1, 0, 0, width, height);
3091
3092   ...
3093 }
3094 </programlisting>
3095
3096 </sect1>
3097
3098 </chapter>
3099
3100 <!-- ***************************************************************** -->
3101 <chapter>
3102 <title>About GLib</title>
3103
3104 <!-- ----------------------------------------------------------------- -->
3105
3106 <sect1>
3107 <title>What is GLib?</title>
3108
3109 <para>GLib is a library of useful functions and definitions
3110 available for use  when creating GDK and GTK applications. It
3111 provides replacements for some standard libc functions, such
3112 as malloc, which are buggy on some systems.</para>
3113
3114 <para>It also provides routines for handling:</para>
3115
3116 <itemizedlist spacing=compact>
3117 <listitem><simpara>Doubly Linked Lists</simpara>
3118 </listitem>
3119
3120 <listitem><simpara>Singly Linked Lists</simpara>
3121 </listitem>
3122
3123 <listitem><simpara>Timers</simpara>
3124 </listitem>
3125
3126 <listitem><simpara>String Handling</simpara>
3127 </listitem>
3128
3129 <listitem><simpara>A Lexical Scanner</simpara>
3130 </listitem>
3131
3132 <listitem><simpara>Error Functions</simpara>
3133 </listitem>
3134 </itemizedlist>
3135
3136 </sect1>
3137
3138 <!-- ----------------------------------------------------------------- -->
3139
3140 <sect1>
3141 <title>How can I use the doubly linked lists?</title>
3142
3143 <para>The GList object is defined as:</para>
3144
3145 <programlisting role="C">
3146 typedef struct _GList GList;
3147
3148 struct _GList
3149 {
3150   gpointer data;
3151   GList *next;
3152   GList *prev;
3153 };
3154 </programlisting>
3155
3156 <para>To use the GList objects, simply:</para>
3157
3158 <programlisting role="C">
3159 GList   *list = NULL;
3160 GList   *listrunner;
3161 gint    array[] = { 1, 2, 3, 4, 5, 6 };
3162 gint    pos;
3163 gint    *value;
3164
3165 /* add data to the list */
3166 for (pos=0;pos < sizeof array; pos++) {
3167   list = g_list_append(list, (gpointer)&amp;array[pos]);
3168 }
3169
3170 /* run through the list */
3171 listrunner = g_list_first(list);
3172 while (listrunner) {
3173   value = (gint *)listrunner->data;
3174   printf("%d\n", *value);
3175   listrunner = g_list_next(listrunner);
3176 }
3177
3178 /* removing datas from the list */
3179 listrunner = g_list_first(list);
3180 list = g_list_remove_link(list, listrunner);
3181 list = g_list_remove(list, &amp;array[4]);
3182 </programlisting>
3183
3184 <para>The same code is usable with singly linked lists (GSList
3185 objects) by replacing g_list_* functions with the relevant
3186 g_slist_* ones (g_slist_append,  g_slist_remove, ...). Just
3187 remember that since you can't go backward in a singly linked
3188 list, there is no g_slist_first function - you'll need to keep
3189 a  reference on the first node of the list.</para>
3190
3191 <!-- Some Examples might be useful here! NF -->
3192 <!-- I believe it should be better :) ED -->
3193 <!-- Linked lists are pretty standard data structures - don't want to
3194 over do it - TRG -->
3195
3196 </sect1>
3197
3198 <!-- ----------------------------------------------------------------- -->
3199
3200 <sect1>
3201 <title>Memory does not seem to be released when I free the
3202 list nodes I've allocated</title>
3203
3204 <para>GLib tries to be "intelligent" on this special issue: it
3205 assumes that you are likely to reuse the objects, so caches
3206 the allocated memory. If you do not want to use this behavior,
3207 you'll probably want to set up a special allocator.</para>
3208
3209 <para>To quote Tim Janik:</para>
3210 <para><quote>If you have a certain portion of code that uses *lots*
3211 of GLists or GNodes, and you know you'd better want to release
3212 all of them after a short while, you'd want to use a
3213 GAllocator. Pushing an allocator into g_list will make all
3214 subsequent glist operations private to that allocator's memory
3215 pool (and thus you have to take care to pop the allocator
3216 again, before making any external calls): </quote></para>
3217
3218 <programlisting role="C">
3219 GAllocator *allocator;
3220 GList *list = NULL;
3221 guint i;
3222
3223 /* set a new allocation pool for GList nodes */
3224 allocator = g_allocator_new ("list heap", 1024);
3225 g_list_push_allocator (allocator);
3226
3227 /* do some list operations */
3228 for (i = 0; i < 4096; i++)
3229   list = g_list_prepend (list, NULL);
3230 list = g_list_reverse (list);
3231
3232 /* beware to pop allocator befor calling external functions */
3233 g_list_pop_allocator ();
3234 gtk_label_set_text (GTK_LABEL (some_label), "some text");
3235
3236 /* and set our private glist pool again */
3237 g_list_push_allocator (allocator);
3238
3239 /* do some list operations */
3240 g_list_free (list);
3241 list = NULL;
3242 for (i = 0; i < 4096; i++)
3243   list = g_list_prepend (list, NULL);
3244   
3245 /* and back out (while freeing all of the list nodes in our pool) */
3246 g_list_pop_allocator ();
3247 g_allocator_free (allocator);
3248 </programlisting>
3249
3250 </sect1>
3251
3252 <!-- ----------------------------------------------------------------- -->
3253
3254 <sect1>
3255 <title>Why use g_print, g_malloc, g_strdup and fellow glib
3256 functions?</title>
3257
3258 <para>Thanks to Tim Janik who wrote to gtk-list: (slightly
3259 modified)</para>
3260
3261 <para><quote>Regarding g_malloc(), g_free() and siblings, these
3262 functions are much safer than their libc equivalents. For
3263 example, g_free() just returns if called with NULL. Also, if
3264 USE_DMALLOC is defined, the definition for these functions
3265 changes (in glib.h) to use MALLOC(), FREE() etc... If
3266 MEM_PROFILE or MEM_CHECK are defined, there are even small
3267 statistics made counting the used block sizes (shown by
3268 g_mem_profile() / g_mem_check()).</quote></para>
3269
3270 <para><quote>Considering the fact that glib provides an interface for
3271 memory chunks to save space if you have lots of blocks that
3272 are always the same size and to mark them ALLOC_ONLY if
3273 needed, it is just straight forward to create a small saver
3274 (debug able) wrapper around the normal malloc/free stuff as
3275 well - just like gdk covers Xlib. ;)</quote></para>
3276
3277 <para><quote>Using g_error() and g_warning() inside of applications
3278 like the GIMP that fully rely on gtk even gives the
3279 opportunity to pop up a window showing the messages inside of
3280 a gtk window with your own handler (by using
3281 g_set_error_handler()) along the lines of
3282 <literal>gtk_print()</literal> (inside of
3283 gtkmain.c).</quote></para>
3284
3285 </sect1>
3286
3287 <!-- ----------------------------------------------------------------- -->
3288
3289 <sect1>
3290 <title>What's a GScanner and how do I use one?</title>
3291
3292 <para>A GScanner will tokenize your text, that is, it'll return
3293 an integer for every word or number that appears in its input
3294 stream, following certain (customizable) rules to perform this
3295 translation. You still need to write the parsing functions on
3296 your own though.</para>
3297
3298 <para>Here's a little test program supplied by Tim Janik that
3299 will parse</para>
3300
3301 <para><literallayout>
3302 <literal>&lt;SYMBOL&gt; = &lt;OPTIONAL-MINUS&gt; &lt;NUMBER&gt; ;</literal>
3303 </literallayout></para>
3304
3305 <para>constructs, while skipping "#\n" and "/**/" style
3306 comments.</para>
3307
3308 <programlisting role="C">
3309 #include &lt;glib.h&gt;
3310
3311 /* some test text to be fed into the scanner */
3312 static const gchar *test_text =
3313 ( "ping = 5;\n"
3314   "/* slide in some \n"
3315   " * comments, just for the\n"
3316   " * fun of it \n"
3317   " */\n"
3318   "pong = -6; \n"
3319   "\n"
3320   "# the next value is a float\n"
3321   "zonk = 0.7;\n"
3322   "# redefine ping\n"
3323   "ping = - 0.5;\n" );
3324
3325 /* define enumeration values to be returned for specific symbols */
3326 enum {
3327   SYMBOL_PING = G_TOKEN_LAST + 1,
3328   SYMBOL_PONG = G_TOKEN_LAST + 2,
3329   SYMBOL_ZONK = G_TOKEN_LAST + 3
3330 };
3331
3332 /* symbol array */
3333 static const struct {
3334   gchar *symbol_name;
3335   guint  symbol_token;
3336 } symbols[] = {
3337   { "ping", SYMBOL_PING, },
3338   { "pong", SYMBOL_PONG, },
3339   { "zonk", SYMBOL_ZONK, },
3340   { NULL, 0, },
3341 }, *symbol_p = symbols;
3342
3343 static gfloat ping = 0;
3344 static gfloat pong = 0;
3345 static gfloat zonk = 0;
3346
3347 static guint
3348 parse_symbol (GScanner *scanner)
3349 {
3350   guint symbol;
3351   gboolean negate = FALSE;
3352
3353   /* expect a valid symbol */
3354   g_scanner_get_next_token (scanner);
3355   symbol = scanner->token;
3356   if (symbol < SYMBOL_PING ||
3357       symbol > SYMBOL_ZONK)
3358     return G_TOKEN_SYMBOL;
3359
3360   /* expect '=' */
3361   g_scanner_get_next_token (scanner);
3362   if (scanner->token != '=')
3363     return '=';
3364
3365   /* feature optional '-' */
3366   g_scanner_peek_next_token (scanner);
3367   if (scanner->next_token == '-')
3368     {
3369       g_scanner_get_next_token (scanner);
3370       negate = !negate;
3371     }
3372
3373   /* expect a float (ints are converted to floats on the fly) */
3374   g_scanner_get_next_token (scanner);
3375   if (scanner->token != G_TOKEN_FLOAT)
3376     return G_TOKEN_FLOAT;
3377
3378   /* make sure the next token is a ';' */
3379   if (g_scanner_peek_next_token (scanner) != ';')
3380     {
3381       /* not so, eat up the non-semicolon and error out */
3382       g_scanner_get_next_token (scanner);
3383       return ';';
3384     }
3385
3386   /* assign value, eat the semicolon and exit successfully */
3387   switch (symbol)
3388     {
3389     case SYMBOL_PING:
3390       ping = negate ? - scanner->value.v_float : scanner->value.v_float;
3391       break;
3392     case SYMBOL_PONG:
3393       pong = negate ? - scanner->value.v_float : scanner->value.v_float;
3394       break;
3395     case SYMBOL_ZONK:
3396       zonk = negate ? - scanner->value.v_float : scanner->value.v_float;
3397       break;
3398     }
3399   g_scanner_get_next_token (scanner);
3400
3401   return G_TOKEN_NONE;
3402 }
3403
3404 int
3405 main (int argc, char *argv[])
3406 {
3407   GScanner *scanner;
3408   guint expected_token;
3409
3410   scanner = g_scanner_new (NULL);
3411
3412   /* adjust lexing behaviour to suit our needs
3413    */
3414   /* convert non-floats (octal values, hex values...) to G_TOKEN_INT */
3415   scanner->config->numbers_2_int = TRUE;
3416   /* convert G_TOKEN_INT to G_TOKEN_FLOAT */
3417   scanner->config->int_2_float = TRUE;
3418   /* don't return G_TOKEN_SYMBOL, but the symbol's value */
3419   scanner->config->symbol_2_token = TRUE;
3420
3421   /* load symbols into the scanner */
3422   while (symbol_p->symbol_name)
3423     {
3424       g_scanner_add_symbol (scanner,
3425                             symbol_p->symbol_name,
3426                             GINT_TO_POINTER (symbol_p->symbol_token));
3427       symbol_p++;
3428     }
3429
3430   /* feed in the text */
3431   g_scanner_input_text (scanner, test_text, strlen (test_text));
3432
3433   /* give the error handler an idea on how the input is named */
3434   scanner->input_name = "test text";
3435
3436   /* scanning loop, we parse the input until its end is reached,
3437    * the scanner encountered a lexing error, or our sub routine came
3438    * across invalid syntax
3439    */
3440   do
3441     {
3442       expected_token = parse_symbol (scanner);
3443       
3444       g_scanner_peek_next_token (scanner);
3445     }
3446   while (expected_token == G_TOKEN_NONE &&
3447          scanner->next_token != G_TOKEN_EOF &&
3448          scanner->next_token != G_TOKEN_ERROR);
3449
3450   /* give an error message upon syntax errors */
3451   if (expected_token != G_TOKEN_NONE)
3452     g_scanner_unexp_token (scanner, expected_token, NULL, "symbol", NULL, NULL, TRUE);
3453
3454   /* finsish parsing */
3455   g_scanner_destroy (scanner);
3456
3457   /* print results */
3458   g_print ("ping: %f\n", ping);
3459   g_print ("pong: %f\n", pong);
3460   g_print ("zonk: %f\n", zonk);
3461   
3462   return 0;
3463 }
3464 </programlisting>
3465
3466 <para>You need to understand that the scanner will parse its
3467 input and tokenize it, it is up to you to interpret these
3468 tokens, not define their types before they get parsed,
3469 e.g. watch gscanner parse a string:</para>
3470
3471 <para><literallayout>
3472 <literal>"hi i am 17"</literal>
3473 <literal> |  | |  |</literal>
3474 <literal> |  | |  v</literal>
3475 <literal> |  | v  TOKEN_INT, value: 17</literal>
3476 <literal> |  v TOKEN_IDENTIFIER, value: "am"</literal>
3477 <literal> v  TOKEN_CHAR, value: 'i'</literal>
3478 <literal>TOKEN_IDENTIFIER, value: "hi"</literal>
3479 </literallayout></para>
3480
3481 <para>If you configure the scanner with:</para>
3482
3483 <programlisting role="C">
3484 scanner->config->int_2_float = TRUE;
3485 scanner->config->char_2_token = TRUE;
3486 scanner->config->scan_symbols = TRUE;
3487 </programlisting>
3488
3489 <para>and add "am" as a symbol with</para>
3490
3491 <programlisting role="C">
3492 g_scanner_add_symbol (scanner, "am", "symbol value");
3493 </programlisting>
3494
3495 <para>GScanner will parse it as</para>
3496
3497 <para><literallayout>
3498 <literal>"hi i am 17"</literal>
3499 <literal> |  | |  |</literal>
3500 <literal> |  | |  v</literal>
3501 <literal> |  | v  TOKEN_FLOAT, value: 17.0  (automatic int->float conversion)</literal>
3502 <literal> |  | TOKEN_SYMBOL, value: "symbol value"  (a successfull hash table lookup</literal>
3503 <literal> |  |                                       turned a TOKEN_IDENTIFIER into a</literal>
3504 <literal> |  |                                       TOKEN_SYMBOL and took over the</literal>
3505 <literal> |  v                                       symbol's value)</literal>
3506 <literal> v  'i'  ('i' can be a valid token as well, as all chars >0 and <256)</literal>
3507 <literal>TOKEN_IDENTIFIER, value: "hi"</literal>
3508 </literallayout></para>
3509
3510 <para>You need to match the token sequence with your code, and
3511 if you encounter something that you don't want, you error
3512 out:</para>
3513
3514 <programlisting role="C">
3515 /* expect an identifier ("hi") */
3516 g_scanner_get_next_token (scanner);
3517 if (scanner->token != G_TOKEN_IDENTIFIER)
3518   return G_TOKEN_IDENTIFIER;
3519 /* expect a token 'i' */
3520 g_scanner_get_next_token (scanner);
3521 if (scanner->token != 'i')
3522   return 'i';
3523 /* expect a symbol ("am") */
3524 g_scanner_get_next_token (scanner);
3525 if (scanner->token != G_TOKEN_SYMBOL)
3526   return G_TOKEN_SYMBOL;
3527 /* expect a float (17.0) */
3528 g_scanner_get_next_token (scanner);
3529 if (scanner->token != G_TOKEN_FLOAT)
3530   return G_TOKEN_FLOAT;
3531 </programlisting>
3532
3533 <para>If you got past here, you have parsed "hi i am 17" and
3534 would have accepted "dooh i am 42" and  "bah i am 0.75" as
3535 well, but you would have not accepted "hi 7 am 17" or "hi i hi
3536 17".</para>
3537
3538 </sect1>
3539
3540 </chapter>
3541
3542 <!-- ***************************************************************** -->
3543
3544 <chapter>
3545 <title>GTK+ FAQ Contributions, Maintainers and Copyright</title>
3546
3547 <para>If you would like to make a contribution to the FAQ, send either one
3548 of us an e-mail message with the exact text you think should be
3549 included (question and answer). With your help, this document can grow
3550 and become more useful!</para>
3551
3552 <para>This document is maintained by
3553 Tony Gale
3554 <ulink url="mailto:gale@gtk.org">&lt;gale@gtk.org&gt;</ulink>
3555
3556 Nathan Froyd
3557 <ulink url="mailto:maestrox@geocities.com">
3558 &lt;maestrox@geocities.com&gt;</ulink>,
3559 and 
3560 Emmanuel Deloget
3561 <ulink url="mailto:logout@free.fr">&lt;logout@free.fr&gt;</ulink>.
3562
3563 This FAQ was created by Shawn T. Amundson 
3564 <ulink url="mailto:amundson@gimp.org">
3565 &lt;amundson@gimp.org&gt;</ulink> who continues to provide support.
3566
3567 Contributions should be sent to Tony Gale <ulink
3568 url="mailto:gale@gtk.org">&lt;gale@gtk.org&gt;</ulink></para>
3569
3570 <para>The GTK+ FAQ is Copyright (C) 1997-2000 by Shawn T. Amundson, 
3571 Tony Gale, Emmanuel Deloget and Nathan Froyd.</para>
3572
3573 <para>Permission is granted to make and distribute verbatim copies of this
3574 manual provided the copyright notice and this permission notice are
3575 preserved on all copies.</para>
3576
3577 <para>Permission is granted to copy and distribute modified versions of this
3578 document under the conditions for verbatim copying, provided that this
3579 copyright notice is included exactly as in the original, and that the
3580 entire resulting derived work is distributed under the terms of a
3581 permission notice identical to this one.</para>
3582
3583 <para>Permission is granted to copy and distribute translations of this
3584 document into another language, under the above conditions for
3585 modified versions.</para>
3586
3587 <para>If you are intending to incorporate this document into a published
3588 work, please contact one of the maintainers, and we will make an
3589 effort to ensure that you have the most up to date information
3590 available.</para>
3591
3592 <para>There is no guarentee that this document lives up to its intended
3593 purpose.  This is simply provided as a free resource.  As such, the
3594 authors and maintainers of the information provided within can not
3595 make any guarentee that the information is even accurate.</para>
3596
3597 </chapter>
3598
3599 <!-- ----------------------------------------------------------------- -->
3600
3601 </book>