  ====================================================================
  |      GTK Tutorial                                                |
  |      Written By                                                  |
  |      Ian Main, slow@intergate.bc.ca                              |
  |      January 24, 1998.                                           |
  |                                                                  |
  |      Translated and Rewritten By                                 |
  |      Seo Joo-tai, liberta@cau.ac.kr                              |
  |      March ??, 1998.                                             |
  ==================================================================== 

   2  ݾ   GTK TutorialԴϴ.  ó GTK+ 
Ȩ http://www.gtk.org/ Դϴ.    ģ (3/??),
 Tutorial 1998/1/24 ¥ ö   ο ̳׿.   
 װ  ߽ϴ.   Ȱ뼺(?) Ͽ ó 
Ϲ ؽƮ(plain text)  ߽ϴ.

  GTK+ Tutorial  24 (Chapter) ̷ 24(Copying)
    ״ ϴ   ̶ Ǵ, 
 ʾҽϴ.  ׸  ߴٰ (?)ϴ  鵵, 
 Ƿ°  Xlib/Widget Programming   ϳ
  ۿ ϴ.    Ű ϱ, ˾Ƽ
޾Ƶ̽ñ ٶϴ.  :)    Ȯ ؼ å  ϴ. 
  ȿ ظ ؼ   /   մϴ.

   Tutorial    ־,  ̳  帮
 ü  Ұմϴ.

==> tut01.txt <==
***********
*** 1. Ұ
***********
	GTK(GTK+)  ҰԴϴ.  ̹  (go linux) 
Խǿ ø GTK+ FAQ   Դϴ.

==> tut02.txt <==
*****************
*** 2. ϸ鼭
*****************
	GTK   ,   helloworld.c α׷Դϴ.
׸ ٵ ġ ϴ  ɼǵ  Ǿ .  ߿ ̷,
 ñ׳(signal) Լ  (callback function) GTK ̿ϴ
Ŀ ؼ ٷϴ.

==> tut03.txt <==
**********************
*** 3.  ư
**********************
	helloworld.c  ϸ鼭 ڷ鿡  ܼҸ ɱ, ׸
ñ׳ ڵ鷯  漳 ֽϴ.  ñ׳, ߿ .

