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