  GTK Tutorial
  Ian Main imain@gtk.org, Tony Gale gale@gtk.org
  1998 5 24
   liberta@cau.ac.kr, ȣ hanjiho@penta.co.kr
  1998 5 25

  1.  ű 

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

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

   Tutorial    ־,  ̳  帮
   ü  Ұմϴ.

     Ұ
        GTK(GTK+)  ҰԴϴ.  ̹  (go linux) 
        Խǿ ø GTK+ FAQ   Դϴ.

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

      ư
        helloworld.c  ϸ鼭 ڷ鿡  ܼҸ ɱ,
        ׸ ñ׳ ڵ鷯  漳 ֽϴ.  ñ׳, ߿
        .

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

     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   ҰǾ ֽϴ.  ſ 
        .

     ư widget
        켱   widget ư ġ ֽϴ.  ׳
        ư, ̻ ư(Ƚ  *), Ư ư(, üũ,
        ,..)  츮  õ鿡  ̿ 
        (?)  ư Ĩϴ.

     پ widget
        ڱ ȥ ̱⺸ ٸ widget ٹ̱  ̴ 
        ִ   widget Ұմϴ.  (label),
        ǳ(tooltip),  (progress bar), ȭ(dialog
        box), Ƚ(pixmap) Դϴ.  Ư Ƚʿ ؼ  
        ڻϰ(?) ٷ𱺿.  Tooltip ǳ̶ ؼ ,
        MacOS(ѱ) ׷  ǳ̶ θ  ͼ
        Դϴ.  Ǵٸ ǥ . :) , ϸ鼭  
        õ鿡 ϰ  ϼ ڽ ҰǾ ֽϴ.
        ׳ ' '    ϳ׿.  :)   ؼ
         ,  ʵ Ŷ(toolkit) ã   
        ̴ϴ.

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

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

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

     ؽƮ widget
          ؽƮ ٷ   ؽƮ widget  ϰ
        ֽϴ.   widget Ϲ ؽƮ ͳ   
         ֽϴ.
     ȭ  widget
         !' -> ̷±. :)    Preview
        widget  ٸ   οߴ.    
        κ (?!) ϰ   ü ׽ϴ.  (˼ *)
        www.gtk.org ִ  ϼ.

     ̺Ʈڽ widget
        gtk+970916.tar.gz   ϴ widget̶±.
        ޴ ƴϰ ư ƴϰ, ·  ϰ(?)
        δٳ׿. :)

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

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

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

     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)Լ ֳ׿.  ׸  ƿƼ 
        Լ Ұ߽ϴ.

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

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

     ,  ׸ 
         ϰ (?)  ٷ Դϴ.  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)
         ̿ϴ   ̾߱ϰ ֽϴ.

     GTK  ϴ 
        ʹ ߿ ̶   ۿ   ׿. ;)

     Contributing
         ſ ߿ ̴ϴ.

     Credits
          ϴ    鿡   ϴ,
          ߿ Դϴ.  Ϻ  ״ ׽ϴ.

     Tutorial Copyright and Permissions Notice
        GPL      ִ,  ߿ Դϴ.
        Ϻη  ״ ׽ϴ.

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

  (´ Ͻ   ȣ ٽ Ϲ text SGML ·
  ٲٰ ֽ  5 24 Tutorial ؼ ޶ κ ¾
  ߽ϴ.    ôٰ ڱ  ٰ
  ô κ ִٸ Ƹ  κ ȣ  ؼ ߰
  ϰ̴ϴ. ^^;    Ͽ ֽô Ͻ ´Բ
  帳ϴ.  Ȥ ߸  ̳ Ǽ, ڸ ߰Ͻ 
  hanjiho@penta.co.kr  ֽø ô ڽϴ. ´
   GTK+ ſ  Ͻñ ٶϴ.)

  2.  Ұ

  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 Լ(Լ  ) ߾ ̴.

  ⿡ ḮƮ(linked list) ٷ    Լ Բ,
  glib Ҹ   ǥԼ ġ  ִ Լ鵵 °
  ҷ ԵǾ ִ.  g_strerror()ó,    Լ ٸ
  н鿡  ǥ ƴϰų    ̱ , GTK
  ̽ļ ̱  ⿡  ġԼ鵵 .   g_malloc
    ȭߵ libc   ̷⵵ ߴ.

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

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

  3.  ϸ鼭

      GTK ҽ ޾Ƽ װ ġϴ ̴.  
   ֽ  ftp.gtk.org /pub/gtk   ִ.  GTK
   Ǵٸ ҽ http://www.gtk.org/ ִ.  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 ̺Ʈ, ŸӾƿ, Ǵ  
    ٸ ϰ ȴ.  ׷   α׷
  ׷ ͵ õǰ ִ.

  3.1.  GTK Hello World α׷

   ϳ widget(ư)  α׷̴,   hello world
  GTKν  .

  /* helloworld.c */

  #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;
  }

  3.2.  Hello world ϱ

  ϱ  ̷ ϶.

       gcc -Wall -g helloworld.c -o hello_world `gtk-config --cflags` \
           `gtk-config --libs`

  ̷ ϴ  gtk Բ  gtk-config α׷ ̿ϴ
  ̴.  α׷ gtk  α׷ ϱ ؼ 
  Ϸ ġ ʿ '˰'ִ.  gtk-config --cflags 
  Ϸ header ϵ ãƺƾ ϴ include 丮
  ϰ, gtk-config --libs  ũǾ ϴ ̺귯 
  ̺귯 ϴ 丮 Ѵ.

   ũŰ ̺귯   ͵̴.

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

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

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

    The Xlib library (-lX11), GDK   ȴ.

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

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

  3.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 ߰ 
    ʿ䰡  ̴.

  3.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 ǰ ϴ ̴.

  ̺Ʈ Ǵٸ   ϴµ  Ŵ 
  ̴.  ̷ ϸ "delete_event" ñ׳ ߻ϰ ̴ 츮
  "delete_event" ڵ鷯 ȣѴ.   츮 ⼭ TRUE ϸ
   ״ ȭ鿡  ƹϵ  ʴ´. FALSE ϸ
  GTK "destroy" ñ׳ ߻ϰ "destroy" callback ȣǾ GTK
  ȴ.

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

  4.   ư

  4.1.  ڷ

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

  4.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,
      ñ׳ ڵ鷯  ش.

  4.3.   Hello World α׷

  CallbackԼ      ణ  hello world .
  ̰  츮    ŷ widget Ұ ̴.

  /* helloworld2.c */

  #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  ִ.  ̰ Ŵ ణ ٸ 
  ȣۿϸ, Ͻ  鿡   Ѵ.

  5.  ŷ Widget

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

  5.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    ־
      ش.

  5.2.  ڽ  ڼ ˾ƺ

  ̷  , GTK ڽ ŷϴ  ó ȥ
  𸥴.   ɼǵ , ׵     
      ̴.  ׷ ᱹ, 츮 ټ  ⺻
  Ÿ  ȴ.

  <CENTER > <IMG SRC="gtk_tut_packbox1.gif" VSPACE="15" HSPACE="10"
  WIDTH="528" HEIGHT="235" ALT="Box Packing Example Image" > </CENTER >

      ư  ִ ϳ ڽ(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  ⿡ ܳ ̴.  ̰ 
   Ȯ  ̴.

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

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

  5.3.  ŷ   α׷

  /* packbox.c */

  #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;
  }

  5.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  ʴ´ٴ
   ϶.

  5.5.  ̺ ŷ 

  ⼭ 츮 2x2 ̺ ȿ  ư ִ  ϳ .
  ó  ư ࿡ ̰ ° quit ư ο ϸ鼭
  Ʒ࿡ δ. ׷Ƿ  ׸ó ̰ ȴ.

  <CENTER > <IMG SRC="gtk_tut_table.gif" VSPACE="15" HSPACE="10"
  ALT="Table Packing Example Image" WIDTH="180" HEIGHT="120" > </CENTER
  >

  ҽ ڵ ̷.

  /* table.c */
  #include <gtk/gtk.h>

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

  /*  callback α׷ Ѵ */
  void delete_event (GtkWidget *widget, gpointer data)
  {
      gtk_main_quit ();
  }

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

      gtk_init (&argc, &argv);

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

      /*   Ѵ. */
      gtk_window_set_title (GTK_WINDOW (window), "Table");

      /* 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), 20);

      /* 2x2 ̺ . */
      table = gtk_table_new (2, 2, TRUE);

      /* ̺  ´. */
      gtk_container_add (GTK_CONTAINER (window), table);

      /* ù ư . */
      button = gtk_button_new_with_label ("button 1");

      /* ư  "button 1" μ ؼ "callback" Լ
       * θ. */
      gtk_signal_connect (GTK_OBJECT (button), "clicked",
                GTK_SIGNAL_FUNC (callback), (gpointer) "button 1");

      /* ù ư ̺    ´. */
      gtk_table_attach_defaults (GTK_TABLE(table), button, 0, 1, 0, 1);

      gtk_widget_show (button);

      /* ι° ư . */

      button = gtk_button_new_with_label ("button 2");

      /* ư  "button 2" μ ؼ "callback" Լ
       * θ. */
      gtk_signal_connect (GTK_OBJECT (button), "clicked",
                GTK_SIGNAL_FUNC (callback), (gpointer) "button 2");
      /* ι° ư ̺    ´. */
      gtk_table_attach_defaults (GTK_TABLE(table), button, 1, 2, 0, 1);

      gtk_widget_show (button);

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

      /* ư  "delete_event" Լ ȣؼ
       * α׷ . */
      gtk_signal_connect (GTK_OBJECT (button), "clicked",
                          GTK_SIGNAL_FUNC (delete_event), NULL);

      /* "Quit" ư ̺ Ʒ  ο ´. */
      gtk_table_attach_defaults (GTK_TABLE(table), button, 0, 2, 1, 2);

      gtk_widget_show (button);

      gtk_widget_show (table);
      gtk_widget_show (window);

      gtk_main ();

      return 0;
  }

  6.  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̴) ҵ   ü   
   ʴ´.

  6.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  ۿϴ ϴ  ׸ 
  ʴ.

  6.2.  Widget 

     ֵ,  widget ϱ  Ŭ
   Ʈ ִ.

    GtkObject
     +GtkData
     | +GtkAdjustment
     | `GtkTooltips
     `GtkWidget
       +GtkContainer
       | +GtkBin
       | | +GtkAlignment
       | | +GtkEventBox
       | | +GtkFrame
       | | | `GtkAspectFrame
       | | +GtkHandleBox
       | | +GtkItem
       | | | +GtkListItem
       | | | +GtkMenuItem
       | | | | `GtkCheckMenuItem
       | | | |   `GtkRadioMenuItem
       | | | `GtkTreeItem
       | | +GtkViewport
       | | `GtkWindow
       | |   +GtkColorSelectionDialog
       | |   +GtkDialog
       | |   | `GtkInputDialog
       | |   `GtkFileSelection
       | +GtkBox
       | | +GtkButtonBox
       | | | +GtkHButtonBox
       | | | `GtkVButtonBox
       | | +GtkHBox
       | | | +GtkCombo
       | | | `GtkStatusbar
       | | `GtkVBox
       | |   +GtkColorSelection
       | |   `GtkGammaCurve
       | +GtkButton
       | | +GtkOptionMenu
       | | `GtkToggleButton
       | |   `GtkCheckButton
       | |     `GtkRadioButton
       | +GtkCList
       |  `GtkCTree
       | +GtkFixed
       | +GtkList
       | +GtkMenuShell
       | | +GtkMenuBar
       | | `GtkMenu
       | +GtkNotebook
       | +GtkPaned
       | | +GtkHPaned
       | | `GtkVPaned
       | +GtkScrolledWindow
       | +GtkTable
       | +GtkToolbar
       | `GtkTree
       +GtkDrawingArea
       | `GtkCurve
       +GtkEditable
       | +GtkEntry
       | | `GtkSpinButton
       | `GtkText
       +GtkMisc
       | +GtkArrow
       | +GtkImage
       | +GtkLabel
       | | `GtkTipsQuery
       | `GtkPixmap
       +GtkPreview
       +GtkProgressBar
       +GtkRange
       | +GtkScale
       | | +GtkHScale
       | | `GtkVScale
       | `GtkScrollbar
       |   +GtkHScrollbar
       |   `GtkVScrollbar
       +GtkRuler
       | +GtkHRuler
       | `GtkVRuler
       `GtkSeparator
         +GtkHSeparator
         `GtkVSeparator

  6.3.    widget

   widget õ   ͵̴.    ̺Ʈ
   Ϸ GtkEventBox ̿ؾ  ̴.  ``The EventBox
  Widget''  section ϶.

       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 
  ã   ̴.

  7.  ư widget

  7.1.   ư

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

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

  /* buttons.c */

  #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 Ƚʰ
   ŷϱ Ͽ    ̴.

  7.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"ñ׳ ߻Ų.

  7.3.  üũư

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

  ̰  ΰ Լ ư .

  GtkWidget* gtk_check_button_new (void);

  GtkWidget* gtk_check_button_new_with_label (gchar *label);

  new_with_labelԼ  ؽƮ   ִ üũư .

  üũư ¸ üũϴ  ۹ư .

  7.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);

  ̰ ۹ư  κп Ǿ, Ȯ  
  .

     ư ̷ ׷ .

  /* radiobuttons.c */

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

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

  main(int argc,char *argv[])
  {
    static GtkWidget *window = NULL;
    GtkWidget *box1;
    GtkWidget *box2;
    GtkWidget *button;
    GtkWidget *separator;
    GSList *group;

    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_window_set_title (GTK_WINDOW (window), "radio buttons");
    gtk_container_border_width (GTK_CONTAINER (window), 0);

    box1 = gtk_vbox_new (FALSE, 0);
    gtk_container_add (GTK_CONTAINER (window), box1);
    gtk_widget_show (box1);

    box2 = gtk_vbox_new (FALSE, 10);
    gtk_container_border_width (GTK_CONTAINER (box2), 10);
    gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
    gtk_widget_show (box2);

    button = gtk_radio_button_new_with_label (NULL, "button1");
    gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
    gtk_widget_show (button);

    group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
    button = gtk_radio_button_new_with_label(group, "button2");
    gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE);
    gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
    gtk_widget_show (button);

    group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
    button = gtk_radio_button_new_with_label(group, "button3");
    gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
    gtk_widget_show (button);

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

    box2 = gtk_vbox_new (FALSE, 10);
    gtk_container_border_width (GTK_CONTAINER (box2), 10);
    gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
    gtk_widget_show (box2);

    button = gtk_button_new_with_label ("close");
    gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
                               GTK_SIGNAL_FUNC(close_application),
                               GTK_OBJECT (window));
    gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
    GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
    gtk_widget_grab_default (button);
    gtk_widget_show (button);
    gtk_widget_show (window);

    gtk_main();
    return(0);
  }

        ϳ ư Ʈ 
  ־ ʿ䰡  ٿ   ִ.

            button2 = gtk_radio_button_new_with_label(
                        gtk_radio_button_group (GTK_RADIO_BUTTON (button1)),
                        "button2");

  8.  پ widget

  8.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);

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

  8.2.  ǳ (tooltip widget)

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

     widget  tooltip  ʴ´.

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

       GtkTooltips *gtk_tooltips_new (void);

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

       void gtk_tooltips_set_tip (GtkTooltips *tooltips,
                                  GtkWidget   *widget,
                                  const gchar *tip_text,
                                  const gchar *tip_private);

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

  ̰ ª .

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

  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 õ Լ ̰ δ.  ̻  ͵ .  :)

  8.3.  ื(progress bar)

  ื ۾ Ȳ Ÿ  δ.   ڵ带 
  ˰, ̰  ϴ.  ׷  ο ื븦
  ִ Լ    .

       GtkWidget *gtk_progress_bar_new (void);

   ื밡  츮 װ ̿  ִ.

       void gtk_progress_bar_update (GtkProgressBar *pbar, gfloat percentage);

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

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

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

  /* progressbar.c */

  #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   ื븦 ƮѴ.

  ׸ ื뿡    ̰ δ, ܺ⸦ !

  8.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 ڿ ų ޽ ų
  ϴ      ̴.  ׸   ÿ
   ۵ϵ ư   ٸ ñ׳    ִ.

  8.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 );

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

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

  /* wheelbarrow.c */

  #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.6.  귯(ruler)

  귯 widget ־   콺  ġ Űµ
  δ.      귯 ̸ 
  귯   ִ.  귯  ׸ ﰢ ǥñ(indicator)
  귯   Ȯ ġ ش.

  귯 ݵ ̸  ߸ Ѵ.    귯 
  Լ ̿ؼ .

       GtkWidget *gtk_hruler_new(void);    /*  귯 */
       GtkWidget *gtk_vruler_new(void);    /*  귯 */

  귯 ѹ     ִ. 귯 
  GTK_PIXELS GTK_INCHES, GTK_CENTIMETERS  ϳ ȴ.

       void gtk_ruler_set_metric( GtkRuler        *ruler,
                                  GtkMetricType   metric );

  ⺻   GTK_PIXELS̴.

       gtk_ruler_set_metric( GTK_RULER(ruler), GTK_PIXELS );

  Ǵٸ ߿ 귯 Ư  ũ  Ÿ ϴ 
  ǥñⰡ ó  ̳ϴ ̴. ̵  Լ Ѵ.

       void  gtk_ruler_set_range  (GtkRuler       *ruler,
                                   gfloat          lower,
                                   gfloat          upper,
                                   gfloat          position,
                                   gfloat          max_size);

   lower upper 귯  ϰ max_size  
   ū  Ѵ. Position 귯  ǥñ ʱ ġ̴.

  800 ȼ  귯 ̷ ȴ.

       gtk_ruler_set_range( GTK_RULER(vruler), 0, 800, 0, 800);

  0 800  100 ȼ ǥ(marking) µ ̴.  
  귯  7 16 ٲٷ   Ѵ.

       gtk_ruler_set_range( GTK_RULER(vruler), 7, 16, 0, 20);

  귯 ǥñ   ġ Ű ׸ ﰢ
  ǥ̴.   귯 콺 ͸  ϰ ʹٸ
  motion_notify_event ñ׳ 귯 motion_notify_event method
  Ǿ߸ Ѵ. Ư     콺  
  ϱ    Ѵ.

       #define EVENT_METHOD(i, x) GTK_WIDGET_CLASS(GTK_OBJECT(i)->klass)->x

       gtk_signal_connect_object( GTK_OBJECT(area), "motion_notify_event",
                (GtkSignalFunc)EVENT_METHOD(ruler, motion_notify_event),
                GTK_OBJECT(ruler) );

     귯   귯 ʿ  drawing area
  .  drawing area 600 ȼ  400 ȼ ̸ .
   귯 7 13   100 ȼ ǥ ϰ  緯
  0 400    100 ȼ ǥ Ѵ.  귯
  drawing area ġ  ̺ Ѵ.

  /* rulers.c */

  #include <gtk/gtk.h>

  #define EVENT_METHOD(i, x) GTK_WIDGET_CLASS(GTK_OBJECT(i)->klass)->x

  #define XSIZE  600
  #define YSIZE  400

  /* ݱ ư(close button)   Լ Ҹ.
   */
  void close_application( GtkWidget *widget, gpointer data ) {
      gtk_main_quit();
  }

  /*  Լ
   */
  int main( int argc, char *argv[] ) {
      GtkWidget *window, *table, *area, *hrule, *vrule;

      /* gtk ʱȭϰ   .*/
      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);

      /* 귯 drawing area  ̺  */
      table = gtk_table_new( 3, 2, FALSE );
      gtk_container_add( GTK_CONTAINER(window), table );

      area = gtk_drawing_area_new();
      gtk_drawing_area_size( (GtkDrawingArea *)area, XSIZE, YSIZE );
      gtk_table_attach( GTK_TABLE(table), area, 1, 2, 1, 2,
                        GTK_EXPAND|GTK_FILL, GTK_FILL, 0, 0 );
      gtk_widget_set_events( area, GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK );

      /*  귯   δ.  콺 drawing area  ̸,
         motion_notify_event  귯  ̺Ʈ ڵ鷯 ޵ȴ.
       */
      hrule = gtk_hruler_new();
      gtk_ruler_set_metric( GTK_RULER(hrule), GTK_PIXELS );
      gtk_ruler_set_range( GTK_RULER(hrule), 7, 13, 0, 20 );
      gtk_signal_connect_object( GTK_OBJECT(area), "motion_notify_event",
                                 (GtkSignalFunc)EVENT_METHOD(hrule, motion_notify_event),
                                 GTK_OBJECT(hrule) );
      /*  GTK_WIDGET_CLASS(GTK_OBJECT(hrule)->klass)->motion_notify_event, */
      gtk_table_attach( GTK_TABLE(table), hrule, 1, 2, 0, 1,
                        GTK_EXPAND|GTK_SHRINK|GTK_FILL, GTK_FILL, 0, 0 );

      /*  귯  ʿ δ.  콺 drawing area  ̸,,
         motion_notify_event  귯  ̺Ʈ ڵ鷯 ޵ȴ.
       */
      vrule = gtk_vruler_new();
      gtk_ruler_set_metric( GTK_RULER(vrule), GTK_PIXELS );
      gtk_ruler_set_range( GTK_RULER(vrule), 0, YSIZE, 10, YSIZE );
      gtk_signal_connect_object( GTK_OBJECT(area), "motion_notify_event",
                                 (GtkSignalFunc)
                                    GTK_WIDGET_CLASS(GTK_OBJECT(vrule)->klass)->motion_notify_event,
                                 GTK_OBJECT(vrule) );
      gtk_table_attach( GTK_TABLE(table), vrule, 0, 1, 1, 2,
                        GTK_FILL, GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0 );

      /*    ش */
      gtk_widget_show( area );
      gtk_widget_show( hrule );
      gtk_widget_show( vrule );
      gtk_widget_show( table );
      gtk_widget_show( window );
      gtk_main();

      return 0;
  }

  8.7.  ǥ(statusbar)

  ǥ ؽƮ ޽ ִµ ̴  widget̴.  
  widget ؽƮ ޽ ÿ Ѵ.   ޽
   ٷ  ޽ ٽ ְ ȴ.

   ø̼  κе ޽ ǥϴµ  ǥ
  ؾϴ , ǥ widget  '' ϴµ
  ̴ Context Identifier Ѵ.  context Ŀ
      ޽ .  ޽ Context
  Identifier  ƴ϶ ߿     
  ÿ δ.

  ǥ  Լ  .

       GtkWidget* gtk_statusbar_new (void);

  ο Context Identifier  context   Բ 
  Լ ȣϿ   ִ.

       guint gtk_statusbar_get_context_id (GtkStatusbar *statusbar,
                                           const gchar  *context_description);

  ǥ ٷ   Լ ִ.

       guint    gtk_statusbar_push        (GtkStatusbar *statusbar,
                                           guint          context_id,
                                           gchar         *text);

       void     gtk_statusbar_pop         (GtkStatusbar *statusbar)
                                           guint         context_id);
       void     gtk_statusbar_remove      (GtkStatusbar *statusbar,
                                           guint         context_id,
                                           guint         message_id);

   gtk_statusbar_push ǥٿ ο ޽ ߰ϴµ
  δ.   Լ ߿ gtk_statusbar_remove ȣϴµ  
  ִ Message Identifier Ѵ. gtk_statusbar_remove ־
  Message Context Identifier ޽ ǥٿ Ѵ.
  gtk_statusbar_pop ־ Context Identifier    ޽
   Ѵ.

    ư 2 ǥ ϳ . ư ϳ
  ǥٿ  ޽ ְ  ٸ ư  ־
  ޽ Ѵ.

  /* statusbar.c */

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

  GtkWidget *status_bar;

  void push_item (GtkWidget *widget, gpointer data)
  {
    static int count = 1;
    char buff[20];

    g_snprintf(buff, 20, "Item %d", count++);
    gtk_statusbar_push( GTK_STATUSBAR(status_bar), (guint) &data, buff);

    return;
  }

  void pop_item (GtkWidget *widget, gpointer data)
  {
    gtk_statusbar_pop( GTK_STATUSBAR(status_bar), (guint) &data );
    return;
  }

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

      GtkWidget *window;
      GtkWidget *vbox;
      GtkWidget *button;

      int context_id;

      gtk_init (&argc, &argv);

      /*   ϳ  */
      window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
      gtk_widget_set_usize( GTK_WIDGET (window), 200, 100);
      gtk_window_set_title(GTK_WINDOW (window), "GTK Statusbar Example");
      gtk_signal_connect(GTK_OBJECT (window), "delete_event",
                         (GtkSignalFunc) gtk_exit, NULL);

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

      status_bar = gtk_statusbar_new();
      gtk_box_pack_start (GTK_BOX (vbox), status_bar, TRUE, TRUE, 0);
      gtk_widget_show (status_bar);

      context_id = gtk_statusbar_get_context_id( GTK_STATUSBAR(status_bar), "Statusbar example");

      button = gtk_button_new_with_label("push item");
      gtk_signal_connect(GTK_OBJECT(button), "clicked",
          GTK_SIGNAL_FUNC (push_item), &context_id);
      gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 2);
      gtk_widget_show(button);

      button = gtk_button_new_with_label("pop last item");
      gtk_signal_connect(GTK_OBJECT(button), "clicked",
          GTK_SIGNAL_FUNC (pop_item), &context_id);
      gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 2);
      gtk_widget_show(button);

      /* ٸ  ͵ ѹ   ̵ ϱ ؼ
       * ׻    ش. */
      gtk_widget_show(window);

      gtk_main ();

      return 0;
  }

  8.8.  ؽƮ Է(text entry)

  ؽƮ Է widget ¥ ؽƮ  ȿ ڸ Ÿ ְų
  Ǵ ׳   ְ ش. ؽƮ  Է widget 
  ߰ϰų Ǵ  üϴ Լ ȣ鿡  ȴ.

  ؽƮ Է widget µ   Լ Ѵ.

       GtkWidget* gtk_entry_new (void);

       GtkWidget* gtk_entry_new_with_max_length (guint16 max);

  ó  ܼ ο Է widget ϳ . ׿  ι°
    ؽƮ    Է widget .

   Է ؽƮ ϴµ ̴  Լ Ѵ.

       void gtk_entry_set_text       (GtkEntry    *entry,
                                      const gchar *text);
       void gtk_entry_append_text    (GtkEntry    *entry,
                                      const gchar *text);
       void gtk_entry_prepend_text   (GtkEntry    *entry,
                                      const gchar *text);

  Լ gtk_entry_set_text Էµ   Ѵ.  Լ
  gtk_entry_append_text gtk_entry_prepend_text    Ǵ
  ڿ ϴ ؽƮ δ.

   Լ  ؽƮ Է ġ Ѵ.

       void gtk_entry_set_position   (GtkEntry *entry,
                                      gint     position);

  Է widget   Լ ȣ⿡ ؼ   ִ.  ̰
  ߿  callback Լ ȿ ϴ  ϴ.

       gchar* gtk_entry_get_text (GtkEntry *entry);

   Էµ  Ÿο ؼ Ǵ   ʴ´ٸ
   Ұϵ ¸ ٲ  ִ.

       void gtk_entry_set_editable (GtkEntry *entry,
                                    gboolean editable);

   Լ editable ڿ TRUE FALSE ־ Է widget 
  ϰ ǰų Ǵ  ʵ   ִ.

   н带 Է ó Էϴ ؽƮ  ʾƾ Ѵٸ
  boolean flag   Լ Ѵ.

       void gtk_entry_set_visibility (GtkEntry *entry,
                                      gboolean visible);

   Լ Ἥ ؽƮ  κ (selected)ǵ  
  ִ.    ̸ ⺻ ؽƮ  ϰ ̸ ڰ ο
  Է ؼ    ְ ϴµ  δ.

       void gtk_entry_select_region (GtkEntry *entry,
                                     gint     start,
                                     gint     end);

  ࿡ ڰ ؽƮ Էϴ  ˾ä ʹٸ, activate
  changed ñ׳   ִ.  Activate ڰ Ű
  Ÿϸ, Changed ؽƮ  ٸ  ٲ ߻Ѵ.(
  ڰ ԷµǾų   )

   ؽƮ Է widget  ̴.

  /* entry.c */

  #include <gtk/gtk.h>

  void enter_callback(GtkWidget *widget, GtkWidget *entry)
  {
    gchar *entry_text;
    entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
    printf("Entry contents: %s\n", entry_text);
  }

  void entry_toggle_editable (GtkWidget *checkbutton,
                                     GtkWidget *entry)
  {
    gtk_entry_set_editable(GTK_ENTRY(entry),
                           GTK_TOGGLE_BUTTON(checkbutton)->active);
  }

  void entry_toggle_visibility (GtkWidget *checkbutton,
                                     GtkWidget *entry)
  {
    gtk_entry_set_visibility(GTK_ENTRY(entry),
                           GTK_TOGGLE_BUTTON(checkbutton)->active);
  }

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

      GtkWidget *window;
      GtkWidget *vbox, *hbox;
      GtkWidget *entry;
      GtkWidget *button;
      GtkWidget *check;

      gtk_init (&argc, &argv);

      /* create a new window */
      window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
      gtk_widget_set_usize( GTK_WIDGET (window), 200, 100);
      gtk_window_set_title(GTK_WINDOW (window), "GTK Entry");
      gtk_signal_connect(GTK_OBJECT (window), "delete_event",
                         (GtkSignalFunc) gtk_exit, NULL);

      vbox = gtk_vbox_new (FALSE, 0);
      gtk_container_add (GTK_CONTAINER (window), vbox);
      gtk_widget_show (vbox);

      entry = gtk_entry_new_with_max_length (50);
      gtk_signal_connect(GTK_OBJECT(entry), "activate",
                         GTK_SIGNAL_FUNC(enter_callback),
                         entry);
      gtk_entry_set_text (GTK_ENTRY (entry), "hello");
      gtk_entry_append_text (GTK_ENTRY (entry), " world");
      gtk_entry_select_region (GTK_ENTRY (entry),
                               0, GTK_ENTRY(entry)->text_length);
      gtk_box_pack_start (GTK_BOX (vbox), entry, TRUE, TRUE, 0);
      gtk_widget_show (entry);

      hbox = gtk_hbox_new (FALSE, 0);
      gtk_container_add (GTK_CONTAINER (vbox), hbox);
      gtk_widget_show (hbox);

      check = gtk_check_button_new_with_label("Editable");
      gtk_box_pack_start (GTK_BOX (hbox), check, TRUE, TRUE, 0);
      gtk_signal_connect (GTK_OBJECT(check), "toggled",
                          GTK_SIGNAL_FUNC(entry_toggle_editable), entry);
      gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(check), TRUE);
      gtk_widget_show (check);

      check = gtk_check_button_new_with_label("Visible");
      gtk_box_pack_start (GTK_BOX (hbox), check, TRUE, TRUE, 0);
      gtk_signal_connect (GTK_OBJECT(check), "toggled",
                          GTK_SIGNAL_FUNC(entry_toggle_visibility), entry);
      gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(check), TRUE);
      gtk_widget_show (check);

      button = gtk_button_new_with_label ("Close");
      gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
                                 GTK_SIGNAL_FUNC(gtk_exit),
                                 GTK_OBJECT (window));
      gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
      GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
      gtk_widget_grab_default (button);
      gtk_widget_show (button);

      gtk_widget_show(window);

      gtk_main();
      return(0);
  }

  8.9.   (color selection)

   widget,    ʰ,   ϴµ
  δ.    widget ڷ Ͽ RGB(Red, Green, Blue)
  HSV (Hue, Saturation, Value)  Ҹ    Ѵ.  ̴
  ̴ Էâ ̿ؼ  ҿ Ư  ְϰų Ǵ, hue-
  saturation wheel   ϰ ν ̷. ʿ信
  󼭴     ִ.

    widget ܺο gtk_color_selection_set_color() 
  ߰ų Ǵ ڰ     
  "color_changed"̶  Ѱ ñ׳θ ߻Ų.

    widget 츮  Ѱ־ ϴ .  widget
  gtk_color_selection gtk_color_selection_dialog  ° ִ.

       GtkWidget *gtk_color_selection_new(void);

  밳  Լ    . ̰ ߿ 򰡷 
  ־߸ ϴ GtkColorSelection widget  ̴.  
  GtkColorSelection widget GtkVBox widget ӵ ̴.

       GtkWidget *gtk_color_selection_dialog_new(const gchar *title);

  밳  Լ  widget   Ѵ.  ̴
  GtkColorSelectionDialog GtkDialog ӵ widget .  
  widget GtkColorSelection, GtkHSeparator "Ok", "Cancel", "Help"
  ư   GtkHBox  GtkFrame widget ̷ִ.
  GtkColorSelectionDialog structure "ok_button", "cancel_button",
  "help_button" widget ؼ   ư  ٷ  ִ.  (
  : GTK_COLOR_SELECTION_DIALOG(colorseldialog)->ok_button)

       void gtk_color_selection_set_update_policy(GtkColorSelection *colorsel,
                                                  GtkUpdateType policy);

   Լ  å Ѵ. ⺻ å ڰ ̵ ϴ
  ׶ ٷ    ű⿡  ٲٴ
  GTK_UPDATE_CONTINOUS̴.  ɹ ߻ϸ
  GTK_UPDATE_DISCONTINOUS GTK_UPDATE_DELAYED ٲپ   ִ.

       void gtk_color_selection_set_opacity(GtkColorSelection *colorsel,
                                            gint use_opacity);

   widget  (ä̶ ˷) ϴ ɵ
  Ѵ.    ⺻  ִ. ̰ Ϸ 
  Լ use_opacity TRUE ؼ ȣѴ.   use_opacity
  FALSE ؼ ȣϸ    .

       void gtk_color_selection_set_color(GtkColorSelection *colorsel,
                                          gdouble *color);

   array(gdouble) Բ  Լ ȣϿ ܺο  
     ִ.  array ̴     ѳҴ
  Ҵ  ޶. ġ 0 , 1 , 2 Ķ̸
  3 ̴.(   ѳ  ǹ̰ ִ.  տ
   gtk_color_selection_set_opacity()  κ .)   
  0.0 1.0 ̿ ִ.

       void gtk_color_selection_get_color(GtkColorSelection *colorsel,
                                          gdouble *color);

   'color_changed" ñ׳ ޾ ,     ˰
  ʹٸ  Լ ϸ ȴ. Color  array̴.   array
    gtk_color_selection_set_color() Լ  κ .

   GtkColorSelectionDialog ϴ  ̴.  α׷
  drawing area   ϳ . ̰ Ŭϸ color
  selection dialog . ̸ ؼ  ٲ  ִ.

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

  GtkWidget *colorseldlg = NULL;
  GtkWidget *drawingarea = NULL;

  /*  ٲ  Լ θ. */

  void color_changed_cb (GtkWidget *widget, GtkColorSelection *colorsel)
  {
    gdouble color[3];
    GdkColor gdk_color;
    GdkColormap *colormap;

    /* drawing area colormap ´ */

    colormap = gdk_window_get_colormap (drawingarea->window);

    /*   ´ */

    gtk_color_selection_get_color (colorsel,color);

    /* unsigned 16 bit (0..65535) ٲ㼭 GdkColor ִ´  */

    gdk_color.red = (guint16)(color[0]*65535.0);
    gdk_color.green = (guint16)(color[1]*65535.0);
    gdk_color.blue = (guint16)(color[2]*65535.0);

    /*  ҴѴ */

    gdk_color_alloc (colormap, &gdk_color);

    /*   Ѵ */

    gdk_window_set_background (drawingarea->window, &gdk_color);

    /*   */

    gdk_window_clear (drawingarea->window);
  }

  /* Drawingarea event handler */

  gint area_event (GtkWidget *widget, GdkEvent *event, gpointer client_data)
  {
    gint handled = FALSE;
    GtkWidget *colorsel;

    /* ư  ȮѴ */

    if (event->type == GDK_BUTTON_PRESS && colorseldlg == NULL)
      {
        /* Yes, we have an event and there's no colorseldlg yet! */

        handled = TRUE;

        /* color selection dialog  */

        colorseldlg = gtk_color_selection_dialog_new("Select background color");

        /* GtkColorSelection widget Ѵ */

        colorsel = GTK_COLOR_SELECTION_DIALOG(colorseldlg)->colorsel;

        /* "color_changed" ñ׳ widget Ѵ. */
        gtk_signal_connect(GTK_OBJECT(colorsel), "color_changed",
          (GtkSignalFunc)color_changed_cb, (gpointer)colorsel);

        /* color seclection dialog δ */

        gtk_widget_show(colorseldlg);
      }

    return handled;
  }

  /*  ݰ ڵ鷯  */

  void destroy_window (GtkWidget *widget, gpointer client_data)
  {
    gtk_main_quit ();
  }

  /* Main */

  gint main (gint argc, gchar *argv[])
  {
    GtkWidget *window;

    /* Ŷ ʱȭϰ gtk õ Է ҵ ش. */

    gtk_init (&argc,&argv);

    /* toplevel    policy Ѵ */

    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title (GTK_WINDOW(window), "Color selection test");
    gtk_window_set_policy (GTK_WINDOW(window), TRUE, TRUE, TRUE);

    /* "delete"  "destroy" ̺Ʈ  Ѵ */

    gtk_signal_connect (GTK_OBJECT(window), "delete_event",
      (GtkSignalFunc)destroy_window, (gpointer)window);

    gtk_signal_connect (GTK_OBJECT(window), "destroy",
      (GtkSignalFunc)destroy_window, (gpointer)window);

    /* drawingarea  ,  ũ⸦ ϰ ư ̺Ʈ Ѵ */

    drawingarea = gtk_drawing_area_new ();

    gtk_drawing_area_size (GTK_DRAWING_AREA(drawingarea), 200, 200);

    gtk_widget_set_events (drawingarea, GDK_BUTTON_PRESS_MASK);

    gtk_signal_connect (GTK_OBJECT(drawingarea), "event",
      (GtkSignalFunc)area_event, (gpointer)drawingarea);

    /* drawingarea   ̰   ش. */

    gtk_container_add (GTK_CONTAINER(window), drawingarea);

    gtk_widget_show (drawingarea);
    gtk_widget_show (window);

    /* gtk main loop . (ٽô ƿ Ѵ.) */

    gtk_main ();

    /* ٷο Ϸ Ų */

    return 0;
  }

  8.10.   (file selection)

  ϼ 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鿡  ͵鵵 ִ.  ׵
   .

    dir_list

    file_list

    selection_entry

    selection_text

    main_vbox

    ok_button

    cancel_button

    help_button

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

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

       #include <gtk/gtk.h>
       /* filesel.c */

       /* õ  ̸ ؼ װ ַܼ ƮѴ. */
       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;
       }

  9.  ̳ widget

  9.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
  ְų  ,      ִ.  ׸ յ
    ٲָ, α׷   ִ.

  /* notebook.c */

  #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    Ʈ ٷ  
   Ǳ⸦ ٶ.

  9.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  ư ŷѴ.
  ⼭ ּ п  κп ٿ ̴.

  /* scrolledwin.c */

  #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.3.  Paned  widget

   paned  widget   ڿ ؼ   ũ⸦
     ִ       Ѵ.  
   ̿ handle ޸ Ȩ ְ ̸ 콺 巡ؼ
  ڴ ϴ     ٲ  ִ.  ̷ 
  (HPaned)̰ų (VPaned) ȴ.

   paned    ϳ θ.

       GtkWidget* gtk_hpaned_new (void)
       GtkWidget* gtk_vpaned_new (void)

  Paned  widget    ʿ ڽ widget ־
  Ѵ.  ̴  Լ ̿ؼ ̷.

       void gtk_paned_add1 (GtkPaned *paned, GtkWidget *child)
       void gtk_paned_add2 (GtkPaned *paned, GtkWidget *child)

  gtk_paned_add1() paned  widget  Ȥ ʿ  ڽ widget
  Ѵ. gtk_paned_add2() ݴ  Ȥ Ʒʿ Ѵ.

     email α׷  ̽ Ϻθ 
   Ѵ.   email ޼ Ʈ ǥϴ  κа
  ޼ ü ǥϴ Ʒ κ . α׷ κ
  ô ϴ.  ΰ ؾ   ִ.  ؽƮ ؽƮ
  widget ̰ realizeǱ    . ̴
  gtk_widget_realize() ȣؼ ̷  ٸ  text
  ϱ  "realize" ñ׳   ִ.  , GTK_SHRINK
  ɼ text  ũѹٸ ϰ ִ ̺  Ϻο
  ִ  ʿϴ. ׷߸ Ʒ κ ۰ 鶧  ٴ
  з  ϴ κ پ ȴ.

  /* paned.c */

  #include <gtk/gtk.h>

  /* "messages" Ʈ  */
  GtkWidget *
  create_list (void)
  {

      GtkWidget *scrolled_window;
      GtkWidget *list;
      GtkWidget *list_item;

      int i;
      char buffer[16];

      /* ũѹ(ʿ )  ũѵ  . */
      scrolled_window = gtk_scrolled_window_new (NULL, NULL);
      gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
                                      GTK_POLICY_AUTOMATIC,
                                      GTK_POLICY_AUTOMATIC);

      /* ο Ʈ  ̸ ũѵ  ִ´. */
      list = gtk_list_new ();
      gtk_container_add (GTK_CONTAINER(scrolled_window), list);
      gtk_widget_show (list);

      /*  ޽  Ѵ */
      for (i=0; i<10; i++) {

          sprintf(buffer,"Message #%d",i);
          list_item = gtk_list_item_new_with_label (buffer);
          gtk_container_add (GTK_CONTAINER(list), list_item);
          gtk_widget_show (list_item);

      }

      return scrolled_window;
  }

  /* ؽƮ  ؽƮ widget Ѵ. - Ʒ Լ 츮  realize 
   Ҹ callback̴. gtk_widget_realize realizeǵ   
  װ    κ Ǿ  ̴.
  */
  void
  realize_text (GtkWidget *text, gpointer data)
  {
      gtk_text_freeze (GTK_TEXT (text));
      gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL,
      "From: pathfinder@nasa.gov\n"
      "To: mom@nasa.gov\n"
      "Subject: Made it!\n"
      "\n"
      "We just got in this morning. The weather has been\n"
      "great - clear but cold, and there are lots of fun sights.\n"
      "Sojourner says hi. See you soon.\n"
      " -Path\n", -1);

      gtk_text_thaw (GTK_TEXT (text));
  }

  /* "message" ִ ũѵ ؽƮ  . */
  GtkWidget *
  create_text (void)
  {
      GtkWidget *table;
      GtkWidget *text;
      GtkWidget *hscrollbar;
      GtkWidget *vscrollbar;

      /* ؽƮ  ũѹٸ  ̺  */
      table = gtk_table_new (2, 2, FALSE);

      /* ؽƮ    ´. Y   GTK_SHRINK  
       * ָ . */
      text = gtk_text_new (NULL, NULL);
      gtk_table_attach (GTK_TABLE (table), text, 0, 1, 0, 1,
                        GTK_FILL | GTK_EXPAND,
                        GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0);
      gtk_widget_show (text);

      /* HScrollbar  Ʒ ´. */
      hscrollbar = gtk_hscrollbar_new (GTK_TEXT (text)->hadj);
      gtk_table_attach (GTK_TABLE (table), hscrollbar, 0, 1, 1, 2,
                        GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
      gtk_widget_show (hscrollbar);

      /* VScrollbar   ´. */
      vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
      gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
                        GTK_FILL, GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0);
      gtk_widget_show (vscrollbar);

      /* ؽƮ widget realizeǾ   widget  ִ ޽
       * Ͽִ ñ׳ ڵ鷯 Ѵ. */
      gtk_signal_connect (GTK_OBJECT (text), "realize",
                          GTK_SIGNAL_FUNC (realize_text), NULL);

      return table;
  }

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

      gtk_init (&argc, &argv);

      window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
      gtk_window_set_title (GTK_WINDOW (window), "Paned Windows");
      gtk_signal_connect (GTK_OBJECT (window), "destroy",
                          GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
      gtk_container_border_width (GTK_CONTAINER (window), 10);

      /* vpaned widget  toplevel  Ѵ. */

      vpaned = gtk_vpaned_new ();
      gtk_container_add (GTK_CONTAINER(window), vpaned);
      gtk_widget_show (vpaned);

      /*    κ  . */

      list = create_list ();
      gtk_paned_add1 (GTK_PANED(vpaned), list);
      gtk_widget_show (list);

      text = create_text ();
      gtk_paned_add2 (GTK_PANED(vpaned), text);
      gtk_widget_show (text);
      gtk_widget_show (window);
      gtk_main ();
      return 0;
  }

  9.4.  Aspect 

  Aspect   Ư¡   widget ϴ.  
  widget ڽ widget aspect (ο  ) ݵ 
  Ư  ǵ     ؼ Ѵ.
  ̰    ū ̹ ̸⸦    
  ϴ.   ̸ ũ ڰ  ũ⸦ ٲ 
  ޶ μ    ̹ ƾ߸ Ѵ.

  ο aspect  ,

       GtkWidget* gtk_aspect_frame_new  (const gchar *label,
                                               gfloat xalign,
                                               gfloat yalign,
                                               gfloat ratio,
                                               gint obey_child)

  xalign yalign Alignment widgetó widget alignment 
  Ѵ.   obey_child  true, ڽ widget μ 
     ̻   ȴ. ݴ false̸ 
   ratio  ־.

  ̹ ϰ ִ aspect  ɼ ٲٷ  Լ
  ̿Ѵ.

       void gtk_aspect_frame_set (GtkAspectFrame *aspect_frame,
                                  gfloat xalign,
                                  gfloat yalign,
                                  gfloat ratio,
                                  gint obey_child)

    α׷ ڰ toplevel  ũ⸦  ٲٵ
   μ  2:1 drawing area ǥϴµ AspectFrame
   ִ.

  /* aspectframe.c */

  #include <gtk/gtk.h>

  int
  main (int argc, char *argv[])
  {
      GtkWidget *window;
      GtkWidget *aspect_frame;
      GtkWidget *drawing_area;
      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_main_quit), NULL);
      gtk_container_border_width (GTK_CONTAINER (window), 10);

      /* aspect_frame  toplevel  Ѵ */

      aspect_frame = gtk_aspect_frame_new ("2x1", /* ̺ */
                                           0.5, /* center x */
                                           0.5, /* center y */
                                           2, /* xsize/ysize = 2 */
                                           FALSE /* ڽ μ  */);

      gtk_container_add (GTK_CONTAINER(window), aspect_frame);
      gtk_widget_show (aspect_frame);

      /* aspect frame  ڽ widget */

      drawing_area = gtk_drawing_area_new ();

      /* 200x200  û AspectFrame 2:1  ϱ 
       * 200x100  ش. */
      gtk_widget_set_usize (drawing_area, 200, 200);
      gtk_container_add (GTK_CONTAINER(aspect_frame), drawing_area);
      gtk_widget_show (drawing_area);

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

  10.  Ʈ 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 ̰͵  ϳ  ̴.

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

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

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

    GTK_SELECTION_EXTENDED -   'NULL'̴.

  Ʈ GTK_SELECTION_MULTIPLE̴.

  10.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 ų
    Ǵٸ ο   ߻Ѵ.

  10.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 ϴ Ѵ.  ڼ
  ˷ Ϲ ũθ ϶.

  10.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");
  }

  10.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    ִ.

  10.5.  ñ׳

  GtkListItem ڽŸ ñ׳   ʰ, GtkItem ñ׳
  ӹ޴´.  ڼ  GtkItem ؼ ϶.

  10.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 ϰ ִ Ѵ.  ڼ
   Ϲ ũο ؼ ϶.

  10.7.  

  GtkList   ϶.  װ GtkListItem ̿
  ؼ  ٷ ִ.

  11.  ޴ widget

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

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

  11.1.   ޴ 

   ٶ 뿡 ,    ̰ڴ.:)

  ޴ٿ ޴(submenu)鸦 µ   widget ִ.

    ޴ (menu item) : ڰ ϴ ٷ װ̴. (:
     'Save')

    ޴(menu) : ޴ ۵ ̴̳.

    ޴(menubar) :  ޴ ϴ ̴̳.

  ޴  widget ΰ ٸ 뵵   ִٴ  ణ
    ִ. ޴  ܼ ޴    ְ Ǵ
  ޴   õǾ  Ư ޴ ȰȭŰ  
  ִ.

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

       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_new_with_label ܼ gtk_menu_new Լ  ư
    Ŀ ϴ ״δ.  gtk_menu_new_with_label 
  ̹ ŷǾ ִ ޴  , gtk_menu_new ִ ޴
   .

  ѹ ޴   ݵ ̸ ޴ ȿ ־߸ Ѵ.  ̴
  gtk_menu_append Լ ̿ؼ ̷.   ڿ
   õǾ  ̸ ˾Ƴ óϱ ؼ activate ñ׳
   ϵ Ѵ.  ׷  Open, Save, Quit ɼ 
  ǥ File ޴  Ѵٸ ҽ ڵ   ȴ.

       file_menu = gtk_menu_new();    /* ޴  ʿ . */

       /* ޴ ۵ . */
       open_item = gtk_menu_item_new_with_label("Open");
       save_item = gtk_menu_item_new_with_label("Save");
       quit_item = gtk_menu_item_new_with_label("Quit");

       /* װ͵ ޴ δ. */
       gtk_menu_append( GTK_MENU(file_menu), open_item);
       gtk_menu_append( GTK_MENU(file_menu), save_item);
       gtk_menu_append( GTK_MENU(file_menu), quit_item);

       /* "activate" ñ׳ΰ callback Լ Ѵ. */
       gtk_signal_connect_object( GTK_OBJECT(open_items), "activate",
                          GTK_SIGNAL_FUNC(menuitem_response), (gpointer) "file.open");
       gtk_signal_connect_object( GTK_OBJECT(save_items), "activate",
                          GTK_SIGNAL_FUNC(menuitem_response), (gpointer) "file.save");

       /* Quit ޴ ۿ  exit Լ Ѵ. */
       gtk_signal_connect_object( GTK_OBJECT(quit_items), "activate",
                          GTK_SIGNAL_FUNC(destroy), (gpointer) "file.quit");

       /*  ޴ ۵  Ѵ. */
       gtk_widget_show( open_item );
       gtk_widget_show( save_item );
       gtk_widget_show( quit_item );

  ϸ ʿ ޴ ϴ  ̴.  ݱ  ޴
   File ޴ ۰ ޴ٸ  Ѵ.  ڵ ̷ ȴ.

       menu_bar = gtk_menu_bar_new();
       gtk_container_add( GTK_CONTAINER(window), menu_bar);
       gtk_widget_show( menu_bar );

       file_item = gtk_menu_item_new_with_label("File");
       gtk_widget_show(file_item);

   file_item ޴ ؾ Ѵ. ̰  Լ 
  ̷.

       void gtk_menu_item_set_submenu( GtkMenuItem *menu_item, GtkWidget
       *submenu);

  ׷ 츮   ڵ ̾.

  gtk_menu_item_set_submenu( GTK_MENU_ITEM(file_item), file_menu);

  ؾ    ޴ ޴ٿ ̴ ̴. ̴  Լ
  ̿Ѵ.

       void gtk_menu_bar_append( GtkMenuBar *menu_bar, GtkWidget *menu_item);

  츮 ڵ忡   ȴ.

       gtk_menu_bar_append( GTK_MENU_BAR (menu_bar), file_item );

   ޴ help ޴  ׷ ó ޴ ʿ
  ġϰ ϰ ʹٸ ޴ٿ ޴ ̱   Լ .
  (  ڷ file_item ָ ȴ.)

       void gtk_menu_item_right_justify (GtkMenuItem *menu_item);

   ޴ ޷ִ ޴ٸ  ܰ鿡  ̴.

    gtk_menu_new() ̿ؼ ο ޴ .

    gtk_menu_item_new()  ̿ؼ ޴ ʿ  ޴
      . ׸ gtk_menu_append() ̿ؼ  ۵
     ޴ ִ´.

    gtk_menu_item_new() ؼ ޴  ϳ .  
      ڽ ؽƮ ޴   Ÿ root ޴
      ȴ.

    gtk_menu_item_set_submenu() ؼ ޴ root ޴ ۿ
     δ.(ٷ  ܰ迡  ޴ )

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

    gtk_menu_bar_append() ̿ؼ ޴  root ޴ ´.

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

    ̺Ʈ ڵ鸵 Լ .  ̰ ̷   Ѵ.

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

  ׸ ̰ ޴ ˾ų  ã  ̺Ʈ ̿ ̴.

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

     Լ ̿Ͽ ̺Ʈ ڵ鷯 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.   ޴  

   и صα    .

  /* menu.c */

  #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_widget_set_usize( GTK_WIDGET (window), 200, 100);
      gtk_window_set_title(GTK_WINDOW (window), "GTK Menu Test");
      gtk_signal_connect(GTK_OBJECT (window), "delete_event",
                         (GtkSignalFunc) gtk_main_quit, NULL);

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

      /*  츮  ޴Ʈ    
       * Ѵ.  ̶, 츮  ޴ ۵鿡 
       * "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);
          }

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

        /*  츮 Ӱ  "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 и ̴.

       /* menufactory.h */

       #ifndef __MENUFACTORY_H__
       #define __MENUFACTORY_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 /* __MENUFACTORY_H__ */

  ׸ ̰ menufactory.c ̴.

  /* menufactory.c */

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

  #include "mfmain.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);
  }

  ̰ mfmain.h.

       /* mfmain.h */

       #ifndef __MFMAIN_H__
       #define __MFMAIN_H__

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

       void file_quit_cmd_callback(GtkWidget *widget, gpointer data);

       #ifdef __cplusplus
       }
       #endif /* __cplusplus */

       #endif /* __MFMAIN_H__ */

  ׸ ̰ mfmain.c.

  /* mfmain.c */

  #include <gtk/gtk.h>

  #include "mfmain.h"
  #include "menufactory.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̴.

  # Makefile.mf

  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 = menufactory

  O_FILES = menufactory.o mfmain.o

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

  .c.o:
      $(CC) -c $(C_FLAGS) $<

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

     ̴. ڼ  ڸƮ ߿ ߰
  ̴.

  12.  ؽƮ widget

  ؽƮ widget   ؽƮ ְų   ְ ش.
   ̳ ۲ ϴ  ÿ    ִ.  
  ŰԷ¿     Emacs ȣȯ ؽƮ  ɵ鵵
  Ѵ.

  ؽƮ widget  ܾ  ü (select)ϴ  Ŭ,
  Ʈ Ŭ ؼ  cut-and-paste   ִ.

  12.1.  ؽƮ   .

  ؽƮ widget  Լ  ϳ̴.

       GtkWidget* gtk_text_new (GtkAdjustment *hadj,
                                GtkAdjustment *vadj);

  ڵ  widget ְ ִ ؽƮ ġ   ְ
  ִ Adjustment ̴.    ϳ  ο NULL
  Ѱָ gtk_text_new Լ ڱ ڽ   .

       void gtk_text_set_adjustments (GtkText       *text,
                                      GtkAdjustment *hadj,
                                      GtkAdjustment *vadj);

   Լ ƹ  ؽƮ widget ,  adjustment ٲ 
  ְ ش.

  ؽƮ  ؽƮ    µǱ⿡ ʹ 
  ڵ ũ ٸ  ʴ´. ׷Ƿ 츮  װ͵
    ̾ƿ ߰Ͽ Ѵ.

         vscrollbar = gtk_vscrollbar_new (GTK_TEXT(text)->vadj);
         gtk_box_pack_start(GTK_BOX(hbox), vscrollbar, FALSE, FALSE, 0);
         gtk_widget_show (vscrollbar);

   ڵ  ũѹٸ ϳ  ̸ ؽƮ widget text
   adjustment δ. ׸   box ִ´.

  ؽƮ widget ϴ ֵ ΰ  ִ. ڿ ؽƮ
     ְ ϰų Ǵ ڿ   ؽƮ
  ֱ⸸   ִ.   ΰ  ̸ Դٰϱ ؼ
  ؽƮ widget  Լ  ִ.

       void gtk_text_set_editable    (GtkText *text,
                                      gint    editable);

   editable TRUE FALSE ־ ڰ ؽƮ widget 
   , Ǵ Ұϵ   ִ. ؽƮ widget  
  ¸  Է ġ Ŀ Ÿ.

   ΰ 忡 ؽƮ widget   ٸ  .  ƹ
   ؽƮ widget  ɻ¸ ٲ  ְ ƹ  ؽƮ
  Է  ִ.

  ؽƮ widget   ٿ     ŭ  ٵ
  wrappingϴ ɷ ִ.  Ѿ ġ ִ ܾ 
  ɰ  ⺻ ̴.  ̴  Լ ٲ  ִ.

       void gtk_text_set_word_wrap (GtkText *text,
                                    gint    word_wrap);

   Լ Ἥ ؽƮ widget ܾ ɰ ʰ wrapϵ  
   ִ.   word_wrap TRUE FALSE  ´.

  12.2.  ؽƮ ٷ

  ؽƮ widget Է Ʈ  Լ ̿Ͽ Ѵ.

       void gtk_text_set_point (GtkText *text,
                                guint   index);

  index Է Ʈ ġ̴.

   Է Ʈ ϴ ͵ ϴ.

       guint gtk_text_get_point (GtkText *text);

    Լ    Լ

       guint gtk_text_get_length (GtkText *text);

  ̴. ̴ ؽƮ widget ̸ .  ̴   
  Ÿ ĳ-  ؽƮ   ĳ ̴.

   Է Ʈ ؽƮ  ؽƮ , , ۲
   ϴ gtk_text_insert Լ Ѵ.

       void gtk_text_insert (GtkText    *text,
                             GdkFont    *font,
                             GdkColor   *fore,
                             GdkColor   *back,
                             const char *chars,
                             gint       length);

  , , ۲ ϴ ڿ NULL     widget
  style   ̿ȴ.  length -1  ־ ؽƮ
  ΰ  Էµȴ.

  ؽƮ widget gtk_main Լ ۿ θ  ٽ
  ׸(redraw) GTK   ȵǴ ̴. ̴ ؽƮ widget
   ϸ   ȿ ״ Ÿٴ ǹ̴. ̷ 
  ؽƮ  Ѳ  ϴ  ٶ ʴ  
  ִ.  ؽƮ widget Ӿ θ ٽ ׸   
  ϱ ؼ widget ׷ ϵ ӽ÷    ִ.
  ׸   Ϻ  ڿ ٽ widget Ǯָ ȴ.

    Լ ϰų Ǯִ    ִ.

       void gtk_text_freeze (GtkText *text);
       void gtk_text_thaw   (GtkText *text);

  ؽƮ  Լ Ἥ  Է Ʈ γ 
   ؽƮ widget   ִ.

  gint gtk_text_backward_delete (GtkText *text,
                                 guint   nchars);
  gint gtk_text_forward_delete  (GtkText *text,
                                 guint   nchars);

  ؽƮ widget   ʹٸ ũ GTK_TEXT_INDEX(t, index)
  ؽƮ widget t index ġ ĳ͸   ְ ش.

     ؽƮ Ѳ   Լ .

       gchar *gtk_editable_get_chars (GtkEditable *editable,
                                      gint        start_pos,
                                      gint        end_pos);

  ̰ ؽƮ widget θ Ŭ Լ̴. end_pos  -1̸
  ̴ ؽƮ  ǹѴ. ؽƮ  0̴.

   Լ  ؽƮ  ο ޸  ҴѴ. ׷Ƿ
   ̿ ڿ g_free Լ ȣϿ ޸  Ǯִ 
  .

  12.3.  Ű Ű

  ؽƮ widget , ̵, (selection)  ̸  Ű
  Ű  ִ. ̵ Control, Alt Ű ̴.

  ⿡ ٿ ĿŰ ̵  Control   Ŀ 
    ƴ϶  ܾ  δ. Shift  
  Ŀ ̵ κ ڵ õȴ.

  12.3.1.  ̵ Ű

    Ctrl-A    ó

    Ctrl-E  

    Ctrl-N    ٷ

    Ctrl-P  ٷ

    Ctrl-B     

    Ctrl-F     

    Alt-B     ܾ ڷ

    Alt-F   ܾ 

  12.3.2.   Ű

    Ctrl-H     ڸ . (Backspace)

    Ctrl-D     ڸ . (Delete)

    Ctrl-W   ܾ .

    Alt-D      ܾ .

    Ctrl-K   .

    Ctrl-U   .

  12.3.3.  Selection Ű

    Ctrl-X   Ŭ忡 ߶󳽴. (Cut)

    Ctrl-C   Ŭ忡 Ѵ. (Copy)

    Ctrl-V Ŭ忡  δ. (Paste)

  13.  ȭ  widget

  ̵  ڸ ٸ ִ! :)  츮    
   ͵  ⸦.

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

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

  13.1.  Range Controls

  13.2.  Previews

  13.3.  Curves

  14.  ̺Ʈڽ widget

   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;
  }

  15.  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);

  16.  ŸӾƿ, ׸ I/O Idle Լ

  16.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);

  16.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);

  16.3.  Idle Լ

  ̻ ƹ͵ Ͼ   ȣ Լ ΰ?

       gint gtk_idle_add (GtkFunction function,
                          gpointer data);

  ̰ ̻ ƹ͵ ߻   GTK  Լ ȣϵ
  ش.

       void gtk_idle_remove (gint tag);

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

  17.  Selection ϱ

  17.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
  Ͽ ĺȴ.

  17.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;
  }

  17.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;
  }

  18.  glib

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

  18.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

  18.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);

  18.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);

  18.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 ٽ ؾ Ѵ.

  18.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);

  18.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,
                                    ...);

  18.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
  ֱ!

  19.  GTK rc 

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

  19.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" Ÿϴ Ѵ.

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

  19.2.  GTK rc  

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

  Widget Ӽ ȭų    ͵ ִ.

    fg - Widget foreground 

    bg - Widget background 

    bg_pixmap - Widget background  Ƚ

    font - ־ widget  Ʈ

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

    NORMAL - Widget  .  콺  widget  
     ʾҰ,     ´.

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

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

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

    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  밡 
  ƴϴ.  ̰ ̰  ̴.  밡  ִٸ
  ϸ ȴ.

  19.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"

  20.  ڽŸ widget 

  20.1.  

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

    ҽ ڵ     ̳ Ǵ 
  ҿ   ִ.

  http://www.msc.cornell.edu/~otaylor/gtk-gimp/tutorial

  20.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 ĳƮ  ִ ̴.

  20.3.  Composite(ռ,ȥ) widget 

  20.3.1.  Ұ

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

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

  20.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 η ٿ
  ̴.

  20.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 üũϴ  Ѵ.

  ̰  ̴.

  /* tictactoe.h */

  #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__ */

  20.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,
          (GtkArgSetFunc) NULL,
          (GtkArgGetFunc) 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;
         GtkArgSetFunc arg_set_func;
         GtkArgGetFunc arg_get_func;
       };

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

  20.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_TYPE_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,
                                                ...);

  ο ñ׳ .  ⿡  ڵ 캸.

    name: ñ׳ ̸

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

    object_type:  ñ׳  object ID. ( object
     descendents )

    function_offset: Ʈ ڵ鷯 Ű  class structure
      ɼ.

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

    return_val: ϰ Ÿ.

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

  Ÿ ϱ , GtkType̶ enumeration δ.

       typedef enum
       {
         GTK_TYPE_INVALID,
         GTK_TYPE_NONE,
         GTK_TYPE_CHAR,
         GTK_TYPE_BOOL,
         GTK_TYPE_INT,
         GTK_TYPE_UINT,
         GTK_TYPE_LONG,
         GTK_TYPE_ULONG,
         GTK_TYPE_FLOAT,
         GTK_TYPE_DOUBLE,
         GTK_TYPE_STRING,
         GTK_TYPE_ENUM,
         GTK_TYPE_FLAGS,
         GTK_TYPE_BOXED,
         GTK_TYPE_FOREIGN,
         GTK_TYPE_CALLBACK,
         GTK_TYPE_ARGS,

         GTK_TYPE_POINTER,

         /* it'd be great if the next two could be removed eventually */
         GTK_TYPE_SIGNAL,
         GTK_TYPE_C_CALLBACK,

         GTK_TYPE_OBJECT

       } GtkFundamentalType;

  gtk_signal_new() ñ׳ο    ĺڸ Ѵ.
  츮 ̵ tictactoe_signals 迭 ϰ, enumeration
  ̿ؼ ε ش. ( enumeration ҵ 빮ڷ
  ñ׳ ̸ Ÿ , ⼭ TICTACTOE() ũο 浹 
  ֱ , 츮 ̵ TICTACTOE_SIGNAL̶ θ.)

  ñ׳ ٸ,  GTK  ñ׳ε Tictactoe Ŭ
  Ű  ؾ Ѵ.   ۾ gtk_object_class_add_signals()
  ش.  ׸ ƹ Ʈ  ٴ  Ÿ ,
  ``tictactoe'' ñ׳  Ʈ ڵ鷯 Ű ִ ͸
  NULL Ѵ.

  20.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]);
                               }
       }

  20.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;
  }

  20.4.  (from scratch) widget 

  20.4.1.  Ұ

  ̹ ǿ widget  ڽŵ  ũ ̰ ϴ,
  ׸ ̺Ʈ ȣۿ ϴ   ̴.  ̿  
  츮 Ͱ ޷ִ Ƴα ̾(analog dial) widget
  , ڰ װ   ϵ  ̴.

  20.4.2.  ũ widget ̱

  ũ ֱ ؼ  ܰ谡 ִ.  Widget
  WIDGETNAME_new() ν  ,  Լ  ʿϴ.

    شϴ widget  WIDGETNAEME_realize() X ش.

    WIDGETNAME_map() ڰ gtk_widget_show() ȣ Ŀ
     ûȴ.  ̴ widget  ũ  ׷(mapped) 
     ȮѴ.  ̳ Ŭ , ü child widget ϱ
      ȣ  ʿϴ.

    WIDGETNAME_draw() widget Ȥ װ ancestor 
     gtk_widget_draw()  ȣǾ  ûǴ ̴.  ̰
     widget ũ ׸   ׸ Լ ȣ ش.
     ̳ widget 쿣 װ child widget 
     gtk_widget_draw() ȣ  Ѵ.

    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() Լ .

  20.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 ۿ뿡  ͼ ʴٸ,  ׵鿡  ˾ 
  ͵   ̴.

  20.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);
  }

  20.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);
       }

  20.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;
                       }
       }

  20.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;
  }

  20.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;
      }
  }

  20.4.9.   

  츮 õ Dial widget  670 ڵ带  ִ.  Ư 
  ڵ  κ  Ϸ(boiler plate)̱ , 츮
    ڵ       ־.  ׷  widget 
     ɰ ִ.

     widget   , Ͱ 巡׵Ǹ鼭 ణ
     ½Ÿ  ߰   ̴.  ̰ Ͱ ̵
      redrawǱ  widget ü  ̴.  
      ذϴ     ʴ(offscreen) Ƚʿ
     ׷ְ, ׸   ũ  ܹ  ִ
     ̴.  (ื(progress bar) widget ̷  .)

    ڴ  ȭŰ ؼ up  down ȭǥŰ(arrow key)
     ̿  ־  ̴.

    츮 widget ũų    ų  ִ ư
     ٸ    ̴.  ̸   ư widget
     ̿ϴ ͵ ϰ, 츮   ư  
     ¿ auto-repeat ǵ ϰʹ, ũѹٿ ִ ȭǥó.
     ̷  ۵ ߰ ִ κ ڵ GtkRange
     widget ã  ִ.

    ̾(Dial) widget տ ޵ ư ٴڿ ġ ϳ
     child widget , ̳ widget   ִ.  ׷
     ڴ ̾ 簪 ̱  ϴ ̳ Ʈ
     widget   ִ.

  20.5.   

  Widget    ׸   Ϻθ  ҰǾ.
  ڽ widget  ̿,   ҽ GTK  ü
  ̴.    widget     غ.
  ̰ Container widgetΰ?  ̰ õ   ִ°?
  ̰ ̹ ϴ widget ΰ?  ׸  widget
  ã, ȭ ֱ ϴ ̴.   !

  21.  ,  ׸ 

  21.1.  

  ⼭ 츮  ׸ α׷  ̴.   
  츮 콺 ̺Ʈ  ٷ ˾ƺ ̰,  ȿ 
  ׸ ׸, ׸ Ƚ  ؼ   ׸ ׸
    ̴.   ׸ α׷  Ŀ, 츮 װͿ
  drawing tablet  XInput device ϴ  Ȯ õ
  ̴.  GTK ׷ device κ pressure tilt, Ȯ 
    ְ ϴ support routine Ѵ.

  21.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 ʿ Ѵ.
  ڼ   ``The 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;
  }

  21.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)̴.

  C 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  Ʒ    ִ
  GtkStateType̶ ڷ Ÿ.
       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     Ϻ  ׸ ϰ 
  ׸ α׷  캸Ҵ.   ҽڵ   
  ̳  ġ   ִ.

  http://www.msc.cornell.edu/~otaylor/gtk-gimp/tutorial

  21.4.  Input support ϱ

   drawing tablet , ״  鼭 콺 ξ
   ǥ ϰ ׸  ְ ִ Էġ(input device)
  ϴ   ô.  ̷ ġ ̿ϴ  
  ̾  콺 ġ  ̰, ̷  ׷
  Էġ     Ұ   ִ.

    Pressure sensitivity

    Tilt reporting

    Sub-pixel positioning

    Multiple inputs (for example, a stylus with a point and eraser)

  XInput extension    XInput-HOWTO  .
   GdkEventMotion ü ü ǰ  , 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  δ.

  21.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  ϴ ɼ  ʾұ ̴.

  21.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);
  }

  21.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;
                       }
       }

  ̰ 츮 ``XInputize'' α׷  ߴ.  ù 
   ̰  ҽ ڵ    ̳ 
  ġ   ִ.

  http://www.msc.cornell.edu/~otaylor/gtk-gimp/tutorial

  21.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'  ׷ ã
    ̴.

  22.  GTK  ϴ 

   κ   GTK    ֵ Ϲ Ÿ
   Ʈ  ٷ ִ.  ̰ μ  ׷ٴ
  ̰,   ʿ ̴.  :)

  GNU autoconf automake ̿϶!  ׵ 츮 ģ.  :)  
  ̵鿡   Ұ  ȹ ִ.

  23.  Contributing

   , ٸ  Ʈ , ο ̿
  ؼ ڹ  ̴.     ȭ 
  GTK  ɿ  Ȯ   ȴٸ,  ڽŵ 
   ⿩    .

   ⿩ϰڴٰ Ծٸ,   Tony Gale
  gale@gtk.org ֱ ٶ.  ,    ο
  ̸ п   ߰  .    ׵
  α׷     κ̶ ̿ ̰,  
  ǰ ϴ   ̴.

  Thank you.

  24.  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.

  25.  Tutorial Copyright and Permissions Notice

  The GTK Tutorial is Copyright (C) 1997 Ian Main.

  Copyright (C) 1998 Tony Gale.

  Permission is granted to make and distribute verbatim copies of this
  manual provided the copyright notice and this permission notice are
  preserved on all copies.

  Permission is granted to copy and distribute modified versions of this
  document under the conditions for verbatim copying, provided that this
  copyright notice is included exactly as in the original, and that the
  entire resulting derived work is distributed under the terms of a
  permission notice identical to this one.

  Permission is granted to copy and distribute translations of this
  document into another language, under the above conditions for
  modified versions.

  If you are intending to incorporate this document into a published
  work, please contact the maintainer, and we will make an effort to
  ensure that you have the most up to date information available.

  There is no guarentee that this document lives up to its intended
  purpose.  This is simply provided as a free resource.  As such, the
  authors and maintainers of the information provided within can not
  make any guarentee that the information is even accurate.