==> tut04.txt <==
******************
*** 4. ŷ Widget
******************
	ŷ(packing)̶ ߿ 信 ( ϴ` :)
 Բ ϰ ֽϴ.  ŷ 簢    ־
дٴ ǹ̷, GTK+ó , ü ٷ ߹Ŀ  ⺻̰
" " Դϴ.  ⼭ ϳ ŷϱ  ڽ(box),
 Ѳ ŷϱ  ̺(table) ʴ Ұմϴ.

==> tut05.txt <==
********************
*** 5. Widget 
********************
	FAQ ߰,     , GTK+
C typedef struct{...} WidgetObject;  ̿ "ü"
߱ϰ ֽϴ.   C++ public member function 䳻 
return_type (*func_pointer)(parameters,...)  Ǵ callback Լ
ϴ.  ⼭ func_pointer ü ˰, ׸     
"C Ƿ(?)" ִٸ GTK  ̱   ̴ϴ.  GTK+ ̷
״   ƴմϴ. :)
	 忡 GTK+ Object γ ٸ widget , 
  ְ ֽϴ.  ̹ ٸ Widget  ẻ  Ȥ
ּ Xlib ٷﺻ  ִٸ C  ͸ŭ̳ ū  
Դϴ.  ,  忡 Gtk widget object   ҰǾ
ֽϴ.  ſ  .

==> tut06.txt <==
******************
*** 6. ư widget
******************
	켱   widget ư ġ ֽϴ.  ׳ ư,
̻ ư(Ƚ ~*), Ư ư(, üũ, ,..)  츮
 õ鿡  ̿  (?)  ư Ĩϴ.

==> tut07.txt <==
**********************
*** 7. پ widget
**********************
	ڱ ȥ ̱⺸ ٸ widget ٹ̱  ̴  ִ
  widget Ұմϴ.  (label), ǳ(tooltip), 
(progress bar), ȭ(dialog box), Ƚ(pixmap) Դϴ.  Ư
Ƚʿ ؼ   ڻϰ(?) ٷ𱺿.
	Tooltip ǳ̶ ؼ , MacOS(ѱ) ׷ 
ǳ̶ θ  ͼ Դϴ.  Ǵٸ ǥ . :)

==> tut08.txt <==
**********************
*** 8. ̳ widget
**********************
	Ʈ(notebook) ũѵ (scrolled window) ٷϴ.
̵    ٸ widget  ϴ widget
Դϴ.  ġ(Yahoo,Altavista,..)  ܾ,  "girl"
˻غ ٵ ˴ٽ   ũ ?  ̶ ȭ
ϱ    ũѵ˴ϴ.  , ũѹ(scroll bar)
.   "girl" ó õ   ũ ٸ ũѹ
ε ?  ׷    Ʒʿ ͺ ü ũ
1 20, ׸ < (NEXT)>̶, (page) ϰ 
  ֽϴ.  ̷  ϴ  ƮԴϴ.

==> tut09.txt <==
********************
*** 9. Ʈ widget
********************
	ϸŴ(file manager)    ǰڳ׿.  M$
Ž(explorer) TkDesk ϰâ ,   ̸ Ӽ
(item) ϴ Ʈ(list) ̷ ֽϴ.   忡 ٷ
 ̷ Ʈ  , 콺ư ¿Ŭ  
(selection) ϴ  Դϴ.    α׷ 
ϼ.

==> tut10.txt <==
*****************
*** 10.  
*****************
	ϸ鼭   õ鿡 ϰ  ϼ ڽ
ҰǾ ֽϴ.  ׳ ' '    ϳ׿.  :)  
ؼ  ,  ʵ Ŷ(toolkit) ã   
̴ϴ.

==> tut11.txt <==
*******************
*** 11. ޴ widget
*******************
	޴(menu)   Ұϰ ֽϴ.  GTK+  ϳ
Ŷ̴ϱ  ޴ ϳ  ִ Լ  մϴ.  ׸
Կ ణ , ޴ â 뷮ִ (factory)
մϴ.  ޴ Ǯٿ(pull-down) ˾(pop-up) ΰ .
׸   ""  (޴)    ֵ 
 α׷ ҰǾϴ.

==> tut12.txt <==
********************************
*** 12. ȭ  widget
********************************
	'̷ ͵鿡 ؼ  Ʃ丮    
 !' -> ̷±. :)    Preview widget 
ٸ   οߴ.     κ (?!) ϰ
  ü ׽ϴ.  (˼~*)  www.gtk.org ִ  
ϼ.

==> tut13.txt <==
*************************
*** 13. ̺Ʈڽ widget
*************************
	gtk+970916.tar.gz   ϴ widget̶±.
޴ ƴϰ ư ƴϰ, ·  ϰ(?) δٳ׿. :)

==> tut14.txt <==
********************************
*** 14. Widget Ӽ ϱ
********************************
	 ׷,     Լ(prototype)
  ̴.   GTK+   Լ̸  ü 
ϴ.  ù κп  ܼҸ ִ, ׳ ִ ״ ؼ ׽ϴ.
 widget object Ӽ(property) ϱ  ԼԴϴ.

==> tut15.txt <==
******************************************
*** 15. ŸӾƿ, ׸ I/O Idle Լ
******************************************
	־ ð(milliseconds) ȣǴ Լ, ׳ ϴ Լ,
 ̵ ϴ(monitoring) Լ  ҰǾ ֽϴ.  
     ̴ϴ. ^^;

==> tut16.txt <==
**************************
*** 16. Selection ϱ
**************************
	κ ͹̳̳ (editor) 콺   
 õ  ǰ, ޴    ī(copy), (cut),
̽Ʈ(paste)  ۾   ֽϴ.  ׷  Ϳ 
ܾ ٷ ٸ        Ǵ?
 ϴ    ,  ܾ  ''Ǵ.
̷  selection մϴ.    ܾ ְ ؼ, ܿ
߽ϴ.  (  о  ߴµ,     бⰡ
ȳ׿. :)

==> tut17.txt <==
************
*** 17. glib
************
	GTK+ FAQ  , GTK+  libc ƴ, glib
̿մϴ.    ÷  ο  C ̺귯 ġؾ
 Ӹ ƴ϶,  ǥԼ glib  ߴ  ˾Ƴ
ϰ.  (Ϲ  忡    ϴ,  printf
g_print ٲ ̴ϱ. ;)
	 忡  libc  ʴ ο ͵ ַ,
  ϰ ֽϴ.   ڷ Ѱ(extrema), Ű
(architecture)  typedef ֿ ڷ(data type), ׸ 
 迡  ḮƮ(linked list) Ұ .   ޸
 Լ  鼭 g_malloc/g_free , glib ޸Լ鵵
, ý Ÿ̸(timer)Լ, ڿ(string)Լ ֳ׿.  ׸
 ƿƼ  Լ Ұ߽ϴ.

==> tut18.txt <==
*********************
*** 18. GTK rc 
*********************
	н 迭 ü ̿ϴ ̶ ޿  rc
  𸣰ڳ׿. ^^;   忡 츮 ͼ õó,
Ȱ ̳ʸ(binary,executable)   Ը ° 'ȯ漳'
ؼ ̿  ְ ϴ  Ұմϴ.  GTK+ rc ٸ κ X
õ , ϰ ִ ɺ(simbol) ̿մϴ.   κп
 rc  ϼ.

==> tut19.txt <==
******************************
*** 19. ڽŸ widget 
******************************
        19  "Creating Your Own Widgets",  "ڽŸ  "
Դϴ.   ϴ ҵ ׷ ̸ Tictactoe widget ̷
     ǲ/ þҽϴ.
        Widget ٴ  ̹ ִ widget ̿ϴ Ͱ Ǵٸ
,   Ѿ  ֽϴ.  켱, ¥ ǿ 
ϴ  ƴ϶ " " ,   parent class ؾ
մϴ.  ׸  widget óؾ ñ׳ΰ ̺Ʈ ؼ 
° "" ؾ.  ׸   , ̷ ֽ(?) 
widget   ϰ,  ذ ϰ ֱ.

==> tut20.txt <==
**********************************
*** 20. ,  ׸ 
**********************************
	 ϰ (?)  ٷ Դϴ.  GIMPó, ¥
׸ ٷ ؼ ˾ƾ  ͵̶ ϴ±.
	 콺 Ű ̹  ̺Ʈ(low-level event)
ٷ ֽϴ.  Xlib   ֵ  #define  Ʈ
(bitwise operation)Ű .    Ű 콺 Ͼ
 ̺Ʈ ϰ ϱ  ̰?  ڸ մ 
  ȭ ϴ Դϴ.  κ widget Լ GTK
̽(base) ̷ GDK(General Drawing Kits) ̺귯  ͵
Դϴ.    ׸ ͺ, Ƚ̶  ȭ ׷
  ʿ    ִ  , Xlibó.
	 Ƚʿ ׸ ׸ 鿡  ܼҸ ̾ϴ.
Xlib GC(Graphics Context)   ôٸ     
̴ϴ.   簢 ϳ ׸  gdk_draw_rectangle()̶ 
ε, 簢 ̷  , , (Ǽ//⼱)  ⺻
Ӽ GC  ,  ׸  gdk_draw_rectangle̶ Լ
ڷμ شϴ Ӽ  ִ GC Ѱݴϴ.   GTK+ 
ü̱  ⺻ Ѵٸ Xlib    
 ̴ϴ.
	  ʾұ! -_-;   忡   ׸ ׸
 콺  ( ?) Էġ ̿ ,  ߱
ֽϴ.  Drawing tablet, Ư Էġ ߻ϴ Ǵٸ ̺Ʈ
 ٷ  Ȯ̺Ʈ(extended event) Ѵٰ ϳ׿.  콺
 ߻ϴ  ̺Ʈε Ӹ µ Դϴ.  :)  ·
  , 콺   ġ(device)  ̿ϴ
  ̾߱ϰ ֽϴ.

==> tut21.txt <==
******************************
*** 21. GTK  ϴ 
******************************
	ʹ ߿ ̶   ۿ   ׿. ;)

==> tut22.txt <==
********************
*** 22. Contributing
********************
	 ſ ߿ ̴ϴ.

==> tut23.txt <==
***************
*** 23. Credits
***************
	  ϴ    鿡   ϴ,
  ߿ Դϴ.  Ϻ  ״ ׽ϴ.

==> tut24.txt <==
***************
*** 24. Copying
***************
	GPL      ִ,  ߿ Դϴ.
Ϻη  ״ ׽ϴ.


	***  3 26Ͽ Դ븦 ϴ  liberta@zeus.phys.cau.ac.kr,
	׸ liberta@cau.ac.kr   ŵ   ̴ϴ. :)
	   ߰ , ׸   ε 
	 ڽſ ޷ ֽϴ.  ׷ GTK+ Բ ſ 
	Ͻñ ٶϴ.  :)



***********
*** 1. Ұ
***********

  GTK(GIMP Toolkit)  GIMP(General Image Manipulation Program) 
 Ŷ ߵǾ.  GTK Xlib Լ鿡  ⺻ wrapper
GDK(GIMP Drawing Kit)  ϰ ִ.   GIMP  
ߵǾ,     Ʈ ۿ ̰ Ǿ.  GTK
ڵ  .  

	Peter Mattis   petm@xcf.berkeley.edu
	Spencer Kimball spencer@xcf.berkeley.edu
	Josh MacDonald jmacd@xcf.berkeley.edu

  GTK  ü   ȯ̴(API, Application
Programmers Interface).    C  Ŭ  callback
Լ(Լ  ) ߾ ̴.  ⿡ ḮƮ ٷ
   Լ Բ, glib Ҹ   ǥԼ ġ 
ִ Լ鵵 ° ҷ ԵǾ ִ.  g_strerror()ó,   
Լ ٸ н鿡  ǥ ƴϰų    ̱ ,
GTK ̽ļ ̱  ⿡  ġԼ鵵 .   g_malloc
  ȭߵ libc   ̷⵵ ߴ.

     GTK    ̸,   ǹ ʴ´. 
ڴ C  ˸ Cα׷   ˰  ̶ 
Ѵ.   ʿ  ƴϰ, ڰ ̹ X α׷  
ִٸ ſ ū   ̴.    widget Ʈ  GTK ó
 ̶,    ߰ϰ Ǿ  Ư  κ 
̶   ˷ֱ ٶ.  GTK  C++ Ŀ  API ִٴ
  ̸,  C++  ȣѴٸ ̰ ſ װ ϱ
ٶ.   Objective C, Guile ε , · ⼭
װ͵  ʰڴ.

      GTK ϴ  ־    ˷
ֱ ٶ, װ   Ǵ Ϳ ū   ̶ Ѵ.



*****************
*** 2. ϸ鼭
*****************

      GTK ҽ ޾Ƽ װ ġϴ ̴.  
 ֽ  ftp.gimp.org /pub/gtk   ִ.  GTK 
Ǵٸ ҽ http://www.gimp.org/gtk ִ.  GTK GNU autoconf
̿Ѵ.  ϴ  Ǭ , ./configure --help ļ ɼǵ 
 ٶ.

  GTK  Ұ ؼ,    α׷  .  
α׷ 200x200 ȼ   ,  ̿ ʰ 
  α׷̴.

  #include <gtk/gtk.h>

  int main (int argc, char *argv[])
  {
      GtkWidget *window;

      gtk_init (&argc, &argv);

      window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
      gtk_widget_show (window);

      gtk_main ();

      return 0;
  }

   α׷  GTK ÿ  , Լ, ü  Ǿ ִ
gtk/gtk.h  ̴.

       gtk_init (&argc, &argv);

  GTK  ٸ  α׷ θ Ǵ Լ gtk_init(gint
*argc, gchar ***argv)  θ ִ.  ̰ Ʈ  ־ Į
  ϸ   gdk_init(gint *argc, gchar ***argv) Ѿ.
 Լ  ̺귯 ʱȭ ϰ, Ʈ ñ׳ ڵ鷯 ¾ϸ,
  α׷  ڵ  Ʒ ͵ ã üũѴ.

	--display
	--debug-level
	--no-xshm
	--sync
	--show-events
	--no-show-events

    ν  ͵ ܵΰ,  ͵  Ʈ
Ѵ.  ̰  GTK ÿ  ǥ ڵ Ʈ .

    ٿ   ش.

	window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
	gtk_widget_show (window);

  GTK_WINDOW_TOPLEVEL̶ ڴ  Ŵ İ ġ 
Ѵ.  0x0 ũ   ʰ, child   Ʈ 200x200
ũ  츮 װ  ٷ  ִ.
 
  gtk_widget_show() Լ  widget Ӽ    GTK
˷ִ ̰, ׷  widget  ȴ.

    GTK  ó   ̴.

       gtk_main ();

  gtk_main() GTK     ִ  ϳ Լȣ̴. 
α׷ ⿡ ̸, GTK X ̺Ʈ, ŸӾƿ, Ǵ   
 ٸ ϰ ȴ.  ׷   α׷ ׷ ͵
õǰ ִ.

***
*** 2-1. GTK Hello World α׷
***
   ϳ widget(ư)  α׷̴,   hello world
GTKν  .

  #include <gtk/gtk.h>

  /* ̰ callbackԼ.  ⼭ ڵ õǾ. */
  void hello (GtkWidget *widget, gpointer data)
  {
      g_print ("Hello World\n");
  }

  gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
  {
      g_print ("delete event occured\n");
      /* "delete_event" ñ׳ڵ鷯 TRUE ϸ,
       * GTK "destroy" ñ׳ ߻Ų.  FALSE ϸ
       *  ¥ ıǱ  ʴ ̴.  ̰
       * '¥ ƴϱ?'  ȭڰ Ƣ  
       * ϴ. */
       
      /* FALSE TRUE ġ main  "delete_event" Բ
       * ı ̴. */
      return (FALSE);
  }

  /* Ǵٸ callback */
  void destroy (GtkWidget *widget, gpointer data)
  {
      gtk_main_quit ();
  }

  int main (int argc, char *argv[])
  {
      /* GtkWidget widget   Ÿ̴. */
      GtkWidget *window;
      GtkWidget *button;

      /* ̰  GTK õ鿡 ȣȴ.  ڵ  κ
       * ־ ÷ . */
      gtk_init (&argc, &argv);

      /* ο  . */
      window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

      /*  "delete_event" (̴ Ŵ Ѵ), 츮
       *   Լ delete_event() ȣ  ȮѴ.  
       * callbackԼ  ʹ NULL̰  ⼭ õȴ. */
      gtk_signal_connect (GTK_OBJECT (window), "delete_event",
                          GTK_SIGNAL_FUNC (delete_event), NULL);

      /* ⼭ ñ׳ڵ鷯 "destroy" ̺Ʈ  ش.
       *  ̺Ʈ 츮   gtk_widget_destroy() ȣϰų,
       * Ǵ "delete_event" callback 'TRUE'   ߻Ѵ. */
      gtk_signal_connect (GTK_OBJECT (window), "destroy",
                          GTK_SIGNAL_FUNC (destroy), NULL);

      /*  border width Ѵ. */
      gtk_container_border_width (GTK_CONTAINER (window), 10);

      /* "Hello World"  ִ ο ư . */
      button = gtk_button_new_with_label ("Hello World");

      /* ư "clicked" ñ׳  NULL ڷ ؼ hello()
       * ȣȴ.   hello() Լ  ǵǾ. */
      gtk_signal_connect (GTK_OBJECT (button), "clicked",
                          GTK_SIGNAL_FUNC (hello), NULL);

      /* ̰ "clicked"Ǹ gtk_widget_destroy(window) ȣ,  
       * ıϰ ȴ.  ռ ߵ, 'destroy' ñ׳ ⼭ ̷
       * ߻ϰų, Ǵ Ŵ  ߻Ѵ. */
      gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
                                 GTK_SIGNAL_FUNC (gtk_widget_destroy),
                                 GTK_OBJECT (window));

      /* ̰ ư ,  GTK ̳ ϳ ŷѴ. */
      gtk_container_add (GTK_CONTAINER (window), button);

      /*    widget ư ִ ̴. */
      gtk_widget_show (button);

      /*  ü ⼭ ش. */
      gtk_widget_show (window);

      /*  GTK   gtk_main() ϳ  ִ.  Ʈ
       * ⼭    ̺Ʈ(Ű ٰų 콺 ϴ
       * ) ߻  Ѵ. */
      gtk_main ();

      return 0;
  }

***
*** 2-2. Hello world ϱ
***
  ϱ  ̷ ϶.

       gcc -Wall -g helloworld.c -o hello_world -L/usr/X11R6/lib \
           -lgtk -lgdk -lglib -lXext -lX11 -lm

   ̺귯 Ʈ Žο ־ ϰ, ׷  
-L<library directory>  ָ gcc ʿ ̺귯  丮
Žϰ  ̴.  ,   Debian Linux ýۿ X11
̺귯 ã  ֵ -L/usr/X11R6/lib  ־ Ѵ.

  ̺귯   ߿ϴ.  Ŀ Ǳ   Լ
 ˰ ־ Ѵ.

    ̺귯 ̿ Ѵٸ ̺귯  Ư ߿
.     ٷ ̷ .

  츮 ũŲ ̺귯   ͵̴.

	The glib library (-lglib), پ Լ ϰ , ⼭
	  g_print()Լ.  GTK glib  ϰ Ƿ
	  ̺귯 ʿ ̴.  ڼ  glib 
	κ ϶.

	The GDK library (-lgdk), Xlib ߾ ѷ wrapper.

	The GTK library (-lgtk), GDK  widget ̺귯.

	The Xlib library (-lX11), GDK   ȴ.

	The Xext library (-lXext), ̰  ޸ pixmap ٸ X Ȯ
	鿡  ڵ带  ̴.

	The math library (-lm), ̰   GTK ̰ ȴ.  

***
*** 2-3. ñ׳ΰ callback  ̷
***
  Hello world α׷ ڼ 캸⿡ ռ, ̺Ʈ callback 
 Ѿ.  GTK ̺Ʈ ư Ŷ̸, ̰  ̺Ʈ
߻ؼ  ٸ Լ  Ѿ ʴ   Ѵٴ ǹ̴.

    ѱٴ  "ñ׳" ̿뿡  ̷.  콺 ư
 Ͱ  ̺Ʈ , ٿ شϴ  ñ׳
widget  "߻"ϰ ȴ.  ̰ GTK ϴ  ۾ κ̴.
ư ۿ   Ű, 츮 ̷ ñ׳ε Ƴ
ñ׳ ڵ鷯 ¾ϰ ̿  Լ θ ȴ.  ̰  
Լ ̿ν ̷.

       gint gtk_signal_connect (GtkObject *object,
                                gchar *name,
                                GtkSignalFunc func,
                                gpointer func_data);

  ù° ڴ ñ׳ ߻ų widget̰, ι° Ƴ ϴ
ñ׳ ̸̴.  ° ڴ  ñ׳ ŽǾ  ȣ Լ,
׹°  Լ Ѱ .

  ° ڷ ִ Լ "callbackԼ" θ ó ̷
ִ.

       void callback_func(GtkWidget *widget, gpointer *callback_data);

   Լ ù° ڴ ñ׳ ߻Ų widget  Ͱ ǰ,
ι° ڴ   gtk_signal_connect() Լ ׹° ڷ ־
ִ   ʹ.

  Hello world   Ǵٸ ȣ ̴̰.

       gint gtk_signal_connect_object (GtkObject *object,
                                       gchar  *name,
                                       GtkSignalFunc func,
                                       GtkObject *slot_object);

  gtk_signal_connect_object() callbackԼ GTK object  Ͷ,
 ϳ ڸ ̿Ѵٴ   gtk_signal_connect() . 
׷Ƿ ñ׳ ų   Լ ̿Ѵٸ callbackԼ ̷
 ؾ  ̴.

       void callback_func (GtkObject *object);

  ⼭ object 밳 widget Ѵ.  츮 · ǵ gtk_signal
_connect_object ̿ؼ callback ¾  ̴.  ׵ 츮
hello world ó, ַ ڷμ ñ׳ widget/object ϴ GTK
Լ θ  ̰ ִ.

  ñ׳ Ű    Լ  ִ    ٸ
 ڸ  ִ callback ϱ ؼ̴.  GTK ̺귯
ִ  Լ ڷμ  GtkWidget ͸ ϹǷ, ̷ 
 gtk_signal_connect_object()  ̿ϸ  ̴.  ݸ ڽ Լ
ؼ, callback ߰    ʿ䰡  ̴.

***
*** 2-4. Hello World  Ѱ
***
    ̷п  ˾Ұ, hello world  α׷   Ȯ
ص.

  ̰ ư ""̶ ̺Ʈ  ȣ callbackԼ.   
 widget   õ, װ͵ ٷ  ״ 
ʴ.  ̰    ư ° ˷ֱ   ڸ
̿ϴ ̴.

       void hello (GtkWidget *widget, gpointer *data)
       {
           g_print ("Hello World\n");
       }

   callback ټ Ưϴ.  Ŵ ÿ  ̺Ʈ 
"delete_event" ߻ϰ ȴ.  츮 ⼭ ̷ ̺Ʈ鿡  
  Ѵ.  츮 װ   ְ, ̿  
  , Ǵ      ִ.

   callback ϰ  GTK   ؾ  ˰ ȴ.  FALSE
ϸ GTK 츮 "destroy"ñ׳ ߻ϴ   ʴ´ٰ Ǵ
ϰ ȴ.  ׸ TRUE ϴ  츮 "destroy"ñ׳ ߻
ȮνŰ, "destroy"ñ׳ ڵ鷯 ȣϰ ȴ.

       gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
       {
           g_print ("delete event occured\n");

           return (FALSE);
       }

    gtk_main_quit() ȣϴ   , Ǵٸ callback
Լ ִ.  ̰Ϳ ؼ 主 ʰڴ,     ̹Ƿ.

       void destroy (GtkWidget *widget, gpointer *data)
       {
           gtk_main_quit ();
       }

   main()  Ϳ  ˰  Ѵ, ٸ ð ,
 GTK   main()  ϳ  ִ.

       int main (int argc, char *argv[])
       {

   κп, GtkWidget ü  ͸ Ѵ.  ̰͵
 ư   Ʒ ̰ ȴ.

           GtkWidget *window;
           GtkWidget *button;

   ٽ gtk_init ´.   , ̰ Ŷ ʱȭϰ,
࿡ ־ ڵ мѴ.  ̰ ࿡   ڶ
 Ʈ ϰ, argc argv   ڵ  ʴ
ó ̰ ؼ,   ִ ڵ鸸 мϵ ش.

           gtk_init (&argc, &argv);

    ϳ .  ̰ ϳ ϴ.  GtkWidget *window  
Ű ü ޸𸮰 ҴǾ   ϴ ü Ű 
̴.  ο  ¾,  gtk_widget_show(window) ȣ
ʾұ    ʰ ִ.    α׷  ó
̰  ̴.

           window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

   쿣  ǰ,   object ñ׳ ڵ鷯 Ű
 ִ.  ⼭ "destory"ñ׳ Žȴ.   ñ׳ 츮 
ֱ ؼ Ŵ  ̿ (׸ 츮 "delete_event"
ڵ鷯 TRUE  ), Ǵ ı object widget Ͽ
gtk_widget_destroy() ȣ  ߻Ѵ.  ̰ ¾ϴ  츮
  ȣ   θ ٷ  ִ.  ⼭, װ տ ǵ
destroy() Լ NULL ڷ ȣϿ GTK ϰ Ѵ.

  GTK_OBJECT GTK_SIGNAL_FUNC ڵ带  м  ְ ָ ڷ
ĳð üũ ִ ũε̴.

           gtk_signal_connect (GTK_OBJECT (window), "destroy",
                               GTK_SIGNAL_FUNC (destroy), NULL);

  ̹ Լ container object Ӽ  ֱ  .  ̰
 10 ȼ ʺ   ѷ̰ Ѵ.  츮  "Widget
Ӽ "̶ section    ٸ Լ ϰ 
̴.
  ׸, GTK_CONTAINER  ڷ ĳ ִ ũδ.

           gtk_container_border_width (GTK_CONTAINER (window), 10);

   ȣ  ư ϳ .  ̰ ο GtkWidget ü 
޸  Ҵϰ, װ ʱȭϸ, ׸ button̶ Ͱ 
 Ű Ѵ.   ư  Ǿ  "Hello World"
   ̴.

           button = gtk_button_new_with_label ("Hello World");

  츮 ⼭  ư    ϵ Ѵ.  츮 װͿ
ñ׳ ڵ鷯 ޾ְ, "clicked"ñ׳ ߻  츮 hello()
Լ ȣǵ Ѵ.    ,  츮 hello()
callbackԼ ܼ NULL ش.  и, 츮 콺 ͷ 
ư Ŭ  "clicked"ñ׳ ߻ϰ ȴ.

           gtk_signal_connect (GTK_OBJECT (button), "clicked",
                               GTK_SIGNAL_FUNC (hello), NULL);

  츮  α׷  ؼ  ư ̿Ѵ.  ̰ 
Ŵ ؼ, Ȥ 츮 α׷ ؼ "destroy"ñ׳  
  ̴.  տó ư   hello() callback
Լ ҷ, ̾ ׵ ¾  ̰ ȣȴ. ʿϴٸ
󸶵 callbackԼ   , װ͵ δ 츮 ѳ
 ȴ.  gtk_widget_destroy()Լ  GtkWidget *widget
ڷ ϱ , 츮 ⼭ gtk_signal_connect() ٷ  ʰ
gtk_signal_connect_object() .

           gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
                                      GTK_SIGNAL_FUNC (gtk_widget_destroy),
                                      GTK_OBJECT (window));

  ̰ ŷȣ̸ ڿ   ٷ ̴.     
 ִ.  ̰  GTK, ư  ư    ġؾ
ȴٴ  ˷ش.

           gtk_container_add (GTK_CONTAINER (window), button);

   츮 ʿ  ¾ ƴ.  ڸ   ñ׳ ڵ鷯
Բ,  ư  ־   ڸ Ұ, 츮 GTK ũ
 widget "ֱ" 䱸Ѵ.  widget  ߿ . 
     ο ư  ̾ ׷  ƴ϶,
    Ѳ  ȴ. 
 
           gtk_widget_show (button);

           gtk_widget_show (window);

  ׸ , 츮 gtk_main() ҷ X κ ̺Ʈ ߻ϱ⸦
ٸ ϰ,  ̺Ʈ ŽǾ  ñ׳  widget ȣ
̴.

           gtk_main ();

  ׸  .  gtk_quit() ȣ   ⼭  ȴ.

           return 0;

  , 츮 GTK ư  콺 ư Ŭϸ widget "clicked"
ñ׳ ߻Ų.  ̷  ̿ϱ  츮 α׷  ñ׳
Ƴ ñ׳ ڵ鷯 ¾ϰ, װ 츮 ÿ  Լ 绡
θ ȴ.  츮  츮  ư  hello()Լ
NULL ڷ ȣǰ, ̾  ñ׳   ڵ鷯 ȣȴ. 
̰ widget ڷ Ͽ gtk_widget_destroy()Լ ȣؼ 
widget ش.  ̰  "destroy"ñ׳ ߻ϰ ؼ Žǰ,
"destroy" شϴ callbackԼ ȣؼ GTK ǰ ϴ ̴.

   ӻ   , н ý ñ׳ ⼭ ϴ
̷ ñ׳ΰ ٸ ̸  ʴ´ٴ  ϱ ٶ.



**********************
*** 3.  ư
**********************

***
*** 3-1. ڷ 
***
  ռ  ָ߰  ʿ   ִ.  gint, gchar 
 int char  typedef̴.  ̰     ڷ
ũ⿡    ϱ  ̴.  64Ʈ ĵ 32Ʈ
̵ "gint32" ÷  32Ʈ  typedefǾ ִ 
   ̴.   typedef  ̴.  ׵  glib/
glib.h ǵǾ ִ(̰ gtk.h ԽŰ ȴ.).   
Լ GtkObject θ  GtkWidget ̿ϴ Ϳ ָ ̴.  GTK
ü  ̰, widget ϳ object̴.

***
*** 3-2. ñ׳ ڵ鷯    ˾ƺ
***
  gtk_signal_connect   ٸ 캸.

       gint gtk_signal_connect (GtkObject *object, gchar *name,
                                GtkSignalFunc func, gpointer func_data);

  gint ϰ?  ̰ callbackԼ Ȯϱ  ǥ.  ռ
ߵ 츮 ñ׳ΰ object  ʿ ŭ  callback 
 ְ, װ͵ ٿ ִ    ̴.   ǥ
츮 Ʈ ̷ callback ϵ ش.

       void gtk_signal_disconnect (GtkObject *object,
                                   gint id);

  ׷, ڵ鷯κ ϰ ϴ widget signal_connectԼκ
ϵȱ widget ǥ Ȥ id Ѱν ñ׳ ڵ鷯  
ִ.

  Object  ñ׳ ڵ鷯 ϴ Ǵٸ Լ ̴̰.

       gtk_signal_handlers_destroy (GtkObject *object);

   ȣ ̴ ״δ.  ̰ ù° ڷ Ѱܹ object, 
   ñ׳ ڵ鷯  ش.

***
*** 3-3.  Hello World α׷
***
  CallbackԼ      ణ  hello world . 
̰  츮    ŷ widget Ұ ̴.

  #include <gtk/gtk.h>
  /* 츮 ణ  callback.   Լ  ʹ ǥ
   * . */
  void callback (GtkWidget *widget, gpointer *data)
  {
      g_print ("Hello again - %s was pressed\n", (char *) data);
  }
  /* ٸ callback */
  void delete_event (GtkWidget *widget, GdkEvent *event, gpointer *data)
  {
      gtk_main_quit ();
  }
  int main (int argc, char *argv[])
  {
      /* GtkWidget widget   Ÿ̴. */ 
      GtkWidget *window;
      GtkWidget *button;
      GtkWidget *box1;
      /* ̰  GTK ÿ .  ࿡ ־ ڵ ̰
       * ؼ ÿ ޵ȴ. */
      gtk_init (&argc, &argv);
      /* ο  . */
      window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
      /*  ϴ Լ,  "Hello Buttons!" ŸƲ ش. */
      gtk_window_set_title (GTK_WINDOW (window), "Hello Buttons!");
      /* ⼭ 츮 GTK   ϴ delete_event  ڵ鷯
       * Ѵ. */
      gtk_signal_connect (GTK_OBJECT (window), "delete_event",
                          GTK_SIGNAL_FUNC (delete_event), NULL);
      /*  border width Ѵ. */
      gtk_container_border_width (GTK_CONTAINER (window), 10);
      /* widget ŷ ڽ .  ̰ ŷ  κп
       * ڼ  ̴.  ڽ  ̴  ƴϸ 
       * widget   μ δ. */
      box1 = gtk_hbox_new(FALSE, 0);
      /* ڽ  ȿ ´. */
      gtk_container_add (GTK_CONTAINER (window), box1);
      /* "Button 1"̶   ο ư . */
      button = gtk_button_new_with_label ("Button 1");
      /*  ư ŬǸ 츮  ư  ͸ ڷ 
       * "callback" Լ ȣѴ. */
      gtk_signal_connect (GTK_OBJECT (button), "clicked",
                         GTK_SIGNAL_FUNC (callback), (gpointer) "button 1");
      /* gtk_container_add ſ, 츮 ̹  ŷǾ ִ 
       * ʴ ڽ ư ŷѴ. */
      gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
      /*    ϶.  ⼭ ư    
       * GTK ˸,  װ    ִ. */
      gtk_widget_show(button);
      /* ι° ư     ģ. */
      button = gtk_button_new_with_label ("Button 2");
      /*  callback ȣѴ.   ڴ "button 2" 
       * ʹ. */
      gtk_signal_connect (GTK_OBJECT (button), "clicked",
                        GTK_SIGNAL_FUNC (callback), (gpointer) "button 2");
      gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
      /* 츮 ư   ϴ    ߿ 
       * ƴϴ.     ͵ Ѳ Ƣ   
       * ֵ   ߿   Ѵ. */
      gtk_widget_show(button);
      gtk_widget_show(box1);
      gtk_widget_show (window);
      /* ⼭  ִ ͵ ٸ ȴ! */
      gtk_main ();
      return 0;
  }

   α׷ 츮 ù°   ũ ڸ ְ .  
츮  α׷ ϱ ؼ Ŵ ̿ϰų ࿡
̴   ٸ  ٴ   ̴.   ° "Quit"
ư  ߰  ͵  ̴.     о gtk_box
_pack_start() ɼ ־  ִ.   ũ⸦ ٲٷ õ
غ,   .

  , gtk_window_new()  Ǵٸ  define GTK_WINDOW_DIALOG
 ִ.  ̰ Ŵ ణ ٸ  ȣۿϸ, Ͻ 
鿡   Ѵ.
******************
*** 4. ŷ Widget
******************

  츮   ϸ鼭, ϳ  ϳ ̻ ư  
̴.  츮 ù° hello world  ϳ widget   츮
װ  ο "pack"ϱ  gtk_container_add Լ .  ׷
츮 ϳ   widget   ,  ׵  ġ
ؾ ұ?  ⼭ ٷ "packing"̶  Ѵ.

***
*** 4-1. ڽ packing 
***
  κ ŷ ռ ó ڽ   ̷. 
̵ 츮 widget  Ȥ   ŷ   ִ, 
ʴ widget ̳ʵ̴.   ڽ ŷwidget , object ȣ
ϴ Ŀ   ʿ  Ȥ ʿ  
ȴ.   ڽ ݴ  Եȴ.  츮 ϴ ȿ 
 ٸ ڽ ƿ Զ ؼ   ִ.

  ο ڽ   츮 gtk_hbox_new(), ׸ ڽ
ؼ gtk_vbox_new() ̿Ѵ.  gtk_box_pack_start() gtk_box_pack_end
() ̷ ̳ ο object ġŰ  Ѵ.  gtk_box_
pack_start()Լ ڽ  Ʒ, ׸ ڽ
ʿ  ŷ ̴.  ׸ gtk_box_pack_end() ̿ ݴ
 ŷѴ.   Լ ̿ν 츮  Ǵ 
widget   ְ, ϴ ȿ   ִ.  츮 κ 
gtk_box_pack_start() ̿ ̴.  Object Ǵٸ ̳ʰų widget
  ִ.  ׸ ,  widget  ư ϰ ִ widget
, 츮  ư  󺧸 ̿ ̴.

  ̷ Լȣν, GTK 츮 widget  ġ ˰Եǰ 
ڵ ũ⸦ Ѵٵ Ǵٸ ŷ ϵ   ְ ȴ.  
 츮 widget  ŷǾ ϴĿ   ɼǵ鵵 ִ. 
츮 ϵ, ̷  widget    ־  
  ش.

***
*** 4-2. ڽ  ڼ ˾ƺ
***
  ̷  , GTK ڽ ŷϴ  ó ȥ
𸥴.   ɼǵ , ׵      
   ̴.  ׷ ᱹ, 츮 ټ  ⺻ Ÿ
 ȴ.

  <IMG ALIGN="center" SRC="packbox1.gif" VSPACE="15" HSPACE="10"
  ALT="Box Packing Example Image" WIDTH="528" HEIGHT="235">

      ư  ִ ϳ ڽ(hbox) Ѵ. 
Լȣ gtk_box_pack  ڽ  ư ŷϴ  
̴.   ư  ڽ   ŷȴ(, gtk_box_pack
_startԼ  ڸ شٴ ).

  ̰ gtk_box_pack_startԼ ̴.

       void gtk_box_pack_start (GtkBox    *box,
                                GtkWidget *child,
                                gint       expand,
                                gint       fill,
                                gint       padding);

  ù° ڴ object ŷ ڽ ι°  object.  Object
⼭  ư  ̰,  츮 ڽȿ ư ŷϰ ȴ.

  gtk_box_pack_start() Ǵ gtk_box_pack_end() expand ڰ TRUE
 , widget   ä ڽ   ̴.  ׸
װ FALSE widget   ΰ ȴ.   expand FALSE θ
츮 widget ¿    ִ.  ׷  ׵ ڽ
 gtk_box_pack_start Ǵ gtk_box_pack_end   ̿ϵ 
ȿ  ȴ.

   fill TRUE  object ڽ  Ѵ.  ׸ FALSE
object ڽ   ʴ´.  ̰ expand ڰ TRUE  ȿ
 ִ.

  ο ڽ   ̷ Լ ִ(ڽ).

  GtkWidget * gtk_hbox_new (gint homogeneous,
                            gint spacing);

  ⼭  homogeneous ڽ   object  ũ⸦ 
Ѵ( ڽ 쿣  ʺ, ڽ 쿣  ). 
̰ õǸ, gtk_box_packԼ expand ڴ  TRUE ȴ.

  ⼭ spacing(ڽ  õ) padding(ҵ ŷǸ
õ)  ϱ?  Spacing object ̿ ܳ ̸
padding  object  ⿡ ܳ ̴.  ̰   Ȯ
 ̴.

  <IMG ALIGN="center" SRC="packbox2.gif" VSPACE="15" HSPACE="10"
  ALT="Box Packing Example Image" WIDTH="509" HEIGHT="213">

    ̹  ִ ڵ尡 ִ.     Ƿ
̰Ϳ    ϴ´.   ؼ   
Ѵ.

***
*** 4-3. ŷ   α׷
***
  #include "gtk/gtk.h"

  void
  delete_event (GtkWidget *widget, GdkEvent *event, gpointer *data)
  {
      gtk_main_quit ();
  }

  /* Button_label ̷ hbox .  츮   
   *  ڵ  Լ Ѱ.
   * 츮 ڽ  ʰ,  ȿ ִ    ̴. */
  GtkWidget *make_box (gint homogeneous, gint spacing,
                       gint expand, gint fill, gint padding)
  {
      GtkWidget *box;
      GtkWidget *button;
      char padstr[80];
      /*  homogenous spacing  hbox . */
      box = gtk_hbox_new (homogeneous, spacing);
      /*  õ ư . */
      button = gtk_button_new_with_label ("gtk_box_pack");
      gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
      gtk_widget_show (button);

      button = gtk_button_new_with_label ("(box,");
      gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
      gtk_widget_show (button);

      button = gtk_button_new_with_label ("button,");
      gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
      gtk_widget_show (button);
      /* expand      ư . */
      if (expand == TRUE)
              button = gtk_button_new_with_label ("TRUE,");
      else
              button = gtk_button_new_with_label ("FALSE,");

      gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
      gtk_widget_show (button);
      /*    ư ,   ǥ̴. */
      button = gtk_button_new_with_label (fill ? "TRUE," : "FALSE,");
      gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
      gtk_widget_show (button);

      sprintf (padstr, "%d);", padding);

      button = gtk_button_new_with_label (padstr);
      gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
      gtk_widget_show (button);

      return box;
  }

  int
  main (int argc, char *argv[])
  {
      GtkWidget *window;
      GtkWidget *button;
      GtkWidget *box1;
      GtkWidget *box2;
      GtkWidget *separator;
      GtkWidget *label;
      GtkWidget *quitbox;
      int which;

      /*  ̷ ϴ    ! */
      gtk_init (&argc, &argv);

      if (argc != 2) {
          fprintf (stderr, "usage: packbox num, where num is 1, 2, 3.\n");
          /* GTK  κ̸, exit status 1̴. */
          gtk_exit (1);
      }

      which = atoi (argv[1]);

      /* 츮  . */
      window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

      /* Main  destroy ñ׳   Ѵ.  ̰  
       *   ſ ߿ ̴. */
      gtk_signal_connect (GTK_OBJECT (window), "delete_event",
                          GTK_SIGNAL_FUNC (delete_event), NULL);
      gtk_container_border_width (GTK_CONTAINER (window), 10);

      /* 츮 ڽ ŷ  ڽ(vbox) .
       * ư ִ ڽ  ڽ   δ.
       * (  ϸ  ̴.) */
      box1 = gtk_vbox_new (FALSE, 0);

      switch (which) {
      case 1:
          /* ο  . */
          label = gtk_label_new ("gtk_hbox_new (FALSE, 0);");

          /* 󺧵  ĽŲ.  ̰Ϳ ؼ widget Ӽ
           * ϱ⿡ ٽ ٷ ̴. */
          gtk_misc_set_alignment (GTK_MISC (label), 0, 0);

          /*  ڽ(vbox box1) ŷѴ.   vbox ŷǴ
           * widget  ٸ ͵  ŷȴ. */
          gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);

          /*  ش. */
          gtk_widget_show (label);

          /* make_box Լ  ڷν ȣѴ. */
          box2 = make_box (FALSE, 0, FALSE, FALSE, 0);
          gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
          gtk_widget_show (box2);

          box2 = make_box (FALSE, 0, TRUE, FALSE, 0);
          gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
          gtk_widget_show (box2);

          box2 = make_box (FALSE, 0, TRUE, TRUE, 0);
          gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
          gtk_widget_show (box2);
          /* ϳ separator .  ̵鿡 ؼ ڿ ڼ
           * ٷ ̸, ϳ  ̴. */
          separator = gtk_hseparator_new ();

          /* separator vbox  ŷѴ.  ̵  widget
           * vbox  ŷǹǷ,    ̴. */
          gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
          gtk_widget_show (separator);

          /* Ǵٸ   װ ش. */
          label = gtk_label_new ("gtk_hbox_new (TRUE, 0);");
          gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
          gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
          gtk_widget_show (label);

          /*  ڴ homogeneous, spacing, expand, fill, padding̴. */
          box2 = make_box (TRUE, 0, TRUE, FALSE, 0);
          gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
          gtk_widget_show (box2);

          box2 = make_box (TRUE, 0, TRUE, TRUE, 0);
          gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
          gtk_widget_show (box2);

          /* Ǵٸ separator */
          separator = gtk_hseparator_new ();
          /* gtk_box_pack_start   3 ڵ
           * expand, fill, padding ̴. */
          gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
          gtk_widget_show (separator);

          break;

      case 2:

          /*   . box1 main() ۺκп 
           *  vbox̴. */
          label = gtk_label_new ("gtk_hbox_new (FALSE, 10);");
          gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
          gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
          gtk_widget_show (label);

          box2 = make_box (FALSE, 10, TRUE, FALSE, 0);
          gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
          gtk_widget_show (box2);

          box2 = make_box (FALSE, 10, TRUE, TRUE, 0);
          gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
          gtk_widget_show (box2);

          separator = gtk_hseparator_new ();
          gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
          gtk_widget_show (separator);

          label = gtk_label_new ("gtk_hbox_new (FALSE, 0);");
          gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
          gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
          gtk_widget_show (label);

          box2 = make_box (FALSE, 0, TRUE, FALSE, 10);
          gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
          gtk_widget_show (box2);

          box2 = make_box (FALSE, 0, TRUE, TRUE, 10);
          gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
          gtk_widget_show (box2);

          separator = gtk_hseparator_new ();
          gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
          gtk_widget_show (separator);
          break;

      case 3:
          /* ̰ gtk_box_pack_end() ̿Ͽ widget  ϴ
           *  ش.  , տó ο ڽ ϳ . */
          box2 = make_box (FALSE, 0, FALSE, FALSE, 0);
          /*  ϳ . */
          label = gtk_label_new ("end");
          /* װ gtk_box_pack_end()ν ŷϹǷ, make_box() 
           * hbox   ȴ.
          gtk_box_pack_end (GTK_BOX (box2), label, FALSE, FALSE, 0);
          /*  δ. */
          gtk_widget_show (label);

          /* box2 box1  ŷѴ. */
          gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
          gtk_widget_show (box2);

          /* bottom   separator. */
          separator = gtk_hseparator_new ();
          /* ̰ 400ȼ ʺ 5ȼ (β) separator
           * Ѵ. ̰ 츮  hbox  400ȼ ʺ̱
           * ̰, "end"  hbox ٸ 󺧵 е(separated)
           * ̴.  ׷ , hbox   widget Ѹŭ
           *   پ ŷ ̴. */
          gtk_widget_set_usize (separator, 400, 5);
          /* main()Լ ۺκп  vbox(box1) separator 
           * ŷѴ. */
          gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
          gtk_widget_show (separator);
      }

      /* Ǵٸ hbox .. 츮 ϴ ŭ 󸶵  ִ! */
      quitbox = gtk_hbox_new (FALSE, 0);

      /* 츮 quit ư̴. */
      button = gtk_button_new_with_label ("Quit");

      /*  ıϱ ñ׳ Ѵ.  ̰  ǵ 츮 
       * ñ׳ ڵ鷯  , "destroy"ñ׳  ش. */
      gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
                                 GTK_SIGNAL_FUNC (gtk_widget_destroy),
                                 GTK_OBJECT (window));
      /* quitbox ư ŷѴ.  gtk_box_pack_start   ڴ
       * expand, fill, padding̴. */
      gtk_box_pack_start (GTK_BOX (quitbox), button, TRUE, FALSE, 0);
      /* vbox(box1)  quitbox ŷѴ. */
      gtk_box_pack_start (GTK_BOX (box1), quitbox, FALSE, FALSE, 0);

      /* 츮  widget ϰ   vbox, main ŷ. */
      gtk_container_add (GTK_CONTAINER (window), box1);

      /* ׸ ִ   ش. */
      gtk_widget_show (button);
      gtk_widget_show (quitbox);

      gtk_widget_show (box1);
      /*   ༭   ѹ Ƣ δ. */
      gtk_widget_show (window);

      /* 翬 츮 gtk_main̴. */
      gtk_main ();

      /* gtk_main_quit() ȣߴٸ  ̰ ´.  gtk_exit()
       * ȣϸ ׷ ʴ. */

      return 0;
  }

***
*** 4-4. ̺ ̿ ŷ
***
  Ǵٸ ŷ - ̺ ̿  .  ̰  Ȳ  
̴.

  ̺ ̿ؼ, 츮 widget ־   ȴ.   widget
 츮 ϴ´ 󸶵    ̴.

       gtk_table_new Լ.

       GtkWidget* gtk_table_new (gint rows,
                                 gint columns,
                                 gint homogeneous);

  ù° ڴ ̺   , ι° 翬  .

   homogeneous ̺ ڽ ũⰡ  Ǿ ϴ 
Ѵ.  ̰ TRUE ̺ ڽ  ̺  ū widget
ũ⿡  ȴ.   FALSE  ڽ  ࿡   widget
̸, ׸     widget ʺ  ȴ.

     0 n ϰ ȴ.  ⼭ n gtk_table_new ȣ
  ڴ.  ׷,  츮 =2 ׸ =2, ̷ ϰ
Ǹ  ̷ ȴ.

        0          1          2
       0+----------+----------+
        |          |          |
       1+----------+----------+
        |          |          |
       2+----------+----------+

  ǥ   ϴ  .  ڽȿ widget 
 Լ ̿Ѵ.

       void gtk_table_attach (GtkTable      *table,
                              GtkWidget     *child,
                              gint           left_attach,
                              gint           right_attach,
                              gint           top_attach,
                              gint           bottom_attach,
                              gint           xoptions,
                              gint           yoptions,
                              gint           xpadding,
                              gint           ypadding);

  ù°  table 츮  ̺̰ ι° child  ̺
 ϴ widget̴. 

  ʰ  attach ڵ widget  ġ ̿ ڽ
 Ѵ.   츮 2x2 ̺  Ʒ ĭ ġ ư
Ѵٸ, ׸  Ҹ ä⸦ Ѵٸ, left_attach=1, right_
attach=2, top_attach=1, bottom_attach=2, ̷ Ǿ Ѵ.

  , 츮 2x2 ̺ ù°  ü ߴٸ, left_attach=0,
right_attach=2, top_attach=0, bottom_attach=1 ̶ ϸ ȴ.

   xoption yoption ŷ ɼ ϱ  ,  ɼ
ֱ ؼ OR ڸ   ִ.

   ɼǵ  .

     GTK_FILL - GTK_FILL Ǹ ̺ ڽ widget Ŭ  widget
     밡   Ȯȴ.

     GTK_SHRINK - ̺ widget    ϵ Ǿ  widget
        Ʒ з Ϻΰ  ʰ ȴ.  
     GTK_SHRINK Ǹ widget ڵ پ ο  ° ȴ.

     GTK_EXPAND - ̰ Ǹ ̺     
     Ȯȴ.

  е ڽ ȿó, ȼ  ѷ  widget  
ش.

  gtk_table_attach()  ɼ  ִ.  ׷ ̷ shortcut
ִ.

       void gtk_table_attach_defaults (GtkTable   *table,
                                       GtkWidget  *widget,
                                       gint        left_attach,
                                       gint        right_attach,
                                       gint        top_attach,
                                       gint        bottom_attach);

  X Y ɼ Ʈ GTK_FILL|GTK_EXPAND, ׸ X Y е 0̴. 
 ڵ  Լ .

   gtk_table_set_row_spacing() gtk_table_set_col_spacing()̶ Լ
ִ.  ̰ ־  Ǵ   spacing Ѵ.

       void gtk_table_set_row_spacing (GtkTable      *table,
                                       gint           row,
                                       gint           spacing);

  ׸

       void       gtk_table_set_col_spacing  (GtkTable      *table,
                                              gint           column,
                                              gint           spacing);

    ؼ space  , ׷ ࿡ ؼ  Ʒ
 ־ٴ  ο .

      ϰ spacing   Լ Ѵ.

       void gtk_table_set_row_spacings (GtkTable *table,
                                        gint      spacing);

       void gtk_table_set_col_spacings (GtkTable  *table,
                                        gint       spacing);

    Լ     ؼ spacing  ʴ´ٴ 
϶.

***
*** 4-5. ̺ ŷ 
***
   κ, gtk ǿ Բ ִ testgtk.c table  ϱ
ٶ.



********************
*** 5. Widget 
********************

  GTK widget  Ϲ   .

  1. gtk_*_new - ο widget   پ Լ.  ̰͵ δ
  ⼭ ڼ  ̴.

  2.  ڵ鷯   ñ׳ սŲ.

  3. Widget Ӽ Ѵ.

  4. gtk_container_add() gtk_box_pack_start()  Լ Ἥ
  widget ̳  ŷѴ.

  5. gtk_widget_show() widget δ.

  gtk_widget_show() 츮 widget Ӽ   GTK ˸,
װ   غ   ̴.  츮 װ ٽ  ʰ ϱ
 gtk_widget_hide ̿  ִ.  Widget   ߿
 ʴ.   Ϸ ,  widget ܳ  ũ
 ϴ ͺٴ,   ߿  ؼ  Ұ
ѹ Ƣ ϴ  ٴ ̴.  gtk_widget_show()Լ ̿ϰ
Ǹ  widget(  ϳ widget̴) ҵ   ü
    ʴ´.

***
*** 5-1. ĳ(ڷ ȯ)
***
  ϸ鼭 ˰, GTK ڷ ȯ ý̴.  ̰ ־
 ĳϴ ɷ ׽Ʈ , ׸ ĳ  , 
ũθ ̿ν ̷.  츮     .
  
        GTK_WIDGET(widget)

        GTK_OBJECT(object)

        GTK_SIGNAL_FUNC(function)

        GTK_CONTAINER(container)

        GTK_WINDOW(window)

        GTK_BOX(box)

  ̰͵  Լ ڵ ĳƮϱ  .  츮 ̵
鿡  ̸, Լ θ  ͸ ׵ ̿  
  ̴.

  Ʒ Ŭ    ֵ,  GtkWidget Ŭ
GtkObject Ļ ̴.  ̰  Լ object 䱸  
 widget ̿   ǹѴ - ܼ GTK_OBJECT() ũθ
̿ؼ.    .

       gtk_signal_connect(GTK_OBJECT(button), "clicked",
                          GTK_SIGNAL_FUNC(callback_function), callback_data);

  ̰ ư ϳ object ĳƮϰ, Լ ͸ callback
ĳƮѴ.

   widget  ̳ʴ.  Ʒ Ŭ   
widget GtkContainer ĻǾ    ̴.  ׵  
widget̶ ̳ʸ 䱸ϴ Լ Ѱֱ  GTK_CONTAINER ũθ
̿  ִ.

  ϰԵ ̷ ũε   ϰ ٷ ʾҴ.  
 GTK ϵ 캸⸦ Ѵ.  , Լ θ 鼭
widget  ۿϴ ϴ  ׸  ʴ.

***
*** 5-2. Widget 
***
     ֵ,  widget ϱ  Ŭ 
Ʈ ִ.

      GtkObject
      +-- GtkData
      |   \-- GtkAdjustment
      |
      \-- GtkWidget
          +-- GtkContainer
          |   +-- GtkBin
          |   |   +-- GtkAlignment
          |   |   +-- GtkFrame
          |   |   |   *-- GtkAspectFrame
          |   |   |
          |   |   +-- GtkItem
          |   |   |   +-- GtkListItem
          |   |   |   +-- GtkMenuItem
          |   |   |   |   +-- GtkCheckMenuItem
          |   |   |   |       *-- GtkRadioMenuItem
          |   |   |   |
          |   |   |   *-- GtkTreeItem
          |   |   |
          |   |   +-- GtkViewport
          |   |   \-- GtkWindow
          |   |       +-- GtkDialog
          |   |       \-- GtkFileSelection
          |   |
          |   +-- GtkBox
          |   |   +-- GtkHBox
          |   |   \-- GtkVBox
          |   |       +-- GtkColorSelection
          |   |       \-- GtkCurve
          |   |
          |   +-- GtkButton
          |   |   +-- GtkOptionMenu
          |   |   \-- GtkToggleButton
          |   |       \-- GtkCheckButton
          |   |           \-- GtkRadioButton
          |   |
          |   +-- GtkList
          |   +-- GtkMenuShell
          |   |   +-- GtkMenu
          |   |   \-- GtkMenuBar
          |   |
          |   +-- GtkNotebook
          |   +-- GtkScrolledWindow
          |   +-- GtkTable
          |   \-- GtkTree
          |
          +-- GtkDrawingArea
          +-- GtkEntry
          +-- GtkMisc
          |   +-- GtkArrow
          |   +-- GtkImage
          |   +-- GtkLabel
          |   \-- GtkPixmap
          |
          +-- GtkPreview
          +-- GtkProgressBar
          +-- GtkRange
          |   +-- GtkScale
          |   |   +-- GtkHScale
          |   |   \-- GtkVScale
          |   |
          |   \-- GtkScrollbar
          |       +-- GtkHScrollbar
          |       \-- GtkVScrollbar
          |
          +-- GtkRuler
          |   +-- GtkHRuler
          |   \-- GtkVRuler
          |
          \-- GtkSeparator
              +-- GtkHSeparator
              \-- GtkVSeparator

***
*** 5-3.   widget
***
   widget õ   ͵̴.    ̺Ʈ 
Ϸ GtkEventBox ̿ؾ  ̴.  "EventBox Widget"  κ
϶.

       GtkAlignment
       GtkArrow
       GtkBin
       GtkBox
       GtkImage
       GtkItem
       GtkLabel
       GtkPaned
       GtkPixmap
       GtkScrolledWindow
       GtkSeparator
       GtkTable
       GtkViewport
       GtkAspectFrame
       GtkFrame
       GtkVPaned
       GtkHPaned
       GtkVBox
       GtkHBox
       GtkVSeparator
       GtkHSeparator

  츮  widget ʷ ϰ ׵   ִ  Լ
  GTK  Ž  ̴.  Ǵٸ Ǹ ҽ GTK
Բ  testgtk.c ̴.  װ gtk/testgtk.c  ã   ̴.

******************
*** 6. ư widget
******************

***
*** 6-1.  ư
***

  츮 ưwidget ؼ  ƿԴ.  װ  ϴ. 
׷ ư µ ΰ  ִ.  츮  ִ ư
  gtk_button_new_with_labe() ̿  ְ,  ư 
 gtk_button_new() ̿  ִ.  ׷  װͿ  ̵
Ƚ ̵ ϴ  п ޷ִ.  ׷ Ϸ ο
ڽ  gtk_box_pack_startν  ڽ ȿ 츮 object ŷϸ,
  gtk_container_addν  ڽ ư  ŷϸ ȴ.

    gtk_button_new ̿Ͽ ׸  ִ ư . 
ڽ  ڵ尡 ٸ ͵κ     α׷
 װ ̿   ̴.

  #include <gtk/gtk.h>

  /* ̹ װͿ ŷ   ִ hbox ϳ .
   * ׸  ڽ Ѵ. */

  GtkWidget *xpm_label_box (GtkWidget *parent, gchar *xpm_filename, gchar *label_text)
  {
      GtkWidget *box1;
      GtkWidget *label;
      GtkWidget *pixmapwid;
      GdkPixmap *pixmap;
      GdkBitmap *mask;
      GtkStyle *style;

      /* xpm   ڽ . */
      box1 = gtk_hbox_new (FALSE, 0);
      gtk_container_border_width (GTK_CONTAINER (box1), 2);

      /* ư Ÿ Ѵ.. background  ϴ  ,
       * ƴ϶    ֱ ٶ. */
      style = gtk_widget_get_style(parent);

      /* xpm Ϸκ Ƚ . */
      pixmap = gdk_pixmap_create_from_xpm (parent->window, &mask,
                                           &style->bg[GTK_STATE_NORMAL],
                                           xpm_filename);
      pixmapwid = gtk_pixmap_new (pixmap, mask);

      /* ư   . */
      label = gtk_label_new (label_text);

      /* ڽ  Ƚʰ  ŷ ִ´. */
      gtk_box_pack_start (GTK_BOX (box1),
                          pixmapwid, FALSE, FALSE, 3);

      gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 3);

      gtk_widget_show(pixmapwid);
      gtk_widget_show(label);

      return (box1);
  }

  /* 츮  callback Լ. */
  void callback (GtkWidget *widget, gpointer *data)
  {
      g_print ("Hello again - %s was pressed\n", (char *) data);
  }

  int main (int argc, char *argv[])
  {
      /* GtkWidget widget   . */
      GtkWidget *window;
      GtkWidget *button;
      GtkWidget *box1;

      gtk_init (&argc, &argv);

      /*  ϳ . */
      window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

      gtk_window_set_title (GTK_WINDOW (window), "Pixmap'd Buttons!");

      /*  鿡  ̷ ִ   ̴. */
      gtk_signal_connect (GTK_OBJECT (window), "destroy",
                          GTK_SIGNAL_FUNC (gtk_exit), NULL);

      /*  border width Ѵ. */
      gtk_container_border_width (GTK_CONTAINER (window), 10);

      /* ο ư ϳ . */
      button = gtk_button_new ();

      /* 뿡  Լ   ϶. */
      gtk_signal_connect (GTK_OBJECT (button), "clicked",
                          GTK_SIGNAL_FUNC (callback), (gpointer) "cool button");

      /* ڽ  Լ. */
      box1 = xpm_label_box(window, "info.xpm", "cool button");

      /* 츮 widget ŷϰ, ش. */
      gtk_widget_show(box1);

      gtk_container_add (GTK_CONTAINER (button), box1);

      gtk_widget_show(button);

      gtk_container_add (GTK_CONTAINER (window), button);

      gtk_widget_show (window);

      /* ⼭ʹ  ִ  ۵   ٸ. */
      gtk_main ();

      return 0;
  }

  xpm_label_box Լ ̳ʰ   ִ  widget Ƚʰ
 ŷϱ Ͽ    ̴.

***
*** 6-2.  ư
***
  ۹ư Ŭ  ϵǴ ΰ    ¿ ־ Ѵٴ
 ٸ  ư ſ ϴ.  װ  · ִٰ,
츮 ٽ Ŭ ָ ٽ Ƣ   ִ.   Ŭϸ װ
ٽ   ̴.

  ۹ư ̴  Լ  üũ ư  ӵǾ
̵, ۹ư üũư ư  ȴ.  ̰͵ ϰ
Ǹ   ٽ  ̴.

  ο ۹ư  ̰ ̿Ѵ.

       GtkWidget* gtk_toggle_button_new (void);

       GtkWidget* gtk_toggle_button_new_with_label (gchar *label);

    ְ, ̰ ư widget ȣ Ȱ ۿѴ. 
ù°   ۹ư, ׸ ι°  ̹ widget ŷǾ
ִ ư .
  ۹ư ư, üũư ¸ ǵ , 츮 Ʒ
  ũθ ̿Ѵ.  ̰  callback  ¸
׽ƮѴ.  ۹ư  ߻ϴ ñ׳ (/üũ/ ư
widget) "toggled" ñ׳̴.   ư ¸ üũϷ  toggled
ñ׳ Ƴ ñ׳ ڵ鷯 ¾ϰ, װ ¸ ϱ 
ũθ ̿Ѵ.   callback ̷  ̴.

       void toggle_button_callback (GtkWidget *widget, gpointer   data)
       {
           if (GTK_TOGGLE_BUTTON (widget)->active)
           {
               /* Ʈ  , ۹ư ´ up̴. */

           } else {

               /* ۹ư down̴. */
           }
       }

       void gtk_toggle_button_set_state (GtkToggleButton *toggle_button,
                                         gint state);

   ȣ ۹ư, װͿ ĻǴ  üũư ¸
ϱ    ִ.  ù° ڷ 츮  ư Ѱְ,
׸ װ   ƴ ϱ  ι° ڸ TRUE Ǵ
FALSE Ѱش.  Ʈ   ,  FALSE̴.

  츮 gtk_toggle_button_set_state()Լ  ư "clicked"ñ׳
߻ؼ ư °  ϰ  .

       void    gtk_toggle_button_toggled (GtkToggleButton *toggle_button);

  ̰  ư ϰ, "toggled"ñ׳ ߻Ų.

***
*** 6-3. üũư
***
  üũư  ִ ۹ư  Ư Լ ӹ޾ ټ
ٸ δ.  ̰ ư   ؽƮ ִٱ⺸ٴ, ؽƮ 
ִ  簢̶   ִ.  ̵  ÿ ۵Ǵ ɼμ
  ̴.

  ̰  ΰ Լ ư .

       GtkWidget* gtk_check_button_new (void);

       GtkWidget* gtk_check_button_new_with_label (gchar *label);

  new_with_labelԼ  ؽƮ   ִ üũư .

  üũư ¸ üũϴ  ۹ư .

***
*** 6-4. ư
***
  ư ׵ ׷ȭǾ ־    ϳ /͵ 
ִٴ   üũư ϴ.  ̰  ɼ Ʈ
ϳ ϵ ϴ 쿡 ̸  ̴.

  ο ư    Լ̴.

       GtkWidget* gtk_radio_button_new (GSList *group);

       GtkWidget* gtk_radio_button_new_with_label (GSList *group,
                                                   gchar *label);

   ȣ鿡 ټ ٸ ڰ ִٴ   .  ̵ 
ӹ  ׷ ʿ Ѵ.  ù° Լ ù° ڷ NULL Ѱ
 Ѵ.  ׸ 츮 ̰ ̿Ͽ ׷ .

       GSList* gtk_radio_button_group (GtkRadioButton *radio_button);

  ׸  ׷ gtk_radio_button_new Ǵ gtk_radio_button_new_with_
label ù° ڷ Ѱش.   ̿ؼ  ư Ʈ
 Ǵ и صδ ͵  ̴.

       void gtk_toggle_button_set_state (GtkToggleButton *toggle_button,
                                         gint state);

  ̰ ۹ư  κп Ǿ, Ȯ   .
**********************
*** 7. پ widget
**********************

***
*** 7-1. (label)
***
   GTK  ̰   ̴.  ̵ õ X
Ƿ ñ׳ ߻ ʴ´.   ñ׳ Ƴų Ŭ 
̶ EventBox widget ̿϶.

  ο    ̰ ̿Ѵ.

       GtkWidget* gtk_label_new (char *str);

  ϳ ڴ 츮 Ÿ ϴ  ڿ̴.

    Ŀ   ؽƮ ٲٷ ̰ ̿Ѵ.

       void gtk_label_set (GtkLabel  *label,
                           char      *str);

  ù° ڴ   ִ (GTK_LABEL()ũην ĳƮ)
̰, ι° ο ڿ̴.

  ο    ʿ 쿡 ڵ ȴ.

   ڿ ã ʹٸ ̰ ̿Ѵ.

       void gtk_label_get (GtkLabel  *label,
                           char     **str);

  ù° ڴ  ̰, ι° ǻ츮 ϴ ڿ̴.

***
*** 7-2. ǳ (tooltip widget)
***
  콺͸  ư̳ ٸ widget    ӹ ϸ 
ؽƮ ڿ Ƣ 찡 ִ.  ̰  ̸, ׷
⼭  ϰڴ.   ڵ带 ʹٸ GDK Բ Ǵ
testgtk.c α׷ ϶.

     widget  tooltip  ʴ´.

  츮 ó ̿ Լ ο tooltip  ̴.  ̰ ־
Լ ѹ ָ ȴ.   Լ ϴ GtkTooltip  tooltip
 µ ̿  ִ.

  GtkTooltips *gtk_tooltips_new (void);

  ϴ ο tooltip װ  widget , װ ϱ
  Լ ̿϶.

       void gtk_tooltips_set_tips   (GtkTooltips *tooltips,
                                     GtkWidget   *widget,
                                     gchar       *tips_text);

  ù° ڴ 츮  tooltip̰,   tooltip ϰ 
widget̴.  ׸   ؽƮ 츮 tooltip ϰ ϴ
̴.

  ̰ ª .

       GtkTooltips *tooltips;
       GtkWidget *button;
       tooltips = gtk_tooltips_new ();
       button = gtk_button_new_with_label ("button 1");
       gtk_tooltips_set_tips (tooltips, button, "This is button 1");

  Tooltip ̴ ٸ Լ鵵 ִ.  ⼭ ׵  Ұϰڴ.

       void gtk_tooltips_destroy    (GtkTooltips *tooltips);

   tooltip Ѵ.

       void gtk_tooltips_enable     (GtkTooltips *tooltips);

  Disable  tooltip enableѴ.

       void gtk_tooltips_disable    (GtkTooltips *tooltips);

  Enable  tooltip disableѴ.

       void gtk_tooltips_set_delay  (GtkTooltips *tooltips,
                                     gint         delay);

  Tooltip Ƣ  󸶳 콺͸ widget ӹ
ؾϴ , millisecond Ѵ.  Ʈ 1000millisecond, 
1ʴ.

       void      gtk_tooltips_set_tips (GtkTooltips *tooltips,
                                        GtkWidget   *widget,
                                        gchar    *tips_text);

  ̹  tooltip ؽƮ  ٲ۴.

       void gtk_tooltips_set_colors (GtkTooltips *tooltips,
                                     GdkColor    *background,
                                     GdkColor    *foreground);

  Tooltip ǥ  ٲ۴.    ϴ ؼ
𸣰ڴ.

  Tooltip õ Լ ̰ δ.  ̻  ͵ .  :)

***
*** 7-3. ื(progress bar)
***
  ื ۾ Ȳ Ÿ  δ.   ڵ带  ˰,
̰  ϴ.  ׷  ο ื븦 ִ Լ 
  .

       GtkWidget *gtk_progress_bar_new (void);

   ื밡  츮 װ ̿  ִ.

       void gtk_progress_bar_update (GtkProgressBar *pbar, gfloat percentage);

  ù° ڴ ۽ų ื밡 ǰ, ι° ڴ 'Ϸ' з
Ÿ.  ̰  ڷ 0 1, 0 100ۼƮ ǹϴ
̴.

  ื  ŸӾƿ̳ Ǵ Ƽ½ŷϴ  Ű ϴ
Լ Բ δ.  ('ŸӾƿ, I/O idleԼ'  κ ϶.)
 쿡 gtk_progress_bar_updateԼ   ̰ ȴ.

  ̰ ŸӾƿ ̿ ƮǴ ื븦  .  ̰ 
ื븦 ,  ʱȭϴ   ̴.

  #include <gtk/gtk.h>

  static int ptimer = 0;
  int pstat = TRUE;

  /*  Լ ื븦 Ű ƮѴ.   pstat FALSE Ǹ
   * ื븦 ,  ʱȭѴ. */
  gint progress (gpointer data)
  {
      gfloat pvalue;

      /* ื 簪 ˾Ƴ. */
      pvalue = GTK_PROGRESS_BAR (data)->percentage;

      if ((pvalue >= 1.0) || (pstat == FALSE)) {
          pvalue = 0.0;
          pstat = TRUE;
      }
      pvalue += 0.01;

      gtk_progress_bar_update (GTK_PROGRESS_BAR (data), pvalue);

      return TRUE;
  }

  /*  Լ ื   ñ׳ . */
  void progress_r (void)
  {
      pstat = FALSE;
  }

  void destroy (GtkWidget *widget, gpointer *data)
  {
      gtk_main_quit ();
  }

  int main (int argc, char *argv[])
  {
      GtkWidget *window;
      GtkWidget *button;
      GtkWidget *label;
      GtkWidget *table;
      GtkWidget *pbar;

      gtk_init (&argc, &argv);

      window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

      gtk_signal_connect (GTK_OBJECT (window), "delete_event",
                          GTK_SIGNAL_FUNC (destroy), NULL);

      gtk_container_border_width (GTK_CONTAINER (window), 10);

      table = gtk_table_new(3,2,TRUE);
      gtk_container_add (GTK_CONTAINER (window), table);

      label = gtk_label_new ("Progress Bar Example");
      gtk_table_attach_defaults(GTK_TABLE(table), label, 0,2,0,1);
      gtk_widget_show(label);

      /* ο ื븦 , װ ̺ ŷϿ ش. */
      pbar = gtk_progress_bar_new ();
      gtk_table_attach_defaults(GTK_TABLE(table), pbar, 0,2,1,2);
      gtk_widget_show (pbar);

      /* ื ڵ Ʈ  timeout Ѵ. */
      ptimer = gtk_timeout_add (100, progress, pbar);

      /*  ư ื븦 ϴ ñ׳  ̴. */
      button = gtk_button_new_with_label ("Reset");
      gtk_signal_connect (GTK_OBJECT (button), "clicked",
                          GTK_SIGNAL_FUNC (progress_r), NULL);
      gtk_table_attach_defaults(GTK_TABLE(table), button, 0,1,2,3);
      gtk_widget_show(button);

      button = gtk_button_new_with_label ("Cancel");
      gtk_signal_connect (GTK_OBJECT (button), "clicked",
                          GTK_SIGNAL_FUNC (destroy), NULL);

      gtk_table_attach_defaults(GTK_TABLE(table), button, 1,2,2,3);
      gtk_widget_show (button);

      gtk_widget_show(table);
      gtk_widget_show(window);

      gtk_main ();

      return 0;
  }

    α׷ ื Ϲ ۰ õ   
ִ.  ׵    ˾ƺ .

       pbar = gtk_progress_bar_new ();

   ڵ pbar ̸ ο ื븦  ִ.

       ptimer = gtk_timeout_add (100, progress, pbar);

   ڵ忡  ð ŸӾƿ ̿ϴµ, ื ̿뿡 
ŸӾƿ  Ǵ  ƴϴ.

       pvalue = GTK_PROGRESS_BAR (data)->percentage;

  ⼭ pvalue  percentage bar    ְ ִ.

       gtk_progress_bar_update (GTK_PROGRESS_BAR (data), pvalue);

  , pvalue   ื븦 ƮѴ.

  ׸ ื뿡    ̰ δ, ܺ⸦~!

***
*** 7-4. ȭ
***
  ȭ widget ſ  ε,  ̰  ̸ ŷǾ
ִ ϳ  ̴.  Dialog  ü ̴̰.

       struct GtkDialog
       {
             GtkWindow window;

             GtkWidget *vbox;
             GtkWidget *action_area;
       };

  ٽ ̰ ܼ  , ׸ vbox   ŷϰ,
 separator, ׸  "action_area"  hbox ŷѴ. 

  ȭwidget ڿ ˾ ޽ ̰ų ϴ   
 ִ.  ̰  ⺻ , ȭڽ  Լ ̰ ϳ
̴.

       GtkWidget* gtk_dialog_new (void);

  ׷ ο ȭڽ  ̷ Ѵ.

       GtkWidget window;
       window = gtk_dialog_new ();

  ̰ ȭڸ  ̰,  ̿ ڿ ޷ִ. 
츮 ̷  ؼ action_area ȿ ư ŷ  ִ.

       button = ...
       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button,
                           TRUE, TRUE, 0);
       gtk_widget_show (button);

  ׸ 츮 ŷ Ͽ vbox    ߰  ִ.  Ʒ
 غ.

       label = gtk_label_new ("Dialogs are groovy");
       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), label, TRUE,
                           TRUE, 0);
       gtk_widget_show (label);

  ȭڸ ̿ ó, 츮 action_area Cancel Ok 
ư, ׸ vbox ڿ ų ޽ ų ϴ
     ̴.  ׸   ÿ 
۵ϵ ư   ٸ ñ׳    ִ.

***
*** 7-5. Ƚ
***
  Ƚ ׸ ϰ ִ ڷ ̴.  ̷ ׸  
 ִµ,    ̿ X ũ ̳ Ŀ ̴. 
Ʈ̶ 2 Ƚ̴.

  GTK Ƚ ̿ϱ , 츮  GDK  Լν
GdkPixmap ü  Ѵ.  Ƚ ޸ ڷ Ȥ Ϸκ
о ڷκ   ִ.  츮 Ƚ   
Լ ݺ 캼 ̴.

       GdkPixmap *gdk_bitmap_create_from_data( GdkWindow *window,
                                               gchar     *data,
                                               gint      width,
                                               gint      height );

   Լ ޸ ͷ 2 single-plane Ƚ   ,
  Ʈ ȼ on/off θ Ÿ.  width/height ȼ
.  Ƚ ҽ װ  ũ 濡 ǹ̰ Ƿ,
GdkWindow  ʹ   Ű ȴ.

       GdkPixmap* gdk_pixmap_create_from_data( GdkWindow  *window,
                                               gchar      *data,
                                               gint        width,
                                               gint        height,
                                               gint        depth,
                                               GdkColor   *fg,
                                               GdkColor   *bg );

  ̰ ־ Ʈ Ÿκ  depth( )  Ƚ
  δ.  fg bg ̿ foreground  background ̴.

  GdkPixmap* gdk_pixmap_create_from_xpm( GdkWindow  *window,
                                         GdkBitmap **mask,
                                         GdkColor   *transparent_color,
                                         const gchar *filename );

  XPM  Xýۿ о  ִ ϳ Ƚ ´.  ̰
θ ̰  ̹     ִ  ƿƼ
ִ.  ̸ Ҹ     ̹ ϰ ־
ϰ, װ Ƚ ü  εȴ.   Ƚ  Ʈ 
ؾ ϴ mask Ѵ.    Ʈ transparent_color
    ȴ.  ̰ ̿ϴ  Ʒ ڵ
̴.

       GdkPixmap* gdk_pixmap_create_from_xpm_d (GdkWindow  *window,
                                                GdkBitmap **mask,
                                                GdkColor   *transparent_color,
                                                gchar     **data);

   ̹ XPM  ͷμ α׷ ο ԵǾ  
ִ.   Ƚ Ϸκ ͸ о̴  ̷ ͸
̿ .     ̷ ̴.

       /* XPM */
       static const char * xpm_data[] = {
       "16 16 3 1",
       "       c None",
       ".      c #000000000000",
       "X      c #FFFFFFFFFFFF",
       "                ",
       "   ......       ",
       "   .XXX.X.      ",
       "   .XXX.XX.     ",
       "   .XXX.XXX.    ",
       "   .XXX.....    ",
       "   .XXXXXXX.    ",
       "   .XXXXXXX.    ",
       "   .XXXXXXX.    ",
       "   .XXXXXXX.    ",
       "   .XXXXXXX.    ",
       "   .XXXXXXX.    ",
       "   .XXXXXXX.    ",
       "   .........    ",
       "                ",
       "                "};

       void gdk_pixmap_destroy( GdkPixmap  *pixmap );

  츮  Ƚ ̿߰  а ٽ ̿ ʿ䰡  , 
ҽ gdk_pixmap_destory ޸𸮿 ݳִ ͵  ̴. 
Ƚ ߿ ҽ ֵǾ Ѵ.

  츮 ϴ Ƚ , װ GTK widgetó   ִ.  츮
GDK Ƚ ԽŰ ؼ Ƚwidget ߸ Ѵ.  ̰ ̿
ؼ ׷   ִ.

       GtkWidget* gtk_pixmap_new( GdkPixmap  *pixmap,
                                  GdkBitmap  *mask );

  Ǵٸ Ƚwidget Լ  .

       guint gtk_pixmap_get_type( void );
       void  gtk_pixmap_set( GtkPixmap  *pixmap,
                             GdkPixmap  *val,
                             GdkBitmap  *mask);
       void  gtk_pixmap_get( GtkPixmap  *pixmap,
                             GdkPixmap **val,
                             GdkBitmap **mask);

  gtk_pixmap_set widget  ٷ ִ Ƚ ȭŰ 
̿Ѵ.   val GDK ̿  Ƚ̴.

    ư ȿ Ƚ ִ ̴.

  #include <gtk/gtk.h>

  /* Open-File   XPM  */
  static const char * xpm_data[] = {
  "16 16 3 1",
  "       c None",
  ".      c #000000000000",
  "X      c #FFFFFFFFFFFF",
  "                ",
  "   ......       ",
  "   .XXX.X.      ",
  "   .XXX.XX.     ",
  "   .XXX.XXX.    ",
  "   .XXX.....    ",
  "   .XXXXXXX.    ",
  "   .XXXXXXX.    ",
  "   .XXXXXXX.    ",
  "   .XXXXXXX.    ",
  "   .XXXXXXX.    ",
  "   .XXXXXXX.    ",
  "   .XXXXXXX.    ",
  "   .........    ",
  "                ",
  "                "};

  /* ̰ ȣǸ(delete_event ñ׳ )  ȴ. */
  void close_application( GtkWidget *widget, GdkEvent *event, gpointer *data )
  {
      gtk_main_quit();
  }

  /* ư ŬǸ ȣǾ ޽ ƮѴ. */
  void button_clicked( GtkWidget *widget, gpointer *data )
  {
      printf( "button clicked\n" );
  }

  int main( int argc, char *argv[] )
  {
      /* GtkWidget widget   Ÿ̴. */ 
      GtkWidget *window, *pixmapwid, *button;
      GdkPixmap *pixmap;
      GdkBitmap *mask;
      GtkStyle *style;

      /* main  ,    delete_event ñ׳
       *  д. */
      gtk_init( &argc, &argv );
      window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
      gtk_signal_connect( GTK_OBJECT (window), "delete_event",
                          GTK_SIGNAL_FUNC (close_application), NULL );
      gtk_container_border_width( GTK_CONTAINER (window), 10 );
      gtk_widget_show( window );

      /* gdkԼ Ƚ   ̴. */
      style = gtk_widget_get_style( window );
      pixmap = gdk_pixmap_create_from_xpm_d( window->window,  &mask,
                                             &style->bg[GTK_STATE_NORMAL],
                                             (gchar **)xpm_data );

      /* Ƚ ٷ pixmap widget̴. */
      pixmapwid = gtk_pixmap_new( pixmap, mask );
      gtk_widget_show( pixmapwid );

      /* pixmap widget  Ǵ ư̴. */
      button = gtk_button_new();
      gtk_container_add( GTK_CONTAINER(button), pixmapwid );
      gtk_container_add( GTK_CONTAINER(window), button );
      gtk_widget_show( button );

      gtk_signal_connect( GTK_OBJECT(button), "clicked",
                          GTK_SIGNAL_FUNC(button_clicked), NULL );

      /*  δ. */
      gtk_main ();

      return 0;
  }

   丮 icon0.xpm ̶ XPM  ҷ ؼ, 츮
Ƚ  Ѵ.

           /* Ϸκ Ƚ ҷ´. */
           pixmap = gdk_pixmap_create_from_xpm( window->window, &mask,
                                                &style->bg[GTK_STATE_NORMAL],
                                                "./icon0.xpm" );
           pixmapwid = gtk_pixmap_new( pixmap, mask );
           gtk_widget_show( pixmapwid );
           gtk_container_add( GTK_CONTAINER(window), pixmapwid );

  Ƚ ̿   ϳ ̹    簢
̶ ̴.  츮 ũ ÿ   ڿ 
 ϰʹ.     ̽, 츮  ư
ձ   ϰ ;Ѵ.  ̷ ϱ ؼ Ư  
 ̿Ѵ.

  Ư      ̷ ȼ   Ѵ.
 ̹    ִٸ, ̷ 츮 츮  ѷ
 ʴ  簢  ׸ ʴ´.  ̹  ̷
 ؼ ũ鿡  ̹ ش.

  #include <gtk/gtk.h>

  /* XPM */
  static char * WheelbarrowFull_xpm[] = {
  "48 48 64 1",
  "       c None",
  ".      c #DF7DCF3CC71B",
  "X      c #965875D669A6",
  "o      c #71C671C671C6",
  "O      c #A699A289A699",
  "+      c #965892489658",
  "@      c #8E38410330C2",
  "#      c #D75C7DF769A6",
  "$      c #F7DECF3CC71B",
  "%      c #96588A288E38",
  "&      c #A69992489E79",
  "*      c #8E3886178E38",
  "=      c #104008200820",
  "-      c #596510401040",
  ";      c #C71B30C230C2",
  ":      c #C71B9A699658",
  ">      c #618561856185",
  ",      c #20811C712081",
  "<      c #104000000000",
  "1      c #861720812081",
  "2      c #DF7D4D344103",
  "3      c #79E769A671C6",
  "4      c #861782078617",
  "5      c #41033CF34103",
  "6      c #000000000000",
  "7      c #49241C711040",
  "8      c #492445144924",
  "9      c #082008200820",
  "0      c #69A618611861",
  "q      c #B6DA71C65144",
  "w      c #410330C238E3",
  "e      c #CF3CBAEAB6DA",
  "r      c #71C6451430C2",
  "t      c #EFBEDB6CD75C",
  "y      c #28A208200820",
  "u      c #186110401040",
  "i      c #596528A21861",
  "p      c #71C661855965",
  "a      c #A69996589658",
  "s      c #30C228A230C2",
  "d      c #BEFBA289AEBA",
  "f      c #596545145144",
  "g      c #30C230C230C2",
  "h      c #8E3882078617",
  "j      c #208118612081",
  "k      c #38E30C300820",
  "l      c #30C2208128A2",
  "z      c #38E328A238E3",
  "x      c #514438E34924",
  "c      c #618555555965",
  "v      c #30C2208130C2",
  "b      c #38E328A230C2",
  "n      c #28A228A228A2",
  "m      c #41032CB228A2",
  "M      c #104010401040",
  "N      c #492438E34103",
  "B      c #28A2208128A2",
  "V      c #A699596538E3",
  "C      c #30C21C711040",
  "Z      c #30C218611040",
  "A      c #965865955965",
  "S      c #618534D32081",
  "D      c #38E31C711040",
  "F      c #082000000820",
  "                                                ",
  "          .XoO                                  ",
  "         +@#$%o&                                ",
  "         *=-;#::o+                              ",
  "           >,<12#:34                            ",
  "             45671#:X3                          ",
  "               +89<02qwo                        ",
  "e*                >,67;ro                       ",
  "ty>                 459@>+&&                    ",
  "$2u+                  ><ipas8*                  ",
  "%$;=*                *3:.Xa.dfg>                ",
  "Oh$;ya             *3d.a8j,Xe.d3g8+             ",
  " Oh$;ka          *3d$a8lz,,xxc:.e3g54           ",
  "  Oh$;kO       *pd$%svbzz,sxxxxfX..&wn>         ",
  "   Oh$@mO    *3dthwlsslszjzxxxxxxx3:td8M4       ",
  "    Oh$@g& *3d$XNlvvvlllm,mNwxxxxxxxfa.:,B*     ",
  "     Oh$@,Od.czlllllzlmmqV@V#V@fxxxxxxxf:%j5&   ",
  "      Oh$1hd5lllslllCCZrV#r#:#2AxxxxxxxxxcdwM*  ",
  "       OXq6c.%8vvvllZZiqqApA:mq:Xxcpcxxxxxfdc9* ",
  "        2r<6gde3bllZZrVi7S@SV77A::qApxxxxxxfdcM ",
  "        :,q-6MN.dfmZZrrSS:#riirDSAX@Af5xxxxxfevo",
  "         +A26jguXtAZZZC7iDiCCrVVii7Cmmmxxxxxx%3g",
  "          *#16jszN..3DZZZZrCVSA2rZrV7Dmmwxxxx&en",
  "           p2yFvzssXe:fCZZCiiD7iiZDiDSSZwwxx8e*>",
  "           OA1<jzxwwc:$d%NDZZZZCCCZCCZZCmxxfd.B ",
  "            3206Bwxxszx%et.eaAp77m77mmmf3&eeeg* ",
  "             @26MvzxNzvlbwfpdettttttttttt.c,n&  ",
  "             *;16=lsNwwNwgsvslbwwvccc3pcfu<o    ",
  "              p;<69BvwwsszslllbBlllllllu<5+     ",
  "              OS0y6FBlvvvzvzss,u=Blllj=54       ",
  "               c1-699Blvlllllu7k96MMMg4         ",
  "               *10y8n6FjvllllB<166668           ",
  "                S-kg+>666<M<996-y6n<8*          ",
  "                p71=4 m69996kD8Z-66698&&        ",
  "                &i0ycm6n4 ogk17,0<6666g         ",
  "                 N-k-<>     >=01-kuu666>        ",
  "                 ,6ky&      &46-10ul,66,        ",
  "                 Ou0<>       o66y<ulw<66&       ",
  "                  *kk5       >66By7=xu664       ",
  "                   <<M4      466lj<Mxu66o       ",
  "                   *>>       +66uv,zN666*       ",
  "                              566,xxj669        ",
  "                              4666FF666>        ",
  "                               >966666M         ",
  "                                oM6668+         ",
  "                                  *4            ",
  "                                                ",
  "                                                "};

  /* ̰ ȣǸ(delete_event ñ׳ )  ȴ. */
  void close_application( GtkWidget *widget, GdkEvent *event, gpointer *data )
  {
      gtk_main_quit();
  }

  int main (int argc, char *argv[])
  {
      GtkWidget *window, *pixmap, *fixed;
      GdkPixmap *gdk_pixmap;
      GdkBitmap *mask;
      GtkStyle *style;
      GdkGC *gc;

      /* main ,    delete_event ñ׳ ű⿡
       *  д.  main  츮 popup ǵ  
       * ŸƲٸ   ̴. */
      gtk_init (&argc, &argv);
      window = gtk_window_new( GTK_WINDOW_POPUP );
      gtk_signal_connect (GTK_OBJECT (window), "delete_event",
                          GTK_SIGNAL_FUNC (close_application), NULL);
      gtk_widget_show (window);

      /* Ƚʰ pixmap widget  ̴. */
      style = gtk_widget_get_default_style();
      gc = style->black_gc;
      gdk_pixmap = gdk_pixmap_create_from_xpm_d( window->window, &mask,
                                               &style->bg[GTK_STATE_NORMAL],
                                               WheelbarrowFull_xpm );
      pixmap = gtk_pixmap_new( gdk_pixmap, mask );
      gtk_widget_show( pixmap );

      /* Ƚ ̱ , 츮 Ƚ Ƶ fixed widget
       * ̿Ѵ. */
      fixed = gtk_fixed_new();
      gtk_widget_set_usize( fixed, 200, 200 );
      gtk_fixed_put( GTK_FIXED(fixed), pixmap, 0, 0 );
      gtk_container_add( GTK_CONTAINER(window), fixed );
      gtk_widget_show( fixed );

      /* ̰ ̹ ڽ  ٸ   Ѵ. */
      gtk_widget_shape_combine_mask( window, mask, 0, 0 );

      /*  δ. */
      gtk_widget_set_uposition( window, 20, 400 );
      gtk_widget_show( window );
      gtk_main ();

      return 0;
  }

   ̹  ϰ  , 츮 ư  ̺Ʈ
ñ׳    ϵ   ִ.   ̴  
ڵ 콺ư     ش.

       gtk_widget_set_events( window,
                              gtk_widget_get_events( window ) |
                              GDK_BUTTON_PRESS_MASK );

       gtk_signal_connect( GTK_OBJECT(window), "button_press_event",
                           GTK_SIGNAL_FUNC(close_application), NULL );
**********************
*** 8. ̳ widget
**********************

***
*** 8-1. Ʈ
***
  Ʈwidget  Ǹ ٸ   ִ ''
̴.  ̷ widget ֱ GUI α׷ֿ  ϹȭǾ, ȭ鿡
 Ǿ    ̴   ̴.

  츮 ˾ƾ  ù° Լ Ѵ ο Ʈwidget 
̴.

       GtkWidget* gtk_notebook_new (void);

  ϴ Ʈ ,  Ʈwidget ٷ 12 Լ ִ. 
׵ ϳϳ 캸.

  츮     ǥ ġ   ˾ƺ ̴. 
̷  ǥ Ȥ 'tab',      ִ.   top,
bottom, left, Ǵ right̴.

       void gtk_notebook_set_tab_pos (GtkNotebook *notebook, GtkPositionType pos);

  GtkPositionType   ϳ̸,  ̴.

	GTK_POS_LEFT
	GTK_POS_RIGHT
	GTK_POS_TOP
	GTK_POS_BOTTOM

  GTK_POS_TOP Ʈ.

   ƮϿ   ִ ˾ƺ.  ̷ ϴ Ϳ
  ִ.  켱   ΰ  캸.

       void gtk_notebook_append_page (GtkNotebook *notebook, GtkWidget *child, GtkWidget *tab_label);

       void gtk_notebook_prepend_page (GtkNotebook *notebook, GtkWidget *child, GtkWidget *tab_label);

  ̷ Լ Ʈ ڿ ԵǴ(append), Ǵ Ʈ տ
ԵǴ(prepend) ؼ  ش.  *child Ʈ 
ġϴ widget̰, *tab_label    ̴.

   ִ  Լ  ΰ  Ư  
ִ.   ̰ 츮 Ʈ  ġ   
ϵ ش.

       void gtk_notebook_insert_page (GtkNotebook *notebook, GtkWidget *child, GtkWidget *tab_label, gint position);

  position̶  ϳ ڸ Ѵٴ ͸ , gtk_notebook_
append_page ׸ gtk_notebook_prepend_page ڰ .  position
ڴ    ġ Ե   ش.

     ϴ ˾Ƿ, ƮϿ  
ϴ ˾ƺ .

       void gtk_notebook_remove_page (GtkNotebook *notebook, gint page_num);

   Լ page_num ڷ ־  ؼ, װ *notebook̶
widget ش.

    ˾Ƴ ؼ  Լ ̿Ѵ.

       gint gtk_notebook_current_page (GtkNotebook *notebook);

   Ұϴ  Լ Ʈ  յڷ ̵   
Լ̴.  츮 ٷ Ʈ widget ٷ ؼ  Լ
ֱ⸸ ϸ ȴ.   ,   gtk_notebook_next_page
ȣǸ Ʈ ù°  ư ٴ ̴.  
ù°  gtk_notebook_prev_page ȣǸ Ʈ  
 .

       void gtk_notebook_next_page (GtkNoteBook *notebook);
       void gtk_notebook_prev_page (GtkNoteBook *notebook);

  ̹ Լ 'active',  Ȱȭ  Ѵ.   ó
5  Ʈ   Լ ̿ϸ  ̴.  ̰ 
, Ʈ Ʈ ù°   ȴ.

       void gtk_notebook_set_page (GtkNotebook *notebook, gint page_num);

    Լ  Ʈ  tab 踦 ϰų ش.

       void gtk_notebook_set_show_tabs (GtkNotebook *notebook, gint show_tabs);
       void gtk_notebook_set_show_border (GtkNotebook *notebook, gint show_border);

   show_tabs show_border TRUE/FALSE  ϳ   ִ.

    ϳ .  ̰ GTK  Բ ִ testgtk.c α׷
, 13 Լ  ش.    α׷ Ʈϰ  
ư  ִ  .  Ʈ  ٸ ,  append/
insert/prepend   11   ִ.  ư tab
ġ ȯų  ְ, tab border ְų  ,  
   ִ.  ׸ յ   ٲָ, α׷
  ִ.

  #include <gtk/gtk.h>

  /*  Լ tab ġ ̼ Ų. */
  void rotate_book (GtkButton *button, GtkNotebook *notebook)
  {
      gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos +1) %4);
  }

  /* page tab border ϰų Ѵ. */
  void tabsborder_book (GtkButton *button, GtkNotebook *notebook)
  {
      gint tval = FALSE;
      gint bval = FALSE;
      if (notebook->show_tabs == 0)
              tval = TRUE;
      if (notebook->show_border == 0)
              bval = TRUE;

      gtk_notebook_set_show_tabs (notebook, tval);
      gtk_notebook_set_show_border (notebook, bval);
  }

  /* ƮϿ   Ѵ. */
  void remove_book (GtkButton *button, GtkNotebook *notebook)
  {
      gint page;

      page = gtk_notebook_current_page(notebook);
      gtk_notebook_remove_page (notebook, page);
      /* Need to refresh the widget --
       This forces the widget to redraw itself. */
      gtk_widget_draw(GTK_WIDGET(notebook), NULL);
  }

  void delete (GtkWidget *widget, GdkEvent *event, gpointer *data)
  {
      gtk_main_quit ();
  }

  int main (int argc, char *argv[])
  {
      GtkWidget *window;
      GtkWidget *button;
      GtkWidget *table;
      GtkWidget *notebook;
      GtkWidget *frame;
      GtkWidget *label;
      GtkWidget *checkbutton;
      int i;
      char bufferf[32];
      char bufferl[32];

      gtk_init (&argc, &argv);

      window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

      gtk_signal_connect (GTK_OBJECT (window), "delete_event",
                          GTK_SIGNAL_FUNC (delete), NULL);

      gtk_container_border_width (GTK_CONTAINER (window), 10);

      table = gtk_table_new(2,6,TRUE);
      gtk_container_add (GTK_CONTAINER (window), table);

      /*  Ʈ , tab ġ Ѵ. */
      notebook = gtk_notebook_new ();
      gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP);
      gtk_table_attach_defaults(GTK_TABLE(table), notebook, 0,6,0,1);
      gtk_widget_show(notebook);

      /* ƮϿ   ߰Ѵ. */
      for (i=0; i < 5; i++) {
          sprintf(bufferf, "Append Frame %d", i+1);
          sprintf(bufferl, "Page %d", i+1);

          frame = gtk_frame_new (bufferf);
          gtk_container_border_width (GTK_CONTAINER (frame), 10);
          gtk_widget_set_usize (frame, 100, 75);
          gtk_widget_show (frame);

          label = gtk_label_new (bufferf);
          gtk_container_add (GTK_CONTAINER (frame), label);
          gtk_widget_show (label);

          label = gtk_label_new (bufferl);
          gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, label);
      }

      /*     Ѵ. */
      checkbutton = gtk_check_button_new_with_label ("Check me please!");
      gtk_widget_set_usize(checkbutton, 100, 75);
      gtk_widget_show (checkbutton);

      label = gtk_label_new ("Add spot");
      gtk_container_add (GTK_CONTAINER (checkbutton), label);
      gtk_widget_show (label);
      label = gtk_label_new ("Add page");
      gtk_notebook_insert_page (GTK_NOTEBOOK (notebook), checkbutton, label, 2);

      /*  Ʈ ο  prependѴ. */
      for (i=0; i < 5; i++) {
          sprintf(bufferf, "Prepend Frame %d", i+1);
          sprintf(bufferl, "PPage %d", i+1);

          frame = gtk_frame_new (bufferf);
          gtk_container_border_width (GTK_CONTAINER (frame), 10);
          gtk_widget_set_usize (frame, 100, 75);
          gtk_widget_show (frame);

          label = gtk_label_new (bufferf);
          gtk_container_add (GTK_CONTAINER (frame), label);
          gtk_widget_show (label);

          label = gtk_label_new (bufferl);
          gtk_notebook_prepend_page (GTK_NOTEBOOK(notebook), frame, label);
      }

      /*   Ѵ(⼭ page 4). */
      gtk_notebook_set_page (GTK_NOTEBOOK(notebook), 3);

      /* ư ٹ(bunch) ϳ . */
      button = gtk_button_new_with_label ("close");
      gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
                                 GTK_SIGNAL_FUNC (destroy), NULL);
      gtk_table_attach_defaults(GTK_TABLE(table), button, 0,1,1,2);
      gtk_widget_show(button);

      button = gtk_button_new_with_label ("next page");
      gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
                                 (GtkSignalFunc) gtk_notebook_next_page,
                                 GTK_OBJECT (notebook));
      gtk_table_attach_defaults(GTK_TABLE(table), button, 1,2,1,2);
      gtk_widget_show(button);

      button = gtk_button_new_with_label ("prev page");
      gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
                                 (GtkSignalFunc) gtk_notebook_prev_page,
                                 GTK_OBJECT (notebook));
      gtk_table_attach_defaults(GTK_TABLE(table), button, 2,3,1,2);
      gtk_widget_show(button);

      button = gtk_button_new_with_label ("tab position");
      gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
                                 (GtkSignalFunc) rotate_book, GTK_OBJECT(notebook));
      gtk_table_attach_defaults(GTK_TABLE(table), button, 3,4,1,2);
      gtk_widget_show(button);

      button = gtk_button_new_with_label ("tabs/border on/off");
      gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
                                 (GtkSignalFunc) tabsborder_book,
                                 GTK_OBJECT (notebook));
      gtk_table_attach_defaults(GTK_TABLE(table), button, 4,5,1,2);
      gtk_widget_show(button);

      button = gtk_button_new_with_label ("remove page");
      gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
                                 (GtkSignalFunc) remove_book,
                                 GTK_OBJECT(notebook));
      gtk_table_attach_defaults(GTK_TABLE(table), button, 5,6,1,2);
      gtk_widget_show(button);

      gtk_widget_show(table);
      gtk_widget_show(window);

      gtk_main ();

      return 0;
  }

  ̰  GTK    Ʈ ٷ   
Ǳ⸦ ٶ.

***
*** 8-2. ũѵ 
***
  ̰   ο ũѵ    ̴ ̴.  츮
̷ ũѵ    widget̶   ְ, ũѹٸ
̿Ͽ ũ⿡     ̴.

   Լ ο ũ   ̴.

       GtkWidget* gtk_scrolled_window_new (GtkAdjustment *hadjustment,
                                           GtkAdjustment *vadjustment);

  ù° ڴ , ׸ ι° ڴ   ش. 
̰͵ 밳 NULL õȴ.

       void gtk_scrolled_window_set_policy (GtkScrolledWindow *scrolled_window,
                                            GtkPolicyType hscrollbar_policy,
                                            GtkPolicyType vscrollbar_policy);

  ̰ ũѹٵ   Ѵ.  ù° ڴ 츮 ȭ
Ű ϴ ũ .  ι° ° ڵ   ũѹٿ
 ũѹ  Ѵ.

   ̶  GTK_POLICY_AUTOMATIC Ȥ GTK_POLICY_ALWAYS  ȴ. 
GTK_POLICY_AUTOMATIC ũѹٰ ʿ  ڵ ϰ, ݸ
GTK_POLICY_ALWAYS  ũѹٸ  д.

     ũѵ  100  ư ŷѴ.  ⼭
ּ п  κп ٿ ̴.
 
  #include <gtk/gtk.h>

  void destroy(GtkWidget *widget, gpointer *data)
  {
      gtk_main_quit();
  }

  int main (int argc, char *argv[])
  {
      static GtkWidget *window;
      GtkWidget *scrolled_window;
      GtkWidget *table;
      GtkWidget *button;
      char buffer[32];
      int i, j;

      gtk_init (&argc, &argv);

      /* ũѵ  ŷǾ  dialog  . 
       * Dialog  vbox װͿ ŷǾ   seperator 
       * ִٴ ͸     ̴.  ̰ dialog
       *  Ǵ  shortcut̴. */
      window = gtk_dialog_new ();
      gtk_signal_connect (GTK_OBJECT (window), "destroy",
                          (GtkSignalFunc) destroy, NULL);
      gtk_window_set_title (GTK_WINDOW (window), "dialog");
      gtk_container_border_width (GTK_CONTAINER (window), 0);

      /* ũѵ(scrolled)  ϳ . */
      scrolled_window = gtk_scrolled_window_new (NULL, NULL);

      gtk_container_border_width (GTK_CONTAINER (scrolled_window), 10);

      /* ⼭  GTK_POLICY_AUTOMATIC Ǵ GTK_POLICY_ALWAYS 
       * ϳ̴.  GTK_POLICY_AUTOMATIC ũѹٰ ʿ ڵ
       * ϰ, ݸ GTK_POLICY_ALWAYS  ũѹٸ  Ѵ.
       * ù°  ũѹ, ׸ ι°  ̴. */

      gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
                                      GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
      /* vbox ŷǾ  dialog  ϳ . */
      gtk_box_pack_start (GTK_BOX (GTK_DIALOG(window)->vbox), scrolled_window,
                          TRUE, TRUE, 0);
      gtk_widget_show (scrolled_window);

      /* 10 10 ̺ . */
      table = gtk_table_new (10, 10, FALSE);

      /* x y  10 ŭ spacing Ѵ. */
      gtk_table_set_row_spacings (GTK_TABLE (table), 10);
      gtk_table_set_col_spacings (GTK_TABLE (table), 10);

      /* ũѵ  ̺ ŷѴ. */
      gtk_container_add (GTK_CONTAINER (scrolled_window), table);
      gtk_widget_show (table);

      /* ̰ ܼ ũѵ  ֱ  ̺ 
       * ۹ư (grid) ϳ . */
      for (i = 0; i < 10; i++)
              for (j = 0; j < 10; j++) {
                  sprintf (buffer, "button (%d,%d)\n", i, j);
                  button = gtk_toggle_button_new_with_label (buffer);
                  gtk_table_attach_defaults (GTK_TABLE (table), button,
                                             i, i+1, j, j+1);
                  gtk_widget_show (button);
              }
      /* Dialog  Ʒʿ "close" ư ߰Ѵ. */
      button = gtk_button_new_with_label ("close");
      gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
                                 (GtkSignalFunc) gtk_widget_destroy,
                                 GTK_OBJECT (window));

      /* ̰ Ʈ ư Ѵ. */

      GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
      gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button, TRUE, TRUE, 0);

      /*  ư Ʈ ư ǵ æ.   "Enter" ġ
       *  ư Ȱȭ ų ̴. */
      gtk_widget_grab_default (button);
      gtk_widget_show (button);

      gtk_widget_show (window);

      gtk_main();

      return(0);
  }

   ũ⸦ ϰ غ.  ũѹٰ  ϴ   
̴.  츮   ٸ widget Ʈ ũ⸦ ϱ 
gtk_widget_set_usize()Լ ̿   ̴.



********************
*** 9. Ʈ widget
********************

  GtkList widget GtkListItem widget   ̳ó
۵ϵ Ǿ.

  ϳ GtkList widget ̺Ʈ  ڽŸ ,  white
ڽŸ background   ִ.  GtkContainerκ ĻǾ⿡
GTK_CONTAINER(List) ũθ ̿ ٷ  ִµ, ̰Ϳ ؼ
GtkContainer widget  κ ϱ ٶ.

  GtkList widget ü ǿ ξ  ̷ο ϳ ʵ尡 ִ. 
ٷ ̴̰.

       struct _GtkList
       {
         ...
         GList *selection;
         guint selection_mode;
         ...
       };

  GtkList selection ʵ  õ  ۵ ḮƮ
Ű ְ,  õ  ٸ 'NULL'̴.  ׷ 츮 
õ  ˱ GTK_LIST()->selection ʵ带 ,  
ʵ gtk_list*() Լν ǰ Ƿ װ ؼ ȵȴ.
  GtkList selection_mode GtkList  GTK_LIST()->selection ʵ ͵鿡
  Ӽ Ѵ.

  selection_mode ̰͵  ϳ  ̴.

  o GTK_SELECTION_SINGLE -  'NULL'̰ų ϳ õ  
  GList*  ʹ.

  o GTK_SELECTION_BROWSE - Ʈ widget   ʰų Ǵ 
  ͸     'NULL'̴.  ƴϸ װ ϳ GList
  ü  GList* ͸ ϰ,  Ȯ ϳ Ʈ 
   ϰ ȴ.

  o GTK_SELECTION_MULTIPLE - ƹ  õ ʾҴٸ 'NULL'̰,
  Ǵ ù° õ   GList* Ͱ ȴ.  ̰ ι° 
  õ  ü Ű ǰ, ׷ ư.

  o GTK_SELECTION_EXTENDED -   'NULL'̴.

  Ʈ GTK_SELECTION_MULTIPLE̴.

***
*** 9-1. ñ׳
***

       void GtkList::selection_changed (GtkList *LIST)

   ñ׳ GtkList selection ʵ尡 ȭ  ûȴ.  ̰
GtkList child õǰų  Ǿ  ߻Ѵ.

       void GtkList::select_child (GtkList *LIST, GtkWidget *CHILD)

   ñ׳ GtkList child õǷ   ߻Ѵ.  ̰ ַ
gtk_list_select_item() gtk_list_select_child() ȣ , ư 
  ߻ϸ,  child GtkList ų Ǿ  ٸ
ε鿡   ߻ϱ⵵ Ѵ.

       void GtkList::unselect_child (GtkList *LIST, GtkWidget *CHILD)

  ̰ GtkList child    ûȴ.  ̰ ַ gtk_list_
unselect_item()̳ gtk_list_unselect_child()Լ θ  ư 
 ߻ϸ,  GtkList child ų   Ǵٸ ο
  ߻Ѵ.

***
*** 9-2. Լ
***

       guint gtk_list_get_type (void)

  ̰ GtkList ĺڸ Ѵ.

       GtkWidget* gtk_list_new (void)

  ̰ ο GtkList object .    widget  GtkWidget object
  · ϵȴ.   쿣 'NULL' Ѵ.

       void gtk_list_insert_items (GtkList *LIST, GList *ITEMS, gint POSITION)

  POSITION ؼ, Ʈ  LIST Ѵ.  ITEMS  
 Ͱ Ӱ  GtkListItem Ű Ǿִ, 
ḮƮ.  ITEMS GList LIST  .

       void gtk_list_append_items (GtkList *LIST, GList *ITEMS)

  LIST  gtk_list_insert_items() ó Ʈ  Ѵ. 
ITEMS GList  LIST  .

       void gtk_list_prepend_items (GtkList *LIST, GList *ITEMS)

  LIST  ùκп gtk_list_insert_items() ó Ʈ  Ѵ.
 ITEMS GList  LIST  .

       void gtk_list_remove_items (GtkList *LIST, GList *ITEMS)

  LISTκ Ʈ  Ѵ.  ITEMS   Ÿ Ͱ
LIST  child Ű Ǿ ִ  ḮƮ.  ؼ
g_list_free(ITEMS) θ  ȣϴ  å̴.   ȣڴ
Ʈ   ü ı ־ Ѵ.

       void gtk_list_clear_items (GtkList *LIST, gint START, gint END)

  LISTκ Ʈ  ϰ ıش.  LIST  ġ
START END ̷   ִ widget   ̴.

       void gtk_list_select_item (GtkList *LIST, gint ITEM)

  LIST  ġ   Ʈ   GtkList::select_
child ñ׳ ûѴ.

       void gtk_list_unselect_item (GtkList *LIST, gint ITEM)

    쿡 GtkList::unselect_child ñ׳ ûѴ.

       void gtk_list_select_child (GtkList *LIST, GtkWidget *CHILD)

  ־ CHILD  GtkList::select_child ñ׳ ûѴ.

       void gtk_list_unselect_child (GtkList *LIST, GtkWidget *CHILD)

  ־ CHILD  GtkList::unselect_child ñ׳ ûѴ.

       gint gtk_list_child_position (GtkList *LIST, GtkWidget *CHILD)

  LIST CHILD ġ Ѵ.  '-1'   ϰ̴.

       void gtk_list_set_selection_mode (GtkList *LIST, GtkSelectionMode MODE)

    MODE LIST Ѵ.   GTK_SELECTION_SINGLE, GTK_
SELECTION_BROWSE, GTK_SELECTION_MULTIPLE, GTK_SELECTION_EXTENDED ߿
ϳ ȴ.

       GtkList* GTK_LIST (gpointer OBJ)

  κ ͸ GtkList*  ĳƮѴ.   ڼ ˷ Ϲ
ũθ ϶.

       GtkListClass* GTK_LIST_CLASS (gpointer CLASS)

  κ ͸ GtkListClass*  ĳƮѴ.  Ϲ ũθ
϶.

       gint GTK_IS_LIST (gpointer OBJ)

   κ Ͱ GtkList object ϴ Ѵ.  ڼ
˷ Ϲ ũθ ϶.

***
*** 9-3. 
***
  ̹  GtkList  ȭŰ   ̴.  ׸
Ʈ ۵ 콺  ư ν ׵ Ƶ 
ְ  ̴.

  /*  α׷ Ϸ ̷ Ѵ.
   * $ gcc -I/usr/local/include/ -lgtk -lgdk -lglib -lX11 -lm -Wall main.c
   */

  /* GTK+  includeѴ.
   * printf()Լ  <stdio.h> includeѴ.
   */
  #include        <gtk/gtk.h>
  #include        <stdio.h>

  /* ̰ Ʈ ۿ ͸ ϱ   ĺڴ. */
  const   gchar   *list_item_data_key="list_item_data";

  /* 츮 GtkList widget ų ñ׳ ڵ鷯 Լ. */
  static  void    sigh_print_selection    (GtkWidget      *gtklist,
                                           gpointer       func_data);
  static  void    sigh_button_event       (GtkWidget      *gtklist,
                                           GdkEventButton *event,
                                           GtkWidget      *frame);

  /*  ̽ ϴ main Լ */

  gint main (int argc, gchar *argv[])
  {
      GtkWidget       *separator;
      GtkWidget       *window;
      GtkWidget       *vbox;
      GtkWidget       *scrolled_window;
      GtkWidget       *frame;
      GtkWidget       *gtklist;
      GtkWidget       *button;
      GtkWidget       *list_item;
      GList           *dlist;
      guint           i;
      gchar           buffer[64];

      /* gtk+(׸  gdk) ʱȭѴ. */

      gtk_init(&argc, &argv);

      /*  widget ־  .
       *  Ŵ close-window-event ٷ  gtk_main_quit()
       * Լ  "destroy" ̺Ʈ Ų. */
      window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
      gtk_window_set_title(GTK_WINDOW(window), "GtkList Example");
      gtk_signal_connect(GTK_OBJECT(window),
                         "destroy",
                         GTK_SIGNAL_FUNC(gtk_main_quit),
                         NULL);

      /*  ο widget   ڽ ־ Ѵ. */
      vbox=gtk_vbox_new(FALSE, 5);
      gtk_container_border_width(GTK_CONTAINER(vbox), 5);
      gtk_container_add(GTK_CONTAINER(window), vbox);
      gtk_widget_show(vbox);
      /* GtkList widget ־ΰ ϴ ũѵ . */
      scrolled_window=gtk_scrolled_window_new(NULL, NULL);
      gtk_widget_set_usize(scrolled_window, 250, 150);
      gtk_container_add(GTK_CONTAINER(vbox), scrolled_window);
      gtk_widget_show(scrolled_window);

      /* GtkList widget .  selection    õ
       *  Ʈ ֱ  sigh_print_selection()
       * ñ׳ ڵ鷯 Լ GtkList "selection_changed" ñ׳ο
       *  д. */
      gtklist=gtk_list_new();
      gtk_container_add(GTK_CONTAINER(scrolled_window), gtklist);
      gtk_widget_show(gtklist);
      gtk_signal_connect(GTK_OBJECT(gtklist),
                         "selection_changed",
                         GTK_SIGNAL_FUNC(sigh_print_selection),
                         NULL);

      /* Ʈ  ξ  "Prison" . ;) */
      frame=gtk_frame_new("Prison");
      gtk_widget_set_usize(frame, 200, 50);
      gtk_container_border_width(GTK_CONTAINER(frame), 5);
      gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
      gtk_container_add(GTK_CONTAINER(vbox), frame);
      gtk_widget_show(frame);

      /* Ʈ  "arresting" ٷ GtkList sigh_button_event()
       * ñ׳ ڵ鷯 Ų. */
      gtk_signal_connect(GTK_OBJECT(gtklist),
                         "button_release_event",
                         GTK_SIGNAL_FUNC(sigh_button_event),
                         frame);

      /* Separator . */
      separator=gtk_hseparator_new();
      gtk_container_add(GTK_CONTAINER(vbox), separator);
      gtk_widget_show(separator);

      /*  ư  װ "clicked" ñ׳  ı
       * Ų. */
      button=gtk_button_new_with_label("Close");
      gtk_container_add(GTK_CONTAINER(vbox), button);
      gtk_widget_show(button);
      gtk_signal_connect_object(GTK_OBJECT(button),
                                "clicked",
                                GTK_SIGNAL_FUNC(gtk_widget_destroy),
                                GTK_OBJECT(window));

      /*     ִ 5 Ʈ  ,
       * gtk_container_add()ν ׵ GtkList ÷Ѵ.
       *   ؽƮ ڿ ϰ װ  Ʈ 
       * list_item_data_key սŲ. */
      for (i=0; i<5; i++) {
          GtkWidget       *label;
          gchar           *string;

          sprintf(buffer, "ListItemContainer with Label #%d", i);
          label=gtk_label_new(buffer);
          list_item=gtk_list_item_new();
          gtk_container_add(GTK_CONTAINER(list_item), label);
          gtk_widget_show(label);
          gtk_container_add(GTK_CONTAINER(gtklist), list_item);
          gtk_widget_show(list_item);
          gtk_label_get(GTK_LABEL(label), &string);
          gtk_object_set_data(GTK_OBJECT(list_item),
                              list_item_data_key,
                              string);
      }
      /* ⼭, gtk_list_item_new_with_label() ̿ؼ
       * ٸ 5  .
       * ̹ 󺧵鿡  Ͱ Ƿ  ؽƮ
       * ڿ   , ׷Ƿ  Ʈ 
       * list_item_data_key Ȱ ؽƮ ڿ Ѵ.
       * Ʈ  ߰ϱ ؼ 츮 ׵  
       * Ʈ(GList) оְ, gtk_list_append_items() 
       * ȣش.  츮 ۵   Ʈ оֱ
       *  g_list_prepend() ϱ , ׵ 
       * ڷ ̾(descending)  ȴ.  ݴ g_list_append()
       *  ̿ߴٸ տ ٿ(ascending)  ̴. */
      dlist=NULL;
      for (; i<10; i++) {
          sprintf(buffer, "List Item with Label %d", i);
          list_item=gtk_list_item_new_with_label(buffer);
          dlist=g_list_prepend(dlist, list_item);
          gtk_widget_show(list_item);
          gtk_object_set_data(GTK_OBJECT(list_item),
                              list_item_data_key,
                              "ListItem with integrated Label");
      }
      gtk_list_append_items(GTK_LIST(gtklist), dlist);

      /*  츮   ; Ѵ, ƴѰ? ;) */
      gtk_widget_show(window);

      /* GTK main ̺Ʈ  õѴ. */
      gtk_main();

      /* gtk_main_quit() ȣǸ   ´. */
      return 0;
  }

  /* GtkList ư press/release ̺Ʈ  ñ׳
   * ڵ鷯 Լ̴. */
  void
  sigh_button_event       (GtkWidget      *gtklist,
                           GdkEventButton *event,
                           GtkWidget      *frame)
  {
      /* °,   ʿ ִ 콺 ư  
       *   ϵ Ѵ. */
      if (event->type==GDK_BUTTON_RELEASE &&
          event->button==3) {
          GList           *dlist, *free_list;
          GtkWidget       *new_prisoner;

          /*  õ  ͼ 츮  prisoner
           * Ѵ. */
          dlist=GTK_LIST(gtklist)->selection;
          if (dlist)
                  new_prisoner=GTK_WIDGET(dlist->data);
          else
                  new_prisoner=NULL;

          /* ̹  Ʈ  ϰ, ׵
           * ٽ Ʈ ش.
           * gtk_container_children() ϴ   Ʈ
           *  (free)  ϶. */
          dlist=gtk_container_children(GTK_CONTAINER(frame));
          free_list=dlist;
          while (dlist) {
              GtkWidget       *list_item;

              list_item=dlist->data;

              gtk_widget_reparent(list_item, gtklist);

              dlist=dlist->next;
          }
          g_list_free(free_list);

          /*  prisoner  Ǹ, GtkListκ װ
           * ϰ "Prison"  оִ´.
           *   unselectǾ Ѵ. */
          if (new_prisoner) {
              GList   static_dlist;

              static_dlist.data=new_prisoner;
              static_dlist.next=NULL;
              static_dlist.prev=NULL;

              gtk_list_unselect_child(GTK_LIST(gtklist),
                                      new_prisoner);
              gtk_widget_reparent(new_prisoner, frame);
          }
      }
  }

  /* ̰ GtkList "selection_changed" ñ׳ ߻Ű
   * ȣǴ ñ׳ ڵ鷯. */
  void
  sigh_print_selection    (GtkWidget      *gtklist,
                           gpointer       func_data)
  {
      GList   *dlist;

      /* GtkList õ    Ʈ ´.
       * ̰ read-only ٷ   ! */
      dlist=GTK_LIST(gtklist)->selection;

      /* õ    ƹ ۾    װ
       * ڿ ˷ش. */
      if (!dlist) {
          g_print("Selection cleared\n");
          return;
      }
      /*  ߰ װ ƮѴ. */
      g_print("The selection is a ");

      /*   Ʈ Ʈ  ϰ
       * list_item_data_key õ ͸ Ѵ.
       * ׸  װ ƮѴ. */
      while (dlist) {
          GtkObject       *list_item;
          gchar           *item_data_string;

          list_item=GTK_OBJECT(dlist->data);
          item_data_string=gtk_object_get_data(list_item,
                                               list_item_data_key);
          g_print("%s ", item_data_string);

          dlist=dlist->next;
      }
      g_print("\n");
  }

***
*** 9-4. Ʈ  widget
***
  GtkListItem widget ϳ child ־  ִ ̳ó ۵ϵ
Ǿ, GtkList widget  child  ׷ϵ ̰ 
selection/deselection Լ ϰ ִ.

  GtkListItem ̺Ʈ ޱ ؼ ڽŸ   ְ,  
white ڽŸ background   ִ.

  ̰ GtkItemκ  ĻǾ   GTK_ITEM(
ListItem) ũη ٷ  , ڼ  GtkItem widget ϸ
 ̴.  밳 GtkListItem ĺǱ    ִ,  
GtkList ִ filenameó.   convenient Լ gtk_list_item_new_with
_label() ȴ.   ȿ ڽŸ GtkLabel ν  
ִ.  GtkListItem ̾ ̳ʿ Բ xalign=0, yalign=0.5
ϸ ȴ.

  GtkListItem  GtkLabel  ִ  ƴϸ, 츮 GtkVBox Ǵ
GtkArrow    ִ.

***
*** 9-5. ñ׳
***
  GtkListItem ڽŸ ñ׳   ʰ, GtkItem ñ׳
ӹ޴´.  ڼ  GtkItem ؼ ϶.

***
*** 9-6. Լ
***

       guint gtk_list_item_get_type (void)

  GtkListItem ĺڸ Ѵ.

       GtkWidget* gtk_list_item_new (void)

  ο GtkListItem object .   ο widget GtkWidget object
  ͷμ ϵȴ.  'NULL'   ϰ̴.

       GtkWidget* gtk_list_item_new_with_label (gchar *LABEL)

  ϳ child ϳ GtkLabel  GtkListItem object . 
 ο widget GtkWidget object  ͷμ ϵȴ.  'NULL'
  ϰ̴.

       void gtk_list_item_select (GtkListItem *LIST_ITEM)

  ̰ ٺ, GtkItem::select ñ׳ ߻ gtk_item_select
ȣϴ  ־ wrapper(GTK_ITEM(list_item)).  ڼ  GtkItem
϶.

       void gtk_list_item_deselect (GtkListItem *LIST_ITEM)

  ̰ GtkItem::deselect ñ׳ ߻ gtk_item_deselect ȣϴ 
־ wrapper(GTK_ITEM(list_item)).   ڼ  GtkItem 
϶.

       GtkListItem* GTK_LIST_ITEM (gpointer OBJ)

  κ ͸ GtkListItem* ĳƮѴ.  ڼ  Ϲ
ũθ ϶.

       GtkListItemClass* GTK_LIST_ITEM_CLASS (gpointer CLASS)

  κ ͸ GtkListItemClass* ĳƮѴ.   Ϲ ũο
 κ ϶.

       gint GTK_IS_LIST_ITEM (gpointer OBJ)

   Ͱ GtkListItem object ϰ ִ Ѵ.  ڼ
 Ϲ ũο ؼ ϶.

***
*** 9-7. 
***
  GtkList   ϶.  װ GtkListItem ̿ ؼ
 ٷ ִ.

***
*** 9-8.  
***
*****************
*** 10.  
*****************

  ϼ widget  ȭڸ ̴   ̴.  ̰
Ok, Cancel, Help ư  , α׷ ð  ٿش.

  ο ϼ ڽ  ̰ ̿Ѵ.

       GtkWidget* gtk_file_selection_new (gchar *title);

  ̸ ϱ ؼ  Լ ̿Ѵ.

       void gtk_file_selection_set_filename (GtkFileSelection *filesel, gchar *filename);

  ڰ Ű Ȥ 콺 Ŭ Է ؽƮ ϱ ؼ 
Լ .

       gchar* gtk_file_selection_get_filename (GtkFileSelection *filesel);

  ϼwidget ο Ե widget鿡  ͵鵵 ִ.  ׵
 .

  o  dir_list

  o  file_list

  o  selection_entry

  o  selection_text

  o  main_vbox

  o  ok_button

  o  cancel_button

  o  help_button

  츮   ̿ϰ   ok_button, cancel_button, ׸
help_button Ͱ  ̴.

  ̰ testgtk.c       ̴.  
˰, ⼭ ϼwidget ϳ  ̴.  Help ư ũ
̰, ƹ ñ׳ Ǿ  Ƿ ƹ   ̴.

       #include <gtk/gtk.h>

       /* õ  ̸ ؼ װ ַܼ ƮѴ. */
       void file_ok_sel (GtkWidget *w, GtkFileSelection *fs)
       {
           g_print ("%s\n", gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs)));
       }

       void destroy (GtkWidget *widget, gpointer *data)
       {
           gtk_main_quit ();
       }

       int main (int argc, char *argv[])
       {
           GtkWidget *filew;

           gtk_init (&argc, &argv);

           /* ϼ widget ϳ . */
           filew = gtk_file_selection_new ("File selection");

           gtk_signal_connect (GTK_OBJECT (filew), "destroy",
                               (GtkSignalFunc) destroy, &filew);
           /* file_ok_sel Լ ok_button Ų. */
           gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (filew)->ok_button),
                               "clicked", (GtkSignalFunc) file_ok_sel, filew );

           /* gtk_widget_destroy Լ cancel_button Ų. */
           gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION (filew)->cancel_button),
                                      "clicked", (GtkSignalFunc) gtk_widget_destroy,
                                      GTK_OBJECT (filew));

           /* ̸ Ѵ. */
           gtk_file_selection_set_filename (GTK_FILE_SELECTION(filew),
                                            "penguin.png");

           gtk_widget_show(filew);
           gtk_main ();
           return 0;
       }



*******************
*** 11. ޴ widget
*******************

  ޴       ΰ ִ.    
ִ ͵, 츮    menu_factory   
̴.  "" ̶ Լ ̿ؼ  ޴  ̴.
׸   gtk_menu_factory Լ  ̴.  ̰ ξ
,     ִ.

      wrapper Լ   ޴  
뼺 ־ ξ Կ ұϰ, menufactory ̿ϴ 
ξ ϱ   ο ޴ ߰ϱ⵵ .  Menufactory ̿ϰ
Ǹ, ޴ ̹簡 '/'   Ұ.

***
*** 11-1.  ޴ 
***
   ٶ 뿡 ,    ̰ڴ.  :)

  ޴   ̴ Լ 캸.   ù° Լ ο
޴   δ.

       GtkWidget *gtk_menu_bar_new()

  ̰ ̸ ״ ο ޴ٸ .  ư , 츮
̰  ŷϱ  gtk_container_add ̿Ҽ ְ, Ǵ
ڽ ŷϱ  box_pack Լ ̿  ִ.

       GtkWidget *gtk_menu_new();

   Լ ο ޴  ͸ ϴµ, ̰  
ʰ(gtk_widget_showν) ٸ ޴ ۵  ִ.   Ʒ
    Ȯ ϱ⸦ ٶ.

  ̹  Լ ޴  ŷǴ ޴    δ.

       GtkWidget *gtk_menu_item_new()

       GtkWidget *gtk_menu_item_new_with_label(const char *label)

   Լ   ޴   δ.  gtk_menu_newν
 "޴" gtk_menu_item_newν  "޴ " 
ؾ Ѵ.  ޴    ִ  ư  ,
ݸ ޴ ̰͵  ִ ̳ʰ  ̴.

       gtk_menu_item_append()

       gtk_menu_item_set_submenu()

  gtk_menu_new_with_label ܼ gtk_menu_new Լ  ư 
 Ŀ ϴ ״δ.  gtk_menu_new_with_label  ̹
ŷǾ ִ ޴  , gtk_menu_new ִ ޴ 
.

  ̰ ޴ ޷ִ ޴ٸ  ̴ܰ.

  o gtk_menu_new() ̿ؼ ο ޴ .

  o gtk_menu_item_new() ̿ؼ ޴  .  ̰ root
    ޴ ǰ,  ؽƮ ޴ ڽ ̸  ̴.

  o  ۸ gtk_menu_item_new() ̿ ϴ ޴ Ѵ. 
    ׸ ̰͵  ο  ̱  gtk_menu_item_append()
     .  ̷ ޴  Ʈ .

  o Ӱ  ޴  root ޴ (ι° ܰ迡 ִ)
     ٿֱ  gtk_menu_item_set_submenu() ̿Ѵ.

  o gtk_menu_bar_new() ̿ؼ ο ޴ٸ .   ܰ  
    ޴  Ϸ ޴   ʿϴ.

  o gtk_menu_bar_append() ̿ؼ ޴  root ޴ ´.

  ˾޴  ͵  .  ٸ  ִٸ ޴ ޴ٿ 
ڵ ٿ  ƴ϶, button_press ̺Ʈκ gtk_menu_popup()
Լ ȣν ٿٴ ̴.    .

  o ̺Ʈ ڵ鸵 Լ .  ̰ ̷   Ѵ.

      static gint handler(GtkWidget *widget, GdkEvent *event);

    ׸ ̰ ޴ ˾ų  ã  ̺Ʈ ̿ ̴.

  o ̺Ʈ ڵ鷯,  ̺Ʈ 콺 ư  ̶,
    ̺Ʈ ư ̺Ʈ ٷ, gtk_menu_popup()  Ѱִ
     ڵ忡 δ ̿϶.

  o  Լ ̿Ͽ ̺Ʈ ڵ鷯 widget սŲ.

      gtk_signal_connect_object(GTK_OBJECT(widget), "event", GTK_SIGNAL_FUNC
      (handler), GTK_OBJECT(menu));

    ⼭ widget ڴ 츮 ε widget̰, handler ڴ
    ڵ鸵 Լ.  ׸ menu ڴ gtk_menu_new()ν  ޴.
     ڵ忡 δ, ̰ ޴ٿ ٿ ִ ޴  
    ִ.

***
*** 11-2.  ޴  
***
   и صα    .

       #include <gtk/gtk.h>

       static gint button_press (GtkWidget *, GdkEvent *);
       static void menuitem_response (GtkWidget *, gchar *);

       int main (int argc, char *argv[])
       {

           GtkWidget *window;
           GtkWidget *menu;
           GtkWidget *menu_bar;
           GtkWidget *root_menu;
           GtkWidget *menu_items;
           GtkWidget *vbox;
           GtkWidget *button;
           char buf[128];
           int i;

           gtk_init (&argc, &argv);

           /*  . */
           window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
           gtk_window_set_title(GTK_WINDOW (window), "GTK Menu Test");
           gtk_signal_connect(GTK_OBJECT (window), "delete_event",
                              (GtkSignalFunc) gtk_exit, NULL);

           /* menu-widget Ѵ.  ⼭ ޴ widget鿡 
            * gtk_show_widget()  ȵȴ!
            * ̰ ޴   ִ ޴, 츮 ÿ
            * "Root Menu" Ŭ  ˾ ̴. */
           menu = gtk_menu_new();

           /* ̰ root ޴, ޴ٿ Ÿ ޴ ̸  
            *  ̴.  ̰    ޴  κ
            * ˾Ǳ⸸  ̹Ƿ Ư ñ׳ ڵ鷯 յǾ
            *  ʿ . */
           root_menu = gtk_menu_item_new_with_label("Root Menu");

           gtk_widget_show(root_menu);

           /*  츮  ޴Ʈ    
            * Ѵ.  ̶, 츮  ޴ ۵鿡 
            * "clicked" ñ׳ Ƴ ̰, װ  callback
            *  ̴.  ׷  ϱ   
            * Ѵ. */

           for(i = 0; i < 3; i++)
               {
                   /* buf ޴ ̸ Ѵ. */
                   sprintf(buf, "Test-undermenu - %d", i);

                   /* ̸   ޴  . */
                   menu_items = gtk_menu_item_new_with_label(buf);

                   /* ̰ ޴ ÷Ѵ. */
                   gtk_menu_append(GTK_MENU (menu), menu_items);

                   /* ޴  õǸ    Ų. */
                   gtk_signal_connect (GTK_OBJECT(menu_items), "activate",
                       GTK_SIGNAL_FUNC(menuitem_response), (gpointer)
                       g_strdup(buf));

                   /* widget δ. */
                   gtk_widget_show(menu_items);
               }

      /*  츮 Ӱ  "menu", "root menu" ǵ
       *  . */
      gtk_menu_item_set_submenu(GTK_MENU_ITEM (root_menu), menu);

      /* ޴ ư 鿩 vbox */
      vbox = gtk_vbox_new(FALSE, 0);
      gtk_container_add(GTK_CONTAINER(window), vbox);
      gtk_widget_show(vbox);

      /* ޴   menu-bar  װ 츮 main 
       * ߰Ѵ. */
      menu_bar = gtk_menu_bar_new();
      gtk_box_pack_start(GTK_BOX(vbox), menu_bar, FALSE, FALSE, 2);
      gtk_widget_show(menu_bar);

      /* ޴ ˾Ű   ư . */
      button = gtk_button_new_with_label("press me");
      gtk_signal_connect_object(GTK_OBJECT(button), "event",
          GTK_SIGNAL_FUNC (button_press), GTK_OBJECT(menu));
      gtk_box_pack_end(GTK_BOX(vbox), button, TRUE, TRUE, 2);
      gtk_widget_show(button);

      /*  menu-item menu-bar ̾ش.  ̰ ٷ
       *  ݲ   "root" ޴ ̴. =) */
      gtk_menu_bar_append(GTK_MENU_BAR (menu_bar), root_menu);

      /*  ü   ش. */
      gtk_widget_show(window);

      gtk_main ();

      return 0;
  }

  /* "widget" Ѱܹ ޴ ν button-press Ѵ.
   *
   *  "widget"  ư ƴ϶  ޴  . */

  static gint button_press (GtkWidget *widget, GdkEvent *event)
  {

      if (event->type == GDK_BUTTON_PRESS) {
          GdkEventButton *bevent = (GdkEventButton *) event;
          gtk_menu_popup (GTK_MENU(widget), NULL, NULL, NULL, NULL,
                          bevent->button, bevent->time);
          /* 츮  ̺Ʈ ٷ Ѵ.  ⼭ . */
          return TRUE;
      }

      /* 츮  ̺Ʈ ٷ ʾ Ѵ.   ģ. */
      return FALSE;
  }

  /* ޴  õǾ  ڿ ƮѴ. */

  static void menuitem_response (GtkWidget *widget, gchar *string)
  {
      printf("%s\n", string);
  }

  츮  ޴    ʰԵ   ְ, ǥ 
ؼ ޴ Լ鿡 Ű ε   ִ.

***
*** 11-3. GtkMenuFactory ̿ϱ
***
     , gtk_menu_factory Լ ̿ϴ  
ִ.

***
*** 11-4. Menu factory 
***
  ̰ GTK menu factory ̿ϴ ̴.  ̰ ù°  menus.h
.  츮 menus.c  global ؼ menus.c  main.c
и ̴.

       #ifndef __MENUS_H__
       #define __MENUS_H__

       #ifdef __cplusplus
       extern "C" {
       #endif /* __cplusplus */

       void get_main_menu (GtkWidget **menubar, GtkAcceleratorTable **table);
       void menus_create(GtkMenuEntry *entries, int nmenu_entries);

       #ifdef __cplusplus
       }
       #endif /* __cplusplus */

       #endif /* __MENUS_H__ */

  ׸ ̰ menus.c ̴.

  #include <gtk/gtk.h>
  #include <strings.h>

  #include "main.h"

  static void menus_remove_accel(GtkWidget * widget, gchar * signal_name, gchar * path);
  static gint menus_install_accel(GtkWidget * widget, gchar * signal_name, gchar key, gchar modifiers, gchar * path);
  void menus_init(void);
  void menus_create(GtkMenuEntry * entries, int nmenu_entries);

  /* ̰ ο ޴    GtkMenuEntry ü.
   * ù°  ޴ ϴ ڿ̴.  ι°  ޴Լ
   * Ű ҷ  ̴ Ʈ Ű.  °   ޴
   *  õǾ(콺 Ȥ Űν)  ȣ callback Լ.
   * ׸    callbackԼ Ѱ ʹ. */

  static GtkMenuEntry menu_items[] =
  {
          {"<Main>/File/New", "<control>N", NULL, NULL},
          {"<Main>/File/Open", "<control>O", NULL, NULL},
          {"<Main>/File/Save", "<control>S", NULL, NULL},
          {"<Main>/File/Save as", NULL, NULL, NULL},
          {"<Main>/File/<separator>", NULL, NULL, NULL},
          {"<Main>/File/Quit", "<control>Q", file_quit_cmd_callback, "OK, I'll quit"},
          {"<Main>/Options/Test", NULL, NULL, NULL}
  };

  /* ޴   Ѵ. */
  static int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);

  static int initialize = TRUE;
  static GtkMenuFactory *factory = NULL;
  static GtkMenuFactory *subfactory[1];
  static GHashTable *entry_ht = NULL;

  void get_main_menu(GtkWidget ** menubar, GtkAcceleratorTable ** table)
  {
      if (initialize)
              menus_init();

      if (menubar)
              *menubar = subfactory[0]->widget;
      if (table)
              *table = subfactory[0]->table;
  }

  void menus_init(void)
  {
      if (initialize) {
          initialize = FALSE;

          factory = gtk_menu_factory_new(GTK_MENU_FACTORY_MENU_BAR);
          subfactory[0] = gtk_menu_factory_new(GTK_MENU_FACTORY_MENU_BAR);

          gtk_menu_factory_add_subfactory(factory, subfactory[0], "<Main>");
          menus_create(menu_items, nmenu_items);
      }
  }

  void menus_create(GtkMenuEntry * entries, int nmenu_entries)
  {
      char *accelerator;
      int i;

      if (initialize)
              menus_init();

      if (entry_ht)
              for (i = 0; i < nmenu_entries; i++) {
                  accelerator = g_hash_table_lookup(entry_ht, entries[i].path);
                  if (accelerator) {
                      if (accelerator[0] == '\0')
                              entries[i].accelerator = NULL;
                      else
                              entries[i].accelerator = accelerator;
                  }
              }
      gtk_menu_factory_add_entries(factory, entries, nmenu_entries);

      for (i = 0; i < nmenu_entries; i++)
              if (entries[i].widget) {
                  gtk_signal_connect(GTK_OBJECT(entries[i].widget), "install_accelerator",
                                     (GtkSignalFunc) menus_install_accel,
                                     entries[i].path);
                  gtk_signal_connect(GTK_OBJECT(entries[i].widget), "remove_accelerator",
                                     (GtkSignalFunc) menus_remove_accel,
                                     entries[i].path);
              }
  }

  static gint menus_install_accel(GtkWidget * widget, gchar * signal_name, gchar key, gchar modifiers, gchar * path)
  {
      char accel[64];
      char *t1, t2[2];

      accel[0] = '\0';
      if (modifiers & GDK_CONTROL_MASK)
              strcat(accel, "<control>");
      if (modifiers & GDK_SHIFT_MASK)
              strcat(accel, "<shift>");
      if (modifiers & GDK_MOD1_MASK)
              strcat(accel, "<alt>");

      t2[0] = key;
      t2[1] = '\0';
      strcat(accel, t2);

      if (entry_ht) {
          t1 = g_hash_table_lookup(entry_ht, path);
          g_free(t1);
      } else
              entry_ht = g_hash_table_new(g_string_hash, g_string_equal);

      g_hash_table_insert(entry_ht, path, g_strdup(accel));

      return TRUE;
  }

  static void menus_remove_accel(GtkWidget * widget, gchar * signal_name, gchar * path)
  {
      char *t;

      if (entry_ht) {
          t = g_hash_table_lookup(entry_ht, path);
          g_free(t);

          g_hash_table_insert(entry_ht, path, g_strdup(""));
      }
  }

  void menus_set_sensitive(char *path, int sensitive)
  {
      GtkMenuPath *menu_path;

      if (initialize)
              menus_init();

      menu_path = gtk_menu_factory_find(factory, path);
      if (menu_path)
              gtk_widget_set_sensitive(menu_path->widget, sensitive);
      else
              g_warning("Unable to set sensitivity for menu which doesn't exist: %s", path);
  }

  ̰ main.h.

       #ifndef __MAIN_H__
       #define __MAIN_H__

       #ifdef __cplusplus
       extern "C" {
       #endif /* __cplusplus */

       void file_quit_cmd_callback(GtkWidget *widget, gpointer data);

       #ifdef __cplusplus
       }
       #endif /* __cplusplus */

       #endif /* __MAIN_H__ */

  ׸ ̰ main.c.

  #include <gtk/gtk.h>

  #include "main.h"
  #include "menus.h"

  int main(int argc, char *argv[])
  {
      GtkWidget *window;
      GtkWidget *main_vbox;
      GtkWidget *menubar;

      GtkAcceleratorTable *accel;

      gtk_init(&argc, &argv);

      window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
      gtk_signal_connect(GTK_OBJECT(window), "destroy",
                         GTK_SIGNAL_FUNC(file_quit_cmd_callback),
                         "WM destroy");
      gtk_window_set_title(GTK_WINDOW(window), "Menu Factory");
      gtk_widget_set_usize(GTK_WIDGET(window), 300, 200);

      main_vbox = gtk_vbox_new(FALSE, 1);
      gtk_container_border_width(GTK_CONTAINER(main_vbox), 1);
      gtk_container_add(GTK_CONTAINER(window), main_vbox);
      gtk_widget_show(main_vbox);

      get_main_menu(&menubar, &accel);
      gtk_window_add_accelerator_table(GTK_WINDOW(window), accel);
      gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
      gtk_widget_show(menubar);

      gtk_widget_show(window);
      gtk_main();

      return(0);
  }

  /* ⼭ menufactory ̿  callback  ۵ϴ
   * ش.  ,  ޴κ  callback  Ͽ
   * Ƶΰ, ű⼭  Լ ȣ   ϱ⵵ Ѵ. */
  void file_quit_cmd_callback (GtkWidget *widget, gpointer data)
  {
      g_print ("%s\n", (char *) data);
      gtk_exit(0);
  }

  ׸   ִ makefile̴.

  CC      = gcc
  PROF    = -g
  C_FLAGS =  -Wall $(PROF) -L/usr/local/include -DDEBUG
  L_FLAGS =  $(PROF) -L/usr/X11R6/lib -L/usr/local/lib
  L_POSTFLAGS = -lgtk -lgdk -lglib -lXext -lX11 -lm
  PROGNAME = at

  O_FILES = menus.o main.o

  $(PROGNAME): $(O_FILES)
          rm -f $(PROGNAME)
          $(CC) $(L_FLAGS) -o $(PROGNAME) $(O_FILES) $(L_POSTFLAGS)

          $(CC) -c $(C_FLAGS) $<

  clean:
          rm -f core *.o $(PROGNAME) nohup.out
  distclean: clean
          rm -f *~



********************************
*** 12. ȭ  widget
********************************

  ̵  ڸ ٸ ִ! :)  츮     
͵  ⸦.

    ȭ   widget  ȴٸ, GTK ǿ ִ
׵   캸⸦  Ѵ.  GTK Լ̸ ſ
̴.  ϴ   ۵ϴ Ѵٸ,  widget õ
Լ    widget  ̿ϴ     ̴. 

    ȭ  widget  Լ ϰ Ǹ, 
tutorial Ἥ ٸ 鿡  ִ    Ѵ.

***
*** 12-1. Text Entries
*** 12-2. Color Selections
*** 12-3. Range Controls
*** 12-4. Rulers
*** 12-5. Text Boxes
*** 12-6. Previews
***



*************************
*** 13. ̺Ʈڽ widget
*************************

  ̰ gtk+970916.tar.gz     ȴ.

   GTK widget ׵鸸 X  ʰ  ׵ parent
׷ ̴.  ̷  ׵ ̺Ʈ     Ȯ ũ
  Ŭ ʱ   ĥǾ   ִ.  ̷
widget     Ϸ ٷ  EventBox ̿  ִ.

   ⿡, EventBox widget    ִ.  ̰ ũ
ƹ͵ ׸  ̺Ʈ  ʴ´.   ̰ ڽ
child widget X ϴ  Լ Ѵ.  ̰  GTK
widget õ X  ʴ´ٴ  ߿ϴ.  X 
ʴ  ޸𸮸 ϰ ս ,    ִ.
X  widget ̺Ʈ   , ׸  ׸鿡 
Ŭε  ʴ´.  EventBox ̸ ̺Ʈ ٷ Լ ǹ̵
, widget Ŭε  ִٴ  ǹϱ⵵ Ѵ.  (׸ 
ִ.. Ʒ  .)

  ο EventBox widget  ؼ ̰ ̿Ѵ.

       GtkWidget* gtk_event_box_new (void);

   EventBox child widget   ִ.

       gtk_container_add (GTK_CONTAINER(event_box), widget);

  ̹   EventBox ΰ ӻ  ش.    ڽ
Ŭε  ְ, ̰Ϳ  콺 Ŭϸ α׷  ȴ.

  #include <gtk/gtk.h>

  int
  main (int argc, char *argv[])
  {
      GtkWidget *window;
      GtkWidget *event_box;
      GtkWidget *label;

      gtk_init (&argc, &argv);

      window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

      gtk_window_set_title (GTK_WINDOW (window), "Event Box");

      gtk_signal_connect (GTK_OBJECT (window), "destroy",
                          GTK_SIGNAL_FUNC (gtk_exit), NULL);

      gtk_container_border_width (GTK_CONTAINER (window), 10);

      /* EventBox ϳ  װ toplevel  ش. */

      event_box = gtk_event_box_new ();
      gtk_container_add (GTK_CONTAINER(window), event_box);
      gtk_widget_show (event_box);

      /*   . */

      label = gtk_label_new ("Click here to quit, quit, quit, quit, quit");
      gtk_container_add (GTK_CONTAINER (event_box), label);
      gtk_widget_show (label);

      /* ̰ ۰ ŬѴ. */
      gtk_widget_set_usize (label, 110, 20);

      /* ̰Ϳ (action)  ش. */
      gtk_widget_set_events (event_box, GDK_BUTTON_PRESS_MASK);
      gtk_signal_connect (GTK_OBJECT(event_box), "button_press_event",
                          GTK_SIGNAL_FUNC (gtk_exit), NULL);

      /*  X      ʿ  ִ... */

      gtk_widget_realize (event_box);
      gdk_window_set_cursor (event_box->window, gdk_cursor_new (GDK_HAND1));

      gtk_widget_show (window);

      gtk_main ();

      return 0;
  }



********************************
*** 14. Widget Ӽ ϱ
********************************

  ⼭ widget ϱ  Լ Ұȴ.  ̰͵ style,
padding, size  ϱ  δ.

  (Accelerator    ʿ  .)

  void       gtk_widget_install_accelerator (GtkWidget           *widget,
                                             GtkAcceleratorTable *table,
                                             gchar               *signal_name,
                                             gchar                key,
                                             guint8               modifiers);

  void       gtk_widget_remove_accelerator  (GtkWidget           *widget,
                                             GtkAcceleratorTable *table,
                                             gchar               *signal_name);

  void       gtk_widget_activate            (GtkWidget           *widget);

  void       gtk_widget_set_name            (GtkWidget           *widget,
                                             gchar               *name);
  gchar*     gtk_widget_get_name            (GtkWidget           *widget);

  void       gtk_widget_set_sensitive       (GtkWidget           *widget,
                                             gint                 sensitive);

  void       gtk_widget_set_style           (GtkWidget           *widget,
                                             GtkStyle            *style);

  GtkStyle*    gtk_widget_get_style     (GtkWidget *widget);

  GtkStyle*    gtk_widget_get_default_style    (void);

  void       gtk_widget_set_uposition       (GtkWidget           *widget,
                                             gint                 x,
                                             gint                 y);
  void       gtk_widget_set_usize           (GtkWidget           *widget,
                                             gint                 width,
                                             gint                 height);

  void       gtk_widget_grab_focus          (GtkWidget           *widget);

  void       gtk_widget_show                (GtkWidget           *widget);

  void       gtk_widget_hide                (GtkWidget           *widget);



******************************************
*** 15. ŸӾƿ, ׸ I/O Idle Լ
******************************************

***
*** 15-1. ŸӾƿ
***
  Ƹ gtk_main  GTK  ۾ ϰ  ñ ̴.
⿡  ɼ ִ.   Լ ̿ϸ  millisecond ȣ
ŸӾƿ Լ  ִ.

       gint gtk_timeout_add (guint32 interval,
                             GtkFunction function,
                             gpointer data);

  ù° ڴ 츮 Լ ȣϴµ ɸ ð̴.  ι° θ
ߴ Լ, °  callbackԼ Ѱ ʹ.  ϰ 
"tag"  Լ ȣν ŸӾƿ ϱ  δ.

       void gtk_timeout_remove (gint tag);

  츮 callbackԼ 0Ǵ FALSE ν  ŸӾƿ Լ
ų  ִ.  翬 ̰ 츮 Լ ӵǱ ؼ 0 ƴ
, ڸ TRUE ؾ  ǹѴ.

  츮 callbackԼ  ̷ · ؾѴ.

       gint timeout_callback (gpointer data);

***
*** 15-2. IO ϱ
***
  GTK Ǵٸ   ϳ, 츮   ĺ(file descriptor)
 ͸ üũ شٴ ̴(open(2) Ȥ socket(2) ϵǴ´).
̰ Ư Ʈ ÿ ϴ.   Լ .

       gint gdk_input_add (gint source,
                           GdkInputCondition condition,
                           GdkInputFunction  function,
                           gpointer data);

  ù° ڴ  ϴ file descriptor, ι° GDK ã 
 ش.  ̰ ̵  ϳ  ̴.

  GDK_INPUT_READ - 츮 file descriptor  غ  Ͱ  
                  츮 Լ ȣѴ.

  GDK_INPUT_WRITE - 츮 file descriptor (write) غ Ǿ 
                   츮 Լ ȣѴ.

  ̹ ġë, ° ڴ     ȣ Լ,
׹°  Լ Ѱ ʹ.

  ϰ GDK file descriptor ϴ  Ʒ Լ ̿ؼ
߰  tag̴.

       void gdk_input_remove (gint tag);

  CallbackԼ Ǿ Ѵ.

       void input_callback (gpointer data, gint source,
                            GdkInputCondition condition);

***
*** 15-3. Idle Լ
***
  ̻ ƹ͵ Ͼ   ȣ Լ ΰ?

       gint gtk_idle_add (GtkFunction function,
                          gpointer data);

  ̰ ̻ ƹ͵ ߻   GTK  Լ ȣϵ
ش.

       void gtk_idle_remove (gint tag);

   Լ ڵ    Ͱ ſ ϱ  ⼭ 
 ʰڴ.  gtk_idle_add ù° ڷ ־ Լ ȸ 
 ȣ ̴.  ٸ ͵ , FALSE ϰ Ǹ idle
Լ ȣ ߴܵ ̴.
**************************
*** 16. Selection ϱ
**************************

***
*** 16-1. 
***
  GTK ϴ μ    ϳ selection̴. 
Selection ڰ 콺 ܰų ؼ õ ؽƮ Ϻΰ, 
 νѴ.  ڰ   ϰ   ִ  ϳ
̸,   ÿ   䱸Ǿ ,  ڴ
selection Ǿ ڿ ǥ ־ Ѵ.  ٸ õ
target̶ Ҹ, ٸ  selection ûѴ.  Selection 
 , κ X õ primary selection̶ θ 
ϳ ٷ.

  κ , GTK  selection ü ٷ ʿ .  Entry widget
 ǥ widget ڰ ؽƮ  콺 巡ϴ  մ
쿡 selection  ɷ ̹  , ׸ ڰ 콺
 ι° ư Ŭϴ ó ٸ ̳ widget  
selection ׸ ã  ִ.  ׷ 츮 ٸ widget selection
 ϴ ɷ  ϰ 쵵  ̸, Ʈ 
ʴ target ã    ̴.

  Selection ٷ⸦ ϱ  ʿ ⺻  atom̶ ̴.
Atom̶  display,  ڿ ϰ   ִ  ̴.
 atom X   ̸ ǵǾ ,  쿣 ̷ atom鿡
 constant gtk.h   ִ.    GDK_PRIMARY_
SELECTION ڿ "PRIMARY" شȴ.  ٸ , 츮  ڿ
 ϴ atom ϱ  gdk_atom_interm(), ׸ atom ̸
ϱ ؼ gdk_atom_name() ̿ؾ Ѵ.  Selection target 
atom Ͽ ĺȴ.

***
*** 16-2. Selection ϱ
***
  Selection ã´ٴ  ϳ 񵿽ü ̴.    
ϱ   Լ ̿Ѵ.

       gint gtk_selection_convert   (GtkWidget           *widget,
                                     GdkAtom              selection,
                                     GdkAtom              target,
                                     guint32              time)

  ̰ target   · selection ȯѴ.   ϴٸ,
time ڴ selection  ̺Ʈκ ð Ǿ Ѵ.  ̰
ڰ û  ̺Ʈ ߻ϴ  Ȯ ش.  ׷ 
̰   ٸ( ȯ "clicked"ñ׳ο  ̷ٸ)
츮  GDK_CURRENT_TIME ̿   ̴. 

  Selecting owner  䱸 ϸ "selection_received" ñ׳
츮 ÿ  ȴ.   ñ׳ο  ڵ鷯 Ʒ  ǵ
GtkSelectionData ü  ͸ ޴´.

       struct _GtkSelectionData
       {
         GdkAtom selection;
         GdkAtom target;
         GdkAtom type;
         gint    format;
         guchar *data;
         gint    length;
       };

   selection target 츮 gtk_selection_convert()Լ  ̴.
 type selection owner  ϵ  Ÿ ĺϴ atom̴. 
  δ ƾ  ڿ "STRING", atom ø "ATOM",
ϳ  "INTEGER"  ִ.  κ target    type
  ִ.   format   ̸ Ʈ   ̴.  ,
͸   ̰Ϳ ؼ Ű澵 ʿ䰡 .   data ϵ
Ϳ  ͸, length   ̸ Ʈ   ̴.
 length   ߻ ̰ selection    
.  ̰  selection   ų, Ǵ   ʴ
target û  Ͼ  ִ ̴.   ۴ length 1Ʈ
 Ǵ  ޴´.   Ʈ  zero  ̰, 
NULLν ڿ    ڿ 纻   ʿ䰡 .

  ̹ , 츮 "TARGETS" Ư target  ̴.  ̰
selection ȯ  ִ  target Ʈ̴.

  #include <gtk/gtk.h>

  void selection_received (GtkWidget *widget,
                           GtkSelectionData *selection_data,
                           gpointer data);

  /* ڰ "Get Targets" ư Ŭ  ûǴ ñ׳ ڵ鷯 */
  void
  get_targets (GtkWidget *widget, gpointer data)
  {
    static GdkAtom targets_atom = GDK_NONE;

    /* ڿ "TARGETS" شϴ atom Ѵ. */
    if (targets_atom == GDK_NONE)
      targets_atom = gdk_atom_intern ("TARGETS", FALSE);

    /* ׸ primary selectionμ "TARGETS" target ûѴ. */
    gtk_selection_convert (widget, GDK_SELECTION_PRIMARY, targets_atom,
                           GDK_CURRENT_TIME);
  }

  /* Selection owner ͸   ҷ ñ׳ ڵ鷯 */
  void
  selection_received (GtkWidget *widget, GtkSelectionData *selection_data,
                      gpointer data)
  {
    GdkAtom *atoms;
    GList *item_list;
    int i;

    /* **** ߿ **** Selection  ϴ üũ . */
    if (selection_data->length < 0)
      {
        g_print ("Selection retrieval failed\n");
        return;
      }
    /*  · ͸  ȮѴ. */
    if (selection_data->type != GDK_SELECTION_TYPE_ATOM)
      {
        g_print ("Selection \"TARGETS\" was not returned as atoms!\n");
        return;
      }

    /* 츮 ع atom ƮѴ. */
    atoms = (GdkAtom *)selection_data->data;

    item_list = NULL;
    for (i=0; i<selection_data->length/sizeof(GdkAtom); i++)
      {
        char *name;
        name = gdk_atom_name (atoms[i]);
        if (name != NULL)
          g_print ("%s\n",name);
        else
          g_print ("(bad atom)\n");
      }

    return;
  }

  int
  main (int argc, char *argv[])
  {
    GtkWidget *window;
    GtkWidget *button;

    gtk_init (&argc, &argv);

    /* Toplevel  . */

    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title (GTK_WINDOW (window), "Event Box");
    gtk_container_border_width (GTK_CONTAINER (window), 10);

    gtk_signal_connect (GTK_OBJECT (window), "destroy",
                        GTK_SIGNAL_FUNC (gtk_exit), NULL);

    /* ڰ target Ϸ Ŭ  ִ ư . */

    button = gtk_button_new_with_label ("Get Targets");
    gtk_container_add (GTK_CONTAINER (window), button);

    gtk_signal_connect (GTK_OBJECT(button), "clicked",
                        GTK_SIGNAL_FUNC (get_targets), NULL);
    gtk_signal_connect (GTK_OBJECT(button), "selection_received",
                        GTK_SIGNAL_FUNC (selection_received), NULL);

    gtk_widget_show (button);
    gtk_widget_show (window);

    gtk_main ();

    return 0;
  }

***
*** 16-3. Selection ϱ
***
  Selection ϴ    ϴ.  츮 츮 selection
ûǾ  ȣ ڵ鷯  ־ Ѵ.  츮 ٷ 
selection/target ֵ鿡  ̷ ȣ ϴ ̴.

       void gtk_selection_add_handler (GtkWidget           *widget,
                                       GdkAtom              selection,
                                       GdkAtom              target,
                                       GtkSelectionFunction function,
                                       GtkRemoveFunction    remove_func,
                                       gpointer             data);

  widget, selection, target  ڵ鷯  û(request) ĺѴ. 
remove_func ڴ ñ׳ ڵ鷯 ŵ  NULL ƴ  ȴ.  ̰
,   Ϳ  reference count Ʈ 
ʿ伺 ִ   ϴ.

  ̷  callback Լ .

       typedef void (*GtkSelectionFunction) (GtkWidget *widget,
                                             GtkSelectionData *selection_data,
                                             gpointer data);

  GtkSelectionData    , ̹ 츮 ʵ带
type, format, data, ׸ length ä Ѵ.  (ʵ format ⼭
 ߿ϴ.  X  Ͱ byte-swapǾ ϴ θ ̰
ν Ѵ.   ̰ 8  ϳ ̰ų, Ǵ 32  
ȴ.)  ̰  Լ ȣؼ ̷.

       void gtk_selection_data_set (GtkSelectionData *selection_data,
                                    GdkAtom           type,
                                    gint              format,
                                    guchar           *data,
                                    gint              length);

   Լ   纻 鵵 ֱ  츮 
̰Ϳ Ű澵 ʿ䰡 .  (츮  GtkSelectionData ʵ ä
 ʾƵ ȴٴ ̴.)

  츮  Լ ȣؼ selection (ownership)   ִ.

       gint gtk_selection_owner_set (GtkWidget           *widget,
                                     GdkAtom              selection,
                                     guint32              time);

   Ǵٸ  selection  Ѵٸ, 츮 "selection_
clear_event" ްԵ ̴. 

  Selection ϴ μ,  α׷  ۹ư selection
 ÷ ̴.   ۹ư  ¶, α׷ primary
selection  ̴.  GTK ü  ־ "TARGETS"  
 ΰ, ⼭ ־  target "STRING" target̴.   target
ûǸ, ð ִ  ڿ ϵȴ.

  #include <gtk/gtk.h>
  #include <time.h>

  /* ڰ selection   ȣǴ callback. */
  void
  selection_toggled (GtkWidget *widget, gint *have_selection)
  {
    if (GTK_TOGGLE_BUTTON(widget)->active)
      {
        *have_selection = gtk_selection_owner_set (widget,
                                                   GDK_SELECTION_PRIMARY,
                                                   GDK_CURRENT_TIME);
        /* Selection 䱸ϴ  ϸ, out state  ư
         * Ѵ. */
        if (!*have_selection)
          gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON(widget), FALSE);
      }
    else
      {
        if (*have_selection)
          {
            /* Selection owner NULL ؼ selection  ,
             * 츮   owner üũ. */
            if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window)
              gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY,
                                       GDK_CURRENT_TIME);
            *have_selection = FALSE;
          }
      }
  }

  /* ٸ  selection   ȣȴ. */
  gint
  selection_clear (GtkWidget *widget, GdkEventSelection *event,
                   gint *have_selection)
  {
    *have_selection = FALSE;
    gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON(widget), FALSE);

    return TRUE;
  }

  /* Selectionμ  ð Ѵ. */
  void
  selection_handle (GtkWidget *widget,
                    GtkSelectionData *selection_data,
                    gpointer data)
  {
    gchar *timestr;
    time_t current_time;

    current_time = time (NULL);
    timestr = asctime (localtime(&current_time));
    /* 츮 ϳ Ʈ  ,  NULL ڷ  
     * ʾƵ ȴ.  ̹ óǾ ֱ ̴. */

    gtk_selection_data_set (selection_data, GDK_SELECTION_TYPE_STRING,
                            8, timestr, strlen(timestr));
  }

  int
  main (int argc, char *argv[])
  {
    GtkWidget *window;

    GtkWidget *selection_button;
    static int have_selection = FALSE;

    gtk_init (&argc, &argv);

    /* Toplevel  . */

    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title (GTK_WINDOW (window), "Event Box");
    gtk_container_border_width (GTK_CONTAINER (window), 10);

    gtk_signal_connect (GTK_OBJECT (window), "destroy",
                        GTK_SIGNAL_FUNC (gtk_exit), NULL);

    /* Selectionμ  ۹ư ϳ . */

    selection_button = gtk_toggle_button_new_with_label ("Claim Selection");
    gtk_container_add (GTK_CONTAINER (window), selection_button);
    gtk_widget_show (selection_button);

    gtk_signal_connect (GTK_OBJECT(selection_button), "toggled",
                        GTK_SIGNAL_FUNC (selection_toggled), &have_selection);
    gtk_signal_connect (GTK_OBJECT(selection_button), "selection_clear_event",
                        GTK_SIGNAL_FUNC (selection_clear), &have_selection);

    gtk_selection_add_handler (selection_button, GDK_SELECTION_PRIMARY,
                               GDK_SELECTION_TYPE_STRING,
                               selection_handle, NULL, NULL);

    gtk_widget_show (selection_button);
    gtk_widget_show (window);

    gtk_main ();

    return 0;
  }



************
*** 17. glib
************

  glib GDK  GTK      Լ ǵ Ѵ.
 ⼭ ׵   Բ  ̴.   ǥ libc
ߺǱ  ׵鿡  ڼ ٷ ʴ´.  ̰ ַ ϳ
μ,   ̿  ִ° ľϰ  ̴.

***
*** 17-1. 
***
    ڷ鿡  extreme  Ǵ ̷.

  G_MINFLOAT
  G_MAXFLOAT
  G_MINDOUBLE
  G_MAXDOUBLE
  G_MINSHORT
  G_MAXSHORT
  G_MININT
  G_MAXINT
  G_MINLONG
  G_MAXLONG

  , typedef鵵 ִ.   ͵  architecture  ٸ
õȴ.  ȣȯ Ϸ  ũ⸦  ȵȴٴ  
϶.  ϳ ʹ Alpha  8Ʈ,  Intel 4Ʈ̴.

       char   gchar;
       short  gshort;
       long   glong;
       int    gint;
       char   gboolean;

       unsigned char   guchar;
       unsigned short  gushort;
       unsigned long   gulong;
       unsigned int    guint;

       float   gfloat;
       double  gdouble;
       long double gldouble;

       void* gpointer;

       gint8
       guint8
       gint16
       guint16
       gint32
       guint32

***
*** 17-2.   Ʈ
***
  Ʒ Լ   Ʈ , ϰ,  ıϱ 
̴ ͵̴.    ḮƮ  ٷ  ⿡, 
 װ ̹ ˰ ִٰ Ѵ.  , װ GTK Ϲ
ӻ ˱   ʿ  ƴ, ׷ ˸  ̴.

  GList* g_list_alloc       (void);

  void   g_list_free        (GList     *list);

  void   g_list_free_1      (GList     *list);

  GList* g_list_append      (GList     *list,
                             gpointer   data);

  GList* g_list_prepend     (GList     *list,
                             gpointer   data);

  GList* g_list_insert      (GList     *list,
                             gpointer   data,
                             gint       position);

  GList* g_list_remove      (GList     *list,
                             gpointer   data);

  GList* g_list_remove_link (GList     *list,
                             GList     *link);

  GList* g_list_reverse     (GList     *list);

  GList* g_list_nth         (GList     *list,
                             gint       n);

  GList* g_list_find        (GList     *list,
                             gpointer   data);

  GList* g_list_last        (GList     *list);

  GList* g_list_first       (GList     *list);

  gint   g_list_length      (GList     *list);

  void   g_list_foreach     (GList     *list,
                             GFunc      func,
                             gpointer   user_data);

***
*** 17-3.  Ʈ
***
   ִ  Լ  ḮƮ鿡 ؼ   ִ ͵
̴.    Լ Ʈ ִ.

  GSList* g_slist_alloc       (void);

  void    g_slist_free        (GSList   *list);

  void    g_slist_free_1      (GSList   *list);

  GSList* g_slist_append      (GSList   *list,
                               gpointer  data);

  GSList* g_slist_prepend     (GSList   *list,
                               gpointer  data);

  GSList* g_slist_insert      (GSList   *list,
                               gpointer  data,
                               gint      position);

  GSList* g_slist_remove      (GSList   *list,
                               gpointer  data);

  GSList* g_slist_remove_link (GSList   *list,
                               GSList   *link);

  GSList* g_slist_reverse     (GSList   *list);

  GSList* g_slist_nth         (GSList   *list,
                               gint      n);

  GSList* g_slist_find        (GSList   *list,
                               gpointer  data);

  GSList* g_slist_last        (GSList   *list);

  gint    g_slist_length      (GSList   *list);

  void    g_slist_foreach     (GSList   *list,
                               GFunc     func,
                               gpointer  user_data);

***
*** 17-4. ޸ 
***

       gpointer g_malloc      (gulong    size);

  ̰ malloc() üϴ ̴.   Լ ο ϰ 
üũ ̷Ƿ 츮  װ  ʿ .

       gpointer g_malloc0     (gulong    size);

   , װ  ͸ ϱ  0̴.

  gpointer g_realloc     (gpointer  mem,
                          gulong    size);

  "mem" Ͽ "size"ŭ Ʈ ٽ ҴѴ.    ޸𸮴
 ҴǾ ־ Ѵ.

       void     g_free        (gpointer  mem);

  ϴ, ޸𸮸 ݳѴ.

       void     g_mem_profile (void);

   ޸ profile Ƴ ش.   ̰  ؼ 츮
glib/gmem.c  κп #define MEM_PROFILE ְ make ٽ ؾ
Ѵ.

       void     g_mem_check   (gpointer  mem);

  ޸ ġ ȿ  üũѴ.  gmem.c  κп #define
MEM_CHECK ְ make ٽ ؾ Ѵ.

***
*** 17-5. Ÿ̸
***
  Ÿ̸ Լ̴.

       GTimer* g_timer_new     (void);

       void    g_timer_destroy (GTimer  *timer);

       void    g_timer_start   (GTimer  *timer);

       void    g_timer_stop    (GTimer  *timer);

       void    g_timer_reset   (GTimer  *timer);

       gdouble g_timer_elapsed (GTimer  *timer,
                                gulong  *microseconds);

***
*** 17-6. ڿ ٷ
***
  ڿ ٷ Լ̴.  ̵   ̷Ӱ,  ǥ C
ڿ Լ麸   ɵ  ̴.   ̵鿡  ʿ
 ̴.

       GString* g_string_new       (gchar   *init);
       void     g_string_free      (GString *string,
                                    gint     free_segment);

       GString* g_string_assign    (GString *lval,
                                    gchar   *rval);

       GString* g_string_truncate  (GString *string,
                                    gint     len);

       GString* g_string_append    (GString *string,
                                    gchar   *val);

       GString* g_string_append_c  (GString *string,
                                    gchar    c);

       GString* g_string_prepend   (GString *string,
                                    gchar   *val);

       GString* g_string_prepend_c (GString *string,
                                    gchar    c);

       void     g_string_sprintf   (GString *string,
                                    gchar   *fmt,
                                    ...);

       void     g_string_sprintfa  (GString *string,
                                    gchar   *fmt,
                                    ...);

***
*** 17-7. Utility  Error Լ
***

       gchar* g_strdup    (const gchar *str);

  strdupԼ üѴ.   ڿ Ӱ Ҵ ޸𸮿 ϰ,
   ͸ Ѵ.

       gchar* g_strerror  (gint errnum);

    ޽  Լ ̿  Ѵ.  ̰ perror() ٸ
ͺ ξ , Ȯ强  ̴.    ̷ ̴.

       program name:function that failed:file or further description:strerror

  ̰ 츮 hello_world α׷  ̴.

       g_print("hello_world:open:%s:%s\n", filename, g_strerror(errno));

       void g_error   (gchar *format, ...);

   ޽ Ѵ.   printf ,  ոӸ "** ERROR
**: " ̰, ׸ α׷ .  ġ  ϶.

       void g_warning (gchar *format, ...);

   ,  "** WARNING **: " ոӸ ̰,  α׷
 ʴ´.

       void g_message (gchar *format, ...);

  츮 Ϸ ڿ "message: " տ ٿ ش.

       void g_print   (gchar *format, ...);

  printf üѴ.

  ׸ 츮  Լ ̴̰.

       gchar* g_strsignal (gint signum);

  ڷ  ñ׳ ȣ شϴ н ý ñ׳ ̸ ش.
ټ ñ׳ ٷ Լ鿡 ϴ.

   Ұ  ͵ glib.h ̷ ο ̴.   
  Լ  ȭ ϰڴٸ,  email ֱ!



*********************
*** 18. GTK rc 
*********************

  GTK rc  ̿ؼ  Ʈ ȯ ٷ.  ̵ ռ 
 widget   濡  pixmap   ִ.

***
*** 18-1. rc   Լ
***
   ϴ κп  Լ ԽŰ.

       void gtk_rc_parse (char *filename);

  ڴ 츮 rc  ̸̴.  ̰ GTK   о widget
Ÿ װ ǵ  ϵ Ѵ.

   widget ߿ ٸ ͵ Ǿ  Ư Ÿ  
 ִٸ, Ǵ ٸ  widget  зϷ,  Լ
̿Ѵ.

       void gtk_widget_set_name (GtkWidget *widget,
                                 gchar *name);

  ù° ڷ   widget ְ, ι° ڴ װͿ οϰ
ϴ ̸̴.  ̰  widget Ӽ rc Ͽ ִ ̸ Ͽ
ٲ  ְ Ѵ.

  ̷  Լ ȣߴٰ  .

       button = gtk_button_new_with_label ("Special Button");
       gtk_widget_set_name (button, "special button");

  ׷  ư "special button" ̸ٰ rc Ͽ "special button.
GtkButton"̶ ̸  ̴.  (Ȯ !)

  Ʒ rc   main  Ӽ ϰ,  main  child
 "main button" Ÿ ӹް ȴ.   ÿ  ڵ ̷
ȴ.

       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
       gtk_widget_set_name (window, "main window");

  ׸ rc Ͽ ǵǴ Ÿ ̷ ȴ.

       widget "main window.*GtkButton*" style "main_button"

  "main window" ִ  GtkButton widget rc Ͽ  "main_
buttons" Ÿϴ Ѵ.

  ٽ, ̰  ϰ  ý̴.  ̰ ְ
ȿ       ٶ.

***
*** 18-2. GTK rc  
***
  GTK rc   ڵ   ִ.  ̰ GTK 
Բ ִ testgtkrc ̰,  ణ ּ   ߴ.  
̰ ÿ ԽѼ ڵ ̿ϰ    ̴.

  Widget Ӽ ȭų    ͵ ִ.

  o fg - Widget foreground 

  o bg - Widget background 

  o bg_pixmap - Widget background  Ƚ

  o font - ־ widget  Ʈ

  ̰͵鿡 ٿ, widget鿡   ִ  state ְ, 츮
ٸ , Ƚ, ׸ Ʈ  ¿    ִ.   state
 .

  o NORMAL - Widget  .  콺  widget   ʾҰ,
                 ´.

  o PRELIGHT - 콺 Ͱ  widget   Ǹ,  state
                 ȿ  ȴ.

  o ACTIVE - Widget ų ŬǸ activḛ,  tag ؼ
             ǵ Ӽ ȿ .

  o INSENSITIVE -  widget insensitive, ׸ active  
                  õǸ ⼭ Ӽ  ȴ.

  o  SELECTED - Object selectedǸ ⼭ Ӽ  ȴ.

  Widget  ȭŰ Ű "fg" "bg"   
̷.

       fg[<STATE>] = { Red, Green, Blue }

  ⼭ STATE  ǥ(PRELIGHT, ACTIVE )  ϳ, Red, Green,
Blue 0 1 εҼ .  ̵ ݵ εҼ ǥǾ
ϸ, ׷  0 νĵ ̴.  "1"  ʴ´,  "1.0"
 ؾ Ѵ.  ܼ "0"̶ ϴ  νĵ ʴ  0̹Ƿ
 ̴.

  bg_pixmap   ſ ϴ, color filename ġ .

  pixmap_path ":" е  Ʈ.   δ 츮 
  Ƚ̶ ã ̴.

  font  ̷Ը ϸ ȴ.

       font = "<font name>"

   ϳ   ִٸ Ʈ ̸ ڿ ٷ ̴.  xfontsel
̳  ƿƼ   ̴.

  "widget_class" widget Ŭ Ÿ Ѵ.   Ŭ
widget  κп  Ŭ   ִ.

  "widget" , ̸ ٿ widget  ־ Ÿϴ
ϸ, ־ widget Ŭ   Ÿ̶ εѴ.  ̷
widget gtk_widget_set_name() Լ   ο ϵǾ ִ.
̰ widget Ŭ üΰ ƴ϶  widget basis ϰ ִ
  widget Ư    ֵ Ѵ.  ڵ  
ؼ ̿ ֵ, ̷ Ư widget̶  ȭ   
ϴ ̴.

  Ű "parent" Ӽ  ̸,  widget parent Ӽ 
ȴ.

  Ÿ ϸ鼭,  ǵ Ÿ ο Ϳ  ִ ͵
ϴ.

       style "main_button" = "button"
       {
         font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*"
         bg[PRELIGHT] = { 0.75, 0, 0 }
       }

    "button" Ÿ ؼ,  ̰Ϳ font prelight
background color ٲٴ  ο "main_button" Ÿ .

  , ̷ Ӽ   ͵  widget  밡  ƴϴ.
̰ ̰  ̴.  밡  ִٸ ϸ ȴ.

***
*** 18-3. rc  
***

  # pixmap_path "<dir 1>:<dir 2>:<dir 3>:..."
  #
  pixmap_path "/usr/include/X11R6/pixmaps:/home/imain/pixmaps"
  #
  # style <name> [= <name>]
  # {
  #   <option>
  # }
  #
  # widget <widget_set> style <style_name>
  # widget_class <widget_class_set> style <style_name>

  # ̰  state Ʈ.  ̵  Ϻδ Ư widget鿡
  # ؼ   ϶.
  #
  # NORMAL - The normal state of a widget, without the mouse over top of
  # it, and not being pressed etc.
  #
  # PRELIGHT - When the mouse is over top of the widget, colors defined
  # using this state will be in effect.
  #
  # ACTIVE - When the widget is pressed or clicked it will be active, and
  # the attributes assigned by this tag will be in effect.
  #
  # INSENSITIVE - When a widget is set insensitive, and cannot be
  # activated, it will take these attributes.
  #
  # SELECTED - When an object is selected, it takes these attributes.
  #
  # Given these states, we can set the attributes of the widgets in each of
  # these states using the following directives.
  #
  # fg - Sets the foreground color of a widget.
  # fg - Sets the background color of a widget.
  # bg_pixmap - Sets the background of a widget to a tiled pixmap.
  # font - Sets the font to be used with the given widget.
  #

  # ⼭ "button"̶ Ҹ Ÿ Ѵ.    κп
  #  widget ǰ Ƿ ⼭ ̸ ߿ ʴ.

  style "window"
  {
    # ̰ ־ Ƚ  е Ѵ.
    #bg_pixmap[<STATE>] = "<pixmap filename>"
    bg_pixmap[NORMAL] = "warning.xpm"
  }

  style "scale"
  {
    # "NORMAL" state foreground(font)  red Ѵ.

    fg[NORMAL] = { 1.0, 0, 0 }

    #  widget background pixmap parent װ Ѵ.
    bg_pixmap[NORMAL] = "<parent>"
  }

  style "button"
  {
    # ⼭  ư Ͽ   state ش.   ϳ
    #  ʴ  SELECTED state.

    fg[PRELIGHT] = { 0, 1.0, 1.0 }
    bg[PRELIGHT] = { 0, 0, 1.0 }
    bg[ACTIVE] = { 1.0, 0, 0 }
    fg[ACTIVE] = { 0, 1.0, 0 }
    bg[NORMAL] = { 1.0, 1.0, 0 }
    fg[NORMAL] = { .99, 0, .99 }
    bg[INSENSITIVE] = { 1.0, 1.0, 1.0 }
    fg[INSENSITIVE] = { 1.0, 0, 1.0 }
  }

  #  , 츮 "button" Ÿ Ӽ ӹ޴´.  ׸ 
  #  "main_button" Ÿ  ɶ font background 
  #  ؼ .

  style "main_button" = "button"
  {
    font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*"
    bg[PRELIGHT] = { 0.75, 0, 0 }
  }

  style "toggle_button" = "button"
  {
    fg[NORMAL] = { 1.0, 0, 0 }
    fg[ACTIVE] = { 1.0, 0, 0 }

    # toggle_button background pixmap װ parent widget(ÿ
    # ǵȴ) Ӽ Ѵ.
    bg_pixmap[NORMAL] = "<parent>"
  }

  style "text"
  {
    bg_pixmap[NORMAL] = "marble.xpm"
    fg[NORMAL] = { 1.0, 1.0, 1.0 }
  }

  style "ruler"
  {
    font = "-adobe-helvetica-medium-r-normal--*-80-*-*-*-*-*-*"
  }

  # pixmap_path "~/.pixmaps"

  # ̵ widget ŸԵ  ǵ ŸϿ  Ѵ.
  # Widget ŸԵ Ŭ  ƮǾ ,   Ʈ
  # ͵鵵 ڵ鿡     ִ.

  widget_class "GtkWindow" style "window"
  widget_class "GtkDialog" style "window"
  widget_class "GtkFileSelection" style "window"
  widget_class "*Gtk*Scale" style "scale"
  widget_class "*GtkCheckButton*" style "toggle_button"
  widget_class "*GtkRadioButton*" style "toggle_button"
  widget_class "*GtkButton*" style "button"
  widget_class "*Ruler" style "ruler"
  widget_class "*GtkText" style "text"

  # ̰  ư("main window" children) main_button Ÿ
  #  Ѵ.
  widget "main window.*GtkButton*" style "main_button"
******************************
*** 19. ڽŸ widget 
******************************

***
*** 19-1. 
***
   GTK ǿ ԵǾ ִ  widget κ ⺻
䱸  ,   ο widget   
 ̴.  GTK widget  ϰ ̿ϰ    ִ
widget  䱸  ͵̱ , ϰ ο widget
 ͵    ڵν   ִ.  ׷ ο widget
 ۾ ϱ ,   װ ̹   ʾҴ
üũ.  ̷ ؼ  ߺ   GTK widget  ּ
  ִ.  ̰  ٸ õ ̿ ڵ ̽ 
ϼ ϴ ̴.  ̷ ϴ Ѱ ,  
ڽŸ widget ϼϰ Ǹ, װ ٸ   ̿  ְ
迡 θ ˸.  ̷   ִ   Ҵ Ƹ gtk-list
̴.

***
*** 19-2. Widget 
***
  ο widget   ־, GTK object  ϴ 
ϴ  ߿ ̴.  ̹   ª 丸 Ұϰ Ѵ.
ڼ    .

  GTK widget ü  Ѵ.  ׷, ׵ ǥ C
.  ̰   C++ Ϸ  ͺ ̽ļ 
ũ Ų.   ̰ widget ۼڰ    Ǹ
￩߸ ϴ  ǹѴ.   Ŭ widget(ڸ  Button
widget) instance ο   class structure Ǿ
ִ.   class ñ׳ε Լ  ,  callback Լ ó
ǰ, C++ virtual Լó ϳ 纻  ش.  
ϱ ؼ, class structure ù° ʵ parent class structure
copy Ǿ Ѵ.  GtkButton̶ class structure  ̷ ȴ.  

       struct _GtkButtonClass
       {
         GtkContainerClass parent_class;

         void (* pressed)  (GtkButton *button);
         void (* released) (GtkButton *button);
         void (* clicked)  (GtkButton *button);
         void (* enter)    (GtkButton *button);
         void (* leave)    (GtkButton *button);
       };

  ư ϳ ̳ʷ ٷٸ(, resizeǾ ), װ
class structure GtkContainerClass ĳƮ  ְ,  ñ׳ε ٷ
 õ ʵ ̰ ȴ.

  ϳ instance basis    widget  ü ִ.
 ü  widget  instance   ٸ  
ִ.  츮  ü object structure θ ̴.  ư Ŭ
 ٸ ̷ ȴ.

       struct _GtkButton
       {
         GtkContainer container;

         GtkWidget *child;

         guint in_button : 1;
         guint button_down : 1;
       };

  Class structure  ù° ʵ parent class object
structure ϶.  ׷  ü ʿ  parent class
object ĳƮ  ִ ̴.

***
*** 19-3. Composite(ռ,ȥ) widget 
***

***
*** 19-3.1. Ұ
***
  츮  ϴ  widget  ٸ GTK widget ü 
 ִ.  ̷ widget  ο     ƴ,
뼺   ̽ ҵ Ű¡ϴ  ־ 
 Ѵ.  ǥ GTK ǿ ִ FileSelection ColorSelection
widget   ̴.

  츮 ⼭   Tictactoe widget, ۹ư 3x3 迭
    Ǵ  Ǵ 밢 ΰ  Ǹ ñ׳ 
.

***
*** 19-3.2. Parent class 
***
   composite widget parent class  composite widget 
  ִ ̳ Ŭ̴.  , FileSelection widget
parent class Dialog Ŭ̴.  츮 ư table ȿ þ  
̹Ƿ, parent class GtkTable Ŭ Ǵ  ڿ.  ,
̰  ʴ´.   widget    Լ  
.  WIDGETNAME_new() Լ ڰ θ, ׸ WIDGETNAME_init()
Լ _new()Լ ڷ ־ widget鿡  ⺻ ʱȭ ۾
Ѵ.  Descendent widget  ׵ parent widget _init()Լ
θ ȴ.  ׷  ۾  ̺ ؼ   ʴ´. 
̺ 쿡       ʿ伺 ֱ ̴. 
׷  츮  Tictactoe widget ִ gtk_table_new() κ
ɵ ߺؼ ̿ϰ  ̴.  ׷Ƿ, 츮  װ GtkVBox
κ ̲, 츮 ̺ VBox η ٿ ̴.

***
*** 19-3.3.  
***
   widget class public Լ ü  ü  ִ 
  ִ.  ⼭  캸.  ߺ Ǹ ϱ ؼ,
츮  ü ̷ ѷѴ.

  #ifndef __TICTACTOE_H__
  #define __TICTACTOE_H__
  #endif /* __TICTACTOE_H__ */

  ׸ C++ α׷ ؼ ̰͵ ߰Ѵ.

       #ifdef __cplusplus
       extern "C" {
       #endif /* __cplusplus */
       #ifdef __cplusplus
       }
       #endif /* __cplusplus */

  Լ ü鿡 , 츮    ǥ ũθ
Ѵ.   TICTACTOE(obj), TICTACTOE_CLASS(klass), IS_TICTACTOE(obj)̴.
̵   ͸ object Ȥ class structure  ͷ ĳƮ
ϰ,  object Tictactoe widget üũϴ  Ѵ.

  ̰  ̴.

  #ifndef __TICTACTOE_H__
  #define __TICTACTOE_H__

  #include <gdk/gdk.h>
  #include <gtk/gtkvbox.h>

  #ifdef __cplusplus
  extern "C" {
  #endif /* __cplusplus */

  #define TICTACTOE(obj)          GTK_CHECK_CAST (obj, tictactoe_get_type (), Tictactoe)
  #define TICTACTOE_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, tictactoe_get_type (), TictactoeClass)
  #define IS_TICTACTOE(obj)       GTK_CHECK_TYPE (obj, tictactoe_get_type ())

  typedef struct _Tictactoe       Tictactoe;
  typedef struct _TictactoeClass  TictactoeClass;

  struct _Tictactoe
  {
    GtkVBox vbox;

    GtkWidget *buttons[3][3];
  };

  struct _TictactoeClass
  {
    GtkVBoxClass parent_class;

    void (* tictactoe) (Tictactoe *ttt);
  };

  guint          tictactoe_get_type        (void);
  GtkWidget*     tictactoe_new             (void);
  void           tictactoe_clear           (Tictactoe *ttt);

  #ifdef __cplusplus
  }
  #endif /* __cplusplus */

  #endif /* __TICTACTOE_H__ */

***
*** 19-3.4. _get_type() Լ
***
   츮 widget  ٵ .   widget鿡  ٽ(core)
Լ WIDGETNAME_get_type()̴.   Լ ó ȣǾ , GTK
widget class  ˷ش.  ׸ widget class Ȯ ĺϴ ID
Ѵ.   ȣϸ ٷ  ID Ѵ.

  guint
  tictactoe_get_type ()
  {
    static guint ttt_type = 0;

    if (!ttt_type)
      {
        GtkTypeInfo ttt_info =
        {
          "Tictactoe",
          sizeof (Tictactoe),
          sizeof (TictactoeClass),
          (GtkClassInitFunc) tictactoe_class_init,
          (GtkObjectInitFunc) tictactoe_init,
          (GtkArgFunc) NULL,
        };

        ttt_type = gtk_type_unique (gtk_vbox_get_type (), &ttt_info);
      }

    return ttt_type;
  }

  ü GtkTypeInfo   ǵǾ.

       struct _GtkTypeInfo
       {
         gchar *type_name;
         guint object_size;
         guint class_size;
         GtkClassInitFunc class_init_func;
         GtkObjectInitFunc object_init_func;
         GtkArgFunc arg_func;
       };

   ü  ʵ  ̴ ״δ.  츮 ⼭ arg_func ʵ
  ̴.  ̰   ԵǾ widget ɼǵ
ϰ   ֵ ϴ ߿    ,  밳
߾ ʾҴ.  ϴ GTK  ü   纻  Ǹ,
װ Ư widget type object   ˰ ȴ.

***
*** 19-3.5. _class_init() Լ
***
  WIDGETNAME_class_init() Լ widget class structure ִ ʵ
ʱȭϰ,  Ŭ  ñ׳ε鵵 ¾ ش.  츮 Tictactoe
widget ؼ ̰ ̷ .

  enum {
    TICTACTOE_SIGNAL,
    LAST_SIGNAL
  };

  static gint tictactoe_signals[LAST_SIGNAL] = { 0 };

  static void
  tictactoe_class_init (TictactoeClass *class)
  {
    GtkObjectClass *object_class;

    object_class = (GtkObjectClass*) class;

    tictactoe_signals[TICTACTOE_SIGNAL] = gtk_signal_new ("tictactoe",
                                           GTK_RUN_FIRST,
                                           object_class->type,
                                           GTK_SIGNAL_OFFSET (TictactoeClass, tictactoe),
                                           gtk_signal_default_marshaller, GTK_ARG_NONE, 0);

    gtk_object_class_add_signals (object_class, tictactoe_signals, LAST_SIGNAL);

    class->tictactoe = NULL;
  }

  츮 widget   ñ׳ 'tictactoe' ñ׳η, ̰  ,
, Ȥ 밢   ä 䱸ȴ.   ռ widget ñ׳
 ʿ ϴ  ƴϸ,    κ ó а ִ 
  (section) Ѿ .   κ ټ  ̱
̴.

   Լ .

       gint   gtk_signal_new (gchar               *name,
                              GtkSignalRunType     run_type,
                              gint                 object_type,
                              gint                 function_offset,
                              GtkSignalMarshaller  marshaller,
                              GtkArgType           return_val,
                              gint                 nparams,
                              ...);

  ο ñ׳ .  ⿡  ڵ 캸.

  o name: ñ׳ ̸

  o run_type: Ʈ ڵ鷯  ڵ鷯 ռ Ȥ
    ڵ ۵ϴ Ѵ.  ٸ ɼ鵵 , 
    ̰ GTK_RUN_FIRST Ǵ GTK_RUN_LAST ȴ.

  o object_type:  ñ׳  object ID. ( object
    descendents )

  o function_offset: Ʈ ڵ鷯 Ű 
    class structure  ɼ.

  o marshaller: ñ׳ ڵ鷯 ҷ  ̴ Լ.
    ñ׳ΰ  ͸ ߻ object ڷ 
    ñ׳ ڵ鷯 , 츮 ̹ Ǵ marshaller Լ
    gtk_signal_default_marshaller ̿  ִ.

  o return_val: ϰ Ÿ.

  o nparams: ñ׳ ڵ鷯  . ( ޵  Ʈ
     ̿ ٸ ͵)

  Ÿ ϱ , GtkArgType̶ enumeration δ.

       typedef enum
       {
         GTK_ARG_INVALID,
         GTK_ARG_NONE,
         GTK_ARG_CHAR,
         GTK_ARG_SHORT,
         GTK_ARG_INT,
         GTK_ARG_LONG,
         GTK_ARG_POINTER,
         GTK_ARG_OBJECT,
         GTK_ARG_FUNCTION,
         GTK_ARG_SIGNAL
       } GtkArgType;

  gtk_signal_new() ñ׳ο    ĺڸ Ѵ.  츮
̵ tictactoe_signals 迭 ϰ, enumeration ̿ؼ ε
ش. ( enumeration ҵ 빮ڷ ñ׳ ̸ Ÿ
, ⼭ TICTACTOE() ũο 浹  ֱ , 츮 ̵
TICTACTOE_SIGNAL̶ θ.)

  ñ׳ ٸ,  GTK  ñ׳ε Tictactoe Ŭ Ű
 ؾ Ѵ.   ۾ gtk_object_class_add_signals() ش.  ׸
ƹ Ʈ  ٴ  Ÿ , tictactoe ñ׳  Ʈ
ڵ鷯 Ű ִ ͸ NULL Ѵ.

***
*** 19-3.6. _init() Լ
***
   widget Ŭ  object structure ʱȭ  Լ ʿ Ѵ.
,  Լ ü ʵ Ʈ  ϴ  ѵ
  ִ.  ׷ ռ widget ,  Լ  Ǵٸ
widget  ֱ⵵ Ѵ.

  static void
  tictactoe_init (Tictactoe *ttt)
  {
    GtkWidget *table;
    gint i,j;

    table = gtk_table_new (3, 3, TRUE);
    gtk_container_add (GTK_CONTAINER(ttt), table);
    gtk_widget_show (table);

    for (i=0;i<3; i++)
      for (j=0;j<3; j++)
        {
          ttt->buttons[i][j] = gtk_toggle_button_new ();
          gtk_table_attach_defaults (GTK_TABLE(table), ttt->buttons[i][j],
                                     i, i+1, j, j+1);
          gtk_signal_connect (GTK_OBJECT (ttt->buttons[i][j]), "toggled",
                              GTK_SIGNAL_FUNC (tictactoe_toggle), ttt);
          gtk_widget_set_usize (ttt->buttons[i][j], 20, 20);
          gtk_widget_show (ttt->buttons[i][j]);
        }
  }

***
*** 19-3.7. ׸ ...
***
   widget(GtkBinó ޸    base widget )
 ־  Լ ϳ  ִ.  ٷ  شϴ Ÿ object
  Լ.  ̰ ʻ WIDGETNAME_new() ȴ.  Tictactoe
widget ش , Ϻ widget  Լ ڸ ,
׸  ڸ ؼ  ¾ ϱ⵵ Ѵ.  ٸ  Լ 츮
Tictactoe widget  Ư ͵̴.

  tictactoe_clear() widget ִ  ư up ·  ش.  ư
  츮 ñ׳ ڵ鷯 ʿϰ صǴ  ֱ 
gtk_signal_handler_block_by_data() ̿ϴ  .

  tictactoe_toggle() ڰ  ư Ŭ  ûǴ ñ׳
ڵ鷯.  ̰ ۵ ư   ŷ ޺(combination)
̷ üũϰ,  ׷ٸ "tictactoe" ñ׳ ߻Ų.

  GtkWidget*
  tictactoe_new ()
  {
    return GTK_WIDGET ( gtk_type_new (tictactoe_get_type ()));
  }

  void
  tictactoe_clear (Tictactoe *ttt)
  {
    int i,j;

    for (i=0;i<3;i++)
      for (j=0;j<3;j++)
        {
          gtk_signal_handler_block_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
          gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (ttt->buttons[i][j]),
                                       FALSE);
          gtk_signal_handler_unblock_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
        }
  }

  static void
  tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt)
  {
    int i,k;

    static int rwins[8][3] = { { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
                               { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
                               { 0, 1, 2 }, { 0, 1, 2 } };
    static int cwins[8][3] = { { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
                               { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
                               { 0, 1, 2 }, { 2, 1, 0 } };

    int success, found;

    for (k=0; k<8; k++)
      {
        success = TRUE;
        found = FALSE;

        for (i=0;i<3;i++)
          {
            success = success &&
              GTK_TOGGLE_BUTTON(ttt->buttons[rwins[k][i]][cwins[k][i]])->active;
            found = found ||
              ttt->buttons[rwins[k][i]][cwins[k][i]] == widget;
          }

        if (success && found)
          {
            gtk_signal_emit (GTK_OBJECT (ttt),
                             tictactoe_signals[TICTACTOE_SIGNAL]);
            break;
          }
      }
  }

  ׸ 츮 Tictactoe widget ̿  α׷ 
̴̰.

  #include <gtk/gtk.h>
  #include "tictactoe.h"

  /*  , , Ȥ 밢   Ǹ ûȴ. */
  void
  win (GtkWidget *widget, gpointer data)
  {
    g_print ("Yay!\n");
    tictactoe_clear (TICTACTOE (widget));
  }

  int
  main (int argc, char *argv[])
  {
    GtkWidget *window;
    GtkWidget *ttt;

    gtk_init (&argc, &argv);

    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

    gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");

    gtk_signal_connect (GTK_OBJECT (window), "destroy",
                        GTK_SIGNAL_FUNC (gtk_exit), NULL);

    gtk_container_border_width (GTK_CONTAINER (window), 10);

    /* Tictactoe widget ϳ . */
    ttt = tictactoe_new ();
    gtk_container_add (GTK_CONTAINER (window), ttt);
    gtk_widget_show (ttt);

    /* ׸ ̰ "tictactoe" ñ׳ο ս д. */
    gtk_signal_connect (GTK_OBJECT (ttt), "tictactoe",
                        GTK_SIGNAL_FUNC (win), NULL);

    gtk_widget_show (window);

    gtk_main ();

    return 0;
  }

***
*** 19-4. (from scratch) widget 
***

***
*** 19-4.1. Ұ
***
  ̹ ǿ widget  ڽŵ  ũ ̰ ϴ,
׸ ̺Ʈ ȣۿ ϴ   ̴.  ̿   츮
Ͱ ޷ִ Ƴα ̾(analog dial) widget , ڰ
װ   ϵ  ̴.

***
*** 19-4.2. ũ widget ̱
***
  ũ ֱ ؼ  ܰ谡 ִ.  Widget WIDGETNAME_new()
ν  ,  Լ  ʿϴ.

  o شϴ widget  WIDGETNAEME_realize() X ش.

  o WIDGETNAME_map() ڰ gtk_widget_show() ȣ Ŀ ûȴ.
    ̴ widget  ũ  ׷(mapped)  ȮѴ.
    ̳ Ŭ , ü child widget ϱ  ȣ 
    ʿϴ.

  o WIDGETNAME_draw() widget Ȥ װ ancestor  gtk_widget_draw()
     ȣǾ  ûǴ ̴.  ̰ widget ũ ׸ 
     ׸ Լ ȣ ش.  ̳ widget 쿣 װ child
    widget  gtk_widget_draw() ȣ  Ѵ.

  o  WIDGETNAME_expose() expose ̺Ʈ  ڵ鷯.  ̰ ũ
     expose  ׷ֱ  ʿ Լ ȣѴ.  ̳ widget
      ,  Լ ڽŸ   ʴ child widget鿡 
     expose ̺Ʈ ߻ش. ( ׵  ٸ, ʿ
     expose ̺Ʈ X ߻Ų.)

      Լ ؾ  ̴.    Ÿ
widget    ״  ʴ´.  Widget Ŭ
Ʈ draw() Լ  ٽ ׷    expose ̺Ʈ
߻ų ̴.  ׷  Ÿ widget  Լ ν ۾
ּȭϱ⵵ Ѵ.     X  widget  
(affected)  ٽ ׷  ִµ, ̰ ܼ draw() ȣϴ
δ Ұ ̴.

  ̳ widget    ڱ ڽ  ,
׵ child widget θ и ؾ ϹǷ,  Ʈ draw()
Լ   .  ,  Լ ̿ ׸ ڵ带 ߺϴ 
.  ̷ widget  WIDGETNAME_paint()  Ҹ Լ
.   Լ widget  ׸  ϸ, draw()  expose()
Լ  Ҹ ȴ.

  츮  dial widget ̳ʰ ƴϸ  ϳ  
 , 츮 ϰ  ذ  ִ.   Ʈ draw() ̿
ϰ  expose() Լ .

***
*** 19-4.3. Dial Widget 
***
      ó  缭  ó,
Gtk widget鵵   widget  ϴ  ִ.  ׷,
 (section) "Creating a Widget from Scratch"  Ǿ ,
Dial widget  Range widget ڵ忡 Ѵ.  ̴  Range
widget Ļ Scale widget Ȱ ̽, 츮 Dial widget
  ִٸ  ̶ .      
 scale widget ۿ뿡  ͼ ʴٸ,  ׵鿡  ˾
 ͵   ̴.

***
*** 19-4.4. 
***
  츮 widget  κ Tictactoe widget  ϰ  ̴.  
  .

  /* GTK - The GIMP Toolkit
   * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
   *
   * This library is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Library General Public
   * License as published by the Free Software Foundation; either
   * version 2 of the License, or (at your option) any later version.
   *
   * This library is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Library General Public License for more details.
   *
   * You should have received a copy of the GNU Library General Public
   * License along with this library; if not, write to the Free
   * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   */

  #ifndef __GTK_DIAL_H__
  #define __GTK_DIAL_H__

  #include <gdk/gdk.h>
  #include <gtk/gtkadjustment.h>
  #include <gtk/gtkwidget.h>

  #ifdef __cplusplus
  extern "C" {
  #endif /* __cplusplus */

  #define GTK_DIAL(obj)          GTK_CHECK_CAST (obj, gtk_dial_get_type (), GtkDial)
  #define GTK_DIAL_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, gtk_dial_get_type (), GtkDialClass)
  #define GTK_IS_DIAL(obj)       GTK_CHECK_TYPE (obj, gtk_dial_get_type ())

  typedef struct _GtkDial        GtkDial;
  typedef struct _GtkDialClass   GtkDialClass;

  struct _GtkDial
  {
    GtkWidget widget;

    /* policy ƮѴ(GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]). */
    guint policy : 2;

    /*   ư,  ʾҴٸ 0. */
    guint8 button;

    /* ̾ ҵ ġ. */
    gint radius;
    gint pointer_width;

    /* Ʈ Ÿ̸ ID, Ʈ  0. */
    guint32 timer;

    /*  . */
    gfloat angle;

    /* Adjustment   , 츮  ȭ ˾Ƴ  ִ. */
    gfloat old_value;
    gfloat old_lower;
    gfloat old_upper;

    /* ̾ ͸ ϴ adjustment object. */
    GtkAdjustment *adjustment;
  };

  struct _GtkDialClass
  {
    GtkWidgetClass parent_class;
  };

  GtkWidget*     gtk_dial_new                    (GtkAdjustment *adjustment);
  guint          gtk_dial_get_type               (void);
  GtkAdjustment* gtk_dial_get_adjustment         (GtkDial      *dial);
  void           gtk_dial_set_update_policy      (GtkDial      *dial,
                                                  GtkUpdateType  policy);

  void           gtk_dial_set_adjustment         (GtkDial      *dial,
                                                  GtkAdjustment *adjustment);
  #ifdef __cplusplus
  }
  #endif /* __cplusplus */

  #endif /* __GTK_DIAL_H__ */

  ̰  widget ΰ ƴϰ  ü ʵ  , ٸ
͵    Ͱ ϴ.

    (include)ϰ,   (constant) ϰ,
widget   ϰ װ ʱȭ ִ Լ ִ.

  #include <math.h>
  #include <stdio.h>
  #include <gtk/gtkmain.h>
  #include <gtk/gtksignal.h>

  #include "gtkdial.h"

  #define SCROLL_DELAY_LENGTH  300
  #define DIAL_DEFAULT_SIZE 100

  /*  κ  */

  [  Ƴ  . ]

  /*   */

  static GtkWidgetClass *parent_class = NULL;

  guint
  gtk_dial_get_type ()
  {
    static guint dial_type = 0;

    if (!dial_type)
      {
        GtkTypeInfo dial_info =
        {
          "GtkDial",
          sizeof (GtkDial),
          sizeof (GtkDialClass),
          (GtkClassInitFunc) gtk_dial_class_init,
          (GtkObjectInitFunc) gtk_dial_init,
          (GtkArgFunc) NULL,
        };

        dial_type = gtk_type_unique (gtk_widget_get_type (), &dial_info);
      }

    return dial_type;
  }

  static void
  gtk_dial_class_init (GtkDialClass *class)
  {
    GtkObjectClass *object_class;
    GtkWidgetClass *widget_class;

    object_class = (GtkObjectClass*) class;
    widget_class = (GtkWidgetClass*) class;

    parent_class = gtk_type_class (gtk_widget_get_type ());

    object_class->destroy = gtk_dial_destroy;

    widget_class->realize = gtk_dial_realize;
    widget_class->expose_event = gtk_dial_expose;
    widget_class->size_request = gtk_dial_size_request;
    widget_class->size_allocate = gtk_dial_size_allocate;
    widget_class->button_press_event = gtk_dial_button_press;
    widget_class->button_release_event = gtk_dial_button_release;
    widget_class->motion_notify_event = gtk_dial_motion_notify;
  }

  static void
  gtk_dial_init (GtkDial *dial)
  {
    dial->button = 0;
    dial->policy = GTK_UPDATE_CONTINUOUS;
    dial->timer = 0;
    dial->radius = 0;
    dial->pointer_width = 0;
    dial->angle = 0.0;
    dial->old_value = 0.0;
    dial->old_lower = 0.0;
    dial->old_upper = 0.0;
    dial->adjustment = NULL;
  }

  GtkWidget*
  gtk_dial_new (GtkAdjustment *adjustment)
  {
    GtkDial *dial;

    dial = gtk_type_new (gtk_dial_get_type ());

    if (!adjustment)
      adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);

    gtk_dial_set_adjustment (dial, adjustment);

    return GTK_WIDGET (dial);
  }

  static void
  gtk_dial_destroy (GtkObject *object)
  {
    GtkDial *dial;

    g_return_if_fail (object != NULL);
    g_return_if_fail (GTK_IS_DIAL (object));

    dial = GTK_DIAL (object);

    if (dial->adjustment)
      gtk_object_unref (GTK_OBJECT (dial->adjustment));

    if (GTK_OBJECT_CLASS (parent_class)->destroy)
      (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
  }

  ̰ ռ widget ƴϹǷ ⼭ init()Լ Tictactoe widget
ؼ   ۾ Ѵ.  ׸ ڸ  ǾǷ new()
Լ   ۾ Ѵ.  , 츮 Adjustment object  ͸
  װ reference count Ŵ ϶. (̰ ̻
̿   ݴ ҽŲ.)  ׷ GTK װ ϰ ı
 ֵ Ʈ   ִ.

  Widget ɼ ٷ  ִ   Լ ִ.

  GtkAdjustment*
  gtk_dial_get_adjustment (GtkDial *dial)
  {
    g_return_val_if_fail (dial != NULL, NULL);
    g_return_val_if_fail (GTK_IS_DIAL (dial), NULL);

    return dial->adjustment;
  }

  void
  gtk_dial_set_update_policy (GtkDial      *dial,
                               GtkUpdateType  policy)
  {
    g_return_if_fail (dial != NULL);
    g_return_if_fail (GTK_IS_DIAL (dial));

    dial->policy = policy;
  }

  void
  gtk_dial_set_adjustment (GtkDial      *dial,
                            GtkAdjustment *adjustment)
  {
    g_return_if_fail (dial != NULL);
    g_return_if_fail (GTK_IS_DIAL (dial));

    if (dial->adjustment)
      {
        gtk_signal_disconnect_by_data (GTK_OBJECT (dial->adjustment), (gpointer) dial);
        gtk_object_unref (GTK_OBJECT (dial->adjustment));
      }

    dial->adjustment = adjustment;
    gtk_object_ref (GTK_OBJECT (dial->adjustment));

    gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
                        (GtkSignalFunc) gtk_dial_adjustment_changed,
                        (gpointer) dial);
    gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
                        (GtkSignalFunc) gtk_dial_adjustment_value_changed,
                        (gpointer) dial);

    dial->old_value = adjustment->value;
    dial->old_lower = adjustment->lower;
    dial->old_upper = adjustment->upper;

    gtk_dial_update (dial);
  }

***
*** 19-4.5. gtk_dial_realize()
***
   ο Ÿ Լ .  , X  ۾ ִ
Լ.  Լ gdk_window_new()  ũ Ѱ  ָ϶.  ̰
GdkWindowAttr ü  ʵ尡  ͸    ִ
̴.   ʵ Ʈ  ä ȴ.     
 widget ̺Ʈ ũ Ǵ ̴.  츮 gtk_widget_get_
events()ν  widget  ڰ   ̺Ʈ ũ 
  ִ(gtk_widget_set_events(), ׸ 츮 ϴ ̺Ʈ 
ش).

   ٸ, 츮 װ Ÿϰ  ϰ, ׸ 
widget  ͸ GdkWindow user data ʵ忡 ´.   
ܰ GTK  widget    ̺Ʈ   ֵ
Ѵ.

       static void
       gtk_dial_realize (GtkWidget *widget)
       {
         GtkDial *dial;
         GdkWindowAttr attributes;
         gint attributes_mask;

         g_return_if_fail (widget != NULL);
         g_return_if_fail (GTK_IS_DIAL (widget));

         GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
         dial = GTK_DIAL (widget);

         attributes.x = widget->allocation.x;
         attributes.y = widget->allocation.y;
         attributes.width = widget->allocation.width;
         attributes.height = widget->allocation.height;
         attributes.wclass = GDK_INPUT_OUTPUT;
         attributes.window_type = GDK_WINDOW_CHILD;
         attributes.event_mask = gtk_widget_get_events (widget) |
           GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
           GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
           GDK_POINTER_MOTION_HINT_MASK;
         attributes.visual = gtk_widget_get_visual (widget);
         attributes.colormap = gtk_widget_get_colormap (widget);

         attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
         widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);

         widget->style = gtk_style_attach (widget->style, widget->window);

         gdk_window_set_user_data (widget->window, widget);

         gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
       }

***
*** 19.4.6. ũ 
***
   widget   ó  Ǳ⿡ ռ, ׸ 
layout   , GTK װ  ũ  child widget
䱸Ѵ.   û Լ gtk_dial_size_request()  ٷ.  츮
widget ̳ widget ƴϰ  ũ⿡    ǵ Ƿ,
츮  մ Ʈ   ش.

       static void
       gtk_dial_size_request (GtkWidget      *widget,
                              GtkRequisition *requisition)
       {
         requisition->width = DIAL_DEFAULT_SIZE;
         requisition->height = DIAL_DEFAULT_SIZE;
       }

   widget ̻ ũ û ,  layout ǰ 
child widget װ  ũ ޴´.   ̰ ּ û
ũ⸸ŭ ȴ.   ڰ  resizeϴ ó, Ȥ û
ũ⺸ ۾  ִ.  ũ (notification) Լ gtk_dial_size_
allocate() ٷ.   ̿  Ϻ    ũ⸦
  ƴ϶, ̵ Լ ο ġ ũ widget X Ű
ִ  Ѵٴ  .

       static void
       gtk_dial_size_allocate (GtkWidget     *widget,
                               GtkAllocation *allocation)
       {
         GtkDial *dial;

         g_return_if_fail (widget != NULL);
         g_return_if_fail (GTK_IS_DIAL (widget));
         g_return_if_fail (allocation != NULL);

         widget->allocation = *allocation;
         if (GTK_WIDGET_REALIZED (widget))
           {
             dial = GTK_DIAL (widget);

             gdk_window_move_resize (widget->window,
                                     allocation->x, allocation->y,
                                     allocation->width, allocation->height);

             dial->radius = MAX(allocation->width,allocation->height) * 0.45;
             dial->pointer_width = dial->radius / 5;
           }
       }

***
*** 19-4.7. gtk_dial_expose()
***
  տ ߵ,  widget  ׸ ۾ expose ̺Ʈ 
ڵ鷯 .  ⼭ ָ    ̴.  Widget ŸϿ
 鿡  3 ׸  ͸ ׸ , gtk_draw_
polygon ̿Ѵٴ ̴.

  static gint
  gtk_dial_expose (GtkWidget      *widget,
                   GdkEventExpose *event)
  {
    GtkDial *dial;
    GdkPoint points[3];
    gdouble s,c;
    gdouble theta;
    gint xc, yc;
    gint tick_length;
    gint i;

    g_return_val_if_fail (widget != NULL, FALSE);
    g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
    g_return_val_if_fail (event != NULL, FALSE);

    if (event->count > 0)
      return FALSE;

    dial = GTK_DIAL (widget);

    gdk_window_clear_area (widget->window,
                           0, 0,
                           widget->allocation.width,
                           widget->allocation.height);

    xc = widget->allocation.width/2;
    yc = widget->allocation.height/2;

    /* ð  ׸. */

    for (i=0; i<25; i++)
      {
        theta = (i*M_PI/18. - M_PI/6.);
        s = sin(theta);
        c = cos(theta);

        tick_length = (i%6 == 0) ? dial->pointer_width : dial->pointer_width/2;

        gdk_draw_line (widget->window,
                       widget->style->fg_gc[widget->state],
                       xc + c*(dial->radius - tick_length),
                       yc - s*(dial->radius - tick_length),
                       xc + c*dial->radius,
                       yc - s*dial->radius);
      }

    /* ͸ ׸. */

    s = sin(dial->angle);
    c = cos(dial->angle);

    points[0].x = xc + s*dial->pointer_width/2;
    points[0].y = yc + c*dial->pointer_width/2;
    points[1].x = xc + c*dial->radius;
    points[1].y = yc - s*dial->radius;
    points[2].x = xc - s*dial->pointer_width/2;
    points[2].y = yc - c*dial->pointer_width/2;

    gtk_draw_polygon (widget->style,
                      widget->window,
                      GTK_STATE_NORMAL,
                      GTK_SHADOW_OUT,
                      points, 3,
                      TRUE);
    return FALSE;
  }

***
*** 19-4.8. ̺Ʈ ٷ
***
  Widget ڵ忡  ڵ پ  ̺Ʈ ٷ.   ̰
 GTK õ ̿ ״ ū ̰  ʴ´.  ̺Ʈ ũ
ΰ ·   ִ.   ڰ widget  콺 Ŭϰų
͸ ̵Ű 巡׸   ִ.  ׸ ܺ Ȳ ,
Adjustment object    찡 ִ.

  ڰ widget  Ŭ ϸ, 츮 Ŭ   ó
̷ üũϰ,  ׷ٸ widget ü ư ʵ忡  
ư ϰ, ׸ gtk_grab_add() ȣν  콺 ̺Ʈ 
æ.  ڵ 콺   ٽ Ǿ Ѵ(gtk_dial_
update_mouseԼν).  õ policy , "value_changed" ̺Ʈ ٸ
߻Ѵ.   GTK_UPDATE_CONTINUOUS 쿣   ߻ϰ, GTK_
UPDATE_DELAYED 쿣 Լ gtk_timeout_add()  Ÿ̸Ӹŭ Ǹ
߻ϸ, GTK_UPDATE_DISCONTINUOUS 쿣 ư releaseǴ  ߻
Ѵ.

  static gint
  gtk_dial_button_press (GtkWidget      *widget,
                         GdkEventButton *event)
  {
    GtkDial *dial;
    gint dx, dy;
    double s, c;
    double d_parallel;
    double d_perpendicular;

    g_return_val_if_fail (widget != NULL, FALSE);
    g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
    g_return_val_if_fail (event != NULL, FALSE);

    dial = GTK_DIAL (widget);

    /* ư    ο ̷ üũѴ.
     * ̰  ġ 콺  ġ    Ÿ
     * ν ̷. */

    dx = event->x - widget->allocation.width / 2;
    dy = widget->allocation.height / 2 - event->y;

    s = sin(dial->angle);
    c = cos(dial->angle);

    d_parallel = s*dy + c*dx;
    d_perpendicular = fabs(s*dx - c*dy);

    if (!dial->button &&
        (d_perpendicular < dial->pointer_width/2) &&
        (d_parallel > - dial->pointer_width))
      {
        gtk_grab_add (widget);

        dial->button = event->button;

        gtk_dial_update_mouse (dial, event->x, event->y);
      }

    return FALSE;
  }

  static gint
  gtk_dial_button_release (GtkWidget      *widget,
                            GdkEventButton *event)
  {
    GtkDial *dial;

    g_return_val_if_fail (widget != NULL, FALSE);
    g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
    g_return_val_if_fail (event != NULL, FALSE);

    dial = GTK_DIAL (widget);

    if (dial->button == event->button)
      {
        gtk_grab_remove (widget);

        dial->button = 0;

        if (dial->policy == GTK_UPDATE_DELAYED)
          gtk_timeout_remove (dial->timer);

        if ((dial->policy != GTK_UPDATE_CONTINUOUS) &&
            (dial->old_value != dial->adjustment->value))
          gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
      }

    return FALSE;
  }

  static gint
  gtk_dial_motion_notify (GtkWidget      *widget,
                           GdkEventMotion *event)
  {
    GtkDial *dial;
    GdkModifierType mods;
    gint x, y, mask;

    g_return_val_if_fail (widget != NULL, FALSE);
    g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
    g_return_val_if_fail (event != NULL, FALSE);

    dial = GTK_DIAL (widget);

    if (dial->button != 0)
      {
        x = event->x;
        y = event->y;

        if (event->is_hint || (event->window != widget->window))
          gdk_window_get_pointer (widget->window, &x, &y, &mods);

        switch (dial->button)
          {
          case 1:
            mask = GDK_BUTTON1_MASK;
            break;
          case 2:
            mask = GDK_BUTTON2_MASK;
            break;
          case 3:
            mask = GDK_BUTTON3_MASK;
            break;
          default:
            mask = 0;
            break;
          }

        if (mods & mask)
          gtk_dial_update_mouse (dial, x,y);
      }

    return FALSE;
  }

  static gint
  gtk_dial_timer (GtkDial *dial)
  {
    g_return_val_if_fail (dial != NULL, FALSE);
    g_return_val_if_fail (GTK_IS_DIAL (dial), FALSE);

    if (dial->policy == GTK_UPDATE_DELAYED)
      gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");

    return FALSE;
  }

  static void
  gtk_dial_update_mouse (GtkDial *dial, gint x, gint y)
  {
    gint xc, yc;
    gfloat old_value;

    g_return_if_fail (dial != NULL);
    g_return_if_fail (GTK_IS_DIAL (dial));

    xc = GTK_WIDGET(dial)->allocation.width / 2;
    yc = GTK_WIDGET(dial)->allocation.height / 2;

    old_value = dial->adjustment->value;
    dial->angle = atan2(yc-y, x-xc);

    if (dial->angle < -M_PI/2.)
      dial->angle += 2*M_PI;

    if (dial->angle < -M_PI/6)
      dial->angle = -M_PI/6;

    if (dial->angle > 7.*M_PI/6.)
      dial->angle = 7.*M_PI/6.;

    dial->adjustment->value = dial->adjustment->lower + (7.*M_PI/6 - dial->angle) *
      (dial->adjustment->upper - dial->adjustment->lower) / (4.*M_PI/3.);

    if (dial->adjustment->value != old_value)
      {
        if (dial->policy == GTK_UPDATE_CONTINUOUS)
          {
            gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
          }
        else
          {
            gtk_widget_draw (GTK_WIDGET(dial), NULL);

            if (dial->policy == GTK_UPDATE_DELAYED)
              {
                if (dial->timer)
                  gtk_timeout_remove (dial->timer);

                dial->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
                                               (GtkFunction) gtk_dial_timer,
                                               (gpointer) dial);
              }
          }
      }
  }

  ׸ ܺ ο  Adjustment ȭ 'changed' 'value_changed'
ñ׳  츮 widget ޵Ǵ ̴.  ̷ Լ  ڵ鷯
gtk_dial_update() ȣؼ, ڵ Ȯϰ, ο   
ϰ, ׸ widget ٽ ׷ش(gtk_widget_draw() ȣؼ).

  static void
  gtk_dial_update (GtkDial *dial)
  {
    gfloat new_value;

    g_return_if_fail (dial != NULL);
    g_return_if_fail (GTK_IS_DIAL (dial));

    new_value = dial->adjustment->value;

    if (new_value < dial->adjustment->lower)
      new_value = dial->adjustment->lower;

    if (new_value > dial->adjustment->upper)
      new_value = dial->adjustment->upper;

    if (new_value != dial->adjustment->value)
      {
        dial->adjustment->value = new_value;
        gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
      }

    dial->angle = 7.*M_PI/6. - (new_value - dial->adjustment->lower) * 4.*M_PI/3. /
      (dial->adjustment->upper - dial->adjustment->lower);

    gtk_widget_draw (GTK_WIDGET(dial), NULL);
  }

  static void
  gtk_dial_adjustment_changed (GtkAdjustment *adjustment,
                                gpointer       data)
  {
    GtkDial *dial;

    g_return_if_fail (adjustment != NULL);
    g_return_if_fail (data != NULL);

    dial = GTK_DIAL (data);

    if ((dial->old_value != adjustment->value) ||
        (dial->old_lower != adjustment->lower) ||
        (dial->old_upper != adjustment->upper))
      {
        gtk_dial_update (dial);

        dial->old_value = adjustment->value;
        dial->old_lower = adjustment->lower;
        dial->old_upper = adjustment->upper;
      }
  }

  static void
  gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment,
                                      gpointer       data)
  {
    GtkDial *dial;

    g_return_if_fail (adjustment != NULL);
    g_return_if_fail (data != NULL);

    dial = GTK_DIAL (data);

    if (dial->old_value != adjustment->value)
      {
        gtk_dial_update (dial);

        dial->old_value = adjustment->value;
      }
  }

***
*** 19-4.9.  
***
  츮 õ Dial widget  670 ڵ带  ִ.  Ư  ڵ
 κ  Ϸ(boiler plate)̱ , 츮   ڵ
      ־.  ׷  widget    
ɰ ִ.

  o  widget   , Ͱ 巡׵Ǹ鼭 ణ ½Ÿ
    ߰   ̴.  ̰ Ͱ ̵  redrawǱ
    widget ü  ̴.    ذϴ  
     ʴ(offscreen) Ƚʿ ׷ְ, ׸  
   ũ  ܹ  ִ ̴.  
   (ื(progress bar) widget ̷  .)

  o ڴ  ȭŰ ؼ up  down ȭǥŰ(arrow key) ̿
    ־  ̴.

  o 츮 widget ũų    ų  ִ ư ٸ
      ̴.  ̸   ư widget ̿ϴ ͵
   ϰ, 츮   ư   ¿ auto-repeat
   ǵ ϰʹ, ũѹٿ ִ ȭǥó.  ̷  ۵ ߰
   ִ κ ڵ GtkRange widget ã  ִ.

  o ̾(Dial) widget տ ޵ ư ٴڿ ġ ϳ child
   widget , ̳ widget   ִ.  ׷ ڴ
   ̾ 簪 ̱  ϴ ̳ Ʈ widget  
   ִ.

***
*** 19-5.  
***
  Widget    ׸   Ϻθ  ҰǾ.
ڽ widget  ̿,   ҽ GTK  ü ̴.
  widget     غ.  ̰
Container widgetΰ?  ̰ õ   ִ°?  ̰ ̹
ϴ widget ΰ?  ׸  widget ã, ȭ ֱ
ϴ ̴.   !

**********************************
*** 20. ,  ׸ 
**********************************

***
*** 20-1. 
***
  ⼭ 츮  ׸ α׷  ̴.    츮
콺 ̺Ʈ  ٷ ˾ƺ ̰,  ȿ  ׸
׸, ׸ Ƚ  ؼ   ׸ ׸  
̴.   ׸ α׷  Ŀ, 츮 װͿ drawing tablet
 XInput device ϴ  Ȯ õ ̴.  GTK ׷ device
κ pressure tilt, Ȯ    ְ ϴ support
routine Ѵ.

***
*** 20-2. ̺Ʈ ٷ
***
  츮 ̹ 캻 GTK ñ׳ ޴  ó  
 ͵̴.  , 콺 ̶ Ű ,
  ϴ ͵   ̴.  GTK ñ׳ ߿
̷  ̺Ʈ  ͵鵵 ִ.  ̷ ̺Ʈ  ڵ鷯 ׷
̺Ʈ    ִ ü Ű ִ Ǵٸ ڵ
 ȴ.  , motion event ڵ鷯 Ʒ  GdkEventMotion
ü  ͸ ڷ  ִ.

       struct _GdkEventMotion
       {
         GdkEventType type;
         GdkWindow *window;
         guint32 time;
         gdouble x;
         gdouble y;
         ...
         guint state;
         ...
       };

   type ̺Ʈ Ÿ ǰ,  쿡 GDK_MOTION_NOTIFY̴.  
window  ̺Ʈ ߻   ̴.   x y  ̺Ʈ
ǥ̸, state ̺Ʈ ߻  modifier state Ѵ(, 
modifier key modifier button  ).  ̰ Ʒ ̴
 Ʈ ORŲ ̴.

       GDK_SHIFT_MASK
       GDK_LOCK_MASK
       GDK_CONTROL_MASK
       GDK_MOD1_MASK
       GDK_MOD2_MASK
       GDK_MOD3_MASK
       GDK_MOD4_MASK
       GDK_MOD5_MASK
       GDK_BUTTON1_MASK
       GDK_BUTTON2_MASK
       GDK_BUTTON3_MASK
       GDK_BUTTON4_MASK
       GDK_BUTTON5_MASK

  ٸ ñ׳ε鿡 ؼó, ̺Ʈ ߻  װ   
ϱ  츮 gtk_signal_connect() ̿Ѵ.  ׷  츮 
̺Ʈ ŽǾ ϴ GTK   ֵ ؾѴ.  ̸ ؼ
 Լ ̿Ѵ.

       void       gtk_widget_set_events          (GtkWidget           *widget,
                                                  gint                 events);

   ° ڴ 츮   ̺Ʈ Ѵ.  ̰  
̺Ʈ ؼ   Ʈ ORŲ ̴.    ؼ 
鸦 ҰѴ.

       GDK_EXPOSURE_MASK
       GDK_POINTER_MOTION_MASK
       GDK_POINTER_MOTION_HINT_MASK
       GDK_BUTTON_MOTION_MASK
       GDK_BUTTON1_MOTION_MASK
       GDK_BUTTON2_MOTION_MASK
       GDK_BUTTON3_MOTION_MASK
       GDK_BUTTON_PRESS_MASK
       GDK_BUTTON_RELEASE_MASK
       GDK_KEY_PRESS_MASK
       GDK_KEY_RELEASE_MASK
       GDK_ENTER_NOTIFY_MASK
       GDK_LEAVE_NOTIFY_MASK
       GDK_FOCUS_CHANGE_MASK
       GDK_STRUCTURE_MASK
       GDK_PROPERTY_CHANGE_MASK
       GDK_PROXIMITY_IN_MASK
       GDK_PROXIMITY_OUT_MASK

  gtk_widget_set_events() ȣ  Ǿ    ̹ 
ִ.  , װ GTK widget  X   ȣǾ
Ѵ.  , ̰ widget   Ŀ ȣǾ Ѵٴ ̴.  °
,  widget õ X   Ѵ.  ȿ ؼ  widget
type ׵鸸   ʰ ׵ parent  ȿ ׷ִ´.
̷ widget   ͵̴.

       GtkAlignment
       GtkArrow
       GtkBin
       GtkBox
       GtkImage
       GtkItem
       GtkLabel
       GtkPaned
       GtkPixmap
       GtkScrolledWindow
       GtkSeparator
       GtkTable
       GtkViewport
       GtkAspectFrame
       GtkFrame
       GtkVPaned
       GtkHPaned
       GtkVBox
       GtkHBox
       GtkVSeparator
       GtkHSeparator

  ̷ ̺Ʈ Žϱ  츮 EventBox widget ʿ Ѵ.  ڼ
  EventBox widget  κ ϶.  츮 ׸ α׷
 콺 ư  Ͱ ̴  Žϰ ;ϹǷ, GDK_
POINTER_MOTION_MASK GDK_BUTTON_PRESS_MASK Ѵ.  츮  
ٽ ׷   ˾ƾ ϹǷ GDK_EXPOSURE_MASK Ѵ.  
츮  ũⰡ   Configure eventν Žؾ , 츮
̸  GDK_STRUCTURE_MASK flag  ʿ䰡 .  ̰  
 ڵ Ǳ ̴.  ׷ GDK_POINTER_MOTION_MASK 
ϴ  ־  ִٴ   ̴.  ̰ ڰ 콺
   event queue motion event   ̴.  
motion event ٷ  0.1ʰ ɸٰ  .  ׷ X 
 0.05ʸ ο motion queue Ѵ.  츮  ڰ ׸
     ̴.   ڰ 5ʵ ׸ ׸,
׵ 콺 ư    Ǵٸ 5ʰ, װ Ƴ  ʿϰ
 ̴.  츮 ϴ  Ǵ  ̺Ʈ   ϳ motion
event Žϴ ̴.  ̷ ϱ ؼ 츮 GDK_POINTER_MOTION_HINT_
MASK Ѵ.  츮 GDK_POINTER_MOTION_HINT_MASK ϸ, 
콺 Ͱ 츮    Ǵ ư press release
̺Ʈ ߻ϰ  ó   motion event ش.  ڵ
motion event 츮 Ʒ Լν иϰ 콺  ġ 
  ̴.

       GdkWindow*    gdk_window_get_pointer     (GdkWindow       *window,
                                                 gint            *x,
                                                 gint            *y,
                                                 GdkModifierType *mask);
(  ӻ  gtk_widget_get_pointer() Լ , ״
  巯 ̴.  ֳϸ װ 콺 ư ¿ 
  ġ ֱ ̴.)

  츮  ̺Ʈ ϴ ڵ ׷Ƿ ̷   ̴.

         gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
                             (GtkSignalFunc) expose_event, NULL);
         gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
                             (GtkSignalFunc) configure_event, NULL);
         gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
                             (GtkSignalFunc) motion_notify_event, NULL);
         gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
                             (GtkSignalFunc) button_press_event, NULL);
         gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
                                | GDK_LEAVE_NOTIFY_MASK
                                | GDK_BUTTON_PRESS_MASK
                                | GDK_POINTER_MOTION_MASK
                                | GDK_POINTER_MOTION_HINT_MASK);

  "expose_event" "configure_event"  ؼ ܵд.  "motion_
notify_event" "button_press_event" ڵ鷯  ϴ.

       static gint
       button_press_event (GtkWidget *widget, GdkEventButton *event)
       {
         if (event->button == 1 && pixmap != NULL)
             draw_brush (widget, event->x, event->y);
         return TRUE;
       }
       static gint
       motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
       {
         int x, y;
         GdkModifierType state;
         if (event->is_hint)
           gdk_window_get_pointer (event->window, &x, &y, &state);
         else
           {
             x = event->x;
             y = event->y;
             state = event->state;
           }
         if (state & GDK_BUTTON1_MASK && pixmap != NULL)
           draw_brush (widget, x, y);
         return TRUE;
       }

***
*** 20-3. DrawingArea widget, ׸ ׸
***
   ũ ׸ ׸   ˾ƺ.  ̶ ʿ 
DrawingArea widget̴.  ׸ ׸  widget̶  ٸ
ƴ X.  ̰ 츮 ϴ  ̵ ׷  ִ 
ĵ.  Drawing area  Լ ̿ؼ .

       GtkWidget* gtk_drawing_area_new        (void);

   widget Ʈ ũ  Լν Ѵ.

       void       gtk_drawing_area_size       (GtkDrawingArea      *darea,
                                               gint                 width,
                                               gint                 height);

   widget  Ѵٸ  Ʈ ũ gtk_widget_set_usize()ν
ε  ִ.  ׸ ڰ   drawing area  
ũ⸦ ϸ  εȴ.  츮 DrawingArea widget  ,
׸  ΰ  Ǹ ￩ Ѵ.   츮 
߾ٰ ٽ 巯ٸ, 츮 exposure ũ ϰ ׸ 
߾  ̾  ٽ ׷ Ѵ.  ٿ, 
Ϻκ ٰ ܰ ٽ ׷  ð 길 
ִ.  ̷   ع offscreen backing pixmap ̿ϴ ̴.
ũ  ٷ ׸ ,  ʴ  ޸𸮿   ̹
 ׷, ̹ ߰ų Ǵ ̹ ο   Ǹ
شϴ  ũ  ִ ̴.

   offscreen pixmap  , 츮  Լ ̿Ѵ.

       GdkPixmap* gdk_pixmap_new               (GdkWindow  *window,
                                                gint        width,
                                                gint        height,
                                                gint        depth);

   window  Ƚ Ư ̾ GDK  Ѵ.  width
height Ƚ ũ⸦ Ѵ.  depth color depthμ,  ο 
  ȼ Ʈ .   depth -1 Ǹ, װ 
depth Ȱ.  츮 Ƚ "configure_event" handler ȿ .
 ̺Ʈ  ó   ؼ,  ũⰡ  
߻Ѵ.

  /* ׸   backing pixmap */
  static GdkPixmap *pixmap = NULL;
  /*  ũ backing pixmap ϳ . */
  static gint
  configure_event (GtkWidget *widget, GdkEventConfigure *event)
  {
    if (pixmap)
      {
        gdk_pixmap_destroy(pixmap);
      }
    pixmap = gdk_pixmap_new(widget->window,
                            widget->allocation.width,
                            widget->allocation.height,
                            -1);
    gdk_draw_rectangle (pixmap,
                        widget->style->white_gc,
                        TRUE,
                        0, 0,
                        widget->allocation.width,
                        widget->allocation.height);
    return TRUE;
  }

  gdk_draw_rectangle() θ Ƚ white ʱȭѴ.  ⿡ 
   ̴.  ׷ 츮 exposure event handler ܼ 
Ƚ  portion ũ  Ѵ(츮 exposure event
event->area ʵν redraw  Ѵ).

       /* Backing pixmapκ ũ Ѵ. */
       static gint
       expose_event (GtkWidget *widget, GdkEventExpose *event)
       {
         gdk_draw_pixmap(widget->window,
                         widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
                         pixmap,
                         event->area.x, event->area.y,
                         event->area.x, event->area.y,
                         event->area.width, event->area.height);
         return FALSE;
       }

  츮  Ƚʿ   ũ ϴ Ҵ.  ׷
츮 Ƚʿ  ִ ͵  ׷?  GTK GDK
̺귯 drawables ׸  ʿ   Լ ִ.
Drawable̶  򰡿 ׷  ִ  ̴.  ⼭ 
ϳ window, pixmap, Ǵ bitmap( ̹)   ִ.  츮
̹ ̷ Լ ΰ Ҵ.  gdk_draw_rectangle() gdk_draw_pixmap()
 װ̴.   Լ  Ʈ ̷.

  gdk_draw_line ()
  gdk_draw_rectangle ()
  gdk_draw_arc ()
  gdk_draw_polygon ()
  gdk_draw_string ()
  gdk_draw_text ()
  gdk_draw_pixmap ()
  gdk_draw_bitmap ()
  gdk_draw_image ()
  gdk_draw_points ()
  gdk_draw_segments ()

   Լ鿡   ڼ ˷   ų <gdk/gdk.h> 
.   Լ ó   ڸ  .  ù ° ׷
 drawable, ׸ ι° graphics context(GC)̴.  GC foreground/
background color line  width, ׷ Ϳ   ĸȭ
̴.  GDK  GC   ϴµ ʿ  Լ 
,   ϱ ؼ(Keep things  simple) 츮 ̹
ǵǾ ִ GC  ̴.   widget  Ÿ ִ(̵
rc  ν ϴ.  GTK rc Ͽ  κ ).
̰ ٸ ͵ ̿ GC  Ѵ.  ̷ GC ϴ 
 ̰ڴ.

       widget->style->white_gc
       widget->style->black_gc
       widget->style->fg_gc[GTK_STATE_NORMAL]
       widget->style->bg_gc[GTK_WIDGET_STATE(widget)]

  ʵ fg_gc, bg_gc, dark_gc, light_gc  Ʒ    ִ Gtk
StateType̶ ڷ Ÿ.

       GTK_STATE_NORMAL,
       GTK_STATE_ACTIVE,
       GTK_STATE_PRELIGHT,
       GTK_STATE_SELECTED,
       GTK_STATE_INSENSITIVE

  , GTK_STATE_SELECTED  Ʈ foreground  whitḛ
background  dark blue̴.   ũ  ׸ Լ draw_
brush() ׷Ƿ ̷ ȴ.

  /* ũ 簢 ϳ ׸. */
  static void
  draw_brush (GtkWidget *widget, gdouble x, gdouble y)
  {
    GdkRectangle update_rect;
    update_rect.x = x - 5;
    update_rect.y = y - 5;
    update_rect.width = 10;
    update_rect.height = 10;
    gdk_draw_rectangle (pixmap,
                        widget->style->black_gc,
                        TRUE,
                        update_rect.x, update_rect.y,
                        update_rect.width, update_rect.height);
    gtk_widget_draw (widget, &update_rect);
  }

  츮 Ƚ  귯 ǥϴ 簢 ׸ ,  Լ
ȣѴ.

       void       gtk_widget_draw                (GtkWidget           *widget,
                                                  GdkRectangle        *area);

  ̰ area ڷ ־  ƮǾ  X ˷ش.
ᱹ X expose ̺Ʈ ߻ϰ, ̰ 츮 expose ̺Ʈ ڵ鷯
  ũ  ϰԲ  ̴.

   츮 main     Ϻ  ׸ ϰ 
׸ α׷  캸Ҵ.  

***
*** 20-4. Input support ϱ
***
   drawing tablet , ״  鼭 콺 ξ 
ǥ ϰ ׸  ְ ִ Էġ(input device) ϴ 
 ô.  ̷ ġ ̿ϴ   ̾  콺
ġ  ̰, ̷  ׷ Էġ    
Ұ   ִ.

  o  Pressure sensitivity
  o  Tilt reporting
  o  Sub-pixel positioning
  o  Multiple inputs (for example, a stylus with a point and eraser)

  XInput extension    XInput-HOWTO <http://www.msc.
cornell.edu/~otaylor/xinput/XInput-HOWTO.html>  .   GdkEvent
Motion ü ü ǰ  , extended device ϱ 
ʵ带    ̴. 

       struct _GdkEventMotion
       {
         GdkEventType type;
         GdkWindow *window;
         guint32 time;
         gdouble x;
         gdouble y;
         gdouble pressure;
         gdouble xtilt;
         gdouble ytilt;
         guint state;
         gint16 is_hint;
         GdkInputSource source;
         guint32 deviceid;
       };

  pressure ڴ 0 1  εҼ  pressure ش.  xtilt
ytile   tilt  شϴ -1 1    
ִ.  source deviceid ڴ ΰ ٸ  ߻ ̺Ʈ 
ġ(device) Ѵ.  source ġ ŸԿ    ش.
̰  enumeration    ִ.

       GDK_SOURCE_MOUSE
       GDK_SOURCE_PEN
       GDK_SOURCE_ERASER
       GDK_SOURCE_CURSOR

  deviceid  ġ    ID Ѵ.  ̰ gdk_input_
list_devices()Լ(ڿ )  ġ     ϰ 
   ִ.  Core pointer device( 콺)  Ư GDK_CORE_
POINTER  δ.

***
*** 20-4.1. Extended device  밡ϰ ϱ
***
  GTK 츮   extended device   ˷ ַ,
츮 α׷   ٸ ָ ȴ.

       gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_CURSOR);

  GDK_EXTENSION_EVENTS_CURSOR  ν 츮 Ȯ ̺Ʈ鿡
  ˸.  , ̶ 츮  Ŀ ׷ ȵȴ.  Ŀ
׸  ؼ ڿ  '  ̿' κ ϶.  츮
츮 Ŀ ׸ Ѵٸ GDK_EXTENSION_EVENTS_ALL  ǰ, Ʈ
 ư GDK_EXTENSION_EVENTS_NONE .

  ̾߱ ̰  ʴ´.  Ʈ, extension device disable
Ǿ ִ.  츮 ڷ Ͽ ׵ extension device enableŰ
  ְ ִ Ŀ ʿϴ.  GTK   ڵ 
ִ InputDialog widget Ѵ.     InputDialog
widget Ѵ.  ̰ device   dialog ˷ְ,
 쿣 top ÷.

       void
       input_dialog_destroy (GtkWidget *w, gpointer data)
       {
         *((GtkWidget **)data) = NULL;
       }

       void
       create_input_dialog ()
       {
         static GtkWidget *inputd = NULL;
         if (!inputd)
           {
             inputd = gtk_input_dialog_new();
             gtk_signal_connect (GTK_OBJECT(inputd), "destroy",
                                 (GtkSignalFunc)input_dialog_destroy, &inputd);
             gtk_signal_connect_object 
             (GTK_OBJECT(GTK_INPUT_DIALOG(inputd)->close_button),
                                        "clicked",
                                        (GtkSignalFunc)gtk_widget_hide,
                                        GTK_OBJECT(inputd));
             gtk_widget_hide ( GTK_INPUT_DIALOG(inputd)->save_button);
             gtk_widget_show (inputd);
           }
         else
           {
             if (!GTK_WIDGET_MAPPED(inputd))
               gtk_widget_show(inputd);
             else
               gdk_window_raise(inputd->window);
           }
       }
  (츮  dialog ٷ  Ǹ ￩  ̴.  "destroy"
ñ׳ο  δ , 츮 dialog ı  ͸ dialog
 ܵδ Ǽ - ̰ Segfault(!) θ -    ִ.)

  InputDialog "Close" ׸ "Save"  ư  , Ʈ
δ ƹ  Ǿ  ʴ.   "Close" ư dialog
ߴµ , "Save" ư ߾ ȴ.   α׷ XInput 
ϴ ɼ  ʾұ ̴.

***
*** 20.4.2. Extended device  ̿ϱ
***
  ϴ ġ(device) enable, 츮 ̺Ʈ ü  ʵ忡
ִ extended device  ̿  ִ.  ,   ̿ϴ 
 ϴ.  Extended event disableǾ ִ ̵ 
Ʈ  ֱ ̴.

      gdk_window_get_pointer() ſ gdk_input_window_get_
pointer() ȣѴٴ ̴.  ̰ gdk_window_get_pointer extended
device   ϱ ̴.

       void gdk_input_window_get_pointer     (GdkWindow       *window,
                                              guint32         deviceid,
                                              gdouble         *x,
                                              gdouble         *y,
                                              gdouble         *pressure,
                                              gdouble         *xtilt,
                                              gdouble         *ytilt,
                                              GdkModifierType *mask);

   Լ θ ,    device ID  
Ѵ.  , 츮 device ID event ü deviceid ʵκ 
̴.  ٽ ѹ,  Լ extension event disable ¿ մ
  .  ( 쿣, event->deviceid GDK_CORE_POINTER
  ̴.)  ׷ 츮 button-press  motion ̺Ʈ ڵ鷯
⺻  ׸  ʴ´ - 츰  extended شϴ 
ٷ ڵ带 ߰ϱ⸸ ϸ ȴ.

  static gint
  button_press_event (GtkWidget *widget, GdkEventButton *event)
  {
    print_button_press (event->deviceid);
    if (event->button == 1 && pixmap != NULL)
      draw_brush (widget, event->source, event->x, event->y, event->pressure);
    return TRUE;
  }

  static gint
  motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
  {
    gdouble x, y;
    gdouble pressure;
    GdkModifierType state;
    if (event->is_hint)
      gdk_input_window_get_pointer (event->window, event->deviceid,
                                    &x, &y, &pressure, NULL, NULL, &state);
    else
      {
        x = event->x;
        y = event->y;
        pressure = event->pressure;
        state = event->state;
      }
    if (state & GDK_BUTTON1_MASK && pixmap != NULL)
      draw_brush (widget, event->source, x, y, pressure);
    return TRUE;
  }

  츰  ο  ̿ϴ   ؾ Ѵ.  츮 draw_brush()
Լ  event->source ٸ  ׸  ְ ϰ, ׸ pressure
 brush ũ⸦ ϰ Ѵ.

  /* ũ 簢 ׸.  ũ pressure ϰ,
   * ׸  device ŸԿ Ѵ. */
  static void
  draw_brush (GtkWidget *widget, GdkInputSource source,
              gdouble x, gdouble y, gdouble pressure)
  {
    GdkGC *gc;
    GdkRectangle update_rect;
    switch (source)
      {
      case GDK_SOURCE_MOUSE:
        gc = widget->style->dark_gc[GTK_WIDGET_STATE (widget)];
        break;
      case GDK_SOURCE_PEN:
        gc = widget->style->black_gc;
        break;
      case GDK_SOURCE_ERASER:
        gc = widget->style->white_gc;
        break;
      default:
        gc = widget->style->light_gc[GTK_WIDGET_STATE (widget)];
      }
    update_rect.x = x - 10 * pressure;
    update_rect.y = y - 10 * pressure;
    update_rect.width = 20 * pressure;
    update_rect.height = 20 * pressure;
    gdk_draw_rectangle (pixmap, gc, TRUE,
                        update_rect.x, update_rect.y,
                        update_rect.width, update_rect.height);
    gtk_widget_draw (widget, &update_rect);
  }

***
*** 20.4.3. Device     ˾Ƴ
***
  Device     ˾Ƴ ִ μ, 츮 
׷  ư  device ̸ Ʈ ̴.  Device ̸
˾Ƴ Ͽ  Լ ̿Ѵ.

       GList *gdk_input_list_devices               (void);

  ̰ GdkDeviceInfo ü GList(glib ̺귯  ḮƮ
Ÿ) Ѵ.  GdkDeviceInfo ü ̷ ǵǾ ִ.

  struct _GdkDeviceInfo
  {
    guint32 deviceid;
    gchar *name;
    GdkInputSource source;
    GdkInputMode mode;
    gint has_cursor;
    gint num_axes;
    GdkAxisUse *axes;
    gint num_keys;
    GdkDeviceKey *keys;
  };

  ִ κ ʵ  XInput  ϴ  ߰
ʾҴٸ ص   ̴.   츮   
ܼ X device ο ̸(name)̴.  (configuration)ʵ忡
ش ʴ  has_cursor̴.  ׷ 츮 GDK_EXTENSION_EVENTS_
CURSOR Ƿ,  ʵ忡 ؼ  .

  print_button_press() Լ ġǴ Ʈ   ܼ ݺ
̸, device ̸ Ʈ  ̴.

       static void
       print_button_press (guint32 deviceid)
       {
         GList *tmp_list;
         /* gdk_input_list_devices  Ʈ ϸ,
          *  츮 Ŀ ̰    ̴. */
         tmp_list = gdk_input_list_devices();
         while (tmp_list)
           {
             GdkDeviceInfo *info = (GdkDeviceInfo *)tmp_list->data;
             if (info->deviceid == deviceid)
               {
                 printf("Button press on device '%s'\n", info->name);
                 return;
               }
             tmp_list = tmp_list->next;
           }
       }

***
*** 20-4.4.   ̿
***
   츮 α׷  XInput   Կ ұϰ,  ü
    ̴ 鵵 ִ.  , ڴ α׷ 
 ׵ ġ Ϸ   ̹Ƿ, 츮  ġ
   ֵ  Ѵ.  ̰ gdk_input_list_devices()
 Ǯϰ,  Ͽ (write)ϴ  ̷.  
׷      state  ֱ ؼ, GDK device
   Լ Ѵ.

       gdk_input_set_extension_events()
       gdk_input_set_source()
       gdk_input_set_mode()
       gdk_input_set_axes()
       gdk_input_set_key()

  (gdk_input_list_devices()  Ʈ Ȯ    ִ.)
̰Ϳ   ׸ α׷ Gsumi(http://www.msc.cornell.edu/~
otaylor/gsumi/ ִ.)  ̴.  ᱹ,  õ鿡   
ǥ    ִٸ    ̴.  ̰ Ƹ GNOME
̺귯 GTK ణ    ̴.

  츮 տ ٷ Ϳ  ϳ ߿  cursor  ̴.
XFree86 ٸ ÷ μ ÿ  - Core pointer, ׸
ÿ    - Ͽ ġ ٷ  .  ̰Ϳ  
ڼ  XInput-HOWTO .  <http://www.msc.cornell.edu/~otaylor/
xinput/XInput-HOWTO.html> ִ.  ̰ ִ ̿ڸ ȮϷ
̶ ڽŸ Ŀ ׷ִ  ʿ ǹѴ.  ڽŸ Ŀ
׸     ؾ Ѵ.  ù°  ġ ׷ Ŀ
ʿ ϴ θ ϰ, °  ġ (proximity)Ǿ
ִ θ Ѵ.  ( ġ drawing tablet , stylus
tablet   Ŀ  ʰ ϴ   ̴.  ġ
stylus پ  , ̸ ٵǾ(in proximity) ǥѴ.)  ù°
۾ 츮 device ̸ ˾Ƴ  ߵ, device Ʈ 
ν ذȴ.  ι° ۾ "proximity_out" ̺Ʈ ν
ذѴ.   Ŀ ׸  GTK ǿ ִ 'testinput' 
׷ ã   ̴.
******************************
*** 21. GTK  ϴ 
******************************

   κ   GTK    ֵ Ϲ Ÿ 
Ʈ  ٷ ִ.  ̰ μ  ׷ٴ ̰, 
 ʿ ̴.  :)

  GNU autoconf automake ̿϶!  ׵ 츮 ģ.  :)   ̵鿡
  Ұ  ȹ ִ.



********************
*** 22. Contributing
********************   

   , ٸ  Ʈ , ο ̿ ؼ
ڹ  ̴.     ȭ  GTK 
ɿ  Ȯ   ȴٸ,  ڽŵ   ⿩ 
  .

   ⿩ϰڴٰ Ծٸ,   slow@intergate.bc.ca,  
Ian Main ֱ ٶ.  ,    ο ̸
п   ߰  .    ׵ α׷
    κ̶ ̿ ̰,   ǰ ϴ
  ̴.

  THANK YOU



***************
*** 23. Credits
***************

      鿡 Ѵ.

     *** Bawer Dagdeviren, chamele0n@geocities.com
     FOR the menus tutorial. 

     *** Raph Levien, raph@acm.org 
     FOR hello world ala GTK, widget packing, and general all around wisdom.
     He's also generously donated a home for this tutorial.

     *** Peter Mattis, petm@xcf.berkeley.edu 
     FOR the simplest GTK program.. and the ability to make it :) 

     *** Werner Koch werner.koch@guug.de 
     FOR converting the original plain text to SGML, and the widget class
     hierarchy. 

     *** Mark Crichton crichton@expert.cc.purdue.edu 
     FOR the menu factory code, and the table packing tutorial. 

     *** Owen Taylor owt1@cornell.edu 
     FOR the EventBox widget section (and the patch to the distro). He's
     also responsible for the selections code and tutorial, as well as
     the sections on writing your own GTK widgets, and the example
     application. Thanks a lot Owen for all you help! 

     *** Mark VanderBoom mvboom42@calvin.edu 
     FOR his wonderful work on the Notebook, Progress Bar, Dialogs, and File
     selection widgets. Thanks a lot Mark! You've been a great help. 

     *** Tim Janik timj@psynet.net 
     FOR his great job on the Lists Widget. Thanks Tim :) 

     *** Rajat Datta rajat@ix.netcom.com 
     FOR the excellent job on the Pixmap tutorial. 

     *** Michael K. Johnson johnsonm@redhat.com 
     FOR info and code for popup menus. 

  ׸  ְ  õ  ǵ   ̵鿡Ե Ѵ.

Thanks. 



***************
*** 24. Copying
***************

This tutorial is Copyright (C) 1997 Ian Main 

This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your option)
any later version. 

This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details. 

You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
675 Mass Ave, Cambridge, MA 02139, USA. 
