From fe0324d76a4d165a310a720f0c2190cdf4104ee9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Jard=C3=B3n?= Date: Tue, 12 Jan 2010 16:57:00 +0100 Subject: [PATCH] [docs] Remove GTK+ 1.2 tutorial from master The tutorial it's still inside the gtk-1-2 branch if It's needed --- docs/tutorial/gtk_tut.sgml | 18447 --------------------------- docs/tutorial/gtk_tut_12.es.sgml | 17638 ------------------------- docs/tutorial/gtk_tut_fr.sgml | 8600 ------------- docs/tutorial/gtk_tut_it.sgml | 10090 --------------- docs/tutorial/gtk_tut_packbox1.eps | 7262 ----------- docs/tutorial/gtk_tut_packbox1.gif | Bin 52480 -> 0 bytes docs/tutorial/gtk_tut_packbox1.jpg | Bin 24613 -> 0 bytes docs/tutorial/gtk_tut_packbox2.eps | 5428 -------- docs/tutorial/gtk_tut_packbox2.gif | Bin 43000 -> 0 bytes docs/tutorial/gtk_tut_packbox2.jpg | Bin 19530 -> 0 bytes docs/tutorial/gtk_tut_table.eps | 1262 -- docs/tutorial/gtk_tut_table.gif | Bin 10056 -> 0 bytes docs/tutorial/gtk_tut_table.jpg | Bin 3890 -> 0 bytes docs/tutorial/package_tutorial.sh | 99 - 14 files changed, 68826 deletions(-) delete mode 100644 docs/tutorial/gtk_tut.sgml delete mode 100755 docs/tutorial/gtk_tut_12.es.sgml delete mode 100644 docs/tutorial/gtk_tut_fr.sgml delete mode 100644 docs/tutorial/gtk_tut_it.sgml delete mode 100644 docs/tutorial/gtk_tut_packbox1.eps delete mode 100644 docs/tutorial/gtk_tut_packbox1.gif delete mode 100644 docs/tutorial/gtk_tut_packbox1.jpg delete mode 100644 docs/tutorial/gtk_tut_packbox2.eps delete mode 100644 docs/tutorial/gtk_tut_packbox2.gif delete mode 100644 docs/tutorial/gtk_tut_packbox2.jpg delete mode 100644 docs/tutorial/gtk_tut_table.eps delete mode 100644 docs/tutorial/gtk_tut_table.gif delete mode 100644 docs/tutorial/gtk_tut_table.jpg delete mode 100755 docs/tutorial/package_tutorial.sh diff --git a/docs/tutorial/gtk_tut.sgml b/docs/tutorial/gtk_tut.sgml deleted file mode 100644 index d42a349b43..0000000000 --- a/docs/tutorial/gtk_tut.sgml +++ /dev/null @@ -1,18447 +0,0 @@ - - - - -
-GTK v1.2 Tutorial -<author> -Tony Gale <tt><htmlurl url="mailto:gale@gtk.org" - name="<gale@gtk.org>"></tt>, -Ian Main <tt><htmlurl url="mailto:imain@gtk.org" - name="<imain@gtk.org>"></tt> -<date>February 23rd, 2000 -<abstract> -This is a tutorial on how to use GTK (the GIMP Toolkit) through its C -interface. -</abstract> - -<!-- Table of contents --> -<!-- Older versions of this tutorial did not have a table of contents, - but the tutorial is now so large that having one is very useful. --> -<toc> - - -<!-- ***************************************************************** --> -<sect>Introduction -<!-- ***************************************************************** --> -<p> -GTK (GIMP Toolkit) is a library for creating graphical user -interfaces. It is licensed using the LGPL license, so you can develop -open software, free software, or even commercial non-free software -using GTK without having to spend anything for licenses or royalties. - -It's called the GIMP toolkit because it was originally written for -developing the GNU Image Manipulation Program (GIMP), but GTK has -now been used in a large number of software projects, including the -GNU Network Object Model Environment (GNOME) project. GTK is built on -top of GDK (GIMP Drawing Kit) which is basically a wrapper around the -low-level functions for accessing the underlying windowing functions -(Xlib in the case of the X windows system). The primary authors of GTK -are: - -<itemize> -<item> Peter Mattis <tt><htmlurl url="mailto:petm@xcf.berkeley.edu" - name="petm@xcf.berkeley.edu"></tt> -<item> Spencer Kimball <tt><htmlurl url="mailto:spencer@xcf.berkeley.edu" - name="spencer@xcf.berkeley.edu"></tt> -<item> Josh MacDonald <tt><htmlurl url="mailto:jmacd@xcf.berkeley.edu" - name="jmacd@xcf.berkeley.edu"></tt> -</itemize> - -GTK is essentially an object oriented application programmers -interface (API). Although written completely in C, it is implemented -using the idea of classes and callback functions (pointers to -functions). - -There is also a third component called GLib which contains a few -replacements for some standard calls, as well as some additional -functions for handling linked lists, etc. The replacement functions -are used to increase GTK's portability, as some of the functions -implemented here are not available or are nonstandard on other unixes -such as g_strerror(). Some also contain enhancements to the libc -versions, such as g_malloc that has enhanced debugging utilities. - -This tutorial describes the C interface to GTK. There are GTK -bindings for many other languages including C++, Guile, Perl, Python, -TOM, Ada95, Objective C, Free Pascal, and Eiffel. If you intend to -use another language's bindings to GTK, look at that binding's -documentation first. In some cases that documentation may describe -some important conventions (which you should know first) and then -refer you back to this tutorial. There are also some cross-platform -APIs (such as wxWindows and V) which use GTK as one of their target -platforms; again, consult their documentation first. - -If you're developing your GTK application in C++, a few extra notes -are in order. There's a C++ binding to GTK called GTK--, which -provides a more C++-like interface to GTK; you should probably look -into this instead. If you don't like that approach for whatever -reason, there are two alternatives for using GTK. First, you can use -only the C subset of C++ when interfacing with GTK and then use the C -interface as described in this tutorial. Second, you can use GTK and -C++ together by declaring all callbacks as static functions in C++ -classes, and again calling GTK using its C interface. If you choose -this last approach, you can include as the callback's data value a -pointer to the object to be manipulated (the so-called "this" value). -Selecting between these options is simply a matter of preference, -since in all three approaches you get C++ and GTK. None of these -approaches requires the use of a specialized preprocessor, so no -matter what you choose you can use standard C++ with GTK. - -This tutorial is an attempt to document as much as possible of GTK, -but it is by no means complete. This tutorial assumes a good -understanding of C, and how to create C programs. It would be a great -benefit for the reader to have previous X programming experience, but -it shouldn't be necessary. If you are learning GTK as your first -widget set, please comment on how you found this tutorial, and what -you had trouble with. There are also C++, Objective C, ADA, Guile and -other language bindings available, but I don't follow these. - -This document is a "work in progress". Please look for updates on -<htmlurl url="http://www.gtk.org/" name="http://www.gtk.org/">. - -I would very much like to hear of any problems you have learning GTK -from this document, and would appreciate input as to how it may be -improved. Please see the section on <ref id="sec_Contributing" -name="Contributing"> for further information. - -<!-- ***************************************************************** --> -<sect>Getting Started -<!-- ***************************************************************** --> - -<p> -The first thing to do, of course, is download the GTK source and -install it. You can always get the latest version from ftp.gtk.org in -/pub/gtk. You can also view other sources of GTK information on -<htmlurl url="http://www.gtk.org/" name="http://www.gtk.org/">. GTK -uses GNU autoconf for configuration. Once untar'd, type ./configure ---help to see a list of options. - -The GTK source distribution also contains the complete source to all -of the examples used in this tutorial, along with Makefiles to aid -compilation. - -To begin our introduction to GTK, we'll start with the simplest -program possible. This program will create a 200x200 pixel window and -has no way of exiting except to be killed by using the shell. - -<tscreen><verb> -/* example-start base base.c */ - -#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); -} -/* example-end */ -</verb></tscreen> - -You can compile the above program with gcc using: -<tscreen><verb> -gcc base.c -o base `gtk-config --cflags --libs` -</verb></tscreen> - -The meaning of the unusual compilation options is explained below in -<ref id="sec_compiling" name="Compiling Hello World">. - -All programs will of course include gtk/gtk.h which declares the -variables, functions, structures, etc. that will be used in your GTK -application. - -The next line: - -<tscreen><verb> -gtk_init (&argc, &argv); -</verb></tscreen> - -calls the function gtk_init(gint *argc, gchar ***argv) which will be -called in all GTK applications. This sets up a few things for us such -as the default visual and color map and then proceeds to call -gdk_init(gint *argc, gchar ***argv). This function initializes the -library for use, sets up default signal handlers, and checks the -arguments passed to your application on the command line, looking for -one of the following: - -<itemize> -<item> <tt/--gtk-module/ -<item> <tt/--g-fatal-warnings/ -<item> <tt/--gtk-debug/ -<item> <tt/--gtk-no-debug/ -<item> <tt/--gdk-debug/ -<item> <tt/--gdk-no-debug/ -<item> <tt/--display/ -<item> <tt/--sync/ -<item> <tt/--no-xshm/ -<item> <tt/--name/ -<item> <tt/--class/ -</itemize> - -It removes these from the argument list, leaving anything it does not -recognize for your application to parse or ignore. This creates a set -of standard arguments accepted by all GTK applications. - -The next two lines of code create and display a window. - -<tscreen><verb> - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_widget_show (window); -</verb></tscreen> - -The <tt/GTK_WINDOW_TOPLEVEL/ argument specifies that we want the -window to undergo window manager decoration and placement. Rather than -create a window of 0x0 size, a window without children is set to -200x200 by default so you can still manipulate it. - -The gtk_widget_show() function lets GTK know that we are done setting -the attributes of this widget, and that it can display it. - -The last line enters the GTK main processing loop. - -<tscreen><verb> - gtk_main (); -</verb></tscreen> - -gtk_main() is another call you will see in every GTK application. -When control reaches this point, GTK will sleep waiting for X events -(such as button or key presses), timeouts, or file IO notifications to -occur. In our simple example, however, events are ignored. - -<!-- ----------------------------------------------------------------- --> -<sect1>Hello World in GTK -<p> -Now for a program with a widget (a button). It's the classic -hello world a la GTK. - -<tscreen><verb> -/* example-start helloworld helloworld.c */ - -#include <gtk/gtk.h> - -/* This is a callback function. The data arguments are ignored - * in this example. More on callbacks below. */ -void hello( GtkWidget *widget, - gpointer data ) -{ - g_print ("Hello World\n"); -} - -gint delete_event( GtkWidget *widget, - GdkEvent *event, - gpointer data ) -{ - /* If you return FALSE in the "delete_event" signal handler, - * GTK will emit the "destroy" signal. Returning TRUE means - * you don't want the window to be destroyed. - * This is useful for popping up 'are you sure you want to quit?' - * type dialogs. */ - - g_print ("delete event occurred\n"); - - /* Change TRUE to FALSE and the main window will be destroyed with - * a "delete_event". */ - - return(TRUE); -} - -/* Another callback */ -void destroy( GtkWidget *widget, - gpointer data ) -{ - gtk_main_quit(); -} - -int main( int argc, - char *argv[] ) -{ - /* GtkWidget is the storage type for widgets */ - GtkWidget *window; - GtkWidget *button; - - /* This is called in all GTK applications. Arguments are parsed - * from the command line and are returned to the application. */ - gtk_init(&argc, &argv); - - /* create a new window */ - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - - /* When the window is given the "delete_event" signal (this is given - * by the window manager, usually by the "close" option, or on the - * titlebar), we ask it to call the delete_event () function - * as defined above. The data passed to the callback - * function is NULL and is ignored in the callback function. */ - gtk_signal_connect (GTK_OBJECT (window), "delete_event", - GTK_SIGNAL_FUNC (delete_event), NULL); - - /* Here we connect the "destroy" event to a signal handler. - * This event occurs when we call gtk_widget_destroy() on the window, - * or if we return FALSE in the "delete_event" callback. */ - gtk_signal_connect (GTK_OBJECT (window), "destroy", - GTK_SIGNAL_FUNC (destroy), NULL); - - /* Sets the border width of the window. */ - gtk_container_set_border_width (GTK_CONTAINER (window), 10); - - /* Creates a new button with the label "Hello World". */ - button = gtk_button_new_with_label ("Hello World"); - - /* When the button receives the "clicked" signal, it will call the - * function hello() passing it NULL as its argument. The hello() - * function is defined above. */ - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (hello), NULL); - - /* This will cause the window to be destroyed by calling - * gtk_widget_destroy(window) when "clicked". Again, the destroy - * signal could come from here, or the window manager. */ - gtk_signal_connect_object (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (gtk_widget_destroy), - GTK_OBJECT (window)); - - /* This packs the button into the window (a gtk container). */ - gtk_container_add (GTK_CONTAINER (window), button); - - /* The final step is to display this newly created widget. */ - gtk_widget_show (button); - - /* and the window */ - gtk_widget_show (window); - - /* All GTK applications must have a gtk_main(). Control ends here - * and waits for an event to occur (like a key press or - * mouse event). */ - gtk_main (); - - return(0); -} -/* example-end */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Compiling Hello World <label id="sec_compiling"> -<p> -To compile use: - -<tscreen><verb> -gcc -Wall -g helloworld.c -o helloworld `gtk-config --cflags` \ - `gtk-config --libs` -</verb></tscreen> - -This uses the program <tt/gtk-config/, which comes with GTK. This -program "knows" what compiler switches are needed to compile programs -that use GTK. <tt/gtk-config --cflags/ will output a list of include -directories for the compiler to look in, and <tt>gtk-config --libs</> -will output the list of libraries for the compiler to link with and -the directories to find them in. In the above example they could have -been combined into a single instance, such as -<tt/`gtk-config --cflags --libs`/. - -Note that the type of single quote used in the compile command above -is significant. - -The libraries that are usually linked in are: -<itemize> -<item>The GTK library (-lgtk), the widget library, based on top of GDK. -<item>The GDK library (-lgdk), the Xlib wrapper. -<item>The gmodule library (-lgmodule), which is used to load run time -extensions. -<item>The GLib library (-lglib), containing miscellaneous functions; -only g_print() is used in this particular example. GTK is built on top -of glib so you will always require this library. See the section on -<ref id="sec_glib" name="GLib"> for details. -<item>The Xlib library (-lX11) which is used by GDK. -<item>The Xext library (-lXext). This contains code for shared memory -pixmaps and other X extensions. -<item>The math library (-lm). This is used by GTK for various purposes. -</itemize> - -<!-- ----------------------------------------------------------------- --> -<sect1>Theory of Signals and Callbacks -<p> -Before we look in detail at <em>helloworld</em>, we'll discuss signals -and callbacks. GTK is an event driven toolkit, which means it will -sleep in gtk_main until an event occurs and control is passed to the -appropriate function. - -This passing of control is done using the idea of "signals". (Note -that these signals are not the same as the Unix system signals, and -are not implemented using them, although the terminology is almost -identical.) When an event occurs, such as the press of a mouse button, -the appropriate signal will be "emitted" by the widget that was -pressed. This is how GTK does most of its useful work. There are -signals that all widgets inherit, such as "destroy", and there are -signals that are widget specific, such as "toggled" on a toggle -button. - -To make a button perform an action, we set up a signal handler to -catch these signals and call the appropriate function. This is done by -using a function such as: - -<tscreen><verb> -gint gtk_signal_connect( GtkObject *object, - gchar *name, - GtkSignalFunc func, - gpointer func_data ); -</verb></tscreen> - -where the first argument is the widget which will be emitting the -signal, and the second the name of the signal you wish to catch. The -third is the function you wish to be called when it is caught, and the -fourth, the data you wish to have passed to this function. - -The function specified in the third argument is called a "callback -function", and should generally be of the form - -<tscreen><verb> -void callback_func( GtkWidget *widget, - gpointer callback_data ); -</verb></tscreen> - -where the first argument will be a pointer to the widget that emitted -the signal, and the second a pointer to the data given as the last -argument to the gtk_signal_connect() function as shown above. - -Note that the above form for a signal callback function declaration is -only a general guide, as some widget specific signals generate -different calling parameters. For example, the CList "select_row" -signal provides both row and column parameters. - -Another call used in the <em>helloworld</em> example, is: - -<tscreen><verb> -gint gtk_signal_connect_object( GtkObject *object, - gchar *name, - GtkSignalFunc func, - GtkObject *slot_object ); -</verb></tscreen> - -gtk_signal_connect_object() is the same as gtk_signal_connect() except -that the callback function only uses one argument, a pointer to a GTK -object. So when using this function to connect signals, the callback -should be of the form - -<tscreen><verb> -void callback_func( GtkObject *object ); -</verb></tscreen> - -where the object is usually a widget. We usually don't setup callbacks -for gtk_signal_connect_object however. They are usually used to call a -GTK function that accepts a single widget or object as an argument, as -is the case in our <em>helloworld</em> example. - -The purpose of having two functions to connect signals is simply to -allow the callbacks to have a different number of arguments. Many -functions in the GTK library accept only a single GtkWidget pointer as -an argument, so you want to use the gtk_signal_connect_object() for -these, whereas for your functions, you may need to have additional -data supplied to the callbacks. - -<!-- ----------------------------------------------------------------- --> -<sect1>Events -<p> -In addition to the signal mechanism described above, there is a set -of <em>events</em> that reflect the X event mechanism. Callbacks may -also be attached to these events. These events are: - -<itemize> -<item> event -<item> button_press_event -<item> button_release_event -<item> motion_notify_event -<item> delete_event -<item> destroy_event -<item> expose_event -<item> key_press_event -<item> key_release_event -<item> enter_notify_event -<item> leave_notify_event -<item> configure_event -<item> focus_in_event -<item> focus_out_event -<item> map_event -<item> unmap_event -<item> property_notify_event -<item> selection_clear_event -<item> selection_request_event -<item> selection_notify_event -<item> proximity_in_event -<item> proximity_out_event -<item> drag_begin_event -<item> drag_request_event -<item> drag_end_event -<item> drop_enter_event -<item> drop_leave_event -<item> drop_data_available_event -<item> other_event -</itemize> - -In order to connect a callback function to one of these events, you -use the function gtk_signal_connect, as described above, using one of -the above event names as the <tt/name/ parameter. The callback -function for events has a slightly different form than that for -signals: - -<tscreen><verb> -void callback_func( GtkWidget *widget, - GdkEvent *event, - gpointer callback_data ); -</verb></tscreen> - -GdkEvent is a C <tt/union/ structure whose type will depend upon which -of the above events has occurred. In order for us to tell which event -has been issued each of the possible alternatives has a <tt/type/ -parameter which reflects the event being issued. The other components -of the event structure will depend upon the type of the -event. Possible values for the type are: - -<tscreen><verb> - GDK_NOTHING - GDK_DELETE - GDK_DESTROY - GDK_EXPOSE - GDK_MOTION_NOTIFY - GDK_BUTTON_PRESS - GDK_2BUTTON_PRESS - GDK_3BUTTON_PRESS - GDK_BUTTON_RELEASE - GDK_KEY_PRESS - GDK_KEY_RELEASE - GDK_ENTER_NOTIFY - GDK_LEAVE_NOTIFY - GDK_FOCUS_CHANGE - GDK_CONFIGURE - GDK_MAP - GDK_UNMAP - GDK_PROPERTY_NOTIFY - GDK_SELECTION_CLEAR - GDK_SELECTION_REQUEST - GDK_SELECTION_NOTIFY - GDK_PROXIMITY_IN - GDK_PROXIMITY_OUT - GDK_DRAG_BEGIN - GDK_DRAG_REQUEST - GDK_DROP_ENTER - GDK_DROP_LEAVE - GDK_DROP_DATA_AVAIL - GDK_CLIENT_EVENT - GDK_VISIBILITY_NOTIFY - GDK_NO_EXPOSE - GDK_OTHER_EVENT /* Deprecated, use filters instead */ -</verb></tscreen> - -So, to connect a callback function to one of these events we would use -something like: - -<tscreen><verb> -gtk_signal_connect( GTK_OBJECT(button), "button_press_event", - GTK_SIGNAL_FUNC(button_press_callback), - NULL); -</verb></tscreen> - -This assumes that <tt/button/ is a Button widget. Now, when the -mouse is over the button and a mouse button is pressed, the function -<tt/button_press_callback/ will be called. This function may be -declared as: - -<tscreen><verb> -static gint button_press_callback( GtkWidget *widget, - GdkEventButton *event, - gpointer data ); -</verb></tscreen> - -Note that we can declare the second argument as type -<tt/GdkEventButton/ as we know what type of event will occur for this -function to be called. - -The value returned from this function indicates whether the event -should be propagated further by the GTK event handling -mechanism. Returning TRUE indicates that the event has been handled, -and that it should not propagate further. Returning FALSE continues -the normal event handling. See the section on -<ref id="sec_Adv_Events_and_Signals" -name="Advanced Event and Signal Handling"> for more details on this -propagation process. - -For details on the GdkEvent data types, see the appendix entitled -<ref id="sec_GDK_Event_Types" name="GDK Event Types">. - -<!-- ----------------------------------------------------------------- --> -<sect1>Stepping Through Hello World -<p> -Now that we know the theory behind this, let's clarify by walking -through the example <em>helloworld</em> program. - -Here is the callback function that will be called when the button is -"clicked". We ignore both the widget and the data in this example, but -it is not hard to do things with them. The next example will use the -data argument to tell us which button was pressed. - -<tscreen><verb> -void hello( GtkWidget *widget, - gpointer data ) -{ - g_print ("Hello World\n"); -} -</verb></tscreen> - -The next callback is a bit special. The "delete_event" occurs when the -window manager sends this event to the application. We have a choice -here as to what to do about these events. We can ignore them, make -some sort of response, or simply quit the application. - -The value you return in this callback lets GTK know what action to -take. By returning TRUE, we let it know that we don't want to have -the "destroy" signal emitted, keeping our application running. By -returning FALSE, we ask that "destroy" be emitted, which in turn will -call our "destroy" signal handler. - -<tscreen><verb> -gint delete_event( GtkWidget *widget, - GdkEvent *event, - gpointer data ) -{ - g_print ("delete event occurred\n"); - - return (TRUE); -} -</verb></tscreen> - -Here is another callback function which causes the program to quit by -calling gtk_main_quit(). This function tells GTK that it is to exit -from gtk_main when control is returned to it. - -<tscreen><verb> -void destroy( GtkWidget *widget, - gpointer data ) -{ - gtk_main_quit (); -} -</verb></tscreen> - -I assume you know about the main() function... yes, as with other -applications, all GTK applications will also have one of these. - -<tscreen><verb> -int main( int argc, - char *argv[] ) -{ -</verb></tscreen> - -This next part declares pointers to a structure of type -GtkWidget. These are used below to create a window and a button. - -<tscreen><verb> - GtkWidget *window; - GtkWidget *button; -</verb></tscreen> - -Here is our gtk_init again. As before, this initializes the toolkit, -and parses the arguments found on the command line. Any argument it -recognizes from the command line, it removes from the list, and -modifies argc and argv to make it look like they never existed, -allowing your application to parse the remaining arguments. - -<tscreen><verb> - gtk_init (&argc, &argv); -</verb></tscreen> - -Create a new window. This is fairly straightforward. Memory is -allocated for the GtkWidget *window structure so it now points to a -valid structure. It sets up a new window, but it is not displayed -until we call gtk_widget_show(window) near the end of our program. - -<tscreen><verb> - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); -</verb></tscreen> - -Here are two examples of connecting a signal handler to an object, in -this case, the window. Here, the "delete_event" and "destroy" signals -are caught. The first is emitted when we use the window manager to -kill the window, or when we use the gtk_widget_destroy() call passing -in the window widget as the object to destroy. The second is emitted -when, in the "delete_event" handler, we return FALSE. - -The <tt/GTK_OBJECT/ and <tt/GTK_SIGNAL_FUNC/ are macros that perform -type casting and checking for us, as well as aid the readability of -the code. - -<tscreen><verb> - gtk_signal_connect (GTK_OBJECT (window), "delete_event", - GTK_SIGNAL_FUNC (delete_event), NULL); - gtk_signal_connect (GTK_OBJECT (window), "destroy", - GTK_SIGNAL_FUNC (destroy), NULL); -</verb></tscreen> - -This next function is used to set an attribute of a container object. -This just sets the window so it has a blank area along the inside of -it 10 pixels wide where no widgets will go. There are other similar -functions which we will look at in the section on -<ref id="sec_setting_widget_attributes" name="Setting Widget Attributes"> - -And again, <tt/GTK_CONTAINER/ is a macro to perform type casting. - -<tscreen><verb> - gtk_container_set_border_width (GTK_CONTAINER (window), 10); -</verb></tscreen> - -This call creates a new button. It allocates space for a new GtkWidget -structure in memory, initializes it, and makes the button pointer -point to it. It will have the label "Hello World" on it when -displayed. - -<tscreen><verb> - button = gtk_button_new_with_label ("Hello World"); -</verb></tscreen> - -Here, we take this button, and make it do something useful. We attach -a signal handler to it so when it emits the "clicked" signal, our -hello() function is called. The data is ignored, so we simply pass in -NULL to the hello() callback function. Obviously, the "clicked" signal -is emitted when we click the button with our mouse pointer. - -<tscreen><verb> - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (hello), NULL); -</verb></tscreen> - -We are also going to use this button to exit our program. This will -illustrate how the "destroy" signal may come from either the window -manager, or our program. When the button is "clicked", same as above, -it calls the first hello() callback function, and then this one in the -order they are set up. You may have as many callback functions as you -need, and all will be executed in the order you connected -them. Because the gtk_widget_destroy() function accepts only a -GtkWidget *widget as an argument, we use the -gtk_signal_connect_object() function here instead of straight -gtk_signal_connect(). - -<tscreen><verb> - gtk_signal_connect_object (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (gtk_widget_destroy), - GTK_OBJECT (window)); -</verb></tscreen> - -This is a packing call, which will be explained in depth later on in -<ref id="sec_packing_widgets" name="Packing Widgets">. But it is -fairly easy to understand. It simply tells GTK that the button is to -be placed in the window where it will be displayed. Note that a GTK -container can only contain one widget. There are other widgets, that -are described later, which are designed to layout multiple widgets in -various ways. - -<tscreen><verb> - gtk_container_add (GTK_CONTAINER (window), button); -</verb></tscreen> - -Now we have everything set up the way we want it to be. With all the -signal handlers in place, and the button placed in the window where it -should be, we ask GTK to "show" the widgets on the screen. The window -widget is shown last so the whole window will pop up at once rather -than seeing the window pop up, and then the button form inside of -it. Although with such a simple example, you'd never notice. - -<tscreen><verb> - gtk_widget_show (button); - - gtk_widget_show (window); -</verb></tscreen> - -And of course, we call gtk_main() which waits for events to come from -the X server and will call on the widgets to emit signals when these -events come. - -<tscreen><verb> - gtk_main (); -</verb></tscreen> - -And the final return. Control returns here after gtk_quit() is called. - -<tscreen><verb> - return (0); -</verb></tscreen> - -Now, when we click the mouse button on a GTK button, the widget emits -a "clicked" signal. In order for us to use this information, our -program sets up a signal handler to catch that signal, which -dispatches the function of our choice. In our example, when the button -we created is "clicked", the hello() function is called with a NULL -argument, and then the next handler for this signal is called. This -calls the gtk_widget_destroy() function, passing it the window widget -as its argument, destroying the window widget. This causes the window -to emit the "destroy" signal, which is caught, and calls our destroy() -callback function, which simply exits GTK. - -Another course of events is to use the window manager to kill the -window, which will cause the "delete_event" to be emitted. This will -call our "delete_event" handler. If we return TRUE here, the window -will be left as is and nothing will happen. Returning FALSE will cause -GTK to emit the "destroy" signal which of course calls the "destroy" -callback, exiting GTK. - -<!-- ***************************************************************** --> -<sect>Moving On -<!-- ***************************************************************** --> - -<!-- ----------------------------------------------------------------- --> -<sect1>Data Types -<p> -There are a few things you probably noticed in the previous examples -that need explaining. The gint, gchar, etc. that you see are typedefs -to int and char, respectively, that are part of the GLlib system. This -is done to get around that nasty dependency on the size of simple data -types when doing calculations. - -A good example is "gint32" which will be typedef'd to a 32 bit integer -for any given platform, whether it be the 64 bit alpha, or the 32 bit -i386. The typedefs are very straightforward and intuitive. They are -all defined in glib/glib.h (which gets included from gtk.h). - -You'll also notice GTK's ability to use GtkWidget when the function -calls for an Object. GTK is an object oriented design, and a widget -is an object. - -<!-- ----------------------------------------------------------------- --> -<sect1>More on Signal Handlers -<p> -Lets take another look at the gtk_signal_connect declaration. - -<tscreen><verb> -gint gtk_signal_connect( GtkObject *object, - gchar *name, - GtkSignalFunc func, - gpointer func_data ); -</verb></tscreen> - -Notice the gint return value? This is a tag that identifies your -callback function. As stated above, you may have as many callbacks per -signal and per object as you need, and each will be executed in turn, -in the order they were attached. - -This tag allows you to remove this callback from the list by using: - -<tscreen><verb> -void gtk_signal_disconnect( GtkObject *object, - gint id ); -</verb></tscreen> - -So, by passing in the widget you wish to remove the handler from, and -the tag returned by one of the signal_connect functions, you can -disconnect a signal handler. - -You can also temporarily disable signal handlers with the -gtk_signal_handler_block() and gtk_signal_handler_unblock() family of -functions. - -<tscreen><verb> -void gtk_signal_handler_block( GtkObject *object, - guint handler_id ); - -void gtk_signal_handler_block_by_func( GtkObject *object, - GtkSignalFunc func, - gpointer data ); - -void gtk_signal_handler_block_by_data( GtkObject *object, - gpointer data ); - -void gtk_signal_handler_unblock( GtkObject *object, - guint handler_id ); - -void gtk_signal_handler_unblock_by_func( GtkObject *object, - GtkSignalFunc func, - gpointer data ); - -void gtk_signal_handler_unblock_by_data( GtkObject *object, - gpointer data); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>An Upgraded Hello World -<p> -Let's take a look at a slightly improved <em>helloworld</em> with -better examples of callbacks. This will also introduce us to our next -topic, packing widgets. - -<tscreen><verb> -/* example-start helloworld2 helloworld2.c */ - -#include <gtk/gtk.h> - -/* Our new improved callback. The data passed to this function - * is printed to stdout. */ -void callback( GtkWidget *widget, - gpointer data ) -{ - g_print ("Hello again - %s was pressed\n", (char *) data); -} - -/* another callback */ -gint delete_event( GtkWidget *widget, - GdkEvent *event, - gpointer data ) -{ - gtk_main_quit(); - return(FALSE); -} - -int main( int argc, - char *argv[] ) -{ - /* GtkWidget is the storage type for widgets */ - GtkWidget *window; - GtkWidget *button; - GtkWidget *box1; - - /* This is called in all GTK applications. Arguments are parsed - * from the command line and are returned to the application. */ - gtk_init (&argc, &argv); - - /* Create a new window */ - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - - /* This is a new call, which just sets the title of our - * new window to "Hello Buttons!" */ - gtk_window_set_title (GTK_WINDOW (window), "Hello Buttons!"); - - /* Here we just set a handler for delete_event that immediately - * exits GTK. */ - gtk_signal_connect (GTK_OBJECT (window), "delete_event", - GTK_SIGNAL_FUNC (delete_event), NULL); - - /* Sets the border width of the window. */ - gtk_container_set_border_width (GTK_CONTAINER (window), 10); - - /* We create a box to pack widgets into. This is described in detail - * in the "packing" section. The box is not really visible, it - * is just used as a tool to arrange widgets. */ - box1 = gtk_hbox_new(FALSE, 0); - - /* Put the box into the main window. */ - gtk_container_add (GTK_CONTAINER (window), box1); - - /* Creates a new button with the label "Button 1". */ - button = gtk_button_new_with_label ("Button 1"); - - /* Now when the button is clicked, we call the "callback" function - * with a pointer to "button 1" as its argument */ - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (callback), (gpointer) "button 1"); - - /* Instead of gtk_container_add, we pack this button into the invisible - * box, which has been packed into the window. */ - gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0); - - /* Always remember this step, this tells GTK that our preparation for - * this button is complete, and it can now be displayed. */ - gtk_widget_show(button); - - /* Do these same steps again to create a second button */ - button = gtk_button_new_with_label ("Button 2"); - - /* Call the same callback function with a different argument, - * passing a pointer to "button 2" instead. */ - 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); - - /* The order in which we show the buttons is not really important, but I - * recommend showing the window last, so it all pops up at once. */ - gtk_widget_show(button); - - gtk_widget_show(box1); - - gtk_widget_show (window); - - /* Rest in gtk_main and wait for the fun to begin! */ - gtk_main (); - - return(0); -} -/* example-end */ -</verb></tscreen> - -Compile this program using the same linking arguments as our first -example. You'll notice this time there is no easy way to exit the -program, you have to use your window manager or command line to kill -it. A good exercise for the reader would be to insert a third "Quit" -button that will exit the program. You may also wish to play with the -options to gtk_box_pack_start() while reading the next section. Try -resizing the window, and observe the behavior. - -Just as a side note, there is another useful define for -gtk_window_new() - <tt/GTK_WINDOW_DIALOG/. This interacts with the -window manager a little differently and should be used for transient -windows. - -<!-- ***************************************************************** --> -<sect>Packing Widgets <label id="sec_packing_widgets"> -<!-- ***************************************************************** --> -<p> -When creating an application, you'll want to put more than one widget -inside a window. Our first <em>helloworld</em> example only used one -widget so we could simply use a gtk_container_add call to "pack" the -widget into the window. But when you want to put more than one widget -into a window, how do you control where that widget is positioned? -This is where packing comes in. - -<!-- ----------------------------------------------------------------- --> -<sect1>Theory of Packing Boxes -<p> -Most packing is done by creating boxes as in the example above. These -are invisible widget containers that we can pack our widgets into -which come in two forms, a horizontal box, and a vertical box. When -packing widgets into a horizontal box, the objects are inserted -horizontally from left to right or right to left depending on the call -used. In a vertical box, widgets are packed from top to bottom or vice -versa. You may use any combination of boxes inside or beside other -boxes to create the desired effect. - -To create a new horizontal box, we use a call to gtk_hbox_new(), and -for vertical boxes, gtk_vbox_new(). The gtk_box_pack_start() and -gtk_box_pack_end() functions are used to place objects inside of these -containers. The gtk_box_pack_start() function will start at the top -and work its way down in a vbox, and pack left to right in an hbox. -gtk_box_pack_end() will do the opposite, packing from bottom to top in -a vbox, and right to left in an hbox. Using these functions allows us -to right justify or left justify our widgets and may be mixed in any -way to achieve the desired effect. We will use gtk_box_pack_start() in -most of our examples. An object may be another container or a -widget. In fact, many widgets are actually containers themselves, -including the button, but we usually only use a label inside a button. - -By using these calls, GTK knows where you want to place your widgets -so it can do automatic resizing and other nifty things. There are also -a number of options as to how your widgets should be packed. As you -can imagine, this method gives us a quite a bit of flexibility when -placing and creating widgets. - -<!-- ----------------------------------------------------------------- --> -<sect1>Details of Boxes -<p> -Because of this flexibility, packing boxes in GTK can be confusing at -first. There are a lot of options, and it's not immediately obvious how -they all fit together. In the end, however, there are basically five -different styles. - -<? <CENTER> > -<? -<IMG SRC="gtk_tut_packbox1.gif" VSPACE="15" HSPACE="10" WIDTH="528" -HEIGHT="235" ALT="Box Packing Example Image"> -> -<? </CENTER> > - -Each line contains one horizontal box (hbox) with several buttons. The -call to gtk_box_pack is shorthand for the call to pack each of the -buttons into the hbox. Each of the buttons is packed into the hbox the -same way (i.e., same arguments to the gtk_box_pack_start() function). - -This is the declaration of the gtk_box_pack_start function. - -<tscreen><verb> -void gtk_box_pack_start( GtkBox *box, - GtkWidget *child, - gint expand, - gint fill, - gint padding ); -</verb></tscreen> - -The first argument is the box you are packing the object into, the -second is the object. The objects will all be buttons for now, so -we'll be packing buttons into boxes. - -The expand argument to gtk_box_pack_start() and gtk_box_pack_end() -controls whether the widgets are laid out in the box to fill in all -the extra space in the box so the box is expanded to fill the area -allotted to it (TRUE); or the box is shrunk to just fit the widgets -(FALSE). Setting expand to FALSE will allow you to do right and left -justification of your widgets. Otherwise, they will all expand to fit -into the box, and the same effect could be achieved by using only one -of gtk_box_pack_start or gtk_box_pack_end. - -The fill argument to the gtk_box_pack functions control whether the -extra space is allocated to the objects themselves (TRUE), or as extra -padding in the box around these objects (FALSE). It only has an effect -if the expand argument is also TRUE. - -When creating a new box, the function looks like this: - -<tscreen><verb> -GtkWidget *gtk_hbox_new (gint homogeneous, - gint spacing); -</verb></tscreen> - -The homogeneous argument to gtk_hbox_new (and the same for -gtk_vbox_new) controls whether each object in the box has the same -size (i.e., the same width in an hbox, or the same height in a -vbox). If it is set, the gtk_box_pack routines function essentially -as if the <tt/expand/ argument was always turned on. - -What's the difference between spacing (set when the box is created) -and padding (set when elements are packed)? Spacing is added between -objects, and padding is added on either side of an object. The -following figure should make it clearer: - -<? <CENTER> > -<? -<IMG ALIGN="center" SRC="gtk_tut_packbox2.gif" WIDTH="509" -HEIGHT="213" VSPACE="15" HSPACE="10" -ALT="Box Packing Example Image"> -> -<? </CENTER> > - -Here is the code used to create the above images. I've commented it -fairly heavily so I hope you won't have any problems following -it. Compile it yourself and play with it. - -<!-- ----------------------------------------------------------------- --> -<sect1>Packing Demonstration Program -<p> -<tscreen><verb> -/* example-start packbox packbox.c */ - -#include <stdio.h> -#include <stdlib.h> -#include "gtk/gtk.h" - -gint delete_event( GtkWidget *widget, - GdkEvent *event, - gpointer data ) -{ - gtk_main_quit(); - return(FALSE); -} - -/* Make a new hbox filled with button-labels. Arguments for the - * variables we're interested are passed in to this function. - * We do not show the box, but do show everything inside. */ -GtkWidget *make_box( gint homogeneous, - gint spacing, - gint expand, - gint fill, - gint padding ) -{ - GtkWidget *box; - GtkWidget *button; - char padstr[80]; - - /* Create a new hbox with the appropriate homogeneous - * and spacing settings */ - box = gtk_hbox_new (homogeneous, spacing); - - /* Create a series of buttons with the appropriate settings */ - 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); - - /* Create a button with the label depending on the value of - * 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); - - /* This is the same as the button creation for "expand" - * above, but uses the shorthand form. */ - 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; - - /* Our init, don't forget this! :) */ - gtk_init (&argc, &argv); - - if (argc != 2) { - fprintf (stderr, "usage: packbox num, where num is 1, 2, or 3.\n"); - /* This just does cleanup in GTK and exits with an exit status of 1. */ - gtk_exit (1); - } - - which = atoi (argv[1]); - - /* Create our window */ - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - - /* You should always remember to connect the delete_event signal - * to the main window. This is very important for proper intuitive - * behavior */ - gtk_signal_connect (GTK_OBJECT (window), "delete_event", - GTK_SIGNAL_FUNC (delete_event), NULL); - gtk_container_set_border_width (GTK_CONTAINER (window), 10); - - /* We create a vertical box (vbox) to pack the horizontal boxes into. - * This allows us to stack the horizontal boxes filled with buttons one - * on top of the other in this vbox. */ - box1 = gtk_vbox_new (FALSE, 0); - - /* which example to show. These correspond to the pictures above. */ - switch (which) { - case 1: - /* create a new label. */ - label = gtk_label_new ("gtk_hbox_new (FALSE, 0);"); - - /* Align the label to the left side. We'll discuss this function and - * others in the section on Widget Attributes. */ - gtk_misc_set_alignment (GTK_MISC (label), 0, 0); - - /* Pack the label into the vertical box (vbox box1). Remember that - * widgets added to a vbox will be packed one on top of the other in - * order. */ - gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0); - - /* Show the label */ - gtk_widget_show (label); - - /* Call our make box function - homogeneous = FALSE, spacing = 0, - * expand = FALSE, fill = FALSE, padding = 0 */ - box2 = make_box (FALSE, 0, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0); - gtk_widget_show (box2); - - /* Call our make box function - homogeneous = FALSE, spacing = 0, - * expand = TRUE, fill = FALSE, padding = 0 */ - box2 = make_box (FALSE, 0, TRUE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0); - gtk_widget_show (box2); - - /* Args are: homogeneous, spacing, expand, fill, padding */ - box2 = make_box (FALSE, 0, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0); - gtk_widget_show (box2); - - /* Creates a separator, we'll learn more about these later, - * but they are quite simple. */ - separator = gtk_hseparator_new (); - - /* Pack the separator into the vbox. Remember each of these - * widgets is being packed into a vbox, so they'll be stacked - * vertically. */ - gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5); - gtk_widget_show (separator); - - /* Create another new label, and show it. */ - 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); - - /* Args are: 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); - - /* Args are: homogeneous, spacing, expand, fill, padding */ - box2 = make_box (TRUE, 0, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0); - gtk_widget_show (box2); - - /* Another new separator. */ - separator = gtk_hseparator_new (); - /* The last 3 arguments to gtk_box_pack_start are: - * expand, fill, padding. */ - gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5); - gtk_widget_show (separator); - - break; - - case 2: - - /* Create a new label, remember box1 is a vbox as created - * near the beginning of main() */ - 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); - - /* Args are: homogeneous, spacing, expand, fill, padding */ - box2 = make_box (FALSE, 10, TRUE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0); - gtk_widget_show (box2); - - /* Args are: homogeneous, spacing, expand, fill, padding */ - 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 (); - /* The last 3 arguments to gtk_box_pack_start are: - * expand, fill, padding. */ - 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); - - /* Args are: homogeneous, spacing, expand, fill, padding */ - box2 = make_box (FALSE, 0, TRUE, FALSE, 10); - gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0); - gtk_widget_show (box2); - - /* Args are: homogeneous, spacing, expand, fill, padding */ - 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 (); - /* The last 3 arguments to gtk_box_pack_start are: expand, fill, padding. */ - gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5); - gtk_widget_show (separator); - break; - - case 3: - - /* This demonstrates the ability to use gtk_box_pack_end() to - * right justify widgets. First, we create a new box as before. */ - box2 = make_box (FALSE, 0, FALSE, FALSE, 0); - - /* Create the label that will be put at the end. */ - label = gtk_label_new ("end"); - /* Pack it using gtk_box_pack_end(), so it is put on the right - * side of the hbox created in the make_box() call. */ - gtk_box_pack_end (GTK_BOX (box2), label, FALSE, FALSE, 0); - /* Show the label. */ - gtk_widget_show (label); - - /* Pack box2 into box1 (the vbox remember ? :) */ - gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0); - gtk_widget_show (box2); - - /* A separator for the bottom. */ - separator = gtk_hseparator_new (); - /* This explicitly sets the separator to 400 pixels wide by 5 pixels - * high. This is so the hbox we created will also be 400 pixels wide, - * and the "end" label will be separated from the other labels in the - * hbox. Otherwise, all the widgets in the hbox would be packed as - * close together as possible. */ - gtk_widget_set_usize (separator, 400, 5); - /* pack the separator into the vbox (box1) created near the start - * of main() */ - gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5); - gtk_widget_show (separator); - } - - /* Create another new hbox.. remember we can use as many as we need! */ - quitbox = gtk_hbox_new (FALSE, 0); - - /* Our quit button. */ - button = gtk_button_new_with_label ("Quit"); - - /* Setup the signal to terminate the program when the button is clicked */ - gtk_signal_connect_object (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (gtk_main_quit), - GTK_OBJECT (window)); - /* Pack the button into the quitbox. - * The last 3 arguments to gtk_box_pack_start are: - * expand, fill, padding. */ - gtk_box_pack_start (GTK_BOX (quitbox), button, TRUE, FALSE, 0); - /* pack the quitbox into the vbox (box1) */ - gtk_box_pack_start (GTK_BOX (box1), quitbox, FALSE, FALSE, 0); - - /* Pack the vbox (box1) which now contains all our widgets, into the - * main window. */ - gtk_container_add (GTK_CONTAINER (window), box1); - - /* And show everything left */ - gtk_widget_show (button); - gtk_widget_show (quitbox); - - gtk_widget_show (box1); - /* Showing the window last so everything pops up at once. */ - gtk_widget_show (window); - - /* And of course, our main function. */ - gtk_main (); - - /* Control returns here when gtk_main_quit() is called, but not when - * gtk_exit is used. */ - - return(0); -} -/* example-end */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Packing Using Tables -<p> -Let's take a look at another way of packing - Tables. These can be -extremely useful in certain situations. - -Using tables, we create a grid that we can place widgets in. The -widgets may take up as many spaces as we specify. - -The first thing to look at, of course, is the gtk_table_new function: - -<tscreen><verb> -GtkWidget *gtk_table_new( gint rows, - gint columns, - gint homogeneous ); -</verb></tscreen> - -The first argument is the number of rows to make in the table, while -the second, obviously, is the number of columns. - -The homogeneous argument has to do with how the table's boxes are -sized. If homogeneous is TRUE, the table boxes are resized to the size -of the largest widget in the table. If homogeneous is FALSE, the size -of a table boxes is dictated by the tallest widget in its same row, -and the widest widget in its column. - -The rows and columns are laid out from 0 to n, where n was the number -specified in the call to gtk_table_new. So, if you specify rows = 2 -and columns = 2, the layout would look something like this: - -<tscreen><verb> - 0 1 2 -0+----------+----------+ - | | | -1+----------+----------+ - | | | -2+----------+----------+ -</verb></tscreen> - -Note that the coordinate system starts in the upper left hand corner. -To place a widget into a box, use the following function: - -<tscreen><verb> -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 ); -</verb></tscreen> - -The first argument ("table") is the table you've created and the -second ("child") the widget you wish to place in the table. - -The left and right attach arguments specify where to place the widget, -and how many boxes to use. If you want a button in the lower right -table entry of our 2x2 table, and want it to fill that entry ONLY, -left_attach would be = 1, right_attach = 2, top_attach = 1, -bottom_attach = 2. - -Now, if you wanted a widget to take up the whole top row of our 2x2 -table, you'd use left_attach = 0, right_attach = 2, top_attach = 0, -bottom_attach = 1. - -The xoptions and yoptions are used to specify packing options and may -be bitwise OR'ed together to allow multiple options. - -These options are: -<itemize> -<item><tt/GTK_FILL/ - If the table box is larger than the widget, and -<tt/GTK_FILL/ is specified, the widget will expand to use all the room -available. - -<item><tt/GTK_SHRINK/ - If the table widget was allocated less space -then was requested (usually by the user resizing the window), then the -widgets would normally just be pushed off the bottom of the window and -disappear. If <tt/GTK_SHRINK/ is specified, the widgets will shrink -with the table. - -<item><tt/GTK_EXPAND/ - This will cause the table to expand to use up -any remaining space in the window. -</itemize> - -Padding is just like in boxes, creating a clear area around the widget -specified in pixels. - -gtk_table_attach() has a LOT of options. So, there's a shortcut: - -<tscreen><verb> -void gtk_table_attach_defaults( GtkTable *table, - GtkWidget *widget, - gint left_attach, - gint right_attach, - gint top_attach, - gint bottom_attach ); -</verb></tscreen> - -The X and Y options default to <tt/GTK_FILL | GTK_EXPAND/, and X and Y -padding are set to 0. The rest of the arguments are identical to the -previous function. - -We also have gtk_table_set_row_spacing() and -gtk_table_set_col_spacing(). These places spacing between the rows at -the specified row or column. - -<tscreen><verb> -void gtk_table_set_row_spacing( GtkTable *table, - gint row, - gint spacing ); -</verb></tscreen> - -and - -<tscreen><verb> -void gtk_table_set_col_spacing ( GtkTable *table, - gint column, - gint spacing ); -</verb></tscreen> - -Note that for columns, the space goes to the right of the column, and -for rows, the space goes below the row. - -You can also set a consistent spacing of all rows and/or columns with: - -<tscreen><verb> -void gtk_table_set_row_spacings( GtkTable *table, - gint spacing ); -</verb></tscreen> - -And, - -<tscreen><verb> -void gtk_table_set_col_spacings( GtkTable *table, - gint spacing ); -</verb></tscreen> - -Note that with these calls, the last row and last column do not get -any spacing. - -<!-- ----------------------------------------------------------------- --> -<sect1>Table Packing Example -<p> -Here we make a window with three buttons in a 2x2 table. -The first two buttons will be placed in the upper row. -A third, quit button, is placed in the lower row, spanning both columns. -Which means it should look something like this: - -<? <CENTER> > -<? -<IMG SRC="gtk_tut_table.gif" VSPACE="15" HSPACE="10" -ALT="Table Packing Example Image" WIDTH="180" HEIGHT="120"> -> -<? </CENTER> > - -Here's the source code: - -<tscreen><verb> -/* example-start table table.c */ - -#include <gtk/gtk.h> - -/* Our callback. - * The data passed to this function is printed to stdout */ -void callback( GtkWidget *widget, - gpointer data ) -{ - g_print ("Hello again - %s was pressed\n", (char *) data); -} - -/* This callback quits the program */ -gint delete_event( GtkWidget *widget, - GdkEvent *event, - gpointer data ) -{ - gtk_main_quit (); - return(FALSE); -} - -int main( int argc, - char *argv[] ) -{ - GtkWidget *window; - GtkWidget *button; - GtkWidget *table; - - gtk_init (&argc, &argv); - - /* Create a new window */ - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - - /* Set the window title */ - gtk_window_set_title (GTK_WINDOW (window), "Table"); - - /* Set a handler for delete_event that immediately - * exits GTK. */ - gtk_signal_connect (GTK_OBJECT (window), "delete_event", - GTK_SIGNAL_FUNC (delete_event), NULL); - - /* Sets the border width of the window. */ - gtk_container_set_border_width (GTK_CONTAINER (window), 20); - - /* Create a 2x2 table */ - table = gtk_table_new (2, 2, TRUE); - - /* Put the table in the main window */ - gtk_container_add (GTK_CONTAINER (window), table); - - /* Create first button */ - button = gtk_button_new_with_label ("button 1"); - - /* When the button is clicked, we call the "callback" function - * with a pointer to "button 1" as its argument */ - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (callback), (gpointer) "button 1"); - - - /* Insert button 1 into the upper left quadrant of the table */ - gtk_table_attach_defaults (GTK_TABLE(table), button, 0, 1, 0, 1); - - gtk_widget_show (button); - - /* Create second button */ - - button = gtk_button_new_with_label ("button 2"); - - /* When the button is clicked, we call the "callback" function - * with a pointer to "button 2" as its argument */ - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (callback), (gpointer) "button 2"); - /* Insert button 2 into the upper right quadrant of the table */ - gtk_table_attach_defaults (GTK_TABLE(table), button, 1, 2, 0, 1); - - gtk_widget_show (button); - - /* Create "Quit" button */ - button = gtk_button_new_with_label ("Quit"); - - /* When the button is clicked, we call the "delete_event" function - * and the program exits */ - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (delete_event), NULL); - - /* Insert the quit button into the both - * lower quadrants of the table */ - 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; -} -/* example-end */ -</verb></tscreen> - -<!-- ***************************************************************** --> -<sect>Widget Overview -<!-- ***************************************************************** --> -<p> -The general steps to creating a widget in GTK are: -<enum> -<item> gtk_*_new - one of various functions to create a new widget. -These are all detailed in this section. - -<item> Connect all signals and events we wish to use to the -appropriate handlers. - -<item> Set the attributes of the widget. - -<item> Pack the widget into a container using the appropriate call -such as gtk_container_add() or gtk_box_pack_start(). - -<item> gtk_widget_show() the widget. -</enum> - -gtk_widget_show() lets GTK know that we are done setting the -attributes of the widget, and it is ready to be displayed. You may -also use gtk_widget_hide to make it disappear again. The order in -which you show the widgets is not important, but I suggest showing the -window last so the whole window pops up at once rather than seeing the -individual widgets come up on the screen as they're formed. The -children of a widget (a window is a widget too) will not be displayed -until the window itself is shown using the gtk_widget_show() function. - -<!-- ----------------------------------------------------------------- --> -<sect1> Casting -<p> -You'll notice as you go on that GTK uses a type casting system. This -is always done using macros that both test the ability to cast the -given item, and perform the cast. Some common ones you will see are: - -<tscreen><verb> - GTK_WIDGET(widget) - GTK_OBJECT(object) - GTK_SIGNAL_FUNC(function) - GTK_CONTAINER(container) - GTK_WINDOW(window) - GTK_BOX(box) -</verb></tscreen> - -These are all used to cast arguments in functions. You'll see them in the -examples, and can usually tell when to use them simply by looking at the -function's declaration. - -As you can see below in the class hierarchy, all GtkWidgets are -derived from the Object base class. This means you can use a widget -in any place the function asks for an object - simply use the -<tt/GTK_OBJECT()/ macro. - -For example: - -<tscreen><verb> -gtk_signal_connect( GTK_OBJECT(button), "clicked", - GTK_SIGNAL_FUNC(callback_function), callback_data); -</verb></tscreen> - -This casts the button into an object, and provides a cast for the -function pointer to the callback. - -Many widgets are also containers. If you look in the class hierarchy -below, you'll notice that many widgets derive from the Container -class. Any one of these widgets may be used with the -<tt/GTK_CONTAINER/ macro to pass them to functions that ask for -containers. - -Unfortunately, these macros are not extensively covered in the -tutorial, but I recommend taking a look through the GTK header -files. It can be very educational. In fact, it's not difficult to -learn how a widget works just by looking at the function declarations. - -<!-- ----------------------------------------------------------------- --> -<sect1>Widget Hierarchy -<p> -For your reference, here is the class hierarchy tree used to implement widgets. - -<tscreen><verb> - GtkObject - +GtkWidget - | +GtkMisc - | | +GtkLabel - | | | +GtkAccelLabel - | | | `GtkTipsQuery - | | +GtkArrow - | | +GtkImage - | | `GtkPixmap - | +GtkContainer - | | +GtkBin - | | | +GtkAlignment - | | | +GtkFrame - | | | | `GtkAspectFrame - | | | +GtkButton - | | | | +GtkToggleButton - | | | | | `GtkCheckButton - | | | | | `GtkRadioButton - | | | | `GtkOptionMenu - | | | +GtkItem - | | | | +GtkMenuItem - | | | | | +GtkCheckMenuItem - | | | | | | `GtkRadioMenuItem - | | | | | `GtkTearoffMenuItem - | | | | +GtkListItem - | | | | `GtkTreeItem - | | | +GtkWindow - | | | | +GtkColorSelectionDialog - | | | | +GtkDialog - | | | | | `GtkInputDialog - | | | | +GtkDrawWindow - | | | | +GtkFileSelection - | | | | +GtkFontSelectionDialog - | | | | `GtkPlug - | | | +GtkEventBox - | | | +GtkHandleBox - | | | +GtkScrolledWindow - | | | `GtkViewport - | | +GtkBox - | | | +GtkButtonBox - | | | | +GtkHButtonBox - | | | | `GtkVButtonBox - | | | +GtkVBox - | | | | +GtkColorSelection - | | | | `GtkGammaCurve - | | | `GtkHBox - | | | +GtkCombo - | | | `GtkStatusbar - | | +GtkCList - | | | `GtkCTree - | | +GtkFixed - | | +GtkNotebook - | | | `GtkFontSelection - | | +GtkPaned - | | | +GtkHPaned - | | | `GtkVPaned - | | +GtkLayout - | | +GtkList - | | +GtkMenuShell - | | | +GtkMenuBar - | | | `GtkMenu - | | +GtkPacker - | | +GtkSocket - | | +GtkTable - | | +GtkToolbar - | | `GtkTree - | +GtkCalendar - | +GtkDrawingArea - | | `GtkCurve - | +GtkEditable - | | +GtkEntry - | | | `GtkSpinButton - | | `GtkText - | +GtkRuler - | | +GtkHRuler - | | `GtkVRuler - | +GtkRange - | | +GtkScale - | | | +GtkHScale - | | | `GtkVScale - | | `GtkScrollbar - | | +GtkHScrollbar - | | `GtkVScrollbar - | +GtkSeparator - | | +GtkHSeparator - | | `GtkVSeparator - | +GtkPreview - | `GtkProgress - | `GtkProgressBar - +GtkData - | +GtkAdjustment - | `GtkTooltips - `GtkItemFactory -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Widgets Without Windows -<p> -The following widgets do not have an associated window. If you want to -capture events, you'll have to use the EventBox. See the section on -the <ref id="sec_EventBox" name="EventBox"> widget. - -<tscreen><verb> -GtkAlignment -GtkArrow -GtkBin -GtkBox -GtkImage -GtkItem -GtkLabel -GtkPixmap -GtkScrolledWindow -GtkSeparator -GtkTable -GtkAspectFrame -GtkFrame -GtkVBox -GtkHBox -GtkVSeparator -GtkHSeparator -</verb></tscreen> - -We'll further our exploration of GTK by examining each widget in turn, -creating a few simple functions to display them. Another good source -is the testgtk.c program that comes with GTK. It can be found in -gtk/testgtk.c. - -<!-- ***************************************************************** --> -<sect>The Button Widget -<!-- ***************************************************************** --> - -<!-- ----------------------------------------------------------------- --> -<sect1>Normal Buttons -<p> -We've almost seen all there is to see of the button widget. It's -pretty simple. There are however two ways to create a button. You can -use the gtk_button_new_with_label() to create a button with a label, -or use gtk_button_new() to create a blank button. It's then up to you -to pack a label or pixmap into this new button. To do this, create a -new box, and then pack your objects into this box using the usual -gtk_box_pack_start, and then use gtk_container_add to pack the box -into the button. - -Here's an example of using gtk_button_new to create a button with a -picture and a label in it. I've broken up the code to create a box -from the rest so you can use it in your programs. There are further -examples of using pixmaps later in the tutorial. - -<tscreen><verb> -/* example-start buttons buttons.c */ - -#include <gtk/gtk.h> - -/* Create a new hbox with an image and a label packed into it - * and return the box. */ - -GtkWidget *xpm_label_box( GtkWidget *parent, - gchar *xpm_filename, - gchar *label_text ) -{ - GtkWidget *box1; - GtkWidget *label; - GtkWidget *pixmapwid; - GdkPixmap *pixmap; - GdkBitmap *mask; - GtkStyle *style; - - /* Create box for xpm and label */ - box1 = gtk_hbox_new (FALSE, 0); - gtk_container_set_border_width (GTK_CONTAINER (box1), 2); - - /* Get the style of the button to get the - * background color. */ - style = gtk_widget_get_style(parent); - - /* Now on to the xpm stuff */ - pixmap = gdk_pixmap_create_from_xpm (parent->window, &mask, - &style->bg[GTK_STATE_NORMAL], - xpm_filename); - pixmapwid = gtk_pixmap_new (pixmap, mask); - - /* Create a label for the button */ - label = gtk_label_new (label_text); - - /* Pack the pixmap and label into the box */ - 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); -} - -/* Our usual callback function */ -void callback( GtkWidget *widget, - gpointer data ) -{ - g_print ("Hello again - %s was pressed\n", (char *) data); -} - - -int main( int argc, - char *argv[] ) -{ - /* GtkWidget is the storage type for widgets */ - GtkWidget *window; - GtkWidget *button; - GtkWidget *box1; - - gtk_init (&argc, &argv); - - /* Create a new window */ - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - - gtk_window_set_title (GTK_WINDOW (window), "Pixmap'd Buttons!"); - - /* It's a good idea to do this for all windows. */ - gtk_signal_connect (GTK_OBJECT (window), "destroy", - GTK_SIGNAL_FUNC (gtk_exit), NULL); - - gtk_signal_connect (GTK_OBJECT (window), "delete_event", - GTK_SIGNAL_FUNC (gtk_exit), NULL); - - /* Sets the border width of the window. */ - gtk_container_set_border_width (GTK_CONTAINER (window), 10); - gtk_widget_realize(window); - - /* Create a new button */ - button = gtk_button_new (); - - /* Connect the "clicked" signal of the button to our callback */ - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (callback), (gpointer) "cool button"); - - /* This calls our box creating function */ - box1 = xpm_label_box(window, "info.xpm", "cool button"); - - /* Pack and show all our widgets */ - 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); - - /* Rest in gtk_main and wait for the fun to begin! */ - gtk_main (); - - return(0); -} -/* example-end */ -</verb></tscreen> - -The xpm_label_box function could be used to pack xpm's and labels into -any widget that can be a container. - -Notice in <tt/xpm_label_box/ how there is a call to -<tt/gtk_widget_get_style/. Every widget has a "style", consisting of -foreground and background colors for a variety of situations, font -selection, and other graphics data relevant to a widget. These style -values are defaulted in each widget, and are required by many GDK -function calls, such as <tt/gdk_pixmap_create_from_xpm/, which here is -given the "normal" background color. The style data of widgets may -be customized, using <ref id="sec_gtkrc_files" name="GTK's rc files">. - -Also notice the call to <tt/gtk_widget_realize/ after setting the -window's border width. This function uses GDK to create the X -windows related to the widget. The function is automatically called -when you invoke <tt/gtk_widget_show/ for a widget, and so has not been -shown in earlier examples. But the call to -<tt/gdk_pixmap_create_from_xpm/ requires that its <tt/window/ argument -refer to a real X window, so it is necessary to realize the widget -before this GDK call. - -The Button widget has the following signals: - -<itemize> -<item><tt/pressed/ - emitted when pointer button is pressed within -Button widget -<item><tt/released/ - emitted when pointer button is released within -Button widget -<item><tt/clicked/ - emitted when pointer button is pressed and then -released within Button widget -<item><tt/enter/ - emitted when pointer enters Button widget -<item><tt/leave/ - emitted when pointer leaves Button widget -</itemize> - -<!-- ----------------------------------------------------------------- --> -<sect1> Toggle Buttons -<p> -Toggle buttons are derived from normal buttons and are very similar, -except they will always be in one of two states, alternated by a -click. They may be depressed, and when you click again, they will pop -back up. Click again, and they will pop back down. - -Toggle buttons are the basis for check buttons and radio buttons, as -such, many of the calls used for toggle buttons are inherited by radio -and check buttons. I will point these out when we come to them. - -Creating a new toggle button: - -<tscreen><verb> -GtkWidget *gtk_toggle_button_new( void ); - -GtkWidget *gtk_toggle_button_new_with_label( gchar *label ); -</verb></tscreen> - -As you can imagine, these work identically to the normal button widget -calls. The first creates a blank toggle button, and the second, a -button with a label widget already packed into it. - -To retrieve the state of the toggle widget, including radio and check -buttons, we use a construct as shown in our example below. This tests -the state of the toggle, by accessing the <tt/active/ field of the -toggle widget's structure, after first using the -<tt/GTK_TOGGLE_BUTTON/ macro to cast the widget pointer into a toggle -widget pointer. The signal of interest to us emitted by toggle -buttons (the toggle button, check button, and radio button widgets) is -the "toggled" signal. To check the state of these buttons, set up a -signal handler to catch the toggled signal, and access the structure -to determine its state. The callback will look something like: - -<tscreen><verb> -void toggle_button_callback (GtkWidget *widget, gpointer data) -{ - if (GTK_TOGGLE_BUTTON (widget)->active) - { - /* If control reaches here, the toggle button is down */ - - } else { - - /* If control reaches here, the toggle button is up */ - } -} -</verb></tscreen> - -To force the state of a toggle button, and its children, the radio and -check buttons, use this function: - -<tscreen><verb> -void gtk_toggle_button_set_active( GtkToggleButton *toggle_button, - gint state ); -</verb></tscreen> - -The above call can be used to set the state of the toggle button, and -its children the radio and check buttons. Passing in your created -button as the first argument, and a TRUE or FALSE for the second state -argument to specify whether it should be down (depressed) or up -(released). Default is up, or FALSE. - -Note that when you use the gtk_toggle_button_set_active() function, and -the state is actually changed, it causes the "clicked" signal to be -emitted from the button. - -<tscreen><verb> -void gtk_toggle_button_toggled (GtkToggleButton *toggle_button); -</verb></tscreen> - -This simply toggles the button, and emits the "toggled" signal. - -<!-- ----------------------------------------------------------------- --> -<sect1> Check Buttons -<p> -Check buttons inherit many properties and functions from the the -toggle buttons above, but look a little different. Rather than being -buttons with text inside them, they are small squares with the text to -the right of them. These are often used for toggling options on and -off in applications. - -The two creation functions are similar to those of the normal button. - -<tscreen><verb> -GtkWidget *gtk_check_button_new( void ); - -GtkWidget *gtk_check_button_new_with_label ( gchar *label ); -</verb></tscreen> - -The new_with_label function creates a check button with a label beside -it. - -Checking the state of the check button is identical to that of the -toggle button. - -<!-- ----------------------------------------------------------------- --> -<sect1> Radio Buttons <label id="sec_Radio_Buttons"> -<p> -Radio buttons are similar to check buttons except they are grouped so -that only one may be selected/depressed at a time. This is good for -places in your application where you need to select from a short list -of options. - -Creating a new radio button is done with one of these calls: - -<tscreen><verb> -GtkWidget *gtk_radio_button_new( GSList *group ); - -GtkWidget *gtk_radio_button_new_with_label( GSList *group, - gchar *label ); -</verb></tscreen> - -You'll notice the extra argument to these calls. They require a group -to perform their duty properly. The first call to -gtk_radio_button_new_with_label or gtk_radio_button_new_with_label -should pass NULL as the first argument. Then create a group using: - -<tscreen><verb> -GSList *gtk_radio_button_group( GtkRadioButton *radio_button ); -</verb></tscreen> - -The important thing to remember is that gtk_radio_button_group must be -called for each new button added to the group, with the previous -button passed in as an argument. The result is then passed into the -next call to gtk_radio_button_new or -gtk_radio_button_new_with_label. This allows a chain of buttons to be -established. The example below should make this clear. - -You can shorten this slightly by using the following syntax, which -removes the need for a variable to hold the list of buttons. This form -is used in the example to create the third button: - -<tscreen><verb> - button2 = gtk_radio_button_new_with_label( - gtk_radio_button_group (GTK_RADIO_BUTTON (button1)), - "button2"); -</verb></tscreen> - -It is also a good idea to explicitly set which button should be the -default depressed button with: - -<tscreen><verb> -void gtk_toggle_button_set_active( GtkToggleButton *toggle_button, - gint state ); -</verb></tscreen> - -This is described in the section on toggle buttons, and works in -exactly the same way. Once the radio buttons are grouped together, -only one of the group may be active at a time. If the user clicks on -one radio button, and then on another, the first radio button will -first emit a "toggled" signal (to report becoming inactive), and then -the second will emit its "toggled" signal (to report becoming active). - -The following example creates a radio button group with three buttons. - -<tscreen><verb> -/* example-start radiobuttons radiobuttons.c */ - -#include <gtk/gtk.h> -#include <glib.h> - -gint close_application( GtkWidget *widget, - GdkEvent *event, - gpointer data ) -{ - gtk_main_quit(); - return(FALSE); -} - -int main( int argc, - char *argv[] ) -{ - 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_set_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_set_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_active (GTK_TOGGLE_BUTTON (button), TRUE); - gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0); - gtk_widget_show (button); - - button = gtk_radio_button_new_with_label( - gtk_radio_button_group (GTK_RADIO_BUTTON (button)), - "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_set_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); -} -/* example-end */ -</verb></tscreen> - -<!-- TODO: check out gtk_radio_button_new_from_widget function - TRG --> - -<!-- ***************************************************************** --> -<sect> Adjustments <label id="sec_Adjustment"> -<!-- ***************************************************************** --> -<p> -GTK has various widgets that can be visually adjusted by the user -using the mouse or the keyboard, such as the range widgets, described -in the <ref id="sec_Range_Widgets" name="Range Widgets"> -section. There are also a few widgets that display some adjustable -portion of a larger area of data, such as the text widget and the -viewport widget. - -Obviously, an application needs to be able to react to changes the -user makes in range widgets. One way to do this would be to have each -widget emit its own type of signal when its adjustment changes, and -either pass the new value to the signal handler, or require it to look -inside the widget's data structure in order to ascertain the value. -But you may also want to connect the adjustments of several widgets -together, so that adjusting one adjusts the others. The most obvious -example of this is connecting a scrollbar to a panning viewport or a -scrolling text area. If each widget has its own way of setting or -getting the adjustment value, then the programmer may have to write -their own signal handlers to translate between the output of one -widget's signal and the "input" of another's adjustment setting -function. - -GTK solves this problem using the Adjustment object, which is not a -widget but a way for widgets to store and pass adjustment information -in an abstract and flexible form. The most obvious use of Adjustment -is to store the configuration parameters and values of range widgets, -such as scrollbars and scale controls. However, since Adjustments are -derived from Object, they have some special powers beyond those of -normal data structures. Most importantly, they can emit signals, just -like widgets, and these signals can be used not only to allow your -program to react to user input on adjustable widgets, but also to -propagate adjustment values transparently between adjustable widgets. - -You will see how adjustments fit in when you see the other widgets -that incorporate them: -<ref id="sec_ProgressBar" name="Progress Bars">, -<ref id="sec_Viewports" name="Viewports">, -<ref id="sec_ScrolledWindow" name="Scrolled Windows">, and others. - -<sect1> Creating an Adjustment -<p> -Many of the widgets which use adjustment objects do so automatically, -but some cases will be shown in later examples where you may need to -create one yourself. You create an adjustment using: - -<tscreen><verb> -GtkObject *gtk_adjustment_new( gfloat value, - gfloat lower, - gfloat upper, - gfloat step_increment, - gfloat page_increment, - gfloat page_size ); -</verb></tscreen> - -The <tt/value/ argument is the initial value you want to give to the -adjustment, usually corresponding to the topmost or leftmost position -of an adjustable widget. The <tt/lower/ argument specifies the lowest -value which the adjustment can hold. The <tt/step_increment/ argument -specifies the "smaller" of the two increments by which the user can -change the value, while the <tt/page_increment/ is the "larger" one. -The <tt/page_size/ argument usually corresponds somehow to the visible -area of a panning widget. The <tt/upper/ argument is used to represent -the bottom most or right most coordinate in a panning widget's -child. Therefore it is <em/not/ always the largest number that -<tt/value/ can take, since the <tt/page_size/ of such widgets is -usually non-zero. - -<!-- ----------------------------------------------------------------- --> -<sect1> Using Adjustments the Easy Way -<p> -The adjustable widgets can be roughly divided into those which use and -require specific units for these values and those which treat them as -arbitrary numbers. The group which treats the values as arbitrary -numbers includes the range widgets (scrollbars and scales, the -progress bar widget, and the spin button widget). These widgets are -all the widgets which are typically "adjusted" directly by the user -with the mouse or keyboard. They will treat the <tt/lower/ and -<tt/upper/ values of an adjustment as a range within which the user -can manipulate the adjustment's <tt/value/. By default, they will only -modify the <tt/value/ of an adjustment. - -The other group includes the text widget, the viewport widget, the -compound list widget, and the scrolled window widget. All of these -widgets use pixel values for their adjustments. These are also all -widgets which are typically "adjusted" indirectly using scrollbars. -While all widgets which use adjustments can either create their own -adjustments or use ones you supply, you'll generally want to let this -particular category of widgets create its own adjustments. Usually, -they will eventually override all the values except the <tt/value/ -itself in whatever adjustments you give them, but the results are, in -general, undefined (meaning, you'll have to read the source code to -find out, and it may be different from widget to widget). - -Now, you're probably thinking, since text widgets and viewports insist -on setting everything except the <tt/value/ of their adjustments, -while scrollbars will <em/only/ touch the adjustment's <tt/value/, if -you <em/share/ an adjustment object between a scrollbar and a text -widget, manipulating the scrollbar will automagically adjust the text -widget? Of course it will! Just like this: - -<tscreen><verb> - /* creates its own adjustments */ - text = gtk_text_new (NULL, NULL); - /* uses the newly-created adjustment for the scrollbar as well */ - vscrollbar = gtk_vscrollbar_new (GTK_TEXT(text)->vadj); -</verb></tscreen> - -</sect1> -<!-- ----------------------------------------------------------------- --> -<sect1> Adjustment Internals -<p> -Ok, you say, that's nice, but what if I want to create my own handlers -to respond when the user adjusts a range widget or a spin button, and -how do I get at the value of the adjustment in these handlers? To -answer these questions and more, let's start by taking a look at -<tt>struct _GtkAdjustment</tt> itself: - -<tscreen><verb> -struct _GtkAdjustment -{ - GtkData data; - - gfloat lower; - gfloat upper; - gfloat value; - gfloat step_increment; - gfloat page_increment; - gfloat page_size; -}; -</verb></tscreen> - -The first thing you should know is that there aren't any handy-dandy -macros or accessor functions for getting the <tt/value/ out of an -Adjustment, so you'll have to (horror of horrors) do it like a -<em/real/ C programmer. Don't worry - the <tt>GTK_ADJUSTMENT -(Object)</tt> macro does run-time type checking (as do all the GTK -type-casting macros, actually). - -Since, when you set the <tt/value/ of an adjustment, you generally -want the change to be reflected by every widget that uses this -adjustment, GTK provides this convenience function to do this: - -<tscreen><verb> -void gtk_adjustment_set_value( GtkAdjustment *adjustment, - gfloat value ); -</verb></tscreen> - -As mentioned earlier, Adjustment is a subclass of Object just -like all the various widgets, and thus it is able to emit signals. -This is, of course, why updates happen automagically when you share an -adjustment object between a scrollbar and another adjustable widget; -all adjustable widgets connect signal handlers to their adjustment's -<tt/value_changed/ signal, as can your program. Here's the definition -of this signal in <tt/struct _GtkAdjustmentClass/: - -<tscreen><verb> - void (* value_changed) (GtkAdjustment *adjustment); -</verb></tscreen> - -The various widgets that use the Adjustment object will emit this -signal on an adjustment whenever they change its value. This happens -both when user input causes the slider to move on a range widget, as -well as when the program explicitly changes the value with -<tt/gtk_adjustment_set_value()/. So, for example, if you have a scale -widget, and you want to change the rotation of a picture whenever its -value changes, you would create a callback like this: - -<tscreen><verb> -void cb_rotate_picture (GtkAdjustment *adj, GtkWidget *picture) -{ - set_picture_rotation (picture, adj->value); -... -</verb></tscreen> - -and connect it to the scale widget's adjustment like this: - -<tscreen><verb> -gtk_signal_connect (GTK_OBJECT (adj), "value_changed", - GTK_SIGNAL_FUNC (cb_rotate_picture), picture); -</verb></tscreen> - -What about when a widget reconfigures the <tt/upper/ or <tt/lower/ -fields of its adjustment, such as when a user adds more text to a text -widget? In this case, it emits the <tt/changed/ signal, which looks -like this: - -<tscreen><verb> - void (* changed) (GtkAdjustment *adjustment); -</verb></tscreen> - -Range widgets typically connect a handler to this signal, which -changes their appearance to reflect the change - for example, the size -of the slider in a scrollbar will grow or shrink in inverse proportion -to the difference between the <tt/lower/ and <tt/upper/ values of its -adjustment. - -You probably won't ever need to attach a handler to this signal, -unless you're writing a new type of range widget. However, if you -change any of the values in a Adjustment directly, you should emit -this signal on it to reconfigure whatever widgets are using it, like -this: - -<tscreen><verb> -gtk_signal_emit_by_name (GTK_OBJECT (adjustment), "changed"); -</verb></tscreen> - -Now go forth and adjust! -</sect1> -</sect> - -<!-- ***************************************************************** --> -<sect> Range Widgets<label id="sec_Range_Widgets"> -<!-- ***************************************************************** --> - -<p> -The category of range widgets includes the ubiquitous scrollbar widget -and the less common "scale" widget. Though these two types of widgets -are generally used for different purposes, they are quite similar in -function and implementation. All range widgets share a set of common -graphic elements, each of which has its own X window and receives -events. They all contain a "trough" and a "slider" (what is sometimes -called a "thumbwheel" in other GUI environments). Dragging the slider -with the pointer moves it back and forth within the trough, while -clicking in the trough advances the slider towards the location of the -click, either completely, or by a designated amount, depending on -which mouse button is used. - -As mentioned in <ref id="sec_Adjustment" name="Adjustments"> above, -all range widgets are associated with an adjustment object, from which -they calculate the length of the slider and its position within the -trough. When the user manipulates the slider, the range widget will -change the value of the adjustment. - -<!-- ----------------------------------------------------------------- --> -<sect1> Scrollbar Widgets -<p> -These are your standard, run-of-the-mill scrollbars. These should be -used only for scrolling some other widget, such as a list, a text box, -or a viewport (and it's generally easier to use the scrolled window -widget in most cases). For other purposes, you should use scale -widgets, as they are friendlier and more featureful. - -There are separate types for horizontal and vertical scrollbars. -There really isn't much to say about these. You create them with the -following functions, defined in <tt><gtk/gtkhscrollbar.h></tt> -and <tt><gtk/gtkvscrollbar.h></tt>: - -<tscreen><verb> -GtkWidget *gtk_hscrollbar_new( GtkAdjustment *adjustment ); - -GtkWidget *gtk_vscrollbar_new( GtkAdjustment *adjustment ); -</verb></tscreen> - -and that's about it (if you don't believe me, look in the header -files!). The <tt/adjustment/ argument can either be a pointer to an -existing Adjustment, or NULL, in which case one will be created for -you. Specifying NULL might actually be useful in this case, if you -wish to pass the newly-created adjustment to the constructor function -of some other widget which will configure it for you, such as a text -widget. -</sect1> - -<!-- ----------------------------------------------------------------- --> -<sect1> Scale Widgets -<p> -Scale widgets are used to allow the user to visually select and -manipulate a value within a specific range. You might want to use a -scale widget, for example, to adjust the magnification level on a -zoomed preview of a picture, or to control the brightness of a color, -or to specify the number of minutes of inactivity before a screensaver -takes over the screen. - -<!-- ----------------------------------------------------------------- --> -<sect2>Creating a Scale Widget -<p> -As with scrollbars, there are separate widget types for horizontal and -vertical scale widgets. (Most programmers seem to favour horizontal -scale widgets.) Since they work essentially the same way, there's no -need to treat them separately here. The following functions, defined -in <tt><gtk/gtkvscale.h></tt> and -<tt><gtk/gtkhscale.h></tt>, create vertical and horizontal scale -widgets, respectively: - -<tscreen> -<verb> -GtkWidget *gtk_vscale_new( GtkAdjustment *adjustment ); - -GtkWidget *gtk_hscale_new( GtkAdjustment *adjustment ); -</verb> -</tscreen> - -The <tt/adjustment/ argument can either be an adjustment which has -already been created with <tt/gtk_adjustment_new()/, or <tt/NULL/, in -which case, an anonymous Adjustment is created with all of its -values set to <tt/0.0/ (which isn't very useful in this case). In -order to avoid confusing yourself, you probably want to create your -adjustment with a <tt/page_size/ of <tt/0.0/ so that its <tt/upper/ -value actually corresponds to the highest value the user can select. -(If you're <em/already/ thoroughly confused, read the section on <ref -id="sec_Adjustment" name="Adjustments"> again for an explanation of -what exactly adjustments do and how to create and manipulate them.) - -<!-- ----------------------------------------------------------------- --> -<sect2> Functions and Signals (well, functions, at least) -<p> -Scale widgets can display their current value as a number beside the -trough. The default behaviour is to show the value, but you can change -this with this function: - -<tscreen><verb> -void gtk_scale_set_draw_value( GtkScale *scale, - gint draw_value ); -</verb></tscreen> - -As you might have guessed, <tt/draw_value/ is either <tt/TRUE/ or -<tt/FALSE/, with predictable consequences for either one. - -The value displayed by a scale widget is rounded to one decimal point -by default, as is the <tt/value/ field in its GtkAdjustment. You can -change this with: - -<tscreen> -<verb> -void gtk_scale_set_digits( GtkScale *scale, - gint digits ); -</verb> -</tscreen> - -where <tt/digits/ is the number of decimal places you want. You can -set <tt/digits/ to anything you like, but no more than 13 decimal -places will actually be drawn on screen. - -Finally, the value can be drawn in different positions -relative to the trough: - -<tscreen> -<verb> -void gtk_scale_set_value_pos( GtkScale *scale, - GtkPositionType pos ); -</verb> -</tscreen> - -The argument <tt/pos/ is of type <tt>GtkPositionType</tt>, which is -defined in <tt><gtk/gtkenums.h></tt>, and can take one of the -following values: - -<tscreen><verb> - GTK_POS_LEFT - GTK_POS_RIGHT - GTK_POS_TOP - GTK_POS_BOTTOM -</verb></tscreen> - -If you position the value on the "side" of the trough (e.g., on the -top or bottom of a horizontal scale widget), then it will follow the -slider up and down the trough. - -All the preceding functions are defined in -<tt><gtk/gtkscale.h></tt>. The header files for all GTK widgets -are automatically included when you include -<tt><gtk/gtk.h></tt>. But you should look over the header files -of all widgets that interest you, - -</sect2> -</sect1> - -<!-- ----------------------------------------------------------------- --> -<sect1> Common Range Functions <label id="sec_Range_Functions"> -<p> -The Range widget class is fairly complicated internally, but, like -all the "base class" widgets, most of its complexity is only -interesting if you want to hack on it. Also, almost all of the -functions and signals it defines are only really used in writing -derived widgets. There are, however, a few useful functions that are -defined in <tt><gtk/gtkrange.h></tt> and will work on all range -widgets. - -<!-- ----------------------------------------------------------------- --> -<sect2> Setting the Update Policy -<p> -The "update policy" of a range widget defines at what points during -user interaction it will change the <tt/value/ field of its -Adjustment and emit the "value_changed" signal on this -Adjustment. The update policies, defined in -<tt><gtk/gtkenums.h></tt> as type <tt>enum GtkUpdateType</tt>, -are: - -<itemize> -<item>GTK_UPDATE_POLICY_CONTINUOUS - This is the default. The -"value_changed" signal is emitted continuously, i.e., whenever the -slider is moved by even the tiniest amount. -</item> -<item>GTK_UPDATE_POLICY_DISCONTINUOUS - The "value_changed" signal is -only emitted once the slider has stopped moving and the user has -released the mouse button. -</item> -<item>GTK_UPDATE_POLICY_DELAYED - The "value_changed" signal is emitted -when the user releases the mouse button, or if the slider stops moving -for a short period of time. -</item> -</itemize> - -The update policy of a range widget can be set by casting it using the -<tt>GTK_RANGE (Widget)</tt> macro and passing it to this function: - -<tscreen><verb> -void gtk_range_set_update_policy( GtkRange *range, - GtkUpdateType policy) ; -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect2>Getting and Setting Adjustments -<p> -Getting and setting the adjustment for a range widget "on the fly" is -done, predictably, with: - -<tscreen><verb> -GtkAdjustment* gtk_range_get_adjustment( GtkRange *range ); - -void gtk_range_set_adjustment( GtkRange *range, - GtkAdjustment *adjustment ); -</verb></tscreen> - -<tt/gtk_range_get_adjustment()/ returns a pointer to the adjustment to -which <tt/range/ is connected. - -<tt/gtk_range_set_adjustment()/ does absolutely nothing if you pass it -the adjustment that <tt/range/ is already using, regardless of whether -you changed any of its fields or not. If you pass it a new -Adjustment, it will unreference the old one if it exists (possibly -destroying it), connect the appropriate signals to the new one, and -call the private function <tt/gtk_range_adjustment_changed()/, which -will (or at least, is supposed to...) recalculate the size and/or -position of the slider and redraw if necessary. As mentioned in the -section on adjustments, if you wish to reuse the same Adjustment, -when you modify its values directly, you should emit the "changed" -signal on it, like this: - -<tscreen><verb> -gtk_signal_emit_by_name (GTK_OBJECT (adjustment), "changed"); -</verb></tscreen> -</sect2> -</sect1> - -<!-- ----------------------------------------------------------------- --> -<sect1> Key and Mouse bindings -<p> -All of the GTK range widgets react to mouse clicks in more or less -the same way. Clicking button-1 in the trough will cause its -adjustment's <tt/page_increment/ to be added or subtracted from its -<tt/value/, and the slider to be moved accordingly. Clicking mouse -button-2 in the trough will jump the slider to the point at which the -button was clicked. Clicking any button on a scrollbar's arrows will -cause its adjustment's value to change <tt/step_increment/ at a time. - -It may take a little while to get used to, but by default, scrollbars -as well as scale widgets can take the keyboard focus in GTK. If you -think your users will find this too confusing, you can always disable -this by unsetting the <tt/GTK_CAN_FOCUS/ flag on the scrollbar, like -this: - -<tscreen><verb> -GTK_WIDGET_UNSET_FLAGS (scrollbar, GTK_CAN_FOCUS); -</verb></tscreen> - -The key bindings (which are, of course, only active when the widget -has focus) are slightly different between horizontal and vertical -range widgets, for obvious reasons. They are also not quite the same -for scale widgets as they are for scrollbars, for somewhat less -obvious reasons (possibly to avoid confusion between the keys for -horizontal and vertical scrollbars in scrolled windows, where both -operate on the same area). - -<sect2> Vertical Range Widgets -<p> -All vertical range widgets can be operated with the up and down arrow -keys, as well as with the <tt/Page Up/ and <tt/Page Down/ keys. The -arrows move the slider up and down by <tt/step_increment/, while -<tt/Page Up/ and <tt/Page Down/ move it by <tt/page_increment/. - -The user can also move the slider all the way to one end or the other -of the trough using the keyboard. With the VScale widget, this is -done with the <tt/Home/ and <tt/End/ keys, whereas with the -VScrollbar widget, this is done by typing <tt>Control-Page Up</tt> -and <tt>Control-Page Down</tt>. - -<!-- ----------------------------------------------------------------- --> -<sect2> Horizontal Range Widgets -<p> -The left and right arrow keys work as you might expect in these -widgets, moving the slider back and forth by <tt/step_increment/. The -<tt/Home/ and <tt/End/ keys move the slider to the ends of the trough. -For the HScale widget, moving the slider by <tt/page_increment/ is -accomplished with <tt>Control-Left</tt> and <tt>Control-Right</tt>, -while for HScrollbar, it's done with <tt>Control-Home</tt> and -<tt>Control-End</tt>. -</sect2> -</sect1> - -<!-- ----------------------------------------------------------------- --> -<sect1> Example<label id="sec_Range_Example"> -<p> -This example is a somewhat modified version of the "range controls" -test from <tt/testgtk.c/. It basically puts up a window with three -range widgets all connected to the same adjustment, and a couple of -controls for adjusting some of the parameters mentioned above and in -the section on adjustments, so you can see how they affect the way -these widgets work for the user. - -<tscreen><verb> -/* example-start rangewidgets rangewidgets.c */ - -#include <gtk/gtk.h> - -GtkWidget *hscale, *vscale; - -void cb_pos_menu_select( GtkWidget *item, - GtkPositionType pos ) -{ - /* Set the value position on both scale widgets */ - gtk_scale_set_value_pos (GTK_SCALE (hscale), pos); - gtk_scale_set_value_pos (GTK_SCALE (vscale), pos); -} - -void cb_update_menu_select( GtkWidget *item, - GtkUpdateType policy ) -{ - /* Set the update policy for both scale widgets */ - gtk_range_set_update_policy (GTK_RANGE (hscale), policy); - gtk_range_set_update_policy (GTK_RANGE (vscale), policy); -} - -void cb_digits_scale( GtkAdjustment *adj ) -{ - /* Set the number of decimal places to which adj->value is rounded */ - gtk_scale_set_digits (GTK_SCALE (hscale), (gint) adj->value); - gtk_scale_set_digits (GTK_SCALE (vscale), (gint) adj->value); -} - -void cb_page_size( GtkAdjustment *get, - GtkAdjustment *set ) -{ - /* Set the page size and page increment size of the sample - * adjustment to the value specified by the "Page Size" scale */ - set->page_size = get->value; - set->page_increment = get->value; - /* Now emit the "changed" signal to reconfigure all the widgets that - * are attached to this adjustment */ - gtk_signal_emit_by_name (GTK_OBJECT (set), "changed"); -} - -void cb_draw_value( GtkToggleButton *button ) -{ - /* Turn the value display on the scale widgets off or on depending - * on the state of the checkbutton */ - gtk_scale_set_draw_value (GTK_SCALE (hscale), button->active); - gtk_scale_set_draw_value (GTK_SCALE (vscale), button->active); -} - -/* Convenience functions */ - -GtkWidget *make_menu_item( gchar *name, - GtkSignalFunc callback, - gpointer data ) -{ - GtkWidget *item; - - item = gtk_menu_item_new_with_label (name); - gtk_signal_connect (GTK_OBJECT (item), "activate", - callback, data); - gtk_widget_show (item); - - return(item); -} - -void scale_set_default_values( GtkScale *scale ) -{ - gtk_range_set_update_policy (GTK_RANGE (scale), - GTK_UPDATE_CONTINUOUS); - gtk_scale_set_digits (scale, 1); - gtk_scale_set_value_pos (scale, GTK_POS_TOP); - gtk_scale_set_draw_value (scale, TRUE); -} - -/* makes the sample window */ - -void create_range_controls( void ) -{ - GtkWidget *window; - GtkWidget *box1, *box2, *box3; - GtkWidget *button; - GtkWidget *scrollbar; - GtkWidget *separator; - GtkWidget *opt, *menu, *item; - GtkWidget *label; - GtkWidget *scale; - GtkObject *adj1, *adj2; - - /* Standard window-creating stuff */ - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_signal_connect (GTK_OBJECT (window), "destroy", - GTK_SIGNAL_FUNC(gtk_main_quit), - NULL); - gtk_window_set_title (GTK_WINDOW (window), "range controls"); - - box1 = gtk_vbox_new (FALSE, 0); - gtk_container_add (GTK_CONTAINER (window), box1); - gtk_widget_show (box1); - - box2 = gtk_hbox_new (FALSE, 10); - gtk_container_set_border_width (GTK_CONTAINER (box2), 10); - gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0); - gtk_widget_show (box2); - - /* value, lower, upper, step_increment, page_increment, page_size */ - /* Note that the page_size value only makes a difference for - * scrollbar widgets, and the highest value you'll get is actually - * (upper - page_size). */ - adj1 = gtk_adjustment_new (0.0, 0.0, 101.0, 0.1, 1.0, 1.0); - - vscale = gtk_vscale_new (GTK_ADJUSTMENT (adj1)); - scale_set_default_values (GTK_SCALE (vscale)); - gtk_box_pack_start (GTK_BOX (box2), vscale, TRUE, TRUE, 0); - gtk_widget_show (vscale); - - box3 = gtk_vbox_new (FALSE, 10); - gtk_box_pack_start (GTK_BOX (box2), box3, TRUE, TRUE, 0); - gtk_widget_show (box3); - - /* Reuse the same adjustment */ - hscale = gtk_hscale_new (GTK_ADJUSTMENT (adj1)); - gtk_widget_set_usize (GTK_WIDGET (hscale), 200, 30); - scale_set_default_values (GTK_SCALE (hscale)); - gtk_box_pack_start (GTK_BOX (box3), hscale, TRUE, TRUE, 0); - gtk_widget_show (hscale); - - /* Reuse the same adjustment again */ - scrollbar = gtk_hscrollbar_new (GTK_ADJUSTMENT (adj1)); - /* Notice how this causes the scales to always be updated - * continuously when the scrollbar is moved */ - gtk_range_set_update_policy (GTK_RANGE (scrollbar), - GTK_UPDATE_CONTINUOUS); - gtk_box_pack_start (GTK_BOX (box3), scrollbar, TRUE, TRUE, 0); - gtk_widget_show (scrollbar); - - box2 = gtk_hbox_new (FALSE, 10); - gtk_container_set_border_width (GTK_CONTAINER (box2), 10); - gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0); - gtk_widget_show (box2); - - /* A checkbutton to control whether the value is displayed or not */ - button = gtk_check_button_new_with_label("Display value on scale widgets"); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); - gtk_signal_connect (GTK_OBJECT (button), "toggled", - GTK_SIGNAL_FUNC(cb_draw_value), NULL); - gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0); - gtk_widget_show (button); - - box2 = gtk_hbox_new (FALSE, 10); - gtk_container_set_border_width (GTK_CONTAINER (box2), 10); - - /* An option menu to change the position of the value */ - label = gtk_label_new ("Scale Value Position:"); - gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0); - gtk_widget_show (label); - - opt = gtk_option_menu_new(); - menu = gtk_menu_new(); - - item = make_menu_item ("Top", - GTK_SIGNAL_FUNC(cb_pos_menu_select), - GINT_TO_POINTER (GTK_POS_TOP)); - gtk_menu_append (GTK_MENU (menu), item); - - item = make_menu_item ("Bottom", GTK_SIGNAL_FUNC (cb_pos_menu_select), - GINT_TO_POINTER (GTK_POS_BOTTOM)); - gtk_menu_append (GTK_MENU (menu), item); - - item = make_menu_item ("Left", GTK_SIGNAL_FUNC (cb_pos_menu_select), - GINT_TO_POINTER (GTK_POS_LEFT)); - gtk_menu_append (GTK_MENU (menu), item); - - item = make_menu_item ("Right", GTK_SIGNAL_FUNC (cb_pos_menu_select), - GINT_TO_POINTER (GTK_POS_RIGHT)); - gtk_menu_append (GTK_MENU (menu), item); - - gtk_option_menu_set_menu (GTK_OPTION_MENU (opt), menu); - gtk_box_pack_start (GTK_BOX (box2), opt, TRUE, TRUE, 0); - gtk_widget_show (opt); - - gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0); - gtk_widget_show (box2); - - box2 = gtk_hbox_new (FALSE, 10); - gtk_container_set_border_width (GTK_CONTAINER (box2), 10); - - /* Yet another option menu, this time for the update policy of the - * scale widgets */ - label = gtk_label_new ("Scale Update Policy:"); - gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0); - gtk_widget_show (label); - - opt = gtk_option_menu_new(); - menu = gtk_menu_new(); - - item = make_menu_item ("Continuous", - GTK_SIGNAL_FUNC (cb_update_menu_select), - GINT_TO_POINTER (GTK_UPDATE_CONTINUOUS)); - gtk_menu_append (GTK_MENU (menu), item); - - item = make_menu_item ("Discontinuous", - GTK_SIGNAL_FUNC (cb_update_menu_select), - GINT_TO_POINTER (GTK_UPDATE_DISCONTINUOUS)); - gtk_menu_append (GTK_MENU (menu), item); - - item = make_menu_item ("Delayed", - GTK_SIGNAL_FUNC (cb_update_menu_select), - GINT_TO_POINTER (GTK_UPDATE_DELAYED)); - gtk_menu_append (GTK_MENU (menu), item); - - gtk_option_menu_set_menu (GTK_OPTION_MENU (opt), menu); - gtk_box_pack_start (GTK_BOX (box2), opt, TRUE, TRUE, 0); - gtk_widget_show (opt); - - gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0); - gtk_widget_show (box2); - - box2 = gtk_hbox_new (FALSE, 10); - gtk_container_set_border_width (GTK_CONTAINER (box2), 10); - - /* An HScale widget for adjusting the number of digits on the - * sample scales. */ - label = gtk_label_new ("Scale Digits:"); - gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0); - gtk_widget_show (label); - - adj2 = gtk_adjustment_new (1.0, 0.0, 5.0, 1.0, 1.0, 0.0); - gtk_signal_connect (GTK_OBJECT (adj2), "value_changed", - GTK_SIGNAL_FUNC (cb_digits_scale), NULL); - scale = gtk_hscale_new (GTK_ADJUSTMENT (adj2)); - gtk_scale_set_digits (GTK_SCALE (scale), 0); - gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0); - gtk_widget_show (scale); - - gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0); - gtk_widget_show (box2); - - box2 = gtk_hbox_new (FALSE, 10); - gtk_container_set_border_width (GTK_CONTAINER (box2), 10); - - /* And, one last HScale widget for adjusting the page size of the - * scrollbar. */ - label = gtk_label_new ("Scrollbar Page Size:"); - gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0); - gtk_widget_show (label); - - adj2 = gtk_adjustment_new (1.0, 1.0, 101.0, 1.0, 1.0, 0.0); - gtk_signal_connect (GTK_OBJECT (adj2), "value_changed", - GTK_SIGNAL_FUNC (cb_page_size), adj1); - scale = gtk_hscale_new (GTK_ADJUSTMENT (adj2)); - gtk_scale_set_digits (GTK_SCALE (scale), 0); - gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0); - gtk_widget_show (scale); - - gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0); - gtk_widget_show (box2); - - 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_set_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 ("Quit"); - gtk_signal_connect_object (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC(gtk_main_quit), - NULL); - 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); -} - -int main( int argc, - char *argv[] ) -{ - gtk_init(&argc, &argv); - - create_range_controls(); - - gtk_main(); - - return(0); -} - -/* example-end */ -</verb></tscreen> - -You will notice that the program does not call <tt/gtk_signal_connect/ -for the "delete_event", but only for the "destroy" signal. This will -still perform the desired function, because an unhandled -"delete_event" will result in a "destroy" signal being given to the -window. - -</sect1> -</sect> - -<!-- ***************************************************************** --> -<sect> Miscellaneous Widgets -<!-- ***************************************************************** --> - -<!-- ----------------------------------------------------------------- --> -<sect1> Labels -<p> -Labels are used a lot in GTK, and are relatively simple. Labels emit -no signals as they do not have an associated X window. If you need to -catch signals, or do clipping, place it inside a <ref id="sec_EventBox" -name="EventBox"> widget or a Button widget. - -To create a new label, use: - -<tscreen><verb> -GtkWidget *gtk_label_new( char *str ); -</verb></tscreen> - -The sole argument is the string you wish the label to display. - -To change the label's text after creation, use the function: - -<tscreen><verb> -void gtk_label_set_text( GtkLabel *label, - char *str ); -</verb></tscreen> - -The first argument is the label you created previously (cast -using the <tt/GTK_LABEL()/ macro), and the second is the new string. - -The space needed for the new string will be automatically adjusted if -needed. You can produce multi-line labels by putting line breaks in -the label string. - -To retrieve the current string, use: - -<tscreen><verb> -void gtk_label_get( GtkLabel *label, - char **str ); -</verb></tscreen> - -The first argument is the label you've created, and the second, -the return for the string. Do not free the return string, as it is -used internally by GTK. - -The label text can be justified using: - -<tscreen><verb> -void gtk_label_set_justify( GtkLabel *label, - GtkJustification jtype ); -</verb></tscreen> - -Values for <tt/jtype/ are: -<tscreen><verb> - GTK_JUSTIFY_LEFT - GTK_JUSTIFY_RIGHT - GTK_JUSTIFY_CENTER (the default) - GTK_JUSTIFY_FILL -</verb></tscreen> - -The label widget is also capable of line wrapping the text -automatically. This can be activated using: - -<tscreen><verb> -void gtk_label_set_line_wrap (GtkLabel *label, - gboolean wrap); -</verb></tscreen> - -The <tt/wrap/ argument takes a TRUE or FALSE value. - -If you want your label underlined, then you can set a pattern on the -label: - -<tscreen><verb> -void gtk_label_set_pattern (GtkLabel *label, - const gchar *pattern); -</verb></tscreen> - -The pattern argument indicates how the underlining should look. It -consists of a string of underscore and space characters. An underscore -indicates that the corresponding character in the label should be -underlined. For example, the string <verb/"__ __"/ would underline the -first two characters and eight and ninth characters. - -Below is a short example to illustrate these functions. This example -makes use of the Frame widget to better demonstrate the label -styles. You can ignore this for now as the <ref id="sec_Frames" -name="Frame"> widget is explained later on. - -<tscreen><verb> -/* example-start label label.c */ - -#include <gtk/gtk.h> - -int main( int argc, - char *argv[] ) -{ - static GtkWidget *window = NULL; - GtkWidget *hbox; - GtkWidget *vbox; - GtkWidget *frame; - GtkWidget *label; - - /* Initialise GTK */ - gtk_init(&argc, &argv); - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_signal_connect (GTK_OBJECT (window), "destroy", - GTK_SIGNAL_FUNC(gtk_main_quit), - NULL); - - gtk_window_set_title (GTK_WINDOW (window), "Label"); - vbox = gtk_vbox_new (FALSE, 5); - hbox = gtk_hbox_new (FALSE, 5); - gtk_container_add (GTK_CONTAINER (window), hbox); - gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0); - gtk_container_set_border_width (GTK_CONTAINER (window), 5); - - frame = gtk_frame_new ("Normal Label"); - label = gtk_label_new ("This is a Normal label"); - gtk_container_add (GTK_CONTAINER (frame), label); - gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); - - frame = gtk_frame_new ("Multi-line Label"); - label = gtk_label_new ("This is a Multi-line label.\nSecond line\n" \ - "Third line"); - gtk_container_add (GTK_CONTAINER (frame), label); - gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); - - frame = gtk_frame_new ("Left Justified Label"); - label = gtk_label_new ("This is a Left-Justified\n" \ - "Multi-line label.\nThird line"); - gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT); - gtk_container_add (GTK_CONTAINER (frame), label); - gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); - - frame = gtk_frame_new ("Right Justified Label"); - label = gtk_label_new ("This is a Right-Justified\nMulti-line label.\n" \ - "Fourth line, (j/k)"); - gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_RIGHT); - gtk_container_add (GTK_CONTAINER (frame), label); - gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); - - vbox = gtk_vbox_new (FALSE, 5); - gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0); - frame = gtk_frame_new ("Line wrapped label"); - label = gtk_label_new ("This is an example of a line-wrapped label. It " \ - "should not be taking up the entire " /* big space to test spacing */\ - "width allocated to it, but automatically " \ - "wraps the words to fit. " \ - "The time has come, for all good men, to come to " \ - "the aid of their party. " \ - "The sixth sheik's six sheep's sick.\n" \ - " It supports multiple paragraphs correctly, " \ - "and correctly adds "\ - "many extra spaces. "); - gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); - gtk_container_add (GTK_CONTAINER (frame), label); - gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); - - frame = gtk_frame_new ("Filled, wrapped label"); - label = gtk_label_new ("This is an example of a line-wrapped, filled label. " \ - "It should be taking "\ - "up the entire width allocated to it. " \ - "Here is a sentence to prove "\ - "my point. Here is another sentence. "\ - "Here comes the sun, do de do de do.\n"\ - " This is a new paragraph.\n"\ - " This is another newer, longer, better " \ - "paragraph. It is coming to an end, "\ - "unfortunately."); - gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_FILL); - gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); - gtk_container_add (GTK_CONTAINER (frame), label); - gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); - - frame = gtk_frame_new ("Underlined label"); - label = gtk_label_new ("This label is underlined!\n" - "This one is underlined in quite a funky fashion"); - gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT); - gtk_label_set_pattern (GTK_LABEL (label), - "_________________________ _ _________ _ ______ __ _______ ___"); - gtk_container_add (GTK_CONTAINER (frame), label); - gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); - - gtk_widget_show_all (window); - - gtk_main (); - - return(0); -} -/* example-end */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1> Arrows -<p> -The Arrow widget draws an arrowhead, facing in a number of possible -directions and having a number of possible styles. It can be very -useful when placed on a button in many applications. Like the Label -widget, it emits no signals. - -There are only two functions for manipulating an Arrow widget: - -<tscreen><verb> -GtkWidget *gtk_arrow_new( GtkArrowType arrow_type, - GtkShadowType shadow_type ); - -void gtk_arrow_set( GtkArrow *arrow, - GtkArrowType arrow_type, - GtkShadowType shadow_type ); -</verb></tscreen> - -The first creates a new arrow widget with the indicated type and -appearance. The second allows these values to be altered -retrospectively. The <tt/arrow_type/ argument may take one of the -following values: - -<tscreen><verb> - GTK_ARROW_UP - GTK_ARROW_DOWN - GTK_ARROW_LEFT - GTK_ARROW_RIGHT -</verb></tscreen> - -These values obviously indicate the direction in which the arrow will -point. The <tt/shadow_type/ argument may take one of these values: - -<tscreen><verb> - GTK_SHADOW_IN - GTK_SHADOW_OUT (the default) - GTK_SHADOW_ETCHED_IN - GTK_SHADOW_ETCHED_OUT -</verb></tscreen> - -Here's a brief example to illustrate their use. - -<tscreen><verb> -/* example-start arrow arrow.c */ - -#include <gtk/gtk.h> - -/* Create an Arrow widget with the specified parameters - * and pack it into a button */ -GtkWidget *create_arrow_button( GtkArrowType arrow_type, - GtkShadowType shadow_type ) -{ - GtkWidget *button; - GtkWidget *arrow; - - button = gtk_button_new(); - arrow = gtk_arrow_new (arrow_type, shadow_type); - - gtk_container_add (GTK_CONTAINER (button), arrow); - - gtk_widget_show(button); - gtk_widget_show(arrow); - - return(button); -} - -int main( int argc, - char *argv[] ) -{ - /* GtkWidget is the storage type for widgets */ - GtkWidget *window; - GtkWidget *button; - GtkWidget *box; - - /* Initialize the toolkit */ - gtk_init (&argc, &argv); - - /* Create a new window */ - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - - gtk_window_set_title (GTK_WINDOW (window), "Arrow Buttons"); - - /* It's a good idea to do this for all windows. */ - gtk_signal_connect (GTK_OBJECT (window), "destroy", - GTK_SIGNAL_FUNC (gtk_main_quit), NULL); - - /* Sets the border width of the window. */ - gtk_container_set_border_width (GTK_CONTAINER (window), 10); - - /* Create a box to hold the arrows/buttons */ - box = gtk_hbox_new (FALSE, 0); - gtk_container_set_border_width (GTK_CONTAINER (box), 2); - gtk_container_add (GTK_CONTAINER (window), box); - - /* Pack and show all our widgets */ - gtk_widget_show(box); - - button = create_arrow_button(GTK_ARROW_UP, GTK_SHADOW_IN); - gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3); - - button = create_arrow_button(GTK_ARROW_DOWN, GTK_SHADOW_OUT); - gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3); - - button = create_arrow_button(GTK_ARROW_LEFT, GTK_SHADOW_ETCHED_IN); - gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3); - - button = create_arrow_button(GTK_ARROW_RIGHT, GTK_SHADOW_ETCHED_OUT); - gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3); - - gtk_widget_show (window); - - /* Rest in gtk_main and wait for the fun to begin! */ - gtk_main (); - - return(0); -} -/* example-end */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>The Tooltips Object -<p> -These are the little text strings that pop up when you leave your -pointer over a button or other widget for a few seconds. They are easy -to use, so I will just explain them without giving an example. If you -want to see some code, take a look at the testgtk.c program -distributed with GTK. - -Widgets that do not receive events (widgets that do not have their -own window) will not work with tooltips. - -The first call you will use creates a new tooltip. You only need to do -this once for a set of tooltips as the <tt/GtkTooltips/ object this -function returns can be used to create multiple tooltips. - -<tscreen><verb> -GtkTooltips *gtk_tooltips_new( void ); -</verb></tscreen> - -Once you have created a new tooltip, and the widget you wish to use it -on, simply use this call to set it: - -<tscreen><verb> -void gtk_tooltips_set_tip( GtkTooltips *tooltips, - GtkWidget *widget, - const gchar *tip_text, - const gchar *tip_private ); -</verb></tscreen> - -The first argument is the tooltip you've already created, followed by -the widget you wish to have this tooltip pop up for, and the text you -wish it to say. The last argument is a text string that can be used as -an identifier when using GtkTipsQuery to implement context sensitive -help. For now, you can set it to NULL. - -<!-- TODO: sort out what how to do the context sensitive help --> - -Here's a short example: - -<tscreen><verb> -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); -</verb></tscreen> - -There are other calls that can be used with tooltips. I will just list -them with a brief description of what they do. - -<tscreen><verb> -void gtk_tooltips_enable( GtkTooltips *tooltips ); -</verb></tscreen> - -Enable a disabled set of tooltips. - -<tscreen><verb> -void gtk_tooltips_disable( GtkTooltips *tooltips ); -</verb></tscreen> - -Disable an enabled set of tooltips. - -<tscreen><verb> -void gtk_tooltips_set_delay( GtkTooltips *tooltips, - gint delay ); - -</verb></tscreen> - -Sets how many milliseconds you have to hold your pointer over the -widget before the tooltip will pop up. The default is 500 -milliseconds (half a second). - -<tscreen><verb> -void gtk_tooltips_set_colors( GtkTooltips *tooltips, - GdkColor *background, - GdkColor *foreground ); -</verb></tscreen> - -Set the foreground and background color of the tooltips. - -And that's all the functions associated with tooltips. More than -you'll ever want to know :-) - -<!-- ----------------------------------------------------------------- --> -<sect1> Progress Bars <label id="sec_ProgressBar"> -<p> -Progress bars are used to show the status of an operation. They are -pretty easy to use, as you will see with the code below. But first -lets start out with the calls to create a new progress bar. - -There are two ways to create a progress bar, one simple that takes -no arguments, and one that takes an Adjustment object as an -argument. If the former is used, the progress bar creates its own -adjustment object. - -<tscreen><verb> -GtkWidget *gtk_progress_bar_new( void ); - -GtkWidget *gtk_progress_bar_new_with_adjustment( GtkAdjustment *adjustment ); -</verb></tscreen> - -The second method has the advantage that we can use the adjustment -object to specify our own range parameters for the progress bar. - -The adjustment of a progress object can be changed dynamically using: - -<tscreen><verb> -void gtk_progress_set_adjustment( GtkProgress *progress, - GtkAdjustment *adjustment ); -</verb></tscreen> - -Now that the progress bar has been created we can use it. - -<tscreen><verb> -void gtk_progress_bar_update( GtkProgressBar *pbar, - gfloat percentage ); -</verb></tscreen> - -The first argument is the progress bar you wish to operate on, and the -second argument is the amount "completed", meaning the amount the -progress bar has been filled from 0-100%. This is passed to the -function as a real number ranging from 0 to 1. - -GTK v1.2 has added new functionality to the progress bar that enables -it to display its value in different ways, and to inform the user of -its current value and its range. - -A progress bar may be set to one of a number of orientations using the -function - -<tscreen><verb> -void gtk_progress_bar_set_orientation( GtkProgressBar *pbar, - GtkProgressBarOrientation orientation ); -</verb></tscreen> - -The <tt/orientation/ argument may take one of the following -values to indicate the direction in which the progress bar moves: - -<tscreen><verb> - GTK_PROGRESS_LEFT_TO_RIGHT - GTK_PROGRESS_RIGHT_TO_LEFT - GTK_PROGRESS_BOTTOM_TO_TOP - GTK_PROGRESS_TOP_TO_BOTTOM -</verb></tscreen> - -When used as a measure of how far a process has progressed, the -ProgressBar can be set to display its value in either a continuous -or discrete mode. In continuous mode, the progress bar is updated for -each value. In discrete mode, the progress bar is updated in a number -of discrete blocks. The number of blocks is also configurable. - -The style of a progress bar can be set using the following function. - -<tscreen><verb> -void gtk_progress_bar_set_bar_style( GtkProgressBar *pbar, - GtkProgressBarStyle style ); -</verb></tscreen> - -The <tt/style/ parameter can take one of two values: - -<tscreen><verb> - GTK_PROGRESS_CONTINUOUS - GTK_PROGRESS_DISCRETE -</verb></tscreen> - -The number of discrete blocks can be set by calling - -<tscreen><verb> -void gtk_progress_bar_set_discrete_blocks( GtkProgressBar *pbar, - guint blocks ); -</verb></tscreen> - -As well as indicating the amount of progress that has occured, the -progress bar may be set to just indicate that there is some -activity. This can be useful in situations where progress cannot be -measured against a value range. Activity mode is not affected by the -bar style that is described above, and overrides it. This mode is -either TRUE or FALSE, and is selected by the following function. - -<tscreen><verb> -void gtk_progress_set_activity_mode( GtkProgress *progress, - guint activity_mode ); -</verb></tscreen> - -The step size of the activity indicator, and the number of blocks are -set using the following functions. - -<tscreen><verb> -void gtk_progress_bar_set_activity_step( GtkProgressBar *pbar, - guint step ); - -void gtk_progress_bar_set_activity_blocks( GtkProgressBar *pbar, - guint blocks ); -</verb></tscreen> - -When in continuous mode, the progress bar can also display a -configurable text string within its trough, using the following -function. - -<tscreen><verb> -void gtk_progress_set_format_string( GtkProgress *progress, - gchar *format); -</verb></tscreen> - -The <tt/format/ argument is similiar to one that would be used in a C -<tt/printf/ statement. The following directives may be used within the -format string: - -<itemize> -<item> %p - percentage -<item> %v - value -<item> %l - lower range value -<item> %u - upper range value -</itemize> - -The displaying of this text string can be toggled using: - -<tscreen><verb> -void gtk_progress_set_show_text( GtkProgress *progress, - gint show_text ); -</verb></tscreen> - -The <tt/show_text/ argument is a boolean TRUE/FALSE value. The -appearance of the text can be modified further using: - -<tscreen><verb> -void gtk_progress_set_text_alignment( GtkProgress *progress, - gfloat x_align, - gfloat y_align ); -</verb></tscreen> - -The <tt/x_align/ and <tt/y_align/ arguments take values between 0.0 -and 1.0. Their values indicate the position of the text string within -the trough. Values of 0.0 for both would place the string in the top -left hand corner; values of 0.5 (the default) centres the text, and -values of 1.0 places the text in the lower right hand corner. - -The current text setting of a progress object can be retrieved using -the current or a specified adjustment value using the following two -functions. The character string returned by these functions should be -freed by the application (using the g_free() function). These -functions return the formatted string that would be displayed within -the trough. - -<tscreen><verb> -gchar *gtk_progress_get_current_text( GtkProgress *progress ); - -gchar *gtk_progress_get_text_from_value( GtkProgress *progress, - gfloat value ); -</verb></tscreen> - -There is yet another way to change the range and value of a progress -object using the following function: - -<tscreen><verb> -void gtk_progress_configure( GtkProgress *progress, - gfloat value, - gfloat min, - gfloat max ); -</verb></tscreen> - -This function provides quite a simple interface to the range and value -of a progress object. - -The remaining functions can be used to get and set the current value -of a progess object in various types and formats: - -<tscreen><verb> -void gtk_progress_set_percentage( GtkProgress *progress, - gfloat percentage ); - -void gtk_progress_set_value( GtkProgress *progress, - gfloat value ); - -gfloat gtk_progress_get_value( GtkProgress *progress ); - -gfloat gtk_progress_get_current_percentage( GtkProgress *progress ); - -gfloat gtk_progress_get_percentage_from_value( GtkProgress *progress, - gfloat value ); -</verb></tscreen> - -These functions are pretty self explanatory. The last function uses -the the adjustment of the specified progess object to compute the -percentage value of the given range value. - -Progress Bars are usually used with timeouts or other such functions -(see section on <ref id="sec_timeouts" name="Timeouts, I/O and Idle -Functions">) to give the illusion of multitasking. All will employ the -gtk_progress_bar_update function in the same manner. - -Here is an example of the progress bar, updated using timeouts. This -code also shows you how to reset the Progress Bar. - -<tscreen><verb> -/* example-start progressbar progressbar.c */ - -#include <gtk/gtk.h> - -typedef struct _ProgressData { - GtkWidget *window; - GtkWidget *pbar; - int timer; -} ProgressData; - -/* Update the value of the progress bar so that we get - * some movement */ -gint progress_timeout( gpointer data ) -{ - gfloat new_val; - GtkAdjustment *adj; - - /* Calculate the value of the progress bar using the - * value range set in the adjustment object */ - - new_val = gtk_progress_get_value( GTK_PROGRESS(data) ) + 1; - - adj = GTK_PROGRESS (data)->adjustment; - if (new_val > adj->upper) - new_val = adj->lower; - - /* Set the new value */ - gtk_progress_set_value (GTK_PROGRESS (data), new_val); - - /* As this is a timeout function, return TRUE so that it - * continues to get called */ - return(TRUE); -} - -/* Callback that toggles the text display within the progress - * bar trough */ -void toggle_show_text( GtkWidget *widget, - ProgressData *pdata ) -{ - gtk_progress_set_show_text (GTK_PROGRESS (pdata->pbar), - GTK_TOGGLE_BUTTON (widget)->active); -} - -/* Callback that toggles the activity mode of the progress - * bar */ -void toggle_activity_mode( GtkWidget *widget, - ProgressData *pdata ) -{ - gtk_progress_set_activity_mode (GTK_PROGRESS (pdata->pbar), - GTK_TOGGLE_BUTTON (widget)->active); -} - -/* Callback that toggles the continuous mode of the progress - * bar */ -void set_continuous_mode( GtkWidget *widget, - ProgressData *pdata ) -{ - gtk_progress_bar_set_bar_style (GTK_PROGRESS_BAR (pdata->pbar), - GTK_PROGRESS_CONTINUOUS); -} - -/* Callback that toggles the discrete mode of the progress - * bar */ -void set_discrete_mode( GtkWidget *widget, - ProgressData *pdata ) -{ - gtk_progress_bar_set_bar_style (GTK_PROGRESS_BAR (pdata->pbar), - GTK_PROGRESS_DISCRETE); -} - -/* Clean up allocated memory and remove the timer */ -void destroy_progress( GtkWidget *widget, - ProgressData *pdata) -{ - gtk_timeout_remove (pdata->timer); - pdata->timer = 0; - pdata->window = NULL; - g_free(pdata); - gtk_main_quit(); -} - -int main( int argc, - char *argv[]) -{ - ProgressData *pdata; - GtkWidget *align; - GtkWidget *separator; - GtkWidget *table; - GtkAdjustment *adj; - GtkWidget *button; - GtkWidget *check; - GtkWidget *vbox; - - gtk_init (&argc, &argv); - - /* Allocate memory for the data that is passwd to the callbacks */ - pdata = g_malloc( sizeof(ProgressData) ); - - pdata->window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_policy (GTK_WINDOW (pdata->window), FALSE, FALSE, TRUE); - - gtk_signal_connect (GTK_OBJECT (pdata->window), "destroy", - GTK_SIGNAL_FUNC (destroy_progress), - pdata); - gtk_window_set_title (GTK_WINDOW (pdata->window), "GtkProgressBar"); - gtk_container_set_border_width (GTK_CONTAINER (pdata->window), 0); - - vbox = gtk_vbox_new (FALSE, 5); - gtk_container_set_border_width (GTK_CONTAINER (vbox), 10); - gtk_container_add (GTK_CONTAINER (pdata->window), vbox); - gtk_widget_show(vbox); - - /* Create a centering alignment object */ - align = gtk_alignment_new (0.5, 0.5, 0, 0); - gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, FALSE, 5); - gtk_widget_show(align); - - /* Create a Adjusment object to hold the range of the - * progress bar */ - adj = (GtkAdjustment *) gtk_adjustment_new (0, 1, 150, 0, 0, 0); - - /* Create the GtkProgressBar using the adjustment */ - pdata->pbar = gtk_progress_bar_new_with_adjustment (adj); - - /* Set the format of the string that can be displayed in the - * trough of the progress bar: - * %p - percentage - * %v - value - * %l - lower range value - * %u - upper range value */ - gtk_progress_set_format_string (GTK_PROGRESS (pdata->pbar), - "%v from [%l-%u] (=%p%%)"); - gtk_container_add (GTK_CONTAINER (align), pdata->pbar); - gtk_widget_show(pdata->pbar); - - /* Add a timer callback to update the value of the progress bar */ - pdata->timer = gtk_timeout_add (100, progress_timeout, pdata->pbar); - - separator = gtk_hseparator_new (); - gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0); - gtk_widget_show(separator); - - /* rows, columns, homogeneous */ - table = gtk_table_new (2, 3, FALSE); - gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0); - gtk_widget_show(table); - - /* Add a check button to select displaying of the trough text */ - check = gtk_check_button_new_with_label ("Show text"); - gtk_table_attach (GTK_TABLE (table), check, 0, 1, 0, 1, - GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, - 5, 5); - gtk_signal_connect (GTK_OBJECT (check), "clicked", - GTK_SIGNAL_FUNC (toggle_show_text), - pdata); - gtk_widget_show(check); - - /* Add a check button to toggle activity mode */ - check = gtk_check_button_new_with_label ("Activity mode"); - gtk_table_attach (GTK_TABLE (table), check, 0, 1, 1, 2, - GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, - 5, 5); - gtk_signal_connect (GTK_OBJECT (check), "clicked", - GTK_SIGNAL_FUNC (toggle_activity_mode), - pdata); - gtk_widget_show(check); - - separator = gtk_vseparator_new (); - gtk_table_attach (GTK_TABLE (table), separator, 1, 2, 0, 2, - GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, - 5, 5); - gtk_widget_show(separator); - - /* Add a radio button to select continuous display mode */ - button = gtk_radio_button_new_with_label (NULL, "Continuous"); - gtk_table_attach (GTK_TABLE (table), button, 2, 3, 0, 1, - GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, - 5, 5); - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (set_continuous_mode), - pdata); - gtk_widget_show (button); - - /* Add a radio button to select discrete display mode */ - button = gtk_radio_button_new_with_label( - gtk_radio_button_group (GTK_RADIO_BUTTON (button)), - "Discrete"); - gtk_table_attach (GTK_TABLE (table), button, 2, 3, 1, 2, - GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, - 5, 5); - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (set_discrete_mode), - pdata); - gtk_widget_show (button); - - separator = gtk_hseparator_new (); - gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0); - gtk_widget_show(separator); - - /* Add a button to exit the program */ - button = gtk_button_new_with_label ("close"); - gtk_signal_connect_object (GTK_OBJECT (button), "clicked", - (GtkSignalFunc) gtk_widget_destroy, - GTK_OBJECT (pdata->window)); - gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); - - /* This makes it so the button is the default. */ - GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); - - /* This grabs this button to be the default button. Simply hitting - * the "Enter" key will cause this button to activate. */ - gtk_widget_grab_default (button); - gtk_widget_show(button); - - gtk_widget_show (pdata->window); - - gtk_main (); - - return(0); -} -/* example-end */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1> Dialogs -<p> -The Dialog widget is very simple, and is actually just a window with a -few things pre-packed into it for you. The structure for a Dialog is: - -<tscreen><verb> -struct GtkDialog -{ - GtkWindow window; - - GtkWidget *vbox; - GtkWidget *action_area; -}; -</verb></tscreen> - -So you see, it simply creates a window, and then packs a vbox into the -top, which contains a separator and then an hbox called the -"action_area". - -The Dialog widget can be used for pop-up messages to the user, and -other similar tasks. It is really basic, and there is only one -function for the dialog box, which is: - -<tscreen><verb> -GtkWidget *gtk_dialog_new( void ); -</verb></tscreen> - -So to create a new dialog box, use, - -<tscreen><verb> - GtkWidget *window; - window = gtk_dialog_new (); -</verb></tscreen> - -This will create the dialog box, and it is now up to you to use it. -You could pack a button in the action_area by doing something like this: - -<tscreen><verb> - button = ... - gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), - button, TRUE, TRUE, 0); - gtk_widget_show (button); -</verb></tscreen> - -And you could add to the vbox area by packing, for instance, a label -in it, try something like this: - -<tscreen><verb> - 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); -</verb></tscreen> - -As an example in using the dialog box, you could put two buttons in -the action_area, a Cancel button and an Ok button, and a label in the -vbox area, asking the user a question or giving an error etc. Then -you could attach a different signal to each of the buttons and perform -the operation the user selects. - -If the simple functionality provided by the default vertical and -horizontal boxes in the two areas doesn't give you enough control for -your application, then you can simply pack another layout widget into -the boxes provided. For example, you could pack a table into the -vertical box. - -<!-- ----------------------------------------------------------------- --> -<sect1> Pixmaps <label id="sec_Pixmaps"> -<p> -Pixmaps are data structures that contain pictures. These pictures can -be used in various places, but most commonly as icons on the X -desktop, or as cursors. - -A pixmap which only has 2 colors is called a bitmap, and there are a -few additional routines for handling this common special case. - -To understand pixmaps, it would help to understand how X window -system works. Under X, applications do not need to be running on the -same computer that is interacting with the user. Instead, the various -applications, called "clients", all communicate with a program which -displays the graphics and handles the keyboard and mouse. This -program which interacts directly with the user is called a "display -server" or "X server." Since the communication might take place over -a network, it's important to keep some information with the X server. -Pixmaps, for example, are stored in the memory of the X server. This -means that once pixmap values are set, they don't need to keep getting -transmitted over the network; instead a command is sent to "display -pixmap number XYZ here." Even if you aren't using X with GTK -currently, using constructs such as Pixmaps will make your programs -work acceptably under X. - -To use pixmaps in GTK, we must first build a GdkPixmap structure using -routines from the GDK layer. Pixmaps can either be created from -in-memory data, or from data read from a file. We'll go through each -of the calls to create a pixmap. - -<tscreen><verb> -GdkPixmap *gdk_bitmap_create_from_data( GdkWindow *window, - gchar *data, - gint width, - gint height ); -</verb></tscreen> - -This routine is used to create a single-plane pixmap (2 colors) from -data in memory. Each bit of the data represents whether that pixel is -off or on. Width and height are in pixels. The GdkWindow pointer is to -the current window, since a pixmap's resources are meaningful only in -the context of the screen where it is to be displayed. - -<tscreen><verb> -GdkPixmap *gdk_pixmap_create_from_data( GdkWindow *window, - gchar *data, - gint width, - gint height, - gint depth, - GdkColor *fg, - GdkColor *bg ); -</verb></tscreen> - -This is used to create a pixmap of the given depth (number of colors) from -the bitmap data specified. <tt/fg/ and <tt/bg/ are the foreground and -background color to use. - -<tscreen><verb> -GdkPixmap *gdk_pixmap_create_from_xpm( GdkWindow *window, - GdkBitmap **mask, - GdkColor *transparent_color, - const gchar *filename ); -</verb></tscreen> - -XPM format is a readable pixmap representation for the X Window -System. It is widely used and many different utilities are available -for creating image files in this format. The file specified by -filename must contain an image in that format and it is loaded into -the pixmap structure. The mask specifies which bits of the pixmap are -opaque. All other bits are colored using the color specified by -transparent_color. An example using this follows below. - -<tscreen><verb> -GdkPixmap *gdk_pixmap_create_from_xpm_d( GdkWindow *window, - GdkBitmap **mask, - GdkColor *transparent_color, - gchar **data ); -</verb></tscreen> - -Small images can be incorporated into a program as data in the XPM -format. A pixmap is created using this data, instead of reading it -from a file. An example of such data is - -<tscreen><verb> -/* 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. ", -" ......... ", -" ", -" "}; -</verb></tscreen> - -When we're done using a pixmap and not likely to reuse it again soon, -it is a good idea to release the resource using -g_object_unref(). Pixmaps should be considered a precious resource, -because they take up memory in the end-user's X server process. Even -though the X client you write may run on a powerful "server" computer, -the user may be running the X server on a small personal computer. - -Once we've created a pixmap, we can display it as a GTK widget. We -must create a GTK pixmap widget to contain the GDK pixmap. This is -done using - -<tscreen><verb> -GtkWidget *gtk_pixmap_new( GdkPixmap *pixmap, - GdkBitmap *mask ); -</verb></tscreen> - -The other pixmap widget calls are - -<tscreen><verb> -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); -</verb></tscreen> - -gtk_pixmap_set is used to change the pixmap that the widget is currently -managing. Val is the pixmap created using GDK. - -The following is an example of using a pixmap in a button. - -<tscreen><verb> -/* example-start pixmap pixmap.c */ - -#include <gtk/gtk.h> - - -/* XPM data of Open-File icon */ -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. ", -" ......... ", -" ", -" "}; - - -/* when invoked (via signal delete_event), terminates the application. - */ -gint close_application( GtkWidget *widget, - GdkEvent *event, - gpointer data ) -{ - gtk_main_quit(); - return(FALSE); -} - - -/* is invoked when the button is clicked. It just prints a message. - */ -void button_clicked( GtkWidget *widget, - gpointer data ) { - g_print( "button clicked\n" ); -} - -int main( int argc, - char *argv[] ) -{ - /* GtkWidget is the storage type for widgets */ - GtkWidget *window, *pixmapwid, *button; - GdkPixmap *pixmap; - GdkBitmap *mask; - GtkStyle *style; - - /* create the main window, and attach delete_event signal to terminating - the application */ - 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_set_border_width( GTK_CONTAINER (window), 10 ); - gtk_widget_show( window ); - - /* now for the pixmap from 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 ); - - /* a pixmap widget to contain the pixmap */ - pixmapwid = gtk_pixmap_new( pixmap, mask ); - gtk_widget_show( pixmapwid ); - - /* a button to contain the 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 ); - - /* show the window */ - gtk_main (); - - return 0; -} -/* example-end */ -</verb></tscreen> - -To load a file from an XPM data file called icon0.xpm in the current -directory, we would have created the pixmap thus - -<tscreen><verb> - /* load a pixmap from a file */ - 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 ); -</verb></tscreen> - -A disadvantage of using pixmaps is that the displayed object is always -rectangular, regardless of the image. We would like to create desktops -and applications with icons that have more natural shapes. For -example, for a game interface, we would like to have round buttons to -push. The way to do this is using shaped windows. - -A shaped window is simply a pixmap where the background pixels are -transparent. This way, when the background image is multi-colored, we -don't overwrite it with a rectangular, non-matching border around our -icon. The following example displays a full wheelbarrow image on the -desktop. - -<tscreen><verb> -/* example-start wheelbarrow 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 ", -" ", -" "}; - - -/* When invoked (via signal delete_event), terminates the application */ -gint close_application( GtkWidget *widget, - GdkEvent *event, - gpointer data ) -{ - gtk_main_quit(); - return(FALSE); -} - -int main (int argc, - char *argv[] ) -{ - /* GtkWidget is the storage type for widgets */ - GtkWidget *window, *pixmap, *fixed; - GdkPixmap *gdk_pixmap; - GdkBitmap *mask; - GtkStyle *style; - GdkGC *gc; - - /* Create the main window, and attach delete_event signal to terminate - * the application. Note that the main window will not have a titlebar - * since we're making it a 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); - - /* Now for the pixmap and the 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 ); - - /* To display the pixmap, we use a fixed widget to place the pixmap */ - 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 ); - - /* This masks out everything except for the image itself */ - gtk_widget_shape_combine_mask( window, mask, 0, 0 ); - - /* show the window */ - gtk_widget_set_uposition( window, 20, 400 ); - gtk_widget_show( window ); - gtk_main (); - - return(0); -} -/* example-end */ -</verb></tscreen> - -To make the wheelbarrow image sensitive, we could attach the button -press event signal to make it do something. The following few lines -would make the picture sensitive to a mouse button being pressed which -makes the application terminate. - -<tscreen><verb> - 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 ); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Rulers -<p> -Ruler widgets are used to indicate the location of the mouse pointer -in a given window. A window can have a vertical ruler spanning across -the width and a horizontal ruler spanning down the height. A small -triangular indicator on the ruler shows the exact location of the -pointer relative to the ruler. - -A ruler must first be created. Horizontal and vertical rulers are -created using - -<tscreen><verb> -GtkWidget *gtk_hruler_new( void ); /* horizontal ruler */ - -GtkWidget *gtk_vruler_new( void ); /* vertical ruler */ -</verb></tscreen> - -Once a ruler is created, we can define the unit of measurement. Units -of measure for rulers can be<tt/GTK_PIXELS/, <tt/GTK_INCHES/ or -<tt/GTK_CENTIMETERS/. This is set using - -<tscreen><verb> -void gtk_ruler_set_metric( GtkRuler *ruler, - GtkMetricType metric ); -</verb></tscreen> - -The default measure is <tt/GTK_PIXELS/. - -<tscreen><verb> - gtk_ruler_set_metric( GTK_RULER(ruler), GTK_PIXELS ); -</verb></tscreen> - -Other important characteristics of a ruler are how to mark the units -of scale and where the position indicator is initially placed. These -are set for a ruler using - -<tscreen><verb> -void gtk_ruler_set_range( GtkRuler *ruler, - gfloat lower, - gfloat upper, - gfloat position, - gfloat max_size ); -</verb></tscreen> - -The lower and upper arguments define the extent of the ruler, and -max_size is the largest possible number that will be displayed. -Position defines the initial position of the pointer indicator within -the ruler. - -A vertical ruler can span an 800 pixel wide window thus - -<tscreen><verb> - gtk_ruler_set_range( GTK_RULER(vruler), 0, 800, 0, 800); -</verb></tscreen> - -The markings displayed on the ruler will be from 0 to 800, with a -number for every 100 pixels. If instead we wanted the ruler to range -from 7 to 16, we would code - -<tscreen><verb> - gtk_ruler_set_range( GTK_RULER(vruler), 7, 16, 0, 20); -</verb></tscreen> - -The indicator on the ruler is a small triangular mark that indicates -the position of the pointer relative to the ruler. If the ruler is -used to follow the mouse pointer, the motion_notify_event signal -should be connected to the motion_notify_event method of the ruler. -To follow all mouse movements within a window area, we would use - -<tscreen><verb> -#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) ); -</verb></tscreen> - -The following example creates a drawing area with a horizontal ruler -above it and a vertical ruler to the left of it. The size of the -drawing area is 600 pixels wide by 400 pixels high. The horizontal -ruler spans from 7 to 13 with a mark every 100 pixels, while the -vertical ruler spans from 0 to 400 with a mark every 100 pixels. -Placement of the drawing area and the rulers is done using a table. - -<tscreen><verb> -/* example-start rulers 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 - -/* This routine gets control when the close button is clicked */ -gint close_application( GtkWidget *widget, - GdkEvent *event, - gpointer data ) -{ - gtk_main_quit(); - return(FALSE); -} - -/* The main routine */ -int main( int argc, - char *argv[] ) { - GtkWidget *window, *table, *area, *hrule, *vrule; - - /* Initialize GTK and create the main window */ - 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_set_border_width (GTK_CONTAINER (window), 10); - - /* Create a table for placing the ruler and the 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 ); - - /* The horizontal ruler goes on top. As the mouse moves across the - * drawing area, a motion_notify_event is passed to the - * appropriate event handler for the ruler. */ - 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 ); - - /* The vertical ruler goes on the left. As the mouse moves across - * the drawing area, a motion_notify_event is passed to the - * appropriate event handler for the ruler. */ - 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 ); - - /* Now show everything */ - gtk_widget_show( area ); - gtk_widget_show( hrule ); - gtk_widget_show( vrule ); - gtk_widget_show( table ); - gtk_widget_show( window ); - gtk_main(); - - return(0); -} -/* example-end */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Statusbars -<p> -Statusbars are simple widgets used to display a text message. They -keep a stack of the messages pushed onto them, so that popping the -current message will re-display the previous text message. - -In order to allow different parts of an application to use the same -statusbar to display messages, the statusbar widget issues Context -Identifiers which are used to identify different "users". The message -on top of the stack is the one displayed, no matter what context it is -in. Messages are stacked in last-in-first-out order, not context -identifier order. - -A statusbar is created with a call to: - -<tscreen><verb> -GtkWidget *gtk_statusbar_new( void ); -</verb></tscreen> - -A new Context Identifier is requested using a call to the following -function with a short textual description of the context: - -<tscreen><verb> -guint gtk_statusbar_get_context_id( GtkStatusbar *statusbar, - const gchar *context_description ); -</verb></tscreen> - -There are three functions that can operate on statusbars: - -<tscreen><verb> -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 ); -</verb></tscreen> - -The first, gtk_statusbar_push, is used to add a new message to the -statusbar. It returns a Message Identifier, which can be passed later -to the function gtk_statusbar_remove to remove the message with the -given Message and Context Identifiers from the statusbar's stack. - -The function gtk_statusbar_pop removes the message highest in the -stack with the given Context Identifier. - -The following example creates a statusbar and two buttons, one for -pushing items onto the statusbar, and one for popping the last item -back off. - -<tscreen><verb> -/* example-start statusbar 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), GPOINTER_TO_INT(data), buff); - - return; -} - -void pop_item( GtkWidget *widget, - gpointer data ) -{ - gtk_statusbar_pop( GTK_STATUSBAR(status_bar), GPOINTER_TO_INT(data) ); - return; -} - -int main( int argc, - char *argv[] ) -{ - - GtkWidget *window; - GtkWidget *vbox; - GtkWidget *button; - - gint context_id; - - 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 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), GINT_TO_POINTER(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), GINT_TO_POINTER(context_id) ); - gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 2); - gtk_widget_show(button); - - /* always display the window as the last step so it all splashes on - * the screen at once. */ - gtk_widget_show(window); - - gtk_main (); - - return 0; -} -/* example-end */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Text Entries -<p> -The Entry widget allows text to be typed and displayed in a single line -text box. The text may be set with function calls that allow new text -to replace, prepend or append the current contents of the Entry widget. - -There are two functions for creating Entry widgets: - -<tscreen><verb> -GtkWidget *gtk_entry_new( void ); - -GtkWidget *gtk_entry_new_with_max_length( guint16 max ); -</verb></tscreen> - -The first just creates a new Entry widget, whilst the second creates a -new Entry and sets a limit on the length of the text within the Entry. - -There are several functions for altering the text which is currently -within the Entry widget. - -<tscreen><verb> -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 ); -</verb></tscreen> - -The function gtk_entry_set_text sets the contents of the Entry widget, -replacing the current contents. The functions gtk_entry_append_text -and gtk_entry_prepend_text allow the current contents to be appended -and prepended to. - -The next function allows the current insertion point to be set. - -<tscreen><verb> -void gtk_entry_set_position( GtkEntry *entry, - gint position ); -</verb></tscreen> - -The contents of the Entry can be retrieved by using a call to the -following function. This is useful in the callback functions described below. - -<tscreen><verb> -gchar *gtk_entry_get_text( GtkEntry *entry ); -</verb></tscreen> - -The value returned by this function is used internally, and must not -be freed using either free() or g_free() - -If we don't want the contents of the Entry to be changed by someone typing -into it, we can change its editable state. - -<tscreen><verb> -void gtk_entry_set_editable( GtkEntry *entry, - gboolean editable ); -</verb></tscreen> - -The function above allows us to toggle the editable state of the -Entry widget by passing in a TRUE or FALSE value for the <tt/editable/ -argument. - -If we are using the Entry where we don't want the text entered to be -visible, for example when a password is being entered, we can use the -following function, which also takes a boolean flag. - -<tscreen><verb> -void gtk_entry_set_visibility( GtkEntry *entry, - gboolean visible ); -</verb></tscreen> - -A region of the text may be set as selected by using the following -function. This would most often be used after setting some default -text in an Entry, making it easy for the user to remove it. - -<tscreen><verb> -void gtk_entry_select_region( GtkEntry *entry, - gint start, - gint end ); -</verb></tscreen> - -If we want to catch when the user has entered text, we can connect to -the <tt/activate/ or <tt/changed/ signal. Activate is raised when the -user hits the enter key within the Entry widget. Changed is raised -when the text changes at all, e.g., for every character entered or -removed. - -The following code is an example of using an Entry widget. - -<tscreen><verb> -/* example-start entry entry.c */ - -#include <stdio.h> -#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_active(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_active(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); -} -/* example-end */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Spin Buttons -<p> -The Spin Button widget is generally used to allow the user to select a -value from a range of numeric values. It consists of a text -entry box with up and down arrow buttons attached to the -side. Selecting one of the buttons causes the value to "spin" up and -down the range of possible values. The entry box may also be edited -directly to enter a specific value. - -The Spin Button allows the value to have zero or a number of decimal -places and to be incremented/decremented in configurable steps. The -action of holding down one of the buttons optionally results in an -acceleration of change in the value according to how long it is -depressed. - -The Spin Button uses an <ref id="sec_Adjustment" name="Adjustment"> -object to hold information about the range of values that the spin -button can take. This makes for a powerful Spin Button widget. - -Recall that an adjustment widget is created with the following -function, which illustrates the information that it holds: - -<tscreen><verb> -GtkObject *gtk_adjustment_new( gfloat value, - gfloat lower, - gfloat upper, - gfloat step_increment, - gfloat page_increment, - gfloat page_size ); -</verb></tscreen> - -These attributes of an Adjustment are used by the Spin Button in the -following way: - -<itemize> -<item> <tt/value/: initial value for the Spin Button -<item> <tt/lower/: lower range value -<item> <tt/upper/: upper range value -<item> <tt/step_increment/: value to increment/decrement when pressing -mouse button 1 on a button -<item> <tt/page_increment/: value to increment/decrement when pressing -mouse button 2 on a button -<item> <tt/page_size/: unused -</itemize> - -Additionally, mouse button 3 can be used to jump directly to the -<tt/upper/ or <tt/lower/ values when used to select one of the -buttons. Lets look at how to create a Spin Button: - -<tscreen><verb> -GtkWidget *gtk_spin_button_new( GtkAdjustment *adjustment, - gfloat climb_rate, - guint digits ); -</verb></tscreen> - -The <tt/climb_rate/ argument take a value between 0.0 and 1.0 and -indicates the amount of acceleration that the Spin Button has. The -<tt/digits/ argument specifies the number of decimal places to which -the value will be displayed. - -A Spin Button can be reconfigured after creation using the following -function: - -<tscreen><verb> -void gtk_spin_button_configure( GtkSpinButton *spin_button, - GtkAdjustment *adjustment, - gfloat climb_rate, - guint digits ); -</verb></tscreen> - -The <tt/spin_button/ argument specifies the Spin Button widget that is -to be reconfigured. The other arguments are as specified above. - -The adjustment can be set and retrieved independantly using the -following two functions: - -<tscreen><verb> -void gtk_spin_button_set_adjustment( GtkSpinButton *spin_button, - GtkAdjustment *adjustment ); - -GtkAdjustment *gtk_spin_button_get_adjustment( GtkSpinButton *spin_button ); -</verb></tscreen> - -The number of decimal places can also be altered using: - -<tscreen><verb> -void gtk_spin_button_set_digits( GtkSpinButton *spin_button, - guint digits) ; -</verb></tscreen> - -The value that a Spin Button is currently displaying can be changed -using the following function: - -<tscreen><verb> -void gtk_spin_button_set_value( GtkSpinButton *spin_button, - gfloat value ); -</verb></tscreen> - -The current value of a Spin Button can be retrieved as either a -floating point or integer value with the following functions: - -<tscreen><verb> -gfloat gtk_spin_button_get_value_as_float( GtkSpinButton *spin_button ); - -gint gtk_spin_button_get_value_as_int( GtkSpinButton *spin_button ); -</verb></tscreen> - -If you want to alter the value of a Spin Value relative to its current -value, then the following function can be used: - -<tscreen><verb> -void gtk_spin_button_spin( GtkSpinButton *spin_button, - GtkSpinType direction, - gfloat increment ); -</verb></tscreen> - -The <tt/direction/ parameter can take one of the following values: - -<tscreen><verb> - GTK_SPIN_STEP_FORWARD - GTK_SPIN_STEP_BACKWARD - GTK_SPIN_PAGE_FORWARD - GTK_SPIN_PAGE_BACKWARD - GTK_SPIN_HOME - GTK_SPIN_END - GTK_SPIN_USER_DEFINED -</verb></tscreen> - -This function packs in quite a bit of functionality, which I will -attempt to clearly explain. Many of these settings use values from the -Adjustment object that is associated with a Spin Button. - -<tt/GTK_SPIN_STEP_FORWARD/ and <tt/GTK_SPIN_STEP_BACKWARD/ change the -value of the Spin Button by the amount specified by <tt/increment/, -unless <tt/increment/ is equal to 0, in which case the value is -changed by the value of <tt/step_increment/ in theAdjustment. - -<tt/GTK_SPIN_PAGE_FORWARD/ and <tt/GTK_SPIN_PAGE_BACKWARD/ simply -alter the value of the Spin Button by <tt/increment/. - -<tt/GTK_SPIN_HOME/ sets the value of the Spin Button to the bottom of -the Adjustments range. - -<tt/GTK_SPIN_END/ sets the value of the Spin Button to the top of the -Adjustments range. - -<tt/GTK_SPIN_USER_DEFINED/ simply alters the value of the Spin Button -by the specified amount. - -We move away from functions for setting and retreving the range attributes -of the Spin Button now, and move onto functions that affect the -appearance and behaviour of the Spin Button widget itself. - -The first of these functions is used to constrain the text box of the -Spin Button such that it may only contain a numeric value. This -prevents a user from typing anything other than numeric values into -the text box of a Spin Button: - -<tscreen><verb> -void gtk_spin_button_set_numeric( GtkSpinButton *spin_button, - gboolean numeric ); -</verb></tscreen> - -You can set whether a Spin Button will wrap around between the upper -and lower range values with the following function: - -<tscreen><verb> -void gtk_spin_button_set_wrap( GtkSpinButton *spin_button, - gboolean wrap ); -</verb></tscreen> - -You can set a Spin Button to round the value to the nearest -<tt/step_increment/, which is set within the Adjustment object used -with the Spin Button. This is accomplished with the following -function: - -<tscreen><verb> -void gtk_spin_button_set_snap_to_ticks( GtkSpinButton *spin_button, - gboolean snap_to_ticks ); -</verb></tscreen> - -The update policy of a Spin Button can be changed with the following -function: - -<tscreen><verb> -void gtk_spin_button_set_update_policy( GtkSpinButton *spin_button, - GtkSpinButtonUpdatePolicy policy ); -</verb></tscreen> - -<!-- TODO: find out what this does - TRG --> - -The possible values of <tt/policy/ are either <tt/GTK_UPDATE_ALWAYS/ or -<tt/GTK_UPDATE_IF_VALID/. - -These policies affect the behavior of a Spin Button when parsing -inserted text and syncing its value with the values of the -Adjustment. - -In the case of <tt/GTK_UPDATE_IF_VALID/ the Spin Button only value -gets changed if the text input is a numeric value that is within the -range specified by the Adjustment. Otherwise the text is reset to the -current value. - -In case of <tt/GTK_UPDATE_ALWAYS/ we ignore errors while converting -text into a numeric value. - -The appearance of the buttons used in a Spin Button can be changed -using the following function: - -<tscreen><verb> -void gtk_spin_button_set_shadow_type( GtkSpinButton *spin_button, - GtkShadowType shadow_type ); -</verb></tscreen> - -As usual, the <tt/shadow_type/ can be one of: - -<tscreen><verb> - GTK_SHADOW_IN - GTK_SHADOW_OUT - GTK_SHADOW_ETCHED_IN - GTK_SHADOW_ETCHED_OUT -</verb></tscreen> - -Finally, you can explicitly request that a Spin Button update itself: - -<tscreen><verb> -void gtk_spin_button_update( GtkSpinButton *spin_button ); -</verb></tscreen> - -It's example time again. - -<tscreen><verb> -/* example-start spinbutton spinbutton.c */ - -#include <stdio.h> -#include <gtk/gtk.h> - -static GtkWidget *spinner1; - -void toggle_snap( GtkWidget *widget, - GtkSpinButton *spin ) -{ - gtk_spin_button_set_snap_to_ticks (spin, GTK_TOGGLE_BUTTON (widget)->active); -} - -void toggle_numeric( GtkWidget *widget, - GtkSpinButton *spin ) -{ - gtk_spin_button_set_numeric (spin, GTK_TOGGLE_BUTTON (widget)->active); -} - -void change_digits( GtkWidget *widget, - GtkSpinButton *spin ) -{ - gtk_spin_button_set_digits (GTK_SPIN_BUTTON (spinner1), - gtk_spin_button_get_value_as_int (spin)); -} - -void get_value( GtkWidget *widget, - gpointer data ) -{ - gchar buf[32]; - GtkLabel *label; - GtkSpinButton *spin; - - spin = GTK_SPIN_BUTTON (spinner1); - label = GTK_LABEL (gtk_object_get_user_data (GTK_OBJECT (widget))); - if (GPOINTER_TO_INT (data) == 1) - sprintf (buf, "%d", gtk_spin_button_get_value_as_int (spin)); - else - sprintf (buf, "%0.*f", spin->digits, - gtk_spin_button_get_value_as_float (spin)); - gtk_label_set_text (label, buf); -} - - -int main( int argc, - char *argv[] ) -{ - GtkWidget *window; - GtkWidget *frame; - GtkWidget *hbox; - GtkWidget *main_vbox; - GtkWidget *vbox; - GtkWidget *vbox2; - GtkWidget *spinner2; - GtkWidget *spinner; - GtkWidget *button; - GtkWidget *label; - GtkWidget *val_label; - GtkAdjustment *adj; - - /* Initialise GTK */ - gtk_init(&argc, &argv); - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - - gtk_signal_connect (GTK_OBJECT (window), "destroy", - GTK_SIGNAL_FUNC (gtk_main_quit), - NULL); - - gtk_window_set_title (GTK_WINDOW (window), "Spin Button"); - - main_vbox = gtk_vbox_new (FALSE, 5); - gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 10); - gtk_container_add (GTK_CONTAINER (window), main_vbox); - - frame = gtk_frame_new ("Not accelerated"); - gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0); - - vbox = gtk_vbox_new (FALSE, 0); - gtk_container_set_border_width (GTK_CONTAINER (vbox), 5); - gtk_container_add (GTK_CONTAINER (frame), vbox); - - /* Day, month, year spinners */ - - hbox = gtk_hbox_new (FALSE, 0); - gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 5); - - vbox2 = gtk_vbox_new (FALSE, 0); - gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5); - - label = gtk_label_new ("Day :"); - gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); - gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0); - - adj = (GtkAdjustment *) gtk_adjustment_new (1.0, 1.0, 31.0, 1.0, - 5.0, 0.0); - spinner = gtk_spin_button_new (adj, 0, 0); - gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE); - gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON (spinner), - GTK_SHADOW_OUT); - gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0); - - vbox2 = gtk_vbox_new (FALSE, 0); - gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5); - - label = gtk_label_new ("Month :"); - gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); - gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0); - - adj = (GtkAdjustment *) gtk_adjustment_new (1.0, 1.0, 12.0, 1.0, - 5.0, 0.0); - spinner = gtk_spin_button_new (adj, 0, 0); - gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE); - gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON (spinner), - GTK_SHADOW_ETCHED_IN); - gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0); - - vbox2 = gtk_vbox_new (FALSE, 0); - gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5); - - label = gtk_label_new ("Year :"); - gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); - gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0); - - adj = (GtkAdjustment *) gtk_adjustment_new (1998.0, 0.0, 2100.0, - 1.0, 100.0, 0.0); - spinner = gtk_spin_button_new (adj, 0, 0); - gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), FALSE); - gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON (spinner), - GTK_SHADOW_IN); - gtk_widget_set_usize (spinner, 55, 0); - gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0); - - frame = gtk_frame_new ("Accelerated"); - gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0); - - vbox = gtk_vbox_new (FALSE, 0); - gtk_container_set_border_width (GTK_CONTAINER (vbox), 5); - gtk_container_add (GTK_CONTAINER (frame), vbox); - - hbox = gtk_hbox_new (FALSE, 0); - gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5); - - vbox2 = gtk_vbox_new (FALSE, 0); - gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5); - - label = gtk_label_new ("Value :"); - gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); - gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0); - - adj = (GtkAdjustment *) gtk_adjustment_new (0.0, -10000.0, 10000.0, - 0.5, 100.0, 0.0); - spinner1 = gtk_spin_button_new (adj, 1.0, 2); - gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner1), TRUE); - gtk_widget_set_usize (spinner1, 100, 0); - gtk_box_pack_start (GTK_BOX (vbox2), spinner1, FALSE, TRUE, 0); - - vbox2 = gtk_vbox_new (FALSE, 0); - gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5); - - label = gtk_label_new ("Digits :"); - gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); - gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0); - - adj = (GtkAdjustment *) gtk_adjustment_new (2, 1, 5, 1, 1, 0); - spinner2 = gtk_spin_button_new (adj, 0.0, 0); - gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner2), TRUE); - gtk_signal_connect (GTK_OBJECT (adj), "value_changed", - GTK_SIGNAL_FUNC (change_digits), - (gpointer) spinner2); - gtk_box_pack_start (GTK_BOX (vbox2), spinner2, FALSE, TRUE, 0); - - hbox = gtk_hbox_new (FALSE, 0); - gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5); - - button = gtk_check_button_new_with_label ("Snap to 0.5-ticks"); - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (toggle_snap), - spinner1); - gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); - - button = gtk_check_button_new_with_label ("Numeric only input mode"); - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (toggle_numeric), - spinner1); - gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); - - val_label = gtk_label_new (""); - - hbox = gtk_hbox_new (FALSE, 0); - gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5); - button = gtk_button_new_with_label ("Value as Int"); - gtk_object_set_user_data (GTK_OBJECT (button), val_label); - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (get_value), - GINT_TO_POINTER (1)); - gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5); - - button = gtk_button_new_with_label ("Value as Float"); - gtk_object_set_user_data (GTK_OBJECT (button), val_label); - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (get_value), - GINT_TO_POINTER (2)); - gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5); - - gtk_box_pack_start (GTK_BOX (vbox), val_label, TRUE, TRUE, 0); - gtk_label_set_text (GTK_LABEL (val_label), "0"); - - hbox = gtk_hbox_new (FALSE, 0); - gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, TRUE, 0); - - button = gtk_button_new_with_label ("Close"); - gtk_signal_connect_object (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (gtk_widget_destroy), - GTK_OBJECT (window)); - gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5); - - gtk_widget_show_all (window); - - /* Enter the event loop */ - gtk_main (); - - return(0); -} -/* example-end */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Combo Box -<p> -The combo box is another fairly simple widget that is really just a -collection of other widgets. From the user's point of view, the widget -consists of a text entry box and a pull down menu from which the user -can select one of a set of predefined entries. Alternatively, the user -can type a different option directly into the text box. - -The following extract from the structure that defines a Combo Box -identifies several of the components: - -<tscreen><verb> -struct _GtkCombo { - GtkHBox hbox; - GtkWidget *entry; - GtkWidget *button; - GtkWidget *popup; - GtkWidget *popwin; - GtkWidget *list; - ... }; -</verb></tscreen> - -As you can see, the Combo Box has two principal parts that you really -care about: an entry and a list. - -First off, to create a combo box, use: - -<tscreen><verb> -GtkWidget *gtk_combo_new( void ); -</verb></tscreen> - -Now, if you want to set the string in the entry section of the combo -box, this is done by manipulating the <tt/entry/ widget directly: - -<tscreen><verb> - gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), "My String."); -</verb></tscreen> - -To set the values in the popdown list, one uses the function: - -<tscreen><verb> -void gtk_combo_set_popdown_strings( GtkCombo *combo, - GList *strings ); -</verb></tscreen> - -Before you can do this, you have to assemble a GList of the strings -that you want. GList is a linked list implementation that is part of -<ref id="sec_glib" name="GLib">, a library supporing GTK. For the -moment, the quick and dirty explanation is that you need to set up a -GList pointer, set it equal to NULL, then append strings to it with - -<tscreen><verb> -GList *g_list_append( GList *glist, - gpointer data ); -</verb></tscreen> - -It is important that you set the initial GList pointer to NULL. The -value returned from the g_list_append function must be used as the new -pointer to the GList. - -Here's a typical code segment for creating a set of options: - -<tscreen><verb> - GList *glist=NULL; - - glist = g_list_append(glist, "String 1"); - glist = g_list_append(glist, "String 2"); - glist = g_list_append(glist, "String 3"); - glist = g_list_append(glist, "String 4"); - - gtk_combo_set_popdown_strings( GTK_COMBO(combo), glist) ; -</verb></tscreen> - -The combo widget makes a copy of the strings passed to it in the glist -structure. As a result, you need to make sure you free the memory used -by the list if that is appropriate for your application. - -At this point you have a working combo box that has been set up. -There are a few aspects of its behavior that you can change. These -are accomplished with the functions: - -<tscreen><verb> -void gtk_combo_set_use_arrows( GtkCombo *combo, - gint val ); - -void gtk_combo_set_use_arrows_always( GtkCombo *combo, - gint val ); - -void gtk_combo_set_case_sensitive( GtkCombo *combo, - gint val ); -</verb></tscreen> - -<tt/gtk_combo_set_use_arrows()/ lets the user change the value in the -entry using the up/down arrow keys. This doesn't bring up the list, but -rather replaces the current text in the entry with the next list entry -(up or down, as your key choice indicates). It does this by searching -in the list for the item corresponding to the current value in the -entry and selecting the previous/next item accordingly. Usually in an -entry the arrow keys are used to change focus (you can do that anyway -using TAB). Note that when the current item is the last of the list -and you press arrow-down it changes the focus (the same applies with -the first item and arrow-up). - -If the current value in the entry is not in the list, then the -function of <tt/gtk_combo_set_use_arrows()/ is disabled. - -<tt/gtk_combo_set_use_arrows_always()/ similarly allows the use the -the up/down arrow keys to cycle through the choices in the dropdown -list, except that it wraps around the values in the list, completely -disabling the use of the up and down arrow keys for changing focus. - -<tt/gtk_combo_set_case_sensitive()/ toggles whether or not GTK -searches for entries in a case sensitive manner. This is used when the -Combo widget is asked to find a value from the list using the current -entry in the text box. This completion can be performed in either a -case sensitive or insensitive manner, depending upon the use of this -function. The Combo widget can also simply complete the current entry -if the user presses the key combination MOD-1 and "Tab". MOD-1 is -often mapped to the "Alt" key, by the <tt/xmodmap/ utility. Note, -however that some window managers also use this key combination, which -will override its use within GTK. - -Now that we have a combo box, tailored to look and act how we want it, -all that remains is being able to get data from the combo box. This is -relatively straightforward. The majority of the time, all you are -going to care about getting data from is the entry. The entry is -accessed simply by <tt>GTK_ENTRY(GTK_COMBO(combo)->entry)</tt>. The -two principal things that you are going to want to do with it are -attach to the activate signal, which indicates that the user has -pressed the Return or Enter key, and read the text. The first is -accomplished using something like: - -<tscreen><verb> - gtk_signal_connect(GTK_OBJECT(GTK_COMB(combo)->entry), "activate", - GTK_SIGNAL_FUNC (my_callback_function), my_data); -</verb></tscreen> - -Getting the text at any arbitrary time is accomplished by simply using -the entry function: - -<tscreen><verb> -gchar *gtk_entry_get_text(GtkEntry *entry); -</verb></tscreen> - -Such as: - -<tscreen><verb> - char *string; - - string = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(combo)->entry)); -</verb></tscreen> - -That's about all there is to it. There is a function - -<tscreen><verb> -void gtk_combo_disable_activate(GtkCombo *combo); -</verb></tscreen> - -that will disable the activate signal on the entry widget in the combo -box. Personally, I can't think of why you'd want to use it, but it -does exist. - -<!-- There is also a function to set the string on a particular item, void -gtk_combo_set_item_string(GtkCombo *combo, GtkItem *item, const gchar -*item_value), but this requires that you have a pointer to the -appropriate Item. Frankly, I have no idea how to do that. ---> - -<!-- ----------------------------------------------------------------- --> -<sect1> Calendar -<p> -The Calendar widget is an effective way to display and retrieve -monthly date related information. It is a very simple widget to create -and work with. - -Creating a GtkCalendar widget is a simple as: - -<tscreen><verb> -GtkWidget *gtk_calendar_new(); -</verb></tscreen> - -There might be times where you need to change a lot of information -within this widget and the following functions allow you to make -multiple change to a Calendar widget without the user seeing multiple -on-screen updates. - -<tscreen><verb> -void gtk_calendar_freeze( GtkCalendar *Calendar ); - -void gtk_calendar_thaw ( GtkCalendar *Calendar ); -</verb></tscreen> - -They work just like the freeze/thaw functions of every other -widget. - -The Calendar widget has a few options that allow you to change the way -the widget both looks and operates by using the function - -<tscreen><verb> -void gtk_calendar_display_options( GtkCalendar *calendar, - GtkCalendarDisplayOptions flags ); -</verb></tscreen> - -The <tt/flags/ argument can be formed by combining either of the -following five options using the logical bitwise OR (|) operation: -<itemize> -<item> GTK_CALENDAR_SHOW_HEADING - this option specifies that -the month and year should be shown when drawing the calendar. -<item> GTK_CALENDAR_SHOW_DAY_NAMES - this option specifies that the -three letter descriptions should be displayed for each day (eg -MON,TUE...). - -<item> GTK_CALENDAR_NO_MONTH_CHANGE - this option states that the user -should not and can not change the currently displayed month. This can -be good if you only need to display a particular month such as if you -are displaying 12 calendar widgets for every month in a particular -year. - -<item> GTK_CALENDAR_SHOW_WEEK_NUMBERS - this option specifies that the -number for each week should be displayed down the left side of the -calendar. (eg. Jan 1 = Week 1,Dec 31 = Week 52). - -<item> GTK_CALENDAR_WEEK_START_MONDAY - this option states that the -calander week will start on Monday instead of Sunday which is the -default. This only affects the order in which days are displayed from -left to right. -</itemize> - -The following functions are used to set the the currently displayed -date: -<tscreen><verb> -gint gtk_calendar_select_month( GtkCalendar *calendar, - guint month, - guint year ); - -void gtk_calendar_select_day( GtkCalendar *calendar, - guint day ); -</verb></tscreen> - -The return value from <tt/gtk_calendar_select_month()/ is a boolean -value indicating whether the selection was successful. - -With <tt/gtk_calendar_select_day()/ the specified day number is -selected within the current month, if that is possible. A -<tt/day/ value of 0 will deselect any current selection. - -In addition to having a day selected, any number of days in the month -may be "marked". A marked day is highlighted within the calendar -display. The following functions are provided to manipulate marked -days: - -<tscreen><verb> -gint gtk_calendar_mark_day( GtkCalendar *calendar, - guint day); - -gint gtk_calendar_unmark_day( GtkCalendar *calendar, - guint day); - -void gtk_calendar_clear_marks( GtkCalendar *calendar); -</verb></tscreen> - -The currently marked days are stored within an array within the -GtkCalendar structure. This array is 31 elements long so to test -whether a particular day is currently marked, you need to access the -corresponding element of the array (don't forget in C that array -elements are numbered 0 to n-1). For example: - -<tscreen><verb> - GtkCalendar *calendar; - calendar = gtk_calendar_new(); - - ... - - /* Is day 7 marked? */ - if (calendar->marked_date[7-1]) - /* day is marked */ -</verb></tscreen> - -Note that marks are persistent across month and year changes. - -The final Calendar widget function is used to retrieve the currently -selected date, month and/or year. - -<tscreen><verb> -void gtk_calendar_get_date( GtkCalendar *calendar, - guint *year, - guint *month, - guint *day ); -</verb></tscreen> - -This function requires you to pass the addresses of <tt/guint/ -variables, into which the result will be placed. Passing <tt/NULL/ as -a value will result in the corresponding value not being returned. - -The Calendar widget can generate a number of signals indicating date -selection and change. The names of these signals are self explanatory, -and are: - -<itemize> -<item> <tt/month_changed/ -<item> <tt/day_selected/ -<item> <tt/day_selected_double_click/ -<item> <tt/prev_month/ -<item> <tt/next_month/ -<item> <tt/prev_year/ -<item> <tt/next_year/ -</itemize> - -That just leaves us with the need to put all of this together into -example code. - -<tscreen><verb> -/* example-start calendar calendar.c */ -/* - * Copyright (C) 1998 Cesar Miquel, Shawn T. Amundson, Mattias Grönlund - * Copyright (C) 2000 Tony Gale - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <gtk/gtk.h> -#include <stdio.h> -#include <string.h> -#include <time.h> - -#define DEF_PAD 10 -#define DEF_PAD_SMALL 5 - -#define TM_YEAR_BASE 1900 - -typedef struct _CalendarData { - GtkWidget *flag_checkboxes[5]; - gboolean settings[5]; - gchar *font; - GtkWidget *font_dialog; - GtkWidget *window; - GtkWidget *prev2_sig; - GtkWidget *prev_sig; - GtkWidget *last_sig; - GtkWidget *month; -} CalendarData; - -enum { - calendar_show_header, - calendar_show_days, - calendar_month_change, - calendar_show_week, - calendar_monday_first -}; - -/* - * GtkCalendar - */ - -void calendar_date_to_string( CalendarData *data, - char *buffer, - gint buff_len ) -{ - struct tm tm; - time_t time; - - memset (&tm, 0, sizeof (tm)); - gtk_calendar_get_date (GTK_CALENDAR(data->window), - &tm.tm_year, &tm.tm_mon, &tm.tm_mday); - tm.tm_year -= TM_YEAR_BASE; - time = mktime(&tm); - strftime (buffer, buff_len-1, "%x", gmtime(&time)); -} - -void calendar_set_signal_strings( char *sig_str, - CalendarData *data) -{ - gchar *prev_sig; - - gtk_label_get (GTK_LABEL (data->prev_sig), &prev_sig); - gtk_label_set (GTK_LABEL (data->prev2_sig), prev_sig); - - gtk_label_get (GTK_LABEL (data->last_sig), &prev_sig); - gtk_label_set (GTK_LABEL (data->prev_sig), prev_sig); - gtk_label_set (GTK_LABEL (data->last_sig), sig_str); -} - -void calendar_month_changed( GtkWidget *widget, - CalendarData *data ) -{ - char buffer[256] = "month_changed: "; - - calendar_date_to_string (data, buffer+15, 256-15); - calendar_set_signal_strings (buffer, data); -} - -void calendar_day_selected( GtkWidget *widget, - CalendarData *data ) -{ - char buffer[256] = "day_selected: "; - - calendar_date_to_string (data, buffer+14, 256-14); - calendar_set_signal_strings (buffer, data); -} - -void calendar_day_selected_double_click( GtkWidget *widget, - CalendarData *data ) -{ - struct tm tm; - char buffer[256] = "day_selected_double_click: "; - - calendar_date_to_string (data, buffer+27, 256-27); - calendar_set_signal_strings (buffer, data); - - memset (&tm, 0, sizeof (tm)); - gtk_calendar_get_date (GTK_CALENDAR(data->window), - &tm.tm_year, &tm.tm_mon, &tm.tm_mday); - tm.tm_year -= TM_YEAR_BASE; - - if(GTK_CALENDAR(data->window)->marked_date[tm.tm_mday-1] == 0) { - gtk_calendar_mark_day(GTK_CALENDAR(data->window),tm.tm_mday); - } else { - gtk_calendar_unmark_day(GTK_CALENDAR(data->window),tm.tm_mday); - } -} - -void calendar_prev_month( GtkWidget *widget, - CalendarData *data ) -{ - char buffer[256] = "prev_month: "; - - calendar_date_to_string (data, buffer+12, 256-12); - calendar_set_signal_strings (buffer, data); -} - -void calendar_next_month( GtkWidget *widget, - CalendarData *data ) -{ - char buffer[256] = "next_month: "; - - calendar_date_to_string (data, buffer+12, 256-12); - calendar_set_signal_strings (buffer, data); -} - -void calendar_prev_year( GtkWidget *widget, - CalendarData *data ) -{ - char buffer[256] = "prev_year: "; - - calendar_date_to_string (data, buffer+11, 256-11); - calendar_set_signal_strings (buffer, data); -} - -void calendar_next_year( GtkWidget *widget, - CalendarData *data ) -{ - char buffer[256] = "next_year: "; - - calendar_date_to_string (data, buffer+11, 256-11); - calendar_set_signal_strings (buffer, data); -} - - -void calendar_set_flags( CalendarData *calendar ) -{ - gint i; - gint options=0; - for (i=0;i<5;i++) - if (calendar->settings[i]) - { - options=options + (1<<i); - } - if (calendar->window) - gtk_calendar_display_options (GTK_CALENDAR (calendar->window), options); -} - -void calendar_toggle_flag( GtkWidget *toggle, - CalendarData *calendar ) -{ - gint i; - gint j; - j=0; - for (i=0; i<5; i++) - if (calendar->flag_checkboxes[i] == toggle) - j = i; - - calendar->settings[j]=!calendar->settings[j]; - calendar_set_flags(calendar); - -} - -void calendar_font_selection_ok( GtkWidget *button, - CalendarData *calendar ) -{ - GtkStyle *style; - GdkFont *font; - - calendar->font = gtk_font_selection_dialog_get_font_name( - GTK_FONT_SELECTION_DIALOG (calendar->font_dialog)); - if (calendar->window) - { - font = gtk_font_selection_dialog_get_font(GTK_FONT_SELECTION_DIALOG(calendar->font_dialog)); - if (font) - { - style = gtk_style_copy (gtk_widget_get_style (calendar->window)); - gdk_font_unref (style->font); - style->font = font; - gdk_font_ref (style->font); - gtk_widget_set_style (calendar->window, style); - } - } -} - -void calendar_select_font( GtkWidget *button, - CalendarData *calendar ) -{ - GtkWidget *window; - - if (!calendar->font_dialog) { - window = gtk_font_selection_dialog_new ("Font Selection Dialog"); - g_return_if_fail(GTK_IS_FONT_SELECTION_DIALOG(window)); - calendar->font_dialog = window; - - gtk_window_position (GTK_WINDOW (window), GTK_WIN_POS_MOUSE); - - gtk_signal_connect (GTK_OBJECT (window), "destroy", - GTK_SIGNAL_FUNC (gtk_widget_destroyed), - &calendar->font_dialog); - - gtk_signal_connect (GTK_OBJECT (GTK_FONT_SELECTION_DIALOG (window)->ok_button), - "clicked", GTK_SIGNAL_FUNC(calendar_font_selection_ok), - calendar); - gtk_signal_connect_object (GTK_OBJECT (GTK_FONT_SELECTION_DIALOG (window)->cancel_button), - "clicked", - GTK_SIGNAL_FUNC (gtk_widget_destroy), - GTK_OBJECT (calendar->font_dialog)); - } - window=calendar->font_dialog; - if (!GTK_WIDGET_VISIBLE (window)) - gtk_widget_show (window); - else - gtk_widget_destroy (window); - -} - -void create_calendar() -{ - GtkWidget *window; - GtkWidget *vbox, *vbox2, *vbox3; - GtkWidget *hbox; - GtkWidget *hbbox; - GtkWidget *calendar; - GtkWidget *toggle; - GtkWidget *button; - GtkWidget *frame; - GtkWidget *separator; - GtkWidget *label; - GtkWidget *bbox; - static CalendarData calendar_data; - gint i; - - struct { - char *label; - } flags[] = - { - { "Show Heading" }, - { "Show Day Names" }, - { "No Month Change" }, - { "Show Week Numbers" }, - { "Week Start Monday" } - }; - - - calendar_data.window = NULL; - calendar_data.font = NULL; - calendar_data.font_dialog = NULL; - - for (i=0; i<5; i++) { - calendar_data.settings[i]=0; - } - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_title(GTK_WINDOW(window), "GtkCalendar Example"); - gtk_container_border_width (GTK_CONTAINER (window), 5); - gtk_signal_connect(GTK_OBJECT(window), "destroy", - GTK_SIGNAL_FUNC(gtk_main_quit), - NULL); - gtk_signal_connect(GTK_OBJECT(window), "delete-event", - GTK_SIGNAL_FUNC(gtk_false), - NULL); - - gtk_window_set_policy(GTK_WINDOW(window), FALSE, FALSE, TRUE); - - vbox = gtk_vbox_new(FALSE, DEF_PAD); - gtk_container_add (GTK_CONTAINER (window), vbox); - - /* - * The top part of the window, Calendar, flags and fontsel. - */ - - hbox = gtk_hbox_new(FALSE, DEF_PAD); - gtk_box_pack_start (GTK_BOX(vbox), hbox, TRUE, TRUE, DEF_PAD); - hbbox = gtk_hbutton_box_new(); - gtk_box_pack_start(GTK_BOX(hbox), hbbox, FALSE, FALSE, DEF_PAD); - gtk_button_box_set_layout(GTK_BUTTON_BOX(hbbox), GTK_BUTTONBOX_SPREAD); - gtk_button_box_set_spacing(GTK_BUTTON_BOX(hbbox), 5); - - /* Calendar widget */ - frame = gtk_frame_new("Calendar"); - gtk_box_pack_start(GTK_BOX(hbbox), frame, FALSE, TRUE, DEF_PAD); - calendar=gtk_calendar_new(); - calendar_data.window = calendar; - calendar_set_flags(&calendar_data); - gtk_calendar_mark_day ( GTK_CALENDAR(calendar), 19); - gtk_container_add( GTK_CONTAINER( frame), calendar); - gtk_signal_connect (GTK_OBJECT (calendar), "month_changed", - GTK_SIGNAL_FUNC (calendar_month_changed), - &calendar_data); - gtk_signal_connect (GTK_OBJECT (calendar), "day_selected", - GTK_SIGNAL_FUNC (calendar_day_selected), - &calendar_data); - gtk_signal_connect (GTK_OBJECT (calendar), "day_selected_double_click", - GTK_SIGNAL_FUNC (calendar_day_selected_double_click), - &calendar_data); - gtk_signal_connect (GTK_OBJECT (calendar), "prev_month", - GTK_SIGNAL_FUNC (calendar_prev_month), - &calendar_data); - gtk_signal_connect (GTK_OBJECT (calendar), "next_month", - GTK_SIGNAL_FUNC (calendar_next_month), - &calendar_data); - gtk_signal_connect (GTK_OBJECT (calendar), "prev_year", - GTK_SIGNAL_FUNC (calendar_prev_year), - &calendar_data); - gtk_signal_connect (GTK_OBJECT (calendar), "next_year", - GTK_SIGNAL_FUNC (calendar_next_year), - &calendar_data); - - - separator = gtk_vseparator_new (); - gtk_box_pack_start (GTK_BOX (hbox), separator, FALSE, TRUE, 0); - - vbox2 = gtk_vbox_new(FALSE, DEF_PAD); - gtk_box_pack_start(GTK_BOX(hbox), vbox2, FALSE, FALSE, DEF_PAD); - - /* Build the Right frame with the flags in */ - - frame = gtk_frame_new("Flags"); - gtk_box_pack_start(GTK_BOX(vbox2), frame, TRUE, TRUE, DEF_PAD); - vbox3 = gtk_vbox_new(TRUE, DEF_PAD_SMALL); - gtk_container_add(GTK_CONTAINER(frame), vbox3); - - for (i = 0; i < 5; i++) - { - toggle = gtk_check_button_new_with_label(flags[i].label); - gtk_signal_connect (GTK_OBJECT (toggle), - "toggled", - GTK_SIGNAL_FUNC(calendar_toggle_flag), - &calendar_data); - gtk_box_pack_start (GTK_BOX (vbox3), toggle, TRUE, TRUE, 0); - calendar_data.flag_checkboxes[i]=toggle; - } - /* Build the right font-button */ - button = gtk_button_new_with_label("Font..."); - gtk_signal_connect (GTK_OBJECT (button), - "clicked", - GTK_SIGNAL_FUNC(calendar_select_font), - &calendar_data); - gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0); - - /* - * Build the Signal-event part. - */ - - frame = gtk_frame_new("Signal events"); - gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, DEF_PAD); - - vbox2 = gtk_vbox_new(TRUE, DEF_PAD_SMALL); - gtk_container_add(GTK_CONTAINER(frame), vbox2); - - hbox = gtk_hbox_new (FALSE, 3); - gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, TRUE, 0); - label = gtk_label_new ("Signal:"); - gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0); - calendar_data.last_sig = gtk_label_new (""); - gtk_box_pack_start (GTK_BOX (hbox), calendar_data.last_sig, FALSE, TRUE, 0); - - hbox = gtk_hbox_new (FALSE, 3); - gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, TRUE, 0); - label = gtk_label_new ("Previous signal:"); - gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0); - calendar_data.prev_sig = gtk_label_new (""); - gtk_box_pack_start (GTK_BOX (hbox), calendar_data.prev_sig, FALSE, TRUE, 0); - - hbox = gtk_hbox_new (FALSE, 3); - gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, TRUE, 0); - label = gtk_label_new ("Second previous signal:"); - gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0); - calendar_data.prev2_sig = gtk_label_new (""); - gtk_box_pack_start (GTK_BOX (hbox), calendar_data.prev2_sig, FALSE, TRUE, 0); - - bbox = gtk_hbutton_box_new (); - gtk_box_pack_start (GTK_BOX (vbox), bbox, FALSE, FALSE, 0); - gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END); - - button = gtk_button_new_with_label ("Close"); - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (gtk_main_quit), - NULL); - gtk_container_add (GTK_CONTAINER (bbox), button); - GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); - gtk_widget_grab_default (button); - - gtk_widget_show_all(window); -} - - -int main(int argc, - char *argv[] ) -{ - gtk_set_locale (); - gtk_init (&argc, &argv); - - create_calendar(); - - gtk_main(); - - return(0); -} -/* example-end */ -</verb></tscreen> - - - -<!-- ----------------------------------------------------------------- --> -<sect1> Color Selection -<p> -The color selection widget is, not surprisingly, a widget for -interactive selection of colors. This composite widget lets the user -select a color by manipulating RGB (Red, Green, Blue) and HSV (Hue, -Saturation, Value) triples. This is done either by adjusting single -values with sliders or entries, or by picking the desired color from a -hue-saturation wheel/value bar. Optionally, the opacity of the color -can also be set. - -The color selection widget currently emits only one signal, -"color_changed", which is emitted whenever the current color in the -widget changes, either when the user changes it or if it's set -explicitly through gtk_color_selection_set_color(). - -Lets have a look at what the color selection widget has to offer -us. The widget comes in two flavours: gtk_color_selection and -gtk_color_selection_dialog. - -<tscreen><verb> -GtkWidget *gtk_color_selection_new( void ); -</verb></tscreen> - -You'll probably not be using this constructor directly. It creates an -orphan ColorSelection widget which you'll have to parent -yourself. The ColorSelection widget inherits from the VBox -widget. - -<tscreen><verb> -GtkWidget *gtk_color_selection_dialog_new( const gchar *title ); -</verb></tscreen> - -This is the most common color selection constructor. It creates a -ColorSelectionDialog. It consists of a Frame containing a -ColorSelection widget, an HSeparator and an HBox with three buttons, -"Ok", "Cancel" and "Help". You can reach these buttons by accessing -the "ok_button", "cancel_button" and "help_button" widgets in the -ColorSelectionDialog structure, -(i.e., <tt>GTK_COLOR_SELECTION_DIALOG(colorseldialog)->ok_button</tt>)). - -<tscreen><verb> -void gtk_color_selection_set_update_policy( GtkColorSelection *colorsel, - GtkUpdateType policy ); -</verb></tscreen> - -This function sets the update policy. The default policy is -<tt/GTK_UPDATE_CONTINUOUS/ which means that the current color is -updated continuously when the user drags the sliders or presses the -mouse and drags in the hue-saturation wheel or value bar. If you -experience performance problems, you may want to set the policy to -<tt/GTK_UPDATE_DISCONTINUOUS/ or <tt/GTK_UPDATE_DELAYED/. - -<tscreen><verb> -void gtk_color_selection_set_opacity( GtkColorSelection *colorsel, - gint use_opacity ); -</verb></tscreen> - -The color selection widget supports adjusting the opacity of a color -(also known as the alpha channel). This is disabled by -default. Calling this function with use_opacity set to TRUE enables -opacity. Likewise, use_opacity set to FALSE will disable opacity. - -<tscreen><verb> -void gtk_color_selection_set_color( GtkColorSelection *colorsel, - gdouble *color ); -</verb></tscreen> - -You can set the current color explicitly by calling this function with -a pointer to an array of colors (gdouble). The length of the array -depends on whether opacity is enabled or not. Position 0 contains the -red component, 1 is green, 2 is blue and opacity is at position 3 -(only if opacity is enabled, see -gtk_color_selection_set_opacity()). All values are between 0.0 and -1.0. - -<tscreen><verb> -void gtk_color_selection_get_color( GtkColorSelection *colorsel, - gdouble *color ); -</verb></tscreen> - -When you need to query the current color, typically when you've -received a "color_changed" signal, you use this function. Color is a -pointer to the array of colors to fill in. See the -gtk_color_selection_set_color() function for the description of this -array. - -<!-- Need to do a whole section on DnD - TRG -Drag and drop -------------- - -The color sample areas (right under the hue-saturation wheel) supports -drag and drop. The type of drag and drop is "application/x-color". The -message data consists of an array of 4 (or 5 if opacity is enabled) -gdouble values, where the value at position 0 is 0.0 (opacity on) or -1.0 (opacity off) followed by the red, green and blue values at -positions 1,2 and 3 respectively. If opacity is enabled, the opacity -is passed in the value at position 4. ---> - -Here's a simple example demonstrating the use of the -ColorSelectionDialog. The program displays a window containing a -drawing area. Clicking on it opens a color selection dialog, and -changing the color in the color selection dialog changes the -background color. - -<tscreen><verb> -/* example-start colorsel colorsel.c */ - -#include <glib.h> -#include <gdk/gdk.h> -#include <gtk/gtk.h> - -GtkWidget *colorseldlg = NULL; -GtkWidget *drawingarea = NULL; - -/* Color changed handler */ - -void color_changed_cb( GtkWidget *widget, - GtkColorSelection *colorsel ) -{ - gdouble color[3]; - GdkColor gdk_color; - GdkColormap *colormap; - - /* Get drawingarea colormap */ - - colormap = gdk_window_get_colormap (drawingarea->window); - - /* Get current color */ - - gtk_color_selection_get_color (colorsel,color); - - /* Fit to a unsigned 16 bit integer (0..65535) and - * insert into the GdkColor structure */ - - gdk_color.red = (guint16)(color[0]*65535.0); - gdk_color.green = (guint16)(color[1]*65535.0); - gdk_color.blue = (guint16)(color[2]*65535.0); - - /* Allocate color */ - - gdk_color_alloc (colormap, &gdk_color); - - /* Set window background color */ - - gdk_window_set_background (drawingarea->window, &gdk_color); - - /* Clear window */ - - gdk_window_clear (drawingarea->window); -} - -/* Drawingarea event handler */ - -gint area_event( GtkWidget *widget, - GdkEvent *event, - gpointer client_data ) -{ - gint handled = FALSE; - GtkWidget *colorsel; - - /* Check if we've received a button pressed event */ - - if (event->type == GDK_BUTTON_PRESS && colorseldlg == NULL) - { - /* Yes, we have an event and there's no colorseldlg yet! */ - - handled = TRUE; - - /* Create color selection dialog */ - - colorseldlg = gtk_color_selection_dialog_new("Select background color"); - - /* Get the ColorSelection widget */ - - colorsel = GTK_COLOR_SELECTION_DIALOG(colorseldlg)->colorsel; - - /* Connect to the "color_changed" signal, set the client-data - * to the colorsel widget */ - - gtk_signal_connect(GTK_OBJECT(colorsel), "color_changed", - (GtkSignalFunc)color_changed_cb, (gpointer)colorsel); - - /* Show the dialog */ - - gtk_widget_show(colorseldlg); - } - - return handled; -} - -/* Close down and exit handler */ - -gint destroy_window( GtkWidget *widget, - GdkEvent *event, - gpointer client_data ) -{ - gtk_main_quit (); - return(TRUE); -} - -/* Main */ - -gint main( gint argc, - gchar *argv[] ) -{ - GtkWidget *window; - - /* Initialize the toolkit, remove gtk-related commandline stuff */ - - gtk_init (&argc,&argv); - - /* Create toplevel window, set title and policies */ - - 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); - - /* Attach to the "delete" and "destroy" events so we can exit */ - - gtk_signal_connect (GTK_OBJECT(window), "delete_event", - (GtkSignalFunc)destroy_window, (gpointer)window); - - /* Create drawingarea, set size and catch button events */ - - 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); - - /* Add drawingarea to window, then show them both */ - - gtk_container_add (GTK_CONTAINER(window), drawingarea); - - gtk_widget_show (drawingarea); - gtk_widget_show (window); - - /* Enter the gtk main loop (this never returns) */ - - gtk_main (); - - /* Satisfy grumpy compilers */ - - return(0); -} -/* example-end */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1> File Selections -<p> -The file selection widget is a quick and simple way to display a File -dialog box. It comes complete with Ok, Cancel, and Help buttons, a -great way to cut down on programming time. - -To create a new file selection box use: - -<tscreen><verb> -GtkWidget *gtk_file_selection_new( gchar *title ); -</verb></tscreen> - -To set the filename, for example to bring up a specific directory, or -give a default filename, use this function: - -<tscreen><verb> -void gtk_file_selection_set_filename( GtkFileSelection *filesel, - gchar *filename ); -</verb></tscreen> - -To grab the text that the user has entered or clicked on, use this -function: - -<tscreen><verb> -gchar *gtk_file_selection_get_filename( GtkFileSelection *filesel ); -</verb></tscreen> - -There are also pointers to the widgets contained within the file -selection widget. These are: - -<tscreen><verb> - dir_list - file_list - selection_entry - selection_text - main_vbox - ok_button - cancel_button - help_button -</verb></tscreen> - -Most likely you will want to use the ok_button, cancel_button, and -help_button pointers in signaling their use. - -Included here is an example stolen from testgtk.c, modified to run on -its own. As you will see, there is nothing much to creating a file -selection widget. While in this example the Help button appears on the -screen, it does nothing as there is not a signal attached to it. - -<tscreen><verb> -/* example-start filesel filesel.c */ - -#include <gtk/gtk.h> - -/* Get the selected filename and print it to the console */ -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); - - /* Create a new file selection widget */ - filew = gtk_file_selection_new ("File selection"); - - gtk_signal_connect (GTK_OBJECT (filew), "destroy", - (GtkSignalFunc) destroy, &filew); - /* Connect the ok_button to file_ok_sel function */ - gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (filew)->ok_button), - "clicked", (GtkSignalFunc) file_ok_sel, filew ); - - /* Connect the cancel_button to destroy the widget */ - gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION - (filew)->cancel_button), - "clicked", (GtkSignalFunc) gtk_widget_destroy, - GTK_OBJECT (filew)); - - /* Lets set the filename, as if this were a save dialog, and we are giving - a default filename */ - gtk_file_selection_set_filename (GTK_FILE_SELECTION(filew), - "penguin.png"); - - gtk_widget_show(filew); - gtk_main (); - return 0; -} -/* example-end */ -</verb></tscreen> - -<!-- ***************************************************************** --> -<sect> Container Widgets -<!-- ***************************************************************** --> - -<!-- ----------------------------------------------------------------- --> -<sect1>The EventBox <label id="sec_EventBox"> -<p> -Some GTK widgets don't have associated X windows, so they just draw on -their parents. Because of this, they cannot receive events and if they -are incorrectly sized, they don't clip so you can get messy -overwriting, etc. If you require more from these widgets, the EventBox -is for you. - -At first glance, the EventBox widget might appear to be totally -useless. It draws nothing on the screen and responds to no -events. However, it does serve a function - it provides an X window -for its child widget. This is important as many GTK widgets do not -have an associated X window. Not having an X window saves memory and -improves performance, but also has some drawbacks. A widget without an -X window cannot receive events, and does not perform any clipping on -its contents. Although the name <em/EventBox/ emphasizes the -event-handling function, the widget can also be used for clipping. -(and more, see the example below). - -To create a new EventBox widget, use: - -<tscreen><verb> -GtkWidget *gtk_event_box_new( void ); -</verb></tscreen> - -A child widget can then be added to this EventBox: - -<tscreen><verb> - gtk_container_add( GTK_CONTAINER(event_box), child_widget ); -</verb></tscreen> - -The following example demonstrates both uses of an EventBox - a label -is created that is clipped to a small box, and set up so that a -mouse-click on the label causes the program to exit. Resizing the -window reveals varying amounts of the label. - -<tscreen><verb> -/* example-start eventbox eventbox.c */ - -#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_set_border_width (GTK_CONTAINER (window), 10); - - /* Create an EventBox and add it to our toplevel window */ - - event_box = gtk_event_box_new (); - gtk_container_add (GTK_CONTAINER(window), event_box); - gtk_widget_show (event_box); - - /* Create a long label */ - - label = gtk_label_new ("Click here to quit, quit, quit, quit, quit"); - gtk_container_add (GTK_CONTAINER (event_box), label); - gtk_widget_show (label); - - /* Clip it short. */ - gtk_widget_set_usize (label, 110, 20); - - /* And bind an action to it */ - 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); - - /* Yet one more thing you need an X window for ... */ - - 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); -} -/* example-end */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>The Alignment widget <label id="sec_Alignment"> -<p> -The alignment widget allows you to place a widget within its window at -a position and size relative to the size of the Alignment widget -itself. For example, it can be very useful for centering a widget -within the window. - -There are only two functions associated with the Alignment widget: - -<tscreen><verb> -GtkWidget* gtk_alignment_new( gfloat xalign, - gfloat yalign, - gfloat xscale, - gfloat yscale ); - -void gtk_alignment_set( GtkAlignment *alignment, - gfloat xalign, - gfloat yalign, - gfloat xscale, - gfloat yscale ); -</verb></tscreen> - -The first function creates a new Alignment widget with the specified -parameters. The second function allows the alignment paramters of an -exisiting Alignment widget to be altered. - -All four alignment parameters are floating point numbers which can -range from 0.0 to 1.0. The <tt/xalign/ and <tt/yalign/ arguments -affect the position of the widget placed within the Alignment -widget. The <tt/xscale/ and <tt/yscale/ arguments affect the amount of -space allocated to the widget. - -A child widget can be added to this Alignment widget using: - -<tscreen><verb> - gtk_container_add( GTK_CONTAINER(alignment), child_widget ); -</verb></tscreen> - -For an example of using an Alignment widget, refer to the example for -the <ref id="sec_ProgressBar" name="Progress Bar"> widget. - -<!-- ----------------------------------------------------------------- --> -<sect1> Fixed Container -<p> -The Fixed container allows you to place widgets at a fixed position -within its window, relative to its upper left hand corner. The -position of the widgets can be changed dynamically. - -There are only three functions associated with the fixed widget: - -<tscreen><verb> -GtkWidget* gtk_fixed_new( void ); - -void gtk_fixed_put( GtkFixed *fixed, - GtkWidget *widget, - gint16 x, - gint16 y ); - -void gtk_fixed_move( GtkFixed *fixed, - GtkWidget *widget, - gint16 x, - gint16 y ); -</verb></tscreen> - -The function <tt/gtk_fixed_new/ allows you to create a new Fixed -container. - -<tt/gtk_fixed_put/ places <tt/widget/ in the container <tt/fixed/ at -the position specified by <tt/x/ and <tt/y/. - -<tt/gtk_fixed_move/ allows the specified widget to be moved to a new -position. - -The following example illustrates how to use the Fixed Container. - -<tscreen><verb> -/* example-start fixed fixed.c */ - -#include <gtk/gtk.h> - -/* I'm going to be lazy and use some global variables to - * store the position of the widget within the fixed - * container */ -gint x=50; -gint y=50; - -/* This callback function moves the button to a new position - * in the Fixed container. */ -void move_button( GtkWidget *widget, - GtkWidget *fixed ) -{ - x = (x+30)%300; - y = (y+50)%300; - gtk_fixed_move( GTK_FIXED(fixed), widget, x, y); -} - -int main( int argc, - char *argv[] ) -{ - /* GtkWidget is the storage type for widgets */ - GtkWidget *window; - GtkWidget *fixed; - GtkWidget *button; - gint i; - - /* Initialise GTK */ - gtk_init(&argc, &argv); - - /* Create a new window */ - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_title(GTK_WINDOW(window), "Fixed Container"); - - /* Here we connect the "destroy" event to a signal handler */ - gtk_signal_connect (GTK_OBJECT (window), "destroy", - GTK_SIGNAL_FUNC (gtk_main_quit), NULL); - - /* Sets the border width of the window. */ - gtk_container_set_border_width (GTK_CONTAINER (window), 10); - - /* Create a Fixed Container */ - fixed = gtk_fixed_new(); - gtk_container_add(GTK_CONTAINER(window), fixed); - gtk_widget_show(fixed); - - for (i = 1 ; i <= 3 ; i++) { - /* Creates a new button with the label "Press me" */ - button = gtk_button_new_with_label ("Press me"); - - /* When the button receives the "clicked" signal, it will call the - * function move_button() passing it the Fixed Container as its - * argument. */ - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (move_button), fixed); - - /* This packs the button into the fixed containers window. */ - gtk_fixed_put (GTK_FIXED (fixed), button, i*50, i*50); - - /* The final step is to display this newly created widget. */ - gtk_widget_show (button); - } - - /* Display the window */ - gtk_widget_show (window); - - /* Enter the event loop */ - gtk_main (); - - return(0); -} -/* example-end */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1> Layout Container -<p> -The Layout container is similar to the Fixed container except that it -implements an infinite (where infinity is less than 2^32) scrolling -area. The X window system has a limitation where windows can be at -most 32767 pixels wide or tall. The Layout container gets around this -limitation by doing some exotic stuff using window and bit gravities, -so that you can have smooth scrolling even when you have many child -widgets in your scrolling area. - -A Layout container is created using: - -<tscreen><verb> -GtkWidget *gtk_layout_new( GtkAdjustment *hadjustment, - GtkAdjustment *vadjustment ); -</verb></tscreen> - -As you can see, you can optionally specify the Adjustment objects that -the Layout widget will use for its scrolling. - -You can add and move widgets in the Layout container using the -following two functions: - -<tscreen><verb> -void gtk_layout_put( GtkLayout *layout, - GtkWidget *widget, - gint x, - gint y ); - -void gtk_layout_move( GtkLayout *layout, - GtkWidget *widget, - gint x, - gint y ); -</verb></tscreen> - -The size of the Layout container can be set using the next function: - -<tscreen><verb> -void gtk_layout_set_size( GtkLayout *layout, - guint width, - guint height ); -</verb></tscreen> - -Layout containers are one of the very few widgets in the GTK widget -set that actively repaint themselves on screen as they are changed -using the above functions (the vast majority of widgets queue -requests which are then processed when control returns to the -<tt/gtk_main()/ function). - -When you want to make a large number of changes to a Layout container, -you can use the following two functions to disable and re-enable this -repainting functionality: - -<tscreen><verb> -void gtk_layout_freeze( GtkLayout *layout ); - -void gtk_layout_thaw( GtkLayout *layout ); -</verb></tscreen> - -The final four functions for use with Layout widgets are for -manipulating the horizontal and vertical adjustment widgets: - -<tscreen><verb> -GtkAdjustment* gtk_layout_get_hadjustment( GtkLayout *layout ); - -GtkAdjustment* gtk_layout_get_vadjustment( GtkLayout *layout ); - -void gtk_layout_set_hadjustment( GtkLayout *layout, - GtkAdjustment *adjustment ); - -void gtk_layout_set_vadjustment( GtkLayout *layout, - GtkAdjustment *adjustment); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1> Frames <label id="sec_Frames"> -<p> -Frames can be used to enclose one or a group of widgets with a box -which can optionally be labelled. The position of the label and the -style of the box can be altered to suit. - -A Frame can be created with the following function: - -<tscreen><verb> -GtkWidget *gtk_frame_new( const gchar *label ); -</verb></tscreen> - -The label is by default placed in the upper left hand corner of the -frame. A value of NULL for the <tt/label/ argument will result in no -label being displayed. The text of the label can be changed using the -next function. - -<tscreen><verb> -void gtk_frame_set_label( GtkFrame *frame, - const gchar *label ); -</verb></tscreen> - -The position of the label can be changed using this function: - -<tscreen><verb> -void gtk_frame_set_label_align( GtkFrame *frame, - gfloat xalign, - gfloat yalign ); -</verb></tscreen> - -<tt/xalign/ and <tt/yalign/ take values between 0.0 and 1.0. <tt/xalign/ -indicates the position of the label along the top horizontal of the -frame. <tt/yalign/ is not currently used. The default value of xalign -is 0.0 which places the label at the left hand end of the frame. - -The next function alters the style of the box that is used to outline -the frame. - -<tscreen><verb> -void gtk_frame_set_shadow_type( GtkFrame *frame, - GtkShadowType type); -</verb></tscreen> - -The <tt/type/ argument can take one of the following values: -<tscreen><verb> - GTK_SHADOW_NONE - GTK_SHADOW_IN - GTK_SHADOW_OUT - GTK_SHADOW_ETCHED_IN (the default) - GTK_SHADOW_ETCHED_OUT -</verb></tscreen> - -The following code example illustrates the use of the Frame widget. - -<tscreen><verb> -/* example-start frame frame.c */ - -#include <gtk/gtk.h> - -int main( int argc, - char *argv[] ) -{ - /* GtkWidget is the storage type for widgets */ - GtkWidget *window; - GtkWidget *frame; - GtkWidget *button; - gint i; - - /* Initialise GTK */ - gtk_init(&argc, &argv); - - /* Create a new window */ - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_title(GTK_WINDOW(window), "Frame Example"); - - /* Here we connect the "destroy" event to a signal handler */ - gtk_signal_connect (GTK_OBJECT (window), "destroy", - GTK_SIGNAL_FUNC (gtk_main_quit), NULL); - - gtk_widget_set_usize(window, 300, 300); - /* Sets the border width of the window. */ - gtk_container_set_border_width (GTK_CONTAINER (window), 10); - - /* Create a Frame */ - frame = gtk_frame_new(NULL); - gtk_container_add(GTK_CONTAINER(window), frame); - - /* Set the frame's label */ - gtk_frame_set_label( GTK_FRAME(frame), "GTK Frame Widget" ); - - /* Align the label at the right of the frame */ - gtk_frame_set_label_align( GTK_FRAME(frame), 1.0, 0.0); - - /* Set the style of the frame */ - gtk_frame_set_shadow_type( GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT); - - gtk_widget_show(frame); - - /* Display the window */ - gtk_widget_show (window); - - /* Enter the event loop */ - gtk_main (); - - return(0); -} -/* example-end */ - -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1> Aspect Frames -<p> -The aspect frame widget is like a frame widget, except that it also -enforces the aspect ratio (that is, the ratio of the width to the -height) of the child widget to have a certain value, adding extra -space if necessary. This is useful, for instance, if you want to -preview a larger image. The size of the preview should vary when the -user resizes the window, but the aspect ratio needs to always match -the original image. - -To create a new aspect frame use: - -<tscreen><verb> -GtkWidget *gtk_aspect_frame_new( const gchar *label, - gfloat xalign, - gfloat yalign, - gfloat ratio, - gint obey_child); -</verb></tscreen> - -<tt/xalign/ and <tt/yalign/ specify alignment as with Alignment -widgets. If <tt/obey_child/ is true, the aspect ratio of a child -widget will match the aspect ratio of the ideal size it requests. -Otherwise, it is given by <tt/ratio/. - -To change the options of an existing aspect frame, you can use: - -<tscreen><verb> -void gtk_aspect_frame_set( GtkAspectFrame *aspect_frame, - gfloat xalign, - gfloat yalign, - gfloat ratio, - gint obey_child); -</verb></tscreen> - -As an example, the following program uses an AspectFrame to present a -drawing area whose aspect ratio will always be 2:1, no matter how the -user resizes the top-level window. - -<tscreen><verb> -/* example-start 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_set_border_width (GTK_CONTAINER (window), 10); - - /* Create an aspect_frame and add it to our toplevel window */ - - aspect_frame = gtk_aspect_frame_new ("2x1", /* label */ - 0.5, /* center x */ - 0.5, /* center y */ - 2, /* xsize/ysize = 2 */ - FALSE /* ignore child's aspect */); - - gtk_container_add (GTK_CONTAINER(window), aspect_frame); - gtk_widget_show (aspect_frame); - - /* Now add a child widget to the aspect frame */ - - drawing_area = gtk_drawing_area_new (); - - /* Ask for a 200x200 window, but the AspectFrame will give us a 200x100 - * window since we are forcing a 2x1 aspect ratio */ - 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; -} -/* example-end */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1> Paned Window Widgets -<p> -The paned window widgets are useful when you want to divide an area -into two parts, with the relative size of the two parts controlled by -the user. A groove is drawn between the two portions with a handle -that the user can drag to change the ratio. The division can either be -horizontal (HPaned) or vertical (VPaned). - -To create a new paned window, call one of: - -<tscreen><verb> -GtkWidget *gtk_hpaned_new (void); - -GtkWidget *gtk_vpaned_new (void); -</verb></tscreen> - -After creating the paned window widget, you need to add child widgets -to its two halves. To do this, use the functions: - -<tscreen><verb> -void gtk_paned_add1 (GtkPaned *paned, GtkWidget *child); - -void gtk_paned_add2 (GtkPaned *paned, GtkWidget *child); -</verb></tscreen> - -<tt/gtk_paned_add1()/ adds the child widget to the left or top half of -the paned window. <tt/gtk_paned_add2()/ adds the child widget to the -right or bottom half of the paned window. - -A paned widget can be changed visually using the following two -functions. - -<tscreen><verb> -void gtk_paned_set_handle_size( GtkPaned *paned, - guint16 size); - -void gtk_paned_set_gutter_size( GtkPaned *paned, - guint16 size); -</verb></tscreen> - -The first of these sets the size of the handle and the second sets the -size of the gutter that is between the two parts of the paned window. - -As an example, we will create part of the user interface of an -imaginary email program. A window is divided into two portions -vertically, with the top portion being a list of email messages and -the bottom portion the text of the email message. Most of the program -is pretty straightforward. A couple of points to note: text can't be -added to a Text widget until it is realized. This could be done by -calling <tt/gtk_widget_realize()/, but as a demonstration of an -alternate technique, we connect a handler to the "realize" signal to -add the text. Also, we need to add the <tt/GTK_SHRINK/ option to some -of the items in the table containing the text window and its -scrollbars, so that when the bottom portion is made smaller, the -correct portions shrink instead of being pushed off the bottom of the -window. - -<tscreen><verb> -/* example-start paned paned.c */ - -#include <stdio.h> -#include <gtk/gtk.h> - -/* Create the list of "messages" */ -GtkWidget *create_list( void ) -{ - - GtkWidget *scrolled_window; - GtkWidget *list; - GtkWidget *list_item; - - int i; - char buffer[16]; - - /* Create a new scrolled window, with scrollbars only if needed */ - scrolled_window = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); - - /* Create a new list and put it in the scrolled window */ - list = gtk_list_new (); - gtk_scrolled_window_add_with_viewport ( - GTK_SCROLLED_WINDOW (scrolled_window), list); - gtk_widget_show (list); - - /* Add some messages to the window */ - 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; -} - -/* Add some text to our text widget - this is a callback that is invoked -when our window is realized. We could also force our window to be -realized with gtk_widget_realize, but it would have to be part of -a hierarchy first */ - -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)); -} - -/* Create a scrolled text area that displays a "message" */ -GtkWidget *create_text( void ) -{ - GtkWidget *table; - GtkWidget *text; - GtkWidget *hscrollbar; - GtkWidget *vscrollbar; - - /* Create a table to hold the text widget and scrollbars */ - table = gtk_table_new (2, 2, FALSE); - - /* Put a text widget in the upper left hand corner. Note the use of - * GTK_SHRINK in the y direction */ - 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); - - /* Put a HScrollbar in the lower left hand corner */ - 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); - - /* And a VScrollbar in the upper right */ - 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); - - /* Add a handler to put a message in the text widget when it is realized */ - 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_set_border_width (GTK_CONTAINER (window), 10); - gtk_widget_set_usize (GTK_WIDGET(window), 450, 400); - - /* create a vpaned widget and add it to our toplevel window */ - - vpaned = gtk_vpaned_new (); - gtk_container_add (GTK_CONTAINER(window), vpaned); - gtk_paned_set_handle_size (GTK_PANED(vpaned), - 10); - gtk_paned_set_gutter_size (GTK_PANED(vpaned), - 15); - gtk_widget_show (vpaned); - - /* Now create the contents of the two halves of the window */ - - 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; -} -/* example-end */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Viewports <label id="sec_Viewports"> -<p> -It is unlikely that you will ever need to use the Viewport widget -directly. You are much more likely to use the -<ref id="sec_ScrolledWindow" name="Scrolled Window"> widget which -itself uses the Viewport. - -A viewport widget allows you to place a larger widget within it such -that you can view a part of it at a time. It uses -<ref id="sec_Adjustment" name="Adjustments"> to define the area that -is currently in view. - -A Viewport is created with the function - -<tscreen><verb> -GtkWidget *gtk_viewport_new( GtkAdjustment *hadjustment, - GtkAdjustment *vadjustment ); -</verb></tscreen> - -As you can see you can specify the horizontal and vertical Adjustments -that the widget is to use when you create the widget. It will create -its own if you pass NULL as the value of the arguments. - -You can get and set the adjustments after the widget has been created -using the following four functions: - -<tscreen><verb> -GtkAdjustment *gtk_viewport_get_hadjustment (GtkViewport *viewport ); - -GtkAdjustment *gtk_viewport_get_vadjustment (GtkViewport *viewport ); - -void gtk_viewport_set_hadjustment( GtkViewport *viewport, - GtkAdjustment *adjustment ); - -void gtk_viewport_set_vadjustment( GtkViewport *viewport, - GtkAdjustment *adjustment ); -</verb></tscreen> - -The only other viewport function is used to alter its appearance: - -<tscreen><verb> -void gtk_viewport_set_shadow_type( GtkViewport *viewport, - GtkShadowType type ); -</verb></tscreen> - -Possible values for the <tt/type/ parameter are: -<tscreen><verb> - GTK_SHADOW_NONE, - GTK_SHADOW_IN, - GTK_SHADOW_OUT, - GTK_SHADOW_ETCHED_IN, - GTK_SHADOW_ETCHED_OUT -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Scrolled Windows <label id="sec_ScrolledWindow"> -<p> -Scrolled windows are used to create a scrollable area with another -widget inside it. You may insert any type of widget into a scrolled -window, and it will be accessible regardless of the size by using the -scrollbars. - -The following function is used to create a new scrolled window. - -<tscreen><verb> -GtkWidget *gtk_scrolled_window_new( GtkAdjustment *hadjustment, - GtkAdjustment *vadjustment ); -</verb></tscreen> - -Where the first argument is the adjustment for the horizontal -direction, and the second, the adjustment for the vertical direction. -These are almost always set to NULL. - -<tscreen><verb> -void gtk_scrolled_window_set_policy( GtkScrolledWindow *scrolled_window, - GtkPolicyType hscrollbar_policy, - GtkPolicyType vscrollbar_policy ); -</verb></tscreen> - -This sets the policy to be used with respect to the scrollbars. -The first argument is the scrolled window you wish to change. The second -sets the policy for the horizontal scrollbar, and the third the policy for -the vertical scrollbar. - -The policy may be one of <tt/GTK_POLICY_AUTOMATIC/ or -<tt/GTK_POLICY_ALWAYS/. <tt/GTK_POLICY_AUTOMATIC/ will automatically -decide whether you need scrollbars, whereas <tt/GTK_POLICY_ALWAYS/ -will always leave the scrollbars there. - -You can then place your object into the scrolled window using the -following function. - -<tscreen><verb> -void gtk_scrolled_window_add_with_viewport( GtkScrolledWindow *scrolled_window, - GtkWidget *child); -</verb></tscreen> - -Here is a simple example that packs a table eith 100 toggle buttons -into a scrolled window. I've only commented on the parts that may be -new to you. - -<tscreen><verb> -/* example-start scrolledwin scrolledwin.c */ - -#include <stdio.h> -#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); - - /* Create a new dialog window for the scrolled window to be - * packed into. */ - window = gtk_dialog_new (); - gtk_signal_connect (GTK_OBJECT (window), "destroy", - (GtkSignalFunc) destroy, NULL); - gtk_window_set_title (GTK_WINDOW (window), "GtkScrolledWindow example"); - gtk_container_set_border_width (GTK_CONTAINER (window), 0); - gtk_widget_set_usize(window, 300, 300); - - /* create a new scrolled window. */ - scrolled_window = gtk_scrolled_window_new (NULL, NULL); - - gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10); - - /* the policy is one of GTK_POLICY AUTOMATIC, or GTK_POLICY_ALWAYS. - * GTK_POLICY_AUTOMATIC will automatically decide whether you need - * scrollbars, whereas GTK_POLICY_ALWAYS will always leave the scrollbars - * there. The first one is the horizontal scrollbar, the second, - * the vertical. */ - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), - GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); - /* The dialog window is created with a vbox packed into it. */ - gtk_box_pack_start (GTK_BOX (GTK_DIALOG(window)->vbox), scrolled_window, - TRUE, TRUE, 0); - gtk_widget_show (scrolled_window); - - /* create a table of 10 by 10 squares. */ - table = gtk_table_new (10, 10, FALSE); - - /* set the spacing to 10 on x and 10 on y */ - gtk_table_set_row_spacings (GTK_TABLE (table), 10); - gtk_table_set_col_spacings (GTK_TABLE (table), 10); - - /* pack the table into the scrolled window */ - gtk_scrolled_window_add_with_viewport ( - GTK_SCROLLED_WINDOW (scrolled_window), table); - gtk_widget_show (table); - - /* this simply creates a grid of toggle buttons on the table - * to demonstrate the scrolled window. */ - 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); - } - - /* Add a "close" button to the bottom of the dialog */ - button = gtk_button_new_with_label ("close"); - gtk_signal_connect_object (GTK_OBJECT (button), "clicked", - (GtkSignalFunc) gtk_widget_destroy, - GTK_OBJECT (window)); - - /* this makes it so the button is the default. */ - - GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); - gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button, TRUE, TRUE, 0); - - /* This grabs this button to be the default button. Simply hitting - * the "Enter" key will cause this button to activate. */ - gtk_widget_grab_default (button); - gtk_widget_show (button); - - gtk_widget_show (window); - - gtk_main(); - - return(0); -} -/* example-end */ -</verb></tscreen> - -Try playing with resizing the window. You'll notice how the scrollbars -react. You may also wish to use the gtk_widget_set_usize() call to set -the default size of the window or other widgets. - -<!-- ----------------------------------------------------------------- --> -<sect1>Button Boxes -<p> -Button Boxes are a convenient way to quickly layout a group of -buttons. They come in both horizontal and vertical flavours. You -create a new Button Box with one of the following calls, which create -a horizontal or vertical box, respectively: - -<tscreen><verb> -GtkWidget *gtk_hbutton_box_new( void ); - -GtkWidget *gtk_vbutton_box_new( void ); -</verb></tscreen> - -The only attributes pertaining to button boxes affect how the buttons -are laid out. You can change the spacing between the buttons with: - -<tscreen><verb> -void gtk_hbutton_box_set_spacing_default( gint spacing ); - -void gtk_vbutton_box_set_spacing_default( gint spacing ); -</verb></tscreen> - -Similarly, the current spacing values can be queried using: - -<tscreen><verb> -gint gtk_hbutton_box_get_spacing_default( void ); - -gint gtk_vbutton_box_get_spacing_default( void ); -</verb></tscreen> - -The second attribute that we can access affects the layout of the -buttons within the box. It is set using one of: - -<tscreen><verb> -void gtk_hbutton_box_set_layout_default( GtkButtonBoxStyle layout ); - -void gtk_vbutton_box_set_layout_default( GtkButtonBoxStyle layout ); -</verb></tscreen> - -The <tt/layout/ argument can take one of the following values: - -<tscreen><verb> - GTK_BUTTONBOX_DEFAULT_STYLE - GTK_BUTTONBOX_SPREAD - GTK_BUTTONBOX_EDGE - GTK_BUTTONBOX_START - GTK_BUTTONBOX_END -</verb></tscreen> - -The current layout setting can be retrieved using: - -<tscreen><verb> -GtkButtonBoxStyle gtk_hbutton_box_get_layout_default( void ); - -GtkButtonBoxStyle gtk_vbutton_box_get_layout_default( void ); -</verb></tscreen> - -Buttons are added to a Button Box using the usual function: - -<tscreen><verb> - gtk_container_add( GTK_CONTAINER(button_box), child_widget ); -</verb></tscreen> - -Here's an example that illustrates all the different layout settings -for Button Boxes. - -<tscreen><verb> -/* example-start buttonbox buttonbox.c */ - -#include <gtk/gtk.h> - -/* Create a Button Box with the specified parameters */ -GtkWidget *create_bbox( gint horizontal, - char *title, - gint spacing, - gint child_w, - gint child_h, - gint layout ) -{ - GtkWidget *frame; - GtkWidget *bbox; - GtkWidget *button; - - frame = gtk_frame_new (title); - - if (horizontal) - bbox = gtk_hbutton_box_new (); - else - bbox = gtk_vbutton_box_new (); - - gtk_container_set_border_width (GTK_CONTAINER (bbox), 5); - gtk_container_add (GTK_CONTAINER (frame), bbox); - - /* Set the appearance of the Button Box */ - gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), layout); - gtk_button_box_set_spacing (GTK_BUTTON_BOX (bbox), spacing); - gtk_button_box_set_child_size (GTK_BUTTON_BOX (bbox), child_w, child_h); - - button = gtk_button_new_with_label ("OK"); - gtk_container_add (GTK_CONTAINER (bbox), button); - - button = gtk_button_new_with_label ("Cancel"); - gtk_container_add (GTK_CONTAINER (bbox), button); - - button = gtk_button_new_with_label ("Help"); - gtk_container_add (GTK_CONTAINER (bbox), button); - - return(frame); -} - -int main( int argc, - char *argv[] ) -{ - static GtkWidget* window = NULL; - GtkWidget *main_vbox; - GtkWidget *vbox; - GtkWidget *hbox; - GtkWidget *frame_horz; - GtkWidget *frame_vert; - - /* Initialize GTK */ - gtk_init( &argc, &argv ); - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_title (GTK_WINDOW (window), "Button Boxes"); - - gtk_signal_connect (GTK_OBJECT (window), "destroy", - GTK_SIGNAL_FUNC(gtk_main_quit), - NULL); - - gtk_container_set_border_width (GTK_CONTAINER (window), 10); - - main_vbox = gtk_vbox_new (FALSE, 0); - gtk_container_add (GTK_CONTAINER (window), main_vbox); - - frame_horz = gtk_frame_new ("Horizontal Button Boxes"); - gtk_box_pack_start (GTK_BOX (main_vbox), frame_horz, TRUE, TRUE, 10); - - vbox = gtk_vbox_new (FALSE, 0); - gtk_container_set_border_width (GTK_CONTAINER (vbox), 10); - gtk_container_add (GTK_CONTAINER (frame_horz), vbox); - - gtk_box_pack_start (GTK_BOX (vbox), - create_bbox (TRUE, "Spread (spacing 40)", 40, 85, 20, GTK_BUTTONBOX_SPREAD), - TRUE, TRUE, 0); - - gtk_box_pack_start (GTK_BOX (vbox), - create_bbox (TRUE, "Edge (spacing 30)", 30, 85, 20, GTK_BUTTONBOX_EDGE), - TRUE, TRUE, 5); - - gtk_box_pack_start (GTK_BOX (vbox), - create_bbox (TRUE, "Start (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_START), - TRUE, TRUE, 5); - - gtk_box_pack_start (GTK_BOX (vbox), - create_bbox (TRUE, "End (spacing 10)", 10, 85, 20, GTK_BUTTONBOX_END), - TRUE, TRUE, 5); - - frame_vert = gtk_frame_new ("Vertical Button Boxes"); - gtk_box_pack_start (GTK_BOX (main_vbox), frame_vert, TRUE, TRUE, 10); - - hbox = gtk_hbox_new (FALSE, 0); - gtk_container_set_border_width (GTK_CONTAINER (hbox), 10); - gtk_container_add (GTK_CONTAINER (frame_vert), hbox); - - gtk_box_pack_start (GTK_BOX (hbox), - create_bbox (FALSE, "Spread (spacing 5)", 5, 85, 20, GTK_BUTTONBOX_SPREAD), - TRUE, TRUE, 0); - - gtk_box_pack_start (GTK_BOX (hbox), - create_bbox (FALSE, "Edge (spacing 30)", 30, 85, 20, GTK_BUTTONBOX_EDGE), - TRUE, TRUE, 5); - - gtk_box_pack_start (GTK_BOX (hbox), - create_bbox (FALSE, "Start (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_START), - TRUE, TRUE, 5); - - gtk_box_pack_start (GTK_BOX (hbox), - create_bbox (FALSE, "End (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_END), - TRUE, TRUE, 5); - - gtk_widget_show_all (window); - - /* Enter the event loop */ - gtk_main (); - - return(0); -} -/* example-end */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Toolbar -<p> -Toolbars are usually used to group some number of widgets in order to -simplify customization of their look and layout. Typically a toolbar -consists of buttons with icons, labels and tooltips, but any other -widget can also be put inside a toolbar. Finally, items can be -arranged horizontally or vertically and buttons can be displayed with -icons, labels, or both. - -Creating a toolbar is (as one may already suspect) done with the -following function: - -<tscreen><verb> -GtkWidget *gtk_toolbar_new( GtkOrientation orientation, - GtkToolbarStyle style ); -</verb></tscreen> - -where orientation may be one of: - -<tscreen><verb> - GTK_ORIENTATION_HORIZONTAL - GTK_ORIENTATION_VERTICAL -</verb></tscreen> - -and style one of: - -<tscreen><verb> - GTK_TOOLBAR_TEXT - GTK_TOOLBAR_ICONS - GTK_TOOLBAR_BOTH -</verb></tscreen> - -The style applies to all the buttons created with the `item' functions -(not to buttons inserted into toolbar as separate widgets). - -After creating a toolbar one can append, prepend and insert items -(that means simple text strings) or elements (that means any widget -types) into the toolbar. To describe an item we need a label text, a -tooltip text, a private tooltip text, an icon for the button and a -callback function for it. For example, to append or prepend an item -you may use the following functions: - -<tscreen><verb> -GtkWidget *gtk_toolbar_append_item( GtkToolbar *toolbar, - const char *text, - const char *tooltip_text, - const char *tooltip_private_text, - GtkWidget *icon, - GtkSignalFunc callback, - gpointer user_data ); - -GtkWidget *gtk_toolbar_prepend_item( GtkToolbar *toolbar, - const char *text, - const char *tooltip_text, - const char *tooltip_private_text, - GtkWidget *icon, - GtkSignalFunc callback, - gpointer user_data ); -</verb></tscreen> - -If you want to use gtk_toolbar_insert_item, the only additional -parameter which must be specified is the position in which the item -should be inserted, thus: - -<tscreen><verb> -GtkWidget *gtk_toolbar_insert_item( GtkToolbar *toolbar, - const char *text, - const char *tooltip_text, - const char *tooltip_private_text, - GtkWidget *icon, - GtkSignalFunc callback, - gpointer user_data, - gint position ); -</verb></tscreen> - -To simplify adding spaces between toolbar items, you may use the -following functions: - -<tscreen><verb> -void gtk_toolbar_append_space( GtkToolbar *toolbar ); - -void gtk_toolbar_prepend_space( GtkToolbar *toolbar ); - -void gtk_toolbar_insert_space( GtkToolbar *toolbar, - gint position ); - -</verb></tscreen> - -While the size of the added space can be set globally for a -whole toolbar with the function: - -<tscreen><verb> -void gtk_toolbar_set_space_size( GtkToolbar *toolbar, - gint space_size) ; -</verb></tscreen> - -If it's required, the orientation of a toolbar and its style can be -changed "on the fly" using the following functions: - -<tscreen><verb> -void gtk_toolbar_set_orientation( GtkToolbar *toolbar, - GtkOrientation orientation ); - -void gtk_toolbar_set_style( GtkToolbar *toolbar, - GtkToolbarStyle style ); - -void gtk_toolbar_set_tooltips( GtkToolbar *toolbar, - gint enable ); -</verb></tscreen> - -Where <tt/orientation/ is one of <tt/GTK_ORIENTATION_HORIZONTAL/ or -<tt/GTK_ORIENTATION_VERTICAL/. The <tt/style/ is used to set -appearance of the toolbar items by using one of -<tt/GTK_TOOLBAR_ICONS/, <tt/GTK_TOOLBAR_TEXT/, or -<tt/GTK_TOOLBAR_BOTH/. - -To show some other things that can be done with a toolbar, let's take -the following program (we'll interrupt the listing with some -additional explanations): - -<tscreen><verb> -#include <gtk/gtk.h> - -#include "gtk.xpm" - -/* This function is connected to the Close button or - * closing the window from the WM */ -gint delete_event (GtkWidget *widget, GdkEvent *event, gpointer data) -{ - gtk_main_quit (); - return(FALSE); -} -</verb></tscreen> - -The above beginning seems for sure familiar to you if it's not your first -GTK program. There is one additional thing though, we include a nice XPM -picture to serve as an icon for all of the buttons. - -<tscreen><verb> -GtkWidget* close_button; /* This button will emit signal to close - * application */ -GtkWidget* tooltips_button; /* to enable/disable tooltips */ -GtkWidget* text_button, - * icon_button, - * both_button; /* radio buttons for toolbar style */ -GtkWidget* entry; /* a text entry to show packing any widget into - * toolbar */ -</verb></tscreen> - -In fact not all of the above widgets are needed here, but to make things -clearer I put them all together. - -<tscreen><verb> -/* that's easy... when one of the buttons is toggled, we just - * check which one is active and set the style of the toolbar - * accordingly - * ATTENTION: our toolbar is passed as data to callback ! */ -void radio_event (GtkWidget *widget, gpointer data) -{ - if (GTK_TOGGLE_BUTTON (text_button)->active) - gtk_toolbar_set_style(GTK_TOOLBAR ( data ), GTK_TOOLBAR_TEXT); - else if (GTK_TOGGLE_BUTTON (icon_button)->active) - gtk_toolbar_set_style(GTK_TOOLBAR ( data ), GTK_TOOLBAR_ICONS); - else if (GTK_TOGGLE_BUTTON (both_button)->active) - gtk_toolbar_set_style(GTK_TOOLBAR ( data ), GTK_TOOLBAR_BOTH); -} - -/* even easier, just check given toggle button and enable/disable - * tooltips */ -void toggle_event (GtkWidget *widget, gpointer data) -{ - gtk_toolbar_set_tooltips (GTK_TOOLBAR ( data ), - GTK_TOGGLE_BUTTON (widget)->active ); -} -</verb></tscreen> - -The above are just two callback functions that will be called when -one of the buttons on a toolbar is pressed. You should already be -familiar with things like this if you've already used toggle buttons (and -radio buttons). - -<tscreen><verb> -int main (int argc, char *argv[]) -{ - /* Here is our main window (a dialog) and a handle for the handlebox */ - GtkWidget* dialog; - GtkWidget* handlebox; - - /* Ok, we need a toolbar, an icon with a mask (one for all of - the buttons) and an icon widget to put this icon in (but - we'll create a separate widget for each button) */ - GtkWidget * toolbar; - GdkPixmap * icon; - GdkBitmap * mask; - GtkWidget * iconw; - - /* this is called in all GTK application. */ - gtk_init (&argc, &argv); - - /* create a new window with a given title, and nice size */ - dialog = gtk_dialog_new (); - gtk_window_set_title ( GTK_WINDOW ( dialog ) , "GTKToolbar Tutorial"); - gtk_widget_set_usize( GTK_WIDGET ( dialog ) , 600 , 300 ); - GTK_WINDOW ( dialog ) ->allow_shrink = TRUE; - - /* typically we quit if someone tries to close us */ - gtk_signal_connect ( GTK_OBJECT ( dialog ), "delete_event", - GTK_SIGNAL_FUNC ( delete_event ), NULL); - - /* we need to realize the window because we use pixmaps for - * items on the toolbar in the context of it */ - gtk_widget_realize ( dialog ); - - /* to make it nice we'll put the toolbar into the handle box, - * so that it can be detached from the main window */ - handlebox = gtk_handle_box_new (); - gtk_box_pack_start ( GTK_BOX ( GTK_DIALOG(dialog)->vbox ), - handlebox, FALSE, FALSE, 5 ); -</verb></tscreen> - -The above should be similar to any other GTK application. Just -initialization of GTK, creating the window, etc. There is only one -thing that probably needs some explanation: a handle box. A handle box -is just another box that can be used to pack widgets in to. The -difference between it and typical boxes is that it can be detached -from a parent window (or, in fact, the handle box remains in the -parent, but it is reduced to a very small rectangle, while all of its -contents are reparented to a new freely floating window). It is -usually nice to have a detachable toolbar, so these two widgets occur -together quite often. - -<tscreen><verb> - /* toolbar will be horizontal, with both icons and text, and - * with 5pxl spaces between items and finally, - * we'll also put it into our handlebox */ - toolbar = gtk_toolbar_new ( GTK_ORIENTATION_HORIZONTAL, - GTK_TOOLBAR_BOTH ); - gtk_container_set_border_width ( GTK_CONTAINER ( toolbar ) , 5 ); - gtk_toolbar_set_space_size ( GTK_TOOLBAR ( toolbar ), 5 ); - gtk_container_add ( GTK_CONTAINER ( handlebox ) , toolbar ); - - /* now we create icon with mask: we'll reuse it to create - * icon widgets for toolbar items */ - icon = gdk_pixmap_create_from_xpm_d ( dialog->window, &mask, - &dialog->style->white, gtk_xpm ); -</verb></tscreen> - -Well, what we do above is just a straightforward initialization of -the toolbar widget and creation of a GDK pixmap with its mask. If you -want to know something more about using pixmaps, refer to GDK -documentation or to the <ref id="sec_Pixmaps" name="Pixmaps"> section -earlier in this tutorial. - -<tscreen><verb> - /* our first item is <close> button */ - iconw = gtk_pixmap_new ( icon, mask ); /* icon widget */ - close_button = - gtk_toolbar_append_item ( GTK_TOOLBAR (toolbar), /* our toolbar */ - "Close", /* button label */ - "Closes this app", /* this button's tooltip */ - "Private", /* tooltip private info */ - iconw, /* icon widget */ - GTK_SIGNAL_FUNC (delete_event), /* a signal */ - NULL ); - gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) ); /* space after item */ -</verb></tscreen> - -In the above code you see the simplest case: adding a button to -toolbar. Just before appending a new item, we have to construct a -pixmap widget to serve as an icon for this item; this step will have -to be repeated for each new item. Just after the item we also add a -space, so the following items will not touch each other. As you see -gtk_toolbar_append_item returns a pointer to our newly created button -widget, so that we can work with it in the normal way. - -<tscreen><verb> - /* now, let's make our radio buttons group... */ - iconw = gtk_pixmap_new ( icon, mask ); - icon_button = gtk_toolbar_append_element( - GTK_TOOLBAR(toolbar), - GTK_TOOLBAR_CHILD_RADIOBUTTON, /* a type of element */ - NULL, /* pointer to widget */ - "Icon", /* label */ - "Only icons in toolbar", /* tooltip */ - "Private", /* tooltip private string */ - iconw, /* icon */ - GTK_SIGNAL_FUNC (radio_event), /* signal */ - toolbar); /* data for signal */ - gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) ); -</verb></tscreen> - -Here we begin creating a radio buttons group. To do this we use -gtk_toolbar_append_element. In fact, using this function one can also -+add simple items or even spaces (type = <tt/GTK_TOOLBAR_CHILD_SPACE/ -or +<tt/GTK_TOOLBAR_CHILD_BUTTON/). In the above case we start -creating a radio group. In creating other radio buttons for this group -a pointer to the previous button in the group is required, so that a -list of buttons can be easily constructed (see the section on <ref -id="sec_Radio_Buttons" name="Radio Buttons"> earlier in this -tutorial). - -<tscreen><verb> - /* following radio buttons refer to previous ones */ - iconw = gtk_pixmap_new ( icon, mask ); - text_button = - gtk_toolbar_append_element(GTK_TOOLBAR(toolbar), - GTK_TOOLBAR_CHILD_RADIOBUTTON, - icon_button, - "Text", - "Only texts in toolbar", - "Private", - iconw, - GTK_SIGNAL_FUNC (radio_event), - toolbar); - gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) ); - - iconw = gtk_pixmap_new ( icon, mask ); - both_button = - gtk_toolbar_append_element(GTK_TOOLBAR(toolbar), - GTK_TOOLBAR_CHILD_RADIOBUTTON, - text_button, - "Both", - "Icons and text in toolbar", - "Private", - iconw, - GTK_SIGNAL_FUNC (radio_event), - toolbar); - gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) ); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(both_button),TRUE); -</verb></tscreen> - -In the end we have to set the state of one of the buttons manually -(otherwise they all stay in active state, preventing us from switching -between them). - -<tscreen><verb> - /* here we have just a simple toggle button */ - iconw = gtk_pixmap_new ( icon, mask ); - tooltips_button = - gtk_toolbar_append_element(GTK_TOOLBAR(toolbar), - GTK_TOOLBAR_CHILD_TOGGLEBUTTON, - NULL, - "Tooltips", - "Toolbar with or without tips", - "Private", - iconw, - GTK_SIGNAL_FUNC (toggle_event), - toolbar); - gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) ); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tooltips_button),TRUE); -</verb></tscreen> - -A toggle button can be created in the obvious way (if one knows how to create -radio buttons already). - -<tscreen><verb> - /* to pack a widget into toolbar, we only have to - * create it and append it with an appropriate tooltip */ - entry = gtk_entry_new (); - gtk_toolbar_append_widget( GTK_TOOLBAR (toolbar), - entry, - "This is just an entry", - "Private" ); - - /* well, it isn't created within thetoolbar, so we must still show it */ - gtk_widget_show ( entry ); -</verb></tscreen> - -As you see, adding any kind of widget to a toolbar is simple. The -one thing you have to remember is that this widget must be shown manually -(contrary to other items which will be shown together with the toolbar). - -<tscreen><verb> - /* that's it ! let's show everything. */ - gtk_widget_show ( toolbar ); - gtk_widget_show (handlebox); - gtk_widget_show ( dialog ); - - /* rest in gtk_main and wait for the fun to begin! */ - gtk_main (); - - return 0; -} -</verb></tscreen> - -So, here we are at the end of toolbar tutorial. Of course, to appreciate -it in full you need also this nice XPM icon, so here it is: - -<tscreen><verb> -/* XPM */ -static char * gtk_xpm[] = { -"32 39 5 1", -". c none", -"+ c black", -"@ c #3070E0", -"# c #F05050", -"$ c #35E035", -"................+...............", -"..............+++++.............", -"............+++++@@++...........", -"..........+++++@@@@@@++.........", -"........++++@@@@@@@@@@++........", -"......++++@@++++++++@@@++.......", -".....+++@@@+++++++++++@@@++.....", -"...+++@@@@+++@@@@@@++++@@@@+....", -"..+++@@@@+++@@@@@@@@+++@@@@@++..", -".++@@@@@@+++@@@@@@@@@@@@@@@@@@++", -".+#+@@@@@@++@@@@+++@@@@@@@@@@@@+", -".+##++@@@@+++@@@+++++@@@@@@@@$@.", -".+###++@@@@+++@@@+++@@@@@++$$$@.", -".+####+++@@@+++++++@@@@@+@$$$$@.", -".+#####+++@@@@+++@@@@++@$$$$$$+.", -".+######++++@@@@@@@++@$$$$$$$$+.", -".+#######+##+@@@@+++$$$$$$@@$$+.", -".+###+++##+##+@@++@$$$$$$++$$$+.", -".+###++++##+##+@@$$$$$$$@+@$$@+.", -".+###++++++#+++@$$@+@$$@++$$$@+.", -".+####+++++++#++$$@+@$$++$$$$+..", -".++####++++++#++$$@+@$++@$$$$+..", -".+#####+++++##++$$++@+++$$$$$+..", -".++####+++##+#++$$+++++@$$$$$+..", -".++####+++####++$$++++++@$$$@+..", -".+#####++#####++$$+++@++++@$@+..", -".+#####++#####++$$++@$$@+++$@@..", -".++####++#####++$$++$$$$$+@$@++.", -".++####++#####++$$++$$$$$$$$+++.", -".+++####+#####++$$++$$$$$$$@+++.", -"..+++#########+@$$+@$$$$$$+++...", -"...+++########+@$$$$$$$$@+++....", -".....+++######+@$$$$$$$+++......", -"......+++#####+@$$$$$@++........", -".......+++####+@$$$$+++.........", -".........++###+$$$@++...........", -"..........++##+$@+++............", -"...........+++++++..............", -".............++++..............."}; -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1> Notebooks -<p> -The NoteBook Widget is a collection of "pages" that overlap each -other, each page contains different information with only one page -visible at a time. This widget has become more common lately in GUI -programming, and it is a good way to show blocks of similar -information that warrant separation in their display. - -The first function call you will need to know, as you can probably -guess by now, is used to create a new notebook widget. - -<tscreen><verb> -GtkWidget *gtk_notebook_new( void ); -</verb></tscreen> - -Once the notebook has been created, there are a number of functions -that operate on the notebook widget. Let's look at them individually. - -The first one we will look at is how to position the page indicators. -These page indicators or "tabs" as they are referred to, can be -positioned in four ways: top, bottom, left, or right. - -<tscreen><verb> -void gtk_notebook_set_tab_pos( GtkNotebook *notebook, - GtkPositionType pos ); -</verb></tscreen> - -GtkPositionType will be one of the following, which are pretty self -explanatory: -<tscreen><verb> - GTK_POS_LEFT - GTK_POS_RIGHT - GTK_POS_TOP - GTK_POS_BOTTOM -</verb></tscreen> - -<tt/GTK_POS_TOP/ is the default. - -Next we will look at how to add pages to the notebook. There are three -ways to add pages to the NoteBook. Let's look at the first two -together as they are quite similar. - -<tscreen><verb> -void gtk_notebook_append_page( GtkNotebook *notebook, - GtkWidget *child, - GtkWidget *tab_label ); - -void gtk_notebook_prepend_page( GtkNotebook *notebook, - GtkWidget *child, - GtkWidget *tab_label ); -</verb></tscreen> - -These functions add pages to the notebook by inserting them from the -back of the notebook (append), or the front of the notebook (prepend). -<tt/child/ is the widget that is placed within the notebook page, and -<tt/tab_label/ is the label for the page being added. The <tt/child/ -widget must be created separately, and is typically a set of options -setup witin one of the other container widgets, such as a table. - -The final function for adding a page to the notebook contains all of -the properties of the previous two, but it allows you to specify what -position you want the page to be in the notebook. - -<tscreen><verb> -void gtk_notebook_insert_page( GtkNotebook *notebook, - GtkWidget *child, - GtkWidget *tab_label, - gint position ); -</verb></tscreen> - -The parameters are the same as _append_ and _prepend_ except it -contains an extra parameter, <tt/position/. This parameter is used to -specify what place this page will be inserted into the first page -having position zero. - -Now that we know how to add a page, lets see how we can remove a page -from the notebook. - -<tscreen><verb> -void gtk_notebook_remove_page( GtkNotebook *notebook, - gint page_num ); -</verb></tscreen> - -This function takes the page specified by <tt/page_num/ and removes it -from the widget pointed to by <tt/notebook/. - -To find out what the current page is in a notebook use the function: - -<tscreen><verb> -gint gtk_notebook_get_current_page( GtkNotebook *notebook ); -</verb></tscreen> - -These next two functions are simple calls to move the notebook page -forward or backward. Simply provide the respective function call with -the notebook widget you wish to operate on. Note: When the NoteBook is -currently on the last page, and gtk_notebook_next_page is called, the -notebook will wrap back to the first page. Likewise, if the NoteBook -is on the first page, and gtk_notebook_prev_page is called, the -notebook will wrap to the last page. - -<tscreen><verb> -void gtk_notebook_next_page( GtkNoteBook *notebook ); - -void gtk_notebook_prev_page( GtkNoteBook *notebook ); -</verb></tscreen> - -This next function sets the "active" page. If you wish the notebook to -be opened to page 5 for example, you would use this function. Without -using this function, the notebook defaults to the first page. - -<tscreen><verb> -void gtk_notebook_set_page( GtkNotebook *notebook, - gint page_num ); -</verb></tscreen> - -The next two functions add or remove the notebook page tabs and the -notebook border respectively. - -<tscreen><verb> -void gtk_notebook_set_show_tabs( GtkNotebook *notebook, - gboolean show_tabs); - -void gtk_notebook_set_show_border( GtkNotebook *notebook, - gboolean show_border ); -</verb></tscreen> - -The next function is useful when the you have a large number of pages, -and the tabs don't fit on the page. It allows the tabs to be scrolled -through using two arrow buttons. - -<tscreen><verb> -void gtk_notebook_set_scrollable( GtkNotebook *notebook, - gboolean scrollable ); -</verb></tscreen> - -<tt/show_tabs/, <tt/show_border/ and <tt/scrollable/ can be either -TRUE or FALSE. - -Now let's look at an example, it is expanded from the testgtk.c code -that comes with the GTK distribution. This small program creates a -window with a notebook and six buttons. The notebook contains 11 -pages, added in three different ways, appended, inserted, and -prepended. The buttons allow you rotate the tab positions, add/remove -the tabs and border, remove a page, change pages in both a forward and -backward manner, and exit the program. - -<tscreen><verb> -/* example-start notebook notebook.c */ - -#include <stdio.h> -#include <gtk/gtk.h> - -/* This function rotates the position of the tabs */ -void rotate_book( GtkButton *button, - GtkNotebook *notebook ) -{ - gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos +1) %4); -} - -/* Add/Remove the page tabs and the borders */ -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); -} - -/* Remove a page from the notebook */ -void remove_book( GtkButton *button, - GtkNotebook *notebook ) -{ - gint page; - - page = gtk_notebook_get_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); -} - -gint delete( GtkWidget *widget, - GtkWidget *event, - gpointer data ) -{ - gtk_main_quit(); - return(FALSE); -} - -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_set_border_width (GTK_CONTAINER (window), 10); - - table = gtk_table_new(3,6,FALSE); - gtk_container_add (GTK_CONTAINER (window), table); - - /* Create a new notebook, place the position of the tabs */ - 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); - - /* Let's append a bunch of pages to the 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_set_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); - } - - /* Now let's add a page to a specific spot */ - 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 page"); - gtk_notebook_insert_page (GTK_NOTEBOOK (notebook), checkbutton, label, 2); - - /* Now finally let's prepend pages to the notebook */ - 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_set_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); - } - - /* Set what page to start at (page 4) */ - gtk_notebook_set_page (GTK_NOTEBOOK(notebook), 3); - - /* Create a bunch of buttons */ - button = gtk_button_new_with_label ("close"); - gtk_signal_connect_object (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (delete), 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 (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 (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 (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); -} -/* example-end */ -</verb></tscreen> - -I hope this helps you on your way with creating notebooks for your -GTK applications. - -<!-- ***************************************************************** --> -<sect>CList Widget -<!-- ***************************************************************** --> - -<!-- ----------------------------------------------------------------- --> -<p> -The CList widget has replaced the List widget (which is still -available). - -The CList widget is a multi-column list widget that is capable of -handling literally thousands of rows of information. Each column can -optionally have a title, which itself is optionally active, allowing -us to bind a function to its selection. - -<!-- ----------------------------------------------------------------- --> -<sect1>Creating a CList widget -<p> -Creating a CList is quite straightforward, once you have learned -about widgets in general. It provides the almost standard two ways, -that is the hard way, and the easy way. But before we create it, there -is one thing we should figure out beforehand: how many columns should -it have? - -Not all columns have to be visible and can be used to store data that -is related to a certain cell in the list. - -<tscreen><verb> -GtkWidget *gtk_clist_new ( gint columns ); - -GtkWidget *gtk_clist_new_with_titles( gint columns, - gchar *titles[] ); -</verb></tscreen> - -The first form is very straightforward, the second might require some -explanation. Each column can have a title associated with it, and this -title can be a label or a button that reacts when we click on it. If -we use the second form, we must provide pointers to the title texts, -and the number of pointers should equal the number of columns -specified. Of course we can always use the first form, and manually -add titles later. - -Note: The CList widget does not have its own scrollbars and should -be placed within a ScrolledWindow widget if your require this -functionality. This is a change from the GTK 1.0 implementation. - -<!-- ----------------------------------------------------------------- --> -<sect1>Modes of operation -<p> -There are several attributes that can be used to alter the behaviour of -a CList. First there is - -<tscreen><verb> -void gtk_clist_set_selection_mode( GtkCList *clist, - GtkSelectionMode mode ); -</verb></tscreen> - -which, as the name implies, sets the selection mode of the -CList. The first argument is the CList widget, and the second -specifies the cell selection mode (they are defined in gtkenums.h). At -the time of this writing, the following modes are available to us: - -<itemize> -<item> <tt/GTK_SELECTION_SINGLE/ - The selection is either NULL or contains -a GList pointer for a single selected item. - -<item> <tt/GTK_SELECTION_BROWSE/ - The selection is NULL if the list -contains no widgets or insensitive ones only, otherwise it contains a -GList pointer for one GList structure, and therefore exactly one list -item. - -<item> <tt/GTK_SELECTION_MULTIPLE/ - The selection is NULL if no list items -are selected or a GList pointer for the first selected item. That in -turn points to a GList structure for the second selected item and so -on. This is currently the <bf>default</bf> for the CList widget. - -<item> <tt/GTK_SELECTION_EXTENDED/ - The selection is always NULL. -</itemize> - -Others might be added in later revisions of GTK. - -We can also define what the border of the CList widget should look -like. It is done through - -<tscreen><verb> -void gtk_clist_set_shadow_type( GtkCList *clist, - GtkShadowType border ); -</verb></tscreen> - -The possible values for the second argument are - -<tscreen><verb> - GTK_SHADOW_NONE - GTK_SHADOW_IN - GTK_SHADOW_OUT - GTK_SHADOW_ETCHED_IN - GTK_SHADOW_ETCHED_OUT -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Working with titles -<p> -When you create a CList widget, you will also get a set of title -buttons automatically. They live in the top of the CList window, and -can act either as normal buttons that respond to being pressed, or -they can be passive, in which case they are nothing more than a -title. There are four different calls that aid us in setting the -status of the title buttons. - -<tscreen><verb> -void gtk_clist_column_title_active( GtkCList *clist, - gint column ); - -void gtk_clist_column_title_passive( GtkCList *clist, - gint column ); - -void gtk_clist_column_titles_active( GtkCList *clist ); - -void gtk_clist_column_titles_passive( GtkCList *clist ); -</verb></tscreen> - -An active title is one which acts as a normal button, a passive one is -just a label. The first two calls above will activate/deactivate the -title button above the specific column, while the last two calls -activate/deactivate all title buttons in the supplied clist widget. - -But of course there are those cases when we don't want them at all, -and so they can be hidden and shown at will using the following two -calls. - -<tscreen><verb> -void gtk_clist_column_titles_show( GtkCList *clist ); - -void gtk_clist_column_titles_hide( GtkCList *clist ); -</verb></tscreen> - -For titles to be really useful we need a mechanism to set and change -them, and this is done using - -<tscreen><verb> -void gtk_clist_set_column_title( GtkCList *clist, - gint column, - gchar *title ); -</verb></tscreen> - -Note that only the title of one column can be set at a time, so if all -the titles are known from the beginning, then I really suggest using -gtk_clist_new_with_titles (as described above) to set them. It saves -you coding time, and makes your program smaller. There are some cases -where getting the job done the manual way is better, and that's when -not all titles will be text. CList provides us with title buttons -that can in fact incorporate whole widgets, for example a pixmap. It's -all done through - -<tscreen><verb> -void gtk_clist_set_column_widget( GtkCList *clist, - gint column, - GtkWidget *widget ); -</verb></tscreen> - -which should require no special explanation. - -<!-- ----------------------------------------------------------------- --> -<sect1>Manipulating the list itself -<p> -It is possible to change the justification for a column, and it is -done through - -<tscreen><verb> -void gtk_clist_set_column_justification( GtkCList *clist, - gint column, - GtkJustification justification ); -</verb></tscreen> - -The GtkJustification type can take the following values: - -<itemize> -<item><tt/GTK_JUSTIFY_LEFT/ - The text in the column will begin from the -left edge. - -<item><tt/GTK_JUSTIFY_RIGHT/ - The text in the column will begin from the -right edge. - -<item><tt/GTK_JUSTIFY_CENTER/ - The text is placed in the center of the -column. - -<item><tt/GTK_JUSTIFY_FILL/ - The text will use up all available space in -the column. It is normally done by inserting extra blank spaces -between words (or between individual letters if it's a single -word). Much in the same way as any ordinary WYSIWYG text editor. -</itemize> - -The next function is a very important one, and should be standard in -the setup of all CList widgets. When the list is created, the width -of the various columns are chosen to match their titles, and since -this is seldom the right width we have to set it using - -<tscreen><verb> -void gtk_clist_set_column_width( GtkCList *clist, - gint column, - gint width ); -</verb></tscreen> - -Note that the width is given in pixels and not letters. The same goes -for the height of the cells in the columns, but as the default value -is the height of the current font this isn't as critical to the -application. Still, it is done through - -<tscreen><verb> -void gtk_clist_set_row_height( GtkCList *clist, - gint height ); -</verb></tscreen> - -Again, note that the height is given in pixels. - -We can also move the list around without user interaction, however, it -does require that we know what we are looking for. Or in other words, -we need the row and column of the item we want to scroll to. - -<tscreen><verb> -void gtk_clist_moveto( GtkCList *clist, - gint row, - gint column, - gfloat row_align, - gfloat col_align ); -</verb></tscreen> - -The gfloat row_align is pretty important to understand. It's a value -between 0.0 and 1.0, where 0.0 means that we should scroll the list so -the row appears at the top, while if the value of row_align is 1.0, -the row will appear at the bottom instead. All other values between -0.0 and 1.0 are also valid and will place the row between the top and -the bottom. The last argument, gfloat col_align works in the same way, -though 0.0 marks left and 1.0 marks right instead. - -Depending on the application's needs, we don't have to scroll to an -item that is already visible to us. So how do we know if it is -visible? As usual, there is a function to find that out as well. - -<tscreen><verb> -GtkVisibility gtk_clist_row_is_visible( GtkCList *clist, - gint row ); -</verb></tscreen> - -The return value is is one of the following: - -<tscreen><verb> - GTK_VISIBILITY_NONE - GTK_VISIBILITY_PARTIAL - GTK_VISIBILITY_FULL -</verb></tscreen> - -Note that it will only tell us if a row is visible. Currently there is -no way to determine this for a column. We can get partial information -though, because if the return is <tt/GTK_VISIBILITY_PARTIAL/, then -some of it is hidden, but we don't know if it is the row that is being -cut by the lower edge of the listbox, or if the row has columns that -are outside. - -We can also change both the foreground and background colors of a -particular row. This is useful for marking the row selected by the -user, and the two functions that is used to do it are - -<tscreen><verb> -void gtk_clist_set_foreground( GtkCList *clist, - gint row, - GdkColor *color ); - -void gtk_clist_set_background( GtkCList *clist, - gint row, - GdkColor *color ); -</verb></tscreen> - -Please note that the colors must have been previously allocated. - -<!-- ----------------------------------------------------------------- --> -<sect1>Adding rows to the list -<p> -We can add rows in three ways. They can be prepended or appended to -the list using - -<tscreen><verb> -gint gtk_clist_prepend( GtkCList *clist, - gchar *text[] ); - -gint gtk_clist_append( GtkCList *clist, - gchar *text[] ); -</verb></tscreen> - -The return value of these two functions indicate the index of the row -that was just added. We can insert a row at a given place using - -<tscreen><verb> -void gtk_clist_insert( GtkCList *clist, - gint row, - gchar *text[] ); -</verb></tscreen> - -In these calls we have to provide a collection of pointers that are -the texts we want to put in the columns. The number of pointers should -equal the number of columns in the list. If the text[] argument is -NULL, then there will be no text in the columns of the row. This is -useful, for example, if we want to add pixmaps instead (something that -has to be done manually). - -Also, please note that the numbering of both rows and columns start at 0. - -To remove an individual row we use - -<tscreen><verb> -void gtk_clist_remove( GtkCList *clist, - gint row ); -</verb></tscreen> - -There is also a call that removes all rows in the list. This is a lot -faster than calling gtk_clist_remove once for each row, which is the -only alternative. - -<tscreen><verb> -void gtk_clist_clear( GtkCList *clist ); -</verb></tscreen> - -There are also two convenience functions that should be used when a -lot of changes have to be made to the list. This is to prevent the -list flickering while being repeatedly updated, which may be highly -annoying to the user. So instead it is a good idea to freeze the list, -do the updates to it, and finally thaw it which causes the list to be -updated on the screen. - -<tscreen><verb> -void gtk_clist_freeze( GtkCList * clist ); - -void gtk_clist_thaw( GtkCList * clist ); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Setting text and pixmaps in the cells -<p> -A cell can contain a pixmap, text or both. To set them the following -functions are used. - -<tscreen><verb> -void gtk_clist_set_text( GtkCList *clist, - gint row, - gint column, - const gchar *text ); - -void gtk_clist_set_pixmap( GtkCList *clist, - gint row, - gint column, - GdkPixmap *pixmap, - GdkBitmap *mask ); - -void gtk_clist_set_pixtext( GtkCList *clist, - gint row, - gint column, - gchar *text, - guint8 spacing, - GdkPixmap *pixmap, - GdkBitmap *mask ); -</verb></tscreen> - -It's quite straightforward. All the calls have the CList as the first -argument, followed by the row and column of the cell, followed by the -data to be set. The <tt/spacing/ argument in gtk_clist_set_pixtext is -the number of pixels between the pixmap and the beginning of the -text. In all cases the data is copied into the widget. - -To read back the data, we instead use - -<tscreen><verb> -gint gtk_clist_get_text( GtkCList *clist, - gint row, - gint column, - gchar **text ); - -gint gtk_clist_get_pixmap( GtkCList *clist, - gint row, - gint column, - GdkPixmap **pixmap, - GdkBitmap **mask ); - -gint gtk_clist_get_pixtext( GtkCList *clist, - gint row, - gint column, - gchar **text, - guint8 *spacing, - GdkPixmap **pixmap, - GdkBitmap **mask ); -</verb></tscreen> - -The returned pointers are all pointers to the data stored within the -widget, so the referenced data should not be modified or released. It -isn't necessary to read it all back in case you aren't interested. Any -of the pointers that are meant for return values (all except the -clist) can be NULL. So if we want to read back only the text from a -cell that is of type pixtext, then we would do the following, assuming -that clist, row and column already exist: - -<tscreen><verb> -gchar *mytext; - -gtk_clist_get_pixtext(clist, row, column, &mytext, NULL, NULL, NULL); -</verb></tscreen> - -There is one more call that is related to what's inside a cell in the -clist, and that's - -<tscreen><verb> -GtkCellType gtk_clist_get_cell_type( GtkCList *clist, - gint row, - gint column ); -</verb></tscreen> - -which returns the type of data in a cell. The return value is one of - -<tscreen><verb> - GTK_CELL_EMPTY - GTK_CELL_TEXT - GTK_CELL_PIXMAP - GTK_CELL_PIXTEXT - GTK_CELL_WIDGET -</verb></tscreen> - -There is also a function that will let us set the indentation, both -vertical and horizontal, of a cell. The indentation value is of type -gint, given in pixels, and can be both positive and negative. - -<tscreen><verb> -void gtk_clist_set_shift( GtkCList *clist, - gint row, - gint column, - gint vertical, - gint horizontal ); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Storing data pointers -<p> -With a CList it is possible to set a data pointer for a row. This -pointer will not be visible for the user, but is merely a convenience -for the programmer to associate a row with a pointer to some -additional data. - -The functions should be fairly self-explanatory by now. - -<tscreen><verb> -void gtk_clist_set_row_data( GtkCList *clist, - gint row, - gpointer data ); - -void gtk_clist_set_row_data_full( GtkCList *clist, - gint row, - gpointer data, - GtkDestroyNotify destroy ); - -gpointer gtk_clist_get_row_data( GtkCList *clist, - gint row ); - -gint gtk_clist_find_row_from_data( GtkCList *clist, - gpointer data ); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Working with selections -<p> -There are also functions available that let us force the (un)selection -of a row. These are - -<tscreen><verb> -void gtk_clist_select_row( GtkCList *clist, - gint row, - gint column ); - -void gtk_clist_unselect_row( GtkCList *clist, - gint row, - gint column ); -</verb></tscreen> - -And also a function that will take x and y coordinates (for example, -read from the mousepointer), and map that onto the list, returning the -corresponding row and column. - -<tscreen><verb> -gint gtk_clist_get_selection_info( GtkCList *clist, - gint x, - gint y, - gint *row, - gint *column ); -</verb></tscreen> - -When we detect something of interest (it might be movement of the -pointer, a click somewhere in the list) we can read the pointer -coordinates and find out where in the list the pointer is. Cumbersome? -Luckily, there is a simpler way... - -<!-- ----------------------------------------------------------------- --> -<sect1>The signals that bring it together -<p> -As with all other widgets, there are a few signals that can be used. The -CList widget is derived from the Container widget, and so has all the -same signals, but also adds the following: - -<itemize> -<item>select_row - This signal will send the following information, in -order: GtkCList *clist, gint row, gint column, GtkEventButton *event - -<item>unselect_row - When the user unselects a row, this signal is -activated. It sends the same information as select_row - -<item>click_column - Send GtkCList *clist, gint column -</itemize> - -So if we want to connect a callback to select_row, the callback -function would be declared like this - -<tscreen><verb> -void select_row_callback(GtkWidget *widget, - gint row, - gint column, - GdkEventButton *event, - gpointer data); -</verb></tscreen> - -The callback is connected as usual with - -<tscreen><verb> -gtk_signal_connect(GTK_OBJECT( clist), - "select_row" - GTK_SIGNAL_FUNC(select_row_callback), - NULL); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>A CList example -<p> - -<tscreen><verb> -/* example-start clist clist.c */ - -#include <gtk/gtk.h> - -/* User clicked the "Add List" button. */ -void button_add_clicked( gpointer data ) -{ - int indx; - - /* Something silly to add to the list. 4 rows of 2 columns each */ - gchar *drink[4][2] = { { "Milk", "3 Oz" }, - { "Water", "6 l" }, - { "Carrots", "2" }, - { "Snakes", "55" } }; - - /* Here we do the actual adding of the text. It's done once for - * each row. - */ - for ( indx=0 ; indx < 4 ; indx++ ) - gtk_clist_append( (GtkCList *) data, drink[indx]); - - return; -} - -/* User clicked the "Clear List" button. */ -void button_clear_clicked( gpointer data ) -{ - /* Clear the list using gtk_clist_clear. This is much faster than - * calling gtk_clist_remove once for each row. - */ - gtk_clist_clear( (GtkCList *) data); - - return; -} - -/* The user clicked the "Hide/Show titles" button. */ -void button_hide_show_clicked( gpointer data ) -{ - /* Just a flag to remember the status. 0 = currently visible */ - static short int flag = 0; - - if (flag == 0) - { - /* Hide the titles and set the flag to 1 */ - gtk_clist_column_titles_hide((GtkCList *) data); - flag++; - } - else - { - /* Show the titles and reset flag to 0 */ - gtk_clist_column_titles_show((GtkCList *) data); - flag--; - } - - return; -} - -/* If we come here, then the user has selected a row in the list. */ -void selection_made( GtkWidget *clist, - gint row, - gint column, - GdkEventButton *event, - gpointer data ) -{ - gchar *text; - - /* Get the text that is stored in the selected row and column - * which was clicked in. We will receive it as a pointer in the - * argument text. - */ - gtk_clist_get_text(GTK_CLIST(clist), row, column, &text); - - /* Just prints some information about the selected row */ - g_print("You selected row %d. More specifically you clicked in " - "column %d, and the text in this cell is %s\n\n", - row, column, text); - - return; -} - -int main( int argc, - gchar *argv[] ) -{ - GtkWidget *window; - GtkWidget *vbox, *hbox; - GtkWidget *scrolled_window, *clist; - GtkWidget *button_add, *button_clear, *button_hide_show; - gchar *titles[2] = { "Ingredients", "Amount" }; - - gtk_init(&argc, &argv); - - window=gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_widget_set_usize(GTK_WIDGET(window), 300, 150); - - gtk_window_set_title(GTK_WINDOW(window), "GtkCList Example"); - gtk_signal_connect(GTK_OBJECT(window), - "destroy", - GTK_SIGNAL_FUNC(gtk_main_quit), - NULL); - - vbox=gtk_vbox_new(FALSE, 5); - gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); - gtk_container_add(GTK_CONTAINER(window), vbox); - gtk_widget_show(vbox); - - /* Create a scrolled window to pack the CList widget into */ - scrolled_window = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), - GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); - - gtk_box_pack_start(GTK_BOX(vbox), scrolled_window, TRUE, TRUE, 0); - gtk_widget_show (scrolled_window); - - /* Create the CList. For this example we use 2 columns */ - clist = gtk_clist_new_with_titles( 2, titles); - - /* When a selection is made, we want to know about it. The callback - * used is selection_made, and its code can be found further down */ - gtk_signal_connect(GTK_OBJECT(clist), "select_row", - GTK_SIGNAL_FUNC(selection_made), - NULL); - - /* It isn't necessary to shadow the border, but it looks nice :) */ - gtk_clist_set_shadow_type (GTK_CLIST(clist), GTK_SHADOW_OUT); - - /* What however is important, is that we set the column widths as - * they will never be right otherwise. Note that the columns are - * numbered from 0 and up (to 1 in this case). - */ - gtk_clist_set_column_width (GTK_CLIST(clist), 0, 150); - - /* Add the CList widget to the vertical box and show it. */ - gtk_container_add(GTK_CONTAINER(scrolled_window), clist); - gtk_widget_show(clist); - - /* Create the buttons and add them to the window. See the button - * tutorial for more examples and comments on this. - */ - hbox = gtk_hbox_new(FALSE, 0); - gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0); - gtk_widget_show(hbox); - - button_add = gtk_button_new_with_label("Add List"); - button_clear = gtk_button_new_with_label("Clear List"); - button_hide_show = gtk_button_new_with_label("Hide/Show titles"); - - gtk_box_pack_start(GTK_BOX(hbox), button_add, TRUE, TRUE, 0); - gtk_box_pack_start(GTK_BOX(hbox), button_clear, TRUE, TRUE, 0); - gtk_box_pack_start(GTK_BOX(hbox), button_hide_show, TRUE, TRUE, 0); - - /* Connect our callbacks to the three buttons */ - gtk_signal_connect_object(GTK_OBJECT(button_add), "clicked", - GTK_SIGNAL_FUNC(button_add_clicked), - (gpointer) clist); - gtk_signal_connect_object(GTK_OBJECT(button_clear), "clicked", - GTK_SIGNAL_FUNC(button_clear_clicked), - (gpointer) clist); - gtk_signal_connect_object(GTK_OBJECT(button_hide_show), "clicked", - GTK_SIGNAL_FUNC(button_hide_show_clicked), - (gpointer) clist); - - gtk_widget_show(button_add); - gtk_widget_show(button_clear); - gtk_widget_show(button_hide_show); - - /* The interface is completely set up so we show the window and - * enter the gtk_main loop. - */ - gtk_widget_show(window); - gtk_main(); - - return(0); -} -/* example-end */ -</verb></tscreen> - -<!-- ***************************************************************** --> -<sect> Tree Widget <label id="sec_Tree_Widgets"> -<!-- ***************************************************************** --> -<p> -The purpose of tree widgets is to display hierarchically-organized -data. The Tree widget itself is a vertical container for widgets of -type TreeItem. Tree itself is not terribly different from -CList - both are derived directly from Container, and the -Container methods work in the same way on Tree widgets as on -CList widgets. The difference is that Tree widgets can be nested -within other Tree widgets. We'll see how to do this shortly. - -The Tree widget has its own window, and defaults to a white -background, as does CList. Also, most of the Tree methods work in -the same way as the corresponding CList ones. However, Tree is -not derived from CList, so you cannot use them interchangeably. - - -<sect1> Creating a Tree -<p> -A Tree is created in the usual way, using: - -<tscreen><verb> -GtkWidget *gtk_tree_new( void ); -</verb></tscreen> - -Like the CList widget, a Tree will simply keep growing as more -items are added to it, as well as when subtrees are expanded. For -this reason, they are almost always packed into a -ScrolledWindow. You might want to use gtk_widget_set_usize() on the -scrolled window to ensure that it is big enough to see the tree's -items, as the default size for ScrolledWindow is quite small. - -Now that you have a tree, you'll probably want to add some items to -it. <ref id="sec_Tree_Item_Widget" name="The Tree Item Widget"> below -explains the gory details of TreeItem. For now, it'll suffice to -create one, using: - -<tscreen><verb> -GtkWidget *gtk_tree_item_new_with_label( gchar *label ); -</verb></tscreen> - -You can then add it to the tree using one of the following (see -<ref id="sec_Tree_Functions" name="Functions and Macros"> -below for more options): - -<tscreen><verb> -void gtk_tree_append( GtkTree *tree, - GtkWidget *tree_item ); - -void gtk_tree_prepend( GtkTree *tree, - GtkWidget *tree_item ); -</verb></tscreen> - -Note that you must add items to a Tree one at a time - there is no -equivalent to gtk_list_*_items(). - -<!-- ----------------------------------------------------------------- --> -<sect1> Adding a Subtree -<p> -A subtree is created like any other Tree widget. A subtree is added -to another tree beneath a tree item, using: - -<tscreen><verb> -void gtk_tree_item_set_subtree( GtkTreeItem *tree_item, - GtkWidget *subtree ); -</verb></tscreen> - -You do not need to call gtk_widget_show() on a subtree before or after -adding it to a TreeItem. However, you <em>must</em> have added the -TreeItem in question to a parent tree before calling -gtk_tree_item_set_subtree(). This is because, technically, the parent -of the subtree is <em>not</em> the GtkTreeItem which "owns" it, but -rather the GtkTree which holds that GtkTreeItem. - -When you add a subtree to a TreeItem, a plus or minus sign appears -beside it, which the user can click on to "expand" or "collapse" it, -meaning, to show or hide its subtree. TreeItems are collapsed by -default. Note that when you collapse a TreeItem, any selected -items in its subtree remain selected, which may not be what the user -expects. - -<!-- ----------------------------------------------------------------- --> -<sect1> Handling the Selection List -<p> -As with CList, the Tree type has a <tt>selection</tt> field, and -it is possible to control the behaviour of the tree (somewhat) by -setting the selection type using: - -<tscreen><verb> -void gtk_tree_set_selection_mode( GtkTree *tree, - GtkSelectionMode mode ); -</verb></tscreen> - -The semantics associated with the various selection modes are -described in the section on the CList widget. As with the CList -widget, the "select_child", "unselect_child" (not really - see <ref -id="sec_Tree_Signals" name="Signals"> below for an explanation), -and "selection_changed" signals are emitted when list items are -selected or unselected. However, in order to take advantage of these -signals, you need to know <em>which</em> Tree widget they will be -emitted by, and where to find the list of selected items. - -This is a source of potential confusion. The best way to explain this -is that though all Tree widgets are created equal, some are more equal -than others. All Tree widgets have their own X window, and can -therefore receive events such as mouse clicks (if their TreeItems or -their children don't catch them first!). However, to make -<tt/GTK_SELECTION_SINGLE/ and <tt/GTK_SELECTION_BROWSE/ selection -types behave in a sane manner, the list of selected items is specific -to the topmost Tree widget in a hierarchy, known as the "root tree". - -Thus, accessing the <tt>selection</tt> field directly in an arbitrary -Tree widget is not a good idea unless you <em>know</em> it's the root -tree. Instead, use the <tt/GTK_TREE_SELECTION (Tree)/ macro, which -gives the root tree's selection list as a GList pointer. Of course, -this list can include items that are not in the subtree in question if -the selection type is <tt/GTK_SELECTION_MULTIPLE/. - -Finally, the "select_child" (and "unselect_child", in theory) signals -are emitted by all trees, but the "selection_changed" signal is only -emitted by the root tree. Consequently, if you want to handle the -"select_child" signal for a tree and all its subtrees, you will have -to call gtk_signal_connect() for every subtree. - -<sect1> Tree Widget Internals -<p> -The Tree's struct definition looks like this: - -<tscreen><verb> -struct _GtkTree -{ - GtkContainer container; - - GList *children; - - GtkTree* root_tree; /* owner of selection list */ - GtkWidget* tree_owner; - GList *selection; - guint level; - guint indent_value; - guint current_indent; - guint selection_mode : 2; - guint view_mode : 1; - guint view_line : 1; -}; -</verb></tscreen> - -The perils associated with accessing the <tt>selection</tt> field -directly have already been mentioned. The other important fields of -the struct can also be accessed with handy macros or class functions. -<tt/GTK_IS_ROOT_TREE (Tree)/ returns a boolean value which -indicates whether a tree is the root tree in a Tree hierarchy, while -<tt/GTK_TREE_ROOT_TREE (Tree)/ returns the root tree, an object of -type GtkTree (so, remember to cast it using <tt/GTK_WIDGET (Tree)/ if -you want to use one of the gtk_widget_*() functions on it). - -Instead of directly accessing the children field of a Tree widget, -it's probably best to cast it using >tt/GTK_CONTAINER (Tree)/, and -pass it to the gtk_container_children() function. This creates a -duplicate of the original list, so it's advisable to free it up using -g_list_free() after you're done with it, or to iterate on it -destructively, like this: - -<tscreen><verb> - children = gtk_container_children (GTK_CONTAINER (tree)); - while (children) { - do_something_nice (GTK_TREE_ITEM (children->data)); - children = g_list_remove_link (children, children); -} -</verb></tscreen> - -The <tt>tree_owner</tt> field is defined only in subtrees, where it -points to the TreeItem widget which holds the tree in question. -The <tt>level</tt> field indicates how deeply nested a particular tree -is; root trees have level 0, and each successive level of subtrees has -a level one greater than the parent level. This field is set only -after a Tree widget is actually mapped (i.e. drawn on the screen). - -<sect2> Signals<label id="sec_Tree_Signals"> -<p> -<tscreen><verb> -void selection_changed( GtkTree *tree ); -</verb></tscreen> - -This signal will be emitted whenever the <tt>selection</tt> field of a -Tree has changed. This happens when a child of the Tree is -selected or deselected. - -<tscreen><verb> -void select_child( GtkTree *tree, - GtkWidget *child ); -</verb></tscreen> - -This signal is emitted when a child of the Tree is about to get -selected. This happens on calls to gtk_tree_select_item(), -gtk_tree_select_child(), on <em>all</em> button presses and calls to -gtk_tree_item_toggle() and gtk_item_toggle(). It may sometimes be -indirectly triggered on other occasions where children get added to or -removed from the Tree. - -<tscreen><verb> -void unselect_child (GtkTree *tree, - GtkWidget *child); -</verb></tscreen> - -This signal is emitted when a child of the Tree is about to get -deselected. As of GTK 1.0.4, this seems to only occur on calls to -gtk_tree_unselect_item() or gtk_tree_unselect_child(), and perhaps on -other occasions, but <em>not</em> when a button press deselects a -child, nor on emission of the "toggle" signal by gtk_item_toggle(). - -<sect2> Functions and Macros<label id="sec_Tree_Functions"> -<p> -<tscreen><verb> -guint gtk_tree_get_type( void ); -</verb></tscreen> - -Returns the "GtkTree" type identifier. - -<tscreen><verb> -GtkWidget* gtk_tree_new( void ); -</verb></tscreen> - -Create a new Tree object. The new widget is returned as a pointer to a -GtkWidget object. NULL is returned on failure. - -<tscreen><verb> -void gtk_tree_append( GtkTree *tree, - GtkWidget *tree_item ); -</verb></tscreen> - -Append a tree item to a Tree. - -<tscreen><verb> -void gtk_tree_prepend( GtkTree *tree, - GtkWidget *tree_item ); -</verb></tscreen> - -Prepend a tree item to a Tree. - -<tscreen><verb> -void gtk_tree_insert( GtkTree *tree, - GtkWidget *tree_item, - gint position ); -</verb></tscreen> - -Insert a tree item into a Tree at the position in the list -specified by <tt>position.</tt> - -<tscreen><verb> -void gtk_tree_remove_items( GtkTree *tree, - GList *items ); -</verb></tscreen> - -Remove a list of items (in the form of a GList *) from a Tree. -Note that removing an item from a tree dereferences (and thus usually) -destroys it <em>and</em> its subtree, if it has one, <em>and</em> all -subtrees in that subtree. If you want to remove only one item, you -can use gtk_container_remove(). - -<tscreen><verb> -void gtk_tree_clear_items( GtkTree *tree, - gint start, - gint end ); -</verb></tscreen> - -Remove the items from position <tt>start</tt> to position <tt>end</tt> -from a Tree. The same warning about dereferencing applies here, as -gtk_tree_clear_items() simply constructs a list and passes it to -gtk_tree_remove_items(). - -<tscreen><verb> -void gtk_tree_select_item( GtkTree *tree, - gint item ); -</verb></tscreen> - -Emits the "select_item" signal for the child at position -<tt>item</tt>, thus selecting the child (unless you unselect it in a -signal handler). - -<tscreen><verb> -void gtk_tree_unselect_item( GtkTree *tree, - gint item ); -</verb></tscreen> - -Emits the "unselect_item" signal for the child at position -<tt>item</tt>, thus unselecting the child. - -<tscreen><verb> -void gtk_tree_select_child( GtkTree *tree, - GtkWidget *tree_item ); -</verb></tscreen> - -Emits the "select_item" signal for the child <tt>tree_item</tt>, thus -selecting it. - -<tscreen><verb> -void gtk_tree_unselect_child( GtkTree *tree, - GtkWidget *tree_item ); -</verb></tscreen> - -Emits the "unselect_item" signal for the child <tt>tree_item</tt>, -thus unselecting it. - -<tscreen><verb> -gint gtk_tree_child_position( GtkTree *tree, - GtkWidget *child ); -</verb></tscreen> - -Returns the position in the tree of <tt>child</tt>, unless -<tt>child</tt> is not in the tree, in which case it returns -1. - -<tscreen><verb> -void gtk_tree_set_selection_mode( GtkTree *tree, - GtkSelectionMode mode ); -</verb></tscreen> - -Sets the selection mode, which can be one of <tt/GTK_SELECTION_SINGLE/ (the -default), <tt/GTK_SELECTION_BROWSE/, <tt/GTK_SELECTION_MULTIPLE/, or -<tt/GTK_SELECTION_EXTENDED/. This is only defined for root trees, which -makes sense, since the root tree "owns" the selection. Setting it for -subtrees has no effect at all; the value is simply ignored. - -<tscreen><verb> -void gtk_tree_set_view_mode( GtkTree *tree, - GtkTreeViewMode mode ); -</verb></tscreen> - -Sets the "view mode", which can be either <tt/GTK_TREE_VIEW_LINE/ (the -default) or <tt/GTK_TREE_VIEW_ITEM/. The view mode propagates from a -tree to its subtrees, and can't be set exclusively to a subtree (this -is not exactly true - see the example code comments). - -The term "view mode" is rather ambiguous - basically, it controls the -way the highlight is drawn when one of a tree's children is selected. -If it's <tt/GTK_TREE_VIEW_LINE/, the entire TreeItem widget is -highlighted, while for <tt/GTK_TREE_VIEW_ITEM/, only the child widget -(i.e., usually the label) is highlighted. - -<tscreen><verb> -void gtk_tree_set_view_lines( GtkTree *tree, - guint flag ); -</verb></tscreen> - -Controls whether connecting lines between tree items are drawn. -<tt>flag</tt> is either TRUE, in which case they are, or FALSE, in -which case they aren't. - -<tscreen><verb> -GtkTree *GTK_TREE (gpointer obj); -</verb></tscreen> - -Cast a generic pointer to "GtkTree *". - -<tscreen><verb> -GtkTreeClass *GTK_TREE_CLASS (gpointer class); -</verb></tscreen> - -Cast a generic pointer to "GtkTreeClass *". - -<tscreen><verb> -gint GTK_IS_TREE (gpointer obj); -</verb></tscreen> - -Determine if a generic pointer refers to a "GtkTree" object. - -<tscreen><verb> -gint GTK_IS_ROOT_TREE (gpointer obj) -</verb></tscreen> - -Determine if a generic pointer refers to a "GtkTree" object -<em>and</em> is a root tree. Though this will accept any pointer, the -results of passing it a pointer that does not refer to a Tree are -undefined and possibly harmful. - -<tscreen><verb> -GtkTree *GTK_TREE_ROOT_TREE (gpointer obj) -</verb></tscreen> - -Return the root tree of a pointer to a "GtkTree" object. The above -warning applies. - -<tscreen><verb> -GList *GTK_TREE_SELECTION( gpointer obj) -</verb></tscreen> - -Return the selection list of the root tree of a "GtkTree" object. The -above warning applies here, too. - -<sect1> Tree Item Widget<label id="sec_Tree_Item_Widget"> -<p> -The TreeItem widget, like CListItem, is derived from Item, -which in turn is derived from Bin. Therefore, the item itself is a -generic container holding exactly one child widget, which can be of -any type. The TreeItem widget has a number of extra fields, but -the only one we need be concerned with is the <tt>subtree</tt> field. - -The definition for the TreeItem struct looks like this: - -<tscreen><verb> -struct _GtkTreeItem -{ - GtkItem item; - - GtkWidget *subtree; - GtkWidget *pixmaps_box; - GtkWidget *plus_pix_widget, *minus_pix_widget; - - GList *pixmaps; /* pixmap node for this items color depth */ - - guint expanded : 1; -}; -</verb></tscreen> - -The <tt>pixmaps_box</tt> field is an EventBox which catches clicks on -the plus/minus symbol which controls expansion and collapsing. The -<tt>pixmaps</tt> field points to an internal data structure. Since -you can always obtain the subtree of a TreeItem in a (relatively) -type-safe manner with the <tt/GTK_TREE_ITEM_SUBTREE (Item)/ macro, -it's probably advisable never to touch the insides of a TreeItem -unless you <em>really</em> know what you're doing. - -Since it is directly derived from an Item it can be treated as such by -using the <tt/GTK_ITEM (TreeItem)/ macro. A TreeItem usually holds a -label, so the convenience function gtk_list_item_new_with_label() is -provided. The same effect can be achieved using code like the -following, which is actually copied verbatim from -gtk_tree_item_new_with_label(): - -<tscreen><verb> -tree_item = gtk_tree_item_new (); -label_widget = gtk_label_new (label); -gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5); - -gtk_container_add (GTK_CONTAINER (tree_item), label_widget); -gtk_widget_show (label_widget); -</verb></tscreen> - -As one is not forced to add a Label to a TreeItem, you could -also add an HBox or an Arrow, or even a Notebook (though your -app will likely be quite unpopular in this case) to the TreeItem. - -If you remove all the items from a subtree, it will be destroyed and -unparented, unless you reference it beforehand, and the TreeItem -which owns it will be collapsed. So, if you want it to stick around, -do something like the following: - -<tscreen><verb> -g_object_ref (tree); -owner = GTK_TREE(tree)->tree_owner; -gtk_container_remove (GTK_CONTAINER(tree), item); -if (tree->parent == NULL){ - gtk_tree_item_expand (GTK_TREE_ITEM(owner)); - gtk_tree_item_set_subtree (GTK_TREE_ITEM(owner), tree); -} -else - g_object_unref (tree); -</verb></tscreen> - -Finally, drag-n-drop <em>does</em> work with TreeItems. You just -have to make sure that the TreeItem you want to make into a drag -item or a drop site has not only been added to a Tree, but that -each successive parent widget has a parent itself, all the way back to -a toplevel or dialog window, when you call gtk_widget_dnd_drag_set() -or gtk_widget_dnd_drop_set(). Otherwise, strange things will happen. - -<sect2> Signals -<p> -TreeItem inherits the "select", "deselect", and "toggle" signals -from Item. In addition, it adds two signals of its own, "expand" -and "collapse". - -<tscreen><verb> -void select( GtkItem *tree_item ); -</verb></tscreen> - -This signal is emitted when an item is about to be selected, either -after it has been clicked on by the user, or when the program calls -gtk_tree_item_select(), gtk_item_select(), or gtk_tree_select_child(). - -<tscreen><verb> -void deselect( GtkItem *tree_item ); -</verb></tscreen> - -This signal is emitted when an item is about to be unselected, either -after it has been clicked on by the user, or when the program calls -gtk_tree_item_deselect() or gtk_item_deselect(). In the case of -TreeItems, it is also emitted by gtk_tree_unselect_child(), and -sometimes gtk_tree_select_child(). - -<tscreen><verb> -void toggle( GtkItem *tree_item ); -</verb></tscreen> - -This signal is emitted when the program calls gtk_item_toggle(). The -effect it has when emitted on a TreeItem is to call -gtk_tree_select_child() (and never gtk_tree_unselect_child()) on the -item's parent tree, if the item has a parent tree. If it doesn't, -then the highlight is reversed on the item. - -<tscreen><verb> -void expand( GtkTreeItem *tree_item ); -</verb></tscreen> - -This signal is emitted when the tree item's subtree is about to be -expanded, that is, when the user clicks on the plus sign next to the -item, or when the program calls gtk_tree_item_expand(). - -<tscreen><verb> -void collapse( GtkTreeItem *tree_item ); -</verb></tscreen> - -This signal is emitted when the tree item's subtree is about to be -collapsed, that is, when the user clicks on the minus sign next to the -item, or when the program calls gtk_tree_item_collapse(). - -<sect2> Functions and Macros -<p> -<tscreen><verb> -guint gtk_tree_item_get_type( void ); -</verb></tscreen> - -Returns the "GtkTreeItem" type identifier. - -<tscreen><verb> -GtkWidget* gtk_tree_item_new( void ); -</verb></tscreen> - -Create a new TreeItem object. The new widget is returned as a -pointer to a GtkWidget object. NULL is returned on failure. - -<tscreen><verb> -GtkWidget* gtk_tree_item_new_with_label (gchar *label); -</verb></tscreen> - -Create a new TreeItem object, having a single GtkLabel as the sole -child. The new widget is returned as a pointer to a GtkWidget -object. NULL is returned on failure. - -<tscreen><verb> -void gtk_tree_item_select( GtkTreeItem *tree_item ); -</verb></tscreen> - -This function is basically a wrapper around a call to -<tt>gtk_item_select (GTK_ITEM (tree_item))</tt> which will emit the -select signal. - -<tscreen><verb> -void gtk_tree_item_deselect( GtkTreeItem *tree_item ); -</verb></tscreen> - -This function is basically a wrapper around a call to -gtk_item_deselect (GTK_ITEM (tree_item)) which will emit the deselect -signal. - -<tscreen><verb> -void gtk_tree_item_set_subtree( GtkTreeItem *tree_item, - GtkWidget *subtree ); -</verb></tscreen> - -This function adds a subtree to tree_item, showing it if tree_item is -expanded, or hiding it if tree_item is collapsed. Again, remember that -the tree_item must have already been added to a tree for this to work. - -<tscreen><verb> -void gtk_tree_item_remove_subtree( GtkTreeItem *tree_item ); -</verb></tscreen> - -This removes all of tree_item's subtree's children (thus unreferencing -and destroying it, any of its children's subtrees, and so on...), then -removes the subtree itself, and hides the plus/minus sign. - -<tscreen><verb> -void gtk_tree_item_expand( GtkTreeItem *tree_item ); -</verb></tscreen> - -This emits the "expand" signal on tree_item, which expands it. - -<tscreen><verb> -void gtk_tree_item_collapse( GtkTreeItem *tree_item ); -</verb></tscreen> - -This emits the "collapse" signal on tree_item, which collapses it. - -<tscreen><verb> -GtkTreeItem *GTK_TREE_ITEM (gpointer obj) -</verb></tscreen> - -Cast a generic pointer to "GtkTreeItem *". - -<tscreen><verb> -GtkTreeItemClass *GTK_TREE_ITEM_CLASS (gpointer obj) -</verb></tscreen> - -Cast a generic pointer to "GtkTreeItemClass". - -<tscreen><verb> -gint GTK_IS_TREE_ITEM (gpointer obj) -</verb></tscreen> - -Determine if a generic pointer refers to a "GtkTreeItem" object. - -<tscreen><verb> -GtkWidget GTK_TREE_ITEM_SUBTREE (gpointer obj) -</verb></tscreen> - -Returns a tree item's subtree (<tt/obj/ should point to a -"GtkTreeItem" object). - -<sect1> Tree Example -<p> -This is somewhat like the tree example in testgtk.c, but a lot less -complete (although much better commented). It puts up a window with a -tree, and connects all the signals for the relevant objects, so you -can see when they are emitted. - -<tscreen><verb> -/* example-start tree tree.c */ - -#include <gtk/gtk.h> - -/* for all the GtkItem:: and GtkTreeItem:: signals */ -static void cb_itemsignal( GtkWidget *item, - gchar *signame ) -{ - gchar *name; - GtkLabel *label; - - /* It's a Bin, so it has one child, which we know to be a - label, so get that */ - label = GTK_LABEL (GTK_BIN (item)->child); - /* Get the text of the label */ - gtk_label_get (label, &name); - /* Get the level of the tree which the item is in */ - g_print ("%s called for item %s->%p, level %d\n", signame, name, - item, GTK_TREE (item->parent)->level); -} - -/* Note that this is never called */ -static void cb_unselect_child( GtkWidget *root_tree, - GtkWidget *child, - GtkWidget *subtree ) -{ - g_print ("unselect_child called for root tree %p, subtree %p, child %p\n", - root_tree, subtree, child); -} - -/* Note that this is called every time the user clicks on an item, - whether it is already selected or not. */ -static void cb_select_child (GtkWidget *root_tree, GtkWidget *child, - GtkWidget *subtree) -{ - g_print ("select_child called for root tree %p, subtree %p, child %p\n", - root_tree, subtree, child); -} - -static void cb_selection_changed( GtkWidget *tree ) -{ - GList *i; - - g_print ("selection_change called for tree %p\n", tree); - g_print ("selected objects are:\n"); - - i = GTK_TREE_SELECTION(tree); - while (i){ - gchar *name; - GtkLabel *label; - GtkWidget *item; - - /* Get a GtkWidget pointer from the list node */ - item = GTK_WIDGET (i->data); - label = GTK_LABEL (GTK_BIN (item)->child); - gtk_label_get (label, &name); - g_print ("\t%s on level %d\n", name, GTK_TREE - (item->parent)->level); - i = i->next; - } -} - -int main( int argc, - char *argv[] ) -{ - GtkWidget *window, *scrolled_win, *tree; - static gchar *itemnames[] = {"Foo", "Bar", "Baz", "Quux", - "Maurice"}; - gint i; - - gtk_init (&argc, &argv); - - /* a generic toplevel window */ - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_signal_connect (GTK_OBJECT(window), "delete_event", - GTK_SIGNAL_FUNC (gtk_main_quit), NULL); - gtk_container_set_border_width (GTK_CONTAINER(window), 5); - - /* A generic scrolled window */ - scrolled_win = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); - gtk_widget_set_usize (scrolled_win, 150, 200); - gtk_container_add (GTK_CONTAINER(window), scrolled_win); - gtk_widget_show (scrolled_win); - - /* Create the root tree */ - tree = gtk_tree_new(); - g_print ("root tree is %p\n", tree); - /* connect all GtkTree:: signals */ - gtk_signal_connect (GTK_OBJECT(tree), "select_child", - GTK_SIGNAL_FUNC(cb_select_child), tree); - gtk_signal_connect (GTK_OBJECT(tree), "unselect_child", - GTK_SIGNAL_FUNC(cb_unselect_child), tree); - gtk_signal_connect (GTK_OBJECT(tree), "selection_changed", - GTK_SIGNAL_FUNC(cb_selection_changed), tree); - /* Add it to the scrolled window */ - gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW(scrolled_win), - tree); - /* Set the selection mode */ - gtk_tree_set_selection_mode (GTK_TREE(tree), - GTK_SELECTION_MULTIPLE); - /* Show it */ - gtk_widget_show (tree); - - for (i = 0; i < 5; i++){ - GtkWidget *subtree, *item; - gint j; - - /* Create a tree item */ - item = gtk_tree_item_new_with_label (itemnames[i]); - /* Connect all GtkItem:: and GtkTreeItem:: signals */ - gtk_signal_connect (GTK_OBJECT(item), "select", - GTK_SIGNAL_FUNC(cb_itemsignal), "select"); - gtk_signal_connect (GTK_OBJECT(item), "deselect", - GTK_SIGNAL_FUNC(cb_itemsignal), "deselect"); - gtk_signal_connect (GTK_OBJECT(item), "toggle", - GTK_SIGNAL_FUNC(cb_itemsignal), "toggle"); - gtk_signal_connect (GTK_OBJECT(item), "expand", - GTK_SIGNAL_FUNC(cb_itemsignal), "expand"); - gtk_signal_connect (GTK_OBJECT(item), "collapse", - GTK_SIGNAL_FUNC(cb_itemsignal), "collapse"); - /* Add it to the parent tree */ - gtk_tree_append (GTK_TREE(tree), item); - /* Show it - this can be done at any time */ - gtk_widget_show (item); - /* Create this item's subtree */ - subtree = gtk_tree_new(); - g_print ("-> item %s->%p, subtree %p\n", itemnames[i], item, - subtree); - - /* This is still necessary if you want these signals to be called - for the subtree's children. Note that selection_change will be - signalled for the root tree regardless. */ - gtk_signal_connect (GTK_OBJECT(subtree), "select_child", - GTK_SIGNAL_FUNC(cb_select_child), subtree); - gtk_signal_connect (GTK_OBJECT(subtree), "unselect_child", - GTK_SIGNAL_FUNC(cb_unselect_child), subtree); - /* This has absolutely no effect, because it is completely ignored - in subtrees */ - gtk_tree_set_selection_mode (GTK_TREE(subtree), - GTK_SELECTION_SINGLE); - /* Neither does this, but for a rather different reason - the - view_mode and view_line values of a tree are propagated to - subtrees when they are mapped. So, setting it later on would - actually have a (somewhat unpredictable) effect */ - gtk_tree_set_view_mode (GTK_TREE(subtree), GTK_TREE_VIEW_ITEM); - /* Set this item's subtree - note that you cannot do this until - AFTER the item has been added to its parent tree! */ - gtk_tree_item_set_subtree (GTK_TREE_ITEM(item), subtree); - - for (j = 0; j < 5; j++){ - GtkWidget *subitem; - - /* Create a subtree item, in much the same way */ - subitem = gtk_tree_item_new_with_label (itemnames[j]); - /* Connect all GtkItem:: and GtkTreeItem:: signals */ - gtk_signal_connect (GTK_OBJECT(subitem), "select", - GTK_SIGNAL_FUNC(cb_itemsignal), "select"); - gtk_signal_connect (GTK_OBJECT(subitem), "deselect", - GTK_SIGNAL_FUNC(cb_itemsignal), "deselect"); - gtk_signal_connect (GTK_OBJECT(subitem), "toggle", - GTK_SIGNAL_FUNC(cb_itemsignal), "toggle"); - gtk_signal_connect (GTK_OBJECT(subitem), "expand", - GTK_SIGNAL_FUNC(cb_itemsignal), "expand"); - gtk_signal_connect (GTK_OBJECT(subitem), "collapse", - GTK_SIGNAL_FUNC(cb_itemsignal), "collapse"); - g_print ("-> -> item %s->%p\n", itemnames[j], subitem); - /* Add it to its parent tree */ - gtk_tree_append (GTK_TREE(subtree), subitem); - /* Show it */ - gtk_widget_show (subitem); - } - } - - /* Show the window and loop endlessly */ - gtk_widget_show (window); - gtk_main(); - return 0; -} -/* example-end */ -</verb></tscreen> - -<!-- ***************************************************************** --> -<sect>Menu Widget -<!-- ***************************************************************** --> -<p> -There are two ways to create menus: there's the easy way, and there's -the hard way. Both have their uses, but you can usually use the -Itemfactory (the easy way). The "hard" way is to create all the menus -using the calls directly. The easy way is to use the gtk_item_factory -calls. This is much simpler, but there are advantages and -disadvantages to each approach. - -The Itemfactory is much easier to use, and to add new menus to, -although writing a few wrapper functions to create menus using the -manual method could go a long way towards usability. With the -Itemfactory, it is not possible to add images or the character '/' to -the menus. - -<!-- ----------------------------------------------------------------- --> -<sect1>Manual Menu Creation -<p> -In the true tradition of teaching, we'll show you the hard way -first. <tt>:)</> - -There are three widgets that go into making a menubar and submenus: -<itemize> -<item>a menu item, which is what the user wants to select, e.g., -"Save" -<item>a menu, which acts as a container for the menu items, and -<item>a menubar, which is a container for each of the individual -menus. -</itemize> - -This is slightly complicated by the fact that menu item widgets are -used for two different things. They are both the widgets that are -packed into the menu, and the widget that is packed into the menubar, -which, when selected, activates the menu. - -Let's look at the functions that are used to create menus and -menubars. This first function is used to create a new menubar. - -<tscreen> -<verb> -GtkWidget *gtk_menu_bar_new( void ); -</verb> -</tscreen> - -This rather self explanatory function creates a new menubar. You use -gtk_container_add to pack this into a window, or the box_pack -functions to pack it into a box - the same as buttons. - -<tscreen><verb> -GtkWidget *gtk_menu_new( void ); -</verb></tscreen> - -This function returns a pointer to a new menu; it is never actually -shown (with gtk_widget_show), it is just a container for the menu -items. I hope this will become more clear when you look at the -example below. - -The next two calls are used to create menu items that are packed into -the menu (and menubar). - -<tscreen><verb> -GtkWidget *gtk_menu_item_new( void ); -</verb></tscreen> - -and - -<tscreen><verb> -GtkWidget *gtk_menu_item_new_with_label( const char *label ); -</verb></tscreen> - -These calls are used to create the menu items that are to be -displayed. Remember to differentiate between a "menu" as created with -gtk_menu_new and a "menu item" as created by the gtk_menu_item_new -functions. The menu item will be an actual button with an associated -action, whereas a menu will be a container holding menu items. - -The gtk_menu_new_with_label and gtk_menu_new functions are just as -you'd expect after reading about the buttons. One creates a new menu -item with a label already packed into it, and the other just creates a -blank menu item. - -Once you've created a menu item you have to put it into a menu. This -is done using the function gtk_menu_append. In order to capture when -the item is selected by the user, we need to connect to the -<tt/activate/ signal in the usual way. So, if we wanted to create a -standard <tt/File/ menu, with the options <tt/Open/, <tt/Save/, and -<tt/Quit/, the code would look something like: - -<tscreen><verb> - file_menu = gtk_menu_new (); /* Don't need to show menus */ - - /* Create the menu items */ - 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"); - - /* Add them to the menu */ - 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); - - /* Attach the callback functions to the activate signal */ - 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"); - - /* We can attach the Quit menu item to our exit function */ - gtk_signal_connect_object (GTK_OBJECT (quit_items), "activate", - GTK_SIGNAL_FUNC (destroy), - (gpointer) "file.quit"); - - /* We do need to show menu items */ - gtk_widget_show (open_item); - gtk_widget_show (save_item); - gtk_widget_show (quit_item); -</verb></tscreen> - -At this point we have our menu. Now we need to create a menubar and a -menu item for the <tt/File/ entry, to which we add our menu. The code -looks like this: - -<tscreen><verb> - 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); -</verb></tscreen> - -Now we need to associate the menu with <tt/file_item/. This is done -with the function - -<tscreen> -void gtk_menu_item_set_submenu( GtkMenuItem *menu_item, - GtkWidget *submenu ); -</tscreen> - -So, our example would continue with - -<tscreen><verb> - gtk_menu_item_set_submenu (GTK_MENU_ITEM (file_item), file_menu); -</verb></tscreen> - -All that is left to do is to add the menu to the menubar, which is -accomplished using the function - -<tscreen> -void gtk_menu_bar_append( GtkMenuBar *menu_bar, - GtkWidget *menu_item ); -</tscreen> - -which in our case looks like this: - -<tscreen><verb> - gtk_menu_bar_append (GTK_MENU_BAR (menu_bar), file_item); -</verb></tscreen> - -If we wanted the menu right justified on the menubar, such as help -menus often are, we can use the following function (again on -<tt/file_item/ in the current example) before attaching it to the -menubar. - -<tscreen><verb> -void gtk_menu_item_right_justify( GtkMenuItem *menu_item ); -</verb></tscreen> - -Here is a summary of the steps needed to create a menu bar with menus -attached: - -<itemize> -<item> Create a new menu using gtk_menu_new() -<item> Use multiple calls to gtk_menu_item_new() for each item you -wish to have on your menu. And use gtk_menu_append() to put each of -these new items on to the menu. -<item> Create a menu item using gtk_menu_item_new(). This will be the -root of the menu, the text appearing here will be on the menubar -itself. -<item>Use gtk_menu_item_set_submenu() to attach the menu to the root -menu item (the one created in the above step). -<item> Create a new menubar using gtk_menu_bar_new. This step only -needs to be done once when creating a series of menus on one menu bar. -<item> Use gtk_menu_bar_append() to put the root menu onto the menubar. -</itemize> - -Creating a popup menu is nearly the same. The difference is that the -menu is not posted "automatically" by a menubar, but explicitly by -calling the function gtk_menu_popup() from a button-press event, for -example. Take these steps: - -<itemize> -<item>Create an event handling function. It needs to have the -prototype -<tscreen> -static gint handler (GtkWidget *widget, - GdkEvent *event); -</tscreen> -and it will use the event to find out where to pop up the menu. -<item>In the event handler, if the event is a mouse button press, -treat <tt>event</tt> as a button event (which it is) and use it as -shown in the sample code to pass information to gtk_menu_popup(). -<item>Bind that event handler to a widget with -<tscreen> - gtk_signal_connect_object (GTK_OBJECT (widget), "event", - GTK_SIGNAL_FUNC (handler), - GTK_OBJECT (menu)); -</tscreen> -where <tt>widget</tt> is the widget you are binding to, -<tt>handler</tt> is the handling function, and <tt>menu</tt> is a menu -created with gtk_menu_new(). This can be a menu which is also posted -by a menu bar, as shown in the sample code. -</itemize> - -<!-- ----------------------------------------------------------------- --> -<sect1>Manual Menu Example -<p> -That should about do it. Let's take a look at an example to help clarify. - -<tscreen><verb> -/* example-start menu menu.c */ - -#include <stdio.h> -#include <gtk/gtk.h> - -static gint button_press (GtkWidget *, GdkEvent *); -static void menuitem_response (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); - - /* 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 Menu Test"); - gtk_signal_connect (GTK_OBJECT (window), "delete_event", - (GtkSignalFunc) gtk_main_quit, NULL); - - /* Init the menu-widget, and remember -- never - * gtk_show_widget() the menu widget!! - * This is the menu that holds the menu items, the one that - * will pop up when you click on the "Root Menu" in the app */ - menu = gtk_menu_new (); - - /* Next we make a little loop that makes three menu-entries for "test-menu". - * Notice the call to gtk_menu_append. Here we are adding a list of - * menu items to our menu. Normally, we'd also catch the "clicked" - * signal on each of the menu items and setup a callback for it, - * but it's omitted here to save space. */ - - for (i = 0; i < 3; i++) - { - /* Copy the names to the buf. */ - sprintf (buf, "Test-undermenu - %d", i); - - /* Create a new menu-item with a name... */ - menu_items = gtk_menu_item_new_with_label (buf); - - /* ...and add it to the menu. */ - gtk_menu_append (GTK_MENU (menu), menu_items); - - /* Do something interesting when the menuitem is selected */ - gtk_signal_connect_object (GTK_OBJECT (menu_items), "activate", - GTK_SIGNAL_FUNC (menuitem_response), (gpointer) g_strdup (buf)); - - /* Show the widget */ - gtk_widget_show (menu_items); - } - - /* This is the root menu, and will be the label - * displayed on the menu bar. There won't be a signal handler attached, - * as it only pops up the rest of the menu when pressed. */ - root_menu = gtk_menu_item_new_with_label ("Root Menu"); - - gtk_widget_show (root_menu); - - /* Now we specify that we want our newly created "menu" to be the menu - * for the "root menu" */ - gtk_menu_item_set_submenu (GTK_MENU_ITEM (root_menu), menu); - - /* A vbox to put a menu and a button in: */ - vbox = gtk_vbox_new (FALSE, 0); - gtk_container_add (GTK_CONTAINER (window), vbox); - gtk_widget_show (vbox); - - /* Create a menu-bar to hold the menus and add it to our main window */ - menu_bar = gtk_menu_bar_new (); - gtk_box_pack_start (GTK_BOX (vbox), menu_bar, FALSE, FALSE, 2); - gtk_widget_show (menu_bar); - - /* Create a button to which to attach menu as a popup */ - 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); - - /* And finally we append the menu-item to the menu-bar -- this is the - * "root" menu-item I have been raving about =) */ - gtk_menu_bar_append (GTK_MENU_BAR (menu_bar), root_menu); - - /* always display the window as the last step so it all splashes on - * the screen at once. */ - gtk_widget_show (window); - - gtk_main (); - - return(0); -} - -/* Respond to a button-press by posting a menu passed in as widget. - * - * Note that the "widget" argument is the menu being posted, NOT - * the button that was pressed. - */ - -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); - /* Tell calling code that we have handled this event; the buck - * stops here. */ - return TRUE; - } - - /* Tell calling code that we have not handled this event; pass it on. */ - return FALSE; -} - - -/* Print a string when a menu item is selected */ - -static void menuitem_response( gchar *string ) -{ - printf ("%s\n", string); -} -/* example-end */ -</verb></tscreen> - -You may also set a menu item to be insensitive and, using an accelerator -table, bind keys to menu functions. - -<!-- ----------------------------------------------------------------- --> -<sect1>Using ItemFactory -<p> -Now that we've shown you the hard way, here's how you do it using the -gtk_item_factory calls. - -<!-- ----------------------------------------------------------------- --> -<sect1>Item Factory Example -<p> -Here is an example using the GTK item factory. - -<tscreen><verb> -/* example-start menu itemfactory.c */ - -#include <gtk/gtk.h> -#include <strings.h> - -/* Obligatory basic callback */ -static void print_hello( GtkWidget *w, - gpointer data ) -{ - g_message ("Hello, World!\n"); -} - -/* This is the GtkItemFactoryEntry structure used to generate new menus. - Item 1: The menu path. The letter after the underscore indicates an - accelerator key once the menu is open. - Item 2: The accelerator key for the entry - Item 3: The callback function. - Item 4: The callback action. This changes the parameters with - which the function is called. The default is 0. - Item 5: The item type, used to define what kind of an item it is. - Here are the possible values: - - NULL -> "<Item>" - "" -> "<Item>" - "<Title>" -> create a title item - "<Item>" -> create a simple item - "<CheckItem>" -> create a check item - "<ToggleItem>" -> create a toggle item - "<RadioItem>" -> create a radio item - <path> -> path of a radio item to link against - "<Separator>" -> create a separator - "<Branch>" -> create an item to hold sub items (optional) - "<LastBranch>" -> create a right justified branch -*/ - -static GtkItemFactoryEntry menu_items[] = { - { "/_File", NULL, NULL, 0, "<Branch>" }, - { "/File/_New", "<control>N", print_hello, 0, NULL }, - { "/File/_Open", "<control>O", print_hello, 0, NULL }, - { "/File/_Save", "<control>S", print_hello, 0, NULL }, - { "/File/Save _As", NULL, NULL, 0, NULL }, - { "/File/sep1", NULL, NULL, 0, "<Separator>" }, - { "/File/Quit", "<control>Q", gtk_main_quit, 0, NULL }, - { "/_Options", NULL, NULL, 0, "<Branch>" }, - { "/Options/Test", NULL, NULL, 0, NULL }, - { "/_Help", NULL, NULL, 0, "<LastBranch>" }, - { "/_Help/About", NULL, NULL, 0, NULL }, -}; - - -void get_main_menu( GtkWidget *window, - GtkWidget **menubar ) -{ - GtkItemFactory *item_factory; - GtkAccelGroup *accel_group; - gint nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]); - - accel_group = gtk_accel_group_new (); - - /* This function initializes the item factory. - Param 1: The type of menu - can be GTK_TYPE_MENU_BAR, GTK_TYPE_MENU, - or GTK_TYPE_OPTION_MENU. - Param 2: The path of the menu. - Param 3: A pointer to a gtk_accel_group. The item factory sets up - the accelerator table while generating menus. - */ - - item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", - accel_group); - - /* This function generates the menu items. Pass the item factory, - the number of items in the array, the array itself, and any - callback data for the the menu items. */ - gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL); - - /* Attach the new accelerator group to the window. */ - gtk_window_add_accel_group (GTK_WINDOW (window), accel_group); - - if (menubar) - /* Finally, return the actual menu bar created by the item factory. */ - *menubar = gtk_item_factory_get_widget (item_factory, "<main>"); -} - -int main( int argc, - char *argv[] ) -{ - GtkWidget *window; - GtkWidget *main_vbox; - GtkWidget *menubar; - - gtk_init (&argc, &argv); - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_signal_connect (GTK_OBJECT (window), "destroy", - GTK_SIGNAL_FUNC (gtk_main_quit), - "WM destroy"); - gtk_window_set_title (GTK_WINDOW(window), "Item 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 (window, &menubar); - gtk_box_pack_start (GTK_BOX (main_vbox), menubar, FALSE, TRUE, 0); - gtk_widget_show (menubar); - - gtk_widget_show (window); - gtk_main (); - - return(0); -} -/* example-end */ -</verb></tscreen> - - -For now, there's only this example. An explanation and lots 'o' comments -will follow later. - -<!-- ***************************************************************** --> -<sect> Text Widget -<!-- ***************************************************************** --> -<p> -The Text widget allows multiple lines of text to be displayed and -edited. It supports both multi-colored and multi-font text, allowing -them to be mixed in any way we wish. It also has a wide set of key -based text editing commands, which are compatible with Emacs. - -The text widget supports full cut-and-paste facilities, including the -use of double- and triple-click to select a word and a whole line, -respectively. - -<!-- ----------------------------------------------------------------- --> -<sect1>Creating and Configuring a Text box -<p> -There is only one function for creating a new Text widget. - -<tscreen><verb> -GtkWidget *gtk_text_new( GtkAdjustment *hadj, - GtkAdjustment *vadj ); -</verb></tscreen> - -The arguments allow us to give the Text widget pointers to Adjustments -that can be used to track the viewing position of the widget. Passing -NULL values to either or both of these arguments will cause the -gtk_text_new function to create its own. - -<tscreen><verb> -void gtk_text_set_adjustments( GtkText *text, - GtkAdjustment *hadj, - GtkAdjustment *vadj ); -</verb></tscreen> - -The above function allows the horizontal and vertical adjustments of a -text widget to be changed at any time. - -The text widget will not automatically create its own scrollbars when -the amount of text to be displayed is too long for the display -window. We therefore have to create and add them to the display layout -ourselves. - -<tscreen><verb> - vscrollbar = gtk_vscrollbar_new (GTK_TEXT(text)->vadj); - gtk_box_pack_start(GTK_BOX(hbox), vscrollbar, FALSE, FALSE, 0); - gtk_widget_show (vscrollbar); -</verb></tscreen> - -The above code snippet creates a new vertical scrollbar, and attaches -it to the vertical adjustment of the text widget, <tt/text/. It then -packs it into a box in the normal way. - -Note, currently the Text widget does not support horizontal -scrollbars. - -There are two main ways in which a Text widget can be used: to allow -the user to edit a body of text, or to allow us to display multiple -lines of text to the user. In order for us to switch between these -modes of operation, the text widget has the following function: - -<tscreen><verb> -void gtk_text_set_editable( GtkText *text, - gint editable ); -</verb></tscreen> - -The <tt/editable/ argument is a TRUE or FALSE value that specifies -whether the user is permitted to edit the contents of the Text -widget. When the text widget is editable, it will display a cursor at -the current insertion point. - -You are not, however, restricted to just using the text widget in -these two modes. You can toggle the editable state of the text widget -at any time, and can insert text at any time. - -The text widget wraps lines of text that are too long to fit onto a -single line of the display window. Its default behaviour is to break -words across line breaks. This can be changed using the next function: - -<tscreen><verb> -void gtk_text_set_word_wrap( GtkText *text, - gint word_wrap ); -</verb></tscreen> - -Using this function allows us to specify that the text widget should -wrap long lines on word boundaries. The <tt/word_wrap/ argument is a -TRUE or FALSE value. - -<!-- ----------------------------------------------------------------- --> -<sect1>Text Manipulation -<P> -The current insertion point of a Text widget can be set using -<tscreen><verb> -void gtk_text_set_point( GtkText *text, - guint index ); -</verb></tscreen> - -where <tt/index/ is the position to set the insertion point. - -Analogous to this is the function for getting the current insertion -point: - -<tscreen><verb> -guint gtk_text_get_point( GtkText *text ); -</verb></tscreen> - -A function that is useful in combination with the above two functions -is - -<tscreen><verb> -guint gtk_text_get_length( GtkText *text ); -</verb></tscreen> - -which returns the current length of the Text widget. The length is the -number of characters that are within the text block of the widget, -including characters such as newline, which marks the end of -lines. - -In order to insert text at the current insertion point of a Text -widget, the function gtk_text_insert is used, which also allows us to -specify background and foreground colors and a font for the text. - -<tscreen><verb> -void gtk_text_insert( GtkText *text, - GdkFont *font, - GdkColor *fore, - GdkColor *back, - const char *chars, - gint length ); -</verb></tscreen> - -Passing a value of <tt/NULL/ in as the value for the foreground color, -background color or font will result in the values set within the -widget style to be used. Using a value of <tt/-1/ for the length -parameter will result in the whole of the text string given being -inserted. - -The text widget is one of the few within GTK that redraws itself -dynamically, outside of the gtk_main function. This means that all -changes to the contents of the text widget take effect -immediately. This may be undesirable when performing multiple changes -to the text widget. In order to allow us to perform multiple updates -to the text widget without it continuously redrawing, we can freeze -the widget, which temporarily stops it from automatically redrawing -itself every time it is changed. We can then thaw the widget after our -updates are complete. - -The following two functions perform this freeze and thaw action: - -<tscreen><verb> -void gtk_text_freeze( GtkText *text ); - -void gtk_text_thaw( GtkText *text ); -</verb></tscreen> - -Text is deleted from the text widget relative to the current insertion -point by the following two functions. The return value is a TRUE or -FALSE indicator of whether the operation was successful. - -<tscreen><verb> -gint gtk_text_backward_delete( GtkText *text, - guint nchars ); - -gint gtk_text_forward_delete ( GtkText *text, - guint nchars ); -</verb></tscreen> - -If you want to retrieve the contents of the text widget, then the -macro <tt/GTK_TEXT_INDEX(t, index)/ allows you to retrieve the -character at position <tt/index/ within the text widget <tt/t/. - -To retrieve larger blocks of text, we can use the function - -<tscreen><verb> -gchar *gtk_editable_get_chars( GtkEditable *editable, - gint start_pos, - gint end_pos ); -</verb></tscreen> - -This is a function of the parent class of the text widget. A value of --1 as <tt/end_pos/ signifies the end of the text. The index of the -text starts at 0. - -The function allocates a new chunk of memory for the text block, so -don't forget to free it with a call to g_free when you have finished -with it. - -<!-- ----------------------------------------------------------------- --> -<sect1>Keyboard Shortcuts -<p> -The text widget has a number of pre-installed keyboard shortcuts for -common editing, motion and selection functions. These are accessed -using Control and Alt key combinations. - -In addition to these, holding down the Control key whilst using cursor -key movement will move the cursor by words rather than -characters. Holding down Shift whilst using cursor movement will -extend the selection. - -<sect2>Motion Shortcuts -<p> -<itemize> -<item> Ctrl-A Beginning of line -<item> Ctrl-E End of line -<item> Ctrl-N Next Line -<item> Ctrl-P Previous Line -<item> Ctrl-B Backward one character -<item> Ctrl-F Forward one character -<item> Alt-B Backward one word -<item> Alt-F Forward one word -</itemize> - -<sect2>Editing Shortcuts -<p> -<itemize> -<item> Ctrl-H Delete Backward Character (Backspace) -<item> Ctrl-D Delete Forward Character (Delete) -<item> Ctrl-W Delete Backward Word -<item> Alt-D Delete Forward Word -<item> Ctrl-K Delete to end of line -<item> Ctrl-U Delete line -</itemize> - -<sect2>Selection Shortcuts -<p> -<itemize> -<item> Ctrl-X Cut to clipboard -<item> Ctrl-C Copy to clipboard -<item> Ctrl-V Paste from clipboard -</itemize> - -<!-- ----------------------------------------------------------------- --> -<sect1>A GtkText Example -<p> -<tscreen><verb> -/* example-start text text.c */ - -/* text.c */ - -#include <stdio.h> -#include <gtk/gtk.h> - -void text_toggle_editable (GtkWidget *checkbutton, - GtkWidget *text) -{ - gtk_text_set_editable(GTK_TEXT(text), - GTK_TOGGLE_BUTTON(checkbutton)->active); -} - -void text_toggle_word_wrap (GtkWidget *checkbutton, - GtkWidget *text) -{ - gtk_text_set_word_wrap(GTK_TEXT(text), - GTK_TOGGLE_BUTTON(checkbutton)->active); -} - -void close_application( GtkWidget *widget, - gpointer data ) -{ - gtk_main_quit(); -} - -int main( int argc, - char *argv[] ) -{ - GtkWidget *window; - GtkWidget *box1; - GtkWidget *box2; - GtkWidget *hbox; - GtkWidget *button; - GtkWidget *check; - GtkWidget *separator; - GtkWidget *table; - GtkWidget *vscrollbar; - GtkWidget *text; - GdkColormap *cmap; - GdkColor color; - GdkFont *fixed_font; - - FILE *infile; - - gtk_init (&argc, &argv); - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_widget_set_usize (window, 600, 500); - gtk_window_set_policy (GTK_WINDOW(window), TRUE, TRUE, FALSE); - gtk_signal_connect (GTK_OBJECT (window), "destroy", - GTK_SIGNAL_FUNC(close_application), - NULL); - gtk_window_set_title (GTK_WINDOW (window), "Text Widget Example"); - gtk_container_set_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_set_border_width (GTK_CONTAINER (box2), 10); - gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0); - gtk_widget_show (box2); - - - table = gtk_table_new (2, 2, FALSE); - gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2); - gtk_table_set_col_spacing (GTK_TABLE (table), 0, 2); - gtk_box_pack_start (GTK_BOX (box2), table, TRUE, TRUE, 0); - gtk_widget_show (table); - - /* Create the GtkText widget */ - text = gtk_text_new (NULL, NULL); - gtk_text_set_editable (GTK_TEXT (text), TRUE); - gtk_table_attach (GTK_TABLE (table), text, 0, 1, 0, 1, - GTK_EXPAND | GTK_SHRINK | GTK_FILL, - GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0); - gtk_widget_show (text); - - /* Add a vertical scrollbar to the GtkText widget */ - vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj); - gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1, - GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0); - gtk_widget_show (vscrollbar); - - /* Get the system color map and allocate the color red */ - cmap = gdk_colormap_get_system(); - color.red = 0xffff; - color.green = 0; - color.blue = 0; - if (!gdk_color_alloc(cmap, &color)) { - g_error("couldn't allocate color"); - } - - /* Load a fixed font */ - fixed_font = gdk_font_load ("-misc-fixed-medium-r-*-*-*-140-*-*-*-*-*-*"); - - /* Realizing a widget creates a window for it, - * ready for us to insert some text */ - gtk_widget_realize (text); - - /* Freeze the text widget, ready for multiple updates */ - gtk_text_freeze (GTK_TEXT (text)); - - /* Insert some colored text */ - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "Supports ", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &color, NULL, - "colored ", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "text and different ", -1); - gtk_text_insert (GTK_TEXT (text), fixed_font, &text->style->black, NULL, - "fonts\n\n", -1); - - /* Load the file text.c into the text window */ - - infile = fopen("text.c", "r"); - - if (infile) { - char buffer[1024]; - int nchars; - - while (1) - { - nchars = fread(buffer, 1, 1024, infile); - gtk_text_insert (GTK_TEXT (text), fixed_font, NULL, - NULL, buffer, nchars); - - if (nchars < 1024) - break; - } - - fclose (infile); - } - - /* Thaw the text widget, allowing the updates to become visible */ - gtk_text_thaw (GTK_TEXT (text)); - - hbox = gtk_hbutton_box_new (); - gtk_box_pack_start (GTK_BOX (box2), hbox, FALSE, FALSE, 0); - gtk_widget_show (hbox); - - check = gtk_check_button_new_with_label("Editable"); - gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, FALSE, 0); - gtk_signal_connect (GTK_OBJECT(check), "toggled", - GTK_SIGNAL_FUNC(text_toggle_editable), text); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE); - gtk_widget_show (check); - check = gtk_check_button_new_with_label("Wrap Words"); - gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, TRUE, 0); - gtk_signal_connect (GTK_OBJECT(check), "toggled", - GTK_SIGNAL_FUNC(text_toggle_word_wrap), text); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), FALSE); - gtk_widget_show (check); - - 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_set_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 (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC(close_application), - NULL); - 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); -} -/* example-end */ -</verb></tscreen> - - -<!-- ***************************************************************** --> -<sect> Undocumented Widgets -<!-- ***************************************************************** --> -<p> -These all require authors! :) Please consider contributing to our -tutorial. - -If you must use one of these widgets that are undocumented, I strongly -suggest you take a look at their respective header files in the GTK -distribution. GTK's function names are very descriptive. Once you -have an understanding of how things work, it's not difficult to figure -out how to use a widget simply by looking at its function -declarations. This, along with a few examples from others' code, and -it should be no problem. - -When you do come to understand all the functions of a new undocumented -widget, please consider writing a tutorial on it so others may benefit -from your time. - -<!-- ----------------------------------------------------------------- --> -<sect1> CTree -<p> -<!-- ----------------------------------------------------------------- --> -<sect1> Curves -<p> -<!-- ----------------------------------------------------------------- --> -<sect1> Drawing Area -<p> -<!-- ----------------------------------------------------------------- --> -<sect1> Font Selection Dialog -<p> -<!-- ----------------------------------------------------------------- --> -<sect1> Gamma Curve -<p> -<!-- ----------------------------------------------------------------- --> -<sect1> Image -<p> -<!-- ----------------------------------------------------------------- --> -<sect1> Packer -<p> -<!-- ----------------------------------------------------------------- --> -<sect1> Plugs and Sockets -<p> -<!-- ----------------------------------------------------------------- --> -<sect1> Preview -<p> - -<!-- - -(This may need to be rewritten to follow the style of the rest of the tutorial) - -<tscreen><verb> - -Previews serve a number of purposes in GIMP/GTK. The most important one is -this. High quality images may take up to tens of megabytes of memory - easily! -Any operation on an image that big is bound to take a long time. If it takes -you 5-10 trial-and-errors (i.e., 10-20 steps, since you have to revert after -you make an error) to choose the desired modification, it make take you -literally hours to make the right one - if you don't run out of memory -first. People who have spent hours in color darkrooms know the feeling. -Previews to the rescue! - -But the annoyance of the delay is not the only issue. Oftentimes it is -helpful to compare the Before and After versions side-by-side or at least -back-to-back. If you're working with big images and 10 second delays, -obtaining the Before and After impressions is, to say the least, difficult. -For 30M images (4"x6", 600dpi, 24 bit) the side-by-side comparison is right -out for most people, while back-to-back is more like back-to-1001, 1002, -..., 1010-back! Previews to the rescue! - -But there's more. Previews allow for side-by-side pre-previews. In other -words, you write a plug-in (e.g., the filterpack simulation) which would have -a number of here's-what-it-would-look-like-if-you-were-to-do-this previews. -An approach like this acts as a sort of a preview palette and is very -effective for subtle changes. Let's go previews! - -There's more. For certain plug-ins real-time image-specific human -intervention maybe necessary. In the SuperNova plug-in, for example, the -user is asked to enter the coordinates of the center of the future -supernova. The easiest way to do this, really, is to present the user with a -preview and ask him to interactively select the spot. Let's go previews! - -Finally, a couple of misc uses. One can use previews even when not working -with big images. For example, they are useful when rendering complicated -patterns. (Just check out the venerable Diffraction plug-in + many other -ones!) As another example, take a look at the colormap rotation plug-in -(work in progress). You can also use previews for little logos inside you -plug-ins and even for an image of yourself, The Author. Let's go previews! - -When Not to Use Previews - -Don't use previews for graphs, drawing, etc. GDK is much faster for that. Use -previews only for rendered images! - -Let's go previews! - -You can stick a preview into just about anything. In a vbox, an hbox, a -table, a button, etc. But they look their best in tight frames around them. -Previews by themselves do not have borders and look flat without them. (Of -course, if the flat look is what you want...) Tight frames provide the -necessary borders. - - [Image][Image] - -Previews in many ways are like any other widgets in GTK (whatever that -means) except they possess an additional feature: they need to be filled with -some sort of an image! First, we will deal exclusively with the GTK aspect -of previews and then we'll discuss how to fill them. - -GtkWidget *preview! - -Without any ado: - - /* Create a preview widget, - set its size, an show it */ -GtkWidget *preview; -preview=gtk_preview_new(GTK_PREVIEW_COLOR) - /*Other option: - GTK_PREVIEW_GRAYSCALE);*/ -gtk_preview_size (GTK_PREVIEW (preview), WIDTH, HEIGHT); -gtk_widget_show(preview); -my_preview_rendering_function(preview); - -Oh yeah, like I said, previews look good inside frames, so how about: - -GtkWidget *create_a_preview(int Width, - int Height, - int Colorfulness) -{ - GtkWidget *preview; - GtkWidget *frame; - - frame = gtk_frame_new(NULL); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); - gtk_container_set_border_width (GTK_CONTAINER(frame),0); - gtk_widget_show(frame); - - preview=gtk_preview_new (Colorfulness?GTK_PREVIEW_COLOR - :GTK_PREVIEW_GRAYSCALE); - gtk_preview_size (GTK_PREVIEW (preview), Width, Height); - gtk_container_add(GTK_CONTAINER(frame),preview); - gtk_widget_show(preview); - - my_preview_rendering_function(preview); - return frame; -} - -That's my basic preview. This routine returns the "parent" frame so you can -place it somewhere else in your interface. Of course, you can pass the -parent frame to this routine as a parameter. In many situations, however, -the contents of the preview are changed continually by your application. In -this case you may want to pass a pointer to the preview to a -"create_a_preview()" and thus have control of it later. - -One more important note that may one day save you a lot of time. Sometimes -it is desirable to label you preview. For example, you may label the preview -containing the original image as "Original" and the one containing the -modified image as "Less Original". It might occur to you to pack the -preview along with the appropriate label into a vbox. The unexpected caveat -is that if the label is wider than the preview (which may happen for a -variety of reasons unforseeable to you, from the dynamic decision on the -size of the preview to the size of the font) the frame expands and no longer -fits tightly over the preview. The same problem can probably arise in other -situations as well. - - [Image] - -The solution is to place the preview and the label into a 2x1 table and by -attaching them with the following parameters (this is one possible variations -of course. The key is no GTK_FILL in the second attachment): - -gtk_table_attach(GTK_TABLE(table),label,0,1,0,1, - 0, - GTK_EXPAND|GTK_FILL, - 0,0); -gtk_table_attach(GTK_TABLE(table),frame,0,1,1,2, - GTK_EXPAND, - GTK_EXPAND, - 0,0); - - -And here's the result: - - [Image] - -Misc - -Making a preview clickable is achieved most easily by placing it in a -button. It also adds a nice border around the preview and you may not even -need to place it in a frame. See the Filter Pack Simulation plug-in for an -example. - -This is pretty much it as far as GTK is concerned. - -Filling In a Preview - -In order to familiarize ourselves with the basics of filling in previews, -let's create the following pattern (contrived by trial and error): - - [Image] - -void -my_preview_rendering_function(GtkWidget *preview) -{ -#define SIZE 100 -#define HALF (SIZE/2) - - guchar *row=(guchar *) malloc(3*SIZE); /* 3 bits per dot */ - gint i, j; /* Coordinates */ - double r, alpha, x, y; - - if (preview==NULL) return; /* I usually add this when I want */ - /* to avoid silly crashes. You */ - /* should probably make sure that */ - /* everything has been nicely */ - /* initialized! */ - for (j=0; j < ABS(cos(2*alpha)) ) { /* Are we inside the shape? */ - /* glib.h contains ABS(x). */ - row[i*3+0] = sqrt(1-r)*255; /* Define Red */ - row[i*3+1] = 128; /* Define Green */ - row[i*3+2] = 224; /* Define Blue */ - } /* "+0" is for alignment! */ - else { - row[i*3+0] = r*255; - row[i*3+1] = ABS(sin((float)i/SIZE*2*PI))*255; - row[i*3+2] = ABS(sin((float)j/SIZE*2*PI))*255; - } - } - gtk_preview_draw_row( GTK_PREVIEW(preview),row,0,j,SIZE); - /* Insert "row" into "preview" starting at the point with */ - /* coordinates (0,j) first column, j_th row extending SIZE */ - /* pixels to the right */ - } - - free(row); /* save some space */ - gtk_widget_draw(preview,NULL); /* what does this do? */ - gdk_flush(); /* or this? */ -} - -Non-GIMP users can have probably seen enough to do a lot of things already. -For the GIMP users I have a few pointers to add. - -Image Preview - -It is probably wise to keep a reduced version of the image around with just -enough pixels to fill the preview. This is done by selecting every n'th -pixel where n is the ratio of the size of the image to the size of the -preview. All further operations (including filling in the previews) are then -performed on the reduced number of pixels only. The following is my -implementation of reducing the image. (Keep in mind that I've had only basic -C!) - -(UNTESTED CODE ALERT!!!) - -typedef struct { - gint width; - gint height; - gint bbp; - guchar *rgb; - guchar *mask; -} ReducedImage; - -enum { - SELECTION_ONLY, - SELECTION_IN_CONTEXT, - ENTIRE_IMAGE -}; - -ReducedImage *Reduce_The_Image(GDrawable *drawable, - GDrawable *mask, - gint LongerSize, - gint Selection) -{ - /* This function reduced the image down to the the selected preview size */ - /* The preview size is determine by LongerSize, i.e., the greater of the */ - /* two dimensions. Works for RGB images only! */ - gint RH, RW; /* Reduced height and reduced width */ - gint width, height; /* Width and Height of the area being reduced */ - gint bytes=drawable->bpp; - ReducedImage *temp=(ReducedImage *)malloc(sizeof(ReducedImage)); - - guchar *tempRGB, *src_row, *tempmask, *src_mask_row,R,G,B; - gint i, j, whichcol, whichrow, x1, x2, y1, y2; - GPixelRgn srcPR, srcMask; - gint NoSelectionMade=TRUE; /* Assume that we're dealing with the entire */ - /* image. */ - - gimp_drawable_mask_bounds (drawable->id, &x1, &y1, &x2, &y2); - width = x2-x1; - height = y2-y1; - /* If there's a SELECTION, we got its bounds!) - - if (width != drawable->width && height != drawable->height) - NoSelectionMade=FALSE; - /* Become aware of whether the user has made an active selection */ - /* This will become important later, when creating a reduced mask. */ - - /* If we want to preview the entire image, overrule the above! */ - /* Of course, if no selection has been made, this does nothing! */ - if (Selection==ENTIRE_IMAGE) { - x1=0; - x2=drawable->width; - y1=0; - y2=drawable->height; - } - - /* If we want to preview a selection with some surrounding area we */ - /* have to expand it a little bit. Consider it a bit of a riddle. */ - if (Selection==SELECTION_IN_CONTEXT) { - x1=MAX(0, x1-width/2.0); - x2=MIN(drawable->width, x2+width/2.0); - y1=MAX(0, y1-height/2.0); - y2=MIN(drawable->height, y2+height/2.0); - } - - /* How we can determine the width and the height of the area being */ - /* reduced. */ - width = x2-x1; - height = y2-y1; - - /* The lines below determine which dimension is to be the longer */ - /* side. The idea borrowed from the supernova plug-in. I suspect I */ - /* could've thought of it myself, but the truth must be told. */ - /* Plagiarism stinks! */ - if (width>height) { - RW=LongerSize; - RH=(float) height * (float) LongerSize/ (float) width; - } - else { - RH=LongerSize; - RW=(float)width * (float) LongerSize/ (float) height; - } - - /* The entire image is stretched into a string! */ - tempRGB = (guchar *) malloc(RW*RH*bytes); - tempmask = (guchar *) malloc(RW*RH); - - gimp_pixel_rgn_init (&srcPR, drawable, x1, y1, width, height, - FALSE, FALSE); - gimp_pixel_rgn_init (&srcMask, mask, x1, y1, width, height, - FALSE, FALSE); - - /* Grab enough to save a row of image and a row of mask. */ - src_row = (guchar *) malloc (width*bytes); - src_mask_row = (guchar *) malloc (width); - - for (i=0; i < RH; i++) { - whichrow=(float)i*(float)height/(float)RH; - gimp_pixel_rgn_get_row (&srcPR, src_row, x1, y1+whichrow, width); - gimp_pixel_rgn_get_row (&srcMask, src_mask_row, x1, y1+whichrow, width); - - for (j=0; j < RW; j++) { - whichcol=(float)j*(float)width/(float)RW; - - /* No selection made = each point is completely selected! */ - if (NoSelectionMade) - tempmask[i*RW+j]=255; - else - tempmask[i*RW+j]=src_mask_row[whichcol]; - - /* Add the row to the one long string which now contains the image! */ - tempRGB[i*RW*bytes+j*bytes+0]=src_row[whichcol*bytes+0]; - tempRGB[i*RW*bytes+j*bytes+1]=src_row[whichcol*bytes+1]; - tempRGB[i*RW*bytes+j*bytes+2]=src_row[whichcol*bytes+2]; - - /* Hold on to the alpha as well */ - if (bytes==4) - tempRGB[i*RW*bytes+j*bytes+3]=src_row[whichcol*bytes+3]; - } - } - temp->bpp=bytes; - temp->width=RW; - temp->height=RH; - temp->rgb=tempRGB; - temp->mask=tempmask; - return temp; -} - -The following is a preview function which used the same ReducedImage type! -Note that it uses fakes transparency (if one is present by means of -fake_transparency which is defined as follows: - -gint fake_transparency(gint i, gint j) -{ - if ( ((i%20)- 10) * ((j%20)- 10)>0 ) - return 64; - else - return 196; -} - -Now here's the preview function: - -void -my_preview_render_function(GtkWidget *preview, - gint changewhat, - gint changewhich) -{ - gint Inten, bytes=drawable->bpp; - gint i, j, k; - float partial; - gint RW=reduced->width; - gint RH=reduced->height; - guchar *row=malloc(bytes*RW);; - - - for (i=0; i < RH; i++) { - for (j=0; j < RW; j++) { - - row[j*3+0] = reduced->rgb[i*RW*bytes + j*bytes + 0]; - row[j*3+1] = reduced->rgb[i*RW*bytes + j*bytes + 1]; - row[j*3+2] = reduced->rgb[i*RW*bytes + j*bytes + 2]; - - if (bytes==4) - for (k=0; k<3; k++) { - float transp=reduced->rgb[i*RW*bytes+j*bytes+3]/255.0; - row[3*j+k]=transp*a[3*j+k]+(1-transp)*fake_transparency(i,j); - } - } - gtk_preview_draw_row( GTK_PREVIEW(preview),row,0,i,RW); - } - - free(a); - gtk_widget_draw(preview,NULL); - gdk_flush(); -} - -Applicable Routines - -guint gtk_preview_get_type (void); -/* No idea */ -void gtk_preview_uninit (void); -/* No idea */ -GtkWidget* gtk_preview_new (GtkPreviewType type); -/* Described above */ -void gtk_preview_size (GtkPreview *preview, - gint width, - gint height); -/* Allows you to resize an existing preview. */ -/* Apparently there's a bug in GTK which makes */ -/* this process messy. A way to clean up a mess */ -/* is to manually resize the window containing */ -/* the preview after resizing the preview. */ - -void gtk_preview_put (GtkPreview *preview, - GdkWindow *window, - GdkGC *gc, - gint srcx, - gint srcy, - gint destx, - gint desty, - gint width, - gint height); -/* No idea */ - -void gtk_preview_put_row (GtkPreview *preview, - guchar *src, - guchar *dest, - gint x, - gint y, - gint w); -/* No idea */ - -void gtk_preview_draw_row (GtkPreview *preview, - guchar *data, - gint x, - gint y, - gint w); -/* Described in the text */ - -void gtk_preview_set_expand (GtkPreview *preview, - gint expand); -/* No idea */ - -/* No clue for any of the below but */ -/* should be standard for most widgets */ -void gtk_preview_set_gamma (double gamma); -void gtk_preview_set_color_cube (guint nred_shades, - guint ngreen_shades, - guint nblue_shades, - guint ngray_shades); -void gtk_preview_set_install_cmap (gint install_cmap); -void gtk_preview_set_reserved (gint nreserved); -GdkVisual* gtk_preview_get_visual (void); -GdkColormap* gtk_preview_get_cmap (void); -GtkPreviewInfo* gtk_preview_get_info (void); - -That's all, folks! - -</verb></tscreen> - ---> - -<!-- ***************************************************************** --> -<sect>Setting Widget Attributes<label id="sec_setting_widget_attributes"> -<!-- ***************************************************************** --> -<p> -This describes the functions used to operate on widgets. These can be -used to set style, padding, size, etc. - -(Maybe I should make a whole section on accelerators.) - -<tscreen><verb> -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 ); -</verb></tscreen> - -<!-- ***************************************************************** --> -<sect>Timeouts, IO and Idle Functions<label id="sec_timeouts"> -<!-- ***************************************************************** --> - -<!-- ----------------------------------------------------------------- --> -<sect1>Timeouts -<p> -You may be wondering how you make GTK do useful work when in gtk_main. -Well, you have several options. Using the following function you can -create a timeout function that will be called every "interval" -milliseconds. - -<tscreen><verb> -gint gtk_timeout_add( guint32 interval, - GtkFunction function, - gpointer data ); -</verb></tscreen> - -The first argument is the number of milliseconds between calls to your -function. The second argument is the function you wish to have called, -and the third, the data passed to this callback function. The return -value is an integer "tag" which may be used to stop the timeout by -calling: - -<tscreen><verb> -void gtk_timeout_remove( gint tag ); -</verb></tscreen> - -You may also stop the timeout function by returning zero or FALSE from -your callback function. Obviously this means if you want your function -to continue to be called, it should return a non-zero value, -i.e., TRUE. - -The declaration of your callback should look something like this: - -<tscreen><verb> -gint timeout_callback( gpointer data ); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Monitoring IO -<p> -A nifty feature of GDK (the library that underlies GTK), is the -ability to have it check for data on a file descriptor for you (as -returned by open(2) or socket(2)). This is especially useful for -networking applications. The function: - -<tscreen><verb> -gint gdk_input_add( gint source, - GdkInputCondition condition, - GdkInputFunction function, - gpointer data ); -</verb></tscreen> - -Where the first argument is the file descriptor you wish to have -watched, and the second specifies what you want GDK to look for. This -may be one of: - -<itemize> -<item><tt/GDK_INPUT_READ/ - Call your function when there is data -ready for reading on your file descriptor. - -<item>><tt/GDK_INPUT_WRITE/ - Call your function when the file -descriptor is ready for writing. -</itemize> - -As I'm sure you've figured out already, the third argument is the -function you wish to have called when the above conditions are -satisfied, and the fourth is the data to pass to this function. - -The return value is a tag that may be used to stop GDK from monitoring -this file descriptor using the following function. - -<tscreen><verb> -void gdk_input_remove( gint tag ); -</verb></tscreen> - -The callback function should be declared as: - -<tscreen><verb> -void input_callback( gpointer data, - gint source, - GdkInputCondition condition ); -</verb></tscreen> - -Where <tt/source/ and <tt/condition/ are as specified above. - -<!-- ----------------------------------------------------------------- --> -<sect1>Idle Functions -<p> -<!-- TODO: Need to check on idle priorities - TRG --> -What if you have a function which you want to be called when nothing -else is happening ? - -<tscreen><verb> -gint gtk_idle_add( GtkFunction function, - gpointer data ); -</verb></tscreen> - -This causes GTK to call the specified function whenever nothing else -is happening. - -<tscreen><verb> -void gtk_idle_remove( gint tag ); -</verb></tscreen> - -I won't explain the meaning of the arguments as they follow very much -like the ones above. The function pointed to by the first argument to -gtk_idle_add will be called whenever the opportunity arises. As with -the others, returning FALSE will stop the idle function from being -called. - -<!-- ***************************************************************** --> -<sect>Advanced Event and Signal Handling<label id="sec_Adv_Events_and_Signals"> -<!-- ***************************************************************** --> - -<!-- ----------------------------------------------------------------- --> -<sect1>Signal Functions - -<!-- ----------------------------------------------------------------- --> -<sect2>Connecting and Disconnecting Signal Handlers -<p> - -<tscreen><verb> -guint gtk_signal_connect( GtkObject *object, - const gchar *name, - GtkSignalFunc func, - gpointer func_data ); - -guint gtk_signal_connect_after( GtkObject *object, - const gchar *name, - GtkSignalFunc func, - gpointer func_data ); - -guint gtk_signal_connect_object( GtkObject *object, - const gchar *name, - GtkSignalFunc func, - GtkObject *slot_object ); - -guint gtk_signal_connect_object_after( GtkObject *object, - const gchar *name, - GtkSignalFunc func, - GtkObject *slot_object ); - -guint gtk_signal_connect_full( GtkObject *object, - const gchar *name, - GtkSignalFunc func, - GtkCallbackMarshal marshal, - gpointer data, - GtkDestroyNotify destroy_func, - gint object_signal, - gint after ); - -guint gtk_signal_connect_interp( GtkObject *object, - const gchar *name, - GtkCallbackMarshal func, - gpointer data, - GtkDestroyNotify destroy_func, - gint after ); - -void gtk_signal_connect_object_while_alive( GtkObject *object, - const gchar *signal, - GtkSignalFunc func, - GtkObject *alive_object ); - -void gtk_signal_connect_while_alive( GtkObject *object, - const gchar *signal, - GtkSignalFunc func, - gpointer func_data, - GtkObject *alive_object ); - -void gtk_signal_disconnect( GtkObject *object, - guint handler_id ); - -void gtk_signal_disconnect_by_func( GtkObject *object, - GtkSignalFunc func, - gpointer data ); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect2>Blocking and Unblocking Signal Handlers -<p> -<tscreen><verb> -void gtk_signal_handler_block( GtkObject *object, - guint handler_id); - -void gtk_signal_handler_block_by_func( GtkObject *object, - GtkSignalFunc func, - gpointer data ); - -void gtk_signal_handler_block_by_data( GtkObject *object, - gpointer data ); - -void gtk_signal_handler_unblock( GtkObject *object, - guint handler_id ); - -void gtk_signal_handler_unblock_by_func( GtkObject *object, - GtkSignalFunc func, - gpointer data ); - -void gtk_signal_handler_unblock_by_data( GtkObject *object, - gpointer data ); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect2>Emitting and Stopping Signals -<p> -<tscreen><verb> -void gtk_signal_emit( GtkObject *object, - guint signal_id, - ... ); - -void gtk_signal_emit_by_name( GtkObject *object, - const gchar *name, - ... ); - -void gtk_signal_emitv( GtkObject *object, - guint signal_id, - GtkArg *params ); - -void gtk_signal_emitv_by_name( GtkObject *object, - const gchar *name, - GtkArg *params ); - -guint gtk_signal_n_emissions( GtkObject *object, - guint signal_id ); - -guint gtk_signal_n_emissions_by_name( GtkObject *object, - const gchar *name ); - -void gtk_signal_emit_stop( GtkObject *object, - guint signal_id ); - -void gtk_signal_emit_stop_by_name( GtkObject *object, - const gchar *name ); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Signal Emission and Propagation -<p> -Signal emission is the process whereby GTK runs all handlers for a -specific object and signal. - -First, note that the return value from a signal emission is the return -value of the <em>last</em> handler executed. Since event signals are -all of type <tt/GTK_RUN_LAST/, this will be the default (GTK supplied) -handler, unless you connect with gtk_signal_connect_after(). - -The way an event (say "button_press_event") is handled, is: -<itemize> -<item>Start with the widget where the event occured. - -<item>Emit the generic "event" signal. If that signal handler returns -a value of TRUE, stop all processing. - -<item>Otherwise, emit a specific, "button_press_event" signal. If that -returns TRUE, stop all processing. - -<item>Otherwise, go to the widget's parent, and repeat the above two -steps. - -<item>Continue until some signal handler returns TRUE, or until the -top-level widget is reached. -</itemize> - -Some consequences of the above are: -<itemize> -<item>Your handler's return value will have no effect if there is a -default handler, unless you connect with gtk_signal_connect_after(). - -<item>To prevent the default handler from being run, you need to -connect with gtk_signal_connect() and use -gtk_signal_emit_stop_by_name() - the return value only affects whether -the signal is propagated, not the current emission. -</itemize> - -<!-- ***************************************************************** --> -<sect>Managing Selections -<!-- ***************************************************************** --> - -<!-- ----------------------------------------------------------------- --> -<sect1> Overview -<p> -One type of interprocess communication supported by X and GTK is -<em>selections</em>. A selection identifies a chunk of data, for -instance, a portion of text, selected by the user in some fashion, for -instance, by dragging with the mouse. Only one application on a -display (the <em>owner</em>) can own a particular selection at one -time, so when a selection is claimed by one application, the previous -owner must indicate to the user that selection has been -relinquished. Other applications can request the contents of a -selection in different forms, called <em>targets</em>. There can be -any number of selections, but most X applications only handle one, the -<em>primary selection</em>. - -In most cases, it isn't necessary for a GTK application to deal with -selections itself. The standard widgets, such as the Entry widget, -already have the capability to claim the selection when appropriate -(e.g., when the user drags over text), and to retrieve the contents of -the selection owned by another widget or another application (e.g., -when the user clicks the second mouse button). However, there may be -cases in which you want to give other widgets the ability to supply -the selection, or you wish to retrieve targets not supported by -default. - -A fundamental concept needed to understand selection handling is that -of the <em>atom</em>. An atom is an integer that uniquely identifies a -string (on a certain display). Certain atoms are predefined by the X -server, and in some cases there are constants in <tt>gtk.h</tt> -corresponding to these atoms. For instance the constant -<tt>GDK_PRIMARY_SELECTION</tt> corresponds to the string "PRIMARY". -In other cases, you should use the functions -<tt>gdk_atom_intern()</tt>, to get the atom corresponding to a string, -and <tt>gdk_atom_name()</tt>, to get the name of an atom. Both -selections and targets are identified by atoms. - -<!-- ----------------------------------------------------------------- --> -<sect1> Retrieving the selection -<p> -Retrieving the selection is an asynchronous process. To start the -process, you call: - -<tscreen><verb> -gint gtk_selection_convert( GtkWidget *widget, - GdkAtom selection, - GdkAtom target, - guint32 time ); -</verb</tscreen> - -This <em>converts</em> the selection into the form specified by -<tt/target/. If at all possible, the time field should be the time -from the event that triggered the selection. This helps make sure that -events occur in the order that the user requested them. However, if it -is not available (for instance, if the conversion was triggered by a -"clicked" signal), then you can use the constant -<tt>GDK_CURRENT_TIME</tt>. - -When the selection owner responds to the request, a -"selection_received" signal is sent to your application. The handler -for this signal receives a pointer to a <tt>GtkSelectionData</tt> -structure, which is defined as: - -<tscreen><verb> -struct _GtkSelectionData -{ - GdkAtom selection; - GdkAtom target; - GdkAtom type; - gint format; - guchar *data; - gint length; -}; -</verb></tscreen> - -<tt>selection</tt> and <tt>target</tt> are the values you gave in your -<tt>gtk_selection_convert()</tt> call. <tt>type</tt> is an atom that -identifies the type of data returned by the selection owner. Some -possible values are "STRING", a string of latin-1 characters, "ATOM", -a series of atoms, "INTEGER", an integer, etc. Most targets can only -return one type. <tt/format/ gives the length of the units (for -instance characters) in bits. Usually, you don't care about this when -receiving data. <tt>data</tt> is a pointer to the returned data, and -<tt>length</tt> gives the length of the returned data, in bytes. If -<tt>length</tt> is negative, then an error occurred and the selection -could not be retrieved. This might happen if no application owned the -selection, or if you requested a target that the application didn't -support. The buffer is actually guaranteed to be one byte longer than -<tt>length</tt>; the extra byte will always be zero, so it isn't -necessary to make a copy of strings just to null terminate them. - -In the following example, we retrieve the special target "TARGETS", -which is a list of all targets into which the selection can be -converted. - -<tscreen><verb> -/* example-start selection gettargets.c */ - -#include <gtk/gtk.h> - -void selection_received( GtkWidget *widget, - GtkSelectionData *selection_data, - gpointer data ); - -/* Signal handler invoked when user clicks on the "Get Targets" button */ -void get_targets( GtkWidget *widget, - gpointer data ) -{ - static GdkAtom targets_atom = GDK_NONE; - - /* Get the atom corresponding to the string "TARGETS" */ - if (targets_atom == GDK_NONE) - targets_atom = gdk_atom_intern ("TARGETS", FALSE); - - /* And request the "TARGETS" target for the primary selection */ - gtk_selection_convert (widget, GDK_SELECTION_PRIMARY, targets_atom, - GDK_CURRENT_TIME); -} - -/* Signal handler called when the selections owner returns the data */ -void selection_received( GtkWidget *widget, - GtkSelectionData *selection_data, - gpointer data ) -{ - GdkAtom *atoms; - GList *item_list; - int i; - - /* **** IMPORTANT **** Check to see if retrieval succeeded */ - if (selection_data->length < 0) - { - g_print ("Selection retrieval failed\n"); - return; - } - /* Make sure we got the data in the expected form */ - if (selection_data->type != GDK_SELECTION_TYPE_ATOM) - { - g_print ("Selection \"TARGETS\" was not returned as atoms!\n"); - return; - } - - /* Print out the atoms we received */ - 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); - - /* Create the toplevel window */ - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_title (GTK_WINDOW (window), "Event Box"); - gtk_container_set_border_width (GTK_CONTAINER (window), 10); - - gtk_signal_connect (GTK_OBJECT (window), "destroy", - GTK_SIGNAL_FUNC (gtk_exit), NULL); - - /* Create a button the user can click to get targets */ - - 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; -} -/* example-end */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1> Supplying the selection -<p> -Supplying the selection is a bit more complicated. You must register -handlers that will be called when your selection is requested. For -each selection/target pair you will handle, you make a call to: - -<tscreen><verb> -void gtk_selection_add_target (GtkWidget *widget, - GdkAtom selection, - GdkAtom target, - guint info); -</verb></tscreen> - -<tt/widget/, <tt/selection/, and <tt/target/ identify the requests -this handler will manage. When a request for a selection is received, -the "selection_get" signal will be called. <tt/info/ can be used as an -enumerator to identify the specific target within the callback function. - -The callback function has the signature: - -<tscreen><verb> -void "selection_get" (GtkWidget *widget, - GtkSelectionData *selection_data, - guint info, - guint time); -</verb></tscreen> - -The GtkSelectionData is the same as above, but this time, we're -responsible for filling in the fields <tt/type/, <tt/format/, -<tt/data/, and <tt/length/. (The <tt/format/ field is actually -important here - the X server uses it to figure out whether the data -needs to be byte-swapped or not. Usually it will be 8 - <em/i.e./ a -character - or 32 - <em/i.e./ a. integer.) This is done by calling the -function: - -<tscreen><verb> -void gtk_selection_data_set( GtkSelectionData *selection_data, - GdkAtom type, - gint format, - guchar *data, - gint length ); -</verb></tscreen> - -This function takes care of properly making a copy of the data so that -you don't have to worry about keeping it around. (You should not fill -in the fields of the GtkSelectionData structure by hand.) - -When prompted by the user, you claim ownership of the selection by -calling: - -<tscreen><verb> -gint gtk_selection_owner_set( GtkWidget *widget, - GdkAtom selection, - guint32 time ); -</verb></tscreen> - -If another application claims ownership of the selection, you will -receive a "selection_clear_event". - -As an example of supplying the selection, the following program adds -selection functionality to a toggle button. When the toggle button is -depressed, the program claims the primary selection. The only target -supported (aside from certain targets like "TARGETS" supplied by GTK -itself), is the "STRING" target. When this target is requested, a -string representation of the time is returned. - -<tscreen><verb> -/* example-start selection setselection.c */ - -#include <gtk/gtk.h> -#include <time.h> - -/* Callback when the user toggles the selection */ -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); - /* if claiming the selection failed, we return the button to - the out state */ - if (!*have_selection) - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(widget), FALSE); - } - else - { - if (*have_selection) - { - /* Before clearing the selection by setting the owner to NULL, - we check if we are the actual 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; - } - } -} - -/* Called when another application claims the selection */ -gint selection_clear( GtkWidget *widget, - GdkEventSelection *event, - gint *have_selection ) -{ - *have_selection = FALSE; - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(widget), FALSE); - - return TRUE; -} - -/* Supplies the current time as the selection. */ -void selection_handle( GtkWidget *widget, - GtkSelectionData *selection_data, - guint info, - guint time_stamp, - gpointer data ) -{ - gchar *timestr; - time_t current_time; - - current_time = time(NULL); - timestr = asctime (localtime(&current_time)); - /* When we return a single string, it should not be null terminated. - That will be done for us */ - - 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); - - /* Create the toplevel window */ - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_title (GTK_WINDOW (window), "Event Box"); - gtk_container_set_border_width (GTK_CONTAINER (window), 10); - - gtk_signal_connect (GTK_OBJECT (window), "destroy", - GTK_SIGNAL_FUNC (gtk_exit), NULL); - - /* Create a toggle button to act as the 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_target (selection_button, - GDK_SELECTION_PRIMARY, - GDK_SELECTION_TYPE_STRING, - 1); - gtk_signal_connect (GTK_OBJECT(selection_button), "selection_get", - GTK_SIGNAL_FUNC (selection_handle), &have_selection); - - gtk_widget_show (selection_button); - gtk_widget_show (window); - - gtk_main (); - - return 0; -} -/* example-end */ -</verb></tscreen> - - -<!-- ***************************************************************** --> -<sect>GLib<label id="sec_glib"> -<!-- ***************************************************************** --> -<p> -GLib is a lower-level library that provides many useful definitions -and functions available for use when creating GDK and GTK -applications. These include definitions for basic types and their -limits, standard macros, type conversions, byte order, memory -allocation, warnings and assertions, message logging, timers, string -utilities, hook functions, a lexical scanner, dynamic loading of -modules, and automatic string completion. A number of data structures -(and their related operations) are also defined, including memory -chunks, doubly-linked lists, singly-linked lists, hash tables, strings -(which can grow dynamically), string chunks (groups of strings), -arrays (which can grow in size as elements are added), balanced binary -trees, N-ary trees, quarks (a two-way association of a string and a -unique integer identifier), keyed data lists (lists of data elements -accessible by a string or integer id), relations and tuples (tables of -data which can be indexed on any number of fields), and caches. - -A summary of some of GLib's capabilities follows; not every function, -data structure, or operation is covered here. For more complete -information about the GLib routines, see the GLib documentation. One -source of GLib documentation is <htmlurl url="http://www.gtk.org/" -name="http://www.gtk.org/">. - -If you are using a language other than C, you should consult your -language's binding documentation. In some cases your language may -have equivalent functionality built-in, while in other cases it may -not. - -<!-- ----------------------------------------------------------------- --> -<sect1>Definitions -<p> -Definitions for the extremes of many of the standard types are: - -<tscreen><verb> -G_MINFLOAT -G_MAXFLOAT -G_MINDOUBLE -G_MAXDOUBLE -G_MINSHORT -G_MAXSHORT -G_MININT -G_MAXINT -G_MINLONG -G_MAXLONG -</verb></tscreen> - -Also, the following typedefs. The ones left unspecified are dynamically set -depending on the architecture. Remember to avoid counting on the size of a -pointer if you want to be portable! E.g., a pointer on an Alpha is 8 -bytes, but 4 on Intel 80x86 family CPUs. - -<tscreen><verb> -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 -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Doubly Linked Lists -<p> -The following functions are used to create, manage, and destroy -standard doubly linked lists. Each element in the list contains a -piece of data, together with pointers which link to the previous and -next elements in the list. This enables easy movement in either -direction through the list. The data item is of type "gpointer", -which means the data can be a pointer to your real data or (through -casting) a numeric value (but do not assume that int and gpointer have -the same size!). These routines internally allocate list elements in -blocks, which is more efficient than allocating elements individually. - -There is no function to specifically create a list. Instead, simply -create a variable of type GList* and set its value to NULL; NULL is -considered to be the empty list. - -To add elements to a list, use the g_list_append(), g_list_prepend(), -g_list_insert(), or g_list_insert_sorted() routines. In all cases -they accept a pointer to the beginning of the list, and return the -(possibly changed) pointer to the beginning of the list. Thus, for -all of the operations that add or remove elements, be sure to save the -returned value! - -<tscreen><verb> -GList *g_list_append( GList *list, - gpointer data ); -</verb></tscreen> - -This adds a new element (with value <tt/data/) onto the end of the -list. - -<tscreen><verb> -GList *g_list_prepend( GList *list, - gpointer data ); -</verb></tscreen> - -This adds a new element (with value <tt/data/) to the beginning of the -list. - -<tscreen><verb> -GList *g_list_insert( GList *list, - gpointer data, - gint position ); - -</verb></tscreen> - -This inserts a new element (with value data) into the list at the -given position. If position is 0, this is just like g_list_prepend(); -if position is less than 0, this is just like g_list_append(). - -<tscreen><verb> -GList *g_list_remove( GList *list, - gpointer data ); -</verb></tscreen> - -This removes the element in the list with the value <tt/data/; -if the element isn't there, the list is unchanged. - -<tscreen><verb> -void g_list_free( GList *list ); -</verb></tscreen> - -This frees all of the memory used by a GList. If the list elements -refer to dynamically-allocated memory, then they should be freed -first. - -There are many other GLib functions that support doubly linked lists; -see the glib documentation for more information. Here are a few of -the more useful functions' signatures: - -<tscreen><verb> -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 ); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Singly Linked Lists -<p> -Many of the above functions for singly linked lists are identical to the -above. Here is a list of some of their operations: - -<tscreen><verb> -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 ); - -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Memory Management -<p> -<tscreen><verb> -gpointer g_malloc( gulong size ); -</verb></tscreen> - -This is a replacement for malloc(). You do not need to check the return -value as it is done for you in this function. If the memory allocation -fails for whatever reasons, your applications will be terminated. - -<tscreen><verb> -gpointer g_malloc0( gulong size ); -</verb></tscreen> - -Same as above, but zeroes the memory before returning a pointer to it. - -<tscreen><verb> -gpointer g_realloc( gpointer mem, - gulong size ); -</verb></tscreen> - -Relocates "size" bytes of memory starting at "mem". Obviously, the -memory should have been previously allocated. - -<tscreen><verb> -void g_free( gpointer mem ); -</verb></tscreen> - -Frees memory. Easy one. If <tt/mem/ is NULL it simply returns. - -<tscreen><verb> -void g_mem_profile( void ); -</verb></tscreen> - -Dumps a profile of used memory, but requires that you add <tt>#define -MEM_PROFILE</tt> to the top of glib/gmem.c and re-make and make install. - -<tscreen><verb> -void g_mem_check( gpointer mem ); -</verb></tscreen> - -Checks that a memory location is valid. Requires you add <tt>#define -MEM_CHECK</tt> to the top of gmem.c and re-make and make install. - -<!-- ----------------------------------------------------------------- --> -<sect1>Timers -<p> -Timer functions can be used to time operations (e.g., to see how much -time has elapsed). First, you create a new timer with g_timer_new(). -You can then use g_timer_start() to start timing an operation, -g_timer_stop() to stop timing an operation, and g_timer_elapsed() to -determine the elapsed time. - -<tscreen><verb> -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 ); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>String Handling -<p> -GLib defines a new type called a GString, which is similar to a -standard C string but one that grows automatically. Its string data -is null-terminated. What this gives you is protection from buffer -overflow programming errors within your program. This is a very -important feature, and hence I recommend that you make use of -GStrings. GString itself has a simple public definition: - -<tscreen><verb> -struct GString -{ - gchar *str; /* Points to the string's current \0-terminated value. */ - gint len; /* Current length */ -}; -</verb></tscreen> - -As you might expect, there are a number of operations you can do with -a GString. - -<tscreen><verb> -GString *g_string_new( gchar *init ); -</verb></tscreen> - -This constructs a GString, copying the string value of <tt/init/ -into the GString and returning a pointer to it. NULL may be given as -the argument for an initially empty GString. - -<tscreen><verb> - -void g_string_free( GString *string, - gint free_segment ); -</verb></tscreen> - -This frees the memory for the given GString. If <tt/free_segment/ is -TRUE, then this also frees its character data. - -<tscreen><verb> - -GString *g_string_assign( GString *lval, - const gchar *rval ); -</verb></tscreen> - -This copies the characters from rval into lval, destroying the -previous contents of lval. Note that lval will be lengthened as -necessary to hold the string's contents, unlike the standard strcpy() -function. - -The rest of these functions should be relatively obvious (the _c -versions accept a character instead of a string): - -<tscreen><verb> -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, - ... ); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Utility and Error Functions -<p> -<tscreen><verb> -gchar *g_strdup( const gchar *str ); -</verb></tscreen> - -Replacement strdup function. Copies the original strings contents to -newly allocated memory, and returns a pointer to it. - -<tscreen><verb> -gchar *g_strerror( gint errnum ); -</verb></tscreen> - -I recommend using this for all error messages. It's much nicer, and more -portable than perror() or others. The output is usually of the form: - -<tscreen><verb> -program name:function that failed:file or further description:strerror -</verb></tscreen> - -Here's an example of one such call used in our hello_world program: - -<tscreen><verb> -g_print("hello_world:open:%s:%s\n", filename, g_strerror(errno)); -</verb></tscreen> - -<tscreen><verb> -void g_error( gchar *format, ... ); -</verb></tscreen> - -Prints an error message. The format is just like printf, but it -prepends "** ERROR **: " to your message, and exits the program. -Use only for fatal errors. - -<tscreen><verb> -void g_warning( gchar *format, ... ); -</verb></tscreen> - -Same as above, but prepends "** WARNING **: ", and does not exit the -program. - -<tscreen><verb> -void g_message( gchar *format, ... ); -</verb></tscreen> - -Prints "message: " prepended to the string you pass in. - -<tscreen><verb> -void g_print( gchar *format, ... ); -</verb></tscreen> - -Replacement for printf(). - -And our last function: - -<tscreen><verb> -gchar *g_strsignal( gint signum ); -</verb></tscreen> - -Prints out the name of the Unix system signal given the signal number. -Useful in generic signal handling functions. - -All of the above are more or less just stolen from glib.h. If anyone cares -to document any function, just send me an email! - -<!-- ***************************************************************** --> -<sect>GTK's rc Files <label id="sec_gtkrc_files"> -<!-- ***************************************************************** --> -<p> -GTK has its own way of dealing with application defaults, by using rc -files. These can be used to set the colors of just about any widget, and -can also be used to tile pixmaps onto the background of some widgets. - -<!-- ----------------------------------------------------------------- --> -<sect1>Functions For rc Files -<p> -When your application starts, you should include a call to: - -<tscreen><verb> -void gtk_rc_parse( char *filename ); -</verb></tscreen> - -Passing in the filename of your rc file. This will cause GTK to parse -this file, and use the style settings for the widget types defined -there. - -If you wish to have a special set of widgets that can take on a -different style from others, or any other logical division of widgets, -use a call to: - -<tscreen><verb> -void gtk_widget_set_name( GtkWidget *widget, - gchar *name ); -</verb></tscreen> - -Passing your newly created widget as the first argument, and the name -you wish to give it as the second. This will allow you to change the -attributes of this widget by name through the rc file. - -If we use a call something like this: - -<tscreen><verb> -button = gtk_button_new_with_label ("Special Button"); -gtk_widget_set_name (button, "special button"); -</verb></tscreen> - -Then this button is given the name "special button" and may be addressed by -name in the rc file as "special button.GtkButton". [<--- Verify ME!] - -The example rc file below, sets the properties of the main window, and lets -all children of that main window inherit the style described by the "main -button" style. The code used in the application is: - -<tscreen><verb> -window = gtk_window_new (GTK_WINDOW_TOPLEVEL); -gtk_widget_set_name (window, "main window"); -</verb></tscreen> - -And then the style is defined in the rc file using: - -<tscreen><verb> -widget "main window.*GtkButton*" style "main_button" -</verb></tscreen> - -Which sets all the Button widgets in the "main window" to the -"main_buttons" style as defined in the rc file. - -As you can see, this is a fairly powerful and flexible system. Use your -imagination as to how best to take advantage of this. - -<!-- ----------------------------------------------------------------- --> -<sect1>GTK's rc File Format -<p> -The format of the GTK file is illustrated in the example below. This is -the testgtkrc file from the GTK distribution, but I've added a -few comments and things. You may wish to include this explanation in -your application to allow the user to fine tune his application. - -There are several directives to change the attributes of a widget. - -<itemize> -<item>fg - Sets the foreground color of a widget. -<item>bg - Sets the background color of a widget. -<item>bg_pixmap - Sets the background of a widget to a tiled pixmap. -<item>font - Sets the font to be used with the given widget. -</itemize> - -In addition to this, there are several states a widget can be in, and you -can set different colors, pixmaps and fonts for each state. These states are: - -<itemize> -<item>NORMAL - The normal state of a widget, without the mouse over top of -it, and not being pressed, etc. -<item>PRELIGHT - When the mouse is over top of the widget, colors defined -using this state will be in effect. -<item>ACTIVE - When the widget is pressed or clicked it will be active, and -the attributes assigned by this tag will be in effect. -<item>INSENSITIVE - When a widget is set insensitive, and cannot be -activated, it will take these attributes. -<item>SELECTED - When an object is selected, it takes these attributes. -</itemize> - -When using the "fg" and "bg" keywords to set the colors of widgets, the -format is: - -<tscreen><verb> -fg[<STATE>] = { Red, Green, Blue } -</verb></tscreen> - -Where STATE is one of the above states (PRELIGHT, ACTIVE, etc), and the Red, -Green and Blue are values in the range of 0 - 1.0, { 1.0, 1.0, 1.0 } being -white. They must be in float form, or they will register as 0, so a straight -"1" will not work, it must be "1.0". A straight "0" is fine because it -doesn't matter if it's not recognized. Unrecognized values are set to 0. - -bg_pixmap is very similar to the above, except the colors are replaced by a -filename. - -pixmap_path is a list of paths separated by ":"'s. These paths will be -searched for any pixmap you specify. - -The font directive is simply: -<tscreen><verb> -font = "<font name>" -</verb></tscreen> - -The only hard part is figuring out the font string. Using xfontsel or -a similar utility should help. - -The "widget_class" sets the style of a class of widgets. These classes are -listed in the widget overview on the class hierarchy. - -The "widget" directive sets a specifically named set of widgets to a -given style, overriding any style set for the given widget class. -These widgets are registered inside the application using the -gtk_widget_set_name() call. This allows you to specify the attributes of a -widget on a per widget basis, rather than setting the attributes of an -entire widget class. I urge you to document any of these special widgets so -users may customize them. - -When the keyword <tt>parent</> is used as an attribute, the widget will take on -the attributes of its parent in the application. - -When defining a style, you may assign the attributes of a previously defined -style to this new one. - -<tscreen><verb> -style "main_button" = "button" -{ - font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*" - bg[PRELIGHT] = { 0.75, 0, 0 } -} -</verb></tscreen> - -This example takes the "button" style, and creates a new "main_button" style -simply by changing the font and prelight background color of the "button" -style. - -Of course, many of these attributes don't apply to all widgets. It's a -simple matter of common sense really. Anything that could apply, should. - -<!-- ----------------------------------------------------------------- --> -<sect1>Example rc file -<p> - -<tscreen><verb> -# 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> - - -# Here is a list of all the possible states. Note that some do not apply to -# certain widgets. -# -# 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. -# - -# This sets a style called "button". The name is not really important, as -# it is assigned to the actual widgets at the bottom of the file. - -style "window" -{ - #This sets the padding around the window to the pixmap specified. - #bg_pixmap[<STATE>] = "<pixmap filename>" - bg_pixmap[NORMAL] = "warning.xpm" -} - -style "scale" -{ - #Sets the foreground color (font color) to red when in the "NORMAL" - #state. - - fg[NORMAL] = { 1.0, 0, 0 } - - #Sets the background pixmap of this widget to that of its parent. - bg_pixmap[NORMAL] = "<parent>" -} - -style "button" -{ - # This shows all the possible states for a button. The only one that - # doesn't apply is the 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 } -} - -# In this example, we inherit the attributes of the "button" style and then -# override the font and background color when prelit to create a new -# "main_button" style. - -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 } - - # This sets the background pixmap of the toggle_button to that of its - # parent widget (as defined in the application). - 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" - -# These set the widget types to use the styles defined above. -# The widget types are listed in the class hierarchy, but could probably be -# just listed in this document for the users reference. - -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" - -# This sets all the buttons that are children of the "main window" to -# the main_button style. These must be documented to be taken advantage of. -widget "main window.*GtkButton*" style "main_button" -</verb></tscreen> - -<!-- ***************************************************************** --> -<sect>Writing Your Own Widgets -<!-- ***************************************************************** --> - -<!-- ----------------------------------------------------------------- --> -<sect1> Overview -<p> -Although the GTK distribution comes with many types of widgets that -should cover most basic needs, there may come a time when you need to -create your own new widget type. Since GTK uses widget inheritance -extensively, and there is already a widget that is close to what you want, -it is often possible to make a useful new widget type in -just a few lines of code. But before starting work on a new widget, check -around first to make sure that someone has not already written -it. This will prevent duplication of effort and keep the number of -GTK widgets out there to a minimum, which will help keep both the code -and the interface of different applications consistent. As a flip side -to this, once you finish your widget, announce it to the world so -other people can benefit. The best place to do this is probably the -<tt>gtk-list</tt>. - -Complete sources for the example widgets are available at the place you -got this tutorial, or from: - -<htmlurl url="http://www.gtk.org/~otaylor/gtk/tutorial/" -name="http://www.gtk.org/~otaylor/gtk/tutorial/"> - - -<!-- ----------------------------------------------------------------- --> -<sect1> The Anatomy Of A Widget -<p> -In order to create a new widget, it is important to have an -understanding of how GTK objects work. This section is just meant as a -brief overview. See the reference documentation for the details. - -GTK widgets are implemented in an object oriented fashion. However, -they are implemented in standard C. This greatly improves portability -and stability over using current generation C++ compilers; however, -it does mean that the widget writer has to pay attention to some of -the implementation details. The information common to all instances of -one class of widgets (e.g., to all Button widgets) is stored in the -<em>class structure</em>. There is only one copy of this in -which is stored information about the class's signals -(which act like virtual functions in C). To support inheritance, the -first field in the class structure must be a copy of the parent's -class structure. The declaration of the class structure of GtkButtton -looks like: - -<tscreen><verb> -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); -}; -</verb></tscreen> - -When a button is treated as a container (for instance, when it is -resized), its class structure can be cast to GtkContainerClass, and -the relevant fields used to handle the signals. - -There is also a structure for each widget that is created on a -per-instance basis. This structure has fields to store information that -is different for each instance of the widget. We'll call this -structure the <em>object structure</em>. For the Button class, it looks -like: - -<tscreen><verb> -struct _GtkButton -{ - GtkContainer container; - - GtkWidget *child; - - guint in_button : 1; - guint button_down : 1; -}; -</verb></tscreen> - -Note that, similar to the class structure, the first field is the -object structure of the parent class, so that this structure can be -cast to the parent class' object structure as needed. - -<!-- ----------------------------------------------------------------- --> -<sect1> Creating a Composite widget - -<!-- ----------------------------------------------------------------- --> -<sect2> Introduction -<p> -One type of widget that you may be interested in creating is a -widget that is merely an aggregate of other GTK widgets. This type of -widget does nothing that couldn't be done without creating new -widgets, but provides a convenient way of packaging user interface -elements for reuse. The FileSelection and ColorSelection widgets in -the standard distribution are examples of this type of widget. - -The example widget that we'll create in this section is the Tictactoe -widget, a 3x3 array of toggle buttons which triggers a signal when all -three buttons in a row, column, or on one of the diagonals are -depressed. - -<!-- ----------------------------------------------------------------- --> -<sect2> Choosing a parent class -<p> -The parent class for a composite widget is typically the container -class that holds all of the elements of the composite widget. For -example, the parent class of the FileSelection widget is the -Dialog class. Since our buttons will be arranged in a table, it -might seem natural to make our parent class the Table -class. Unfortunately, this turns out not to work. The creation of a -widget is divided among two functions - a <tt/WIDGETNAME_new()/ -function that the user calls, and a <tt/WIDGETNAME_init()/ function -which does the basic work of initializing the widget which is -independent of the arguments passed to the <tt/_new()/ -function. Descendant widgets only call the <tt/_init/ function of -their parent widget. But this division of labor doesn't work well for -tables, which when created need to know the number of rows and -columns in the table. Unless we want to duplicate most of the -functionality of <tt/gtk_table_new()/ in our Tictactoe widget, we had -best avoid deriving it from Table. For that reason, we derive it -from VBox instead, and stick our table inside the VBox. - -<!-- ----------------------------------------------------------------- --> -<sect2> The header file -<p> -Each widget class has a header file which declares the object and -class structures for that widget, along with public functions. -A couple of features are worth pointing out. To prevent duplicate -definitions, we wrap the entire header file in: - -<tscreen><verb> -#ifndef __TICTACTOE_H__ -#define __TICTACTOE_H__ -. -. -. -#endif /* __TICTACTOE_H__ */ -</verb></tscreen> - -And to keep C++ programs that include the header file happy, in: - -<tscreen><verb> -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ -. -. -. -#ifdef __cplusplus -} -#endif /* __cplusplus */ -</verb></tscreen> - -Along with the functions and structures, we declare three standard -macros in our header file, <tt/TICTACTOE(obj)/, -<tt/TICTACTOE_CLASS(klass)/, and <tt/IS_TICTACTOE(obj)/, which cast a -pointer into a pointer to the object or class structure, and check -if an object is a Tictactoe widget respectively. - -Here is the complete header file: - -<tscreen><verb> -/* 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__ */ - -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect2> The <tt/_get_type()/ function. -<p> -We now continue on to the implementation of our widget. A core -function for every widget is the function -<tt/WIDGETNAME_get_type()/. This function, when first called, tells -GTK about the widget class, and gets an ID that uniquely identifies -the widget class. Upon subsequent calls, it just returns the ID. - -<tscreen><verb> -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; -} -</verb></tscreen> - -The GtkTypeInfo structure has the following definition: - -<tscreen><verb> -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; -}; -</verb></tscreen> - -The fields of this structure are pretty self-explanatory. We'll ignore -the <tt/arg_set_func/ and <tt/arg_get_func/ fields here: they have an important, -but as yet largely -unimplemented, role in allowing widget options to be conveniently set -from interpreted languages. Once GTK has a correctly filled in copy of -this structure, it knows how to create objects of a particular widget -type. - -<!-- ----------------------------------------------------------------- --> -<sect2> The <tt/_class_init()/ function -<p> -The <tt/WIDGETNAME_class_init()/ function initializes the fields of -the widget's class structure, and sets up any signals for the -class. For our Tictactoe widget it looks like: - -<tscreen><verb> - -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; -} -</verb></tscreen> - -Our widget has just one signal, the <tt/tictactoe/ signal that is -invoked when a row, column, or diagonal is completely filled in. Not -every composite widget needs signals, so if you are reading this for -the first time, you may want to skip to the next section now, as -things are going to get a bit complicated. - -The function: - -<tscreen><verb> -gint gtk_signal_new( const gchar *name, - GtkSignalRunType run_type, - GtkType object_type, - gint function_offset, - GtkSignalMarshaller marshaller, - GtkType return_val, - guint nparams, - ...); -</verb></tscreen> - -Creates a new signal. The parameters are: - -<itemize> -<item> <tt/name/: The name of the signal. -<item> <tt/run_type/: Whether the default handler runs before or after -user handlers. Usually this will be <tt/GTK_RUN_FIRST/, or <tt/GTK_RUN_LAST/, -although there are other possibilities. -<item> <tt/object_type/: The ID of the object that this signal applies -to. (It will also apply to that objects descendants.) -<item> <tt/function_offset/: The offset within the class structure of -a pointer to the default handler. -<item> <tt/marshaller/: A function that is used to invoke the signal -handler. For signal handlers that have no arguments other than the -object that emitted the signal and user data, we can use the -pre-supplied marshaller function <tt/gtk_signal_default_marshaller/. -<item> <tt/return_val/: The type of the return val. -<item> <tt/nparams/: The number of parameters of the signal handler -(other than the two default ones mentioned above) -<item> <tt/.../: The types of the parameters. -</itemize> - -When specifying types, the <tt/GtkType/ enumeration is used: - -<tscreen><verb> -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; -</verb></tscreen> - -<tt/gtk_signal_new()/ returns a unique integer identifier for the -signal, that we store in the <tt/tictactoe_signals/ array, which we -index using an enumeration. (Conventionally, the enumeration elements -are the signal name, uppercased, but here there would be a conflict -with the <tt/TICTACTOE()/ macro, so we called it <tt/TICTACTOE_SIGNAL/ -instead. - -After creating our signals, we need to tell GTK to associate our -signals with the Tictactoe class. We do that by calling -<tt/gtk_object_class_add_signals()/. We then set the pointer which -points to the default handler for the "tictactoe" signal to NULL, -indicating that there is no default action. - -<!-- ----------------------------------------------------------------- --> -<sect2> The <tt/_init()/ function. -<p> -Each widget class also needs a function to initialize the object -structure. Usually, this function has the fairly limited role of -setting the fields of the structure to default values. For composite -widgets, however, this function also creates the component widgets. - -<tscreen><verb> -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]); - } -} -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect2> And the rest... -<p> -There is one more function that every widget (except for base widget -types like Bin that cannot be instantiated) needs to have - the -function that the user calls to create an object of that type. This is -conventionally called <tt/WIDGETNAME_new()/. In some -widgets, though not for the Tictactoe widgets, this function takes -arguments, and does some setup based on the arguments. The other two -functions are specific to the Tictactoe widget. - -<tt/tictactoe_clear()/ is a public function that resets all the -buttons in the widget to the up position. Note the use of -<tt/gtk_signal_handler_block_by_data()/ to keep our signal handler for -button toggles from being triggered unnecessarily. - -<tt/tictactoe_toggle()/ is the signal handler that is invoked when the -user clicks on a button. It checks to see if there are any winning -combinations that involve the toggled button, and if so, emits -the "tictactoe" signal. - -<tscreen><verb> -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_active (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; - } - } -} -</verb></tscreen> - -And finally, an example program using our Tictactoe widget: - -<tscreen><verb> -#include <gtk/gtk.h> -#include "tictactoe.h" - -/* Invoked when a row, column or diagonal is completed */ -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_set_border_width (GTK_CONTAINER (window), 10); - - /* Create a new Tictactoe widget */ - ttt = tictactoe_new (); - gtk_container_add (GTK_CONTAINER (window), ttt); - gtk_widget_show (ttt); - - /* And attach to its "tictactoe" signal */ - gtk_signal_connect (GTK_OBJECT (ttt), "tictactoe", - GTK_SIGNAL_FUNC (win), NULL); - - gtk_widget_show (window); - - gtk_main (); - - return 0; -} - -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1> Creating a widget from scratch. - -<!-- ----------------------------------------------------------------- --> -<sect2> Introduction -<p> -In this section, we'll learn more about how widgets display themselves -on the screen and interact with events. As an example of this, we'll -create an analog dial widget with a pointer that the user can drag to -set the value. - -<!-- ----------------------------------------------------------------- --> -<sect2> Displaying a widget on the screen -<p> -There are several steps that are involved in displaying on the screen. -After the widget is created with a call to <tt/WIDGETNAME_new()/, -several more functions are needed: - -<itemize> -<item> <tt/WIDGETNAME_realize()/ is responsible for creating an X -window for the widget if it has one. -<item> <tt/WIDGETNAME_map()/ is invoked after the user calls -<tt/gtk_widget_show()/. It is responsible for making sure the widget -is actually drawn on the screen (<em/mapped/). For a container class, -it must also make calls to <tt/map()/> functions of any child widgets. -<item> <tt/WIDGETNAME_draw()/ is invoked when <tt/gtk_widget_draw()/ -is called for the widget or one of its ancestors. It makes the actual -calls to the drawing functions to draw the widget on the screen. For -container widgets, this function must make calls to -<tt/gtk_widget_draw()/ for its child widgets. -<item> <tt/WIDGETNAME_expose()/ is a handler for expose events for the -widget. It makes the necessary calls to the drawing functions to draw -the exposed portion on the screen. For container widgets, this -function must generate expose events for its child widgets which don't -have their own windows. (If they have their own windows, then X will -generate the necessary expose events.) -</itemize> - -You might notice that the last two functions are quite similar - each -is responsible for drawing the widget on the screen. In fact many -types of widgets don't really care about the difference between the -two. The default <tt/draw()/ function in the widget class simply -generates a synthetic expose event for the redrawn area. However, some -types of widgets can save work by distinguishing between the two -functions. For instance, if a widget has multiple X windows, then -since expose events identify the exposed window, it can redraw only -the affected window, which is not possible for calls to <tt/draw()/. - -Container widgets, even if they don't care about the difference for -themselves, can't simply use the default <tt/draw()/ function because -their child widgets might care about the difference. However, -it would be wasteful to duplicate the drawing code between the two -functions. The convention is that such widgets have a function called -<tt/WIDGETNAME_paint()/ that does the actual work of drawing the -widget, that is then called by the <tt/draw()/ and <tt/expose()/ -functions. - -In our example approach, since the dial widget is not a container -widget, and only has a single window, we can take the simplest -approach and use the default <tt/draw()/ function and only implement -an <tt/expose()/ function. - -<!-- ----------------------------------------------------------------- --> -<sect2> The origins of the Dial Widget -<p> -Just as all land animals are just variants on the first amphibian that -crawled up out of the mud, GTK widgets tend to start off as variants -of some other, previously written widget. Thus, although this section -is entitled "Creating a Widget from Scratch", the Dial widget really -began with the source code for the Range widget. This was picked as a -starting point because it would be nice if our Dial had the same -interface as the Scale widgets which are just specialized descendants -of the Range widget. So, though the source code is presented below in -finished form, it should not be implied that it was written, <em>ab -initio</em> in this fashion. Also, if you aren't yet familiar with -how scale widgets work from the application writer's point of view, it -would be a good idea to look them over before continuing. - -<!-- ----------------------------------------------------------------- --> -<sect2> The Basics -<p> -Quite a bit of our widget should look pretty familiar from the -Tictactoe widget. First, we have a header file: - -<tscreen><verb> -/* 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; - - /* update policy (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */ - guint policy : 2; - - /* Button currently pressed or 0 if none */ - guint8 button; - - /* Dimensions of dial components */ - gint radius; - gint pointer_width; - - /* ID of update timer, or 0 if none */ - guint32 timer; - - /* Current angle */ - gfloat angle; - - /* Old values from adjustment stored so we know when something changes */ - gfloat old_value; - gfloat old_lower; - gfloat old_upper; - - /* The adjustment object that stores the data for this dial */ - 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__ */ -</verb></tscreen> - -Since there is quite a bit more going on in this widget than the last -one, we have more fields in the data structure, but otherwise things -are pretty similar. - -Next, after including header files and declaring a few constants, -we have some functions to provide information about the widget -and initialize it: - -<tscreen><verb> -#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 - -/* Forward declarations */ - -[ omitted to save space ] - -/* Local data */ - -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, - (GtkArgSetFunc) NULL, - (GtkArgGetFunc) 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); -} -</verb></tscreen> - -Note that this <tt/init()/ function does less than for the Tictactoe -widget, since this is not a composite widget, and the <tt/new()/ -function does more, since it now has an argument. Also, note that when -we store a pointer to the Adjustment object, we increment its -reference count, (and correspondingly decrement it when we no longer -use it) so that GTK can keep track of when it can be safely destroyed. - -<p> -Also, there are a few function to manipulate the widget's options: - -<tscreen><verb> -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); -} -</verb></tscreen> - -<sect2> <tt/gtk_dial_realize()/ - -<p> -Now we come to some new types of functions. First, we have a function -that does the work of creating the X window. Notice that a mask is -passed to the function <tt/gdk_window_new()/ which specifies which fields of -the GdkWindowAttr structure actually have data in them (the remaining -fields will be given default values). Also worth noting is the way the -event mask of the widget is created. We call -<tt/gtk_widget_get_events()/ to retrieve the event mask that the user -has specified for this widget (with <tt/gtk_widget_set_events()/), and -add the events that we are interested in ourselves. - -<p> -After creating the window, we set its style and background, and put a -pointer to the widget in the user data field of the GdkWindow. This -last step allows GTK to dispatch events for this window to the correct -widget. - -<tscreen><verb> -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); -} -</verb></tscreen> - -<sect2> Size negotiation - -<p> -Before the first time that the window containing a widget is -displayed, and whenever the layout of the window changes, GTK asks -each child widget for its desired size. This request is handled by the -function <tt/gtk_dial_size_request()/. Since our widget isn't a -container widget, and has no real constraints on its size, we just -return a reasonable default value. - -<tscreen><verb> -static void -gtk_dial_size_request (GtkWidget *widget, - GtkRequisition *requisition) -{ - requisition->width = DIAL_DEFAULT_SIZE; - requisition->height = DIAL_DEFAULT_SIZE; -} -</verb></tscreen> - -<p> -After all the widgets have requested an ideal size, the layout of the -window is computed and each child widget is notified of its actual -size. Usually, this will be at least as large as the requested size, -but if for instance the user has resized the window, it may -occasionally be smaller than the requested size. The size notification -is handled by the function <tt/gtk_dial_size_allocate()/. Notice that -as well as computing the sizes of some component pieces for future -use, this routine also does the grunt work of moving the widget's X -window into the new position and size. - -<tscreen><verb> -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; - } -} -</verb></tscreen>. - -<!-- ----------------------------------------------------------------- --> -<sect2> <tt/gtk_dial_expose()/ - -<p> -As mentioned above, all the drawing of this widget is done in the -handler for expose events. There's not much to remark on here except -the use of the function <tt/gtk_draw_polygon/ to draw the pointer with -three dimensional shading according to the colors stored in the -widget's style. - -<tscreen><verb> -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; - - /* Draw ticks */ - - 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); - } - - /* Draw pointer */ - - 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; -} -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect2> Event handling -<p> -The rest of the widget's code handles various types of events, and -isn't too different from what would be found in many GTK -applications. Two types of events can occur - either the user can -click on the widget with the mouse and drag to move the pointer, or -the value of the Adjustment object can change due to some external -circumstance. - -When the user clicks on the widget, we check to see if the click was -appropriately near the pointer, and if so, store the button that the -user clicked with in the <tt/button/ field of the widget -structure, and grab all mouse events with a call to -<tt/gtk_grab_add()/. Subsequent motion of the mouse causes the -value of the control to be recomputed (by the function -<tt/gtk_dial_update_mouse/). Depending on the policy that has been -set, "value_changed" events are either generated instantly -(<tt/GTK_UPDATE_CONTINUOUS/), after a delay in a timer added with -<tt/gtk_timeout_add()/ (<tt/GTK_UPDATE_DELAYED/), or only when the -button is released (<tt/GTK_UPDATE_DISCONTINUOUS/). - -<tscreen><verb> -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); - - /* Determine if button press was within pointer region - we - do this by computing the parallel and perpendicular distance of - the point where the mouse was pressed from the line passing through - the pointer */ - - 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); - } - } - } -} -</verb></tscreen> - -Changes to the Adjustment by external means are communicated to our -widget by the "changed" and "value_changed" signals. The handlers -for these functions call <tt/gtk_dial_update()/ to validate the -arguments, compute the new pointer angle, and redraw the widget (by -calling <tt/gtk_widget_draw()/). - -<tscreen><verb> -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; - } -} -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect2> Possible Enhancements -<p> -The Dial widget as we've described it so far runs about 670 lines of -code. Although that might sound like a fair bit, we've really -accomplished quite a bit with that much code, especially since much of -that length is headers and boilerplate. However, there are quite a few -more enhancements that could be made to this widget: - -<itemize> -<item> If you try this widget out, you'll find that there is some -flashing as the pointer is dragged around. This is because the entire -widget is erased every time the pointer is moved before being -redrawn. Often, the best way to handle this problem is to draw to an -offscreen pixmap, then copy the final results onto the screen in one -step. (The ProgressBar widget draws itself in this fashion.) - -<item> The user should be able to use the up and down arrow keys to -increase and decrease the value. - -<item> It would be nice if the widget had buttons to increase and -decrease the value in small or large steps. Although it would be -possible to use embedded Button widgets for this, we would also like -the buttons to auto-repeat when held down, as the arrows on a -scrollbar do. Most of the code to implement this type of behavior can -be found in the Range widget. - -<item> The Dial widget could be made into a container widget with a -single child widget positioned at the bottom between the buttons -mentioned above. The user could then add their choice of a label or -entry widget to display the current value of the dial. - -</itemize> - -<!-- ----------------------------------------------------------------- --> -<sect1> Learning More - -<p> -Only a small part of the many details involved in creating widgets -could be described above. If you want to write your own widgets, the -best source of examples is the GTK source itself. Ask yourself some -questions about the widget you want to write: IS it a Container -widget? Does it have its own window? Is it a modification of an -existing widget? Then find a similar widget, and start making changes. -Good luck! - -<!-- ***************************************************************** --> -<sect>Scribble, A Simple Example Drawing Program -<!-- ***************************************************************** --> - -<!-- ----------------------------------------------------------------- --> -<sect1> Overview -<p> -In this section, we will build a simple drawing program. In the -process, we will examine how to handle mouse events, how to draw in a -window, and how to do drawing better by using a backing pixmap. After -creating the simple drawing program, we will extend it by adding -support for XInput devices, such as drawing tablets. GTK provides -support routines which makes getting extended information, such as -pressure and tilt, from such devices quite easy. - -<!-- ----------------------------------------------------------------- --> -<sect1> Event Handling -<p> -The GTK signals we have already discussed are for high-level actions, -such as a menu item being selected. However, sometimes it is useful to -learn about lower-level occurrences, such as the mouse being moved, or -a key being pressed. There are also GTK signals corresponding to these -low-level <em>events</em>. The handlers for these signals have an -extra parameter which is a pointer to a structure containing -information about the event. For instance, motion event handlers are -passed a pointer to a GdkEventMotion structure which looks (in part) -like: - -<tscreen><verb> -struct _GdkEventMotion -{ - GdkEventType type; - GdkWindow *window; - guint32 time; - gdouble x; - gdouble y; - ... - guint state; - ... -}; -</verb></tscreen> - -<tt/type/ will be set to the event type, in this case -<tt/GDK_MOTION_NOTIFY/, window is the window in which the event -occurred. <tt/x/ and <tt/y/ give the coordinates of the event. -<tt/state/ specifies the modifier state when the event -occurred (that is, it specifies which modifier keys and mouse buttons -were pressed). It is the bitwise OR of some of the following: - -<tscreen><verb> -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 -</verb></tscreen> - -As for other signals, to determine what happens when an event occurs -we call <tt>gtk_signal_connect()</tt>. But we also need let GTK -know which events we want to be notified about. To do this, we call -the function: - -<tscreen><verb> -void gtk_widget_set_events (GtkWidget *widget, - gint events); -</verb></tscreen> - -The second field specifies the events we are interested in. It -is the bitwise OR of constants that specify different types -of events. For future reference the event types are: - -<tscreen><verb> -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 -</verb></tscreen> - -There are a few subtle points that have to be observed when calling -<tt/gtk_widget_set_events()/. First, it must be called before the X window -for a GTK widget is created. In practical terms, this means you -should call it immediately after creating the widget. Second, the -widget must have an associated X window. For efficiency, many widget -types do not have their own window, but draw in their parent's window. -These widgets are: - -<tscreen><verb> -GtkAlignment -GtkArrow -GtkBin -GtkBox -GtkImage -GtkItem -GtkLabel -GtkPixmap -GtkScrolledWindow -GtkSeparator -GtkTable -GtkAspectFrame -GtkFrame -GtkVBox -GtkHBox -GtkVSeparator -GtkHSeparator -</verb></tscreen> - -To capture events for these widgets, you need to use an EventBox -widget. See the section on the <ref id="sec_EventBox" -name="EventBox"> widget for details. - -For our drawing program, we want to know when the mouse button is -pressed and when the mouse is moved, so we specify -<tt/GDK_POINTER_MOTION_MASK/ and <tt/GDK_BUTTON_PRESS_MASK/. We also -want to know when we need to redraw our window, so we specify -<tt/GDK_EXPOSURE_MASK/. Although we want to be notified via a -Configure event when our window size changes, we don't have to specify -the corresponding <tt/GDK_STRUCTURE_MASK/ flag, because it is -automatically specified for all windows. - -It turns out, however, that there is a problem with just specifying -<tt/GDK_POINTER_MOTION_MASK/. This will cause the server to add a new -motion event to the event queue every time the user moves the mouse. -Imagine that it takes us 0.1 seconds to handle a motion event, but the -X server queues a new motion event every 0.05 seconds. We will soon -get way behind the users drawing. If the user draws for 5 seconds, -it will take us another 5 seconds to catch up after they release -the mouse button! What we would like is to only get one motion -event for each event we process. The way to do this is to -specify <tt/GDK_POINTER_MOTION_HINT_MASK/. - -When we specify <tt/GDK_POINTER_MOTION_HINT_MASK/, the server sends -us a motion event the first time the pointer moves after entering -our window, or after a button press or release event. Subsequent -motion events will be suppressed until we explicitly ask for -the position of the pointer using the function: - -<tscreen><verb> -GdkWindow* gdk_window_get_pointer (GdkWindow *window, - gint *x, - gint *y, - GdkModifierType *mask); -</verb></tscreen> - -(There is another function, <tt>gtk_widget_get_pointer()</tt> which -has a simpler interface, but turns out not to be very useful, since -it only retrieves the position of the mouse, not whether the buttons -are pressed.) - -The code to set the events for our window then looks like: - -<tscreen><verb> - 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); -</verb></tscreen> - -We'll save the "expose_event" and "configure_event" handlers for -later. The "motion_notify_event" and "button_press_event" handlers -are pretty simple: - -<tscreen><verb> -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; -} -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1> The DrawingArea Widget, And Drawing -<p> -We now turn to the process of drawing on the screen. The -widget we use for this is the DrawingArea widget. A drawing area -widget is essentially an X window and nothing more. It is a blank -canvas in which we can draw whatever we like. A drawing area -is created using the call: - -<tscreen><verb> -GtkWidget* gtk_drawing_area_new (void); -</verb></tscreen> - -A default size for the widget can be specified by calling: - -<tscreen><verb> -void gtk_drawing_area_size (GtkDrawingArea *darea, - gint width, - gint height); -</verb></tscreen> - -This default size can be overridden, as is true for all widgets, -by calling <tt>gtk_widget_set_usize()</tt>, and that, in turn, can -be overridden if the user manually resizes the the window containing -the drawing area. - -It should be noted that when we create a DrawingArea widget, we are -<em>completely</em> responsible for drawing the contents. If our -window is obscured then uncovered, we get an exposure event and must -redraw what was previously hidden. - -Having to remember everything that was drawn on the screen so we -can properly redraw it can, to say the least, be a nuisance. In -addition, it can be visually distracting if portions of the -window are cleared, then redrawn step by step. The solution to -this problem is to use an offscreen <em>backing pixmap</em>. -Instead of drawing directly to the screen, we draw to an image -stored in server memory but not displayed, then when the image -changes or new portions of the image are displayed, we copy the -relevant portions onto the screen. - -To create an offscreen pixmap, we call the function: - -<tscreen><verb> -GdkPixmap* gdk_pixmap_new (GdkWindow *window, - gint width, - gint height, - gint depth); -</verb></tscreen> - -The <tt>window</tt> parameter specifies a GDK window that this pixmap -takes some of its properties from. <tt>width</tt> and <tt>height</tt> -specify the size of the pixmap. <tt>depth</tt> specifies the <em>color -depth</em>, that is the number of bits per pixel, for the new window. -If the depth is specified as <tt>-1</tt>, it will match the depth -of <tt>window</tt>. - -We create the pixmap in our "configure_event" handler. This event -is generated whenever the window changes size, including when it -is originally created. - -<tscreen><verb> -/* Backing pixmap for drawing area */ -static GdkPixmap *pixmap = NULL; - -/* Create a new backing pixmap of the appropriate size */ -static gint -configure_event (GtkWidget *widget, GdkEventConfigure *event) -{ - if (pixmap) - g_object_unref(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; -} -</verb></tscreen> - -The call to <tt>gdk_draw_rectangle()</tt> clears the pixmap -initially to white. We'll say more about that in a moment. - -Our exposure event handler then simply copies the relevant portion -of the pixmap onto the screen (we determine the area we need -to redraw by using the event->area field of the exposure event): - -<tscreen><verb> -/* Redraw the screen from the 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; -} -</verb></tscreen> - -We've now seen how to keep the screen up to date with our pixmap, but -how do we actually draw interesting stuff on our pixmap? There are a -large number of calls in GTK's GDK library for drawing on -<em>drawables</em>. A drawable is simply something that can be drawn -upon. It can be a window, a pixmap, or a bitmap (a black and white -image). We've already seen two such calls above, -<tt>gdk_draw_rectangle()</tt> and <tt>gdk_draw_pixmap()</tt>. The -complete list is: - -<tscreen><verb> -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 () -</verb></tscreen> - -See the reference documentation or the header file -<tt><gdk/gdk.h></tt> for further details on these functions. -These functions all share the same first two arguments. The first -argument is the drawable to draw upon, the second argument is a -<em>graphics context</em> (GC). - -A graphics context encapsulates information about things such as -foreground and background color and line width. GDK has a full set of -functions for creating and modifying graphics contexts, but to keep -things simple we'll just use predefined graphics contexts. Each widget -has an associated style. (Which can be modified in a gtkrc file, see -the section GTK's rc file.) This, among other things, stores a number -of graphics contexts. Some examples of accessing these graphics -contexts are: - -<tscreen><verb> -widget->style->white_gc -widget->style->black_gc -widget->style->fg_gc[GTK_STATE_NORMAL] -widget->style->bg_gc[GTK_WIDGET_STATE(widget)] -</verb></tscreen> - -The fields <tt>fg_gc</tt>, <tt>bg_gc</tt>, <tt>dark_gc</tt>, and -<tt>light_gc</tt> are indexed by a parameter of type -<tt>GtkStateType</tt> which can take on the values: - -<tscreen><verb> -GTK_STATE_NORMAL, -GTK_STATE_ACTIVE, -GTK_STATE_PRELIGHT, -GTK_STATE_SELECTED, -GTK_STATE_INSENSITIVE -</verb></tscreen> - -For instance, for <tt/GTK_STATE_SELECTED/ the default foreground -color is white and the default background color, dark blue. - -Our function <tt>draw_brush()</tt>, which does the actual drawing -on the screen, is then: - -<tscreen><verb> -/* Draw a rectangle on the screen */ -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); -} -</verb></tscreen> - -After we draw the rectangle representing the brush onto the pixmap, -we call the function: - -<tscreen><verb> -void gtk_widget_draw (GtkWidget *widget, - GdkRectangle *area); -</verb></tscreen> - -which notifies X that the area given by the <tt>area</tt> parameter -needs to be updated. X will eventually generate an expose event -(possibly combining the areas passed in several calls to -<tt>gtk_widget_draw()</tt>) which will cause our expose event handler -to copy the relevant portions to the screen. - -We have now covered the entire drawing program except for a few -mundane details like creating the main window. - -<!-- ----------------------------------------------------------------- --> -<sect1> Adding XInput support -<p> -It is now possible to buy quite inexpensive input devices such -as drawing tablets, which allow drawing with a much greater -ease of artistic expression than does a mouse. The simplest way -to use such devices is simply as a replacement for the mouse, -but that misses out many of the advantages of these devices, -such as: - -<itemize> -<item> Pressure sensitivity -<item> Tilt reporting -<item> Sub-pixel positioning -<item> Multiple inputs (for example, a stylus with a point and eraser) -</itemize> - -For information about the XInput extension, see the <htmlurl -url="http://www.msc.cornell.edu/~otaylor/xinput/XInput-HOWTO.html" -name="XInput-HOWTO">. - -If we examine the full definition of, for example, the GdkEventMotion -structure, we see that it has fields to support extended device -information. - -<tscreen><verb> -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; -}; -</verb></tscreen> - -<tt/pressure/ gives the pressure as a floating point number between -0 and 1. <tt/xtilt/ and <tt/ytilt/ can take on values between --1 and 1, corresponding to the degree of tilt in each direction. -<tt/source/ and <tt/deviceid/ specify the device for which the -event occurred in two different ways. <tt/source/ gives some simple -information about the type of device. It can take the enumeration -values: - -<tscreen><verb> -GDK_SOURCE_MOUSE -GDK_SOURCE_PEN -GDK_SOURCE_ERASER -GDK_SOURCE_CURSOR -</verb></tscreen> - -<tt/deviceid/ specifies a unique numeric ID for the device. This can -be used to find out further information about the device using the -<tt/gdk_input_list_devices()/ call (see below). The special value -<tt/GDK_CORE_POINTER/ is used for the core pointer device. (Usually -the mouse.) - -<sect2> Enabling extended device information -<p> -To let GTK know about our interest in the extended device information, -we merely have to add a single line to our program: - -<tscreen><verb> -gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_CURSOR); -</verb></tscreen> - -By giving the value <tt/GDK_EXTENSION_EVENTS_CURSOR/ we say that -we are interested in extension events, but only if we don't have -to draw our own cursor. See the section <ref -id="sec_Further_Sophistications" name="Further Sophistications"> below -for more information about drawing the cursor. We could also -give the values <tt/GDK_EXTENSION_EVENTS_ALL/ if we were willing -to draw our own cursor, or <tt/GDK_EXTENSION_EVENTS_NONE/ to revert -back to the default condition. - -This is not completely the end of the story however. By default, -no extension devices are enabled. We need a mechanism to allow -users to enable and configure their extension devices. GTK provides -the InputDialog widget to automate this process. The following -procedure manages an InputDialog widget. It creates the dialog if -it isn't present, and raises it to the top otherwise. - -<tscreen><verb> -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); - } -} -</verb></tscreen> - -(You might want to take note of the way we handle this dialog. By -connecting to the "destroy" signal, we make sure that we don't keep a -pointer to dialog around after it is destroyed - that could lead to a -segfault.) - -The InputDialog has two buttons "Close" and "Save", which by default -have no actions assigned to them. In the above function we make -"Close" hide the dialog, hide the "Save" button, since we don't -implement saving of XInput options in this program. - -<sect2> Using extended device information -<p> -Once we've enabled the device, we can just use the extended -device information in the extra fields of the event structures. -In fact, it is always safe to use this information since these -fields will have reasonable default values even when extended -events are not enabled. - -Once change we do have to make is to call -<tt/gdk_input_window_get_pointer()/ instead of -<tt/gdk_window_get_pointer/. This is necessary because -<tt/gdk_window_get_pointer/ doesn't return the extended device -information. - -<tscreen><verb> -void gdk_input_window_get_pointer( GdkWindow *window, - guint32 deviceid, - gdouble *x, - gdouble *y, - gdouble *pressure, - gdouble *xtilt, - gdouble *ytilt, - GdkModifierType *mask); -</verb></tscreen> - -When calling this function, we need to specify the device ID as -well as the window. Usually, we'll get the device ID from the -<tt/deviceid/ field of an event structure. Again, this function -will return reasonable values when extension events are not -enabled. (In this case, <tt/event->deviceid/ will have the value -<tt/GDK_CORE_POINTER/). - -So the basic structure of our button-press and motion event handlers -doesn't change much - we just need to add code to deal with the -extended information. - -<tscreen><verb> -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; -} -</verb></tscreen> - -We also need to do something with the new information. Our new -<tt/draw_brush()/ function draws with a different color for -each <tt/event->source/ and changes the brush size depending -on the pressure. - -<tscreen><verb> -/* Draw a rectangle on the screen, size depending on pressure, - and color on the type of 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); -} -</verb></tscreen> - -<sect2> Finding out more about a device -<p> -As an example of how to find out more about a device, our program -will print the name of the device that generates each button -press. To find out the name of a device, we call the function: - -<tscreen><verb> -GList *gdk_input_list_devices (void); -</verb></tscreen> - -which returns a GList (a linked list type from the GLib library) -of GdkDeviceInfo structures. The GdkDeviceInfo structure is defined -as: - -<tscreen><verb> -struct _GdkDeviceInfo -{ - guint32 deviceid; - gchar *name; - GdkInputSource source; - GdkInputMode mode; - gint has_cursor; - gint num_axes; - GdkAxisUse *axes; - gint num_keys; - GdkDeviceKey *keys; -}; -</verb></tscreen> - -Most of these fields are configuration information that you can ignore -unless you are implementing XInput configuration saving. The fieldwe -are interested in here is <tt/name/ which is simply the name that X -assigns to the device. The other field that isn't configuration -information is <tt/has_cursor/. If <tt/has_cursor/ is false, then we -we need to draw our own cursor. But since we've specified -<tt/GDK_EXTENSION_EVENTS_CURSOR/, we don't have to worry about this. - -Our <tt/print_button_press()/ function simply iterates through -the returned list until it finds a match, then prints out -the name of the device. - -<tscreen><verb> -static void -print_button_press (guint32 deviceid) -{ - GList *tmp_list; - - /* gdk_input_list_devices returns an internal list, so we shouldn't - free it afterwards */ - 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; - } -} -</verb></tscreen> - -That completes the changes to "XInputize" our program. - -<sect2> Further sophistications <label id="sec_Further_Sophistications"> -<p> -Although our program now supports XInput quite well, it lacks some -features we would want in a full-featured application. First, the user -probably doesn't want to have to configure their device each time they -run the program, so we should allow them to save the device -configuration. This is done by iterating through the return of -<tt/gdk_input_list_devices()/ and writing out the configuration to a -file. - -To restore the state next time the program is run, GDK provides -functions to change device configuration: - -<tscreen><verb> -gdk_input_set_extension_events() -gdk_input_set_source() -gdk_input_set_mode() -gdk_input_set_axes() -gdk_input_set_key() -</verb></tscreen> - -(The list returned from <tt/gdk_input_list_devices()/ should not be -modified directly.) An example of doing this can be found in the -drawing program gsumi. (Available from <htmlurl -url="http://www.msc.cornell.edu/~otaylor/gsumi/" -name="http://www.msc.cornell.edu/~otaylor/gsumi/">) Eventually, it -would be nice to have a standard way of doing this for all -applications. This probably belongs at a slightly higher level than -GTK, perhaps in the GNOME library. - -Another major omission that we have mentioned above is the lack of -cursor drawing. Platforms other than XFree86 currently do not allow -simultaneously using a device as both the core pointer and directly by -an application. See the <url -url="http://www.msc.cornell.edu/~otaylor/xinput/XInput-HOWTO.html" -name="XInput-HOWTO"> for more information about this. This means that -applications that want to support the widest audience need to draw -their own cursor. - -An application that draws its own cursor needs to do two things: -determine if the current device needs a cursor drawn or not, and -determine if the current device is in proximity. (If the current -device is a drawing tablet, it's a nice touch to make the cursor -disappear when the stylus is lifted from the tablet. When the -device is touching the stylus, that is called "in proximity.") -The first is done by searching the device list, as we did -to find out the device name. The second is achieved by selecting -"proximity_out" events. An example of drawing one's own cursor is -found in the "testinput" program found in the GTK distribution. - -<!-- ***************************************************************** --> -<sect>Tips For Writing GTK Applications -<!-- ***************************************************************** --> -<p> -This section is simply a gathering of wisdom, general style guidelines -and hints to creating good GTK applications. Currently this section -is very short, but I hope it will get longer in future editions of -this tutorial. - -Use GNU autoconf and automake! They are your friends :) Automake -examines C files, determines how they depend on each other, and -generates a Makefile so the files can be compiled in the correct -order. Autoconf permits automatic configuration of software -installation, handling a large number of system quirks to increase -portability. I am planning to make a quick intro on them here. - -When writing C code, use only C comments (beginning with "/*" and -ending with "*/"), and don't use C++-style comments ("//"). Although -many C compilers understand C++ comments, others don't, and the ANSI C -standard does not require that C++-style comments be processed as -comments. - -<!-- ***************************************************************** --> -<sect>Contributing <label id="sec_Contributing"> -<!-- ***************************************************************** --> -<p> -This document, like so much other great software out there, was -created for free by volunteers. If you are at all knowledgeable about -any aspect of GTK that does not already have documentation, please -consider contributing to this document. - -If you do decide to contribute, please mail your text to Tony Gale, -<tt><htmlurl url="mailto:gale@gtk.org" -name="gale@gtk.org"></tt>. Also, be aware that the entirety of this -document is free, and any addition by you provide must also be -free. That is, people may use any portion of your examples in their -programs, and copies of this document may be distributed at will, etc. - -Thank you. - -<!-- ***************************************************************** --> -<sect>Credits -<!-- ***************************************************************** --> -<p> -We would like to thank the following for their contributions to this text. - -<itemize> -<item>Bawer Dagdeviren, <tt><htmlurl url="mailto:chamele0n@geocities.com" -name="chamele0n@geocities.com"></tt> for the menus tutorial. - -<item>Raph Levien, <tt><htmlurl url="mailto:raph@acm.org" -name="raph@acm.org"></tt> -for hello world ala GTK, widget packing, and general all around wisdom. -He's also generously donated a home for this tutorial. - -<item>Peter Mattis, <tt><htmlurl url="mailto:petm@xcf.berkeley.edu" -name="petm@xcf.berkeley.edu"></tt> for the simplest GTK program.. -and the ability to make it :) - -<item>Werner Koch <tt><htmlurl url="mailto:werner.koch@guug.de" -name="werner.koch@guug.de"></tt> for converting the original plain text to -SGML, and the widget class hierarchy. - -<item>Mark Crichton <tt><htmlurl -url="mailto:crichton@expert.cc.purdue.edu" -name="crichton@expert.cc.purdue.edu"></tt> for the menu factory code, -and the table packing tutorial. - -<item>Owen Taylor <tt><htmlurl url="mailto:owt1@cornell.edu" -name="owt1@cornell.edu"></tt> 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! - -<item>Mark VanderBoom <tt><htmlurl url="mailto:mvboom42@calvin.edu" -name="mvboom42@calvin.edu"></tt> for his wonderful work on the -Notebook, Progress Bar, Dialogs, and File selection widgets. Thanks a -lot Mark! You've been a great help. - -<item>Tim Janik <tt><htmlurl url="mailto:timj@gtk.org" -name="timj@gtk.org"></tt> for his great job on the Lists -Widget. His excellent work on automatically extracting the widget tree -and signal information from GTK. Thanks Tim :) - -<item>Rajat Datta <tt><htmlurl url="mailto:rajat@ix.netcom.com" -name="rajat@ix.netcom.com"</tt> for the excellent job on the Pixmap -tutorial. - -<item>Michael K. Johnson <tt><htmlurl url="mailto:johnsonm@redhat.com" -name="johnsonm@redhat.com"></tt> for info and code for popup menus. - -<item>David Huggins-Daines <tt><htmlurl -url="mailto:bn711@freenet.carleton.ca" -name="bn711@freenet.carleton.ca"></tt> for the Range Widgets and Tree -Widget sections. - -<item>Stefan Mars <tt><htmlurl url="mailto:mars@lysator.liu.se" -name="mars@lysator.liu.se"></tt> for the CList section. - -<item>David A. Wheeler <tt><htmlurl url="mailto:dwheeler@ida.org" -name="dwheeler@ida.org"></tt> for portions of the text on GLib -and various tutorial fixups and improvements. -The GLib text was in turn based on material developed by Damon Chaplin -<tt><htmlurl url="mailto:DAChaplin@msn.com" name="DAChaplin@msn.com"></tt> - -<item>David King for style checking the entire document. -</itemize> - -And to all of you who commented on and helped refine this document. - -Thanks. - -<!-- ***************************************************************** --> -<sect> Tutorial Copyright and Permissions Notice -<!-- ***************************************************************** --> - -<p> -The GTK Tutorial is Copyright (C) 1997 Ian Main. - -Copyright (C) 1998-1999 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. -<P>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 guarantee 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 guarantee that the information is even accurate. - -<!-- ***************************************************************** --> -<appendix> -<!-- ***************************************************************** --> - -<!-- ***************************************************************** --> -<sect> GTK Signals <label id="sec_GTK_Signals"> -<!-- ***************************************************************** --> -<p> -As GTK is an object oriented widget set, it has a hierarchy of -inheritance. This inheritance mechanism applies for -signals. Therefore, you should refer to the widget hierarchy tree when -using the signals listed in this section. - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkObject -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkObject::destroy (GtkObject *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkWidget -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> - -void GtkWidget::show (GtkWidget *, - gpointer); -void GtkWidget::hide (GtkWidget *, - gpointer); -void GtkWidget::map (GtkWidget *, - gpointer); -void GtkWidget::unmap (GtkWidget *, - gpointer); -void GtkWidget::realize (GtkWidget *, - gpointer); -void GtkWidget::unrealize (GtkWidget *, - gpointer); -void GtkWidget::draw (GtkWidget *, - ggpointer, - gpointer); -void GtkWidget::draw-focus (GtkWidget *, - gpointer); -void GtkWidget::draw-default (GtkWidget *, - gpointer); -void GtkWidget::size-request (GtkWidget *, - ggpointer, - gpointer); -void GtkWidget::size-allocate (GtkWidget *, - ggpointer, - gpointer); -void GtkWidget::state-changed (GtkWidget *, - GtkStateType, - gpointer); -void GtkWidget::parent-set (GtkWidget *, - GtkObject *, - gpointer); -void GtkWidget::style-set (GtkWidget *, - GtkStyle *, - gpointer); -void GtkWidget::add-accelerator (GtkWidget *, - gguint, - GtkAccelGroup *, - gguint, - GdkModifierType, - GtkAccelFlags, - gpointer); -void GtkWidget::remove-accelerator (GtkWidget *, - GtkAccelGroup *, - gguint, - GdkModifierType, - gpointer); -gboolean GtkWidget::event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::button-press-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::button-release-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::motion-notify-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::delete-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::destroy-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::expose-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::key-press-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::key-release-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::enter-notify-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::leave-notify-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::configure-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::focus-in-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::focus-out-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::map-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::unmap-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::property-notify-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::selection-clear-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::selection-request-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::selection-notify-event (GtkWidget *, - GdkEvent *, - gpointer); -void GtkWidget::selection-get (GtkWidget *, - GtkSelectionData *, - gguint, - gpointer); -void GtkWidget::selection-received (GtkWidget *, - GtkSelectionData *, - gguint, - gpointer); -gboolean GtkWidget::proximity-in-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::proximity-out-event (GtkWidget *, - GdkEvent *, - gpointer); -void GtkWidget::drag-begin (GtkWidget *, - GdkDragContext *, - gpointer); -void GtkWidget::drag-end (GtkWidget *, - GdkDragContext *, - gpointer); -void GtkWidget::drag-data-delete (GtkWidget *, - GdkDragContext *, - gpointer); -void GtkWidget::drag-leave (GtkWidget *, - GdkDragContext *, - gguint, - gpointer); -gboolean GtkWidget::drag-motion (GtkWidget *, - GdkDragContext *, - ggint, - ggint, - gguint, - gpointer); -gboolean GtkWidget::drag-drop (GtkWidget *, - GdkDragContext *, - ggint, - ggint, - gguint, - gpointer); -void GtkWidget::drag-data-get (GtkWidget *, - GdkDragContext *, - GtkSelectionData *, - gguint, - gguint, - gpointer); -void GtkWidget::drag-data-received (GtkWidget *, - GdkDragContext *, - ggint, - ggint, - GtkSelectionData *, - gguint, - gguint, - gpointer); -gboolean GtkWidget::client-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::no-expose-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::visibility-notify-event (GtkWidget *, - GdkEvent *, - gpointer); -void GtkWidget::debug-msg (GtkWidget *, - GtkString *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkData -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkData::disconnect (GtkData *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkContainer -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkContainer::add (GtkContainer *, - GtkWidget *, - gpointer); -void GtkContainer::remove (GtkContainer *, - GtkWidget *, - gpointer); -void GtkContainer::check-resize (GtkContainer *, - gpointer); -GtkDirectionType GtkContainer::focus (GtkContainer *, - GtkDirectionType, - gpointer); -void GtkContainer::set-focus-child (GtkContainer *, - GtkWidget *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkCalendar -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkCalendar::month-changed (GtkCalendar *, - gpointer); -void GtkCalendar::day-selected (GtkCalendar *, - gpointer); -void GtkCalendar::day-selected-double-click (GtkCalendar *, - gpointer); -void GtkCalendar::prev-month (GtkCalendar *, - gpointer); -void GtkCalendar::next-month (GtkCalendar *, - gpointer); -void GtkCalendar::prev-year (GtkCalendar *, - gpointer); -void GtkCalendar::next-year (GtkCalendar *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkEditable -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkEditable::changed (GtkEditable *, - gpointer); -void GtkEditable::insert-text (GtkEditable *, - GtkString *, - ggint, - ggpointer, - gpointer); -void GtkEditable::delete-text (GtkEditable *, - ggint, - ggint, - gpointer); -void GtkEditable::activate (GtkEditable *, - gpointer); -void GtkEditable::set-editable (GtkEditable *, - gboolean, - gpointer); -void GtkEditable::move-cursor (GtkEditable *, - ggint, - ggint, - gpointer); -void GtkEditable::move-word (GtkEditable *, - ggint, - gpointer); -void GtkEditable::move-page (GtkEditable *, - ggint, - ggint, - gpointer); -void GtkEditable::move-to-row (GtkEditable *, - ggint, - gpointer); -void GtkEditable::move-to-column (GtkEditable *, - ggint, - gpointer); -void GtkEditable::kill-char (GtkEditable *, - ggint, - gpointer); -void GtkEditable::kill-word (GtkEditable *, - ggint, - gpointer); -void GtkEditable::kill-line (GtkEditable *, - ggint, - gpointer); -void GtkEditable::cut-clipboard (GtkEditable *, - gpointer); -void GtkEditable::copy-clipboard (GtkEditable *, - gpointer); -void GtkEditable::paste-clipboard (GtkEditable *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkTipsQuery -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkTipsQuery::start-query (GtkTipsQuery *, - gpointer); -void GtkTipsQuery::stop-query (GtkTipsQuery *, - gpointer); -void GtkTipsQuery::widget-entered (GtkTipsQuery *, - GtkWidget *, - GtkString *, - GtkString *, - gpointer); -gboolean GtkTipsQuery::widget-selected (GtkTipsQuery *, - GtkWidget *, - GtkString *, - GtkString *, - GdkEvent *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkCList -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkCList::select-row (GtkCList *, - ggint, - ggint, - GdkEvent *, - gpointer); -void GtkCList::unselect-row (GtkCList *, - ggint, - ggint, - GdkEvent *, - gpointer); -void GtkCList::row-move (GtkCList *, - ggint, - ggint, - gpointer); -void GtkCList::click-column (GtkCList *, - ggint, - gpointer); -void GtkCList::resize-column (GtkCList *, - ggint, - ggint, - gpointer); -void GtkCList::toggle-focus-row (GtkCList *, - gpointer); -void GtkCList::select-all (GtkCList *, - gpointer); -void GtkCList::unselect-all (GtkCList *, - gpointer); -void GtkCList::undo-selection (GtkCList *, - gpointer); -void GtkCList::start-selection (GtkCList *, - gpointer); -void GtkCList::end-selection (GtkCList *, - gpointer); -void GtkCList::toggle-add-mode (GtkCList *, - gpointer); -void GtkCList::extend-selection (GtkCList *, - GtkScrollType, - ggfloat, - gboolean, - gpointer); -void GtkCList::scroll-vertical (GtkCList *, - GtkScrollType, - ggfloat, - gpointer); -void GtkCList::scroll-horizontal (GtkCList *, - GtkScrollType, - ggfloat, - gpointer); -void GtkCList::abort-column-resize (GtkCList *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkNotebook -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkNotebook::switch-page (GtkNotebook *, - ggpointer, - gguint, - gpointer); - -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkList -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkList::selection-changed (GtkList *, - gpointer); -void GtkList::select-child (GtkList *, - GtkWidget *, - gpointer); -void GtkList::unselect-child (GtkList *, - GtkWidget *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkMenuShell -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkMenuShell::deactivate (GtkMenuShell *, - gpointer); -void GtkMenuShell::selection-done (GtkMenuShell *, - gpointer); -void GtkMenuShell::move-current (GtkMenuShell *, - GtkMenuDirectionType, - gpointer); -void GtkMenuShell::activate-current (GtkMenuShell *, - gboolean, - gpointer); -void GtkMenuShell::cancel (GtkMenuShell *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkToolbar -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkToolbar::orientation-changed (GtkToolbar *, - ggint, - gpointer); -void GtkToolbar::style-changed (GtkToolbar *, - ggint, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkTree -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkTree::selection-changed (GtkTree *, - gpointer); -void GtkTree::select-child (GtkTree *, - GtkWidget *, - gpointer); -void GtkTree::unselect-child (GtkTree *, - GtkWidget *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkButton -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkButton::pressed (GtkButton *, - gpointer); -void GtkButton::released (GtkButton *, - gpointer); -void GtkButton::clicked (GtkButton *, - gpointer); -void GtkButton::enter (GtkButton *, - gpointer); -void GtkButton::leave (GtkButton *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkItem -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkItem::select (GtkItem *, - gpointer); -void GtkItem::deselect (GtkItem *, - gpointer); -void GtkItem::toggle (GtkItem *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkWindow -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkWindow::set-focus (GtkWindow *, - ggpointer, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkHandleBox -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkHandleBox::child-attached (GtkHandleBox *, - GtkWidget *, - gpointer); -void GtkHandleBox::child-detached (GtkHandleBox *, - GtkWidget *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkToggleButton -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkToggleButton::toggled (GtkToggleButton *, - gpointer); - -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkMenuItem -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkMenuItem::activate (GtkMenuItem *, - gpointer); -void GtkMenuItem::activate-item (GtkMenuItem *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkListItem -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkListItem::toggle-focus-row (GtkListItem *, - gpointer); -void GtkListItem::select-all (GtkListItem *, - gpointer); -void GtkListItem::unselect-all (GtkListItem *, - gpointer); -void GtkListItem::undo-selection (GtkListItem *, - gpointer); -void GtkListItem::start-selection (GtkListItem *, - gpointer); -void GtkListItem::end-selection (GtkListItem *, - gpointer); -void GtkListItem::toggle-add-mode (GtkListItem *, - gpointer); -void GtkListItem::extend-selection (GtkListItem *, - GtkEnum, - ggfloat, - gboolean, - gpointer); -void GtkListItem::scroll-vertical (GtkListItem *, - GtkEnum, - ggfloat, - gpointer); -void GtkListItem::scroll-horizontal (GtkListItem *, - GtkEnum, - ggfloat, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkTreeItem -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkTreeItem::collapse (GtkTreeItem *, - gpointer); -void GtkTreeItem::expand (GtkTreeItem *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkCheckMenuItem -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkCheckMenuItem::toggled (GtkCheckMenuItem *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkInputDialog -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkInputDialog::enable-device (GtkInputDialog *, - ggint, - gpointer); -void GtkInputDialog::disable-device (GtkInputDialog *, - ggint, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkColorSelection -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkColorSelection::color-changed (GtkColorSelection *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkStatusBar -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkStatusbar::text-pushed (GtkStatusbar *, - gguint, - GtkString *, - gpointer); -void GtkStatusbar::text-popped (GtkStatusbar *, - gguint, - GtkString *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkCTree -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkCTree::tree-select-row (GtkCTree *, - GtkCTreeNode *, - ggint, - gpointer); -void GtkCTree::tree-unselect-row (GtkCTree *, - GtkCTreeNode *, - ggint, - gpointer); -void GtkCTree::tree-expand (GtkCTree *, - GtkCTreeNode *, - gpointer); -void GtkCTree::tree-collapse (GtkCTree *, - ggpointer, - gpointer); -void GtkCTree::tree-move (GtkCTree *, - GtkCTreeNode *, - GtkCTreeNode *, - GtkCTreeNode *, - gpointer); -void GtkCTree::change-focus-row-expansion (GtkCTree *, - GtkCTreeExpansionType, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkCurve -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkCurve::curve-type-changed (GtkCurve *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkAdjustment -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkAdjustment::changed (GtkAdjustment *, - gpointer); -void GtkAdjustment::value-changed (GtkAdjustment *, - gpointer); -</verb></tscreen> - -<!-- ***************************************************************** --> -<sect> GDK Event Types<label id="sec_GDK_Event_Types"> -<!-- ***************************************************************** --> -<p> -The following data types are passed into event handlers by GTK+. For -each data type listed, the signals that use this data type are listed. - -<itemize> -<item> GdkEvent - <itemize> - <item>drag_end_event - </itemize> - -<item> GdkEventType - -<item> GdkEventAny - <itemize> - <item>delete_event - <item>destroy_event - <item>map_event - <item>unmap_event - <item>no_expose_event - </itemize> - -<item> GdkEventExpose - <itemize> - <item>expose_event - </itemize> - -<item> GdkEventNoExpose - -<item> GdkEventVisibility - -<item> GdkEventMotion - <itemize> - <item>motion_notify_event - </itemize> - -<item> GdkEventButton - <itemize> - <item>button_press_event - <item>button_release_event - </itemize> - -<item> GdkEventKey - <itemize> - <item>key_press_event - <item>key_release_event - </itemize> - -<item> GdkEventCrossing - <itemize> - <item>enter_notify_event - <item>leave_notify_event - </itemize> - -<item> GdkEventFocus - <itemize> - <item>focus_in_event - <item>focus_out_event - </itemize> - -<item> GdkEventConfigure - <itemize> - <item>configure_event - </itemize> - -<item> GdkEventProperty - <itemize> - <item>property_notify_event - </itemize> - -<item> GdkEventSelection - <itemize> - <item>selection_clear_event - <item>selection_request_event - <item>selection_notify_event - </itemize> - -<item> GdkEventProximity - <itemize> - <item>proximity_in_event - <item>proximity_out_event - </itemize> - -<item> GdkEventDragBegin - <itemize> - <item>drag_begin_event - </itemize> - -<item> GdkEventDragRequest - <itemize> - <item>drag_request_event - </itemize> - -<item> GdkEventDropEnter - <itemize> - <item>drop_enter_event - </itemize> - -<item> GdkEventDropLeave - <itemize> - <item>drop_leave_event - </itemize> - -<item> GdkEventDropDataAvailable - <itemize> - <item>drop_data_available_event - </itemize> - -<item> GdkEventClient - <itemize> - <item>client_event - </itemize> - -<item> GdkEventOther - <itemize> - <item>other_event - </itemize> -</itemize> - -The data type <tt/GdkEventType/ is a special data type that is used by -all the other data types as an indicator of the data type being passed -to the signal handler. As you will see below, each of the event data -structures has a member of this type. It is defined as an enumeration -type as follows: - -<tscreen><verb> -typedef enum -{ - GDK_NOTHING = -1, - GDK_DELETE = 0, - GDK_DESTROY = 1, - GDK_EXPOSE = 2, - GDK_MOTION_NOTIFY = 3, - GDK_BUTTON_PRESS = 4, - GDK_2BUTTON_PRESS = 5, - GDK_3BUTTON_PRESS = 6, - GDK_BUTTON_RELEASE = 7, - GDK_KEY_PRESS = 8, - GDK_KEY_RELEASE = 9, - GDK_ENTER_NOTIFY = 10, - GDK_LEAVE_NOTIFY = 11, - GDK_FOCUS_CHANGE = 12, - GDK_CONFIGURE = 13, - GDK_MAP = 14, - GDK_UNMAP = 15, - GDK_PROPERTY_NOTIFY = 16, - GDK_SELECTION_CLEAR = 17, - GDK_SELECTION_REQUEST = 18, - GDK_SELECTION_NOTIFY = 19, - GDK_PROXIMITY_IN = 20, - GDK_PROXIMITY_OUT = 21, - GDK_DRAG_BEGIN = 22, - GDK_DRAG_REQUEST = 23, - GDK_DROP_ENTER = 24, - GDK_DROP_LEAVE = 25, - GDK_DROP_DATA_AVAIL = 26, - GDK_CLIENT_EVENT = 27, - GDK_VISIBILITY_NOTIFY = 28, - GDK_NO_EXPOSE = 29, - GDK_OTHER_EVENT = 9999 /* Deprecated, use filters instead */ -} GdkEventType; -</verb></tscreen> - -The other event type that is different from the others is -<tt/GdkEvent/ itself. This is a union of all the other -data types, which allows it to be cast to a specific -event data type within a signal handler. - -<!-- Just a big list for now, needs expanding upon - TRG --> -So, the event data types are defined as follows: - -<tscreen><verb> -struct _GdkEventAny -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; -}; - -struct _GdkEventExpose -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; - GdkRectangle area; - gint count; /* If non-zero, how many more events follow. */ -}; - -struct _GdkEventNoExpose -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; - /* XXX: does anyone need the X major_code or minor_code fields? */ -}; - -struct _GdkEventVisibility -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; - GdkVisibilityState state; -}; - -struct _GdkEventMotion -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; - guint32 time; - gdouble x; - gdouble y; - gdouble pressure; - gdouble xtilt; - gdouble ytilt; - guint state; - gint16 is_hint; - GdkInputSource source; - guint32 deviceid; - gdouble x_root, y_root; -}; - -struct _GdkEventButton -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; - guint32 time; - gdouble x; - gdouble y; - gdouble pressure; - gdouble xtilt; - gdouble ytilt; - guint state; - guint button; - GdkInputSource source; - guint32 deviceid; - gdouble x_root, y_root; -}; - -struct _GdkEventKey -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; - guint32 time; - guint state; - guint keyval; - gint length; - gchar *string; -}; - -struct _GdkEventCrossing -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; - GdkWindow *subwindow; - GdkNotifyType detail; -}; - -struct _GdkEventFocus -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; - gint16 in; -}; - -struct _GdkEventConfigure -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; - gint16 x, y; - gint16 width; - gint16 height; -}; - -struct _GdkEventProperty -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; - GdkAtom atom; - guint32 time; - guint state; -}; - -struct _GdkEventSelection -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; - GdkAtom selection; - GdkAtom target; - GdkAtom property; - guint32 requestor; - guint32 time; -}; - -/* This event type will be used pretty rarely. It only is important - for XInput aware programs that are drawing their own cursor */ - -struct _GdkEventProximity -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; - guint32 time; - GdkInputSource source; - guint32 deviceid; -}; - -struct _GdkEventDragRequest -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; - guint32 requestor; - union { - struct { - guint protocol_version:4; - guint sendreply:1; - guint willaccept:1; - guint delete_data:1; /* Do *not* delete if link is sent, only - if data is sent */ - guint senddata:1; - guint reserved:22; - } flags; - glong allflags; - } u; - guint8 isdrop; /* This gdk event can be generated by a couple of - X events - this lets the app know whether the - drop really occurred or we just set the data */ - - GdkPoint drop_coords; - gchar *data_type; - guint32 timestamp; -}; - -struct _GdkEventDragBegin -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; - union { - struct { - guint protocol_version:4; - guint reserved:28; - } flags; - glong allflags; - } u; -}; - -struct _GdkEventDropEnter -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; - guint32 requestor; - union { - struct { - guint protocol_version:4; - guint sendreply:1; - guint extended_typelist:1; - guint reserved:26; - } flags; - glong allflags; - } u; -}; - -struct _GdkEventDropLeave -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; - guint32 requestor; - union { - struct { - guint protocol_version:4; - guint reserved:28; - } flags; - glong allflags; - } u; -}; - -struct _GdkEventDropDataAvailable -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; - guint32 requestor; - union { - struct { - guint protocol_version:4; - guint isdrop:1; - guint reserved:25; - } flags; - glong allflags; - } u; - gchar *data_type; /* MIME type */ - gulong data_numbytes; - gpointer data; - guint32 timestamp; - GdkPoint coords; -}; - -struct _GdkEventClient -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; - GdkAtom message_type; - gushort data_format; - union { - char b[20]; - short s[10]; - long l[5]; - } data; -}; - -struct _GdkEventOther -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; - GdkXEvent *xevent; -}; -</verb></tscreen> - -<!-- ***************************************************************** --> -<sect> Code Examples -<!-- ***************************************************************** --> -<p> -Below are the code examples that are used in the above text -which are not included in complete form elsewhere. - -<!-- ----------------------------------------------------------------- --> -<sect1>Tictactoe -<!-- ----------------------------------------------------------------- --> -<sect2>tictactoe.h -<p> -<tscreen><verb> -/* example-start tictactoe tictactoe.h */ - -/* 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ -#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__ */ - -/* example-end */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect2>tictactoe.c -<p> -<tscreen><verb> -/* example-start tictactoe tictactoe.c */ - -/* 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ -#include "gtk/gtksignal.h" -#include "gtk/gtktable.h" -#include "gtk/gtktogglebutton.h" -#include "tictactoe.h" - -enum { - TICTACTOE_SIGNAL, - LAST_SIGNAL -}; - -static void tictactoe_class_init (TictactoeClass *klass); -static void tictactoe_init (Tictactoe *ttt); -static void tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt); - -static gint tictactoe_signals[LAST_SIGNAL] = { 0 }; - -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; -} - -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; -} - -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]); - } -} - -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_active (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; - } - } -} - -/* example-end */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect2>ttt_test.c -<p> -<tscreen><verb> -/* example-start tictactoe ttt_test.c */ - -#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_set_border_width (GTK_CONTAINER (window), 10); - - ttt = tictactoe_new (); - - gtk_container_add (GTK_CONTAINER (window), ttt); - gtk_widget_show (ttt); - - gtk_signal_connect (GTK_OBJECT (ttt), "tictactoe", - GTK_SIGNAL_FUNC (win), NULL); - - gtk_widget_show (window); - - gtk_main (); - - return 0; -} - -/* example-end */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1> GtkDial - -<!-- ----------------------------------------------------------------- --> -<sect2> gtkdial.h -<p> -<tscreen><verb> -/* example-start gtkdial gtkdial.h */ - -/* 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, 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; - - /* update policy (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */ - guint policy : 2; - - /* Button currently pressed or 0 if none */ - guint8 button; - - /* Dimensions of dial components */ - gint radius; - gint pointer_width; - - /* ID of update timer, or 0 if none */ - guint32 timer; - - /* Current angle */ - gfloat angle; - gfloat last_angle; - - /* Old values from adjustment stored so we know when something changes */ - gfloat old_value; - gfloat old_lower; - gfloat old_upper; - - /* The adjustment object that stores the data for this dial */ - 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__ */ -/* example-end */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect2> gtkdial.c -<p> -<tscreen><verb> -/* example-start gtkdial gtkdial.c */ - -/* 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ -#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 - -/* Forward declarations */ - -static void gtk_dial_class_init (GtkDialClass *klass); -static void gtk_dial_init (GtkDial *dial); -static void gtk_dial_destroy (GtkObject *object); -static void gtk_dial_realize (GtkWidget *widget); -static void gtk_dial_size_request (GtkWidget *widget, - GtkRequisition *requisition); -static void gtk_dial_size_allocate (GtkWidget *widget, - GtkAllocation *allocation); -static gint gtk_dial_expose (GtkWidget *widget, - GdkEventExpose *event); -static gint gtk_dial_button_press (GtkWidget *widget, - GdkEventButton *event); -static gint gtk_dial_button_release (GtkWidget *widget, - GdkEventButton *event); -static gint gtk_dial_motion_notify (GtkWidget *widget, - GdkEventMotion *event); -static gint gtk_dial_timer (GtkDial *dial); - -static void gtk_dial_update_mouse (GtkDial *dial, gint x, gint y); -static void gtk_dial_update (GtkDial *dial); -static void gtk_dial_adjustment_changed (GtkAdjustment *adjustment, - gpointer data); -static void gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment, - gpointer data); - -/* Local data */ - -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, - (GtkArgSetFunc) NULL, - (GtkArgGetFunc) 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); -} - -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); -} - -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); -} - -static void -gtk_dial_size_request (GtkWidget *widget, - GtkRequisition *requisition) -{ - requisition->width = DIAL_DEFAULT_SIZE; - requisition->height = DIAL_DEFAULT_SIZE; -} - -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; - dial = GTK_DIAL (widget); - - if (GTK_WIDGET_REALIZED (widget)) - { - - gdk_window_move_resize (widget->window, - allocation->x, allocation->y, - allocation->width, allocation->height); - - } - dial->radius = MIN(allocation->width,allocation->height) * 0.45; - dial->pointer_width = dial->radius / 5; -} - -static gint -gtk_dial_expose (GtkWidget *widget, - GdkEventExpose *event) -{ - GtkDial *dial; - GdkPoint points[6]; - gdouble s,c; - gdouble theta, last, increment; - GtkStyle *blankstyle; - gint xc, yc; - gint upper, lower; - gint tick_length; - gint i, inc; - - 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; - - upper = dial->adjustment->upper; - lower = dial->adjustment->lower; - - /* Erase old pointer */ - - s = sin(dial->last_angle); - c = cos(dial->last_angle); - dial->last_angle = 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; - points[3].x = xc - c*dial->radius/10; - points[3].y = yc + s*dial->radius/10; - points[4].x = points[0].x; - points[4].y = points[0].y; - - blankstyle = gtk_style_new (); - blankstyle->bg_gc[GTK_STATE_NORMAL] = - widget->style->bg_gc[GTK_STATE_NORMAL]; - blankstyle->dark_gc[GTK_STATE_NORMAL] = - widget->style->bg_gc[GTK_STATE_NORMAL]; - blankstyle->light_gc[GTK_STATE_NORMAL] = - widget->style->bg_gc[GTK_STATE_NORMAL]; - blankstyle->black_gc = - widget->style->bg_gc[GTK_STATE_NORMAL]; - - gtk_draw_polygon (blankstyle, - widget->window, - GTK_STATE_NORMAL, - GTK_SHADOW_OUT, - points, 5, - FALSE); - - g_object_unref(blankstyle); - - - /* Draw ticks */ - - if ((upper - lower) == 0) - return; - - increment = (100*M_PI)/(dial->radius*dial->radius); - - inc = (upper - lower); - - while (inc < 100) inc *=10; - while (inc >= 1000) inc /=10; - last = -1; - - for (i=0; i<=inc; i++) - { - theta = ((gfloat)i*M_PI/(18*inc/24.) - M_PI/6.); - - if ((theta - last) < (increment)) - continue; - last = theta; - - s = sin(theta); - c = cos(theta); - - tick_length = (i%(inc/10) == 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); - } - - /* Draw pointer */ - - s = sin(dial->angle); - c = cos(dial->angle); - dial->last_angle = 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; - points[3].x = xc - c*dial->radius/10; - points[3].y = yc + s*dial->radius/10; - points[4].x = points[0].x; - points[4].y = points[0].y; - - - gtk_draw_polygon (widget->style, - widget->window, - GTK_STATE_NORMAL, - GTK_SHADOW_OUT, - points, 5, - TRUE); - - return FALSE; -} - -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); - - /* Determine if button press was within pointer region - we - do this by computing the parallel and perpendicular distance of - the point where the mouse was pressed from the line passing through - the pointer */ - - 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); - } - } - } -} - -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; - } -} -/* example-end */ - -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect2> dial_test.c -<p> -<tscreen><verb> -#include <stdio.h> -#include <gtk/gtk.h> -#include "gtkdial.h" - -void value_changed( GtkAdjustment *adjustment, - GtkWidget *label ) -{ - char buffer[16]; - - sprintf(buffer,"%4.2f",adjustment->value); - gtk_label_set (GTK_LABEL (label), buffer); -} - -int main( int argc, - char *argv[]) -{ - GtkWidget *window; - GtkAdjustment *adjustment; - GtkWidget *dial; - GtkWidget *frame; - GtkWidget *vbox; - GtkWidget *label; - - gtk_init (&argc, &argv); - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - - gtk_window_set_title (GTK_WINDOW (window), "Dial"); - - gtk_signal_connect (GTK_OBJECT (window), "destroy", - GTK_SIGNAL_FUNC (gtk_exit), NULL); - - gtk_container_border_width (GTK_CONTAINER (window), 10); - - vbox = gtk_vbox_new (FALSE, 5); - gtk_container_add (GTK_CONTAINER (window), vbox); - gtk_widget_show(vbox); - - frame = gtk_frame_new (NULL); - gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN); - gtk_container_add (GTK_CONTAINER (vbox), frame); - gtk_widget_show (frame); - - adjustment = GTK_ADJUSTMENT(gtk_adjustment_new (0, 0, 100, 0.01, 0.1, 0)); - - dial = gtk_dial_new(adjustment); - gtk_dial_set_update_policy (GTK_DIAL(dial), GTK_UPDATE_DELAYED); - /* gtk_widget_set_usize (dial, 100, 100); */ - - gtk_container_add (GTK_CONTAINER (frame), dial); - gtk_widget_show (dial); - - label = gtk_label_new("0.00"); - gtk_box_pack_end (GTK_BOX(vbox), label, 0, 0, 0); - gtk_widget_show (label); - - gtk_signal_connect (GTK_OBJECT(adjustment), "value_changed", - GTK_SIGNAL_FUNC (value_changed), label); - - gtk_widget_show (window); - - gtk_main (); - - return 0; -} - -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1> Scribble -<p> -<!-- ----------------------------------------------------------------- --> -<sect2> scribble-simple.c -<p> -<tscreen><verb> -/* example-start scribble-simple scribble-simple.c */ - -/* 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include <gtk/gtk.h> - -/* Backing pixmap for drawing area */ -static GdkPixmap *pixmap = NULL; - -/* Create a new backing pixmap of the appropriate size */ -static gint configure_event( GtkWidget *widget, - GdkEventConfigure *event ) -{ - if (pixmap) - g_object_unref(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; -} - -/* Redraw the screen from the 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; -} - -/* Draw a rectangle on the screen */ -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); -} - -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; -} - -void quit () -{ - gtk_exit (0); -} - -int main( int argc, - char *argv[] ) -{ - GtkWidget *window; - GtkWidget *drawing_area; - GtkWidget *vbox; - - GtkWidget *button; - - gtk_init (&argc, &argv); - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_widget_set_name (window, "Test Input"); - - vbox = gtk_vbox_new (FALSE, 0); - gtk_container_add (GTK_CONTAINER (window), vbox); - gtk_widget_show (vbox); - - gtk_signal_connect (GTK_OBJECT (window), "destroy", - GTK_SIGNAL_FUNC (quit), NULL); - - /* Create the drawing area */ - - drawing_area = gtk_drawing_area_new (); - gtk_drawing_area_size (GTK_DRAWING_AREA (drawing_area), 200, 200); - gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0); - - gtk_widget_show (drawing_area); - - /* Signals used to handle backing pixmap */ - - 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); - - /* Event signals */ - - 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); - - /* .. And a quit button */ - button = gtk_button_new_with_label ("Quit"); - gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); - - gtk_signal_connect_object (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (gtk_widget_destroy), - GTK_OBJECT (window)); - gtk_widget_show (button); - - gtk_widget_show (window); - - gtk_main (); - - return 0; -} -/* example-end */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect2> scribble-xinput.c -<p> -<tscreen><verb> -/* example-start scribble-xinput scribble-xinput.c */ - -/* 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include <gtk/gtk.h> - -/* Backing pixmap for drawing area */ -static GdkPixmap *pixmap = NULL; - -/* Create a new backing pixmap of the appropriate size */ -static gint -configure_event (GtkWidget *widget, GdkEventConfigure *event) -{ - if (pixmap) - g_object_unref(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; -} - -/* Redraw the screen from the 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; -} - -/* Draw a rectangle on the screen, size depending on pressure, - and color on the type of 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); -} - -static void -print_button_press (guint32 deviceid) -{ - GList *tmp_list; - - /* gdk_input_list_devices returns an internal list, so we shouldn't - free it afterwards */ - tmp_list = gdk_input_list_devices(); - - while (tmp_list) - { - GdkDeviceInfo *info = (GdkDeviceInfo *)tmp_list->data; - - if (info->deviceid == deviceid) - { - g_print("Button press on device '%s'\n", info->name); - return; - } - - tmp_list = tmp_list->next; - } -} - -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; -} - -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); - } -} - -void -quit () -{ - gtk_exit (0); -} - -int -main (int argc, char *argv[]) -{ - GtkWidget *window; - GtkWidget *drawing_area; - GtkWidget *vbox; - - GtkWidget *button; - - gtk_init (&argc, &argv); - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_widget_set_name (window, "Test Input"); - - vbox = gtk_vbox_new (FALSE, 0); - gtk_container_add (GTK_CONTAINER (window), vbox); - gtk_widget_show (vbox); - - gtk_signal_connect (GTK_OBJECT (window), "destroy", - GTK_SIGNAL_FUNC (quit), NULL); - - /* Create the drawing area */ - - drawing_area = gtk_drawing_area_new (); - gtk_drawing_area_size (GTK_DRAWING_AREA (drawing_area), 200, 200); - gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0); - - gtk_widget_show (drawing_area); - - /* Signals used to handle backing pixmap */ - - 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); - - /* Event signals */ - - 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); - - /* The following call enables tracking and processing of extension - events for the drawing area */ - gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_CURSOR); - - /* .. And some buttons */ - button = gtk_button_new_with_label ("Input Dialog"); - gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); - - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (create_input_dialog), NULL); - gtk_widget_show (button); - - button = gtk_button_new_with_label ("Quit"); - gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); - - gtk_signal_connect_object (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (gtk_widget_destroy), - GTK_OBJECT (window)); - gtk_widget_show (button); - - gtk_widget_show (window); - - gtk_main (); - - return 0; -} -/* example-end */ -</verb></tscreen> - -<!-- ***************************************************************** --> -<sect> List Widget -<!-- ***************************************************************** --> -<p> -NOTE: The List widget has been superseded by the CList widget. It is -detailed here just for completeness. - -The List widget is designed to act as a vertical container for -widgets that should be of the type ListItem. - -A List widget has its own window to receive events and its own -background color which is usually white. As it is directly derived -from a Container it can be treated as such by using the -GTK_CONTAINER(List) macro, see the Container widget for more on -this. One should already be familiar with the usage of a GList and -its related functions g_list_*() to be able to use the List widget -to it full extent. - -There is one field inside the structure definition of the List -widget that will be of greater interest to us, this is: - -<tscreen><verb> -struct _GtkList -{ - ... - GList *selection; - guint selection_mode; - ... -}; -</verb></tscreen> - -The selection field of a List points to a linked list of all items -that are currently selected, or NULL if the selection is empty. So to -learn about the current selection we read the GTK_LIST()->selection -field, but do not modify it since the internal fields are maintained -by the gtk_list_*() functions. - -The selection_mode of the List determines the selection facilities -of a List and therefore the contents of the GTK_LIST()->selection -field. The selection_mode may be one of the following: - -<itemize> -<item> <tt/GTK_SELECTION_SINGLE/ - The selection is either NULL - or contains a GList pointer - for a single selected item. - -<item> <tt/GTK_SELECTION_BROWSE/ - The selection is NULL if the list - contains no widgets or insensitive - ones only, otherwise it contains - a GList pointer for one GList - structure, and therefore exactly - one list item. - -<item> <tt/GTK_SELECTION_MULTIPLE/ - The selection is NULL if no list - items are selected or a GList pointer - for the first selected item. That - in turn points to a GList structure - for the second selected item and so - on. - -<item> <tt/GTK_SELECTION_EXTENDED/ - The selection is always NULL. -</itemize> - -The default is <tt/GTK_SELECTION_MULTIPLE/. - -<!-- ----------------------------------------------------------------- --> -<sect1> Signals -<p> -<tscreen><verb> -void selection_changed( GtkList *list ); -</verb></tscreen> - -This signal will be invoked whenever the selection field of a List -has changed. This happens when a child of thekList got selected or -deselected. - -<tscreen><verb> -void select_child( GtkList *list, - GtkWidget *child); -</verb></tscreen> - -This signal is invoked when a child of the List is about to get -selected. This happens mainly on calls to gtk_list_select_item(), -gtk_list_select_child(), button presses and sometimes indirectly -triggered on some else occasions where children get added to or -removed from the List. - -<tscreen><verb> -void unselect_child( GtkList *list, - GtkWidget *child ); -</verb></tscreen> - -This signal is invoked when a child of the List is about to get -deselected. This happens mainly on calls to gtk_list_unselect_item(), -gtk_list_unselect_child(), button presses and sometimes indirectly -triggered on some else occasions where children get added to or -removed from the List. - -<!-- ----------------------------------------------------------------- --> -<sect1> Functions -<p> -<tscreen><verb> -guint gtk_list_get_type( void ); -</verb></tscreen> - -Returns the "GtkList" type identifier. - -<tscreen><verb> -GtkWidget *gtk_list_new( void ); -</verb></tscreen> - -Create a new List object. The new widget is returned as a pointer -to a GtkWidget object. NULL is returned on failure. - -<tscreen><verb> -void gtk_list_insert_items( GtkList *list, - GList *items, - gint position ); -</verb></tscreen> - -Insert list items into the list, starting at <tt/position/. -<tt/items/ is a doubly linked list where each nodes data pointer is -expected to point to a newly created ListItem. The GList nodes of -<tt/items/ are taken over by the list. - -<tscreen><verb> -void gtk_list_append_items( GtkList *list, - GList *items); -</verb></tscreen> - -Insert list items just like gtk_list_insert_items() at the end of the -list. The GList nodes of <tt/items/ are taken over by the list. - -<tscreen><verb> -void gtk_list_prepend_items( GtkList *list, - GList *items); -</verb></tscreen> - -Insert list items just like gtk_list_insert_items() at the very -beginning of the list. The GList nodes of <tt/items/ are taken over by -the list. - -<tscreen><verb> -void gtk_list_remove_items( GtkList *list, - GList *items); -</verb></tscreen> - -Remove list items from the list. <tt/items/ is a doubly linked list -where each nodes data pointer is expected to point to a direct child -of list. It is the callers responsibility to make a call to -g_list_free(items) afterwards. Also the caller has to destroy the list -items himself. - -<tscreen><verb> -void gtk_list_clear_items( GtkList *list, - gint start, - gint end ); -</verb></tscreen> - -Remove and destroy list items from the list. A widget is affected if -its current position within the list is in the range specified by -<tt/start/ and <tt/end/. - -<tscreen><verb> -void gtk_list_select_item( GtkList *list, - gint item ); -</verb></tscreen> - -Invoke the select_child signal for a list item specified through its -current position within the list. - -<tscreen><verb> -void gtk_list_unselect_item( GtkList *list, - gint item); -</verb></tscreen> - -Invoke the unselect_child signal for a list item specified through its -current position within the list. - -<tscreen><verb> -void gtk_list_select_child( GtkList *list, - GtkWidget *child); -</verb></tscreen> - -Invoke the select_child signal for the specified child. - -<tscreen><verb> -void gtk_list_unselect_child( GtkList *list, - GtkWidget *child); -</verb></tscreen> - -Invoke the unselect_child signal for the specified child. - -<tscreen><verb> -gint gtk_list_child_position( GtkList *list, - GtkWidget *child); -</verb></tscreen> - -Return the position of <tt/child/ within the list. "-1" is returned on -failure. - -<tscreen><verb> -void gtk_list_set_selection_mode( GtkList *list, - GtkSelectionMode mode ); -</verb></tscreen> - -Set the selection mode MODE which can be of GTK_SELECTION_SINGLE, -GTK_SELECTION_BROWSE, GTK_SELECTION_MULTIPLE or -GTK_SELECTION_EXTENDED. - -<tscreen><verb> -GtkList *GTK_LIST( gpointer obj ); -</verb></tscreen> - -Cast a generic pointer to "GtkList *". - -<tscreen><verb> -GtkListClass *GTK_LIST_CLASS( gpointer class); -</verb></tscreen> - -Cast a generic pointer to "GtkListClass *". - -<tscreen><verb> -gint GTK_IS_LIST( gpointer obj); -</verb></tscreen> - -Determine if a generic pointer refers to a "GtkList" object. - -<!-- ----------------------------------------------------------------- --> -<sect1> Example -<p> -Following is an example program that will print out the changes of the -selection of a List, and lets you "arrest" list items into a prison -by selecting them with the rightmost mouse button. - -<tscreen><verb> -/* example-start list list.c */ - -/* Include the GTK header files - * Include stdio.h, we need that for the printf() function - */ -#include <gtk/gtk.h> -#include <stdio.h> - -/* This is our data identification string to store - * data in list items - */ -const gchar *list_item_data_key="list_item_data"; - - -/* prototypes for signal handler that we are going to connect - * to the List widget - */ -static void sigh_print_selection( GtkWidget *gtklist, - gpointer func_data); - -static void sigh_button_event( GtkWidget *gtklist, - GdkEventButton *event, - GtkWidget *frame ); - - -/* Main function to set up the user interface */ - -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]; - - - /* Initialize GTK (and subsequently GDK) */ - - gtk_init(&argc, &argv); - - - /* Create a window to put all the widgets in - * connect gtk_main_quit() to the "destroy" event of - * the window to handle window manager close-window-events - */ - 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); - - - /* Inside the window we need a box to arrange the widgets - * vertically */ - vbox=gtk_vbox_new(FALSE, 5); - gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); - gtk_container_add(GTK_CONTAINER(window), vbox); - gtk_widget_show(vbox); - - /* This is the scrolled window to put the List widget inside */ - 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); - - /* Create thekList widget. - * Connect the sigh_print_selection() signal handler - * function to the "selection_changed" signal of the List - * to print out the selected items each time the selection - * has changed */ - gtklist=gtk_list_new(); - gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(scrolled_window), - gtklist); - gtk_widget_show(gtklist); - gtk_signal_connect(GTK_OBJECT(gtklist), - "selection_changed", - GTK_SIGNAL_FUNC(sigh_print_selection), - NULL); - - /* We create a "Prison" to put a list item in ;) */ - frame=gtk_frame_new("Prison"); - gtk_widget_set_usize(frame, 200, 50); - gtk_container_set_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); - - /* Connect the sigh_button_event() signal handler to the List - * which will handle the "arresting" of list items - */ - gtk_signal_connect(GTK_OBJECT(gtklist), - "button_release_event", - GTK_SIGNAL_FUNC(sigh_button_event), - frame); - - /* Create a separator */ - separator=gtk_hseparator_new(); - gtk_container_add(GTK_CONTAINER(vbox), separator); - gtk_widget_show(separator); - - /* Finally create a button and connect its "clicked" signal - * to the destruction of the window */ - 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)); - - - /* Now we create 5 list items, each having its own - * label and add them to the List using gtk_container_add() - * Also we query the text string from the label and - * associate it with the list_item_data_key for each list item - */ - 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); - } - /* Here, we are creating another 5 labels, this time - * we use gtk_list_item_new_with_label() for the creation - * we can't query the text string from the label because - * we don't have the labels pointer and therefore - * we just associate the list_item_data_key of each - * list item with the same text string. - * For adding of the list items we put them all into a doubly - * linked list (GList), and then add them by a single call to - * gtk_list_append_items(). - * Because we use g_list_prepend() to put the items into the - * doubly linked list, their order will be descending (instead - * of ascending when using g_list_append()) - */ - 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); - - /* Finally we want to see the window, don't we? ;) */ - gtk_widget_show(window); - - /* Fire up the main event loop of gtk */ - gtk_main(); - - /* We get here after gtk_main_quit() has been called which - * happens if the main window gets destroyed - */ - return(0); -} - -/* This is the signal handler that got connected to button - * press/release events of the List - */ -void sigh_button_event( GtkWidget *gtklist, - GdkEventButton *event, - GtkWidget *frame ) -{ - /* We only do something if the third (rightmost mouse button - * was released - */ - if (event->type==GDK_BUTTON_RELEASE && - event->button==3) { - GList *dlist, *free_list; - GtkWidget *new_prisoner; - - /* Fetch the currently selected list item which - * will be our next prisoner ;) - */ - dlist=GTK_LIST(gtklist)->selection; - if (dlist) - new_prisoner=GTK_WIDGET(dlist->data); - else - new_prisoner=NULL; - - /* Look for already imprisoned list items, we - * will put them back into the list. - * Remember to free the doubly linked list that - * gtk_container_children() returns - */ - 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); - - /* If we have a new prisoner, remove him from the - * List and put him into the frame "Prison". - * We need to unselect the item first. - */ - 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); - } - } -} - -/* This is the signal handler that gets called if List - * emits the "selection_changed" signal - */ -void sigh_print_selection( GtkWidget *gtklist, - gpointer func_data ) -{ - GList *dlist; - - /* Fetch the doubly linked list of selected items - * of the List, remember to treat this as read-only! - */ - dlist=GTK_LIST(gtklist)->selection; - - /* If there are no selected items there is nothing more - * to do than just telling the user so - */ - if (!dlist) { - g_print("Selection cleared\n"); - return; - } - /* Ok, we got a selection and so we print it - */ - g_print("The selection is a "); - - /* Get the list item from the doubly linked list - * and then query the data associated with list_item_data_key. - * We then just print it */ - 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"); -} -/* example-end */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1> List Item Widget -<p> -The ListItem widget is designed to act as a container holding up to -one child, providing functions for selection/deselection just like the -List widget requires them for its children. - -A ListItem has its own window to receive events and has its own -background color which is usually white. - -As it is directly derived from an Item it can be treated as such by -using the GTK_ITEM(ListItem) macro, see the Item widget for more on -this. Usually a ListItem just holds a label to identify, e.g., a -filename within a List -- therefore the convenience function -gtk_list_item_new_with_label() is provided. The same effect can be -achieved by creating a Label on its own, setting its alignment to -xalign=0 and yalign=0.5 with a subsequent container addition to the -ListItem. - -As one is not forced to add a GtkLabel to a GtkListItem, you could -also add a GtkVBox or a GtkArrow etc. to the GtkListItem. - -<!-- ----------------------------------------------------------------- --> -<sect1> Signals -<p> -AkListItem does not create new signals on its own, but inherits -the signals of a Item. - -<!-- ----------------------------------------------------------------- --> -<sect1> Functions -<p> -<tscreen><verb> -guint gtk_list_item_get_type( void ); -</verb></tscreen> - -Returns the "GtkListItem" type identifier. - -<tscreen><verb> -GtkWidget *gtk_list_item_new( void ); -</verb></tscreen> - -Create a new ListItem object. The new widget is returned as a -pointer to a GtkWidget object. NULL is returned on failure. - -<tscreen><verb> -GtkWidget *gtk_list_item_new_with_label( gchar *label ); -</verb></tscreen> - -Create a new ListItem object, having a single GtkLabel as the sole -child. The new widget is returned as a pointer to a GtkWidget -object. NULL is returned on failure. - -<tscreen><verb> -void gtk_list_item_select( GtkListItem *list_item ); -</verb></tscreen> - -This function is basically a wrapper around a call to gtk_item_select -(GTK_ITEM (list_item)) which will emit the select signal. *Note -GtkItem::, for more info. - -<tscreen><verb> -void gtk_list_item_deselect( GtkListItem *list_item ); -</verb></tscreen> - -This function is basically a wrapper around a call to -gtk_item_deselect (GTK_ITEM (list_item)) which will emit the deselect -signal. *Note GtkItem::, for more info. - -<tscreen><verb> -GtkListItem *GTK_LIST_ITEM( gpointer obj ); -</verb></tscreen> - -Cast a generic pointer to "GtkListItem *". - -<tscreen><verb> -GtkListItemClass *GTK_LIST_ITEM_CLASS( gpointer class ); -</verb></tscreen> - -Cast a generic pointer to GtkListItemClass*. *Note Standard Macros::, -for more info. - -<tscreen><verb> -gint GTK_IS_LIST_ITEM( gpointer obj ); -</verb></tscreen> - -Determine if a generic pointer refers to a `GtkListItem' object. -*Note Standard Macros::, for more info. - -<!-- ----------------------------------------------------------------- --> -<sect1> Example -<p> -Please see the List example on this, which covers the usage of a -ListItem as well. - - -</article> diff --git a/docs/tutorial/gtk_tut_12.es.sgml b/docs/tutorial/gtk_tut_12.es.sgml deleted file mode 100755 index 22ce28f870..0000000000 --- a/docs/tutorial/gtk_tut_12.es.sgml +++ /dev/null @@ -1,17638 +0,0 @@ -<!doctype linuxdoc system> - -<!-- - Traducción realizada por: - Joaquín Cuenca Abela (e98cuenc@criens.u-psud.fr) - Eduardo Anglada Varela (eduardo.anglada@adi.uam.es) - - Versión beta 2 de la traducción del GTK+ - Tutorial 1.2. Cualquier sugerencia será bienvenida. - Los cambios más significativos de esta versión son la traducción - de las variables de los programas y XXX. - - Si quiere obtener este documento puede encontrarlo en Linux Landia: - http://www.croftj.net/~barreiro/spanish/gnome-es/ ---> - -<article> -<title>GTK Tutorial v1.2 -<author>Tony Gale <tt><htmlurl url="mailto:gale@gtk.org" - name="<gale@gtk.org>"></tt>, -Ian Main <tt><htmlurl url="mailto:imain@gtk.org" - name="<imain@gtk.org>"></tt> -<date>21 de Febrero de 1999 -<abstract> -Este documento es un tutorial sobre como utilizar GTK (el GIMP -Toolkit) en C -</abstract> - -<toc> - -<!-- ***************************************************************** --> -<sect>Introducción -<!-- ***************************************************************** --> -<p> -GTK (GIMP Toolkit) es una biblioteca para crear interfaces gráficas -de usuario. Su licencia es la LGPL, así que mediante GTK podrá -desarrollar programas con licencias abiertas, gratuitas, libres, y -hasta licencias comerciales no libres sin mayores problemas. - -Se llama el GIMP toolkit porque fue escrito para el desarrollo del -General Image Manipulation Program (GIMP), pero ahora GTK se utiliza -en un gran número de proyectos de programación, incluyendo el -proyecto GNU Network Object Model Environment (GNOME). GTK está -construido encima de GDK (GIMP Drawing Kit) que básicamente es un -recubrimiento de las funciones de bajo nivel que deben haber para -acceder al sistema de ventanas sobre el que se programe (Xlib en el -caso de X windows). Los principales autores de GTK son: - -<itemize> -<item> Peter Mattis <tt><htmlurl url="mailto:petm@xcf.berkeley.edu" - name="petm@xcf.berkeley.edu"></tt> -<item> Spencer Kimball <tt><htmlurl url="mailto:spencer@xcf.berkeley.edu" - name="spencer@xcf.berkeley.edu"></tt> -<item> Josh MacDonald <tt><htmlurl url="mailto:jmacd@xcf.berkeley.edu" - name="jmacd@xcf.berkeley.edu"></tt> -</itemize> - -GTK es esencialmente una interfaz para la programación de -aplicaciones orientadas al objeto (API). Aunque está completamente -escrito en C, esta implementado haciendo uso de la idea de clases y de -funciones respuesta o de <em/callback/ (punteros o funciones). - -Tenemos un tercer componente llamado glib, que contiene unas cuantas -funciones para reemplazar algunas llamadas estándar, así como -funciones adicionales para manejar listas enlazadas, etc... Se -reemplazan algunas funciones para aumentar la portabilidad de GTK, ya -que algunas de las funciones implementadas no están disponibles o -no son estándar en otros unixs, como por ejemplo -g_strerror(). Algunas otras contienen mejoras a la versión de libc, -como g_malloc que mejora las posibilidades de encontrar errores. - -Este tutorial describe la interfaz C de GTK. Hay recubrimientos GTK -para muchos otros lenguajes, incluyendo C++, Guile, Perl, Python, TOM, -Ada95, Objective C, Free Pascal, y Eiffel. Si va a utilizar el -recubrimiento para alguno de estos lenguajes, mire primero su -documentación. En algunos casos la documentación puede describir -algún convenio importante (que debería conocer de antemano) y -después puede volver a este tutorial. También hay algún API -multiplataforma (como wxWindows y V) que utilizan GTK como una de sus -plataformas destino; de nuevo, consulte primero la documentación -que viene con estos paquetes. - -Si está desarrollando su aplicación GTK en C++, hay algunas -cosas que debería saber. Hay un recubriento a GTK para C++ llamado -GTK--, que proporciona una interfaz C++ a GTK; probablemente -debería empezar mirando ahí. Si no le gusta esa aproximación -al problema, por los motivos que sean, tiene dos -alternativas. Primero, puede ceñirse al subconjunto C de C++ cuando -realice alguna llamada a GTK a través de su interfaz en C. Segundo, -puede utilizar GTK y C++ al mismo tiempo declarando todas las -funciones respuesta como funciones estáticas en clases C++, y de -nuevo, llamar a GTK utilizando su interfaz C. Si elige esta última -forma de actuar, puede incluir como dato de la función respuesta un -puntero al objeto a manipular (el también llamado valor -«this»). La elección de una u otra opción es cuestión de -gustos personales, ya que de las tres maneras conseguirá utilizar -GTK en C++. Ninguna de estas aproximaciones requiere el uso de un -preprocesador especializado, por lo que sin importar la opción que -escoja podrá utilizar C++ estándar en C++. - -Este tutorial es un intento de documentar GTK tanto como sea posible, -pero no está completo. Este tutorial asume un buen conocimiento de -C y de como crear programas bajo este lenguaje. Se verá beneficiado -si tiene un conocimiento previo de la programación en X, pero no -debería ser necesario. Si está aprendiendo GTK y es el primer -conjunto de <em/widgets/ que utiliza, por favor envíenos sus -comentarios sobre este tutorial y los problemas que ha -encontrado. - -Este documento es un `trabajo pendiente de finalizar'. Para encontrar -actualizaciones mire en http://www.gtk.org/ <htmlurl -url="http://www.gtk.org/" name="http://www.gtk.org/">. - -Me gustaría escuchar cualquier problema que le surja mientras -aprende GTK siguiendo este documento, y apreciaré cualquier -información sobre como mejorarlo. Por favor, vea la sección <ref -id="sec_Contributing" name="Contribuyendo"> para encontrar más -información. - -<!-- ***************************************************************** --> -<sect>Comenzando -<!-- ***************************************************************** --> - -<p> -Por supuesto lo primero que hay que hacer es descargar las fuentes de -GTK e instalarlas. La última versión siempre se puede obtener de -ftp.gtk.org (en el directorio /pub/gtk). En <htmlurl -url="http://www.gtk.org/" name="http://www.gtk.org/"> hay más -información sobre GTK. Para configurar GTK hay que usar GNU -autoconf. Una vez descomprimido se pueden obtener las opciones usando -<tt>./configure --help</tt>. - -El código de GTK además contiene las fuentes completas de todos -los ejemplos usados en este manual, así como los makefiles para -compilarlos. - -Para comenzar nuestra introducción a GTK vamos a empezar con el -programa más sencillo posible. Con él vamos a crear una ventana de -200x200 <em/pixels/ que sólo se puede destruir desde el shell. - -<tscreen><verb> -/* principio del ejemplo base base.c */ - -#include <gtk/gtk.h> - -int main (int argc, char *argv[]) -{ - GtkWidget *ventana; - - gtk_init (&argc, &argv); - - ventana = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_widget_show (ventana); - - gtk_main (); - - return 0; -} -/* final del ejemplo */ -</verb></tscreen> - -Puede compilar el programa anterior con gcc tecleando: -<tscreen><verb> -gcc base.c -o base `gtk-config --cflags --libs` -</verb></tscreen> - -El significado de la extraña opción de compilación se explica -más adelante. - -Todo programa que use GTK debe llamar a <tt>gtk/gtk.h</tt> donde se -declaran todas las variables, funciones, estructuras, etc. que serán -usadas en el programa. - -La siguiente línea: - -<tscreen><verb> -gtk_init (&argc, &argv); -</verb></tscreen> - -Llama a la función gtk_init (gint *argc, gchar *** argv) responsable -de `arrancar' la biblioteca y de establecer algunos parámetros (como son -los colores y los visuales por defecto), llama a gdk_init (gint *argc, -gchar *** argv) que inicializa la biblioteca para que pueda -utilizarse, establece los controladores de las señales y comprueba los -argumentos pasados a la aplicación desde la línea de comandos, -buscando alguno de los siguientes: - -<itemize> -<item> <tt/--gtk-module/ -<item> <tt/--g-fatal-warnings/ -<item> <tt/--gtk-debug/ -<item> <tt/--gtk-no-debug/ -<item> <tt/--gdk-debug/ -<item> <tt/--gdk-no-debug/ -<item> <tt/--display/ -<item> <tt/--sync/ -<item> <tt/--no-xshm/ -<item> <tt/--name/ -<item> <tt/--class/ -</itemize> - -En el caso de que encuentre alguno lo quita de la lista, dejando todo -aquello que no reconozca para que el programa lo utilice o lo -ignore. Así se consigue crear un conjunto de argumentos que son -comunes a todas las aplicaciones basadas en GTK. - -Las dos líneas de código siguientes crean y muestran una ventana. - -<tscreen><verb> - ventana = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_widget_show (ventana); -</verb></tscreen> - -El argumento GTK_WINDOW_TOPLEVEL especifica que queremos que el gestor -de ventanas decore y sitúe la ventana. En lugar de crear una ventana -de tamaño 0 x 0 toda ventana sin hijos por defecto es de 200 x 200, con -lo que se consigue que pueda ser manipulada. - -La función gtk_widget_show() le comunica a GTK que hemos acabado de -especificar los atributos del <em/widget/, y que por tanto puede -mostrarlo. - -La última línea comienza el proceso del bucle principal de GTK. - -<tscreen><verb> -gtk_main (); -</verb></tscreen> - -Otra llamada que siempre está presente en cualquier aplicación es -gtk_main(). Cuando el control llega a ella, GTK se queda dormido -esperando a que suceda algún tipo de evento de las X (como puede ser -pulsar un botón), que pase el tiempo necesario para que el usuario -haga algo, o que se produzcan notificaciones de IO de archivos. En -nuestro caso concreto todos los eventos serán ignorados. - - -<!-- ----------------------------------------------------------------- --> -<sect1>Programa «Hola Mundo» en GTK -<p> -El siguiente ejemplo es un programa con un <em/widget/ (un -botón). Simplemente es la versión de GTK del clásico «hola mundo». - -<tscreen><verb> -/* comienzo del ejemplo holamundo */ -#include <gtk/gtk.h> - -/* Ésta es una función respuesta (callback). Sus argumentos - son ignorados por en este ejemplo */ -void hello (GtkWidget *widget, gpointer data) -{ - g_print ("Hola mundo\n"); -} - -gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data) -{ - /* si se devuelve FALSE al administrador de llamadas - * "delete_event", GTK emitirá la señal de destrucción - * "destroy". Esto es útil para diálogos emergentes del - * tipo: ¿Seguro que desea salir? - - g_print ("Ha ocurrido un evento delete\n"); - - /* Cambiando TRUE por FALSE la ventana se destruirá con - * "delete_event"*/ - - return (TRUE); -} - -/* otra respuesta */ -void destroy (GtkWidget *widget, gpointer data) -{ - gtk_main_quit (); -} - -int main (int argc, char *argv[]) -{ - - /* GtkWidget es el tipo de almacenamiento usado para los - * widgets */ - GtkWidget *ventana; - GtkWidget *boton; - - /* En cualquier aplicación hay que realizar la siguiente - * llamada. Los argumentos son tomados de la línea de comandos - * y devueltos a la aplicación. */ - - gtk_init (&argc, &argv); - - /* creamos una ventana nueva */ - ventana = gtk_window_new (GTK_WINDOW_TOPLEVEL); - - /* Cuando la ventana recibe la señal "delete_event" (emitida - * por el gestor de ventanas, normalmente mediante la opción - * 'close', o en la barra del título) hacemos que llame a la - * función delete_event() tal y como ya hemos visto. Los datos - * pasados a la función de respuesta son NULL, y serán ignorados. */ - gtk_signal_connect (GTK_OBJECT (ventana), "delete_event", - GTK_SIGNAL_FUNC (delete_event), NULL); - - /* Aquí conectamos el evento "destroy" con el administrador de - * señales. El evento se produce cuando llamamos a - * gtk_widget_destroy() desde la ventana o si devolvemos 'FALSE' - * en la respuesta "delete_event". */ - gtk_signal_connect (GTK_OBJECT (ventana), "destroy", - GTK_SIGNAL_FUNC (destroy), NULL); - - /* establecemos el ancho del borde de la ventana. */ - gtk_container_border_width (GTK_CONTAINER (ventana), 10); - - /* creamos un botón nuevo con la etiqueta "Hola mundo" */ - boton = gtk_button_new_with_label ("Hola mundo"); - - /* Cuando el botón recibe la señal "clicked" llama a la - * función hello() pasándole NULL como argumento. (La - * función ya ha sido definida arriba). */ - gtk_signal_connect (GTK_OBJECT (boton), "clicked", - GTK_SIGNAL_FUNC (hello), NULL); - - /* Esto hará que la ventana sea destruida llamando a - * gtk_widget_destroy(ventana) cuando se produzca "clicked". Una - * vez mas la señal de destrucción puede provenir del gestor - * de ventanas o de aquí. */ - gtk_signal_connect_object (GTK_OBJECT (boton), "clicked", - GTK_SIGNAL_FUNC (gtk_widget_destroy), - GTK_OBJECT (ventana)); - - /* Ahora empaquetamos el botón en la ventana (usamos un gtk - * container ). */ - gtk_container_add (GTK_CONTAINER (ventana), boton); - - /* El último paso es representar el nuevo widget... */ - gtk_widget_show (boton); - - /* y la ventana */ - gtk_widget_show (ventana); - - /* Todas las aplicaciones basadas en GTK deben tener una llamada - * gtk_main() ya que el control termina justo aquí y debe - * esperar a que suceda algún evento */ - - gtk_main (); - - return 0; -} -/* final del ejemplo*/ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Compilando Hello World -<p> -Para compilar el ejemplo hay que usar: - -<tscreen><verb> -gcc -Wall -g helloworld.c -o hello_world `gtk-config --cflags` \ - `gtk-config --libs` -</verb></tscreen> - -Usamos el programa <tt>gtk-config</>, que ya viene (y se instala) con -la biblioteca. Es muy útil porque `conoce' que opciones son -necesarias para compilar programas que usen gtk. <tt>gtk-config ---cflags</tt> dará una lista con los directorios donde el -compilador debe buscar ficheros «include». A su vez <tt>gtk-config ---libs</tt> nos permite saber las bibliotecas que el compilador -intentará enlazar y dónde buscarlas. - -Hay que destacar que las comillas simples en la orden de -compilación son absolutamente necesarias. - -Las bibliotecas que se enlazan normalmente son: - -<itemize> - -<item>La biblioteca GTK (-lgtk), la biblioteca de <em/widgets/ que se -encuentra encima de GDK. - -<item>La biblioteca GDK (-lgdk), el wrapper de Xlib. - -<item>La biblioteca glib (-lglib), que contiene diversas funciones. En -nuestro ejemplo sólo hemos usado g_print(). GTK está construida -encima de glib por lo que simpre se usará. Vea la sección <ref -id="sec_glib" name="glib"> para más detalles. - -<item>La biblioteca Xlib (-lX11) que es usada por GDK. - -<item> La biblioteca Xext (-lXext) contiene código para -<em/pixmaps/ de memoria compartida y otras extensiones. - -<item>La biblioteca matemática (-lm). Es usada por GTK para -diferentes cosas. - -</itemize> - -<!-- ----------------------------------------------------------------- --> -<sect1>Teoría de señales y respuestas -<p> -Antes de profundizar en <tt/holamundo/ vamos a discutir las -señales y las respuestas. GTK es un toolkit (conjunto de -herramientas) gestionadas mediante eventos. Esto quiere decir que GTK -«duerme» en gtk_main hasta que se recibe un evento, momento en el -cual se transfiere el control a la función adecuada. - -El control se transfiere mediante «señales». (Conviene destacar -que las señales de GTK no son iguales que las de los sistemas -UNIX, aunque la terminología es la misma.) Cuando sucede un evento, -como por ejemplo la pulsación de un botón, se «emitirá» la -señal apropiada por el <em/widget/ pulsado. Así es como GTK -proporciona la mayor parte de su utilidad. Hay un conjunto de -señales que todos los <em/widgets/ heredan, como por ejemplo -«destroy» y hay señales que son específicas de cada -<em/widget/, como por ejemplo la señal «toggled» de un botón -de selección (botón <em/toggle/). - -Para que un botón haga algo crearemos un controlador que se encarga de -recoger las señales y llamar a la función apropiada. Esto se hace -usando una función como: - -<tscreen><verb> -gint gtk_signal_connect( GtkObject *objeto, - gchar *nombre, - GtkSignalFunc func, - gpointer datos_func ); -</verb></tscreen> - -Donde el primer argumento es el <em/widget/ que emite la señal, el -segundo el nombre de la señal que queremos `cazar', el tercero es -la función a la que queremos que se llame cuando se `cace' la -señal y el cuarto los datos que queremos pasarle a esta función. - -La función especificada en el tercer argumento se denomina «función -de respuesta» y debe tener la forma siguiente: - -<tscreen><verb> -void callback_func( GtkWidget *widget, - gpointer datos_respuesta ); -</verb></tscreen> - -Donde el primer argumento será un puntero al <em/widget/ que emitió la -señal, y el segundo un puntero a los datos pasados a la función tal y -como hemos visto en el último argumento a gtk_signal_connect(). - -Conviene destacar que la declaración de la función de respuesta debe -servir sólo como guía general, ya que algunas señales específicas -pueden generar diferentes parámetros de llamada. Por ejemplo, la señal -de GtkCList «select_row» proporciona los parámetros fila y columna. - -Otra llamada usada en el ejemplo del hola mundo es: - -<tscreen><verb> -gint gtk_signal_connect_object( GtkObject *objeto, - gchar *nombre, - GtkSignalFunc func, - GtkObject *slot_object ); -</verb></tscreen> - -gtk_signal_connect_object() es idéntica a gtk_signal_connect() excepto -en que la función de llamada sólo usa un argumento, un puntero a un -objeto GTK. Por tanto cuando usemos esta función para conectar -señales, la función de respuesta debe ser de la forma: - -<tscreen><verb> -void callback_func( GtkObject *object ); -</verb></tscreen> - -Donde, por regla general, el objeto es un <em/widget/. Sin embargo no -es normal establecer una respuesta para gtk_signal_connect_object. En -lugar de ello llamamos a una función de GTK que acepte un <em/widget/ -o un objeto como un argumento, tal y como se vio en el ejemplo hola -mundo. - -¿Para qué sirve tener dos funciones para conectar señales? Simplemente -para permitir que las funciones de respuesta puedan tener un número -diferente de argumentos. Muchas funciones de GTK sólo aceptan un -puntero a un GtkWidget como argumento, por lo que tendrá que usar -gtk_signal_connect_object() con estas funciones, mientras que -probablemente tenga que suministrarle información adicional a sus -funciones. - -<!-- XXX Completamente revisado hasta aquí -------------------------- --> -<sect1>Eventos -<p> -Además del mecanismo de señales descrito arriba existe otro conjunto -de <em>eventos</em> que reflejan como las X manejan los eventos. Se -pueden asignar funciones de respuesta a estos eventos. Los eventos -son: - -<itemize> -<item> event -<item> button_press_event -<item> button_release_event -<item> motion_notify_event -<item> delete_event -<item> destroy_event -<item> expose_event -<item> key_press_event -<item> key_release_event -<item> enter_notify_event -<item> leave_notify_event -<item> configure_event -<item> focus_in_event -<item> focus_out_event -<item> map_event -<item> unmap_event -<item> property_notify_event -<item> selection_clear_event -<item> selection_request_event -<item> selection_notify_event -<item> proximity_in_event -<item> proximity_out_event -<item> drag_begin_event -<item> drag_request_event -<item> drag_end_event -<item> drop_enter_event -<item> drop_leave_event -<item> drop_data_available_event -<item> other_event -</itemize> - -Para conectar una función de respuesta a alguno de los eventos -anteriores debe usar la función gtk_signal_connect, tal y como se -descrivió anteriormente, utilizando en el parámetro <tt/name/ uno de -los nombres de los eventos que se acaban de mencionar. La función de -respuesta para los eventos tiene un forma ligeramente diferente de la -que tiene para las señales: - -<tscreen><verb> -void callback_func( GtkWidget *widget, - GdkEvent *event, - gpointer callback_data ); -</verb></tscreen> - -GdkEvent es una estructura <tt/union/ cuyo tipo depende de cual de los -eventos anteriores haya ocurrido. Para que podamos decir que evento se -ha lanzado cada una de las posibles alternativas posee un parámetro -<tt/type/ que refleja cual es el evento en cuestión. Los otros -componentes de la estructura dependerán del tipo de evento. Algunos -valores posibles son: - -<tscreen><verb> - GDK_NOTHING - GDK_DELETE - GDK_DESTROY - GDK_EXPOSE - GDK_MOTION_NOTIFY - GDK_BUTTON_PRESS - GDK_2BUTTON_PRESS - GDK_3BUTTON_PRESS - GDK_BUTTON_RELEASE - GDK_KEY_PRESS - GDK_KEY_RELEASE - GDK_ENTER_NOTIFY - GDK_LEAVE_NOTIFY - GDK_FOCUS_CHANGE - GDK_CONFIGURE - GDK_MAP - GDK_UNMAP - GDK_PROPERTY_NOTIFY - GDK_SELECTION_CLEAR - GDK_SELECTION_REQUEST - GDK_SELECTION_NOTIFY - GDK_PROXIMITY_IN - GDK_PROXIMITY_OUT - GDK_DRAG_BEGIN - GDK_DRAG_REQUEST - GDK_DROP_ENTER - GDK_DROP_LEAVE - GDK_DROP_DATA_AVAIL - GDK_CLIENT_EVENT - GDK_VISIBILITY_NOTIFY - GDK_NO_EXPOSE - GDK_OTHER_EVENT /* En desuso, usar filtros en lugar de ella */ -</verb></tscreen> - -Por lo tanto para conectar una función de respuesta a uno de estos -eventos debemos usar algo como: - -<tscreen><verb> -gtk_signal_connect( GTK_OBJECT(boton), "button_press_event", - GTK_SIGNAL_FUNC(button_press_callback), - NULL); -</verb></tscreen> - -Por supuesto se asume que <tt/boton/ es un <em/widget/ -GtkButton. Cada vez que el puntero del ratón se encuentre sobre el -botón y éste sea presionado, se llamará a la función -<tt/button_press_callback/. Esta función puede declararse así: - -<tscreen><verb> -static gint button_press_event (GtkWidget *widget, - GdkEventButton *event, - gpointer data); -</verb></tscreen> - -Conviene destacar que se puede declarar el segundo argumento como -<tt/GdkEventButton/ porque sabemos que este tipo de evento ocurrirá -cuando se llame a la función. - -El valor devuelto por esta función es usado para saber si el evento -debe ser propagado a un nivel más profundo dentro del mecanismo de -GTK para gestionar los eventos. Si devuelve TRUE el evento ya ha sido -gestionado y por tanto no tiene que ser tratado por el mecanismo de -gestión. Por contra si devuelve FALSE se continua con la gestión -normal del evento. Para más detalles se recomienda leer la sección -donde se aclara como se produce el proceso de propagación. - -Para más detalles acerca de los tipos de información GdkEvent -consultar el apéndice <ref id="sec_GDK_Event_Types" name="Tipos de -eventos GDK">. - -<!-- ----------------------------------------------------------------- --> -<sect1>Aclaración de Hello World -<p> -Ahora que conocemos la teoría vamos a aclarar las ideas estudiando -en detalle el programa <tt/helloworld/. - -Ésta es la función respuesta a la que se llamará cuando se -pulse el botón. En el ejemplo ignoramos tanto el <em/widget/ como -la información, pero no es difícil usarlos. El siguiente ejemplo -usará la información que recibe como argumento para decirnos que -botón fue presionado. - -<tscreen><verb> -void hello (GtkWidget *widget, gpointer data) -{ - g_print ("Hello World\n"); -} -</verb></tscreen> - -La siguiente respuesta es un poco especial, el «delete_event» ocurre -cuando el gestor de ventanas envía este evento a la aplicación. Aquí -podemos decidir que hacemos con estos eventos. Los podemos ignorar, -dar algún tipo de respuesta, o simplemente terminar la aplicación. - -El valor devuelto en esta respuesta le permite a GTK saber que tiene -que hacer. Si devolvemos TRUE, estamos diciendo que no queremos que se -emita la señal «destroy» y por lo tanto queremos que nuestra -aplicación siga ejecutándose. Si devolvemos FALSE, decimos que -se emita «destroy», lo que hará que se ejecute nuestro manejador -de señal de «destroy». - -<tscreen><verb> -gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data) -{ - g_print ("delete event occured\n"); - - return (TRUE); -} -</verb></tscreen> - -Con el siguiente ejemplo presentamos otra función de respuesta que hace -que el programa salga llamando a gtk_main_quit(). Con esta función le -decimos a GTK que salga de la rutina gtk_main() cuando vuelva a estar -en ella. - -<tscreen><verb> -void destroy (GtkWidget *widget, gpointer data) -{ - gtk_main_quit (); -} -</verb></tscreen> - -Como el lector probablemente ya sabe toda aplicación debe tener una -función main(), y una aplicación GTK no va a ser menos. Todas las -aplicaciones GTK también tienen una función de este tipo. - -<tscreen><verb> -int main (int argc, char *argv[]) -</verb></tscreen> - -Las líneas siguientes declaran un puntero a una estructura del tipo -GtkWidget, que se utilizarán más adelante para crear una ventana y un -botón. - -<tscreen><verb> - GtkWidget *ventana; - GtkWidget *boton; -</verb></tscreen> - -Aquí tenemos otra vez a gtk_init. Como antes arranca el conjunto de -herramientas y filtra las opciones introducidas en la línea de -órdenes. Cualquier argumento que sea reconocido será borrado de la -lista de argumentos, de modo que la aplicación recibirá el resto. - -<tscreen><verb> - gtk_init (&argc, &argv); -</verb></tscreen> - -Ahora vamos a crear una ventana. Simplemente reservamos memoria para -la estructura GtkWindow *ventana, con lo que ya tenemos una nueva -ventana, ventana que no se mostrará hasta que llamemos a -gtk_widget_show (ventana) hacia el final del programa. - -<tscreen><verb> - ventana = gtk_window_new (GTK_WINDOW_TOPLEVEL); -</verb></tscreen> - -Aquí tenemos un ejemplo de como conectar un manejador de señal a un -objeto, en este caso, la ventana. La señal a cazar será -«destroy». Esta señal se emite cuando utilizamos el administrador de -ventanas para matar la ventana (y devolvemos TRUE en el manejador -«delete_event»), o cuando usamos llamamos a gtk_widget_destroy() -pasándole el <em/widget/ que representa la ventana como argumento. -Así conseguimos manejar los dos casos con una simple llamada a la -función destroy () (definida arriba) pasándole NULL como argumento y -ella acabará con la aplicación por nosotros. - -GTK_OBJECT y GTK_SIGNAL_FUNC son macros que realizan la comprobación y -transformación de tipos por nosotros. También aumentan la legibilidad -del código. - -<tscreen><verb> - gtk_signal_connect (GTK_OBJECT (ventana), "destroy", - GTK_SIGNAL_FUNC (destroy), NULL); -</verb></tscreen> - -La siguiente función establece un atributo a un objeto contenedor -(discutidos luego). En este caso le pone a la ventana un área -negra de 10 <em/pixels/ de ancho donde no habrán <em/widgets/. Hay -funciones similares que serán tratadas con más detalle en la sección -<ref id="sec_setting_widget_attributes" name="Estableciendo los -atributos de los <em/widgets/"> - -De nuevo, GTK_CONTAINER es una macro que se encarga de la conversión -entre tipos - -<tscreen><verb> - gtk_container_border_width (GTK_CONTAINER (ventana), 10); -</verb></tscreen> - -La siguiente llamada crea un nuevo botón. Reserva espacio en la -memoria para una nueva estructura del tipo GtkWidget, la inicializa -y hace que el puntero <tt/boton/ apunte a esta estructura. Su etiqueta -será: "Hola mundo". - -<tscreen><verb> - boton = gtk_button_new_with_label ("Hola mundo"); -</verb></tscreen> - -Ahora hacemos que el botón sea útil, para ello enlazamos el botón con -el manejador de señales para que cuando emita la señal «clicked», se -llame a nuestra función hola(). Los datos adicionales serán -ignorados, por lo que simplemente le pasaremos NULL a la función -respuesta. Obviamente se emitirá la señal «clicked» cuando pulsemos -en el botón con el ratón. - -<tscreen><verb> - gtk_signal_connect (GTK_OBJECT (boton), "clicked", - GTK_SIGNAL_FUNC (hola), NULL); -</verb></tscreen> -XXX -Ahora vamos a usar el botón para terminar nuestro programa. Así -aclararemos cómo es posible que la señal «destroy» sea emitida tanto -por el gestor de ventanas como por nuestro programa. Cuando el botón -es pulsado, al igual que arriba, se llama a la primera función -respuesta hello() y después se llamará a esta función. Las funciones -respuesta serán ejecutadas en el orden en que sean conectadas. Como la -función gtk_widget_destroy() sólo acepta un GtkWidget como argumento, -utilizaremos gtk_signal_connect_object() en lugar de -gtk_signal_connect(). - -<tscreen><verb> -gtk_signal_connect_object (GTK_OBJECT (boton), "clicked", - GTK_SIGNAL_FUNC (gtk_widget_destroy), - GTK_OBJECT (ventana)); -</verb></tscreen> - -La siguiente llamada sirve para empaquetar (más detalles luego). Se -usa para decirle a GTK que el botón debe estar en la ventana dónde -será mostrado. Conviene destacar que un contenedor GTK sólo puede -contener un <em/widget/. Existen otros <em/widgets/ (descritos -después) que sirven para contener y establecer la disposición de -varios <em/widgets/ de diferentes formas. - -<tscreen><verb> - gtk_container_add (GTK_CONTAINER (ventana), boton); -</verb></tscreen> - -Ahora ya tenemos todo bien organizado. Como todos los controladores de -las señales ya están en su sitio, y el botón está situado en la -ventana donde queremos que esté, sólo nos queda pedirle a GTK que -muestre todos los <em/widgets/ en pantalla. El <em/widget/ ventana será -el último en mostrarse queremos que aparezca todo de golpe, en vez de -ver aparecer la ventana, y después ver aparecer el botón. De todas -formas con un ejemplo tan simple nunca se notaría cual es el orden de -aparición. - -<tscreen><verb> - gtk_widget_show (boton); - - gtk_widget_show (ventana); -</verb></tscreen> - -Llamamos a gtk_main() que espera hasta que el servidor X le comunique -que se ha producido algún evento para emitir las señales apropiadas. - -<tscreen><verb> - gtk_main (); -</verb></tscreen> - -Por último el `return' final que devuelve el control cuando gtk_quit() -sea invocada. - -<tscreen><verb> - return 0; -</verb></tscreen> - -Cuando pulsemos el botón del ratón el <em/widget/ emite la señal -correspondiente «clicked». Para que podamos usar la información el -programa activa el gestor de eventos que al recibir la señal llama a -la función que hemos elegido. En nuestro ejemplo cuando pulsamos el -botón se llama a la función hello() con NULL como argumento y además -se invoca al siguiente manipulador de señal. Así conseguimos que se -llame a la función gtk_widget_destroy() con el <em/widget/ asociado a -la ventana como argumento, lo que destruye al <em/widget/. Esto hace -que la ventana emita la señal «destroy», que es cazada, y que llama -a nuestra función respuesta destroy(), que simplemente sale de GTK. - -Otra posibilidad es usar el gestor de ventanas para acabar con la -aplicación. Esto emitirá «delete_event» que hará que se -llame a nuestra función manejadora correspondiente. Si en la -función manejadora «delete_event» devolvemos TRUE la ventana se -quedará como si nada hubiese ocurrido, pero si devolvemos FALSE GTK -emitirá la señal «destroy» que, por supuesto, llamará a la -función respuesta «destroy», que saldrá de GTK. - -<!-- ***************************************************************** --> -<sect>Avanzando -<!-- ***************************************************************** --> - -<!-- ----------------------------------------------------------------- --> -<sect1>Tipos de datos -<p> -Existen algunos detalles de los ejemplos anteriores que hay que aclarar. -Los tipos gint, gchar, etc. que puede ver por ahí son typedefs a int y -a char respectivamente. Sirven para que no haya que tener en cuenta el -tamaño de cada uno de ellos a la hora de hacer cálculos. - -Un buen ejemplo es <tt/gint32/ que es un entero de 32 bits independientemente -de la plataforma, bien sea un Alpha de 64 bits o un i386 de 32. Todas las -definiciones son muy intuitivas y se encuentran definidas en glib/glib.h -(que se incluye desde gtk.h). - -Probablemente el lector se haya dado cuenta de que se puede usar GtkWidget -cuando la función llama a un GtkObject. Esto es debido a que GTK -está orienta a objetos y un <em/widget/ es un GtkObject. - -<!-- ----------------------------------------------------------------- --> -<sect1>Más sobre el manejo de señales -<p> -Si estudiamos en mayor profundidad la declaración de -gtk_signal_connect: - -<tscreen><verb> -gint gtk_signal_connect( GtkObject *object, - gchar *name, - GtkSignalFunc func, - gpointer func_data ); -</verb></tscreen> - -Podemos darnos cuenta de que el valor devuelto es del tipo gint. Este -valor es una etiqueta que identifica a la función de respuesta. Tal -y como ya vimos podemos tener tantas funciones de respuesta por -seÑal y objeto como sean necesarias, y cada una de ellas se -ejecutará en el mismo orden en el que fueron enlazadas. - -Esta etiqueta nos permite eliminar la función respuesta de la lista -usando: - -<tscreen><verb> -void gtk_signal_disconnect( GtkObject *object, - gint id ); -</verb></tscreen> - -Por lo tanto podemos desconectar un manejador de señal pasándole -a la función anterior el <em/widget/ del que queremos desconectar y -la etiqueta o id devuelta por una de las funciones signal_connect. - -Otra función que se usa para quitar desconectar todos los -controladores de un objeto es: - -<tscreen><verb> -void gtk_signal_handlers_destroy( GtkObject *object ); -</verb></tscreen> - -Esta llamada es bastante auto explicativa. Simplemente quitamos todos los -controladores de señales del objeto que pasamos como primer argumento. - -<!-- ----------------------------------------------------------------- --> -<sect1>Un Hello World mejorado. -<p> -Vamos a mejorar el ejemplo para obtener una visión más amplia -sobre el manejo de señales y respuestas. También introduciremos -los <em/widgets/ usados para empaquetar. - -<tscreen><verb> -/* principio del ejemplo helloworld2 */ - -#include <gtk/gtk.h> - -/* Nuestra respuesta mejorada. Los argumentos de la función se - * imprimen en el stdout.*/ -void callback (GtkWidget *widget, gpointer data) -{ - g_print ("Hello again - %s was pressed\n", (char *) data); -} - -/* otra respuesta*/ -void delete_event (GtkWidget *widget, GdkEvent *event, gpointer data) -{ - gtk_main_quit (); -} - -int main (int argc, char *argv[]) -{ - /* GtkWidget es el tipo de almacenamiento usado para los wigtes*/ - GtkWidget *ventana; - GtkWidget *boton; - GtkWidget *caja1; - - /* Esta llamada está presente en todas las aplicaciones basadas - * en GTK. Los argumentos introducidos a la aplicación*/ - gtk_init (&argc, &argv); - - /* creamos una nueva ventana*/ - ventana = gtk_window_new (GTK_WINDOW_TOPLEVEL); - - /* Esta función es nueva, pone como título de la ventana - * "¡Hola botones!"*/ - - gtk_window_set_title (GTK_WINDOW (ventana), "¡Hola botones!"); - - /* Establecemos el controlador para la llamada delete_event que - * termina la aplicación inmediatamente. */ - - gtk_signal_connect (GTK_OBJECT (ventana), "delete_event", - GTK_SIGNAL_FUNC (delete_event), NULL); - - - /* Establecemos el ancho del borde de la ventana.*/ - gtk_container_border_width (GTK_CONTAINER (ventana), 10); - - /* Creamos una caja donde empaquetaremos los widgets. El - * procedimiento de empaquetamiento se describe en detalle en la - * sección correspondiente. La caja no se ve realmente, sólo - * sirve para introducir los widgets. */ - caja1 = gtk_hbox_new(FALSE, 0); - - /* ponemos la caja en la ventana principal */ - gtk_container_add (GTK_CONTAINER (ventana), caja1); - - /* Creamos un nuevo botón con la etiqueta "Botón 1". */ - boton = gtk_button_new_with_label ("Botón 1"); - - /* Cada vez que el botón sea pulsado llamamos a la función - * "callback" con un puntero a "botón 1" como argumento. */ - gtk_signal_connect (GTK_OBJECT (boton), "clicked", - GTK_SIGNAL_FUNC (callback), (gpointer) "botón 1"); - - /* En lugar de gtk_container_add empaquetamos el botón en la - * caja invisible, que a su vez ha sido empaquetado en la - * ventana. */ - gtk_box_pack_start(GTK_BOX(caja1), boton, TRUE, TRUE, 0); - - /* Siempre se debe realizar este paso. Sirve para decirle a GTK - * que los preparativos del botón ya se han finalizado y que - * por tanto puede ser mostrado. */ - gtk_widget_show(boton); - - /* hacemos lo mismo para crear un segundo botón. */ - boton = gtk_button_new_with_label ("Botón 2"); - - /* Llamamos a la misma función de respuesta pero con diferente - * argumento: un puntero a "botón 2". */ - gtk_signal_connect (GTK_OBJECT (boton), "clicked", - GTK_SIGNAL_FUNC (callback), (gpointer) "botón 2"); - - gtk_box_pack_start(GTK_BOX(caja1), boton, TRUE, TRUE, 0); - - /* El orden en que mostramos los botones no es realmente - * importante, pero se recomienda mostrar la ventana la última - * para que todo aparezca de golpe. */ - gtk_widget_show(boton); - - gtk_widget_show(caja1); - - gtk_widget_show (ventana); - - /* Esperamos en gtk_main a que comience el espectáculo.*/ - gtk_main (); - - return 0; -} -/* final del ejemplo*/ -</verb></tscreen> - -Compile el programa usando los mismos argumentos que en el ejemplo -anterior. Probablemente ya se habrá dado cuenta de que no hay una -forma sencilla para terminar el programa, se debe usar el gestor de -ventanas o la línea de comandos para ello. Un buen ejercicio para -el lector es introducir un tercer botón que termine el -programa. También puede resultar interesante probar las diferentes -opciones de gtk_box_pack_start() mientras lee la siguiente -sección. Intente cambiar el tamaño de la ventana y observe el -comportamiento. - -Como última nota, existe otra definición bastante útil: -gtk_widow_new() - GTK_WINDOW_DIALOG. Su comportamiento es un poco -diferente y debe ser usado para ventanas intermedias (cuadros de -diálogo). - -<!-- ***************************************************************** --> -<sect><em/Widgets/ usados para empaquetar -<!-- ***************************************************************** --> -<p> -Al crear una aplicación normalmente se quiere que haya más de un -<em/widget/ por ventana. Nuestro primer ejemplo sólo usaba un -<em/widget/ por lo que usábamos la función gtk_container_add -para «empaquetar» el <em/widget/ en la ventana. Pero cuando cuando -se quiere poner más de un <em/widget/ en una ventana, ¿Cómo -podemos controlar donde aparecerá el <em/widget/?. Aquí es donde -entra el empaquetamiento. - -<!-- ----------------------------------------------------------------- --> -<sect1>Empaquetamiento usando cajas -<p> -Normalmente para empaquetar se usan cajas, tal y como ya hemos -visto. Éstas son <em/widgets/ invisibles que pueden contener -nuestros <em/widgets/ de dos formas diferentes, horizontal o -verticalmente. Al hacerlo de la primera forma los objetos son -insertados de izquierda a derecha o al revés (dependiendo de que -llamada se use). Lo mismo ocurre en los verticales (de arriba a bajo o -al revés). Se pueden usar tantas cajas como se quieran para -conseguir cualquier tipo de efecto. - -Para crear una caja horizontal llamamos a gtk_hbox_new() y para las -verticales gtk_vbox_new(). Las funciones usadas para introducir -objetos dentro son gtk_box_pack_start() y gtk_box_pack_end(). La -primera llenará de arriba a abajo o de izquierda a derecha. La -segunda lo hará al revés. -Usando estas funciones podemos ir metiendo <em/widgets/ con una -justificación a la izquierda o a la derecha y además podemos -mezclarlas de cualquier manera para conseguir el efecto -deseado. Nosotros usaremos gtk_box_pack_start() en la mayoria de -nuestros ejemplos. Un objeto puede ser otro contenedor o un -<em/widget/. De hecho, muchos <em/widgets/ son contenedores, -incluyendo el <em/widget/ botón (button) (aunque normalmente lo -único que meteremos dentro será una etiqueta de texto). - -Mediante el uso de estas funciones le decimos a GTK dónde queremos -situar nuestros widgets, y GTK podrá, por ejemplo, cambiarles el -tamaño de forma automática y hacer otras cosas de -utilidad. También hay unas cuantas opciones que tienen que ver con -la forma en la que los <em/widgets/ serán empaquetados. Como puede -imaginarse, este método nos da una gran flexibilidad a la hora de -colocar y crear <em/widgets/. - -<!-- ----------------------------------------------------------------- --> -<sect1>Detalles de la cajas. -<p> -Debido a esta flexibilidad el empaquetamiento puede ser confuso al -principio. Hay muchas opciones y no es obvio como encajan unas con -otras. Pero en la práctica sólo hay cinco estilos diferentes. - -<? <CENTER> > -<? -<IMG SRC="gtk_tut_packbox1.gif" VSPACE="15" HSPACE="10" WIDTH="528" -HEIGHT="235" ALT="Imagen de ejemplo sobre el empaquetado con cajas"> -> -<? </CENTER> > - -Cada línea contiene una caja horizontal (hbox) con diferentes -botones. La llamada a gtk_box_pack es una manera de conseguir -empaquetar cada uno de los botones dentro de la caja. Eso sí, cada uno -de ellos se empaqueta de la misma forma que el resto (se llama con los -mismos argumentos a gtk_box_pack_start()). - -Esta es la declaración de la función gtk_box_pack_start: - -<tscreen><verb> -void gtk_box_pack_start( GtkBox *box, - GtkWidget *hijo, - gint expand, - gint fill, - gint padding ); -</verb></tscreen> - -El primer argumento es la caja dónde se empaqueta, el segundo el -objeto. Por ahora el objeto será un botón, ya que estamos -empaquetando botones dentro de las cajas. - -El argumento <tt/expand/ de gtk_box_pack_start() y de -gtk_box_pack_end() controla si los <em/widgets/ son expandidos en la -caja para rellenar todo el espacio de la misma (TRUE) o si por el -contrario no se usa el espacio extra dentro de la caja -(FALSE). Poniendo FALSE en <em/expand/ podremos hacer que nuestros -<em/widgets/ tengan una justaficación a la derecha o a la -izquierda. En caso contrario, los <em/widgets/ se expandirán para -llenar toda la caja, y podemos conseguir el mismo efecto utilizando -sólo una de las funciones gtk_box_pack_start o pack_end. - -El argumento <tt/fill/ de gtk_box controla si el espacio extra se mete -dentro de los objetos (TRUE) o como relleno extra (FALSE). Sólo -tiene efecto si el argumento de expansión también es TRUE. - -Al crear una nueva ventana la función debe ser parecida a esta: - -<tscreen><verb> -GtkWidget *gtk_hbox_new (gint homogeneous, - gint spacing); -</verb></tscreen> - -El argumento <tt/homogeneous/ (tanto para gtk_hbox_new como para -gtk_vbox_new) controla si cada objeto en la caja tiene el mismo -tamaño (anchura en una hbox o altura en una vbox). Si se activa, el -argumento <tt/expand/ de las rutinas gtk_box_pack siempre estará -activado. - -Puede que el lector se esté haciendo la siguiente pregunta: -¿Cúal es la diferencia entre espaciar (establecido cuando se -crea la caja) y rellenar (determinado cuando se empaquetan los -elementos)? El espaciado se añade entre objetos, y el rellenado se -hace en cada parte de cada objeto. La siguiente figura debe aclarar la -cuestión. - -<? <CENTER> > -<? -<IMG ALIGN="center" SRC="gtk_tut_packbox2.gif" WIDTH="509" HEIGHT="213" -VSPACE="15" HSPACE="10" ALT="Imagen de ejemplo sobre el empaquetado con cajas"> -> -<? </CENTER> > - -Estudiemos el código usado para crear las imágenes -anteriores. Con los comentarios no debería de haber ningún -problema para entenderlo. - -<!-- ----------------------------------------------------------------- --> -<sect1>Programa demostración de empaquetamiento -<p> -<tscreen><verb> -/* principio del ejemplo packbox packbox.c */ - -#include <stdio.h> -#include "gtk/gtk.h" - -void -delete_event (GtkWidget *widget, GdkEvent *event, gpointer data) -{ - gtk_main_quit (); -} - -/* Hacemos una hbox llena de etiquetas de botón. Los argumentos - * para las variables que estamos interesados son pasados a esta - * función. No mostramos la caja, pero hacemos todo lo que - * queremos. */ -GtkWidget *make_box (gint homogeneous, gint spacing, - gint expand, gint fill, gint padding) -{ - GtkWidget *box; - GtkWidget *boton; - char padstr[80]; - - /* creamos una nueva caja con los argumentos homogeneous y - * spacing */ - box = gtk_hbox_new (homogeneous, spacing); - - /* crear una serie de botones */ - boton = gtk_button_new_with_label ("gtk_box_pack"); - gtk_box_pack_start (GTK_BOX (box), boton, expand, fill, padding); - gtk_widget_show (boton); - - boton = gtk_button_new_with_label ("(box,"); - gtk_box_pack_start (GTK_BOX (box), boton, expand, fill, padding); - gtk_widget_show (boton); - - boton = gtk_button_new_with_label ("boton,"); - gtk_box_pack_start (GTK_BOX (box), boton, expand, fill, padding); - gtk_widget_show (boton); - - /* Este botón llevará por etiqueta el valor de expand */ - if (expand == TRUE) - boton = gtk_button_new_with_label ("TRUE,"); - else - boton = gtk_button_new_with_label ("FALSE,"); - - gtk_box_pack_start (GTK_BOX (box), boton, expand, fill, padding); - gtk_widget_show (boton); - - /* Este es el mismo caso que el de arriba, pero más compacto */ - boton = gtk_button_new_with_label (fill ? "TRUE," : "FALSE,"); - gtk_box_pack_start (GTK_BOX (box), boton, expand, fill, padding); - gtk_widget_show (boton); - - sprintf (padstr, "%d);", padding); - - boton = gtk_button_new_with_label (padstr); - gtk_box_pack_start (GTK_BOX (box), boton, expand, fill, padding); - gtk_widget_show (boton); - - return box; -} - -int -main (int argc, char *argv[]) -{ - GtkWidget *ventana; - GtkWidget *boton; - GtkWidget *caja1; - GtkWidget *caja2; - GtkWidget *separator; - GtkWidget *etiqueta; - GtkWidget *quitbox; - int which; - - /* ¡No olvidar la siguiente llamada! */ - gtk_init (&argc, &argv); - - if (argc != 2) { - fprintf (stderr, "usage: packbox num, where num is 1, 2, or 3.\n"); - /* hacemos limpieza en GTK y devolvemos el valor de 1 */ - gtk_exit (1); - } - - which = atoi (argv[1]); - - /* Creamos la ventana */ - ventana = gtk_window_new (GTK_WINDOW_TOPLEVEL); - - /* Siempre hay que conectar la señal de destrucción con la - * ventana principal. Esto es muy importante para que el - * comportamiento de la ventana sea intuitivo. */ - gtk_signal_connect (GTK_OBJECT (ventana), "delete_event", - GTK_SIGNAL_FUNC (delete_event), NULL); - gtk_container_border_width (GTK_CONTAINER (ventana), 10); - - /* Creamos una caja vertical donde empaquetaremos las cajas - * horizontales. Así podemos apilar las cajas horizontales - * llenas con botones una encima de las otras. */ - caja1 = gtk_vbox_new (FALSE, 0); - - /* Aclaramos cúal es el ejemplo a mostrar. Se corresponde con - * las imágenes anteriores. */ - switch (which) { - case 1: - /* creamos una nueva etiqueta. */ - etiqueta = gtk_label_new ("gtk_hbox_new (FALSE, 0);"); - - /* Alineamos la etiqueta a la izquierda. Está función - * será discutida en detalle en la sección de los - * atributos de los widgets. */ - gtk_misc_set_alignment (GTK_MISC (etiqueta), 0, 0); - - /* Empaquetamos la etiqueta en la caja vertical (vbox - * caja1). Siempre hay que recordar que los widgets añadidos a - * una vbox serán empaquetados uno encimo de otro. */ - gtk_box_pack_start (GTK_BOX (caja1), etiqueta, FALSE, FALSE, 0); - - /* mostramos la etiqueta. */ - gtk_widget_show (etiqueta); - - /* llamada a la función que hace las cajas. Los argumentos - * son homogenous = FALSE, expand = FALSE, fill = FALSE, - * padding = 0 */ - caja2 = make_box (FALSE, 0, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (caja1), caja2, FALSE, FALSE, 0); - gtk_widget_show (caja2); - - /* Llamad a la función para hacer cajas - - * homogeneous = FALSE, spacing = 0, expand = FALSE, - * fill = FALSE, padding = 0 */ - caja2 = make_box (FALSE, 0, TRUE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (caja1), caja2, FALSE, FALSE, 0); - gtk_widget_show (caja2); - - /* Los argumentos son: homogeneous, spacing, expand, fill, - * padding */ - caja2 = make_box (FALSE, 0, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (caja1), caja2, FALSE, FALSE, 0); - gtk_widget_show (caja2); - - - /* creamos un separador. Más tarde aprenderemos más cosas - * sobre ellos, pero son bastante sencillos. */ - separator = gtk_hseparator_new (); - - /* empaquetamos el separador el la vbox. Los widgets serán - * apilados verticalmente. */ - gtk_box_pack_start (GTK_BOX (caja1), separator, FALSE, TRUE, 5); - gtk_widget_show (separator); - - /* creamos una nueva etiqueta y la mostramos */ - etiqueta = gtk_label_new ("gtk_hbox_new (TRUE, 0);"); - gtk_misc_set_alignment (GTK_MISC (etiqueta), 0, 0); - gtk_box_pack_start (GTK_BOX (caja1), etiqueta, FALSE, FALSE, 0); - gtk_widget_show (etiqueta); - - /* Los argumentos son: homogeneous, spacing, expand, fill, - * padding */ - caja2 = make_box (TRUE, 0, TRUE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (caja1), caja2, FALSE, FALSE, 0); - gtk_widget_show (caja2); - - /* Los argumentos son: homogeneous, spacing, expand, fill, - * padding */ - caja2 = make_box (TRUE, 0, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (caja1), caja2, FALSE, FALSE, 0); - gtk_widget_show (caja2); - - /* un nuevo separador */ - separator = gtk_hseparator_new (); - /* Los tres últimos argumentos son: expand, fill, padding. */ - gtk_box_pack_start (GTK_BOX (caja1), separator, FALSE, TRUE, 5); - gtk_widget_show (separator); - - break; - - case 2: - - /* Nueva etiqueta */ - etiqueta = gtk_label_new ("gtk_hbox_new (FALSE, 10);"); - gtk_misc_set_alignment (GTK_MISC (etiqueta), 0, 0); - gtk_box_pack_start (GTK_BOX (caja1), etiqueta, FALSE, FALSE, 0); - gtk_widget_show (etiqueta); - - /* Los argumentos son: homogeneous, spacing, expand, fill, - * padding */ - caja2 = make_box (FALSE, 10, TRUE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (caja1), caja2, FALSE, FALSE, 0); - gtk_widget_show (caja2); - - /* Los argumentos son: homogeneous, spacing, expand, fill, - * padding */ - caja2 = make_box (FALSE, 10, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (caja1), caja2, FALSE, FALSE, 0); - gtk_widget_show (caja2); - - separator = gtk_hseparator_new (); - /* Los argumentos son: expand, fill, padding. */ - gtk_box_pack_start (GTK_BOX (caja1), separator, FALSE, TRUE, 5); - gtk_widget_show (separator); - - etiqueta = gtk_label_new ("gtk_hbox_new (FALSE, 0);"); - gtk_misc_set_alignment (GTK_MISC (etiqueta), 0, 0); - gtk_box_pack_start (GTK_BOX (caja1), etiqueta, FALSE, FALSE, 0); - gtk_widget_show (etiqueta); - - /* Los argumentos son: homogeneous, spacing, expand, fill, - * padding */ - caja2 = make_box (FALSE, 0, TRUE, FALSE, 10); - gtk_box_pack_start (GTK_BOX (caja1), caja2, FALSE, FALSE, 0); - gtk_widget_show (caja2); - - /* Los argumentos son: homogeneous, spacing, expand, fill, - * padding */ - caja2 = make_box (FALSE, 0, TRUE, TRUE, 10); - gtk_box_pack_start (GTK_BOX (caja1), caja2, FALSE, FALSE, 0); - gtk_widget_show (caja2); - - separator = gtk_hseparator_new (); - /* Los argumentos son: expand, fill, padding. */ - gtk_box_pack_start (GTK_BOX (caja1), separator, FALSE, TRUE, 5); - gtk_widget_show (separator); - break; - - case 3: - - /* Con esto demostramos como hay que usar gtk_box_pack_end () - * para conseguir que los - widgets esten alineados a la izquierda. */ - caja2 = make_box (FALSE, 0, FALSE, FALSE, 0); - - /* la última etiqueta*/ - etiqueta = gtk_label_new ("end"); - - /* la empaquetamos usando gtk_box_pack_end(), por lo que se - * sitúa en el lado derecho de la hbox.*/ - gtk_box_pack_end (GTK_BOX (caja2), etiqueta, FALSE, FALSE, 0); - - /* mostrar la etiqueta */ - gtk_widget_show (etiqueta); - - - /* empaquetamos caja2 en caja1 */ - gtk_box_pack_start (GTK_BOX (caja1), caja2, FALSE, FALSE, 0); - gtk_widget_show (caja2); - - - /* el separador para la parte de abajo. */ - separator = gtk_hseparator_new (); - - /* Así se determina el tamaño del separador a 400 pixels - * de largo por 5 de alto. La hbox también tendrá 400 - * pixels de largo y la etiqueta "end" estará separada de - * las demás etiquetas en la hbox. Si no establecemos estos - * parámetros todos los widgets en la hbox serán - * empaquetados tan juntos como se pueda.*/ - gtk_widget_set_usize (separator, 400, 5); - - /* Empaquetamos el separador creado al principio de main() en - * la vbox (caja1). */ - gtk_box_pack_start (GTK_BOX (caja1), separator, FALSE, TRUE, 5); - gtk_widget_show (separator); - } - - /* Creamos otra hbox... recordar que podemos crear tantas como - * queramos. */ - quitbox = gtk_hbox_new (FALSE, 0); - - /* El botón de salida. */ - boton = gtk_button_new_with_label ("Quit"); - - /* Establecemos la señal de destrucción de la ventana. - * Recuerde que emitirá la señal de "destroy" que a su vez - * será procesada por el controlador de señales, tal y como - * ya hemos visto. */ - - gtk_signal_connect_object (GTK_OBJECT (boton), "clicked", - GTK_SIGNAL_FUNC (gtk_main_quit), - GTK_OBJECT (ventana)); - /* Empaquetamos el botón en la caja de salida (quitbox). - * los tres últimos argumentos de gtk_box_pack_start - * son:expand, fill, padding. */ - gtk_box_pack_start (GTK_BOX (caja1), quitbox, FALSE, FALSE, 0); - - /* empaquetamos la vbox (caja1) que ya contiene todos los widgets - * en la ventana principal. */ - gtk_container_add (GTK_CONTAINER (ventana), caja1); - - /* mostramos todo aquello que faltaba por mostrar */ - gtk_widget_show (boton); - gtk_widget_show (quitbox); - - gtk_widget_show (caja1); - - /* Si mostramos la ventana lo último todo aparece de golpe. */ - gtk_widget_show (ventana); - - /* por supuesto tenemos una función main. */ - gtk_main (); - - /* El programa llega aquí cuando se llama a gtk_main_quit(), - * pero no cuando se llama a gtk_exit(). */ - return 0; -} -/* final del ejemplo*/ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Empaquetamiento usando tablas -<p> -Existe otra forma de empaquetar: usando tablas. Estas pueden llegar a -ser extremadamente útiles. - -Usando tablas creamos una cuadrícula donde podemos poner los -widgets. Estos pueden ocupar tanto espacio como queramos. - -La primera función que conviene estudiar es gtk_table_new: - -<tscreen><verb> -GtkWidget *gtk_table_new( gint rows, - gint columns, - gint homogeneous ); -</verb></tscreen> - -Como es lógico el primer argumento es el número de filas y el -segundo el de columnas. - -El tercero establece el tamaño de las celdas de la tabla. Si es TRUE -se fuerza a que el tamaño de las celdas sea igual al de la celda -mayor. Con FALSE se establece el ancho de toda una columna igual al de -la celda más ancha de esa columna, y la altura de una fila será -la de la celda más alta de esa fila. - -El número de filas y columnas varía entre 0 y n, donde n es el -número especificado en la llamada a gtk_table_new. Así si se -especifica columnas = 2 y filas = 2 la apariencia será parecida a: - -<tscreen><verb> - 0 1 2 -0+----------+----------+ - | | | -1+----------+----------+ - | | | -2+----------+----------+ -</verb></tscreen> - -Conviene destacar que el origen de coordenadas se sitúa en la esquina superior izquierda. Para -situar un widget en una ventana se usa la siguiente función: - -<tscreen><verb> -void gtk_table_attach( GtkTable *table, - GtkWidget *hijo, - gint left_attach, - gint right_attach, - gint top_attach, - gint bottom_attach, - gint xoptions, - gint yoptions, - gint xpadding, - gint ypadding ); -</verb></tscreen> - -El primer argumento (<tt/table/) es el nombre de la tabla y el segundo -(<tt/hijo/) el <em/widget/ que quiere poner en la tabla. - -Los argumentos <tt/left_attach/, <tt/right_attach/ especifican donde -se pone el widget y cuantas cajas se usan. Por ejemplo, supongamos que -queremos poner un botón que sólo ocupe la esquina inferior -izquierda en nuestra tabla 2x2. Los valores serán left_attach = 1, -right_attach = 2, top_attach = 2, top_attach = 1, bottom_attach = 2. - -Supongamos que queremos ocupar toda la fila de nuestra tabla 2x2, -usaríamos left_attach = 0, right_attach = 2, top_attach = 0, -bottom_attach = 1. - -Las opciones <tt/xoptions/ e <tt/yoptions/ son usadas para especificar -como queremos el empaquetamiento y podemos utilizar multiples -opciones simultaneamente con OR. - -Las opciones son: - -<itemize> -<item>GTK_FILL - Si el relleno es más grande que el widget, y se -especifica GTK_FILL, el <em/widget/ se expandirá ocupando todo el -espacio disponible. - -<item>GTK_SHRINK - En el caso de que hayamos dejado espacio sin usar -cuando el usuario reajuste el tamaño de la ventana los <em/widgets/ -normalmente serán empujados al fondo de la ventana y -desaparecerán. Si especifica GTK_SHRINK los widgets se reducirán -con la tabla. - -<item>GTK_EXPAND - Mediante esta opción la tabla se expande usando -todo el espacio libre de la ventana. -</itemize> - -El relleno es igual que con las cajas. Simplemente se crea una zona -vacía alrededor del widget (el tamaño se especifica en pixels). - -gtk_table_attach() tiene MUCHAS opciones. Asi que hay un atajo: - -<tscreen><verb> -void gtk_table_attach_defaults( GtkTable *table, - GtkWidget *widget, - gint left_attach, - gint right_attach, - gint top_attach, - gint bottom_attach ); -</verb></tscreen> - -Las opciones X e Y se ponen por defecto a GTK_FILL | GTK_EXPAND, y el -relleno X e Y se pone a 0. El resto de los argumentos son identicos a -la función anterior. - -Existen otras funciones como gtk_table_set_row_spacing() y -gtk_table_set_col_spacing(), que sirven para especificar el espaciado -entre las columnas/filas en la columna/fila que queramos. - -<tscreen><verb> -void gtk_table_set_row_spacing( GtkTable *table, - gint row, - gint spacing ); -</verb></tscreen> - -y - -<tscreen><verb> -void gtk_table_set_col_spacing ( GtkTable *table, - gint column, - gint spacing ); -</verb></tscreen> - -Conviene destacar que el espaciado se sitúa a la derecha de la -columna y debajo de la fila. - -Tambien se puede forzar que el espaciado sea el mismo para las filas -y/o las columnas: - -<tscreen><verb> -void gtk_table_set_row_spacings( GtkTable *table, - gint spacing ); -</verb></tscreen> - -y - -<tscreen><verb> -void gtk_table_set_col_spacings( GtkTable *table, - gint spacing ); -</verb></tscreen> - -Usando estas funciones las últimas fila y columna no estarán -espaciadas. - -<!-- ----------------------------------------------------------------- --> -<sect1>Ejemplo de empaquetamiento mediante tablas. -<p> -Haremos una ventana con tres botones en una tabla 2x2. Los dos -primeros botones ocuparán la fila de arriba, mientras que el -tercero (de salida) ocupará toda la fila de abajo. El resultado es -el siguiente: - -<? <CENTER> > -<? -<IMG SRC="gtk_tut_table.gif" VSPACE="15" HSPACE="10" -ALT="Imagen de ejemplo sobre el empaquetado mediante tablas" WIDTH="180" HEIGHT="120"> -> -<? </CENTER> > - -Este es el código: -<tscreen><verb> -/* principio del ejemplo table table.c */ - -#include <gtk/gtk.h> - -/* La respuesta, que además se imprime en stdout. */ -void callback (GtkWidget *widget, gpointer data) -{ - g_print ("Hello again - %s was pressed\n", (char *) data); -} - -/* Con esta otra respuesta terminamos el programa. */ -void delete_event (GtkWidget *widget, GdkEvent *event, gpointer data) -{ - gtk_main_quit (); -} - -int main (int argc, char *argv[]) -{ - GtkWidget *ventana; - GtkWidget *boton; - GtkWidget *table; - - gtk_init (&argc, &argv); - - ventana = gtk_window_new (GTK_WINDOW_TOPLEVEL); - - gtk_window_set_title (GTK_WINDOW (ventana), "Table"); - - gtk_signal_connect (GTK_OBJECT (ventana), "delete_event", - GTK_SIGNAL_FUNC (delete_event), NULL); - - gtk_container_border_width (GTK_CONTAINER (ventana), 20); - - table = gtk_table_new (2, 2, TRUE); - - gtk_container_add (GTK_CONTAINER (ventana), table); - - boton = gtk_button_new_with_label ("botón 1"); - - gtk_signal_connect (GTK_OBJECT (boton), "clicked", - GTK_SIGNAL_FUNC (callback), (gpointer) "botón 1"); - - gtk_table_attach_defaults (GTK_TABLE(table), boton, 0, 1, 0, 1); - - gtk_widget_show (boton); - - boton = gtk_button_new_with_label ("botón 2"); - - gtk_signal_connect (GTK_OBJECT (boton), "clicked", - GTK_SIGNAL_FUNC (callback), (gpointer) "botón 2"); - gtk_table_attach_defaults (GTK_TABLE(table), boton, 1, 2, 0, 1); - - gtk_widget_show (boton); - - boton = gtk_button_new_with_label ("Quit"); - - gtk_signal_connect (GTK_OBJECT (boton), "clicked", - GTK_SIGNAL_FUNC (delete_event), NULL); - gtk_table_attach_defaults (GTK_TABLE(table), boton, 0, 2, 1, 2); - - gtk_widget_show (boton); - - gtk_widget_show (table); - gtk_widget_show (ventana); - - gtk_main (); - - return 0; -} -/* final del ejemplo */ -</verb></tscreen> - -<!-- ***************************************************************** --> -<sect>Estudio general de los <em/widgets/ -<!-- ***************************************************************** --> -<p> -Los pasos generales a la hora de crear un <em/widget/ son: - -<enum> - -<item> Usar gtk_*_new - Una de las diferentes formas de crear un -<em/widget/. (Todas serán explicadas en esta sección). - -<item> Connectar todas las señales y los eventos a los -controladores apropiados. - -<item> Establecer los atributos del <em/widget/. - -<item> Empaquetar el <em/widget/ en un contenedor usando las llamadas -apropiadas, como gtk_container_add() o gtk_box_pack_start(). - -<item> Mostrar el <em/widget/ usando gtk_widget_show(). - -</enum> - -Mediante esta última llamada GTK `sabe' que hemos acabado de -establecer los atributos del <em/widget/, y que por lo tanto puede -mostrarse. Se puede usar gtk_widget_hide para hacer que desaparezca. -El orden en el que se muestran los <em/widgets/ no es importante, pero -se recomienda mostrar al final la ventana para que todo aparezca de -golpe. El hijo de un <em/widget/ no se muestra hasta que lo hace la -propia ventana (que en este caso es un <em/widget/ padre) mediante -gtk_widget_show(). - - -<!-- ----------------------------------------------------------------- --> -<sect1> Conversión de tipos -<p> -GTK usa un sistema de conversión de tipos mediante macros que -comprueban si se puede realizar la conversión y en caso -afirmativo la hacen. Las más comunes son: - -<itemize> -<item> GTK_WIDGET(widget) -<item> GTK_OBJECT(object) -<item> GTK_SIGNAL_FUNC(function) -<item> GTK_CONTAINER(container) -<item> GTK_WINDOW(ventana) -<item> GTK_BOX(box) -</itemize> - -Todas son usadas para cambiar de tipo los argumentos de una función. -Aparecerán mucho en los ejemplos, para usarlas sólo hay que mirar la -declaración de la función. - -Tal y como se puede ver en el árbol de clases (situado un poco -más adelante) todos los <em/widgets/ derivan de la clase base -GtkObject. Esto significa que siempre se puede usar un <em/widget/ -como argumento de una función (que acepte un objeto, claro) -realizando la conversión de tipo GTK_OBJECT(). - -Por ejemplo: - -<tscreen><verb> -gtk_signal_connect( GTK_OBJECT(boton), "clicked", - GTK_SIGNAL_FUNC(callback_function), callback_data); -</verb></tscreen> - -Hemos hecho que el botón pase a ser un objeto y que se cambie el -puntero a la función a una función respuesta. - -Muchos <em/widgets/ son contenedores, por lo que unos pueden derivar -de otros (la mayoría lo hace de GtkContainer). Cualquiera puede ser -usado junto con la macro GTK_CONTAINER como argumento a funciones en -forma de puntero. - -Desgraciadamente estas macros no son descritas en detalle en el -tutorial, por lo que se recomienda echar un vistazo a los archivos de -cabecera de GTK. En la práctica es posible aprender a manejar un -<em/widget/ leyendo las declaraciones de las funciones. - -<!-- ----------------------------------------------------------------- --> -<sect1>Árbol formado por los <em/widgets/ -<p> -A continuación se detallan todas las ramas del árbol que forman -los <em/widgets/. - -<tscreen><verb> - GtkObject - +GtkWidget - | +GtkMisc - | | +GtkLabel - | | | +GtkAccelLabel - | | | `GtkTipsQuery - | | +GtkArrow - | | +GtkImage - | | `GtkPixmap - | +GtkContainer - | | +GtkBin - | | | +GtkAlignment - | | | +GtkFrame - | | | | `GtkAspectFrame - | | | +GtkButton - | | | | +GtkToggleButton - | | | | | `GtkCheckButton - | | | | | `GtkRadioButton - | | | | `GtkOptionMenu - | | | +GtkItem - | | | | +GtkMenuItem - | | | | | +GtkCheckMenuItem - | | | | | | `GtkRadioMenuItem - | | | | | `GtkTearoffMenuItem - | | | | +GtkListItem - | | | | `GtkTreeItem - | | | +GtkWindow - | | | | +GtkColorSelectionDialog - | | | | +GtkDialog - | | | | | `GtkInputDialog - | | | | +GtkDrawWindow - | | | | +GtkFileSelection - | | | | +GtkFontSelectionDialog - | | | | `GtkPlug - | | | +GtkEventBox - | | | +GtkHandleBox - | | | +GtkScrolledWindow - | | | `GtkViewport - | | +GtkBox - | | | +GtkButtonBox - | | | | +GtkHButtonBox - | | | | `GtkVButtonBox - | | | +GtkVBox - | | | | +GtkColorSelection - | | | | `GtkGammaCurve - | | | `GtkHBox - | | | +GtkCombo - | | | `GtkStatusbar - | | +GtkCList - | | | `GtkCTree - | | +GtkFixed - | | +GtkNotebook - | | | `GtkFontSelection - | | +GtkPaned - | | | +GtkHPaned - | | | `GtkVPaned - | | +GtkLayout - | | +GtkList - | | +GtkMenuShell - | | | +GtkMenuBar - | | | `GtkMenu - | | +GtkPacker - | | +GtkSocket - | | +GtkTable - | | +GtkToolbar - | | `GtkTree - | +GtkCalendar - | +GtkDrawingArea - | | `GtkCurve - | +GtkEditable - | | +GtkEntry - | | | `GtkSpinButton - | | `GtkText - | +GtkRuler - | | +GtkHRuler - | | `GtkVRuler - | +GtkRange - | | +GtkScale - | | | +GtkHScale - | | | `GtkVScale - | | `GtkScrollbar - | | +GtkHScrollbar - | | `GtkVScrollbar - | +GtkSeparator - | | +GtkHSeparator - | | `GtkVSeparator - | +GtkPreview - | `GtkProgress - | `GtkProgressBar - +GtkData - | +GtkAdjustment - | `GtkTooltips - `GtkItemFactory -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1><em/Widgets/ sin ventanas -<p> -Los siguientes <em/widgets/ no tienen ventanas asociadas. Si se -quieren capturar eventos se tendrá que utilizar GtkEventBox. En la -sección <ref id="sec_The_EventBox_Widget" name="El widget -EventBox"> se pueden encontrar más detalles sobre su uso. - -<tscreen><verb> -GtkAlignment -GtkArrow -GtkBin -GtkBox -GtkImage -GtkItem -GtkLabel -GtkPixmap -GtkScrolledWindow -GtkSeparator -GtkTable -GtkAspectFrame -GtkFrame -GtkVBox -GtkHBox -GtkVSeparator -GtkHSeparator -</verb></tscreen> - -Vamos a continuar la explicación describiendo cada uno de los -<em/widgets/ mediante ejemplos. También se puede consultar el -programa testgtk.c (Se encuentra en gtk/testgtk.c). - -<!-- ***************************************************************** --> -<sect>El <em/widget/ Botón -<!-- ***************************************************************** --> - -<!-- ----------------------------------------------------------------- --> -<sect1>Botones normales <label id="sec_Radio_Buttons"> -<p> -Ya hemos visto prácticamente todo lo que hay que saber a cerca de -este <em/widget/. Existen dos formas diferentes de crear un -botón. Se puede usar gtk_button_new_with_label() para conseguir un -botón con etiqueta o simplemente gtk_button_new(). Si se quiere se -puede añadir una etiqueta a este último empaquetándola, -primero se crea una nueva caja y luego se empaquetan los objetos que -se quieran mediante gtk_box_pack_start. Una vez finalizado esto se -relaciona la caja con el botón mediante gtk_container_add. - -Estudiemos un ejemplo de gtk_button_new para crear un botón con una -imagen y una etiqueta. El código está dividido en dos para que -pueda ser reusado. - -<tscreen><verb> -/* principio del ejemplo buttons buttons.c */ - -#include <gtk/gtk.h> - -/* Creamos la caja con una imagen y una etiqueta empaquetadas. Se - * devuelve la caja. */ -GtkWidget *xpm_label_box (GtkWidget *parent, gchar *xpm_filename, gchar *label_text) -{ - GtkWidget *caja1; - GtkWidget *etiqueta; - GtkWidget *pixmapwid; - GdkPixmap *pixmap; - GdkBitmap *mask; - GtkStyle *style; - - /* create box for xpm and etiqueta */ - caja1 = gtk_hbox_new (FALSE, 0); - gtk_container_border_width (GTK_CONTAINER (caja1), 2); - - /* obtenemos el estilo del botón (probablemente para el color - * de fondo, pero no estoy seguro) */ - style = gtk_widget_get_style(parent); - - /* cargamos el pixmap. Hay una sección que describe el proceso - * en detalle */ - pixmap = gdk_pixmap_create_from_xpm (parent->window, &mask, - &style->bg[GTK_STATE_NORMAL], - xpm_filename); - pixmapwid = gtk_pixmap_new (pixmap, mask); - - etiqueta = gtk_label_new (label_text); - - gtk_box_pack_start (GTK_BOX (caja1), - pixmapwid, FALSE, FALSE, 3); - - gtk_box_pack_start (GTK_BOX (caja1), etiqueta, FALSE, FALSE, 3); - - gtk_widget_show(pixmapwid); - gtk_widget_show(etiqueta); - - return (caja1); -} - -/* respuesta */ -void callback (GtkWidget *widget, gpointer data) -{ - g_print ("Hola de nuevo. Se ha pulsado %s\n", (char *) data); -} - - -int main (int argc, char *argv[]) -{ - - GtkWidget *ventana; - GtkWidget *boton; - GtkWidget *caja1; - - gtk_init (&argc, &argv); - - ventana = gtk_window_new (GTK_WINDOW_TOPLEVEL); - - gtk_window_set_title (GTK_WINDOW (ventana), "Botones con dibujos"); - - /* It's a good idea to do this for all windows. */ - gtk_signal_connect (GTK_OBJECT (ventana), "destroy", - GTK_SIGNAL_FUNC (gtk_exit), NULL); - - gtk_signal_connect (GTK_OBJECT (ventana), "delete_event", - GTK_SIGNAL_FUNC (gtk_exit), NULL); - - gtk_container_border_width (GTK_CONTAINER (ventana), 10); - gtk_widget_realize(ventana); - - boton = gtk_button_new (); - - gtk_signal_connect (GTK_OBJECT (boton), "clicked", - GTK_SIGNAL_FUNC (callback), - (gpointer) "botón divertido"); - - caja1 = xpm_label_box(ventana, "info.xpm", "botón divertido"); - - gtk_widget_show(caja1); - - gtk_container_add (GTK_CONTAINER (boton), caja1); - - gtk_widget_show(boton); - - gtk_container_add (GTK_CONTAINER (ventana), boton); - - gtk_widget_show (ventana); - - gtk_main (); - - return 0; -} -/* final del ejemplo */ -</verb></tscreen> - -La función xpm_label_box puede ser usada para empaquetar xpm y -etiquetas en cualquier widget que pueda ser un contenedor. - -El botón puede responder a las siguientes señales: - -<itemize> -<item> pressed -<item> released -<item> clicked -<item> enter -<item> leave -</itemize> - -<!-- ----------------------------------------------------------------- --> -<sect1> Botones de selección -<p> -Estos botones son muy similares a los normales. La única diferencia -es que sólo pueden estar en dos posiciones diferentes alternadas -mediante pulsaciones del ratón. - -Los botones de selección son la base de otros tipos: los de -comprobación y los circulares. Por lo tanto muchas de sus llamadas -seran heredadas por estos. - -Creamos un nuevo botón de selección: - -<tscreen><verb> -GtkWidget *gtk_toggle_button_new( void ); - -GtkWidget *gtk_toggle_button_new_with_label( gchar *etiqueta ); -</verb></tscreen> - -Como se ha podido imaginar estas funciones son iguales a las de un -botón normal. La primera crea un botón, mientras que la segunda -crea un botón con una etiqueta. - -Para saber cual es el estado de un botón de selección, -comprobación o circular se usa una de las macros del ejemplo -siguiente. En éstas se comprueba el estado del botón mediante -una respuesta. La señal que queremos recibir es -«toggled». Generalmente para comprobar el estado de una señal se -establece un controlador de señales y luego se usa la siguiente -macro. La función de respuesta debe ser de la forma: - -<tscreen><verb> -void toggle_button_callback (GtkWidget *widget, gpointer data) -{ - if (GTK_TOGGLE_BUTTON (widget)->active) - { - /* Si el control llega aquí el botón está pulsado */ - - } else { - - /* El botón no está pulsado (sobresale) */ - } -} -</verb></tscreen> - -<tscreen><verb> -void gtk_toggle_button_set_state( GtkToggleButton *toggle_button, - gint state ); -</verb></tscreen> - -La llamada de arriba puede ser usada para establecer el estado de un -botón de selección (o de cualquiera de sus hijos: el circular o -el de comprobación). El primer argumento es el botón, el segundo -TRUE cuando queremos que el botón no esté pulsado o FALSE para -cuando lo esté. Por defecto se establece FALSE. - -Hay que destacar que cuando se usa gtk_toggle_button_set_state() y se -cambia el estado del botón este emite la señal «clicked». - -<tscreen><verb> -void gtk_toggle_button_toggled (GtkToggleButton *toggle_button); -</verb></tscreen> - -Cambia el estado del botón emitiendo la señal «toggled». -<!-- ----------------------------------------------------------------- --> -<sect1> Botones de comprobación -<p> -Los botones de comprobación son un poco diferentes a los anteriores, aunque -sus propiedades y funciones son bastante similares. En lugar de ser botones -con texto en su interior son pequeños cuadrados con texto a su derecha. -Normalmente son usados para (des)seleccionar opciones. - -Las dos funciones que los crean son muy similares a las de los botones -normales. - -<tscreen><verb> -GtkWidget *gtk_check_button_new( void ); - -GtkWidget *gtk_check_button_new_with_label ( gchar *etiqueta ); -</verb></tscreen> - -La función new_with_label crea un botón de comprobación con -una etiqueta dentro. - -El proceso para comprobar el estado de un botón de este tipo es -igual al de los de comprobación. - -<!-- ----------------------------------------------------------------- --> -<sect1> Botones circulares -<p> -Estos botones son similares a los de selección con la salvedad de -que están agrupados, de modo que sólo uno puede estar -seleccionado. Por tanto son usados para permitir al usuario -seleccionar algo de una lista de opciones mutuamente excluyentes. - -Las llamadas para crear un botón circular son: -<tscreen><verb> -GtkWidget *gtk_radio_button_new( GSList *group ); - -GtkWidget *gtk_radio_button_new_with_label( GSList *group, - gchar *etiqueta ); -</verb></tscreen> - -El nuevo argumento sirve para especificar el grupo al que -pertenecen. La primera llamada debe pasar NULL como primer -argumento. A continuación de ésta se puede crear el grupo -usando: - -<tscreen><verb> -GSList *gtk_radio_button_group( GtkRadioButton *radio_button ); -</verb></tscreen> - -Para añadir un nuevo botón a un grupo hay que usar -gtk_radio_button_group con el anterior botón como argumento. El -resultado se le pasa a gtk_radio_button_new o a -gtk_radio_button_new_with_label. Así se consigue enlazar una cadena -de botones. (El ejemplo siguiente sirve para aclarar el proceso) - -También se puede establecer cúal es el botón pulsado por -defecto: - -<tscreen><verb> -void gtk_toggle_button_set_state( GtkToggleButton *toggle_button, - gint state ); -</verb></tscreen> -El siguiente ejemplo crea un grupo de tres botones: - -<tscreen><verb> -/* Principio del ejemplo radiobuttons.c */ - -#include <gtk/gtk.h> -#include <glib.h> - -void close_application( GtkWidget *widget, GdkEvent *event, gpointer data ) { - gtk_main_quit(); -} - -main(int argc,char *argv[]) -{ - static GtkWidget *ventana = NULL; - GtkWidget *caja1; - GtkWidget *caja2; - GtkWidget *boton; - GtkWidget *separator; - GSList *group; - - gtk_init(&argc,&argv); - ventana = gtk_window_new (GTK_WINDOW_TOPLEVEL); - - gtk_signal_connect (GTK_OBJECT (ventana), "delete_event", - GTK_SIGNAL_FUNC(close_application), - NULL); - - gtk_window_set_title (GTK_WINDOW (ventana), "radio buttons"); - gtk_container_border_width (GTK_CONTAINER (ventana), 0); - - caja1 = gtk_vbox_new (FALSE, 0); - gtk_container_add (GTK_CONTAINER (ventana), caja1); - gtk_widget_show (caja1); - - caja2 = gtk_vbox_new (FALSE, 10); - gtk_container_border_width (GTK_CONTAINER (caja2), 10); - gtk_box_pack_start (GTK_BOX (caja1), caja2, TRUE, TRUE, 0); - gtk_widget_show (caja2); - - boton = gtk_radio_button_new_with_label (NULL, "botón1"); - gtk_box_pack_start (GTK_BOX (caja2), boton, TRUE, TRUE, 0); - gtk_widget_show (boton); - - group = gtk_radio_button_group (GTK_RADIO_BUTTON (boton)); - boton = gtk_radio_button_new_with_label(group, "botón2"); - gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (boton), TRUE); - gtk_box_pack_start (GTK_BOX (caja2), boton, TRUE, TRUE, 0); - gtk_widget_show (boton); - - group = gtk_radio_button_group (GTK_RADIO_BUTTON (boton)); - boton = gtk_radio_button_new_with_label(group, "botón3"); - gtk_box_pack_start (GTK_BOX (caja2), boton, TRUE, TRUE, 0); - gtk_widget_show (boton); - - separator = gtk_hseparator_new (); - gtk_box_pack_start (GTK_BOX (caja1), separator, FALSE, TRUE, 0); - gtk_widget_show (separator); - - caja2 = gtk_vbox_new (FALSE, 10); - gtk_container_border_width (GTK_CONTAINER (caja2), 10); - gtk_box_pack_start (GTK_BOX (caja1), caja2, FALSE, TRUE, 0); - gtk_widget_show (caja2); - - boton = gtk_button_new_with_label ("close"); - gtk_signal_connect_object (GTK_OBJECT (boton), "clicked", - GTK_SIGNAL_FUNC(close_application), - GTK_OBJECT (ventana)); - gtk_box_pack_start (GTK_BOX (caja2), boton, TRUE, TRUE, 0); - GTK_WIDGET_SET_FLAGS (boton, GTK_CAN_DEFAULT); - gtk_widget_grab_default (boton); - gtk_widget_show (boton); - gtk_widget_show (ventana); - - gtk_main(); - return(0); -} -/* final del ejemplo */ -</verb></tscreen> - -<!-- TODO: checout out gtk_radio_button_new_from_widget function - TRG --> - -<!-- ***************************************************************** --> -<sect>Ajustes (<em/Adjustment/) <label id="sec_Adjustment"> -<!-- ***************************************************************** --> -<p> -Existen diferentes <em/widgets/ en GTK+ que pueden ser ajustados -visualmente por el usuario mediante el ratón o el teclado. Un -ejemplo son los <em/widgets/ de selección descritos en la -sección <ref id="sec_Range_Widgets" name="Widgets de selección -de rango">. También hay otros widgets que pueden ser ajustados -parcialmente, por ejemplo el <em/widget/ de texto o el <em/viewport/. - -Como es lógico el programa tiene que poder reaccionar a los -cambios que el usuario realiza en los <em/widgets/ de selección de -rango. Una forma de hacer que el programa reaccione sería tener -cada <em/widget/ emitiendo su propio tipo de señal cuando cambie el -ajuste, y bien pasar el nuevo valor al manejador de señal o bien -obligarle a que mire dentro de la estructura de datos del <em/widget/ -para conocer este valor. Pero también puede ser que quiera conectar -los ajustes de varios <em/widgets/, para que así cuando se ajuste -uno, los demás se ajusten automáticamente. El ejemplo más -obvio es conectar una barra de desplazamiento a una región con -texto. Si cada <em/widget/ posee su propia forma de establecer u -obtener sus valores de ajuste el programador puede que tenga que -escribir sus propios controladores de señales para traducir el -resultado de la señal producida por un <em/widget/ como el -argumento de una función usada para determinar valores en otro -<em/widget/. - -Para resolver este problema GTK+ usa objetos del tipo GtkAdjustment. -Con ellos se consigue almacenar y traspasar información de una forma -abstracta y flexible. El uso más obvio es el de almacenes de -párametros para <em/widgets/ de escala (barras deslizantes y -escalas). Como los GtkAdjustment derivan de GtkObject poseen -cualidades intrínsecas que les permiten ser algo más que simples -estructuras de datos. Lo más importante es que pueden emitir -señales que a su vez pueden ser usadas tanto para reaccionar frente -al cambio de datos introducidos por el usuario como para transferir -los nuevos valores de forma transparente entre <em/widgets/ ajustables. - -<sect1>Creando un ajuste -<p> -Los ajustes se pueden crear usando: - -<tscreen><verb> -GtkObject *gtk_adjustment_new( gfloat value, - gfloat lower, - gfloat upper, - gfloat step_increment, - gfloat page_increment, - gfloat page_size ); -</verb></tscreen> - -El argumento <tt/value/ es el valor inicial que le queremos dar -al ajuste. Normalmente se corresponde con las posiciones situadas -más arriba y a la izquierda de un <em/widget/ ajustable. El argumento -<tt/lower/ especifica los valores más pequeños que el ajuste -puede contener. A su vez con <tt/step_increment/ se especifica el -valor más pequeño en el que se puede variar la magnitud en -cuestión (valor de paso asociado), mientras que <tt/page_increment/ -es el mayor. Con <tt/page_size/ se determina el valor visible de un -<em/widget/. - -<!-- ----------------------------------------------------------------- --> -<sect1> Forma sencilla de usar los ajustes -<p> -Los <em/widgets/ ajustábles se pueden dividir en dos categorias -diferentes, aquellos que necesitan saber las unidades de la cantidad -almacenada y los que no. Este último grupo incluye los <em/widgets/ -de tamaño (barras deslizantes, escalas, barras de estado, o botones -giratorios). Normalmente estos <em/widgets/ son ajustados -«directamente» por el usuario. Los argumentos <tt/lower/ y -<tt/upper/ serán los limites dentro de los cuales el usuario puede -manipular los ajustes. Por defecto sólo se modificará el -<tt/value/ (valor) de un ajuste. - -El otro grupo incluye los <em/widgets/ de texto, la lista compuesta o -la ventana con barra deslizante. Estos <em/widgets/ usan valores en -pixels para sus ajustes, y normalmente son ajustados -«indirectamente» mediante barras deslizantes. Aunque todos los -<em/widgets/ pueden crear sus propios ajustes o usar otros creados por -el programador con el segundo grupo suele ser conveniente dejarles que -creen sus propios ajustes. Normalmente no tendrán en cuenta ninguno -de los valores de un ajuste proporcionado por el programador, excepto -<tt/value/, pero los resultados son, en general, indefinidos -(entiendase que tendrá que leer el código fuente para saber que -pasa con cada widget). - -Probablemente ya se habrá dado cuenta de que como los <em/widgets/ -de texto (y todos los <em/widgets/ del segundo grupo), insisten en -establecer todos los valores excepto <tt/value/, mientras que las -barras deslizantes sólo modifican <tt/value/, si se comparte un -objeto de ajuste entre una barra deslizante y un <em/widget/ de texto -al manipular la barra se modificará el <em/widget/ de texto. Ahora -queda completamente demostrada la utilidad de los ajustes. Veamos un -ejemplo: - -<tscreen><verb> - /* creamos un ajuste */ - text = gtk_text_new (NULL, NULL); - /* lo usamos con la barra deslizante */ - vscrollbar = gtk_vscrollbar_new (GTK_TEXT(text)->vadj); -</verb></tscreen> - -</sect1> -<!-- ----------------------------------------------------------------- --> -<sect1> Descripción detallada de los ajustes -<p> -Puede que se esté preguntando cómo es posible crear sus propios -controladores para responder a las modificaciones producidas por -el usuario y cómo obtener el valor del ajuste hecho por este. -Para aclarar esto y otras cosas vamos a estudiar la estructura -del ajuste - -<tscreen><verb> -struct _GtkAdjustment -{ - GtkData data; - - gfloat lower; - gfloat upper; - gfloat value; - gfloat step_increment; - gfloat page_increment; - gfloat page_size; -}; -</verb></tscreen> - -Lo primero que hay que aclarar es que no hay ninguna macro o función -de acceso que permita obtener el <tt/value/ de un GtkAdjustment, por -lo que tendrá que hacerlo usted mismo. Tampoco se preocupe mucho -porque la macro <tt>GTK_ADJUSTMENT (Object)</tt> comprueba los tipos -durante el proceso de ejecución (como hacen todas las macros de GTK+ -que sirven para comprobar los tipos). - -Cuando se establece el <tt/value/ de un ajuste normalmente se quiere -que cualquier <em/widget/ se entere del cambio producido. Para ello -GTK+ posee una función especial: - -<tscreen><verb> -void gtk_adjustment_set_value( GtkAdjustment *adjustment, - gfloat value ); -</verb></tscreen> - -Tal y como se mencionó antes GtkAdjustment es una subclase de GtkObject -y por tanto puede emitir señales. Así se consigue que se actualicen -los valores de los ajustes cuando se comparten entre varios <em/widgets/. -Por tanto todos los <em/widgets/ ajustables deben conectar controladores -de señales a sus señales del tipo <tt/value_changed/. Esta es la -definición de la señal como viene en <tt/struct _GtkAdjustmentClass/ - -<tscreen><verb> - void (* value_changed) (GtkAdjustment *adjustment); -</verb></tscreen> - -Todos los <em/widgets/ que usan GtkAdjustment deben emitir esta -señal cuando cambie el valor de algún ajuste. Esto sucede cuando -el usuario cambia algo o el programa modifica los ajustes -mediante. Por ejemplo si queremos que rote una figura cuando -modificamos un <em/widget/ de escala habría que usar una respuesta -como esta: - -<tscreen><verb> -void cb_rotate_picture (GtkAdjustment *adj, GtkWidget *picture) -{ - set_picture_rotation (picture, adj->value); -... -</verb></tscreen> - -y conectarla con el ajuste del <em/widget/ de escala mediante: - -<tscreen><verb> -gtk_signal_connect (GTK_OBJECT (adj), "value_changed", - GTK_SIGNAL_FUNC (cb_rotate_picture), picture); -</verb></tscreen> -¿Qué pasa cuando un <em/widget/ reconfigura los valores -<tt/upper/ o <tt/lower/ (por ejemplo cuando se añade más texto)? -Simplemente que se emite la señal <tt/changed/, que debe ser -parecida a: - -<tscreen><verb> - void (* changed) (GtkAdjustment *adjustment); -</verb></tscreen> - -Los <em/widgets/ de tamaño normalmente conectan un controlador a -esta señal, que cambia el aspecto de éste para reflejar el -cambio. Por ejemplo el tamaño de la guía en una barra deslizante -que se alarga o encoge según la inversa de la diferencia de los -valores <tt/lower/ y <tt/upper/. - -Probablemente nunca tenga que conectar un controlador a esta señal -a no ser que esté escribiendo un nuevo tipo de <em/widget/. Pero si -cambia directamente alguno de los valores de GtkAdjustment debe hacer -que se emita la siguiente señal para reconfigurar todos aquellos -<em/widgets/ que usen ese ajuste: - -<tscreen><verb> -gtk_signal_emit_by_name (GTK_OBJECT (adjustment), "changed"); -</verb></tscreen> - -</sect1> -</sect> -<!-- ***************************************************************** --> -<sect>Los <em/widgets/ de selección de rango <label id="sec_Range_Widgets"> -<!-- ***************************************************************** --> -<p> -Este tipo de <em/widgets/ incluye a las barras de desplazamiento -(<em>scroollbar</em>) y la menos conocida escala -(<em/scale</em>). Ambos pueden ser usados para muchas cosas, pero como -sus funciones y su implementación son muy parecidas los describimos -al mismo tiempo. Principalmente se utilizan para permitirle al usuario -escoger un valor dentro de un rango ya prefijado. - -Todos los <em/widgets/ de selección comparten elementos -gráficos, cada uno de los cuales tiene su propia ventana X window y -recibe eventos. Todos contienen una guía y un rectángulo para -determinar la posición dentro de la guía (en una procesador de -textos con entorno gráfico se encuentra situado a la derecha del -texto y sirve para situarnos en las diferentes partes del texto). Con -el ratón podemos subir o bajar el rectángulo, mientras que si -hacemos `click' dentro de la guía, pero no sobre el rectángulo, -este se mueve hacia donde hemos hecho el click. Dependiendo del -botón pulsado el rectángulo se moverá hasta la posición -del click o una cantidad prefijada de ante mano. - -Tal y como se mencionó en <ref id="sec_Adjustment" name="Ajustes"> -todos los <em/widgets/ usados para seleccionar un rango estan -asociados con un objeto de ajuste, a partir del cual calculan la -longitud de la barra y su posición. Cuando el usuario manipula la -barra de desplazamiento el widget cambiará el valor del ajuste. - -<sect1>El <em/widget/ barra de desplazamiento -<p> -El <em/widget/ barra de desplazamiento solamente debe utilizarse para -hacer <em/scroll/ sobre otro <em/widget/, como una lista, una caja de -texto, o un puerto de visión (y en muchos es más fácil utilizar -el <em/widget/ scrolled window). Para el resto de los casos, debería -utilizar los <em/widgets/ de escala, ya son más sencillos de usar y -más potentes. - -Hay dos tipos separados de barras de desplazamiento, según sea -horizontal o vertical. Realmente no hay mucho que añadir. Puede -crear estos <em/widgets/ utilizar las funciones siguientes, definidas -en <tt><gtk/gtkhscrollbar.h></tt> y -<tt><gtk/gtkvscrollbar.h></tt>: - -<tscreen><verb> -GtkWidget* gtk_hscrollbar_new( GtkAdjustment *adjustment ); - -GtkWidget* gtk_vscrollbar_new( GtkAdjustment *adjustment ); -</verb></tscreen> - -y esto es todo lo que hay (si no me cree, ¡mire los ficheros de -cabecera!). El argumento <tt/adjustment/ puede ser un puntero a un -ajuste ya existente, o puede ser NULL, en cuyo caso se creará -uno. Es útil especificar NULL si quiere pasar el ajuste recién -creado a la función constructora de algún otro <em/widget/ (como -por ejemplo el <em/widget/ texto) que se ocupará de configurarlo -correctamente por usted. - -<!-- ----------------------------------------------------------------- --> -<sect1><em/Widgets/ de escala -<p> -Los <em/widgets/ de escala se usan para determinar el valor de una -cantidad que se puede interpretar visualmente. El usuario -probablemente fijará el valor a ojo. Por ejemplo el <em/widget/ -GtkColorSelection contiene <em/widgets/ de escala que controlan las -componentes del color a seleccionar. Normalmente el valor preciso es -menos importante que el efecto visual, por lo que el color se -selecciona con el ratón y no mediante un número concreto. - -<!-- ----------------------------------------------------------------- --> -<sect2>Creación de un <em/widget/ de escala -<p> -Existen dos tipos de <em/widgets/ de escala: GtkHScale (que es -horizontal) y GtkVscale (vertical). Como funcionan de la misma manera -los vamos a describir a la vez. Las funciones definidas en -<tt><gtk/gtkvscale.h></tt> y <tt><gtk/gtkhscale.h></tt>, -crean <em/widgets/ de escala verticales y horizontales -respectivamente. - -<tscreen><verb> -GtkWidget* gtk_vscale_new( GtkAdjustment *adjustment ); - -GtkWidget* gtk_hscale_new( GtkAdjustment *adjustment ); -</verb></tscreen> - -El <tt/ajuste/ (adjustment) puede ser tanto un ajuste creado -mediante <tt/gtk_adjustment_new()/ como <tt/NULL/. En este -último caso se crea un GtkAdjustment anónimo con todos sus -valores iguales a <tt/0.0/. Si no ha quedado claro el uso de esta -función consulte la sección <ref id="sec_Adjustment" -name="Ajustes"> para una discusión más detallada. - -<!-- ----------------------------------------------------------------- --> -<sect2> Funciones y señales -<p> -Los <em/widgets/ de escala pueden indicar su valor actual como un -número. Su comportamiento por defecto es mostrar este valor, pero -se puede modificar usando: - -<tscreen><verb> -void gtk_scale_set_draw_value( GtkScale *scale, - gint draw_value ); -</verb></tscreen> - -Los valores posibles de <tt/draw_value son/ son <tt/TRUE/ o <tt/FALSE/. -Con el primero se muestra el valor y con el segundo no. - -El valor mostrado por un <em/widget/ de escala por defecto se redondea -a un valor decimal (igual que con <tt/value/ en un GtkAdjustment). Se -puede cambiar con: - -<tscreen> -<verb> -void gtk_scale_set_digits( GtkScale *scale, - gint digits ); -</verb> -</tscreen> - -donde <tt/digits/ es el número de posiciones decimales que se -quiera. En la práctica sólo se mostrarán 13 como máximo. - -Por último, el valor se puede dibujar en diferentes posiciones con -respecto a la posición del rectangulo que hay dentro de la guía: - -<tscreen> -<verb> -void gtk_scale_set_value_pos( GtkScale *scale, - GtkPositionType pos ); -</verb> -</tscreen> - -Si ha leido la sección acerca del <em/widget/ libro de notas -entonces ya conoce cuales son los valores posibles de <tt/pos/. Estan -definidos en <tt><gtk/gtkscale.h></tt> como <tt/enum GtkPositionType/ -y son auto explicatorios. Si se escoge un lateral de la guía, -entonces seguirá al rectángulo a lo largo de la guía. - -Todas las funcioenes precedentes se encuentran definidas en: -<tt><gtk/gtkscale.h></tt>. -</sect2> -</sect1> - -<!-- ----------------------------------------------------------------- --> -<sect1> Funciones comunes <label id="sec_funciones_range"> -<p> -La descripción interna de la clase GtkRange es bastante complicada, -pero al igual que con el resto de las «clases base» sólo es -interesante si se quiere «hackear». Casi todas las señales y -funciones sólo son útiles para desarrollar derivados. Para un -usuario normal las funciones interesantes son aquellas definidas en: -<tt><gtk/gtkrange.h></tt> y funcionan igual en todos los -<em/widgets/ de rango. - -<!-- ----------------------------------------------------------------- --> -<sect2> Estableciendo cada cúanto se actualizan -<p> -La política de actualización de un <em/widget/ define en que -puntos de la interacción con el usuario debe cambiar el valor -<tt/value/ en su GtkAdjustment y emitir la señal -«value_changed». Las actualizaciones definidas en -<tt><gtk/gtkenums.h></tt> como <tt>enum GtkUpdateType</tt>, son: - -<itemize> -<item>GTK_UPDATE_POLICY_CONTINUOUS - Este es el valor por defecto.La -señal «value_changed» se emite continuamente, por ejemplo cuando -la barra deslizante se mueve incluso aunque sea un poquito. -</item> -<item>GTK_UPDATE_POLICY_DISCONTINUOUS - La señal «value_changed» -sólo se emite cuando se ha parado de mover la barra y el usuario ha -soltado el botón del ratón. -</item> -<item>GTK_UPDATE_POLICY_DELAYED - La señal sólo se emite cuando -el usuario suelta el botón del ratón o si la barra no se mueve -durante un periodo largo de tiempo. -</item> -</itemize> - -Para establecer la política de actualización se usa la -conversión definida en la macro - -<tscreen><verb> -void gtk_range_set_update_policy( GtkRange *range, - GtkUpdateType policy) ; -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect2>Obteniendo y estableciendo Ajustes -<p> -Para obtener o establecer el ajuste de un <em/widget/ de rango se usa: - -<tscreen><verb> -GtkAdjustment* gtk_range_get_adjustment( GtkRange *range ); - -void gtk_range_set_adjustment( GtkRange *range, - GtkAdjustment *adjustment ); -</verb></tscreen> - -La función <tt/gtk_range_get_adjustment()/ devuelve un puntero al -ajuste al que <tt/range/ esté conectado. - -La función <tt/gtk_range_set_adjustment()/ no hace nada si se le -pasa como argumento el valor <tt/range/ del ajuste que esta siendo -usado (aunque se haya modificado algún valor). En el caso de que -sea un ajuste nuevo (GtkAdjustment) dejará de usar el antiguo -(probablemente lo destruirá) y conectará las señales -apropiadas al nuevo. A continuación llamará a la función -<tt/gtk_range_adjustment_changed()/ que en teoría recalculará el -tamaño y/o la posición de la barra, redibujándola en caso de -que sea necesario. Tal y como se mencionó en la sección de los -ajustes si se quiere reusar el mismo GtkAdjustment cuando se modifican -sus valores se debe emitir la señal «changed». Por ejemplo: - -<tscreen><verb> -gtk_signal_emit_by_name (GTK_OBJECT (adjustment), "changed"); -</verb></tscreen> -</sect2> -</sect1> - -<!-- ----------------------------------------------------------------- --> -<sect1> Enlaces con el teclado y el ratón -<p> -Todos los <em/widgets/ de rango reaccionan más o menos de la misma -manera a las pulsaciones del ratón. Al pulsar el botón 1 sobre -el rectángulo de la barra el <tt/value/ del ajuste aumentará o -disminuirá según <tt/page_increment/. Con el botón 2 la barra -se desplazará al punto en el que el botón fue pulsado. Con cada -pulsación de cualquier botón sobre las flechas el valor del -ajuste se modifica una cantidad igual a <tt/step_increment/. - - -Acostumbrarse a que tanto las barras deslizantes como los <em/widgets/ de -escala puedan tomar la atención del teclado puede ser un proceso largo. -Si que se cree que los usuarios no lo van a entender se puede anular -mediante la función GTK_WIDGET_UNSET_FLAGS y con GTK_CAN_FOCUS como -argumento: - -<tscreen><verb> -GTK_WIDGET_UNSET_FLAGS (scrollbar, GTK_CAN_FOCUS); -</verb></tscreen> - -Los enlaces entre teclas (que sólo estan activos cuando el -<em/widget/ tiene la atención (focus)) se comportan de manera -diferente para los <em/widgets/ de rango horizontales que para los -verticales. También son diferentes para los <em/widgets/ de escala -y para las barras deslizantes. (Simplemente para evitar confusiones -entre las teclas de las barras deslizantes horizontales y verticales, -ya que ambas actúan sobre la misma área) - -<sect2><em/Widgets/ de rango vertical -<p> -Todos los <em/widgets/ de rango pueden ser manipulados con las teclas -arriba, abajo, <tt/Re Pág/, <tt/ Av Pág/. Las flechas mueven las -barras la cantidad fijada mediante <tt/step_increment/, mientras que -<tt/Re Pág/ y <tt/Av Pag/ lo hacen según <tt/page_increment/. - -El usuario también puede mover la barra de un extremo al otro de la -guía mediante el teclado. Con el <em/widget/ GtkVScale podemos ir a -los extremos utilizando las teclas <tt/Inicio/ y <tt/Final/ mientras -que con el <em/widget/ GtkVScrollbar habrá que utilizar -<tt/Control-Re Pág/ y <tt/Control-Av Pág/. - -<!-- ----------------------------------------------------------------- --> -<sect2><em/Widgets/ de rango horizontal -<p> -Las teclas izquierda y derecha funcionan tal y como espera que -funcionen en estos <em/widgets/: mueven la barra una cantidad dada por -<tt/step_increment/. A su vez <tt/Inicio/ y <tt/Final/ sirven para -pasar de un extremo al otro de la guía. Para el <em/widget/ -GtkHScale el mover la barra una cantidad dada por <tt/page_increment/ -se consigue mediante <tt>Control-Izquierda</tt> y -<tt>Control-derecha</tt>, mientras que para el <em/widget/ -GtkHScrollbar se consigue con <tt/Control-Inicio/ y -<tt/Control-Final/. -</sect2> -</sect1> - -<!-- ----------------------------------------------------------------- --> -<sect1> Ejemplo <label id="sec_Ejemplo_Rango"> -<p> -Este ejemplo es una versión modificada del test «range controls» -que a su vez forma parte de <tt/testgtk.c/. Simplemente dibuja una -ventana con tres <em/widgets/ de rango conectados al mismo ajuste, y -un conjunto de controles para ajustar algunos de los parámetros -ya mencionados. Así se consigue ver como funcionan estos -<em/widgets/ al ser manipulados por el usuario. - -<tscreen><verb> -/* principio del ejemplo widgets de selección de rango rangewidgets.c */ - -#include <gtk/gtk.h> - -GtkWidget *hscale, *vscale; - -void cb_pos_menu_select( GtkWidget *item, - GtkPositionType pos ) -{ - /* Establece el valor position en los widgets de escala */ - gtk_scale_set_value_pos (GTK_SCALE (hscale), pos); - gtk_scale_set_value_pos (GTK_SCALE (vscale), pos); -} - -void cb_update_menu_select( GtkWidget *item, - GtkUpdateType policy ) -{ - /* Establece la política de actualización para los widgets - * de escala */ - gtk_range_set_update_policy (GTK_RANGE (hscale), policy); - gtk_range_set_update_policy (GTK_RANGE (vscale), policy); -} - -void cb_digits_scale( GtkAdjustment *adj ) -{ - /* Establece el número de cifras decimales a las que se - * redondeará adj->value */ - gtk_scale_set_digits (GTK_SCALE (hscale), (gint) adj->value); - gtk_scale_set_digits (GTK_SCALE (vscale), (gint) adj->value); -} - -void cb_page_size( GtkAdjustment *get, - GtkAdjustment *set ) -{ - /* Establece el tamaño de la página y el incremento del - * ajuste al valor especificado en la escala "Page Size" */ - set->page_size = get->value; - set->page_increment = get->value; - /* Ahora emite la señal "changed" para reconfigurar todos los - * widgets que están enlazados a este ajuste */ - gtk_signal_emit_by_name (GTK_OBJECT (set), "changed"); -} - -void cb_draw_value( GtkToggleButton *boton ) -{ - /* Activa o desactiva el valor display en los widgets de escala - * dependiendo del estado del botón de comprobación */ - gtk_scale_set_draw_value (GTK_SCALE (hscale), boton->active); - gtk_scale_set_draw_value (GTK_SCALE (vscale), boton->active); -} - -/* Funciones varias */ - -GtkWidget *make_menu_item( gchar *name, - GtkSignalFunc callback, - gpointer data ) -{ - GtkWidget *item; - - item = gtk_menu_item_new_with_label (name); - gtk_signal_connect (GTK_OBJECT (item), "activate", - callback, data); - gtk_widget_show (item); - - return(item); -} - -void scale_set_default_values( GtkScale *scale ) -{ - gtk_range_set_update_policy (GTK_RANGE (scale), - GTK_UPDATE_CONTINUOUS); - gtk_scale_set_digits (scale, 1); - gtk_scale_set_value_pos (scale, GTK_POS_TOP); - gtk_scale_set_draw_value (scale, TRUE); -} - -/* crea la ventana principal */ - -void create_range_controls( void ) -{ - GtkWidget *ventana; - GtkWidget *caja1, *caja2, *caja3; - GtkWidget *boton; - GtkWidget *scrollbar; - GtkWidget *separator; - GtkWidget *opt, *menu, *item; - GtkWidget *etiqueta; - GtkWidget *scale; - GtkObject *adj1, *adj2; - - /* creación estándar de una ventana */ - ventana = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_signal_connect (GTK_OBJECT (ventana), "destroy", - GTK_SIGNAL_FUNC(gtk_main_quit), - NULL); - gtk_window_set_title (GTK_WINDOW (ventana), "range controls"); - - caja1 = gtk_vbox_new (FALSE, 0); - gtk_container_add (GTK_CONTAINER (ventana), caja1); - gtk_widget_show (caja1); - - caja2 = gtk_hbox_new (FALSE, 10); - gtk_container_border_width (GTK_CONTAINER (caja2), 10); - gtk_box_pack_start (GTK_BOX (caja1), caja2, TRUE, TRUE, 0); - gtk_widget_show (caja2); - - /* value, lower, upper, step_increment, page_increment, page_size */ - /* Observe que el valor de page_size solo sirve para los widgets - * barras de desplazamiento (scrollbar), y que el valor más - * alto que obtendrá será (upper - page_size). */ - adj1 = gtk_adjustment_new (0.0, 0.0, 101.0, 0.1, 1.0, 1.0); - - vscale = gtk_vscale_new (GTK_ADJUSTMENT (adj1)); - scale_set_default_values (GTK_SCALE (vscale)); - gtk_box_pack_start (GTK_BOX (caja2), vscale, TRUE, TRUE, 0); - gtk_widget_show (vscale); - - caja3 = gtk_vbox_new (FALSE, 10); - gtk_box_pack_start (GTK_BOX (caja2), caja3, TRUE, TRUE, 0); - gtk_widget_show (caja3); - - /* Reutilizamos el mismo ajuste */ - hscale = gtk_hscale_new (GTK_ADJUSTMENT (adj1)); - gtk_widget_set_usize (GTK_WIDGET (hscale), 200, 30); - scale_set_default_values (GTK_SCALE (hscale)); - gtk_box_pack_start (GTK_BOX (caja3), hscale, TRUE, TRUE, 0); - gtk_widget_show (hscale); - - /* Reutilizamos de nuevo el mismo ajuste */ - scrollbar = gtk_hscrollbar_new (GTK_ADJUSTMENT (adj1)); - /* Observe que con esto conseguimos que la escala siempre se - * actualice de una forma continua cuando se mueva la barra de - * desplazamiento */ - gtk_range_set_update_policy (GTK_RANGE (scrollbar), - GTK_UPDATE_CONTINUOUS); - gtk_box_pack_start (GTK_BOX (caja3), scrollbar, TRUE, TRUE, 0); - gtk_widget_show (scrollbar); - - caja2 = gtk_hbox_new (FALSE, 10); - gtk_container_border_width (GTK_CONTAINER (caja2), 10); - gtk_box_pack_start (GTK_BOX (caja1), caja2, TRUE, TRUE, 0); - gtk_widget_show (caja2); - - /* Un botón para comprobar si el valor se muestra o no*/ - boton = gtk_check_button_new_with_label("Display value on scale widgets"); - gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (boton), TRUE); - gtk_signal_connect (GTK_OBJECT (boton), "toggled", - GTK_SIGNAL_FUNC(cb_draw_value), NULL); - gtk_box_pack_start (GTK_BOX (caja2), boton, TRUE, TRUE, 0); - gtk_widget_show (boton); - - caja2 = gtk_hbox_new (FALSE, 10); - gtk_container_border_width (GTK_CONTAINER (caja2), 10); - - /* Una opción en el menú para cambiar la posición del - * valor */ - etiqueta = gtk_label_new ("Scale Value Position:"); - gtk_box_pack_start (GTK_BOX (caja2), etiqueta, FALSE, FALSE, 0); - gtk_widget_show (etiqueta); - - opt = gtk_option_menu_new(); - menu = gtk_menu_new(); - - item = make_menu_item ("Top", - GTK_SIGNAL_FUNC(cb_pos_menu_select), - GINT_TO_POINTER (GTK_POS_TOP)); - gtk_menu_append (GTK_MENU (menu), item); - - item = make_menu_item ("Bottom", GTK_SIGNAL_FUNC (cb_pos_menu_select), - GINT_TO_POINTER (GTK_POS_BOTTOM)); - gtk_menu_append (GTK_MENU (menu), item); - - item = make_menu_item ("Left", GTK_SIGNAL_FUNC (cb_pos_menu_select), - GINT_TO_POINTER (GTK_POS_LEFT)); - gtk_menu_append (GTK_MENU (menu), item); - - item = make_menu_item ("Right", GTK_SIGNAL_FUNC (cb_pos_menu_select), - GINT_TO_POINTER (GTK_POS_RIGHT)); - gtk_menu_append (GTK_MENU (menu), item); - - gtk_option_menu_set_menu (GTK_OPTION_MENU (opt), menu); - gtk_box_pack_start (GTK_BOX (caja2), opt, TRUE, TRUE, 0); - gtk_widget_show (opt); - - gtk_box_pack_start (GTK_BOX (caja1), caja2, TRUE, TRUE, 0); - gtk_widget_show (caja2); - - caja2 = gtk_hbox_new (FALSE, 10); - gtk_container_border_width (GTK_CONTAINER (caja2), 10); - - /* Sí, otra opción de menú, esta vez para la política - * de actualización de los widgets */ - etiqueta = gtk_label_new ("Scale Update Policy:"); - gtk_box_pack_start (GTK_BOX (caja2), etiqueta, FALSE, FALSE, 0); - gtk_widget_show (etiqueta); - - opt = gtk_option_menu_new(); - menu = gtk_menu_new(); - - item = make_menu_item ("Continuous", - GTK_SIGNAL_FUNC (cb_update_menu_select), - GINT_TO_POINTER (GTK_UPDATE_CONTINUOUS)); - gtk_menu_append (GTK_MENU (menu), item); - - item = make_menu_item ("Discontinuous", - GTK_SIGNAL_FUNC (cb_update_menu_select), - GINT_TO_POINTER (GTK_UPDATE_DISCONTINUOUS)); - gtk_menu_append (GTK_MENU (menu), item); - - item = make_menu_item ("Delayed", - GTK_SIGNAL_FUNC (cb_update_menu_select), - GINT_TO_POINTER (GTK_UPDATE_DELAYED)); - gtk_menu_append (GTK_MENU (menu), item); - - gtk_option_menu_set_menu (GTK_OPTION_MENU (opt), menu); - gtk_box_pack_start (GTK_BOX (caja2), opt, TRUE, TRUE, 0); - gtk_widget_show (opt); - - gtk_box_pack_start (GTK_BOX (caja1), caja2, TRUE, TRUE, 0); - gtk_widget_show (caja2); - - caja2 = gtk_hbox_new (FALSE, 10); - gtk_container_border_width (GTK_CONTAINER (caja2), 10); - - /* Un widget GtkHScale para ajustar el número de dígitos en - * la escala. */ - etiqueta = gtk_label_new ("Scale Digits:"); - gtk_box_pack_start (GTK_BOX (caja2), etiqueta, FALSE, FALSE, 0); - gtk_widget_show (etiqueta); - - adj2 = gtk_adjustment_new (1.0, 0.0, 5.0, 1.0, 1.0, 0.0); - gtk_signal_connect (GTK_OBJECT (adj2), "value_changed", - GTK_SIGNAL_FUNC (cb_digits_scale), NULL); - scale = gtk_hscale_new (GTK_ADJUSTMENT (adj2)); - gtk_scale_set_digits (GTK_SCALE (scale), 0); - gtk_box_pack_start (GTK_BOX (caja2), scale, TRUE, TRUE, 0); - gtk_widget_show (scale); - - gtk_box_pack_start (GTK_BOX (caja1), caja2, TRUE, TRUE, 0); - gtk_widget_show (caja2); - - caja2 = gtk_hbox_new (FALSE, 10); - gtk_container_border_width (GTK_CONTAINER (caja2), 10); - - /* Y un último widget GtkHScale para ajustar el tamaño de la - * página de la barra de desplazamiento. */ - etiqueta = gtk_label_new ("Scrollbar Page Size:"); - gtk_box_pack_start (GTK_BOX (caja2), etiqueta, FALSE, FALSE, 0); - gtk_widget_show (etiqueta); - - adj2 = gtk_adjustment_new (1.0, 1.0, 101.0, 1.0, 1.0, 0.0); - gtk_signal_connect (GTK_OBJECT (adj2), "value_changed", - GTK_SIGNAL_FUNC (cb_page_size), adj1); - scale = gtk_hscale_new (GTK_ADJUSTMENT (adj2)); - gtk_scale_set_digits (GTK_SCALE (scale), 0); - gtk_box_pack_start (GTK_BOX (caja2), scale, TRUE, TRUE, 0); - gtk_widget_show (scale); - - gtk_box_pack_start (GTK_BOX (caja1), caja2, TRUE, TRUE, 0); - gtk_widget_show (caja2); - - separator = gtk_hseparator_new (); - gtk_box_pack_start (GTK_BOX (caja1), separator, FALSE, TRUE, 0); - gtk_widget_show (separator); - - caja2 = gtk_vbox_new (FALSE, 10); - gtk_container_border_width (GTK_CONTAINER (caja2), 10); - gtk_box_pack_start (GTK_BOX (caja1), caja2, FALSE, TRUE, 0); - gtk_widget_show (caja2); - - boton = gtk_button_new_with_label ("Quit"); - gtk_signal_connect_object (GTK_OBJECT (boton), "clicked", - GTK_SIGNAL_FUNC(gtk_main_quit), - NULL); - gtk_box_pack_start (GTK_BOX (caja2), boton, TRUE, TRUE, 0); - GTK_WIDGET_SET_FLAGS (boton, GTK_CAN_DEFAULT); - gtk_widget_grab_default (boton); - gtk_widget_show (boton); - - gtk_widget_show (ventana); -} - -int main( int argc, - char *argv[] ) -{ - gtk_init(&argc, &argv); - - create_range_controls(); - - gtk_main(); - - return(0); -} - -/* fin del ejemplo */ -</verb></tscreen> - -Observe que el programa no llama a <tt/gtk_signal_connect/ para -conectar el «delete_event», y que sólo conecta la señal -«destroy». Con esto seguimos realizando la función deseada, ya que -un «delete_event» no manejado desenboca en una señal «destroy» -para la ventana. -</sect1> -</sect> - -<!-- ***************************************************************** --> -<sect><em/Widgets/ varios -<!-- ***************************************************************** --> - -<!-- ----------------------------------------------------------------- --> -<sect1> Etiquetas -<p> -Las etiquetas se usan mucho en GTK y son bastante simples de manejar. -No pueden emitir señales ya que no tienen ventanas X window -asociadas. Si se desea capturar señales se debe usar el <em/widget/ -EventBox o un <em/widget/ botón. - -Para crear una nueva etiqueta se usa: - -<tscreen><verb> -GtkWidget *gtk_label_new( char *str ); -</verb></tscreen> - -El único argumento es la cadena de texto que se quiere mostrar. - -Para cambiarla después de que haya sido creada se usa: - -<tscreen><verb> -void gtk_label_set( GtkLabel *etiqueta, - char *str ); -</verb></tscreen> - -En este caso el primer argumento es la etiqueta ya creada (cambiado su -tipo mediante la macro <tt/GTK_LABEL()/) y el segundo es la nueva cadena. -El espacio que necesite la nueva etiqueta se ajustará -automáticamente, si es necesario. - -Para obtener el estado de la cadena en un momento dado existe la -función: - -<tscreen><verb> -void gtk_label_get( GtkLabel *etiqueta, - char **str ); -</verb></tscreen> -El primer argumento es la etiqueta, mientras que el segundo es el -valor devuelto para la cadena. No libere la memoria de la cadena -devuelta, ya que se utiliza internamente por GTK. - -El texto de la etiqueta se puede justificar utilizando: - -<tscreen><verb> -void gtk_label_set_justify( GtkLabel *etiqueta, - GtkJustification jtype ); -</verb></tscreen> - -Los valores posibles para <tt/jtype/ son: -<itemize> -<item> GTK_JUSTIFY_LEFT -<item> GTK_JUSTIFY_RIGHT -<item> GTK_JUSTIFY_CENTER (the default) -<item> GTK_JUSTIFY_FILL -</itemize> - -El <em/widget/ etiqueta también es capaz de separar el texto de forma -automática cuando se llega al final de una linea. Esto se puede -conseguir utilizando: - -<tscreen><verb> -void gtk_label_set_line_wrap (GtkLabel *etiqueta, - gboolean wrap); -</verb></tscreen> - -El argumento <tt/wrap/ toma el valor TRUE o FALSE. - -Si quiere que su etiqueta salga subrayada, puede especificar un motivo -para el subrayado con: - -<tscreen><verb> -void gtk_label_set_pattern (GtkLabel *etiqueta, - const gchar *pattern); -</verb></tscreen> - -El argumento <tt/pattern/ indica cual debe ser el aspecto del -subrayado. Consiste en una cadena de espacios en blanco y carácteres -de subrayado. Por ejemplo, la cadena <tt/"__ __"/ debe hacer que -se subrayen los dos primeros y el octavo y el noveno carácter. - -A continuación tenemos un pequeño ejemplo que ilustra el uso de estas -funciones. Este ejemplo utiliza el <em/widget/ marco (<em/frame/) para -hacer una mejor demostración de los estilos de la etiqueta. Por ahora -puede ignorarlo, ya que el <em/widget/ <ref id="sec_Frames" -name="Frame"> se explicará más tarde. - -<tscreen><verb> -/* principio del ejemplo label label.c */ - -#include <gtk/gtk.h> - -int main( int argc, - char *argv[] ) -{ - static GtkWidget *ventana = NULL; - GtkWidget *hbox; - GtkWidget *vbox; - GtkWidget *frame; - GtkWidget *etiqueta; - - /* Inicializa GTK */ - gtk_init(&argc, &argv); - - ventana = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_signal_connect (GTK_OBJECT (ventana), "destroy", - GTK_SIGNAL_FUNC(gtk_main_quit), - NULL); - - gtk_window_set_title (GTK_WINDOW (ventana), "Etiqueta"); - vbox = gtk_vbox_new (FALSE, 5); - hbox = gtk_hbox_new (FALSE, 5); - gtk_container_add (GTK_CONTAINER (ventana), hbox); - gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0); - gtk_container_set_border_width (GTK_CONTAINER (ventana), 5); - - frame = gtk_frame_new ("Normal Label"); - etiqueta = gtk_label_new ("This is a Normal label"); - gtk_container_add (GTK_CONTAINER (frame), etiqueta); - gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); - - frame = gtk_frame_new ("Multi-line Label"); - etiqueta = gtk_label_new ("This is a Multi-line label.\nSecond line\n" \ - "Third line"); - gtk_container_add (GTK_CONTAINER (frame), etiqueta); - gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); - - frame = gtk_frame_new ("Left Justified Label"); - etiqueta = gtk_label_new ("This is a Left-Justified\n" \ - "Multi-line label.\nThird line"); - gtk_label_set_justify (GTK_LABEL (etiqueta), GTK_JUSTIFY_LEFT); - gtk_container_add (GTK_CONTAINER (frame), etiqueta); - gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); - - frame = gtk_frame_new ("Right Justified Label"); - etiqueta = gtk_label_new ("This is a Right-Justified\nMulti-line label.\n" \ - "Fourth line, (j/k)"); - gtk_label_set_justify (GTK_LABEL (etiqueta), GTK_JUSTIFY_RIGHT); - gtk_container_add (GTK_CONTAINER (frame), etiqueta); - gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); - - vbox = gtk_vbox_new (FALSE, 5); - gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0); - frame = gtk_frame_new ("Line wrapped label"); - etiqueta = gtk_label_new ("This is an example of a line-wrapped label. It " \ - "should not be taking up the entire " /* big space to test spacing */\ - "width allocated to it, but automatically " \ - "wraps the words to fit. " \ - "The time has come, for all good men, to come to " \ - "the aid of their party. " \ - "The sixth sheik's six sheep's sick.\n" \ - " It supports multiple paragraphs correctly, " \ - "and correctly adds "\ - "many extra spaces. "); - gtk_label_set_line_wrap (GTK_LABEL (etiqueta), TRUE); - gtk_container_add (GTK_CONTAINER (frame), etiqueta); - gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); - - frame = gtk_frame_new ("Filled, wrapped label"); - etiqueta = gtk_label_new ("This is an example of a line-wrapped, filled label. " \ - "It should be taking "\ - "up the entire width allocated to it. " \ - "Here is a seneance to prove "\ - "my point. Here is another sentence. "\ - "Here comes the sun, do de do de do.\n"\ - " This is a new paragraph.\n"\ - " This is another newer, longer, better " \ - "paragraph. It is coming to an end, "\ - "unfortunately."); - gtk_label_set_justify (GTK_LABEL (etiqueta), GTK_JUSTIFY_FILL); - gtk_label_set_line_wrap (GTK_LABEL (etiqueta), TRUE); - gtk_container_add (GTK_CONTAINER (frame), etiqueta); - gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); - - frame = gtk_frame_new ("Underlined label"); - etiqueta = gtk_label_new ("This label is underlined!\n" - "This one is underlined in quite a funky fashion"); - gtk_label_set_justify (GTK_LABEL (etiqueta), GTK_JUSTIFY_LEFT); - gtk_label_set_pattern (GTK_LABEL (etiqueta), - "_________________________ _ _________ _ ______ __ _______ ___"); - gtk_container_add (GTK_CONTAINER (frame), etiqueta); - gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); - - gtk_widget_show_all (ventana); - - gtk_main (); - - return(0); -} -/* fin del ejemplo */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1> Flechas -<p> -En <em/widget/ flecha (<em/arrow/) dibuja la punta de una flecha, -con un estilo y hacia una dirección a escoger. Puede ser muy útil -en muchas aplicaciones cuando se coloca en un botón. - -Sólo hay dos funciones para manipular el <em/widget/ flecha: - -<tscreen><verb> -GtkWidget *gtk_arrow_new( GtkArrowType arrow_type, - GtkShadowType shadow_type ); - -void gtk_arrow_set( GtkArrow *arrow, - GtkArrowType arrow_type, - GtkShadowType shadow_type ); -</verb></tscreen> - -La primera crea un nuevo <em/widget/ flecha del tipo y apariencia -indicados. La segunda permite alterar posteriormente estos valores. El -argumento <tt/arrow_type/ puede tomar uno de los valores siguientes: - -<itemize> -<item> GTK_ARROW_UP -<item> GTK_ARROW_DOWN -<item> GTK_ARROW_LEFT -<item> GTK_ARROW_RIGHT -</itemize> - -Naturalmente, estos valores indican la dirección a la que debe apuntar -la flecha. El argumento <tt/shadow_type/ puede tomar uno de los -valores siguientes: - -<itemize> -<item> GTK_SHADOW_IN -<item> GTK_SHADOW_OUT (por defecto) -<item> GTK_SHADOW_ETCHED_IN -<item> GTK_SHADOW_ETCHED_OUT -</itemize> - -Aquí tenemos un pequeño ejemplo para ilustrar la utilización de la -flecha. - -<tscreen><verb> -/* principio del ejemplo arrow arrow.c */ - -#include <gtk/gtk.h> - -/* Crea un widget flecha con los parámetros especificados - * y lo empaqueta en un botón */ -GtkWidget *create_arrow_button( GtkArrowType arrow_type, - GtkShadowType shadow_type ) -{ - GtkWidget *boton; - GtkWidget *arrow; - - boton = gtk_button_new(); - arrow = gtk_arrow_new (arrow_type, shadow_type); - - gtk_container_add (GTK_CONTAINER (boton), arrow); - - gtk_widget_show(boton); - gtk_widget_show(arrow); - - return(boton); -} - -int main( int argc, - char *argv[] ) -{ - /* GtkWidget es el tipo utilizado para los widgets */ - GtkWidget *ventana; - GtkWidget *boton; - GtkWidget *box; - - /* Inicializa el toolkit */ - gtk_init (&argc, &argv); - - /* Crea una nueva ventana */ - ventana = gtk_window_new (GTK_WINDOW_TOPLEVEL); - - gtk_window_set_title (GTK_WINDOW (ventana), "Arrow Buttons"); - - /* Es una buena idea hacer esto con todas las ventanas. */ - gtk_signal_connect (GTK_OBJECT (ventana), "destroy", - GTK_SIGNAL_FUNC (gtk_main_quit), NULL); - - /* Establece el ancho del borde de la ventana. */ - gtk_container_set_border_width (GTK_CONTAINER (ventana), 10); - - /* Crea una caja para almacenar las flechas/botones */ - box = gtk_hbox_new (FALSE, 0); - gtk_container_set_border_width (GTK_CONTAINER (box), 2); - gtk_container_add (GTK_CONTAINER (ventana), box); - - /* Empaqueta y muestra todos nuestros widgets */ - gtk_widget_show(box); - - boton = create_arrow_button(GTK_ARROW_UP, GTK_SHADOW_IN); - gtk_box_pack_start (GTK_BOX (box), boton, FALSE, FALSE, 3); - - boton = create_arrow_button(GTK_ARROW_DOWN, GTK_SHADOW_OUT); - gtk_box_pack_start (GTK_BOX (box), boton, FALSE, FALSE, 3); - - boton = create_arrow_button(GTK_ARROW_LEFT, GTK_SHADOW_ETCHED_IN); - gtk_box_pack_start (GTK_BOX (box), boton, FALSE, FALSE, 3); - - boton = create_arrow_button(GTK_ARROW_RIGHT, GTK_SHADOW_ETCHED_OUT); - gtk_box_pack_start (GTK_BOX (box), boton, FALSE, FALSE, 3); - - gtk_widget_show (ventana); - - /* Nos quedamos en gtk_main y ¡esperamos que empiece la diversión! */ - gtk_main (); - - return(0); -} -/* fin del ejemplo */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>El <em/widget/ de información rápida (<em/tooltip/) -<p> -Estos <em/widgets/ son las pequeñas etiquetas que texto que -aparecen cuando se sitúa el puntero del ratón sobre un botón -u otro <em/widget/ durante algunos segundos. Son bastante fáciles -de usar, así que no se dará ningún ejemplo. Si quiere ver -algún ejemplo se recomienda leer el programa testgtk.c que -acompaña a GTK. - -Algunos <em/widgets/ (como la etiqueta) no pueden llevar asociado un -<em/tooltip/. - -Para cada función sólo hay que hacer una llamada para conseguir -un <em/tooltip/. El objeto <tt/GtkTooltip/ que devuelve la siguiente -función puede ser usado para crear múltiples <em/widgets/. - -<tscreen><verb> -GtkTooltips *gtk_tooltips_new( void ); -</verb></tscreen> - -Una vez que el <em/tooltip/ ha sido creado (y el <em/widget/ sobre el -que se quiere usar) simplemente hay que usar la siguiente llamada para -pegarlo: - -<tscreen><verb> -void gtk_tooltips_set_tip( GtkTooltips *tooltips, - GtkWidget *widget, - const gchar *tip_text, - const gchar *tip_private ); -</verb></tscreen> - -El primer argumento es el <em/tooltip/ que ya ha creado, seguido del -<em/widget/ al que se desea asociar el <em/tooltip/, el tercero es el -texto que se quiere que aparezca y el último es una cadena de texto -que puede ser usada como un identificador cuando se usa GtkTipsQuery -para desarollar ayuda sensible al contexto. Por ahora conviene dejarlo -como NULL. - -<!-- TODO: sort out what how to do the context sensitive help --> - -Veamos un ejemplo: - -<tscreen><verb> -GtkTooltips *tooltips; -GtkWidget *boton; -... -tooltips = gtk_tooltips_new (); -boton = gtk_button_new_with_label ("botón 1"); -... -gtk_tooltips_set_tip (tooltips, boton, "Este es el botón 1", NULL); -</verb></tscreen> - -Existen otras funciones que pueden ser usadas con los <em/tooltips/. -Solamente vamos a enumerlarlas añadiendo una pequeña descripción -de que hace cada una. - -<tscreen><verb> -void gtk_tooltips_enable( GtkTooltips *tooltips ); -</verb></tscreen> - -Permite que funcionen un conjunto de <em/tooltips/ - -<tscreen><verb> -void gtk_tooltips_disable( GtkTooltips *tooltips ); -</verb></tscreen> - -Oculta un conjunto de <em/tooltips/ para que no pueda ser mostrado. - -<tscreen><verb> -void gtk_tooltips_set_delay( GtkTooltips *tooltips, - gint delay ); - -</verb></tscreen> - -Establece cuantos milisegundos tiene que estar el puntero sobre el -<em/widget/ para que aparezca el <em/tooltip/. Por defecto se usan 1000 -milisegundos (1 segundo). - -<tscreen><verb> -void gtk_tooltips_set_colors( GtkTooltips *tooltips, - GdkColor *background, - GdkColor *foreground ); -</verb></tscreen> - -Establece el color del texto y del fondo del <em/tooltip/. No se como -se especifica el color. - -<!-- ----------------------------------------------------------------- --> -<sect1> Barras de progreso <label id="sec_ProgressBar"> -<p> -Estas barras se usan para mostrar el estado de una operación. Son -bastante sencillas de utilizar, tal y como se verá en los ejemplos -siguientes. Pero primero vamos a ver cuales son las funciones que hay -que utilizar para crear una nueva barra de progreso. - -Hay dos formas de crear una nueva barra de progreso, la sencilla no -necesita de argumentos, y la otra recibe un objeto GtkAdjustment. Si -se utiliza la primera forma, la barra de progreso creará su propio -GtkAdjustment. - -<tscreen><verb> -GtkWidget *gtk_progress_bar_new( void ); - -GtkWidget *gtk_progress_bar_new_with_adjustment( GtkAdjustment *adjustment ); -</verb></tscreen> - -El segundo método tiene la ventaja de que podemos utilizar el objeto -adjustment para especificar nuestro propio rango de parámetros para la -barra de progreso. - -El ajuste de una barra de progreso se puede cambiar de forma dinámica -utilizando: - -<tscreen><verb> -void gtk_progress_set_adjustment( GtkProgress *progress, - GtkAdjustment *adjustment ); -</verb></tscreen> - -Ahora que hemos creado la barra de progreso ya podemos utilizarla. - -<tscreen><verb> -void gtk_progress_bar_update( GtkProgressBar *pbar, - gfloat percentage ); -</verb></tscreen> - -El primer argumento es la barra que se quiere manejar, el segundo es -tanto por ciento que ha sido `completado' (indica cuanto ha sido -llenada la barra y oscila entre 0-100%). El valor que se le tiene que -pasar oscila entre 0 y 1. - -GTK+ v1.2 ha añadido una nueva característica a la barra de progreso, -y es que ahora permite mostrar su valor de varias maneras distintas, e -informar al usuario del valor y rango actual. - -Una barra de progreso puede mostrarse con distintas orientaciones -utilizando la función - -<tscreen><verb> -void gtk_progress_bar_set_orientation( GtkProgressBar *pbar, - GtkProgressBarOrientation orientation ); -</verb></tscreen> - -Donde el argumento <tt/orientación/ puede tomar uno de los valores que -vienen a continuación para indicar la dirección en la que se mueve la -barra de progreso: - -<itemize> -<item> GTK_PROGRESS_LEFT_TO_RIGHT -<item> GTK_PROGRESS_RIGHT_TO_LEFT -<item> GTK_PROGRESS_BOTTOM_TO_TOP -<item> GTK_PROGRESS_TOP_TO_BOTTOM -</itemize> - -Cuando se utiliza como una medida de cuanto se ha completado de un -proceso, la barra de progreso puede configurarse para que muestre su -valor de una forma continua o discreta. En modo continuo, la barra de -progreso se actualiza mediante un número discreto de bloques, el -número de bloques también es configurable. - -Se puede configurar el estilo de la barra de progreso utilizando la -siguiente función: - -<tscreen><verb> -void gtk_progress_bar_set_bar_style( GtkProgressBar *pbar, - GtkProgressBarStyle style ); -</verb></tscreen> - -El parámetro <tt/style/ puede tomar uno de los dos valores siguientes: - -<itemize> -<item>GTK_PROGRESS_CONTINUOUS -<item>GTK_PROGRESS_DISCRETE -</itemize> - -El número de bloques se puede establecer utilizando - -<tscreen><verb> -void gtk_progress_bar_set_discrete_blocks( GtkProgressBar *pbar, - guint blocks ); -</verb></tscreen> - -La barra de progreso también se puede utilizar, a parte de para -indicar lo «avanzado» de una tarea, para indicar que hay algún tipo -de actividad. Esto puede ser útil en situaciones donde no se pueda -medir el progreso de una tarea con un rango de valores. Para el modo -actividad, no sirve el estilo de barra que se ha descrito más -arriba. Este modo hay que seleccionarlo utilizando la siguiente -función: - -<tscreen><verb> -void gtk_progress_set_activity_mode( GtkProgress *progress, - guint activity_mode ); -</verb></tscreen> - -El tamaño del paso del indicador de actividad, y el número de bloques -se indican usando las siguientes funciones: - -<tscreen><verb> -void gtk_progress_bar_set_activity_step( GtkProgressBar *pbar, - guint step ); - -void gtk_progress_bar_set_activity_blocks( GtkProgressBar *pbar, - guint blocks ); -</verb></tscreen> - -Cuando estamos en modo continuo, la barra de progreso puede mostrar un -texto configurable dentro la barra misma, utilizando la función -siguiente: - -<tscreen><verb> -void gtk_progress_set_format_string( GtkProgress *progress, - gchar *format); -</verb></tscreen> - -El argumento <tt/format/ es parecido al que se utiliza en una orden -<tt/printf/ de C. Se pueden utilizar las siguientes opciones para el -formateado de la cadena: - -<itemize> -<item> %p - porcentaje -<item> %v - valor -<item> %l - valor inferior del rango -<item> %u - valor superior del rango -</itemize> - -Puede activar o desactivar el texto utilizando: - -<tscreen><verb> -void gtk_progress_set_show_text( GtkProgress *progress, - gint show_text ); -</verb></tscreen> - -El argumento <tt/show_text/ es un valor booleano TRUE/FALSE. La -apariencia del texto puede modificarse utilizando: - -<tscreen><verb> -void gtk_progress_set_text_alignment( GtkProgress *progress, - gfloat x_align, - gfloat y_align ); -</verb></tscreen> - -Los argumentos <tt/x_align/ y <tt/y_align/ toman un valor entre 0.0 y -1.0. Este valor indica la posición de la cadena de texto dentro de la -barra. Si ponemos 0.0 en los dos sitios la cadena de texto aparecerá -en la esquina superior izquierda; un valor de 0.5 (el que se utiliza -por defecto) centra el texto, y un valor de 1.0 coloca el texto en la -esquina inferior derecha. - -Se pueden leer los parámetros actuales del texto de un objeto barra -de progreso utilizando las dos funciones que se muestran a -continuación. La cadena de carácteres devuelta por estas funciones -debe liberarse en la aplicación (utilizando la función -g_free()). Estas funciones devuelven el texto formateado que se -mostrará en la barra. - -<tscreen><verb> -gchar *gtk_progress_get_current_text( GtkProgress *progress ); - -gchar *gtk_progress_get_text_from_value( GtkProgress *progress, - gfloat value ); -</verb></tscreen> - -Hay otra forma de cambiar el rango y el valor de un objeto barra de -progreso utilizando la función: - -<tscreen><verb> -void gtk_progress_configure( GtkProgress *progress, - gfloat value, - gfloat min, - gfloat max ); -</verb></tscreen> - -Esta función proporciona una interfaz sencilla al rango y valor de una -barra de progreso. - -Las funciones restantes se pueden utilizar para obtener y establecer -el valor actual de una barra de progreso utilizando distintos tipos y -formatos para el valor. - -<tscreen><verb> -void gtk_progress_set_percentage( GtkProgress *progress, - gfloat percentage ); - -void gtk_progress_set_value( GtkProgress *progress, - gfloat value ); - -gfloat gtk_progress_get_value( GtkProgress *progress ); - -gfloat gtk_progress_get_current_percentage( GtkProgress *progress ); - -gfloat gtk_progress_get_percentage_from_value( GtkProgress *progress, - gfloat value ); -</verb></tscreen> - -Estas funciones son autoexplicatorias. La última función utiliza el -ajuste de la barra de progreso especificada para calcular el -porcentaje dentro del rango de valores de la barra. - -Las barras de progreso se usan con otras funciones como los tiempos de -espera (<em/timeouts/), sección <ref id="sec_timeouts" -name="Tiempos de espera, E/S (I/O) y funciones ociosas (idle)">) para -crear la ilusión de la multitarea. Todas usan la función -gtk_progress_bar_update de la misma manera. - -Estudiemos un ejemplo de barras de progreso actualizada usando -tiempos de espera. También se muestra como se debe reestablecer una -barra. - -<tscreen><verb> -/* comienzo del programa-ejemplo progressbar.c */ - -#include <gtk/gtk.h> - -#include <gtk/gtk.h> - -typedef struct _ProgressData { - GtkWidget *ventana; - GtkWidget *pbar; - int timer; -} ProgressData; - -/* Actualiza el valor de la barra de progreso para que - * podamos ver algún movimiento */ -gint progress_timeout( gpointer data ) -{ - gfloat new_val; - GtkAdjustment *adj; - - /* Calcula el valor de la barra de progreso utilizando - * el rango de valores establecido en el ajuste de la - * barra */ - - new_val = gtk_progress_get_value( GTK_PROGRESS(data) ) + 1; - - adj = GTK_PROGRESS (data)->adjustment; - if (new_val > adj->upper) - new_val = adj->lower; - - /* Establece el nuevo valor */ - - gtk_progress_set_value (GTK_PROGRESS (data), new_val); - - /* Como esta es una función de espera, devolvemos TRUE - * para que continue siendo llamada */ - - return(TRUE); -} - -/* Función de llamada que activa/desactiva el texto de dentro - * de la barra de progreso */ -void toggle_show_text( GtkWidget *widget, - ProgressData *pdata ) -{ - gtk_progress_set_show_text (GTK_PROGRESS (pdata->pbar), - GTK_TOGGLE_BUTTON (widget)->active); -} - -/* Función de llamada que activa/desactiva el modo actividad - * de la barra de progreso */ -void toggle_activity_mode( GtkWidget *widget, - ProgressData *pdata ) -{ - gtk_progress_set_activity_mode (GTK_PROGRESS (pdata->pbar), - GTK_TOGGLE_BUTTON (widget)->active); -} - -/* Función de llamada que activa/desactiva el modo continuo - * de la barra de progreso */ -void set_continuous_mode( GtkWidget *widget, - ProgressData *pdata ) -{ - gtk_progress_bar_set_bar_style (GTK_PROGRESS_BAR (pdata->pbar), - GTK_PROGRESS_CONTINUOUS); -} - -/* Función de llamada que activa/desactiva el modo discreto - * de la barra de progreso */ -void set_discrete_mode( GtkWidget *widget, - ProgressData *pdata ) -{ - gtk_progress_bar_set_bar_style (GTK_PROGRESS_BAR (pdata->pbar), - GTK_PROGRESS_DISCRETE); -} - -/* Libera la memoria y elimina el temporizador */ -void destroy_progress( GtkWidget *widget, - ProgressData *pdata) -{ - gtk_timeout_remove (pdata->timer); - pdata->timer = 0; - pdata->ventana = NULL; - g_free(pdata); - gtk_main_quit(); -} - -int main( int argc, - char *argv[]) -{ - ProgressData *pdata; - GtkWidget *align; - GtkWidget *separator; - GtkWidget *table; - GtkAdjustment *adj; - GtkWidget *boton; - GtkWidget *check; - GtkWidget *vbox; - - gtk_init (&argc, &argv); - - /* Reserva memoria para los datos que se le pasan a las funciones - * de llamada */ - pdata = g_malloc( sizeof(ProgressData) ); - - pdata->ventana = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_policy (GTK_WINDOW (pdata->ventana), FALSE, FALSE, TRUE); - - gtk_signal_connect (GTK_OBJECT (pdata->ventana), "destroy", - GTK_SIGNAL_FUNC (destroy_progress), - pdata); - gtk_window_set_title (GTK_WINDOW (pdata->ventana), "GtkProgressBar"); - gtk_container_set_border_width (GTK_CONTAINER (pdata->ventana), 0); - - vbox = gtk_vbox_new (FALSE, 5); - gtk_container_set_border_width (GTK_CONTAINER (vbox), 10); - gtk_container_add (GTK_CONTAINER (pdata->ventana), vbox); - gtk_widget_show(vbox); - - /* Crea un objeto de alineamiento centrado */ - align = gtk_alignment_new (0.5, 0.5, 0, 0); - gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, FALSE, 5); - gtk_widget_show(align); - - /* Crea un objeto GtkAdjusment para albergar el rango de la barra - * de progreso */ - adj = (GtkAdjustment *) gtk_adjustment_new (0, 1, 150, 0, 0, 0); - - /* Crea la GtkProgressBar utilizando el ajuste */ - pdata->pbar = gtk_progress_bar_new_with_adjustment (adj); - - /* Establece el formato de la cadena de texto que puede mostrarse - * en la barra de progreso: - * %p - porcentaje - * %v - valor - * %l - valor inferior del rango - * %u - valor superior del rango */ - gtk_progress_set_format_string (GTK_PROGRESS (pdata->pbar), - "%v from [%l-%u] (=%p%%)"); - gtk_container_add (GTK_CONTAINER (align), pdata->pbar); - gtk_widget_show(pdata->pbar); - - /* Añade un temporizador para la actualización del valor de la - * barra de progreso */ - pdata->timer = gtk_timeout_add (100, progress_timeout, pdata->pbar); - - separator = gtk_hseparator_new (); - gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0); - gtk_widget_show(separator); - - /* filas, columnas, homogéneo */ - table = gtk_table_new (2, 3, FALSE); - gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0); - gtk_widget_show(table); - - /* Añade un botón de comprobación para seleccionar si se debe - * mostrar el texto dentro de la barra */ - check = gtk_check_button_new_with_label ("Show text"); - gtk_table_attach (GTK_TABLE (table), check, 0, 1, 0, 1, - GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, - 5, 5); - gtk_signal_connect (GTK_OBJECT (check), "clicked", - GTK_SIGNAL_FUNC (toggle_show_text), - pdata); - gtk_widget_show(check); - - /* Añade un botón de comprobación para activar/desactivar el modo - * actividad */ - check = gtk_check_button_new_with_label ("Activity mode"); - gtk_table_attach (GTK_TABLE (table), check, 0, 1, 1, 2, - GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, - 5, 5); - gtk_signal_connect (GTK_OBJECT (check), "clicked", - GTK_SIGNAL_FUNC (toggle_activity_mode), - pdata); - gtk_widget_show(check); - - separator = gtk_vseparator_new (); - gtk_table_attach (GTK_TABLE (table), separator, 1, 2, 0, 2, - GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, - 5, 5); - gtk_widget_show(separator); - - /* Añade un botón circular para seleccionar el modo continuo */ - boton = gtk_radio_button_new_with_label (NULL, "Continuous"); - gtk_table_attach (GTK_TABLE (table), boton, 2, 3, 0, 1, - GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, - 5, 5); - gtk_signal_connect (GTK_OBJECT (boton), "clicked", - GTK_SIGNAL_FUNC (set_continuous_mode), - pdata); - gtk_widget_show (boton); - - /* Añade un botón circular para seleccionar el modo discreto */ - boton = gtk_radio_button_new_with_label( - gtk_radio_button_group (GTK_RADIO_BUTTON (boton)), - "Discrete"); - gtk_table_attach (GTK_TABLE (table), boton, 2, 3, 1, 2, - GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, - 5, 5); - gtk_signal_connect (GTK_OBJECT (boton), "clicked", - GTK_SIGNAL_FUNC (set_discrete_mode), - pdata); - gtk_widget_show (boton); - - separator = gtk_hseparator_new (); - gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0); - gtk_widget_show(separator); - - /* Añade un botón para salir del programa */ - boton = gtk_button_new_with_label ("close"); - gtk_signal_connect_object (GTK_OBJECT (boton), "clicked", - (GtkSignalFunc) gtk_widget_destroy, - GTK_OBJECT (pdata->ventana)); - gtk_box_pack_start (GTK_BOX (vbox), boton, FALSE, FALSE, 0); - - /* Esto hace que este botón sea el botón pueda utilizarse por - * defecto defecto. */ - GTK_WIDGET_SET_FLAGS (boton, GTK_CAN_DEFAULT); - - /* Esto marca este botón para que sea el botón por - * defecto. Simplemente utilizando la tecla "Intro" haremos que se - * active este botón. */ - gtk_widget_grab_default (boton); - gtk_widget_show(boton); - - gtk_widget_show (pdata->ventana); - - gtk_main (); - - return(0); -} -/* final del ejemplo */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Cuadros de diálogo -<p> -El <em/widget/ del cuadro de diálogo es bastante simple, sólo es una -ventana con algunas cosas ya preempaquetadas. Su estructura es la -siguiente: - -<tscreen><verb> -struct GtkDialog -{ - GtkWindow ventana; - - GtkWidget *vbox; - GtkWidget *action_area; -}; -</verb></tscreen> - -Simplemente se crea una ventana en la cual se empaqueta una vbox, un -separador y una hbox llamada «action_area». - -Este tipo de <em/widgets/ pueden ser usados como mensages <em/pop-up/ -(pequeñas ventanas con texto en su interior que aparecen cuando el -usuario hace algo y queremos informarle de alguna cosa) y otras cosas -parecidas. Su manejo desde el punto de vista del programador -es bastante fácil, sólo hay que usar una función: - -<tscreen><verb> -GtkWidget *gtk_dialog_new( void ); -</verb></tscreen> - -Para crear un nuevo cuadro de diálogo hay que llamar a: - -<tscreen><verb> -GtkWidget *ventana; -ventana = gtk_dialog_new (); -</verb></tscreen> - -Una vez que el cuadro ha sido creado sólo hay que usarlo. Por -ejemplo para empaquetar un botón en la action_area escribiríamos -algo así: - -<tscreen><verb> -boton = ... -gtk_box_pack_start (GTK_BOX (GTK_DIALOG (ventana)->action_area), boton, - TRUE, TRUE, 0); -gtk_widget_show (boton); -</verb></tscreen> - -Otra cosa que nos puede interesar es empaquetar una etiqueta en la -vbox: - -<tscreen><verb> -etiqueta = gtk_label_new ("Dialogs are groovy"); -gtk_box_pack_start (GTK_BOX (GTK_DIALOG (ventana)->vbox), etiqueta, TRUE, - TRUE, 0); -gtk_widget_show (etiqueta); -</verb></tscreen> - -Otros ejemplo posible es poner dos botones en el action_area (uno -para cancelar y el otro para permitir algo) junto con una etiqueta en -la vbox el usuario puede seleccionar lo que quiera. - -Si se precisa algo más complejo siempre se puede empaquetar otro -<em/widget/ en cualquiera de las cajas (p.j. una tabla en una vbox). - -<!-- ----------------------------------------------------------------- --> -<sect1> <em/Pixmaps/ <label id="sec_Pixmaps"> -<p> -Los <em/pixmaps/ son estructuras de datos que contienen dibujos. Estos -pueden ser usados en diferentes lugares, pero los iconos y los -cursores son los más comunes. - -Un <em/bitmap/ es un <em/pixmap/ que sólo tiene dos colores, y hay -unas cuantas rutinas especiales para controlar este caso particular. - -Para comprender los <em/pixmaps/, puede ayudar entender como funciona -X-windows. Bajo X-windows, las aplicaciones no tienen porque estar -ejecutándose en el ordenador que está interactuando con el -usuario. Las distintas aplicaciones, llamadas «clientes», comunican -con un programa que muestra los gráficos y que controla el tecledo y -el ratón. Este programa que interactua directamente con el usuario se -llama un «<em/display server/» o «servidor X». Como la -comunicación entre el servidor y el cliente puede llevarse a cabo -mediante una red, es importante mantener alguna información en el -servidor X. Los <em/pixmaps/ por ejemplo, se almacenan en la memoria -del servidor X. Esto significa que una vez que se establecen los -valores del <em/pixmap/, no tienen que estar transmitiéndose por la -red; en su lugar lo único que hay que enviar es una orden del estilo -«mostrar <em/pixmap/ número XYZ aquí». Incluso si no está utilizando -X-windows con GTK, al utilizar construcciones como los <em/pixmaps/ -conseguirá que sus programas funciones de forma aceptable bajo -X-windows. - -Para usar un <em/pixmap/ en GTK primero tiene que construir una -estructura del tipo GdkPixmap usando rutinas de GDK. Los <em/pixmaps/ -se pueden crear usando datos que se encuentren en la memoria o en un -archivo. Veremos con detalle cada una de las dos posibilidades. - -<tscreen><verb> -GdkPixmap *gdk_bitmap_create_from_data( GdkWindow *ventana, - gchar *data, - gint width, - gint height ); -</verb></tscreen> - -Esta rutina se utiliza para crear un <em/bitmap/ a partir de datos -almacenados en la memoria. Cada bit de información indica si el -<em/pixel/ luce o no. Tanto la altura como la anchura estan expresadas -en <em/pixels/. El puntero del tipo GdkWindow indica la ventana en -cuestión, ya que los <em/pixmaps/ sólo tienen sentido dentro de -la pantalla en la que van a ser mostrados. - -<tscreen><verb> -GdkPixmap *gdk_pixmap_create_from_data( GdkWindow *ventana, - gchar *data, - gint width, - gint height, - gint depth, - GdkColor *fg, - GdkColor *bg ); -</verb></tscreen> - -Con esto creamos un <em/pixmap/ con la profundidad (número de -colores) especificada en los datos del <em/bitmap/. Los valores -<tt/fg/ y <tt/bg/ son los colores del frente y del fondo -respectivamente. - -<tscreen><verb> -GdkPixmap *gdk_pixmap_create_from_xpm( GdkWindow *ventana, - GdkBitmap **mask, - GdkColor *transparent_color, - const gchar *filename ); -</verb></tscreen> - -El formato XPM es una representacion de los <em/pixmaps/ para el -sistema X Window. Es bastante popular y existen muchos programas para -crear imágenes en este formato. El archivo especificado mediante -<tt/filename/ debe contener una imagen en ese formato para que sea -cargada en la estructura. La máscara especifica que bits son -opacos. Todos los demás bits se colorean usando el color -especificado en <tt/transparent_color/. Más adelante veremos un -ejemplo. - -<tscreen><verb> -GdkPixmap *gdk_pixmap_create_from_xpm_d( GdkWindow *ventana, - GdkBitmap **mask, - GdkColor *transparent_color, - gchar **data ); -</verb></tscreen> - -Se pueden incorporar imágenes pequeñas dentro de un programa en -formato XPM. Un <em/pixmap/ se crea usando esta información, en -lugar de leerla de un archivo. Un ejemplo sería: - -<tscreen><verb> -/* 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. ", -" ......... ", -" ", -" "}; -</verb></tscreen> - -Cuando hayamos acabado de usar un <em/pixmap/ y no lo vayamos a usar -durante un tiempo suele ser conveniente liberar el recurso mediante -g_object_unref(). (Los <em/pixmaps/ deben ser considerados recursos -preciosos). - -Una vez que hemos creado el <em/pixmap/ lo podemos mostrar como un -<em/widget/ GTK. Primero tenemos que crear un <em/widget pixmap/ que -contenga un <em/pixmap/ GDK. Esto se hace usando: - -<tscreen><verb> -GtkWidget *gtk_pixmap_new( GdkPixmap *pixmap, - GdkBitmap *mask ); -</verb></tscreen> - -Las otras funciones del <em/widget pixmap/ son: - -<tscreen><verb> -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); -</verb></tscreen> - -La función gtk_pixmap_set se usa para cambiar los datos del -<em/pixmap/ que el <em/widget/ está manejando en ese -momento. <tt/val/ es el <em/pixmap/ creado usando GDK. - -El ejemplo siguiente usa un <em/pixmap/ en un botón: - -<tscreen><verb> -/* comienzo del ejemplo pixmap.c */ - -#include <gtk/gtk.h> - - -/* Datos en formato XPM del icono de apertura de archivo */ -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. ", -" ......... ", -" ", -" "}; - -/* Cuando se llama a esta función (usando signal delete_event) se - * termina la aplicación*/ - -void close_application( GtkWidget *widget, GdkEvent *event, gpointer data ) { - gtk_main_quit(); -} - - -/* Al presionar el botón aparece el mensaje */ -void button_clicked( GtkWidget *widget, gpointer data ) { - printf( "botón pulsado\n" ); -} - -int main( int argc, char *argv[] ) -{ - - GtkWidget *ventana, *pixmapwid, *boton; - GdkPixmap *pixmap; - GdkBitmap *mask; - GtkStyle *style; - - /* Creamos la ventana principal y relacionamos la señal - * delete_event con acabar el programa.*/ - gtk_init( &argc, &argv ); - ventana = gtk_window_new( GTK_WINDOW_TOPLEVEL ); - gtk_signal_connect( GTK_OBJECT (ventana), "delete_event", - GTK_SIGNAL_FUNC (close_application), NULL ); - gtk_container_border_width( GTK_CONTAINER (ventana), 10 ); - gtk_widget_show( ventana ); - - /* Ahora para el pixmap de gdk */ - style = gtk_widget_get_style( ventana ); - pixmap = gdk_pixmap_create_from_xpm_d( ventana->window, &mask, - &style->bg[GTK_STATE_NORMAL], - (gchar **)xpm_data ); - - /* Un pixmap widget que contendrá al pixmap */ - pixmapwid = gtk_pixmap_new( pixmap, mask ); - gtk_widget_show( pixmapwid ); - - /* Un botón para contener al pixmap */ - boton = gtk_button_new(); - gtk_container_add( GTK_CONTAINER(boton), pixmapwid ); - gtk_container_add( GTK_CONTAINER(ventana), boton ); - gtk_widget_show( boton ); - - gtk_signal_connect( GTK_OBJECT(boton), "clicked", - GTK_SIGNAL_FUNC(button_clicked), NULL ); - - /* mostramos la ventana */ - gtk_main (); - - return 0; -} -/* final del ejemplo */ -</verb></tscreen> - -Para cargar un archivo llamado icon0.xpm con la información XPM (que -se encuentra en en directorio actual) habríamos usado: - -<tscreen><verb> - /* cargar un pixmap desde un fichero */ - pixmap = gdk_pixmap_create_from_xpm( ventana->window, &mask, - &style->bg[GTK_STATE_NORMAL], - "./icon0.xpm" ); - pixmapwid = gtk_pixmap_new( pixmap, mask ); - gtk_widget_show( pixmapwid ); - gtk_container_add( GTK_CONTAINER(ventana), pixmapwid ); -</verb></tscreen> - -Una desventaja de los <em/pixmaps/ es que la imagen mostrada siempre -es rectangular (independientemente de como sea la imagen en sí). Si -queremos usar imágenes con otras formas debemos usar ventanas con -forma (<em/shaped windows/). - -Este tipo de ventanas son pixmaps en los que el fondo es -transparente. Así cuando la imagen del fondo tiene muchos colores -no los sobreescribimos con el borde de nuestro icono. El ejemplo -siguiente muestra la imagen de una carretilla en el escritorio. - -<tscreen><verb> -/* comienzo del ejemplo carretilla 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 ", -" ", -" "}; - - - -void close_application( GtkWidget *widget, GdkEvent *event, gpointer data ) { - gtk_main_quit(); -} - -int main (int argc, char *argv[]) -{ - - GtkWidget *ventana, *pixmap, *fixed; - GdkPixmap *gdk_pixmap; - GdkBitmap *mask; - GtkStyle *style; - GdkGC *gc; - - /* Creamos la ventana principal y relacionamos la señal - * delete_event para terminar la aplicación. Conviene destacar - * que la ventana no tendrá título puesto que es popup.*/ - gtk_init (&argc, &argv); - ventana = gtk_window_new( GTK_WINDOW_POPUP ); - gtk_signal_connect (GTK_OBJECT (ventana), "delete_event", - GTK_SIGNAL_FUNC (close_application), NULL); - gtk_widget_show (ventana); - - style = gtk_widget_get_default_style(); - gc = style->black_gc; - gdk_pixmap = gdk_pixmap_create_from_xpm_d( ventana->window, &mask, - &style->bg[GTK_STATE_NORMAL], - WheelbarrowFull_xpm ); - pixmap = gtk_pixmap_new( gdk_pixmap, mask ); - gtk_widget_show( pixmap ); - - - 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(ventana), fixed ); - gtk_widget_show( fixed ); - - /* Con esto cubrimos todo menos la imagen */ - gtk_widget_shape_combine_mask( ventana, mask, 0, 0 ); - - /* mostramos la ventana */ - gtk_widget_set_uposition( ventana, 20, 400 ); - gtk_widget_show( ventana ); - gtk_main (); - - return 0; -} -/* final del ejemplo */ -</verb></tscreen> - -Para que la carretilla sea más realista podríamos relacionar la -pulsación del botón con que haga algo. Con las líneas -siguientes la pulsación del botón hace que se acabe el programa. - -<tscreen><verb> -gtk_widget_set_events( ventana, - gtk_widget_get_events( ventana ) | - GDK_BUTTON_PRESS_MASK ); - -gtk_signal_connect( GTK_OBJECT(ventana), "button_press_event", - GTK_SIGNAL_FUNC(close_application), NULL ); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Reglas -<p> - -Las reglas son usadas para indicar la posición del puntero del -ratón en una ventana dada. Una ventana puede tener una regla -vertical a lo largo de su alto y una horizontal a lo largo de su -ancho. Un pequeño indicador triangular muestra la relación entre -el puntero del ratón y la regla. - -Las reglas (horizontales y verticales) se crean usando: - -<tscreen><verb> -GtkWidget *gtk_hruler_new( void ); /* horizontal */ -GtkWidget *gtk_vruler_new( void ); /* vertical */ -</verb></tscreen> - -Las unidades de la regla pueden ser pixels, pulgadas o centímetros -(GKD_PIXELS, GDK_INCHES, GDK_CENTIMETRES). Esto se hace usando: - -<tscreen><verb> -void gtk_ruler_set_metric( GtkRuler *ruler, - GtkMetricType metric ); -</verb></tscreen> - -El valor por defecto es GTK_PIXELS. - -<tscreen><verb> -gtk_ruler_set_metric( GTK_RULER(ruler), GTK_PIXELS ); -</verb></tscreen> - -Otra característica importante de las reglas es cómo mostrar las -unidades de escala y la posicion inicial dónde se situa el indicador. -Todo esto se consigue mediante: - -<tscreen><verb> -void gtk_ruler_set_range( GtkRuler *ruler, - gfloat lower, - gfloat upper, - gfloat posicion, - gfloat max_size ); -</verb></tscreen> - -Los argumentos <tt/lower/ (valor más bajo) y <tt/upper/ (más -alto) delimitan la extensión de la regla. El argumento -<tt/max_size/ es el número más alto que será mostrado. Como -es lógico <tt/posicion/ define la posición inicial del indicador -dentro de la regla. - -Una regla vertical puede puede llegar a ser de 800 pixels: - -<tscreen><verb> -gtk_ruler_set_range( GTK_RULER(vruler), 0, 800, 0, 800); -</verb></tscreen> - -Las marcas dentro de la regla oscilarán entre 0 y 800 con una -periodicidad de 100. Si queremos que varíe entre 7 y 16 -debemos usar: - -<tscreen><verb> -gtk_ruler_set_range( GTK_RULER(vruler), 7, 16, 0, 20); -</verb></tscreen> - -El indicador de la regla es un pequeño triángulo que señala la -posición del puntero con relación a la regla. Si la regla debe -seguir al puntero del ratón la señal motion_notify_event debe estar -conectada con el motion_notify_event de la regla. Para seguir todos -los movimientos dentro de una ventana conviene usar: - -<tscreen><verb> -#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) ); -</verb></tscreen> - -El siguiente ejemplo crea una zona de dibujo con una regla horizontal -y otra vertical. El tamaño de la zona de dibujo es de 600 x 400 -<em/pixels/. La regla horizontal oscila entre 7 y 13 con marcas cada -100 <em/pixels/, mientras que la vertical va desde 0 a 400 con -separaciones cada 100. La zona de dibujo y las reglas se sitúan -usando una tabla. - -<tscreen><verb> -/* comienzo del ejemplo 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 - -/* Esta rutina toma el control cuando se pulsa el botón close - */ -void close_application( GtkWidget *widget, GdkEvent *event, gpointer data ) { - gtk_main_quit(); -} - -int main( int argc, char *argv[] ) { - GtkWidget *ventana, *table, *area, *hrule, *vrule; - - - gtk_init( &argc, &argv ); - - ventana = gtk_window_new( GTK_WINDOW_TOPLEVEL ); - gtk_signal_connect (GTK_OBJECT (ventana), "delete_event", - GTK_SIGNAL_FUNC( close_application ), NULL); - gtk_container_border_width (GTK_CONTAINER (ventana), 10); - - /* creación de la tabla donde pondremos las reglas y la zona de - * dibujo */ - table = gtk_table_new( 3, 2, FALSE ); - gtk_container_add( GTK_CONTAINER(ventana), 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 ); - - /* La regla horizontal está arriba. Cuando el ratón se mueve - * a lo largo de la zona de dibujo el controlador de eventos de la - * regla recibe 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 ); - - - /* la zona de dibujo el controlador de eventos de la regla recibe - * 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 ); - - - /* mostramos todo */ - gtk_widget_show( area ); - gtk_widget_show( hrule ); - gtk_widget_show( vrule ); - gtk_widget_show( table ); - gtk_widget_show( ventana ); - gtk_main(); - - return 0; -} -/* final del ejemplo */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Barras de estado -<p> -Las barras de estado son widgets usados para mostrar un mensaje. Todo -aquello que haya sido mostrado se guarda en una pila, con lo que es -muy fácil repetir el último mensaje. - -Para permitir que diferentes partes del programa usen la misma barra -de estado éstas usan Identificadores por Contexto (Context -Identifiers) para identificar a los `usuarios'. El mensaje que está -en lo alto de la pila será el siguiente en mostrarse, sin importar -el contexto en el que se esté. Los mensajes se almacenan en el -orden el último en entrar es el primero en salir, y el -Identificador por Contexto no influye en este orden. - -Las barras de estado se crean con una llamada a: - -<tscreen><verb> -GtkWidget *gtk_statusbar_new( void ); -</verb></tscreen> - -Se pide un nuevo Identificador por Contexto con una pequeña -descripción textual del contexto y una llamada a la función: - -<tscreen><verb> -guint gtk_statusbar_get_context_id( GtkStatusbar *statusbar, - const gchar *context_description ); -</verb></tscreen> - -Hay tres funciones que pueden manipular las barras de estado: - -<tscreen><verb> -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 ); -</verb></tscreen> - -La primera, gtk_statusbar_push, se utiliza para añadir un nuevo -mensaje a la barra de estado. Devuelve un Identificador de Mensaje, -que podemos pasarle más tarde a la función gtk_statusbar_remove para -eliminar el mensaje con los Identificadores de Contexto y de Mensaje -que hay en la pila de barras de estado. - -La función gtk_statusbar_pop elimina el mensaje que se encuentra -más alto en pila y que contiene el Identificador por Contexto -especificado. - -El ejemplo siguiente crea una barra de estado y dos botones, uno para -meter un elemento en la barra y el otro para sacar el último elemento -introducido. - -<tscreen><verb> -/* Principio del ejemplo de barras de estado 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), GPOINTER_TO_INT(data), buff); - - return; -} - -void pop_item (GtkWidget *widget, gpointer data) -{ - gtk_statusbar_pop( GTK_STATUSBAR(status_bar), GPOINTER_TO_INT(data) ); - return; -} - -int main (int argc, char *argv[]) -{ - - GtkWidget *ventana; - GtkWidget *vbox; - GtkWidget *boton; - - int context_id; - - gtk_init (&argc, &argv); - - /* crear una nueva ventana */ - ventana = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_widget_set_usize( GTK_WIDGET (ventana), 200, 100); - gtk_window_set_title(GTK_WINDOW (ventana), "GTK Statusbar Example"); - gtk_signal_connect(GTK_OBJECT (ventana), "delete_event", - (GtkSignalFunc) gtk_exit, NULL); - - vbox = gtk_vbox_new(FALSE, 1); - gtk_container_add(GTK_CONTAINER(ventana), 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"); - - boton = gtk_button_new_with_label("push item"); - gtk_signal_connect(GTK_OBJECT(boton), "clicked", - GTK_SIGNAL_FUNC (push_item), &context_id); - gtk_box_pack_start(GTK_BOX(vbox), boton, TRUE, TRUE, 2); - gtk_widget_show(boton); - - boton = gtk_button_new_with_label("pop last item"); - gtk_signal_connect(GTK_OBJECT(boton), "clicked", - GTK_SIGNAL_FUNC (pop_item), &context_id); - gtk_box_pack_start(GTK_BOX(vbox), boton, TRUE, TRUE, 2); - gtk_widget_show(boton); - - /* siempre mostramos la ventana en el último paso para que todo se - * dibuje en la pantalla de un golpe. */ - gtk_widget_show(ventana); - - gtk_main (); - - return 0; -} -/* Final del ejemplo */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Entrada de texto -<p> -El <em/widget/ Entry permite mostrar e introducir texto en una línea -de un cuadro de diálogo. El texto se puede poner con llamadas a funciones -que permiten reemplazar, preañadir o añadir el texto al contenido -actual del <em/widget/ Entry. - -Hay dos funciones para crear un <em/widget/ Entry: - -<tscreen><verb> -GtkWidget *gtk_entry_new( void ); - -GtkWidget *gtk_entry_new_with_max_length( guint16 max ); -</verb></tscreen> - -La primera sirve para crear un nuevo <em/widget/ Entry, mientras que la -segunda crea el <em/widget/ y además establece un límite en la longitud -del texto que irá en el mismo. - -hay varias funciones que sirven para alterar el que texto que se está -en el <em/widget/ Entry. - -<tscreen><verb> -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 ); -</verb></tscreen> - -La función <tt/gtk_entry_set_text/ cambia el contenido actual del -<em/widget/ Entry. Las funciones <tt/gtk_entry_append_text/ y -<tt/gtk_entry_prepend_text/ permiten añadir o preañadir texto. - -Las función siguientes permiten decir donde poner el punto de inserción. - -<tscreen><verb> -void gtk_entry_set_position( GtkEntry *entry, - gint posicion ); -</verb></tscreen> - -Se pueden obtener los contenidos del <em/widget/ llamando a la función -que se describe a continuación. Obtener los contenidos del <em/widget/ -puede ser útil en las funciones de llamada descritas más adelante. - -<tscreen><verb> -gchar *gtk_entry_get_text( GtkEntry *entry ); -</verb></tscreen> - -Si quiere impedir que alguien cambie el contenido del <em/widget/ escribiendo -en él, utilice la función - -<tscreen><verb> -void gtk_entry_set_editable( GtkEntry *entry, - gboolean editable ); -</verb></tscreen> - -Esta función permite camiar el estado de edición de un <em/widget/ Entry, -siendo el argumento <tt/editable/ TRUE o FALSE. - -Si estamos utilizando el <em/widget/ Entry en un sitio donde no queremos -que el texto que se introduce sea visible, como por ejemplo cuando estamos -introduciendo una clave, podemos utilizar la función siguiente, que también -admite como argumento una bandera booleana. - -<tscreen><verb> -void gtk_entry_set_visibility( GtkEntry *entry, - gboolean visible ); -</verb></tscreen> - -Se puede seleccionar una región del texto utilizando la siguiente función. -Esta función se puede utilizar después de poner algún texto por defecto en -el <em/widget/, haciéndole fácil al usuario eliminar este texto. - -<tscreen><verb> -void gtk_entry_select_region( GtkEntry *entry, - gint start, - gint end ); -</verb></tscreen> - -Si queremos saber el momento en el que el usuario ha introducido el texto, -podemos conectar con las señales <tt/activate/ o <tt/changed/. <tt/activate/ -se activa cuando el usuario aprieta la tecla enter en el <em/widget/. -<tt/changed/ se activa cuando cambia algo del texto, p.e. cuando se introduce -o se elimina algún carácter. - -<tscreen><verb> -/* Principio del ejemplo entry 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 *ventana; - GtkWidget *vbox, *hbox; - GtkWidget *entry; - GtkWidget *boton; - GtkWidget *check; - - gtk_init (&argc, &argv); - - /* crear una nueva ventana */ - ventana = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_widget_set_usize( GTK_WIDGET (ventana), 200, 100); - gtk_window_set_title(GTK_WINDOW (ventana), "GTK Entry"); - gtk_signal_connect(GTK_OBJECT (ventana), "delete_event", - (GtkSignalFunc) gtk_exit, NULL); - - vbox = gtk_vbox_new (FALSE, 0); - gtk_container_add (GTK_CONTAINER (ventana), 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); - - boton = gtk_button_new_with_label ("Close"); - gtk_signal_connect_object (GTK_OBJECT (boton), "clicked", - GTK_SIGNAL_FUNC(gtk_exit), - GTK_OBJECT (ventana)); - gtk_box_pack_start (GTK_BOX (vbox), boton, TRUE, TRUE, 0); - GTK_WIDGET_SET_FLAGS (boton, GTK_CAN_DEFAULT); - gtk_widget_grab_default (boton); - gtk_widget_show (boton); - - gtk_widget_show(ventana); - - gtk_main(); - return(0); -} -/* fin del ejemplo */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Botones <em/spin/ -<p> -El <em/widget/ botón <em/spin/ se utiliza normalmente para permitir -que el usuario elija un valor de un rango de valores. Consiste en una -caja para la entrada de texto con una flecha para arriba y otra para -abajo justo al lado de la caja. Si utilizamos alguna de las flechas -haremos que el valor suba o baje dentro del rango de los valores -posibles. También podemos introducir directamente un valor específico -(utilizando la caja de texto). - -El <em/widget/ botón <em/spin/ permite tener valores con un número de -cifras decimales (o sin cifras decimales) y la posibilidad de -incrementarlo/decrementarlo en pasos configurables. La acción de -matener pulsado uno de los botones puede resultar (es opcional) en una -aceleración del cambio en el valor de acuerdo con el tiempo que se -mantenga pulsado. - -El botón <em/spin/ utiliza un objeto <ref id="sec_Adjustment" -name="Ajuste"> para conservar la información referente al rango de -valores que puede tomar el botón <em/spin/. Esto hace que el -<em/widget/ botón <em/spin/ sea muy poderoso. - -Recuerde que un <em/widget/ ajuste puede crearse con la siguiente -función, que ilustra la información que se guarda: - -<tscreen><verb> -GtkObject *gtk_adjustment_new( gfloat valor, - gfloat inferior, - gfloat superior, - gfloat paso, - gfloat incremento_pagina, - gfloat tamano_pagina ); -</verb></tscreen> - -Estos atributos de un ajuste se utilizan en un botón <em/spin/ de la -forma siguiente: - -<itemize> -<item> <tt/valor/: valor inicial del botón <em/spin/ -<item> <tt/inferior/: valor inferior del rango -<item> <tt/superior/: valor superior del rango -<item> <tt/paso/: valor a incrementar/decrementar cuando pulsemos el -botón 1 en una flecha -<item> <tt/incremento_pagina/: valor a incrementar/decrementar cuando -pulsemos el botón 2 en una flecha -<item> <tt/tamano_pagina/: no se utiliza -</itemize> - -Además, se puede utilizar el botón 3 para saltar directamente a los -valores <tt/superior/ o <tt/inferior/ cuando se pulsa en una de las -flechas. Veamos como crear un botón <em/spin/: - -<tscreen><verb> -GtkWidget *gtk_spin_button_new( GtkAdjustment *ajuste, - gfloat aceleracion, - guint digitos ); -</verb></tscreen> - -El argumento <tt/aceleracion/ toma un valor entre 0.0 y 1.0 e indica -la aceleración que tendrá el botón <em/spin/. El argumento -<tt/digitos/ especifica el número de cifras decimales con que se -mostrará el valor. - -Se puede reconfigurar un botón <em/spin/ después de su creación -utilizando la función: - -<tscreen><verb> -void gtk_spin_button_configure( GtkSpinButton *boton_spin, - GtkAdjustment *ajuste, - gfloat aceleracion, - guint digitos ); -</verb></tscreen> - -El argumento <tt/boton_spin/ especifica el botón <em/spin/ que va a -reconfigurarse. El resto de argumentos son los que acabamos de -explicar. - -Podemos establecer y obtener el ajuste utilizando las dos funciones -siguientes: - -<tscreen><verb> -void gtk_spin_button_set_adjustment( GtkSpinButton *boton_spin, - GtkAdjustment *ajuste ); - -GtkAdjustment *gtk_spin_button_get_adjustment( GtkSpinButton *boton_spin ); -</verb></tscreen> - -El número de cifras decimales también puede alterarse utilizando: - -<tscreen><verb> -void gtk_spin_button_set_digits( GtkSpinButton *boton_spin, - guint digitos) ; -</verb></tscreen> - -El valor que un botón <em/spin/ está mostrando actualmente puede -cambiarse utilizando las siguientes funciones: - -<tscreen><verb> -void gtk_spin_button_set_value( GtkSpinButton *boton_spin, - gfloat valor ); -</verb></tscreen> - -El valor actual de un botón <em/spin/ puede obtenerse como un entero o -como un flotante con las funciones siguientes: - -<tscreen><verb> -gfloat gtk_spin_button_get_value_as_float( GtkSpinButton *boton_spin ); - -gint gtk_spin_button_get_value_as_int( GtkSpinButton *boton_spin ); -</verb></tscreen> - -Si quiere alterar el valor de un <em/spin/ de forma relativa a su -valor actual, puede utilizar la siguiente función: - -<tscreen><verb> -void gtk_spin_button_spin( GtkSpinButton *boton_spin, - GtkSpinType direccion, - gfloat incremento ); -</verb></tscreen> - -El parámetro <tt/direccion/ puede tomar uno de los valores siguientes: - -<itemize> -<item> GTK_SPIN_STEP_FORWARD -<item> GTK_SPIN_STEP_BACKWARD -<item> GTK_SPIN_PAGE_FORWARD -<item> GTK_SPIN_PAGE_BACKWARD -<item> GTK_SPIN_HOME -<item> GTK_SPIN_END -<item> GTK_SPIN_USER_DEFINED -</itemize> - -Trataré de explicar todas las posibilidades que ofrece esta -función. Algunos de los valores que puede utilizar <tt/direccion/ -hacen que se utilicen valores que están almacenados en el objeto -Ajuste que está asociado con el botón <em/spin/. - -GTK_SPIN_STEP_FORWARD y GTK_SPIN_STEP_BACKWARD aumentan o disminuyen -(respectivamente) el valor del botón <em/spin/ por la cantidad -especificada por <tt/incremento/, a menos que <tt/incremento/ sea -igual a 0, en cuyo caso el valor se aumentará o disminuirá por el -valor especificado en <tt/paso/ dentro del Ajuste. - -GTK_SPIN_PAGE_FORWARD y GTK_SPIN_PAGE_BACKWARD sencillamente alteran -el valor del botón <em/spin/ por la cantidad <tt/incremento/. - -GTK_SPIN_HOME hace que el botón <em/spin/ tenga el mismo valor que el -valor inferior del rango Ajuste. - -GTK_SPIN_END hace que el botón <em/spin/ tenga el mismo valor que el -valor superior del rango Ajuste. - -GTK_SPIN_USER_DEFINED cambia el valor del botón <em/spin/ por la -cantidad especificada. - -Ahora vamos a dejar de lado las funciones para establecer y obtener el -rango de los atributos del botón <em/spin/, y vamos a pasar a las -funciones que afectan a la apariencia y al comportamiento del -<em/widget/ botón <em/spin/ en sí mismo. - -La primera de estas funciones se utiliza para restringir el contenido -de la caja de texto de un botón <em/spin/ a un valor numérico. Esto -evita que un usuario introduzca cualquier valor no númerico. - -<tscreen><verb> -void gtk_spin_button_set_numeric( GtkSpinButton *boton_spin, - gboolean numerico ); -</verb></tscreen> - -Puede indicar si un botón <em/spin/ pasará del límite superior al -inferior utilizando la siguiente función: - -<tscreen><verb> -void gtk_spin_button_set_wrap( GtkSpinButton *boton_spin, - gboolean wrap ); -</verb></tscreen> - -Puede hacer que un botón <em/spin/ redondee su valor al <tt/paso/ más -cercano, que se indica cuando creamos el Ajuste que se utiliza con el -botón <em/spin/. Para hacer que redondee tenemos que utilizar la -función siguiente: - -<tscreen><verb> -void gtk_spin_button_set_snap_to_ticks( GtkSpinButton *boton_spin, - gboolean redondear ); -</verb></tscreen> - -Para política de actualización de un botón <em/spin/ puede cambiarse -con la siguiente función: - -<tscreen><verb> -void gtk_spin_button_set_update_policy( GtkSpinButton *boton_spin, - GtkSpinButtonUpdatePolicy politica ); -</verb></tscreen> - -<!-- TODO: find out what this does - TRG --> - -Los valores posibles de <tt/politica/ son o GTK_UPDATE_ALWAYS o -GTK_UPDATE_IF_VALID. - -Estas políticas afectan al comportamiento de un botón <em/spin/ cuando -se lee el texto insertado en la caja de texto y se sincroniza con los -valores del Ajuste. - -En el caso de GTK_UPDATE_IF_VALID el valor de un botón <em/spin/ -cambiará si el texto introducido es un valor numérico contenido dentro -del rango especificado por el Ajuste. En caso contrario el texto -introducido se convierte al valor del botón <em/spin/. - -En caso de utilizar GTK_UPDATE_ALWAYS se ignorarán los errores que -puedan ocurrir en la conversión del texto en un valor numérico. - -El aspecto de los botones utilizados en un botón <em/spin/ pueden -cambiarse utilizando las siguientes funciones: - -<tscreen><verb> -void gtk_spin_button_set_shadow_type( GtkSpinButton *boton_spin, - GtkShadowType tipo_sombra ); -</verb></tscreen> - -Como siempre, el <tt/tipo_sombra/ puede ser uno de los siguientes: - -<itemize> -<item> GTK_SHADOW_IN -<item> GTK_SHADOW_OUT -<item> GTK_SHADOW_ETCHED_IN -<item> GTK_SHADOW_ETCHED_OUT -</itemize> - -Finalmente, puede pedir de forma explícita que un botón <em/spin/ se -actualice a sí mismo: - -<tscreen><verb> -void gtk_spin_button_update( GtkSpinButton *boton_spin ); -</verb></tscreen> - -Es hora de un nuevo ejemplo. - -<tscreen><verb> -/* principio del ejemplo spinbutton spinbutton.c */ - -#include <gtk/gtk.h> - -static GtkWidget *spinner1; - -void toggle_snap( GtkWidget *widget, - GtkSpinButton *spin ) -{ - gtk_spin_button_set_snap_to_ticks (spin, GTK_TOGGLE_BUTTON (widget)->active); -} - -void toggle_numeric( GtkWidget *widget, - GtkSpinButton *spin ) -{ - gtk_spin_button_set_numeric (spin, GTK_TOGGLE_BUTTON (widget)->active); -} - -void change_digits( GtkWidget *widget, - GtkSpinButton *spin ) -{ - gtk_spin_button_set_digits (GTK_SPIN_BUTTON (spinner1), - gtk_spin_button_get_value_as_int (spin)); -} - -void get_value( GtkWidget *widget, - gpointer data ) -{ - gchar buf[32]; - GtkLabel *etiqueta; - GtkSpinButton *spin; - - spin = GTK_SPIN_BUTTON (spinner1); - etiqueta = GTK_LABEL (gtk_object_get_user_data (GTK_OBJECT (widget))); - if (GPOINTER_TO_INT (data) == 1) - sprintf (buf, "%d", gtk_spin_button_get_value_as_int (spin)); - else - sprintf (buf, "%0.*f", spin->digits, - gtk_spin_button_get_value_as_float (spin)); - gtk_label_set_text (etiqueta, buf); -} - - -int main( int argc, - char *argv[] ) -{ - GtkWidget *ventana; - GtkWidget *frame; - GtkWidget *hbox; - GtkWidget *main_vbox; - GtkWidget *vbox; - GtkWidget *vbox2; - GtkWidget *spinner2; - GtkWidget *spinner; - GtkWidget *boton; - GtkWidget *etiqueta; - GtkWidget *val_label; - GtkAdjustment *adj; - - /* Inicializar GTK */ - gtk_init(&argc, &argv); - - ventana = gtk_window_new (GTK_WINDOW_TOPLEVEL); - - gtk_signal_connect (GTK_OBJECT (ventana), "destroy", - GTK_SIGNAL_FUNC (gtk_main_quit), - NULL); - - gtk_window_set_title (GTK_WINDOW (ventana), "Spin Button"); - - main_vbox = gtk_vbox_new (FALSE, 5); - gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 10); - gtk_container_add (GTK_CONTAINER (ventana), main_vbox); - - frame = gtk_frame_new ("Not accelerated"); - gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0); - - vbox = gtk_vbox_new (FALSE, 0); - gtk_container_set_border_width (GTK_CONTAINER (vbox), 5); - gtk_container_add (GTK_CONTAINER (frame), vbox); - - /* spin del día, mes y año */ - - hbox = gtk_hbox_new (FALSE, 0); - gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 5); - - vbox2 = gtk_vbox_new (FALSE, 0); - gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5); - - etiqueta = gtk_label_new ("Day :"); - gtk_misc_set_alignment (GTK_MISC (etiqueta), 0, 0.5); - gtk_box_pack_start (GTK_BOX (vbox2), etiqueta, FALSE, TRUE, 0); - - adj = (GtkAdjustment *) gtk_adjustment_new (1.0, 1.0, 31.0, 1.0, - 5.0, 0.0); - spinner = gtk_spin_button_new (adj, 0, 0); - gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE); - gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON (spinner), - GTK_SHADOW_OUT); - gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0); - - vbox2 = gtk_vbox_new (FALSE, 0); - gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5); - - etiqueta = gtk_label_new ("Month :"); - gtk_misc_set_alignment (GTK_MISC (etiqueta), 0, 0.5); - gtk_box_pack_start (GTK_BOX (vbox2), etiqueta, FALSE, TRUE, 0); - - adj = (GtkAdjustment *) gtk_adjustment_new (1.0, 1.0, 12.0, 1.0, - 5.0, 0.0); - spinner = gtk_spin_button_new (adj, 0, 0); - gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE); - gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON (spinner), - GTK_SHADOW_ETCHED_IN); - gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0); - - vbox2 = gtk_vbox_new (FALSE, 0); - gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5); - - etiqueta = gtk_label_new ("Year :"); - gtk_misc_set_alignment (GTK_MISC (etiqueta), 0, 0.5); - gtk_box_pack_start (GTK_BOX (vbox2), etiqueta, FALSE, TRUE, 0); - - adj = (GtkAdjustment *) gtk_adjustment_new (1998.0, 0.0, 2100.0, - 1.0, 100.0, 0.0); - spinner = gtk_spin_button_new (adj, 0, 0); - gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), FALSE); - gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON (spinner), - GTK_SHADOW_IN); - gtk_widget_set_usize (spinner, 55, 0); - gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0); - - frame = gtk_frame_new ("Accelerated"); - gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0); - - vbox = gtk_vbox_new (FALSE, 0); - gtk_container_set_border_width (GTK_CONTAINER (vbox), 5); - gtk_container_add (GTK_CONTAINER (frame), vbox); - - hbox = gtk_hbox_new (FALSE, 0); - gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5); - - vbox2 = gtk_vbox_new (FALSE, 0); - gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5); - - etiqueta = gtk_label_new ("Value :"); - gtk_misc_set_alignment (GTK_MISC (etiqueta), 0, 0.5); - gtk_box_pack_start (GTK_BOX (vbox2), etiqueta, FALSE, TRUE, 0); - - adj = (GtkAdjustment *) gtk_adjustment_new (0.0, -10000.0, 10000.0, - 0.5, 100.0, 0.0); - spinner1 = gtk_spin_button_new (adj, 1.0, 2); - gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner1), TRUE); - gtk_widget_set_usize (spinner1, 100, 0); - gtk_box_pack_start (GTK_BOX (vbox2), spinner1, FALSE, TRUE, 0); - - vbox2 = gtk_vbox_new (FALSE, 0); - gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5); - - etiqueta = gtk_label_new ("Digits :"); - gtk_misc_set_alignment (GTK_MISC (etiqueta), 0, 0.5); - gtk_box_pack_start (GTK_BOX (vbox2), etiqueta, FALSE, TRUE, 0); - - adj = (GtkAdjustment *) gtk_adjustment_new (2, 1, 5, 1, 1, 0); - spinner2 = gtk_spin_button_new (adj, 0.0, 0); - gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner2), TRUE); - gtk_signal_connect (GTK_OBJECT (adj), "value_changed", - GTK_SIGNAL_FUNC (change_digits), - (gpointer) spinner2); - gtk_box_pack_start (GTK_BOX (vbox2), spinner2, FALSE, TRUE, 0); - - hbox = gtk_hbox_new (FALSE, 0); - gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5); - - boton = gtk_check_button_new_with_label ("Snap to 0.5-ticks"); - gtk_signal_connect (GTK_OBJECT (boton), "clicked", - GTK_SIGNAL_FUNC (toggle_snap), - spinner1); - gtk_box_pack_start (GTK_BOX (vbox), boton, TRUE, TRUE, 0); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (boton), TRUE); - - boton = gtk_check_button_new_with_label ("Numeric only input mode"); - gtk_signal_connect (GTK_OBJECT (boton), "clicked", - GTK_SIGNAL_FUNC (toggle_numeric), - spinner1); - gtk_box_pack_start (GTK_BOX (vbox), boton, TRUE, TRUE, 0); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (boton), TRUE); - - val_label = gtk_label_new (""); - - hbox = gtk_hbox_new (FALSE, 0); - gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5); - boton = gtk_button_new_with_label ("Value as Int"); - gtk_object_set_user_data (GTK_OBJECT (boton), val_label); - gtk_signal_connect (GTK_OBJECT (boton), "clicked", - GTK_SIGNAL_FUNC (get_value), - GINT_TO_POINTER (1)); - gtk_box_pack_start (GTK_BOX (hbox), boton, TRUE, TRUE, 5); - - boton = gtk_button_new_with_label ("Value as Float"); - gtk_object_set_user_data (GTK_OBJECT (boton), val_label); - gtk_signal_connect (GTK_OBJECT (boton), "clicked", - GTK_SIGNAL_FUNC (get_value), - GINT_TO_POINTER (2)); - gtk_box_pack_start (GTK_BOX (hbox), boton, TRUE, TRUE, 5); - - gtk_box_pack_start (GTK_BOX (vbox), val_label, TRUE, TRUE, 0); - gtk_label_set_text (GTK_LABEL (val_label), "0"); - - hbox = gtk_hbox_new (FALSE, 0); - gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, TRUE, 0); - - boton = gtk_button_new_with_label ("Close"); - gtk_signal_connect_object (GTK_OBJECT (boton), "clicked", - GTK_SIGNAL_FUNC (gtk_widget_destroy), - GTK_OBJECT (ventana)); - gtk_box_pack_start (GTK_BOX (hbox), boton, TRUE, TRUE, 5); - - gtk_widget_show_all (ventana); - - /* Entramos dentro del bucle de eventos */ - gtk_main (); - - return(0); -} -/* fin del ejemplo */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Caja combinada (<em/Combo Box/) -<p> -La caja combinada o <em/combo box/ es otro sencillo <em/widget/ -exclusivamente compuesto por otros <em/widgets/. Desde el punto de -vista del usuario, el <em/widget/ consiste en una caja para la -introducción de texto y un menú desplegable desde el que el usuario -puede seleccionar una de un conjunto predefinido de entradas. De forma -alternativa, el usuario puede introducir una opción diferente en la -caja de texto. - -El siguiente extracto de la estructura que define un Combo Box -identifica algunos de sus componentes: - -<tscreen><verb> -struct _GtkCombo { - GtkHBox hbox; - GtkWidget *entry; - GtkWidget *boton; - GtkWidget *popup; - GtkWidget *popwin; - GtkWidget *list; - ... }; -</verb></tscreen> - -Como puede ver, el Combo Box tiene dos partes principales que tiene -que conocer: un <em/widget entry/ y un <em/widget list/ (lista). - -Lo primero, para crear un combo box, utilice: - -<tscreen><verb> -GtkWidget *gtk_combo_new( void ); -</verb></tscreen> - -Ahora, si quiere indicar la cadena que debe aparecer en la sección -entry del combo box, podrá hacerlo manipulando directamente el -<em/widget/ <tt/entry/: - -<tscreen><verb> - gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), "Mi cadena."); -</verb></tscreen> - -Para introducir valores en la lista desplegable, puede utilizar la -función: - -<tscreen><verb> -void gtk_combo_set_popdown_strings( GtkCombo *combo, - GList *cadenas ); -</verb></tscreen> - -Antes de llamar a esta función, tiene que ensamblar una GList con las -cadenas que quiere. GList es una implementación de una lista enlazada -que forma parte de <ref id="sec_glib" name="glib">, una biblioteca -base de GTK. Por el momento, la explicación fea y rápida es que tiene -que crear un puntero GList, hacerlo igual a NULL, y añadirle cadenas -de texto con la función - -<tscreen><verb> -GList *g_list_append( GList *glist, - gpointer datos ); -</verb></tscreen> - -Es importante que inicialice el puntero GList a NULL antes de -utilizarlo. El valor devuelto por la función g_list_append debe -utilizarse como el nuevo puntero a la GList. - -Aquí tenemos un trozo de código típico para crear un conjunto de -opciones: - -<tscreen><verb> - GList *glist=NULL; - - glist = g_list_append(glist, "Cadena 1"); - glist = g_list_append(glist, "Cadena 2"); - glist = g_list_append(glist, "Cadena 3"); - glist = g_list_append(glist, "Cadena 4"); - - gtk_combo_set_popdown_strings( GTK_COMBO(combo), glist) ; -</verb></tscreen> - -A partir de este momento tendrá un combo box completo funcionando. Hay -unos cuantos aspectos de su funcionamiento que puede cambiar. Para -hacerlo tiene las funciones siguientes: - -<tscreen><verb> -void gtk_combo_set_use_arrows( GtkCombo *combo, - gint valor ); - -void gtk_combo_set_use_arrows_always( GtkCombo *combo, - gint valor ); - -void gtk_combo_set_case_sensitive( GtkCombo *combo, - gint valor ); -</verb></tscreen> - -<tt/gtk_combo_set_use_arrows()/ le deja al usuario cambiar el valor -del combo box utilizando las flechas de arriba/abajo. Utilizando estas -teclas no haremos salir la lista, pero se reemplazará el texto actual -del combo box con el siguiente elemento de la lista (superior o -inferior, según la tecla que se pulse). Esto se consigue buscando en -la lista el elemento correspondiente al valor actual del combo box y -seleccionando el anterior o el posterior (según corresponda). -Normalmente en una caja de entrada de texto las flechas se utilizan -para cambiar el foco (ie. el <em/widget/ que recibe la entrada del -teclado), pero en este caso será el TAB quien se ocupe. Cuando el -elemento actual sea el último de la lista y presione la flecha abajo -se cambiará el foco (lo mismo se aplica cuando estamos sobre el primer -elemento y pulsamos la tecla arriba). - -Si el valor actual en la caja de entrada de texto no está en la lista, -entonces se desactiva la función de <tt/gtk_combo_set_use_arrows()/. - -<tt/gtk_combo_set_use_arrows_always()/ igualmente permite la -utilización de las flechas arriba/abajo para cambiar el elemento -seleccionado por el siguiente/anterior de la lista, pero además trata -la lista como si fuese circular (ie. pasa del último al primer -elemento), desactivando completamente la utilidad de las teclas arriba -y abajo para cambiar el foco. - -<tt/gtk_combo_set_case_sensitive()/ cambia entre una búsqueda por la -lista que discrimine entre mayúsculas y minúsculas y una búsqueda que -no discrimine. Se utiliza cuando se quiere que el <em/widget/ combo -complete el valor que se está introduciendo con un valor de la -lista. Dependiendo de esta función, se completará distinguiendo entre -mayúsculas y minúsculas o no. El <em/widget/ combo completará la -entrada actual si el usuario presiona la combinación de teclas MOD-1 y -`Tab'. MOD-1 normalmente es la tecla `Alt'. Hay algunos -administradores de ventanas que también utilizan esta combinación de -teclas, con lo que perderemos su posible utilización por parte de GTK. - -Ahora que tenemos un combo box que actua como queremos que actue, todo -lo que nos queda es saber como hay que hacer para obtener los datos -que nos puede proporcionar. Esto es relativamente sencillo. La mayoría -del tiempo, de lo único que tiene que preocuparse es de obtener datos -de la caja de texto. Podemos acceder a la caja de texto mediante -GTK_ENTRY(GTK_COMBO(combo)->entry). Las dos cosas que son interesantes -hacer con esta caja son: enlazarla con la señal <tt/activate/, que -indica que el usuario ha presionado la tecla «Intro», y leer el -texto. Lo primero podemos hacerlo utilizando algo así: - -<tscreen><verb> - gtk_signal_connect(GTK_OBJECT(GTK_COMB(combo)->entry), "activate", - GTK_SIGNAL_FUNC (mi_funcion_respuesta), mis_datos); -</verb></tscreen> - -Para conseguir el texto que hay en la caja en cualquier momento sólo -tenemos que utilizar la función siguiente: - -<tscreen><verb> -gchar *gtk_entry_get_text(GtkEntry *entry); -</verb></tscreen> - -De esta forma: - -<tscreen><verb> - char *cadena; - - cadena = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(combo)->entry)); -</verb></tscreen> - -Esto es todo lo interesante. Existe otra función, - -<tscreen><verb> -void gtk_combo_disable_activate(GtkCombo *combo); -</verb></tscreen> - -que permite desactivar la señal <tt/activate/ en el <em/widget/ entry -dentro del combo box. Personalmente no se me ocurre ningún motivo para -utilizarla, pero existir existe. - -<!-- There are also a function to set the string on a particular item, void -gtk_combo_set_item_string(GtkCombo *combo, GtkItem *item, const gchar -*item_value), but this requires that you have a pointer to the -appropriate GtkItem. Frankly, I have no idea how to do that. ---> - -<!-- ************************************** --> - -<!-- ----------------------------------------------------------------- --> -<sect1> Selección de Color -<p> -El <em/widget/ selección de color, nos permite (¡sorpresa!) la selección -interactiva de colores. Este <em/widget/ compuesto le permite al usuario -seleccionar un color manipulando los tripletes RGB (rojo, verde y azul) y -HSV (tono, saturación, valor). Para conseguirlo puede ajustar cada variable -mediante las regletas o introduciendo directamente el valor deseado. -También puede pinchar en la rueda de colores y seleccionar así el color -deseado. También se puede establecer, opcionalmente, la transparencia -del color. - -El <em/widget/ de selección de color emite (por ahora) sólo una señal, -<tt/color_changed/, que se emite cuando cambia el color seleccionado, -ya sea mediante un cambio que haga el usuario o median el resultado -de una llamada a la función <tt/gtk_color_selection_set_color()/. - -Echémosle un vistazo a lo que nos ofrece el <em/widget/ de selección de color. -El <em/widget/ tiene dos «sabores» diferentes; <tt/gtk_color_selection/ -y <tt/gtk_color_selection_dialog/: - -<tscreen><verb> -GtkWidget *gtk_color_selection_new( void ); -</verb></tscreen> - -Probablemente no utilizará este constructor directamente. Crea un <em/widget/ -GtkColorSelection huérfano al que le tendrá que asignarle un padre. El -<em/widget/ GtkColorSelection está heredado del <em/widget/ GtkVBox. - -<tscreen><verb> -GtkWidget *gtk_color_selection_dialog_new( const gchar *title ); -</verb></tscreen> - -Éste es el constructor del cuadro de selección de color más común. Crea un -<tt/GtkColorSelectionDialog/, heredado de un <tt/GtkDialog/. Consiste en un -<tt/GtkFrame/ con un <tt/GtkColorSelection/, un <tt/GtkHSeparator/ y un -<tt/GtkHBox/ con tres botones, «Aceptar», «Cancelar» y «Ayuda». -Puede utilizar estos botones accediendo a los <em/widgets/ <tt/ok_button/, -<tt/cancel_button/ y <tt/help_button/ de la estructura GtkColorSelectionDialog, -(es decir GTK_COLOR_SELECTION_DIALOG(colorseldialog)->ok_button). - -<tscreen><verb> -void gtk_color_selection_set_update_policy( GtkColorSelection *colorsel, - GtkUpdateType policy ); -</verb></tscreen> - -Esta función se utiliza para indicar la política de actuación. La política -por defecto es <tt/GTK_UPDATE_CONTINUOUS/ que significa que el color -seleccionado se actualiza continuamente cuando el usuario arrastra la barra -o selecciona con el ratón un color de la rueda de colores. Si tiene problemas -de rendimiento, puede poner la política <tt/GTK_UPDATE_DISCONTINUOUS/ o -<tt/GTK_UPDATE_DELAYED/. - -<tscreen><verb> -void gtk_color_selection_set_opacity( GtkColorSelection *colorsel, - gint use_opacity ); -</verb></tscreen> - -El <em/widget/ de selección de color admite el ajuste de la transparencia -de un color (también conocido como el canal alfa). Esta opción está -desactivada por defecto. Si se llama a esta función con <tt/use_opacity/ -como TRUE se activa la transparencia. Si se utiliza <tt/use_opacity/ como -FALSE se desactiva la transparencia. - -<tscreen><verb> -void gtk_color_selection_set_color( GtkColorSelection *colorsel, - gdouble *color ); -</verb></tscreen> - -Puede poner el color actual explicitamente haciendo uso de esta función con -un puntero a un vector de colores (de tipo <tt/gdouble/). La longitud del -vector depende de si está activada la transparencia. La posición 0 contiene -la componente roja del color, la 1 contiene la verde, la 2 la azul y la -transparencia está en la posición 3 (solamente si está activada la -transparencia, ver <tt/gtk_color_selection_set_opacity()/). Todos los -valores se encuentran entre 0.0 y 1.0. - -<tscreen><verb> -void gtk_color_selection_get_color( GtkColorSelection *colorsel, - gdouble *color ); -</verb></tscreen> - -Cuando necesite preguntar por el color actual, normalmente cuando haya -recibido una señal <tt/color_changed/, utilice esta función. <tt/color/ -es un puntero al vector de colores que se rellenará. Ver la descripción -de la función <tt/gtk_color_selection_set_color()/ para conocer la -estructura de este vector. - -<!-- Need to do a whole section on DnD - TRG -Drag and drop -------------- - -The color sample areas (right under the hue-saturation wheel) supports -drag and drop. The type of drag and drop is "application/x-color". The -message data consists of an array of 4 (or 5 if opacity is enabled) -gdouble values, where the value at position 0 is 0.0 (opacity on) or -1.0 (opacity off) followed by the red, green and blue values at -positions 1,2 and 3 respectively. If opacity is enabled, the opacity -is passed in the value at position 4. ---> - -Aquí tenemos un pequeño ejemplo que muestra el uso de -<tt/GtkColorSelectionDialog/. El programa muestra una ventana con una -zona de dibujo. Pulsando en ella se abre un cuadro de diálogo de -selección del color, y cambiando el color en el cuadro de diálogo se -cambia el color de fondo de la zona de dibujo. - -<tscreen><verb> -/* principio del ejemplo colorsel colorsel.c */ - -#include <glib.h> -#include <gdk/gdk.h> -#include <gtk/gtk.h> - -GtkWidget *colorseldlg = NULL; -GtkWidget *drawingarea = NULL; - -/* Manejador del cambio de color */ - -void color_changed_cb (GtkWidget *widget, GtkColorSelection *colorsel) -{ - gdouble color[3]; - GdkColor gdk_color; - GdkColormap *colormap; - - /* Obtener el mapa de colores de la zona de dibujo */ - - colormap = gdk_window_get_colormap (drawingarea->window); - - /* Obtener el color actual */ - - gtk_color_selection_get_color (colorsel,color); - - /* Meterlo en un entero sin signo de 16 bits (0..65535) e insertarlo - en la estructura 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); - - /* Pedir memoria para el color */ - - gdk_color_alloc (colormap, &gdk_color); - - /* Poner el color de fondo de la ventana */ - - gdk_window_set_background (drawingarea->window, &gdk_color); - - /* Limpiar la ventana */ - - gdk_window_clear (drawingarea->window); -} - -/* Manejador del evento Drawingarea */ - -gint area_event (GtkWidget *widget, GdkEvent *event, gpointer client_data) -{ - gint handled = FALSE; - GtkWidget *colorsel; - - /* Comprobar si hemos recibido un evento de pulsación de botón */ - - if (event->type == GDK_BUTTON_PRESS && colorseldlg == NULL) - { - /* Sí, ¡tenemos un evento y todavía no está el colorseldlg! */ - - handled = TRUE; - - /* Crear el cuadro de diálogo de selección del color */ - - colorseldlg = gtk_color_selection_dialog_new("Select background color"); - - /* Obtener el widget GtkColorSelection */ - - colorsel = GTK_COLOR_SELECTION_DIALOG(colorseldlg)->colorsel; - - /* Conectar con la señal «color_changed», darle al dato del - cliente el valor del widget colorsel */ - - gtk_signal_connect(GTK_OBJECT(colorsel), "color_changed", - (GtkSignalFunc)color_changed_cb, (gpointer)colorsel); - - /* Mostrar el cuadro de diálogo */ - - gtk_widget_show(colorseldlg); - } - - return handled; -} - -/* Manipulador de los eventos cerrar y salir */ - -void destroy_window (GtkWidget *widget, gpointer client_data) -{ - gtk_main_quit (); -} - -/* Principal */ - -gint main (gint argc, gchar *argv[]) -{ - GtkWidget *ventana; - - /* Inicializa el toolkit, y elimina las opciones relacionadas con - gtk incluidas en la línea de órdenes */ - - gtk_init (&argc,&argv); - - /* Crea la ventana de más alto nivel, le da título y la política */ - - ventana = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_title (GTK_WINDOW(ventana), "Color selection test"); - gtk_window_set_policy (GTK_WINDOW(ventana), TRUE, TRUE, TRUE); - - /* Enlaza con los eventos «delete» y «destroy», para que podamos - salir */ - - gtk_signal_connect (GTK_OBJECT(ventana), "delete_event", - (GtkSignalFunc)destroy_window, (gpointer)ventana); - - gtk_signal_connect (GTK_OBJECT(ventana), "destroy", - (GtkSignalFunc)destroy_window, (gpointer)ventana); - - /* Crea la zona de dibujo, pone el tamaño y caza los eventos de los - botones */ - - 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); - - /* Add drawingarea to window, then show them both */ - - gtk_container_add (GTK_CONTAINER(ventana), drawingarea); - - gtk_widget_show (drawingarea); - gtk_widget_show (ventana); - - /* Entrar en el bucle principal de gtk (nunca sale de aquí) */ - - gtk_main (); - - /* Para satisfacer a los compiladores pijos */ - - return 0; -} -/* final del ejemplo */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1> Selección de ficheros -<p> -El <em/widget/ de selección de ficheros nos proporciona una forma -rápida y sencilla de mostrar un cuadro de diálogo para la selección de -un fichero. Ya viene con los botones Aceptar, Cancelar y Ayuda. Una -magnifica ayuda para acortar el tiempo de programación. - -Para crear un nuevo cuadro de diálogo de selección de ficheros -utilice: - -<tscreen><verb> -GtkWidget *gtk_file_selection_new( gchar *title ); -</verb></tscreen> - -Para poner el nombre del fichero en el cuadro de diálogo, por -ejemplo para poder utilizar un directorio o un fichero por defecto, -utilice la función: - -<tscreen><verb> -void gtk_file_selection_set_filename( GtkFileSelection *filesel, - gchar *filename ); -</verb></tscreen> - -Para obtener el texto que el usuario ha introducido, utilice la función: - -<tscreen><verb> -gchar *gtk_file_selection_get_filename( GtkFileSelection *filesel ); -</verb></tscreen> - -También hay punteros a los <em/widgets/ que contiene el cuadro de -diálogo. Son los siguientes: - -<itemize> -<item>dir_list -<item>file_list -<item>selection_entry -<item>selection_text -<item>main_vbox -<item>ok_button -<item>cancel_button -<item>help_button -</itemize> - -Lo más probable es que sólo utilice los punteros <tt/ok_button/, -<tt/cancel_button/, y <tt/help_button/ para controlar cuando se pulsan. - -Aquí incluímos un ejemplo robado de <tt/testgtk.c/, modificado -para que se puede ejecutar independientemente. Como puede ver, no es -muy complicado crear un <em/widget/ para la selección de -ficheros. Aunque aparezca el botón de ayuda en la pantalla, no hace -nada y no tiene ninguna señal conectada. - -<tscreen><verb> -/* principio del ejemplo filesel filesel.c */ - -#include <gtk/gtk.h> - -/* Obtener el nombre del fichero e imprimirlo en la consola */ -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); - - /* Crear un nuevo widget de selección de ficheros */ - filew = gtk_file_selection_new ("File selection"); - - gtk_signal_connect (GTK_OBJECT (filew), "destroy", - (GtkSignalFunc) destroy, &filew); - /* Conectar el ok_button con la función file_ok_sel */ - gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (filew)->ok_button), - "clicked", (GtkSignalFunc) file_ok_sel, filew ); - - /* Conectar el cancel_button con la destrucción del widget */ - gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION (filew)->cancel_button), - "clicked", (GtkSignalFunc) gtk_widget_destroy, - GTK_OBJECT (filew)); - - /* Damos el nombre del fichero, como si fuese un cuadro de diálogo para - grabar ficheros y estuviesemos dando un nombre por defecto */ - gtk_file_selection_set_filename (GTK_FILE_SELECTION(filew), - "penguin.png"); - - gtk_widget_show(filew); - gtk_main (); - return 0; -} -/* fin del ejemplo */ -</verb></tscreen> - -<!-- ***************************************************************** --> -<sect> El <em/widget/ contenedor -<!-- ***************************************************************** --> - -<!-- ----------------------------------------------------------------- --> -<sect1> El <em/widget/ EventBox<label id="sec_EventBox"> -<label id="sec_The_EventBox_Widget"> -<p> -Algunos <em/widget/ gtk no tienen asociada una ventana X, por lo que -sólo pueden dibujar en la de su padre. Debido a esto, no pueden -recibir ningún evento y si tienen un tamaño incorrecto, no se -recortarán correctamente por lo que puede que se sobreescriban ciertas -zonas, etc... Si necesita este tipo de <em/widgets/, el EventBox es -para usted. - -Cuando se ve por primera vez, el <em/widget/ EventBox puede parecer -completamente inútil. No dibuja nada en la pantalla y no responde -a ningún evento. Sin embargo, tiene una utilidad - proporciona una -ventana X para su <em/widget/ hijo. Esto es importante ya que -muchos <em/widgets/ GTK no tienen una ventana X asociada. No tener una -ventana X ahorra memoria y mejora el rendimiento, pero tiene sus -desventajas. Un <em/widget/ sin una ventana X no puede recibir -eventos, y no realizará ningún recorte en sus contenidos. Aunque el -nombre <em/EventBox/ enfatiza su función de manejador de eventos, el -<em/widget/ también puede utilizarse para hacer los recortes. -(Y más... ver el ejemplo más abajo.) - -Para crear un nuevo <em/widget/ EventBox, utilice: - -<tscreen><verb> -GtkWidget *gtk_event_box_new( void ); -</verb></tscreen> - -Un <em/widget/ hijo puede añadirse a su EventBox así: - -<tscreen><verb> -gtk_container_add( GTK_CONTAINER(event_box), widget ); -</verb></tscreen> - -El siguiente ejemplo demuestra los dos usos de EventBox - se crea -una etiqueta que se recorta dentro de una pequeña caja, y hace -que una pulsación del ratón en la misma finalice el programa. - -<tscreen><verb> -/* principio del ejemplo eventbox eventbox.c */ - -#include <gtk/gtk.h> - -int -main (int argc, char *argv[]) -{ - GtkWidget *ventana; - GtkWidget *event_box; - GtkWidget *etiqueta; - - gtk_init (&argc, &argv); - - ventana = gtk_window_new (GTK_WINDOW_TOPLEVEL); - - gtk_window_set_title (GTK_WINDOW (ventana), "Event Box"); - - gtk_signal_connect (GTK_OBJECT (ventana), "destroy", - GTK_SIGNAL_FUNC (gtk_exit), NULL); - - gtk_container_border_width (GTK_CONTAINER (ventana), 10); - - /* Crea un EventBox y lo añade a nuestra ventana superior */ - - event_box = gtk_event_box_new (); - gtk_container_add (GTK_CONTAINER(ventana), event_box); - gtk_widget_show (event_box); - - /* Crea una larga etiqueta */ - - etiqueta = gtk_label_new ("Click here to quit, quit, quit, quit, quit"); - gtk_container_add (GTK_CONTAINER (event_box), etiqueta); - gtk_widget_show (etiqueta); - - /* La recortamos. */ - gtk_widget_set_usize (etiqueta, 110, 20); - - /* Y enlazamos una acción con la etiqueta */ - 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); - - /* Otra cosa más que necesita una ventana X ... */ - - gtk_widget_realize (event_box); - gdk_window_set_cursor (event_box->window, gdk_cursor_new (GDK_HAND1)); - - gtk_widget_show (ventana); - - gtk_main (); - - return 0; -} -/* Final del ejemplo */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>El <em/widget/ alineamiento <label id="sec_Alignment"> -<p> -El <em/widget/ alineamiento (<em/alignment/) le permitirá colocar un -<em/widget/ dentro de su ventana utilizando una posición y un tamaño -relativos al mismo <em/widget/ de alineamiento. Por ejemplo, puede ser -muy útil para centrar un <em/widget/ en la ventana. - -Sólo hay dos funciones asociadas con el <em/widget/ alineamiento: - -<tscreen><verb> -GtkWidget* gtk_alignment_new( gfloat xalign, - gfloat yalign, - gfloat xscale, - gfloat yscale ); - -void gtk_alignment_set( GtkAlignment *alignment, - gfloat xalign, - gfloat yalign, - gfloat xscale, - gfloat yscale ); -</verb></tscreen> - -La primera función crea un nuevo <em/widget/ alineamiento con los -parámetros especificados. La segunda función permite alterar los -parámetros de un <em/widget/ alineamiento ya existente. - -Los cuatro parámetros de alineamiento son números en coma flotante que -pueden tener variar entre 0.0 y 1.0. Los argumentos <tt/xalign/ e -<tt/yalign/ afectan a la posición del <em/widget/ colocado dentro del -<em/widget/ de alineamiento. Los argumentos <tt/xscale/ e <tt/yscale/ -afectan a la cantidad de espacio que ocupa el <em/widget/. - -Se le puede añadir un <em/widget/ hijo a un alineamiento utilizando: - -<tscreen><verb> - gtk_container_add( GTK_CONTAINER(alignment), child_widget ); -</verb></tscreen> - -Para ver un ejemplo de utilización del <em/widget/ alineamiento, -diríjase al ejemplo del <em/widget/ <ref id="sec_ProgressBar" -name="Barra de progreso">. - - -<!-- ----------------------------------------------------------------- --> -<sect1> Contenedor fijo -<p> -El contenedor fijo le permite situar <em/widgets/ en una posición fija -dentro de su ventana, relativa a la esquina superior izquierda. La -posición de los <em/widgets/ puede cambiarse dinámicamente. - -Sólo hay tres funciones asociadas al <em/widget/ contenedor fijo: - -<tscreen><verb> -GtkWidget* gtk_fixed_new( void ); - -void gtk_fixed_put( GtkFixed *fixed, - GtkWidget *widget, - gint16 x, - gint16 y ); - -void gtk_fixed_move( GtkFixed *fixed, - GtkWidget *widget, - gint16 x, - gint16 y ); -</verb></tscreen> - -La función <tt/gtk_fixed_new/ permite la creación de un nuevo -contenedor fijo. - -<tt/gtk_fixed_put/ situa <tt/widget/ dentro del contenedor <tt/fixed/ -en la posición especificada por <tt/x/ e <tt/y/. - -<tt/gtk_fixed_move/ permite que mover hacia una nuevo posición el -<em/widget/ especificado. - -El ejemplo siguiente muestra como utilizar el contenedor fijo. - -<tscreen><verb> -/* principio del ejemplo fixed fixed.c */ - -#include <gtk/gtk.h> - -/* Voy a ser un poco torpe y utilizar algunas variables - * globales para almacenar la posición del widget que - * hay dentro del contenedor */ -gint x=50; -gint y=50; - -/* Esta función de llamada mueve el botón a una nueva - * posición dentro del contenedor fijo. */ -void move_button( GtkWidget *widget, - GtkWidget *fixed ) -{ - x = (x+30)%300; - y = (y+50)%300; - gtk_fixed_move( GTK_FIXED(fixed), widget, x, y); -} - -int main( int argc, - char *argv[] ) -{ - /* GtkWidget es el tipo de almacenamiento para los widgets */ - GtkWidget *ventana; - GtkWidget *fixed; - GtkWidget *boton; - gint i; - - /* Inicializa GTK */ - gtk_init(&argc, &argv); - - /* Crear una nueva ventana */ - ventana = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_title(GTK_WINDOW(ventana), "Fixed Container"); - - /* Aquí conectamos el evento "destroy" al manejador de la señal */ - gtk_signal_connect (GTK_OBJECT (ventana), "destroy", - GTK_SIGNAL_FUNC (gtk_main_quit), NULL); - - /* Establecemos el ancho del borde la ventana */ - gtk_container_set_border_width (GTK_CONTAINER (ventana), 10); - - /* Creamos un contenedor fijo */ - fixed = gtk_fixed_new(); - gtk_container_add(GTK_CONTAINER(ventana), fixed); - gtk_widget_show(fixed); - - for (i = 1 ; i <= 3 ; i++) { - /* Crea un nuevo botón con la etiqueta "Press me" */ - boton = gtk_button_new_with_label ("Press me"); - - /* Cuando el botón reciba la señal "pulsado", llamará a la función - * move_button() pasándole el contenedor fijo como argumento. */ - gtk_signal_connect (GTK_OBJECT (boton), "clicked", - GTK_SIGNAL_FUNC (move_button), fixed); - - /* Esto mete el botón dentro de la ventana del window contenedor - * fijo. */ - gtk_fixed_put (GTK_FIXED (fixed), boton, i*50, i*50); - - /* El paso final es mostrar el widget recien creado */ - gtk_widget_show (boton); - } - - /* Mostrar la ventana */ - gtk_widget_show (ventana); - - /* Entrar en el bucle principal */ - gtk_main (); - - return(0); -} -/* fin del ejemplo */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1> Contenedor capa -<p> -El contenedor capa es similar al contenedor fijo, excepto que permite -implementar una zona de <em/scroll/ infinita (donde infinito significa -menor de 2^32). Xwindows tiene una limitación en la que las ventanas -pueden tener un máximo de 32767 <em/pixels/ de alto o de ancho. El -contenedor capa sortea esta limitación con una exótica combinación de -ventanas y <em/bits/ de gravedad, <!-- Si alguien entiende que -significa esto: e98cuenc@criens.u-psud.fr --> para que puede tener un -suave <em/scroll/ aún cuando utilice una gran cantidad de <em/widgets/ -hijos dentro de su zona de <em/scroll/. - -Podrá crear un contenedor capa utilizando: - -<tscreen><verb> -GtkWidget *gtk_layout_new( GtkAdjustment *hadjustment, - GtkAdjustment *vadjustment ); -</verb></tscreen> - -Como puede observar, podrá especificar (de forma opcional) los objetos -de ajuste que utilizará el <em/widget/ capa para hacer su <em/scroll/. - -Puede añadir y mover <em/widgets/ dentro del contenedor capa -utilizando las dos funciones siguientes: - -<tscreen><verb> -void gtk_layout_put( GtkLayout *layout, - GtkWidget *widget, - gint x, - gint y ); - -void gtk_layout_move( GtkLayout *layout, - GtkWidget *widget, - gint x, - gint y ); -</verb></tscreen> - -El tamaño del contenedor capa se puede establecer utilizando la -siguiente función: - -<tscreen><verb> -void gtk_layout_set_size( GtkLayout *layout, - guint width, - guint height ); -</verb></tscreen> - -Los contenedores capa son uno de los poquísimos <em/widgets/ dentro de -GTK que se repintan ellos mismos en la pantalla cuando se cambian -utilizando las funciones anteriores (la inmensa mayoria de los -<em/widgets/ mandan una petición a la cola que será procesada cuando -se devuelva el control a la función <tt/gtk_main()/). - -Cuando quiera hacer una gran cantidad de cambios dentro del contenedor -capa, podrá utilizar las dos funciones siguientes para desactivar y -reactivar la característica de repintado: - -<tscreen><verb> -void gtk_layout_freeze( GtkLayout *layout ); - -void gtk_layout_thaw( GtkLayout *layout ); -</verb></tscreen> - -Las cuatro funciones finales a utilizar con los <em/widgets/capa son -para la manipulación de los <em/widgets/ de ajuste horizontal y -vertical: - -<tscreen><verb> -GtkAdjustment* gtk_layout_get_hadjustment( GtkLayout *layout ); - -GtkAdjustment* gtk_layout_get_vadjustment( GtkLayout *layout ); - -void gtk_layout_set_hadjustment( GtkLayout *layout, - GtkAdjustment *adjustment ); - -void gtk_layout_set_vadjustment( GtkLayout *layout, - GtkAdjustment *adjustment); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1> Marcos <label id="sec_Frames"> -<p> -Los marcos pueden utilizarse para meter uno o un grupo de -<em/widgets/dentro de una caja puede ser (de forma opcional) -etiquetada. La posición de la etiqueta y el estilo de la caja pueden -modificarse. - -Se puede crear un marco con la siguiente función: - -<tscreen><verb> -GtkWidget *gtk_frame_new( const gchar *etiqueta ); -</verb></tscreen> - -La etiqueta se coloca por defecto en la esquina superior izquierda del -marco. Si el argumento <tt/etiqueta/ es NULL no se mostrará ninguna -etiqueta. Puede cambiarse el texto de la etiqueta utilizando la -función siguiente. - -<tscreen><verb> -void gtk_frame_set_label( GtkFrame *frame, - const gchar *etiqueta ); -</verb></tscreen> - -La posición de la etiqueta se puede cambiar utilizado la función: - -<tscreen><verb> -void gtk_frame_set_label_align( GtkFrame *frame, - gfloat xalign, - gfloat yalign ); -</verb></tscreen> - -<tt/xalign/ e <tt/yalign/ toman valores entre 0.0 y 1.0. <tt/yalign/ -no se actualmente no se utiliza. El valor por defecto de <tt/xalign/ -es 0.0, lo que coloca la etiqueta a la izquierda del marco. - -La siguiente función altera el estilo de la caja que se utiliza para -señalar el marco. - -<tscreen><verb> -void gtk_frame_set_shadow_type( GtkFrame *frame, - GtkShadowType type); -</verb></tscreen> - -El argumento <tt/type/ puede tomar uno de los valores siguientes: - -<itemize> -<item> GTK_SHADOW_NONE -<item> GTK_SHADOW_IN -<item> GTK_SHADOW_OUT -<item> GTK_SHADOW_ETCHED_IN (the default) -<item> GTK_SHADOW_ETCHED_OUT -</itemize> - -El código siguiente ilustra la utilización del <em/widget/ marco. - -<tscreen><verb> -/* principio del ejemplo frame frame.c */ - -#include <gtk/gtk.h> - -int main( int argc, - char *argv[] ) -{ - /* GtkWidget es el tipo de almacenamiento para los widgets */ - GtkWidget *ventana; - GtkWidget *frame; - GtkWidget *boton; - gint i; - - /* Inicializa GTK */ - gtk_init(&argc, &argv); - - /* Crea una nueva ventana */ - ventana = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_title(GTK_WINDOW(ventana), "Frame Example"); - - /* Aquí conectamos el evento "destroy"al manejador de señal */ - gtk_signal_connect (GTK_OBJECT (ventana), "destroy", - GTK_SIGNAL_FUNC (gtk_main_quit), NULL); - - gtk_widget_set_usize(ventana, 300, 300); - - /* Establecemos el ancho del borde de la ventana */ - gtk_container_set_border_width (GTK_CONTAINER (ventana), 10); - - /* Crea un marco */ - frame = gtk_frame_new(NULL); - gtk_container_add(GTK_CONTAINER(ventana), frame); - - /* Establece la etiqueta del marco */ - gtk_frame_set_label( GTK_FRAME(frame), "GTK Frame Widget" ); - - /* Alinea la etiqueta a la derecha del marco */ - gtk_frame_set_label_align( GTK_FRAME(frame), 1.0, 0.0); - - /* Establece el estilo del marco */ - gtk_frame_set_shadow_type( GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT); - - gtk_widget_show(frame); - - /* Muestra la ventana */ - gtk_widget_show (ventana); - - /* Entra dentro del bucle principal */ - gtk_main (); - - return(0); -} -/* fin del ejemplo */ - -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1> Marcos con proporciones fijas -<p> -El <em/widget aspect frame/ (marco proporcional) es como el <em/widget -frame/ (marco), excepto que conserva las proporciones (esto es, la -relación entre el ancho y el alto) del <em/widget/ hijo, añadiendo -espacio extra en caso de ser necesario. Esto es útil, por ejemplo, si -quiere hacer una vista previa de una gran imagen. El tamaño de la -vista previa debería variar cuando el usuario redimensione la ventana, -pero la proporción tiene que coincidir con la de la imagen original. - -Para crear un nuevo marco proporcional utilice: - -<tscreen><verb> -GtkWidget *gtk_aspect_frame_new( const gchar *etiqueta, - gfloat xalign, - gfloat yalign, - gfloat ratio, - gint obey_child); -</verb></tscreen> - -<tt/xalign/ e <tt/yalign/ indican la alineación exactamente igual que -con los <em/widgets Alignment/. Si <tt/obey_child/ es TRUE, la -proporción de un <em/widget/ hijo será la misma que la proporción del -tamaño ideal que éste pida. En caso contrario, vendrá dada por -<tt/ratio/. - -Para cambiar las opciones de un marco proporcional ya existente, puede -utilizar: - -<tscreen><verb> -void gtk_aspect_frame_set( GtkAspectFrame *aspect_frame, - gfloat xalign, - gfloat yalign, - gfloat ratio, - gint obey_child); -</verb></tscreen> - -Como por ejemplo, el siguiente programa utiliza un marco proporcional -para mostrar una zona de dibujo cuyas proporciones siempre será de -2:1, no importa como el usuario redimensione la ventana. - -<tscreen><verb> -/* principio del ejemplo aspectframe aspectframe.c */ - -#include <gtk/gtk.h> - -int -main (int argc, char *argv[]) -{ - GtkWidget *ventana; - GtkWidget *aspect_frame; - GtkWidget *drawing_area; - gtk_init (&argc, &argv); - - ventana = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_title (GTK_WINDOW (ventana), "Aspect Frame"); - gtk_signal_connect (GTK_OBJECT (ventana), "destroy", - GTK_SIGNAL_FUNC (gtk_main_quit), NULL); - gtk_container_border_width (GTK_CONTAINER (ventana), 10); - - /* Crear un aspect_frame y añadirlo a nuestra ventana superior */ - - aspect_frame = gtk_aspect_frame_new ("2x1", /* etiqueta */ - 0.5, /* centro x */ - 0.5, /* centro y */ - 2, /* tamañox/tamañoy = 2 */ - FALSE /* ignorar el aspecto del hijo */); - - gtk_container_add (GTK_CONTAINER(ventana), aspect_frame); - gtk_widget_show (aspect_frame); - - /* Añadir un widget hijo al marco proporcional */ - - drawing_area = gtk_drawing_area_new (); - - /* Pediremos una ventana de 200x200, pero el marco proporcional - * sólo no dejará una ventana de 200x100, ya que tenemos una - * relación de 2x1 */ - 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 (ventana); - gtk_main (); - return 0; -} -/* fin del ejemplo */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> - -<sect1> El <em/widget/ ventana dividida (<em/Paned Window/) -<p> -El <em/widget/ ventana dividida es útil para cuando se quiere dividir -una zona en dos partes, con un tamaño relativo controlado por el -usuario. Entre las dos porciones de la ventana se dibuja un separador -con un botoncito que el usuario puede arrastrar para cambiar el tamaño -de cada zona. La división puede ser horizontal (HPaned) o vertical -(VPaned). - -Para crear una nueva ventana dividida, utilice una de las siguientes -funciones: - -<tscreen><verb> -GtkWidget *gtk_hpaned_new (void); - -GtkWidget *gtk_vpaned_new (void); -</verb></tscreen> - -Después de crear el <em/widget/ ventana dividida, tiene que añadirle -un <em/widget/ hijo a cada mitad. Para hacerlo, utilice: - -<tscreen><verb> -void gtk_paned_add1 (GtkPaned *paned, GtkWidget *hijo); - -void gtk_paned_add2 (GtkPaned *paned, GtkWidget *hijo); -</verb></tscreen> - -<tt/gtk_paned_add1()/ añade el <em/widget/ hijo a la mitad que se -encuentra en la parte izquierda o superior de la ventana -dividida. <tt/gtk_paned_add2()/ añade el <em/widget/ a la mitad que -hay en la parte derecha o inferior de la ventana. - -Por ejemplo, si queremos crear una parte del interface de usuario de -un programa de correo-e imaginario. Dividiremos verticalmente una -ventana en dos partes, teniendo en la parte superior una lista de los -mensajes de correo-e y en la parte inferior el texto de uno de estos -mensajes. El programa es bastante fácil de entender. Solo un par de -cosillas: no se puede añadir texto en un <em/widget/ de texto (Text) -si no se ha hecho antes <tt/gtk_widget_realize()/, pero como -demostración de una técnica alternativa, para añadir el texto -conectaremos un manipulador a la señal «realize». Y tenemos que -añadir la opción <tt/GTK_SHRINK/ a algunos de los elementos que hay en -la tabla con la ventana de texto y sus barras de desplazamiento, así -cuando la porción de abajo se haga más pequeña, se encogerá -correctamente en lugar de desaparecer por la parte de abajo de la -ventana. - -<tscreen><verb> -/* principio del ejemplo paned paned.c */ - -#include <gtk/gtk.h> - -/* Crear la lista de "messages" */ -GtkWidget * -create_list (void) -{ - - GtkWidget *scrolled_window; - GtkWidget *list; - GtkWidget *list_item; - - int i; - char buffer[16]; - - /* Crear una nueva ventana con barras de desplazamiento si hacen - falta */ - scrolled_window = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); - - /* Crear una nueva lista y poner en ella la ventana con barras */ - list = gtk_list_new (); - gtk_container_add (GTK_CONTAINER(scrolled_window), list); - gtk_widget_show (list); - - /* Añadir algunos mensajes a la ventana */ - 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; -} - -/* Añadir algún texto a nuestro widget de texto - esta función se - invoca cada vez que se produce una señal realize en la - ventana. Podemos forzar esta señal mediante gtk_widget_realize, pero - primero tiene que formar parte de una jerarquía */ - -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)); -} - -/* Creamos una zona con texto que muestra un "message" */ -GtkWidget * -create_text (void) -{ - GtkWidget *table; - GtkWidget *text; - GtkWidget *hscrollbar; - GtkWidget *vscrollbar; - - /* Crea una tabla para contener el widget de texto y las barras de - desplazamiento */ - table = gtk_table_new (2, 2, FALSE); - - /* Pone un widget de texto en la esquina superior izquierda. - Observe la utilización de GTK_SHRINK en la dirección y */ - 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); - - /* Pone una HScrollbar en la esquina inferior izquierda */ - 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); - - /* Y una VScrollbar en la esquina superior derecha */ - 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); - - /* Y un manejador para poner un mensaje en el widget de texto - cuando reciba realize */ - gtk_signal_connect (GTK_OBJECT (text), "realize", - GTK_SIGNAL_FUNC (realize_text), NULL); - - return table; -} - -int -main (int argc, char *argv[]) -{ - GtkWidget *ventana; - GtkWidget *vpaned; - GtkWidget *list; - GtkWidget *text; - - gtk_init (&argc, &argv); - - ventana = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_title (GTK_WINDOW (ventana), "Paned Windows"); - gtk_signal_connect (GTK_OBJECT (ventana), "destroy", - GTK_SIGNAL_FUNC (gtk_main_quit), NULL); - gtk_container_border_width (GTK_CONTAINER (ventana), 10); - - /* crea un widget vpaned y lo añade a nuestra ventana superior */ - - vpaned = gtk_vpaned_new (); - gtk_container_add (GTK_CONTAINER(ventana), vpaned); - gtk_widget_show (vpaned); - - /* Ahora crea los contenidos de las dos mitades de la ventana */ - - 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 (ventana); - gtk_main (); - return 0; -} -/* fin del ejemplo */ -</verb></tscreen> - -<!-- XXX --> -<!-- ----------------------------------------------------------------- --> -<sect1> <em/Viewports/ <label id="sec_Viewports"> -<p> -Probablemente nunca le llegue a hacer falta utilizar el <em/widget/ -Viewport directamente. Será mucho más probable que tenga que utilizar -el <em/widget/ <ref id="sec_ScrolledWindows" name="Ventanas con barras -de desplazamiento"> que a su vez hace uso de <em/viewport/. - -Un <em/widget viewport/ le permite meter dentro un gran <em/widget/, -de forma que sólo verá una parte del mismo. Utiliza -<ref id="sec_Adjustment" name="ajustes"> para definir la zona que se -está viendo actualmente. - -Para crear un <em/viewport/ hay que utilizar la función: - -<tscreen><verb> -GtkWidget *gtk_viewport_new( GtkAdjustment *hadjustment, - GtkAdjustment *vadjustment ); -</verb></tscreen> - -Como puede observar, se pueden especificar los ajustes horizontal y -vertical que el <em/widget/ va a utilizar en el mismo momento de su -creación. El <em/widget/ creará sus propios ajustes en caso de que -reciba como argumento un valor NULL. - -Puede obtener y establecer los ajustes después de que se haya -creado el <em/widget/ utilizado las cuatro funciones siguientes: - -<tscreen><verb> -GtkAdjustment *gtk_viewport_get_hadjustment (GtkViewport *viewport ); - -GtkAdjustment *gtk_viewport_get_vadjustment (GtkViewport *viewport ); - -void gtk_viewport_set_hadjustment( GtkViewport *viewport, - GtkAdjustment *adjustment ); - -void gtk_viewport_set_vadjustment( GtkViewport *viewport, - GtkAdjustment *adjustment ); -</verb></tscreen> - -La única función relativa al <em/viewport/ que queda que altera su -apariencia es: - -<tscreen><verb> -void gtk_viewport_set_shadow_type( GtkViewport *viewport, - GtkShadowType type ); -</verb></tscreen> - -Los valores posibles para el argumento <tt/type/ son: -<itemize> -<item> GTK_SHADOW_NONE, -<item> GTK_SHADOW_IN, -<item> GTK_SHADOW_OUT, -<item> GTK_SHADOW_ETCHED_IN, -<item> GTK_SHADOW_ETCHED_OUT -</itemize> - -<!-- ----------------------------------------------------------------- --> -<sect1>Ventanas con barras de desplazamiento <label id="sec_ScrolledWindows"> -<p> - -Las ventanas con barras de desplazamiento se utilizan para crear una zona -con barras de desplazamiento dentro de una ventana real. Puede insertar -cualquier tipo de <em/widget/ en una ventana con barras de -desplazamiento, y podrá utilizarlo sin importar su tamaño gracias a -las barras de desplazamiento. - -La función siguiente se utiliza para crear una nueva ventana con -barras de desplazamiento. - -<tscreen><verb> -GtkWidget *gtk_scrolled_window_new( GtkAdjustment *hadjustment, - GtkAdjustment *vadjustment ); -</verb></tscreen> - -Donde el primer argumento es el ajuste para la dirección horizontal, y -el segundo es el ajuste para la dirección vertical. Casi siempre valen -NULL. - -<tscreen><verb> -void gtk_scrolled_window_set_policy( GtkScrolledWindow *scrolled_window, - GtkPolicyType hscrollbar_policy, - GtkPolicyType vscrollbar_policy ); -</verb></tscreen> - -Esta función establece la política que se utilizará con respecto a las -barras de desplazamiento. El primer argumento es la ventana con barras -de desplazamiento sobre la que queremos actuar. El segundo establece -la política para la barra de desplazamiento horizontal, y el tercero -la política para la barra de desplazamiento vertical. - -La política puede ser GTK_POLICY_AUTOMATIC, o -GTK_POLICY_ALWAYS. GTK_POLICY_AUTOMATIC decidirá automáticamente si -necesita barras de desplazamiento, mientras que GTK_POLICY_ALWAYS pondrá -siempre las barras de desplazamiento. - -Aquí tenemos un ejemplo sencillo que empaqueta 100 botones de -selección en una ventana con barras de desplazamiento. Solamente he -comentado las partes que debería ser nuevas para usted. - -<tscreen><verb> -/* principio del ejemplo scrolledwin scrolledwin.c */ - -#include <gtk/gtk.h> - -void destroy(GtkWidget *widget, gpointer data) -{ - gtk_main_quit(); -} - -int main (int argc, char *argv[]) -{ - static GtkWidget *ventana; - GtkWidget *scrolled_window; - GtkWidget *table; - GtkWidget *boton; - char buffer[32]; - int i, j; - - gtk_init (&argc, &argv); - - /* Crea un nuevo cuadro de diálogo para que la ventana con barras de - * desplazamiento se meta dentro. Un cuadro de diálogo es como una - * ventana normal excepto que tiene dentro una vbox y un separador - * horizontal. Es sólo un atajo para crear cuadros de diálogo */ - ventana = gtk_dialog_new (); - gtk_signal_connect (GTK_OBJECT (ventana), "destroy", - (GtkSignalFunc) destroy, NULL); - gtk_window_set_title (GTK_WINDOW (ventana), "dialog"); - gtk_container_border_width (GTK_CONTAINER (ventana), 0); - gtk_widget_set_usize(ventana, 300, 300); - - /* crea una nueva ventana con barras de desplazamiento. */ - scrolled_window = gtk_scrolled_window_new (NULL, NULL); - - gtk_container_border_width (GTK_CONTAINER (scrolled_window), 10); - - /* la política es GTK_POLICY_AUTOMATIC, o GTK_POLICY_ALWAYS. - * GTK_POLICY_AUTOMATIC decidirá automáticamente si necesita - * barras de desplazamiento, mientras que GTK_POLICY_ALWAYS pondrá - * siempre las barras de desplazamiento. El primer argumento se - * refiere a la barra horizontal, el segundo a la vertical. */ - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), - GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); - /* El cuadro de diálogo se crea con una vbox dentro de él. */ - gtk_box_pack_start (GTK_BOX (GTK_DIALOG(ventana)->vbox), scrolled_window, - TRUE, TRUE, 0); - gtk_widget_show (scrolled_window); - - /* crea una tabla de 10 por 10 casillas. */ - table = gtk_table_new (10, 10, FALSE); - - /* pone el espacio en x y en y a 10 */ - gtk_table_set_row_spacings (GTK_TABLE (table), 10); - gtk_table_set_col_spacings (GTK_TABLE (table), 10); - - /* empaqueta la tabla en la ventana con barras de desplazamiento */ - gtk_container_add (GTK_CONTAINER (scrolled_window), table); - gtk_widget_show (table); - - /* crea una rejilla de botones de selección en la tabla para - * demostrar la ventana con barras de desplazamiento. */ - for (i = 0; i < 10; i++) - for (j = 0; j < 10; j++) { - sprintf (buffer, "botón (%d,%d)\n", i, j); - boton = gtk_toggle_button_new_with_label (buffer); - gtk_table_attach_defaults (GTK_TABLE (table), boton, - i, i+1, j, j+1); - gtk_widget_show (boton); - } - - /* Añade un botón "close" en la parte de abajo del cuadro de - * diálogo */ - boton = gtk_button_new_with_label ("close"); - gtk_signal_connect_object (GTK_OBJECT (boton), "clicked", - (GtkSignalFunc) gtk_widget_destroy, - GTK_OBJECT (ventana)); - - /* hace que el botón puede ser elegido por defecto. */ - - GTK_WIDGET_SET_FLAGS (boton, GTK_CAN_DEFAULT); - gtk_box_pack_start (GTK_BOX (GTK_DIALOG (ventana)->action_area), boton, TRUE, TRUE, 0); - - /* Hace que el botón sea el elegido por defecto. Con pulsar la - * tecla "Enter" se activará este botón. */ - gtk_widget_grab_default (boton); - gtk_widget_show (boton); - - gtk_widget_show (ventana); - - gtk_main(); - - return(0); -} -/* fin del ejemplo */ -</verb></tscreen> - -Juegue un poco redimensionando la ventana. Vea como actuan las barras -de desplazamiento. También puede utilizar la función -<tt/gtk_widget_set_usize()/ para poner el tamaño por defecto de la -ventana o de cualquier otro <em/widget/. - -<!-- XXX --> -<!-- ----------------------------------------------------------------- --> -<sect1>Cajas de botones -<p> -Las cajas de botones son útiles para crear grupos de botones. Hay -cajas horizontales y verticales. Puede crear una nueva caja de botones -utilizando alguna de las funciones siguientes, que crean -respectivamente una caja horizontal y otra vertical: - -<tscreen><verb> -GtkWidget *gtk_hbutton_box_new( void ); - -GtkWidget *gtk_vbutton_box_new( void ); -</verb></tscreen> - -Los únicos atributos pertenecientes a las cajas de botones son los -que definen como se distribuyen los botones. Puede cambiar el -espaciado que hay entre los botones con: - -<tscreen><verb> -void gtk_hbutton_box_set_spacing_default( gint spacing ); - -void gtk_vbutton_box_set_spacing_default( gint spacing ); -</verb></tscreen> - -Igualmente, se pueden obtener los actuales valores para el espaciado -utilizando: - -<tscreen><verb> -gint gtk_hbutton_box_get_spacing_default( void ); - -gint gtk_vbutton_box_get_spacing_default( void ); -</verb></tscreen> - -El segundo atributo al que podemos acceder afecta al esquema de los -botones dentro de la caja. Se establece utilizando: - -<tscreen><verb> -void gtk_hbutton_box_set_layout_default( GtkButtonBoxStyle layout ); - -void gtk_vbutton_box_set_layout_default( GtkButtonBoxStyle layout ); -</verb></tscreen> - -El argumento <tt/layout/ puede tomar uno de los siguientes valores: - -<itemize> -<item> GTK_BUTTONBOX_DEFAULT_STYLE -<item> GTK_BUTTONBOX_SPREAD -<item> GTK_BUTTONBOX_EDGE -<item> GTK_BUTTONBOX_START -<item> GTK_BUTTONBOX_END -</itemize> - -Puede obtenerse el esquema actual utilizando: - -<tscreen><verb> -GtkButtonBoxStyle gtk_hbutton_box_get_layout_default( void ); - -GtkButtonBoxStyle gtk_vbutton_box_get_layout_default( void ); -</verb></tscreen> - -Podemos añadir botones a una caja de botones utilizando (como -siempre) la función: - -<tscreen><verb> - gtk_container_add( GTK_CONTAINER(button_box), child_widget ); -</verb></tscreen> - -Aquí hay un ejemplo que ilustra todos los diferentes esquemas que -podemos utilizar con las cajas de botones. - -<tscreen><verb> -/* principio del ejemplo buttonbox buttonbox.c */ - -#include <gtk/gtk.h> - -/* Crear una Caja de Botones con los parámetros - * especificados */ -GtkWidget *create_bbox (gint horizontal, - char* title, - gint spacing, - gint child_w, - gint child_h, - gint layout) -{ - GtkWidget *frame; - GtkWidget *bbox; - GtkWidget *boton; - - frame = gtk_frame_new (title); - - if (horizontal) - bbox = gtk_hbutton_box_new (); - else - bbox = gtk_vbutton_box_new (); - - gtk_container_set_border_width (GTK_CONTAINER (bbox), 5); - gtk_container_add (GTK_CONTAINER (frame), bbox); - - /* Establece la apariencia de la Caja de Botones */ - gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), layout); - gtk_button_box_set_spacing (GTK_BUTTON_BOX (bbox), spacing); - gtk_button_box_set_child_size (GTK_BUTTON_BOX (bbox), child_w, child_h); - - boton = gtk_button_new_with_label ("OK"); - gtk_container_add (GTK_CONTAINER (bbox), boton); - - boton = gtk_button_new_with_label ("Cancel"); - gtk_container_add (GTK_CONTAINER (bbox), boton); - - boton = gtk_button_new_with_label ("Help"); - gtk_container_add (GTK_CONTAINER (bbox), boton); - - return(frame); -} - -int main( int argc, - char *argv[] ) -{ - static GtkWidget* ventana = NULL; - GtkWidget *main_vbox; - GtkWidget *vbox; - GtkWidget *hbox; - GtkWidget *frame_horz; - GtkWidget *frame_vert; - - /* Inicializa GTK */ - gtk_init( &argc, &argv ); - - ventana = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_title (GTK_WINDOW (ventana), "Button Boxes"); - - gtk_signal_connect (GTK_OBJECT (ventana), "destroy", - GTK_SIGNAL_FUNC(gtk_main_quit), - NULL); - - gtk_container_set_border_width (GTK_CONTAINER (ventana), 10); - - main_vbox = gtk_vbox_new (FALSE, 0); - gtk_container_add (GTK_CONTAINER (ventana), main_vbox); - - frame_horz = gtk_frame_new ("Horizontal Button Boxes"); - gtk_box_pack_start (GTK_BOX (main_vbox), frame_horz, TRUE, TRUE, 10); - - vbox = gtk_vbox_new (FALSE, 0); - gtk_container_set_border_width (GTK_CONTAINER (vbox), 10); - gtk_container_add (GTK_CONTAINER (frame_horz), vbox); - - gtk_box_pack_start (GTK_BOX (vbox), - create_bbox (TRUE, "Spread (spacing 40)", 40, 85, 20, GTK_BUTTONBOX_SPREAD), - TRUE, TRUE, 0); - - gtk_box_pack_start (GTK_BOX (vbox), - create_bbox (TRUE, "Edge (spacing 30)", 30, 85, 20, GTK_BUTTONBOX_EDGE), - TRUE, TRUE, 5); - - gtk_box_pack_start (GTK_BOX (vbox), - create_bbox (TRUE, "Start (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_START), - TRUE, TRUE, 5); - - gtk_box_pack_start (GTK_BOX (vbox), - create_bbox (TRUE, "End (spacing 10)", 10, 85, 20, GTK_BUTTONBOX_END), - TRUE, TRUE, 5); - - frame_vert = gtk_frame_new ("Vertical Button Boxes"); - gtk_box_pack_start (GTK_BOX (main_vbox), frame_vert, TRUE, TRUE, 10); - - hbox = gtk_hbox_new (FALSE, 0); - gtk_container_set_border_width (GTK_CONTAINER (hbox), 10); - gtk_container_add (GTK_CONTAINER (frame_vert), hbox); - - gtk_box_pack_start (GTK_BOX (hbox), - create_bbox (FALSE, "Spread (spacing 5)", 5, 85, 20, GTK_BUTTONBOX_SPREAD), - TRUE, TRUE, 0); - - gtk_box_pack_start (GTK_BOX (hbox), - create_bbox (FALSE, "Edge (spacing 30)", 30, 85, 20, GTK_BUTTONBOX_EDGE), - TRUE, TRUE, 5); - - gtk_box_pack_start (GTK_BOX (hbox), - create_bbox (FALSE, "Start (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_START), - TRUE, TRUE, 5); - - gtk_box_pack_start (GTK_BOX (hbox), - create_bbox (FALSE, "End (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_END), - TRUE, TRUE, 5); - - gtk_widget_show_all (ventana); - - /* Entra dentro del bucle de eventos */ - gtk_main (); - - return(0); -} -/* fin del ejemplo */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Barras de herramientas -<p> -Las barras de herramientas acostumbran a agrupar un conjunto de -<em>widgets</em> para hacer más sencilla la personalización -de su aspecto y composición. Típicamente una barra de herramientas -consiste en botones con iconos, etiquetas y <em/tips/ para los iconos -(pequeño texto descriptivo que aparece cuando se mantiene el ratón -sobre el icono), pero en realidad en una barra se puede poner -cualquier tipo de <em>widget</em>. Finalmente, los elementos se pueden -disponer de forma horizontal o vertical, y los botones pueden mostrar -iconos, etiquetas o ambos. - -La creación de una barra de herramientas se hace (como puede que ya -haya sospechado) mediante la función siguiente: - -<tscreen><verb> -GtkWidget *gtk_toolbar_new( GtkOrientation orientation, - GtkToolbarStyle style ); -</verb></tscreen> - -donde <tt/orientation/ puede ser: - -<tscreen><verb> - GTK_ORIENTATION_HORIZONTAL - GTK_ORIENTATION_VERTICAL -</verb></tscreen> - -y <tt/style/: - -<tscreen><verb> - GTK_TOOLBAR_TEXT - GTK_TOOLBAR_ICONS - GTK_TOOLBAR_BOTH -</verb></tscreen> - -La variable <tt/style/ se aplica a todos los botones que se crean con las -funciones `item' (pero no a los botones insertados en la barra de -herramientas como <em>widgets</em> separados). - -Después de crear una barra de herramientas, se pueden añadir, -preañadir e insertar elementos (o sea, botones) en la misma. Los -campos que describen un elemento son el texto de la etiqueta, el texto -del <em/tip/, un texto para el <em/tip/ privado, un icono para el -botón y una función de llamada para el mismo. Por ejemplo, para añadir -un elemento puede utilizar la siguiente función: - -<tscreen><verb> -GtkWidget *gtk_toolbar_append_item( GtkToolbar *toolbar, - const char *text, - const char *tooltip_text, - const char *tooltip_private_text, - GtkWidget *icon, - GtkSignalFunc callback, - gpointer user_data ); -</verb></tscreen> - -Si quiere utilizar <tt/gtk_toolbar_insert_item/, el único parámetro -adicional que debería especificar es la posición en la que quiere que -se introduzca el elemento. - -Para añadir un espacio en blanco entre los elementos de la barra de -herramientas, puede utilizar la función siguiente: - -<tscreen><verb> -void gtk_toolbar_append_space( GtkToolbar *toolbar ); - -void gtk_toolbar_prepend_space( GtkToolbar *toolbar ); - -void gtk_toolbar_insert_space( GtkToolbar *toolbar, - gint posicion ); - -</verb></tscreen> - -Y el tamaño del espacio en blanco puede establecerse globalmente -para toda una barra de herramientas con la función: - -<tscreen><verb> -void gtk_toolbar_set_space_size( GtkToolbar *toolbar, - gint space_size) ; -</verb></tscreen> - -Si tiene que establecer la orientación de una barra de herramientas y -su estilo, puede hacerlo `al vuelo' con las funciones siguientes: - -<tscreen><verb> -void gtk_toolbar_set_orientation( GtkToolbar *toolbar, - GtkOrientation orientation ); - -void gtk_toolbar_set_style( GtkToolbar *toolbar, - GtkToolbarStyle style ); - -void gtk_toolbar_set_tooltips( GtkToolbar *toolbar, - gint enable ); -</verb></tscreen> - -Para mostrar algunas otras cosas que pueden hacerse con una barra de -herramientas, vamos a ver el siguiente programa (interrumpiremos el -listado con alguna explicación adicional): - -<tscreen><verb> -#include <gtk/gtk.h> - -#include "gtk.xpm" - -/* Esta función está conectada al botón Close o a la acción de cerrar - * la ventana desde el WM */ -void delete_event (GtkWidget *widget, GdkEvent *event, gpointer data) -{ - gtk_main_quit (); -} -</verb></tscreen> - -Este principio ya debería de sonarle familiar, a no ser que éste sea -su primer programa GTK. En nuestro programa no habrá ninguna novedad, -salvo un bonito dibujo XPM que utilizaremos como icono para todos los -botones. - -<tscreen><verb> -GtkWidget* close_button; // este botón emitirá la señal de cerrar el programa -GtkWidget* tooltips_button; // para activar/desactivar los tooltips -GtkWidget* text_button, - * icon_button, - * both_button; // botones circulares para el estilo de la barra -GtkWidget* entry; // un widget para meter texto para mostrar como - // empaquetar widgets en la barra de herramientas -</verb></tscreen> - -En realidad no necesitamos todos los <em>widgets</em> que acabo de -poner, pero para aclarar las cosas un poco más los he puesto todos. - -<tscreen><verb> -/* Esto es fácil... cuando uno de los botones cambia, sólo - * tenemos que comprobar quien está activo y hacer que el estilo - * de la barra de herramientas esté acorde con la elección - * ATENCIÓN: ¡nuestra barra de herramientas es data ! -void radio_event (GtkWidget *widget, gpointer data) -{ - if (GTK_TOGGLE_BUTTON (text_button)->active) - gtk_toolbar_set_style(GTK_TOOLBAR ( data ), GTK_TOOLBAR_TEXT); - else if (GTK_TOGGLE_BUTTON (icon_button)->active) - gtk_toolbar_set_style(GTK_TOOLBAR ( data ), GTK_TOOLBAR_ICONS); - else if (GTK_TOGGLE_BUTTON (both_button)->active) - gtk_toolbar_set_style(GTK_TOOLBAR ( data ), GTK_TOOLBAR_BOTH); -} - -/* todavía más fácil, sólo hay que comprobar el botón de selección - * y activar/desactivar los tooltips */ -void toggle_event (GtkWidget *widget, gpointer data) -{ - gtk_toolbar_set_tooltips (GTK_TOOLBAR ( data ), - GTK_TOGGLE_BUTTON (widget)->active ); -} -</verb></tscreen> - -Lo de arriba son sólo dos funciones de llamada que se invocarán cuando -se presione uno de los botones de la barra de herramientas. Todo esto -ya debería resultarle familiar si ha utilizado alguna vez los botones -de selección (o los botones circulares) - -<tscreen><verb> -int main (int argc, char *argv[]) -{ - /* Aquí está nuestra ventana principal (un cuadro de diálogo) y una - * caja flotante */ - GtkWidget* dialog; - GtkWidget* handlebox; - - /* De acuerdo, necesitamos una barra de herramientas, un icono con - * una máscara (una para todos los botones) y un widget icono donde - * meter el icono (crearemos un widget diferente para cada botón) */ - GtkWidget * toolbar; - GdkPixmap * icon; - GdkBitmap * mask; - GtkWidget * iconw; - - /* a esta función se le llama en todas las aplicación GTK */ - gtk_init (&argc, &argv); - - /* crear una ventana nueva con un título y el tamaño adecuado */ - dialog = gtk_dialog_new (); - gtk_window_set_title ( GTK_WINDOW ( dialog ) , "GTKToolbar Tutorial"); - gtk_widget_set_usize( GTK_WIDGET ( dialog ) , 600 , 300 ); - GTK_WINDOW ( dialog ) ->allow_shrink = TRUE; - - /* salimos si alguien intenta cerrarnos */ - gtk_signal_connect ( GTK_OBJECT ( dialog ), "delete_event", - GTK_SIGNAL_FUNC ( delete_event ), NULL); - - /* tenemos que mandar la señalo realize porque utilizamos pixmaps - * para los elementos que hay en la barra de herramientas */ - gtk_widget_realize ( dialog ); - - /* para hacerlo más bonito ponemos la barra de herramientas en la - * caja flotante, para que así se pueda desatar de la ventana - * principal */ - handlebox = gtk_handle_box_new (); - gtk_box_pack_start ( GTK_BOX ( GTK_DIALOG(dialog)->vbox ), - handlebox, FALSE, FALSE, 5 ); -</verb></tscreen> - -Lo de arriba debería ser parecido en cualquier aplicación GTK. Sólo -está la inicialización de GTK, la creación de la ventana, etc... -Solamente hay una cosa que probablemente necesite una explicación: -una barra de herramientas flotante. Una barra de herramientas flotante -sólo es otra barra donde pueden empaquetarse <em>widgets</em>. La -diferencia que tiene con una barra típica es que puede desatarse de la -ventana padre (o, de hecho, la barra de herramientas flotante permanece -en el padre, pero reducida a un rectángulo muy pequeño, mientras que -todos sus contenidos se pasan a una nueva ventana flotante). Es bonito -tener una barra de herramientas flotante, por lo que estos dos -<em>widgets</em> suelen aparecer juntos. - -<tscreen><verb> - /* la barra de herramientas será horizontal, con iconos y texto, y - * con un espacio de 5pxl entre elementos y finalmente, la ponemos en - * nuestra caja flotante */ - toolbar = gtk_toolbar_new ( GTK_ORIENTATION_HORIZONTAL, - GTK_TOOLBAR_BOTH ); - gtk_container_border_width ( GTK_CONTAINER ( toolbar ) , 5 ); - gtk_toolbar_set_space_size ( GTK_TOOLBAR ( toolbar ), 5 ); - gtk_container_add ( GTK_CONTAINER ( handlebox ) , toolbar ); - - /* ahora creamos el icono con la máscara: utilizaremos el widget - * icon con todos los elementos de la barra de herramientas */ - icon = gdk_pixmap_create_from_xpm_d ( dialog->window, &mask, - &dialog->style->white, gtk_xpm ); -</verb></tscreen> - -Bien, lo que acabamos de escribir es la inicialización del -<em>widget</em> de la barra de herramientas y la creación de un -<em>pixmap</em> GDK con su máscara. Si quiere saber algo más sobre la -utilización de <em>pixmaps</em>, vea la documentación de GDK o la -sección <ref id="sec_Pixmaps" name="Pixmaps"> en este tutorial. - -<tscreen><verb> - /* nuestro primer elemento es el botón <close> */ - iconw = gtk_pixmap_new ( icon, mask ); // icon widget - close_button = - gtk_toolbar_append_item ( GTK_TOOLBAR (toolbar), // nuestra barra - "Close", // etiqueta del botón - "Closes this app", // tooltip para el botón - "Private", // cadena privada del tooltip - iconw, // widget del icono - GTK_SIGNAL_FUNC (delete_event), // una señal - NULL ); - gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) ); // espacio después del elemento -</verb></tscreen> - -En el trozo de código de arriba puede ver como se hace la acción más -simple: añadir un botón a la barra de herramientas. Justo antes de -añadir un nuevo elemento, tenemos que construir un <em>widget -pixmap</em> para que sirva como icono para este elemento; este paso -tendrá que repetirse para cada nuevo elemento. Después del elemento -añadiremos un espacio en blanco en la barra de herramientas, para que -los elementos que añadamos a continuación no se toquen los unos a los -otros. Como puede ver, <tt/gtk_toolbar_append_item/ devuelve un -puntero al <em>widget</em> de nuestro nuevo botón recien creado, por -lo que podremos trabajar con él como siempre. - -<tscreen><verb> - /* ahora, vamos a hacer nuestro grupo de botones circulares... */ - iconw = gtk_pixmap_new ( icon, mask ); - icon_button = - gtk_toolbar_append_element(GTK_TOOLBAR(toolbar), - GTK_TOOLBAR_CHILD_RADIOBUTTON, // un tipo de elemento - NULL, // puntero al widget - "Icon", // etiqueta - "Only icons in toolbar", // tooltip - "Private", // cadena privada del tooltip - iconw, // icono - GTK_SIGNAL_FUNC (radio_event), // señal - toolbar); // dato para la señal - gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) ); -</verb></tscreen> - -Aquí empezamos creando un grupo de botones circulares. Para hacerlo -hemos utilizado <tt/gtk_toolbar_append_element/. De hecho, utilizando -esta función se pueden añadir tanto elementos simples como espacios en -blanco (tipo = GTK_TOOLBAR_CHILD_SPACE o GTK_TOOLBAR_CHILD_BUTTON). En -el caso de arriba, hemos empezado creando un grupo de botones circulares. -Para crear más botones circulares para este grupo -necesitaremos un puntero al botón anterior del grupo, mediante el que -podremos construir fácilmente una lista de botones (ver la sección -<ref id="sec_Radio_Buttons" name="Botones circulares"> que se encuentra -más adelante en este tutorial). - -<tscreen><verb> - /* los botones circulares que vienen a continuación están - relacionados con los anteriores */ - iconw = gtk_pixmap_new ( icon, mask ); - text_button = - gtk_toolbar_append_element(GTK_TOOLBAR(toolbar), - GTK_TOOLBAR_CHILD_RADIOBUTTON, - icon_button, - "Text", - "Only texts in toolbar", - "Private", - iconw, - GTK_SIGNAL_FUNC (radio_event), - toolbar); - gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) ); - - iconw = gtk_pixmap_new ( icon, mask ); - both_button = - gtk_toolbar_append_element(GTK_TOOLBAR(toolbar), - GTK_TOOLBAR_CHILD_RADIOBUTTON, - text_button, - "Both", - "Icons and text in toolbar", - "Private", - iconw, - GTK_SIGNAL_FUNC (radio_event), - toolbar); - gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) ); - gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(both_button),TRUE); -</verb></tscreen> - -Al final hemos activado manualmente uno de los botones (en caso -contrario los botones permanecerían todos en estado activo, -impidiéndonos poder cambiar de uno a otro). - -<tscreen><verb> - /* aquí tenemos un sencillo botón de selección */ - iconw = gtk_pixmap_new ( icon, mask ); - tooltips_button = - gtk_toolbar_append_element(GTK_TOOLBAR(toolbar), - GTK_TOOLBAR_CHILD_TOGGLEBUTTON, - NULL, - "Tooltips", - "Toolbar with or without tips", - "Private", - iconw, - GTK_SIGNAL_FUNC (toggle_event), - toolbar); - gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) ); - gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(tooltips_button),TRUE); -</verb></tscreen> - -Un botón de selección puede crearse de una forma obvia (si ya sabe como -crear botones circulares). - -<tscreen><verb> - /* para empaquetar un widget en la barra de herramientas, sólo - * tenemos que crearlo y añadirlo en la barra con el tooltip - * apropiado */ - entry = gtk_entry_new (); - gtk_toolbar_append_widget( GTK_TOOLBAR (toolbar), - entry, - "This is just an entry", - "Private" ); - - /* bien, no se ha creado con la barra, así que debemos mostrarlo - * explicitamente */ - gtk_widget_show ( entry ); -</verb></tscreen> - -Como puede ver, añadir cualquier tipo de <em>widget</em> a la barra -de herramientas es fácil. Lo único que debe recordar es que este -<em>widget</em> debe mostrarse manualmente (al contrario que los demás -elementos que se mostrarán junto con la barra de herramientas). - -<tscreen><verb> - /* ¡ Eso es ! mostremos algo. */ - gtk_widget_show ( toolbar ); - gtk_widget_show (handlebox); - gtk_widget_show ( dialog ); - - /* quedémonos en gtk_main y ¡esperemos a que empiece la diversión! */ - gtk_main (); - - return 0; -} -</verb></tscreen> - -Y ya estamos en el final del tutorial sobre la barra de herramientas. -Por supuesto, para apreciar completamente el ejemplo, necesita además -del código este precioso icono XPM que le mostramos a continuación: - -<tscreen><verb> -/* XPM */ -static char * gtk_xpm[] = { -"32 39 5 1", -". c none", -"+ c black", -"@ c #3070E0", -"# c #F05050", -"$ c #35E035", -"................+...............", -"..............+++++.............", -"............+++++@@++...........", -"..........+++++@@@@@@++.........", -"........++++@@@@@@@@@@++........", -"......++++@@++++++++@@@++.......", -".....+++@@@+++++++++++@@@++.....", -"...+++@@@@+++@@@@@@++++@@@@+....", -"..+++@@@@+++@@@@@@@@+++@@@@@++..", -".++@@@@@@+++@@@@@@@@@@@@@@@@@@++", -".+#+@@@@@@++@@@@+++@@@@@@@@@@@@+", -".+##++@@@@+++@@@+++++@@@@@@@@$@.", -".+###++@@@@+++@@@+++@@@@@++$$$@.", -".+####+++@@@+++++++@@@@@+@$$$$@.", -".+#####+++@@@@+++@@@@++@$$$$$$+.", -".+######++++@@@@@@@++@$$$$$$$$+.", -".+#######+##+@@@@+++$$$$$$@@$$+.", -".+###+++##+##+@@++@$$$$$$++$$$+.", -".+###++++##+##+@@$$$$$$$@+@$$@+.", -".+###++++++#+++@$$@+@$$@++$$$@+.", -".+####+++++++#++$$@+@$$++$$$$+..", -".++####++++++#++$$@+@$++@$$$$+..", -".+#####+++++##++$$++@+++$$$$$+..", -".++####+++##+#++$$+++++@$$$$$+..", -".++####+++####++$$++++++@$$$@+..", -".+#####++#####++$$+++@++++@$@+..", -".+#####++#####++$$++@$$@+++$@@..", -".++####++#####++$$++$$$$$+@$@++.", -".++####++#####++$$++$$$$$$$$+++.", -".+++####+#####++$$++$$$$$$$@+++.", -"..+++#########+@$$+@$$$$$$+++...", -"...+++########+@$$$$$$$$@+++....", -".....+++######+@$$$$$$$+++......", -"......+++#####+@$$$$$@++........", -".......+++####+@$$$$+++.........", -".........++###+$$$@++...........", -"..........++##+$@+++............", -"...........+++++++..............", -".............++++..............."}; -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1> Libros de notas (<em/Notebooks/) -<p> -El <em/widget/ Notebook es una colección de `páginas' que se solapan -las unas a las otras, cada una con un contenido diferente. Este -<em/widget/ se ha vuelto cada vez más común últimamente en la -programación de interfaces gráficos de usuario (GUI en inglés), y es -una buena forma de mostrar bloques de información similar que -necesitan aparecer de forma separada. - -La primera función que necesita conocer, como probablemente ya habrá -adivinado, se utiliza para crear un nuevo <em/widget/ notebook. - -<tscreen><verb> -GtkWidget *gtk_notebook_new( void ); -</verb></tscreen> - -Una vez haya crear el libro de notas, hay 12 funciones que se pueden -utilizar para trabajar con él. Echémosles un vistazo una a una. - -La primera que estudiaremos será la que nos permita establecer la -posición de los indicadores de la página. Estos indicadores se pueden -poner en cuatro lugares diferentes: arriba, abajo, a la derecha o a la -izquierda. - -<tscreen><verb> -void gtk_notebook_set_tab_pos( GtkNotebook *notebook, - GtkPositionType pos ); -</verb></tscreen> - -<tt/GtkPositionType/ debe tener uno de los valores siguientes (su significado -está bastante claro): - -<itemize> -<item> GTK_POS_LEFT -<item> GTK_POS_RIGHT -<item> GTK_POS_TOP -<item> GTK_POS_BOTTOM -</itemize> - -GTK_POS_TOP es el valor por defecto. - -Lo siguiente que estudiaremos es como añadir páginas al libro de notas. -Hay tres formas de añadirle páginas al <em/widget/. Veamos las dos primeras -formas (son muy parecidas). - -<tscreen><verb> -void gtk_notebook_append_page( GtkNotebook *notebook, - GtkWidget *hijo, - GtkWidget *tab_label ); - -void gtk_notebook_prepend_page( GtkNotebook *notebook, - GtkWidget *hijo, - GtkWidget *tab_label ); -</verb></tscreen> - -Estas funciones le añaden páginas al libro de notas insertándolas desde -el fondo del libro (añadiéndolas), o desde parte superior del libro -(preañadiéndolas). <tt/hijo/ es el <em/widget/ que se mete en la página -del libro de notas, y <tt/tab_label/ es la etiqueta para la página que -estamos añadiendo. - -La función que queda que sirve para añadir una página contiene todas las -propiedades de las anteriores, pero además permite especificar en que -posición quiere que esté la página dentro del libro de notas. - -<tscreen><verb> -void gtk_notebook_insert_page( GtkNotebook *notebook, - GtkWidget *hijo, - GtkWidget *tab_label, - gint posicion ); -</verb></tscreen> - -Los parámetros son los mismos que habían en las funciones _append_ y -_prepend_ excepto que hay uno más que antes, <tt/posicion/. Este -parámetro se utiliza para especificar en que lugar debe introducirse -la página. - -Ahora que sabemos como añadir un página, veamos como podemos eliminar -una página del libro de notas. - -<tscreen><verb> -void gtk_notebook_remove_page( GtkNotebook *notebook, - gint page_num ); -</verb></tscreen> - -Esta función coge la página especificada por <tt/page_num/ y la -elimina del <em/widget/ al que apunta <tt/notebook/. - -Para saber cual es la página actual del libro de notas utilice la -función: - -<tscreen><verb> -gint gtk_notebook_current_page( GtkNotebook *notebook ); -</verb></tscreen> - -Las dos funciones siguientes sirven para ir a la página siguiente o a -la anterior del libro de notas. Para utilizarlas sólo hay que -proporcionar el <em/widget/ notebook que queremos manipular. Nota: -cuando el libro de notas está en la última página y se llama a -<tt/gtk_notebook_next_page/, se pasará a la primera página. Sin -embargo, si el libro de notas está en la primera página, y se llama a -<tt/gtk_notebook_prev_page/, no se pasará a la última página. - -<tscreen><verb> -void gtk_notebook_next_page( GtkNoteBook *notebook ); - -void gtk_notebook_prev_page( GtkNoteBook *notebook ); -</verb></tscreen> - -La siguiente función establece la página `activa'. Si quiere que se -abra el libro de notas por la página 5, por ejemplo, debe utilizar -esta función. Si no utiliza esta función el libro de notas empezará -por defecto en la primera página. - -<tscreen><verb> -void gtk_notebook_set_page( GtkNotebook *notebook, - gint page_num ); -</verb></tscreen> - -Las dos funciones siguientes añaden o eliminan los indicadores de las -páginas o el borde del libro, respectivamente. - -<tscreen><verb> -void gtk_notebook_set_show_tabs( GtkNotebook *notebook, - gint show_tabs); - -void gtk_notebook_set_show_border( GtkNotebook *notebook, - gint show_border ); -</verb></tscreen> - -<tt/show_tabs/ y <tt/show_border/ puede ser TRUE o FALSE. - -Ahora echémosle un vistaza a un ejemplo, sacado del código de -<tt/testgtk.c/ que viene con la distribución de GTK, y que muestra -la utilización de las 13 funciones. Este pequeño programa crea una -ventana con un libro de notas y seis botones. El libro de notas -contiene 11 páginas, incluidas de tres formas diferentes, añadidas, -insertadas, y preañadidas. Los botones le permiten rotar las -posiciones de los indicadores, añadir y eliminar los indicadores y el -borde, eliminar una página, cambiar páginas hacia delante y hacia -detrás, y salir del programa. - -<tscreen><verb> -/* principio del ejemplo notebook notebook.c */ - -#include <gtk/gtk.h> - -/* Esta función rota la posición de los indicadores */ -void rotate_book (GtkButton *boton, GtkNotebook *notebook) -{ - gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos +1) %4); -} - -/* Añade/Elimina los indicadores de la página y los bordes */ -void tabsborder_book (GtkButton *boton, 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); -} - -/* Elimina una página del libro de notas */ -void remove_book (GtkButton *boton, GtkNotebook *notebook) -{ - gint page; - - page = gtk_notebook_current_page(notebook); - gtk_notebook_remove_page (notebook, page); - /* Hay que redibujar el widget -- - Esto fuerza que el widget se autoredibuje */ - gtk_widget_draw(GTK_WIDGET(notebook), NULL); -} - -void delete (GtkWidget *widget, GtkWidget *event, gpointer data) -{ - gtk_main_quit (); -} - -int main (int argc, char *argv[]) -{ - GtkWidget *ventana; - GtkWidget *boton; - GtkWidget *table; - GtkWidget *notebook; - GtkWidget *frame; - GtkWidget *etiqueta; - GtkWidget *checkbutton; - int i; - char bufferf[32]; - char bufferl[32]; - - gtk_init (&argc, &argv); - - ventana = gtk_window_new (GTK_WINDOW_TOPLEVEL); - - gtk_signal_connect (GTK_OBJECT (ventana), "delete_event", - GTK_SIGNAL_FUNC (delete), NULL); - - gtk_container_border_width (GTK_CONTAINER (ventana), 10); - - table = gtk_table_new(2,6,TRUE); - gtk_container_add (GTK_CONTAINER (ventana), table); - - /* Crea un nuevo libro de notas, indicando la posición de los - indicadores */ - 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); - - /* le añadimos un montón de páginas al libro de notas */ - 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); - - etiqueta = gtk_label_new (bufferf); - gtk_container_add (GTK_CONTAINER (frame), etiqueta); - gtk_widget_show (etiqueta); - - etiqueta = gtk_label_new (bufferl); - gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, etiqueta); - } - - - /* Ahora añadimos una página en punto específico */ - checkbutton = gtk_check_button_new_with_label ("Check me please!"); - gtk_widget_set_usize(checkbutton, 100, 75); - gtk_widget_show (checkbutton); - - etiqueta = gtk_label_new ("Add spot"); - gtk_container_add (GTK_CONTAINER (checkbutton), etiqueta); - gtk_widget_show (etiqueta); - etiqueta = gtk_label_new ("Add page"); - gtk_notebook_insert_page (GTK_NOTEBOOK (notebook), checkbutton, etiqueta, 2); - - /* Y finalmente preañadimos páginas en el libro de notas */ - 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); - - etiqueta = gtk_label_new (bufferf); - gtk_container_add (GTK_CONTAINER (frame), etiqueta); - gtk_widget_show (etiqueta); - - etiqueta = gtk_label_new (bufferl); - gtk_notebook_prepend_page (GTK_NOTEBOOK(notebook), frame, etiqueta); - } - - /* Decimos en que página empezar (página 4) */ - gtk_notebook_set_page (GTK_NOTEBOOK(notebook), 3); - - - /* creamos un montón de botones */ - boton = gtk_button_new_with_label ("close"); - gtk_signal_connect_object (GTK_OBJECT (boton), "clicked", - GTK_SIGNAL_FUNC (delete), NULL); - gtk_table_attach_defaults(GTK_TABLE(table), boton, 0,1,1,2); - gtk_widget_show(boton); - - boton = gtk_button_new_with_label ("next page"); - gtk_signal_connect_object (GTK_OBJECT (boton), "clicked", - (GtkSignalFunc) gtk_notebook_next_page, - GTK_OBJECT (notebook)); - gtk_table_attach_defaults(GTK_TABLE(table), boton, 1,2,1,2); - gtk_widget_show(boton); - - boton = gtk_button_new_with_label ("prev page"); - gtk_signal_connect_object (GTK_OBJECT (boton), "clicked", - (GtkSignalFunc) gtk_notebook_prev_page, - GTK_OBJECT (notebook)); - gtk_table_attach_defaults(GTK_TABLE(table), boton, 2,3,1,2); - gtk_widget_show(boton); - - boton = gtk_button_new_with_label ("tab position"); - gtk_signal_connect_object (GTK_OBJECT (boton), "clicked", - (GtkSignalFunc) rotate_book, GTK_OBJECT(notebook)); - gtk_table_attach_defaults(GTK_TABLE(table), boton, 3,4,1,2); - gtk_widget_show(boton); - - boton = gtk_button_new_with_label ("tabs/border on/off"); - gtk_signal_connect_object (GTK_OBJECT (boton), "clicked", - (GtkSignalFunc) tabsborder_book, - GTK_OBJECT (notebook)); - gtk_table_attach_defaults(GTK_TABLE(table), boton, 4,5,1,2); - gtk_widget_show(boton); - - boton = gtk_button_new_with_label ("remove page"); - gtk_signal_connect_object (GTK_OBJECT (boton), "clicked", - (GtkSignalFunc) remove_book, - GTK_OBJECT(notebook)); - gtk_table_attach_defaults(GTK_TABLE(table), boton, 5,6,1,2); - gtk_widget_show(boton); - - gtk_widget_show(table); - gtk_widget_show(ventana); - - gtk_main (); - - return 0; -} -/* fin del ejemplo */ -</verb></tscreen> - -Espero que la explicación le ayude de alguna manera a crear libros de -notas en sus aplicaciones GTK. - -<!-- ***************************************************************** --> -<sect> El <em/widget/ GtkCList -<!-- ***************************************************************** --> -<!-- ----------------------------------------------------------------- --> -<p> -El <em>widget</em> GtkCList ha reemplazado al <em>widget</em> GtkList -(que sigue estando disponible). - -El <em>widget</em> GtkCList es un <em>widget</em> de una lista -multicolumna que es capaz de manejar, literalmente, miles de filas de -información. Cada columna puede tener (opcionalmente) un título, que -puede estar activado (opcionalmente), permitiéndonos enlazar una -función con la selección. - -<!-- ----------------------------------------------------------------- --> -<sect1>Creando un <em>widget</em> GtkCList -<p> -Crear un GtkCList es algo bastante sencillo, una vez que sabe como -crear un <em>widget</em> en general. Se proporcionan al menos dos -formas estándar de crearlo, la forma fácil y la forma difícil. Pero -antes de crear una GtkCList, hay una cosa que debemos saber: ¿Cuántas -columnas va a tener? - -No todas las columnas tienen que ser visibles y pueden utilizarse para -almacenar datos que estén relacionados con una cierta celda de la -lista. - -<tscreen><verb> -GtkWidget *gtk_clist_new ( gint columns ); - -GtkWidget *gtk_clist_new_with_titles( gint columns, - gchar *titles[] ); -</verb></tscreen> - -Esta primera aproximación al problema es muy sencilla, pero la segunda -requerirá alguna explicación adicional. Cada columna puede tener un -título asociado. Si utilizamos la segunda forma, deberemos proporcionar -punteros al texto del título, y el número de punteros debe ser igual -al número de columnas especificadas. Por supuesto, siempre podemos -utilizar la primera forma de creación y añadir más tarde los títulos -de forma manual. - -<!-- ----------------------------------------------------------------- --> -<sect1>Modos de operación -<p> -Hay varios atributos que pueden utilizarse para alterar el aspecto -de un GtkCList. Primero tenemos - -<tscreen><verb> -void gtk_clist_set_selection_mode( GtkCList *clist, - GtkSelectionMode mode ); -</verb></tscreen> - -que, como el propio nombre indica, establece el modo de selección de la -lista GtkCList. El primer argumento es el <em>widget</em> GtkCList, y el -segundo especifica el modo de selección de la celda (están definidos -en <tt/gtkenums.h/). En el momento de escribir esto, estaban -disponibles los siguientes modos: - -<itemize> -<item> GTK_SELECTION_SINGLE - La selección o es NULL o contiene un -puntero GList a un elemento seleccionado. - -<item> GTK_SELECTION_BROWSE - La selección es NULL si la lista no -contiene <em>widgets</em> o si los que contiene son insensibles, en -caso contrario contendrá un puntero GList hacia una estructura GList, -y por tanto con exactamente un elemento. - -<item> GTK_SELECTION_MULTIPLE - La selección es NULL si no hay -seleccionados una lista de elementos o un puntero GList para el primer -elemento seleccionado.<!-- FIXME: Todo esto no se si tiene sentido --> -Éste apunta de nuevo a una estructura GList para el segundo elemento -seleccionado y continua así. Éste es, actualmente, el modo por -<bf>defecto</bf> para el <em>widget</em> GtkCList. - -<item> GTK_SELECTION_EXTENDED - La selección siempre es NULL. -</itemize> - -Puede que se añadan otros modos en versiones posteriores de GTK. - -También tenemos - -<tscreen><verb> -void gtk_clist_set_policy (GtkCList *clist, - GtkPolicyType vscrollbar_policy, - GtkPolicyType hscrollbar_policy); -</verb></tscreen> - -que define que es lo que ocurre con las barras de desplazamiento. Los -siguientes valores son los posibles para las barras de desplazamiento -horizontal y vertical: - -<itemize> -<item> GTK_POLICY_ALWAYS - La barra de desplazamiento siempre está ahí. - -<item> GTK_POLICY_AUTOMATIC - La barra de desplazamiento estará ahí sólo -cuando el número de elementos en la GtkCList supere el número que puede -mostrarse en el <em>widget</em>. -</itemize> - -También podemos definir como debería ser el aspecto del borde del -<em>widget</em> GtkCList. Esto lo podemos hacer mediante - -<tscreen><verb> -void gtk_clist_set_border( GtkCList *clist, - GtkShadowType border ); -</verb></tscreen> - -Y los posibles valores para el segundo argumento son - -<itemize> -<item> GTK_SHADOW_NONE - -<item> GTK_SHADOW_IN - -<item> GTK_SHADOW_OUT - -<item> GTK_SHADOW_ETCHED_IN - -<item> GTK_SHADOW_ETCHED_OUT -</itemize> - -<!-- ----------------------------------------------------------------- --> -<sect1>Trabajando con los títulos -<p> -Cuando cree un <em>widget</em> GtkCList, también obtendrá -automáticamente un conjunto de botones título. Vivirán en lo alto de -una ventana CList, y pueden actuar como botones normales que responden -cuando se pulsa sobre ellos, o bien pueden ser pasivos, en cuyo caso -no serán nada más que un título. Hay cuatro llamadas diferentes que -nos ayudarán a establecer el estado de los botones título. - -<tscreen><verb> -void gtk_clist_column_title_active( GtkCList *clist, - gint column ); - -void gtk_clist_column_title_passive( GtkCList *clist, - gint column ); - -void gtk_clist_column_titles_active( GtkCList *clist ); - -void gtk_clist_column_titles_passive( GtkCList *clist ); -</verb></tscreen> - -Un título activo es aquel que actua como un botón normal, y uno pasivo -es sólo una etiqueta. Las primeras dos llamadas de arriba -activarán/desactivarán el botón título correspondiente a la columna -<tt/column/, mientras que las dos llamadas siguientes -activarán/desactivarán todos los botones título que hayan en el -<em>widget</em> <tt/clist/ que se le proporcione a la función. - -Pero, por supuesto, habrá casos en el que no querremos utilizar los -botones título, así que también tenemos la posibilidad de ocultarlos y -de volverlos a mostrar utilizando las dos llamadas siguientes: - -<tscreen><verb> -void gtk_clist_column_titles_show( GtkCList *clist ); - -void gtk_clist_column_titles_hide( GtkCList *clist ); -</verb></tscreen> - -Para que los títulos sean realmente útiles necesitamos un mecanismo -que nos permita darles el valor que nosotros queramos y cambiar ese -valor, y podremos hacerlo mediante - -<tscreen><verb> -void gtk_clist_set_column_title( GtkCList *clist, - gint column, - gchar *title ); -</verb></tscreen> - -Debe llevar cuidado, ya que sólo se puede especificar el título de una -columna a la vez, por lo que si conoce todos los títulos desde el -principio, le sugiero que utilice <tt/gtk_clist_new_with_titles/ (como -se describe arriba) para establecerlos adecuadamente. Le ahorrará -tiempo de programación, y hará su programa más pequeño. Hay algunos -casos donde es mejor utilizar la forma manual, y uno de ellos es -cuando no todos los títulos son texto. GtkCList nos proporciona -botones título que pueden, de hecho, incorporar un <em>widget</em> -entero, por ejemplo un <em>pixmap</em>. Todo esto se hace mediante - -<tscreen><verb> -void gtk_clist_set_column_widget( GtkCList *clist, - gint column, - GtkWidget *widget ); -</verb></tscreen> - -que no debería necesitar de explicaciones adicionales. - -<!-- ----------------------------------------------------------------- --> -<sect1>Manipulando la lista en sí. -<p> -Es posible cambiar la justificación de una columna, y esto se hace -mediante - -<tscreen><verb> -void gtk_clist_set_column_justification( GtkCList *clist, - gint column, - GtkJustification justification ); -</verb></tscreen> - -El tipo GtkJustification puede tomar los valores siguientes: - -<itemize> -<item>GTK_JUSTIFY_LEFT - El texto en la columna empezará desde el lado -izquierdo. - -<item>GTK_JUSTIFY_RIGHT - El texto en la columna empezará desde el -lado derecho. - -<item>GTK_JUSTIFY_CENTER - El texto se colocará en el centro de la -columna. - -<item>GTK_JUSTIFY_FILL - El texto utilizará todo el espacio disponible -en la columna. Normalmente se hace añadiendo espacios en blanco entre -las palabras (o entre letras por separado, si se trata de una sola -palabra). Más o menos de la misma forma en la que lo hace un -procesador de textos WYSIWYG. -</itemize> - -La siguiente función es muy importante, y debería ser un estándar -para inicializar todos los <em>widgets</em> GtkCList. Cuando se crea -la lista, los anchos de las distintas columnas se eligen para que -coincidan con sus títulos, y éste es el ancho adecuado que tenemos que -poner, utilizando - -<tscreen><verb> -void gtk_clist_set_column_width( GtkCList *clist, - gint column, - gint width ); -</verb></tscreen> - -Observe que el ancho viene dado en pixeles y no en letras. Lo mismo -vale para el alto de la celda en las columnas, pero como el valor por -defecto es la altura del tipo de letra actual, no es algo tan crítico -para la aplicación. De todas formas, la altura se cambia mediante - -<tscreen><verb> -void gtk_clist_set_row_height( GtkCList *clist, - gint height ); -</verb></tscreen> - -De nuevo, hay que advertir que el ancho viene dado en pixeles. - -También podemos ir hacia un elemento sin la intervención del usuario, -sin embargo hace falta que sepamos hacia donde queremos ir. O en otras -palabras, necesitamos la fila y la columna del elemento al que queremos -pasar. - -<tscreen><verb> -void gtk_clist_moveto( GtkCList *clist, - gint row, - gint column, - gfloat row_align, - gfloat col_align ); -</verb></tscreen> - -Es importante comprender bien el significado de <tt/gfloat -row_align/. Tiene un valor entre 0.0 y 1.0, donde 0.0 significa que -debemos hacer que la fila seleccionada aparezca en la alto de la -lista, mientras que 1.0 significa que la fila aparecerá en la parte de -abajo. El resto de valores entre 0.0 y 1.0 son válidos y harán que la -fila aparezca entre la parte superior y la inferior. El último -argumento, <tt/gfloat col_align/ funciona igual, siendo 0.0 la -izquierda y 1.0 la derecha. - -Dependiendo de las necesidades de la aplicación, puede que no tengamos -que hacer un desplazamiento hacia un elemento que ya sea visible. Por -tanto, ¿cómo podemos saber si ya es visible? Como siempre, hay una función -que sirve para averiguarlo - -<tscreen><verb> -GtkVisibility gtk_clist_row_is_visible( GtkCList *clist, - gint row ); -</verb></tscreen> - -El valor devuelto es uno de los siguientes: - -<itemize> -<item>GTK_VISIBILITY_NONE - -<item>GTK_VISIBILITY_PARTIAL - -<item>GTK_VISIBILITY_FULL -</itemize> - -Como puede ver, sólo nos dice si una fila es visible. Actualmente no hay -ninguna forma de obtener el mismo dato para una columna. Sin embargo -podemos obtener información parcial, porque si el valor devuelto es -GTK_VISIBILITY_PARTIAL, entonces es que alguna parte está oculta, -pero no sabemos si es la fila que está cortada por la parte de abajo -de la lista, o si la fila tiene columnas que están fuera. - -También podemos cambiar el color del primer y del segundo plano de una -fila en particular. Esto es útil para marcar la fila seleccionada por -el usuario, y las dos funciones que hay que utilizar son - -<tscreen><verb> -void gtk_clist_set_foreground( GtkCList *clist, - gint row, - GdkColor *color ); - -void gtk_clist_set_background( GtkCList *clist, - gint row, - GdkColor *color ); -</verb></tscreen> - -Cuidado, ya que los colores deben estar asignados previamente en la -memoria. - -<!-- ----------------------------------------------------------------- --> -<sect1>Añadiendo filas a la lista -<p> -Podemos añadir filas de dos formas. Se pueden añadir al final de la lista -utilizando - -<tscreen><verb> -gint gtk_clist_append( GtkCList *clist, - gchar *text[] ); -</verb></tscreen> - -o podemos insertar una fila en un lugar determinado utilizando - -<tscreen><verb> -void gtk_clist_insert( GtkCList *clist, - gint row, - gchar *text[] ); -</verb></tscreen> - -En ambas llamadas podemos proporcionar un conjunto de punteros que -serán los textos que queremos poner en las columnas. El número de -punteros debe ser igual al número de columnas en la lista. Si el -argumento <tt/text[]/ es NULL, entonces no habrá texto en las columnas -de la fila. Esto sería útil, por ejemplo, si queremos añadir -<em>pixmaps</em> en lugar de texto (en general para cualquier cosa que -haya que hacer manualmente). - -De nuevo, cuidado ya que el número de filas y de columnas comienza en -0. - -Para eliminar una fila individual podemos utilizar - -<tscreen><verb> -void gtk_clist_remove( GtkCList *clist, - gint row ); -</verb></tscreen> - -Hay también una llamada que elimina todas las filas en la lista. -Es mucho más rápido que llamar a <tt/gtk_clist_remove/ una vez por -cada fila, que sería la única alternativa. - -<tscreen><verb> -void gtk_clist_clear( GtkCList *clist ); -</verb></tscreen> - -También hay dos funciones que es conveniente utilizarlas cuando hay -que hacerle muchos cambios a una lista. Son para evitar que la lista -parpadee mientras es actualizada repetidamente, que puede ser muy -molesto para el usuario. Por tanto es una buena idea congelar la -lista, hacer los cambios, y descongelarla, que hará que la lista se -actualice en la pantalla. - -<tscreen><verb> -void gtk_clist_freeze( GtkCList * clist ); - -void gtk_clist_thaw( GtkCList * clist ); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Poniendo texto y <em>pixmaps</em> en las celdas -<p> -Una celda puede contener un <em>pixmap</em>, texto o ambos. Para ponerlos -en las celdas, podemos utilizar las siguientes funciones. - -<tscreen><verb> -void gtk_clist_set_text( GtkCList *clist, - gint row, - gint column, - gchar *text ); - -void gtk_clist_set_pixmap( GtkCList *clist, - gint row, - gint column, - GdkPixmap *pixmap, - GdkBitmap *mask ); - -void gtk_clist_set_pixtext( GtkCList *clist, - gint row, - gint column, - gchar *text, - guint8 spacing, - GdkPixmap *pixmap, - GdkBitmap *mask ); -</verb></tscreen> - -Son bastante sencillas de entender. Todas las llamadas tienen la -GtkCList como primer argumento, seguidas por la fila y la columna -de la celda, y seguidas por el dato que debe ponerse en la celda. El -argumento <tt/gint8 spacing/ en <tt/gtk_clist_set_pixtext/ es el -número de <em>pixels</em> entre el <em>pixmap</em> y el principio del -texto. - -Para leer los datos que hay en una celda, podemos utilizar - -<tscreen><verb> -gint gtk_clist_get_text( GtkCList *clist, - gint row, - gint column, - gchar **text ); - -gint gtk_clist_get_pixmap( GtkCList *clist, - gint row, - gint column, - GdkPixmap **pixmap, - GdkBitmap **mask ); - -gint gtk_clist_get_pixtext( GtkCList *clist, - gint row, - gint column, - gchar **text, - guint8 *spacing, - GdkPixmap **pixmap, - GdkBitmap **mask ); -</verb></tscreen> - -No es necesario leer todos los datos en caso de que no estemos -interesados. Cualquiera de los punteros que se supone contendrán los -valores a devolver (cualquiera excepto el <tt/clist/) pueden ser -NULL. Por lo que si sólo queremos leer el texto de una celda que es de -tipo <tt/pixtext/, deberíamos hacer lo siguiente, suponiendo que -<tt/clist/, <tt/row/ y <tt/column/ ya existan: - -<tscreen><verb> -gchar *mytext; - -gtk_clist_get_pixtext(clist, row, column, &mytext, NULL, NULL, NULL); -</verb></tscreen> - -Hay una rutina más que está relacionada con lo que está dentro -de una celda de una <tt/clist/, y es - -<tscreen><verb> -GtkCellType gtk_clist_get_cell_type( GtkCList *clist, - gint row, - gint column ); -</verb></tscreen> - -que devuelve el tipo de datos que hay en la celda. El valor devuelto es -uno de los siguientes - -<itemize> -<item>GTK_CELL_EMPTY - -<item>GTK_CELL_TEXT - -<item>GTK_CELL_PIXMAP - -<item>GTK_CELL_PIXTEXT - -<item>GTK_CELL_WIDGET -</itemize> - -También hay una función que nos permite especificar la indentación de -un celda (horizontal o vertical). El valor de la indentación es del -tipo <tt/gint/, viene dado en <em>pixeles</em>, y puede ser positivo o -negativo. - -<tscreen><verb> -void gtk_clist_set_shift( GtkCList *clist, - gint row, - gint column, - gint vertical, - gint horizontal ); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Almacenando punteros a datos -<p> -Con una GtkCList es posible poner un puntero a datos en una -fila. Este puntero no será visible al usuario, pero puede serle útil -al programador. - -De nuevo, las funciones son lo suficientemente autoexplicativas - -<tscreen><verb> -void gtk_clist_set_row_data( GtkCList *clist, - gint row, - gpointer data ); - -void gtk_clist_set_row_data_full( GtkCList *clist, - gint row, - gpointer data, - GtkDestroyNotify destroy ); - -gpointer gtk_clist_get_row_data( GtkCList *clist, - gint row ); - -gint gtk_clist_find_row_from_data( GtkCList *clist, - gpointer data ); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Trabajando con la selección -<p> -También hay funciones que nos permiten forzar la (de)selección de una -fila. Son - -<tscreen><verb> -void gtk_clist_select_row( GtkCList *clist, - gint row, - gint column ); - -void gtk_clist_unselect_row( GtkCList *clist, - gint row, - gint column ); -</verb></tscreen> - -Y también una función que tomará las coordenadas x e y (por ejemplo, -recibidas del ratón), mirará en la lista y devolverá la fila y la -columna que les corresponden. - -<tscreen><verb> -gint gtk_clist_get_selection_info( GtkCList *clist, - gint x, - gint y, - gint *row, - gint *column ); -</verb></tscreen> - -Cuando detectemos algo interesante, como por ejemplo el movimiento del -ratón, o una pulsación en cualquier lugar de la lista, podemos leer -las coordenadas del ratón y encontrar en que elemento de la lista se -encuentra. ¿Engorroso? Afortunadamente, hay una forma más sencilla de -hacer las cosas... - -<!-- ----------------------------------------------------------------- --> -<sect1>Las señales que lo hacen todo -<p> -Como con el resto de <em>widgets</em>, hay unas cuantas señales que -podemos utilizar. El <em>widget</em> GtkCList está derivado del -<em>widget</em> GtkContainer, y por tanto tiene las mismas -señales que éste, pero además añade las siguientes: - -<itemize> -<item><tt/select_row/ - Esta señal enviará la siguiente información, -en este orden: GtkCList *clist, gint row, gint column, GtkEventButton -*event - -<item><tt/unselect_row/ - Cuando el usuario deselecciona una fila, se -activará esta señal. Envia la misma información que <tt/select_row/ - -<item><tt/click_column/ - Envia GtkCList *clist, gint column -</itemize> - -Por tanto si queremos conectar una llamada a <tt/select_row/, la -llamada se deberá declarar como - -<tscreen><verb> -void select_row_callback(GtkWidget *widget, - gint row, - gint column, - GdkEventButton *event, - gpointer data); -</verb></tscreen> - -La llamada se conectará, como siempre, con - -<tscreen><verb> -gtk_signal_connect(GTK_OBJECT( clist), - "select_row" - GTK_SIGNAL_FUNC(select_row_callback), - NULL); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Un ejemplo GtkCList -<p> - -<tscreen><verb> -/* principio del ejemplo clist clist.c */ - -#include <gtk/gtk.h> -#include <glib.h> - -/* Aquí tenemos algunos prototipos de las funciones de llamada */ -void button_add_clicked( GtkWidget *boton, gpointer data); -void button_clear_clicked( GtkWidget *boton, gpointer data); -void button_hide_show_clicked( GtkWidget *boton, gpointer data); -void selection_made( GtkWidget *clist, gint row, gint column, - GdkEventButton *event, gpointer data); - -gint main (int argc, gchar *argv[]) -{ - GtkWidget *ventana; - GtkWidget *vbox, *hbox; - GtkWidget *clist; - GtkWidget *button_add, *button_clear, *button_hide_show; - gchar *titles[2] = {"Ingredients","Amount"}; - - gtk_init(&argc, &argv); - - - ventana=gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_widget_set_usize(GTK_WIDGET(ventana), 300, 150); - - gtk_window_set_title(GTK_WINDOW(ventana), "GtkCList Example"); - gtk_signal_connect(GTK_OBJECT(ventana), - "destroy", - GTK_SIGNAL_FUNC(gtk_main_quit), - NULL); - - vbox=gtk_vbox_new(FALSE, 5); - gtk_container_border_width(GTK_CONTAINER(vbox), 5); - gtk_container_add(GTK_CONTAINER(ventana), vbox); - gtk_widget_show(vbox); - - /* Crear el GtkCList. Para este ejemplo utilizaremos 2 columnas */ - clist = gtk_clist_new_with_titles( 2, titles); - - /* Cuando se hace una selección, queremos saber algo acerca de - * ella. La función de llamada utilizada es selection_made, y su - * código lo podemos encontrar más abajo */ - gtk_signal_connect(GTK_OBJECT(clist), "select_row", - GTK_SIGNAL_FUNC(selection_made), - NULL); - - /* No es necesario ponerle sombra al borde, pero es bonito :) */ - gtk_clist_set_border(GTK_CLIST(clist), GTK_SHADOW_OUT); - - /* Lo que sí que es importante, es poner el ancho de las columnas - * ya no tendrán el valor correcto en caso contrario. Recuerde que - * las columnas se numeran desde el 0 en adelante (hasta el 1 en - * este caso). - */ - gtk_clist_set_column_width (GTK_CLIST(clist), 0, 150); - - /* Scollbars _only when needed_ */ - gtk_clist_set_policy(GTK_CLIST(clist), GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); - - /* Añade el widget GtkCList a la caja vertical y lo muestra. */ - gtk_box_pack_start(GTK_BOX(vbox), clist, TRUE, TRUE, 0); - gtk_widget_show(clist); - - /* Crea los botones y los añade a la ventana. Ver la parte del - * tutorial sobre botones para ver más ejemplos y comentarios - * acerca de todo esto. - */ - hbox = gtk_hbox_new(FALSE, 0); - gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0); - gtk_widget_show(hbox); - - button_add = gtk_button_new_with_label("Add List"); - button_clear = gtk_button_new_with_label("Clear List"); - button_hide_show = gtk_button_new_with_label("Hide/Show titles"); - - gtk_box_pack_start(GTK_BOX(hbox), button_add, TRUE, TRUE, 0); - gtk_box_pack_start(GTK_BOX(hbox), button_clear, TRUE, TRUE, 0); - gtk_box_pack_start(GTK_BOX(hbox), button_hide_show, TRUE, TRUE, 0); - - /* Conectar nuestras funciones de llamada a los tres botones */ - gtk_signal_connect_object(GTK_OBJECT(button_add), "clicked", - GTK_SIGNAL_FUNC(button_add_clicked), - (gpointer) clist); - gtk_signal_connect_object(GTK_OBJECT(button_clear), "clicked", - GTK_SIGNAL_FUNC(button_clear_clicked), - (gpointer) clist); - gtk_signal_connect_object(GTK_OBJECT(button_hide_show), "clicked", - GTK_SIGNAL_FUNC(button_hide_show_clicked), - (gpointer) clist); - - gtk_widget_show(button_add); - gtk_widget_show(button_clear); - gtk_widget_show(button_hide_show); - - /* Ahora hemos terminado el interface y sólo nos queda mostrar la - * ventana y entrar en el bucle gtk_main. - */ - gtk_widget_show(ventana); - gtk_main(); - - return 0; -} - -/* El usuario pulsó el botón "Add List". */ -void button_add_clicked( GtkWidget *boton, gpointer data) -{ - int indx; - - /* Algo tonto que añadir a la lista. 4 filas con 2 columnas cada - * una - */ - gchar *drink[4][2] = {{"Milk", "3 Oz"}, - {"Water", "6 l"}, - {"Carrots", "2"}, - {"Snakes", "55"}}; - - /* Aquí hacemos la adición del texto. Se hace una vez por cada - * fila. - */ - for( indx=0; indx < 4; indx++) - gtk_clist_append( (GtkCList*) data, drink[indx]); - - return; -} - -/* El usuario pulsó el botón "Clear List" */ -void button_clear_clicked( GtkWidget *boton, gpointer data) -{ - /* Borrar la lista utilizando gtk_clist_clear. Esto es mucho más - * rápido que llamar a gtk_clist_remove una vez por cada fila. - */ - gtk_clist_clear((GtkCList*) data); - - return; -} - -/* El usuario pulsó el botón "Hide/Show titles". */ -void button_hide_show_clicked( GtkWidget *boton, gpointer data) -{ - /* Una bandera para recordar el estado. 0 = actualmente visible */ - static short int flag = 0; - - if (flag == 0) - { - /* Oculta los títulos y pone la bandera a 1 */ - gtk_clist_column_titles_hide((GtkCList*) data); - flag++; - } - else - { - /* Muestra los títulos y pone la bandera a 0 */ - gtk_clist_column_titles_show((GtkCList*) data); - flag--; - } - - return; -} - -/* Se llegamos aquí, entonces el usuario ha seleccionado una fila de - * la lista. - */ -void selection_made( GtkWidget *clist, gint row, gint column, - GdkEventButton *event, gpointer data) -{ - gchar *text; - - /* Obtiene el texto que se ha almacenado en la fila y columna - * sobre las que se ha pulsado. Lo recibiremos como un puntero en - * el argumento text. - */ - gtk_clist_get_text(GTK_CLIST(clist), row, column, &text); - - /* Imprime alguna información sobre la fila seleccionada */ - g_print("You selected row %d. More specifically you clicked in column %d, and the text in this cell is %s\n\n", row, column, text); - - return; -} -/* final del ejemplo */ -</verb></tscreen> - -<!-- ***************************************************************** --> -<sect> El <em>widget</em> árbol<label id="sec_Tree_Widgets"> -<!-- ***************************************************************** --> -<p> - -El propósito del <em>widget</em> GtkTree es mostrar datos organizados -de forma jerárquica. El <em>widget</em> GtkTree en sí es un contenedor -vertical para los <em>widgets</em> del tipo GtkTreeItem. GtkTree en -sí mismo no es muy diferente de GtkList - ambos están derivados -directamente de GtkContainer, y los métodos GtkContainer funcionan -igual en los <em>widgets</em> GtkTree que en los GtkList. La -diferencia es que los <em>widgets</em> GtkTree pueden anidarse -dentro de otros <em>widgets</em> GtkTree. Vamos a verlo de forma -resumida. - -El <em>widget</em> GtkTree tiene su propia ventana, y tiene por -defecto un fondo de color blanco, como GtkList. La mayoría de los -métodos de GtkTree funcionan igual que sus correspondientes de -GtkList. Sin embargo, GtkTree no está derivado de GtkList, por lo que -no puede intercambiarlos. - -<sect1> Creando un árbol -<p> -Puede crear un GtkTree de la forma usual, utilizando: - -<tscreen><verb> -GtkWidget* gtk_tree_new( void ); -</verb></tscreen> - -Como el <em>widget</em> GtkList, un GtkTree crecerá cuando le añadan -elementos o cuando crezca alguno de sus subárboles. Por esta razón, -suelen venir dentro de una GtkScrolledWindow. Puede que quiera -utilizar <tt/gtk_widget_set_usize()/ con la ventana para asegurarse de -que es lo suficientemente grande como para poder ver todos los -elementos del árbol, ya que el valor por defecto de GtkScrolledWindow -es bastante pequeño. - -Ahora que ya sabemos como crear un árbol, probablemente quiera -añadirle algunos elementos. <ref id="sec_Tree_Item_Widget" name="El -widget elemento de árbol"> más adelante explica todos los -detalles de GtkTreeItem. Por ahora, es suficiente con saber como crear -uno, utilizando: - -<tscreen><verb> -GtkWidget* gtk_tree_item_new_with_label( gchar *etiqueta ); -</verb></tscreen> - -Puede añadirlo al árbol utilizando una de las siguientes funciones -(ver <ref id="sec_GtkTree_Functions" name="Funciones y macros"> -más adelante para leer más opciones): - -<tscreen><verb> -void gtk_tree_append( GtkTree *arbol, - GtkWidget *elemento_arbol ); - -void gtk_tree_prepend( GtkTree *arbol, - GtkWidget *elemento_arbol ); -</verb></tscreen> - -Observe que debe añadir elementos a un GtkTree de uno en uno - no -hay un equivalente a <tt/gtk_list_*_items()/. - -<sect1> Añadiendo un Subárbol -<p> -Un subárbol se crea como cualquier otro <em>widget</em> GtkTree. Un -subárbol se añade a otro árbol bajo un elemento del mismo, utilizando: - -<tscreen><verb> -void gtk_tree_item_set_subtree( GtkTreeItem *elemento_arbol, - GtkWidget *subarbol ); -</verb></tscreen> - -No necesita llamar a <tt/gtk_widget_show()/ en un subárbol ni antes ni -después de añadirlo a GtkTreeItem. Sin embargo, <em>deberá</em> haber -añadido el GtkTreeItem en cuestión a un árbol padre antes de llamar a -<em/gtk_tree_item_set_subtree()/. Esto se debe a que, técnicamente, -el padre del subárbol <em>no</em> es el GtkTreeItem «propietario», -sino el GtkTree que contiene al GtkTreeItem. - -Cuando le añade un subárbol a un GtkTreeItem, aparece el signo de un -más o de un menos a su lado, donde puede pinchar el usuario para -«expandirlo» u «contraerlo», o sea, para mostrar u ocultar su -subárbol. Los GtkTreeItems están contraídos por defecto. Observe que -cuando contrae un GtkTreeItem, cualquier elemento seleccionado en el -subárbol permanece seleccionado, que puede no coincidir con lo que el -usuario espera. - -<sect1> Manejando la lista de selección -<p> -Como con GtkList, GtkTree tiene un campo <tt>selection</tt>, y -es posible controlar el comportamiento del árbol (de alguna manera) -estableciendo el tipo de selección, utilizando: - -<tscreen><verb> -void gtk_tree_set_selection_mode( GtkTree *arbol, - GtkSelectionMode mode ); -</verb></tscreen> - -La semántica asociada con los distintos modos de selección está -descrita en la sección del <em>widget</em> GtkList. Como ocurría con -el <em>widget</em> GtkList, se enviarán las señales <tt/select_child/, -<tt/unselect_child/ (realmente no - ver <ref id="sec_GtkTree_Signals" -name="Señales"> más adelante para una explicación), y -<tt/selection_changed/ cuando los elementos de la lista sean -seleccionados o deseleccionados. Sin embargo, para aprovechar estas -señales, necesita conocer por medio <em>de que</em> <em>widget</em> -GtkTree serán emitidas, y donde encontrar una lista con los elementos -seleccionados. - -Todo esto es una potencial fuente de confusión. La mejor manera de -entenderlo es imaginarse que aunque todos los <em>widgets</em> GtkTree -son creados iguales, algunos son más iguales que otros. Todos los -<em>widgets</em> GtkTree tienen su propia ventana X, y por tanto -pueden recibir eventos como pulsaciones de ratón (¡si sus hijos o -GtkTreeItems no las capturan primero!). Sin embargo, para hacer -que GTK_SELECTION_SINGLE y GTK_SELECTION_BROWSE funcionen bien, la -lista de elementos seleccionados debe ser específica al <em>widget</em> -GtkTree superior de la jerarquia, conocido como el «árbol raíz». - -Por tanto no es una buena idea acceder al campo <tt>selection</tt> -directamente en un <em>widget</em> GtkTree arbitrario, a menos que -<em>sepa</em> que es el árbol raíz. En vez de eso, utilice la -macro GTK_TREE_SELECTION (arbol), que da la lista selección del árbol -raíz como un puntero <tt/GList/. Por supuesto, esta lista puede -incluir elementos que no estén en el subárbol en cuestión si el tipo -de selección es GTK_SELECTION_MULTIPLE. - -Para terminar, las señales <tt/select_child/ (y tt/unselect_child/, en -teoría) son emitidas por todos los árboles, pero la señal -<em/selection_changed/ es emitida sólo por el árbol raíz. En -consecuencia, si quiere manipular la señal <tt/select_child/ de un -árbol y todos sus subárboles, tendrá que llamar a -<tt/gtk_signal_connect()/ una vez por cada subárbol. - -<sect1> Estructura interna del <em>widget</em> árbol -<p> -La definición de la estructura GtkTree es ls siguiente: - -<tscreen><verb> -struct _GtkTree -{ - GtkContainer container; - - GList *child; - - GtkTree* root_tree; /* propietario de la lista de selección */ - GtkWidget* tree_owner; - GList *selection; - guint level; - guint indent_value; - guint current_indent; - guint selection_mode : 2; - guint view_mode : 1; - guint view_line : 1; -}; -</verb></tscreen> - -Ya se han mencionado los peligros asociados con el acceso directo al -campo <tt>selection</tt>. Se puede acceder a los otros campos -importantes de la estructura mediante macros manipuladoras o -funciones de clase. GTK_TREE_IS_ROOT_TREE (arbol) devuelve un valor -booleano que indica si un árbol es árbol raíz de una jerarquia -GtkTree, mientras que GTK_TREE_ROOT_TREE (arbol) devuelve el árbol -raíz, un objeto de tipo GtkTree (recuerde transformarlo utilizando -GTK_WIDGET (arbol) si quiere utilizar con él alguna de la funciones -<tt/gtk_widget_*()/). - -En lugar de acceder directamente al campo hijo de un <em>widget</em> -GtkTree, probablemente sea mejor transformarlo utilizando -GTK_CONTAINER (arbol), y pasárselo a la función -<tt/gtk_container_children()/. Con esto crearemos un duplicado de la -lista original, por lo que deberá eliminarlo de la memoria utilizando -<tt/g_list_free()/ después haber hecho con él lo que tenga que hacer, -o bien crear un bucle que lo vaya destruyendo de elemento en elemento, -como por ejemplo así: - -<tscreen><verb> -hijo = gtk_container_children (GTK_CONTAINER (arbol)); -while (hijo) { - do_something_nice (GTK_TREE_ITEM (hijo->data)); - hijo = g_list_remove_link (hijo, hijo); -} -</verb></tscreen> - -El campo <tt>tree_owner</tt> sólo está definido en subárboles, donde -apunta al <em>widget</em> GtkTreeItem que contiene al árbol en -cuestión. El campo <tt>level</tt> indica el nivel de profundidad de un -árbol en particular; los árboles raíz tienen un nivel 0, y cada nivel -sucesivo de subárboles tiene un nivel superior al del padre. Sólo se -puede asegurar que este campo contiene un valor correcto después de -que el <em>widget</em> GtkTree se dibuje en la pantalla. - -<sect2> Señales<label id="sec_GtkTree_Signals"> -<p> -<tscreen><verb> -void selection_changed( GtkTree *arbol ); -</verb></tscreen> - -Esta señal se emitirá cuando cambie el campo <tt>selection</tt> de -un GtkTree. Esto ocurre cuando se selecciona o deselecciona un hijo del -GtkTree. - -<tscreen><verb> -void select_child( GtkTree *arbol, - GtkWidget *hijo ); -</verb></tscreen> - -Esta señal se emite cuando se está seleccionando un hijo del GtkTree. -Esto ocurre en las llamadas a <tt/gtk_tree_select_item()/, -<tt/gtk_tree_select_child()/, en <em>todas</em> las pulsaciones de -botón y llamadas a <tt/gtk_tree_item_toggle()/ y -<tt/gtk_item_toggle()/. Puede que a veces se invoque indirectamente en -otras ocasiones, cuando el hijo se añada o elimine del GtkTree. - -<tscreen><verb> -void unselect_child (GtkTree *arbol, - GtkWidget *hijo); -</verb></tscreen> - -Esta señal se emite cuando se deselecciona un hijo del GtkTree. Con -GTK+ 1.0.4, esto sólo parece ocurrir en las llamadas a -<tt/gtk_tree_unselect_item()/ o a <tt/gtk_tree_unselect_child()/, y quizás -en otras ocasiones, pero <em>no</em> cuando la pulsación de un botón -deselecciona un hijo, y tampoco por la emisión de la señal «toggle» -por <tt/gtk_item_toggle()/. - -<sect2> Funciones y macros<label id="sec_GtkTree_Functions"> -<p> -<tscreen><verb> -guint gtk_tree_get_type( void ); -</verb></tscreen> - -Devuelve el identificador de tipo de `GtkTree'. - -<tscreen><verb> -GtkWidget* gtk_tree_new( void ); -</verb></tscreen> - -Crea un nuevo objeto GtkTree. El nuevo <em>widget</em> se devuelve como -un puntero a un objeto GtkWidget. Se devolverá NULL si se produce algún -error. - -<tscreen><verb> -void gtk_tree_append( GtkTree *arbol, - GtkWidget *elemento_arbol ); -</verb></tscreen> - -Añade un árbol a un GtkTree. - -<tscreen><verb> -void gtk_tree_prepend( GtkTree *arbol, - GtkWidget *elemento_arbol ); -</verb></tscreen> - -Preañade un árbol a un GtkTree. - -<tscreen><verb> -void gtk_tree_insert( GtkTree *arbol, - GtkWidget *elemento_arbol, - gint posicion ); -</verb></tscreen> - -Inserta un árbol en un GtkTree en la posición de la lista especificada -por <tt>posicion.</tt> - -<tscreen><verb> -void gtk_tree_remove_items( GtkTree *arbol, - GList *items ); -</verb></tscreen> - -Elimina una lista de elementos (en forma de una <tt/GList */) de un -GtkTree. Eliminar un elemento de un árbol lo dereferencia (y por tanto -normalmente) lo destruye (""), a él <em>y</em> a su subárbol, de -haberlo, <em>y</em> a todos los subárboles que contenga ese -subárbol. Si quiere eliminar sólo un elemento, deberá utilizar -<tt/gtk_container_remove()/. - -<tscreen><verb> -void gtk_tree_clear_items( GtkTree *arbol, - gint start, - gint end ); -</verb></tscreen> - -Elimina los elementos de un GtkTree desde la posición <tt>start</tt> -hasta la posición <tt>end</tt>. De nuevo hay que llevarse cuidado -con donde se aplica la dereferencia, ya que <tt/gtk_tree_clear_items()/ -simplemente construye una lista y se la pasa a -<tt/gtk_tree_remove_items()/. - -<tscreen><verb> -void gtk_tree_select_item( GtkTree *arbol, - gint item ); -</verb></tscreen> - -Emite la señal <tt/select_item/ para el hijo que se encuentra en la -posición <tt>item</tt>, y por tanto selecciona a ese hijo (a menos que -lo deseleccione en un manejador de señal...) - -<tscreen><verb> -void gtk_tree_unselect_item( GtkTree *arbol, - gint item ); -</verb></tscreen> - -Emite la señal <tt/unselect_item/ para el hijo en la posición -<tt>item</tt>, y por tanto deselecciona al hijo. - -<tscreen><verb> -void gtk_tree_select_child( GtkTree *arbol, - GtkWidget *elemento_arbol ); -</verb></tscreen> - -Emite la señal <tt/select_item/ para el hijo <tt>elemento_arbol</tt>, y por tanto -lo selecciona. - -<tscreen><verb> -void gtk_tree_unselect_child( GtkTree *arbol, - GtkWidget *elemento_arbol ); -</verb></tscreen> - -Emite la señal <tt/unselect_item/ para el hijo <tt>elemento_arbol</tt>, y por -tanto lo deselecciona. - -<tscreen><verb> -gint gtk_tree_child_position( GtkTree *arbol, - GtkWidget *hijo ); -</verb></tscreen> - -Devuelve la posición en el árbol de <tt>child</tt>, a menos que -<tt>child</tt> no esté en el árbol, en cuya caso devuelve -1. - -<tscreen><verb> -void gtk_tree_set_selection_mode( GtkTree *arbol, - GtkSelectionMode mode ); -</verb></tscreen> - -Establece el modo de selección, que puede ser uno de los siguientes -GTK_SELECTION_SINGLE (por defecto), GTK_SELECTION_BROWSE, -GTK_SELECTION_MULTIPLE, o GTK_SELECTION_EXTENDED. Esto sólo está -definido para los árboles raíz, que es donde tiene sentido, ya que el -árbol raíz es el «propietario» de la selección. Establecer este -valor en un subárbol no tiene ningún efecto en absoluto; el valor -simplemente será ignorado. - -<tscreen><verb> -void gtk_tree_set_view_mode( GtkTree *arbol, - GtkTreeViewMode mode ); -</verb></tscreen> - -Establece el «modo de visión», que puede ser o GTK_TREE_VIEW_LINE -(por defecto) o GTK_TREE_VIEW_ITEM. El modo de visión se propaga -de un árbol a sus subárboles, y no puede establecerse en exclusiva -para un subárbol (esto no es exacto del todo - vea los comentarios en el -código de ejemplo). - -El termino «modo de visión» es algo ambiguo - básicamente, controla -la forma en que se resalta a uno de los hijos del árbol cuando es -seleccionado. Si es GTK_TREE_VIEW_LINE, se resaltará el -<em>widget</em> GtkTreeItem completo, mientras que si es -GTK_TREE_VIEW_ITEM, sólo se resaltará el <em>widget</em> hijo (es -decir, lo que normalmente es la etiqueta). - -<tscreen><verb> -void gtk_tree_set_view_lines( GtkTree *arbol, - guint flag ); -</verb></tscreen> - -Controla si se dibujarán las líneas de conexión entre los elementos -del árbol. <tt>flag</tt> es o TRUE, en cuyo caso se dibujarán, o -FALSE, en cuyo caso no se dibujarán. - -<tscreen><verb> -GtkTree *GTK_TREE (gpointer obj); -</verb></tscreen> - -Convierte un puntero genérico a `GtkTree *'. - -<tscreen><verb> -GtkTreeClass *GTK_TREE_CLASS (gpointer class); -</verb></tscreen> - -Convierte un puntero genérico a `GtkTreeClass *'. - -<tscreen><verb> -gint GTK_IS_TREE (gpointer obj); -</verb></tscreen> - -Determina si un puntero genérico se refiere a un objeto `GtkTree'. - -<tscreen><verb> -gint GTK_IS_ROOT_TREE (gpointer obj) -</verb></tscreen> - -Determina si un puntero genérico se refiere a un objeto `GtkTree' -<em>y</em> es un árbol raíz. Aunque la función acepta cualquier -puntero, los resultados de pasarle un puntero que no se refiera -a un GtkTree no están definidos y probablemente no tengan ningún -sentido. - -<tscreen><verb> -GtkTree *GTK_TREE_ROOT_TREE (gpointer obj) -</verb></tscreen> - -Devuelve el árbol raíz de un puntero a un objeto `GtkTree'. Seguimos -con el mismo problema que en el caso anterior. - -<tscreen><verb> -GList *GTK_TREE_SELECTION(gpointer obj) -</verb></tscreen> - -Devuelve la lista de selección del árbol raíz de un objeto -`GtkTree'. Seguimos con el mismo problema que antes. - -<sect1> El <em>widget</em> elemento de árbol<label id="sec_Tree_Item_Widget"> -<p> -El <em>widget</em> GtkTreeItem, cómo el GtkListItem, está derivado -de GtkItem, que de nuevo, está derivado de GtkBin. Sin embargo, el -elemento en sí mismo es un contenedor genérico que contiene un -<em>widget</em> hijo, que puede ser de cualquier tipo. El <em>widget</em> -GtkTreeItem tiene ciertos campos extra, pero el único que nos -interesa ahora es el campo <em>subárbol</em>. - -La definición de la estructura GtkTreeItem es así: - -<tscreen><verb> -struct _GtkTreeItem -{ - GtkItem item; - - GtkWidget *subtree; - GtkWidget *pixmaps_box; - GtkWidget *plus_pix_widget, *minus_pix_widget; - - GList *pixmaps /* nodo pixmap para esta profundidad de color */ - - guint expanded : 1; -}; -</verb></tscreen> - -El campo <tt>pixmaps_box</tt> es un GtkEventBox que caza las pulsaciones -en el símbolo más/menos que controla la expansión y contracción. El -campo <tt>pixmaps</tt> apunta a una estructura de datos interna. Ya que -siempre puede obtener el subárbol de un GtkTreeItem de una forma -(relativamente) segura mediante la macro GTK_TREE_ITEM_SUBTREE (Item), -es aconsejable no tocar las tripas de un GtkTreeItem a menos que -<em>realmente</em> sepa que es lo que está haciendo. - -Ya que está derivado directamente de un GtkItem, puede tratarse como -tal utilizando la macro GTK_ITEM (ElementoArbol). Un GtkTreeItem normalmente -tiene una etiqueta, por lo que tenemos a nuestra disposición la -función gtk_list_item_new_with_label(). Podemos conseguir el mismo -efecto utilizando código como el siguiente, que por ahora es sólo -una copia de la función gtk_tree_item_new_with_label(): - -<tscreen><verb> -elemento_arbol = gtk_tree_item_new (); -etiqueta_widget = gtk_label_new (etiqueta); -gtk_misc_set_alignment (GTK_MISC (etiqueta_widget), 0.0, 0.5); - -gtk_container_add (GTK_CONTAINER (elemento_arbol), etiqueta_widget); -gtk_widget_show (etiqueta_widget); -</verb></tscreen> - -Cómo no es obligatorio añadir una GtkLabel a un GtkTreeItem, puede -también añadirle un GtkHBox o una GtkArrow, o hasta un GtkNotebook -(aunque en esos casos su aplicación no será muy popular). - -Si elimina todos los elementos de un subárbol, será destruido -y se eliminará la información sobre su padre, a menos que lo -referencie de antemano, además el GtkTreeItem que sea su propietario -se colapsará. Por lo tanto, si quiere que se mantenga el subárbol -tendrá que hacer algo así: - -<tscreen><verb> -g_object_ref (arbol); -propietario = GTK_TREE(arbol)->tree_owner; -gtk_container_remove (GTK_CONTAINER(arbol), item); -if (arbol->parent == NULL){ - gtk_tree_item_expand (GTK_TREE_ITEM(propietario)); - gtk_tree_item_set_subtree (GTK_TREE_ITEM(propietario), arbol); -} -else - g_object_unref (arbol); -</verb></tscreen> - -Finalmente, hay que mencionar que la opción de drag-n-drop (arrastar y -soltar) <em>funciona</em> con los GtkTreeItems. Sólo tiene que -asegurarse de que el GtkTreeItem que quiere convertir en un elemento -de arrastre o en un lugar en el que, además de haber sido añadido a -GtkTree, sino que además cada su <em>widget</em> padre tiene a su vez -un padre, y así hasta llegar al nivel más alto o ventana de diálogo, -cuando llamamos a <tt/gtk_widget_dnd_drag_set()/ o -<tt/gtk_widget_dnd_drop_set()/. En caso contrario, podrían ocurrir -cosas extrañas. - -<sect2> Señales -<p> -GtkTreeItem hereda las señales <tt/select/, <tt/deselect/, y -<tt/toggle/ de GtkItem. Además, añade dos señales propias, <tt/expand/ -y <tt/collapse/. - -<tscreen><verb> -void select( GtkItem *elemento_arbol ); -</verb></tscreen> - -Esta señal se emite cuando un elemento está siendo seleccionado, -o bien después de que el usuario pinche en él, o bien cuando -el programa llame a <tt/gtk_tree_item_select()/, -<tt/gtk_item_select()/, o a <tt/gtk_tree_select_child()/. - -<tscreen><verb> -void deselect( GtkItem *elemento_arbol ); -</verb></tscreen> - -Esta señal se emite cuando un elemento está siendo deseleccionado, -o bien después de que el usuario pinche en él, o bien cuando -el programa llame a <tt/gtk_tree_item_deselect()/ o a -<tt/gtk_item_deselect()/. En el caso de GtkTreeItems, también se -emitirá por <tt/gtk_tree_unselect_child()/, y a veces por -<tt/gtk_tree_select_child()/. - -<tscreen><verb> -void toggle( GtkItem *elemento_arbol ); -</verb></tscreen> - -Esta señal se emite cuando el programa llama a <tt/gtk_item_toggle()/. El -efecto que tiene cuando se emite en un GtkTreeItem es llamar a -<tt/gtk_tree_select_child()/ (y nunca a -<tt/gtk_tree_unselect_child()/) en el árbol padre del elemento, si el -elemento tiene un árbol padre. Si no lo tiene, entonces se cambiará el -resaltado del elemento. - -<tscreen><verb> -void expand( GtkTreeItem *elemento_arbol ); -</verb></tscreen> - -Esta señal se emite cuando se está expandiendo el subárbol del -elemento, esto es, cuando el usuario pincha en el signo más que -hay al lado del elemento, o cuando el programa llama a -<tt/gtk_tree_item_expand()/. - -<tscreen><verb> -void collapse( GtkTreeItem *elemento_arbol ); -</verb></tscreen> - -Esta señal se emite cuando se está contrayendo el subárbol del -elemento, esto es, cuando el usuario pincha en el signo menos que hay -al lado del elemento, o cuando el programa llama a -<tt/gtk_tree_item_collapse()/. - -<sect2> Funciones y Macros -<p> -<tscreen><verb> -guint gtk_tree_item_get_type( void ); -</verb></tscreen> - -Devuelve el identificador de tipo de `GtkTreeItem'. - -<tscreen><verb> -GtkWidget* gtk_tree_item_new( void ); -</verb></tscreen> - -Crea un nuevo objeto GtkTreeItem. El nuevo <em>widget</em> se devuelve -como un puntero a un objeto GtkWidget. Se devolverá NULL si hay algún -fallo. - -<tscreen><verb> -GtkWidget* gtk_tree_item_new_with_label (gchar *etiqueta); -</verb></tscreen> - -Crea un nuevo objeto GtkTreeItem, teniendo una simple GtkLabel -como único hijo. El nuevo <em>widget</em> se devolverá como -un puntero a un objeto GtkWidget. Se devolverá NULL en caso -de haber algún fallo. - -<tscreen><verb> -void gtk_tree_item_select( GtkTreeItem *elemento_arbol ); -</verb></tscreen> - -Esta función es básicamente un recubrimiento de una llamada a -gtk_item_select (GTK_ITEM (elemento_arbol)) que emitirá la -señal select. - -<tscreen><verb> -void gtk_tree_item_deselect( GtkTreeItem *elemento_arbol ); -</verb></tscreen> - -Esta función es básicamente un recubrimiento de una llamada a -gtk_item_deselect (GTK_ITEM (elemento_arbol)) que emitirá la -señal deselect. - -<tscreen><verb> -void gtk_tree_item_set_subtree( GtkTreeItem *elemento_arbol, - GtkWidget *subarbol ); -</verb></tscreen> - -Esta función añade <tt/subarbol/ a <tt/elemento_arbol/, mostrándolo si -<tt/elemento_arbol/ está expandido, u ocultándolo si <tt/elemento_arbol/ está -contraído. De nuevo, recuerde que el <tt/elemento_arbol/ ya debe de haber -sido añadido a un árbol para que esto funcione. - -<tscreen><verb> -void gtk_tree_item_remove_subtree( GtkTreeItem *elemento_arbol ); -</verb></tscreen> - -Esto elimina todos los hijos de los subárboles del <tt/elemento_arbol/ -(esto es, dereferencia y destruye a los subárboles hijos, y a los -hijos de los hijos y...), entonces elimina el subárbol en si mismo, y -oculta el signo más/menos. - -<tscreen><verb> -void gtk_tree_item_expand( GtkTreeItem *elemento_arbol ); -</verb></tscreen> - -Esto emite la señal «expand» para el <tt/elemento_arbol/, que lo -expande. - -<tscreen><verb> -void gtk_tree_item_collapse( GtkTreeItem *elemento_arbol ); -</verb></tscreen> - -Esto emite la señal «collapse» en el <tt/elemento_arbol/, que lo -contrae. - -<tscreen><verb> -GtkTreeItem *GTK_TREE_ITEM (gpointer obj) -</verb></tscreen> - -Convierte un puntero genérico en un `GtkTreeItem *'. - -<tscreen><verb> -GtkTreeItemClass *GTK_TREE_ITEM_CLASS (gpointer obj) -</verb></tscreen> - -Convierte un puntero genérico en un `GtkTreeItemClass'. - -<tscreen><verb> -gint GTK_IS_TREE_ITEM (gpointer obj) -</verb></tscreen> - -Determina si un puntero genérico se refiere a un objeto `GtkTreeItem'. - -<tscreen><verb> -GtkWidget GTK_TREE_ITEM_SUBTREE (gpointer obj) -</verb></tscreen> - -Devuelve un subárbol del elemento (<tt/obj/ debería apuntar a un -objeto `GtkTreeItem'). - -<sect1> Árbol ejemplo -<p> -Este ejemplo es muy parecido al árbol ejemplo que hay en -<tt/testgtk.c/, pero mucho menos completo (aunque mucho mejor -comentado). Pone una ventana con un árbol, y conecta todas las señales -de los objetos relevantes, con lo que podrá ver cuando se emiten. - -<!-- Hay un comentario en el código que no se traducir --> -<tscreen><verb> -/* principio del ejemplo tree tree.c */ - -#include <gtk/gtk.h> - -/* para todas las señales GtkItem:: y GtkTreeItem:: */ -static void cb_itemsignal (GtkWidget *item, gchar *signame) -{ - gchar *name; - GtkLabel *etiqueta; - - /* Es un GtkBin, por lo que tiene un hijo, que sabemos que es una - * etiqueta, por lo que la cogemos */ - etiqueta = GTK_LABEL (GTK_BIN (item)->child); - /* Conseguimos el texto de la etiqueta */ - gtk_label_get (etiqueta, &name); - /* Conseguimos el nivel del árbol en el que se encuentra el elemento */ - g_print ("%s called for item %s->%p, level %d\n", signame, name, - item, GTK_TREE (item->parent)->level); -} - -/* nunca se llamará a esta función */ -static void cb_unselect_child (GtkWidget *arbol_raiz, GtkWidget *hijo, - GtkWidget *subarbol) -{ - g_print ("unselect_child called for root tree %p, subtree %p, child %p\n", - arbol_raiz, subarbol, hijo); -} - -/* Se llamará a esta función cada vez que el usuario pulse en un - * elemento, esté o no seleccionado. */ - whether it is already selected or not. */ -static void cb_select_child (GtkWidget *arbol_raiz, GtkWidget *hijo, - GtkWidget *subarbol) -{ - g_print ("select_child called for root tree %p, subtree %p, child %p\n", - arbol_raiz, subarbol, hijo); -} - -static void cb_selection_changed (GtkWidget *arbol) -{ - GList *i; - - g_print ("selection_change called for tree %p\n", arbol); - g_print ("selected objects are:\n"); - - i = GTK_TREE_SELECTION(arbol); - while (i){ - gchar *name; - GtkLabel *etiqueta; - GtkWidget *item; - - /* Get a GtkWidget pointer from the list node */ - item = GTK_WIDGET (i->data); - etiqueta = GTK_LABEL (GTK_BIN (item)->child); - gtk_label_get (etiqueta, &name); - g_print ("\t%s on level %d\n", name, GTK_TREE - (item->parent)->level); - i = i->next; - } -} - -int main (int argc, char *argv[]) -{ - GtkWidget *ventana, *scrolled_win, *arbol; - static gchar *itemnames[] = {"Foo", "Bar", "Baz", "Quux", - "Maurice"}; - gint i; - - gtk_init (&argc, &argv); - - /* una ventana general */ - ventana = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_signal_connect (GTK_OBJECT(ventana), "delete_event", - GTK_SIGNAL_FUNC (gtk_main_quit), NULL); - gtk_container_border_width (GTK_CONTAINER(ventana), 5); - - /* una ventana con barras de desplazamiento */ - scrolled_win = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); - gtk_widget_set_usize (scrolled_win, 150, 200); - gtk_container_add (GTK_CONTAINER(ventana), scrolled_win); - gtk_widget_show (scrolled_win); - - /* Crear el árbol raíz */ - arbol = gtk_tree_new(); - g_print ("root tree is %p\n", arbol); - /* connect all GtkTree:: signals */ - gtk_signal_connect (GTK_OBJECT(arbol), "select_child", - GTK_SIGNAL_FUNC(cb_select_child), arbol); - gtk_signal_connect (GTK_OBJECT(arbol), "unselect_child", - GTK_SIGNAL_FUNC(cb_unselect_child), arbol); - gtk_signal_connect (GTK_OBJECT(arbol), "selection_changed", - GTK_SIGNAL_FUNC(cb_selection_changed), arbol); - /* Añadirlo a la ventana con barras de desplazamiento */ - gtk_container_add (GTK_CONTAINER(scrolled_win), arbol); - /* Poner el modo de selección */ - gtk_tree_set_selection_mode (GTK_TREE(arbol), - GTK_SELECTION_MULTIPLE); - /* mostrar el árbol */ - gtk_widget_show (arbol); - - for (i = 0; i < 5; i++){ - GtkWidget *subarbol, *item; - gint j; - - /* Crear un elemento del árbol */ - item = gtk_tree_item_new_with_label (itemnames[i]); - /* Conectar todas las señales GtkItem:: y GtkTreeItem:: */ - gtk_signal_connect (GTK_OBJECT(item), "select", - GTK_SIGNAL_FUNC(cb_itemsignal), "select"); - gtk_signal_connect (GTK_OBJECT(item), "deselect", - GTK_SIGNAL_FUNC(cb_itemsignal), "deselect"); - gtk_signal_connect (GTK_OBJECT(item), "toggle", - GTK_SIGNAL_FUNC(cb_itemsignal), "toggle"); - gtk_signal_connect (GTK_OBJECT(item), "expand", - GTK_SIGNAL_FUNC(cb_itemsignal), "expand"); - gtk_signal_connect (GTK_OBJECT(item), "collapse", - GTK_SIGNAL_FUNC(cb_itemsignal), "collapse"); - /* Añadirlo al árbol padre */ - gtk_tree_append (GTK_TREE(arbol), item); - /* Mostrarlo - esto se puede hacer en cualquier momento */ - gtk_widget_show (item); - /* Crear el subárbol de este elemento */ - subarbol = gtk_tree_new(); - g_print ("-> item %s->%p, subtree %p\n", itemnames[i], item, - subarbol); - - /* Esto todavía es necesario si quiere que se llamen a están - * señales en el subárbol hijo. Note that selection_change will - * be signalled for the root tree regardless. */ - gtk_signal_connect (GTK_OBJECT(subarbol), "select_child", - GTK_SIGNAL_FUNC(cb_select_child), subarbol); - gtk_signal_connect (GTK_OBJECT(subarbol), "unselect_child", - GTK_SIGNAL_FUNC(cb_unselect_child), subarbol); - /* Esto no tiene absolutamente ningún efecto, ya que se ignora - * completamente en los subárboles */ - gtk_tree_set_selection_mode (GTK_TREE(subarbol), - GTK_SELECTION_SINGLE); - /* Esto tampoco hace nada, pero por una razón diferente - los - * valores view_mode y view_line de un árbol se propagan a los - * subárboles cuando son mapeados. Por tanto, establecer los - * valores después actualmente tendría (algún impredecible) efecto - */ - gtk_tree_set_view_mode (GTK_TREE(subarbol), GTK_TREE_VIEW_ITEM); - /* Establecer este subárbol del elemento - ¡Recuerde que no puede - * hacerlo hasta que se haya añadido a su árbol padre! */ - gtk_tree_item_set_subtree (GTK_TREE_ITEM(item), subarbol); - - for (j = 0; j < 5; j++){ - GtkWidget *subitem; - - /* Crea un elemento subárbol, más o menos lo mismo de antes */ - subitem = gtk_tree_item_new_with_label (itemnames[j]); - /* Conectar todas las señales GtkItem:: y GtkTreeItem:: */ - gtk_signal_connect (GTK_OBJECT(subitem), "select", - GTK_SIGNAL_FUNC(cb_itemsignal), "select"); - gtk_signal_connect (GTK_OBJECT(subitem), "deselect", - GTK_SIGNAL_FUNC(cb_itemsignal), "deselect"); - gtk_signal_connect (GTK_OBJECT(subitem), "toggle", - GTK_SIGNAL_FUNC(cb_itemsignal), "toggle"); - gtk_signal_connect (GTK_OBJECT(subitem), "expand", - GTK_SIGNAL_FUNC(cb_itemsignal), "expand"); - gtk_signal_connect (GTK_OBJECT(subitem), "collapse", - GTK_SIGNAL_FUNC(cb_itemsignal), "collapse"); - g_print ("-> -> item %s->%p\n", itemnames[j], subitem); - /* Añadirlo a su árbol padre */ - gtk_tree_append (GTK_TREE(subarbol), subitem); - /* Mostrarlo */ - gtk_widget_show (subitem); - } - } - - /* Mostrar la ventana y entrar en el bucle final */ - gtk_widget_show (ventana); - gtk_main(); - return 0; -} -/* fin del ejemplo */ -</verb></tscreen> - -<!-- ***************************************************************** --> -<sect> El <em>widget</em> menú -<!-- ***************************************************************** --> -<p> -Hay dos formas de crear menús, la fácil, y la difícil. Ambas tienen su -utilidad, aunque lo más probable es que normalmente utilice la -menufactory (la forma fácil). La forma «difícil» consiste en crear -todos los menús utilizando las llamadas directamente. La forma fácil -consiste en utilizar las llamadas de <tt/gtk_item_factory/. Es mucho -más fácil, pero aun así cada aproximación tiene sus ventajas y sus -inconvenientes. - -La menufactory es mucho más fácil de utilizar, y tambíen es más fácil -añadir nuevos menús, aunque a larga, escribiendo unas cuántas -funciones de recubrimiento para crear menús utilizando el método -manual puede acabar siendo más útil. Con la itemfactory, no es posible -añadir imágenes o el carácter `/' a los menús. - -<!-- ----------------------------------------------------------------- --> -<sect1>Creación manual de menús -<p> -Siguiendo la auténtica tradición de la enseñanza, vamos a enseñarle -primero la forma difícil. <tt>:)</tt> - -Se utilizan tres <em>widgets</em> para hacer una barra de menús y -submenús: -<itemize> -<item>un elemento del menú, que es lo que el usuario quiere seleccionar, -p.e. 'Guardar' -<item>un menú, que actua como un contenedor para los elementos del menú, y -<item>una barra de menú, que es un contenedor para cada uno de los menús, -</itemize> - -Todo esto se complica ligeramente por el hecho de que los -<em>widgets</em> de los elementos del menú se utilizan para dos cosas -diferentes. Están los <em>widgets</em> que se empaquetan en el menú, y -los que se empaquetan en una barra de menús, que cuando se selecciona, -activa el menú. - -Vamos a ver las funciones que se utilizan para crear menús y barras -de menús. ésta primera función se utiliza para crear una barra de menús. - -<tscreen><verb> -GtkWidget *gtk_menu_bar_new( void ); -</verb></tscreen> - -Como el propio nombre indica, esta función crea una nueva barra de -menús. Utilice <tt/gtk_container_add/ para empaquetarla en una -ventana, o las funciones <tt/box_pack/ para empaquetarla en una caja - -exactamente igual que si fuesen botones. - -<tscreen><verb> -GtkWidget *gtk_menu_new( void ); -</verb></tscreen> - -Esta función devuelve un puntero a un nuevo menú, que no se debe -mostrar nunca (no hace falta utilizar <tt/gtk_widget_show/), es sólo -un contenedor para los elementos del menú. Espero que todo esto se -aclare un poco cuando vea en el ejemplo que hay más abajo. - -Las siguientes dos llamadas se utilizan para crear elementos de menú -que se empaquetarán en el menú (y en la barra de menú). - -<tscreen><verb> -GtkWidget *gtk_menu_item_new( void ); -</verb></tscreen> - -y - -<tscreen><verb> -GtkWidget *gtk_menu_item_new_with_label( const char *etiqueta ); -</verb></tscreen> - -Estas llamadas se utilizan para crear los elementos del menú que -van a mostrarse. Recuerde que hay que distinguir entre un «menú» -creado con <tt/gtk_menu_new/ y un «elemento del menú» creado con las -funciones <tt/gtk_menu_item_new/. El elemento de menú será un botón -con una acción asociada, y un menú será un contenedor con los -elementos del menú. - -Las funciones <tt/gtk_menu_new_with_label/ y <tt/gtk_menu_new/ son -sólo lo que espera que sean después de leer lo de los botones. Una -crea un nuevo elemento del menú con una etiqueta ya dentro, y la otra -crea un elemento del menú en blanco. - -Una vez ha creado un elemento del menú tiene que ponerlo en un menú. -Esto se hace utilizando la función <tt/gtk_menu_append/. Para capturar -el momento en el que el elemento se selecciona por el usuario, -necesitamos conectar con la señal <tt/activate/ de la forma usual. Por -tanto, si quiere crear un menú estándar <tt/File/, con las opciones -<tt/Open/, <tt/Save/ y <tt/Quit/ el código debería ser algo como - -<tscreen><verb> -file_menu = gtk_menu_new(); /* No hay que mostrar menús */ - -/* Crear los elementos del menú */ -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"); - -/* Añadirlos al menú */ -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); - -/* Enlazar las función de llamada a la señal "activate" */ -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"); - -/* Podemos enlazar el elemento de menú Quit con nuestra función de - * salida */ -gtk_signal_connect_object( GTK_OBJECT(quit_items), "activate", - GTK_SIGNAL_FUNC(destroy), (gpointer) "file.quit"); - -/* Tenemos que mostrar los elementos del menú */We do need to show menu items */ -gtk_widget_show( open_item ); -gtk_widget_show( save_item ); -gtk_widget_show( quit_item ); -</verb></tscreen> - -En este momento tendremos nuestro menú. Ahora necesitamos crear una -barra de menús y un elemento de menú para el elemento <tt/File/, que -vamos a añadir a nuestro menú. El código es el siguiente - -<tscreen><verb> -menu_bar = gtk_menu_bar_new(); -gtk_container_add( GTK_CONTAINER(ventana), menu_bar); -gtk_widget_show( menu_bar ); - -file_item = gtk_menu_item_new_with_label("File"); -gtk_widget_show(file_item); -</verb></tscreen> - -Ahora necesitamos asociar el menú con <tt/file_item/. Esto se hace con -la función - -<tscreen> -void gtk_menu_item_set_submenu( GtkMenuItem *menu_item, - GtkWidget *submenu ); -</tscreen> - -Por lo que nuestro ejemplo continua con - -<tscreen><verb> -gtk_menu_item_set_submenu( GTK_MENU_ITEM(file_item), file_menu ); -</verb></tscreen> - -Todo lo que queda por hacer es añadir el menú a la barra de menús, que -se hace mediante la función - -<tscreen> -void gtk_menu_bar_append( GtkMenuBar *menu_bar, GtkWidget *menu_item); -</tscreen> - -que en nuestro caso habrá que utilizar así: - -<tscreen><verb> -gtk_menu_bar_append( GTK_MENU_BAR (menu_bar), file_item ); -</verb></tscreen> - -Si queremos que el menú esté alineado a la derecha en la barra de -menús, como suele estar la opción de ayuda, podemos utilizar la -función siguiente (otra vez en <tt/file_item/ en el ejemplo actual) -antes de enlazarla en la barra de menú. - -<tscreen><verb> -void gtk_menu_item_right_justify( GtkMenuItem *menu_item ); -</verb></tscreen> - -Aquí hay un resumen de los pasos que son necesarios para crear una -barra de menús con los menús correspondientes ya enlazados: - -<itemize> -<item> Crear un nuevo menú utilizando <tt/gtk_menu_new()/ -<item> Utilizar multiples llamadas a <tt/gtk_menu_item_new()/ para -cada elemento que desee tener en su menú. Y utilizar -<tt/gtk_menu_append()/ para poner cada uno de esos nuevos elementos en -el menú. -<item> Crear un elemento de menú utilizando -<tt/gtk_menu_item_new()/. Ésta será la raíz del menú, el texto que -aparezca aquí estará en la barra de menús. -<item> Utilizar <tt/gtk_menu_item_set_submenu()/ para enlazar el menú -al elemento del menú raíz (el creado en el paso anterior). -<item> Crear una nueva barra de menús utilizando -<tt/gtk_menu_bar_new/. Este paso solo necesita hacerse una vez cuando -se crea una serie de menús en una barra de menús. -<item> Utilizar <tt/gtk_menu_bar_append/ para poner el menú raíz en la -barra de menús. -</itemize> - -Para hacer un menú desplegable hay que seguir prácticamente los mismos -pasos. La única diferencia es que el menú no estará conectado -`automáticamente' a una barra de menú, sino que para que aparezca -deberá llamarse explícitamente a la función <tt/gtk_menu_popup()/ -utilizando, por ejemplo, un evento de pulsación de botón. Siga los -pasos siguientes: - -<itemize> -<item>Cree una función manejadora de eventos. Tiene que tener el -siguiente prototipo -<tscreen> -static gint handler( GtkWidget *widget, - GdkEvent *event ); -</tscreen> - -y utilice el evento para encontrar donde debe aparecer el menú. - -<item>En el manejador de eventos, si el evento es una pulsación de un -botón del ratón, tratar <tt>event</tt> como un evento de botón -(que lo es) y utilizarlo como se indica en el código ejemplo para -pasarle información a <tt/gtk_menu_popup()/. -<item>Enlazar este manejador de eventos con el <em>widget</em> con -<tscreen> -gtk_signal_connect_object(GTK_OBJECT(widget), "event", - GTK_SIGNAL_FUNC (handler), GTK_OBJECT(menu)); -</tscreen> -donde <tt>widget</tt> es el <em>widget</em> con el que esta conectando, -<tt>handler</tt> es la función manejadora, y <tt>menu</tt> es un menú -creado con <tt/gtk_menu_new()/. Éste puede ser un menú que esté -contenido en una barra de menús, como se puede ver en el código de -ejemplo. -</itemize> - -<!-- ----------------------------------------------------------------- --> -<sect1>Ejemplo de la creación manual de un menú -<p> -Esto debería funcionar. Échele un vistazo al ejemplo para aclarar los -conceptos. - -<tscreen><verb> -/* principio del ejemplo menu menu.c */ - -#include <gtk/gtk.h> - -static gint button_press (GtkWidget *, GdkEvent *); -static void menuitem_response (gchar *); - -int main (int argc, char *argv[]) -{ - - GtkWidget *ventana; - GtkWidget *menu; - GtkWidget *menu_bar; - GtkWidget *root_menu; - GtkWidget *menu_items; - GtkWidget *vbox; - GtkWidget *boton; - char buf[128]; - int i; - - gtk_init (&argc, &argv); - - /* crear una nueva ventana */ - ventana = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_widget_set_usize( GTK_WIDGET (ventana), 200, 100); - gtk_window_set_title(GTK_WINDOW (ventana), "GTK Menu Test"); - gtk_signal_connect(GTK_OBJECT (ventana), "delete_event", - (GtkSignalFunc) gtk_main_quit, NULL); - - /* Inicializar el widget-menu, y recuerde -- ¡¡Nunca haga - * gtk_show_widget() con el widget menu!! - * Éste es el menú que contiene todos los elementos del menú, el - * que se desplegará cuando pulse en el "Root Menu" en la - * aplicación - */ - menu = gtk_menu_new(); - - /* Ahora hacemos un pequeño bucle que crea tres elementos de menú - * para "test-menu". Recuerde llamar a gtk_menu_append. Aquí - * estamos añadiendo una lista de elementos de menú a nuestro - * menú. Normalmente tendríamos que cazar aquí la señal "clicked" - * de cada uno de los elementos del menú y le deberíamos dar una - * función de llamada a cada uno, pero lo vamos a omitimos para - * ahorrar espacio. */ - - for(i = 0; i < 3; i++) - { - /* Copia los nombres al búfer. */ - sprintf(buf, "Test-undermenu - %d", i); - - /* Crea un nuevo elemento de menú con un nombre... */ - menu_items = gtk_menu_item_new_with_label(buf); - - /* ...y lo añade al menú. */ - gtk_menu_append(GTK_MENU (menu), menu_items); - - /* Hace algo interesante cuando se selecciona el menuitem */ - gtk_signal_connect_object(GTK_OBJECT(menu_items), "activate", - GTK_SIGNAL_FUNC(menuitem_response), (gpointer) g_strdup(buf)); - - /* Muestra el widget */ - gtk_widget_show(menu_items); - } - - /* Ésta es el menú raíz, y será la etiqueta mostrada en la - * barra de menús. No habrá ningún manejador de señal conectado, ya que - * lo único que hace es desplegar el resto del menú. */ - root_menu = gtk_menu_item_new_with_label("Root Menu"); - - gtk_widget_show(root_menu); - - /* Ahora especificamos que queremos que el recien creado "menu" - * sea el menú para el "root menu" */ - gtk_menu_item_set_submenu(GTK_MENU_ITEM (root_menu), menu); - - /* Un vbox para poner dentro un menú y un botón */ - vbox = gtk_vbox_new(FALSE, 0); - gtk_container_add(GTK_CONTAINER(ventana), vbox); - gtk_widget_show(vbox); - - /* Crear una barra de menú para que contenga al menú y la añadamos - * a nuestra ventana principal */ - menu_bar = gtk_menu_bar_new(); - gtk_box_pack_start(GTK_BOX(vbox), menu_bar, FALSE, FALSE, 2); - gtk_widget_show(menu_bar); - - /* Crear un botón al que atar los menús como un popup */ - boton = gtk_button_new_with_label("press me"); - gtk_signal_connect_object(GTK_OBJECT(boton), "event", - GTK_SIGNAL_FUNC (button_press), GTK_OBJECT(menu)); - gtk_box_pack_end(GTK_BOX(vbox), boton, TRUE, TRUE, 2); - gtk_widget_show(boton); - - /* Y finalmente añadimos el elemento de menú y la barra de menú -- - * éste es el elemento de menú "raíz" sobre el que he estado - * delirando =) */ - gtk_menu_bar_append(GTK_MENU_BAR (menu_bar), root_menu); - - /* siempre mostramos la ventana como último paso para que todo se - * pongo en pantalla a la vez. */ - gtk_widget_show(ventana); - - gtk_main (); - - return 0; -} - -/* Responde a una pulsación del botón enviando un menú como un widget - * Recuerde que el argumento "widget" es el menú que se está enviando, - * NO el botón que se ha pulsado. - */ - -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); - /* Le dice al que llamó a la rutina que hemos manejado el - * evento; la historia termina aquí. */ - return TRUE; - } - - /* Le dice al que llamó a la rutina que no hemos manejado el - * evento. */ - return FALSE; -} - - -/* Imprime una cadena cuando se selecciona un elemento del menú */ - -static void menuitem_response (gchar *string) -{ - printf("%s\n", string); -} -/* final del ejemplo */ -</verb></tscreen> - -También puede hacer que un elemento del menú sea insensible y, utilizando -una tabla de teclas aceleradoras, conectar las teclas con las funciones -del menú. - -<!-- XXX Las dos sect1 que vienen han cambiado --> -<!-- ----------------------------------------------------------------- --> -<sect1>Utilizando GtkItemFactory -<p> -Ahora que le hemos enseñado la forma difícil, le mostraremos como -utilizar las llamadas <tt/gtk_item_factory/. - -<!-- ----------------------------------------------------------------- --> -<sect1>Ejemplo de la fábrica de elementos -<p> -Aquí hay un ejemplo de cómo utilizar la fábrica de elementos -GTK. - -<tscreen><verb> -/* principio del ejemplo menu itemfactory.h */ - -#include <gtk/gtk.h> -#include <strings.h> - -/* La obligatoria función de llamada */ -static void print_hello( GtkWidget *w, - gpointer data ) -{ - g_message ("Hello, World!\n"); -} - -/* Esta es la estructura GtkItemFactoryEntry utilizada para crear - nuevos menúes. - - This is the GtkItemFactoryEntry structure used to generate new menus. - Elemento 1: La dirección del menú. La letra que hay - después del subrayado indica una tecla aceleradora - una vez que el menú esté abierto. - Elemento 2: La tecla aceleradora para la entrada del menú. - Elemento 3: La función de llamada. - Elemento 4: La acción de llamada. Cambia los parámetros que - se le pasan a la función de llamada. El valor por - defecto es 0. - Elemento 5: El tipo de elemento, se utiliza para definir de que - tipo de elemento se trata. Los valores posibles son: - - NULL -> "<Item>" - "" -> "<Item>" - "<Title>" -> crea un elemento título - "<Item>" -> crea un simple elemento - "<CheckItem>" -> crea un elemento de comprobación - "<ToggleItem>" -> crea un elemento de selección - "<RadioItem>" -> crea un elemento circular - <path> -> dirección de un elemento circular - con el que enlazar - "<Separator>" -> crea un separador - "<Branch>" -> crea un elemento para contener - subelementos (de forma opcional) - "<LastBranch>" -> crea una rama justificada a la - derecha -*/ - -static GtkItemFactoryEntry menu_items[] = { - { "/_File", NULL, NULL, 0, "<Branch>" }, - { "/File/_New", "<control>N", print_hello, 0, NULL }, - { "/File/_Open", "<control>O", print_hello, 0, NULL }, - { "/File/_Save", "<control>S", print_hello, 0, NULL }, - { "/File/Save _As", NULL, NULL, 0, NULL }, - { "/File/sep1", NULL, NULL, 0, "<Separator>" }, - { "/File/Quit", "<control>Q", gtk_main_quit, 0, NULL }, - { "/_Options", NULL, NULL, 0, "<Branch>" }, - { "/Options/Test", NULL, NULL, 0, NULL }, - { "/_Help", NULL, NULL, 0, "<LastBranch>" }, - { "/_Help/About", NULL, NULL, 0, NULL }, -}; - - -void get_main_menu( GtkWidget *ventana, - GtkWidget **menubar ) -{ - GtkItemFactory *item_factory; - GtkAccelGroup *accel_group; - gint nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]); - - accel_group = gtk_accel_group_new (); - - /* Esta función inicializa la fábrica de elementos - Param 1: El tipo de menú - puede ser GTK_TYPE_MENU_BAR, - GTK_TYPE_MENU, o GTK_TYPE_OPTION_MENU. - Param 2: La dirección del menú. - Param 3: Un puntero a un gtk_accel_group. La fábrica de - elementos actualiza la tabla de teclas aceleradoras - mientras genera los menúes. - */ - - item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", - accel_group); - - /* Esta función genera los elementos de menú. Pasa la - fábrica de elementos (item_factory), el número de elementos - del vector, el vector en sí, y cualquier dato de llamada para - los elementos de menú. */ - gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL); - - /* Enlaza el nuevo grupo acelerador a la ventana. */ - gtk_accel_group_attach (accel_group, GTK_OBJECT (ventana)); - - if (menubar) - /* Finalmente, devuelve la barra de menú creada por la - * fábrica de elementos. */ - *menubar = gtk_item_factory_get_widget (item_factory, "<main>"); -} - -int main( int argc, - char *argv[] ) -{ - GtkWidget *ventana; - GtkWidget *main_vbox; - GtkWidget *menubar; - - gtk_init (&argc, &argv); - - ventana = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_signal_connect (GTK_OBJECT (ventana), "destroy", - GTK_SIGNAL_FUNC (gtk_main_quit), - "WM destroy"); - gtk_window_set_title (GTK_WINDOW(ventana), "Item Factory"); - gtk_widget_set_usize (GTK_WIDGET(ventana), 300, 200); - - main_vbox = gtk_vbox_new (FALSE, 1); - gtk_container_border_width (GTK_CONTAINER (main_vbox), 1); - gtk_container_add (GTK_CONTAINER (ventana), main_vbox); - gtk_widget_show (main_vbox); - - get_main_menu (ventana, &menubar); - gtk_box_pack_start (GTK_BOX (main_vbox), menubar, FALSE, TRUE, 0); - gtk_widget_show (menubar); - - gtk_widget_show (ventana); - gtk_main (); - - return(0); -} -/* fin del ejemplo */ -</verb></tscreen> - -Por ahora, sólo está este ejemplo. Ya llegará una -explicación del mismo y más comentarios. - -<!-- ***************************************************************** --> -<sect> El <em>widget</em> texto -<!-- ***************************************************************** --> -<p> -El <em>widget</em> texto permite mostrar y editar multiples líneas de -texto. Admite texto en varios colores y con varios tipos de letra, -permitiendo mezclarlos de cualquier forma que desee. También hay un -gran número de teclas para la edición de textos, que son compatibles -con Emacs. - -El <em>widget</em> texto admite copiar-y-pegar, incluyendo la -utilización de doble y triple-click para seleccionar una palabra y una -línea completa, respectivamente. - -<!-- ----------------------------------------------------------------- --> -<sect1>Creando y configurando un cuadro de texto -<p> -Sólo hay una función para crear un nuevo <em>widget</em> texto. -<tscreen><verb> -GtkWidget *gtk_text_new( GtkAdjustment *hadj, - GtkAdjustment *vadj ); -</verb></tscreen> - -Los argumentos nos permitirán dar al <em>widget</em> texto punteros a -<tt/GtkAdjustement/ que pueden ser utilizados para controlar la visión -de la posición del <em>widget</em>. Si le ponemos un valor NULL en -cualquiera de los dos argumentos (o en los dos), la función -<tt/gtk_text_new/ creará su propio ajuste. - -<tscreen><verb> -void gtk_text_set_adjustments( GtkText *text, - GtkAdjustment *hadj, - GtkAdjustment *vadj ); -</verb></tscreen> - -La función de arriba permite cambiar en cualquier momento el ajuste -horizontal y vertical de un <em>widget</em> texto. - -El <em>widget</em> texto no crea automáticamente sus propiar barras -de desplazamiento cuando el texto a mostrar es demasiado largo -para la ventana en la que se encuentra. Tenemos que crearlas y -añadirlas a la capa del <em>display</em> nosotros mismos. - -<tscreen><verb> - vscrollbar = gtk_vscrollbar_new (GTK_TEXT(text)->vadj); - gtk_box_pack_start(GTK_BOX(hbox), vscrollbar, FALSE, FALSE, 0); - gtk_widget_show (vscrollbar); -</verb></tscreen> - -El trozo de código de arriba crea una nueva barra de desplazamiento -vertical, y la conecta con el ajuste vertical del <em>widget</em> -de texto, <tt/text/. Entonces la empaqueta en un cuadro de la forma -usual. - -Observe que, actualmente el <em>widget</em> GtkText no admite barras -de desplazamiento horizontal. - -Principalmente hay dos maneras de utilizar un <em>widget</em> de -texto: permitiendo al usuario editar el texto, o permitiéndonos -mostrar varias líneas de texto al usuario. Para cambiar entre estos -dos modos de operación, el <em>widget</em> de texto tiene las -siguientes funciones: - -<tscreen><verb> -void gtk_text_set_editable( GtkText *text, - gint editable ); -</verb></tscreen> - -El argumento <tt/editable/ es un valor TRUE o FALSE que especifica si se -permite al usuario editar los contenidos del <em>widget</em> texto. -Cuando el <em>widget</em> texto se pueda editar, mostrará un cursor -en la posición actual de inserción. - -Sin embargo la utilización del <em>widget</em> en estos dos modos no -es algo permanente, ya que puede cambiar el estado editable del -<em>widget</em> texto e insertar texto en cualquier momento. - -El <em>widget</em> texto corta las líneas de texto que son demasiado -largas para que quepan en una sólo línea en la ventana. Su -comportamiento por defecto es cortar las palabras donde se terminan -las líneas. Esto puede cambiarse utilizando la siguiente función: - -<tscreen><verb> -void gtk_text_set_word_wrap( GtkText *text, - gint word_wrap ); -</verb></tscreen> - -Utilizando esta función podremos especificar que el <em>widget</em> -texto debería cortar las líneas largas en los límites de las -palabras. El argumento <tt/word_wrap/ es un valor TRUE o FALSE. - -<!-- ----------------------------------------------------------------- --> -<sect1>Manipulación de texto -<P> -El punto actual de inserción en un <em>widget</em> texto puede -cambiarse utilizando -<tscreen><verb> -void gtk_text_set_point( GtkText *text, - guint index ); -</verb></tscreen> - -donde <tt/index/ es la posición en la que poner el punto de inserción. - -Análogamente tenemos la función para obtener la posición del punto -de inserción: - -<tscreen><verb> -guint gtk_text_get_point( GtkText *text ); -</verb></tscreen> - -Una función que es útil en combinación con las dos anteriores es - -<tscreen><verb> -guint gtk_text_get_length( GtkText *text ); -</verb></tscreen> - -que devuelve la longitud actual del <em>widget</em> texto. La -longitud es el número de caracteres que hay en el bloque de texto, -incluyendo caracteres como el retorno de carro, que marca el final de -las líneas. - -Para insertar texto en la posición actual del cursor, tendrá que -utilizar la función <tt/gtk_text_insert/, que nos permitirá -especificar los colores de fondo y de la letra y un tipo de letra para -el texto. - -<tscreen><verb> -void gtk_text_insert( GtkText *text, - GdkFont *font, - GdkColor *fore, - GdkColor *back, - const char *chars, - gint length ); -</verb></tscreen> - -Pasar un valor <tt/NULL/ como el color de la letra (<tt/fore/), el -color de fondo (<tt/back/) o el tipo de letra (<tt/font/) hará que -se utilicen los valores que indiquen el estilo del <em>widget</em>. -Utilizar un valor de <tt/-1/ para el parámetro <tt/length/ hará -que se inserte todo el texto. - -El <em/widget/ texto es uno de los pocos de GTK que se redibuja -a sí mismo dinámicamente, fuera de la función <tt/gtk_main/. Esto -significa que todos los cambios en el contenido del <em/widget/ texto -se manifestarán inmediatamente. Para permitirnos realizar varias -actualizaciones del <em/widget/ de texto sin que se redibuje -continuamente, podemos congelar el <em/widget/, lo que hará que pare -momentaneamente de redibujarse a sí mismo cada vez que haya algún -cambio. Podemos descongelarlo cuando hayamos acabado con nuestras -actualizaciones. - -Las siguientes dos funciones realizarán la acción de congelar y -descongelar el <em/widget/: - -<tscreen><verb> -void gtk_text_freeze( GtkText *text ); - -void gtk_text_thaw( GtkText *text ); -</verb></tscreen> - -Se puede borrar el texto que se encuentra en el punto actual de -inserción del <em/widget/ de texto mediante dos funciones. El valor -devuelto es TRUE o FALSE en función del éxito de la operación. - -<tscreen><verb> -gint gtk_text_backward_delete( GtkText *text, - guint nchars ); - -gint gtk_text_forward_delete ( GtkText *text, - guint nchars ); -</verb></tscreen> - -Si quiere recuperar el contenido del <em/widget/ de texto, entonces -la macro <tt/GTK_TEXT_INDEX(t, index)/ le permitirá obtener el -carácter que se encuentra en la posición <tt/index/ del <em/widget/ -de texto <tt/t/. - -Para obtener mayores bloques de texto, podemos utilizar la función - -<tscreen><verb> -gchar *gtk_editable_get_chars( GtkEditable *editable, - gint start_pos, - gint end_pos ); -</verb></tscreen> - -Esta es una función de la clase padre del <em/widget/ texto. Un valor -de -1 en <tt/end_pos/ significa el final del texto. El índice del -texto empieza en 0. - -La función reserva un espacio de memoria para el bloque de texto, -por lo que no debe olvidarse de liberarlo con una llamada a -<tt/g_free/ cuando haya acabado el bloque. - -<!-- ----------------------------------------------------------------- --> -<sect1>Atajos por teclado -<p> -El <em/widget/ texto tiene ciertos atajos de teclado preinstalados -para las funciones de edición estándar, movimiento y selección. Pueden -utilizarse mediante combinaciones de las teclas Control y Alt. - -Además, si se mantiene apretada la tecla de Control y se utilizan las -teclas de movimiento, el cursor se moverá por palabras en lugar de por -caracteres. Manteniendo apretada la tecla Shift, las teclas de movimiento -harán que se extienda la selección. - -<sect2>Atajos para el movimiento -<p> -<itemize> -<item> Ctrl-A Principio de línea -<item> Ctrl-E Final de línea -<item> Ctrl-N Línea siguiente -<item> Ctrl-P Línea anterior -<item> Ctrl-B Retrasarse un carácter -<item> Ctrl-F Adelantarse un carácter -<item> Alt-B Retrasarse una palabra -<item> Alt-F Adelantarse una palabra -</itemize> - -<sect2>Atajos para la edición -<p> -<itemize> -<item> Ctrl-H Borrar el carácter anterior (Backspace) -<item> Ctrl-D Borrar el carácter siguiente (Suprimir) -<item> Ctrl-W Borrar la palabra anterior -<item> Alt-D Borrar la palabra siguiente -<item> Ctrl-K Borrar hasta el fin de la línea -<item> Ctrl-U Borrar la línea -</itemize> - -<sect2>Atajos de selección -<p> -<itemize> -<item> Ctrl-X Cortar al portapapeles -<item> Ctrl-C Copiar al portapapeles -<item> Ctrl-V Pegar desde el portapapeles -</itemize> - -<!-- ----------------------------------------------------------------- --> -<sect1>Un ejemplo de GtkText -<p> -<tscreen><verb> -/* principio del ejemplo text text.c */ - -/* text.c */ - -#include <stdio.h> -#include <gtk/gtk.h> - -void text_toggle_editable (GtkWidget *checkbutton, - GtkWidget *text) -{ - gtk_text_set_editable(GTK_TEXT(text), - GTK_TOGGLE_BUTTON(checkbutton)->active); -} - -void text_toggle_word_wrap (GtkWidget *checkbutton, - GtkWidget *text) -{ - gtk_text_set_word_wrap(GTK_TEXT(text), - GTK_TOGGLE_BUTTON(checkbutton)->active); -} - -void close_application( GtkWidget *widget, gpointer data ) -{ - gtk_main_quit(); -} - -int main (int argc, char *argv[]) -{ - GtkWidget *ventana; - GtkWidget *caja1; - GtkWidget *caja2; - GtkWidget *hbox; - GtkWidget *boton; - GtkWidget *check; - GtkWidget *separator; - GtkWidget *table; - GtkWidget *vscrollbar; - GtkWidget *text; - GdkColormap *cmap; - GdkColor colour; - GdkFont *fixed_font; - - FILE *infile; - - gtk_init (&argc, &argv); - - ventana = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_widget_set_usize (ventana, 600, 500); - gtk_window_set_policy (GTK_WINDOW(ventana), TRUE, TRUE, FALSE); - gtk_signal_connect (GTK_OBJECT (ventana), "destroy", - GTK_SIGNAL_FUNC(close_application), - NULL); - gtk_window_set_title (GTK_WINDOW (ventana), "Text Widget Example"); - gtk_container_border_width (GTK_CONTAINER (ventana), 0); - - - caja1 = gtk_vbox_new (FALSE, 0); - gtk_container_add (GTK_CONTAINER (ventana), caja1); - gtk_widget_show (caja1); - - - caja2 = gtk_vbox_new (FALSE, 10); - gtk_container_border_width (GTK_CONTAINER (caja2), 10); - gtk_box_pack_start (GTK_BOX (caja1), caja2, TRUE, TRUE, 0); - gtk_widget_show (caja2); - - - table = gtk_table_new (2, 2, FALSE); - gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2); - gtk_table_set_col_spacing (GTK_TABLE (table), 0, 2); - gtk_box_pack_start (GTK_BOX (caja2), table, TRUE, TRUE, 0); - gtk_widget_show (table); - - /* Crear el widget GtkText */ - text = gtk_text_new (NULL, NULL); - gtk_text_set_editable (GTK_TEXT (text), TRUE); - gtk_table_attach (GTK_TABLE (table), text, 0, 1, 0, 1, - GTK_EXPAND | GTK_SHRINK | GTK_FILL, - GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0); - gtk_widget_show (text); - - /* Añadir una barra de desplazamiento vertical al widget GtkText */ - vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj); - gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1, - GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0); - gtk_widget_show (vscrollbar); - - /* Obtener el mapa de colores del sistema y conseguir el color rojo */ - cmap = gdk_colormap_get_system(); - colour.red = 0xffff; - colour.green = 0; - colour.blue = 0; - if (!gdk_color_alloc(cmap, &colour)) { - g_error("couldn't allocate colour"); - } - - /* Cargar un fuente de tamaño fijo */ - fixed_font = gdk_font_load ("-misc-fixed-medium-r-*-*-*-140-*-*-*-*-*-*"); - - /* Al enviar la señal relize a un widget se crea una ventana para el - * mismo, y nos permite insertar texto */ - gtk_widget_realize (text); - - /* Congela el widget text, lo que nos permite hacer varias - * actualizaciones */ - gtk_text_freeze (GTK_TEXT (text)); - - /* Insertamos algún texto coloreado */ - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "Supports ", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &colour, NULL, - "colored ", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "text and different ", -1); - gtk_text_insert (GTK_TEXT (text), fixed_font, &text->style->black, NULL, - "fonts\n\n", -1); - - /* Cargamos el fichero text.c en la ventana de texto */ - - infile = fopen("text.c", "r"); - - if (infile) { - char buffer[1024]; - int nchars; - - while (1) - { - nchars = fread(buffer, 1, 1024, infile); - gtk_text_insert (GTK_TEXT (text), fixed_font, NULL, - NULL, buffer, nchars); - - if (nchars < 1024) - break; - } - - fclose (infile); - } - - /* Descongelamos el widget text, permitiéndonos ver todos los - * cambios */ - gtk_text_thaw (GTK_TEXT (text)); - - hbox = gtk_hbutton_box_new (); - gtk_box_pack_start (GTK_BOX (caja2), hbox, FALSE, FALSE, 0); - gtk_widget_show (hbox); - - check = gtk_check_button_new_with_label("Editable"); - gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, FALSE, 0); - gtk_signal_connect (GTK_OBJECT(check), "toggled", - GTK_SIGNAL_FUNC(text_toggle_editable), text); - gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(check), TRUE); - gtk_widget_show (check); - check = gtk_check_button_new_with_label("Wrap Words"); - gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, TRUE, 0); - gtk_signal_connect (GTK_OBJECT(check), "toggled", - GTK_SIGNAL_FUNC(text_toggle_word_wrap), text); - gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(check), FALSE); - gtk_widget_show (check); - - separator = gtk_hseparator_new (); - gtk_box_pack_start (GTK_BOX (caja1), separator, FALSE, TRUE, 0); - gtk_widget_show (separator); - - caja2 = gtk_vbox_new (FALSE, 10); - gtk_container_border_width (GTK_CONTAINER (caja2), 10); - gtk_box_pack_start (GTK_BOX (caja1), caja2, FALSE, TRUE, 0); - gtk_widget_show (caja2); - - boton = gtk_button_new_with_label ("close"); - gtk_signal_connect (GTK_OBJECT (boton), "clicked", - GTK_SIGNAL_FUNC(close_application), - NULL); - gtk_box_pack_start (GTK_BOX (caja2), boton, TRUE, TRUE, 0); - GTK_WIDGET_SET_FLAGS (boton, GTK_CAN_DEFAULT); - gtk_widget_grab_default (boton); - gtk_widget_show (boton); - - gtk_widget_show (ventana); - - gtk_main (); - - return 0; -} -/* fin del ejemplo */ -</verb></tscreen> - -<!-- ***************************************************************** --> -<sect> Los <em>widgets</em> no documentados -<!-- ***************************************************************** --> -<p> -¡Todos ellos necesitan de gente que los documente! :) Por favor, -considere el contribuir a nuestro tutorial. - -Si debe utilizar uno de estos <em/widgets/, que permanecen no -documentados, le sugiero que le eche un vistazo a su fichero de -cabecera respectivo en la distribución GTK. Los nombre de las -funciones GTK son muy descriptivos. Una vez haya comprendido como -funcionan las cosas, no le será difícil ver como hay que utilizar un -<em/widget/ simplemente mirando su declaración de funciones. Con esto, -y unos cuántos ejemplos del código de otros, no debería tener -problemas. - -Cuando haya comprendido todas las funciones de un nuevo <em/widget/ -no documentado, por favor considere el hecho de escribir un tutorial -para él, para que así otros se puedan beneficiar del tiempo que usted -gastó. - - -<!-- ----------------------------------------------------------------- --> -<sect1> Calendar -<p> -<!-- ----------------------------------------------------------------- --> -<sect1> CTree -<p> -<!-- ----------------------------------------------------------------- --> -<sect1> Curves -<p> -<!-- ----------------------------------------------------------------- --> -<sect1> Drawing Area -<p> -<!-- ----------------------------------------------------------------- --> -<sect1> Font Selection Dialog -<p> -<!-- ----------------------------------------------------------------- --> -<sect1> Gamma Curve -<p> -<!-- ----------------------------------------------------------------- --> -<sect1> Image -<p> -<!-- ----------------------------------------------------------------- --> -<sect1> Packer -<p> -<!-- ----------------------------------------------------------------- --> -<sect1> Plugs and Sockets -<p> -<!-- ----------------------------------------------------------------- --> -<sect1> Preview -<p> - -<!-- - -(This may need to be rewritten to follow the style of the rest of the tutorial) - -<tscreen><verb> - -Previews serve a number of purposes in GIMP/GTK. The most important one is -this. High quality images may take up to tens of megabytes of memory - easy! -Any operation on an image that big is bound to take a long time. If it takes -you 5-10 trial-and-errors (i.e. 10-20 steps, since you have to revert after -you make an error) to choose the desired modification, it make take you -literally hours to make the right one - if you don't run out of memory -first. People who have spent hours in color darkrooms know the feeling. -Previews to the rescue! - -But the annoyance of the delay is not the only issue. Oftentimes it is -helpful to compare the Before and After versions side-by-side or at least -back-to-back. If you're working with big images and 10 second delays, -obtaining the Before and After impressions is, to say the least, difficult. -For 30M images (4"x6", 600dpi, 24 bit) the side-by-side comparison is right -out for most people, while back-to-back is more like back-to-1001, 1002, -..., 1010-back! Previews to the rescue! - -But there's more. Previews allow for side-by-side pre-previews. In other -words, you write a plug-in (e.g. the filterpack simulation) which would have -a number of here's-what-it-would-look-like-if-you-were-to-do-this previews. -An approach like this acts as a sort of a preview palette and is very -effective for subtle changes. Let's go previews! - -There's more. For certain plug-ins real-time image-specific human -intervention maybe necessary. In the SuperNova plug-in, for example, the -user is asked to enter the coordinates of the center of the future -supernova. The easiest way to do this, really, is to present the user with a -preview and ask him to interactively select the spot. Let's go previews! - -Finally, a couple of misc uses. One can use previews even when not working -with big images. For example, they are useful when rendering complicated -patterns. (Just check out the venerable Diffraction plug-in + many other -ones!) As another example, take a look at the colormap rotation plug-in -(work in progress). You can also use previews for little logos inside you -plug-ins and even for an image of yourself, The Author. Let's go previews! - -When Not to Use Previews - -Don't use previews for graphs, drawing etc. GDK is much faster for that. Use -previews only for rendered images! - -Let's go previews! - -You can stick a preview into just about anything. In a vbox, an hbox, a -table, a button, etc. But they look their best in tight frames around them. -Previews by themselves do not have borders and look flat without them. (Of -course, if the flat look is what you want...) Tight frames provide the -necessary borders. - - [Image][Image] - -Previews in many ways are like any other widgets in GTK (whatever that -means) except they possess an additional feature: they need to be filled with -some sort of an image! First, we will deal exclusively with the GTK aspect -of previews and then we'll discuss how to fill them. - -GtkWidget *preview! - -Without any ado: - - /* Create a preview widget, - set its size, an show it */ -GtkWidget *preview; -preview=gtk_preview_new(GTK_PREVIEW_COLOR) - /*Other option: - GTK_PREVIEW_GRAYSCALE);*/ -gtk_preview_size (GTK_PREVIEW (preview), WIDTH, HEIGHT); -gtk_widget_show(preview); -my_preview_rendering_function(preview); - -Oh yeah, like I said, previews look good inside frames, so how about: - -GtkWidget *create_a_preview(int Width, - int Height, - int Colorfulness) -{ - GtkWidget *preview; - GtkWidget *frame; - - frame = gtk_frame_new(NULL); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); - gtk_container_set_border_width (GTK_CONTAINER(frame),0); - gtk_widget_show(frame); - - preview=gtk_preview_new (Colorfulness?GTK_PREVIEW_COLOR - :GTK_PREVIEW_GRAYSCALE); - gtk_preview_size (GTK_PREVIEW (preview), Width, Height); - gtk_container_add(GTK_CONTAINER(frame),preview); - gtk_widget_show(preview); - - my_preview_rendering_function(preview); - return frame; -} - -That's my basic preview. This routine returns the "parent" frame so you can -place it somewhere else in your interface. Of course, you can pass the -parent frame to this routine as a parameter. In many situations, however, -the contents of the preview are changed continually by your application. In -this case you may want to pass a pointer to the preview to a -"create_a_preview()" and thus have control of it later. - -One more important note that may one day save you a lot of time. Sometimes -it is desirable to label you preview. For example, you may label the preview -containing the original image as "Original" and the one containing the -modified image as "Less Original". It might occur to you to pack the -preview along with the appropriate label into a vbox. The unexpected caveat -is that if the label is wider than the preview (which may happen for a -variety of reasons unforseeable to you, from the dynamic decision on the -size of the preview to the size of the font) the frame expands and no longer -fits tightly over the preview. The same problem can probably arise in other -situations as well. - - [Image] - -The solution is to place the preview and the label into a 2x1 table and by -attaching them with the following parameters (this is one possible variations -of course. The key is no GTK_FILL in the second attachment): - -gtk_table_attach(GTK_TABLE(table),label,0,1,0,1, - 0, - GTK_EXPAND|GTK_FILL, - 0,0); -gtk_table_attach(GTK_TABLE(table),frame,0,1,1,2, - GTK_EXPAND, - GTK_EXPAND, - 0,0); - - -And here's the result: - - [Image] - -Misc - -Making a preview clickable is achieved most easily by placing it in a -boton. It also adds a nice border around the preview and you may not even -need to place it in a frame. See the Filter Pack Simulation plug-in for an -example. - -This is pretty much it as far as GTK is concerned. - -Filling In a Preview - -In order to familiarize ourselves with the basics of filling in previews, -let's create the following pattern (contrived by trial and error): - - [Image] - -void -my_preview_rendering_function(GtkWidget *preview) -{ -#define SIZE 100 -#define HALF (SIZE/2) - - guchar *row=(guchar *) malloc(3*SIZE); /* 3 bits per dot */ - gint i, j; /* Coordinates */ - double r, alpha, x, y; - - if (preview==NULL) return; /* I usually add this when I want */ - /* to avoid silly crashes. You */ - /* should probably make sure that */ - /* everything has been nicely */ - /* initialized! */ - for (j=0; j < ABS(cos(2*alpha)) ) { /* Are we inside the shape? */ - /* glib.h contains ABS(x). */ - row[i*3+0] = sqrt(1-r)*255; /* Define Red */ - row[i*3+1] = 128; /* Define Green */ - row[i*3+2] = 224; /* Define Blue */ - } /* "+0" is for alignment! */ - else { - row[i*3+0] = r*255; - row[i*3+1] = ABS(sin((float)i/SIZE*2*PI))*255; - row[i*3+2] = ABS(sin((float)j/SIZE*2*PI))*255; - } - } - gtk_preview_draw_row( GTK_PREVIEW(preview),row,0,j,SIZE); - /* Insert "row" into "preview" starting at the point with */ - /* coordinates (0,j) first column, j_th row extending SIZE */ - /* pixels to the right */ - } - - free(row); /* save some space */ - gtk_widget_draw(preview,NULL); /* what does this do? */ - gdk_flush(); /* or this? */ -} - -Non-GIMP users can have probably seen enough to do a lot of things already. -For the GIMP users I have a few pointers to add. - -Image Preview - -It is probably wise to keep a reduced version of the image around with just -enough pixels to fill the preview. This is done by selecting every n'th -pixel where n is the ratio of the size of the image to the size of the -preview. All further operations (including filling in the previews) are then -performed on the reduced number of pixels only. The following is my -implementation of reducing the image. (Keep in mind that I've had only basic -C!) - -(UNTESTED CODE ALERT!!!) - -typedef struct { - gint width; - gint height; - gint bbp; - guchar *rgb; - guchar *mask; -} ReducedImage; - -enum { - SELECTION_ONLY, - SELECTION_IN_CONTEXT, - ENTIRE_IMAGE -}; - -ReducedImage *Reduce_The_Image(GDrawable *drawable, - GDrawable *mask, - gint LongerSize, - gint Selection) -{ - /* This function reduced the image down to the the selected preview size */ - /* The preview size is determine by LongerSize, i.e. the greater of the */ - /* two dimensions. Works for RGB images only! */ - gint RH, RW; /* Reduced height and reduced width */ - gint width, height; /* Width and Height of the area being reduced */ - gint bytes=drawable->bpp; - ReducedImage *temp=(ReducedImage *)malloc(sizeof(ReducedImage)); - - guchar *tempRGB, *src_row, *tempmask, *src_mask_row,R,G,B; - gint i, j, whichcol, whichrow, x1, x2, y1, y2; - GPixelRgn srcPR, srcMask; - gint NoSelectionMade=TRUE; /* Assume that we're dealing with the entire */ - /* image. */ - - gimp_drawable_mask_bounds (drawable->id, &x1, &y1, &x2, &y2); - width = x2-x1; - height = y2-y1; - /* If there's a SELECTION, we got its bounds!) - - if (width != drawable->width && height != drawable->height) - NoSelectionMade=FALSE; - /* Become aware of whether the user has made an active selection */ - /* This will become important later, when creating a reduced mask. */ - - /* If we want to preview the entire image, overrule the above! */ - /* Of course, if no selection has been made, this does nothing! */ - if (Selection==ENTIRE_IMAGE) { - x1=0; - x2=drawable->width; - y1=0; - y2=drawable->height; - } - - /* If we want to preview a selection with some surrounding area we */ - /* have to expand it a little bit. Consider it a bit of a riddle. */ - if (Selection==SELECTION_IN_CONTEXT) { - x1=MAX(0, x1-width/2.0); - x2=MIN(drawable->width, x2+width/2.0); - y1=MAX(0, y1-height/2.0); - y2=MIN(drawable->height, y2+height/2.0); - } - - /* How we can determine the width and the height of the area being */ - /* reduced. */ - width = x2-x1; - height = y2-y1; - - /* The lines below determine which dimension is to be the longer */ - /* side. The idea borrowed from the supernova plug-in. I suspect I */ - /* could've thought of it myself, but the truth must be told. */ - /* Plagiarism stinks! */ - if (width>height) { - RW=LongerSize; - RH=(float) height * (float) LongerSize/ (float) width; - } - else { - RH=LongerSize; - RW=(float)width * (float) LongerSize/ (float) height; - } - - /* The entire image is stretched into a string! */ - tempRGB = (guchar *) malloc(RW*RH*bytes); - tempmask = (guchar *) malloc(RW*RH); - - gimp_pixel_rgn_init (&srcPR, drawable, x1, y1, width, height, - FALSE, FALSE); - gimp_pixel_rgn_init (&srcMask, mask, x1, y1, width, height, - FALSE, FALSE); - - /* Grab enough to save a row of image and a row of mask. */ - src_row = (guchar *) malloc (width*bytes); - src_mask_row = (guchar *) malloc (width); - - for (i=0; i < RH; i++) { - whichrow=(float)i*(float)height/(float)RH; - gimp_pixel_rgn_get_row (&srcPR, src_row, x1, y1+whichrow, width); - gimp_pixel_rgn_get_row (&srcMask, src_mask_row, x1, y1+whichrow, width); - - for (j=0; j < RW; j++) { - whichcol=(float)j*(float)width/(float)RW; - - /* No selection made = each point is completely selected! */ - if (NoSelectionMade) - tempmask[i*RW+j]=255; - else - tempmask[i*RW+j]=src_mask_row[whichcol]; - - /* Add the row to the one long string which now contains the image! */ - tempRGB[i*RW*bytes+j*bytes+0]=src_row[whichcol*bytes+0]; - tempRGB[i*RW*bytes+j*bytes+1]=src_row[whichcol*bytes+1]; - tempRGB[i*RW*bytes+j*bytes+2]=src_row[whichcol*bytes+2]; - - /* Hold on to the alpha as well */ - if (bytes==4) - tempRGB[i*RW*bytes+j*bytes+3]=src_row[whichcol*bytes+3]; - } - } - temp->bpp=bytes; - temp->width=RW; - temp->height=RH; - temp->rgb=tempRGB; - temp->mask=tempmask; - return temp; -} - -The following is a preview function which used the same ReducedImage type! -Note that it uses fakes transparency (if one is present by means of -fake_transparency which is defined as follows: - -gint fake_transparency(gint i, gint j) -{ - if ( ((i%20)- 10) * ((j%20)- 10)>0 ) - return 64; - else - return 196; -} - -Now here's the preview function: - -void -my_preview_render_function(GtkWidget *preview, - gint changewhat, - gint changewhich) -{ - gint Inten, bytes=drawable->bpp; - gint i, j, k; - float partial; - gint RW=reduced->width; - gint RH=reduced->height; - guchar *row=malloc(bytes*RW);; - - - for (i=0; i < RH; i++) { - for (j=0; j < RW; j++) { - - row[j*3+0] = reduced->rgb[i*RW*bytes + j*bytes + 0]; - row[j*3+1] = reduced->rgb[i*RW*bytes + j*bytes + 1]; - row[j*3+2] = reduced->rgb[i*RW*bytes + j*bytes + 2]; - - if (bytes==4) - for (k=0; k<3; k++) { - float transp=reduced->rgb[i*RW*bytes+j*bytes+3]/255.0; - row[3*j+k]=transp*a[3*j+k]+(1-transp)*fake_transparency(i,j); - } - } - gtk_preview_draw_row( GTK_PREVIEW(preview),row,0,i,RW); - } - - free(a); - gtk_widget_draw(preview,NULL); - gdk_flush(); -} - -Applicable Routines - -guint gtk_preview_get_type (void); -/* No idea */ -void gtk_preview_uninit (void); -/* No idea */ -GtkWidget* gtk_preview_new (GtkPreviewType type); -/* Described above */ -void gtk_preview_size (GtkPreview *preview, - gint width, - gint height); -/* Allows you to resize an existing preview. */ -/* Apparently there's a bug in GTK which makes */ -/* this process messy. A way to clean up a mess */ -/* is to manually resize the window containing */ -/* the preview after resizing the preview. */ - -void gtk_preview_put (GtkPreview *preview, - GdkWindow *ventana, - GdkGC *gc, - gint srcx, - gint srcy, - gint destx, - gint desty, - gint width, - gint height); -/* No idea */ - -void gtk_preview_put_row (GtkPreview *preview, - guchar *src, - guchar *dest, - gint x, - gint y, - gint w); -/* No idea */ - -void gtk_preview_draw_row (GtkPreview *preview, - guchar *data, - gint x, - gint y, - gint w); -/* Described in the text */ - -void gtk_preview_set_expand (GtkPreview *preview, - gint expand); -/* No idea */ - -/* No clue for any of the below but */ -/* should be standard for most widgets */ -void gtk_preview_set_gamma (double gamma); -void gtk_preview_set_color_cube (guint nred_shades, - guint ngreen_shades, - guint nblue_shades, - guint ngray_shades); -void gtk_preview_set_install_cmap (gint install_cmap); -void gtk_preview_set_reserved (gint nreserved); -GdkVisual* gtk_preview_get_visual (void); -GdkColormap* gtk_preview_get_cmap (void); -GtkPreviewInfo* gtk_preview_get_info (void); - -That's all, folks! - -</verb></tscreen> - ---> - -<!-- ***************************************************************** --> -<sect>Estableciendo los atributos de un <em/widget/<label id="sec_setting_widget_attributes"> -<!-- ***************************************************************** --> -<p> -En este capítulo se describen las funciones utilizadas para manejar los -<em/widgets/. Pueden utilizarse para establecer el estilo, relleno, -tamaño, etc... - -(Puede que deba hacer una sección completa para los aceleradores.) - -<tscreen><verb> -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 ); -</verb></tscreen> - -<!-- ***************************************************************** --> -<sect>Tiempos de espera, ES (<em/IO/) y funciones ociosas (<em/idle/)<label id="sec_timeouts"> -<!-- ***************************************************************** --> - -<!-- ----------------------------------------------------------------- --> -<sect1>Tiempos de espera -<p> -Puede que se esté preguntando como hacer que GTK haga algo útil -cuando se encuentra en <tt/gtk_main/. Bien, tiene varias -opciones. Utilizando las rutinas siguientes puede crear una función -a la que se llamará cada <tt/interval/ milisegundos. - -<tscreen><verb> -gint gtk_timeout_add( guint32 interval, - GtkFunction function, - gpointer data ); -</verb></tscreen> - -El primer argumento es el número de milisegundos que habrá entre dos -llamadas a su función. El segundo argumento es la función a la que -desea llamar, y el tercero, los datos que le pasará a ésta función. -El valor devuelto es un «identificador» (un valor entero) que puede -utilizar para detener las llamadas haciendo: - -<tscreen><verb> -void gtk_timeout_remove( gint tag ); -</verb></tscreen> - -También puede hacer que cesen las llamadas a la función haciendo que -la misma devuelva cero o FALSE. Obviamente esto significa que si -quiere que se continue llamando a su función, deberá devolver un valor -distinto de cero, es decir TRUE. - -La declaración de su función debería ser algo como: - -<tscreen><verb> -gint timeout_callback( gpointer data ); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Monitorizando la ES -<p> -Otra característica divertida de GTK, es la habilidad que tiene de -comprobar datos por usted en un descriptor de fichero (tal y como -se devuelven por <tt/open(2)/ o <tt/socket(2)/). Esto es especialmente -útil para las aplicaciones de red. La función: - -<tscreen><verb> -gint gdk_input_add( gint source, - GdkInputCondition condition, - GdkInputFunction function, - gpointer data ); -</verb></tscreen> - -Donde el primer argumento es el descriptor de fichero que desea vigilar, -y el segundo especifica que es lo que quiere que GDK busque. Puede ser uno -de los siguientes: - -<itemize> -<item>GDK_INPUT_READ - Llama a su función cuando hay datos listos para -leerse del fichero. - -<item>GDK_INPUT_WRITE - Llama a su función cuando el descriptor del -fichero está listo para la escritura. -</itemize> - -Tal y como se habrá imaginado, el tercer argumento es la función a la -que desea que se llame cuando se den las condiciones anteriores, y el -cuarto son los datos que se le pasarán a ésta función. - -El valor devuelto es un identificador que puede utilizarse para que GDK -pare de vigilar ese fichero, utilizando la función - -<tscreen><verb> -void gdk_input_remove( gint tag ); -</verb></tscreen> - -La función a la que quiere que se llame deberá declararse así: - -<tscreen><verb> -void input_callback( gpointer data, - gint source, - GdkInputCondition condition ); -</verb></tscreen> - -Donde <tt/source/ y <tt/condition/ están especificados más arriba. - -<!-- ----------------------------------------------------------------- --> -<sect1>Funciones ociosas -<p> -<!-- Need to check on idle priorities - TRG --> -¿Qué le parece si tuviese una función a la que se llamase cuando -no ocurriese nada? - -<tscreen><verb> -gint gtk_idle_add( GtkFunction function, - gpointer data ); -</verb></tscreen> - -Esto hace que GTK llame a la función especificada cuando no ocurra -nada más. - -<tscreen><verb> -void gtk_idle_remove( gint tag ); -</verb></tscreen> - -No voy a explicar el significado de los argumentos ya que se parece -mucho a los que he explicado más arriba. La función a la que se apunta -mediante el primer argumento de <tt/gtk_idle_add/ será a la que se -llame cuando llegue el momento. Como antes, si devuelve FALSE hará que -cese de llamarse a la función. - -<!-- ***************************************************************** --> -<sect>Manejo avanzado de eventos y señales<label id="sec_Adv_Events_and_Signals"> -<!-- ***************************************************************** --> - -<!-- ----------------------------------------------------------------- --> -<sect1>Funciones señal - -<!-- ----------------------------------------------------------------- --> -<sect2>Conectando y desconectando los manejadores de señal -<p> - -<tscreen><verb> -guint gtk_signal_connect( GtkObject *object, - const gchar *name, - GtkSignalFunc func, - gpointer func_data ); - -guint gtk_signal_connect_after( GtkObject *object, - const gchar *name, - GtkSignalFunc func, - gpointer func_data ); - -guint gtk_signal_connect_object( GtkObject *object, - const gchar *name, - GtkSignalFunc func, - GtkObject *slot_object ); - -guint gtk_signal_connect_object_after( GtkObject *object, - const gchar *name, - GtkSignalFunc func, - GtkObject *slot_object ); - -guint gtk_signal_connect_full( GtkObject *object, - const gchar *name, - GtkSignalFunc func, - GtkCallbackMarshal marshal, - gpointer data, - GtkDestroyNotify destroy_func, - gint object_signal, - gint after ); - -guint gtk_signal_connect_interp( GtkObject *object, - const gchar *name, - GtkCallbackMarshal func, - gpointer data, - GtkDestroyNotify destroy_func, - gint after ); - -void gtk_signal_connect_object_while_alive( GtkObject *object, - const gchar *signal, - GtkSignalFunc func, - GtkObject *alive_object ); - -void gtk_signal_connect_while_alive( GtkObject *object, - const gchar *signal, - GtkSignalFunc func, - gpointer func_data, - GtkObject *alive_object ); - -void gtk_signal_disconnect( GtkObject *object, - guint handler_id ); - -void gtk_signal_disconnect_by_func( GtkObject *object, - GtkSignalFunc func, - gpointer data ); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect2>Bloqueando y desbloqueando los manejadores de señal -<p> -<tscreen><verb> -void gtk_signal_handler_block( GtkObject *object, - guint handler_id); - -void gtk_signal_handler_block_by_func( GtkObject *object, - GtkSignalFunc func, - gpointer data ); - -void gtk_signal_handler_block_by_data( GtkObject *object, - gpointer data ); - -void gtk_signal_handler_unblock( GtkObject *object, - guint handler_id ); - -void gtk_signal_handler_unblock_by_func( GtkObject *object, - GtkSignalFunc func, - gpointer data ); - -void gtk_signal_handler_unblock_by_data( GtkObject *object, - gpointer data ); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect2>Emitiendo y deteniendo señales -<p> -<tscreen><verb> -void gtk_signal_emit( GtkObject *object, - guint signal_id, - ... ); - -void gtk_signal_emit_by_name( GtkObject *object, - const gchar *name, - ... ); - -void gtk_signal_emitv( GtkObject *object, - guint signal_id, - GtkArg *params ); - -void gtk_signal_emitv_by_name( GtkObject *object, - const gchar *name, - GtkArg *params ); - -guint gtk_signal_n_emissions( GtkObject *object, - guint signal_id ); - -guint gtk_signal_n_emissions_by_name( GtkObject *object, - const gchar *name ); - -void gtk_signal_emit_stop( GtkObject *object, - guint signal_id ); - -void gtk_signal_emit_stop_by_name( GtkObject *object, - const gchar *name ); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Emisión y propagación de señales -<p> -La emisión de señales es el proceso mediante el cual GTK+ ejecuta -todos los manejadores de un objeto y una señal en especial. - -Primero, observe que el valor devuelto por la emisión de una -señal es el mismo que el valor devuelto por el <em>último</em> -manipulador ejecutado. Ya que las señales de los eventos son todas -del tipo GTK_RUN_LAST, el manejador por defecto (proporcionado por -GTK+) será de este tipo, a menos que lo conecte con -<tt/gtk_signal_connect_after()/. - -La forma en que se maneja un evento (digamos GTK_BUTTON_PRESS), es la -siguiente: - -<itemize> -<item>Empieza con el <em>widget</em> donde ocurrió el evento. - -<item>Emite la señal genérica <tt/event/. Si esta señal devuelve un -valor TRUE, detiene todo el proceso. - -<item>En caso contrario, emite una señal especifica, -«button_press_event» en nuestro caso. Si ésta devuelve TRUE, detiene -todo el proceso. - -<item>En caso contrario, va al <em>widget</em> padre y repite los -pasos anteriores. - -<item>Continua hasta que algún manejador de señal devuelva TRUE, o -hasta que se llegue al <em>widget</em> de más alto nivel. -</itemize> - -Algunas consecuencias son: -<itemize> -<item>El valor que devuelva su manejador no tendrá ningún efecto si -hay un manejador por defecto, a menos que lo conecte mediante -<tt/gtk_signal_connect_after()/. - -<item>Para evitar que el manejador por defecto se ejecute, necesita -conectar mediante <tt/gtk_signal_connect()/ y utilizar -<tt/gtk_signal_emit_stop_by_name()/ - el valor devuelto sólo se ve -afectado si la señal se propaga, y no sólo por el hecho de emitirse. -</itemize> - -<!-- ***************************************************************** --> -<sect>Manejando selecciones -<!-- ***************************************************************** --> - -<!-- ----------------------------------------------------------------- --> -<sect1> Contenido -<p> -Un tipo de comunicación entre procesos que se puede utilizar con GTK -son las <em/selecciones/. Una selección identifica un conjunto de -datos, por ejemplo, un trozo de texto, seleccionado por el usuario de -alguna manera, por ejemplo, cogiéndolo con el ratón. Sólo una -aplicación en un <em/display/ (la <em>propietaria</em>) puede tener -una selección en particular en un momento dado, por lo que cuando una -aplicación pide una selección, el propietario previo debe indicar al -usuario que la selección ya no es válida. Otras aplicaciones pueden -pedir el contenido de la selección de diferentes formas, llamadas -<em/objetivos/. Puede haber cualquier número de selecciones, pero la -mayoría de las aplicacion X sólo pueden manejar una, la <em/selección -primaria/. - -En muchos casos, no es necesario para una aplicación GTK tratar por -sí misma con las selecciones. Los <em/widgets/ estándar, como el -<em/widget/ Entry, ya tienen la posibilidad de crear la selección -cuando sea necesario (p.e., cuando el usuario pase el ratón sobre el -texto manteniendo el botón derecho del ratón pulsado), y de recoger -los contenidos de la selección propiedad de otro <em/widget/, o de -otra aplicación (p.e., cuando el usuario pulsa el segundo botón del -ratón). Sin embargo, pueden haber casos en los que quiera darle a -otros <em/widgets/ la posibilidad de proporcionar la selección, o -puede que quiera recuperar objetivos que no estén admitidos por -defecto. - -Un concepto fundamental que es necesario para comprender el manejo de -la selección es el de <em>átomo</em>. Un átomo es un entero que -identifica de una manera unívoca una cadena (en un cierto -<em/display/). Ciertos átomos están predefinidos por el servidor X, y -en algunos casos hay constantes en <tt>gtk.h</tt> que corresponden a -estos átomos. Por ejemplo la constante <tt>GDK_PRIMARY_SELECTION</tt> -corresponde a la cadena «PRIMARY». En otros casos, debería utilizar -las funciones <tt>gdk_atom_intern()</tt>, para obtener el átomo -correspondiente a una cadena, y <tt>gdk_atom_name()</tt>, para obtener -el nombre de un átomo. Ambas, selecciones y objetivos, están -identificados por átomos. - -<!-- ----------------------------------------------------------------- --> -<sect1> Recuperando la selección -<p> -Recuperar la selección es un proceso asíncrono. Para comenzar el -proceso, deberá llamar a: - -<tscreen><verb> -gint gtk_selection_convert( GtkWidget *widget, - GdkAtom selection, - GdkAtom target, - guint32 time ); -</verb</tscreen> - -Este proceso <em/convierte/ la selección en la forma especificada por -<tt/target/. Si es posible, el campo <tt/time/ debe ser el tiempo -desde que el evento lanzó la selección. Esto ayuda a asegurarse de que -los eventos ocurran en el orden en que el usuario los ha pedido. Sin -embargo, si no está disponible (por ejemplo, si se empezó la -conversión por una señal de «pulsación»), entonces puede utilizar la -constante <tt>GDK_CURRENT_TIME</tt>. - -Cuando el propietario de la selección responda a la petición, se -enviará una señal «selection_received» a su aplicación. El manejador -de esta señal recibe un puntero a una estructura -<tt>GtkSelectionData</tt>, que se define como: - -<tscreen><verb> -struct _GtkSelectionData -{ - GdkAtom selection; - GdkAtom target; - GdkAtom type; - gint format; - guchar *data; - gint length; -}; -</verb></tscreen> - -<tt>selection</tt> y <tt>target</tt> son los valores que dió en su -llamada a <tt>gtk_selection_convert()</tt>. <tt>type</tt> es un átomo -que identifica el tipo de datos devueltos por el propietario de la -selección. Algunos valores posibles son «STRING», un cadena de -caracteres latin-1, «ATOM», una serie de átomos, «INTEGER», un -entero, etc. Muchos objetivos sólo pueden devolver un -tipo. <tt/format/ da la longitud de las unidades (por ejemplo -caracteres) en bits. Normalmente, no tiene porque preocuparse de todo -esto cuando recibe datos. <tt/data/ es un puntero a los datos -devueltos, y <tt/length/ da la longitud de los datos devueltos, en -bytes. Si <tt/length/ es negativo, es que a ocurrido un error y no se -puede obtener la selección. Esto podría ocurrir si no hay ninguna -aplicación que sea la propietaria de la selección, o si pide un -objetivo que la aplicación no admite. Actualmente se garantiza que el -búfer tendrá un byte más que <tt/length/; el byte extra siempre será -cero, por lo que no es necesario hacer una copia de las cadenas sólo -para añadirles un carácter nulo al final. - -En el siguiente ejemplo, recuperamos el objetivo especial «TARGETS», -que es una lista de todos los objetivos en los que se puede convertir -la selección. - -<tscreen><verb> -/* principio del ejemplo selection gettargets.c */ - -#include <gtk/gtk.h> - -void selection_received (GtkWidget *widget, - GtkSelectionData *selection_data, - gpointer data); - -/* Manejador de señal invocado cuando el usuario pulsa en el botón -"Get Targets" */ -void -get_targets (GtkWidget *widget, gpointer data) -{ - static GdkAtom targets_atom = GDK_NONE; - - /* Obtener el atom correpondiente a la cadena "TARGETS" */ - if (targets_atom == GDK_NONE) - targets_atom = gdk_atom_intern ("TARGETS", FALSE); - - /* Y pide el objetivo "TARGETS" de la selección primaria */ - gtk_selection_convert (widget, GDK_SELECTION_PRIMARY, targets_atom, - GDK_CURRENT_TIME); -} - -/* Manipulador de señal llamado cuando el propietario de la señal - * devuelve los datos */ -void -selection_received (GtkWidget *widget, GtkSelectionData *selection_data, - gpointer data) -{ - GdkAtom *atoms; - GList *item_list; - int i; - - /* **** IMPORTANTE **** Comprobar si se da la recuperación de los - * datos */ - if (selection_data->length < 0) - { - g_print ("Selection retrieval failed\n"); - return; - } - /* Asegurarse de que obtenemos los datos de la forma esperada */ - if (selection_data->type != GDK_SELECTION_TYPE_ATOM) - { - g_print ("Selection \"TARGETS\" was not returned as atoms!\n"); - return; - } - - /* Imprimir los atoms que hemos recibido */ - 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 *ventana; - GtkWidget *boton; - - gtk_init (&argc, &argv); - - /* Crear la ventana superior */ - - ventana = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_title (GTK_WINDOW (ventana), "Event Box"); - gtk_container_border_width (GTK_CONTAINER (ventana), 10); - - gtk_signal_connect (GTK_OBJECT (ventana), "destroy", - GTK_SIGNAL_FUNC (gtk_exit), NULL); - - /* Crear un botón que el usuario puede pulsar para obtener los - * objetivos */ - - boton = gtk_button_new_with_label ("Get Targets"); - gtk_container_add (GTK_CONTAINER (ventana), boton); - - gtk_signal_connect (GTK_OBJECT(boton), "clicked", - GTK_SIGNAL_FUNC (get_targets), NULL); - gtk_signal_connect (GTK_OBJECT(boton), "selection_received", - GTK_SIGNAL_FUNC (selection_received), NULL); - - gtk_widget_show (boton); - gtk_widget_show (ventana); - - gtk_main (); - - return 0; -} -/* fin del ejemplo */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1> Proporcionando la selección -<p> -Proporcionar la selección es un poco más complicado. Debe registrar -los manejadores a los que se llamarán cuando se le pida la -selección. Por cada par selección/objetivo que quiera manejar, deberá -hacer una llamada a: - -<tscreen><verb> -void gtk_selection_add_handler( GtkWidget *widget, - GdkAtom selection, - GdkAtom target, - GtkSelectionFunction function, - GtkRemoveFunction remove_func, - gpointer data ); -</verb></tscreen> - -<tt/widget/, <tt/selection/, y <tt/target/ identifican las peticiones -que este manejador puede manipular. Si <tt/remove_func/ no es NULL, se -le llamará cuando se elimine el manejador de la señal. Esto es útil, -por ejemplo, para los lenguajes interpretados que necesitan mantener -una memoria de las referencias a <tt/data/. - -La función de llamada tiene el prototipo: - -<tscreen><verb> -typedef void (*GtkSelectionFunction)( GtkWidget *widget, - GtkSelectionData *selection_data, - gpointer data ); - -</verb></tscreen> - -El <tt/GtkSelectionData/ es el mismo que hay más arriba, pero esta -vez, seremos nosotros los responsables de rellenar los campos -<tt/type/, <tt/format/, <tt/data/, y <tt/length/. (El campo -<tt/format/ es importante - el servidor X lo utiliza para saber si -tienen que intercambiarse los bytes que forman los datos o -no. Normalmente será 8 - es decir un carácter - o 32 - es decir un -entero.) Esto se hace llamando a la función: - -<tscreen><verb> -void gtk_selection_data_set( GtkSelectionData *selection_data, - GdkAtom type, - gint format, - guchar *data, - gint length ); -</verb></tscreen> - -Esta función tiene la responsabilidad de hacer una copia de los datos -para que no tenga que preocuparse de ir guardándolos. (No debería -rellenar los campos de la estructura <tt/GtkSelectionData/ a mano.) - -Cuando haga falta, puede pedir el propietario de la selección llamando -a: - -<tscreen><verb> -gint gtk_selection_owner_set( GtkWidget *widget, - GdkAtom selection, - guint32 time ); -</verb></tscreen> - -Si otra aplicación pide el propietario de la selección, recibira un -«selection_clear_event». - -Como ejemplo de proporciar la selección, el programa siguiente le añade -la posibilidad de selección a un botón de comprobación. Cuando se presione -el botón de comprobación, el programa pedirá la selección primaria. El -único objetivo que admite es un objetivo «STRING» (aparte de ciertos -objetivos como "TARGETS", proporcionados por GTK). Cuando se pida este -objetivo, se devolverá una representación del tiempo. - -<tscreen><verb> -/* principio del ejemplo selection setselection.c */ - -#include <gtk/gtk.h> -#include <time.h> - -/* Función de llamada para cuando el usuario cambia la selección */ -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); - /* Si la demanda de la selección ha fallado, ponemos el botón en - * estado apagado */ - if (!*have_selection) - gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON(widget), FALSE); - } - else - { - if (*have_selection) - { - /* Antes de eliminar la seleción poniendo el propietario a - * NULL, comprobamos si somos el propietario actual */ - if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window) - gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY, - GDK_CURRENT_TIME); - *have_selection = FALSE; - } - } -} - -/* Llamado cuando otra aplicación pide la selección */ -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; -} - -/* Proporciona el tiempo actual como selección. */ -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)); - /* Cuando devolvemos una cadena, no debe terminar en NULL. La - * función lo hará por nosotros */ - - gtk_selection_data_set (selection_data, GDK_SELECTION_TYPE_STRING, - 8, timestr, strlen(timestr)); -} - -int -main (int argc, char *argv[]) -{ - GtkWidget *ventana; - - GtkWidget *selection_button; - - static int have_selection = FALSE; - - gtk_init (&argc, &argv); - - /* Crear la ventana superior */ - - ventana = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_title (GTK_WINDOW (ventana), "Event Box"); - gtk_container_border_width (GTK_CONTAINER (ventana), 10); - - gtk_signal_connect (GTK_OBJECT (ventana), "destroy", - GTK_SIGNAL_FUNC (gtk_exit), NULL); - - /* Crear un botón de selección para que actue como la selección */ - - selection_button = gtk_toggle_button_new_with_label ("Claim Selection"); - gtk_container_add (GTK_CONTAINER (ventana), 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); - - gtk_widget_show (selection_button); - gtk_widget_show (ventana); - - gtk_main (); - - return 0; -} -/* fin del ejemplo */ -</verb></tscreen> - - -<!-- ***************************************************************** --> -<sect>Glib<label id="sec_glib"> -<!-- ***************************************************************** --> -<p> -Glib proporciona muchas definiciones y funciones útiles disponibles -para su utilización cuando se crean aplicaciones GDK y GTK. Haré una -lista con todas ellas incluyendo una pequeña explicación. Muchas no -son más que duplicados de funciones estándar de libc por lo que no -entraré en detalle en la explicación de las mismas. Esta sección está -pensada principalmente para que se utilice como referencia, para que -sepa que es lo que puede utilizar. - -<!-- ----------------------------------------------------------------- --> -<sect1>Definiciones -<p> -Las definiciones para los límites de muchos de los tipos estándar son: - -<tscreen><verb> -G_MINFLOAT -G_MAXFLOAT -G_MINDOUBLE -G_MAXDOUBLE -G_MINSHORT -G_MAXSHORT -G_MININT -G_MAXINT -G_MINLONG -G_MAXLONG -</verb></tscreen> - -Y también, los siguientes <tt/typedefs/. Cuando no se especifica el -tipo que debería aparecer a la izquierda significa que el mismo se -establecerá dinámicamente en función de la arquitectura. ¡Recuerde -evitar los calculos relativos al tamaño de un puntero si quiere que -su aplicación sea portable! P.e., un puntero en un Alpha tiene 8 -bytes, pero 4 en Intel. - -<tscreen><verb> -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 -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Listas doblemente enlazadas -<p> -Las funciones siguientes se utilizan para crear, manipular, y destruir -listas doblemente enlazadas. Supondré que sabe lo que son las listas -enlazadas, ya que explicarlas va más allá del objetivo de este -documento. Por supuesto, no es necesario que conozca como manejar -todo esto para utilizar GTK, pero siempre es bonito aprender cosas. - -<tscreen><verb> -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 posicion ); - -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 ); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Listas simplemente enlazadas -<p> -Muchas de las funciones para las listas enlazadas son idénticas a las -de más arriba. Aquí hay una lista completa: - -<tscreen><verb> -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 posicion ); - -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 ); - -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Control de la memoria -<p> -<tscreen><verb> -gpointer g_malloc( gulong size ); -</verb></tscreen> - -Reemplaza a <tt/malloc()/. No necesita comprobar el valor devuelto, ya -que ya lo hace por usted esta función. - -<tscreen><verb> -gpointer g_malloc0( gulong size ); -</verb></tscreen> - -Lo mismo que antes, pero rellena con ceros la memoria antes de -devolver un puntero a ella. - -<tscreen><verb> -gpointer g_realloc( gpointer mem, - gulong size ); -</verb></tscreen> - -Vuelve a reservar <tt/size/ bites de memoria empezando en -<tt/mem/. Obviamente, la memoria debe haber sido previamente reservada. - -<tscreen><verb> -void g_free( gpointer mem ); -</verb></tscreen> - -Libera la memoria. Fácil. - -<tscreen><verb> -void g_mem_profile( void ); -</verb></tscreen> - -Crea un fichero donde vuelca la memoria que se está utilizando, pero -tiene que añadir <tt/#define MEM_PROFILE/ en lo alto de -<tt>glib/gmem.c</tt> y tendrá que hacer un make y un make install. - -<tscreen><verb> -void g_mem_check( gpointer mem ); -</verb></tscreen> - -Comprueba que una dirección de memoria es válida. Tiene que añadir -<tt/#define MEM_CHECK/ en lo alto de <tt/gmem.c/ y tiene que hacer un -make y un make install. - -<!-- ----------------------------------------------------------------- --> -<sect1>Timers -<p> -Temporizadores... - -<tscreen><verb> -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 ); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Manejo de cadenas de texto -<p> -Un puñado de funciones para manejar cadenas de texto. Parecen muy -interesantes, y probablemente sean mejores en muchos aspectos que las -funciones estándar de C, pero necesitan documentación. - -<tscreen><verb> -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, - ... ); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Funciones de error y funciones varias -<p> -<tscreen><verb> -gchar *g_strdup( const gchar *str ); -</verb></tscreen> - -Reemplaza a la función <tt/strdup/. Copia el contenido de la cadena -original en un nuevo lugar en memoria, y devuelve un puntero al nuevo -lugar. - -<tscreen><verb> -gchar *g_strerror( gint errnum ); -</verb></tscreen> - -Recomiendo utilizar esta función para todos los mensages de error. Es -mucho más bonita, y más portable que <tt/perror()/ y demás funciones -clásicas. La salida es normalmente de la forma: - -<tscreen><verb> -nombre del programa:función que falló:fichero o descripción adicional:strerror -</verb></tscreen> - -Aquí hay un ejemplo de una llamada utilizada en nuestro programa -<tt/hello_world/: - -<tscreen><verb> -g_print("hello_world:open:%s:%s\n", filename, g_strerror(errno)); -</verb></tscreen> - -<tscreen><verb> -void g_error( gchar *format, ... ); -</verb></tscreen> - -Imprime un mensaje de error. El formato es como el de <tt/printf/, -pero le añade <tt/** ERROR **: / a su mensaje, y sale del -programa. Sólo para errores fatales. - -<tscreen><verb> -void g_warning( gchar *format, ... ); -</verb></tscreen> - -El mismo que el anterior, pero añade "** WARNING **: ", y no sale del -programa. - -<tscreen><verb> -void g_message( gchar *format, ... ); -</verb></tscreen> - -Imprime <tt/message: / antes de la cadena que le pase. - -<tscreen><verb> -void g_print( gchar *format, ... ); -</verb></tscreen> - -Reemplazo de <tt/printf()/. - -Y nuestra última función: - -<tscreen><verb> -gchar *g_strsignal( gint signum ); -</verb></tscreen> - -Imprime el nombre de la señal del sistema Unix que corresponde con el -número <tt/signum/. Útil para las funciones genéricas de manejo de señal. - -Todo lo anterior está más o menos robado de <tt/glib.h/. Si alguien -quiere documentar una función, ¡sólo tiene que enviarme un correo-e! - -<!-- ***************************************************************** --> -<sect>Ficheros rc de GTK -<!-- ***************************************************************** --> -<p> -GTK tiene su propia forma de conseguir los valores por defecto de una -aplicación, y es utilizando los ficheros <tt/rc/. Pueden ser -utilizados para poner los colores de cualquier <em/widget/, y también -pueden utilizarse para poner imágenes como fondos de algunos <em/widgets/. - -<!-- ----------------------------------------------------------------- --> -<sect1>Funciones para los ficheros <tt/rc/ -<p> -Cuando empiece su aplicación, debería incluir una llamada a: - -<tscreen><verb> -void gtk_rc_parse( char *filename ); -</verb></tscreen> - -Poniendo el nombre del fichero de su rc. Esto hará que GTK analice -este fichero, y utilice el estilo para los <em/widgets/ que se definan -ahí. - -Si desea tener un conjunto especial de <em/widgets/ con un estilo -diferente de los otros, o realizar cualquier otra división lógica de -los <em/widgets/, haga una llamada a: - -<tscreen><verb> -void gtk_widget_set_name( GtkWidget *widget, - gchar *name ); -</verb></tscreen> - -Pasándole su nuevo <em/widget/ como primer argumento, y el nombre que -desea darle como el segundo. Mediante este nombre podrá cambiar los -atributos de ese <em/widget/. - -Si hacemos algo así: - -<tscreen><verb> -boton = gtk_button_new_with_label ("Botón especial"); -gtk_widget_set_name (boton, "botón especial"); -</verb></tscreen> - -El botón tendrá el nombre «botón especial» y podría hacersele -referencia en el fichero <tt/rc/ como «botón especial.GtkButton». -[<--- ¡Verificadme! ] - -El fichero de ejemplo <tt/rc/ que mostramos a continuación, establece las -propiedades de la ventana principal, y deja que todos los hijos de la -ventana principal hereden el estilo descrito por «main button». El -código utilizado en la aplicación es: - -<tscreen><verb> -ventana = gtk_window_new (GTK_WINDOW_TOPLEVEL); -gtk_widget_set_name (ventana, "main window"); -</verb></tscreen> - -Y el estilo se define en el fichero <tt/rc/ utilizando: - -<tscreen><verb> -widget "main window.*GtkButton*" style "main_button" -</verb></tscreen> - -Qué hace que todos los <em/widgets/ GtkButton de la «main window» -(ventana principal) tengan el estilo "main_buttons" tal y como se -define en el fichero <tt/rc/. - -Como puede ver, es un sistema muy poderoso y flexible. Utilice su -imaginación para aprovecharse al máximo de este sistema. - -<!-- ----------------------------------------------------------------- --> -<sect1>Formato de los ficheros <tt/rc/ de GTK -<p> -El formato de los ficheros GTK se muestra en el ejemplo de más -abajo. Éste es el fichero <tt/testgtkrc/ de la distribución GTK, pero he -añadido unos cuantos comentarios y alguna cosilla. Puede que quiera -incluir esta explicación en su aplicación para permitir al usuario -personalizar su aplicación. - -Hay varias directivas para cambiar los atributos de un <em/widget/. - -<itemize> -<item>fg - Establece el color de primer plano de un <em/widget/. -<item>bg - Establece el color de fondo de un <em/widget/. -<item>bg_pixmap - Establece la imagen que servirá de fondo al -<em/widget/ (como mosaico). -<item>font - Establece el tipo de letra que se utilizará con el -<em/widget/. -</itemize> - -Además de esto, hay varios estados en el que puede estar un -<em/widget/, y puede especificar diferentes colores, imágenes y tipos -de letra para cada estado. Estos estados son: - -<itemize> -<item>NORMAL - El estado normal de un <em/widget/, sin el ratón sobre -él, y no siendo presionado, etc... -<item>PRELIGHT - Cuando el ratón esté sobre este <em/widget/ se -utilizarán los colores definidos para este estado. -<item>ACTIVE - Cuando se presiona o se pulsa sobre el <em/widget/, -estará activo, y los atributos asignados por está etiqueta serán -utilizados. -<item>INSENSITIVE - Cuando un <em/widget/ es insensible, y no se puede -activar, tomará estos atributos. -<item>SELECTED - Cuando se seleccione un objeto, tomará estos atributos. -</itemize> - -Cuando se utilizan las directivas «fg» y «bg» para poner los colores de -los <em/widgets/, se utilizará el formato siguiente: - -<tscreen><verb> -fg[<STATE>] = { Red, Green, Blue } -</verb></tscreen> - -Donde <tt/STATE/ es uno de los estados anteriores (PRELIGHT, ACTIVE, -etc...), y el <tt/Red/, <tt/Green/ y <tt/Blue/ (Rojo, Verde y Azul) -son valores en el rango 0 - 1.0, { 1.0, 1.0, 1.0 } es blanco. Deben -estar en formato flotante, o serán un 0, por lo que "1" no funcionará, -debe ser "1.0". Un "0" está bien ya que es lo mismo si no se -reconoce. Los valores no reconocidos se pondrán a 0. - -<tt/bg_pixmap/ es muy similar al de arriba, salvo que los colores se -reemplazan por un nombre de fichero. - -<tt/pixmap_path/ es una lista de los caminos (<em/paths/) separados por -«:». Estos caminos se utilizarán para buscar cualquier imagen que -indique. - -La directiva sobre el tipo de letra es simplemente: -<tscreen><verb> -font = "<nombre del tipo de letra>" -</verb></tscreen> - -Donde lo único difícil es saber la cadena del tipo de letra a -elegir. Utilizar <tt/xfontsel/ o un programa similar debería ayudar. - -El <tt/widget_class/ establece el estilo de una clase de -<em/widgets/. Estas clases se muestran en el resumen de <em/widgets/ -dentro de la jerarquía de clases. - -La directiva <tt/widget/ hace que un conjunto específico de -<em/widgets/ tenga un estido determinado, sobreescribiendo cualquier -estilo anterior que tuviese esa clase de <em/widgets/. Estos -<em/widgets/ se registran dentro de la aplicación utilizando una -llamada a <tt/gtk_widget_set_name()/. Esto le permitirá especificar -los atributos de un <em/widget/ uno a uno, en vez de establecer los -atributos de toda una clase <em/widget/. Deberá documentar cualquiera -de estos <em/widgets/ especiales para que los usuarios puedan -personalizarlos. - -Cuando la palabra clave <tt/parent/ se utiliza como un atributo, el -<em/widget/ tomará los atributos de su padre en la aplicación. - -Puede asignar los atributos de un estilo previamente definido a uno -nuevo. - -<tscreen><verb> -style "main_button" = "button" -{ - font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*" - bg[PRELIGHT] = { 0.75, 0, 0 } -} -</verb></tscreen> - -Este ejemplo toma el estilo «button», y crea un nuevo estilo -«main_button» cambiando simplemente el tipo de letra y cambiando el -color de fondo cuando el <em/widget/ esté en estado <tt/PRELIGHT/. - -Por supuesto, muchos de estos atributos no se aplican a todos los -<em/widgets/. Realmente es una cuestión de sentido común. Se utilizará -cualquier atributo que se pueda aplicar. - -<!-- ----------------------------------------------------------------- --> -<sect1>Fichero <tt/rc/ de ejemplo -<p> - -<!-- Esto hay que traducirlo --> -<tscreen><verb> -# 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> - - -# Here is a list of all the possible states. Note that some do not apply to -# certain widgets. -# -# 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. -# - -# This sets a style called "button". The name is not really important, as -# it is assigned to the actual widgets at the bottom of the file. - -style "window" -{ - #This sets the padding around the window to the pixmap specified. - #bg_pixmap[<STATE>] = "<pixmap filename>" - bg_pixmap[NORMAL] = "warning.xpm" -} - -style "scale" -{ - #Sets the foreground color (font color) to red when in the "NORMAL" - #state. - - fg[NORMAL] = { 1.0, 0, 0 } - - #Sets the background pixmap of this widget to that of its parent. - bg_pixmap[NORMAL] = "<parent>" -} - -style "button" -{ - # This shows all the possible states for a button. The only one that - # doesn't apply is the 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 } -} - -# In this example, we inherit the attributes of the "button" style and then -# override the font and background color when prelit to create a new -# "main_button" style. - -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 } - - # This sets the background pixmap of the toggle_button to that of its - # parent widget (as defined in the application). - 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" - -# These set the widget types to use the styles defined above. -# The widget types are listed in the class hierarchy, but could probably be -# just listed in this document for the users reference. - -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" - -# This sets all the buttons that are children of the "main window" to -# the main_button style. These must be documented to be taken advantage of. -widget "main window.*GtkButton*" style "main_button" -</verb></tscreen> - -<!-- ***************************************************************** --> -<sect>Escribiendo sus propios <em/widgets/ -<!-- ***************************************************************** --> - -<!-- ----------------------------------------------------------------- --> -<sect1> Visión general -<p> -Aunque la distribución de GTK viene con muchos tipos de <em/widgets/ -que debería cubrir todas la mayoría de las necesidades básicas, puede -que haya llegado el momento en que necesite crear su propio -<em/widget/. Debido a que GTK utiliza mucho la herencia de -<em/widgets/, y si ya hay un <em/widget/ que se acerque lo suficiente -a lo que quiere, tal vez pueda hacer un nuevo <em/widget/ con tan solo -unas cuantas líneas de código. Pero antes de empezar a trabajar en un -nuevo <em/widget/, asegúrese primero de que no hay nadie que ya haya -hecho otro parecido. Así evitará la duplicación de esfuerzo y -mantendrá el número de <em/widgets/ GTK en su valor mínimo, lo que -ayudará a que el código y la interfaz de las diferentes aplicaciones -sea consistente. Por otra parte, cuando haya acabado su <em/widget/, -anúncielo al mundo entreo para que todo el mundo se pueda -beneficiar. Probablemente el mejor lugar para hacerlo sea la -<tt>gtk-list</tt>. - -Las fuentes completas de los <em/widgets/ de ejemplo están disponibles -en el mismo lugar en el que consiguió este tutorial, o en: - -<htmlurl url="http://www.gtk.org/~otaylor/gtk/tutorial/" -name="http://www.gtk.org/~otaylor/gtk/tutorial/"> - - -<!-- ----------------------------------------------------------------- --> -<sect1> La anatomía de un <em/widget/ -<p> -Para crear un nuevo <em/widget/, es importante conocer como funcionan -los objetos de GTK. Esta sección es sólo un breve resumen. Ver la -documentación a la que se hace referencia para obtener más detalles. - -Los widgets GTK están implementados siguiendo una orientación a -objetos. Sin embargo, están implementados en C estándar. De esta forma -se mejora enormemente la portabilidad y la estabilidad con respecto a -la actual generación de compiladores C++; sin embargo, con todo esto -no queremos decir que el creador de <em/widgets/ tenga que prestar -atención a ninguno de los detalles de implementación. La información -que es común a todos los <em/widgets/ de una clase de <em/widgets/ -(p.e., a todos los <em/widgets/ botón) se almacena en la -<em>estructura de clase</em>. Sólo hay una copia de ésta en la que se -almacena información sobre las señales de la clase (que actuan como -funciones virtuales en C). Para permitir la herencia, el primer campo -en la estructura de la clase debe ser una copia de la estructura de la -clase del padre. La declaración de la estructura de la clase de -GtkButton debe ser algo así: - -<tscreen><verb> -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); -}; -</verb></tscreen> - -Cuando un botón se trata como un contenedor (por ejemplo, cuando se le -cambia el tamaño), su estructura de clase puede convertirse a -GtkContainerClass, y los campos relevantes se utilizarán para manejar -las señales. - -También hay una estructura que se crea para cada <em/widget/. Esta -estructura tiene campos para almacenar la información que es diferente -para cada copia del <em/widget/. Nosotros llamaremos a esta estructura -la <em>estructura objeto</em>. Para la clase botón, es así: - -<tscreen><verb> -struct _GtkButton -{ - GtkContainer container; - - GtkWidget *child; - - guint in_button : 1; - guint button_down : 1; -}; -</verb></tscreen> - -Observe que, como en la estructura de clase, el primer campo es la -estructura objeto de la clase padre, por lo que esta estructura puede -convertirse en la estructura de la clase del objeto padre cuando haga -falta. - -<!-- ----------------------------------------------------------------- --> -<sect1> Creando un <em/widget/ compuesto - -<!-- ----------------------------------------------------------------- --> -<sect2> Introducción -<p> -Un tipo de widget que puede interesarnos es uno que sea un mero -agregado de otros <em/widgets/ GTK. Este tipo de <em/widget/ no hace -nada que no pueda hacerse sin la necesidad de crear un nuevo -<em/widget/, pero proporciona una forma conveniente de empaquetar los -elementos del interfaz de usuario para su reutilización. Los -<em/widgets/ <tt/FileSelection/ y <tt/ColorSelection/ incluidos en la -distribución estándar son ejemplos de este tipo de <em/widgets/. - -El <em/widget/ ejemplo que hemos creado en esta sección es el -<em/widget/ Tictactoe, una matriz de 3x3 de botones de selección que -lanza una señal cuando están deseleccionados tres botones en una misma -fila, columna, o diagonal. - -<!-- ----------------------------------------------------------------- --> -<sect2> Escogiendo una clase padre -<p> -Normalmente la clase padre para un <em/widget/ compuesto es la clase -contenedor que tenga todos los elementos del <em/widget/ -compuesto. Por ejemplo, la clase padre del <em/widget/ -<tt/FileSelection/ es la clase <tt/Dialog/. Ya que nuestros botones se -ordenarán en una tabla, parece natural hacer que nuestra clase padre -sea la clase <tt/GtkTable/. Desafortunadamente, esto no -funcionaría. La creación de un <em/widget/ se divide en dos funciones -- una función <tt/NOMBREWIDGET_new()/ que utilizará el usuario, y una -función <tt/NOMBREWIDGET_init()/ que hará el trabajo básico de -inicializar el <em/widget/ que es independiente de los argumentos que -se le pasen a la función <tt/_new()/. Los <em/widgets/ derivados sólo -llaman a la función <tt/_init/ de su <em/widget/ padre. Pero esta -división del trabajo no funciona bien con las tablas, que necesitan -saber en el momento de su creación el número de filas y de columnas -que deben tener. A menos que queramos duplicar la mayor parte de lo -hecho en <tt/gtk_table_new()/ en nuestro <em/widget/ Tictactoe, -haremos mejor si evitamos derivar de GtkTable. Por esta razón, -derivaremos de <tt/GtkVBox/, y meteremos nuestra tabla dentro de la -caja vertical. - -<!-- ----------------------------------------------------------------- --> -<sect2> El fichero de cabecera -<p> -Cada clase <em/widget/ tiene un fichero de cabecera que declara el -objeto y las estructuras de clase para ese <em/widget/, así como las -funciones públicas. Un par de características que merecen dejarse -aparte. Para evitar la duplicación de definiciones, meteremos el -fichero de cabecera al completo entre: - -<tscreen><verb> -#ifndef __TICTACTOE_H__ -#define __TICTACTOE_H__ -. -. -. -#endif /* __TICTACTOE_H__ */ -</verb></tscreen> - -Y para que los programas en C++ incluyan sin problemas el fichero de -cabecera, pondremos: - -<tscreen><verb> -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ -. -. -. -#ifdef __cplusplus -} -#endif /* __cplusplus */ -</verb></tscreen> - -Con las funciones y las estructuras, declararemos tres macros estándar -en nuestro fichero de cabecera, <tt/TICTACTOE(obj)/, -<tt/TICTACTOE_CLASS(class)/, y <tt/IS_TICTACTOE(obj)/, que, -convierten, respectivamente, un puntero en un puntero al objeto o a la -estructura de la clase, y comprueba si un objeto es un <em/widget/ -Tictactoe. - -Aquí está el fichero de cabecera al completo: - -<tscreen><verb> -/* 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 *botones[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__ */ - -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect2> La función <tt/_get_type()/. -<p> -Ahora continuaremos con la implementación de nuestro <em/widget/. Una -función del núcleo de todo <em/widget/ es -<tt/NOMBREWIDGET_get_type()/. Cuando se llame a esta función por -vez primera, le informará a GTK sobre la clase del <em/widget/, y -devolverá un ID que identificará unívocamente la clase <em/widget/. En -las llamadas siguientes, lo único que hará será devolver el ID. - -<tscreen><verb> -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; -} -</verb></tscreen> - -La estructura GtkTypeInfo tiene la definición siguiente: - -<tscreen><verb> -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; -}; -</verb></tscreen> - -Los utilidad de cada campo de esta estructura se explica por su propio -nombre. Ignoraremos por ahora los campos <tt/arg_set_func/ -y <tt/arg_get_func/: son importantes, pero todavía es raro -utilizarlos, su papel es permitir que las opciones de los <em/wdigets/ -puedan establecerse correctamente mediante lenguajes -interpretados. Una vez que GTK tiene una copia de esta estructura -correctamente rellenada, sabrá como crear objetos de un tipo -particular de <em/widget/. - -<!-- ----------------------------------------------------------------- --> -<sect2> La función <tt/_class_init()/ -<p> -La función <tt/NOMBREWIDGET_class_init()/ inicializa los campos de la -estructura clase del <em/widget/, y establece las señales de la -clase. Para nuestro <em/widget/ Tictactoe será una cosa así: - -<tscreen><verb> - -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; -} -</verb></tscreen> - -Nuestro <em/widget/ sólo tiene una señal, la señal <tt/tictactoe/ que -se invoca cuando una fila, columna, o diagonal se rellena -completamente. No todos los <em/widgets/ compuestos necesitan señales, -por lo que si está leyendo esto por primera vez, puede que sea mejor -que pase a la sección siguiente, ya que las cosas van a complicarse un -poco. - -La función: - -<tscreen><verb> -gint gtk_signal_new( const gchar *name, - GtkSignalRunType run_type, - GtkType object_type, - gint function_offset, - GtkSignalMarshaller marshaller, - GtkType return_val, - guint nparams, - ...); -</verb></tscreen> - -crea una nueva señal. Los parámetros son: - -<itemize> -<item> <tt/name/: El nombre de la señal. -<item> <tt/run_type/: Si el manejador por defecto se ejecuta antes o -despues del manejador de usuario. Normalmente debe ser -<tt/GTK_RUN_FIRST/, o <tt/GTK_RUN_LAST/, aunque hay otras -posibilidades. -<item> <tt/object_type/: El ID del objeto al que se le aplica esta -señal. (También se aplicará a los descendientes de los objetos) -<item> <tt/function_offset/: El desplazamiento en la estructura de la -clase de un puntero al manejador por defecto. -<item> <tt/marshaller/: Una función que se utiliza para invocar al -manejador de señal. Para los manejadores de señal que no tengan más -argumentos que el objeto que emitió la señal podemos utilizar la -función marshaller por defecto <tt/gtk_signal_default_marshaller/. -<item> <tt/return_val/: El tipo del valor devuelto. -<item> <tt/nparams/: El número de parámetros del manejador de señal -(distintos de los dos por defecto que hemos mencionado arriba). -<item> <tt/.../: Los tipos de los parámetros. -</itemize> - -Cuando se especifican los tipos, se utilizará la enumeración -<tt/GtkType/: - -<tscreen><verb> -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; -</verb></tscreen> - -<tt/gtk_signal_new()/ devuelve un identificador entero único para la -señal, que almacenamos en el vector <tt/tictactoe_signals/, que -indexaremos utilizando una enumeración. (Convencionalmente, los -elementos de la enumeración son el nombre de la señal, en mayúsculas, -pero aquí tendríamos un conflicto con la macro <tt/TICTACTOE()/, por -lo que lo llamaremos <tt/TICTACTOE_SIGNAL/. - -Después de crear nuestras señales, necesitamos llamar a GTK para -asociarlas con la clase Tictactoe. Hacemos esto llamando a -<tt/gtk_object_class_add_signals()/. Entonces haremos que el puntero -que apunta al manejador por defecto para la señal `tictactoe' sea NULL, -indicando que no hay ninguna acción por defecto. - -<!-- ----------------------------------------------------------------- --> -<sect2> La función <tt/_init()/. -<p> -Cada clase <em/widget/ también necesita una función para inicializar -la estructura del objeto. Normalmente, esta función tiene el limitado -rol de poner los distintos campos de la estructura a su valor por -defecto. Sin embargo para los <em/widgets/ de composición, esta -función también crea los distintos <em/widgets/ componentes. - -<tscreen><verb> -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]); - } -} -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect2> Y el resto... -<p> -Hay una función más que cada <em/widget/ (excepto los <em/widget/ muy -básicos como GtkBin que no pueden crear objetos) tiene que -tener - la función que el usuario llama para crear un objeto de ese -tipo. Normalmente se llama <tt/NOMBREWIDGET_new()/. En algunos -<em/widgets/, que no es el caso del <em/widget/ Tictactoe, esta -función toma argumentos, y hace alguna inicialización en función de -estos. Las otras dos funciones son específicas al <em/widget/ -Tictactoe. - -<tt/tictactoe_clear()/ es una función pública que reinicia todos los -botones en el <em/widget/ a la posición alta. Observe la utilización -de <tt/gtk_signal_handler_block_by_data()/ para hacer que no se -ejecute nuestro manejador de señal innecesariamente por cambios en los -botones. - -<tt/tictactoe_toggle()/ es el manejador de señal que se invoca cuando -el usuario pulsa un botón. Hace una comprobación para ver si hay -alguna combinación ganadora, y si la hay, emite la señal -«tictactoe». - -<tscreen><verb> -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; - } - } -} -</verb></tscreen> - -Y finalmente, un programa ejemplo que utiliza nuestro <em/widget/ -Tictactoe: - -<tscreen><verb> -#include <gtk/gtk.h> -#include "tictactoe.h" - -/* Invocado cuando se completa una fila, columna o diagonal */ -void -win (GtkWidget *widget, gpointer data) -{ - g_print ("Yay!\n"); - tictactoe_clear (TICTACTOE (widget)); -} - -int -main (int argc, char *argv[]) -{ - GtkWidget *ventana; - GtkWidget *ttt; - - gtk_init (&argc, &argv); - - ventana = gtk_window_new (GTK_WINDOW_TOPLEVEL); - - gtk_window_set_title (GTK_WINDOW (ventana), "Aspect Frame"); - - gtk_signal_connect (GTK_OBJECT (ventana), "destroy", - GTK_SIGNAL_FUNC (gtk_exit), NULL); - - gtk_container_border_width (GTK_CONTAINER (ventana), 10); - - /* Create a new Tictactoe widget */ - ttt = tictactoe_new (); - gtk_container_add (GTK_CONTAINER (ventana), ttt); - gtk_widget_show (ttt); - - /* And attach to its "tictactoe" signal */ - gtk_signal_connect (GTK_OBJECT (ttt), "tictactoe", - GTK_SIGNAL_FUNC (win), NULL); - - gtk_widget_show (ventana); - - gtk_main (); - - return 0; -} - -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1> Creando un <em/widget/ desde cero. - -<!-- ----------------------------------------------------------------- --> -<sect2> Introducción -<p> -En esta sección, averiguaremos como se dibujan los <em/widgets/ a sí -mismos en pantalla y como interactuan con los eventos. Como ejemplo, -crearemos un marcador analógico con un puntero que el usuario -podrá arrastrar para hacer que el marcador tenga un valor dado. - -<!-- ----------------------------------------------------------------- --> -<sect2> Mostrando un <em/widget/ en la pantalla -<p> -Hay varios pasos que están involucrados en el dibujado en pantalla. -Después de que el <em/widget/ se cree con una llamada a -<tt/NOMBREWIDGET_new()/, se necesitarán muchas más funciones: - -<itemize> -<item> <tt/NOMBREWIDGET_realize()/ es la responsable de crear una -ventana X para el <em/widget/, si tiene alguna. -<item> <tt/NOMBREWIDGET_map()/ se invoca después de las llamadas del -usuario -<tt/gtk_widget_show()/. Es la responsable de asegurarse de que el -<em/widget/ está dibujado (<em/mapeado/) en la pantalla. Para una -clase contenedor, también deberá ocuparse de llamar a las funciones -<tt/map()/ de cada <em/widget/ hijo. -<item> <tt/NOMBREWIDGET_draw()/ se invoca cuando se llama a -<tt/gtk_widget_draw()/ desde el <em/widget/ de uno de sus -antepasados. Hace las llamadas necesarias a las funciones de dibujo -para dibujar el <em/widget/ en la pantalla. Para los <em/widgets/ -contenedores, esta función debe llamar a las <tt/gtk_widget_draw/ de -sus <em/widgets/ hijos. -<item> <tt/NOMBREWIDGET_expose()/ es un manejador de los eventos -<tt/expose/ del <em/widget/. Hace las llamadas necesarias a las -funciones de dibujo para dibujar la parte expuesta en la -pantalla. Para los <em/widgets/ contenedores, esta función debe -generar los eventos <tt/expose/ de sus <em/widgets/ hijos que no -tengan su propia ventana. (Si tuviesen su propia ventana, X generaría -los eventos <tt/expose/ necesarios) -</itemize> - -Las últimas dos funciones son bastante similares - ambas son -responsables de dibujar el <em/widget/ en pantalla. De hecho en muchos -<em/widgets/ realmente no importa la diferencia que hay entre ambas -funciones. La función <em/draw()/ que hay por defecto en -la clase <em/widget/ simplemente genera un evento <tt/expose/ -artificial de la zona a redibujar. Sin embargo, algunos tipos de -<em/widgets/ puede ahorrarse trabajo distinguiendo entre las dos -funciones. Por ejemplo, si un <em/widget/ tiene varias ventanas X, -entonces, como los eventos <tt/expose/ identifican a la ventana -expuesta, podrán redibujar sólo la ventana afectada, lo que no es -posible con llamadas a <tt/draw()/. - -Los <em/widgets/ contenedores, aunque no utilicen la diferecia -existente entre las dos funciones por sí mismos, no pueden utilizar -simplemente las funciones <tt/draw()/ que hay por defecto ya que sus -<em/widgets/ hijos puede que tengan que utilizar la diferencia. Sin -embargo, sería un derroche duplicar el código de dibujado entre las -dos funciones. Lo normal es que cada <em/widget/ tenga una función -llamada <tt/NOMBREWIDGET_paint()/ que haga el trabajo de dibujar el -<em/widget/, ésta función será a la que se llame por las funciones -<tt/draw()/ y <tt/expose()/. - -En nuestro ejemplo, como el <em/widget/ Dial no es un <em/widget/ -contenedor, y sólo tiene una ventana, podemos tomar el camino más -corto, utilizar la función <tt/draw()/ por defecto y sólo -implementar la función <tt/expose()/. - -<!-- ----------------------------------------------------------------- --> -<sect2> Los orígenes del <em/widget/ Dial -<p> -Así como todos los animales terrestes son variaciones del primer -anfíbio que salió del barro, los <em/widgets/ Gtk tienden a nacer -como variaciones de algún otro <em/widget/ escrito previamente. Por -tanto, aunque esta sección se titule `Creando un <em/widget/ de la -nada', el <em/widget/ Dial empieza realmente con el código fuente -del <em/widget/ Range. He tomado éste como punto de arranque porque -sería bonito que nuestro dial tuviese la misma interfaz que los -<em/widgets/ Scale, que son sólo una especialización del <em/widget/ -Range. Por tanto, aunque el código fuente se presente más adelante en -su forma final, no implica que fuese escrito de esta forma <em>deus ex -machina</em>. Si todavía no está familiarizado, desde el punto de -vista del escritor de aplicaciones, con la forma de funcionar de los -<em/widgets/ Scale, sería una buena idea echarles un vistazo antes de -continuar. - -<!-- ----------------------------------------------------------------- --> -<sect2> Los comienzos -<p> -Nuestro <em/widget/ tiene un aspecto algo parecido al del <em/widget/ -Tictactoe. Primero, tenemos un fichero de cabecera: - -<tscreen><verb> -/* 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; - - /* política de actualización - * (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */ - guint policy : 2; - - /* Botón actualmente presionado o 0 si no hay ninguno */ - guint8 boton; - - /* Dimensión de los componendes del dial */ - gint radius; - gint pointer_width; - - /* ID del temporizador de actualización, o 0 si no hay ninguno */ - guint32 timer; - - /* ángulo actual */ - gfloat angle; - - /* Viejos valores almacenados del adjustment, para que así no - * tengamos que saber cuando cambia algo */ - gfloat old_value; - gfloat old_lower; - gfloat old_upper; - - /* El objeto adjustment que almacena los datos para este dial */ - 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__ */ -</verb></tscreen> - -Como vamos a ir con este <em/widget/ un poco más lejos que con el -último que creamos, ahora tenemos unos cuantos campos más en la -estructura de datos, pero el resto de las cosas son muy parecidas. - -Ahora, después de incluir los ficheros de cabecera, y declarar unas -cuantas constantes, tenemos algunas funciones que proporcionan -información sobre el <em/widget/ y lo inicializan: - -<tscreen><verb> -#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 - -/* Declaraciones de funciones */ - -[ omitido para salvar espacio ] - -/* datos locales */ - -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, - (GtkArgSetFunc) NULL, - (GtkArgGetFunc) 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); -} -</verb></tscreen> - -Observe que ésta función <tt/init()/ hace menos cosas de las que hacía -la función <tt/init()/ que utilizamos con el <em/widget/ Tictactoe, ya -que éste no es un <em/widget/ compuesto, y la función <tt/new()/ hace -más cosas, ya que ahora admite un argumento. Observe también que -cuando almacenamos un puntero en un objeto Adjustment, incrementamos -su contador interno, (y lo decrementamos cuando ya no lo utilizamos) -por lo que GTK puede saber cuando se puede destruir sin que se -produzcan problemas. - -<p> -Aquí tenemos unas cuantas funciones para manipular las opciones del -<em/widget/: - -<tscreen><verb> -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); -} -</verb></tscreen> - -<sect2> <tt/gtk_dial_realize()/ - -<p> -Ahora vienen algunas funciones nuevas. Primero, tenemos una función -que hace el trabajo de crear la ventana X. A la función se le pasará -una máscara <tt/gdk_window_new()/ que especifica que campos de la -estructura <tt/GdkWindowAttr/ tienen datos (los campos restantes -tendrán los valores por defecto). También es bueno fijarse en la forma -en que se crea la máscara de eventos. Llamamos a -<tt/gtk_widget_get_events()/ para recuperar la máscara de eventos que -el usuario ha especificado para su <em/widget/ (con -<tt/gtk_widget_set_events()/), y añadir nosotros mismos los eventos -en los que estemos interesados. - -<p> -Después de crear la ventana, decidiremos su estilo y su fondo, y -pondremos un puntero al <em/widget/ en el campo de datos del usuario -de la <tt/GdkWindow/. Este último paso le permite a GTK despachar los -eventos que hayan para esta ventana hacia el <em/widget/ correcto. - -<tscreen><verb> -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); -} -</verb></tscreen> - -<sect2> Negociación del tamaño - -<p> -Antes de que se muestre por primera vez la ventana conteniendo un -<em/widget/, y cuando quiera que la capa de la ventana cambie, GTK le -preguntara a cada <em/widget/ hijo por su tamaño deseado. Esta -petición se controla mediante la función -<tt/gtk_dial_size_request()/. Como nuestro <em/widget/ no es un -<em/widget/ contenedor, y no tiene ninguna limitación en su tamaño, -nos contentaremos con devolver un valor por defecto. - -<tscreen><verb> -static void -gtk_dial_size_request (GtkWidget *widget, - GtkRequisition *requisition) -{ - requisition->width = DIAL_DEFAULT_SIZE; - requisition->height = DIAL_DEFAULT_SIZE; -} -</verb></tscreen> - -<p> -Después de que todos los <em/widgets/ hayan pedido su tamaño ideal, -se calculará la ventana y cada <em/widget/ hijo será informado de su -tamaño actual. Normalmente, éste será al menos tan grande como el -pedido, pero si por ejemplo, el usuario ha redimensionado la ventana, -entonces puede que el tamaño que se le de al <em/widget/ sea menor -que el que pidió. La notificación del tamaño se maneja mediante la -función <tt/gtk_dial_size_allocate()/. Fíjese que esta función calcula -los tamaños de los diferentes elementos que componen la ventana para -su uso futuro, así como todo el trabajo sucio que poner los -<em/widgets/ de la ventana X en la nueva posición y con el nuevo -tamaño. - -<tscreen><verb> -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; - } -} -</verb></tscreen>. - -<!-- ----------------------------------------------------------------- --> -<sect2> <tt/gtk_dial_expose()/ - -<p> -Como se mencionó arriba, todo el dibujado de este <em/widget/ se hace -en el manejador de los eventos <tt/expose/. No hay mucho destacable -aquí, excepto la utilización de la función <tt/gtk_draw_polygon/ para -dibujar el puntero con un degradado tridimensional de acuerdo con los -colores almacenados en el estilo del <em/widget/. - -<tscreen><verb> -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; - - /* Dibujar las rayitas */ - - 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); - } - - /* Dibujar el puntero */ - - 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; -} -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect2> Manejo de eventos - -<p> -El resto del código del <em/widget/ controla varios tipos de eventos, -y no es muy diferente del que podemos encontrar en muchas aplicaciones -GTK. Pueden ocurrir dos tipos de eventos - el usuario puede pulsar en -el <em/widget/ con el ratón y arrastrar para mover el puntero, o el -valor del objeto Adjustement puede cambiar debido a alguna -circunstancia externa. - -<p> -Cuando el usuario pulsa en el <em/widget/, haremos una comprobación -para ver si la pulsación se hizo lo suficientemente cerca del -puntero, y si así fue, almacenamos el botón que pulsó el usuario en -en el campo <tt/button/ de la estructura del <em/widget/, y grabamos -todos los eventos del ratón con una llamada a <tt/gtk_grab_add()/. El -movimiento del ratón hará que se recalcule el valor del control -(mediante la función <tt/gtk_dial_update_mouse/). Dependiendo de la -política que sigamos, o bien se generarán instantáneamente los eventos -<tt/value_changed/ (<tt/GTK_UPDATE_CONTINUOUS/), o bien después de una -espera del temporizador establecido mediante <tt/gtk_timeout_add()/ -(<tt/GTK_UPDATE_DELAYED/), o bien sólo cuando se levante el botón -(<tt/GTK_UPDATE_DISCONTINUOUS/). - -<tscreen><verb> -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); - - /* Determinar si la pulsación del botón fue dentro de la región del - puntero - esto lo hacemos calculando la distancia x e y del punto - donde se pulsó el botón ratón de la línea que se ha pasado mediante el - puntero */ - - 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); - } - } - } -} -</verb></tscreen> - -<p> -Cambios en el Adjustment por motivos externos significa que se le -comunicarán a nuestro <em/widget/ mediante las señales <tt/changed/ y -<tt/value_changed/. Los manejadores de estas funciones llaman a -<tt/gtk_dial_update()/ para comprobar los argumentos, calcular el -nuevo ángulo del puntero, y redibujar el <em/widget/ (llamando a -<tt/gtk_widget_draw()/). - -<tscreen><verb> -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; - } -} -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect2> Posibles mejoras -<p> - -El <em/widget/ Dial tal y como lo hemos descrito tiene unas 670 -líneas de código. Aunque pueda parecer un poco exagerado, todavía -no hemos escrito demasiado código, ya que la mayoría de las líneas -son de ficheros de cabecera y de adornos. Todavía se le pueden hacer -algunas mejoras a este <em/widget/: - -<itemize> -<item> Si prueba el <em/widget/, verá que el puntero cambia a -pantallazos cuando se le arrastra. Esto es debido a que todo el -<em/widget/ se borra cada vez que se mueve el puntero, antes de -redibujarse. Normalmente, la mejor forma de tratar este problema es -dibujar en un <em/pixmap/ que no represente lo que se ve directamente -en pantalla, y copiar el resultado final en la pantalla en sólo un -paso. (El <em/widget/ ProgressBar funciona de esta forma.) - -<item> El usuario debería ser capaz de utilizar las flechas de arriba -y abajo para aumentar y decrementar el valor. - -<item> Sería bonito si el <em/widget/ tuviese botones para -incrementar y decrementar el valor a saltos más o menos -grandes. Es posible utilizar <em/widgets/ botón, aunque también -queremos que los botones pudiesen realizar la operación de incrementar -o decrementar varias veces, mientras se mantenga el botón pulsado, tal -y como lo hacen las flechas en una barra de desplazamiento. La mayoría -del código para implementar todo esto lo podemos encontrar en el -<em/widget/ GtkRange. - -<item> El <em/widget/ Dial puede utilizarse en un <em/widget/ -contenedor con un simple <em/widget/ hijo colocado en la parte -inferior entre los botones antes mencionados. El usuario puede añadir -(según prefiera) una etiqueta o un <em/widget/ entry para mostrar el -valor actual del marcador. - -</itemize> - -<!-- ----------------------------------------------------------------- --> -<sect1> Aprendiendo más - -<p> -Sólo se han descrito una pequeña parte de los muchos detalles -involucrados en la creación de <em/widgets/, la mejor fuente de -ejemplos es el código mismo de GTK. Hágase algunas preguntas acerca -del <em/widget/ que desea crear: ¿es un <em/widget/ contenedor? -¿Debe tener su propia ventana? ¿Es una modificación de un -<em/widget/ existente? En ese momento busque un <em/widget/ similar, y -comience a hacer los cambios. -¡Buena suerte! - -<!-- ***************************************************************** --> -<sect>Scribble, un sencillo programa de dibujo de ejemplo -<!-- ***************************************************************** --> - -<!-- ----------------------------------------------------------------- --> -<sect1> Objetivos - -<p> -En esta sección, vamos a crear un sencillo programa de dibujo. En el -proceso, vamos a examinar como se manejan los eventos de ratón, como -dibujar en una ventana, y como mejorar el dibujado utilizando un -<em/pixmap/ intermedio. Después de crear el programa de dibujo, lo -ampliaremos añadiendole la posibilidad de utilizar dispositivos -XInput, como tabletas digitalizadoras. GTK proporciona las rutinas que -nos darán la posibilidad de obtener información extra, como la presión -y la inclinación, de todo tipo de dispositivos de una forma sencilla. - -<!-- ----------------------------------------------------------------- --> -<sect1> Manejo de eventos - -<p> -Las señales GTK sobre las que ya hemos discutido son para las -acciones de alto nivel, como cuando se selecciona un elemento de un -menú. Sin embargo a veces es útil tratar con los acontecimientos a -bajo nivel, como cuando se mueve el ratón, o cuando se está -presionando una tecla. También hay señales GTK relacionadas con -estos <em/eventos/ de bajo nivel. Los manejadores de estas señales -tienen un parámetro extra que es un puntero a una estructura -conteniendo información sobre el evento. Por ejemplo, a los manejadores -de los eventos de movimiento se les pasa una estructura -<tt/GdkEventMotion/ que es (en parte) así: - -<tscreen><verb> -struct _GdkEventMotion -{ - GdkEventType type; - GdkWindow *ventana; - guint32 time; - gdouble x; - gdouble y; - ... - guint state; - ... -}; -</verb></tscreen> - -<tt/type/ adquirirá su valor adecuado dependiendo del tipo de evento, -en nuestro caso <tt/GDK_MOTION_NOTIFY/, <tt/ventana/ es la ventana en -la que ocurre el evento. <tt/x/ e <tt/y/ dan las coordenadas del -evento, y <tt/state/ especifica cual es la modificación que ha habido -cuando ocurrió el evento (esto es, especifica que teclas han cambiado -su estado y que botones del ratón se han presionado.) Es la -operación OR (O) de algunos de los siguientes valores: - -<tscreen><verb> -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 -</verb></tscreen> - -<p> -Como con las otras señales, para especificar que es lo que pasa cuando -ocurre un evento, llamaremos a <tt>gtk_signal_connect()</tt>. Pero -también necesitamos decirle a GTK sobre que eventos queremos ser -informados. Para ello, llamaremos a la función: - -<tscreen><verb> -void gtk_widget_set_events (GtkWidget *widget, - gint events); -</verb></tscreen> - -El segundo campo especifica los eventos en los que estamos -interesados. Es el OR (O) de las constantes que especifican los -diferentes tipos de eventos. Por las referencias futuras que podamos -hacer, presentamos aquí los tipos de eventos que hay disponibles: - -<tscreen><verb> -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 -</verb></tscreen> - -Hay unos cuantas sutilezas que debemos respetar cuando llamamos a -<tt/gtk_widget_set_events()/. Primero, debemos llamar a esta función -antes de que se cree la ventana X para el <em/widget/ GTK. En -términos prácticos, significa que debemos llamarla inmediatamente -después de crear el <em/widget/. Segundo, el <em/widget/ debe tener -una ventana X asociado. Por motivos de eficiencia, hay muchos -<em/widgets/ que no tienen su propia ventana, sino que dibujan en la -de su padre. Estos <em/widgets/ son: - -<tscreen><verb> -GtkAlignment -GtkArrow -GtkBin -GtkBox -GtkImage -GtkItem -GtkLabel -GtkPixmap -GtkScrolledWindow -GtkSeparator -GtkTable -GtkAspectFrame -GtkFrame -GtkVBox -GtkHBox -GtkVSeparator -GtkHSeparator -</verb></tscreen> - -Para capturar eventos para estos <em/widgets/, necesita utilizar un -<em/widget/ EventBox. Vea la sección <ref -id="sec_The_EventBox_Widget" name="El widget EventBox"> para más -detalles. - -<p> -Para nuestro programa de dibujo, queremos saber cuando se presiona el -botón del ratón y cuando se mueve, por lo que debemos especificar -los eventos <tt/GDK_POINTER_MOTION_MASK/ y -<tt/GDK_BUTTON_PRESS_MASK/. También queremos saber cuando necesitamos -redibujar nuestra ventana, por lo que especificaremos el evento -<tt/GDK_EXPOSURE_MASK/. Aunque queremos estar informados mediante un -evento <tt/Configure/ cuando cambie el tamaño de nuestra ventana, no -tenemos que especificar la correspondiente <tt/GDK_STRUCTURE_MASK/, -porque ya está activada por defecto para todas las ventanas. - -<p> -Tenemos un problema con lo que acabamos de hacer, y tiene que ver con -la utilización de <tt/GDK_POINTER_MOTION_MASK/. Si especificamos este -evento, el servidor añadirá un evento de movimiento a la cola de -eventos cada vez que el usuario mueva el ratón. Imagine que nos -cuesta 0'1 segundo tratar el evento de movimiento, pero que el -servidor X añade a la cola un nuevo evento de moviento cada 0'05 -segundos. Pronto nos iremos quedando retrasados con respecto al resto -de los eventos. Si el usuario dibuja durante 5 segundos, ¡nos llevará -otros 5 segundos el cazarle después de que hay levantado el botón -del ratón! Lo que queremos es sólo un evento de movimiento por cada -evento que procesemos. La manera de hacerlo es especificando -<tt/GDK_POINTER_MOTION_HINT_MASK/. - -<p> -Cuando especificamos <tt/GDK_POINTER_MOTION_HINT_MASK/, el servidor -nos envia un evento de movimiento la primera ver que el puntero se -mueve depués de entrar en nuestra ventana, o después de que se -apriete o se suelte un botón (y se reciba el evento -correspondiente). Los eventos de movimiento restantes se eliminarán a -no ser que preguntemos especificamente por la posición del puntero -utilizando la función: - -<tscreen><verb> -GdkWindow* gdk_window_get_pointer (GdkWindow *ventana, - gint *x, - gint *y, - GdkModifierType *mask); -</verb></tscreen> - -(Hay otra función, <tt>gtk_widget_get_pointer()</tt> que tiene una -interfaz más sencillo, pero esta simplificación le resta utilidad, ya -que sólo devuelve la posición del ratón, y no si alguno de sus botones -está presionado.) - -<p> -El código para establecer los eventos para nuestra ventana es el -siguiente: - -<tscreen><verb> - 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); -</verb></tscreen> - -Vamos a dejar los manejadores de los eventos <tt/expose_event/ y -<tt/configure_event/ para después. Los manejadores de -<tt/motion_notify_event/ y de <tt/button_press_event/ son bastante -simples: - -<tscreen><verb> -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; -} -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1> El <em/widget/ DrawingArea, y dibujando - -<p> -Vamos a pasar al proceso de dibujar en la pantalla. El <em/widget/ que -utilizaremos será el DrawingArea. Un <em/widget/ DrawingArea es -esencialmente una ventana X y nada más. Es un lienzo en blanco en -el que podemos dibujar lo que queramos. Crearemos un área de dibujo -utilizando la llamada: - -<tscreen><verb> -GtkWidget* gtk_drawing_area_new (void); -</verb></tscreen> - -Se puede especificar un tamaño por defecto para el <em/widget/ -llamando a: - -<tscreen><verb> -void gtk_drawing_area_size (GtkDrawingArea *darea, - gint width, - gint height); -</verb></tscreen> - -Se puede cambiar el tamaño por defecto, como para todos los -<em/widgets/, llamando a <tt/gtk_widget_set_usize()/, y esto, además, -puede cambiarse si el usuario cambia manualmente el tamaño de la -ventana que contiene el área de dibujo. - -<p> -Debemos hacer notar que cuando creamos un <em/widget/ DrawingArea, -seremos <em/completamente/ responsables de dibujar su contenido. Si -nuestra ventana se tapa y se vuelve a poner al descubierto, -obtendremos un evento de exposición y deberemos redibujar lo que se -había tapado. - -<p> -Tener que recordar todo lo que se dibujó en la pantalla para que -podamos redibujarla convenientemente es, por decirlo de alguna manera -suave, una locura. Además puede quedar mal si hay que borrar partes -de la pantalla y hay que redibujarlas paso a paso. La solución a este -problema es utilizar un <em>pixmap</em> intermedio. En lugar de -dibujar directamente en la pantalla, dibujaremos en una imagen que -estará almacenada en la memoria del servidor, pero que no se mostrará, -y cuando cambie la imagen o se muestren nuevas partes de -la misma, copiaremos las porciones relevantes en la pantalla. - -<p> -Para crear un <em/pixmap/ intermedio, llamaremos a la función: - -<tscreen><verb> -GdkPixmap* gdk_pixmap_new (GdkWindow *ventana, - gint width, - gint height, - gint depth); -</verb></tscreen> - -El parámetro <tt/widget/ especifica una ventana GDK de las que este -<em/pixmap/ tomará algunas propiedades. <tt/width/ y <tt/height/ -especifican el tamaño del <em/pixmap/. <tt/depth/ especifica la -<em/profundidad del color/, que es el número de bits por pixel de la -nueva ventana. Si la profundidad que se especifica es <tt/-1/, se -utilizará la misma profundidad de color que tenga la <tt/ventana/. - -<p> -Creamos nuestro <em/pixmap/ en nuestro manejador del evento -<tt/configure_event/. Este evento se genera cada vez que cambia el -tamaño de la ventana, incluyendo cuando ésta se crea. - -<tscreen><verb> -/* Backing pixmap for drawing area */ -static GdkPixmap *pixmap = NULL; - -/* Create a new backing pixmap of the appropriate size */ -static gint -configure_event (GtkWidget *widget, GdkEventConfigure *event) -{ - if (pixmap) - g_object_unref(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; -} -</verb></tscreen> - -La llamada a <tt/gdk_draw_rectangle()/ rellena todo el <em/pixmap/ de -blanco. Hablaremos más de todo esto en un momento. - -<p> -Nuestro manejador del evento de exposición simplemente copia la -porción relevante del <em/pixmap/ en la pantalla (determinaremos la -zona a redibujar utilizando el campo <tt/event->area/ del evento de -exposición): - -<tscreen><verb> -/* Redraw the screen from the 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; -} -</verb></tscreen> - -Ahora ya sabemos como mantener la pantalla actualizada con el -contenido de nuestro <em/pixmap/, pero ¿cómo podemos dibujar algo -interesante en nuestro <em/pixmap/? Hay un gran número de llamadas en -la biblioteca GDK para dibujar en los <em/dibujables/. Un dibujable es -simplemente algo sobre lo que se puede dibujar. Puede ser una ventana, -un <em/pixmap/, un <em/bitmap/ (una imagen en blanco y negro), etc. Ya -hemos visto arriba dos de estas llamadas, -<tt>gdk_draw_rectangle()</tt> y <tt>gdk_draw_pixmap()</tt>. La lista -completa de funciones para dibujar es: - -<tscreen><verb> -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 () -</verb></tscreen> - -Ver la documentación de estas funciones o el fichero de cabecera -<tt><gdk/gdk.h></tt> para obtener más detalles sobre estas -funciones. Todas comparten los dos primeros argumentos. El primero es -el dibujable en el que se dibujará, y el segundo argumento es un -<em/contexto gráfico/ (GC). - -<p> -Un contexto gráfico reúne la información sobre cosas como el color -de fondo y del color de lo que se dibuja, el ancho de la línea, -etc... GDK tiene un conjunto completo de funciones para crear y -modificar los contextos gráficos. Cada <em/widget/ tiene un GC -asociado. (Que puede modificarse en un fichero gtkrc, ver la sección -«Ficheros rc de GTK».) Estos, junto con otras cosas, almacenan -GC's. Algunos ejemplos de como acceder a estos GC's son: - -<tscreen><verb> -widget->style->white_gc -widget->style->black_gc -widget->style->fg_gc[GTK_STATE_NORMAL] -widget->style->bg_gc[GTK_WIDGET_STATE(widget)] -</verb></tscreen> - -Los campos <tt>fg_gc</tt>, <tt>bg_gc</tt>, <tt>dark_gc</tt>, y -<tt>light_gc</tt> se indexan con un parámetro del tipo -<tt/GtkStateType/ que puede tomar uno de los valores: - -<tscreen><verb> -GTK_STATE_NORMAL, -GTK_STATE_ACTIVE, -GTK_STATE_PRELIGHT, -GTK_STATE_SELECTED, -GTK_STATE_INSENSITIVE -</verb></tscreen> - -Por ejemplo, para el <tt/GTK_STATE_SELECTED/, el color que se utiliza -para pintar por defecto es el blanco y el color del fondo por defecto, -es el azul oscuro. - -<p> -Nuestra función <tt/draw_brush()/, que es la que dibuja en la -pantalla, será la siguiente: - -<tscreen><verb> -/* Draw a rectangle on the screen */ -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); -} -</verb></tscreen> - -Después de que dibujemos el rectángulo representando la brocha en el -<em/pixmap/ llamaremos a la función: - -<tscreen><verb> -void gtk_widget_draw (GtkWidget *widget, - GdkRectangle *area); -</verb></tscreen> - -que le informa a X de que la zona dada por el parámetro <tt/area/ -necesita actualizarse. X generará un evento de exposición -(combinando posiblemente distintas zonas pasadas mediante distintas -llamadas a <tt/gtk_widget_draw()/) que hará que nuestro manejador de -eventos de exposición copie las porciones relevantes en la pantalla. - -<p> -Ya hemos cubierto el programa de dibujo completo, excepto unos cuantos -detalles mundanos como crear la ventana principal. El código completo -está disponible en el mismo lugar en el que consiguió este tutorial, -o en: - -<htmlurl url="http://www.gtk.org/~otaylor/gtk/tutorial/" -name="http://www.gtk.org/~otaylor/gtk/tutorial/"> - - -<!-- ----------------------------------------------------------------- --> -<sect1> Añadiendo la capacidad de utilizar XInput - -<p> -Ahora es posible comprar dispositos de entrada bastante baratos, como -tabletas digitalizadoras, que permiten dibujar de forma artística -mucho más fácilmente de cómo lo haríamos con un ratón. La forma -más sencilla de utilizar estos dispositivos es simplemente -reemplazando a los ratones, pero así perdemos muchas de las ventajas -de este tipo de dispositivos, como por ejemplo: - -<itemize> -<item> Sensibilidad a la presión -<item> Información sobre la inclinación -<item> Colocación subpixel -<item> Multiples entradas (por ejemplo, un lápiz con una punta y una -goma) -</itemize> - -Para información sobre la extensión XInput, ver el <htmlurl -url="http://www.msc.cornell.edu/~otaylor/xinput/XInput-HOWTO.html" -name="XInput-HOWTO">. - -<p> -Si examinamos la definición completa de, por ejemplo, la estructura -<tt/GdkEventMotion/, veremos que tiene campos para almacenar la -información de los dispositivos extendidos. - -<tscreen><verb> -struct _GdkEventMotion -{ - GdkEventType type; - GdkWindow *ventana; - guint32 time; - gdouble x; - gdouble y; - gdouble pressure; - gdouble xtilt; - gdouble ytilt; - guint state; - gint16 is_hint; - GdkInputSource source; - guint32 deviceid; -}; -</verb></tscreen> - -<tt/pressure/ da la presión como un número de coma flotante entre 0 -y 1. <tt/xtilt/ e <tt/ytilt/ pueden tomar valores entre -1 y 1, -correspondiendo al grado de inclinación en cada dirección. <tt/source/ -y <tt/deviceid/ especifican el dispositivo para el que ocurre el -evento de dos maneras diferentes. <tt/source/ da alguna información -simple sobre el tipo de dispositivo. Puede tomar los valores de la -enumeración siguiente: - -<tscreen><verb> -GDK_SOURCE_MOUSE -GDK_SOURCE_PEN -GDK_SOURCE_ERASER -GDK_SOURCE_CURSOR -</verb></tscreen> - -<tt/deviceid/ especifica un número único ID para el dispositivo. Puede -utilizarse para obtener más información sobre el dispositivo -utilizando la función <tt/gdk_input_list_devices()/ (ver abajo). El -valor especial <tt/GDK_CORE_POINTER/ se utiliza para el núcleo del -dispositivo apuntador. (Normalmente el ratón.) - -<sect2> Activando la información del dispositivo extendido - -<p> -Para informar a GTK de nuestro interés en la información sobre los -dispositivos extendidos, sólo tenemos que añadirle una línea a -nuestro programa: - -<tscreen><verb> -gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_CURSOR); -</verb></tscreen> - -Dando el valor <tt/GDK_EXTENSION_EVENTS_CURSOR/ decimos que estamos -interesados en los eventos de extensión, pero sólo si no tenemos que -dibujar nuestro propio cursor. Ver la sección <ref -id="sec_Further_Sophistications" name="Sofisticaciones adicionales"> -más abajo para obtener más información sobre el dibujado del -cursor. También podríamos dar los valores -<tt/GDK_EXTENSION_EVENTS_ALL/ si queremos dibujar nuestro propio -cursor, o <tt/GDK_EXTENSION_EVENTS_NONE/ para volver al estado -inicial. - -<p> -Todavía no hemos llegado al final de la historia. Por defecto, no hay -ningún dispositivo extra activado. Necesitamos un mecanismo que -permita a los usuarios activar y configurar sus dispositivos -extra. GTK proporciona el <em/widget/ InputDialog para automatizar el -proceso. El siguiente procedimiento utiliza el <em/widget/ -InputDialog. Crea el cuadro de diálogo si no ha sido ya creado, y lo -pone en primer plano en caso contrario. - -<tscreen><verb> -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); - } -} -</verb></tscreen> - -(Tome nota de la manera en que hemos manejado el cuadro de -diálogo. Conectando la señal <tt/destroy/, nos aseguramos de que no -tendremos un puntero al cuadro de diálogo después de que haya sido -destruido, lo que nos podría llevar a un segfault.) - -<p> -El InputDialog tiene dos botones «Cerrar» y «Guardar», que por -defecto no tienen ninguna acción asignada. En la función anterior -hemos hecho que «Cerrar» oculte el cuadro de diálogo, ocultando el -botón «Guardar», ya que no implementaremos en este programa la -acción de guardar las opciones de XInput. - -<sect2> Utilizando la información de los dispositivos extras - -<p> -Una vez hemos activado el dispositivo, podemos utilizar la -información que hay respecto a los dispositivos extendidos en los -campos extras de las estructuras de los eventos. De hecho, es bueno -utilizar esa información ya que esos campos tienen unos valores por -defecto razonables aún cuando no se activen los eventos extendidos. - -<p> -Un cambio que tenemos que hacer es llamar a -<tt/gdk_input_window_get_pointer()/ en vez de a -<tt/gdk_window_get_pointer/. Esto es necesario porque -<tt/gdk_window_get_pointer/ no devuelve la información de los -dispositivos extra. - -<tscreen><verb> -void gdk_input_window_get_pointer (GdkWindow *ventana, - guint32 deviceid, - gdouble *x, - gdouble *y, - gdouble *pressure, - gdouble *xtilt, - gdouble *ytilt, - GdkModifierType *mask); -</verb></tscreen> - -Cuando llamamos a esta función, necesitamos especificar tanto el ID -del dispositivo como la ventana. Normalmente, obtendremos el ID del -dispositivo del campo <tt/deviceid/ de una estructura de evento. De -nuevo, esta función devolverá valores razonables cuando no estén -activados los eventos extendidos. (En ese caso, <tt/event->deviceid/ -tendrá el valor <tt/GDK_CORE_POINTER/). - -Por tanto la estructura básica de nuestros manejadores de los -eventos de movimiento y de pulsación del botón del ratón no -cambiarán mucho - sólo tenemos que añadir código para manejar la -información extra. - -<tscreen><verb> -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; -} -</verb></tscreen> - -También tenemos que hacer algo con la nueva información. Nuestra -nueva función <tt/draw_brush()/ dibuja con un color diferente -dependiendo de <tt/event->source/ y cambia el tamaño de la brocha -dependiendo de la presión. - -<tscreen><verb> -/* Draw a rectangle on the screen, size depending on pressure, - and color on the type of 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); -} -</verb></tscreen> - -<sect2> Obteniendo más información de un dispositivo - -<p> -Como ejemplo de como podemos obtener más información de un -dispositivo, nuestro programa imprimirá el nombre del dispositivo que -genera cada pulsación de botón. Para encontrar el nombre de un -dispositivo, llamaremos a la función: - -<tscreen><verb> -GList *gdk_input_list_devices (void); -</verb></tscreen> - -que devuelve una GList (una lista enlazada de la biblioteca glib) -de estructuras <tt/GdkDeviceInfo/. La estructura <tt/GdkDeviceInfo/ se -define como: - -<tscreen><verb> -struct _GdkDeviceInfo -{ - guint32 deviceid; - gchar *name; - GdkInputSource source; - GdkInputMode mode; - gint has_cursor; - gint num_axes; - GdkAxisUse *axes; - gint num_keys; - GdkDeviceKey *keys; -}; -</verb></tscreen> - -Muchos de estos campos son información de configuración que puede -ignorar, a menos que quiera permitir la opción de grabar la -configuración de XInput. El campo que nos interesa ahora es <tt/name/ -que es simplemente el nombre que X le asigna al dispositivo. El otro -campo que no tiene información sobre la configuración es -<tt/has_cursor/. Si <tt/has_cursor/ es falso, tendremos que dibujar -nuestro propio cursor. Pero como hemos especificado -<tt/GDK_EXTENSION_EVENTS_CURSOR/, no tendremos que preocuparnos por -esto. - -<p> -Nuestra función <tt/print_button_press()/ simplemente recorre la -lista devuelta hasta que encuentra una coincidencia, y entonces -imprime el nombre del dispositivo. - -<tscreen><verb> -static void -print_button_press (guint32 deviceid) -{ - GList *tmp_list; - - /* gdk_input_list_devices returns an internal list, so we shouldn't - free it afterwards */ - 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; - } -} -</verb></tscreen> - -Con esto hemos completado los cambios para `XInputizar' nuestro -programa. Como ocurría con la primera versión, el código completo se -encuentra disponible en el mismo sitio donde obtuvo este tutorial, o -desde: - -<htmlurl url="http://www.gtk.org/~otaylor/gtk/tutorial/" -name="http://www.gtk.org/~otaylor/gtk/tutorial/"> - - -<sect2> Sofisticaciones adicionales <label id="sec_Further_Sophistications"> - -<p> -Aunque ahora nuestro programa admite XInput bastante bien, todavía -falla en algunas características que deberían estar disponibles en una -aplicación bien hecha. Primero, el usuario no debería tener que -configurar su dispositivo cada vez que ejecute el programa, por lo que -debería estar disponible la opción de guardar la configuración del -dispositivo. Esto se hace recorriendo el resultado de -<tt/gdk_input_list_devices()/ y escribiendo la configuración en un -fichero. - -<p> -Para cargar la configuración del dispositivo cuando se vuelva a -ejecutar el programa, puede utilizar las funciones que proporciona GDK -para cambiar la configuración de los dispositivos: - -<tscreen><verb> -gdk_input_set_extension_events() -gdk_input_set_source() -gdk_input_set_mode() -gdk_input_set_axes() -gdk_input_set_key() -</verb></tscreen> - -(La lista devuelta por <tt/gdk_input_list_devices()/ no debería -modificarse directamente.) Podemos encontrar un ejemplo de como debe -utilizarse en el programa de dibujo <tt/gsumi/. (Disponible en -<htmlurl url="http://www.msc.cornell.edu/~otaylor/gsumi/" -name="http://www.msc.cornell.edu/~otaylor/gsumi/">) Estaría bien -tener un procedimiento estándar para poder hacer todo esto en -cualquier aplicaciones. Probablemente se llegue a esto en una capa -superior a GTK, quizás en la biblioteca GNOME. - -<p> -El programa tiene otra carencia importante que ya hemos mencionado más -arriba, y es la falta del cursor. Ninguna plataforma distinta de -XFree86 permite utilizar simultaneamente un dispositivo como puntero -núcleo y como dispositivo directamente utilizable por una -aplicación. Ver el <url -url="http://www.msc.cornell.edu/~otaylor/xinput/XInput-HOWTO.html" -name="XInput-HOWTO"> para más información sobre esto. Con esto -queremos decir que si quiere tener la máxima audiencia necesita -dibujar su propio cursor. - -<p> -Una aplicación que dibuja su propio cursor necesita hacer dos cosas: -determinar si el dispositivo actual necesita que se dibuje un cursor o -no, y determinar si el dispositivo está «próximo». (Si el -dispositivo es una tableta digitalizadora, queda muy bonito que el -cursor desaparezca cuando el lápiz se separa de la tableta. Cuando el -lápiz está tocando la tableta, se dice que el dispositivo está -«próximo»). Lo primero se hace buscando la lista de dispositivos, -tal y como hicimos para encontrar el nombre del dispositivo. Lo -segundo se consigue seleccionando los eventos -<em/proximity_out/. Podemos encontrar un ejemplo de como dibujar -nuestro propio cursor en el programa `testinput' que viene con la -distribución de GTK. - -<!-- ***************************************************************** --> -<sect>Trucos para escribir aplicaciones GTK -<!-- ***************************************************************** --> - -<p> -Esta sección es sólo un compendio de sabiduria, de guías generales -de estilo y de consejos para crear buenas aplicaciones GTK. Y es -totalmente inútil por ahora ya que esta frase es sólo un tópico :) - -¡Utilice GNU autoconf y automake! Son sus amigos :) Pretendo poner -aquí una rápida introducción a ambos. - -<!-- ***************************************************************** --> -<sect>Contribuyendo <label id="sec_Contributing"> -<!-- ***************************************************************** --> - -<p> -Este documento, como muchos otros grandes paquetes de programas que -hay por ahí, fue creado de forma libre por voluntarios. Si comprende -algo de GTK que todavía no se ha documentado, por favor piense en -contribuir a este documento. - -<p> -Si decide contribuir, por favor mande un correo-e con su texto a Tony -Gale, <tt><htmlurl url="mailto:gale@gtk.org" -name="gale@gtk.org"></tt>. Recuerde que todas las partes que componen -este documento son libre, y cualquier añadido que haga debe ser -libre. Esto es, la gente debe de poder utilizar cualquier trozo de sus -ejemplos en sus programas, podrán distribuir copias de su documento -como deseen, etc... -<p> -Gracias. - -<!-- ***************************************************************** --> -<sect>Créditos -<!-- ***************************************************************** --> -<p> -Quiero agradecer a las siguientes personas por sus contribuciones a -este texto. - -<itemize> -<item>Bawer Dagdeviren, <tt><htmlurl url="mailto:chamele0n@geocities.com" -name="chamele0n@geocities.com"></tt> por el tutorial sobre los menús. - -<item>Raph Levien, <tt><htmlurl url="mailto:raph@acm.org" -name="raph@acm.org"></tt> por el «hola mundo» a la GTK, el -empaquetado de <em/widgets/, y su sabiduría general. Ha donado -generosamente un hogar para este tutorial. - -<item>Peter Mattis, <tt><htmlurl url="mailto:petm@xcf.berkeley.edu" -name="petm@xcf.berkeley.edu"></tt> por el más simple de los programas -GTK... y por la posibilidad de hacerlo :) - -<item>Werner Koch <tt><htmlurl url="mailto:werner.koch@guug.de" -name="werner.koch@guug.de"></tt> por convertir el texto original a -SGML, y por la jerarquia de clases de <em/widgets/. - -<item>Mark Crichton <tt><htmlurl url="mailto:crichton@expert.cc.purdue.edu" -name="crichton@expert.cc.purdue.edu"></tt> por el código del menú -factory, y el tutorial sobre el empaquetamiento de las tablas. - -<item>Owen Taylor <tt><htmlurl url="mailto:owt1@cornell.edu" -name="owt1@cornell.edu"></tt> por la sección sobre el <em/widget/ -EventBox (y el parche para el distro). También es el responsable -del código de las selecciones y el tutorial, así como de la -sección de escribiendo su propio <em/widget/ GTK, y la aplicación de -ejemplo. ¡Muchas gracias por toda tu ayuda, Owen! - -<item>Mark VanderBoom <tt><htmlurl url="mailto:mvboom42@calvin.edu" -name="mvboom42@calvin.edu"></tt> por su fantástico trabajo sobre los -<em/widgets/ Notebook, Progress Bar, Dialog, y selección de ficheros. -¡Muchas gracias Mark! -Has sido de una gran ayuda. - -<item>Tim Janik <tt><htmlurl url="mailto:timj@gtk.org" -name="timj@gtk.org"></tt> por su gran trabajo en el <em/widget/ List. -Gracias Tim :) - -<item>Rajat Datta <tt><htmlurl url="mailto:rajat@ix.netcom.com" -name="rajat@ix.netcom.com"</tt> por el excelente trabajo con el -tutorial Pixmap. - -<item>Michael K. Johnson <tt><htmlurl url="mailto:johnsonm@redhat.com" -name="johnsonm@redhat.com"></tt> por la información y el código de -los menús ("popup"). - -<item>David Huggins-Daines <tt><htmlurl url="mailto:bn711@freenet.carleton.ca" -name="bn711@freenet.carleton.ca"></tt> por las secciones sobre los -<em/widgets/ Range y Tree. - -<item>Stefan Mars <tt><htmlurl url="mailto:mars@lysator.liu.se" -name="mars@lysator.liu.se"></tt> por la sección GtkCList -</itemize> -<p> -Y a todos los que han comentado y ayudado a refinar este documento. -<p> -Gracias. - -<!-- ***************************************************************** --> -<sect> Copyright del Tutorial y notas sobre los permisos -<!-- ***************************************************************** --> - -<p> -Esta traducción está bajo la misma licencia bajo la que está -el documento original. A continuación se presenta la traducción -de la licencia y la licencia en versión original. En caso de haber -alguna discrepancia entre la traducción y la licencia original, se -aplicará esta última. - -El Tutorial GTK tiene Copyright (C) 1997 Ian Main. - -Copyright (C) 1998 Tony Gale. -<p> -Se da permiso para hacer y distribuir copias idénticas de este manual -siempre que se incluya el copyright en todas las copias. -<p> -Se da permiso para copiar y distribuir versiones modificadas de este -documento bajo las mismas condiciones que para las copias idénticas, -siempre que el copyright se incluya exactamente tal y como se -encuentra en el original, y que el trabajo completo derivado de este -documento se distribuya bajo los términos de un permiso idéntico a -éste. -<P> -Se da permiso para copiar y distribuir traducciones de este documento -en otro lenguaje, bajo las condiciones arriba mencionadas para las -versiones modificadas. -<P> -Si se propone incluir este documento en un trabajo que vaya a ser -impreso, por favor contacte con el encargado del mantenimiento, y -haremos un esfuerzo para asegurarnos de que dispone de la información -lo más actualizada posible. -<P> -No hay ninguna garantia de que este documento se mantenga activo lo -suficiente como para conseguir cumplir con su propósito. Se -proporciona como un documento libre. Como tal, los autores y -encargados del mantenimiento de la información que se da en el -documento no pueden dar ninguna garantia de que la misma esté al día. -<P> ------------------------------ -<p> -The GTK Tutorial is Copyright (C) 1997 Ian Main. - -Copyright (C) 1998 Tony Gale. -<p> -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. -<P>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. -<P>Permission is granted to copy and distribute translations of this -document into another language, under the above conditions for modified -versions. -<P>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. -<P>There is no guarantee 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 guarantee that the information is even accurate. - -<sect1>Acerca de la traducción - -<p> -Esta traduccion tiene copyright (C) 1999 de Joaquín Cuenca Abela -<tt><htmlurl url="mailto:e98cuenc@criens.u-psud.fr" -name="<e98cuenc@criens.u-psud.fr>"></tt> -y de Eduardo Anglada Varela -<tt><htmlurl url="mailto:eduardo.anglada@adi.uam.es" -name="<eduardo.anglada@adi.uam.es>"></tt>. -Si tiene cualquier -duda, sugerencia o corrección no dude en consultarnos. - -Gracias a Manuel de Vega Barreiro <tt><htmlurl -url="mailto:barreiro@arrakis.es" -name="<barreiro@arrakis.es>"></tt> por haber hospedado las -versiones beta y la versión actual de este tutorial en su página -web Linux Landia <tt><url -url="http://www.croftj.net/~barreiro/spain/gnome/" -name="www.croftj.net/~barreiro/spain/gnome/"></tt>. - -</sect1> - -<!-- ***************************************************************** --> -<appendix> -<!-- ***************************************************************** --> - -<!-- ***************************************************************** --> -<sect> Señales GTK <label id="sec_GTK_Signals"> -<!-- ***************************************************************** --> -<p> -GTK+, al ser un conjunto de <em/widgets/ orientado al objeto, tiene -una jerarquía de herencias. Este mecanismo de herencia se aplica a las -señales. Por eso, debe utilizar el árbol de jerarquías de los -<em/widgets/ cuando utilice las señales que aparecen en esta sección. - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkObject -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkObject::destroy (GtkObject *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkWidget -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> - -void GtkWidget::show (GtkWidget *, - gpointer); -void GtkWidget::hide (GtkWidget *, - gpointer); -void GtkWidget::map (GtkWidget *, - gpointer); -void GtkWidget::unmap (GtkWidget *, - gpointer); -void GtkWidget::realize (GtkWidget *, - gpointer); -void GtkWidget::unrealize (GtkWidget *, - gpointer); -void GtkWidget::draw (GtkWidget *, - ggpointer, - gpointer); -void GtkWidget::draw-focus (GtkWidget *, - gpointer); -void GtkWidget::draw-default (GtkWidget *, - gpointer); -void GtkWidget::size-request (GtkWidget *, - ggpointer, - gpointer); -void GtkWidget::size-allocate (GtkWidget *, - ggpointer, - gpointer); -void GtkWidget::state-changed (GtkWidget *, - GtkStateType, - gpointer); -void GtkWidget::parent-set (GtkWidget *, - GtkObject *, - gpointer); -void GtkWidget::style-set (GtkWidget *, - GtkStyle *, - gpointer); -void GtkWidget::add-accelerator (GtkWidget *, - gguint, - GtkAccelGroup *, - gguint, - GdkModifierType, - GtkAccelFlags, - gpointer); -void GtkWidget::remove-accelerator (GtkWidget *, - GtkAccelGroup *, - gguint, - GdkModifierType, - gpointer); -gboolean GtkWidget::event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::button-press-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::button-release-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::motion-notify-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::delete-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::destroy-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::expose-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::key-press-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::key-release-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::enter-notify-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::leave-notify-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::configure-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::focus-in-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::focus-out-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::map-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::unmap-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::property-notify-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::selection-clear-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::selection-request-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::selection-notify-event (GtkWidget *, - GdkEvent *, - gpointer); -void GtkWidget::selection-get (GtkWidget *, - GtkSelectionData *, - gguint, - gpointer); -void GtkWidget::selection-received (GtkWidget *, - GtkSelectionData *, - gguint, - gpointer); -gboolean GtkWidget::proximity-in-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::proximity-out-event (GtkWidget *, - GdkEvent *, - gpointer); -void GtkWidget::drag-begin (GtkWidget *, - GdkDragContext *, - gpointer); -void GtkWidget::drag-end (GtkWidget *, - GdkDragContext *, - gpointer); -void GtkWidget::drag-data-delete (GtkWidget *, - GdkDragContext *, - gpointer); -void GtkWidget::drag-leave (GtkWidget *, - GdkDragContext *, - gguint, - gpointer); -gboolean GtkWidget::drag-motion (GtkWidget *, - GdkDragContext *, - ggint, - ggint, - gguint, - gpointer); -gboolean GtkWidget::drag-drop (GtkWidget *, - GdkDragContext *, - ggint, - ggint, - gguint, - gpointer); -void GtkWidget::drag-data-get (GtkWidget *, - GdkDragContext *, - GtkSelectionData *, - gguint, - gguint, - gpointer); -void GtkWidget::drag-data-received (GtkWidget *, - GdkDragContext *, - ggint, - ggint, - GtkSelectionData *, - gguint, - gguint, - gpointer); -gboolean GtkWidget::client-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::no-expose-event (GtkWidget *, - GdkEvent *, - gpointer); -gboolean GtkWidget::visibility-notify-event (GtkWidget *, - GdkEvent *, - gpointer); -void GtkWidget::debug-msg (GtkWidget *, - GtkString *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkData -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkData::disconnect (GtkData *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkContainer -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkContainer::add (GtkContainer *, - GtkWidget *, - gpointer); -void GtkContainer::remove (GtkContainer *, - GtkWidget *, - gpointer); -void GtkContainer::check-resize (GtkContainer *, - gpointer); -GtkDirectionType GtkContainer::focus (GtkContainer *, - GtkDirectionType, - gpointer); -void GtkContainer::set-focus-child (GtkContainer *, - GtkWidget *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkCalendar -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkCalendar::month-changed (GtkCalendar *, - gpointer); -void GtkCalendar::day-selected (GtkCalendar *, - gpointer); -void GtkCalendar::day-selected-double-click (GtkCalendar *, - gpointer); -void GtkCalendar::prev-month (GtkCalendar *, - gpointer); -void GtkCalendar::next-month (GtkCalendar *, - gpointer); -void GtkCalendar::prev-year (GtkCalendar *, - gpointer); -void GtkCalendar::next-year (GtkCalendar *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkEditable -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkEditable::changed (GtkEditable *, - gpointer); -void GtkEditable::insert-text (GtkEditable *, - GtkString *, - ggint, - ggpointer, - gpointer); -void GtkEditable::delete-text (GtkEditable *, - ggint, - ggint, - gpointer); -void GtkEditable::activate (GtkEditable *, - gpointer); -void GtkEditable::set-editable (GtkEditable *, - gboolean, - gpointer); -void GtkEditable::move-cursor (GtkEditable *, - ggint, - ggint, - gpointer); -void GtkEditable::move-word (GtkEditable *, - ggint, - gpointer); -void GtkEditable::move-page (GtkEditable *, - ggint, - ggint, - gpointer); -void GtkEditable::move-to-row (GtkEditable *, - ggint, - gpointer); -void GtkEditable::move-to-column (GtkEditable *, - ggint, - gpointer); -void GtkEditable::kill-char (GtkEditable *, - ggint, - gpointer); -void GtkEditable::kill-word (GtkEditable *, - ggint, - gpointer); -void GtkEditable::kill-line (GtkEditable *, - ggint, - gpointer); -void GtkEditable::cut-clipboard (GtkEditable *, - gpointer); -void GtkEditable::copy-clipboard (GtkEditable *, - gpointer); -void GtkEditable::paste-clipboard (GtkEditable *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkTipsQuery -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkTipsQuery::start-query (GtkTipsQuery *, - gpointer); -void GtkTipsQuery::stop-query (GtkTipsQuery *, - gpointer); -void GtkTipsQuery::widget-entered (GtkTipsQuery *, - GtkWidget *, - GtkString *, - GtkString *, - gpointer); -gboolean GtkTipsQuery::widget-selected (GtkTipsQuery *, - GtkWidget *, - GtkString *, - GtkString *, - GdkEvent *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkCList -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkCList::select-row (GtkCList *, - ggint, - ggint, - GdkEvent *, - gpointer); -void GtkCList::unselect-row (GtkCList *, - ggint, - ggint, - GdkEvent *, - gpointer); -void GtkCList::row-move (GtkCList *, - ggint, - ggint, - gpointer); -void GtkCList::click-column (GtkCList *, - ggint, - gpointer); -void GtkCList::resize-column (GtkCList *, - ggint, - ggint, - gpointer); -void GtkCList::toggle-focus-row (GtkCList *, - gpointer); -void GtkCList::select-all (GtkCList *, - gpointer); -void GtkCList::unselect-all (GtkCList *, - gpointer); -void GtkCList::undo-selection (GtkCList *, - gpointer); -void GtkCList::start-selection (GtkCList *, - gpointer); -void GtkCList::end-selection (GtkCList *, - gpointer); -void GtkCList::toggle-add-mode (GtkCList *, - gpointer); -void GtkCList::extend-selection (GtkCList *, - GtkScrollType, - ggfloat, - gboolean, - gpointer); -void GtkCList::scroll-vertical (GtkCList *, - GtkScrollType, - ggfloat, - gpointer); -void GtkCList::scroll-horizontal (GtkCList *, - GtkScrollType, - ggfloat, - gpointer); -void GtkCList::abort-column-resize (GtkCList *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkNotebook -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkNotebook::switch-page (GtkNotebook *, - ggpointer, - gguint, - gpointer); - -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkList -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkList::selection-changed (GtkList *, - gpointer); -void GtkList::select-child (GtkList *, - GtkWidget *, - gpointer); -void GtkList::unselect-child (GtkList *, - GtkWidget *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkMenuShell -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkMenuShell::deactivate (GtkMenuShell *, - gpointer); -void GtkMenuShell::selection-done (GtkMenuShell *, - gpointer); -void GtkMenuShell::move-current (GtkMenuShell *, - GtkMenuDirectionType, - gpointer); -void GtkMenuShell::activate-current (GtkMenuShell *, - gboolean, - gpointer); -void GtkMenuShell::cancel (GtkMenuShell *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkToolbar -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkToolbar::orientation-changed (GtkToolbar *, - ggint, - gpointer); -void GtkToolbar::style-changed (GtkToolbar *, - ggint, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkTree -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkTree::selection-changed (GtkTree *, - gpointer); -void GtkTree::select-child (GtkTree *, - GtkWidget *, - gpointer); -void GtkTree::unselect-child (GtkTree *, - GtkWidget *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkButton -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkButton::pressed (GtkButton *, - gpointer); -void GtkButton::released (GtkButton *, - gpointer); -void GtkButton::clicked (GtkButton *, - gpointer); -void GtkButton::enter (GtkButton *, - gpointer); -void GtkButton::leave (GtkButton *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkItem -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkItem::select (GtkItem *, - gpointer); -void GtkItem::deselect (GtkItem *, - gpointer); -void GtkItem::toggle (GtkItem *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkWindow -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkWindow::set-focus (GtkWindow *, - ggpointer, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkHandleBox -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkHandleBox::child-attached (GtkHandleBox *, - GtkWidget *, - gpointer); -void GtkHandleBox::child-detached (GtkHandleBox *, - GtkWidget *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkToggleButton -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkToggleButton::toggled (GtkToggleButton *, - gpointer); - -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkMenuItem -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkMenuItem::activate (GtkMenuItem *, - gpointer); -void GtkMenuItem::activate-item (GtkMenuItem *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkListItem -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkListItem::toggle-focus-row (GtkListItem *, - gpointer); -void GtkListItem::select-all (GtkListItem *, - gpointer); -void GtkListItem::unselect-all (GtkListItem *, - gpointer); -void GtkListItem::undo-selection (GtkListItem *, - gpointer); -void GtkListItem::start-selection (GtkListItem *, - gpointer); -void GtkListItem::end-selection (GtkListItem *, - gpointer); -void GtkListItem::toggle-add-mode (GtkListItem *, - gpointer); -void GtkListItem::extend-selection (GtkListItem *, - GtkEnum, - ggfloat, - gboolean, - gpointer); -void GtkListItem::scroll-vertical (GtkListItem *, - GtkEnum, - ggfloat, - gpointer); -void GtkListItem::scroll-horizontal (GtkListItem *, - GtkEnum, - ggfloat, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkTreeItem -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkTreeItem::collapse (GtkTreeItem *, - gpointer); -void GtkTreeItem::expand (GtkTreeItem *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkCheckMenuItem -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkCheckMenuItem::toggled (GtkCheckMenuItem *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkInputDialog -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkInputDialog::enable-device (GtkInputDialog *, - ggint, - gpointer); -void GtkInputDialog::disable-device (GtkInputDialog *, - ggint, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkColorSelection -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkColorSelection::color-changed (GtkColorSelection *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkStatusBar -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkStatusbar::text-pushed (GtkStatusbar *, - gguint, - GtkString *, - gpointer); -void GtkStatusbar::text-popped (GtkStatusbar *, - gguint, - GtkString *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkCTree -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkCTree::tree-select-row (GtkCTree *, - GtkCTreeNode *, - ggint, - gpointer); -void GtkCTree::tree-unselect-row (GtkCTree *, - GtkCTreeNode *, - ggint, - gpointer); -void GtkCTree::tree-expand (GtkCTree *, - GtkCTreeNode *, - gpointer); -void GtkCTree::tree-collapse (GtkCTree *, - ggpointer, - gpointer); -void GtkCTree::tree-move (GtkCTree *, - GtkCTreeNode *, - GtkCTreeNode *, - GtkCTreeNode *, - gpointer); -void GtkCTree::change-focus-row-expansion (GtkCTree *, - GtkCTreeExpansionType, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkCurve -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkCurve::curve-type-changed (GtkCurve *, - gpointer); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>GtkAdjustment -<!-- ----------------------------------------------------------------- --> -<p> -<tscreen><verb> -void GtkAdjustment::changed (GtkAdjustment *, - gpointer); -void GtkAdjustment::value-changed (GtkAdjustment *, - gpointer); -</verb></tscreen> - -<!-- ***************************************************************** --> -<sect> Tipos de eventos GDK<label id="sec_GDK_Event_Types"> -<!-- ***************************************************************** --> -<p> -Los siguientes tipos de datos se pasan en los manejadores de los -eventos por GTK+. Para cada tipo de dato que se muestra, se muestran -las señales que utilizan ese tipo de dato. - -<itemize> -<item> GdkEvent - <itemize> - <item>drag_end_event - </itemize> - -<item> GdkEventType - -<item> GdkEventAny - <itemize> - <item>delete_event - <item>destroy_event - <item>map_event - <item>unmap_event - <item>no_expose_event - </itemize> - -<item> GdkEventExpose - <itemize> - <item>expose_event - </itemize> - -<item> GdkEventNoExpose - -<item> GdkEventVisibility - -<item> GdkEventMotion - <itemize> - <item>motion_notify_event - </itemize> - -<item> GdkEventButton - <itemize> - <item>button_press_event - <item>button_release_event - </itemize> - -<item> GdkEventKey - <itemize> - <item>key_press_event - <item>key_release_event - </itemize> - -<item> GdkEventCrossing - <itemize> - <item>enter_notify_event - <item>leave_notify_event - </itemize> - -<item> GdkEventFocus - <itemize> - <item>focus_in_event - <item>focus_out_event - </itemize> - -<item> GdkEventConfigure - <itemize> - <item>configure_event - </itemize> - -<item> GdkEventProperty - <itemize> - <item>property_notify_event - </itemize> - -<item> GdkEventSelection - <itemize> - <item>selection_clear_event - <item>selection_request_event - <item>selection_notify_event - </itemize> - -<item> GdkEventProximity - <itemize> - <item>proximity_in_event - <item>proximity_out_event - </itemize> - -<item> GdkEventDragBegin - <itemize> - <item>drag_begin_event - </itemize> - -<item> GdkEventDragRequest - <itemize> - <item>drag_request_event - </itemize> - -<item> GdkEventDropEnter - <itemize> - <item>drop_enter_event - </itemize> - -<item> GdkEventDropLeave - <itemize> - <item>drop_leave_event - </itemize> - -<item> GdkEventDropDataAvailable - <itemize> - <item>drop_data_available_event - </itemize> - -<item> GdkEventClient - <itemize> - <item>client_event - </itemize> - -<item> GdkEventOther - <itemize> - <item>other_event - </itemize> -</itemize> - -El tipo de dato <tt/GdkEventType/ es un tipo de dato especial que se -utiliza por todos los otros tipos de datos como un indicador del tipo -de dato que se le está pasando al manejador de señal. Como verá -más adelante, cada una de estructuras de los datos de los eventos -tienen un miembro de este tipo. Se define como la siguiente -enumeración: - -<tscreen><verb> -typedef enum -{ - GDK_NOTHING = -1, - GDK_DELETE = 0, - GDK_DESTROY = 1, - GDK_EXPOSE = 2, - GDK_MOTION_NOTIFY = 3, - GDK_BUTTON_PRESS = 4, - GDK_2BUTTON_PRESS = 5, - GDK_3BUTTON_PRESS = 6, - GDK_BUTTON_RELEASE = 7, - GDK_KEY_PRESS = 8, - GDK_KEY_RELEASE = 9, - GDK_ENTER_NOTIFY = 10, - GDK_LEAVE_NOTIFY = 11, - GDK_FOCUS_CHANGE = 12, - GDK_CONFIGURE = 13, - GDK_MAP = 14, - GDK_UNMAP = 15, - GDK_PROPERTY_NOTIFY = 16, - GDK_SELECTION_CLEAR = 17, - GDK_SELECTION_REQUEST = 18, - GDK_SELECTION_NOTIFY = 19, - GDK_PROXIMITY_IN = 20, - GDK_PROXIMITY_OUT = 21, - GDK_DRAG_BEGIN = 22, - GDK_DRAG_REQUEST = 23, - GDK_DROP_ENTER = 24, - GDK_DROP_LEAVE = 25, - GDK_DROP_DATA_AVAIL = 26, - GDK_CLIENT_EVENT = 27, - GDK_VISIBILITY_NOTIFY = 28, - GDK_NO_EXPOSE = 29, - GDK_OTHER_EVENT = 9999 /* Anacrónico, utilice en su lugar los - filtros */ -} GdkEventType; -</verb></tscreen> - -El otro tipo de evento que es diferente del resto es el mismo -<tt/GdkEvent/. Ésta es una unión de todos los otros tipos de -datos, que permite que se convierta en un tipo de dato de evento -específico con un manejador de señal. - -<!-- Just a big list for now, needs expanding upon - TRG --> -Por tanto, los tipos de los datos de los eventos se definen como -sigue: - -<tscreen><verb> -struct _GdkEventAny -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; -}; - -struct _GdkEventExpose -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; - GdkRectangle area; - gint count; /* Si count no es, entonces es el número de eventos que - * siguen. */ -}; - -struct _GdkEventNoExpose -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; - /* XXX: ¿Hay alguien que necesite los campos major_code y minor_code - de X ? */ -}; - -struct _GdkEventVisibility -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; - GdkVisibilityState state; -}; - -struct _GdkEventMotion -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; - guint32 time; - gdouble x; - gdouble y; - gdouble pressure; - gdouble xtilt; - gdouble ytilt; - guint state; - gint16 is_hint; - GdkInputSource source; - guint32 deviceid; - gdouble x_root, y_root; -}; - -struct _GdkEventButton -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; - guint32 time; - gdouble x; - gdouble y; - gdouble pressure; - gdouble xtilt; - gdouble ytilt; - guint state; - guint button; - GdkInputSource source; - guint32 deviceid; - gdouble x_root, y_root; -}; - -struct _GdkEventKey -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; - guint32 time; - guint state; - guint keyval; - gint length; - gchar *string; -}; - -struct _GdkEventCrossing -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; - GdkWindow *subwindow; - GdkNotifyType detail; -}; - -struct _GdkEventFocus -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; - gint16 in; -}; - -struct _GdkEventConfigure -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; - gint16 x, y; - gint16 width; - gint16 height; -}; - -struct _GdkEventProperty -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; - GdkAtom atom; - guint32 time; - guint state; -}; - -struct _GdkEventSelection -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; - GdkAtom selection; - GdkAtom target; - GdkAtom property; - guint32 requestor; - guint32 time; -}; - -/* Este tipo de evento se utiliza muy raramente. Solamente es - * importante para los programas que utilizan XInput y que dibujar su - * propio cursor */ - -struct _GdkEventProximity -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; - guint32 time; - GdkInputSource source; - guint32 deviceid; -}; - -struct _GdkEventDragRequest -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; - guint32 requestor; - union { - struct { - guint protocol_version:4; - guint sendreply:1; - guint willaccept:1; - guint delete_data:1; /* No borrar si se ha mandado un enlace, - sólo si se ha mandado el dato */ - guint senddata:1; - guint reserved:22; - } flags; - glong allflags; - } u; - guint8 isdrop; /* Este evento gdk puede ser generado por un par de - eventos X - esto le permite a las aplicaciones - saber si ha ocurrido realmente el soltado (drop), - o si sólo hemos cambiado el valor de algunos datos - */ - - GdkPoint drop_coords; - gchar *data_type; - guint32 timestamp; -}; - -struct _GdkEventDragBegin -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; - union { - struct { - guint protocol_version:4; - guint reserved:28; - } flags; - glong allflags; - } u; -}; - -struct _GdkEventDropEnter -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; - guint32 requestor; - union { - struct { - guint protocol_version:4; - guint sendreply:1; - guint extended_typelist:1; - guint reserved:26; - } flags; - glong allflags; - } u; -}; - -struct _GdkEventDropLeave -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; - guint32 requestor; - union { - struct { - guint protocol_version:4; - guint reserved:28; - } flags; - glong allflags; - } u; -}; - -struct _GdkEventDropDataAvailable -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; - guint32 requestor; - union { - struct { - guint protocol_version:4; - guint isdrop:1; - guint reserved:25; - } flags; - glong allflags; - } u; - gchar *data_type; /* tipo MIME */ - gulong data_numbytes; - gpointer data; - guint32 timestamp; - GdkPoint coords; -}; - -struct _GdkEventClient -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; - GdkAtom message_type; - gushort data_format; - union { - char b[20]; - short s[10]; - long l[5]; - } data; -}; - -struct _GdkEventOther -{ - GdkEventType type; - GdkWindow *window; - gint8 send_event; - GdkXEvent *xevent; -}; -</verb></tscreen> - -<!-- ***************************************************************** --> -<sect> Código ejemplo -<!-- ***************************************************************** --> -<p> -A continuación tenemos el código ejemplo que se ha utilizado en el -texto anterior y que no se ha incluido al completo en otro lugar. - -<!-- ----------------------------------------------------------------- --> -<sect1>Tictactoe -<!-- ----------------------------------------------------------------- --> -<sect2>tictactoe.h -<p> -<tscreen><verb> -/* principio del ejemplo tictactoe tictactoe.h */ - -/* 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ -#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 *botones[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__ */ - -/* fin del ejemplo */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect2>tictactoe.c -<p> -<tscreen><verb> -/* principio del ejemplo tictactoe tictactoe.c */ - -/* 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ -#include "gtk/gtksignal.h" -#include "gtk/gtktable.h" -#include "gtk/gtktogglebutton.h" -#include "tictactoe.h" - -enum { - TICTACTOE_SIGNAL, - LAST_SIGNAL -}; - -static void tictactoe_class_init (TictactoeClass *klass); -static void tictactoe_init (Tictactoe *ttt); -static void tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt); - -static gint tictactoe_signals[LAST_SIGNAL] = { 0 }; - -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; -} - -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; -} - -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]); - } -} - -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; - } - } -} - -/* fin del ejemplo */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect2>ttt_test.c -<p> -<tscreen><verb> -/* principio del ejemplo tictactoe ttt_test.c */ - -#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 *ventana; - GtkWidget *ttt; - - gtk_init (&argc, &argv); - - ventana = gtk_window_new (GTK_WINDOW_TOPLEVEL); - - gtk_window_set_title (GTK_WINDOW (ventana), "Aspect Frame"); - - gtk_signal_connect (GTK_OBJECT (ventana), "destroy", - GTK_SIGNAL_FUNC (gtk_exit), NULL); - - gtk_container_border_width (GTK_CONTAINER (ventana), 10); - - ttt = tictactoe_new (); - - gtk_container_add (GTK_CONTAINER (ventana), ttt); - gtk_widget_show (ttt); - - gtk_signal_connect (GTK_OBJECT (ttt), "tictactoe", - GTK_SIGNAL_FUNC (win), NULL); - - gtk_widget_show (ventana); - - gtk_main (); - - return 0; -} - -/* fin del ejemplo */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1> GtkDial - -<!-- ----------------------------------------------------------------- --> -<sect2> gtkdial.h -<p> -<tscreen><verb> -/* principio del ejmplo gtkdial gtkdial.h */ - -/* 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, 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; - - /* política de actualización - * (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */ - guint policy : 2; - - /* Botón actualmente presionado o 0 si no hay ninguno */ - guint8 boton; - - /* Dimensión de los componendes del dial */ - gint radius; - gint pointer_width; - - /* ID del temporizador de actualización, o 0 si no hay ninguno */ - guint32 timer; - - /* ángulo actual */ - gfloat angle; - - /* Viejos valores almacenados del adjustment, para que así no - * tengamos que saber cuando cambia algo */ - gfloat old_value; - gfloat old_lower; - gfloat old_upper; - - /* El objeto adjustment que almacena los datos para este dial */ - 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__ */ -/* fin del ejemplo */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect2> gtkdial.c -<p> -<tscreen><verb> -/* principio del ejemplo gtkdial gtkdial.c */ - -/* 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ -#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 - -/* declaraciones de funciones */ - -static void gtk_dial_class_init (GtkDialClass *klass); -static void gtk_dial_init (GtkDial *dial); -static void gtk_dial_destroy (GtkObject *object); -static void gtk_dial_realize (GtkWidget *widget); -static void gtk_dial_size_request (GtkWidget *widget, - GtkRequisition *requisition); -static void gtk_dial_size_allocate (GtkWidget *widget, - GtkAllocation *allocation); -static gint gtk_dial_expose (GtkWidget *widget, - GdkEventExpose *event); -static gint gtk_dial_button_press (GtkWidget *widget, - GdkEventButton *event); -static gint gtk_dial_button_release (GtkWidget *widget, - GdkEventButton *event); -static gint gtk_dial_motion_notify (GtkWidget *widget, - GdkEventMotion *event); -static gint gtk_dial_timer (GtkDial *dial); - -static void gtk_dial_update_mouse (GtkDial *dial, gint x, gint y); -static void gtk_dial_update (GtkDial *dial); -static void gtk_dial_adjustment_changed (GtkAdjustment *adjustment, - gpointer data); -static void gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment, - gpointer data); - -/* datos locales */ - -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, - (GtkArgSetFunc) NULL, - (GtkArgGetFunc) 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); -} - -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); -} - -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); -} - -static void -gtk_dial_size_request (GtkWidget *widget, - GtkRequisition *requisition) -{ - requisition->width = DIAL_DEFAULT_SIZE; - requisition->height = DIAL_DEFAULT_SIZE; -} - -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; - dial = GTK_DIAL (widget); - - if (GTK_WIDGET_REALIZED (widget)) - { - - gdk_window_move_resize (widget->window, - allocation->x, allocation->y, - allocation->width, allocation->height); - - } - dial->radius = MIN(allocation->width,allocation->height) * 0.45; - dial->pointer_width = dial->radius / 5; -} - -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; - - /* Dibuja las rayitas */ - - 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); - } - - /* Dibuja el puntero */ - - 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; -} - -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); - - - /* Determinar si la pulsación del botón fue dentro de la región del - puntero - esto lo hacemos calculando la distancia x e y del punto - donde se pulsó el botón ratón de la línea que se ha pasado mediante el - puntero */ - - 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); - } - } - } -} - -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; - } -} -/* fin del ejemplo */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1> Scribble -<p> -<tscreen><verb> -/* principio del ejemplo scribble-simple scribble-simple.c */ - -/* 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include <gtk/gtk.h> - -/* Creamos un backing pixmap para la zona donde dibujamos */ -static GdkPixmap *pixmap = NULL; - -/* Creamos un nuevo backing pixmap del tamaño apropiado */ -static gint -configure_event (GtkWidget *widget, GdkEventConfigure *event) -{ - if (pixmap) - g_object_unref(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; -} - -/* Redibujamos la pantalla con el 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; -} - -/* Dibujamos un rectángulo en la pantalla */ -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); -} - -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; -} - -void -quit () -{ - gtk_exit (0); -} - -int -main (int argc, char *argv[]) -{ - GtkWidget *ventana; - GtkWidget *drawing_area; - GtkWidget *vbox; - - GtkWidget *boton; - - gtk_init (&argc, &argv); - - ventana = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_widget_set_name (ventana, "Test Input"); - - vbox = gtk_vbox_new (FALSE, 0); - gtk_container_add (GTK_CONTAINER (ventana), vbox); - gtk_widget_show (vbox); - - gtk_signal_connect (GTK_OBJECT (ventana), "destroy", - GTK_SIGNAL_FUNC (quit), NULL); - - /* Crear la zona de dibujado */ - - drawing_area = gtk_drawing_area_new (); - gtk_drawing_area_size (GTK_DRAWING_AREA (drawing_area), 200, 200); - gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0); - - gtk_widget_show (drawing_area); - - /* Las señales utilizadas para manejar el backing pixmap */ - - 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); - - /* Señales evento */ - - 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); - - /* .. Y un botón para salir */ - boton = gtk_button_new_with_label ("Quit"); - gtk_box_pack_start (GTK_BOX (vbox), boton, FALSE, FALSE, 0); - - gtk_signal_connect_object (GTK_OBJECT (boton), "clicked", - GTK_SIGNAL_FUNC (gtk_widget_destroy), - GTK_OBJECT (ventana)); - gtk_widget_show (boton); - - gtk_widget_show (ventana); - - gtk_main (); - - return 0; -} -/* fin del ejemplo */ -</verb></tscreen> - -<!-- ***************************************************************** --> -<sect> El <em>widget</em> lista -<!-- ***************************************************************** --> -<p> -ATENCIÓN: El <em>widget</em> GtkList ha sido reemplazado por el -<em>widget</em> GtkCList. - -El <em>widget</em> GtkList está diseñado para actuar como un -contenedor vertical de <em>widgets</em> que deben ser del tipo -GtkListItem. - -Un <em>widget</em> GtkList tiene su propia ventana para recibir -eventos y su propio color de fondo, que normalmente es blanco. -Como es un objeto derivado directamente de GtkContainer puede tratarse -utilizando la macro GTK_CONTAINER(List), ver el <em>widget</em> -GtkContainer para obtener más información. - -Debería familiarizarse con la utilización de un GList y con sus -funciones relacionadas <tt/g_list_*()/ para ser capaz de explotar el -<em>widget</em> GtkList hasta su límite. - -Sólo hay un campo dentro de la definición de la estructura del -<em>widget</em> GtkList que nos es de interés, y es: - -<tscreen><verb> -struct _GtkList -{ - ... - GList *selection; - guint selection_mode; - ... -}; -</verb></tscreen> - -El campo <tt/selection/ de un GtkList apunta a una lista enlazada de -todos los elementos que están actualmente seleccionados, o NULL si la -selección está vacia. Por lo tanto para saber quien es la actual -selección debemos leer el campo <tt/GTK_LIST()->selection/, pero no -modificarlo ya que los campos de los que está constituido GtkList -están controlados por las funciones gtk_list_*(). - -El <tt/selection_mode/ de la GtkList determina las posibilidades de -selección de una GtkList y por tanto los contenidos del campo -<tt/GTK_LIST()->selection/. El <tt/selection_mode/ puede tener uno de -los valores siguientes: - -<itemize> -<item> GTK_SELECTION_SINGLE - La selección es o NULL o contiene un -puntero a un GList con un solo elemento seleccionado. - -<item> GTK_SELECTION_BROWSE - La selección es NULL si la lista no -contiene <em>widgets</em> o si los que contiene no son sensibles, en -cualquier otro caso contiene un puntero GList a una estructura GList, -y contendrá por tanto un solo elemento. - -<item> GTK_SELECTION_MULTIPLE - La selección es NULL si no hay -elementos seleccionados o un puntero GList hacia el primer elemento -seleccionado. ("That in turn") apunta a una estructura GList para -el segundo elemento seleccionado y así. - -<item> GTK_SELECTION_EXTENDED - La selección siempre es NULL. -</itemize> - -El valor por defecto es GTK_SELECTION_MULTIPLE. - -<!-- ----------------------------------------------------------------- --> -<sect1> Señales -<p> -<tscreen><verb> -void selection_changed( GtkList *list ); -</verb></tscreen> - -Se invocará esta señal cuando cambie el campo <tt/selection/ de un -GtkList. Es decir, cuando un hijo de una GtkList se selecciona o -deselecciona. - -<tscreen><verb> -void select_child( GtkList *list, - GtkWidget *hijo); -</verb></tscreen> - -Se invoca esta señal cuando un hijo de la GtkList está siendo -seleccionado. Esto ocurre principalmente en llamadas a -<tt/gtk_list_select_item()/, a <tt/gtk_list_select_child()/, cuando se -pulsa algún botón y a veces se lanza indirectamente cuando se añade o -se elimina un hijo del GtkList. - -<tscreen><verb> -void unselect_child( GtkList *list, - GtkWidget *hijo ); -</verb></tscreen> - -Se invoca esta señal cuando un hijo del GtkList está siendo -deseleccionado. Esto ocurre principalmente cuando ocurre una llamada a -<tt/gtk_list_unselect_item()/, <tt/gtk_list_unselect_item()/, -pulsaciones de botón y a veces se lanza indirectamente cuando se añade -o se elimina algún hijo de la GtkList. - -<!-- ----------------------------------------------------------------- --> -<sect1> Funciones -<p> -<tscreen><verb> -guint gtk_list_get_type( void ); -</verb></tscreen> - -Devuelve el identificador de tipo `GtkList'. - -<tscreen><verb> -GtkWidget *gtk_list_new( void ); -</verb></tscreen> - -Crea un nuevo objeto GtkList. Se devuelve el nuevo <em/widget/ como un -puntero a un objeto GtkWidget. Se devuelve NULL en caso de producirse -algún fallo. - -<tscreen><verb> -void gtk_list_insert_items( GtkList *list, - GList *items, - gint posicion ); -</verb></tscreen> - -Introduce elementos en la lista, comenzando en la posición -<tt/posicion/. <tt/items/ es una lista doblemente enlazada donde cada -puntero de datos de cada nodo se supone que apunta a una nueva -GtkListItem (recien creada). Los nodos GList de <tt/items/ son -controlados por la lista. - -<tscreen><verb> -void gtk_list_append_items( GtkList *list, - GList *items); -</verb></tscreen> - -Introduce elementos tal y como lo hace <tt/gtk_list_insert_items()/, -pero los mete en el final de la lista. Los nodos GList de <tt/items/ -son controlados por la lista. - -<tscreen><verb> -void gtk_list_prepend_items( GtkList *list, - GList *items); -</verb></tscreen> - -Introduce elementos tal y como lo hace <tt/gtk_list_insert_items()/, -pero los mete al principio de la lista. Los nodos GList de <tt/items/ -son controlados por la lista. - -<tscreen><verb> -void gtk_list_remove_items( GtkList *list, - GList *items); -</verb></tscreen> - -Elimina elementos de la lista. <tt/items/ es una lista doblemente -enlazada donde cada puntero de datos de cada nodo se supone que apunta -a un hijo directo de la lista. El ejecutar o no -<tt/g_list_free(items)/ cuando la función termine de ejecutarse es -responsabilidad del que llama a la misma. Está bajo su responsabilidad -la destrucción de los elementos de la lista. - -<tscreen><verb> -void gtk_list_clear_items( GtkList *list, - gint start, - gint end ); -</verb></tscreen> - -Elimina y destruye los elementos de la lista. Esta operación afectará -a todos los <em/widgets/ que se encuentren en la lista y en el rango -especificado por <tt/start/ y <tt/end/. - -<tscreen><verb> -void gtk_list_select_item( GtkList *list, - gint item ); -</verb></tscreen> - -Invoca la señal <tt/select_child/ para el elemento especificado -mediante su posición actual en la lista. - -<tscreen><verb> -void gtk_list_unselect_item( GtkList *list, - gint item); -</verb></tscreen> - -Invoca la señal <tt/unselect_child/ para un elemento especificado -mediante su posición actual en la lista. - -<tscreen><verb> -void gtk_list_select_child( GtkList *list, - GtkWidget *hijo); -</verb></tscreen> - -Invoca la señal <tt/select_child/ para el hijo especificado. - -<tscreen><verb> -void gtk_list_unselect_child( GtkList *list, - GtkWidget *hijo); -</verb></tscreen> - -Invoca la señal <tt/unselect_child/ para el hijo especificado. - -<tscreen><verb> -gint gtk_list_child_position( GtkList *list, - GtkWidget *hijo); -</verb></tscreen> - -Devuelve la posición de <tt/hijo/ en la lista. Se devuelve «-1» en -caso de producirse algún error. - -<tscreen><verb> -void gtk_list_set_selection_mode( GtkList *list, - GtkSelectionMode mode ); -</verb></tscreen> - -Pone el modo de selección, que puede ser <tt/GTK_SELECTION_SINGLE/, -<tt/GTK_SELECTION_BROWSE/, <tt/GTK_SELECTION_MULTIPLE/ o -<tt/GTK_SELECTION_EXTENDED/. - -<tscreen><verb> -GtkList *GTK_LIST( gpointer obj ); -</verb></tscreen> - -Convierte un puntero general en `GtkList *'. Para más información *Note -Standard Macros::. - -<tscreen><verb> -GtkListClass *GTK_LIST_CLASS( gpointer class); -</verb></tscreen> - -Convierte un puntero general en `GtkListClass *'. Para más información -*Note Standard Macros::. - -<tscreen><verb> -gint GTK_IS_LIST( gpointer obj); -</verb></tscreen> - -Determina si un puntero general se refiere a un objeto `GtkList'. Para -más información, *Note Standard Macros::. - -<!-- ----------------------------------------------------------------- --> -<sect1> Ejemplo -<p> -A continuación tenemos un programa ejemplo que muestra los cambios de -la selección de un GtkList, y le deja «arrestar» elementos de la -lista en una prisión, seleccionándolos con el botón derecho del ratón. - -<tscreen><verb> -/* principio del ejemplo list list.c */ - -/* incluye los ficheros de cabecera de gtk+ - * incluye stdio.h, que necesitamos para la función printf() - */ -#include <gtk/gtk.h> -#include <stdio.h> - -/* ésta es nuestra cadena de identificación para almacenar datos en la - * lista de elementos - */ -const gchar *list_item_data_key="list_item_data"; - - -/* prototipos para los manejadores de señal que vamos a conectar con - * el widget GtkList - */ -static void sigh_print_selection (GtkWidget *gtklist, - gpointer func_data); -static void sigh_button_event (GtkWidget *gtklist, - GdkEventButton *event, - GtkWidget *frame); - - -/* función principal donde se establece el interface con el usuario */ - -gint main (int argc, gchar *argv[]) -{ - GtkWidget *separator; - GtkWidget *ventana; - GtkWidget *vbox; - GtkWidget *scrolled_window; - GtkWidget *frame; - GtkWidget *gtklist; - GtkWidget *boton; - GtkWidget *list_item; - GList *dlist; - guint i; - gchar buffer[64]; - - - /* inicializar gtk+ (y consecuentemente gdk) */ - - gtk_init(&argc, &argv); - - - /* crear una ventana donde meter todos los widgets y conectar - * gtk_main_quit() con el evento "destroy" de la ventana para - * poder controlar los eventos de cerrado de ventana del - * administrador de ventanas - */ - ventana=gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_title(GTK_WINDOW(ventana), "GtkList Example"); - gtk_signal_connect(GTK_OBJECT(ventana), - "destroy", - GTK_SIGNAL_FUNC(gtk_main_quit), - NULL); - - - /* dentro de la ventana necesitamos una caja para alinear los - * widgets verticalmente */ - vbox=gtk_vbox_new(FALSE, 5); - gtk_container_border_width(GTK_CONTAINER(vbox), 5); - gtk_container_add(GTK_CONTAINER(ventana), vbox); - gtk_widget_show(vbox); - - /* Ésta es la ventana con barras de desplazamiento donde meteremos - * el widget GtkList */ - 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); - - /* crear el widget GtkList - * conectar la función manipuladora de señal - * sigh_print_selection() a la señal "selection_changed" del - * GtkList para imprimir los elementos seleccionados cada vez que - * cambie la selección */ - 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); - - /* creamos una "Prisión" donde meteremos una lista de elementos ;) - */ - 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); - - /* conectamos el manipulador de señal sigh_button_event() al - * GtkList que manejará la lista de elementos "arrestados" - */ - gtk_signal_connect(GTK_OBJECT(gtklist), - "button_release_event", - GTK_SIGNAL_FUNC(sigh_button_event), - frame); - - /* crear un separador - */ - separator=gtk_hseparator_new(); - gtk_container_add(GTK_CONTAINER(vbox), separator); - gtk_widget_show(separator); - - /* crear finalmente un botón y conectar su señal "clicked" con la - * destrucción de la ventana - */ - boton=gtk_button_new_with_label("Close"); - gtk_container_add(GTK_CONTAINER(vbox), boton); - gtk_widget_show(boton); - gtk_signal_connect_object(GTK_OBJECT(boton), - "clicked", - GTK_SIGNAL_FUNC(gtk_widget_destroy), - GTK_OBJECT(ventana)); - - - /* ahora creamos 5 elementos de lista, teniendo cada uno su propia - * etiqueta y añadiéndolos a la GtkList mediante - * gtk_container_add() también consultaremos la cadena de texto de - * la etiqueta y la asociaremos con la list_item_data_key para - * cada elemento de la lista - */ - for (i=0; i<5; i++) { - GtkWidget *etiqueta; - gchar *string; - - sprintf(buffer, "ListItemContainer with Label #%d", i); - etiqueta=gtk_label_new(buffer); - list_item=gtk_list_item_new(); - gtk_container_add(GTK_CONTAINER(list_item), etiqueta); - gtk_widget_show(etiqueta); - gtk_container_add(GTK_CONTAINER(gtklist), list_item); - gtk_widget_show(list_item); - gtk_label_get(GTK_LABEL(etiqueta), &string); - gtk_object_set_data(GTK_OBJECT(list_item), - list_item_data_key, - string); - } - /* aquí, estamos creando otras 5 etiquetas, esta vez utilizaremos - * gtk_list_item_new_with_label() para la creación - * no podemos consultar la cadena de texto de la etiqueta ya que - * no tenemos el puntero de etiquetas y por tanto lo único que - * haremos será asociar el list_item_data_key de cada elemento de - * la lista con la misma cadena de texto. Para añadirlo a la lista - * de elementos los pondremos en lista doblemente enlazada - * (GList), y entonces los añadimos mediante una simple llamada a - * gtk_list_append_items() - * como utilizamos g_list_prepend() para poner los elementos en la - * lista doblemente enlazada, su orden será descendente (en vez de - * ascendente como cuando utilizamos g_list_append()) - */ - 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); - - /* finalmente queremos ver la ventana, ¿verdad? ;) - */ - gtk_widget_show(ventana); - - /* y nos metemos en el bucle de eventos de gtk - */ - gtk_main(); - - /* llegaremos aquí después de que se llame a gtk_main_quit(), lo - * que ocurre si se destruye la ventana - */ - return 0; -} - -/* éste es el manejador de señal que se conectó a los eventos de - * pulsar/soltar de los botones de la GtkList - */ -void -sigh_button_event (GtkWidget *gtklist, - GdkEventButton *event, - GtkWidget *frame) -{ - /* sólo hacemos algo si el tercer botón (el botón derecho) se - * levanta - */ - if (event->type==GDK_BUTTON_RELEASE && - event->button==3) { - GList *dlist, *free_list; - GtkWidget *new_prisoner; - - /* sacar la lista de elementos que están actualmente - * seleccionados y que serán nuestro próximos prisioneros ;) - */ - dlist=GTK_LIST(gtklist)->selection; - if (dlist) - new_prisoner=GTK_WIDGET(dlist->data); - else - new_prisoner=NULL; - - /* buscar por elementos de la lista ya encarcelados, los - * volveremos a poner en la lista, recordar que hay que - * eliminar la lista doblemente enlazada que devuelve - * gtk_container_children() - */ - 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); - - /* si tenemos un nuevo prisionero, lo eliminamos de la GtkList - * y lo ponemos en el marco "Prisión". Primero tenemos que - * deseleccionarlo - */ - 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); - } - } -} - -/* éste es el manipulador de señal que se llama si GtkList emite la - * señal "selection_changed" - */ -void -sigh_print_selection (GtkWidget *gtklist, - gpointer func_data) -{ - GList *dlist; - - /* sacar la lista doblemente enlazada de los elementos - * seleccionados en GtkList, ¡recuerde que hay que tratarla como - * de solo lectura! - */ - dlist=GTK_LIST(gtklist)->selection; - - /* si no hay elementos seleccionados no queda nada por hacer - * excepto informar al usuario - */ - if (!dlist) { - g_print("Selection cleared\n"); - return; - } - /* Bien, conseguimos una selección y la imprimimos - */ - g_print("The selection is a "); - - /* obtenemos la lista de elementos de la lista doblemente enlazada - * y entonces consultamos los datos asociados con la - * list_item_data_key que acabamos de imprimir - */ - 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"); -} -/* fin del ejemplo */ -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1> El <em/widget/ GtkListItem -<p> -El <em/widget/ GtkListItem está diseñado para comportarse como un -contenedor que tiene un hijo, proporcionando funciones para la -selección/deselección justo como las necesitan los hijos del -<em/widget/ GtkList. - -Un GtkListItem tiene su propia ventana para recibir eventos y tiene su -propio color de fondo, que normalmente es blanco. - -Como está derivado directamente de un GtkItem, puede tratarse como tal -utilizando la macro GTK_ITEM(ListItem), ver el <em/widget/ GtkItem -para más detalles. Normalmente un GtkListItem sólo tiene una etiqueta -para identificar, por ejemplo, el nombre de un fichero dentro de una -GtkList -- por lo tanto se proporciona la función -<tt/gtk_list_item_new_with_label()/. Se puede conseguir el mismo -efecto creando un GtkLabel, poniendo su alineación a <tt/xalign=0/ e -<tt/yalign=0.5/ y seguido de una adición al contenedor GtkListItem. - -Nadie le obliga a meter un GtkLabel en un GtkListItem, puede meter un -GtkVBox o un GtkArrow, etc... - -<!-- ----------------------------------------------------------------- --> -<sect1> Señales -<p> -Un GtkListItem no crea por sí misma nuevas señales, pero hereda las -señales de un GtkItem. Para más información *Note GtkItem::. - -<!-- ----------------------------------------------------------------- --> -<sect1> Funciones -<p> -<tscreen><verb> -guint gtk_list_item_get_type( void ); -</verb></tscreen> - -Devuelve el identificador de tipo `GtkListItem'. - -<tscreen><verb> -GtkWidget *gtk_list_item_new( void ); -</verb></tscreen> - -Crea un nuevo objeto GtkListItem. Se devuelve el nuevo <em/widget/ -como un puntero a un objeto GtkWidget. Se devuelve NULL en caso de -producirse algún error. - -<tscreen><verb> -GtkWidget *gtk_list_item_new_with_label( gchar *etiqueta ); -</verb></tscreen> - -Crea un nuevo objeto GtkListItem, con una sola GtkLabel como único -hijo. Se devuelve el nuevo <em/widget/ como un puntero a un objeto -GtkWidget. Se devuelve NULL en caso de producirse algún error. - -<tscreen><verb> -void gtk_list_item_select( GtkListItem *list_item ); -</verb></tscreen> - -Esta función es, básicamente, un recubrimiento de una llamada a -<tt/gtk_item_select (GTK_ITEM (list_item))/, y emitirá la señal -<tt/select/. Para más información *Note GtkItem::. - -<tscreen><verb> -void gtk_list_item_deselect( GtkListItem *list_item ); -</verb></tscreen> - -Esta función es, básicamente, un recubrimiento de una llamada a -<tt/gtk_item_deselect (GTK_ITEM (list_item))/, y emitirá la señal -<tt/deselect/. Para más información *Note GtkItem::. - -<tscreen><verb> -GtkListItem *GTK_LIST_ITEM( gpointer obj ); -</verb></tscreen> - -Convierte un puntero general a `GtkListItem *'. Para más información -*Note Standard Macros::. - -<tscreen><verb> -GtkListItemClass *GTK_LIST_ITEM_CLASS( gpointer class ); -</verb></tscreen> - -Convierte un puntero general a `GtkListItemClass *'. Para más -información *Note Standard Macros::. - -<tscreen><verb> -gint GTK_IS_LIST_ITEM( gpointer obj ); -</verb></tscreen> - -Determina si un puntero general se refiere a un puntero -`GtkListItem'. Para más información *Note Standard Macros::. - -<!-- ----------------------------------------------------------------- --> -<sect1> Ejemplo -<p> -Para ver un ejemplo de todo esto, mire el de GtkList, que también -cubre la utilización un GtkListItem. - -</article> diff --git a/docs/tutorial/gtk_tut_fr.sgml b/docs/tutorial/gtk_tut_fr.sgml deleted file mode 100644 index efb75e8c0e..0000000000 --- a/docs/tutorial/gtk_tut_fr.sgml +++ /dev/null @@ -1,8600 +0,0 @@ -<!doctype linuxdoc system> -<article> -<title>Didacticiel -<author>Ian Main, <tt><htmlurl url="mailto:slow@intergate.bc.ca" - name="slow@intergate.bc.ca"></tt> -<date>January 24, 1998. - - -<sect>Introduction -<p> -GTK (GIMP Toolkit) a été d'abord développé pour être une boîte à -outils pour GIMP (General Image Manipulation Program). GTK est -construit sur GDK (GIMP Drawing Kit) qui est, avant tout, une -encapsulation des fonctions Xlib. On l'appelle « GIMP toolkit » car il -fut créé pour développer GIMP, mais il est désormais utilisé dans -plusieurs projets de logiciels libres. Les auteurs sont : -<itemize> -<item> Peter Mattis <tt><htmlurl url="mailto:petm@xcf.berkeley.edu" - name="petm@xcf.berkeley.edu"></tt> -<item> Spencer Kimball <tt><htmlurl url="mailto:spencer@xcf.berkeley.edu" - name="spencer@xcf.berkeley.edu"></tt> -<item> Josh MacDonald <tt><htmlurl url="mailto:jmacd@xcf.berkeley.edu" - name="jmacd@xcf.berkeley.edu"></tt> -</itemize> - -<p> -GTK est essentiellement une interface de programmation (API) orientée -objet. Bien qu'il soit entièrement écrit en C, il est implanté en -utilisant la notion de classes et de fonctions de rappel (pointeurs -de fonctions). -<p> -Un troisième composant, appelé glib, remplace certains appels -standard et comporte quelques fonctions supplémentaires pour gérer les -listes chaînées, etc. Les fonctions de remplacement sont utilisées -pour accroître la portabilité de GTK car certaines de ces fonctions, -comme g_strerror(), ne sont pas disponibles ou ne sont pas standard -sur d'autres Unix. D'autres comportent des améliorations par rapport -aux versions de la libc : g_malloc(), par exemple, facilite le -débuggage.<p> - -Ce didacticiel tente de décrire du mieux possible GTK, mais il n'est pas -exhaustif. Il suppose une bonne connaissance du langage C, et de la façon de -créer des programmes C. Il serait très précieux au lecteur d'avoir déjà une -expérience de la programmation X, mais cela n'est pas nécessaire. Si -l'apprentissage de GTK marque vos débuts dans l'approche des widgets, n'hésitez -pas à faire des commentaires sur ce didacticiel et sur les problèmes qu'il vous -a posé. Il y a aussi une API C++ pour GTK (GTK--), si vous préférez utiliser -ce langage, consultez plutôt la documentation qui la concerne. Une -encapsulation en Objective C et des liaisons Guile sont également disponibles, -mais ne seront pas abordées ici. -<p> -J'apprécierais beaucoup avoir un écho des problèmes que vous avez -rencontré pour apprendre GTK à partir de ce document. De plus, toute -suggestion sur son amélioration est la bienvenue. - -<sect>Bien débuter -<p> -La première chose à faire est, bien sûr, de récupérer les sources de -GTK et de les installer. Vous pouvez en obtenir la dernière version -sur <tt/ftp.gimp.org/ dans le répertoire <tt>/pub/gtk</tt>. D'autres -sources d'informations se trouvent sur -<tt>http://www.gimp.org/gtk</tt>. GTK utilise <em/autoconf/ de GNU -pour se configurer. Lorsque vous l'aurez détarré, tapez -<em>./configure --help</em> pour consulter la liste des options. -<p> -Pour commencer notre introduction à GTK, nous débuterons avec le -programme le plus simple qui soit. Celui-ci créera une fenêtre de -200x200 pixels et ne pourra se terminer qu'en le tuant à partir du -shell. - -<tscreen><verb> -#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; -} -</verb></tscreen> - -Tous les programmes inclueront évidemment le fichier -<tt>gtk/gtk.h</tt> qui déclare les variables, fonctions, structures, -etc. qui seront utilisées par votre application GTK. -<p> -La ligne  : - -<tscreen><verb> -gtk_init (&argc, &argv); -</verb></tscreen> - -appelle la fonction <em/gtk_init(gint *argc, gchar ***argv)/ qui sera -appelée dans toutes les applications GTK. Cette fonction configure -certaines choses pour nous, comme l'aspect visuel et les couleurs par -défaut, puis appelle <em/gdk_init(gint *argc, gchar ***argv)/. Cette -dernière initialise la bibliothèque pour qu'elle puisse être utilisée, -configure les gestionnaires de signaux par défaut et vérifie les -paramètres passés à notre application via la ligne de commande en -recherchant l'un des suivants : - -<itemize> -<item> <tt/--display/ -<item> <tt/--debug-level/ -<item> <tt/--no-xshm/ -<item> <tt/--sync/ -<item> <tt/--show-events/ -<item> <tt/--no-show-events/ -</itemize> -<p> -Elle les supprime alors de la liste des paramètres, en laissant tout -ce qu'elle ne reconnaît pas pour que notre application l'analyse ou -l'ignore. Ceci crée un ensemble de paramètres standards acceptés par -toutes les applications GTK. -<p> -Les deux lignes de code suivantes créent et affichent une fenêtre. - -<tscreen><verb> - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_widget_show (window); -</verb></tscreen> - -Le paramètre <tt/GTK_WINDOW_TOPLEVEL/ précise que l'on veut que la -fenêtre créée suive l'aspect et le placement définis par le -gestionnaire de fenêtres. Plutôt que de créer une fenêtre de 0x0, une -fenêtre sans fenêtre fille est de 200x200 par défaut : on peut -ainsi la manipuler facilement. -<p> -La fonction <em/gtk_widget_show()/ informe GTK que l'on a configuré -le widget et qu'il peut l'afficher. -<p> -La ligne suivante lance la boucle principale de traitement de GTK. - -<tscreen><verb> -gtk_main (); -</verb></tscreen> - -<em/gtk_main()/ est un autre appel que vous verrez dans toute -application GTK. Lorsque le contrôle atteind ce point, GTK se met en -attente d'événements X (click sur un bouton, ou appui d'une touche, par -exemple), de timeouts ou d'entrées-sorties fichier. Dans notre exemple -simple, cependant, les événements sont ignorés. - - -<sect1>« Bonjour tout le monde » en GTK -<p> -OK, écrivons un programme avec un widget (bouton). C'est le classique « Bonjour tout le monde » à la sauce GTK. - -<tscreen><verb> - -#include <gtk/gtk.h> - - /* fonction de rappel. Dans cet exemple, les paramètres sont ignorés... - * Les fonctions de rappel sont détaillées plus loin. */ - -void hello (GtkWidget *widget, gpointer data) -{ - g_print ("Bonjour tout le monde.\n"); -} - -gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data) -{ - g_print ("le signal delete_event est survenu.\n"); - - /* Si l'on renvoit TRUE dans le gestionnaire du signal "delete_event", - * GTK émettra le signal "destroy". Retourner FALSE signifie que l'on - * ne veut pas que la fenêtre soit détruite. - * Utilisé pour faire apparaître des boîtes de dialogue du type - * « Êtes-vous sûr de vouloir quitter ? » */ - - /* Remplacez FALSE par TRUE et la fenêtre principale sera détruite par - * un signal « delete_event ». */ - - return (FALSE); -} - -/* Autre fonction de rappel */ - -void destroy (GtkWidget *widget, gpointer data) -{ - gtk_main_quit (); -} - -int main (int argc, char *argv[]) -{ - /* GtkWidget est le type pour déclarer les widgets. */ - - GtkWidget *window; - GtkWidget *button; - - /* Cette fonction est appelée dans toutes les applications GTK. - * Les paramètres passés en ligne de commande sont analysés et - * retournés à l'application. */ - - gtk_init (&argc, &argv); - - /* Création d'une nouvelle fenêtre. */ - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - - /* Lorsque la fenêtre reçoit le signal "delete_event" - * (envoyé par le gestionnaire de fenêtres en utilisant l'option - * « close » ou la barre de titre), on lui demande d'appeler la - * fonction delete_event() définie plus haut. La donnée passée en - * paramètre à la fonction de rappel est NULL et est ignoré dans le - * rappel. */ - - gtk_signal_connect (GTK_OBJECT (window), "delete_event", - GTK_SIGNAL_FUNC (delete_event), NULL); - - /* Ici, on connecte l'évenement "destroy" à un gestionnaire de signal. - * Cet événement arrive lorsqu'on appelle gtk_widget_destroy() sur la - * fenêtre, ou si l'on retourne TRUE dans le rappel "delete_event". */ - - gtk_signal_connect (GTK_OBJECT (window), "destroy", - GTK_SIGNAL_FUNC (destroy), NULL); - - /* Configuration de la largeur du contour de la fenêtre. */ - - gtk_container_border_width (GTK_CONTAINER (window), 10); - - /* Création d'un nouveau bouton portant le label - * "Bonjour tout le monde". */ - - button = gtk_button_new_with_label ("Bonjour tout le monde"); - - /* Quand le bouton recevra le signal "clicked", il appellera la - * fonction hello() définie plus haut en lui passant NULL en paramètre. */ - - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (hello), NULL); - - /* Ceci provoquera la destruction de la fenêtre par appel de la - * fonction gtk_widget_destroy(window) lors du signal "clicked". - * Le signal de destruction pourrait venir de là, ou du - * gestionnaire de fenêtres. */ - - gtk_signal_connect_object (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (gtk_widget_destroy), - GTK_OBJECT (window)); - - /* Insertion du bouton dans la fenêtre (container gtk). */ - - gtk_container_add (GTK_CONTAINER (window), button); - - /* L'étape finale consiste à afficher ce nouveau widget... */ - - gtk_widget_show (button); - - /* ... et la fenêtre. */ - - gtk_widget_show (window); - - /* Toutes les applications GTK doivent avoir un gtk_main(). - * Le déroulement du programme se termine là et attend qu'un - * événement survienne (touche pressée ou événement souris). */ - - gtk_main (); - - return 0; -} -</verb></tscreen> - -<sect1>Compilation de « Bonjour tout le monde » -<p> -Supposons que vous avez sauvegardé le code précédent dans un fichier -nommé <em/bonjour.c/, pour le compiler tapez la commande -suivante : - -<tscreen><verb> -gcc -Wall -g bonjour.c -o bonjour_monde -L/usr/X11R6/lib \ - -lgtk -lgdk -lglib -lXext -lX11 -lm -</verb></tscreen> -<p> -Les bibliothèques invoquées ci-dessus doivent toutes être dans vos -chemins de recherche par défaut, sinon, ajoutez <tt/-L<library -directory>/ pour que <em/gcc/ recherche dans ces répertoires les -bibliothèques nécessaires. Sur mon système Debian GNU/Linux, par exemple, -je dois ajouter <tt>-L/usr/X11R6/lib</> pour qu'il trouve les -bibliothèques X11 (NdT : et c'est pareil sur mon système Red Hat -Linux...). -<p> -L'ordre des bibliothèques est important. L'éditeur de liens doit -connaître les fonctions d'une bibliothèque dont il a besoin avant de -les traiter. -<p> -Si vous compilez en utilisant des bibliothèques statiques, l'ordre -dans lequel vous listez les bibliothèques devient très -important. L'exemple donné ci-dessus devrait fonctionner dans tous les -cas. -<p> -Les bibliothèques que l'on utilise sont : -<itemize> -<item>La bibliothèque glib (<tt/-lglib/), qui contient diverses -fonctions. Seule <em/g_print()/ est utilisée dans cet exemple. GTK est -construit au dessus de <em/glib/ et vous aurez donc toujours besoin de -celle-ci. Voir la section concernant <ref id="sec_glib" name="glib"> -pour plus de détails. - -<item>La bibliothèque GDK (<tt/-lgdk/), l'enveloppe de Xlib. - -<item>La bibliothèque GTK (<tt/-lgtk/), la bibliothèque des widgets, -construite au dessus de GDK. - -<item>La bibliothèque Xlib (<tt/-lX11/ utilisée par GDK. - -<item>La bibliothèque Xext (<tt/-lXext/). Cette dernière contient le -code pour les pixmaps en mémoire partagée et les autres extensions X. - -<item>La bibliothèque mathématique (<tt/-lm/). Elle est utilisée pour -différentes raisons par GTK. -</itemize> - -<sect1>Théorie des signaux et des rappels -<p> -Avant de voir en détail le programme « Bonjour tout le monde », nous -parlerons d'abord des événements et des fonctions de rappel. GTK est -dirigé par les événements, ce qui signifie qu'il restera inactif dans -<em/gtk_main/ jusqu'à ce qu'un événement survienne et que le contrôle -soit passé à la fonction appropriée. -<p> -Ce passage du contrôle est réalisé en utilisant le concept de « signal -». Lorsqu'un événement survient, comme l'appui sur un bouton, le -signal approprié sera « émis » par le widget qui a été pressé. C'est -de cette façon que GTK réalise la plupart de son travail. Pour qu'un -bouton réalise une action, on configure un gestionnaire de signal pour -capturer ces signaux et appeler la fonction adéquate. Ceci est fait -en utilisant une fonction comme : - -<tscreen><verb> -gint gtk_signal_connect (GtkObject *object, - gchar *name, - GtkSignalFunc func, - gpointer func_data); -</verb></tscreen> -<p> -Où le premier paramètre est le widget qui émettra le signal, et le -deuxième est le nom du signal que l'on souhaite intercepter. Le -troisième paramètre est la fonction que l'on veut appeler quand le -signal est capturé, et le quatrième sont les données que l'on souhaite -passer à cette fonction. -<p> -La fonction spécifiée par le troisième paramètre s'appelle une « -fonction de rappel » et doit être de la forme : - -<tscreen><verb> -void callback_func(GtkWidget *widget, gpointer *callback_data); -</verb></tscreen> -<p> -Où le premier paramètre sera un pointeur vers le widget qui a émis le -signal, et le second un pointeur vers les données passées par le -dernier paramètre de la fonction <em/gtk_signal_connect()/ décrite -plus haut. -<p> -Un autre appel utilisé dans l'exemple « Bonjour tout le monde » est : - -<tscreen><verb> -gint gtk_signal_connect_object (GtkObject *object, - gchar *name, - GtkSignalFunc func, - GtkObject *slot_object); -</verb></tscreen> -<p> -<em/gtk_signal_connect_object()/ est la même chose que -<em/gtk_signal_connect()/ sauf que la fonction de rappel utilise un -seul paramètre : un pointeur vers un objet GTK. Lorsqu'on utilise -cette fonction pour connecter des signaux, le rappel doit être de -cette forme : - -<tscreen><verb> -void callback_func (GtkObject *object); -</verb></tscreen> -<p> -Où l'objet est d'ordinaire un widget. En général, on ne configure pas -de rappels pour <em/gtk_signal_connect_object/. D'habitude, ceux-ci sont -utilisés pour appeler une fonction GTK acceptant un simple widget ou -objet comme paramètre, comme dans notre exemple. - -La raison pour laquelle il y a deux fonctions pour connecter les -signaux est simplement de permettre aux fonctions de rappel d'avoir un -nombre différent de paramètres. De nombreuses fonctions de la -bibliothèque GTK n'acceptent qu'un simple pointeur vers un -<em/GtkWidget/ comme paramètre et vous pouvez donc utiliser -<em/gtk_signal_connect_object()/ pour celles-ci, tandis que pour vos -fonctions vous pouvez avoir besoin d'avoir de fournir plus de données -aux fonctions de rappel. - -<sect1>« Bonjour tout le monde » pas à pas -<p> -Maintenant que nous connaissons la théorie, clarifions un peu en progressant à travers le programme « Bonjour tout le monde ». -<p> -Voici la fonction de rappel appelée lorsque le bouton est « clicked -». Dans notre exemple, on ignore le widget et les données mais il -n'est pas difficile de faire quelque chose avec. Le prochain exemple -utilisera le paramètre des données pour nous dire quel bouton a été -pressé. - -<tscreen><verb> -void hello (GtkWidget *widget, gpointer *data) -{ - g_print ("Bonjour tout le monde\n"); -} -</verb></tscreen> - -<p> -Cette fonction de rappel est un peu spéciale. L'événement -"delete_event" survient lorsque le gestionnaire de fenêtres l'envoie à -l'application. On doit choisir ce qu'il faut faire de ces -événements. On peut les ignorer, leur donner une réponse, ou -simplement quitter l'application. - -La valeur que l'on retourne dans cette fonction de rappel permet à GTK -de savoir ce qu'il a à faire. En retournant FALSE, on l'informe que -l'on ne veut pas que le signal "destroy" soit émis, afin de laisser -notre application tourner. En retournant TRUE, on lui demande -d'émettre "destroy" qui appellera à son tour notre gestionnaire du -signal "destroy". - -<tscreen><verb> -gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data) -{ - g_print ("le signal delete_event est survenu.\n"); - - return (FALSE); -} -</verb></tscreen> - -<p> -Voici une autre fonction de rappel qui ne fait que quitter -l'application en appelant <em/gtk_main_quit()/. Il n'y a pas grand -chose de plus à dire car elle est plutôt triviale : - -<tscreen><verb> -void destroy (GtkWidget *widget, gpointer *data) -{ - gtk_main_quit (); -} -</verb></tscreen> -<p> -Je suppose que vous connaissez la fonction <em/main()/... oui, comme -les autres programmes C, toutes les applications GTK en ont une. - -<tscreen><verb> -int main (int argc, char *argv[]) -{ -</verb></tscreen> -<p> -La partie qui suit déclare deux pointeurs sur des structures de type -<em/GtkWidget/. Ceux-ci sont utilisés plus loin pour créer une -fenêtre et un bouton. - -<tscreen><verb> - GtkWidget *window; - GtkWidget *button; -</verb></tscreen> -<p> -Et revoici notre <em/gtk_init/. Comme précédemment, il initialise le toolkit -et analyse les paramètres de la ligne de commande. Il supprime chaque -paramètre reconnu de la liste et modifie <em/argc/ et <em/argv/ pour -faire comme si ces paramètres n'avaient jamais existé, laissant notre -application analyser les paramètres restants. - -<tscreen><verb> - gtk_init (&argc, &argv); -</verb></tscreen> -<p> -Création d'une nouvelle fenêtre. C'est plutôt classique. La mémoire -est allouée pour une structure <em/GtkWidget/ et <em/window/ pointe -donc sur celle-ci. Cela configure une nouvelle fenêtre, mais celle-ci -ne sera pas affichée tant que l'on n'a pas appelé -<em/gtk_widget_show(window)/ vers la fin de notre programme. - -<tscreen><verb> - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); -</verb></tscreen> -<p> -Voici maintenant un exemple de connexion d'un gestionnaire de signal à -un objet : la fenêtre. Le signal "destroy" est capturé. Il est -émis lorsqu'on utilise le gestionnaire de fenêtres pour tuer la -fenêtre (et que l'on retourne TRUE dans le gestionnaire -"delete_event"), ou lorsqu'on utilise l'appel -<em/gtk_widget_destroy()/ en lui passant le widget <em/window/ comme -objet à détruire. Ici, on appelle juste la fonction <em/destroy()/ -définie ci-dessus avec le paramètre NULL, ce qui quitte GTK pour -nous. -<p> -<tt/GTK_OBJECT/ et <tt/GTK_SIGNAL_FUNC/ sont des macros qui réalisent -les conversions et les vérifications de types pour nous. Elles rendent -aussi le code plus lisible. - -<tscreen><verb> - gtk_signal_connect (GTK_OBJECT (window), "destroy", - GTK_SIGNAL_FUNC (destroy), NULL); -</verb></tscreen> -<p> -La fonction suivante sert à configurer un attribut d'un objet -container. Elle configure simplement la fenêtre pour qu'elle ait une -zone vide autour d'elle de 10 pixels de large où aucun widget ne -pourra se trouver. Il existe d'autres fonctions similaires que nous -verrons dans la section sur la -<ref id="sec_setting_widget_attributes" -name="Configuration des attributs des widgets"> -<p> -À nouveau, <tt/GTK_CONTAINER/ est une macro réalisant la conversion de type. -<tscreen><verb> - gtk_container_border_width (GTK_CONTAINER (window), 10); -</verb></tscreen> -<p> -Cet appel crée un nouveau bouton. Il alloue l'espace mémoire pour une -nouvelle structure GtkWidget, l'initialise et fait pointer <em/button/ -vers elle. Ce bouton portera le label « Bonjour tout le monde » -lorsqu'il sera affiché. - -<tscreen><verb> - button = gtk_button_new_with_label ("Bonjour tout le monde"); -</verb></tscreen> -<p> -Maintenant, prenons ce bouton et faisons lui faire quelque chose -d'utile. On lui attache un gestionnaire de signal pour que, lorsqu'il -émettra le signal "clicked", notre fonction <em/hello()/ soit -appelée. On ignore les paramètres et on ne passe donc que la valeur -NULL à la fonction de rappel <em/hello()/. Évidemment, le signal -"clicked" est émis lorsqu'on clique sur le bouton avec la souris. - -<tscreen><verb> - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (hello), NULL); -</verb></tscreen> -<p> -On utilisera aussi ce bouton pour quitter notre programme, ce qui -permettra d'illustrer la façon dont le signal "destroy" peut venir -soit du gestionnaire de fenêtres, soit de notre programme. Quand le -bouton est "clicked" comme cela est décrit plus haut, il appelle -d'abord la fonction de rappel <em/hello()/ puis celle-ci dans l'ordre -dans lequel elles sont configurées. On peut avoir autant de fonctions -de rappel que l'on désire, elles seront exécutées selon leur ordre de -connexion. Puisque la fonction <em/gtk_widget_destroy()/ n'accepte que -<em/GtkWidget *widget/ comme paramètre, on utilise ici la fonction -<em/gtk_signal_connect_object()/ à la place de -<em/gtk_signal_connect()/. - -<tscreen><verb> - gtk_signal_connect_object (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (gtk_widget_destroy), - GTK_OBJECT (window)); -</verb></tscreen> -<p> -Voici un appel de placement, qui sera expliqué en détail plus tard, -mais qui est plutôt facile à comprendre. Il indique simplement à GTK -que le bouton doit être placé dans la fenêtre où il s'affichera. - -<tscreen><verb> gtk_container_add (GTK_CONTAINER (window), button); -</verb></tscreen> -<p> -Maintenant, nous avons tout configuré comme on le souhaitait : -les gestionnaires de signaux sont en place et le bouton est mis dans -la fenêtre où il doit se trouver. On demande alors à GTK de « montrer -» les widgets à l'écran. Le widget <em/window/ est affiché en dernier -afin que la fenêtre entière surgisse d'un coup plutôt que voir d'abord -la fenêtre s'afficher puis ensuite le bouton apparaître à -l'intérieur. Il faut dire qu'avec des exemples simples comme celui-ci, -vous ne ferez pas la différence. -<tscreen><verb> - gtk_widget_show(button); - - gtk_widget_show (window); -</verb></tscreen> -<p> -Bien sûr, on appelle <em/gtk_main()/ qui attendra les événements -venant du serveur X et demandera aux widgets d'émettre les signaux -lorsque ces événements surviendront. -<tscreen><verb> - gtk_main (); -</verb></tscreen> -Enfin, le <em/return/ final. Il est exécuté lorsque <em/gtk_quit()/ est appelé. -<tscreen><verb> - return 0; -</verb></tscreen> -<p> -Lorsque l'on clique sur un bouton GTK, le widget émet un -signal "clicked". Afin de pouvoir utiliser cette information, notre -programme configure un gestionnaire pour capturer ce signal. Ce -gestionnaire appelle la fonction de notre choix. Dans notre exemple, -lorsque le bouton que l'on a créé est "clicked", la fonction -<em/hello()/ est appelée avec le paramètre NULL, puis le gestionnaire -suivant de ce signal est à son tour appelé. Il appelle la fonction -<em/gtk_widget_destroy()/ en lui passant le widget <em/window/ comme -paramètre, ce qui provoque la destruction de celui-ci. Ceci -force la fenêtre à envoyer un signal "destroy", qui est capturé à son -tour et appelle notre fonction de rappel <em/destroy()/ qui ferme -simplement GTK. -<p> -Une autre façon de procéder consiste à utiliser le gestionnaire de -fenêtres pour détruire la fenêtre. Cela provoquera l'émission du -signal "delete_event" qui sera pris en charge par notre gestionnaire -<em/delete_event()/. S'il retourne FALSE, la fenêtre restera telle -quelle et rien ne se passera. Retourner TRUE forcera GTK à émettre -le signal "destroy" qui, bien sûr, appelera la fonction de rappel -<em/destroy()/ provoquant la sortie du GTK. <p> -On remarquera que ces signaux ne sont pas les mêmes que les signaux -systèmes Unix et ne sont pas implantés en utilisant ceux-ci, bien que -la terminologie employée soit presque identique. - - -<sect>Continuons -<p> -<sect1>Types de données -<p> -Vous avez probablement noté certaines choses qui nécessitent des -explications dans les exemples précédents. les <em/gint/, <em/gchar/, -etc. que vous avez pu voir sont des redéfinitions de <em/int/ et -<em/char/, respectivement. Leur raison d'être est de s'affranchir des -dépendances ennuyeuses concernant la taille des types de données -simples lorsqu'on réalise des calculs. Un bon exemple est <em/gint32/ -qui désignera un entier codé sur 32 bits pour toutes les plateformes, -que ce soit une station Alpha 64 bits ou un PC i386 32 bits. Les -redéfinitions de type sont très simples et intuitives. Elles sont -toutes décrites dans le fichier <em>glib/glib.h</em> (qui est inclus -par <em/gtk.h/). -<p> -On notera aussi la possibilité d'utiliser un <em/GtkWidget/ lorsque la -fonction attend un <em/GtkObject/. GTK possède une architecture -orientée objet, et un widget est un objet. - -<sect1>Compléments sur les gestionnaires de signaux -<p> -Regardons à nouveau la déclaration de <em/gtk_signal_connect/. - -<tscreen><verb> -gint gtk_signal_connect (GtkObject *object, gchar *name, - GtkSignalFunc func, gpointer func_data); -</verb></tscreen> - -Vous avez remarqué que le valeur de retour est de type <em/gint/ ? Il -s'agit d'un marqueur qui identifie votre fonction de rappel. Comme on -le disait plus haut, on peut avoir autant de fonctions de rappel que -l'on a besoin, par signal et par objet, et chacune sera exécutée à son -tour, dans l'ordre dans lequel elle a été attachée. Ce marqueur vous -permet d'ôter ce rappel de la liste en faisant &;: - -<tscreen><verb> - void gtk_signal_disconnect (GtkObject *object, gint id); -</verb></tscreen> - -Ainsi, en passant le widget dont on veut supprimer le gestionnaire et -le marqueur ou identificateur retourné par l'une des fonctions -<em/signal_connect/, on peut déconnecter un gestionnaire de signal. -<p> -Une autre fonction permettant de supprimer tous les gestionnaires de -signaux pour un objet est : - -<tscreen><verb> - gtk_signal_handlers_destroy (GtkObject *object); -</verb></tscreen> -<p> -Cet appel n'a pas trop besoin d'explications. Il ôte simplement tous -les gestionnaires de signaux de l'objet passé en paramètre. - - -<sect1>Un « Bonjour tout le monde » amélioré -<p> -Étudions une version légèrement améliorée avec de meilleurs exemples -de fonctions de rappel. Ceci permettra aussi d'introduire le sujet -suivant : le placement des wigdets. - -<tscreen><verb> -#include <gtk/gtk.h> - -/* Notre nouveau rappel amélioré. La donnée passée à cette fonction est - * imprimée sur stdout. */ - -void rappel (GtkWidget *widget, gpointer *data) -{ - g_print ("Re-Bonjour - %s a été pressé\n", (char *) data); -} - -/* Un autre rappel */ - -void delete_event (GtkWidget *widget, GdkEvent *event, gpointer *data) -{ - gtk_main_quit (); -} - -int main (int argc, char *argv[]) -{ - /* GtkWidget est le type pour déclarer les widgets */ - - GtkWidget *window; - GtkWidget *button; - GtkWidget *box1; - - /* Cette fonction est appelée dans toutes les applications GTK. - * Les paramètre passés en ligne de commande sont analysés et - * retournés à l'application. */ - - gtk_init (&argc, &argv); - - /* Création d'une nouvelle fenêtre. */ - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - - /* Nouvel appel qui intitule notre nouvelle fenêtre - * "Salut les boutons !" */ - - gtk_window_set_title (GTK_WINDOW (window), "Salut les boutons !"); - - /* Configuration d'un gestionnaire pour "delete_event" afin de - * quitter immédiatement GTK. */ - - gtk_signal_connect (GTK_OBJECT (window), "delete_event", - GTK_SIGNAL_FUNC (delete_event), NULL); - - - /* Configuration de la largeur du contour de la fenêtre. */ - - gtk_container_border_width (GTK_CONTAINER (window), 10); - - /* Création d'une boîte pour y placer les widgets. - * Ceci est décrit en détails plus loin dans la section - * « placement ». La boîte n'est pas matérialisée, elle est juste - * utilisée comme moyen d'arranger les widgets. */ - - box1 = gtk_hbox_new(FALSE, 0); - - /* On met la boîte dans la fenêtre principale. */ - - gtk_container_add (GTK_CONTAINER (window), box1); - - /* On crée un nouveau bouton portant le label « Bouton 1 ». */ - - button = gtk_button_new_with_label ("Bouton 1"); - - /* Lorsque le bouton est cliqué, on appelle la fonction « rappel » - * avec un pointeur sur la chaîne « Bouton 1 » comme paramètre. */ - - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (rappel), (gpointer) "Bouton 1"); - - /* Au lieu d'utiliser gtk_container_add, on place ce bouton dans - * la boîte invisible qui a été placée dans la fenêtre. */ - - gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0); - - /* N'oubliez jamais cette étape qui indique à GTK que la configuration - * de ce bouton est terminée et qu'il peut être affiché. */ - - gtk_widget_show(button); - - /* On fait la même chose pour créer un deuxième bouton. */ - - button = gtk_button_new_with_label ("Bouton 2"); - - /* On appelle la même fonction de rappel avec un paramètre différent, - * un pointeur sur la chaîne « Bouton 2 ». */ - - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (rappel), (gpointer) "Bouton 2"); - - gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0); - - /* L'ordre dans lequel on affiche les boutons n'est pas vraiment - * important, mais il est préférable d'afficher la fenêtre en dernier - * pour qu'elle surgisse d'un coup. */ - - gtk_widget_show(button); - - gtk_widget_show(box1); - - gtk_widget_show (window); - - /* Le reste est dans gtk_main et on attend que la fête commence ! */ - - gtk_main (); - - return 0; -} -</verb></tscreen> -<p> -Compilez ce programme en utilisant les mêmes paramètres que pour -l'exemple précédent. Vous remarquerez que, maintenant, il est plus -difficile de quitter le programme : vous devez utiliser le -gestionnaire de fenêtres ou une commande shell pour le détruire. Un -bon exercice pour le lecteur serait d'insérer un troisième bouton « -Quitter » qui permettrait de sortir du programme. Vous pouvez aussi -jouer avec les options de <em/gtk_box_pack_start()/ en lisant la -section suivante. Essayez de redimensionner la fenêtre, et observez -son comportement. -<p> -Juste une remarque : il existe une autre constante utilisable -avec <em/gtk_window_new()/ - GTK_WINDOW_DIALOG. Ceci permet -d'interagir de façon un peu différente avec le gestionnaire de -fenêtres et doit être utilisé pour les fenêtres temporaires comme les -boîtes de dialogue, par exemple. - -<sect>Placement des widgets -<p> -Lorsqu'on crée une application, on veut mettre plus qu'un simple -bouton dans une fenêtre. Notre premier exemple « Bonjour le monde » -n'utilisait qu'un seul widget et on pouvait donc simplement faire un -appel à <em/gtk_container_add/ pour « placer » le widget dans la -fenêtre. Mais si l'on désire en mettre plus, comment peut-on contrôler -l'endroit où le widget sera positionné ? C'est ici que le placement -entre en jeu. - -<sect1>Théorie des boîtes de placement -<p> -La majeure partie du placement est faites en créant des boîtes comme -dans l'exemple ci-dessus. Ce sont des widgets containers invisibles où -l'on peut placer nos widgets. Elles existent sous deux formes : -boîtes horizontales et boîtes verticales. Lorsque l'on place des -widgets dans une boîte horizontale, les objets sont insérés -horizontalement de gauche à droite ou de droite à gauche selon l'appel -utilisé. Dans une boîte verticale, les widgets sont placés de haut en -bas ou vice versa. On peut utiliser n'importe quelle combinaison de -boîtes à l'intérieur ou à côté d'autres boîtes pour créer l'effet -désiré. -<p> -Pour créer une nouvelle boîte horizontale, on appelle -<em/gtk_hbox_new()/, et pour les boîtes verticales, -<em/gtk_vbox_new()/. Les fonctions <em/gtk_box_pack_start()/ et -<em/gtk_box_pack_end()/ servent à placer les objets à l'intérieur de -ces containers. La fonction <em/gtk_box_pack_start()/ placera de haut -en bas dans une boîte verticale et de gauche à droite dans une boîte -horizontale. <em/gtk_box_pack_end()/ fera le contraire en plaçant de -bas en haut et de droite à gauche. En utilisant ces fonctions, on peut -aligner à droite ou à gauche nos widgets et même les mélanger de -n'importe quelle façon pour obtenir l'effet désiré. Dans la plupart de -nos exemples, on utilisera <em/gtk_box_pack_start()/. Un objet peut -être un autre container ou un widget. En fait, de nombreux widgets -(dont les boutons) sont eux-mêmes des containers, mais on utilise -généralement seulement un label dans un bouton. -<p> -En utilisant ces appels, GTK sait où vous voulez placer vos widgets et -il peut donc les dimensionner automatiquement et faire d'autres choses -bien pratiques. Il existe aussi plusieurs options permettant de -préciser comment les widgets doivent être placés. Comme vous pouvez -l'imaginer, cette méthode nous donne pas mal de liberté pour placer et -créer les widgets. - -<sect1>Détails sur les boîtes -<p> -À cause de cette liberté, le placement des boîtes avec GTK peut -paraître déroutant au premier abord. Il existe beaucoup d'options et -il n'est pas tout de suite évident de comprendre comment elles -s'accordent toutes ensemble. En fait, il y a 5 styles de base -différents. - -<p> -<? -<IMG ALIGN="center" SRC="packbox1.gif" -VSPACE="15" HSPACE="10" ALT="Box Packing Example Image" WIDTH="528" -HEIGHT="235"> -> - -Chaque ligne contient une boîte horizontale (<em/hbox/) contenant -plusieurs boutons. L'appel à <em/gtk_box_pack/ indique la façon dont -sont placés tous les boutons dans la hbox. Chaque bouton est placé -dans la hbox de la même façon (mêmes paramètres que la fonction -<em/gtk_box_pack_start()/). -<p> -Voici la déclaration de la fonction <em/gtk_box_pack_start/. - -<tscreen><verb> -void gtk_box_pack_start (GtkBox *box, - GtkWidget *child, - gint expand, - gint fill, - gint padding); -</verb></tscreen> - -Le premier paramètre est la boîte dans laquelle on place l'objet, le -second est cet objet. Tous les objets sont tous des boutons jusqu'à -maintenant, on place donc des boutons dans des boîtes. -<p> -Le paramètre <em/expand/ de <em/gtk_box_pack_start()/ ou -<em/gtk_box_pack_end()/ contrôle la façon dont le widget est placé -dans la boîte. S'il vaut TRUE, les widgets sont disposés dans la boîte -de façon à en occuper tout l'espace. S'il vaut FALSE, la boîte est -rétrécie pour correspondre à la taille du widget. Mettre <em/expand/ à -FALSE vous permettra d'aligner à droite et à gauche vos -widgets. Sinon, ils s'élargiront pour occuper toute la boîte. Le même -effet pourrait être obtenu en utilisant uniquement une des deux -fonctions <em/gtk_box_pack_start/ ou <em/pack_end/. -<p> -Le paramètre <em/fill/ des fonctions <em/gtk_box_pack/ contrôle si de -l'espace supplémentaire doit être alloué aux objets eux-mêmes (TRUE), -ou si on doit rajouter de l'espace (<em/padding/) dans la boîte autour -des objets (FALSE). Il n'a de sens que si le paramètre <em/expand/ -vaut TRUE. -<p> -Lorsque l'on crée une nouvelle boîte, on utilise une fonction comme : - -<tscreen><verb> -GtkWidget * gtk_hbox_new (gint homogeneous, - gint spacing); -</verb></tscreen> - -Le paramètre <em/homogeneous/ de <em/gtk_hbox_new/ (et c'est la même -chose pour <em/gtk_vbox_new/) vérifie que chaque objet de la boîte ait -la même taille (i.e. la même largeur dans une hbox, la même hauteur -dans une vbox). S'il vaut TRUE, le paramètre <em/expand/ des fonctions -<em/gtk_box_pack/ sera toujours mis à TRUE. -<p> -Quelle est alors la différence entre les paramètres <em/spacing/ -(configuré lorsque la boîte est créée) et <em/padding/ (configuré -lorque les éléments sont placés) ? <em/spacing/ ajoute de l'espace -entre les objets, et <em/padding/ en ajoute de chaque côté d'un -objet. La figure suivante devrait éclairer tout cela : - -<? -<IMG ALIGN="center" SRC="packbox2.gif" -VSPACE="15" HSPACE="10" ALT="Box Packing Example Image" WIDTH="509" -HEIGHT="213"> -> - -Voici le code utilisé pour créer les images ci-dessus. J'y ai mis beaucoup de -commentaires en espérant que vous n'aurez pas de problème pour le -relire. Compilez-le et jouez avec les différents paramètres. - -<sect1>Programme de démonstration des placements -<p> - -<tscreen><verb> -#include "gtk/gtk.h" - -void -delete_event (GtkWidget *widget, GdkEvent *event, gpointer *data) -{ - gtk_main_quit (); -} - -/* Construction d'une nouvelle hbox remplie de boutons. Les paramètres qui - * nous intéressent sont passés à cette fonction. - * On n'affiche pas la boîte, mais tout ce qu'elle contient. */ - -GtkWidget *make_box (gint homogeneous, gint spacing, - gint expand, gint fill, gint padding) -{ - GtkWidget *box; - GtkWidget *button; - char padstr[80]; - - /* Création d'une hbox avec les paramètres homogeneous et spacing - * voulus. */ - - box = gtk_hbox_new (homogeneous, spacing); - - /* Création d'une série de boutons configurés de façon appropriée */ - - 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); - - /* Création d'un bouton portant un label dépendant de la valeur - * du paramètre 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); - - /* Même chose que ci-dessus mais sous forme abrégée. */ - - button = gtk_button_new_with_label (fill ? "TRUE," : "FALSE,"); - gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding); - gtk_widget_show (button); - - /* Récupération du paramètre padding sous forme de chaîne. */ - - 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; - - /* Initialisation, à ne jamais oublier ! :) */ - - gtk_init (&argc, &argv); - - if (argc != 2) { - fprintf (stderr, "usage : %s num, où num vaut 1, 2, ou 3.\n", *argv); - - /* Nettoyage dans GTK et sortie avec un code d'erreur de 1 */ - gtk_exit (1); - } - - which = atoi (argv[1]); - - /* Création de notre fenêtre. */ - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - - /* Il ne faut jamais oublier de connecter le signal "destroy" à la - * fenêtre principale. C'est très important pour disposer d'un - * comportement intuitif adéquat. */ - - gtk_signal_connect (GTK_OBJECT (window), "delete_event", - GTK_SIGNAL_FUNC (delete_event), NULL); - - gtk_container_border_width (GTK_CONTAINER (window), 10); - - - /* Création d'une boîte verticale (vbox) pour y placer les boîtes - * horizontales. - * Ceci permet de placer les boîtes horizontales contenant les boutons - * les unes au dessus des autres dans cette vbox. */ - - box1 = gtk_vbox_new (FALSE, 0); - - /* L'exemple à afficher. Ils correspondent aux images ci-dessus. */ - - switch (which) { - case 1: - /* Création d'un label. */ - - label = gtk_label_new ("gtk_hbox_new (FALSE, 0);"); - - /* Alignement du label à gauche. On précisera cette fonction ainsi - * que les autres dans la section sur les attributs des widgets. */ - - gtk_misc_set_alignment (GTK_MISC (label), 0, 0); - - /* Placement du label dans la boîte verticale (vbox box1). Il ne - * faut pas oublier que les widgets qui s'ajoutent à une vbox sont - * placés les uns au dessus des autres. */ - - gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0); - - /* Affichage du label */ - - gtk_widget_show (label); - - /* On appelle notre fonction de construction de boîte : - * homogeneous = FALSE, spacing = 0, - * expand = FALSE, fill = FALSE, padding = 0 */ - - box2 = make_box (FALSE, 0, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0); - gtk_widget_show (box2); - - /* On appelle notre fonction de construction de boîte : - * homogeneous = FALSE, spacing = 0, - * expand = FALSE, fill = FALSE, padding = 0 */ - - box2 = make_box (FALSE, 0, TRUE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0); - gtk_widget_show (box2); - - /* Paramètres : homogeneous = FALSE, spacing = 0, - * expand = TRUE, fill = TRUE, padding = 0 */ - - box2 = make_box (FALSE, 0, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0); - gtk_widget_show (box2); - - /* Création d'un séparateur, on verra cela plus tard, mais ils sont - * simples à utiliser. */ - - separator = gtk_hseparator_new (); - - /* Placement du séparateur dans la vbox. Ne pas oublier que tous les - * widgets sont placés dans une vbox et qu'il seront placés - * verticalement. */ - - gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5); - gtk_widget_show (separator); - - /* Création d'un nouveau label et affichage de celui-ci. */ - - 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); - - /* Paramètres : homogeneous = TRUE, spacing = 0, - * expand = TRUE, fill = FALSE, padding = 0 */ - - box2 = make_box (TRUE, 0, TRUE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0); - gtk_widget_show (box2); - - /* Paramètres : homogeneous = TRUE, spacing = 0, - * expand = TRUE, fill = TRUE, padding = 0 */ - - box2 = make_box (TRUE, 0, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0); - gtk_widget_show (box2); - - /* Un autre séparateur */ - - separator = gtk_hseparator_new (); - - /* Les 3 derniers paramètres de gtk_box_pack_start sont : - * expand = FALSE, fill = TRUE, padding = 5. */ - - gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5); - gtk_widget_show (separator); - - break; - - case 2: - - /* Création d'un label, box1 est une vbox identique à - * celle créée au début de main() */ - - 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); - - /* Paramètres : homogeneous = FALSE, spacing = 10, - * expand = TRUE, fill = FALSE, padding = 0 */ - - box2 = make_box (FALSE, 10, TRUE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0); - gtk_widget_show (box2); - - /* Paramètres : homogeneous = FALSE, spacing = 10, - * expand = TRUE, fill = TRUE, padding = 0 */ - - 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 (); - - /* Les 3 derniers paramètres de gtk_box_pack_start sont : - * expand = FALSE, fill = TRUE, padding = 5. */ - - 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); - - /* Paramètres : homogeneous = FALSE, spacing = 0, - * expand = TRUE, fill = FALSE, padding = 10 */ - - box2 = make_box (FALSE, 0, TRUE, FALSE, 10); - gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0); - gtk_widget_show (box2); - - /* Paramètres : homogeneous = FALSE, spacing = 0, - * expand = TRUE, fill = TRUE, padding = 10 */ - - 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 (); - - /* Les 3 derniers paramètres de gtk_box_pack_start sont : - * expand = FALSE, fill = TRUE, padding = 5. */ - - gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5); - gtk_widget_show (separator); - break; - - case 3: - - /* Ceci est une démonstration de la possibilité d'utiliser - * gtk_box_pack_end() pour aligner les widgets à droite. - * On crée d'abord une nouvelle boîte comme d'habitude. */ - - box2 = make_box (FALSE, 0, FALSE, FALSE, 0); - - /* On crée le label qui sera mis à la fin. */ - - label = gtk_label_new ("end"); - - /* On le place en utilisant gtk_box_pack_end(), il est ainsi - * mis à droite de la hbox créée par l'appel à make_box(). */ - - gtk_box_pack_end (GTK_BOX (box2), label, FALSE, FALSE, 0); - - /* Affichage du label. */ - - gtk_widget_show (label); - - /* Placement de box2 dans box1 (la vbox, vous vous rappelez ? :) */ - - gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0); - gtk_widget_show (box2); - - /* Séparateur pour le bas. */ - - separator = gtk_hseparator_new (); - - /* Configuration du séparateur en 400x5 pixels. - * La hbox que l'on a créée aura donc 400 pixels de large, - * et le label "end" sera séparé des autres de la hbox. - * Sinon, tous les widgets de la hbox seraient placés les plus - * près possible les uns des autres. */ - - gtk_widget_set_usize (separator, 400, 5); - - /* Placement du séparateur dans la vbox (box1) - * créée au debut de main(). */ - - gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5); - gtk_widget_show (separator); - } - - /* Création d'une nouvelle hbox.. vous pouvez en utiliser autant que - * que vous en avez besoin ! */ - - quitbox = gtk_hbox_new (FALSE, 0); - - /* Notre bouton pour quitter. */ - - button = gtk_button_new_with_label ("Quit"); - - /* Configuration du signal pour détruire la fenêtre. Ceci enverra le - * signal "destroy" à la fenêtre. Ce signal sera à son tour capturé - * par notre gestionnaire de signal défini plus haut. */ - - gtk_signal_connect_object (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (gtk_widget_destroy), - GTK_OBJECT (window)); - - /* Placement du bouton dans la « quitbox ». - * Les 3 derniers paramètres de gtk_box_pack_start sont : - * expand = TRUE, fill = FALSE, padding = 0. */ - - gtk_box_pack_start (GTK_BOX (quitbox), button, TRUE, FALSE, 0); - - /* Placement de la quitbox dans la vbox (box1) */ - - gtk_box_pack_start (GTK_BOX (box1), quitbox, FALSE, FALSE, 0); - - /* Placement de la vbox (box1), qui contient maintenant tous nos - * widgets, dans la fenêtre principale. */ - - gtk_container_add (GTK_CONTAINER (window), box1); - - /* Affichage */ - - gtk_widget_show (button); - gtk_widget_show (quitbox); - - gtk_widget_show (box1); - - /* Affichage de la fenêtre en dernier */ - - gtk_widget_show (window); - - /* Ne pas oublier notre fonction principale. */ - - gtk_main (); - - /* Le contrôle revient ici lorsque gtk_main_quit() est appelée, - * jusqu'à ce que gtk_exit() soitutilisée. */ - - return 0; -} -</verb></tscreen> - -<p> -<sect1>Placement avec les tables -<p> -Étudions une autre méthode de placement : les tables. Elles -peuvent s'avérer très utiles dans certaines situations. - -En utilisant des tables, on crée une grille dans laquelle on peut -placer les widgets. Ceux-ci peuvent occuper tous les endroits que l'on -désire. - -La première chose à faire est, bien sûr, d'étudier la fonction -<em/gtk_table_new/ : - -<tscreen><verb> -GtkWidget* gtk_table_new (gint rows, - gint columns, - gint homogeneous); -</verb></tscreen> -<p> -Le premier paramètre est le nombre de lignes de la table et le -deuxième, le nombre de colonnes. - -Le paramètre <em/homogeneous/ s'occupe de la façon dont les cases de -la table seront dimensionnées. Si homogeneous vaut TRUE, les cases -prennent la taille du plus grand widget de la table. S'il vaut FALSE, -la taille des cases dépend du widget le plus haut de la ligne et du -plus large de cette colonne. - -Le nombre de lignes et colonnes va de 0 à n, où n est le nombre spécifié dans -l'appel à <em/gtk_table_new/. Ainsi, avec <em/rows/ = 2 et -<em/columns/ = 2, la table ressemblera à ceci : - -<tscreen><verb> - 0 1 2 -0+----------+----------+ - | | | -1+----------+----------+ - | | | -2+----------+----------+ -</verb></tscreen> -<p> -On notera que le système de coordonnées part du coin en haut à -gauche. Pour placer un widget dans une case, ou utilise la fonction -suivante : - -<tscreen><verb> -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); -</verb></tscreen> -<p> -Où le premier paramètre (<em/table/) est la table que l'on a créée et -le second (<em/child/) est le widget que l'on veut placer dans la -table. - -Les paramètres <em/left_attach/ et <em/right_attach/ spécifient -l'emplacement du widget et le nombre de cases à utiliser. Par exemple, -si on veut placer un bouton dans le coin inférieur droit de la table -décrite plus haut et que l'on désire ne remplir QUE cette case, -<em/left_attach/ vaudra 1, <em/right_attach/ vaudra 2; <em/top_attach/ -vaudra 1 et <em/bottom_attach/ vaudra 2. - -Si on veut un widget occupant toute la ligne supérieure de notre table, on utilisera -les valeurs 0, 2, 0, 1. - -Les paramètres <em/xoptions/ et <em/yoptions/ servent à préciser les -options de placement et peuvent être combinées par un OU logique pour -permettre des options multiples. - -Ces options sont : -<itemize> -<item>GTK_FILL - Si la case de la table est plus large que le widget, et que -GTK_FILL est spécifié, le widget s'élargira pour occuper toute la place -disponible. - -<item>GTK_SHRINK - Si la table a moins de place qu'il ne lui en faut -(généralement, à cause d'un redimensionnement de la fenêtre par -l'utilisateur), les widgets sont alors simplement poussés vers le bas -de la fenêtre et disparaissent. Si GTK_SHRINK est spécifié, les -widgets se réduiront en même temps que la table. - -<item>GTK_EXPAND - Cette option provoque l'extension de la table pour -qu'elle utilise tout l'espace restant dans la fenêtre. -</itemize> - -Le paramêtres de <em/padding/ jouent le même rôle que pour les boîtes, -il créent une zone libre, spécifiée en pixels, autour du widget. - -gtk_table_attach() a BEAUCOUP d'options. Voici donc une fonction-raccourci : - -<tscreen><verb> -void gtk_table_attach_defaults (GtkTable *table, - GtkWidget *widget, - gint left_attach, - gint right_attach, - gint top_attach, - gint bottom_attach); -</verb></tscreen> - -<em/xoptions/ et <em/options/ valent par défaut GTK_FILL | GTK_EXPAND, -et <em/xpadding/ et <em/ypadding/ valent 0. Les autres paramètres sont -les mêmes que ceux de la fonction précédente. - -Il existe aussi les fonctions <em/gtk_table_set_row_spacing()/ et -<em/gtk_table_set_col_spacing()/. Elles permettent de placer des -espaces après une ligne ou une colonne. - -<tscreen><verb> -void gtk_table_set_row_spacing (GtkTable *table, - gint row, - gint spacing); -</verb></tscreen> -et -<tscreen><verb> -void gtk_table_set_col_spacing (GtkTable *table, - gint column, - gint spacing); -</verb></tscreen> - -Pour les colonnes, l'espace est ajouté à droite de la colonne et pour -les lignes, il est ajouté en dessous. - -On peut aussi configurer un espacement pour toutes les lignes et/ou -colonnes avec : - -<tscreen><verb> -void gtk_table_set_row_spacings (GtkTable *table, - gint spacing); -</verb></tscreen> -<p> -Et, -<tscreen><verb> -void gtk_table_set_col_spacings (GtkTable *table, - gint spacing); -</verb></tscreen> -<p> -Avec ces appels, la dernière ligne et la dernière colonne n'ont pas -d'espace supplémentaire. - -<sect1>Exemple de placement avec table -<p> -Pour le moment, étudiez l'exemple sur les tables (testgtk.c) distribué -avec les sources de GTK. - -<sect>Vue d'ensemble des widgets -<p> -<p> -Les étapes pour créer un widget en GTK sont : -<enum> -<item> <em/gtk_*_new()/ - une des fonctions disponibles pour créer un -nouveau widget. Ces fonctions sont décrites dans cette section. - -<item> Connexion de tous les signaux que l'on souhaite utiliser avec -les gestionnaires adéquats. - -<item> Configuration des attributs du widget. - -<item> Placement du widget dans un container en utilisant un appel approprié comme -<em/gtk_container_add()/ ou <em/gtk_box_pack_start()/. - -<item> Affichage du widget grâce à <em/gtk_widget_show()/. -</enum> -<p> -<em/gtk_widget_show()/ permet à GTK de savoir que l'on a fini de -configurer les attributs du widget et qu'il est prêt à être -affiché. On peut aussi utiliser <em/gtk_widget_hide()/ pour le faire -disparaître. L'ordre dans lequel on affiche les widgets n'est pas -important, mais il est préférable d'afficher la fenêtre en dernier -pour qu'elle surgisse d'un seul coup plutôt que de voir les différents -widgets apparaître à l'écran au fur et à mesure. Les fils d'un widget -(une fenêtre est aussi un widget) ne seront pas affichés tant que la -fenêtre elle-même n'est pas affichée par la fonction -<em/gtk_widget_show()/. - -<sect1> Conversions de types -<p> -Vous remarquerez, au fur et à mesure que vous progressez, que GTK -utilise un système de coercition de type. Celle-ci est toujours -réalisée en utilisant des macros qui vérifient si l'objet donné peut -être converti et qui réalisent cette coercition. Les macros que vous -rencontrerez le plus sont : - -<itemize> -<item> GTK_WIDGET(widget) -<item> GTK_OBJECT(object) -<item> GTK_SIGNAL_FUNC(function) -<item> GTK_CONTAINER(container) -<item> GTK_WINDOW(window) -<item> GTK_BOX(box) -</itemize> - -Elles sont toutes utilisées pour convertir les paramètres des -fonctions. Vous les verrez dans les exemples et, en règle générale, -vous saurez les utiliser simplement en regardant la -déclaration d'une fonction. - -Comme vous pouvez le voir dans la hiérarchie de classes ci-dessous, -tous les <em/GtkWidgets/ dérivent d'une classe de base -<em/GtkObject/. Ceci signifie que vous pouvez utiliser un widget à -chaque fois qu'une fonction requiert un objet - il suffit d'utiliser -la macro GTK_OBJECT(). - -Par exemple : - -<tscreen><verb> -gtk_signal_connect(GTK_OBJECT(button), "clicked", - GTK_SIGNAL_FUNC(fonction_rappel), donnee_de_rappel); -</verb></tscreen> - -Cet appel convertit le bouton en objet et fournit une conversion pour -le pointeur de fonction vers la fonction de rappel. - -De nombreux widgets sont aussi des containers. Si vous regardez la -hiérarchie de classe ci-dessous, vous remarquerez que beaucoup de -widgets viennent de la classe <em/GtkContainer/. N'importe lequel de -ces widgets peut être utilisé avec la macro GTK_CONTAINER pour être -passé en paramètre à une fonction qui attend un container. - -Malheureusement, ces macros ne peuvent être couvertes en détail dans -ce didacticiel, Je vous recommande donc de jeter un coup d'oeil sur -les fichier en-têtes GTK : ils peuvent s'avérer très -instructifs. En fait, il n'est pas difficile de comprendre comment -fonctionne un widget, il suffit d'étudier les déclarations des -fonctions. - -<p> -<sect1>La hiérarchie des widgets -<p> -Voici l'arbre de la hiérarchie de classes utilisées pour implanter les widgets. - -<tscreen><verb> - GtkObject - +-- GtkData - | \-- GtkAdjustment - | - \-- GtkWidget - +-- GtkContainer - | +-- GtkBin - | | +-- GtkAlignment - | | +-- GtkFrame - | | | *-- GtkAspectFrame - | | | - | | +-- GtkItem - | | | +-- GtkListItem - | | | +-- GtkMenuItem - | | | | +-- GtkCheckMenuItem - | | | | *-- GtkRadioMenuItem - | | | | - | | | *-- GtkTreeItem - | | | - | | +-- GtkViewport - | | \-- GtkWindow - | | +-- GtkDialog - | | \-- GtkFileSelection - | | - | +-- GtkBox - | | +-- GtkHBox - | | \-- GtkVBox - | | +-- GtkColorSelection - | | \-- GtkCurve - | | - | +-- GtkButton - | | +-- GtkOptionMenu - | | \-- GtkToggleButton - | | \-- GtkCheckButton - | | \-- GtkRadioButton - | | - | +-- GtkList - | +-- GtkMenuShell - | | +-- GtkMenu - | | \-- GtkMenuBar - | | - | +-- GtkNotebook - | +-- GtkScrolledWindow - | +-- GtkTable - | \-- GtkTree - | - +-- GtkDrawingArea - +-- GtkEntry - +-- GtkMisc - | +-- GtkArrow - | +-- GtkImage - | +-- GtkLabel - | \-- GtkPixmap - | - +-- GtkPreview - +-- GtkProgressBar - +-- GtkRange - | +-- GtkScale - | | +-- GtkHScale - | | \-- GtkVScale - | | - | \-- GtkScrollbar - | +-- GtkHScrollbar - | \-- GtkVScrollbar - | - +-- GtkRuler - | +-- GtkHRuler - | \-- GtkVRuler - | - \-- GtkSeparator - +-- GtkHSeparator - \-- GtkVSeparator - -</verb></tscreen> -<p> - -<sect1>Widgets sans fenêtre -<p> -Les widgets suivants n'ont pas de fenêtre associée. Si vous voulez -capturer des événements, vous devez utiliser <em/GtkEventBox/. -Reportez-vous à la section sur -<ref id="sec_The_EventBox_Widget" name="Le widget EventBox"> - -<tscreen><verb> -GtkAlignment -GtkArrow -GtkBin -GtkBox -GtkImage -GtkItem -GtkLabel -GtkPaned -GtkPixmap -GtkScrolledWindow -GtkSeparator -GtkTable -GtkViewport -GtkAspectFrame -GtkFrame -GtkVPaned -GtkHPaned -GtkVBox -GtkHBox -GtkVSeparator -GtkHSeparator -</verb></tscreen> -<p> -Nous continuerons notre exploration de GTK en examinant chaque widget -tour à tour, créant quelques fonctions simples pour les afficher. Une -autre source intéressante est le programme <em/testgtk.c/ livré avec -GTK. Il se trouve dans le répertoire <em>gtk/</em> - -<sect>Widgets boutons -<p> -<sect1>Boutons normaux -<p> -On a déjà presque vu tout ce qu'il y avait à voir sur le widget -bouton. Il est très simple. Cependant, il y a deux façons de créer un -bouton. On peut utiliser <em/gtk_button_new_with_label()/ pour créer -un bouton avec un label, ou <em/gtk_button_new()/ pour créer un bouton -vide. Dans ce dernier cas, c'est à vous de placer un label ou un -pixmap sur celui-ci. Pour ce faire, créez une boîte, puis placez vos -objets dans celle-ci en utilisant la fonction habituelle -<em/gtk_box_pack_start/, utilisez alors <em/gtk_container_add/ pour -placer la boîte dans le bouton. -<p> -Voici un exemple d'utilisation de <em/gtk_button_new()/ pour créer un -bouton contenant une image et un label. J'ai séparé du reste le code -qui crée une boîte pour que vous puissiez l'utiliser dans vos -programmes. - - -<tscreen><verb> -#include <gtk/gtk.h> - - -/* Création d'une hbox avec une image et un label. Cette fonction - * retourne la boîte... */ - -GtkWidget *xpm_label_box (GtkWidget *parent, gchar *xpm_filename, - gchar *label_text) -{ - GtkWidget *box1; - GtkWidget *label; - GtkWidget *pixmapwid; - GdkPixmap *pixmap; - GdkBitmap *mask; - GtkStyle *style; - - /* Création de la boite pour un xpm et un label */ - - box1 = gtk_hbox_new (FALSE, 0); - gtk_container_border_width (GTK_CONTAINER (box1), 2); - - /* Choix d'un style de bouton... Je suppose que c'est pour obtenir - * la couleur du fond. Si quelqu'un connaît la vraie raison, qu'il - * m'éclaire sur ce point. */ - - style = gtk_widget_get_style(parent); - - /* Chargement de xpm pour créer une image */ - - pixmap = gdk_pixmap_create_from_xpm (parent->window, &mask, - &style->bg[GTK_STATE_NORMAL], - xpm_filename); - pixmapwid = gtk_pixmap_new (pixmap, mask); - - /* Création d'un label */ - - label = gtk_label_new (label_text); - - /* placement de l'image et du label dans la boîte */ - - 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); -} - -/* Notre fonction de rappel habituelle */ - -void callback (GtkWidget *widget, gpointer *data) -{ - g_print ("Bonjour - %s a été pressé\n", (char *) data); -} - - -int main (int argc, char *argv[]) -{ - /* GtkWidget est le type utilisé pour déclarer les widgets */ - - GtkWidget *window; - GtkWidget *button; - GtkWidget *box1; - - gtk_init (&argc, &argv); - - /* Création d'une fenêtre */ - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - - gtk_window_set_title (GTK_WINDOW (window), "Pixmap'd Buttons!"); - - /* Il est préférable de faire cela pour toutes les fenêtres */ - - gtk_signal_connect (GTK_OBJECT (window), "destroy", - GTK_SIGNAL_FUNC (gtk_exit), NULL); - - - /* Configuration du bord de la fenêtre */ - - gtk_container_border_width (GTK_CONTAINER (window), 10); - - /* Création d'un bouton */ - - button = gtk_button_new (); - - /* Vous devriez être habitué à voir ces fonctions maintenant */ - - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (callback), (gpointer) "cool button"); - - /* Appel de notre fonction de création de boîte */ - - box1 = xpm_label_box(window, "info.xpm", "cool button"); - - /* Placement et affichage de tous nos widgets */ - - 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); - - /* Le reste est dans gtk_main */ - gtk_main (); - - return 0; -} -</verb></tscreen> - -La fonction <em/xpm_label_box()/ peut être utilisée pour placer des -xpms et des labels sur tout widget qui peut être container. - -<sect1> Boutons commutateurs -<p> -Les boutons commutateurs ressemblent beaucoup aux boutons normaux, sauf -qu'ils seront toujours alternativement dans un état ou dans un -autre. Le changement d'état s'effectue par un click. Ils peuvent être -enfoncés et, lorsqu'on clique dessus, ils se relèvent. Re-cliquez, -et ils se renfoncent. - -Les boutons commutateurs sont la base des cases à cocher ou des boutons -radio, donc la plupart des appels utilisés pour les boutons commutateurs -sont hérités par les cases à cocher et les boutons radio. J'insisterai -là dessus quand nous les aborderons. - -Création d'un bouton commutateur : - -<tscreen><verb> -GtkWidget* gtk_toggle_button_new (void); - -GtkWidget* gtk_toggle_button_new_with_label (gchar *label); -</verb></tscreen> -<p> -Comme vous pouvez l'imaginer, elles fonctionnent comme celles des -boutons normaux. La première crée un bouton commutateur vide et la -deuxième un bouton commutateur contenant déjà un label. -<p> -Pour récupérer l'état d'un commutateur et cela comprend aussi les -cases à cocher et les boutons radio, on utilise une macro comme nous -le montrons dans l'exemple qui suit et qui teste l'état du commutateur -dans une fonction de rappel. Le signal qui nous intéresse et qui est -émis par les boutons commutateurs (ce qui comprend aussi les cases à -cocher et les boutons radio), est le signal "toggled". Pour vérifier -l'état de ces boutons, on configure un gestionnaire de signal qui -capture "toggled" et utilise la macro pour déterminer l'état. La -fonction de rappel ressemblera à ceci : - -<tscreen><verb> -void rappel_bouton_commutateur (GtkWidget *widget, gpointer data) -{ - if (GTK_TOGGLE_BUTTON(widget)->active) - { - /* Si l'on est ici, c'est que le bouton est relâché. */ - - } else { - - /* le bouton est enfoncé */ - } -} -</verb></tscreen> - -<!-- - -COMMENTED! - -<tscreen><verb> -guint gtk_toggle_button_get_type (void); -</verb></tscreen> -<p> -No idea... they all have this, but I dunno what it is :) - - -<tscreen><verb> -void gtk_toggle_button_set_mode (GtkToggleButton *toggle_button, - gint draw_indicator); -</verb></tscreen> -<p> -No idea. ---> - -<p> -L'appel qui suit peut être utilisé pour configurer l'état d'un bouton -commutateur et de ses descendants, les cases à cocher et les boutons -radio. On lui passe notre bouton en premier paramètre et TRUE ou -FALSE pour spécifier s'il doit être relâché ou enfoncé. Par défaut, il -est relâché (FALSE). - -<tscreen><verb> -void gtk_toggle_button_set_state (GtkToggleButton *toggle_button, - gint state); -</verb></tscreen> -<p> -On notera que lorsqu'on utilise cette fonction, et que l'état est -modifié, cela force le bouton à émettre un signal "clicked". - -<tscreen><verb> -void gtk_toggle_button_toggled (GtkToggleButton *toggle_button); -</verb></tscreen> -<p> -Cet appel ne fait que commuter le bouton et émettre le signal "toggled". - -<sect1> Cases à cocher -<p> -Les cases à cocher héritent de nombreuses propriétés et fonctions des -boutons commutateurs, mais ont un aspect différent. Au lieu d'être des -boutons contenant du texte, ce sont de petits carrés avec un texte sur -leur droite. Il sont souvent utilisés pour valider ou non des options -dans les applications. - -Les deux fonctions de création sont identiques à celles des boutons normaux. - -<tscreen><verb> -GtkWidget* gtk_check_button_new (void); - -GtkWidget* gtk_check_button_new_with_label (gchar *label); -</verb></tscreen> - -La fonction <em/new_with_label/ crée une case à cocher avec un texte à -coté d'elle. - -La vérification de l'état d'une case à cocher est identique à celle -des boutons commutateurs. - -<sect1> Boutons radio -<p> -Les boutons radio ressemblent aux cases à cocher sauf qu'ils sont -groupés de façon à ce qu'un seul d'entre-eux puisse être sélectionné à -un moment donné. Ils sont utilisés par les applications lorsqu'il -s'agit d'effectuer un choix dans une liste d'options. - -La création d'un bouton radio s'effectue grâce à l'un des appels -suivants : - -<tscreen><verb> -GtkWidget* gtk_radio_button_new (GSList *group); - -GtkWidget* gtk_radio_button_new_with_label (GSList *group, - gchar *label); -</verb></tscreen> -<p> -On notera le paramètre supplémentaire de ces fonctions. Elles -nécessitent un groupe pour réaliser correctement leur tâche. Le -premier appel doit passer NULL au premier paramètre puis on peut créer un -groupe en utilisant : - -<tscreen><verb> -GSList* gtk_radio_button_group (GtkRadioButton *radio_button); -</verb></tscreen> - -<p> -On passe alors ce groupe en premier paramètre des appels suivants aux fonctions de création. Il est préférable, aussi, de préciser quel bouton doit être choisi par défaut avec la fonction : - -<tscreen><verb> -void gtk_toggle_button_set_state (GtkToggleButton *toggle_button, - gint state); -</verb></tscreen> -<p> -Celle-ci est décrite dans la section sur les boutons commutateurs et fonctionne -exactement de la même façon. -<p> -[Mettre ici un exemple d'utilisation de tout cela car je crois que cela ferait -beaucoup de bien...] - - -<sect> Widgets divers -<p> -<sect1> Labels -<p> -Les labels sont très utilisés dans GTK et sont relativement -simples. Ils n'émettent pas de signaux car ils n'ont pas de fenêtre X -qui leur est associée. Si vous avez besoin de capturer des signaux ou -de faire des coupures (« clippings »), utilisez un widget EventBox. - -Pour créer un label, on utilise : - -<tscreen><verb> -GtkWidget* gtk_label_new (char *str); -</verb></tscreen> - -Où l'unique paramètre est la chaîne de caractères que l'on veut que le -label affiche. - -Pour changer le texte d'un label après sa création, on utilise la fonction : - -<tscreen><verb> -void gtk_label_set (GtkLabel *label, - char *str); -</verb></tscreen> -<p> -où le premier paramètre est le label que l'on veut modifier, que l'on -convertit en utilisant la macro GTK_LABEL(), et le second est la -nouvelle chaîne. - -L'espace nécessaire à la nouvelle chaîne sera automatiquement ajusté -si nécessaire. - -Pour récupérer la chaîne courante, on utilise la fonction : - -<tscreen><verb> -void gtk_label_get (GtkLabel *label, - char **str); -</verb></tscreen> - -où le premier paramètre est le label dont on veut récupérer la chaîne -et le second sert à retourner cette chaîne. - -<sect1>Le widget bulle d'aide -<p> -Ce sont les petits textes qui surgissent lorsque vous laissez votre -pointeur sur un bouton ou un autre widget pendant quelques secondes. -Ils sont faciles à utiliser, on ne donnera donc pas d'exemple. Si vous -voulez voir du code, consultez le programme <em/testgtk.c/ distribué -avec GTK. -<p> -Certains widgets (comme les labels) ne fonctionnent pas avec les -bulles d'aide. -<p> -Le premier appel que vous utiliserez sera pour créer une nouvelle -bulle d'aide. Vous n'avez besoin que de le faire une fois dans une -fonction donnée. Le <em/GtkTooltip/ que cette fonction retourne peut -être utilisé pour créer plusieurs bulles d'aide. - -<tscreen><verb> -GtkTooltips *gtk_tooltips_new (void); -</verb></tscreen> - -Lorsque vous avez créé une nouvelle bulle d'aide et le widget sur lequel vous -voulez l'utiliser, vous n'avez qu'à faire cet appel pour la configurer : - -<tscreen><verb> -void gtk_tooltips_set_tips (GtkTooltips *tooltips, - GtkWidget *widget, - gchar *tips_text); -</verb></tscreen> - -Les paramètres sont la bulle d'aide déjà créée, suivi du widget pour -lequel vous voulez voir apparaître cette bulle et le texte que vous -voulez qu'elle contienne. -<p> -Voici un petit exemple : - -<tscreen><verb> -GtkTooltips *tooltips; -GtkWidget *button; -... -tooltips = gtk_tooltips_new (); -button = gtk_button_new_with_label ("bouton 1"); -... -gtk_tooltips_set_tips (tooltips, button, "C'est le bouton 1"); -</verb></tscreen> - - -D'autres fonctions peuvent être utilisées avec les bulles d'aide. Je ne ferais que les énumérer et les décrire brièvement. - -<tscreen><verb> -void gtk_tooltips_destroy (GtkTooltips *tooltips); -</verb></tscreen> - -Destruction de bulles d'aide. - -<tscreen><verb> -void gtk_tooltips_enable (GtkTooltips *tooltips); -</verb></tscreen> - -Activation d'un ensemble de bulles d'aide désactivées. - -<tscreen><verb> -void gtk_tooltips_disable (GtkTooltips *tooltips); -</verb></tscreen> - -Désactivation d'un ensemble de bulles d'aide activées. - -<tscreen><verb> -void gtk_tooltips_set_delay (GtkTooltips *tooltips, - gint delay); - -</verb></tscreen> Configure le nombre de millisecondes pendant lequel -le pointeur soit se trouver sur le widget avant que la bulle d'aide -n'apparaisse. Par défaut, ce délai est de 1000 millisecondes, soit 1 -seconde. - -<tscreen><verb> -void gtk_tooltips_set_tips (GtkTooltips *tooltips, - GtkWidget *widget, - gchar *tips_text); -</verb></tscreen> - -Change le texte d'une bulle d'aide déjà créée. - -<tscreen><verb> -void gtk_tooltips_set_colors (GtkTooltips *tooltips, - GdkColor *background, - GdkColor *foreground); -</verb></tscreen> - -Configure les couleurs de fond et de premier plan des bulles -d'aides. Je ne sais toujours pas comment spécifier les couleurs... -<p> -Et c'est tout concernant les fonctions associées aux bulles -d'aide. C'est plus que vous ne vouliez sûrement en savoir :) - -<sect1> Barres de progression -<p> -Les barres de progression sont utilisées pour afficher la progression -d'une opération. Elles sont très simple à utiliser comme vous pourrez -le constater en étudiant le code ci-dessous. Commençons d'abord par -l'appel permettant de créer une nouvelle barre. - -<tscreen><verb> -GtkWidget *gtk_progress_bar_new (void); -</verb></tscreen> - -Maintenant que la barre est créée, nous pouvons l'utiliser. - -<tscreen><verb> -void gtk_progress_bar_update (GtkProgressBar *pbar, gfloat percentage); -</verb></tscreen> - -Le premier paramètre est la barre de progression sur laquelle on veut -agir, et le second est le pourcentage « effectué », signifiant le -remplissage de la barres de 0 à 100 % (réel compris entre 0 et 1). - -Les barres de progression sont généralement utilisées avec les délais -d'expiration ou autres fonctions identiques (voir la section sur <ref -id="sec_timeouts" name="Expirations, fonctions d'E/S et d'attente">) -pour donner l'illusion du multi-tâches. Toutes emploient la fonction -<em/gtk_progress_bar_update/ de la même façon. - -Voici un exemple de barre de progression mise à jour par des -expirations. Ce code montre aussi comment réinitialiser une barre. - -<tscreen><verb> -#include <gtk/gtk.h> - -static int ptimer = 0; -int pstat = TRUE; - -/* Cette fonction incrémente et met à jour la barre de progression, - * elle la réinitialise si pstat vaut FALSE */ - -gint progress (gpointer data) -{ - gfloat pvalue; - - /* récupération de la valeur courante de la barre */ - - 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; -} - -/* Cette fonction signale une réinitialisation de la barre */ - -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 ("Exemple de barre de progression"); - gtk_table_attach_defaults(GTK_TABLE(table), label, 0,2,0,1); - gtk_widget_show(label); - - /* Crée une barre, la place dans la table et l'affiche */ - - pbar = gtk_progress_bar_new (); - gtk_table_attach_defaults(GTK_TABLE(table), pbar, 0,2,1,2); - gtk_widget_show (pbar); - - /* Configure le délai d'expiration pour gérer automatiquement la - * mise à jour de la barre */ - - ptimer = gtk_timeout_add (100, progress, pbar); - - /* Ce bouton indique à la barre qu'elle doit se réinitialiser */ - - 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 ("Annuler"); - 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; -} -</verb></tscreen> - -Dans ce petit programme, il y a quatre parties concernant le -fonctionnement général des barres de progression, nous les étudierons -dans l'ordre de leurs appels. - -<tscreen><verb> -pbar = gtk_progress_bar_new (); -</verb></tscreen> - -Cet appel crée une nouvelle barre, nommée <em/pbar/. - -<tscreen><verb> -ptimer = gtk_timeout_add (100, progress, pbar); -</verb></tscreen> - -Cet appel utilise des délais d'expiration pour permettre un intervalle -de temps constant. ces délais ne sont pas nécessaires à l'utilisation -des barres de progression. - -<tscreen><verb> -pvalue = GTK_PROGRESS_BAR (data)->percentage; -</verb></tscreen> - -Ce code assigne à <em/pvalue/ la valeur du pourcentage de la barre. - -<tscreen><verb> -gtk_progress_bar_update (GTK_PROGRESS_BAR (data), pvalue); -</verb></tscreen> - -Finalement, ce code met à jour la barre avec la valeur de <em/pvalue/. - -Et c'est tout ce qu'il y a à savoir sur les barres de -progression. Amusez-vous bien. - -<sect1> Boîtes de dialogue -<p> - -Les widgets boîtes de dialogue sont très simples : ce sont -simplement des fenêtres avec plusieurs choses déjà placées dedans. La -structure d'une boîte de dialogue est : - -<tscreen><verb> -struct GtkDialog -{ - GtkWindow window; - - GtkWidget *vbox; - GtkWidget *action_area; -}; -</verb></tscreen> - -Comme vous le voyez, cela crée simplement une fenêtre et la place dans -une vbox suivie d'un séparateur et d'une hbox pour la « zone d'action ». - -Le widget boîte de dialogue peut servir à produire des messages pour -l'utilisateur ainsi qu'à d'autres tâches. Il est vraiment rudimentaire -et il n'y a qu'une seule fonction pour les boîtes de dialogue : - -<tscreen><verb> -GtkWidget* gtk_dialog_new (void); -</verb></tscreen> - -Ainsi, pour créer un nouveau dialogue, on utilise : - -<tscreen><verb> -GtkWidget window; -window = gtk_dialog_new (); -</verb></tscreen> - -Ceci créera la boîte de dialogue et c'est maintenant à vous de -l'utiliser. Vous pouvez, par exemple, placer un bouton dans la zone -d'action en faisant quelque chose comme : - -<tscreen><verb> -button = ... -gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button, - TRUE, TRUE, 0); -gtk_widget_show (button); -</verb></tscreen> - -Et vous pouvez aussi ajouter un label à la zone de la vboxb : - -<tscreen><verb> -label = gtk_label_new ("Les boîtes de dialogues sont pratiques"); -gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), label, TRUE, - TRUE, 0); -gtk_widget_show (label); -</verb></tscreen> - -Comme exemple d'utilisation d'une boîte de dialogue, vous pourriez -mettre deux boutons dans la zone d'action (un bouton « Annuler » et un -bouton « Ok ») et un label dans la zone de la vbox posant une question -à l'utilisateur ou signalant une erreur, etc. Vous pouvez alors -attacher un signal différent à chacun des boutons et réaliser -l'opération que l'utilisateur a choisie. - - -<sect1> Pixmaps -<p> -Les pixmaps sont des structures de données contenant des -images. Celles-ci peuvent être utilisées à différents endroits, mais -le plus souvent comme icônes dans le bureau X Window. Un bitmap est un -pixmap de 2 couleurs. - -Pour utiliser des pixmaps avec GTK, on doit d'abord construire une -structure <em/GdkPixmap/ en utilisant les fonctions de la couche -GDK. Les pixmaps peuvent soit être créés à partir de données en -memoire, ou à partir de données lues dans un fichier. Nous utiliserons -chacun des appels pour créer un pixmap. - -<tscreen><verb> -GdkPixmap *gdk_bitmap_create_from_data( GdkWindow *window, - gchar *data, - gint width, - gint height ); -</verb></tscreen> -<p> -Cette fonction sert à créer un pixmap mono-plan (2 couleurs) à partir -de données en mémoire. Chaque bit de la donnée <em/data/. <em/width/ -et <em/height/ sont exprimés en pixels. Le pointeur vers un -<em/GdkWindow/ pointe sur la fenêtre courante car les ressources d'un -pixmap n'ont de signification que dans le contexte de l'écran où il -doit s'afficher. - -<tscreen><verb> -GdkPixmap* gdk_pixmap_create_from_data( GdkWindow *window, - gchar *data, - gint width, - gint height, - gint depth, - GdkColor *fg, - GdkColor *bg ); -</verb></tscreen> - -Cette fonction est utilisée pour créer un pixmap d'une profondeur -donnée (nombre de couleurs) à partir de la donnée spécifiée pas -<em/data/. <em/fg/ et <em/bg/ sont les couleurs à utiliser pour -l'avant et l'arrière-plan. - -<tscreen><verb> -GdkPixmap* gdk_pixmap_create_from_xpm( GdkWindow *window, - GdkBitmap **mask, - GdkColor *transparent_color, - const gchar *filename ); -</verb></tscreen> - -Le format XPM est une représentation des pixmaps reconnue par le système X Window. Il est largement utilisé et de nombreux utilitaires pour créer des fichiers d'images à ce format sont disponibles. Le fichier <em/filename/ doit contenir une image dans ce format qui sera chargée dans la structure pixmap. Le masque <em/mask/ indique quels sont les bits opaques du pixmap. Tous les autres bits sont colorisés en utilisant la couleur spécifiée par <em/transparent_color/. Un exemple d'utilisation est présenté ci-dessous. - -<tscreen><verb> -GdkPixmap* gdk_pixmap_create_from_xpm_d (GdkWindow *window, - GdkBitmap **mask, - GdkColor *transparent_color, - gchar **data); -</verb></tscreen> - -De petites images peuvent être intégrées dans un programme sous la forme de -données <em/data/ au format XPM. Un pixmap est créé en utilisant ces données au -lieu de les lire dans un fichier. Un exemple de telles données est : - -<tscreen><verb> -/* 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. ", -" ......... ", -" ", -" "}; -</verb></tscreen> - -<tscreen><verb> -void gdk_pixmap_destroy( GdkPixmap *pixmap ); -</verb></tscreen> -<p> -Lorsqu'on a utilisé un pixmap et que l'on en a plus besoin tout de suite, il est préférable de libérer la ressource en utilisant un appel à <em/gdk_pixmap_destroy/. Les pixmaps doivent être considérées comme une ressource précieuse. - -Quand le pixmap est créé, on peut l'afficher comme un widget GTK. On -doit créer un widget pixmap qui contiendra le pixmap GDK. Ceci est -réalisé de la façon suivante : - -<tscreen><verb> -GtkWidget* gtk_pixmap_new( GdkPixmap *pixmap, - GdkBitmap *mask ); -</verb></tscreen> -<p> -Les autres fonctions pour les widgets pixmap sont : - -<tscreen><verb> -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); -</verb></tscreen> -<p> -<em/gtk_pixmap_set/ sert à changer le pixmap pris en charge par le widget. <em/val/ est le pixmap créé par le GDK. - -Voici un exemple illustrant l'utilisation d'un pixmap dans un bouton : - -<tscreen><verb> - -#include <gtk/gtk.h> - - -/* données XPM d'une icône "Ouvrir fichier" */ -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. ", -" ......... ", -" ", -" "}; - - -/* Termine l'application lorsqu'elle est appelée - * via le signal "delete_event" */ - -void close_application( GtkWidget *widget, GdkEvent *event, gpointer *data ) -{ - gtk_main_quit(); -} - - -/* Invoquée lorsque le bouton est cliqué. Affiche simplement - * un message. */ - -void button_clicked( GtkWidget *widget, gpointer *data ) -{ - printf( "bouton cliqué\n" ); -} - - -int main( int argc, char *argv[] ) -{ - /* GtkWidget est le type pour déclarer les widgets */ - - GtkWidget *window, *pixmapwid, *button; - GdkPixmap *pixmap; - GdkBitmap *mask; - GtkStyle *style; - - /* Crée la fenêtre principale et attache le signal "delete_event" pour - * terminer l'application */ - - 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 ); - - /* Utilisation de GDK pour créer le pixmap */ - - style = gtk_widget_get_style( window ); - pixmap = gdk_pixmap_create_from_xpm_d( window->window, &mask, - &style->bg[GTK_STATE_NORMAL], - (gchar **)xpm_data ); - - /* Création d'un widget pixmap GTK pour contenir le pixmap GDK */ - - pixmapwid = gtk_pixmap_new( pixmap, mask ); - gtk_widget_show( pixmapwid ); - - /* Création d'un bouton pour contenir le widget pixmap */ - - 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 ); - - /* Affichage de la fenêtre */ - gtk_main (); - - return 0; -} -</verb></tscreen> - - -Pour charger un fichier à partir d'un fichier XPM appelé -<em/icon0.xpm/ se trouvant dans le répertoire courant, on aurait créé -le pixmap ainsi : - -<tscreen><verb> - /* Charge un pixmap à partir d'un fichier */ - - 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 ); -</verb></tscreen> - - -Utilisation des formes -<p> -Un désavantage de l'utilisation des pixmaps est que l'objet affiché -est toujours rectangulaire, quelle que soit l'image. On voudrait -pouvoir créer des bureaux et des applications avec des icônes ayant -des formes plus naturelles. Par exemple, pour une interface de jeu, on -aimerait avoir des boutons ronds à pousser. Pour faire cela, on doit -utiliser des fenêtres avec des formes. - -Une fenêtre avec forme est simplement un pixmap dont les pixels du -fond sont transparents. Ainsi, lorsque l'image d'arrière-plan est -multicolore, on ne la cache pas avec le bord de notre icône. L'exemple -suivant affiche une image de brouette sur le bureau. - -<tscreen><verb> - -#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 ", -" ", -" "}; - - -/* Termine l'application lorsqu'elle est appelée - * (via le signal "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; - - /* crée la fenêtre principale et attache le signal "delete_event" - * pour terminer l'application. On notera que la fenêtre principale - * n'a pas de barre de titre car nous la faisons surgir. */ - - 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); - - /* Création du pixmap et du widget pixmap */ - - 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 ); - - /* Pour afficher le pixmap, on utilise un widget fixe pour placer - * le pixmap */ - - 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 ); - - /* On masque tout sauf l'image elle-même */ - - gtk_widget_shape_combine_mask( window, mask, 0, 0 ); - - /* Affichage de la fenêtre */ - - gtk_widget_set_uposition( window, 20, 400 ); - gtk_widget_show( window ); - gtk_main (); - - return 0; -} -</verb></tscreen> -<p> -Pour rendre l'image de la brouette sensible aux clics, on peut lui -attacher le signal "button_press_event" pour lui faire faire quelque -chose. Les quelques lignes suivantes font que l'image sera sensible à -un clic souris qui provoquera l'arrêt de l'application. - -<tscreen><verb> -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 ); -</verb></tscreen> - - -<sect> Widgets containers - -<sect1> Bloc-notes -<p> -Le widget bloc-notes est un ensemble de « pages » qui se -chevauchent. Chaque page contient des informations -différentes. Récemment, ce widget est devenu plus commun dans la -programmation des interfaces graphiques et c'est un bon moyen de -montrer des blocs d'information similaires qui justifient une -séparation de leur affichage. - -Le premier appel de fonction que l'on doit connaître est, vous -l'aviez deviné, celui qui crée un widget bloc-notes. - -<tscreen><verb> -GtkWidget* gtk_notebook_new (void); -</verb></tscreen> - -Lorsque le bloc-notes a été créé, il y a 12 fonctions permettant de -travailler sur les blocs-notes. Étudions-les séparément. - -La première permet de positionner les indicateurs de pages. Ceux-ci -(désignés par le mot « tab » (signet)), peuvent se trouver en haut, en -bas, à gauche ou à droite des pages. - -<tscreen><verb> -void gtk_notebook_set_tab_pos (GtkNotebook *notebook, GtkPositionType pos); -</verb></tscreen> - -<em/GtkPositionType/ peut prendre les valeurs suivantes qu'il n'est -pas nécessaire d'expliquer : -<itemize> -<item> GTK_POS_LEFT -<item> GTK_POS_RIGHT -<item> GTK_POS_TOP -<item> GTK_POS_BOTTOM -</itemize> - -GTK_POS_TOP est la valeur par défaut. - -La fonction suivante permet d'ajouter des pages à un bloc-notes. Il y -a trois façons d'ajouter des pages. Regardons les deux premières qui -sont très semblables. - -<tscreen><verb> -void gtk_notebook_append_page (GtkNotebook *notebook, GtkWidget *child, - GtkWidget *tab_label); - -void gtk_notebook_prepend_page (GtkNotebook *notebook, GtkWidget *child, - GtkWidget *tab_label); -</verb></tscreen> - -Ces fonctions ajoutent des pages au bloc-notes<em/*notebook/ en les -insérant à la fin (<em/append/) ou au début -(<em/prepend/). <em/*child/ est le widget qui est placé dans la page -du bloc-notes, et <em/*tab_label/ est le label de la page qui est -ajoutée. - -La troisième fonction ajoutant une page à un bloc-notes conserve -toutes les propriétés des deux précédentes, mais elle nous permet en -plus de spécifier la position où l'on désire insérer cette page. - -<tscreen><verb> -void gtk_notebook_insert_page (GtkNotebook *notebook, GtkWidget *child, - GtkWidget *tab_label, gint position); -</verb></tscreen> - -Les paramètres sont les mêmes que <em/_append_/ et <em/_prepend_/ sauf -qu'il y en a un de plus : <em/position/. Celui-ci sert à -spécifier l'endroit où cette page sera insérée. - -Maintenant que nous savons insérer une page, voyons comment en supprimer une. - -<tscreen><verb> -void gtk_notebook_remove_page (GtkNotebook *notebook, gint page_num); -</verb></tscreen> - -Cette fonction ôte la page spécifiée par <em/page_num/ du widget -<em/*notebook/. - -Pour connaître la page courante d'un bloc-notes, on dispose de la -fonction : - -<tscreen><verb> -gint gtk_notebook_current_page (GtkNotebook *notebook); -</verb></tscreen> - -Les deux fonctions suivantes permettent de passer à la page suivante -ou précédente d'un bloc-notes. Il suffit de faire l'appel de la -fonction adéquate avec le widget sur lequel on veut -opérer. Remarque : lorsqu'on est sur la dernière page du -bloc-notes et que l'on appelle <em/gtk_notebook_next_page/, on revient -à la première page. De même, si l'on est sur la première page et que -l'onappelle <em/gtk_notebook_prev_page/, on se retrouve sur sa -dernière page. - -<tscreen><verb> -void gtk_notebook_next_page (GtkNoteBook *notebook); -void gtk_notebook_prev_page (GtkNoteBook *notebook); -</verb></tscreen> - -La fonction qui suit permet de choisir la page « active ». Si vous -voulez ouvrir le bloc-notes à la page 5, par exemple, vous utiliserez -cette fonction. Sans elle, le bloc-notes s'ouvre sur sa première page -par défaut. - -<tscreen><verb> -void gtk_notebook_set_page (GtkNotebook *notebook, gint page_num); -</verb></tscreen> - -Les deux fonctions suivantes ajoutent ou ôtent les indicateurs de page -et le contour du bloc-notes, respectivement. - -<tscreen><verb> -void gtk_notebook_set_show_tabs (GtkNotebook *notebook, gint show_tabs); -void gtk_notebook_set_show_border (GtkNotebook *notebook, gint show_border); -</verb></tscreen> - -<em/show_tabs/ et <em/show_border/ peuvent valoir TRUE ou FALSE (0 ou 1). - -Voyons maintenant un exemple, il est tiré du code de <em/testgtk.c/ de -la distribution GTK et montre l'utilisation des 13 fonctions. Ce petit -programme crée une fenêtre contenant un bloc-notes et six boutons. Le -bloc-notes contient 11 pages, ajoutées par trois moyens -différents : à la fin, au milieu et au début. Les boutons -permettent de faire tourner les indicateurs de page, ajouter/ôter les -indicateurs et le contour, ôter une page, passer à la page suivante et -précédente, et sortir du programme. - - -<tscreen><verb> - -#include <gtk/gtk.h> - -/* Rotation des indicateurs de page */ - -void rotate_book (GtkButton *button, GtkNotebook *notebook) -{ - gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos +1) %4); -} - -/* Ajout/Suppression des indicateurs de pages et des contours */ - -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); -} - -/* Suppression d'une page */ - -void remove_book (GtkButton *button, GtkNotebook *notebook) -{ - gint page; - - page = gtk_notebook_current_page(notebook); - gtk_notebook_remove_page (notebook, page); - - /* Il faut rafraîchir le widget -- - * ce qui force le widget à se redessiner. */ - - 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); - - /* Création d'un bloc-notes, placement des indicateurs de page. */ - - 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); - - /* Ajoute un groupe de pages à la fin du bloc-notes. */ - - 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); - } - - - /* Ajoute une page à un endroit précis. */ - - checkbutton = gtk_check_button_new_with_label ("Cochez moi !"); - gtk_widget_set_usize(checkbutton, 100, 75); - gtk_widget_show (checkbutton); - - label = gtk_label_new ("Emplacement de la nouvelle page"); - gtk_container_add (GTK_CONTAINER (checkbutton), label); - gtk_widget_show (label); - label = gtk_label_new ("Ajout de page"); - gtk_notebook_insert_page (GTK_NOTEBOOK (notebook), checkbutton, label, 2); - - /* Ajout de pages au début du bloc-notes */ - - for (i=0; i < 5; i++) { - sprintf(bufferf, "Prepend 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_prepend_page (GTK_NOTEBOOK(notebook), frame, label); - } - - /* Configuration de la page de départ (page 4) */ - - gtk_notebook_set_page (GTK_NOTEBOOK(notebook), 3); - - - /* Création des boutons */ - - button = gtk_button_new_with_label ("Fermer"); - gtk_signal_connect_object (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (delete), NULL); - gtk_table_attach_defaults(GTK_TABLE(table), button, 0,1,1,2); - gtk_widget_show(button); - - button = gtk_button_new_with_label ("Page suivante"); - 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 ("Page précédente"); - 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 ("Position des indicateurs"); - 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 ("Indicateurs/Contours oui/non"); - 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 ("Oter 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; -} -</verb></tscreen> -<p> -En espérant que ceci vous aide à créer des blocs-notes pour vos -applications GTK. - - -<sect1> Fenêtres avec barres de défilement -<p> -Les fenêtres avec barres de défilement servent à créer des zones -défilantes à l'intérieur d'une vraie fenêtre. On peut insérer -n'importe quel widget dans ces fenêtres, ils seront accessibles quelle -que soit leur taille en utilisant les barres de défilement. - - -La fonction suivante sert à créer une fenêtre avec barre de -défilement : - -<tscreen><verb> -GtkWidget* gtk_scrolled_window_new (GtkAdjustment *hadjustment, - GtkAdjustment *vadjustment); -</verb></tscreen> -<p> -Le premier paramètre est l'ajustement horizontal, et le second -l'ajustement vertical. Ils sont presque toujours positionnés à NULL. - -<tscreen><verb> -void gtk_scrolled_window_set_policy (GtkScrolledWindow *scrolled_window, - GtkPolicyType hscrollbar_policy, - GtkPolicyType vscrollbar_policy); -</verb></tscreen> - -Cela permet de configurer le fonctionnement des barres de -défilement. Le premier paramètre est la fenêtre à défilement que l'on -veut modifier, le second configure le fonctionnement de la barre -horizontale et le troisième celui de la barre verticale. - -Ce fonctionnement peut être GTK_POLICY AUTOMATIC ou GTK_POLICY_ALWAYS. -GTK_POLICY_AUTOMATIC décidera automatiquement de votre besoin en -barres de défilement, alors que GTK_POLICY_ALWAYS mettra toujours -celles-ci. - -Voici un exemple simple qui place 100 boutons commutateurs dans une -fenêtre à défilement. Je n'ai commenté que les parties qui sont -nouvelles pour vous. - -<tscreen><verb> -#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); - - /* Création d'une boîte de dialogue pour y placer la fenêtre à défilement. - * Une boîte de dialogue est une fenêtre comme les autres sauf qu'elle contient - * une vbox et un séparateur horizontal. Ce n'est qu'un raccourci pour créer des - * zones de dialogue. */ - - 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); - - /* Création d'une fenêtre à défilement. */ - - scrolled_window = gtk_scrolled_window_new (NULL, NULL); - - gtk_container_border_width (GTK_CONTAINER (scrolled_window), 10); - - /* La gestion des barres est soit GTK_POLICY AUTOMATIC, soit GTK_POLICY_ALWAYS. - * GTK_POLICY_AUTOMATIC décide automatiquement s'il faut ou non des barres, - * GTK_POLICY_ALWAYS met toujours des barres - * Le premier paramètre correspond à la barre horizontale, - * le second à la barre verticale. */ - - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), - GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); - - /* Création d'une boîte de dialogue */ - - gtk_box_pack_start (GTK_BOX (GTK_DIALOG(window)->vbox), scrolled_window, - TRUE, TRUE, 0); - gtk_widget_show (scrolled_window); - - /* Création d'une table de 10x10 cases. */ - - table = gtk_table_new (10, 10, FALSE); - - /* Configure l'espace des lignes et des colonnes de 10 pixels */ - - gtk_table_set_row_spacings (GTK_TABLE (table), 10); - gtk_table_set_col_spacings (GTK_TABLE (table), 10); - - /* Place la table fans la fenêtre à défilement */ - - gtk_container_add (GTK_CONTAINER (scrolled_window), table); - gtk_widget_show (table); - - /* Crée une grille de boutons commutateurs dans la table */ - - for (i = 0; i < 10; i++) - for (j = 0; j < 10; j++) { - sprintf (buffer, "bouton (%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); - } - - /* Ajoute un bouton « Fermer » en bas de la boîte de dialogue */ - - button = gtk_button_new_with_label ("Fermer"); - gtk_signal_connect_object (GTK_OBJECT (button), "clicked", - (GtkSignalFunc) gtk_widget_destroy, - GTK_OBJECT (window)); - - /* On met ce bouton en « bouton par défaut ». */ - - GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); - gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button, TRUE, TRUE, 0); - - /* Récupère le bouton par défaut. Le fait de presser la touche « Entrée » - * activera le bouton. */ - - gtk_widget_grab_default (button); - gtk_widget_show (button); - - gtk_widget_show (window); - - gtk_main(); - - return(0); -} -</verb></tscreen> -<p> -Essayez de changer la taille de la fenêtre et faites attention aux -réactions des barres de défilement. On peut aussi utiliser la fonction -<em/gtk_widget_set_usize()/ pour configurer la taille par défaut de la -fenêtre et des autres widgets. - - -<sect>Widgets listes -<p> -Le widget <em/GtkList/ sert de container vertical pour des widgets <em/GtkListItem/. - -Un widget <em/GtkList/ possède sa propre fenêtre pour recevoir les -événements et sa propre couleur de fond qui est habituellement -blanche. Comme il est directement dérivé de <em/GtkContainer/, il peut -être traité comme tel en utilisant la macro GTK_CONTAINER(List) : -voir le widget <em/GtkContainer/ pour en savoir plus. - -On doit d'abord connaître l'utilisation des <em/GList/ et des -fonctions <em/g_list_*()/ qui leur sont liées pour pouvoir utiliser -pleinement le widget <em/GtkList/. - -Un champ de la structure d'un widget <em/GtkList/ nous intéresse particulièrement : - -<tscreen><verb> -struct _GtkList -{ - ... - GList *selection; - guint selection_mode; - ... -}; -</verb></tscreen> - -Le champ <em/selection/ d'un <em/GtkList/ pointe sur une liste chaînée -de tous les items qui sont sélectionnés, ou vaut NULL si aucune -sélection n'est faite. Ainsi, pour connaître la sélection courante, on -consulte le champ <em/GTK_LIST()->selection/ mais on ne doit pas le -modifier car ses champs internes sont gérés par les fonctions -<em/gtk_list_*()/. - -Le champ <em/selection_mode/ détermine les options de sélection d'un -<em/GtkList/ et donc le contenu du champ du -<em/GTK_LIST()->selection/ : - -<em/selection_mode/ peut avoir l'une des valeurs suivantes : -<itemize> -<item> GTK_SELECTION_SINGLE - <em/selection/ vaut NULL ou contient un -pointeur vers un seul item sélectionné. - -<item> GTK_SELECTION_BROWSE - <em/selection/ vaut NULL si la liste ne -contient aucun widget ou seulement des widgets non sensitifs. Sinon, ce -champ contient un pointeur vers une seule structure Glist, et donc -vers exactement un item. - -<item> GTK_SELECTION_MULTIPLE - <em/selection/ vaut NULL si aucun item -n'est sélectionné ou pointe vers le premier item sélectionné. Ce -dernier point à son tour vers le second item, etc. - -<item> GTK_SELECTION_EXTENDED - <em/selection/ vaut toujours NULL. -</itemize> -<p> -La valeur par défaut est GTK_SELECTION_MULTIPLE. - -<sect1>Signaux -<p> -<tscreen><verb> -void GtkList::selection_changed (GtkList *LIST) -</verb></tscreen> - -Ce signal sera invoqué à chaque fois que le champ sélection d'un -GtkList a changé. Cela arrive lorsqu'un fils d'un GtkList a été -sélectionné ou désélectionné. - -<tscreen><verb> -void GtkList::select_child (GtkList *LIST, GtkWidget *CHILD) -</verb></tscreen> - -Ce signal est invoqué lorsqu'un fils du GtkList va être -sélectionné. Ceci arrive principalement lors d'appels à -<em/gtk_list_select_item(), gtk_list_select_child()/ et lors d'appuis -de boutons. Quelques fois, il est indirectement déclenché lorsque des -fils sont ajoutés ou supprimés du GtkList. - -<tscreen><verb> -void GtkList::unselect_child (GtkList *LIST, GtkWidget *CHILD) -</verb></tscreen> - -Ce signal est invoqué lorsqu'un fils du GtkList va être -désélectionné. Cela arrive principalement lors d'appels à -<em/gtk_list_unselect_item(), gtk_list_unselect_child()/, et lors -d'appuis de boutons. Quelques fois, il est indirectement déclenché -lorsque des fils sont ajoutés ou supprimés du GtkList. - - -<sect1>Fonctions -<p> -<tscreen><verb> -guint gtk_list_get_type (void) -</verb></tscreen> - -Retourne l'identificateur de type « GtkList ». - -<tscreen><verb> -GtkWidget* gtk_list_new (void) -</verb></tscreen> - -Crée un nouvel objet « GtkList ». Le nouveau widget est retourné sous -la forme d'un pointeur vers un objet « GtkWidget ». NULL est retourné -en cas d'erreur. - -<tscreen><verb> -void gtk_list_insert_items (GtkList *LIST, GList *ITEMS, gint POSITION) -</verb></tscreen> - -Insère des items dans <em/LIST/, à partir de <em/POSITION/. -<em/ITEMS/ est une liste doublement chaînée où chaque noeud doit -pointer vers un nouveau <em/GtkListItem/. Les noeuds <em/GList/ de -<em/ITEMS/ sont pris en charge par <em/LIST/. - - -<tscreen><verb> -void gtk_list_append_items (GtkList *LIST, GList *ITEMS) -</verb></tscreen> - -Insère des items à la fin de <em/LIST/ selon le même principe que -<em/gtk_list_insert_items/. Les noeuds <em/GList/ de <em/ITEMS/ sont -pris en charge par <em/LIST/. - -<tscreen><verb> -void gtk_list_prepend_items (GtkList *LIST, GList *ITEMS) -</verb></tscreen> - -Insère des items au début de <em/LIST/ selon le même principe que -<em/gtk_list_insert_items/. Les noeuds <em/GList/ de <em/ITEMS/ sont -pris en charge par <em/LIST/. - -<tscreen><verb> -void gtk_list_remove_items (GtkList *LIST, GList *ITEMS) -</verb></tscreen> - -Ôte des items de <em/LIST/. <em/ITEMS/ est une liste doublement -chaînée dont chaque noeud pointe vers un fils direct de <em/LIST/. Il -est de la responsabilité de l'appelant de faire un appel à -<em/g_list_free(ITEMS)/ après cela. L'appelant doit aussi détruire -lui-même les items. - -<tscreen><verb> -void gtk_list_clear_items (GtkList *LIST, gint START, gint END) -</verb></tscreen> - -Ôte et détruit des items de <em/LIST/. Un widget est concerné si sa -position courante dans <em/LIST/ est dans l'intervalle spécifié par -<em/START/ et <em/END/. - -<tscreen><verb> -void gtk_list_select_item (GtkList *LIST, gint ITEM) -</verb></tscreen> - -Invoque le signal <em/GtkList::select_child/ pour un item spécifié par -sa position courante dans <em/LIST/. - -<tscreen><verb> -void gtk_list_unselect_item (GtkList *LIST, gint ITEM) -</verb></tscreen> - -Invoque le signal <em/GtkList::unselect_child/ pour un item spécifié par -sa position courante dans <em/LIST/. - -<tscreen><verb> -void gtk_list_select_child (GtkList *LIST, GtkWidget *CHILD) -</verb></tscreen> - -Invoque le signal <em/GtkList::select_child/ pour le fils <em/CHILD/ spécifié. - -<tscreen><verb> -void gtk_list_unselect_child (GtkList *LIST, GtkWidget *CHILD) -</verb></tscreen> - -Invoque le signal <em/GtkList::unselect_child/ pour le fils <em/CHILD/ spécifié. - -<tscreen><verb> -gint gtk_list_child_position (GtkList *LIST, GtkWidget *CHILD) -</verb></tscreen> - -Retourne la position de <em/CHILD/ dans <em/LIST/. Retourne -1 en cas d'erreur. - -<tscreen><verb> -void gtk_list_set_selection_mode (GtkList *LIST, GtkSelectionMode MODE) -</verb></tscreen> - -Configure <em/LIST/ dans le mode de sélection <em/MODE/ qui peut être -GTK_SELECTION_SINGLE, GTK_SELECTION_BROWSE, GTK_SELECTION_MULTIPLE ou -GTK_SELECTION_EXTENDED. - -<tscreen><verb> -GtkList* GTK_LIST (gpointer OBJ) -</verb></tscreen> - -Convertit un pointeur générique en « <\em GtkList*\ ». Voir -<em/Standard Macros::/, pour plus d'informations. - -<tscreen><verb> -GtkListClass* GTK_LIST_CLASS (gpointer CLASS) -</verb></tscreen> - -Convertit un pointeur générique en « GtkListClass* ». Voir -<em/Standard Macros::/, pour plus d'informations. - -<tscreen><verb> -gint GTK_IS_LIST (gpointer OBJ) -</verb></tscreen> - -Détermine si un pointeur générique référence un objet « GtkList ». Voir -<em/Standard Macros::/, pour plus d'informations. - -<sect1>Exemple -<p> -Voici un programme affichant les changements de sélection dans une -<em/GtkList/ et permettant d'« emprisonner » des items en les -sélectionnant avec le bouton droit de la souris. - -<tscreen><verb> -/* Compilez ce programme avec : - * $ gcc -L/usr/X11R6/lib/ -I/usr/local/include/ -lgtk -lgdk -lglib -lX11 -lm -Wall main.c - */ -#include <gtk/gtk.h> -#include <stdio.h> - -/* Chaîne pour stocker les données dans les items de la liste. */ - -const gchar *list_item_data_key="list_item_data"; - - -/* prototypes des gestionnaires de signaux que l'on connectera au widget GtkList. */ - -static void sigh_print_selection (GtkWidget *gtklist, - gpointer func_data); -static void sigh_button_event (GtkWidget *gtklist, - GdkEventButton *event, - GtkWidget *frame); - - -/* fonction principale pour configurer l'interface utilisateur */ - -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]; - - - /* initialise gtk (et donc gdk) */ - - gtk_init(&argc, &argv); - - - /* Création d'une fenêtre pour placer tous les widgets. - * Connexion de gtk_main_quit() à l'événement "destroy" de - * la fenêtre afin de prendre en charge les événements « fermeture d'une - * fenêtre » du gestionnaire de fenêtre. */ - - window=gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_title(GTK_WINDOW(window), "Exemple de widget GtkList"); - gtk_signal_connect(GTK_OBJECT(window), - "destroy", - GTK_SIGNAL_FUNC(gtk_main_quit), - NULL); - - - /* À l'intérieur de la fenêtre, on a besoin d'une boîte pour placer - * verticalement les widgets. */ - - 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); - - /* Fenêtre à défilement pour placer le widget GtkList à l'intérieur. */ - - 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); - - /* Création du widget GtkList - * Connexion du gestionnaire de signal sigh_print_selection() au signal - * "selection_changed" du GtkList pour afficher les items sélectionnés - * à chaque fois que la sélection change. */ - - 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); - - /* Création d'une « Prison » pour y mettre un item. */ - - 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); - - /* Connexion du gestionnaire de signal sigh_button_event() au signal - * « mise au arrêts » des items du GtkList. */ - - gtk_signal_connect(GTK_OBJECT(gtklist), - "button_release_event", - GTK_SIGNAL_FUNC(sigh_button_event), - frame); - - /* Création d'un séparateur. */ - - separator=gtk_hseparator_new(); - gtk_container_add(GTK_CONTAINER(vbox), separator); - gtk_widget_show(separator); - - /* Création d'un bouton et connexion de son signal "clicked" à la - * destruction de la fenêtre. */ - - button=gtk_button_new_with_label("Fermeture"); - 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)); - - - /* Création de 5 items, chacun ayant son propre label. - * Ajout de ceux-ci au GtkList en utilisant gtk_container_add(). - * On interroge le texte du label et on l'associe avec - * list_item_data_key à chaque item. */ - - for (i=0; i<5; i++) { - GtkWidget *label; - gchar *string; - - sprintf(buffer, "ListItemContainer avec 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); - } - /* Création de 5 autres labels. Cette fois-ci, on utilise - * gtk_list_item_new_with_label(). On ne peut interroger la chaîne - * des labels car on n'a pas les pointeurs de labels et on associe - * donc simplement le list_item_data_key de chaque item ayant la même - * chaîne de texte pour l'ajouter au items que l'on place dans une liste - * doublement chaînée (GList). On les ajoute alors par un simple appel à - * gtk_list_append_items(). - * Comme on utilise g_list_prepend() pour mettre les items dans la liste - * doublement chaînée, leur ordre sera décroissant (au lieu d'être croissant si - * on utilisait g_list_append()). */ - - dlist=NULL; - for (; i<10; i++) { - sprintf(buffer, "Item avec le 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, - "Item avec label intégré"); - } - gtk_list_append_items(GTK_LIST(gtklist), dlist); - - /* Enfin, on veut voir la fenêtre... */ - - gtk_widget_show(window); - - /* Lancement de la boucle principale de gtk */ - - gtk_main(); - - /* On arrive ici après que gtk_main_quit() ait été appelée lorsque - * la fenêtre principale a été détruite. */ - -} - -/* Gestionnaire de signal connecté aux événements boutons presser/relâcher - * du GtkList. */ - -void -sigh_button_event (GtkWidget *gtklist, - GdkEventButton *event, - GtkWidget *frame) -{ - /* On ne fait quelque chose que si le troisième bouton (celui de droite) a été - * relâché. */ - - if (event->type==GDK_BUTTON_RELEASE && - event->button==3) { - GList *dlist, *free_list; - GtkWidget *new_prisoner; - - /* On recherche l'item sélectionné à ce moment précis. - * Ce sera notre prisonnier ! */ - - dlist=GTK_LIST(gtklist)->selection; - if (dlist) - new_prisoner=GTK_WIDGET(dlist->data); - else - new_prisoner=NULL; - - /* On recherche les items déjà prisonniers et on les - * remet dans la liste. - * Il ne faut pas oublier de libérer la liste doublement - * chaînée que gtk_container_children() retourne. */ - - 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); - - /* Si l'on a un nouveau prisonnier, on l'ôte du GtkList et on le place - * dans le cadre « Prison ». On doit désélectionner l'item avant. - - 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); - } - } -} - -/* Gestionnaire de signal appelé lorsque le GtkList - * émet le signal "selection_changed". */ - -void -sigh_print_selection (GtkWidget *gtklist, - gpointer func_data) -{ - GList *dlist; - - /* Recherche dans la liste doublement chaînée des items sélectionnés - * du GtkList, à faire en lecture seulement ! */ - - dlist=GTK_LIST(gtklist)->selection; - - /* S'il n'y a pas d'items sélectionné, il n'y a rien d'autre à faire que - * de le dire à l'utilisateur. */ - - if (!dlist) { - g_print("Sélection nettoyée\n"); - return; - } - /* Ok, on a une sélection et on l'affiche. */ - - g_print("La sélection est "); - - /* On récupère l'item dans la liste doublement chaînée - * puis on interroge la donnée associée par list_item_data_key - * et on l'affiche. */ - - 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"); -} -</verb></tscreen> - -<sect1>Widget item de liste -<p> -Le widget <em/GtkListItem/ sert de container pour contenir un fils, -lui fournissant des fonctions de sélection/déséselection exactement -comme le widget GtkList les demande pour ses fils. - -Un <em/GtkListItem/ a sa propre fenêtre pour recevoir les événements et a -sa propre couleur de fond, habituellement blanche. - -Comme il est directement dérivé d'un <em/GtkItem/, il peut être traité -comme tel en utilisant la macro GTK_ITEM(ListItem), reportez-vous à la -section sur le widget GtkItem pour plus de détail sur celui-ci. -Habituellement, un <em/GtkListItem/ contient juste un label pour -identifier, par exemple, un nom de fichier dans un <em/GtkList/ -- la -fonction appropriée <em/gtk_list_item_new_with_label()/ est donc -fournie. Le même effet peut être obtenu en créant un <em/GtkLabel/ à -part, en configurant son alignement avec <em/xalign/=0 et -<em/yalign/=0.5 suivi d'un ajout ultérieur au <em/GtkListItem/. - -Tout comme on n'est pas forcé d'ajouter un <em/GtkLabel/ à un -<em/GtkListItem/, on peut aussi ajouter un <em/GtkVBox/ ou un -<em/GtkArrow/ etc. à un <em/GtkListItem/. - -<sect1>Signaux -<p> -Un <em/GtkListItem/ ne crée pas de nouveaux signaux par lui-même, mais -hérite de ceux d'un <em/GtkItem/. Voir <em/GtkItem::/, pour plus -d'informations. - - -<sect1>Fonctions -<p> - -<tscreen><verb> -guint gtk_list_item_get_type (void) -</verb></tscreen> - -Retourne l'identificateur du type « GtkListItem ». - -<tscreen><verb> -GtkWidget* gtk_list_item_new (void) -</verb></tscreen> - -Création d'un objet <em/GtkListItem/. Le nouveau widget est retourné -sous la forme d'un pointeur vers un objet <em/GtkWidget/. NULL est -retourné en cas d'erreur. - -<tscreen><verb> -GtkWidget* gtk_list_item_new_with_label (gchar *LABEL) -</verb></tscreen> - -Création d'un objet <em/GtkListItem/ ayant un simple <em/GtkLabel/ -comme seul fils. Le nouveau widget est retourné sous la forme d'un -pointeur vers un objet <em/GtkWidget/. NULL est retourné en cas -d'erreur. - -<tscreen><verb> -void gtk_list_item_select (GtkListItem *LIST_ITEM) -</verb></tscreen> - -Cette fonction est surtout un emballage de <em/gtk_item_select -(GTK_ITEM (list_item))/ qui émettra le signal <em/GtkItem::select/. -Voir <em/GtkItem::/, pour plus d'informations. - -<tscreen><verb> -void gtk_list_item_deselect (GtkListItem *LIST_ITEM) -</verb></tscreen> - -Cette fonction est surtout un emballage de <em/gtk_item_deselect -(GTK_ITEM (list_item))/ qui émettra le signal -<em/GtkItem::deselect/. Voir <em/GtkItem::/, pour plus d'informations. - -<tscreen><verb> -GtkListItem* GTK_LIST_ITEM (gpointer OBJ) -</verb></tscreen> - -Convertit un pointeur générique en <em/GtkListItem*/. Voir -<em/Standard Macros::/ pour plus d'informations. - -<tscreen><verb> -GtkListItemClass* GTK_LIST_ITEM_CLASS (gpointer CLASS) -</verb></tscreen> - -Convertit un pointeur générique en <em/GtkListItemClass*/. Voir -<em/Standard Macros::/ pour plus d'informations. - -<tscreen><verb> -gint GTK_IS_LIST_ITEM (gpointer OBJ) -</verb></tscreen> - -Détermine si un pointeur générique se réfère à un objet -<em/GtkListItem/. Voir <em/Standard Macros::/ pour plus -d'informations. - -<sect1>Exemple -<p> -L'exemple des GtkList couvre aussi l'utilisation des -GtkListItem. Étudiez-le attentivement. - - -<sect>Widgets sélections de fichiers -<p> -Le widget sélection de fichier est un moyen simple et rapide pour -afficher un fichier dans une boîte de dialogue. Il est complet, avec -des boutons Ok, Annuler et Aide. C'est un bon moyen de raccourcir les -temps de programmation. - -Pour créer une boîte de sélection de fichier, on utilise : - -<tscreen><verb> -GtkWidget* gtk_file_selection_new (gchar *title); -</verb></tscreen> - -Pour configurer le nom de fichier, par exemple pour aller dans un -répertoire précis ou donner un nom de fichier par défaut, on utilise -la fonction : - -<tscreen><verb> -void gtk_file_selection_set_filename (GtkFileSelection *filesel, gchar *filename); -</verb></tscreen> - -Pour récupérer le texte que l'utilisateur a entré, ou sur lequel il a -cliqué, on utilisera la fonction : - -<tscreen><verb> -gchar* gtk_file_selection_get_filename (GtkFileSelection *filesel); -</verb></tscreen> - -Des pointeurs permettent d'accéder aux widgets contenus dans la widget -de sélection de fichiers. Ce sont : - -<itemize> -<item>dir_list -<item>file_list -<item>selection_entry -<item>selection_text -<item>main_vbox -<item>ok_button -<item>cancel_button -<item>help_button -</itemize> - -Le plus souvent, on utilise les pointeurs <em/ok_button, cancel_button/, et -<em/help_button/ pour préciser leurs utilisations. - -Voici un exemple emprunté à <em/testgtk.c/ et modifié pour fonctionner -tout seul. Comme vous le verrez, il n'y a pas grand chose à faire pour -créer un wigdget de sélection de fichier. Cependant, dans cet exemple, -si le bouton Aide apparaît à l'écran, il ne fait rien car aucun signal -ne lui est attaché. - -<tscreen><verb> -#include <gtk/gtk.h> - -/* Récupère le nom de fichier sélectionné et l'affiche sur la console. */ - -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); - - /* Création d'un widget de sélection de fichier. */ - - filew = gtk_file_selection_new ("File selection"); - - gtk_signal_connect (GTK_OBJECT (filew), "destroy", - (GtkSignalFunc) destroy, &filew); - - /* Connexion de ok_button à la fonction file_ok_sel() */ - - gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (filew)->ok_button), - "clicked", (GtkSignalFunc) file_ok_sel, filew ); - - /* Connexion de cancel_button pour détruire le widget */ - - gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION (filew)->cancel_button), - "clicked", (GtkSignalFunc) gtk_widget_destroy, - GTK_OBJECT (filew)); - - /* Configuration du nom de fichier, comme s'il s'agissait d'un dialogue de - * sauvegarde et que nous donnions un nom de fichier par défaut. */ - - gtk_file_selection_set_filename (GTK_FILE_SELECTION(filew), - "penguin.png"); - - gtk_widget_show(filew); - gtk_main (); - return 0; -} -</verb></tscreen> - -<sect>Widgets Menu -<p> -Il y a deux façons de créer des menus, la facile et la compliquée. Les -deux ont leur utilité, mais on peut généralement utiliser l'<em/usine -à menus/ (c'est la méthode facile...). La méthode « compliquée » -consiste à créer tous les menus en utilisant directement les -appels. La méthode facile consiste à utiliser les appels -<em/gtk_menu_factory/. C'est beaucoup plus simple, mais chaque -approche a ses avantages et inconvénients. - -L'usine à menus est beaucoup plus facile à utiliser, elle facilite -aussi l'ajout d'autres menus. Par contre, écrire quelques fonctions -permettant de créer des menus en utilisant la méthode manuelle peut -être le début d'un long chemin avant une quelconque utilisation. Avec -l'usine à menus, il n'est pas possible d'ajouter des images ou des « / -» aux menus. -<p> -<sect1>Création manuelle de menus -<p> -Selon la tradition pédagogique, nous commencerons par le plus compliqué <tt/:)/ -<p> -Regardons les fonctions utilisées pour créer les menus. La première sert à créer un nouveau menu. - -<tscreen><verb> -GtkWidget *gtk_menu_bar_new() -</verb></tscreen> - -Cette fonction crée une nouvelle barre de menu. On utilise la fonction -<em/gtk_container_add/ pour la placer dans une fenêtre, ou les -fonctions <em/box_pack/ pour la placer dans une boîte - la même que -pour les boutons. - -<tscreen><verb> -GtkWidget *gtk_menu_new(); -</verb></tscreen> - -Cette fonction retourne un pointeur vers un nouveau menu, il n'est -jamais montré (avec <em/gtk_widget_show/), il ne fait que contenir les -items du menu. Ceci deviendra plus clair lorsque nous étudierons -l'exemple ci-dessous. -<p> -Les deux appels suivants servent à créer des items de menu qui seront -placés dans le menu. - -<tscreen><verb> -GtkWidget *gtk_menu_item_new() -</verb></tscreen> - -et - -<tscreen><verb> -GtkWidget *gtk_menu_item_new_with_label(const char *label) -</verb></tscreen> - -Ces appels servent à créer les menus qui doivent être affichés. On -doit bien faire la différence entre un « menu » qui est créé avec -<em/gtk_menu_new()/ et un « item de menu » créé avec les fonctions -<em/gtk_menu_item_new()/. L'item de menu sera un véritable bouton avec -une action associée alors qu'un menu sera un container contenant les -items. - - -<tscreen><verb> -gtk_menu_item_append() - -gtk_menu_item_set_submenu() -</verb></tscreen> - -Les fonctions <em/gtk_menu_new_with_label()/ et <em/gtk_menu_new()/ -sont telles que vous les attendiez après avoir étudié les -boutons. L'une crée un nouvel item de menu contenant déjà un label, et -l'autre ne fait que créer un item de menu vide. -<p> -Voici les étapes pour créer une barre de menu avec des menus attachés : -<itemize> -<item>Créer un nouveau menu avec <em/gtk_menu_new()/ <item>Créer un -item de menu avec <em/gtk_menu_item_new()/. Ce sera la racine du -menu, le texte apparaissant ici sera aussi sur la barre de menu. -<item>Utiliser plusieurs appels à <em/gtk_menu_item_new()/ pour -chaque item que l'on désire dans le menu. Utiliser -<em/gtk_menu_item_append()/ pour placer chacun de ces items les uns -après les autres. Cela crée une liste d'items de menu. -<item>Utiliser <em/gtk_menu_item_set_submenu()/ pour attacher les -items de menus nouvellement créés à l'item de menu racine (celui créé -à la seconde étape). -<item>Créer une nouvelle barre de menu avec -<em/gtk_menu_bar_new()/. Cette étape ne doit être faite qu'une fois -lorsque l'on crée une série de menu sur une seule barre de menus. -<item>Utiliser <em/gtk_menu_bar_append()/ pour placer le menu racine -dans la barre de menu. -</itemize> -<p> -La création d'un menu surgissant est presque identique. La différence -est que le menu n'est pas posté « automatiquement » par une barre de -menu, mais explicitement en appelant la fonction <em/gtk_menu_popup()/ -par un événement « bouton pressé ». - -Suivez ces étapes  -<itemize> -<item>Créer une fonction de gestion d'événement. Elle doit avoir le prototype -<tscreen> -static gint handler(GtkWidget *widget, GdkEvent *event); -</tscreen> -et elle utilisera l'événement <em/event/ pour savoir où faire surgir -le menu. -<item>Ce gestionnaire, si l'événement est un appui sur un -bouton souris, traite <em/event/ comme un événement bouton (ce qu'il -est) et l'utilise, de la façon indiquée dans le code d'exemple, pour -passer l'information à <em/gtk_menu_popup()/. - -<item> Lier ce gestionnaire à un widget avec : -<tscreen> -gtk_signal_connect_object(GTK_OBJECT(widget), "event", - GTK_SIGNAL_FUNC (handler), GTK_OBJECT(menu)); -</tscreen> -où <em/widget/ est le widget auquel vous le liez, <em/handler/ est -le gestionnaire, et <em/menu/ est un menu créé avec -<em/gtk_menu_new()/. Cela peut être un menu qui est aussi posté par -une barre de menu, comme le montre l'exemple. -</itemize> -<p> -<sect1>Exemple de menu manuel -<p> -<tscreen><verb> - -#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); - - /* Création d'un fenêtre */ - - window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_title(GTK_WINDOW (window), "Test de Menu GTK"); - gtk_signal_connect(GTK_OBJECT (window), "delete_event", - (GtkSignalFunc) gtk_exit, NULL); - - /* Initialise le widget menu -- Attention : n'appelez jamais - * gtk_show_widget() pour le widget menu !!! - * C'est le menu qui contient les items de menu, celui qui surgira - * lorsque vous cliquez sur le « menu racine » de l'application. */ - - menu = gtk_menu_new(); - - /* Voici le menu racine dont le label sera le nom du menu affiché sur la barre - * de menu. Il n'a pas de gestionnaire de signal attaché car il ne fait - * qu'afficher le reste du menu lorsqu'il est pressé. */ - - root_menu = gtk_menu_item_new_with_label("Menu racine"); - - gtk_widget_show(root_menu); - - /* Puis, on crée une petite boucle créant trois entrées pour « menu test » - * Notez l'appel à gtk_menu_append(). Ici, on ajoute une liste d'items à - * notre menu. Normalement, on devrait aussi capturer le signal "clicked" - * pour chacun des items et configurer une fonction de rappel pour lui, - * mais on l'a omis ici pour gagner de la place. */ - - for(i = 0; i < 3; i++) - { - /* Copie des noms dans buf. */ - - sprintf(buf, "Sous-menu Test - %d", i); - - /* Création d'un nouveau item de menu avec un nom... */ - - menu_items = gtk_menu_item_new_with_label(buf); - - /* ...et ajout de celui-ci dans le menu. */ - - gtk_menu_append(GTK_MENU (menu), menu_items); - - /* On fait quelque chose d'intéressant lorsque l'item est - * sélectionné. */ - - gtk_signal_connect (GTK_OBJECT(menu_items), "activate", - GTK_SIGNAL_FUNC(menuitem_response), (gpointer) - g_strdup(buf)); - - /* Affichage du widget. */ - - gtk_widget_show(menu_items); - } - - /* Maintenant, on spécifié que nous voulons que notre nouveau « menu » - * soit le menu du « menu racine ». */ - - gtk_menu_item_set_submenu(GTK_MENU_ITEM (root_menu), menu); - - /* Création d'une vbox pour y mettre un menu et un bouton. */ - - vbox = gtk_vbox_new(FALSE, 0); - gtk_container_add(GTK_CONTAINER(window), vbox); - gtk_widget_show(vbox); - - /* Création d'une barre de menus pour contenir les menus. Puis, on - * l'ajoute à notre fenêtre principale. */ - - menu_bar = gtk_menu_bar_new(); - gtk_box_pack_start(GTK_BOX(vbox), menu_bar, FALSE, FALSE, 2); - gtk_widget_show(menu_bar); - - /* Création d'un bouton pour y attacher le menu. */ - - button = gtk_button_new_with_label("Pressez moi"); - 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); - - /* Finalement, on ajoute l'item de menu à la barre de menu -- - * c'est l'item de menu racine sur lequel je me suis déchaîné ;-) */ - - gtk_menu_bar_append(GTK_MENU_BAR (menu_bar), root_menu); - - /* Affichage de la fenêtre. */ - - gtk_widget_show(window); - - gtk_main (); - - return 0; -} - - - -/* On répond à un appui sur le bouton en postant un nouveau menu passé comme - * un widget. - * - * On remarque que le paramètre "widget" est le menu à poster, PAS le bouton - * qui a été pressé. */ - - -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); - - /* On indique à l'appelant que l'on a géré cet événement. */ - - return TRUE; - } - - /* On indique à l'appelant que l'on n'a pas géré cet événement. */ - - return FALSE; -} - - -/* Affiche une chaîne lorsqu'un item de menu est choisi. */ - -static void menuitem_response (GtkWidget *widget, gchar *string) -{ - printf("%s\n", string); -} -</verb></tscreen> - -Vous pouvez aussi configurer un item de menu pour qu'il ne soit pas -sélectionnable et, en utilisant une table de raccourcis clavier, lier -des touches aux fonctions du menu. -<p> -<sect1>Utilisation de GtkMenuFactory -<p> -Maintenant que nous avons exploré la voie difficile, nous allons voir -l'utilisation des appels <em/gtk_menu_factory./ -<p> -<sect1>Exemple d'usine à menu -<p> -Voici un exemple utilisant l'usine à menu de GTK. Le premier -fichier est <em/menus.h/. Nous séparerons <em/menus.c/ et <em/main.c/ à -cause des variables globales utilisées dans le fichier <em/menus.c/. - -<tscreen><verb> -#ifndef __MENUS_H__ -#define __MENUS_H__ - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -void get_main_menu (GtkWidget **menubar, GtkAcceleratorTable **table); -void menus_create(GtkMenuEntry *entries, int nmenu_entries); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __MENUS_H__ */ -</verb></tscreen> -<p> -Voici le fichier <em/menus.c/ : - -<tscreen><verb> - -#include <gtk/gtk.h> -#include <strings.h> - -#include "main.h" - - -static void menus_remove_accel(GtkWidget * widget, gchar * signal_name, gchar * path); -static gint menus_install_accel(GtkWidget * widget, gchar * signal_name, gchar key, gchar modifiers, gchar * path); -void menus_init(void); -void menus_create(GtkMenuEntry * entries, int nmenu_entries); - - -/* Structure GtkMenuEntry utilisée pour créer les menus. Le premier champ - * est la chaîne de définition du menu. Le second, la touche de raccourci - * utilisée pour accéder à cette fonction du menu avec le clavier. - * Le troisième est la fonction de rappel à utiliser lorsque l'item de menu - * est choisi (par la touche de raccourci ou avec la souris). Le dernier - * élément est la donnée à passer à la fonction de rappel. */ - - -static GtkMenuEntry menu_items[] = -{ - {"<Main>/Fichier/Nouveau", "<control>N", NULL, NULL}, - {"<Main>/Fichier/Ouvrir", "<control>O", NULL, NULL}, - {"<Main>/Fichier/Sauver", "<control>S", NULL, NULL}, - {"<Main>/Fichier/Sauver sous", NULL, NULL, NULL}, - {"<Main>/Fichier/<separator>", NULL, NULL, NULL}, - {"<Main>/Fichier/Quitter", "<control>Q", file_quit_cmd_callback, "OK, c'est fini"}, - {"<Main>/Options/Test", NULL, NULL, NULL} -}; - -/* Calcul du nombre d'éléments de menu_item */ - -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("Impossible de configurer la sensitivité d'un menu qui n'existe pas : %s", path); -} - -</verb></tscreen> -<p> -Voici <em/main.h/ : - -<tscreen><verb> -#ifndef __MAIN_H__ -#define __MAIN_H__ - - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -void file_quit_cmd_callback(GtkWidget *widget, gpointer data); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __MAIN_H__ */ - -</verb></tscreen> -<p> -Et, enfin, <em/main.c/ : - -<tscreen><verb> -#include <gtk/gtk.h> - -#include "main.h" -#include "menus.h" - - -int main(int argc, char *argv[]) -{ - GtkWidget *window; - GtkWidget *main_vbox; - GtkWidget *menubar; - - GtkAcceleratorTable *accel; - - gtk_init(&argc, &argv); - - window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_signal_connect(GTK_OBJECT(window), "destroy", - GTK_SIGNAL_FUNC(file_quit_cmd_callback), - "WM destroy"); - gtk_window_set_title(GTK_WINDOW(window), "Usine à menu"); - 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); -} - -/* Juste une démonstration du fonctionnement des fonctions de rappel - * lorsqu'on utilise l'usine à menus. Souvent, on met tous les rappels - * des menus dans un fichier séparé, ce qui assure une meilleure - * organisation. */ - -void file_quit_cmd_callback (GtkWidget *widget, gpointer data) -{ - g_print ("%s\n", (char *) data); - gtk_exit(0); -} -</verb></tscreen> -<p> -Un <em/makefile/ pour que cela soit plus facile à compiler : - -<tscreen><verb> -CC = gcc -PROF = -g -C_FLAGS = -Wall $(PROF) -L/usr/local/include -DDEBUG -L_FLAGS = $(PROF) -L/usr/X11R6/lib -L/usr/local/lib -L_POSTFLAGS = -lgtk -lgdk -lglib -lXext -lX11 -lm -PROGNAME = at - -O_FILES = menus.o main.o - -$(PROGNAME): $(O_FILES) - rm -f $(PROGNAME) - $(CC) $(L_FLAGS) -o $(PROGNAME) $(O_FILES) $(L_POSTFLAGS) - -.c.o: - $(CC) -c $(C_FLAGS) $< - -clean: - rm -f core *.o $(PROGNAME) nohup.out -distclean: clean - rm -f *~ -</verb></tscreen> -<p> -Pour l'instant, il n'y a que cet exemple. Une explication et de nombreux commentaires seront intégrés plus tard. - - -<sect>Widgets non documentés -<p> -On a besoin de leurs auteurs! :). Participez à notre didacticiel. - -Si vous devez utiliser un de ces widgets non documentés, je vous recommande fortement de consulter leurs fichiers en-têtes respectifs dans la distribution GTK. Les noms de fonctions du GTK sont très parlantes. Lorsque vous avez compris comment les choses fonctionnent, il n'est pas difficile de savoir comment utiliser un widget à partir des déclarations de ses fonctions. Cela, avec quelques exemples de codes pris ailleurs, devrait ne pas poser de problème. - -Lorsque vous avez compris toutes les fonctions d'un nouveau widget non documenté, pensez à écrire un didacticiel pour que les autres puissent bénéficier du temps que vous y avez passé. - -<sect1>Entrées de texte -<p> - -<sect1>Sélections de couleurs -<p> - -<sect1>Contrôle d'intervalle -<p> - -<sect1>Règles -<p> - -<sect1>Boîtes de texte -<p> - -<sect1>Prévisualisation -<p> -(Ceci peut devoir être réécrit pour suivre le style du reste de ce -didacticiel). - -<tscreen><verb> - -Les prévisualisateurs servent à plusieurs choses dans GIMP/GTK. La -plus importante est celle-ci : les images de haute qualité peuvent -occuper des dizaines de mega-octets en mémoire - facilement ! Toute -opération sur une image aussi grosse implique un temps de traitement -élevé. Si cela vous prend 5 à 10 essais (i.e. 10 à 20 étapes puisque -vous devez recommencer lorsque vous avez fait une erreur) pour choisir -la bonne modification, cela prendra littéralement des heures pour -produire la bonne image - pour peu que vous ne manquiez pas de mémoire -avant. Ceux qui on passé des heures dans les chambres noires de -développement couleur connaissent cette sensation. Les -prévisualisations sont notre planche de salut ! - -L'aspect pénible de l'attente n'est pas le seul problème. souvent, il -est utile de comparer les versions « Avant » et « Après » côte à côte -ou, au pire l'une après l'autre. Si vous travaillez avec de grosses -images et des attentes de 10 secondes, l'obtention des versions « -Avant » et « Après » est, pour le moins, difficile. Pour des images de -30Mo (4"x6", 600dpi, 24 bits), la comparaison côte à côte est -impossible pour la plupart des gens, et la comparaison séquentielle -n'est guère mieux. Les prévisualisations sont notre planche de salut ! - -Mais il y a plus. Les prévisualisations permettent les -pré-prévisualisations côte à côte. En d'autres termes, vous écrivez un -plug-in (par exemple la simulation filterpack) qui aurait plusieurs -prévisualisations de ce-que-ce-serait-si-vous-faisiez-ceci. Une approche -comme celle ci agit comme une sorte de palette de prévisualisation et -est très pratique pour les petites modifications. Utilisons les -prévisualisations ! - -Encore plus : pour certains plug-ins une intervention humaine en -temps réel, spécifique aux images, peut s'avérer nécessaire. Dans le -plug-in SuperNova, par exemple, on demande à l'utilisateur d'entrer -les coordonnées du centre de la future supernova. La façon la plus -simple de faire cela, vraiment, est de présenter une prévisualisation -à l'utilisateur et de lui demander de choisir interactivement le -point. Utilisons les prévisualisations ! - -Enfin, quelques utilisations diverses : on peut utiliser les -prévisualisations, même lorsqu'on ne travaille pas avec de grosses -images. Elles sont utiles, par exemple, lorsqu'on veut avoir un rendu -de motifs complexes. (Testez le vénérable plug-in Diffraction et -d'autres !). Comme autre exemple, regardez le plug-in de rotation de -couleur (travail en cours). Vous pouvez aussi utiliser les -prévisualisations pour des petits logos dans vos plug-ins et même pour -une photo de vous, l'Auteur. Utilisons les prévisualisations ! - -Quand ne pas utiliser les prévisualisations - -N'utilisez pas les prévisualisations pour les graphes, les tracés, -etc. GDK est bien plus rapide pour ça. N'utilisez les que pour les -images ! - -Utilisons les prévisualisations ! - -Vous pouvez mettre une prévisualisation dans à peu près n'importe -quoi. Dans une vbox, une hbox, un bouton, etc. Mais elles donnent leur -meilleur d'elles-mêmes dans des cadres resserrés autour d'elles. Les -prévisualisations n'ont, par elles-mêmes, aucun contour et semblent -plates sans eux. (Bien sûr, si c'est cet aspect que vous -voulez...). Les cadres serrés fournissent les bordures nécessaires. - - [Image][Image] - -Les prévisualisations sont, à bien des égards, comme tous les autres -widgets de GTK (avec tout ce que cela implique) sauf qu'il disposent -d'une fonctionnalité supplémentaire : ils doivent être remplis -avec une image ! Nous traiterons d'abord exclusivement de l'aspect GTK -des prévisualisations, puis nous verrons comment les remplir. - - - /* Création d'un widget prévisualisation, - * configuration de sa taille et affichage */ -GtkWidget *preview; -preview=gtk_preview_new(GTK_PREVIEW_COLOR) - /* Autre option : - GTK_PREVIEW_GRAYSCALE);*/ - -gtk_preview_size (GTK_PREVIEW (preview), WIDTH, HEIGHT); -gtk_widget_show(preview); -my_preview_rendering_function(preview); - -Ah oui, comme je le disais, les prévisualisations rendent mieux dans -des cadres : - -GtkWidget *create_a_preview(int Width, - int Height, - int Colorfulness) -{ - GtkWidget *preview; - GtkWidget *frame; - - frame = gtk_frame_new(NULL); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); - gtk_container_border_width (GTK_CONTAINER(frame),0); - gtk_widget_show(frame); - - preview=gtk_preview_new (Colorfulness?GTK_PREVIEW_COLOR - :GTK_PREVIEW_GRAYSCALE); - gtk_preview_size (GTK_PREVIEW (preview), Width, Height); - gtk_container_add(GTK_CONTAINER(frame),preview); - gtk_widget_show(preview); - - my_preview_rendering_function(preview); - return frame; -} - -Ceci est ma prévisualisation de base. Cette fonction retourne le cadre -« père », on peut ainsi le placer ailleurs dans notre interface. Bien -sûr, on peut passer le cadre « père » en paramètre à cette -fonction. Dans de nombreuses situations, toutefois, le contenu de la -prévisualisation est changée continuellement par notre application. En -ce cas, on peut passer un pointeur vers une prévisualisation à la -fonction <em/create_a_preview()/ et avoir ainsi un contrôle sur elle -plus tard. - -Un point plus important qui pourra un jour vous faire économiser -beaucoup de temps. Quelques fois, il est souhaitable de mettre un -label à votre prévisualisation. Par exemple, on peut nommer la -prévisualisation contenant l'image originale « Original » et celle -contenant l'image modifiée « Moins Originale ». Il peut vous arriver -de placer la prévisualisation avec le label approprié dans une -vbox. L'effet inattendu est que si le label est plus large que la -prévisualisation (taille de cette dernière, taille de la fonte du -label, etc), le cadre s'élargit et ne convient plus à la -prévisualisation. Le même problème se passera probablement dans -d'autres situations aussi. - - [Image] - -La solution consiste à placer la prévisualisation et le label dans une -table de 2x2 en les attachant avec les paramètres suivants (c'est -l'une des possibilités, bien sûr. La clé consiste à ne pas mettre -GTK_FILL dans le second attachement)«nbsp;: - -gtk_table_attach(GTK_TABLE(table),label,0,1,0,1, - 0, - GTK_EXPAND|GTK_FILL, - 0,0); -gtk_table_attach(GTK_TABLE(table),frame,0,1,1,2, - GTK_EXPAND, - GTK_EXPAND, - 0,0); - - -Et voici le résultat : - - [Image] - -Divers - -Rendre une prévisualisation cliquable se fait très facilement en la plaçant dans un bouton. Cela ajoute aussi une bordure agréable autour de la prévisualisation et vous n'avez même pas besoin de la mettre dans un cadre. Voir le plug-in Filter Pack Simulation comme exemple. - -Remplir une prévisualisation - -Afin de nous familiariser avec les bases de ce remplissage, créons le motif suivant : - - [Image] - -void -my_preview_rendering_function(GtkWidget *preview) -{ -#define SIZE 100 -#define HALF (SIZE/2) - - guchar *row=(guchar *) malloc(3*SIZE); /* 3 bits par point */ - gint i, j; /* Coordonnées */ - double r, alpha, x, y; - - if (preview==NULL) return; /* J'ajoute généralement ceci quand je */ - /* veux éviter des plantages stupides */ - /* Vous devez vous assurer que tout a */ - /* été correctement initialisé ! */ - - for (j=0; j < ABS(cos(2*alpha)) ) { /* Sommes-nous dans la forme ? */ - /* glib.h contient ABS(x). */ - row[i*3+0] = sqrt(1-r)*255; /* Definit rouge */ - row[i*3+1] = 128; /* Definit vert */ - row[i*3+2] = 224; /* Definit bleu */ - } /* "+0" est pour l'alignement ! */ - else { - row[i*3+0] = r*255; - row[i*3+1] = ABS(sin((float)i/SIZE*2*PI))*255; - row[i*3+2] = ABS(sin((float)j/SIZE*2*PI))*255; - } - } - gtk_preview_draw_row( GTK_PREVIEW(preview),row,0,j,SIZE); - - /* Insère "row" dans "preview" en partant du point de */ - /* coordonnées (0,j) première colonne, j_ième ligne allant de SIZE */ - /* pixels vers la droite */ - } - - free(row); /* on récupère un peu d'espace */ - gtk_widget_draw(preview,NULL); /* qu'est-ce que ça fait ? */ - gdk_flush(); /* et ça ? */ -} - -Ceux qui n'utilisent pas GIMP en ont suffisamment vu pour faire -déjà beaucoup de choses. Pour ceux qui l'utilisent, j'ai quelques -précisions à ajouter. - -Prévisualisation d'image - -Il est pratique de conserver une version réduite de l'image ayant -juste assez de pixels pour remplir la prévisualisation. Ceci est -possible en choisissant chaque énième pixel où n est le ratio de la -taille de l'image par rapport à la taille de la visualisation. Toutes -les opérations suivantes (y compris le remplissage des -prévisualisations) sont alors réalisées seulement sur le nombre réduit -de pixels. Ce qui suit est mon implantation de la réduction d'image -(Gardez à l'esprit que je n'ai que quelques notions de base en C !). - -(ATTENTION : CODE NON TESTÉ !!!) - -typedef struct { - gint width; - gint height; - gint bbp; - guchar *rgb; - guchar *mask; -} ReducedImage; - -enum { - SELECTION_ONLY, - SELCTION_IN_CONTEXT, - ENTIRE_IMAGE -}; - -ReducedImage *Reduce_The_Image(GDrawable *drawable, - GDrawable *mask, - gint LongerSize, - gint Selection) -{ - /* Cette fonction réduit l'image à la taille de prévisualisation choisie */ - /* La taille de la prévisualisation est déterminée par LongerSize, i.e. */ - /* la plus grande des deux dimensions. Ne fonctionne qu'avec des images */ - /* RGB ! */ - - gint RH, RW; /* Hauteur et Largeur réduites */ - gint width, height; /* Largeur et Hauteur de la surface à réduire */ - gint bytes=drawable->bpp; - ReducedImage *temp=(ReducedImage *)malloc(sizeof(ReducedImage)); - - guchar *tempRGB, *src_row, *tempmask, *src_mask_row,R,G,B; - gint i, j, whichcol, whichrow, x1, x2, y1, y2; - GPixelRgn srcPR, srcMask; - gint NoSelectionMade=TRUE; /* Suppose que l'on traite l'image entière */ - - gimp_drawable_mask_bounds (drawable->id, &x1, &y1, &x2, &y2); - width = x2-x1; - height = y2-y1; - /* S'il y a une SELECTION, on récupère ses frontières ! */ - - if (width != drawable->width && height != drawable->height) - NoSelectionMade=FALSE; - /* On vérifie si l'utilisateur a rendu une sélection active */ - /* Ceci sera important plus tard, lorsqu'on créera un masque réduit */ - - /* Si on veut prévisualiser l'image entière, supprimer ce qui suit ! */ - /* Bien sûr, s'il n'y a pas de sélection, cela n'a aucun effet ! */ - if (Selection==ENTIRE_IMAGE) { - x1=0; - x2=drawable->width; - y1=0; - y2=drawable->height; - } - - /* Si on veut prévisualiser une sélection avec une surface qui l'entoure, */ - /* on doit l'agrandir un petit peu. Considérez ça comme une devinette. */ - - if (Selection==SELECTION_IN_CONTEXT) { - x1=MAX(0, x1-width/2.0); - x2=MIN(drawable->width, x2+width/2.0); - y1=MAX(0, y1-height/2.0); - y2=MIN(drawable->height, y2+height/2.0); - } - - /* Calcul de la largeur et de la hauteur de la surface à réduire. */ - - width = x2-x1; - height = y2-y1; - - /* Les lignes ci-dessous déterminent la dimension qui sera le coté */ - /* le plus long. Cette idée est empruntée au plug-in Supernova. */ - /* Je soupçonne que j'aurais pu y penser moi-même, mais la vérité */ - /* doit être dite. Le plagiat pue ! */ - - if (width>height) { - RW=LongerSize; - RH=(float) height * (float) LongerSize/ (float) width; - } - else { - RH=LongerSize; - RW=(float)width * (float) LongerSize/ (float) height; - } - - /* L'image entière est réduite dans une chaîne ! */ - - tempRGB = (guchar *) malloc(RW*RH*bytes); - tempmask = (guchar *) malloc(RW*RH); - - gimp_pixel_rgn_init (&srcPR, drawable, x1, y1, width, height, FALSE, FALSE); - gimp_pixel_rgn_init (&srcMask, mask, x1, y1, width, height, FALSE, FALSE); - - /* Réservation pour sauver une ligne d'image et une ligne du masque */ - src_row = (guchar *) malloc (width*bytes); - src_mask_row = (guchar *) malloc (width); - - for (i=0; i < RH; i++) { - whichrow=(float)i*(float)height/(float)RH; - gimp_pixel_rgn_get_row (&srcPR, src_row, x1, y1+whichrow, width); - gimp_pixel_rgn_get_row (&srcMask, src_mask_row, x1, y1+whichrow, width); - - for (j=0; j < RW; j++) { - whichcol=(float)j*(float)width/(float)RW; - - /* Pas de sélection = chaque point est complètement sélectionné ! */ - - if (NoSelectionMade) - tempmask[i*RW+j]=255; - else - tempmask[i*RW+j]=src_mask_row[whichcol]; - - /* Ajout de la ligne à la longue chaîne qui contient maintenant */ - /* l'image ! */ - - tempRGB[i*RW*bytes+j*bytes+0]=src_row[whichcol*bytes+0]; - tempRGB[i*RW*bytes+j*bytes+1]=src_row[whichcol*bytes+1]; - tempRGB[i*RW*bytes+j*bytes+2]=src_row[whichcol*bytes+2]; - - /* On s'accroche aussi à l'alpha */ - if (bytes==4) - tempRGB[i*RW*bytes+j*bytes+3]=src_row[whichcol*bytes+3]; - } - } - temp->bpp=bytes; - temp->width=RW; - temp->height=RH; - temp->rgb=tempRGB; - temp->mask=tempmask; - return temp; -} - -La suite est une fonction de prévisualisation qui utilise le même type -<em/ReducedImage/ ! On remarque qu'elle utilise une fausse -transparence (au moyen de <em/fake_transparancy/ qui est défini comme -suit : - -gint fake_transparency(gint i, gint j) -{ - if ( ((i%20)- 10) * ((j%20)- 10)>0 ) - return 64; - else - return 196; -} - -Voici maintenant la fonction de prévisualisation«nbsp;: - -void -my_preview_render_function(GtkWidget *preview, - gint changewhat, - gint changewhich) -{ - gint Inten, bytes=drawable->bpp; - gint i, j, k; - float partial; - gint RW=reduced->width; - gint RH=reduced->height; - guchar *row=malloc(bytes*RW);; - - - for (i=0; i < RH; i++) { - for (j=0; j < RW; j++) { - - row[j*3+0] = reduced->rgb[i*RW*bytes + j*bytes + 0]; - row[j*3+1] = reduced->rgb[i*RW*bytes + j*bytes + 1]; - row[j*3+2] = reduced->rgb[i*RW*bytes + j*bytes + 2]; - - if (bytes==4) - for (k=0; k<3; k++) { - float transp=reduced->rgb[i*RW*bytes+j*bytes+3]/255.0; - row[3*j+k]=transp*a[3*j+k]+(1-transp)*fake_transparency(i,j); - } - } - gtk_preview_draw_row( GTK_PREVIEW(preview),row,0,i,RW); - } - - free(a); - gtk_widget_draw(preview,NULL); - gdk_flush(); -} - -Fonctions applicables - -guint gtk_preview_get_type (void); -/* Aucune idée */ -void gtk_preview_uninit (void); -/* Aucune idée */ -GtkWidget* gtk_preview_new (GtkPreviewType type); -/* Décrite ci-dessous */ -void gtk_preview_size (GtkPreview *preview, - gint width, - gint height); -/* Permet de changer la taille d'une prévisualisation existante */ -/* Apparamment, il y a un bug dans GTK qui rend ce traitement */ -/* hasardeux. Une méthode pour corriger ce problème consiste à */ -/* changer manuellement la taille de la fenêtre contenant la */ -/* prévisualisation après avoir changé la taille de la */ -/* prévisualisation. */ - -void gtk_preview_put (GtkPreview *preview, - GdkWindow *window, - GdkGC *gc, - gint srcx, - gint srcy, - gint destx, - gint desty, - gint width, - gint height); -/* Aucune idée */ - -void gtk_preview_put_row (GtkPreview *preview, - guchar *src, - guchar *dest, - gint x, - gint y, - gint w); -/* Aucune idée */ - -void gtk_preview_draw_row (GtkPreview *preview, - guchar *data, - gint x, - gint y, - gint w); -/* Décrite dans le texte */ - -void gtk_preview_set_expand (GtkPreview *preview, - gint expand); -/* Aucune idée */ - -/* Aucune piste pour celles qui suivent mais devrait être */ -/* un standard pour la plupart des widgets. */ - -void gtk_preview_set_gamma (double gamma); -void gtk_preview_set_color_cube (guint nred_shades, - guint ngreen_shades, - guint nblue_shades, - guint ngray_shades); -void gtk_preview_set_install_cmap (gint install_cmap); -void gtk_preview_set_reserved (gint nreserved); -GdkVisual* gtk_preview_get_visual (void); -GdkColormap* gtk_preview_get_cmap (void); -GtkPreviewInfo* gtk_preview_get_info (void); - -That's all, folks! - -</verb></tscreen> - - -<sect1>Courbes -<p> - - -<sect>Widget EventBox <label id="sec_The_EventBox_Widget"> -<p> -Il n'est disponible que dans <em/gtk+970916.tar.gz/ et les -distributions ultérieures. <p> Certains widgets GTK n'ont pas de -fenêtre X associée, il se dessinent donc sur leurs parents. À cause de -cela, ils ne peuvent recevoir d'événements et, s'ils ont une taille -incorrecte, ils ne peuvent pas se mettre en place correctement : on peut -alors avoir des surimpressions douteuses, etc. Si vous avez besoin de -ces widgets, <em/EventBox/ est fait pour vous. - -Au premier abord, le widget <em/EventBox/ peut apparaître comme -totalement dénué d'intérêt. Il ne dessine rien à l'écran et ne répond -à aucun évenement. Cependant, il joue un rôle - il fournit une fenêtre -X pour son widget fils. Ceci est important car de nombreux widgets GTK -n'ont pas de fenêtre X associée. Ne pas avoir de fenêtre permet -d'économiser de la mémoire mais a aussi quelques inconvénients. Un -widget sans fenêtre ne peut recevoir d'événement, et ne réalise aucune -mise en place de ce qu'il contient. Bien que le nom « EventBox » -insiste sur la fonction de gestion d'événement, le widget peut aussi -être utilisé pour la mise en place (et plus... voir l'exemple -ci-dessous). - -<p> -Pour créer un widget EventBox, on utilise : - -<tscreen><verb> -GtkWidget* gtk_event_box_new (void); -</verb></tscreen> - -<p> -Un widget fils peut alors être ajouté à cet <em/EventBox/ : - -<tscreen><verb> -gtk_container_add (GTK_CONTAINER(event_box), widget); -</verb></tscreen> - -<p> -L'exemple suivant montre l'utilisation d'un <em/EventBox/ - un label -est créé et mis en place sur une petite boîte, et configuré pour qu'un -clic souris sur le label provoque la fin du programme. - -<tscreen><verb> -#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); - - /* Création d'un EventBox et ajout de celui-ci dans la fenêtre. */ - - event_box = gtk_event_box_new (); - gtk_container_add (GTK_CONTAINER(window), event_box); - gtk_widget_show (event_box); - - /* Création d'un long label */ - - label = gtk_label_new ("Cliquez ici pour quitter, quitter, quitter, quitter, quitter"); - gtk_container_add (GTK_CONTAINER (event_box), label); - gtk_widget_show (label); - - /* Placement serré. */ - - gtk_widget_set_usize (label, 110, 20); - - /* Attachement d'une action à celui-ci. */ - - 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); - - /* Encore une fois, vous avez besoin d'une fenêtre X pour... */ - - 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; -} -</verb></tscreen> - -<sect>Configuration des attributs de widget<label -id="sec_setting_widget_attributes"> -<p> -Cette section décrit les fonctions opérant sur les widgets. Elles -peuvent être utilisées pour configurer le style, l'espacement, la -taille, etc. - -(Je devrais peut être faire une section uniquement consacrée aux -raccourcis clavier.) - -<tscreen><verb> -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); -</verb></tscreen> - - - -<sect>Temporisations, fonctions d'E/S et d'attente<label id="sec_timeouts"> -<p> -<sect1>Temporisations -<p> -Vous pouvez vous demander comment faire pour que GTK fasse quelque -chose d'utile lorsqu'il est dans <em/gtk_main/. En fait, on a -plusieurs options. L'utilisation des fonctions suivantes permet de -créer une temporisation qui sera appelée tous les -<em/interval/ millisecondes. - -<tscreen><verb> -gint gtk_timeout_add (guint32 interval, - GtkFunction function, - gpointer data); -</verb></tscreen> - -Le premier paramètre est le nombre de millisecondes entre les appels à -notre fonction. Le deuxième est la fonction à appeler et le troisième -est la donnée passée à cette fonction de rappel. La valeur retournée -est un « marqueur » de type entier qui pourra être utilisé pour -arrêter la temporisation en appelant : - -<tscreen><verb> -void gtk_timeout_remove (gint tag); -</verb></tscreen> - -On peut aussi stopper la fonction de temporisation en faisant -retourner zéro ou FALSE à notre fonction de rappel. Évidemment, cela -veut dire que si vous voulez que votre fonction continue à être -appelée, elle doit retourner une valeur non nulle, ou TRUE. - -La déclaration de votre fonction de rappel doit ressembler à ça : - -<tscreen><verb> -gint timeout_callback (gpointer data); -</verb></tscreen> - -<sect1>Surveillance des E/S -<p> -Une autre caractéristique intéressante du GTK est la possibilité de -vérifier les données d'un descripteur de fichier (celles retournées -par <em/open/(2) ou <em/socket/(2)). C'est particulièrement pratique pour les -applications réseau. La fonction suivante permet cette -vérification : - -<tscreen><verb> -gint gdk_input_add (gint source, - GdkInputCondition condition, - GdkInputFunction function, - gpointer data); -</verb></tscreen> - -Le premier paramètre est le descripteur de fichier que l'on veut -étudier, le second spécifie ce qu'on veut que le GDK recherche. Cela -peut être : -<p> -GDK_INPUT_READ - Appel <em/function/ lorsqu'il y a une donnée prête à -être lue dans le descripteur de fichier. -<p> -GDK_INPUT_WRITE - Appel de <em/function/ lorsque le descripteur de -fichier est prêt pour une écriture. -<p> -Je suis sûr que vous vous doutez, maintenant, que le troisième -paramètre est la fonction que l'on veut appeler lorsque les conditions -ci-dessus sont satisfaites. Le dernier paramètre est la donnée à -passer à cette fonction. -<p> -La valeur retournée est un marqueur qui pourra être utilisé pour dire -au GDK de cesser de surveiller ce descripteur à l'aide de la fonction : -<p> -<tscreen><verb> -void gdk_input_remove (gint tag); -</verb></tscreen> -<p> -La fonction de rappel doit être déclarée de la façon suivante : -<p> -<tscreen><verb> -void input_callback (gpointer data, gint source, - GdkInputCondition condition); -</verb></tscreen> -<p> - -<sect1>Fonctions d'attente -<p> -Que se passe-t'il si vous avez une fonction qui doit être appelée -lorsque rien d'autre ne se passe ? On utilise la fonction suivante qui force -GTK à appeler <em/function/ lorsqu'on est en phase d'inaction ; - -<tscreen><verb> -gint gtk_idle_add (GtkFunction function, - gpointer data); -</verb></tscreen> - -<tscreen><verb> -void gtk_idle_remove (gint tag); -</verb></tscreen> -<p> -Je n'expliquerai pas la signification des paramètres car ils -ressemblent beaucoup à ceux déjà vus ci-dessus. La fonction pointée -par le premier paramètre de <em/gtk_idle_add()/ sera appelée à chaque -occasion. Comme pour les autres, retourner FALSE empêchera la fonction -d'attente d'être appelée. - -<sect>Gestion des sélections - -<sect1>Introduction -<p> -Un type de communication inter-processus gérée par GTK est les -<em>sélections</em>. Une sélection identifie un morceau de données, -par exemple une portion de texte sélectionnée par l'utilisateur avec -la souris. Seule une application sur un écran (le <em/propriétaire/) -peut posséder une sélection particulière à un moment donné, ainsi -lorsqu'une sélection est réclamée par une application, le propriétaire -précédent doit indiquer à l'utilisateur que la sélection a été -abandonnée. Les autres applications peuvent demander le contenu d'une -sélection sous différentes formes appelées <em/cibles/. Il peut y -avoir un nombre quelconque de sélections, mais la plupart des -applications X n'en gèrent qu'une, la <em/sélection primaire/. - -<p> -Dans la plupart des cas, une application GTK n'a pas besoin de gérer elle-même -les sélections. Les widgets standards, comme le widget Entrée de texte, -possèdent déjà la capacité de réclamer la sélection lorsqu'il le faut (par -exemple, lorsque l'utilisateur glisse au dessus d'un texte) et de récupérer le -contenu de la sélection détenue par un autre widget ou une autre application -(par exemple, lorsque l'utilisateur clique avec le deuxième bouton de la -souris). Cependant, il peut il y avoir des cas dans lesquels vous voulez donner -aux autres widgets la possibilité de fournir la sélection, ou vous désirez -récupérer des cibles non supportées par défaut. - -<p> -Un concept fondamental dans la compréhension du fonctionnement des -sélections est celui d'<em/atome/. Un atome est un entier qui définit -de façon unique une chaîne (sur un affichage particulier). Certains -atomes sont prédéfinis par le serveur X et, dans certains cas, des -constantes définies dans <em/gtk.h/ correspondent à ces atomes. Par -exemple, la constante GDK_PRIMARY_SELECTION correspond à la chaîne -"PRIMARY". Dans d'autres cas, on doit utiliser les fonctions -<em/gdk_atom_intern()/, pour obtenir l'atome correspondant à une -chaîne, et <em/gdk_atom_name()/, pour obtenir le nom d'un atome. Les -sélections et les cibles sont identifiés par des atomes. - -<sect1>Récupération de la sélection -<p> -La récupération de la sélection est un processus asynchrone. Pour démarrer le processus, on appelle : - -<tscreen><verb> -gint gtk_selection_convert (GtkWidget *widget, - GdkAtom selection, - GdkAtom target, - guint32 time) -</verb</tscreen> - -Cela <em>convertit</em> la sélection dans la forme spécifiée par -<em/target/. Si tout est possible, le paramètre <em/time/ sera le -moment de l'événement qui a déclenché la sélection. Ceci aide à -s'assurer que les événements arrivent dans l'ordre où l'utilisateur -les a demandé. Cependant, si cela n'est pas possible (par exemple, -lorsque la conversion a été déclenchée par un signal "clicked"), alors -on peut utiliser la macro GDK_CURRENT_TIME. - -<p> -Quand le propriétaire de la sélection répond à la requête, un signal -"selection_received" est envoyé à notre application. Le gestionnaire -de ce signal reçoit un pointeur vers une structure -<tt/GtkSelectionData/ définie ainsi : - -<tscreen><verb> -struct _GtkSelectionData -{ - GdkAtom selection; - GdkAtom target; - GdkAtom type; - gint format; - guchar *data; - gint length; -}; -</verb></tscreen> - -<em/selection/ et <em/target/ sont les valeurs que l'on a donné dans -notre appel <em/gtk_selection_convert()/. <em/type/ est un atome qui -identifie le type de données retourné par le propriétaire de la -sélection. Quelques valeurs possibles sont : "STRING", une chaîne -de caractères latin-1, "ATOM", une série d'atomes, "INTEGER", un -entier, etc. La plupart des cibles ne peuvent retourner qu'un -type. <em/format/ donne la longueur des unités (les caractères, par -exemple) en bits. Habituellement, on ne se préoccupe pas de cela -lorsqu'on reçoit des données. <em/data/ est un pointeur vers la donnée -retournée et <em/length/ donne la longueur en octets de la donnée -retournée. Si <em/length/ est négative, cela indique qu'une erreur est -survenue et que la sélection ne peut être récupérée. Ceci peut arriver -si aucune application n'est propriétaire de la sélection, ou si vous -avez demandé une cible que l'application ne sait pas gérer. Le tampon -est garanti d'être un octet plus long que <em/length/ ; l'octet -supplémentaire sera toujours zéro, et il n'est donc pas nécessaire de -faire une copie de chaîne simplement pour qu'elle soit terminée par -zéro (comme doivent l'être toutes les chaînes C). - -<p> -Dans l'exemple qui suit, on récupère la cible spéciale "TARGETS", qui -est une liste de toutes les cibles en lesquelles la sélection peut -être convertie. - -<tscreen><verb> -#include <gtk/gtk.h> - -void selection_received (GtkWidget *widget, - GtkSelectionData *selection_data, - gpointer data); - -/* Gestionnaire de signal invoqué lorsque l'utilisateur clique sur - * le bouton « Obtenir les cibles ». */ - -void get_targets (GtkWidget *widget, gpointer data) -{ - static GdkAtom targets_atom = GDK_NONE; - - /* Obtention de l'atome correspondant à la chaîne "TARGETS" */ - - if (targets_atom == GDK_NONE) - targets_atom = gdk_atom_intern ("TARGETS", FALSE); - - /* Demande de la cible "TARGETS" pour la sélection primaire */ - - gtk_selection_convert (widget, GDK_SELECTION_PRIMARY, targets_atom, - GDK_CURRENT_TIME); -} - -/* Gestionnaire de signal appelé quand le propriétaire des sélections - * retourne la donnée. */ - -void selection_received (GtkWidget *widget, GtkSelectionData *selection_data, - gpointer data) -{ - GdkAtom *atoms; - GList *item_list; - int i; - - /* **** IMPORTANT **** On vérifie si la récupération s'est bien passée. */ - - if (selection_data->length < 0) - { - g_print ("Selection retrieval failed\n"); - return; - } - - /* On s'assure que l'on a obtenu la donnée sous la forme attendue. */ - - if (selection_data->type != GDK_SELECTION_TYPE_ATOM) - { - g_print ("La sélection \"TARGETS\" n'a pas été retournée sous la forme d'atomes !\n"); - return; - } - - /* Affichage des atomes reçus. */ - - 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 ("(atome incorrect)\n"); - } - - return; -} - -int -main (int argc, char *argv[]) -{ - GtkWidget *window; - GtkWidget *button; - - gtk_init (&argc, &argv); - - /* Création de la fenêtre de l'application. */ - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_title (GTK_WINDOW (window), "Sélections"); - gtk_container_border_width (GTK_CONTAINER (window), 10); - - gtk_signal_connect (GTK_OBJECT (window), "destroy", - GTK_SIGNAL_FUNC (gtk_exit), NULL); - - /* Création d'un bouton pour obtenir les cibles */ - - button = gtk_button_new_with_label ("Obtenir les cibles"); - 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; -} -</verb></tscreen> - -<sect1>Fournir la sélection -<p> - -Fournir la sélection est un peu plus compliqué. On doit enregistrer -les gestionnaires qui seront appelés lorsque notre sélection est -demandée. Pour chaque paire sélection/cible que l'on gèrera, on fera -un appel à : - -<tscreen><verb> -void gtk_selection_add_handler (GtkWidget *widget, - GdkAtom selection, - GdkAtom target, - GtkSelectionFunction function, - GtkRemoveFunction remove_func, - gpointer data); -</verb></tscreen> - -<em/widget/, <em/selection/ et <em/target/ identifient les requêtes -que ce gestionnaire gèrera. S'il ne vaut pas NULL, <em/remove_func/ -sera appelé lorsque le gestionnaire de signal est supprimé. Ceci est -utile, par exemple, pour des langages interprétés qui doivent garder -une trace du nombre de références à <em/data/. - -<p> -La fonction de rappel <em/function/ doit avoir la signature suivante : - -<tscreen><verb> -typedef void (*GtkSelectionFunction) (GtkWidget *widget, - GtkSelectionData *selection_data, - gpointer data); - -</verb></tscreen> - -Le <em/GtkSelectionData/ est le même qu'au dessus, mais, cette fois, -nous sommes responsables de l'initialisation de ses champs <em/type/, -<em/format/, <em/data/, et <em/length/. (Le champ <em/format/ est -important ici - le serveur X l'utilise pour savoir si la donnée doit -être échangée par octet ou non. Habituellement, ce sera 8 (un -caractère), ou 32 (un entier)). Cette initialisation est faite en -utilisant l'appel : - -<tscreen><verb> -void gtk_selection_data_set (GtkSelectionData *selection_data, - GdkAtom type, - gint format, - guchar *data, - gint length); -</verb></tscreen> - -Cette fonction s'occupe de faire une copie correcte des données afin -que l'on n'ait pas à se soucier du reste. (On ne doit pas remplir ces -champs à la main). - -<p> -Lorsque cela est demandé par l'utilisateur, on réclame la possession -de la sélection en appelant : - -<tscreen><verb> -gint gtk_selection_owner_set (GtkWidget *widget, - GdkAtom selection, - guint32 time); -</verb></tscreen> - -Si une autre application réclame la possession de la sélection, on -recevra un "selection_clear_event". - -Comme exemple de fourniture de sélection, l'exemple suivant ajoute une -fonctionnalité de sélection à un bouton commutateur. Lorsque ce bouton -est appuyé, le programme réclame la sélection primaire. La seule cible -supportée (à part certaines cibles fournies par GTK lui-même, comme -« TARGETS ») est « STRING ». Lorsque celle-ci est demandée, on -retourne une représentation de l'heure sous forme de chaîne. - -<tscreen><verb> -#include <gtk/gtk.h> -#include <time.h> - -/* Fonction de rappel appelée lorsque l'utilisateur commute la sélection. */ - -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); - /* Si la demande de sélection échoue, on remet le bouton en position sortie. */ - - if (!*have_selection) - gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON(widget), FALSE); - } - else - { - if (*have_selection) - { - /* Avant de nettoyer la selection en mettant son propriétaire à NULL, - * on vérifie que nous sommes bien son propriétaire actuel. */ - - if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window) - gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY, - GDK_CURRENT_TIME); - *have_selection = FALSE; - } - } -} - -/* Appelée lorsqu'une autre application demande la sélection. */ - -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; -} - -/* Fournit l'heure comme sélection. */ - -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)); - - /* Lorsqu'on retourne une chaîne, elle ne doit pas se terminer par - * 0, ce sera fait pour nous. */ - - 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); - - /* Création de la fenêtre principale. */ - - 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); - - /* Création d'un bouton commutateur pour qu'il agisse comme une sélection. */ - - selection_button = gtk_toggle_button_new_with_label ("Demande de sélection"); - 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; -} -</verb></tscreen> - - - -<sect>glib<label id="sec_glib"> -<p> -La <em/glib/ fournit de nombreuses fonctions et définitions utiles, -prêtes à être utilisées lorsqu'on crée des applications GDK et GTK. Je -les énumèrerais toutes avec une brève explication. Beaucoup sont des -répliques des fonctions standards de la <em/libc/, et je ne les -détaillerais donc pas trop. Ceci doit surtout servir de référence afin -de savoir ce qui est disponible pour être utilisé. - -<sect1>Définitions -<p> -Les définitions pour les bornes de la plupart des types standards sont : - -<tscreen><verb> -G_MINFLOAT -G_MAXFLOAT -G_MINDOUBLE -G_MAXDOUBLE -G_MINSHORT -G_MAXSHORT -G_MININT -G_MAXINT -G_MINLONG -G_MAXLONG -</verb></tscreen> - -Voici aussi les redéfinitions de types. Celles qui ne sont pas -spécifiées sont configurées dynamiquement selon l'architecture. Évitez -surtout de compter sur la taille d'un pointeur si vous voulez un -programme portable ! Un pointeur sur un Alpha fait 8 octets, mais il -en fait 4 sur un Intel. - -<tscreen><verb> -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 -</verb></tscreen> - -<sect1>Listes doublement chaînées -<p> -Les fonctions suivantes servent à créer, gérer et détruire des listes -doublement chaînées. Je suppose que vous savez ce qu'est une liste -chaînée car leur explication n'entre pas dans le cadre de ce -document. Bien sûr, il n'y a pas besoin de les connaître pour une -utilisation générale de GTK, mais c'est bien de savoir comment elles -fonctionnent. - -<tscreen><verb> -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); -</verb></tscreen> - - -<sect1>Listes simplement chaînées -<p> -La plupart des fonctions pour les listes simplement chaînées -ci-dessous sont identiques à celles vues plus haut. Voici une liste -complète : - -<tscreen><verb> -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); - -</verb></tscreen> - -<sect1>Gestion de la mémoire -<p> -<tscreen><verb> -gpointer g_malloc (gulong size); -</verb></tscreen> - -Remplace <em/malloc()/. On n'a pas besoin de vérifier la valeur de -retour car cela est fait pour nous dans cette fonction. - -<tscreen><verb> -gpointer g_malloc0 (gulong size); -</verb></tscreen> - -Identique à la précédente, mais initialise la mémoire à zéro avant de -retourner un pointeur vers la zone réservée. - -<tscreen><verb> -gpointer g_realloc (gpointer mem, - gulong size); -</verb></tscreen> - -Réalloue <em/size/ octets de mémoire à partir de <em/mem/. Évidemment, -la mémoire doit avoir été allouée auparavant. - -<tscreen><verb> -void g_free (gpointer mem); -</verb></tscreen> - -Libère la mémoire. Facile. - -<tscreen><verb> -void g_mem_profile (void); -</verb></tscreen> - -Produit un profil de la mémoire utilisée, mais requiert l'ajout de -<em/#define MEM_PROFILE/ au début de <em>glib/gmem.c</em>, -de refaire un <em/make/ et un <em/make install/. - -<tscreen><verb> -void g_mem_check (gpointer mem); -</verb></tscreen> - -Vérifie qu'un emplacement mémoire est valide. Nécessite que l'on -ajoute <em/#define MEM_CHECK/ au début de <em/gmem.c/ que l'on refasse -un <em/make/ et un <em/make install/. - -<sect1>Timers -<p> -Fonctions des timers... - -<tscreen><verb> -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); -</verb></tscreen> - -<sect1>Gestion des chaînes -<p> -Un ensemble complet de fonction de gestion des chaînes. Elles semblent -toutes très intéressantes et sont sûrement meilleures, à bien des -égards, que les fonctions C standards, mais elle nécessitent de la -documentation. - -<tscreen><verb> -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, - ...); -</verb></tscreen> - -<sect1>Utilitaires et fonctions d'erreurs -<p> -<tscreen><verb> -gchar* g_strdup (const gchar *str); -</verb></tscreen> - -Remplace la fonction <em/strdup/. Elle copie le contenu de la chaîne -d'origine dans la mémoire venant d'être allouée et retourne un -pointeur sur cette zone. - -<tscreen><verb> -gchar* g_strerror (gint errnum); -</verb></tscreen> - -Je recommande de l'utiliser pour tous les messages d'erreur. Elle est -beaucoup plus propre et plus portable que <em/perror()/ ou les -autres. La sortie est habituellement de la forme : - -<tscreen><verb> -nom du programme:fonction qui a échoué:fichier ou autre descripteur:strerror -</verb></tscreen> - -Voici un exemple d'appel utilisé dans le programme « Bonjour tout le monde ! » : - -<tscreen><verb> -g_print("bonjour_monde:open:%s:%s\n", filename, g_strerror(errno)); -</verb></tscreen> - -<tscreen><verb> -void g_error (gchar *format, ...); -</verb></tscreen> - -Affiche un message d'erreur. Le format est comme <em/printf/, mais il -ajoute « ** ERROR **: » au début du message et sort du programme. À -n'utiliser que pour les erreurs fatales. - -<tscreen><verb> -void g_warning (gchar *format, ...); -</verb></tscreen> - -Comme au dessus, mais ajoute « ** WARNING **: », et ne termine pas le -programme. - -<tscreen><verb> -void g_message (gchar *format, ...); -</verb></tscreen> -Affiche « message: » avant la chaîne passée en paramètre. - -<tscreen><verb> -void g_print (gchar *format, ...); -</verb></tscreen> - -Remplace <em/printf()/. - -Enfin la dernière fonction : - -<tscreen><verb> -gchar* g_strsignal (gint signum); -</verb></tscreen> - -Affiche le nom du signal système Unix correspondant au numéro de -signal. Utile pour les fonctions génériques de gestion de signaux. - -Tout ce qui est ci-dessus est plus ou moins volé à <em/glib.h/. Si -quelqu'un s'occupe de documenter une fonction, qu'il m'envoit un -courrier ! - - -<sect>Fichiers rc de GTK -<p> -GTK a sa propre méthode pour gérer les configurations par défaut des -applications, en utilisant des fichiers <tt/rc/. Ceux-ci peuvent être -utilisés pour configurer les couleurs de presque tous les widgets, et -pour mettre des pixmaps sur le fond de certains widgets. - -<sect1>Fonctions pour les fichiers rc -<p> -Au démarrage de votre application, ajoutez un appel à : -<tscreen><verb> -void gtk_rc_parse (char *filename); -</verb></tscreen> -<p> -en lui passant le nom de votre fichier rc. Ceci forcera GTK à analyser -ce fichier et à utiliser les configurations de styles pour les types -de widgets qui y sont définis. -<p> -Si vous voulez avoir un ensemble particulier de widgets qui prenne le -pas sur le style des autres, ou une autre division logique de widgets, -utilisez un appel à : -<tscreen><verb> -void gtk_widget_set_name (GtkWidget *widget, - gchar *name); -</verb></tscreen> -<p> -En lui passant comme premier paramètre le widget que vous avez créé, -et le nom que vous voulez lui donner comme second paramètre. Ceci vous -permettra de changer les attributs de ce widget par son nom dans le -fichier rc. -<p> -Si vous utilisez un appel comme celui-ci : - -<tscreen><verb> -button = gtk_button_new_with_label ("Bouton Spécial"); -gtk_widget_set_name (button, "bouton special"); -</verb></tscreen> -<p> -Ce bouton s'appelle « bouton special » et peut être accédé par son nom -dans le fichier rc en tant que « bouton special.GtkButton ». [<--- -Vérifiez !] -<p> -Le fichier rc ci-dessous configure les propriétés de la fenêtre -principale et fait hériter tous les fils de celle-ci du style décrit -par « bouton_principal ». Le code utilisé dans l'application -est : - -<tscreen><verb> -window = gtk_window_new (GTK_WINDOW_TOPLEVEL); -gtk_widget_set_name (window, "fenetre principale"); -</verb></tscreen> -<p> -Et le style est défini dans le fichier rc avec : - -<tscreen><verb> -widget "fenetre principale.*GtkButton*" style "bouton_principal" -</verb></tscreen> -<p> -Ce qui configure tous les widgets <em/GtkButton/ de « fenêtre -principale » avec le style « bouton_principal » défini dans le fichier -rc. -<p> -Ainsi que vous pouvez le voir, il s'agit d'un système puissant et -flexible. Utilisez votre imagination pour en tirer le meilleur. - -<sect1>Format des fichiers rc de GTK -<p> -Le format du fichier GTK est illustré dans l'exemple suivant. Il -s'agit du fichier <em/testgtkrc/ de la distribution GTK mais j'ai -ajouté quelques commentaires et autres choses. Vous pouvez inclure -cette explication à votre application pour permettre à l'utilisateur -de régler finement son application. -<p> -Il y a plusieurs directives pour changer les attributs d'un widget. -<itemize> -<item>fg - configure la couleur de premier plan d'un widget. -<item>bg - configure la couleur d'arrière plan d'un widget. -<item>bg_pixmap - configure l'arrière plan d'un widget avec un pixmap. -<item>font - configure la fonte à utiliser pour un widget. -</itemize> -<p> -De plus, un widget peut se trouver dans différents états et l'on peut -configurer des couleurs, pixmaps et fontes différentes pour chacun -d'eux. Ces états sont : -<itemize> -<item>NORMAL - L'état normal d'un widget, sans la souris au dessus de -lui, non pressé, etc. -<item>PRELIGHT - Lorsque la souris se trouve au dessus du widget, les -couleurs définies pour cet état sont actives. -<item>ACTIVE - Lorsque le widget est pressé ou cliqué, il devient -actif et les attributs associés à cet état sont appliqués. -<item>INSENSITIVE - Quand un widget est configuré pour être -insensible et qu'il ne peut être activé, il prend ces attributs. -<item>SELECTED - Lorsqu'un objet est choisi, il prend ces attributs. -</itemize> -<p> -Lorsqu'on utilise les mots-clés « <em/fg/ » et « <em/bg/ » pour -configurer les couleurs des widgets, le format est : - -<tscreen><verb> fg[<STATE>] = { Red, Green, Blue } </verb></tscreen> -<p> -Où STATE est l'un des états vus plus haut (PRELIGHT, ACTIVE etc), et -où <em/Red/, <em/Green/ et <em/Blue/ sont des valeurs comprises entre -0 et 1.0. { 1.0, 1.0, 1.0 } représente la couleur blanche. Ces -valeurs doivent être de type réel ou elles seront considérées comme -valant 0, ainsi un simple « 1 » ne marchera pas, il faut mettre « 1.0 -». Un « 0 » simple convient car ce n'est pas un problème s'il n'est -pas reconnu puisque toutes les valeurs non reconnues sont mises à 0. -<p> -<em/bg_pixmap/ est très similaire, sauf que les couleurs sont -remplacées par un nom de fichier. - -<em/pixmap_path/ est une liste de chemins séparés par des « : ». Ces -chemins seront parcourus pour chaque pixmap que l'on spécifie. - -<p> -La directive <em/font/ est simplement : -<tscreen><verb> -font = "<font name>" -</verb></tscreen> -<p> -Où la seule partie difficile est d'arriver à comprendre la chaîne -contenant le nom de la fonte. L'utilisation de <em/xfontsel/ ou d'un -autre utilitaire semblable peut aider. -<p> -« <em/widget_class/ » configure le style d'une classe de widgets. Ces -classes sont listées dans la section sur la hiérarchie des widgets. -<p> -La directive « <em/widget/ » configure un ensemble spécifique de -widgets selon un style donné, annulant tout style de configuration -pour la classe de widget donnée. Ces widgets sont enregistrés dans -l'application en utilisant l'appel <em/gtk_widget_set_name()/. Ceci -vous permet de spécifier les attributs d'un widget, widget par widget, -au lieu de configurer les attributs d'une classe entière de -widgets. Je vous demande instamment de documenter tous ces widgets -spéciaux pour que les utilisateurs puisse les adapter à leurs besoins. -<p> -Lorsque le mot-clé « <em/parent/ » est utilisé comme attribut, le -widget prendra les attributs de son parent dans l'application. -<p> -Lorsqu'on définit un style, on peut assigner les attributs d'un style -déjà défini à ce nouveau style. - -<tscreen><verb> -style "bouton_principal" = "button" -{ - font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*" - bg[PRELIGHT] = { 0.75, 0, 0 } -} -</verb></tscreen> -<p> -Cet exemple prend le style "button" et crée un nouveau style -"bouton_principal"en changeant simplement la fonte et la couleur de -fond pour l'état PRELIGHT. -<p> -Bien sûr, un bon nombre de ces attributs ne s'applique pas à tous les -widgets. C'est une question de bon sens. Tout ce qui peut s'appliquer -s'applique. - -<sect1>Exemple de fichier rc -<p> - -<tscreen><verb> -# 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> - - -# Voici une liste des états possibles. Remarquez que certains ne s'appliquent -# pas à certains widgets. -# -# NORMAL - L'état normal d'un widget, sans la souris au dessus de lui, -# non pressé, etc. -# -# PRELIGHT - Lorsque la souris se trouve au dessus du widget, les couleurs -# définies pour cet état sont actives. -# -# ACTIVE - Lorsque le widget est pressé ou cliqué, il devient actif et les -# attributs associés à cet état sont appliqués. -# -# INSENSITIVE - Quand un widget est configuré pour être insensible, et qu'il -# ne peut être activé, il prend ces attributs. -# -# SELECTED - Lorsqu'un objet est choisi, il prend ces attributs. -# -# Avec ces états, on peut configurer les attributs des widgets dans chacun -# de ces états en utilisant les directives suivantes. -# -# fg - configure la couleur de premier plan d'un widget. -# bg - configure la couleur d'arrière plan d'un widget. -# bg_pixmap - configure l'arrière plan d'un widget avec un pixmap. -# font - configure la fonte à utiliser pour un widget. - -# Configuration d'un style appelé "button". Le nom n'est pas important -# car il est assigné aux widgets réels à la fin du fichier. - -style "window" -{ - #Configure l'espace autour de la fenêtre avec le pixmap spécifié. - #bg_pixmap[<STATE>] = "<pixmap filename>" - bg_pixmap[NORMAL] = "warning.xpm" -} - -style "scale" -{ - #Configure la couleur de premier plan (celle de la fonte) à rouge - #lorsqu'on est dans l'état "NORMAL". - - fg[NORMAL] = { 1.0, 0, 0 } - - #Configure le pixmap d'arrière plan de ce widget à celui de son parent. - bg_pixmap[NORMAL] = "<parent>" -} - -style "button" -{ - # Voici tous les états possibles pour un bouton. Le seul qui ne peut - # s'appliquer est l'état SELECTED. - - 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 } -} - -# Dans cet exemple, on hérite des attributs du style "button" puis on -# écrase la fonte et la couleur de fond pour créer un nouveau style -# "main_button". - -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 } - - # Configure le pixmap de fond du toggle_button à celui de son widget - # parent (comme défini dans l'application). - 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" - -# Configuration des types de widget pour utiliser les styles définis -# plus haut. -# Les types de widget sont listés dans la hiérarchie des classes, mais -# peut probablement être listée dans ce document pour que l'utilisateur -# puisse s'y référer. - -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" - -# Configure tous les boutons fils de la "main window" avec le style -# main_button. Ceci doit être documenté pour en tirer profit. -widget "main window.*GtkButton*" style "main_button" -</verb></tscreen> - -<sect>Écriture de vos propres widgets -<p> -<sect1>Vue d'ensemble -<p> -Bien que la distribution GTK fournisse de nombreux types de widgets -qui devraient couvrir la plupart des besoins de base, il peut arriver -un moment où vous aurez besoin de créer votre propre type de -widget. Comme GTK utilise l'héritage de widget de façon intensive et -qu'il y a déjà un widget ressemblant à celui que vous voulez, il est -souvent possible de créer un nouveau type de widget en seulement -quelques lignes de code. Mais, avant de travailler sur un nouveau -widget, il faut vérifier d'abord que quelqu'un ne l'a pas déjà -écrit. Ceci éviter la duplication des efforts et maintient au minimum -le nombre de widgets, ce qui permet de garder la cohérence du code et -de l'interface des différentes applications. Un effet de bord est que, -lorsque l'on a créé un nouveau widget, il faut l'annoncer afin que les -autres puissent en bénéficier. Le meilleur endroit pour faire cela -est, sans doute, la <tt>gtk-list</tt>. - -<sect1>Anatomie d'un widget - -<p> -Afin de créer un nouveau widget, il importe de comprendre comment -fonctionnent les objets GTK. Cette section ne se veut être qu'un -rapide survol. Consultez la documentation de référence pour plus de -détails. - -<p> -Les widgets sont implantés selon une méthode orientée -objet. Cependant, ils sont écrits en C standard. Ceci améliore -beaucoup la portabilité et la stabilité, par contre cela signifie que -celui qui écrit des widgets doit faire attention à certains détails -d'implantation. Les informations communes à toutes les instances d'une -classe de widget (tous les widgets boutons, par exemple) sont stockées -dans la <em/structure de la classe/. Il n'y en a qu'une copie dans -laquelle sont stockées les informations sur les signaux de la -classe (fonctionnement identique aux fonctions virtuelles en C). Pour -permettre l'héritage, le premier champ de la structure de classe doit -être une copie de la structure de classe du père. La déclaration de la -structure de classe de <em/GtkButton/ ressemble à ceci : - -<tscreen><verb> -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); -}; -</verb></tscreen> - -<p> -Lorsqu'un bouton est traité comme un container (par exemple, lorsqu'il -change de taille), sa structure de classe peut être convertie en -<em/GtkContainerClass/ et les champs adéquats utilisés pour gérer les -signaux. - -<p> -Il y a aussi une structure pour chaque widget créé sur une base -d'instance. Cette structure a des champs pour stocker les informations -qui sont différentes pour chaque instance du widget. Nous l'appelerons -<em/structure d'objet/. Pour la classe <em/Button/, elle ressemble -à : - -<tscreen><verb> -struct _GtkButton -{ - GtkContainer container; - - GtkWidget *child; - - guint in_button : 1; - guint button_down : 1; -}; -</verb></tscreen> - -<p> -Notez que, comme pour la structure de classe, le premier champ est la -structure d'objet de la classe parente, cette structure peut donc être -convertie dans la structure d'objet de la classe parente si besoin -est. - -<sect1> Création d'un widget composé - -<sect2> Introduction - -<p> -Un type de widget qui peut être intéressant à créer est un widget qui -est simplement un agrégat d'autres widgets GTK. Ce type de widget ne -fait rien qui ne pourrait être fait sans créer de nouveaux widgets, -mais offre une méthode pratique pour empaqueter les éléments d'une -interface utilisateur afin de la réutiliser facilement. Les widgets -<em/FileSelection/ et <em/ColorSelection/ de la distribution standard -sont des exemples de ce type de widget. - -<p> -L'exemple de widget que nous allons créer dans cette section créera un -widget <em/Tictactoe/, un tableau de 3x3 boutons commutateurs qui -déclenche un signal lorsque tous les boutons d'une ligne, d'une -colonne, ou d'une diagonale sont pressés. - -<sect2> Choix d'une classe parent - -<p> -La classe parent d'un widget composé est, typiquement, la classe -container contenant tous les éléments du widget composé. Par exemple, -la classe parent du widget <em/FileSelection/ est la classe -<em/Dialog/. Comme nos boutons seront mis sous la forme d'un tableau, -il semble naturel d'utiliser la classe <em/GtkTable/ comme -parent. Malheureusement, cela ne peut marcher. La création d'un widget -est divisée en deux fonctions -- <em/WIDGETNAME_new()/ que -l'utilisateur appelle, et <em/WIDGETNAME_init()/ qui réalise le -travail d'initialisation du widget indépendamment des paramètre passés -à la fonction <tt/_new()/. Les widgets fils n'appellent que la -fonction <em/_init/ de leur widget parent. Mais cette division du -travail ne fonctionne pas bien avec les tableaux qui, lorsqu'ils sont -créés, ont besoin de connaître leue nombre de lignes et de -colonnes. Sauf à dupliquer la plupart des fonctionnalités de -<em/gtk_table_new()/ dans notre widget <em/Tictactoe/, nous ferions -mieux d'éviter de le dériver de <em/GtkTable/. Pour cette raison, nous -la dériverons plutôt de <em/GtkVBox/ et nous placerons notre table -dans la VBox. - -<sect2> The header file - -<p> -Chaque classe de widget possède un fichier en-tête qui déclare les -structures d'objet et de classe pour ce widget, en plus de fonctions -publiques. Quelques caractéristiques méritent d'être indiquées. Afin -d'éviter des définitions multiples, on enveloppe le fichier en-tête -avec : - -<tscreen><verb> -#ifndef __TICTACTOE_H__ -#define __TICTACTOE_H__ -. -. -. -#endif /* __TICTACTOE_H__ */ -</verb></tscreen> - -Et, pour faire plaisir aux programmes C++ qui inclueront ce fichier, on l'enveloppe aussi dans : - -<tscreen><verb> -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ -. -. -. -#ifdef __cplusplus -} -#endif /* __cplusplus */ -</verb></tscreen> - -En plus des fonctions et structures, nous déclarons trois macros -standard, <tt/TICTACTOE(obj)/, <tt/TICTACTOE_CLASS(class)/, et -<tt/IS_TICTACTOE(obj)/, qui, respectivement, convertissent un pointeur -en un pointeur vers une structure d'objet ou de classe, et vérifient -si un objet est un widget Tictactoe. - -<p> -Voici le fichier en-tête complet : - -<tscreen><verb> - -#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__ */ - -</verb></tscreen> - -<sect2>La fonction <tt/_get_type()/ - -<p> -Continuons maintenant avec l'implantation de notre widget. La fonction -centrale pour chaque widget est <em/WIDGETNAME_get_type()/. Cette -fonction, lorsqu'elle est appelée pour la première fois, informe le -GTK de la classe et récupère un ID permettant d'identifier celle-ci de -façon unique. Lors des appels suivants, elle ne fait que retourner cet -ID. - -<tscreen><verb> -guint -tictactoe_get_type () -{ - static guint ttt_type = 0; - - if (!ttt_type) - { - GtkTypeInfo ttt_info = - { - "Tictactoe", - sizeof (Tictactoe), - sizeof (TictactoeClass), - (GtkClassInitFunc) tictactoe_class_init, - (GtkObjectInitFunc) tictactoe_init, - (GtkArgFunc) NULL, - }; - - ttt_type = gtk_type_unique (gtk_vbox_get_type (), &ttt_info); - } - - return ttt_type; -} -</verb></tscreen> - -<p> -La structure <em/GtkTypeInfo/ est définie de la façon suivante : - -<tscreen><verb> -struct _GtkTypeInfo -{ - gchar *type_name; - guint object_size; - guint class_size; - GtkClassInitFunc class_init_func; - GtkObjectInitFunc object_init_func; - GtkArgFunc arg_func; -}; -</verb></tscreen> - -<p> -Les champs de cette structure s'expliquent d'eux-mêmes. Nous -ignorerons le champ <em/arg_func/ ici : il a un rôle important -permettant aux options des widgets d'être correctement initialisées à -partir des langages interprétés, mais cette fonctionnalité est encore -très peu implantée. Lorsque GTK dispose d'une copie correctement -remplie de cette structure, il sait comment créer des objets d'un type -particulier de widget. - -<sect2>La fonction <em/_class_init()/ - -<p> -La fonction <em/WIDGETNAME_class_init()/ initialise les champs de la -structure de classe du widget et configure tous les signaux de cette -classe. Pour notre widget Tictactoe, cet appel est : - -<tscreen><verb> - -enum { - TICTACTOE_SIGNAL, - LAST_SIGNAL -}; - -static gint tictactoe_signals[LAST_SIGNAL] = { 0 }; - -static void -tictactoe_class_init (TictactoeClass *class) -{ - GtkObjectClass *object_class; - - object_class = (GtkObjectClass*) class; - - tictactoe_signals[TICTACTOE_SIGNAL] = gtk_signal_new ("tictactoe", - GTK_RUN_FIRST, - object_class->type, - GTK_SIGNAL_OFFSET (TictactoeClass, tictactoe), - gtk_signal_default_marshaller, GTK_ARG_NONE, 0); - - - gtk_object_class_add_signals (object_class, tictactoe_signals, LAST_SIGNAL); - - class->tictactoe = NULL; -} -</verb></tscreen> - -<p> -Notre widget n'a qu'un signal : "tictactoe", invoqué lorsqu'une -ligne, une colonne ou une diagonale est complètement remplie. Tous les -widgets composés n'ont pas besoin de signaux. Si vous lisez ceci pour -la première fois, vous pouvez passer directement à la section suivante -car les choses vont se compliquer un peu - -La fonction : - -<tscreen><verb> -gint gtk_signal_new (gchar *name, - GtkSignalRunType run_type, - gint object_type, - gint function_offset, - GtkSignalMarshaller marshaller, - GtkArgType return_val, - gint nparams, - ...); -</verb></tscreen> - -crée un nouveau signal. Les paramètres sont : - -<itemize> -<item> <em/name/ : Le nom du signal signal. -<item> <em/run_type/ : Indique si le gestionnaire par défaut doit être -lancé avant ou après le gestionnaire de l'utilisateur. Le plus -souvent, ce sera <tt/GTK_RUN_FIRST/, ou <tt/GTK_RUN_LAST/, bien qu'il -y ait d'autres possibilités. - -<item> <em/object_type/ : L'ID de l'objet auquel s'applique ce signal -(il s'appliquera aussi au descendants de l'objet). - -<item> <em/function_offset/ : L'offset d'un pointeur vers le -gestionnaire par défaut dans la structure de classe. - -<item> <em/marshaller/ : Fonction utilisée pour invoquer le -gestionnaire de signal. Pour les gestionnaires de signaux n'ayant pas -d'autres paramètres que l'objet émetteur et les données utilisateur, -on peut utiliser la fonction prédéfinie -<em/gtk_signal_default_marshaller()/. - -<item> <em/return_val/ : Type de la valeur retournée. - -<item> <em/nparams/ : Nombre de paramètres du gestionnaire de signal -(autres que les deux par défaut mentionnés plus haut). - -<item> <em/.../ : Types des paramètres. -</itemize> - -Lorsque l'on spécifie les types, on utilise l'énumération -<em/GtkArgType/ : - -<tscreen><verb> -typedef enum -{ - GTK_ARG_INVALID, - GTK_ARG_NONE, - GTK_ARG_CHAR, - GTK_ARG_SHORT, - GTK_ARG_INT, - GTK_ARG_LONG, - GTK_ARG_POINTER, - GTK_ARG_OBJECT, - GTK_ARG_FUNCTION, - GTK_ARG_SIGNAL -} GtkArgType; -</verb></tscreen> - -<p> -<em/gtk_signal_new()/ retourne un identificateur entier pour le -signal, que l'on stocke dans le tableau <em/tictactoe_signals/, indicé -par une énumération (conventionnellement, les éléments de -l'énumération sont le nom du signal, en majuscules, mais, ici, il y -aurait un conflit avec la macro <tt/TICTACTOE()/, nous l'appellerons -donc <tt/TICTACTOE_SIGNAL/ à la place. - -Après avoir créé nos signaux, nous devons demander à GTK d'associer -ceux-ci à la classe Tictactoe. Ceci est fait en appelant -<em/gtk_object_class_add_signals()/. Puis nous configurons le pointeur -qui pointe sur le gestionnaire par défaut du signal "tictactoe" à -NULL, pour indiquer qu'il n'y a pas d'action par défaut. - -<sect2>La fonction <em/_init()/ -<p> - -Chaque classe de widget a aussi besoin d'une fonction pour initialiser -la structure d'objet. Habituellement, cette fonction a le rôle, plutôt -limité, d'initialiser les champs de la structure avec des valeurs par -défaut. Cependant, pour les widgets composés, cette fonction crée -aussi les widgets composants. - -<tscreen><verb> - -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]); - } -} -</verb></tscreen> - -<sect2> Et le reste... -<p> - -Il reste une fonction que chaque widget (sauf pour les types widget de -base, comme <em/GtkBin/, qui ne peuvent être instanciés) à besoin -d'avoir -- celle que l'utilisateur appelle pour créer un objet de ce -type. Elle est conventionnellement appelée <em/WIDGETNAME_new()/. Pour -certains widgets, par pour ceux de Tictactoe, cette fonction prend des -paramètres et réalise certaines initialisations dépendantes des -paramètres. Les deux autres fonctions sont spécifiques au widget -Tictactoe. - -<p> -<em/tictactoe_clear()/ est une fonction publique qui remet tous les -boutons du widget en position relâchée. Notez l'utilisation de -<em/gtk_signal_handler_block_by_data()/ pour empêcher notre -gestionnaire de signaux des boutons commutateurs d'être déclenché sans -besoin. - -<p> -<em/tictactoe_toggle()/ est le gestionnaire de signal invoqué -lorsqu'on clique sur un bouton. Il vérifie s'il y a des combinaisons -gagnantes concernant le bouton qui vient d'être commuté et, si c'est -le cas, émet le signal "tictactoe". - -<tscreen><verb> -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; - } - } -} -</verb></tscreen> - -<p> - -Enfin, un exemple de programme utilisant notre widget Tictactoe  - -<tscreen><verb> -#include <gtk/gtk.h> -#include "tictactoe.h" - -/* Invoqué lorsqu'une ligne, une colonne ou une diagonale est complète */ - -void win (GtkWidget *widget, gpointer data) -{ - g_print ("Ouais !\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); - - /* Création d'un widget Tictactoe */ - ttt = tictactoe_new (); - gtk_container_add (GTK_CONTAINER (window), ttt); - gtk_widget_show (ttt); - - /* On lui attache le signal "tictactoe" */ - gtk_signal_connect (GTK_OBJECT (ttt), "tictactoe", - GTK_SIGNAL_FUNC (win), NULL); - - gtk_widget_show (window); - - gtk_main (); - - return 0; -} - -</verb></tscreen> - -<sect1> Création d'un widget à partir de zéro - -<sect2> Introduction - -<p> - -Dans cette section, nous en apprendrons plus sur la façon dont les -widgets s'affichent eux-mêmes à l'écran et comment ils interagissent -avec les événements. Comme exemple, nous créerons un widget d'appel -télephonique interactif avec un pointeur que l'utilisateur pourra -déplacer pour initialiser la valeur. - -<sect2>Afficher un widget à l'écran -<p> -Il y a plusieurs étapes mises en jeu lors de l'affichage. Lorsque le widget est -créé par l'appel <em/WIDGETNAME_new()/, plusieurs autres fonctions -supplémentaires sont requises. - -<itemize> -<item> <em/WIDGETNAME_realize()/ s'occupe de créer une fenêtre X pour le -widget, s'il en a une. -<item> <em/WIDGETNAME_map()/ est invoquée après l'appel de -<em/gtk_widget_show()/. Elle s'assure que le widget est bien tracé à l'écran -(<em/mappé/). Dans le cas d'une classe container, elle doit aussi appeler des -fonctions <em/map()/> pour chaque widget fils. -<item> <em/WIDGETNAME_draw()/ est invoquée lorsque <em/gtk_widget_draw()/ est -appelé pour le widget ou l'un de ces ancêtres. Elle réalise les véritables -appels aux fonctions de dessin pour tracer le widget à l'écran. Pour les -widgets containers, cette fonction doit appeler <em/gtk_widget_draw()/ pour ses -widgets fils. -<item> <em/WIDGETNAME_expose()/ est un gestionnaire pour les événements -d'exposition du widget. Il réalise les appels nécessaires aux fonctions de -dessin pour tracer la partie exposée à l'écran. Pour les widgets containers, -cette fonction doit générer les événements d'exposition pour ses widgets -enfants n'ayant pas leurs propres fenêtres (s'ils ont leurs propres fenêtres, X -génèrera les événements d'exposition nécessaires). -</itemize> - -<p> -Vous avez pu noter que les deux dernières fonctions sont assez similaires -- -chacune se charge de tracer le widget à l'écran. En fait, de nombreux types de -widgets ne se préoccupent pas vraiment de la différence entre les deux. La -fonction <em/draw()/ par défaut de la classe widget génère simplement un -événement d'exposition synthétique pour la zone à redessiner. Cependant, -certains types de widgets peuvent économiser du travail en faisant la -différence entre les deux fonctions. Par exemple, si un widget a plusieurs -fenêtres X et puisque les événements d'exposition identifient la fenêtre -exposée, il peut redessiner seulement la fenêtre concernée, ce qui n'est pas -possible avec des appels à <em/draw()/. - -<p> -Les widgets container, même s'ils ne se soucient pas eux-mêmes de la -différence, ne peuvent pas utiliser simplement la fonction <em/draw()/ car -leurs widgets enfants tiennent compte de cette différence. Cependant, ce serait -du gaspillage de dupliquer le code de tracé pour les deux -fonctions. Conventionnellement, de tels widgets possèdent une fonction nommée -<em/WIDGETNAME_paint()/ qui réalise le véritable travail de tracé du widget et -qui est appelée par les fonctions <tt/draw()/ et <tt/expose()/. - -<p> -Dans notre exemple, comme le widget d'appel n'est pas un widget container et -n'a qu'une fenêtre, nous pouvons utiliser l'approche la plus simple : -utiliser la fonction <em/draw()/ par défaut et n'implanter que la fonction -<em/expose()/. - -<sect2>Origines du widget Dial - -<p> -Exactement comme les animaux terrestres ne sont que des variantes des premiers -amphibiens qui rampèrent hors de la boue, les widgets GTK sont des variantes -d'autres widgets, déjà écrits. Ainsi, bien que cette section s'appelle « créer -un widget à partir de zéro », le widget Dial commence réellement avec le code -source du widget Range. Celui-ci a été pris comme point de départ car ce serait -bien que notre Dial ait la même interface que les widgets Scale qui ne sont que -des descendants spécialisés du widget Range. Par conséquent, bien que le code -source soit présenté ci-dessous sous une forme achevée, cela n'implique pas -qu'il a été écrit <em/deus ex machina/. De plus, si vous ne savez pas comment -fonctionnent les widgets Scale du point de vue du programmeur de l'application, -il est préférable de les étudier avant de continuer. - -<sect2>Les bases - -<p> -Un petite partie de notre widget devrait ressembler au widget Tictactoe. Nous -avons d'abord le fichier en-tête : - -<tscreen><verb> -/* 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; - - /* politique de mise à jour - (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */ - - guint policy : 2; - - /* Le bouton qui est pressé, 0 si aucun */ - guint8 button; - - /* Dimensions des composants de dial */ - gint radius; - gint pointer_width; - - /* ID du timer de mise à jour, 0 si aucun */ - guint32 timer; - - /* Angle courant*/ - gfloat angle; - - /* Anciennes valeurs d'ajustement stockées. On sait donc quand quelque - chose change */ - gfloat old_value; - gfloat old_lower; - gfloat old_upper; - - /* L'objet ajustment qui stocke les données de cet appel */ - 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__ */ - -</verb></tscreen> - -Comme il y a plus de choses à faire avec ce widget par rapport à l'autre, nous -avons plus de champs dans la structure de données, mais à part ça, les choses -sont plutôt similaires. - -<p> - -Puis, après avoir inclus les fichiers en-tête et déclaré quelques constantes, -nous devons fournir quelques fonctions pour donner des informations sur le -widget et pour l'initialiser : - -<tscreen><verb> -#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 - -/* Déclararations des prototypes */ - -[ omis pour gagner de la place ] - -/* Données locales */ - -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); -} -</verb></tscreen> - -Notez que cette fonction <em/init()/ fait moins de choses que pour le widget -Tictactoe car ce n'est pas un widget composé et que la fonction <em/new()/ en -fait plus car elle a maintenant un paramètre. Notez aussi que lorsque nous -stockons un pointeur vers l'objet Adjustement, nous incrémentons son nombre de -références (et nous le décrémentons lorsque nous ne l'utilisons plus) afin que -GTK puisse savoir quand il pourra être détruit sans danger. - -<p> -Il y a aussi quelques fonctions pour manipuler les options du widget : - -<tscreen><verb> -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); -} -</verb></tscreen> - -<sect2> <em/gtk_dial_realize()/ - -<p> -Nous arrivons maintenant à quelques nouveaux types de fonctions. D'abord, nous -avons une fonction qui réalise la création de la fenêtre X. Notez que l'on -passe un masque à la fonction <em/gdk_window_new()/ pour spécifier quels sont -les champs de la structure GdkWindowAttr qui contiennent des données (les -autres recevront des valeurs par défaut). Notez aussi la façon dont est créé le -masque d'événement du widget. On appelle <em/gtk_widget_get_events()/ pour -récupérer le masque d'événement que l'utilisateur a spécifié pour ce widget -(avec <em/gtk_widget_set_events()/) et ajouter les événements qui nous -intéressent. - -<p> -Après avoir créé la fenêtre, nous configurons son style et son fond et mettons -un pointeur vers le widget dans le champ user de la GdkWindow. Cette dernière -étape permet à GTK de distribuer les événements pour cette fenêtre au widget -correct. - -<tscreen><verb> -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); -} -</verb></tscreen> - -<sect2>Négotiation de la taille - -<p> -Avant le premier affichage de la fenêtre contenant un widget et à chaque fois -que la forme de la fenêtre change, GTK demande à chaque widget fils la taille -qu'il désire avoir. Cette requête est gérée par la fonction -<em/gtk_dial_size_request()/. Comme notre widget n'est pas un widget container, -et n'a pas de contraintes réelles sur sa taille, nous ne faisons que retourner -une valeur raisonnable par défaut. - -<tscreen><verb> -static void -gtk_dial_size_request (GtkWidget *widget, - GtkRequisition *requisition) -{ - requisition->width = DIAL_DEFAULT_SIZE; - requisition->height = DIAL_DEFAULT_SIZE; -} -</verb></tscreen> - -<p> -Lorsque tous les widgets on demandé une taille idéale, le forme de la fenêtre -est calculée et chaque widget fils est averti de sa taille. Habituellement, ce -sera autant que la taille requise, mais si, par exemple, l'utilisateur a -redimensionné la fenêtre, cette taille peut occasionnellement être plus petite -que la taille requise. La notification de la taille est gérée par la fonction -<em/gtk_dial_size_allocate()/. Notez qu'en même temps qu'elle calcule les -tailles de certains composants pour une utilisation future, cette routine fait -aussi le travail de base consistant à déplacer les widgets X Window dans leur -nouvelles positions et tailles. - -<tscreen><verb> -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; - } -} -</verb></tscreen>. - -<sect2> <em/gtk_dial_expose()/ - -<p> -Comme cela est mentionné plus haut, tout le dessin de ce widget est réalisé -dans le gestionnaire pour les événements d'exposition. Il n'y a pas grand chose -de plus à dire là dessus, sauf constater l'utilisation de la fonction -<em/gtk_draw_polygon/ pour dessiner le pointeur avec une forme en trois -dimensions selon les couleurs stockées dans le style du widget. -style. - -<tscreen><verb> -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; - - /* Draw ticks */ - - 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); - } - - /* Draw pointer */ - - 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; -} -</verb></tscreen> - -<sect2>Gestion des événements - -<p> -Le reste du code du widget gère différents types d'événements et n'est pas -trop différent de ce que l'on trouve dans la plupart des applications GTK. Deux -types d'événements peuvent survenir -- l'utilisateur peut cliquer sur le widget -avec la souris et faire glisser pour déplacer le pointeur, ou bien la valeur de -l'objet Adjustment peut changer à cause d'une circonstance extérieure. - -<p> -Lorsque l'utilisateur clique sur le widget, on vérifie si le clic s'est bien -passé près du pointeur et si c'est le cas, on stocke alors le bouton avec -lequel l'utilisateur a cliqué dans le champ <em/button/ de la structure du -widget et on récupère tous les événements souris avec un appel à -<em/gtk_grab_add()/. Un déplacement ultérieur de la souris provoque le recalcul -de la valeur de contrôle (par la fonction <em/gtk_dial_update_mouse/). Selon la -politique qui a été choisie, les événements "value_changed" sont, soit générés -instantanément (<em/GTK_UPDATE_CONTINUOUS/), après un délai ajouté au timer -avec <em/gtk_timeout_add()/ (<em/GTK_UPDATE_DELAYED/), ou seulement lorsque le -bouton est relâché (<em/GTK_UPDATE_DISCONTINUOUS/). - -<tscreen><verb> -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); - - /* Détermine si le bouton pressé est dans la région du pointeur. - On fait cela en calculant les distances parallèle et perpendiculaire - du point où la souris a été pressée par rapport à la ligne passant - par le pointeur */ - - 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); - } - } - } -} -</verb></tscreen> - -<p> -Les changements de l'Adjustement par des moyens extérieurs sont communiqués à -notre widget par les signaux "changed" et "value_changed". Les gestionnaires -pour ces fonctions appellent <em/gtk_dial_update()/ pour valider les -paramètres, calculer le nouvel angle du pointeur et redessiner le widget (en -appelant <em/gtk_widget_draw()/). - -<tscreen><verb> -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; - } -} -</verb></tscreen> - -<sect2>Améliorations possibles - -<p> - -Le widget Dial décrit jusqu'à maintenant exécute à peu près 670 lignes de -code. Bien que cela puisse sembler beaucoup, nous en avons vraiment fait -beaucoup avec ce code, notamment parce que la majeure partie de cette longueur -est due aux en-têtes et à la préparation. Cependant, certaines améliorations -peuvent être apportées à ce widget : - -<itemize> -<item> Si vous testez ce widget, vous vous apercevrez qu'il y a un peu de -scintillement lorsque le pointeur est déplacé. Ceci est dû au fait que le -widget entier est effacé, puis redessiné à chaque mouvement du -pointeur. Souvent, la meilleure façon de gérer ce problème est de dessiner sur -un pixmap non affiché, puis de copier le résultat final sur l'écran en une -seule étape (le widget <em/ProgressBar/ se dessine de cette façon). - -<item> L'utilisateur devrait pouvoir utiliser les flèches du curseur vers le -haut et vers le bas pour incrémenter et décrémenter la valeur. - -<item> Ce serait bien si le widget avait des boutons pour augmenter et diminuer -la valeur dans de petites ou de grosses proportions. Bien qu'il serait possible -d'utiliser les widgets <em/Button/ pour cela, nous voudrions aussi que les -boutons s'auto-répètent lorsqu'ils sont maintenus appuyés, comme font les -flèches d'une barre de défilement. La majeure partie du code pour implanter ce -type de comportement peut se trouver dans le widget <em/GtkRange/. - -<item> Le widget Dial pourrait être fait dans un widget container avec un seul -widget fils positionnée en bas, entre les boutons mentionnés -ci-dessus. L'utilisateur pourrait alors ajouter au choix, un widget label ou -entrée pour afficher la valeur courante de l'appel. - -</itemize> - -<sect1>En savoir plus - -<p> -Seule une petite partie des nombreux détails de la création des widgets a pu -être décrite. Si vous désirez écrire vos propres widgets, la meilleure source -d'exemples est le source de GTK lui-même. Posez-vous quelques questions sur les -widgets que vous voulez écrire : est-ce un widget container ? possède-t-il -sa propre fenêtre ? est-ce une modification d'un widget existant ? Puis, -trouvez un widget identique et commencez à faire les modifications. Bonne -chance ! - -<sect>Scribble, un programme simple de dessin - -<sect1>Présentation - -<p> -Dans cette section, nous construirons un programme simple de dessin. Ce -faisant, nous examinerons comment gérer les événements souris, comment dessiner -dans une fenêtre, et comment mieux dessiner en utilisant un pixmap en arrière -plan. Après avoir créé ce programme, nous l'étendrons en lui ajoutant le -support des périphériques <em/Xinput/, comme les tables de tracé. GTK dispose -de routines de support qui facilitent beaucoup l'obtention des informations -étendues (comme la pression et l'inclinaison du stylet) à partir de tels -périphériques. - -<sect1>Gestion d'événement - -<p> -Les signaux GTK que nous avons déjà vus concernent les actions de haut niveau, -comme la sélection d'un choix d'un menu. Cependant, il est quelques fois utile -de connaître les cas de bas niveau, comme le déplacement de la souris, ou la -pression d'une touche. Il existe aussi des signaux GTK correspondant à ces -<em/événements/ bas niveau. Les gestionnaires de ces signaux ont un paramètre -supplémentaire qui est un pointeur vers une structure contenant des -informations sur l'événement. Par exemple, les gestionnaires des événements de -déplacement recoivent un paramètre vers une structure <em/GdkEventMotion/ qui -ressemble (en partie) à ceci : - -<tscreen><verb> -struct _GdkEventMotion -{ - GdkEventType type; - GdkWindow *window; - guint32 time; - gdouble x; - gdouble y; - ... - guint state; - ... -}; -</verb></tscreen> - -<em/type/ sera initialisé avec le type de l'événement, ici -<em/GDK_MOTION_NOTIFY/, <em/window/ est la fenêtre dans laquelle l'événement -est survenu. <em/x/ et <em/y/ donnent les coordonnées de l'événement et -<em/state/ spécifie l'état du modificateur lorsque l'événement s'est produit -(c'est-à-dire quelles sont les touches de modification et les boutons souris -qui ont été pressés). Il s'agit d'un OU bit à bit de l'une des valeurs -suivantes : - -<tscreen><verb> -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 -</verb></tscreen> - -<p> -Comme pour les autres signaux, on appelle <em/gtk_signal_connect()/ pour -déterminer ce qui se passe lorsqu'un événement survient. Mais nous devons aussi -faire en sorte que GTK sache de quels événements nous voulons être -avertis. Pour ce faire, on appelle la fonction : - -<tscreen><verb> -void gtk_widget_set_events (GtkWidget *widget, - gint events); -</verb></tscreen> - -Le deuxième champ spécifie les événements qui nous intéressent. Il s'agit d'un -OU bit à bit de constantes qui indiquent différent types d'événements. Pour -référence ultérieure, les types d'événements sont : - -<tscreen><verb> -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 -</verb></tscreen> - -Il y a quelques points subtils qui doivent être observés lorsqu'on appelle -<em/gtk_widget_set_events()/. D'abord, elle doit être appelée avant que la -fenêtre X d'un widget GTK soit créée. En pratique, cela signifie que l'on doit -l'appeler immédiatement après avoir créé le widget. Ensuite, le widget doit -avoir une fenêtre X associée. Pour des raisons d'efficacité, de nombreux types -de widgets n'ont pas de fenêtre propre, mais se dessinent dans la fenêtre de -leur parent. Ces widgets sont : - -<tscreen><verb> -GtkAlignment -GtkArrow -GtkBin -GtkBox -GtkImage -GtkItem -GtkLabel -GtkPaned -GtkPixmap -GtkScrolledWindow -GtkSeparator -GtkTable -GtkViewport -GtkAspectFrame -GtkFrame -GtkVPaned -GtkHPaned -GtkVBox -GtkHBox -GtkVSeparator -GtkHSeparator -</verb></tscreen> - -Pour capturer les événements pour ces widgets, on doit utiliser un widget -<em/EventBox/. Voir la section sur <ref id="sec_The_EventBox_Widget" name="Le -widget EventBox"> pour plus de détails. - -<p> -Pour notre programme de dessin, on veut savoir quand le bouton de la souris est -pressé et quand la souris est déplacée, nous indiquons donc -<em/GDK_POINTER_MOTION_MASK/ et <em/GDK_BUTTON_PRESS_MASK/. On veut aussi -savoir quand il est nécessaire de redessiner notre fenêtre, on indique donc -<em/GDK_EXPOSURE_MASK/. Bien que nous voulions être avertis via un événement -<em/Configure/ lorsque la taille de notre fenêtre change, on n'a pas besoin de -préciser le flag <em/GDK_STRUCTURE_MASK/ correspondant car il est -automatiquement spécifié pour chaque fenêtre. - -<p> -Il arrive cependant qu'il puisse y avoir un problème en indiquant seulement -<em/GDK_POINTER_MOTION_MASK/. Cela fera que le serveur ajoutera un nouvel -événement de déplacement à la file des événements à chaque fois que -l'utilisateur déplace la souris. Si cela nous prend 0,1 seconde pour gérer un -événement de déplacement, si le serveur X n'ajoute un nouvel événement de -déplacement dans la queue que toutes les 0,05 secondes, nous serons vite à la -traîne de l'utilisateur. Si l'utilisateur dessine pendant 5 secondes, cela nous -prendra 5 secondes de plus pour le traiter après qu'il ait relâché le bouton de -la souris ! Ce que l'on voudrait, c'est ne récupérer qu'un événement de -déplacement pour chaque événement que l'on traite. Pour cela, il faut préciser -<em/GDK_POINTER_MOTION_HINT_MASK/. - -<p> -Avec <em/GDK_POINTER_MOTION_HINT_MASK/, le serveur nous envoit un événement de -déplacement la première fois que la pointeur se déplace après être entré dans -la fenêtre, ou après un événement d'appui ou de relâchement d'un bouton. Les -événements de déplacement suivants seront supprimés jusqu'à ce que l'on demande -explicitement la position du pointeur en utilisant la fonction : - -<tscreen><verb> -GdkWindow* gdk_window_get_pointer (GdkWindow *window, - gint *x, - gint *y, - GdkModifierType *mask); -</verb></tscreen> - -(Il existe une autre fonction, <em/gtk_widget_get_pointer()/ qui possède une -interface simple, mais n'est pas très utile car elle ne fait que récupérer la -position de la souris et ne se préoccupe pas de savoir si les boutons sont -pressés). - -<p> -Le code pour configurer les événements pour notre fenêtre ressemble alors -à : - -<tscreen><verb> - 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); -</verb></tscreen> - -Nous garderons les gestionnaires de "expose_event" et "configure_event" pour -plus tard. Les gestionnaires de "motion_notify_event" et "button_press_event" -sont très simples : - -<tscreen><verb> -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; -} -</verb></tscreen> - - -<sect1>Le widget DrawingArea et le dessin - -<p> -Revenons au processus de dessin sur l'écran. Le widget que l'on utilise pour -ceci est le widget <em/DrawingArea/. Un tel widget est essentiellement une -fenêtre X et rien de plus. Il s'agit d'une toile vide sur laquelle nous pouvons -dessiner ce que nous voulons. - -Une zone de dessin est créée avec l'appel : - -<tscreen><verb> -GtkWidget* gtk_drawing_area_new (void); -</verb></tscreen> - -Une taille par défaut peut être donnée au widget par l'appel : - -<tscreen><verb> -void gtk_drawing_area_size (GtkDrawingArea *darea, - gint width, - gint height); -</verb></tscreen> - -Cette taille par défaut peu être surchargée en appelant -<em/gtk_widget_set_usize()/ et celle-ci, à son tour, peut être surchargée si -l'utilisateur modifie manuellement la taille de la fenêtre contenant la zone de -dessin. - -<p> -Il faut noter que lorsque l'on crée un widget <em/DrawingArea/, nous sommes -<em>complètement</em> responsable du dessin du contenu. Si notre fenêtre est -cachée puis redécouverte, nous recevrons un événement d'exposition et devrons -redessiner ce qui a été caché auparavant. - -<p> -Devoir se rappeler tout ce qui a été dessiné à l'écran pour pouvoir -correctement le redessiner peut s'avérer, c'est le moins que l'on puisse dire, -pénible. De plus, cela peut être visible si des portions de la fenêtre sont -effacées puis redessinées étape par étape. La solution à ce problème est -d'utiliser un <em/pixmap d'arrière-plan/ qui n'est pas sur l'écran. Au lieu de -dessiner directement à l'écran, on dessine sur une image stockée dans la -mémoire du serveur et qui n'est pas affichée, puis, lorsque l'image change ou -lorsque de nouvelles portions de l'image sont affichées, on copie les parties -adéquates sur l'écran. - -<p> -Pour créer un pixmap mémoire, on appelle la fonction : - -<tscreen><verb> -GdkPixmap* gdk_pixmap_new (GdkWindow *window, - gint width, - gint height, - gint depth); -</verb></tscreen> - -Le paramètre <em/windows/ indique une fenêtre GTK de laquelle ce pixmap tire -certaines de ses propriétés. <em/width/ et <em/height/ précisent la taille du -pixmap. <em/depth/ précise la <em/profondeur de couleur/, c'est-à-dire le -nombre de bits par pixel, de la nouvelle fenêtre. Si cette profondeur vaut -<em/-1/, elle correspondra à celle de <em/window/. - -<p> -Nous créons le pixmap dans notre gestionnaire "configure_event". Cet événement -est généré à chaque fois que la fenêtre change de taille, y compris lorsqu'elle -initialement créée. - -<tscreen><verb> -/* Pixmap d'arrière-plan pour la zone de dessin */ -static GdkPixmap *pixmap = NULL; - -/* Création d'un nouveau pixmap d'arrière-plan de la taille voulue */ -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; -} -</verb></tscreen> - -L'appel à <em/gdk_draw_rectangle()/ remet le pixmap à blanc. Nous en dirons un -peu plus dans un moment. - -<p> -Notre gestionnaire d'événement d'exposition copie alors simplement la partie -concernées du pixmap sur l'écran (on détermine la zone qu'il faut redessiner en -utilisant le champ <em/event->area/ de l'événement d'exposition) : - -<tscreen><verb> -/* Remplit l'écran à partir du pixmap d'arrière-plan */ -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; -} -</verb></tscreen> - -Nous avons vu comment garder l'écran à jour avec notre pixmap, mais comment -dessine-t-on réellement ce que l'on veut dans le pixmap ? Il existe un grand -nombre d'appels dans la bibliothèque GDK de GTK pour dessiner sur des -<em>dessinables</em>. Un dessinable est simplement quelque chose sur lequel on -peut dessiner. Cela peut être une fenêtre, un pixmap, ou un bitmap (une image -en noir et blanc). Nous avons déjà vu plus haut deux de ces appels, -<em/gdk_draw_rectangle()/ et <em/gdk_draw_pixmap()/. La liste complète -est : - -<tscreen><verb> -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 () -</verb></tscreen> - -Consultez la documentation de référence ou le fichier en-tête -<em/<gdk/gdk.h>/ pour plus de détails sur ces fonctions. Celles-ci -partagent toutes les mêmes deux paramêtres. Le premier est le dessinable sur -lequel dessiner, le second est un <em/contexte graphique/ (GC). - -<p> -Un contexte graphique encapsule l'information sur des choses comme les couleurs -de premier et d'arrière plan et la largeur de ligne. GDK possède un ensemble -complet de fonctions pour créer et manipuler les contextes graphiques, mais, -pour simplifier, nous n'utiliserons que les contextes graphiques -prédéfinis. Chaque widget a un style associé (qui peut être modifié dans un -fichier gtkrc, voir la section sur les fichiers rc de GTK). Celui-ci, entre -autres choses, stocke plusieurs contextes graphiques. Quelques exemples d'accès -à ces contextes sont : - -<tscreen><verb> -widget->style->white_gc -widget->style->black_gc -widget->style->fg_gc[GTK_STATE_NORMAL] -widget->style->bg_gc[GTK_WIDGET_STATE(widget)] -</verb></tscreen> - -Les champs <em/fg_gc, bg_gc, dark_gc/ et <em/light_gc/ sont indexés par un -paramètre de type <em/GtkStateType/ qui peut prendre les valeurs : - -<tscreen><verb> -GTK_STATE_NORMAL, -GTK_STATE_ACTIVE, -GTK_STATE_PRELIGHT, -GTK_STATE_SELECTED, -GTK_STATE_INSENSITIVE -</verb></tscreen> - -Par exemple, pour <em/GTK_STATE_SELECTED/, la couleur de premier plan par -défaut est blanc et la couleur d'arrière plan par défaut est bleu foncé. - -<p> -Notre fonction <em/draw_brush()/, qui réalise le dessin à l'écran est alors : - -<tscreen><verb> -/* Dessine un rectangle à l'écran */ -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); -} -</verb></tscreen> - -Après avoir dessiné le rectangle représentant la brosse sur le pixmap, nous -appelons la fonction : - -<tscreen><verb> -void gtk_widget_draw (GtkWidget *widget, - GdkRectangle *area); -</verb></tscreen> - -qui indique à X que la zone donnée par le paramètre <em/area/ a besoin d'être -mise à jour. X génèrera éventuellement un événement d'exposition (en combinant -peut-être les zones passés dans plusieurs appels à <em/gtk_widget_draw()/) ce -qui forcera notre gestionnaire d'événement d'exposition à copier les parties -adéquates à l'écran. - -<p> -Nous avons maintenant couvert entièrement le programme de dessin, sauf quelques -détails banals comme la création de la fenêtre principale. Le code source -complet est disponible à l'endroit où vous avez obtenu ce didacticiel. - -<sect1>Ajouter le support XInput - -<p> -Il est maintenant possible d'acheter des périphériques bon marché, comme les -tablettes graphiques qui permettent d'exprimer beaucoup plus facilement son -talent qu'avec une souris. La façon la plus simple pour utiliser de tels -périphériques est simplement de le faire comme un remplacement de la souris, -mais cela ne tire pas partie des nombreux avantages de ces périphériques, -comme : - -<itemize> -<item> Sensibilité à la pression ; -<item> rapport d'inclinaison ; -<item> positionnement au dessous du pixel ; -<item> entrées multiples (par exemple, un stylet avec pointe et gomme). -</itemize> - -Pour des informations sur l'extension XInput, voir <url -url="http://www.msc.cornell.edu/~otaylor/xinput/XInput-HOWTO.html" -name="XInput-HOWTO">. - -<p> -Si l'on examine la définition complète de, par exemple, la structure -<em/GdkEventMotion/, on voit qu'elle possède des champs pour supporter des -informations étendues sur les périphériques. - -<tscreen><verb> -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; -}; -</verb></tscreen> - -<em/pressure/ indique la pression comme un nombre réel compris entre 0 et 1. -<em/xtilt/ et <em/ytilt/ peuvent prendre des valeurs entre -1 et 1, -correspondant au degré d'inclinaison dans chaque direction, <em/source/ et -<em/deviceid/ précisent de deux façons différentes le périphérique pour lequel -l'événement est survenus. <em/source/ donne une simple information sur le type -du périphérique. Il peut prendre l'une des valeurs suivantes : - -<tscreen><verb> -GDK_SOURCE_MOUSE -GDK_SOURCE_PEN -GDK_SOURCE_ERASER -GDK_SOURCE_CURSOR -</verb></tscreen> - -<tt/deviceid/ précise un ID numérique unique pour le périphérique. Il peut être -utilisé pour trouver des informations supplémentaires sur le périphérique en -utilisant l'appel <em/gdk_input_list_devices()/ (voir ci-dessous). La valeur -spéciale <em/GDK_CORE_POINTER/ sert à désigner le périphérique de pointage -principal (habituellement la souris). - -<sect2>Valider l'information supplémentaire sur un périphérique - -<p> -Pour indiquer à GTK que l'on désire obtenir des informations supplémentaires -sur le périphérique, on a simplement besoin d'ajouter une ligne à nos -programmes. - -<tscreen><verb> -gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_CURSOR); -</verb></tscreen> - -En donnant la valeur <em/GDK_EXTENSION_EVENTS_CURSOR/, on indique que nous -désirons les événements d'extension, mais seulement si l'on ne doit pas -dessiner notre propre curseur. Voir la section <ref -id="sec_Further_Sophistications" name="Sophistications supplémentaires"> -ci-dessous pour des plus de détails sur le dessin du curseur. Nous pourrions -aussi donner les valeurs <em/GDK_EXTENSION_EVENTS_ALL/ si nous voulons dessiner -notre propre curseur, ou <tt/GDK_EXTENSION_EVENTS_NONE/ pour revenir à la -situation par défaut. - -<p> -Toutefois, nous ne sommes pas complètement à la fin de l'histoire. Par défaut, -aucun périphérique d'extension n'est autorisé. Nous avons besoin d'un mécanisme -pour que les utilisateurs puissent autoriser et configurer leur extensions. GTK -dispose du widget <em/InputDialog/ pour automatiser cette tâche. La procédure -suivante gère un widget InputDialog. Elle crée le dialogue s'il n'est pas -présent et le place au premier plan sinon. - -<tscreen><verb> -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); - } -} -</verb></tscreen> - -(vous pouvez remarquer la façon dont nous gérons ce dialogue. En le connectant -au signal "destroy", nous nous assurons que nous ne garderons pas un pointeur -sur le dialogue après l'avoir détruit -- cela pourrait provoquer une erreur de -segmentation). - - -<p> -InputDialog a deux boutons "Close" et "Save", qui n'ont pas d'actions qui leur -sont assignées par défaut. Dans la fonction ci-dessus, nous associons à "Close" -le masquage du dialogue et nous cachons le bouton "Save" car nous n'implantons -pas la sauvegarde des options XInput dans ce programme. - -<sect2>Utiliser l'information supplémentaire d'un périphérique - -<p> -Lorsque l'on a validé le périphérique, on peut simplement utiliser -l'information supplémentaire des champs des structures d'événement. En fait, il -est toujours prident d'utiliser ces informations car ces champs auront des -valeurs par défaut judicieuses même lorsque les événements supplémentaires ne -sont pas autorisés. - -<p> -La seule modification consiste à appeler <em/gdk_input_window_get_pointer()/ au -lieu de <em/gdk_window_get_pointer/. Cela est nécessaire car -<em/gdk_window_get_pointer/ ne retourne pas l'information supplémentaire. - -<tscreen><verb> -void gdk_input_window_get_pointer (GdkWindow *window, - guint32 deviceid, - gdouble *x, - gdouble *y, - gdouble *pressure, - gdouble *xtilt, - gdouble *ytilt, - GdkModifierType *mask); -</verb></tscreen> - -Lorsque l'on appelle cette fonction, on doit préciser l'ID du périphérique -ainsi que la fenêtre. Habituellement, on aura obtenu cet ID par le champ -<em/deviceid/ d'une structure d'événement. Cette fonction retournera une valeur -cohérente lorsque les événements ne sont pas autorisés (dans ce cas, -<em/event->deviceid/ aura la valeur <em/GDK_CORE_POINTER/). - -La structure de base des gestionnaires d'événements de déplacement et de bouton -pressé ne change donc pas trop -- il faut juste ajouter le code permettant de -traiter l'information supplémentaire. - -<tscreen><verb> -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; -} -</verb></tscreen> - -On doit aussi faire quelquechose de cette nouvelle information. Notre nouvelle -fonction <em/draw_brush()/ dessine avec une couleur différente pour chaque -<em/event->source/ et change la taille du pinceau selon la pression. - -<tscreen><verb> -/* Dessine un rectangle à l'écran, la taille dépend de la pression, - et la couleur dépend du type de périphérique */ -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); -} -</verb></tscreen> - -<sect2>En savoir plus sur un périphérique - -<p> -Notre programme affichera le nom du périphérique qui a généré chaque appui de -bouton. Pour trouver le nom d'un périphérique, nous appelons la fonction : - -<tscreen><verb> -GList *gdk_input_list_devices (void); -</verb></tscreen> - -qui retourne une GList (un type de liste chaînée de la bibliothèque glib) de -structures GdkDeviceInfo. La structure GdkDeviceInfo est définie de la façon -suivante : - -<tscreen><verb> -struct _GdkDeviceInfo -{ - guint32 deviceid; - gchar *name; - GdkInputSource source; - GdkInputMode mode; - gint has_cursor; - gint num_axes; - GdkAxisUse *axes; - gint num_keys; - GdkDeviceKey *keys; -}; -</verb></tscreen> - -La plupart de ces champs sont des informations de configuration que l'on peut -ignorer sauf si l'on implante la sauvegarde de la configuration XInput. Celui -qui nous intéresse est <em/name/ qui est, tout simplement, le nom que X donne -au périphérique. L'autre champ, qui n'est pas une information de configuration, -est <em/has_cursor/. Si <em/has_cursor/ est faux, on doit dessiner notre propre -curseur, mais puisque nous avons précisé <em/GDK_EXTENSION_EVENTS_CURSOR/, nous -n'avons pas à nous en préoccuper. - -<p> -Notre fonction <em/print_button_press()/ ne fait parcourir la liste retournée -jusqu'à trouver une correspondance, puis affiche le nom du périphérique. - -<tscreen><verb> -static void -print_button_press (guint32 deviceid) -{ - GList *tmp_list; - - /* gdk_input_list_devices retourne une liste interne, nous ne devons donc - pas la libérer après */ - tmp_list = gdk_input_list_devices(); - - while (tmp_list) - { - GdkDeviceInfo *info = (GdkDeviceInfo *)tmp_list->data; - - if (info->deviceid == deviceid) - { - printf("Bouton pressé sur le périphérique '%s'\n", info->name); - return; - } - - tmp_list = tmp_list->next; - } -} -</verb></tscreen> - -Ceci termine les modifications de notre programme « XInputize ». Comme pour la -première version, le code complet est disponible à l'endroit où vous avez -obtenu ce didacticiel. - -<sect2>Sophistications supplémentaires<label id="sec_Further_Sophistications"> - -<p> -Bien que notre programme supporte maintenant XInput, il y manque des -caractéristiques que l'on souhaite trouver dans les applications -complètes. D'abord, l'utilisateur ne veut probablement pas avoir à configurer -ses périphériques à chaque fois qu'il lance le programme et nous devons donc -lui permettre de sauvegarder la configuration du périphérique. Ceci est réalisé -en parcourant ce que retourne <em/gdk_input_list_devices()/ et en écrivant la -configuration dans un fichier. - -<p> -Pour restaurer un état au prochain démarrage du programme, GDK dispose de -fonctions pour changer la configuration des périphériques : - -<tscreen><verb> -gdk_input_set_extension_events() -gdk_input_set_source() -gdk_input_set_mode() -gdk_input_set_axes() -gdk_input_set_key() -</verb></tscreen> - -(La liste retournée par <em/gdk_input_list_devices()/ ne doit pas être modifiée -directement). Un exemple est donné dans le programme de dessin <em/gsumi/ -(disponible à l'adresse <htmlurl -url="http://www.msc.cornell.edu/~otaylor/gsumi/" -name="http://www.msc.cornell.edu/~otaylor/gsumi/">). De plus, ce serait -pratique d'avoir une méthode standard pour faire cela pour toutes les -applications. Ceci appartient probablement à un niveau légèrement supérieur à -GTK, peut-être dans la bibliothèque GNOME. - -<p> -Une autre grosse omission que nous avons mentionnée plus haut est l'absence de -dessin du curseur. Les plates-formes autres qu'XFree86 n'autorisent pas encore -l'utilisation simultanée d'un périphérique comme pointeur de base et comme -pointeur d'une application. Lisez le <url -url="http://www.msc.cornell.edu/~otaylor/xinput/XInput-HOWTO.html" -name="XInput-HOWTO"> pour plus d'informations là-dessus. Ceci signifie que les -applications qui veulent atteindre le plus de monde possible doivent dessiner -leur propre curseur. - -<p> -Une application qui dessine son propre curseur doit faire deux choses : -déterminer si le périphérique courant a besoin ou non d'un curseur dessiné et -déterminer si le périphérique courant est à proximité (si celui-ci est une -tablette de dessin, il est pratique de faire disparaître le curseur lorsque le -stylet est en dehors de la tablette. Lorsque le périphérique voit le stylet, on -dit qu'il est « à proximité »). La première vérification est faite en -recherchant dans la liste des périphériques, comme nous l'avons fait pour -obtenir le nom du périphérique. La deuxième est réalisée en choisissant des -événements "proximity_out". Une exemple de dessin d'un curseur personnel est -donné dans le programme <em/testinput/ de la distribution GTK. - - -<sect>Conseils pour l'écriture d'applications GTK -<p> -Cette section est simplement un regroupement de lignes de conduites générales -et sages, ainsi que d'astuces pour créer des applications GTK correctes. Elle -est totalement inutile pour l'instant car il ne s'agit que d'une phrase :) - -Utilisez <em/autoconf/ et <em/automake/ de GNU ! Ce sont vos amis :) J'ai en -projet de les présenter brièvement ici. - -<sect>Contributions - -<p> -Ce document, comme beaucoup d'autres beaux logiciels, a été créé (NdT : et -traduit) par des -volontaires bénévoles. Si vous vous y connaissez sur certains aspects de GTK -qui ne sont pas encore documentés, soyez gentils de contribuer à ce document. - -<p> -Si vous décidez de contribuer, envoyez-moi (Ian Main) votre texte à -<tt><htmlurl url="mailto:slow@intergate.bc.ca" -name="slow@intergate.bc.ca"></tt>. La totalité de ce document est libre et -tout ajout que vous pourriez y faire doit l'être également. Ainsi, tout le -monde peut utiliser n'importe quelle partie de vos exemples dans les -programmes, les copies de ce document peuvent être distribuées à volonté, etc. -<p> -Merci. - - -<sect>Remerciements -<p> -Je voudrai remercier les personnes suivantes pour leurs contributions à ce texte : - -<itemize> -<item>Bawer Dagdeviren, <tt><htmlurl url="mailto:chamele0n@geocities.com" -name="chamele0n@geocities.com"></tt> pour le didacticiel sur les menus. - -<item>Raph Levien, <tt><htmlurl url="mailto:raph@acm.org" -name="raph@acm.org"></tt> -pour <em/bonjour tout le monde/ à la GTK, le placement des widgets et pour sa -sagesse. Il a aussi généreusement donné un abri à ce didacticiel. - -<item>Peter Mattis, <tt><htmlurl url="mailto:petm@xcf.berkeley.edu" -name="petm@xcf.berkeley.edu"></tt> pour le programme GTK le plus simple et pour -sa capacité à le faire :) - -<item>Werner Koch <tt><htmlurl url="mailto:werner.koch@guug.de" -name="werner.koch@guug.de"></tt> pour la conversion du texte original en SGML, -et pour la hiérarchie des classes de widget. - -<item>Mark Crichton <tt><htmlurl url="mailto:crichton@expert.cc.purdue.edu" -name="crichton@expert.cc.purdue.edu"></tt> pour le code de l'usine à menus et -pour le didacticiel de placement des tables. - -<item>Owen Taylor <tt><htmlurl url="mailto:owt1@cornell.edu" -name="owt1@cornell.edu"></tt> pour la section sur le widget EventBox (et le -patch de la distribution). Il est aussi responsable des sections sur l'écriture -de vos propres widgets GTK et de l'application exemple. Merci beaucoup à Owen -pour toute son aide ! - -<item>Mark VanderBoom <tt><htmlurl url="mailto:mvboom42@calvin.edu" -name="mvboom42@calvin.edu"></tt> pour son merveilleux travail sur les widgets -Notebook, Progress Bar, Dialog et File selection. Merci beaucoup, Mark ! Ton -aide a été très précieuse. - -<item>Tim Janik <tt><htmlurl url="mailto:timj@gtk.org" -name="timj@gtk.org"></tt> pour son beau travail sur le widget Lists. -Merci Tim :) - -<item>Rajat Datta <tt><htmlurl url="mailto:rajat@ix.netcom.com" -name="rajat@ix.netcom.com"</tt> pour son excellent travail sur le didacticiel -sur les Pixmaps. - -<item>Michael K. Johnson <tt><htmlurl url="mailto:johnsonm@redhat.com" -name="johnsonm@redhat.com"></tt> pour ses infos et le code pour les menus. - -</itemize> -<p> -Et à tous ceux d'entre vous qui ont commenté et aidé à améliorer ce document. -<p> -Merci. - -<sect>Copyright -<p> -Ce didacticiel est Copyright (C) 1997 Ian Main -<p> -Ce programme est un logiciel libre ; vous pouvez le redistribuer et/ou le -modifier sous les termes de la licence publique générale GNU telle qu'elle est -publiée par la Free Software Foundation ; soit la version 2 de la licence, ou -(comme vous voulez) toute version ultérieure. -<p> -Ce programme est distribué dans l'espoir qu'il sera utile, mais SANS AUCUNE -GARANTIE ; même sans la garantie de COMMERCIALITÉ ou d'ADÉQUATION A UN BUT -PARTICULIER. Voir la licence publique générale GNU pour plus de détails. -<p> -Vous devriez avoir reçu une copie de la licence publique générale GNU avec ce -programme ; si ce n'est pas le cas, écrivez à la Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -<sect1>Notes du traducteur -Ce document a été adapté en Français par <url url="mailto:jaco@dotcom.fr" -name="Éric Jacoboni">. Toute remarque sur cette adaptation sera la bienvenue. -<p> -Merci à <url url="mailto:kheops@linux-kheops.com" name="Joël Bernier"> pour -avoir initié cette adaptation, et à <url url="mailto:vincent@debian.org" - name="Vincent Renardias"> pour sa relecture. -</article> diff --git a/docs/tutorial/gtk_tut_it.sgml b/docs/tutorial/gtk_tut_it.sgml deleted file mode 100644 index 321a2b58de..0000000000 --- a/docs/tutorial/gtk_tut_it.sgml +++ /dev/null @@ -1,10090 +0,0 @@ -<!doctype linuxdoc system> -<article> -<title>GTK Tutorial -<author>Ian Main <tt><htmlurl url="mailto:imain@gtk.org" - name="<imain@gtk.org>"></tt>, -Tony Gale <tt><htmlurl url="mailto:gale@gtk.org" - name="<gale@gtk.org>"></tt> -<date>May 24th, 1998 - Traduzione aggiornata al 27 Maggio 1998 - -<abstract>Tradotto da Michel Morelli, <tt><htmlurl url="mailto:ziobudda@chiara.dei.unipd.it" name="ziobudda@chiara.dei.unipd.it"></tt>, Daniele Canazza, <tt><htmlurl url="mailto:dcanazz@tin.it" name="dcanazz@tin.it"></tt> e Antonio Schifano, <tt><htmlurl url="mailto:schifano@cli.di.unipi.it" name="schifano@cli.di.unipi.it"></tt> -</abstract> -<!-- ***************************************************************** --> -<sect>Introduzione -<!-- ***************************************************************** --> -<p> -GTK (GIMP Toolkit) è stato orginariamente sviluppato come toolkit per -il programma GIMP (General Image Manipulation Program). GTK è costruito -sulla base del kit di disegno di GIMP, il GDK (GIMP Drawing Kit) il quale -è costruito a sua volta attorno alle funzioni della Xlib. E' chiamato -``toolkit di GIMP'' perché era inizialmente scritto per sviluppare GIMP, -ma ora viene utilizzato nello sviluppo di molti progetti software ``free''. -Gli autori sono -<itemize> -<item> Peter Mattis <tt><htmlurl url="mailto:petm@xcf.berkeley.edu" - name="petm@xcf.berkeley.edu"></tt> -<item> Spencer Kimball <tt><htmlurl url="mailto:spencer@xcf.berkeley.edu" - name="spencer@xcf.berkeley.edu"></tt> -<item> Josh MacDonald <tt><htmlurl url="mailto:jmacd@xcf.berkeley.edu" - name="jmacd@xcf.berkeley.edu"></tt> -</itemize> - -<p> -GTK è essenzialmente una API (application programmers interface) -orientata agli oggetti. -Anche se scritto completamente in C, è implementato usando l'idea delle -classi e delle funzioni di callback (puntatori a funzioni). - -<p> -C'è anche una terza componente chiamata glib che contiene una serie di -implementazioni differenti di alcune chiamate di funzioni standard e anche -alcune funzioni aggiuntive, per esempio per la manipolazione delle liste -collegate. Le funzioni sostitutive sono usate per migliorare la -portabilità di GTK. Alcune delle funzioni implementate qui non sono -disponibili o non sono standard, altre sono uniche come g_strerror(). -Altre contengono miglioramenti alle stesse della libc come g_malloc che ha -delle utility di debugging migliorate. - -<p> -Questo tutorial è un tentativo di documentare il meglio possibile la -libreria gtk e non pretende di essere completo. Questo tutorial suppone una -buona conoscenza del linugaggio C e di come creare programmi in C. Saranno -facilitati i lettori che hanno una precedente esperienza nella programmazione -in X. Se il GTK è il primo insieme di widget che studiate, vi prego di -dirmi come avete trovato questo tutorial e che tipo di problemi avete avuto. -Notate che c'è anche una versione per il C++ della libreria GTK (chiamata -GTK--), quindi se preferite utilizzare questo linguaggio al posto del C potreste -cercare questa versione al posto della GTK normale. -Ci sono poi un ``wrapper'' Objective C e un collegamento a Guile, ma non ne -seguo l'evoluzione. - -<p> -Mi farebbe molto piacere conoscere qualsiasi problema che abbiate avuto -nell'imparare il GTK da questo documento e apprezzerei anche critiche sul come -migliorarlo. - -<!-- ***************************************************************** --> -<sect>Iniziamo -<!-- ***************************************************************** --> -<p> -La prima cosa da fare è certamente quella di scaricare il GTK e installarlo. -Potete prendere l'ultima versione dal sito ftp.gtk.org in /pub/gtk. Un'altra -possibile sorgente di informazioni è il sito -<htmlurl url="http://www.gtk.org/" name="http://www.gtk.org/">. - -GTK usa il comando GNU autoconf per autoconfigurarsi. -Una volta estratti i file dall'archivio tar, eseguite configure --help per -vedere una lista delle opzioni del comando configure. - -<p> -Per iniziare la nostra introduzione a GTK, cominceremo con il più semplice -programma possibile. Questo programma crea una finestra con dimensioni (in pixel) -di 200x200 e l'unica possibilità di uscita è di ucciderlo usando la -shell o il Window Manager. - -<tscreen><verb> -#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; -} -</verb></tscreen> - -Tutti i programmi GTK includeranno sicuramente <gtk/gtk.h> in cui vengono -dichiarate le variabili, le funzioni, le strutture, etc. che saranno usate nella -tua applicazione GTK. - -<p> -La linea seguente: - -<tscreen><verb> -gtk_init (&argc, &argv); -</verb></tscreen> - -invoca la funzione gtk_init(gint *argc, gchar ***argv) che sarà usata in -tutte le applicazioni GTK. Questa funzione sistema alcune cose al posto nostro, -come la visuale predefinita e la mappa dei colori, e procede poi chiamando -gdk_init(gint *argc, gchar ***argv). -Questa funzione inizializza la libreria per l'uso, setta il gestore predefinito -dei segnali e guarda negli argomenti, passati via linea di comando alla vostra -applicazione, alla ricerca di uno di questi argomenti: -<itemize> -<item> <tt/--display/ -<item> <tt/--debug-level/ -<item> <tt/--no-xshm/ -<item> <tt/--sync/ -<item> <tt/--show-events/ -<item> <tt/--no-show-events/ -</itemize> -<p> -Rimuove poi questi argomenti dalla lista degli argomenti passati, lasciando -quelli non riconosciuti a disposizione della vostra applicazione che potrà -tenerne conto o ignorarli. -In questo modo si crea un set di argomenti standard accettato da tutte le -applicazioni GTK. - -<p> -Le seguenti 2 linee di codice creano e mostrano la finestra. - -<tscreen><verb> - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_widget_show (window); -</verb></tscreen> - -L'argomento GTK_WINDOW_TOPLEVEL specifica che noi vogliamo che la nostra finestra -si sottometta alle decorazioni del windows manager e alla posizione che quest'ultimo -indicherà. Invece di creare una finestra avente dimensioni 0x0, la dimensione -di una finestra senza figli (altri widget, come i bottoni, etc) è predefinita -a 200x200 così che si possa manipolarla. -La funzione gtk_widget_show() fa sì che GTK sappia che abbiamo finito di -settare gli attributi di questo widget e che quindi quest'ultimo può essere -visualizzato. - -<p> -L'ultima linea ci fa entrare nel ciclo principale del GTK. - -<tscreen><verb> -gtk_main (); -</verb></tscreen> - -gtk_main() è un'altra chiamata che vedrete in tutte le applicazioni GTK. -Quando il controllo raggiunge questo punto, l'applicazione si metterà a -dormire aspettando che si verifichino eventi di X (come la pressione di un bottone -o di un tasto), timeout o notifiche di Input/Output dai file -Nel nostro esempio, comunque, tutti gli eventi vengono ignorati. - -<!-- ----------------------------------------------------------------- --> -<sect1>Hello World in GTK -<!-- ----------------------------------------------------------------- --> -<p> -Ok, ora un programma con un widget (un bottone). E' il classico ``Hello World'' -alla GTK. - -<tscreen><verb> -/* helloworld.c */ -#include <gtk/gtk.h> - - -/* E' una funzione di ritorno (callback). Gli argomenti passati sono ignorati in questo -* esempio. -* Piu' informazioni sulle callback in seguito. */ - -void hello (GtkWidget *widget, gpointer data) -{ - g_print ("Hello World\n"); -} - -gint delete_event(GtkWidget *widget, gpointer data) - { - g_print ("delete event occured\n"); - /* Se si dà FALSE al gestore del segnale ``delete_event'', GTK emettera' il segnale - * ``destroy''. Fornire TRUE significa non volere che la finestra sia distrutta. - * Questo e' utile per far uscire delle finestre di dialogo del tipo: - * 'sei sicuro di voler uscire ?' - * Cambia TRUE in FALSE e la finestra principale sara' distrutta con un "delete_event" - */ - return (TRUE); - -} - - -/* Un'altra callback */ -void destroy (GtkWidget *widget, gpointer data) -{ - gtk_main_quit (); -} - -int main (int argc, char *argv[]) -{ - /* GtkWidget e' il tipo di dato per i Widget */ - GtkWidget *window; - GtkWidget *button; - - /* Questa e' una chiamata presente in tutte le applicazioni GTK. Gli argomenti della - linea di comando vengono scorsi e restituiti alla applicazione */ - gtk_init (&argc, &argv); - - /* Crea una nuova finestra */ - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - - /* Quando alla finestra viene passato il segnale ``delete_event'' (questo - * segnale viene passato Windows Manager di solito con l'opzione 'close' - * o con la barra del titolo (title bar)) noi chiediamo che la funzione - * delete_event() (definita sopra) venga invocata. - * Il dato passato come argomento alla funzione di ritorno é NULL - * ed é ignorato dalla funzione stessa. */ - gtk_signal_connect (GTK_OBJECT (window), "delete_event", - GTK_SIGNAL_FUNC (delete_event), NULL); - - /* Qui connettiamo l'evento ``destroy'' al gestore del segnale. - * Questo evento accade quando noi chiamimo la funzione gtk_widget_destroy() - * sulla finestra o se ritorniamo FALSE dalla callback ``delete_event''. */ - gtk_signal_connect (GTK_OBJECT (window), "destroy", - GTK_SIGNAL_FUNC (destroy), NULL); - - /* Setta il bordo interno della finestra */ - gtk_container_border_width (GTK_CONTAINER (window), 10); - - /* Crea un nuovo bottone avente etichetta (label) uguale a ``Hello World'' */ - button = gtk_button_new_with_label ("Hello World"); - - /* Quando il bottone riceve il segnale ``clicked'', invochera' la funzione - * hello() passando NULL come argomento della funzione. La funzione - * hello() é definita sopra. */ - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (hello), NULL); - - /* Questo farà sì che la finestra venga distrutta dalla chiamata - * gtk_widget_destroy(window) quando il bottone verrà premuto. Ancora, - * questo segnale (``destroy'') puo' arrivare da qui o dal windows - * manager */ - gtk_signal_connect_object (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (gtk_widget_destroy), - GTK_OBJECT (window)); - - /* Questo inserisce il bottone nella finestra - * (un contenitore GTK) */ - gtk_container_add (GTK_CONTAINER (window), button); - - /* Il passo finale é il mostrare questo nuovo widget appena creato */ - gtk_widget_show (button); - - /* e la finestra */ - gtk_widget_show (window); - - /* Tutte le applicazioni GTK devono avere la funzione gtk_main(). - * Il controllo finisce qui e attende un evento (come la pressione - * di un tasto o l'evento di un mouse). */ - gtk_main (); - - return 0; -} -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Compilare hello World -<!-- ----------------------------------------------------------------- --> -<p> -Per compilare si utilizza : - -<tscreen><verb> - -gcc -Wall -g helloworld.c -o hello_world `gtk-config --cflags` \ - `gtk-config --libs` -</verb></tscreen> -(N.d.T.: se lanciato da linea di comando, il precedente comando di -compilazione va messo su di una unica linea eliminando il backslash) -<p> -In questo modo, si usa il progamma <tt>gtk-config</>, che viene -distribuito con gtk. Questo programma 'sa' che opzioni di compilatore -sono necessarie per compilare i programmi che usano gtk. -<tt>gtk-config --cflags</> dà come risultato una lista di directory -in cui i file di include devono essere cercati, e <tt>gtk-config --libs</> -fornisce invece la lista delle librerie che devono essere linkate con le -directory in cui devono essere cercate. - -<p> -Le librerie che normalmente vengono linkate sono: -<itemize> -<item> la libreria glib (-lglib), contiene varie funzioni, ma solo -g_print() é usato in questo esempio. GTK si appoggia a questa -libreria, quindi essa viene sempre, comunque, linkata. Vedi comunque -la sezione sulla <ref id="sec_glib" name="glib"> per altri dettagli. -<item>La libreria GDK (-lgdk), la copertura della X11. -<item>La libreria GTK (-lgtk), la libreria dei widget, basata sulla GDK. -<item>La libreria Xlib(-lX11) la quale è usata dalla GDK. -<item>La libreria Xext(-lXext). Questa contiene il codice per le pixmap a -memoria condivisa e altre estensioni di X. -<item>La libreria matematica (-lm). Questa é usata dalla GTK per -vari scopi. -</itemize> - -<!-- ----------------------------------------------------------------- --> -<sect1>Teoria dei segnali e delle funzioni di ritorno (callback) -<p> -Prima di guardare in dettaglio ``Hello World'', parleremo un po' degli eventi -e delle funzioni di ritorno. GTK è un toolkit guidato dagli eventi, -il che significa che se ne starà a dorimire in gtk_main finché -non succede un evento ed il controllo viene passato alla funzione appropriata. - -<p> -Questo passaggio di controllo è basato sull'idea dei segnali. -Quando si ha un evento, come la pressione di un bottone del mouse, verrà -emesso il segnale appropriato, per esempio dal widget che é stato premuto. -Questo è il modo in cui GTK fa molto del suo utile lavoro. Per far -sì che un bottone esegua una azione, prepareremo un gestore del segnale -che catturi questi segnali e chiami la funzione corretta. Questo viene fatto -usando una funzione del tipo: - -<tscreen><verb> -gint gtk_signal_connect (GtkObject *object, - gchar *name, - GtkSignalFunc func, - gpointer func_data); -</verb></tscreen> -<p> -in cui il primo argomento è il widget che emetterà il segnale, -il secondo è il nome del segnale che si vuole catturare, il terzo è -la funzione che verrà invocata quando il segnale sarà catturato e -il quarto è il dato che potrà essere passato a questa funzione. -<p> -La funzione specificata come terzo argomento è chiamata ``funzione di -ritorno (callback)'', e dovrebbe essere della forma: - -<tscreen><verb> -void callback_func(GtkWidget *widget, gpointer callback_data); -</verb></tscreen> -<p> -Dove il primo argomento sarà un puntatore al widget che emette il segnale -e il secondo un puntatore al dato passato come ultimo argomento della funzione -gtk_signal_connect() come descritto sopra. -<p> -Un'altra chiamata usata nell'esempio Hello World è: - -<tscreen><verb> -gint gtk_signal_connect_object (GtkObject *object, - gchar *name, - GtkSignalFunc func, - GtkObject *slot_object); -</verb></tscreen> -<p> -gtk_signal_connect_object() è uguale a gtk_signal_connect() eccetto che -la funzione di callback usa solo un argomento, un puntatore ad un'oggetto GTK. -Così quando si usa questa funzione per connettere i segnali, la callback -dovrebbe essere della forma : - -<tscreen><verb> -void callback_func (GtkObject *object); -</verb></tscreen> -<p> -dove object è normalmente un widget. Generalmente, non si assegna -una callback per gtk_signal_connect_object. Queste sono invocate, usualmente, -per chiamare una funzione GTK che accetta un widget singolo o un oggetto come -argomento, come nel caso dell'esempio Hello World. - -Lo scopo di avere due funzioni per connettere i segnali è semplicemente -quello di permettere alla funzione di callback di avere un numero di argomenti -diverso. Molte funzioni della libreria GTK accettano solo un singolo puntatore -ad un widget GTK come argomento, così per queste si può usare la -funzione gtk_signal_connect_object(), mentre per le vostre funzioni potreste -aver bisogno di passare dati supplementari alle funzioni di ritorno. - -<sect1>Attraverso Hello World passo per passo -<p> -Ora che conosciamo la teoria che vi è dietro, iniziamo ad essere più -chiari camminando attraverso il programma di Hello World. -<p> -Questa è la funzione di callback che sarà invocata quando il bottone -viene cliccato. -Noi, in questo esempio, ignoriamo sia il widget che i dati passati, ma non è -difficile farci invece qualcosa. Il prossimo esempio userà l'argomento passato -per dire quale bottone è stato premuto. - -<tscreen><verb> -void hello (GtkWidget *widget, gpointer data) -{ - g_print ("Hello World\n"); -} -</verb></tscreen> - -<p> -Questa callback è un po' speciale. L'evento ``delete'' avviene quanto -il Window Manager manda questo evento all'applicazione. Qui abbiamo una scelta -da fare: cosa fare di questo evento. Possiamo ignorarlo, creare qualche tipo di -risposta, o semplicemente terminare l'applicazione. - -Il valore che si restituisce in questa callback fa sì che la GTK sappia -cosa fare. Restituire TRUE significa che non vogliamo che il segnale ``destroy'' -sia emesso, quindi far sì che la nostra applicazione proceda normalmente. -Ritornare FALSE vuole dire far emettere il segnale ``destroy'' il quale -chiamerà la nostra funzione di callback che gestisce il segnale ``destroy''. - -<tscreen><verb> -gint delete_event(GtkWidget *widget, gpointer data) -{ - g_print ("delete event occured\n"); - - return (TRUE); -} -</verb></tscreen> -<p> -Questa è un'altra funzione di callback la quale fa uscire dal programma -chiamando gtk_main_quit(). Questa funzione dice a GTK che deve uscire da gtk_main -quando gli viene restituito il controllo. - -<tscreen><verb> -void destroy (GtkWidget *widget, gpointer data) -{ - gtk_main_quit (); -} -</verb></tscreen> -<p> -Ritengo che conosciate la funzione main()... si, come tutte le altre applicazioni -anche le applicazioni GTK hanno questa funzione. - -<tscreen><verb> -int main (int argc, char *argv[]) -{ -</verb></tscreen> -<p> -Questa parte dichiara un puntatore ad una struttura di tipo GtkWidget. Queste sono -usate più sotto per creare una finestra ed un bottone. - -<tscreen><verb> - GtkWidget *window; - GtkWidget *button; -</verb></tscreen> -<p> -Qui vi è ancora la nostra gtk_init. Come prima questa inizializza il toolkit -e analizza gli argomenti trovati nella linea di comando. Tutti gli argomenti -riconosciuti nella linea di comando sono rimossi dalla lista degli argomenti e -vengono così modificati argc e argv per far sì che sembri che questi -non siano mai esisiti e permettere alla vostra applicazione di analizzare gli -argomenti rimasti. - -<tscreen><verb> - gtk_init (&argc, &argv); -</verb></tscreen> -<p> -Crea una nuova finestra. Questo viene spiegato abbastanza approfonditamente -più avanti. Viene allocata la memoria per la struttura GtkWidget *window -così che si punti ad una struttura valida. In questo modo si predispone -la nuova finestra, ma non la si visualizza fino a sotto dove, quasi alla fine -del nostro programma, invochiamo gtk_widget_show(window). -<tscreen><verb> - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); -</verb></tscreen> -<p> -Questo è un esempio di come connettere un gestore dei segnali con un oggetto, -in questo caso la finestra. Qui viene catturato il segnale ``destroy''. Questo -viene emesso quando usiamo il Window Manager per uccidere la finestra (e noi -restituiamo TRUE dal gestore di ``delete_event'') o quando emettiamo la chiamata -gtk_widget_destroy() passando l'oggetto finestra come oggetto da distruggere. -Sistemando le cose così, trattiamo entrambi i casi con una singola -chiamata. Qui è giusto invocare la funzione destroy() definita sopra con -NULL come argomento, la quale termina l'applicazione GTK per noi. -Questo ci permetterà di utilizzare il Window Manager per uccidere il programma. -<p> -GTK_OBJECT e GTK_SIGNAL_FUNC sono macro che interpretano il casting e il controllo -di tipo per noi, così da rendere piu' leggibile il codice. - -<tscreen><verb> - gtk_signal_connect (GTK_OBJECT (window), "destroy", - GTK_SIGNAL_FUNC (destroy), NULL); -</verb></tscreen> -<p> -La prossima funzione è usata per settare un attributo di un oggetto -contenitore. Questo sistema la finestra così da avere un'area vuota -all'interno della finestrra larga 10 pixel dove non potrà andare nessun -widget. Ci sono altre funzioni simili che vedremo nella -sezione <ref id="sec_setting_widget_attributes" name="Settare gli attributi del Widget."> -<p> -E ancora, GTK_CONTAINER è una macro per interpretare il casting di tipo. - -<tscreen><verb> - gtk_container_border_width (GTK_CONTAINER (window), 10); -</verb></tscreen> -<p> -Questa chiamata crea un nuovo bottone. Alloca spazio in memoria per un nuovo -GtkWidget, inizializzandolo e facendo sì che il puntatore a bottone punti -ad esso. -Quando sarà visualizzato, avrà etichetta ``Hello World''. - -<tscreen><verb> - button = gtk_button_new_with_label ("Hello World"); -</verb></tscreen> -<p> -Qui prendiamo il bottone e gli facciamo fare qualcosa di utile. -Gli colleghiamo un gestore di segnale in modo che quando emetterà il -segnale ``clicked'', verrà invocata la nostra funzione hello(). Il -dato passato alla funzione è ignorato, cosicché alla funzione -di callback hello() passiamo semplicemente NULL. Evidentemente il segnale -``clicked'' viene emesso quando premiamo il bottone con il mouse. - -<tscreen><verb> - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (hello), NULL); -</verb></tscreen> -<p> -Usiamo questo bottone anche per uscire dal programma. Questo illustrerà -come il segnale ``destroy'' può arrivare sia dal Window Manager che dal -nostro programma. Quando il bottone viene cliccato come descritto sopra, -chiamerà la funzione di callback hello() e poi quest'ultima nell'ordine -in cui sono definite. Si possono cioé avere tante funzioni di callback -quante sono necessarie, e saranno eseguite nell'ordine in cui sono connesse. -Visto che la funzione gtk_widget_destroy() accetta come argomento solo un GtkWidget *widget, usiamo la funzione -gtk_signal_connect_object() al posto della normale gtk_signal_connect(). - -<tscreen><verb> - gtk_signal_connect_object (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (gtk_widget_destroy), - GTK_OBJECT (window)); -</verb></tscreen> -<p> -Questa é una chiamata di ``impacchettamento'' che sarà spiegata -più avanti. Ma è molto facile da capire. Semplicemente dice alla -libreria GTK che il bottone è da mettere nella finestra dove sarà -visualizzato. - -<tscreen><verb> - gtk_container_add (GTK_CONTAINER (window), button); -</verb></tscreen> -<p> -A questo punto abbiamo predisposto tutto quello che ci eravamo prefissati. -Con tutti i gestori di segnale a posto e il bottone messo nella finestra in cui -dovrebbe essere, possiamo dire a GTK di mostrare gli oggetti sullo schermo. -L'oggetto finestra viene mostrato per ultimo così che la finestra -completa di tutti i suoi oggetti verrà mostrata tutta in una volta, -invece di vedere prima la finestra spoglia e poi la comparsa del bottone -all'interno di essa. Per quanto, con questi semplici esempi, questo l'avrete -già notato. -<tscreen><verb> - gtk_widget_show (button); - - gtk_widget_show (window); -</verb></tscreen> -<p> -E naturalmente chiamiamo gtk_main(), la quale aspetta l'arrivo degli eventi -dal server X e chiama l'oggetto interessato per fargli emettere il segnale -corrispondente. -<tscreen><verb> - gtk_main (); -</verb></tscreen> -E il return finale. Il controllo ritorna qui dopo che viene invocata gtk_quit(). - -<tscreen><verb> - return 0; -</verb></tscreen> -<p> -Ora, quando premiamo il bottone del mouse su un bottone GTK, questo oggetto -emette il segnale ``clicked''. Per poter utilizzare queste informazioni, il -nostro programma predispone un gestore di segnale per catturare quel segnale, -il quale avvia la funzione da noi scelta. Nel nostro esempio, quando il -bottone creato viene cliccato, la funzione hello() viene invocata con argomento -NULL, dopoodiché viene invocato il successivo gestore di questo segnale. -Questo chiama la funziona gtk_widget_destroy(), passandole l'oggetto-finestra -(window) come argomento, che distruggerà la finestra. Questo fa sì -che la finestra emetta il segnale ``destroy'' che viene catturato e che fa -invocare la funzione di ritorno destroy(), che semplicemente esce dal programma GTK. -<p> -Un'altro modo in cui possono andare le cose è l'uso del window manager per -uccidere la finestra. Questo causera' l'emissione del segnale ``delete_event'' che -automaticamente chiamerà il gestore del segnale ``delete_event''. Se qui noi -restituiamo il valore TRUE, la finestra non verrà toccata e tutto -procederà come se nulla fosse successo. Dare invece il valore FALSE -causerà l'emissione da parte di GTK del segnale ``destroy'' il quale, a sua -volta, invocherà la callback ``destroy'', uscendo dall'applicazione. -<p> -Nota che questi segnali non sono gli stessi del sistema Unix e che non sono -implementati usando quei segnali, anche se la terminologia è praticamente -identica. - -<!-- ***************************************************************** --> -<sect>Proseguiamo -<!-- ***************************************************************** --> -<p> - -<!-- ----------------------------------------------------------------- --> -<sect1>Tipi di Dato -<p> -Ci sono alcune cose che avrete probabilmente notato nei precedenti esempi che -hanno bisogno di una spiegazione. I gint, gchar ecc. che vedete sono tipi di dato -(typedef) riferiti rispettivamente a int e char. Questo viene fatto per rimediare -alle scomode dipendenze dalle dimensioni di semplici tipi di dato quando si fanno -dei calcoli. Un buon esempio è ``gint32'' il quale sarà un tipo di -dato riferito ad un intero a 32 bit per tutte le piattaforme, sia per gli x86 che -per gli per gli alpha a 64 bit. -I tipi di dato sono ben spiegati più avanti e molto intuitivi. Sono definiti -in glib/glib.h (il quale viene incluso da gtk.h). -<p> -Noterete anche la possibilità di utilizzare un GtkWidget quando la funzione -richiede un GtkObject. GTK è una libreria orienta agli oggetti ed un widget -è un oggetto. - -<!-- ----------------------------------------------------------------- --> -<sect1>Altri Dettagli sui Segnali -<p> -Diamo un'altra occhiata alla dichiarazione della funzione gtk_signal_connect. - -<tscreen><verb> -gint gtk_signal_connect (GtkObject *object, gchar *name, - GtkSignalFunc func, gpointer func_data); -</verb></tscreen> -Notate il valore di ritorno definito come gint? Questo è un identificatore -per la vostra funzione di callback. Come detto sopra, si possono avere più -funzioni di ritorno per ogni segnale e per ogni ogetto a seconda delle -necessità, ed ognuna sarà eseguita in sequenza, nell'ordine in cui -è stata collegata. - -Questo identificatore vi permette di rimuovere una funzione dalla lista delle -funzioni di ritorno tramite la seguente chiamata - -<tscreen><verb> -void gtk_signal_disconnect (GtkObject *object, - gint id); -</verb></tscreen> -Così, passando il widget da cui si vuole rimuovere il gestore di segnale e -l'identificativo restituito da una delle funzioni signal_connect, si può -rimuovere il gestore di segnale che si desidera dal widget. - -Un'altra funzione, usata per rimuovere tutti i segnali di un widget in una volta -sola è: - -<tscreen><verb> -gtk_signal_handlers_destroy (GtkObject *object); -</verb></tscreen> -<p> -Questa chiamata è abbastanza auto esplicativa. Semplicemente rimuove tutti -i segnali collegati al widget che si passa alla funzione come argomento. - -<!-- ----------------------------------------------------------------- --> -<sect1>Miglioriamo Hello World - -<p> -Diamo un'occhiata ad una versione migliorata di Hello World con altri esempi -sulle callback. Questo ci introdurrà anche al nostro prossimo argomento, -l'impacchettamento dei widget. - -<tscreen><verb> -/* helloworld2.c */ -#include <gtk/gtk.h> - -/* La nostra funzione di callback migliorata. I dati passati a questa - * vengono stampati su stdout. */ -void callback (GtkWidget *widget, gpointer data) -{ - g_print ("Hello again - %s was pressed\n", (char *) data); -} - -/* Un'altra callback */ -void delete_event (GtkWidget *widget, gpointer data) -{ - gtk_main_quit (); -} - -int main (int argc, char *argv[]) -{ - /* GtkWidget e' il tipo di dato per i widget */ - GtkWidget *window; - GtkWidget *button; - GtkWidget *box1; - - /* Questa funzione e' invocata in tutte le applicazioni GTK, gli - argomenti sono analizzati e restituiti all'applicazione. */ - gtk_init (&argc, &argv); - - /* Crea una nuova finestra */ - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - - /* Questa e' una nuova chiamata. Assegna "Hello Buttons" come titolo - della nostra finestra */ - gtk_window_set_title (GTK_WINDOW (window), "Hello Buttons!"); - - /* Qui settiamo il gestore per il segnale "delete_event" che - immediatamente esce dalla applicazione. - gtk_signal_connect (GTK_OBJECT (window), "delete_event", - GTK_SIGNAL_FUNC (delete_event), NULL); - - - /* predispone il bordo della finestra */ - gtk_container_border_width (GTK_CONTAINER (window), 10); - - /* creiamo una scatola dove mettere tutti i widget. Questa è descritta - dettagliatamente nella sezione "packing". La scatola non è realmente - visibile, è solamente usata per sistemare i widget. */ - box1 = gtk_hbox_new(FALSE, 0); - - /* Inseriamo la scatola nella finestra */ - gtk_container_add (GTK_CONTAINER (window), box1); - - /* Creiamo un nuovo bottone con etichetta "Button 1" */ - button = gtk_button_new_with_label ("Button 1"); - - /* Quando il bottone e' premuto, noi invocheremo la funzione di callback, - con un puntatore alla stringa "button 1" come proprio argomento) */ - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (callback), (gpointer) "button 1"); - - /* invece di aggiungerlo alla finestra, lo inseriamo nella scatola invisibile, - la quale e' stata inserita nella finstra. */ - gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0); - - /* Ricordati sempre questo passo. Dice a GTK che la preparazione di questo - bottone e' finita e che quindi puo' essere mostrato. */ - gtk_widget_show(button); - - /* Facciamo la stessa cosa per il secondo bottone. */ - button = gtk_button_new_with_label ("Button 2"); - - /* Chiamiamo la stessa funzione ma passandogli un argomento differente, - gli passiamo un puntatore alla stringa "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); - - /* L'ordine nel quale i bottoni sono visualizzati non e' realmente importante, - ma io ti raccomando di mostrare per ultima la finestra cosi' che tutto - sia visualizzato in una volta sola */ - gtk_widget_show(button); - - gtk_widget_show(box1); - - gtk_widget_show (window); - - /* e ora ci mettiamo in gtk_main e aspettiamo che il diverimento inizi. - gtk_main (); - - return 0; -} -</verb></tscreen> - -Compilate questo programma usando gli stessi argomenti di link del nostro primo -esempio. Noterete che questa volta non c'è un modo semplice per uscire -dal programma, si deve usare il nostro window manager o la linea di comando per -uccidere l'applicazione. -Un buon esercizio per il lettore è quello di inserire un tezo bottone -``quit'' che faccia uscire dal programma. Potete anche divertirvi con le opzioni -di gtk_box_pack_start() mentre leggete il prossimo capitolo. Provate a -ridimensionare la finestra ed a osservare cosa succede. - -Solo una piccola nota: c'è un'altra definizione di gtk_window_new() - -GTK_WINDOW_DIALOG. Questa interagisce con il window manager in un modo un po' -diverso, e dovrebbe essere usata per finestre temporanee. - -<!-- ***************************************************************** --> -<sect>Come ``Impacchettare'' i Widget -<!-- ***************************************************************** --> -<p> -Nel momento in cui si crea un'applicazione, normalmente si avrà la -necessità di mettere più di un unico bottone all'interno di -una finestra. Il nostro primo esempio ``Hello World'' usava un solo oggetto, -cosicché abbiamo potuto usare semplicemente una chiamata a -gtk_container_add per impacchettare il widget nella finestra. Quando invece -si vuole inserire più di un unico widget in una finestra, come si fa -a controllare dove vengono posizionati i propri oggetti? E' qui che entra in -gioco il meccanismo dell'``impacchettamento''. -<!-- ----------------------------------------------------------------- --> -<sect1>Teoria delle Scatole per Impacchettamento -<p> -La maggior parte dell'impacchettamento viene effettuata creando delle scatole -come nell'esempio più sopra. Le scatole sono dei contenitori invisibili -di widget che possiamo usare per imballarci i nostri oggetti e che esistono in -due varietà: in particolare si possono avere scatole orizzontali (hbox) -e verticali (vbox). -Quando si impacchentano degli oggetti in una scatola orizzontale, gli oggetti -vengono inseriti orizzontalmente da sinistra a destra oppure da destra a sinistra -a seconda della chiamata di funzione che si usa. In una scatola verticale, gli -oggetti vengono inseriti dall'alto in basso o viceversa. Si può usare -qualsiasi combinazione di scatole all'interno o a fianco di altre scatole, fino -ad ottenere l'effetto desiderato. -<p> -Per creare una nuova scatola orizzontale, si usa una chiamata a gtk_hbox_new(), -mentre per le scatole verticali si usa gtk_vbox_new(). Per inserire i widget -all'interno di questi contenitori si usano le funzioni gtk_box_pack_start() e -gtk_box_pack_end(). La funzione gtk_box_pack_start() comincerà dall'alto -verso il basso in una vbox e da sinistra a destra in una hbox. gtk_box_pack_end() -fa l'opposto, impacchettando dal basso verso l'alto in una vbox e da destra a -sinistra in una hbox. Queste funzioni ci permettono di giustificare a destra o -a sinistra i nostri widget, e possono essere mescolate in qualsiasi modo per -ottenere l'effetto desiderato. Useremo gtk_box_pack_start() nella maggior parte -dei nostri esempi. Un oggetto può essere costituito da un altro contenitore -o da un oggetto grafico. Infatti, molti oggetti grafici sono a loro volta dei -contenitori, compreso il bottone, anche se tipicamente all'interno del bottone -mettiamo solo una etichetta. -<p> - -Usando queste chiamate, GTK riesce a capire dove si vogliono piazzare i propri -widget, in modo di essere poi in grado di effettuare il ridimensionamento -automatico e altre cose interessanti. Esiste poi un insieme di opzioni che riguardano -il modo in cui i propri oggetti grafici dovrebbero essere impacchettati. Come -si può immaginare, questo metodo dà una buona flessibilità nella creazione e -nella disposizione dei propri widget. - -<!-- ----------------------------------------------------------------- --> -<sect1>Dettagli sulle Scatole -<p> -A causa di questa flessibilità, le scatole per impacchettamento del GTK -possono, di primo acchito, creare un po' di disorientamento. Sono infatti disponibili -molte opzioni, e non è immediato il modo in cui si combinano l'una con l'altra. -Alla fine però, si possono ottenere essenzialmente cinque diversi stili. - -<p> -<? <CENTER> > -<? -<IMG SRC="gtk_tut_packbox1.gif" VSPACE="15" HSPACE="10" WIDTH="528" HEIGHT="235" -ALT="Box Packing Example Image"> -> -<? </CENTER> > - -Ogni linea contiene una scatola orizzontale (hbox) con diversi bottoni. -La chiamata a gtk_box_pack è una scorciatoia per la chiamata di -impacchettamento di ognuno dei bottoni nella hbox. Ognuno dei bottoni viene -impacchettato nella hbox nello stesso modo (cioè, con gli stessi -argomenti per la funzione gtk_box_pack_start ()). -<p> -Questa è la dichiarazione della funzione gtk_box_pack_start. - -<tscreen><verb> -void gtk_box_pack_start (GtkBox *box, - GtkWidget *child, - gint expand, - gint fill, - gint padding); -</verb></tscreen> -Il primo argomento è la scatola nella quale si stanno inscatolando i -widget, il secondo è il widget stesso. Gli oggetti per ora saranno -bottoni, quindi quello che faremo sarà impacchettare bottoni in scatole. -<p> -L'argomento ``expand'' in gtk_box_pack_start() o gtk_box_pack_end() controlla -se gli oggetti devono essere sistemati nella scatola in modo da riempire tutto -lo spazio in diponibile presente nella scatola, in modo che la scatola si espanda -fino ad occupare tutta l'area assegnatale (valore TRUE). -La scatola può anche essere rimpiciolita in modo da contenere esattamente i -widget (valore FALSE). Assegnare a expand il valore FALSE permette di giustificare -a destra o sinistra i propri oggetti. In caso contrario, tutti gli ogetti si -espandono fino ad adattarsi alla scatola, e il medesimo effetto si può -ottenere usando solo una delle funzioni gtk_box_pack_start o pack_end. -<p> -L'argomento ``fill'' delle funzioni gtk_box_pack stabilisce se lo spazio disponibile -nella scatola deve essere allocato agli oggetti (TRUE) o se deve essere mantenuto -come riempimento attorno a questi oggetti (FALSE). Questo argomento ha effetto -solo se a expand è assegnato il valore TRUE. -<p> -Quando si crea una nuova scatola, la funzione ha questo aspetto: - -<tscreen><verb> -GtkWidget * gtk_hbox_new (gint homogeneous, - gint spacing); -</verb></tscreen> - -L'argomento homogeneous di gtk_hbox_new (la stesso per gtk_vbox_new) -determina se ogni oggetto nella scatola deve avere la stessa dimensione -(cioè la stessa ampiezza in una hbox o la stessa altezza in una vbox). -Se è settato, l'argomento expand delle routine gtk_box_pack è -sempre attivato. -<p> -Qual è la differenza fra la spaziatura (che è stabilita quando -la scatola viene creata) e il riempimento (che viene stabilito quando gli -elementi vengono impacchettati)? La spaziatura viene inserita fra gli oggetti, -mentre il riempimento viene aggiuno a ciascuno dei lati dell'oggetti. La seguente -figura dovrebbe chiarire meglio questo punto: - -<? <CENTER> > - <? -<IMG ALIGN="center" SRC="gtk_tut_packbox2.gif" WIDTH="509" HEIGHT="213" -VSPACE="15" HSPACE="10" ALT="Box Packing Example Image"> -> -<? </CENTER> > - - -Di seguito è riportato il codice usato per creare le immagini precedenti. -L'ho commentato in modo piuttosto pesante, in modo che non dovreste avere -problemi nel seguirlo. Compilatelo voi stessi e provate a giocarci un po'. - -<!-- ----------------------------------------------------------------- --> -<sect1>Programma Dimostrativo di Impacchettamento -<p> - -<tscreen><verb> -/* packbox.c */ -#include "gtk/gtk.h" - -void -delete_event (GtkWidget *widget, gpointer data) -{ - gtk_main_quit (); -} - -/* Costruisco una nuova hbox riempita con bottoni-etichette. Gli - * argomenti per le varabili che ci interessano sono passati - * in questa funzione. Non mostriamo la scatola, ma mostriamo - * tutto quello che c'e' dentro. */ -GtkWidget *make_box (gint homogeneous, gint spacing, - gint expand, gint fill, gint padding) -{ - GtkWidget *box; - GtkWidget *button; - char padstr[80]; - - /* costruisco una nuova hbox con i valori appropriati di - * homogeneous e spacing */ - box = gtk_hbox_new (homogeneous, spacing); - - /* costruisco una serie di bottoni con i valori appropriati */ - 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); - - /* costruisco un bottone con l'etichetta che dipende dal valore di - * 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); - - /* Questo e' la stessa cosa della creazione del bottone per "expand" - * piu' sopra, ma usa la forma breve. */ - 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; - - /* La nostra inizializzazione, non dimenticatela! :) */ - gtk_init (&argc, &argv); - - if (argc != 2) { - fprintf (stderr, "uso: packbox num, dove num è 1, 2, o 3.\n"); - /* questo fa solo un po' di pulizia in GTK, ed esce con un valore 1. */ - gtk_exit (1); - } - - which = atoi (argv[1]); - - /* Creiamo la nostra finestra */ - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - - /* Ci si dovrebbe sempre ricordare di connettere il segnale di destroy - * alla finestra principale. Cio' e' molto importante per avere un funzionamento - * corretto dal punto di vista intuitivo */ - gtk_signal_connect (GTK_OBJECT (window), "delete_event", - GTK_SIGNAL_FUNC (delete_event), NULL); - gtk_container_border_width (GTK_CONTAINER (window), 10); - - /* Creiamo una scatola verticale (vbox) in cui impacchettare quelle - * orizzontali. Questo ci permette di impilare le scatole orizzontali - * piene di bottoni una sull'altra in questa vbox. */ - - box1 = gtk_vbox_new (FALSE, 0); - - /* Decide quale esempio si deve mostrare. Corrispondono alle figure precedenti */ - switch (which) { - case 1: - /* creare una nuova etichetta. */ - label = gtk_label_new ("gtk_hbox_new (FALSE, 0);"); - - /* allineare l'etichetta al lato sinistro. Discuteremo questa e altre - * funzioni nella sezione dedicata agli attributi degli oggetti grafici. */ - gtk_misc_set_alignment (GTK_MISC (label), 0, 0); - - /* Impacchettare l'etichetta nella scatola verticale (vbox box1). - * Ricordare che gli oggetti che vengono aggiunti in una vbox vengono - * impacchettati uno sopra all'altro in ordine. */ - gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0); - - /* mostrare l'etichetta */ - gtk_widget_show (label); - - /* chiamare la nostra funzione make_box - homogeneous = FALSE, - * spacing = 0, expand = FALSE, fill = FALSE, padding = 0 */ - box2 = make_box (FALSE, 0, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0); - gtk_widget_show (box2); - - /* chiamare la nostra funzione make_box - homogeneous = FALSE, spacing = 0, - * expand = FALSE, fill = FALSE, padding = 0 */ - box2 = make_box (FALSE, 0, TRUE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0); - gtk_widget_show (box2); - - /* Gli argomenti sono: homogeneous, spacing, expand, fill, padding */ - box2 = make_box (FALSE, 0, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0); - gtk_widget_show (box2); - - /* Questo crea un separatore. Li conosceremo meglio in seguito, - * comunque sono piuttosto semplici. */ - separator = gtk_hseparator_new (); - - /* Impacchetta il separatore nella vbox. Ricordare che stiamo impacchettando - * ognuno di questi oggetti in una vbox, cosicché essi verranno - * impacchettati verticalmente. */ - gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5); - gtk_widget_show (separator); - - /* crea un'altra nuova etichetta e mostrala. */ - 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); - - /* Gli argomenti sono: 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); - - /* Gli argomenti sono: homogeneous, spacing, expand, fill, padding */ - box2 = make_box (TRUE, 0, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0); - gtk_widget_show (box2); - - /* ancora un nuovo separatore. */ - separator = gtk_hseparator_new (); - /* Gli ultimi 3 argumenti per gtk_box_pack_start sono: expand, fill, padding. */ - gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5); - gtk_widget_show (separator); - - break; - - case 2: - - /* creare una nuova etichetta, ricordare che box1 e' la vbox creata - * vicino all'inizio di main() */ - 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); - - /* Gli argomenti sono: homogeneous, spacing, expand, fill, padding */ - box2 = make_box (FALSE, 10, TRUE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0); - gtk_widget_show (box2); - - /* Gli argomenti sono: homogeneous, spacing, expand, fill, padding */ - 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 (); - /* Gli ultimi tre arcomenti di gtk_box_pack_start sono: expand, fill, padding. */ - 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); - - /* Gli argomenti sono: homogeneous, spacing, expand, fill, padding */ - box2 = make_box (FALSE, 0, TRUE, FALSE, 10); - gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0); - gtk_widget_show (box2); - - /* Gli argomenti sono: homogeneous, spacing, expand, fill, padding */ - 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 (); - /* Gli ultimi tre argomenti di gtk_box_pack_start sono: expand, fill, padding. */ - gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5); - gtk_widget_show (separator); - break; - - case 3: - - /* Questo dimostra la possibilita' di usare use gtk_box_pack_end() per - * giustificare gli oggetti a destra. Per prima cosa creiamo una - * nuova scatola come prima. */ - box2 = make_box (FALSE, 0, FALSE, FALSE, 0); - /* creiamo l'etichetta che sara' aggiunta alla fine. */ - label = gtk_label_new ("end"); - /* impacchettiamola usando gtk_box_pack_end(), cosa' che viene inserita - * sul lato destro della hbox creata nella chiamata a the make_box(). */ - gtk_box_pack_end (GTK_BOX (box2), label, FALSE, FALSE, 0); - /* mostriamo l'etichetta. */ - gtk_widget_show (label); - - /* impacchettiamo box2 in box1 (the vbox, ricordate? :) */ - gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0); - gtk_widget_show (box2); - - /* un separatore per il fondo */ - separator = gtk_hseparator_new (); - /* Questo assegna esplicitamente al separatore l'ampiezza di 400 pixel - * e l'altezza di 5 pixel. Cio' fa si' che la hbox che abbiamo creato sia - * anche essa larga 400 pixel, e che l'etichetta finale sia separata dalle - * altre etichette nella hbox. In caso contrario, tutti gli oggetti nella - * hbox sarebbero impacchettati il piu' vicino possibile. */ - gtk_widget_set_usize (separator, 400, 5); - /* impacchetta il separatore nella vbox (box1) creata vicino all'inizio - * di main() */ - gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5); - gtk_widget_show (separator); - } - - /* Creare un'altra nuova hbox.. ricordate che ne possiamo usare quante ne vogliamo! */ - quitbox = gtk_hbox_new (FALSE, 0); - - /* Il nostro bottone di uscita. */ - button = gtk_button_new_with_label ("Quit"); - - - /* Configuriamo il segnale per distruggere la finestra. Ricordate che - * ciò manderà alla finestra il segnale "destroy", che verrà catturato - * dal nostro gestore di segnali che abbiamo definito in precedenza. */ - gtk_signal_connect_object (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (gtk_main_quit), - GTK_OBJECT (window)); - /* impacchetta il bottone in quitbox. - * Gli ultimi tre argomenti di gtk_box_pack_start sono: expand, fill, padding. */ - gtk_box_pack_start (GTK_BOX (quitbox), button, TRUE, FALSE, 0); - /* impacchetta quitbox nella vbox (box1) */ - gtk_box_pack_start (GTK_BOX (box1), quitbox, FALSE, FALSE, 0); - - /* impacchetta la vbox (box1), che ora contiene tutti i nostri oggetti, - * nella finestra principale. */ - gtk_container_add (GTK_CONTAINER (window), box1); - - /* e mostra tutto quel che rimane */ - gtk_widget_show (button); - gtk_widget_show (quitbox); - - gtk_widget_show (box1); - /* Mostriamo la finestra alla fine in modo che tutto spunti fuori assieme. */ - gtk_widget_show (window); - - /* E, naturalmente, la nostra funzione main. */ - gtk_main (); - - /* Il controllo ritorna a questo punto quando viene chiamata gtk_main_quit(), - * ma non quando si usa gtk_exit. */ - - return 0; -} -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Impacchettamento con uso di Tabelle -<p> -Diamo ora un'occhiata ad un altro modo di impacchettare - le Tabelle. -In certe situazioni, possono risultare estremamente utili. - -Usando le tabelle, creiamo una griglia in cui possiamo piazzare gli oggetti. -Gli oggetti possono occupare tanti spazi quanti ne specifichiamo. - -Naturalmente, la prima cosa da vedere è la funzione gtk_table_new: - -<tscreen><verb> -GtkWidget* gtk_table_new (gint rows, - gint columns, - gint homogeneous); -</verb></tscreen> -<p> -Il primo argomento rappresenta il numero di righe da mettere nella tabella, -mentre il secondo è ovviamente il numero di colonne. - -L'argomento homogeneous ha a che fare con il modo in cui le caselle della tabella -sono dimensionate. Se homogeneous ha il valore TRUE, le caselle sono ridimensionate -fino alla dimensione del più grande oggetto contenuto nella tabelle. Se è FALSE, la -dimensione delle caselleè decisa dal più alto oggetto in una certa riga e dal più -largo oggetto in una stessa colonna. - -Le righe e le colonne sono disposte a partire da 0 fino a n, dove n è il numero -che era stato specificato nella chiamata a gtk_table_new. Così, se specificate -rows = 2 e columns = 2, lo schema avrà questo aspetto: - -<tscreen><verb> - 0 1 2 -0+----------+----------+ - | | | -1+----------+----------+ - | | | -2+----------+----------+ -</verb></tscreen> -<p> -Notate che il sistema di coordinate ha origine nel vertice in alto a sinistra. Per -mettere un oggetto in una tabella, usate la seguente funzione: - -<tscreen><verb> -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); -</verb></tscreen> -<p> -In cui il primo argomento (``table'') è la tabella che avete creato e il secondo -(``child'') è l'oggetto che volete piazzare nella tabella. - -Gli argomenti ``attach'' (right, left, top, bottom) specificano dove mettere l'oggetto -e quante caselle adoperare. Se volete mettere un bottone nella casella in basso a destra -nella nostra tabella 2x2, e volete che esso riempia SOLO quella casella, dovete porre -left_attach = 1, right_attach = 2, top_attach = 1, bottom_attach = 2. - -Se invece volete che un oggetto si prenda tutta la riga più in alto nella nostra tabella -2x2, dovreste usare left_attach = 0, right_attach =2, top_attach = 0, -bottom_attach = 1. - -Gli argomenti ``xoptions'' e ``yoptions'' sono usati per specificare le opzioni di impacchettamento; -di essi si può fare l'OR in modo di ottenere opzioni multiple. - -Le opzioni sono: -<itemize> -<item>GTK_FILL - Se la parte di tabella in cui si vuole inserire il widget è più -grande dell'oggetto, e se si specifica GTK_FILL, l'oggetto viene espanso fino ad -occupare tutto lo spazio disponibile. - -<item>GTK_SHRINK - Se si alloca all'oggetto nella tabella meno spazio del necessario -(di solito succede quando l'utente ridimensiona la finestra), allora normalmente -l'oggetto verrebbe spinto fuori dal fondo della finestra fino a sparire. -Se invece si specifica GTK_SHRINK is specified, gli oggetti si rimpiccioliscono -assieme alla tabella. - -<item>GTK_EXPAND - Questo fa sì che la tabella si espanda fino ad occupare tutto lo -spazio che rimane nella finestra. -</itemize> - -Il riempimento funziona come nelle scatole, con la creazione di un'area vuota -attorno all'oggetto la cui dimensione viene specificata in pixel. - -La funzione gtk_table_attach() ha UN MUCCHIO di opzioni. Quindi, ecco una scorciatoia: - -<tscreen><verb> -void gtk_table_attach_defaults (GtkTable *table, - GtkWidget *widget, - gint left_attach, - gint right_attach, - gint top_attach, - gint bottom_attach); -</verb></tscreen> - -Le xoptions e yoptions vengono posti per difetto a GTK_FILL | GTK_EXPAND, e sia xpadding -che ypadding vengono posti a 0. Il resto degli argomenti sono identici a quelli della funzione -precedente. - -Ci sono poi le funzioni gtk_table_set_row_spacing() and gtk_table_set_col_spacing(). -Queste mettono dello spazio fra le righe (o colonne)in corrispondenza di una specifica -riga (o colonna). - -<tscreen><verb> -void gtk_table_set_row_spacing (GtkTable *table, - gint row, - gint spacing); -</verb></tscreen> -e -<tscreen><verb> -void gtk_table_set_col_spacing (GtkTable *table, - gint column, - gint spacing); -</verb></tscreen> - -Notate che per le colonne lo spazio viene posto alla destra della colonna, mentre -per le righe lo spazio viene posto al di sotto della riga. - -Si può poi inserire una spaziatura identica fra tutte le righe e/o colonne usando: - -<tscreen><verb> -void gtk_table_set_row_spacings (GtkTable *table, - gint spacing); -</verb></tscreen> -<p> -e -<tscreen><verb> -void gtk_table_set_col_spacings (GtkTable *table, - gint spacing); -</verb></tscreen> -<p> -Notate che con queste chiamate, all'ultima riga e all'ultima colonna -non viene assegnata alcuna spaziatura. - -<!-- ----------------------------------------------------------------- --> -<sect1>Esempio di Impacchettamento con Tabelle - <p> -In questo esempio creiamo una finestra avente tre bottoni disposti -in una tabella 2x2. I primi due bottoni li mettiamo nella riga superiore. -Un terzo bottone, quit, lo mettiamo nella riga inferioe, in modo da -comprendere entrambe le colonne. Ciò significa che dovremmo -avere qualcosa di questo tipo: -<p> -<? <CENTER> > -<? -<IMG SRC="gtk_tut_table.gif" VSPACE="15" HSPACE="10" -ALT="Table Packing Example Image" WIDTH="180" HEIGHT="120"> -> -<? </CENTER> > - -Ecco il codice sorgente: - -<tscreen><verb> -/* table.c */ -#include <gtk/gtk.h> - -/* la nostra funzione di ritorno. - * i dati passati a questa funzione vengono stampati su stdout */ -void callback (GtkWidget *widget, gpointer data) -{ - g_print ("Hello again - %s was pressed\n", (char *) data); -} - -/* questa funzione fa uscire dal programma */ -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); - - /* creiamo una nova finestra */ - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - - /* predisponiamo il titolo per la finestra */ - gtk_window_set_title (GTK_WINDOW (window), "Table"); - - /* creiamo un gestore per delete_event che esca immediatamente - * da GTK. */ - gtk_signal_connect (GTK_OBJECT (window), "delete_event", - GTK_SIGNAL_FUNC (delete_event), NULL); - - /* regoliamo la larghezza del bordo della finestra. */ - gtk_container_border_width (GTK_CONTAINER (window), 20); - - /* creiamo una tabella 2x2 */ - table = gtk_table_new (2, 2, TRUE); - - /* mettiamo la tabella nella finesta principale */ - gtk_container_add (GTK_CONTAINER (window), table); - - /*creiamo il primo bottone */ - button = gtk_button_new_with_label ("button 1"); - /* quando viene premuto il bottone, chiamiamo la funzione di ritorno - * con un puntatore a "button 1"come argomento */ - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (callback), (gpointer) "button 1"); - - - /* inseriamo il bottone 1 nel quadrante in alto a sinistra della tabella */ - gtk_table_attach_defaults (GTK_TABLE(table), button, 0, 1, 0, 1); - - gtk_widget_show (button); - - /* creiamo il secondo bottone */ - - button = gtk_button_new_with_label ("button 2"); - - /* quando si preme il bottone, chiamamo la funzione di ritorno - * con un puntatore a "button 2"come argomento */ - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (callback), (gpointer) "button 2"); - /* inseriamo il secondo bottone nel quadrate in alto a destra della tbella */ - gtk_table_attach_defaults (GTK_TABLE(table), button, 1, 2, 0, 1); - - gtk_widget_show (button); - - /* creiamo il botone "Quit" */ - button = gtk_button_new_with_label ("Quit"); - - /* quando viene premuto questo bottone, chiamiamo la funzione "delete_event" - * e si esce dal programma */ - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (delete_event), NULL); - - /* inseriamo il pulsante quit nelle due casele in basso della tabella */ - 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; -} -</verb></tscreen> - -<!-- ***************************************************************** --> -<sect>Panoramica sui Widget -<!-- ***************************************************************** --> - -<p> -La procedura generale di creazione di un widget in GTK prevede i seguenti passi: -<enum> -<item> gtk_*_new - una delle varie funzioni che servono per greare un nuovo widget. -In questa sezione le vedremo tutte in dettaglio. - -<item> Connettere tutti i segnali che si vogliono usare alle funzione gestione appfropriate. - -<item> Assegnare gli attributi all'oggetto. - -<item> Impacchettare l'oggetto in un contenitore usando la chiamate appropriata, -per esempio gtk_container_add() o gtk_box_pack_start(). - -<item> Mostrare l'oggetto con gtk_widget_show(). -</enum> -<p> -gtk_widget_show() fa sì che GTK sappia che abbiamo terminato di assegnare gli -attributi dell'oggetto grafico, e che è pronto per essere visualizzato. -Si può anche usare la funzione gtk_widget_hide per farlo sparire di nuovo. -L'ordine in cui mostrate gli oggetti grafici non è importante, ma io suggerisco -di mostrare per ultima la finestra, in modo che questa spunti fuori già completa, -invece di vedere i singoli oggetti che arrivano sullo schermo a mano a mano che si -formano. I figli di un oggetto grafico (anche una finestra è un oggetto grafico) non -vengono infatti mostrati finché la finestra stessa non viene mostrata usando la -funzione gtk_widget_show(). - -<!-- ----------------------------------------------------------------- --> -<sect1> Casting -<p> -Noterete andando avanti che GTK usa un sistema di casting di tipo. Questa operazione -viene sempre effettuata usando delle macro che allo stesso tempo controllano la -possibilità di effettuare il cast sull'elemento dato e lo effettuano realmente. -Alcune macro che avrete modo di incontrare sono: - -<itemize> -<item> GTK_WIDGET(widget) -<item> GTK_OBJECT(object) -<item> GTK_SIGNAL_FUNC(function) -<item> GTK_CONTAINER(container) -<item> GTK_WINDOW(window) -<item> GTK_BOX(box) -</itemize> - -Tutte queste funzioni sono usate per fare il cast di argomenti di funzione. Le vedrete -negli esempi, e capirete se è il caso di usarle semplicemente guardando alle -dichiarazioni delle funzioni. - -Come potrete vedere più sotto nella gerarchia delle classi, tutti i GtkWidgets -sono derivati dalla classe base GtkObject. Ciò significa che potete usare un -widget in ogni posto in cui una funzione richiede un oggetto - semplicemente -usate la macro GTK_OBJECT(). - -Per esempio: - -<tscreen><verb> -gtk_signal_connect(GTK_OBJECT(button), "clicked", - GTK_SIGNAL_FUNC(callback_function), callback_data); -</verb></tscreen> - -Questo fa il cast del bottone in un oggetto e fornisce alla chiamata di ritorno -un cast al puntatore a funzione. - -Molti oggetti grafici sono anche contenitori. Se guardate alla gerarchia delle -classi più sotto, vedrete che molti oggetti grafici sono derivati dalla classe -GtkContainer. Ognuna di queste classi può essere usata, con la macro GTK_CONTAINER, -come argomento per funzioni che richiedono un contenitore. - -Sfortunatamente, in questo tutorial non si parlerà in modo estensivo di queste macro, -ma raccomando di dare un'occhiata ai file header di GTK. Può essere una cosa molto -educativa. Infatti, non è difficile imparare come funziona un oggetto solo guardando -le dichiarazioni delle funzioni. - -<!-- ----------------------------------------------------------------- --> -<sect1>Gerarchia degli Oggetti Grafici -<p> -Ecco, per vostro riferimento, la gerarchia delle classi usata per implementare gli -oggetti grafici. - - <tscreen><verb> - 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 - | +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 -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Oggetti senza Finestre -<p> -Gli oggetti seguenti non hanno una finestra associata. Se volete catturare -degli eventi, dovrete usare l'oggetto GtkEventBox. Vedete anche la sezione su -<ref id="sec_The_EventBox_Widget" name="Il Widget EventBox"> - -<tscreen><verb> -GtkAlignment -GtkArrow -GtkBin -GtkBox -GtkImage -GtkItem -GtkLabel -GtkPixmap -GtkScrolledWindow -GtkSeparator -GtkTable -GtkAspectFrame -GtkFrame -GtkVBox -GtkHBox -GtkVSeparator -GtkHSeparator -</verb></tscreen> -<p> -Proseguiremo la nostra esplorazione di GTK esaminando uno alla volta tutti -gli oggetti, creando qualche semplice funzione per mostrarli. Un'altra -buona sorgente è il programma testgtk.c che viene fornito con GTK. Potete -trovarlo in gtk/testgtk.c. - -<!-- ***************************************************************** --> -<sect>Il Widget Bottone (Button) -<!-- ***************************************************************** --> - -<!-- ----------------------------------------------------------------- --> -<sect1>Bottoni Normali -<p> -Ormai abbiamo visto tutto quello che c'è da vedere riguardo all'oggetto -``bottone''. E' piuttosto semplice, ma ci sono due modi per crare un bottone. -Potete usare gtk_button_new_with_label() per creare un bottone con una -etichetta, o usare gtk_button_new() per creare un bottone vuoto. In tal caso è poi -vostro compito impacchettare un'etichetta o una pixmap sul bottone creato. -Per fare ciò, create una nuova scatola, e poi impacchettateci i vostri -oggetti usando la solita gtk_box_pack_start, e infine usate la funzione -gtk_container_add per impacchettare la scatola nel bottone. -<p> -Ecco un esempio di utilizzo di gtk_button_new per creare un bottone con -un'immagine ed un'etichetta su di sè. Ho separato il codice usato per -creare la scatola in modo che lo possiate usare nei vostri programmi. - -<tscreen><verb> -/* buttons.c */ -#include <gtk/gtk.h> - - -/* crea una nuova hbox contenente un'immagine ed un'etichetta - * e ritorna la scatola creata. */ - -GtkWidget *xpm_label_box (GtkWidget *parent, gchar *xpm_filename, gchar *label_text) -{ - GtkWidget *box1; - GtkWidget *label; - GtkWidget *pixmapwid; - GdkPixmap *pixmap; - GdkBitmap *mask; - GtkStyle *style; - - /* creare una scatola per una xpm ed una etichetta */ - box1 = gtk_hbox_new (FALSE, 0); - gtk_container_border_width (GTK_CONTAINER (box1), 2); - - /* ottengo lo stile del bottone. Penso che sia per avere il colore - * dello sfondo. Se qualcuno sa il vero motivo, è pregato di dirmelo. */ - style = gtk_widget_get_style(parent); - - /* e ora via con le faccende dell'xpm stuff. Carichiamo l'xpm*/ - pixmap = gdk_pixmap_create_from_xpm (parent->window, &mask, - &style->bg[GTK_STATE_NORMAL], - xpm_filename); - pixmapwid = gtk_pixmap_new (pixmap, mask); - - /* creiamo l'etichetta per il bottone */ - label = gtk_label_new (label_text); - - /* impacchettiamo la pixmap e l'etichetta nella scatola */ - 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); -} - -/* la nostra solita funzione di callback */ -void callback (GtkWidget *widget, gpointer data) -{ - g_print ("Hello again - %s was pressed\n", (char *) data); -} - - -int main (int argc, char *argv[]) -{ - /* GtkWidget è il tipo per contenere gli oggetti */ - GtkWidget *window; - GtkWidget *button; - GtkWidget *box1; - - gtk_init (&argc, &argv); - - /* creiamo una nuova finestra */ - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - - gtk_window_set_title (GTK_WINDOW (window), "Pixmap'd Buttons!"); - - /* E' una buona idea fare questo per tutte le finestre. */ - gtk_signal_connect (GTK_OBJECT (window), "destroy", - GTK_SIGNAL_FUNC (gtk_exit), NULL); - - gtk_signal_connect (GTK_OBJECT (window), "delete_event", - GTK_SIGNAL_FUNC (gtk_exit), NULL); - - /* assegnamo lo spessore del bordo della finestra */ - gtk_container_border_width (GTK_CONTAINER (window), 10); - gtk_widget_realize(window); - - /* creiamo un nuovo bottone */ - button = gtk_button_new (); - - /* Ormai dovreste esservi abituati a vedere la maggior parte di - * queste funzioni */ - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (callback), (gpointer) "cool button"); - - /* questa chiama la nostra funzione di creazione di scatole */ - box1 = xpm_label_box(window, "info.xpm", "cool button"); - - /* impacchetta e mostra tutti i nostri oggetti */ - 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); - - /* mettiti in gtk_main e aspetta che cominci il divertimento! */ - gtk_main (); - - return 0; -} -</verb></tscreen> -La funzione xpm_label_box può essere usata per impacchettare delle xpm -e delle etichette su qualsiasi oggetto che può essere un contenitore. - -<!-- ----------------------------------------------------------------- --> -<sect1> Bottoni a Commutazione (Toggle Buttons) -<p> -I bottoni a commutazione sono molto simili ai bottoni normali, tranne che per il -fatto che essi si trovano sempre in uno di due stati, che si alternano ad ogni -click. Possono trovarsi nello stato ``premuto'', e quando li si ripreme, tornano -ad essere sollevati. Ri-clickandoli, torneranno giù. - -I bottoni a commutazione sono la base per i bottoni di controllo (check button) e -per i radio-bottoni, e quindi molte delle chiamate disponibili per i bottoni -a commutazione vengono ereditati dai radio-bottoni e dai bottoni di controllo. -Ma vedremo questi aspetti nel momento in cui li incontreremo. - -Creare un nuovo bottone a commutazione: - -<tscreen><verb> -GtkWidget* gtk_toggle_button_new (void); - -GtkWidget* gtk_toggle_button_new_with_label (gchar *label); -</verb></tscreen> -<p> -Come potete immaginare, queste funzioni lavorano in modo identico che per -i bottoni normali. La prima crea un bottone a commutazione vuoto e la seconda un -bottone con un'etichetta. -<p> -Per ottenere lo stato dei widget a commutazione, compresi i radio-bottoni e i -bottoni di controllo, si può usare una macro come mostrato nell'esempio -più sotto. In questo modo lo stato dell'oggetto commutabile viene valutato in -una funzione di ritorno. Il segnale emesso dai bottoni a commutazione -(toggle button, il radio button o il check button) che ci interessa è il segnale -``toggled''. Per controllare lo stato di questi bottoni, create un gestore di -segnali che catturi il ``toggled'', e usate la macro per determinare -il suo stato. La funzione di callback avrà un aspetto più o meno così: - -<tscreen><verb> -void toggle_button_callback (GtkWidget *widget, gpointer data) - { - if (GTK_TOGGLE_BUTTON (widget)->active) - { - /* Se il programma si è arrivato a questo punto, il bottone - * a commutazione è premuto */ - - } else { - - /* il bottone è sollevato */ - } - } - </verb></tscreen> - -<!-- - -COMMENTED! - -<tscreen><verb> -guint gtk_toggle_button_get_type (void); -</verb></tscreen> -<p> -No idea... they all have this, but I dunno what it is :) - - -<tscreen><verb> -void gtk_toggle_button_set_mode (GtkToggleButton *toggle_button, - gint draw_indicator); -</verb></tscreen> -<p> -No idea. ---> - -<tscreen><verb> -void gtk_toggle_button_set_state (GtkToggleButton *toggle_button, - gint state); -</verb></tscreen> -<p> -La chiamata qui sopra può essere usata per fare l'assegnazione dello stato -del bottone a commutazione e dei suoi figli, il radio-bottone e il bottone di -controllo. Passando come primo argomento a questa funzione il vostro bottone e -come secondo argomento il valore TRUE o FALSE, si può specificare se il -bottone deve essere sollevato (rilasciato) o abbassato (premuto). Il valore -di difetto è sollevato, cioè FALSE. - -Notate che quando usate la funzione gtk_toggle_button_set_state(), e lo -stato viene cambiato, si ha il risultato che il bottone emette il segnale -``clicked''. - -<tscreen><verb> -void gtk_toggle_button_toggled (GtkToggleButton *toggle_button); -</verb></tscreen> -<p> -Questa funzione semplicemente commuta il bottone, ed emette il segnale ``toggled''. - -<!-- ----------------------------------------------------------------- --> -<sect1> Bottoni di Controllo (Check Buttons) -<p> -I bottoni di controllo ereditano molte proprietà e funzioni dal bottone a commutazione, -ma hanno un aspetto un po' diverso. Invece di essere bottoni contenenti del testo, -si tratta di quadratini con del testo alla propria destra. Questi bottoni sono -spesso usati nelle applicazioni per commutare fra lo stato attivato e disattivato delle -opzioni. - -Le due funzioni di creazione sono analoghe a quelle del bottone normale.. - -<tscreen><verb> -GtkWidget* gtk_check_button_new (void); - -GtkWidget* gtk_check_button_new_with_label (gchar *label); -</verb></tscreen> - -La funzione new_with_label crea un bottone di controllo con una etichetta -a fianco di esso. - -Per controllare lo stato del check button si opera in modo identico al bottone -a commutazione. - -<!-- ----------------------------------------------------------------- --> -<sect1> Radio-Bottoni (Radio Buttons) -<p> -I radio-bottoni sono simili ai bottoni di controllo, tranne che per il -fatto che sono sempre raggruppati in modo che solo uno alla volta di essi -può essere selezionato (premuto). Tornano utili quando nella propria applicazione -si ha bisogno di selezionare una opzione da una breve lista. - -La creazione di un nuovo radio-bottone si fa con una di queste chiamate: - -<tscreen><verb> -GtkWidget* gtk_radio_button_new (GSList *group); - -GtkWidget* gtk_radio_button_new_with_label (GSList *group, - gchar *label); -</verb></tscreen> -<p> -Avrete notato l'argomento in più che c'è in queste chiamate. Queste hanno -infatti bisogno dela specificazione di un ``gruppo'' per svolgere il loro compito. -Per il primo bottone di un gruppo si deve passare come primo argomento il valore -NULL. Dopodiché potete creare un gruppo usando la funzione: - -<tscreen><verb> -GSList* gtk_radio_button_group (GtkRadioButton *radio_button); -</verb></tscreen> - -<p> -La cosa importante da ricordare è che gtk_radio_button_group va chiamata ogni volta che si aggiunge un nuovo bottone al gruppo, con il preceente bottone passato come argomento. Il risultato viene poi passato nella chiamata a gtk_radio_button_new o a gtk_radio_button_new_with_label. Ciò permette di creare una catena di bottoni. L'esempio più sotto dovrebbe chiarire questo punto. - -E' poi una buona idea stabiire quale dev'essere il bottone premuto per difetto, usando: - -<tscreen><verb> -void gtk_toggle_button_set_state (GtkToggleButton *toggle_button, - gint state); -</verb></tscreen> -<p> -Questa funzione è descritta nella sezione sui bottoni a commutazione, e funziona -nello stesso identico modo. - -<p> -Nel seguente esempio creiamo un gruppo di tre radio-bottoni. - -<tscreen><verb> -/* 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); -} -</verb></tscreen> - -La cosa può essere accorciata un po' usando la seguente sintassi, -che elimina la necessità di una variabile per contenere la lista di bottoni: - -<tscreen><verb> - button2 = gtk_radio_button_new_with_label( - gtk_radio_button_group (GTK_RADIO_BUTTON (button1)), - "button2"); -</verb></tscreen> - - -<!-- ***************************************************************** --> -<sect> Alcuni Widget -<!-- ***************************************************************** --> - -<!-- ----------------------------------------------------------------- --> -<sect1> L'Etichetta (Label) -<p> -Le etichette sono molto usate in GTK, e sono relativamente semplici. Le -etichette non emettono segnali, dal momento che non hanno una finestra -X a loro assegnata. Se avete la necessità di avere dei segnali o di fare -delle operazioni di clipping, potete usare il widget EventBox. - -Per creare una nuova etichetta, si usa: - -<tscreen><verb> -GtkWidget* gtk_label_new (char *str); -</verb></tscreen> - -In cui l'unico argomento è la stringa che si vuole sia mostrata. - -Per cambiare il testo dell'etichetta dopo che è stata creata, si usa -la funzione: - -<tscreen><verb> -void gtk_label_set (GtkLabel *label, - char *str); -</verb></tscreen> -<p> -in cui il primo argomento è l'etichetta creata in precedenza (di cui si -fa il cast usando la macro GTK_LABEL()), mentre il secondo è la nuova -stringa. - -Nel caso, lo spazio necessario per la nuova stringa verrà regolato automaticamente. - -Per ottenere la stringa corrente si usa: - -<tscreen><verb> -void gtk_label_get (GtkLabel *label, - char **str); -</verb></tscreen> - -in cui il primo argomento è l'etichetta che avete creato, e il secondo -è il valore di ritorno per la stringa. - -<!-- ----------------------------------------------------------------- --> -<sect1>Il Widget Suggerimenti (Tooltips) -<p> -I suggerimenti sono piccole stringhe di testo che spuntano quando lasciate il -puntatore su un bottone o un altro widget per qualche secondo. Sono piuttosto -semplici da usare, per cui ne darò la spiegazione senza corredarla di esempi. -Se volede vedere un po' di codice, date un'occhiata al programma testgtk.c -distribuito con GTK. -<p> -Con alcuni widget (per esempio con l'etichetta) i suggerimenti non funzionano. -<p> -La prima chiamata che si usa per creare un nuovo tooltip è la seguente. -In una data funzione, è necessario chiamarla una sola volta: il <tt/GtkTooltip/ -che viene restituito da questa funzione può essere usato per creare suggerimenti -multipli. - -<tscreen><verb> -GtkTooltips *gtk_tooltips_new (void); -</verb></tscreen> - -Una volta creato un nuovo suggerimento e il widget su cui lo volete usare, -basta usare la seguente chiamata per fare l'assegnazione: - -<tscreen><verb> -void gtk_tooltips_set_tip (GtkTooltips *tooltips, - GtkWidget *widget, - const gchar *tip_text, - const gchar *tip_private); -</verb></tscreen> - -Il primo argomento è il suggerimento che era già stato creato, che è seguito -dal widget da cui volete che spunti il suggerimento e dal testo che volete -venga mostrato. L'ultimo argomento può essere posto a NULL. -<p> -Ecco un piccolo esempio: - -<tscreen><verb> -GtkTooltips *tooltips; -GtkWidget *button; -... -tooltips = gtk_tooltips_new (); -button = gtk_button_new_with_label ("button 1"); -... -gtk_tooltips_set_tips (tooltips, button, "This is button 1", NULL); -</verb></tscreen> -Ci sono anche altre funzioni che si usano con i suggerimenti. Eccone una lista -con una breve descrizione di quello che fanno. - -<tscreen><verb> -void gtk_tooltips_destroy (GtkTooltips *tooltips); -</verb></tscreen> - -Distrugge un suggerimento esistente. - -<tscreen><verb> -void gtk_tooltips_enable (GtkTooltips *tooltips); -</verb></tscreen> - -Abilita un gruppo di suggerimenti disbilitato. - -<tscreen><verb> -void gtk_tooltips_disable (GtkTooltips *tooltips); -</verb></tscreen> - -Disabilita un gruppo di suggerimenti abilitato. - -<tscreen><verb> -void gtk_tooltips_set_delay (GtkTooltips *tooltips, - gint delay); - -</verb></tscreen> -Stabilisce quanti millisecondi si deve mantenere il puntatore sopra al -widget prima che venga mostrato il suggerimento. Il valore di difetto -è di 1000 millisecondi. - -<tscreen><verb> -void gtk_tooltips_set_tips (GtkTooltips *tooltips, - GtkWidget *widget, - gchar *tips_text); -</verb></tscreen> - -Cambia il testo di un suggerimento già esistente. - -<tscreen><verb> -void gtk_tooltips_set_colors (GtkTooltips *tooltips, - GdkColor *background, - GdkColor *foreground); -</verb></tscreen> - -Assegna i colori di primo piano e di sfondo dei suggerimenti. (Non ho idea -di come si specifichino i colori). -<p> -E questo è tutto riguardo alle funzioni relative ai suggerimenti. Più -di quanto avreste mai voluto sapere :) - - -<!-- ----------------------------------------------------------------- --> -<sect1> La Barra di Avanzamento (Progress Bar) -<p> -Le barre di avanzamento sono usate per mostrare lo stato di una operazione. Come potete -vedere nel frammento di codice qui sotto, sono piuttosto semplici da usare. -Ma prima vediamo come cominciare con la chiamata per creare una nuova progress -bar. - -<tscreen><verb> -GtkWidget *gtk_progress_bar_new (void); -</verb></tscreen> - -Ora che la barra di avanzamento è stata creata, possiamo usarla.. - -<tscreen><verb> -void gtk_progress_bar_update (GtkProgressBar *pbar, gfloat percentage); -</verb></tscreen> - -Il primo argomento è la barra di avanzamento su cui volete lavorare, e il secondo -è la quantità 'completato', cioè la quantità di riempimento della progress -bar fra 0 e 100% (un numero reale fra 0 e 1). - -Le barre di avanzamento sono usate di solito con funzioni di timeout o altre di -questo tipo (vedi alla sezione <ref id="sec_timeouts" name="Timeouts, -I/O and Idle Functions">) per dare l'illusione del multitasking. Tutte -usano la funzione gtk_progress_bar_update nello stesso modo. - -Ecco un esempio di barra di avanzamento, in cui l'aggiornamento avviene usando -dei timeout. Questo codice vi mostra anche come riinizializzare le -barre di avanzamento. - -<tscreen><verb> -/* progressbar.c */ - -#include <gtk/gtk.h> - -static int ptimer = 0; -int pstat = TRUE; - -/* Questa funzione incrementa e aggiorna la barra di avanzamento, e la rimette - a zero se pstat è FALSE */ -gint progress (gpointer data) -{ - gfloat pvalue; - - /* ottiene il valore corrente della status bar */ - 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; -} - -/* Questa funzione segnala la riinizializzazione della - barra di avanzamento */ -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); - /* Crea una nuova barra di avanzamento, impacchettala nella tabella - e mostrala */ - pbar = gtk_progress_bar_new (); - gtk_table_attach_defaults(GTK_TABLE(table), pbar, 0,2,1,2); - gtk_widget_show (pbar); - - /* Attiva un timeout che gestisca l'aggiornamento automatico della barra */ - ptimer = gtk_timeout_add (100, progress, pbar); - - /* Questo bottone segnala alla barra che deve essere resettata */ - 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; -} -</verb></tscreen> - -In questo programmino ci sono quattro aree che riguardano il modo di -uso generale delle Barre di Avanzamento; le vediamo ora nell'ordine. - -<tscreen><verb> -pbar = gtk_progress_bar_new (); -</verb></tscreen> - -Questo codice crea una nuova barra ciamata pbar. - -<tscreen><verb> -ptimer = gtk_timeout_add (100, progress, pbar); -</verb></tscreen> - -Questo codice usa dei timeout per abilitare degli intervalli di tempo uguali. -Per usare le barre di avanzamento non è però necessario servirsi di timeout. - -<tscreen><verb> -pvalue = GTK_PROGRESS_BAR (data)->percentage; -</verb></tscreen> - -Qui si assegna a pvalue il valore corrente della percentuale di avanzamento. - -<tscreen><verb> -gtk_progress_bar_update (GTK_PROGRESS_BAR (data), pvalue); -</verb></tscreen> - -Infine, questo codice aggiorna la barra di avanzamento con il valore di pvalue. - -Questo è tutto quanto c'è da sapere sulle barre di avanzamento, divertitevi. - -<!-- ----------------------------------------------------------------- --> -<sect1> Dialoghi -<p> - -Il widget ``Dialogo'' è molto semplice: si tratta in realtà di una finestra -con alcuni elementi pre-impacchettati. La struttura di un dialogo è la -seguente: - -<tscreen><verb> -struct GtkDialog -{ - GtkWindow window; - - GtkWidget *vbox; - GtkWidget *action_area; -}; -</verb></tscreen> - -Come potete vedere, crea semplicemente una finestra vi inserisce una vbox -in cima, poi un separatore e infine una hbox come ``area di azione''. - -Un Dialogo può essere utilizzato per messaggi per l'utente e -altri scopi simili. E' un widget molto essenziale, che ha una sola funzione, -e precisamente: - -<tscreen><verb> -GtkWidget* gtk_dialog_new (void); -</verb></tscreen> - -Per cui, per creare una nuova finestra di dialogo, uate: - -<tscreen><verb> -GtkWidget *window; -window = gtk_dialog_new (); -</verb></tscreen> - -Questa funzione crea una finestra di dialogo, dopodiché sta a voi -utilizzarla. Potete mettere un bottone nella action_area facendo -qualcosa del tipo: - -<tscreen><verb> -button = ... -gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button, - TRUE, TRUE, 0); -gtk_widget_show (button); -</verb></tscreen> - -Potreste anche aggiungere, ad esempio, un'etichetta all'area della vbox, -con qualcosa di questo genere: - -<tscreen><verb> -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); -</verb></tscreen> - -Per provare a usare una finestra di dialogo, potreste provare a mettere -due bottoni nella action_area, per esempio un bottone ``Cancella'' ed un -bottone ``OK'' e un'etichetta nella vbox che chieda qualcosa all'utente o -segnali un errore. Poi potreste collegare un diverso segnale a ciascun -bottone ed eseguire l'operazione che l'utente che viene scelta dall'utente. - -<!-- ----------------------------------------------------------------- --> -<sect1> Le Pixmap -<p> - -Le Pixmap sono strutture dati che contengono immagini. Queste immagini -possono poi essere utilizzate in varie occasioni, per esempio come -icone sul desktop X-Window o come cusori. Una bitmap è una pixmap a due -colori. - -Per usare una pixmap in GTK, dobbiamo in primo luogo creare una struttura -GdkPixmap utilizzando le routine disponibili nello strato GDK. Una Pixmap -può essere creata a partire da dati presenti in memoria o letti da un file. -Vedremo ora una ad una le chiamate utilizzate per creare una pixmap. - -<tscreen><verb> -GdkPixmap *gdk_bitmap_create_from_data( GdkWindow *window, - gchar *data, - gint width, - gint height ); -</verb></tscreen> -<p> -Si usa questa routine per creare una pixmap ad un solo piano (2 colori) da -dati disponibili in memoria. Ogni bit nei dati indica lo stato acceso o -spento di un pixel. L'altezza (height) e la larghezza (width) sono espresse - in pixel. GdkWindow è un puntatore alla finestra corrente, dal momento che -le risorse di una pixmap hanno significato solo nel contesto dello schermo -in cui deve essere mostrata. - -<tscreen><verb> -GdkPixmap* gdk_pixmap_create_from_data( GdkWindow *window, - gchar *data, - gint width, - gint height, - gint depth, - GdkColor *fg, - GdkColor *bg ); -</verb></tscreen> - -Questa è usata per creare una pixmap con la profondità data (depth, ossia -numero di colori) usando i dati specificati. fg e bg indicano i colori da -usare per il primo piano e per lo sfondo. - -<tscreen><verb> -GdkPixmap* gdk_pixmap_create_from_xpm( GdkWindow *window, - GdkBitmap **mask, - GdkColor *transparent_color, - const gchar *filename ); -</verb></tscreen> - -Il formato XPM è una rappresentazione di pixmap leggibile per X Window. E' una -rappresentazione molto diffusa, e sono disponibili parecchi programmi per creare -immagini in questo formato. Il file specificato da ``filename'' deve contenere -un'immagine in questo formato, che viene caricato nella struttura pixmap. -La maschera (mask) specifica quali pixel della pixmap devono essere opachi. -Tutti gli altri pixel sono colorati usando il colore specificato da -transparent_color. Più sotto mostreremo un esempio di uso di questa funzione. - -<tscreen><verb> -GdkPixmap* gdk_pixmap_create_from_xpm_d (GdkWindow *window, - GdkBitmap **mask, - GdkColor *transparent_color, - gchar **data); -</verb></tscreen> - -Si possono incorporare piccole immagini all'interno di un programma sotto -forma di dati in formato XPM. In questo modo, invece di leggerli da un file, -si possono usare questi dati per creare una pixmap. Un esempio di questo tipo -di dati è - -<tscreen><verb> -/* 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. ", -" ......... ", -" ", -" "}; -</verb></tscreen> - -<tscreen><verb> -void gdk_pixmap_destroy( GdkPixmap *pixmap ); -</verb></tscreen> -<p> -Quando abbiamo finito di usare una pixmap e pensiamo di non doverla riutilizzare -presto, è una buona idea liberare queste risorse usando la funzione -dk_pixmap_destroy. Le pixmap devono essere considerate una risorsa preziosa. - -Quando abbiamo creato una pixmap, possiamo mostrarla come un widget GTK. -E' necessario creare un widget pixmap che contenga una pixmap GDK. Questa -operazione viene compiuta usando - -<tscreen><verb> -GtkWidget* gtk_pixmap_new( GdkPixmap *pixmap, - GdkBitmap *mask ); -</verb></tscreen> -<p> -Le altre chiamate per i widget pixmap sono - -<tscreen><verb> -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); -</verb></tscreen> -<p> -La funzione gtk_pixmap_set viene usata per cambiare la pixmap che viene -gestita correntemente dal widget. -gtk_pixmap_set is used to change the pixmap that the widget is currently -managing. ``val'' è la pixmap che è stata creata usando il GDK. -Segue un esempio di uso di una pixmap in un bottone. - -<tscreen><verb> -/* pixmap.c */ -#include <gtk/gtk.h> - - -/* dat XPM dell'icona Apri File */ -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. ", -" ......... ", -" ", -" "}; - - -/* quando invocata (con il segnale delete_event), termina l'applicazione. */ -void close_application( GtkWidget *widget, gpointer data ) { - gtk_main_quit(); -} - -/* invocata se il bottone è clickato. Stampa semplicemente un messaggio */ -void button_clicked( GtkWidget *widget, gpointer data ) { - printf( "button clicked\n" ); -} - -int main( int argc, char *argv[] ) -{ - /* i widget sono memorizzati nel tipo GtkWidget */ - GtkWidget *window, *pixmapwid, *button; - GdkPixmap *pixmap; - GdkBitmap *mask; - GtkStyle *style; - - /* crea la finestra principale, e collega il segnale delete_event - alla terminazione dell'applicazione */ - 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 ); - - /* la pixmap proviene da 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 ); - - /* un widget pixmap per contenere la pixmap */ - pixmapwid = gtk_pixmap_new( pixmap, mask ); - gtk_widget_show( pixmapwid ); - - /* un bottone per contenere il widget pixmap */ - 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 ); - - /* mostra la finestra */ - gtk_main (); - - return 0; -} -</verb></tscreen> - - -Per caricare una pixmap da un file XPM chiamato icon0.xpm che si trova -nella direttorio corrente, avremmo creato la pixmap in questo modo: - -<tscreen><verb> - /* carica una pixmap da un file */ - 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 ); -</verb></tscreen> - - -Usare le Sagome -<p> -Uno degli svantaggi di usare le pixmap è costituito dal fatto che l'oggetto -mostrato è sempre rettangolare, a prescindere dall'immagine. Ci piacerebbe -invece poter crare dei desktop e delle immagini con forme più naturali. Per -esempio, per l'interfaccia di un gioco, potremmo volere avere dei pulsanti -circolari. Il modo per ottenere questo effetto è di usare delle finestre -sagomate. - -Una finestra sagomata è semplicemente una pixmap in cui i pixel dello -sfondo sono trasparenti. In questo modo, se l'immagine di sfondo è -multicolore, possiamo evitare di sovrascriverla con un bordo rettangolare -attorno all'icona. Il prossimo esempio mostra una carriola sul desktop. - -<tscreen><verb> -/* 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 ", -" ", -" "}; - - -/* quando invocata (con il segnale delete_event), termina l'applicazione. */ -void close_application( GtkWidget *widget, gpointer data ) { - gtk_main_quit(); -} - -int main (int argc, char *argv[]) -{ - /* il tipo di dato per i widget è GtkWidget */ - GtkWidget *window, *pixmap, *fixed; - GdkPixmap *gdk_pixmap; - GdkBitmap *mask; - GtkStyle *style; - GdkGC *gc; - - /* crea la finestra principale e collega il segnale delete_event per - terminare l'applicazione. Notare che non mettiamo un titolo - alla finestra. */ - 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); - - /* ora occupiamoci della pixmap e del widget pixmap */ - 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 ); - - /* Per mostrare la pixmap, usiamo un widget "fixed" in cui metterla */ - 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 ); - - /* Questa maschera tutto tranne l'immagine stessa */ - gtk_widget_shape_combine_mask( window, mask, 0, 0 ); - - /* mostra la finestra */ - gtk_widget_set_uposition( window, 20, 400 ); - gtk_widget_show( window ); - gtk_main (); - - return 0; -} -</verb></tscreen> -<p> -Per rendere sensibile l'immagine della carriola, potremmo collegare -il segnale di pressione del bottone in modo che venga compiuta una certa -azione. Le prossime linee renderebbero l'immagine sensibile alla pressione -di un bottone del mouse che fa sì che l'applicazione termini. - -<tscreen><verb> -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 ); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Righelli -<p> -I widget righello vengono usati per indicare la posizione del pontatore del -mouse in una certa finestra. Una finestra può cioé avere un -righello orizzontale che si estende per tutta la sua ampiezza e un righello verticale -che ne comprende l'altezza. Un piccolo triangolo sui rghelli indica la posizione -esatta del puntatore relativamente ai righelli. - -I righelli devono essere in primo luogo creati. I righlli orizzontali e verticali vengono -creati usando - -<tscreen><verb> -GtkWidget *gtk_hruler_new(void); /* horizontal ruler */ -GtkWidget *gtk_vruler_new(void); /* vertical ruler */ -</verb></tscreen> - -Una volta che che si è creato il righello, si può l'unità di -misura. Le unità di misura possono essere GTK_PIXELS, -GTK_INCHES oppure GTK_CENTIMETERS. Ciò viene stabilito usando - -<tscreen><verb> -void gtk_ruler_set_metric( GtkRuler *ruler, - GtkMetricType metric ); -</verb></tscreen> - -La misura predefinita è GTK_PIXELS. - -<tscreen><verb> -gtk_ruler_set_metric( GTK_RULER(ruler), GTK_PIXELS ); -</verb></tscreen> - -Altre caratteritiche importanti di un righello sono il modo in cui vengono segnate -le tacche delle unità di misura e dove viene posto inizialmente l'indicatore -di posizione. Questi vengono stabiliti usando - -<tscreen><verb> -void gtk_ruler_set_range (GtkRuler *ruler, - gfloat lower, - gfloat upper, - gfloat position, - gfloat max_size); -</verb></tscreen> - -Gli argomenti lower e upper definiscono l'estensione del righello, e -max_size rappresenta il numero massimo che verrà mostrato. -Position definisce l posizione iniziale dell'indicatore del puntatore -all'interno del righello. - -Quindi, un righello che può stare su una finestra di 800 pixel sarà: - -<tscreen><verb> -gtk_ruler_set_range( GTK_RULER(vruler), 0, 800, 0, 800); -</verb></tscreen> - -Sul righello saranno presenti dei segni da 0 a 800, con un numero ogni 100 pixel. -Se avessimo invece voluto che il righello fosse andato da 7 a 16, avremmo scritto: - -<tscreen><verb> -gtk_ruler_set_range( GTK_RULER(vruler), 7, 16, 0, 20); -</verb></tscreen> - -L'indicatore sul righello è un piccolo segno triangolare che indica -la posizione del puntatore rispetto al righello. Se il righello viene usato -per seguire il movimento del mouse, il segnale di motion_notify_event -dovrebbe venir connesso al metodo motion_notify_event del righello. -Per seguire tutti i movimenti del mouse all'interno dell'area di una finestra, -useremmo: - -<tscreen><verb> -#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) ); -</verb></tscreen> - -L'esempio seguente crea un'area di disegno con un reghello orizzontale nella -parte superiore e un righello verticale nella parte sinistra. Le dimensioni -di questa area di disegno sono di 600 e 400 pixel risettivamente per la larghezza -e per l'altezza. Il righello orizzontale va da 7 a 13 con una tacca ogni 100 pixel, -mentre quello verticale va da 0 a 400, ancora con una tacca ogni 100 pixel. -La sistemazione dell'area di disegno e dei righelli viene fatta usando una tabella. - -<tscreen><verb> -/* 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 - -/* il controllo raggiunge questa routine quando si preme il bottone close - */ -void close_application( GtkWidget *widget, gpointer data ) { - gtk_main_quit(); -} - -/* la routine principale - */ -int main( int argc, char *argv[] ) { - GtkWidget *window, *table, *area, *hrule, *vrule; - - /* inizializziamo gtk e creiamo la finestra principale */ - 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); - - /* creiamo una tabella in cui mettere righelli e area di disegno */ - 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 ); - - /* Il righello orizzontale va nella parte superiore. Quando il mouse si muove - * nell'area di disegno, si passa un motion_notify_event al gestore appropriato - * per il righello. */ - - 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 ); - - /* Il righello verticale va nella parte sinistra. Quando il mouse si muove - * nell'area di disegno, si passa un motion_notify_event al gestore appropriato - * per il righello. */ - - 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 ); - - /* ora mostriamo tutto quanto */ - gtk_widget_show( area ); - gtk_widget_show( hrule ); - gtk_widget_show( vrule ); - gtk_widget_show( table ); - gtk_widget_show( window ); - gtk_main(); - - return 0; -} -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Barre di Stato (Statusbar) -<p> -Le barre di stato sono dei semplici widget usati per mostrare messaggi di test. -Hanno la caratteristica di mantenere uno stack dei messggi che vi vengono -mostrati, cosiccheé rimuovendo il messaggio corrente fa sì che -torni ad essere mostrato il messaggio precedente.. - -Per permettere a parti diverse di una stessa applicazione di usare la stessa barra di -stato per mostrare messaggi, questo widget emette degli 'Identificatori di Contesto' -che vengono usati per identificare i diversi 'utenti'. Quello che viene mostrato - è sempre il messaggio che si trova in cima allo stack, a prescindere in -quale contesto si trovi. I messaggi vengono immagazzinati secondo l'ordine -LIFO, e non secondo l'ordine stabilito dal contesto. - -Una barra di stato viene creata con una chiamata a: -<tscreen><verb> -GtkWidget* gtk_statusbar_new (void); -</verb></tscreen> - -Per richiedere un nuovo identificatore di contesto, si usa una chiamata alla seguente -funzione con una breve descrizione testuale: -<tscreen><verb> -guint gtk_statusbar_get_context_id (GtkStatusbar *statusbar, - const gchar *context_description); -</verb></tscreen> - -Le seguenti sono tre funzioni che possono operare sulle barre di stato: -<tscreen><verb> -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); -</verb></tscreen> - -La prima, gtk_statusbar_push, viene usata per aggiungere un nuovo messaggio -alla barra di stato. Questa restituisce un identificatore di messaggio, che può -essere passato successivamente alla funzione gtk_statusbar_remove per rimuovere -dallo stack il messggio con identificatore di messaggio e di contesto dati. - -La funzione gtk_statusbar_pop rimuove il messaggio che si trova in cima allo stack -avente un dato identificatore di contesto. - -Nel seguente esempio si crea una barra di stato e due bottoni, uno per mettere -elementi sulla barra di stato e l'altro per riuovere l'ultimo elemento.. - -<tscreen><verb> -/* 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); - - /* creazione di una nuova finestra */ - 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); - - /* la finestra va sempre mostrata come ultimo passo, in modo che venga - * sullo schermo tutta in una volta. */ - gtk_widget_show(window); - - gtk_main (); - - return 0; -} -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Inserimento di testo -<p> -Questo widget permette diinserire e mostrare del testo in una casella contenente una -sola linea. Il testo può essere assegnato con chiamate di funzione che -permettono a nuovo testo di sostituire, seguire o precedere il contenuto corrente -del widget di inserimento testo. - -Per la creazione di un inserimento di testo, sono disponibili due funzioni: -<tscreen><verb> -GtkWidget* gtk_entry_new (void); - -GtkWidget* gtk_entry_new_with_max_length (guint16 max); -</verb></tscreen> - -La prima crea solamente un inserimento di testo, mentre la seconda lo crea -imponendo un limite alla lunghezza del testo inseribile.. - -Per cambiaere il testo che si trova correntemente nel widget, sono disponibili diverse -funzioni. -<tscreen><verb> -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); -</verb></tscreen> - -La funzione gtk_entry_set_text assegna il contenuto del widget di inserimento, -sostituendo il contenuto corrente. Le funzioni gtk_entry_append_text e gtk_entry_prepend_text -permettono di antemporre o posporre un testo al testo corrente.. - -La prossima funzione permette di stabilire il punto di inserimento. -<tscreen><verb> -void gtk_entry_set_position (GtkEntry *entry, - gint position); -</verb></tscreen> - -Usando la seguente funzione, è possibile estrarre il contenuto di un widget di inserimento. -Ciò può essere utile nelle funzioni di ritorno come descritto più sotto. -<tscreen><verb> -gchar* gtk_entry_get_text (GtkEntry *entry); -</verb></tscreen> - -Se non si vuole che qualcuno possa cambiare il contenuto di una entry sovrascrivendola, -ne possiamo cambiare lo stato di "editabilità".. -<tscreen><verb> -void gtk_entry_set_editable (GtkEntry *entry, - gboolean editable); -</verb></tscreen> - -Questa funzine ci permette di far passare un widget di inserimento dallo sato di editabile a -quello di non editabile passando con l'argomento editable i valori TRUE o FALSE. - -Se stiamo usando l'entry in un punto in cui non vogliamo che il testo sia visibile, per -esempio quando si digita una password, possiamo usare la seguente funzione, che -accetta un parametro booleano.. -<tscreen><verb> -void gtk_entry_set_visibility (GtkEntry *entry, - gboolean visible); -</verb></tscreen> - -Si può stabilire che una parte del testo risulti selezionata usado la seguente funzione. -Si userà di solito questa possibilità dopo aver inserito nel widget un -qualche valore predefinito, in modo che per l'utente sia semplice sostituirlo. - -<tscreen><verb> -void gtk_entry_select_region (GtkEntry *entry, - gint start, - gint end); -</verb></tscreen> - -Se vogliamo accorgerci del momento in cui l'utente ha inserito del testo, possiamo connettere -il segnale <tt/activate/ o <tt/changed/. <tt/activate/ viene reso attivo quando -l'utente preme il tasto Enter mentre si trova nel widget. <tt/changed/ viene invece emesso ogni volta che -il testo cambia, per esempio ogni volta che viene inserito o rimosso un carattere. - -Il seguente codice mostra un esempio di utilizzo del widget di inserimento. -. -<tscreen><verb> -/* 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); - - /* creiamo una nuova finestra */ - 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); -} -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1> Selettori di Colore -<P> -Il widget selettore di colore è chiaramente un widget che permtte di -scegliere interattivamente dei colori. Questo widget composto permette all'utente -di selezionare un colore agendo su terne RGB (Red, Green, Blue) e HSV -(Hue, Saturation, Value). Questo lo si può fare o agendo sui singoli valori -tramite degli slider o inserendoli da tastiera, oppure selezionando direttamente il -colore da un cerchio (valori H e S) e da una barra (valore V). -Opzionalmente, è possibile anche stabilire il grado di trasparenza del -colore. -Il widget di selezione di colore emette per ora un solo segnale, "color_changed", che -viene generato ogni volta che il colore corrente nel widget cambia, sia quando -è l'utente a cambiarlo, sia quando viene modificato esplicitamente tramite -una chiamata a gtk_color_selection_set_color(). - -Diamo ora un'occhiata a cosa ha da offrirci il widget di selezione di colore. -Il widget è disponibile in due versioni, gtk_color_selection e -gtk_color_selection_dialog: - -<tscreen><verb> -GtkWidget *gtk_color_selection_new(void); -</verb></tscreen> - -E' probabile che non userete questo costruttore direttamente. Infatti esso crea un -widget GtkColorSelection orfano a cui dovrete assegnare un genitore voi stessi. -Il widget GtkColorSelection eredita dal widget GtkVBox. - -<tscreen><verb> -GtkWidget *gtk_color_selection_dialog_new(const gchar *title); -</verb></tscreen> - -Questo è il più comune fra i costruttori di selettori di colore. Esso -crea un GtkColorSelectionDialog, che eredita da GtkDialog. Esso consiste di un -GtkFrame che contiene un widget GtkColorSelection, un GtkHSeparator e un -GtkHBox con tre bottoni, "Ok", "Cancel" e "Help". Si arriva a questi bottoni -accedendo ai widget "ok_button", "cancel_button" e "help_button" nella -struttura GtkColorSelectionDialog (cioè (GTK_COLOR_SELECTION_DIALOG(colorseldialog)->ok_button). - -<tscreen><verb> -void gtk_color_selection_set_update_policy(GtkColorSelection *colorsel, - GtkUpdateType policy); -</verb></tscreen> - -Questa funzione stabilisce la politica di aggiornamento. Quella predefinita è -GTK_UPDATE_CONTINOUS, che significa che il colore viene aggiornato -continuamente mano a mano che l'utente trascina gli slider o preme e trascina il -mouse nel cerchio della hue-saturation o nella relativa barra. Se si hanno problemi -di prestazioni, si può decidere di usare la politica -GTK_UPDATE_DISCONTINOUS -o GTK_UPDATE_DELAYED. - -<tscreen><verb> -void gtk_color_selection_set_opacity(GtkColorSelection *colorsel, - gint use_opacity); -</verb></tscreen> - -Il widget di selezione di colore permette anche di variare l'opacità di un -colore (conosciuta anche come canale alfa). Questa caratteristica è -normalmente disabilitata. Chiamare la precedente funzione, con use_opacity uguale -a TRUE abilita la manipolazione dell'opacità. Analogamente, mettendo -use_opacity uguale a FALSE la disabiliterà. - -<tscreen><verb> -void gtk_color_selection_set_color(GtkColorSelection *colorsel, - gdouble *color); -</verb></tscreen> - -Si può assegnare esplicitamente un colore chiamando questa funzione -con un puntatore ad un vettore di colori (gdouble). La lunghezza del vettore -dipende dall'attivazione o meno del controllo dell'opacità. La posizione 0 -contiene la componente rossa, la 1 ` il verde, la 2 il blu e la 3 contiene -l'opacità (se questa ` attivata, come si è detto per -gtk_color_selection_set_opacity()). Tutti i valori sono compresi fra 0.0 e 1.0. - -<tscreen><verb> -void gtk_color_selection_get_color(GtkColorSelection *colorsel, - gdouble *color); -</verb></tscreen> - -Questa funzione viene usata per ottenere il colore corrente, tipicamente quando -si è ricevuto il segnale "color_changed". Color è un puntatore al -vettore di colori da riempire. Vedi la descrizione di questo vettore nella funzione -gtk_color_selection_set_color(). - -<!-- C'e' bisogno di una sezione sul DnD - TRG - -Il Drag and Drop ----------------- - -Le aree con l'esempio del colore (sotto il cerchio H-S) supportano il drag and drop. -Il tipo del drag and drop è "application/x-color". I dati del messaggio sono -costituiti da un vettore di 4 valori gdouble (o 5 nel caso di attivazione -dell'opacità), in cui il valore alla posizione 0 ` può -essere 0.0 (opacità attivata) o 1.0 (disattivata) seguito dal rosso, -dal verde e dal blu alle posizioni 1,2 e 3. Nel caso di opacità attiva, -il suo valore è passato alla posizione 4. ---> - -Ecco un semplice esempio che mostra l'uso di GtkColorSelectionDialog. -Il programma mostra una finestra che contiene un'area di disegno. Cliccandoci -sopra, si apre un dialogo di selezione di colore, e se si modifica il colore -nella finestra di dialogo verrà cambiato anche il colore dello sfondo. - -<tscreen><verb> -#include <glib.h> -#include <gdk/gdk.h> -#include <gtk/gtk.h> - -GtkWidget *colorseldlg = NULL; -GtkWidget *drawingarea = NULL; - -/* gestore del cambiamento del colore */ - -void color_changed_cb (GtkWidget *widget, GtkColorSelection *colorsel) -{ - gdouble color[3]; - GdkColor gdk_color; - GdkColormap *colormap; - - /* recupera la colormap dell'area di disegno */ - - colormap = gdk_window_get_colormap (drawingarea->window); - - /* recupera il colore corrente */ - - gtk_color_selection_get_color (colorsel,color); - - /* adattamento ad un intero unsigned di 16 bit (0..65535) - * e inseriscili nella struttura 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); - - /* Alloca il colore */ - - gdk_color_alloc (colormap, &gdk_color); - - /* assegna il colore di sfondo della finestra */ - - gdk_window_set_background (drawingarea->window, &gdk_color); - - /* pulisce la finestra */ - - gdk_window_clear (drawingarea->window); -} - -/* gestore per l'area di disegno */ - -gint area_event (GtkWidget *widget, GdkEvent *event, gpointer client_data) -{ - gint handled = FALSE; - GtkWidget *colorsel; - - /* controlliamo se abbiamo ricevuto un evento di pressione di pulsante */ - - if (event->type == GDK_BUTTON_PRESS && colorseldlg == NULL) - { - /* Si , c'e' l'evento e ancora non c'e' alcun colorseldlg! */ - - handled = TRUE; - - /* Creiamo una finestra di dialogo per la selezione del colore */ - - colorseldlg = gtk_color_selection_dialog_new("Select background color"); - - /* Otteniamo il widget GtkColorSelection */ - - colorsel = GTK_COLOR_SELECTION_DIALOG(colorseldlg)->colorsel; - - /* Facciamo la connessione al segnale "color_changed", - * ed assegnamo i dati-utente al widget di selezione di colore */ - - gtk_signal_connect(GTK_OBJECT(colorsel), "color_changed", - (GtkSignalFunc)color_changed_cb, (gpointer)colorsel); - - /* Mostriamo il dialogo */ - - gtk_widget_show(colorseldlg); - } - - return handled; -} - -/* Chiusura ed uscita dal getore */ - -void destroy_window (GtkWidget *widget, gpointer client_data) -{ - gtk_main_quit (); -} - -/* Main */ - -gint main (gint argc, gchar *argv[]) -{ - GtkWidget *window; - - /* Inizialliziamo il toolkit, remuoviamo gli argomenti sulla linea di - * comando legati a gtk */ - - gtk_init (&argc,&argv); - - /* creiamo la finestra base, con titolo e politiche */ - - 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); - - /* colleghiamo gli eventi "delete" e "destroy" per poter uscire */ - - 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); - - /* crea un'area di disegna, stabilisce le dimensioni e raccogli - * gli eventi */ - - 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); - - /* aggiungi l'area di disegno alla finestra e mostrale entrambe */ - - gtk_container_add (GTK_CONTAINER(window), drawingarea); - - gtk_widget_show (drawingarea); - gtk_widget_show (window); - - /* entra nel ciclo principale di gtk (che non cede mai il controllo */ - - gtk_main (); - - /* soddisfa i compilatori brontoloni */ - - return 0; -} -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1> Selezione di File (File Selections) - -<p> -Il widget Selezione di File è un modo rapido e semplice per mostrare una -finestra di dialogo `File'. Questa si presenta completa di bottoni Ok, -Cancel e Help, un buon modo per tagliare i tempi di programmazione. - -Per creare una nuova finestra di selezione file usate: - -<tscreen><verb> -GtkWidget* gtk_file_selection_new (gchar *title); -</verb></tscreen> - -Per assegnare il nome del file, ad esempio per predisporre una certa -directory o per dare un certo nome di file per difetto, usate la seguente -funzione: - -<tscreen><verb> -void gtk_file_selection_set_filename (GtkFileSelection *filesel, gchar *filename); -</verb></tscreen> - -Per recuperare il testo che l'utente ha inserito o che ha selezionato con -il mouse, si usa la funzione: - -<tscreen><verb> -gchar* gtk_file_selection_get_filename (GtkFileSelection *filesel); -</verb></tscreen> - -Ci sono anche dei puntatori ai widget che sono contenuti all'interno -del widget di selezione file. Si tratta di: - -<itemize> -<item>dir_list -<item>file_list -<item>selection_entry -<item>selection_text -<item>main_vbox -<item>ok_button -<item>cancel_button -<item>help_button -</itemize> - -Molto probabilmente potreste voler usare i puntatori a ok_button, -cancel_button e help_button per segnalarne l'uso. - -Ecco un esempio rubato da testgtk.c, nodificato per essere eseguito da -solo. Come potrete vedere, non c'è molto più che la creazione di un -widget di selezione file. In questo esempio, il bottone Help non fa nulla -mentre è mostrato allo schermo, dal momento che non c'è alcun segnale -collegato con esso. - -<tscreen><verb> -/* filesel.c */ - -#include <gtk/gtk.h> - -/* Recupera il nome di file selezionato e stampalo a console */ -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); - - /* Crea un nuovo widget di selezione file */ - filew = gtk_file_selection_new ("File selection"); - - gtk_signal_connect (GTK_OBJECT (filew), "destroy", - (GtkSignalFunc) destroy, &filew); - /* Connette ok_button alla funzione file_ok_sel */ - gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (filew)->ok_button), - "clicked", (GtkSignalFunc) file_ok_sel, filew ); - - /* Connette cancel_button alla funzione di distruzione del widget */ - gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION (filew)->cancel_button), - "clicked", (GtkSignalFunc) gtk_widget_destroy, - GTK_OBJECT (filew)); - - /* Preassegnamo un nome di file, come se stessimo dando un valore per difetto in - dialogo di tipo `` salva con nome '' */ - gtk_file_selection_set_filename (GTK_FILE_SELECTION(filew), - "penguin.png"); - - gtk_widget_show(filew); - gtk_main (); - return 0; -} -</verb></tscreen> - -<!-- ***************************************************************** --> -<sect> Widget Contenitore -<!-- ***************************************************************** --> - -<!-- ----------------------------------------------------------------- --> -<sect1> Il widget Blocco Note (Notebook) -<p> -Il widget Blocco note è un insieme di pagine sovrapposte l'una con l'altra, -ognuna contente cose diverse. Questo widget è diventato molto comune nella -programmazione delle interfacce utente ed è un buon metodo per mostrare informazioni -tra loro correlate ma che debbano essere mostrate separatamente. - -<p> -La prima funzione da invocare che si deve conoscere, come si può intuire, è usata -per creare un nuovo Blocco Note. - -<tscreen><verb> -GtkWidget* gtk_notebook_new (void); -</verb></tscreen> - -Una volta che il notebook è sato creato, ci sono 12 funzioni che possono -operare sul widget notebook. Guardiamole individualmente. - -La prima che vediamo riguarda come posizionare l'indicatore di pagina. -Questi inidicatori di pagina o ``linguette'' (come possono anche essere chiamati) -possono essere posizionati in quattro posti: alto, basso, sinistra.destra. - -<tscreen><verb> -void gtk_notebook_set_tab_pos (GtkNotebook *notebook, GtkPositionType pos); -</verb></tscreen> - -GtkPositionType sarà uno dei seguenti valori (molto autoesplicativi) -<itemize> -<item> GTK_POS_LEFT -<item> GTK_POS_RIGHT -<item> GTK_POS_TOP -<item> GTK_POS_BOTTOM -</itemize> - -GTK_POS_TOP e' il valore predefinito. - -Ora vediamo come aggiugere le pagine al Blocco Note. Ci sono 3 modi per farlo. Diamo -un'occhiata ai primi due insieme, viste che sono molto simili. - -<tscreen><verb> -void gtk_notebook_append_page (GtkNotebook *notebook, GtkWidget *child, GtkWidget *tab_label); - -void gtk_notebook_prepend_page (GtkNotebook *notebook, GtkWidget *child, GtkWidget *tab_label); -</verb></tscreen> - -Queste funzioni aggiungono pagine al notebook inserendole rispettivamente alla fine -(append) o all'inizio (prepend). *child è il widget che è posto nella pagina del -notebook e *tab_label e la intestazione della pagina stessa. - -L'ultima funzione per aggiungere una pagina al notebook contiene tutte le proprietà -delle precedenti due, ma permette di specificare dove posizionare la pagina che -si vuole inserire. - -<tscreen><verb> -void gtk_notebook_insert_page (GtkNotebook *notebook, GtkWidget *child, GtkWidget *tab_label, gint position); -</verb></tscreen> - -I parametri sono gli stessi di _append_ e _prepend_ tranne che per il parametro in -più: ``position''. -Questo parametro viene usato per specificare in che posizione ineserire la pagina. - -Ora che conosciamo come aggiungere le pagine, vediamo come poter toglierne una. - -<tscreen><verb> -void gtk_notebook_remove_page (GtkNotebook *notebook, gint page_num); -</verb></tscreen> - -Questa funzione prende il numero della pagina specificata dal campo page_num e -rimuove la pagina corrispondente dal Blocco Note. - -Per trovare qual'è la pagina corrente nel notebook bisogna usare la funzione: - -<tscreen><verb> -gint gtk_notebook_current_page (GtkNotebook *notebook); -</verb></tscreen> - -Le prossime due funzioni sono semplicemente delle chiamate che muovono la pagina del -notebook avanti o indietro. Semplicemente forniscono le chiamate alle rispettive -funzioni del widget notebook su si può operare. NB: quando un notebook è -correntemente sull'ultima pagina e viene invocata la funzione gtk_notebook_next_page, -il notebook ritornerà automaticamente alla prima pagina. Logicamente succede anche -il contrario quando invochi gtk_notebook_prev_page e ti trovi sulla prima pagina. - -<tscreen><verb> -void gtk_notebook_next_page (GtkNoteBook *notebook); -void gtk_notebook_prev_page (GtkNoteBook *notebook); -</verb></tscreen> - -La prossima funzione stabilisce la pagina ``attiva''. Se si vuole che la pagina -principale del notebook sia per esempio la 5 (ad esempio) si può usare questa -funzione. -Se non si usa questa funzione la pagina principale sarà la 1. - -<tscreen><verb> -void gtk_notebook_set_page (GtkNotebook *notebook, gint page_num); -</verb></tscreen> - -Le prossime due funzioni aggiungono o rimuovono, rispettivamente, le intestazioni e -i bordi delle pagine. - -<tscreen><verb> -void gtk_notebook_set_show_tabs (GtkNotebook *notebook, gint show_tabs); -void gtk_notebook_set_show_border (GtkNotebook *notebook, gint show_border); -</verb></tscreen> - -show_tabs e show_border posso avere come valore TRUE o FALSE (0 or 1). - -Diamo ora una occhiata ad un esempio. Si tratta di una espansione del codice preso -dal file testgtk.c che è compreso in tutte le distribuzioni, e mostra -tutte le 13 funzioni. Questo piccolo programma crea una finestra con un notebook -e 6 bottoni. Il notebook contiene 11 pagine, aggiunte nei 3 modi differenti (alla -fine, all'inizio o in qualsiasi posizione). I bottoni permettono di girare le -intestazioni, aggiungere/rimuovere le intestazioni e i bordi, rimuovere una -pagina, cambiare la pagina avanti e indietro e uscire dal programma. - -<tscreen><verb> -/* notebook.c */ - -#include <gtk/gtk.h> - -/* Queta funzione ruota le posizione delle linguette delle pagine */ -void rotate_book (GtkButton *button, GtkNotebook *notebook) -{ - gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos +1) %4); -} - -/* Aggiunge e rimuove le linguette e i bordi */ -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); -} - -/* Rimuove una pagina */ -void remove_book (GtkButton *button, GtkNotebook *notebook) -{ - gint page; - - page = gtk_notebook_current_page(notebook); - gtk_notebook_remove_page (notebook, page); - /* E' necessario fare un refresh del widget -- - Questo forza il widget a ridisegnarsi. */ - gtk_widget_draw(GTK_WIDGET(notebook), NULL); -} - -void delete (GtkWidget *widget, 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), "destroy", - GTK_SIGNAL_FUNC (destroy), NULL); - - gtk_container_border_width (GTK_CONTAINER (window), 10); - - table = gtk_table_new(2,6,TRUE); - gtk_container_add (GTK_CONTAINER (window), table); - - /* Crea un nuovo notebook, e tabilisce la posizione delle linguette */ - 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); - - /* appende una parte delle pagine */ - 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); - } - - - /* Ora aggiungiamo una pagina in una certa posizione */ - 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); - - /* Ora finalmente aggiungiamo le pagine all'inizio */ - 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); - } - - /* Stabilisce quale sarà la prima pagina che sarà visualizzata. */ - gtk_notebook_set_page (GTK_NOTEBOOK(notebook), 3); - - - /* Crea un set di bottoni */ - button = gtk_button_new_with_label ("close"); - gtk_signal_connect_object (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (delete), 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; -} -</verb></tscreen> -<p> -E speriamo che questo vi aiuti a creare i Blocco Note per le vostre applicazioni GTK! - -<!-- ----------------------------------------------------------------- --> -<sect1> Finestre Scorribili (Scrolled Windows) -<p> -Le Finestre Scorribili sono usate per creare areee scorribili in una vera finestra. -Si può inserire qualsiasi tipo di widget in questo tipo di finestra, e possono poi -essere accessibili a prescindere dalle dimensioni usando le barre di scorrimento. - -La funzione seguente è usata per creare una nuova scrolled window. - -<tscreen><verb> -GtkWidget* gtk_scrolled_window_new (GtkAdjustment *hadjustment, - GtkAdjustment *vadjustment); -</verb></tscreen> -<p> -Il primo argomento è l'aggiustamento (di quanto scendere ogni -volta) orizzontale e il secondo è quello verticale. A questi si assegna -quasi sempre il valore NULL. - - -<tscreen><verb> -void gtk_scrolled_window_set_policy (GtkScrolledWindow *scrolled_window, - GtkPolicyType hscrollbar_policy, - GtkPolicyType vscrollbar_policy); -</verb></tscreen> - -Questa funzione stabilisce la politica da usare nella barra di scorrimento. Il primo -argomento è la finestra scorribile interessata. Il secondo stabilisce la politica -per la barra di scorrimento orizzontale e il terzo è quello per la politca verticale. - -La politica può essere GTK_POLICY AUTOMATIC o GTK_POLICY_ALWAYS. -GTK_POLICY_AUTOMATIC decide automaticamente se la barra di scorrimento deve essere -visualizzata, mentre con GTK_POLICY_ALWAYS la barra verrà sempre mostrata. - -<tscreen><verb> -/* 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); - - /* Crea una nuove finestra di dialogo in cui la scrolled window sarà - inserita. Una finestra di dialogo è semplicemente come una - finestra normale, ma ha anche un vbox e un separatore orizzontale - già inseriti per difetto. E'un modo semplice per - creare finestre di dialogo. */ - 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); - gtk_widget_set_usize(window, 300, 300); - - /* crea una nuova finestra scorribile. */ - scrolled_window = gtk_scrolled_window_new (NULL, NULL); - - gtk_container_border_width (GTK_CONTAINER (scrolled_window), 10); - - /* la politica è GTK_POLICY AUTOMATIC per lo scorrimento orizzontale e - GTK_POLICY_ALWAYS per quello verticale. */ - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), - GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); - - /* La finestra di dialogo è creata con un vbox già inserito.*/ - gtk_box_pack_start (GTK_BOX (GTK_DIALOG(window)->vbox), scrolled_window, - TRUE, TRUE, 0); - gtk_widget_show (scrolled_window); - - /* crea una tablella di10 x 10. */ - table = gtk_table_new (10, 10, FALSE); - - /* setta lo spazio tra ogni cella di 10 pixel sia verticale sia orizzontale*/ - gtk_table_set_row_spacings (GTK_TABLE (table), 10); - gtk_table_set_col_spacings (GTK_TABLE (table), 10); - - /* inserisce la tabella nella finestra scorribile*/ - gtk_container_add (GTK_CONTAINER (scrolled_window), table); - gtk_widget_show (table); - - /* questo semplicemente crea una griglia di bottoni nella tabelle per - dimostrare il comportamento della finestra scorribile */ - 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); - } - - /* Aggiunge un bottone "close" alla fine della finestra */ - button = gtk_button_new_with_label ("close"); - gtk_signal_connect_object (GTK_OBJECT (button), "clicked", - (GtkSignalFunc) gtk_widget_destroy, - GTK_OBJECT (window)); - - /* questo fa sì che questo bottone sia quello predefinito */ - - GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); - gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button, TRUE, TRUE, 0); - - /* Questo ottiene il bottone predefinito. Premendo semplicemente l'"enter" il - bottone si avvierà */ - gtk_widget_grab_default (button); - gtk_widget_show (button); - - gtk_widget_show (window); - - gtk_main(); - - return(0); -} -</verb></tscreen> -<p> -Prova a giocare con il ridemensionamento della finestra. Noterete la reazione della -barra di scorrimento. Potete anche usare la funzione gtk_widget_set_usize() per -assegnare la dimensione predefinita della finestra o di un widget. -<!-- (ndMichel: questa chiamata non funziona per i bottoni!) --> - -<!-- ----------------------------------------------------------------- --> -<sect1> Il widget "Finestra Frazionata" (Paned Window) -<p> -Le finestre frazionate tornano utili quando si vuole dividere un'area in due parti, - -le cui dimensioni relative siano sotto il controllo dell'utente. Fra le due zone - -viene disgnato un separatore dotato di una maniglia che l'utente può - -trascinare per cambiare la proporzione fra le aree. La divisione può - -essere sia di tipo orizzontale (HPaned) che verticale (VPaned). - - -Per creare una finestra frazionata, si chiama una delle seguenti: - -<tscreen><verb> -GtkWidget* gtk_hpaned_new (void) -GtkWidget* gtk_vpaned_new (void) -</verb></tscreen> - - -Dopo aver creato il widget della finestra frazionata, si devono aggiungere dei - -widget figli alle due parti. Per farlo, si usano le funzioni: - -<tscreen><verb> -void gtk_paned_add1 (GtkPaned *paned, GtkWidget *child) -void gtk_paned_add2 (GtkPaned *paned, GtkWidget *child) -</verb></tscreen> - -<tt/gtk_paned_add1()/ inserisce il widget figlo alla parte di sinistra o superiore - -della finestra. <tt/gtk_paned_add2()/ lo inserisce invece nella parte destra o - -inferore. - - -Per fare un esempio, creeremo una parte dell'interfaccia utente di un immaginario - -programma di email. Si divide una finestra in due verticalmente, <!-- sicuro ? --> - -con la parte superiore in cui si mette la lista dei messaggi, e quella inferiore con - -il testo. La maggior parte del programma è piuttosto banale. Un paio - -di punti da notare sono: Non si può scrivere su un widget di testo prima - -che esso venga "realizato". Questa operazione può essere fatta con una - -chiamata alla funzione <tt/gtk_widget_realize()/, ma per far vedere un metodo - -alternativo, connetteremo una funzione al segnale "realize" per aggiungere il testo. - -Inoltre, dobbiamo aggiungere l'opzione <tt/GTK_SHRINK/ ad alcuni degli - -elementi della tabella che contiene la finestra del testo e le barre di scorrimento, in - -modo che quando si riducono le dimensioni della parte inferiore, le parti coinvolte - -risultino proporzionalmente rimpicciolite invece di venir spinte fuori dal fondo - -della finestra. - - -<tscreen><verb> -/* paned.c */ - -#include <gtk/gtk.h> - -/*Creiamo la lista dei "messaggi" */ -GtkWidget * -create_list (void) -{ - - GtkWidget *scrolled_window; - GtkWidget *list; - GtkWidget *list_item; - - int i; - char buffer[16]; - - /* Creiamo una nuova finestra scorribile con barre di scorrimento solo - - * se necessarie */ - scrolled_window = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); - - /* Creiamo una nuova lista e la mettiamo nella finestra scorribile */ - list = gtk_list_new (); - gtk_container_add (GTK_CONTAINER(scrolled_window), list); - gtk_widget_show (list); - - /* Aggiungiamo un po' di messaggi alla fiestra */ - 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; -} - -/* Aggiungiamo un po' di testo al nostro widget di testo - questa e' una - -funzione di callback che viene invocata quando la finestra viene "realizzata". - -Potremmo anche forzare la finestra ad essere realizzata con la funzione - - gtk_widget_realize, ma dovrebbe prima essere parte di una certa cerarchia */ - - -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)); -} - -/* Creiamo un'area di testo scorribile che mostra un "messaggio" */ -GtkWidget * -create_text (void) -{ - GtkWidget *table; - GtkWidget *text; - GtkWidget *hscrollbar; - GtkWidget *vscrollbar; - - /*Creiamo una tabella in cui mettere il widget di testo e le barre di scorrimento */ - table = gtk_table_new (2, 2, FALSE); - - /* Mettiamo un widget di testo nella parte superiore destra. Notate l'uso di - * GTK_SHRINK nella direzione y */ - 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); - - /* Mettiamo una HScrollbar nella parte in basso a sinistra */ - 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); - - /* Aggiungiamo una VScrollbar in alto a sinistra */ - 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); - - /* Aggiungiamo un gestore per mettere un messaggio nel wiget di testo - - * viene reaizzato */ - 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); - - /* Creiamo un widget frazionato verticalmente e aggiungiamolo alla - - * finestra di piu' alto livello */ - - vpaned = gtk_vpaned_new (); - gtk_container_add (GTK_CONTAINER(window), vpaned); - gtk_widget_show (vpaned); - - /* Creiamo il contenuto delle de parti della finestra */ - - 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; -} - -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1> Cornici ad aspetto fisso (Aspect Frames) -<p> -Il widget aspect frame ` analogo al widget "cornice", tranne che per il - -fatto che è in grado di forzare le finestre figlie ad avere un certo aspetto, - -cioè un certo rapporto fra altezza e larghezza, aggiungendo se necessario - -dello spazio in più. Ciò può tornare utile se per esempio - -si vuole fare l'anteprima di un'immagine: le dimensioni dell'anteprima devono - -variare se l'utente ridimensiona la finestra, ma le proporzioni devono essere - -sempre quelle dell'immagine originale. - -Per creare una nuova cornice ad aspetto fisso, si usa: - -<tscreen><verb> -GtkWidget* gtk_aspect_frame_new (const gchar *label, - gfloat xalign, - gfloat yalign, - gfloat ratio, - gint obey_child) -</verb></tscreen> - -<tt/xalign/ e <tt/yalign/ specificano l'allineamento come si fa con il widget di - -allineamento. Se <tt/obey_child/ è TRUE, le proporzioni di una finestra - -figlia saranno le stesse delle misure ideali richieste. In caso contrario, vengono - -stabilite da <tt/ratio/. - - -Per cambiare le opzioni di una finestra esistente, si può usare: -To change the options of an existing aspect frame, you can use: - -<tscreen><verb> -void gtk_aspect_frame_set (GtkAspectFrame *aspect_frame, - gfloat xalign, - gfloat yalign, - gfloat ratio, - gint obey_child) -</verb></tscreen> - -<p> -Per fare un esempio, il seguente programma usa un Aspect Frame per rendere - -disponibile un'area disegnabile che sia sempre di proporzioni 2:1, in quasiasi - -modo l'utente ridimensioni la finestra di base. - - -<tscreen><verb> -/* 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); - - /* Creiamo aspect_frame e lo mettiamo nella finestra di base */ - - aspect_frame = gtk_aspect_frame_new ("2x1", /* etichetta */ - 0.5, /* x del centro */ - 0.5, /* y del centro */ - 2, /* xsize/ysize = 2 */ - FALSE /* ignora le proporzioni del figlio */); - - gtk_container_add (GTK_CONTAINER(window), aspect_frame); - gtk_widget_show (aspect_frame); - - /* Aggiungamo un widget figlio alla nostra cornice */ - - drawing_area = gtk_drawing_area_new (); - - /* Chiediamo una finestra 200x200, anche se l'AspectFrame ce ne dara' una - * di 200x100 perche' forziamo l'aspetto 2:1 */ - 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; -} -</verb></tscreen> - -<!-- fin qui --> - - -<!-- ***************************************************************** --> -<sect> Il Widgets Lista -<!-- ***************************************************************** --> -<p> -Il widget GtkList serve come contenitore verticale per altri widget che -devono essere di tipo GtkListItem. - -Un widget GtkList possiede una sua propria finestra per ricevere eventi -e un suo proprio colore di sfondo che di solito è bianco. Dal momento -che è direttamente derivato dal widget GtkContainer, può essere trattato -come tale usando la macro GTK_CONTAINER(List); si veda il widget GtkContainer -per ulteriori dettagli. -Per usare il widget GtkList in tutte le sue potenzialità, si dovrebbe essere -già familiari con l'uso della GList e delle relative funzioni g_list_*(). - -All'interno della definizione della struttura del widget GtkList c'è un -campo che sarà per noi di grande interesse, cioè: - -<tscreen><verb> -struct _GtkList -{ - ... - GList *selection; - guint selection_mode; - ... -}; -</verb></tscreen> - -Il campo ``selection'' in un GtkList punta a una lista collegata di tutti -gli elementi che sono selezionati correntemente, oppure a NULL se la -selezione è vuota. Quindi, per avere informazioni sulla selezione corrente, -leggiamo il campo GTK_LIST()->selection, senza però modificarlo dal momento -che i campi interni debbono essere gestiti dalle funzioni gtk_list_*(). - -Le modalità di selezione in una GtkList, e quindi il contenuto di -GTK_LIST()->selection, sono determinate dal campo selection_mode: - -selection_mode può assumere uno dei seguenti valori: -<itemize> -<item> GTK_SELECTION_SINGLE - La selezione può essere o NULL oppure - un puntatore GList* per un singolo elemento - selezionato. - -<item> GTK_SELECTION_BROWSE - La selezione è null se la lista non contiene - alcun widget o se ha solo widget non sensibili, - oppure può contenere un puntatore a una struttura - GList, e quindi esattamente un elemento di lista. - -<item> GTK_SELECTION_MULTIPLE - La selezione è ``NULL'' se non è selezionato - alcun elemento di lista, oppure un puntatore GList al - primo elemento selezionato. Quello, a sua volta, punta - a una struttura GList per il secondo elemento selezionato - e così via. - -<item> GTK_SELECTION_EXTENDED - La selezione è sempre NULL. -</itemize> -<p> -Il valore per difetto è GTK_SELECTION_MULTIPLE. - -<!-- ----------------------------------------------------------------- --> -<sect1> Segnali -<p> -<tscreen><verb> -void selection_changed (GtkList *LIST) -</verb></tscreen> - -Questo segnale verrà invocato ogni volta che il campo di -selezione di una GtkList è cambiato. Questo accade quando -un figlio della GtkList viene selezionato o deselezionato. - -<tscreen><verb> -void select_child (GtkList *LIST, GtkWidget *CHILD) -</verb></tscreen> - -Questo segnale viene invocato quando un fuglio di una GtkList -sta per essere selezionato. Questo accade principalmente in -occasione di chiamate a gtk_list_select_item() e gtk_list_select_child(), -di pressioni di bottoni e a volte può venir fatto scattare indirettamente -in altre occasioni, in cui vengono aggiunti o rimossi dei figli -dalla GtkList. - -<tscreen><verb> -void unselect_child (GtkList *LIST, GtkWidget *CHILD) -</verb></tscreen> - -Questo segnale viene invocato quando un figlio della GtkList sta -per essere deselezionato. Ciò accade principalmente in occasione -di chiamate a gtk_list_unselect_item() e gtk_list_unselect_child(), -di pressioni di bottoni, e a volte può venir fatto scattare indirettamente -in altre occasioni, in cui vengono aggiunti o rimossi dei figli -dalla GtkList. - -<!-- ----------------------------------------------------------------- --> -<sect1> Funzioni -<p> -<tscreen><verb> -guint gtk_list_get_type (void) -</verb></tscreen> - -Restituisce l'identificatore di tipo `GtkList'. - -<tscreen><verb> -GtkWidget* gtk_list_new (void) -</verb></tscreen> - -Crea un nuovo oggetto `GtkList'. Il nuovo widget viene -restituito sotto forma di un puntoatore ad un oggetto -`GtkWidgetì'. In caso di fallimento, viene ritornato NULL. - -<tscreen><verb> -void gtk_list_insert_items (GtkList *LIST, GList *ITEMS, gint POSITION) -</verb></tscreen> - -Inserisce degli elementi di lista nella LIST, a partire da -POSITION. ITEMS ITEMS è una lista doppiamente collegata, in -cui ci si aspetta che i puntatori di ogni nodo puntino a -un GtkListItem appena creato. I nodi GList di ITEMS vengono -assunti dalla LIST. - -<tscreen><verb> -void gtk_list_append_items (GtkList *LIST, GList *ITEMS) -</verb></tscreen> - -Inserisce elementi di lista proprio come gtk_list_insert_items(), -ma alla fine della LIST. I nodi GList di ITEMS vengono -assunti dalla LIST. - -<tscreen><verb> -void gtk_list_prepend_items (GtkList *LIST, GList *ITEMS) -</verb></tscreen> - -Inserisce elementi di lista proprio come gtk_list_insert_items(), -ma al principio della LIST. I nodi GList di ITEMS vengono -assunti dalla LIST. - -<tscreen><verb> -void gtk_list_remove_items (GtkList *LIST, GList *ITEMS) -</verb></tscreen> - -Rimuove degli elementi di lista dalla LIST. ITEMS è una lista -doppiamente collegata in cui ci si aspetta che i puntatori di -ogni nodo puntino a un figlio diretto di LIST. E' poi responsabilità -del chiamante di fare una chiamata a g_list_free(ITEMS). E' anche -necessario che il chiamante distrugga lui stesso gli elementi della -lista. - -<tscreen><verb> -void gtk_list_clear_items (GtkList *LIST, gint START, gint END) -</verb></tscreen> - -Rimuove e distrugge elementi di lista da LIST. Un widget ne è -interessato se la sua posizione corrente all'interno di LIST è compreso -fra START ed END. - -<tscreen><verb> -void gtk_list_select_item (GtkList *LIST, gint ITEM) -</verb></tscreen> - -Invoca il segnale select_child per un elemento di lista -specificato dalla sua posizione corrente all'interno di LIST. - -<tscreen><verb> -void gtk_list_unselect_item (GtkList *LIST, gint ITEM) -</verb></tscreen> - -Invoca il segnale unselect_child per un elemento di lista -specificato dalla sua posizione corrente all'interno di LIST. - -<tscreen><verb> -void gtk_list_select_child (GtkList *LIST, GtkWidget *CHILD) -</verb></tscreen> - -Invoca il segnale select_child per uno specifico CHILD. - -<tscreen><verb> -void gtk_list_unselect_child (GtkList *LIST, GtkWidget *CHILD) -</verb></tscreen> - -Invoca il segnale unselect_child per uno specifico CHILD. - -<tscreen><verb> -gint gtk_list_child_position (GtkList *LIST, GtkWidget *CHILD) -</verb></tscreen> - -Restituisce la posizione di CHILD all'interno di LIST. In caso di fallimento, -viene restituito `-1'. - -<tscreen><verb> -void gtk_list_set_selection_mode (GtkList *LIST, GtkSelectionMode MODE) -</verb></tscreen> - -Assegna a LIST il modo di selezione MODE, che può essere uno fra -GTK_SELECTION_SINGLE, GTK_SELECTION_BROWSE, GTK_SELECTION_MULTIPLE o -GTK_SELECTION_EXTENDED. - -<tscreen><verb> -GtkList* GTK_LIST (gpointer OBJ) -</verb></tscreen> - -Fa il cast di un generico puntatore a `GtkList*'. Per maggiori -informazioni vedere Standard Macros::. - -<tscreen><verb> -GtkListClass* GTK_LIST_CLASS (gpointer CLASS) -</verb></tscreen> - -Fa il cast di un generico puntatore a `GtkListClass*'. Per maggiori -informazioni vedere Standard Macros::. - -<tscreen><verb> -gint GTK_IS_LIST (gpointer OBJ) -</verb></tscreen> - -Determina se un generico puntatore si riferisce ad un oggetto `GtkList'. -Per maggiori informazioni vedere Standard Macros::. - -<!-- ----------------------------------------------------------------- --> -<sect1> Esempio -<p> -Diamo di seguito un programma di esempio che stamperà i campbiamenti -della selezione di una GtkList, e vi lascia ``imprigionare'' gli elementi -di una lista selezionandoli con il pulsante destro del mouse: - -<tscreen><verb> -/* list.c */ - -/* includiamo i file header di gtk+ - * includiamo stdio.h, ne abbiamo bisogno per printf() - */ -#include <gtk/gtk.h> -#include <stdio.h> - -/* Questa e' la nostra stringa di identificazione dei dati per assegnarli - * ad elementi di lista - */ -const gchar *list_item_data_key="list_item_data"; - - -/* prototipi per i gestori di segnale che connetteremo - * al widget GtkList - */ -static void sigh_print_selection (GtkWidget *gtklist, - gpointer func_data); -static void sigh_button_event (GtkWidget *gtklist, - GdkEventButton *event, - GtkWidget *frame); - - -/* funzione main per predisporre l'interfaccia utente */ - -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]; - - - /* inizializza gtk+ (e di conseguenza gdk) */ - - gtk_init(&argc, &argv); - - - /* crea una finestra in cui mettere tutti i widget - * connette gtk_main_quit() al segnale "destroy" della finestra - * per gestire le richieste di chiusura finestra del window manager - */ - 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); - - - /* all'interno della finestra abbiamo bisogno di una scatola - * in cui mettere i widget verticalmente */ - 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); - - /* questa è la finestra scorribile in cui mettere il widget GtkList */ - 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); - - /* crea il widget GtkList - * connette il gestore di segnale sigh_print_selection() - * al segnale "selection_changed" della GtkList, per stampare - * gli elementi selezionati ogni volta che la selezione cambia - */ - 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); - - /* creiamo una "Prigione" (Prison) in cui mettere gli elementi di lista ;) - */ - 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); - - /* connette il gestore di segnale sigh_button_event() alla GtkList - * il quale gestira' l'"imprigionamento" degli elementi di lista - */ - gtk_signal_connect(GTK_OBJECT(gtklist), - "button_release_event", - GTK_SIGNAL_FUNC(sigh_button_event), - frame); - - /* crea un separatore - */ - separator=gtk_hseparator_new(); - gtk_container_add(GTK_CONTAINER(vbox), separator); - gtk_widget_show(separator); - - /* infine creiamo un bottone e connettiamone il segnale "clicked" - * alla distruzione della finestra - */ - 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)); - - - /* a questo punto creiamo 5 elementi di lista, ognuno con la - * propria etichetta, e li aggiungiamo alla GtkList usando - * gtk_container_add(). Inoltre, recuperiamo la stringa di testo - * dall'etichetta e la associamo, per ogni elemento, a - * 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); - } - - /* qui creiamo altre 5 etichette, questa volta usando - * per la creazione gtk_list_item_new_with_label(). - * Non possiamo recuperare la stringa di testo dall'etichetta - * dal momento che non disponiamo di puntatori alle etichette, - * quindi associamo semplicemente il list_item_data_key di ogni - * elemento di lista con la medesima stringa di testo. - * Per aggiungere elementi di lista, li mettiamo tutti in una lista - * doppiamente collegata (GList), e quindi li aggiungiamo con una - * unica chiamata a gtk_list_append_items(). - * Dal momento che usiamo g_list_prepend() per mettere gli elementi - * nella lista doppiamente collegata, il loro ordine sara' discendente - * (invece che ascendente come sarebbe se usassimo g_list_append()) - */ - 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); - - /* e finalmente vogliamo vedere la finestra, non e' vero? ;) - */ - gtk_widget_show(window); - - /* lancia il ciclo principale di gtk - */ - gtk_main(); - - /* si arriva a questo punto dopo la chiamata di gtk_main_quit(), - * il che accade quando viene distrutta la finestra principale - */ - return 0; -} - -/* questo e' il gestore di segnale che e' stato connesso all'evento di - * pressione/rilascio del bottone della GtkList - */ -void -sigh_button_event (GtkWidget *gtklist, - GdkEventButton *event, - GtkWidget *frame) -{ - /* facciamo qualcosa solo nel caso di rilascio del terzo bottone - * (quello piu' a destra) - */ - if (event->type==GDK_BUTTON_RELEASE && - event->button==3) { - GList *dlist, *free_list; - GtkWidget *new_prisoner; - - /* recuperiamo l'elemento di lista selezionato correntemente, - * che sara' il nostro prossimo prigioniero ;) - */ - dlist=GTK_LIST(gtklist)->selection; - if (dlist) - new_prisoner=GTK_WIDGET(dlist->data); - else - new_prisoner=NULL; - - /* cerchiamo elementi di lista gia' imprigionati, - * li rimetteremo nella lista. - * Ricordare di liberare la lista doppiamente collegata - * che viene restituita da gtk_container_children() - */ - 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); - - /* se abbiamo un nuovo prigioniero, lo rimuoviamo - * dalla GtkList e lo mettiamo nella cornice della - * "Prigione". Dobbiamo prima deselezionare l'elemento - */ - 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); - } - } -} - -/* questo e' il gestore di segnaleche viene chiamato de la - * GtkList emette il segnale "selection_changed" - */ -void -sigh_print_selection (GtkWidget *gtklist, - gpointer func_data) -{ - GList *dlist; - - /* recuperiamo la lista doppiamente collegata degli - * elementi selezionati della GtkList, ricordate di - * trattarla come sola lettura - */ - dlist=GTK_LIST(gtklist)->selection; - - /* se non ci sono elementi selezionati non c'e' altro da - * fare che dirlo all'utente - */ - if (!dlist) { - g_print("Selection cleared\n"); - return; - } - /* ok, abbiamo una selezione e quindi lo scriviamo - */ - g_print("The selection is a "); - - /* ottieniamo l'elemento di lista dalla lista doppiamente - * collegata e poi richiediamo i dati associati con - * list_item_data_key. Poi semplicemente li stampiamo - */ - 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"); -} -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1> Il Widget Elemento di Lista (List Item) -<p> -Il widget GtkListItem è progettato allo scopo di essere un contenitore -collegato ad un figlio, per fornire le funzioni per la selezione e deselezione -allo stesso modo in cui il widget GtkList ne ha bisogno per i propri figli. - -Un GtkListItem ha la sua propria finestra per ricevere eventi, e ha il suo -proprio colore di sfondo, che di solito è bianco. - -Dal momento che questo widget deriva direttamente da GtkItem, può essere -trattato come tale usando la macro GTK_ITEM(ListItem), vedere il widget -GtkItem per ulteriori informazioni. -Di solito un GtkListItem ha solo un'etichetta per identificare per esempio -un nome di file all'interno di una GtkList -- per cui viene fornita la -funzione appropriata gtk_list_item_new_with_label(). Si può ottenere lo -stesso effetto creando una GtkLabel da sola, assegnando al suo allineamento -i valori xalign=0 e yalign=0.5, aggiungendo successivamente un contenitore -alla GtkListItem. - -Dal momento che non si è obbligati a mettere una GtkLabel, si può anche -aggiungere una GtkVBox una GtkArrow ecc. alla GtkListItem. - - -<!-- ----------------------------------------------------------------- --> -<sect1> Segnali -<p> -Un GtkListItem non crea alcun nuovo segnale di per se, ma eredita -i segnali di GtkItem. Per ulteriori informazioni, vedere GtkItem::. - -<!-- ----------------------------------------------------------------- --> -<sect1> Funzioni -<p> - -<tscreen><verb> -guint gtk_list_item_get_type (void) -</verb></tscreen> - -Restituisce l'identificatore di tipo `GtkListItem'. - -<tscreen><verb> -GtkWidget* gtk_list_item_new (void) -</verb></tscreen> - -Crea un nuovo oggetto `GtkListItem'. Il nuovo widget viene restituito -sottoforma di un puntatore ad un oggetto `GtkWidget'. In caso di -fallimento, viene restituito `NULL'. - -<tscreen><verb> -GtkWidget* gtk_list_item_new_with_label (gchar *LABEL) -</verb></tscreen> - -Cre un nuovo oggetto `GtkListItem', avente come unico figlio -un GtkLabel. Il nuovo widget viene restituito -sottoforma di un puntatore ad un oggetto `GtkWidget'. In caso di -fallimento, viene restituito `NULL'. - -<tscreen><verb> -void gtk_list_item_select (GtkListItem *LIST_ITEM) -</verb></tscreen> - -Questa funzione è essenzialmente un wrapper per una chiamata a -gtk_item_select (GTK_ITEM (list_item)) che emetterà il segnale -select. -Vedere GtkItem:: per maggiori informazioni. - -<tscreen><verb> -void gtk_list_item_deselect (GtkListItem *LIST_ITEM) -</verb></tscreen> - -Questa funzione è essenzialmente un wrapper per una chiamata a -gtk_item_deselect (GTK_ITEM (list_item)) che emetterà il segnale -deselect. -Vedere GtkItem:: per maggiori informazioni. - -<tscreen><verb> -GtkListItem* GTK_LIST_ITEM (gpointer OBJ) -</verb></tscreen> - -Effettua il cast di un puntatore generico a `GtkListItem*'. Vedere -Standard Macros:: per maggiorni informazioni. - -<tscreen><verb> -GtkListItemClass* GTK_LIST_ITEM_CLASS (gpointer CLASS) -</verb></tscreen> - -Effettua il cast di un puntatore generico a `GtkListItemClass*'. Vedere -Standard Macros:: per maggiorni informazioni. - -<tscreen><verb> -gint GTK_IS_LIST_ITEM (gpointer OBJ) -</verb></tscreen> - -Determina se un puntatore generico si riferisce ad un oggetto -`GtkListItem'. Vedere Standard Macros:: per maggiorni informazioni. - -<!-- ----------------------------------------------------------------- --> -<sect1> Esempio -<p> -Come esempio su questo argomento, si veda quello relativo alla GtkList, -che riguarda anche l'uso del GtkListItem. - -<!-- ***************************************************************** --> -<sect>Il Widget Menù (Menu Widgets) -<!-- ***************************************************************** --> -<p> -Ci sono due modi per creare dei menù, quello facile e quello difficile. -Ognuno è più adatto per certe circostanze, ma di solito si può usare il -modo semplice, cioé menu_factory (la ``fabbrica dei menù''). Il modo -``difficile'' è di crearsi tutti i menù usando direttamente le chiamate. -Quello semplice è di usare le chiamate di tipo gtk_menu_factory. Anche se -è un modo molto più semplice, ci sono svantaggi e vantaggi per ciascuno -dei due approcci. - -La menu_factory è molto più semplice da usare e per aggiungere dei nuovi -menù, anche se scriversi un po' di funzioni per creare dei menù con il -metodo manuale può dare risultati molto migliori dal punto di vista -dell'usabilità. Con la menufactory, non è possibile mettere immagini o -caratteri '/' nei menù. -<p> -<!-- ----------------------------------------------------------------- --> -<sect1>Creazione Manuale di Menù -<p> -Seguendo la tradizionale arte dell'insegnamento, partiamo dal modo -difficile. <tt>:)</> -<p> -I widget che hanno a che fare con la creazione di una barra di menù e di sottomenù sono tre: -<itemize> -<item>un elemento di menù, che ` quello che l'utente poi selezionerà, per esempio 'Salva' -<item>un menù, che fa la parte di contenitore per gli elementi di menù, e -<item>una barra dei menù, che è un contenitore per ciascuno dei menù -</itemize> - - -La cosa viene un po' complicata dal fatto che i widget elemento di menù vngono usati per - -due scopi diversi. Essi sono sia i widget che vengono impacchettati nei menù, che - -quelli che vengono impacchettati nella barra dei menù che, quando selezonati, attivano i menù. - -Diamo un'occhiata alle funzioni usate per creare i menù e le barre di menù. -Con questa prima funzione si crea un nuova barra di menù: - - -<tscreen><verb> -GtkWidget *gtk_menu_bar_new(void); -</verb></tscreen> - -Questa funzione crea una nuova barra di menù. Per impacchettarla in una -finestra o si usa la funzione gtk_container_add, oppure, per impacchettarla -in una scatola, le funzioni box_pack - come con i bottoni. - -<tscreen><verb> -GtkWidget *gtk_menu_new(); -</verb></tscreen> - -Questa funzione restituisce un puntatore ad un nuovo menù, non viene mai -realmente mostrato (con gtk_widget_show), serve solo per contenere gli -elementi del menù. Spero che il tutto risulti più chiaro quando daremo -un'occhiata all'esempio più sotto. -<p> -Le prossime due chiamate sono usate per creare degli elementi che poi -vengono impacchettati nei menù e nelle barre dei menù.. - -<tscreen><verb> -GtkWidget *gtk_menu_item_new(); -</verb></tscreen> - -e - -<tscreen><verb> -GtkWidget *gtk_menu_item_new_with_label(const char *label); -</verb></tscreen> - -Queste chiamate sono usate per creare gli elementi di menù che devono poi essere mostrati. -Ricordate la differenza che esiste fra un ``menù'' come quelli creati con -gtk_menu_new e un ``elemento di menù'' (menu item) come quelli creati con -la funzione gtk_menu_item_new. L'elemento di menù sarà un bottone -vero e proprio con una azione associata, mentre un menù è solo un contenitore che li raccoglie. -Le funzioni gtk_menu_new_with_label e gtk_menu_new sono esattamente come vi aspettereste che siano dopo - -aver conosciuto i bottoni. Una crea un nuovo elemento di menù con un'etichetta già impacchettata, - -mentre l'altra crea un elemento di menù vuoto. - - -Una volta che si ` creato un elemento di menù, è necessario piazzarlo su di un menù. - -Per fare ciò si usa la funzione gtk_menu_append. Per determinare quando l'utente ha selezionato un elemento, abbiamo bisogno di connettere il segnale <tt/activate/ nel solito modo. - -Quindi, se volessimo creare un normale menù <tt/File/, con le opzioni <tt/Open/, <tt/Save/ e <tt/Quit/, il codice avrebbe più o meno il seguente aspetto: - -<tscreen><verb> -file_menu = gtk_menu_new(); /* Non e' necessario mostrare i menu' */ - -/* Creiamo gli elementi del menu' */ -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"); - -/* Aggiungiamoli al menu' */ -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); - - -/* Colleghiamo le funzioni di callback al segnale activate */ -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"); - -/* Possiamo collegare l'elemento Quit alla nostra funzione di uscita */ -gtk_signal_connect_object( GTK_OBJECT(quit_items), "activate", - GTK_SIGNAL_FUNC(destroy), (gpointer) "file.quit"); - -/* Abbiamo bisogno di mostrare gli elementi di menu' */ -gtk_widget_show( open_item ); -gtk_widget_show( save_item ); -gtk_widget_show( quit_item ); - </verb></tscreen> - - -A questo punto abbiamo il nostro menù Adesso abbiamo bisogno di creare una barra dei menù - -e un elemento di menù per <tt/File/, a cui aggiungeremo il nostro menù. Il codice è questo: - - -<tscreen><verb> -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); -</verb></tscreen> - - -Ora dobbiamo associare il menù con <tt/file_item/. Lo si può fare con la funzione - -<tscreen> -void gtk_menu_item_set_submenu( GtkMenuItem *menu_item, - GtkWidget *submenu); -</tscreen> - - -Quindi, il nostro esempio continuerebbe con - -<tscreen><verb> -gtk_menu_item_set_submenu( GTK_MENU_ITEM(file_item), file_menu); -</verb></tscreen> - - -Ciò che manca a questo punto è di collegare il menù alla barra, cosa che si può ottenere tramite la funzione - -<tscreen> -void gtk_menu_bar_append( GtkMenuBar *menu_bar, GtkWidget *menu_item); -</tscreen> - -che nel nostro caso è: - -<tscreen><verb> -gtk_menu_bar_append( GTK_MENU_BAR(menu_bar), file_item ); -</verb></tscreen> - - -Se volessimo il menù giustificato a dstra, come sono spesso i menù di aiuto, potremm - -usare la seguente funzioe (di nuovo su <tt/file_item/ in questo esempio) prima di fare il collegamento alla barra. - - -<tscreen><verb> -void gtk_menu_item_right_justify (GtkMenuItem *menu_item); -</verb></tscreen> -Ecco un riassunto dei passi necessari per creare una barra con i relativi menù collegati: - -<itemize> -<item> Create un nuovo menù con gtk_menu_new() -<item> Usate delle chiamate multiple a gtk_menu_item_new() per ognuno degli - elementi che volete mettere nel vostro menù. Usate inoltre gtk_menu_item_append() - per mettere ciascuno di questi nuovi elementi sul menù.. -<item> Create un elemento di menù usando gtk_menu_item_new(). Questo rappresenta l'elemento di base - -delmenù, e il testo relativo sarà il testo mostrato sulla barra dei menù stessa. - -<item> Usate gtk_menu_item_set_submenu() per collegare i menù all'elemento base del menù (cioè quello creato al passaggio precedente). - -<item> Create una nuova barra di menù usando gtk_menu_bar_new. Questo passo - necessita di essere effettuato una sola volta quando si crea una serie di - menù su una sola barra. -<item> Usate gtk_menu_bar_append per mettere il menù base sulla barra dei menù. -</itemize> -<p> -Creare un menù a comparsa è più o meno la stessa cosa. La differenza è che il -il menù non viene attivato ``automaticamente'' da una barra, bensì per esempio -con la chiamata espicita alla funzione gtk_menu_popup() da parte di un evento di pressione di un pulsante. -Seguite questi passaggi: -<itemize> -<item>Create una funzione di gestione di un evento. Essa deve seguire il prototipo -<tscreen> -static gint handler(GtkWidget *widget, GdkEvent *event); -</tscreen> -e usare l'evento per scoprire dove il menu deve essere fatto comparire. -<item>Nel gestore di evento, se questo è la pressione di un bottone, trattate -<tt>event</tt> come l'evento relativo ad un bottone (cosa che in effetti è) -e usatelo come mostrato nel codice di esempio per passare informazioni a -gtk_menu_popup(). -<item>Collegate il gestore di evento a un widget con -<tscreen> -gtk_signal_connect_object(GTK_OBJECT(widget), "event", - GTK_SIGNAL_FUNC (handler), GTK_OBJECT(menu)); -</tscreen> -in cui <tt>widget</tt> è il widget a cui state effettuando il collegamento, e -<tt>handler</tt> è la funzione di gestione, mentre <tt>menu</tt> è un menù -creato con gtk_menu_new(). Quest'ultimo può essere un menù che viene anche -attivato da una barra di menù, come mostrato nel codice di esempio. -</itemize> - - -<!-- ----------------------------------------------------------------- --> -<sect1>Esempio di Menù Manuale -<p> -Per la teoria dovrebbe essere abbastanza. Diamo un'occhiata ad un esempio che -ci aiuti a chiarire le cose. - -<tscreen><verb> -/* menu.c */ -#include <gtk/gtk.h> - -static gint button_press (GtkWidget *, GdkEvent *); -static void menuitem_response (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); - - /* crea una nuova finestra */ - 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); - - /* Inizializziamo il menù, e ricordate: mai applicare - * gtk_show_widget() al widget menù!! - * Questo è il menù che contiene gli elementi, quello che - * spunta quando si fa click sul "Menù radice" nell'applicazione */ - menu = gtk_menu_new(); - - /* Ora creiamo un ciclo che crea tre elementi di menu per "test-menu". - * Notete la chiamata a gtk_menu_append. In questo punto aggiungiamo una - * lista di elementi al nostro menù. Normalmente, dovremmo poi catturare - * il segnale di attivazione per ognuno degli elementi del menu, e creare - * una funzione di ritorno per ciascuno di essi, ma qui non li mettiamo per - * brevità. */ - - for(i = 0; i < 3; i++) - { - /* Copia i nomi in buf. */ - sprintf(buf, "Test-undermenu - %d", i); - - /* Crea un nuovo elemento di menù con un nome... */ - menu_items = gtk_menu_item_new_with_label(buf); - - /* ...e aggiungilo al menù. */ - gtk_menu_append(GTK_MENU (menu), menu_items); - - /* Fa qualcosa di interessante quando si seleziona l'elemento */ - gtk_signal_connect_object(GTK_OBJECT(menu_items), "activate", - GTK_SIGNAL_FUNC(menuitem_response), (gpointer) g_strdup(buf)); - - /* Mostra il widget */ - gtk_widget_show(menu_items); - } - - /* Questo è il menù radice, e l'etichetta sarà il nome del menù che - * verrà mostrato sulla barra dei menù. Non ci sarà alcun gestore di - * segnale collegato, dal momento che non fa altro che mostrare il resto - * del menù quando viene premuto. */ - root_menu = gtk_menu_item_new_with_label("Root Menu"); - - gtk_widget_show(root_menu); - - - - - /* Ora specifichiamo che vogliamo che il menù che abbiamo appena creato - * sia il menù radice *// - gtk_menu_item_set_submenu(GTK_MENU_ITEM (root_menu), menu); - - /* Una vbox in cui mettere un menù ed un bottone: */ - vbox = gtk_vbox_new(FALSE, 0); - gtk_container_add(GTK_CONTAINER(window), vbox); - gtk_widget_show(vbox); - - /* Crea una barra dei menù per metterci i menù e l'aggiunge alla finestra principale */ - menu_bar = gtk_menu_bar_new(); - gtk_box_pack_start(GTK_BOX(vbox), menu_bar, FALSE, FALSE, 2); - gtk_widget_show(menu_bar); - - /* Crea un bottone a cui collegare un menù */ - 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); - - /* E finalmente attacchiamo l'elemento di menù alla barra dei menù -- questo - * è l'elemento di menù "radice" di cui parlavo */ - gtk_menu_bar_append(GTK_MENU_BAR (menu_bar), root_menu); - - /* La finestra va mostrata sempre come ultimo passo in modo che sia già - * completa di tutti i suoi elementi. */ - gtk_widget_show(window); - - gtk_main (); - - return 0; -} - - - -/* Risponde alla pressione di un bottone impostando un menù che - * viene passato come widget. - * Notate che l'argomento "widget" si riferisce al menù impostato - * e NON al bottone premuto. - */ - -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); - /* Riferisce al codice chiamante che abbiamo trattato l'evento; - * la faccenda finisce qui. */ - return TRUE; - } - - /* Riferisce al codice chiamante che abbiamo trattato l'evento; passa avanti. */ - return FALSE; -} - - -/* Stampa una stringa quando viene selezionato un elemento di menù */ - -static void menuitem_response (gchar *string) -{ - printf("%s\n", string); -} -</verb></tscreen> - -Si può anche fare in modo che un elemento di menù sia insensibile e, usando -una tabella di acelleratori, collegare dei tasti a delle funzioni di menù. - - -<!-- ----------------------------------------------------------------- --> -<sect1>Usare GtkMenuFactory -<p> -Ora che vi abbiamo mostrato il modo difficile, ecco invece come si fa usando -le chiamate di gtk_menu_factory. - - -<!-- ----------------------------------------------------------------- --> -<sect1>Esempio di Menu Factory -<p> -Ecco un esempio di utilizzo della ``Fabbrica'' di Menù di GTK (Menu Factory). -Questo è il primo file, menufactoy.h. Teniemo dei file menufactory.c e main.c separati -a causa delle variabili globali usate nel file menufactory.c. - -<tscreen><verb> - -/* 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__ */ - -</verb></tscreen> -<p> -Ed ecco il file menufactory.c. - -<tscreen><verb> -/* 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); - -/* Questa è la struttuta GtkMenuEntry, che viene usata per creare dei nuovi - * menù. Il primo membro à la stringa di definizione del menù. Il secondo - * è il tasto acceleratore predefinito, usato per accedere a questa funzione - * con la tastiera. Il terzo è la funzione di ritorno che viene chiamata - * quando si seleziona con la tastiera o il mouse questo elemento di menù. - * L'ultimo membro costituisce il dato che viene passato alla funzione di - * ritorno. */ - -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} -}; - -/* calcola il numero di menu_item */ -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_str_hash, g_str_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("Impossibile assegnare sensibilità a menù inesistente: %s", path); -} - -</verb></tscreen> -<p> -Ed ecco mfmain.h - -<tscreen><verb> -/* 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__ */ - -</verb></tscreen> -<p> -E mfmain.c - -<tscreen><verb> -/* 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); -} - -/* Questo è per mostrare come si usano le funzioni di ritorno quando - * si utilizza la MenuFactory. Spesso, si mettono tutte le funzioni di - * callback in un file separato, e le si fanno chiamare le funzioni - * appropriate da lì. Così le cose sono più organizzate. */ -void file_quit_cmd_callback (GtkWidget *widget, gpointer data) -{ - g_print ("%s\n", (char *) data); - gtk_exit(0); -} -</verb></tscreen> -<p> -Ed infine un bel makefile per semplificare la compilazione. - -<tscreen><verb> - -# 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 *~ -</verb></tscreen> -<p> -Per il momento, accontentatevi di questo esempio. Più avanti aggiungeremo -una spiegazione ed un bel po' di commenti. - - -<!-- ***************************************************************** --> -<sect> Widget "Testo" (Text Widget) -<!-- ***************************************************************** --> -<p> -Il widget di testo permette di mostrare e modificare del testo disposto su più -linee. Questo widget supporta sia la presenza di diversi colori che di diversi font -contemporaneamente, permettendo di mischiarli nel modo in cui si desidera. Mette poi a -disposizione un ampio gruppo di comandi basati sulla tastiera, che sono compatibili con -Emacs. - -Il widget di testo dà la possibilità di fare taglia e incolla in modo -completo, compreso l'uso del doppio e triplo click per selezionare un'intera parola o -un'intera linea. - -<!-- ----------------------------------------------------------------- --> -<sect1>Creazione e configurazione di una casella di testo -<p> -Esiste un'unica funzione per la creazione di un nuovo widget di testo: -<tscreen><verb> -GtkWidget* gtk_text_new (GtkAdjustment *hadj, - GtkAdjustment *vadj); -</verb></tscreen> - -Gli argomenti di questa chiamata ci permettono di assegnare dei puntatori a dei -valori che stabiliscono il punto di vista del widget. Passare dei valori NULL all'uno -o all'altro o ad entrambi questi argomenti, fà sì che gtk_text_new li -crei automaticamente. - -<tscreen><verb> -void gtk_text_set_adjustments (GtkText *text, - GtkAdjustment *hadj, - GtkAdjustment *vadj); -</verb></tscreen> - -La funzione precedente permette di cambiare gli aggiustamenti orizzontale e verticale -di un widget di testo i ogni momento. - -Il widget di testo non ` di creare delle barre di scorrimento quando la -quantità è troppo grande per la finestra. Dobbiamo quindi crearle e -aggiungerle alla finestra noi stessi. - -<tscreen><verb> - vscrollbar = gtk_vscrollbar_new (GTK_TEXT(text)->vadj); - gtk_box_pack_start(GTK_BOX(hbox), vscrollbar, FALSE, FALSE, 0); - gtk_widget_show (vscrollbar); -</verb></tscreen> - -Il pezzetto di codice precedente crea una nuova barra di scorrimento verticale e la -collega all'aggiustamento verticale del widget di testo, <tt/text/, dopodiché la -impacchetta nella hbox al solito modo. - -Ci sono due modi principali di utilizzo di un widget di testo: per permettere all'utente -di editare del testo, oppure per permettere a noi di mostrare all'utente del testo -disposto su più righe. Per passare dall'una all'altra di queste modalità, -il widget di testo ci mette a disposizione la seguente funzione: - -<tscreen><verb> -void gtk_text_set_editable (GtkText *text, - gint editable); -</verb></tscreen> - -L'argomento <tt/editable/ è un valore TRUE o FALSE che specifica se l'utente -può modificare o meno il contenuto del widgte. Quando il widget è -modificabile, mostrerà un cursore nel punto di inserimento corrente. - -Niente però vi obbliga ad usare il widget di testo in questi due soli modi. Si -può passare dall'una all'altra delle due modalità in qualsiasi momento, -e si può inserire del testo in ogni momento. - -Il widget di testo è in grado di andare a capo automaticamente quando delle linee -di testo sono troppo lunghe per stare su una sola linea della finestra. Il comportamento -predefinito è di andare a capo automaticamente al termine della linea. Questo -può essere cambiato con la seguente funzione: - -<tscreen><verb> -void gtk_text_set_word_wrap (GtkText *text, - gint word_wrap); -</verb></tscreen> - -L'uso di questa funzione ci permette di specificare se il widget di testo deve spezzare -o no le linee lunghe ai bordi della finestra. L'argomento <tt/word_wrap/ è un -valore di tipo TRUE o FALSE. - -<!-- ----------------------------------------------------------------- --> -<sect1>Manipolazione del testo -<P> -Il punto di inserimento corrente del widget può essere stabilito usando -<tscreen><verb> -void gtk_text_set_point (GtkText *text, - guint index); -</verb></tscreen> -in cui <tt/index/ è la posizione in cui mettere il punto di inserimento. - -La funzione per ottenere la posizione di inserimento corrente è analoga: -<tscreen><verb> -guint gtk_text_get_point (GtkText *text); -</verb></tscreen> - -Una funzione che è utile in combinazione con le precedenti due è -<tscreen><verb> -guint gtk_text_get_length (GtkText *text); -</verb></tscreen> -la quale restituisce la lunghezza corrente del widget di testo. La lunghezza è -definita come il numero di caratteri che si trovano nel blocco di testo della finestra, -compresi i caratteri tipo CR, che marcano la fine delle linee. - -Per inserire del testo alla posizione corrente del widget di testo, si usa la funzione -gtk_text_insert, che permette anche di specificare i colori di primo piano e di sfondo -per il testo, oltre al font da usare. - -<tscreen><verb> -void gtk_text_insert (GtkText *text, - GdkFont *font, - GdkColor *fore, - GdkColor *back, - const char *chars, - gint length); -</verb></tscreen> - -Passare un valore di NULL come valore per il colore di primo piano (fore), di sfondo (back) -o per il font, farà sì che vengano usati i valori che sono specifici dello -stile del widget. Usare un valore di <tt/-1/ per il parametro lunghezza (length) avrà -come risultato l'inserzione dell'intera stringa di testo. - -Il widget di testo è uno dei pochi in GTK che vengono disegnati dinamicamente, fuori -dalla funzione gtk_main. Ciò significa che tutti i cambiamenti al suo contenuto -avranno effetto immediato. Questo può essere un comportamento indesiderabile quando -si stanno facendo delle modifiche multiple al contenuto del widget. Per permettere di -operare cambiamenti multipli sul widget senza che esso si ridisegni continuamente, -si può congelare il contenuto della finestra, in modo che esso interrompa -temporaneamente di ridisegnarsi. Potremo poi sbloccare il widget una volta che tutte -le modifiche sono state completate. - -Le due seguenti funzioni fanno il congelamento e lo sbloccaggio (thaw) del widget: - -<tscreen><verb> -void gtk_text_freeze (GtkText *text); -void gtk_text_thaw (GtkText *text); -</verb></tscreen> - -Il testo può essere cancellato nel widget di testo a partire dal punto di -inserimento corrente usando le seguenti due funzioni, andando all'indietro (backward) -o all'avanti (forward): - -<tscreen><verb> -gint gtk_text_backward_delete (GtkText *text, - guint nchars); -gint gtk_text_forward_delete (GtkText *text, - guint nchars); -</verb></tscreen> - -Quando si vuole recuperare il contenuto del widget di testo, è -disponibile la macro <tt/GTK_TEXT_INDEX(t, index)/, che permette di -ottenere il crattere alla posizione <tt/index/ all'interno del widget -<tt/t/. - -Per ecuperare un blocco di testo più ampio, si usa la funzione: - -<tscreen><verb> -gchar *gtk_editable_get_chars (GtkEditable *editable, - gint start_pos, - gint end_pos); -</verb></tscreen> - -Questa è una funzione della classe madre del widget di testo. Un valore -di -1 per <tt/end_pos/, sta ad indicare la fine del testo. L'indice per il -testo parte da 0. - -Questa funzione alloca una nuova porzione di memoria per il blocco di testo, -per cui non dimenticate di liberarla con una chiamata a g_free quando non -ne avete più bisogno. - -<!-- ----------------------------------------------------------------- --> -<sect1>Keyboard Shortcuts -<p> -Il widget di testo mette a disposizione un certo numero di scorciatoie da tastiera -per le più comuni operazioni di modifica, movimento e selezione. Si possono -utilizzare con delle combinazioni che comprendono i tasti Control e Alt. - -Oltre a queste, mantenendo premuto il pulsante Control mentre si usano i tasti di -movimento del cursore, causerà lo spostamento parola per parola invece che -carattere per carattere. Mantenere invece premuto il tasto Shift mentre si sposta il -cursore, causerà l'estensione della selezione. - -<sect2>Scorciatoie per il movimento -<p> -<itemize> -<item> Ctrl-A Inizio della linea -<item> Ctrl-E Fine della linea -<item> Ctrl-N Prossima linea -<item> Ctrl-P Linea precedente -<item> Ctrl-B Indietro di un carattere -<item> Ctrl-F Avanti di un carattere -<item> Alt-B Indietro di una parola -<item> Alt-F Avanti di una parola -</itemize> - -<sect2>Scorciatoie per la modifica -<p> -<itemize> -<item> Ctrl-H Cancella il carattere precedente (Backspace) -<item> Ctrl-D Cancella il carattere successivo (Delete) -<item> Ctrl-W Cancella la parola precedente -<item> Alt-D Cancella la parola successiva -<item> Ctrl-K Cancella fino alla fine della linea -<item> Ctrl-U Cancella la linea -</itemize> - -<sect2>Scorciatoie per la selezione -<p> -<itemize> -<item> Ctrl-X Taglia -<item> Ctrl-C Copia -<item> Ctrl-V Incolla -</itemize> - - -<!-- ***************************************************************** --> -<sect> Widget non documentati -<!-- ***************************************************************** --> - -<p> -Per questi sarebbe utile il contributo degli autori! :) Prendete in -considerazione la possibilità di contribuire al nostro tutorial. - -Se dovete usare uno di questi widget non documentati, vi suggeriamo -caldamente di dare un'occhiata ai loro rispettivi file header nella -distribuzione di GTK. I nomi delle funzioni di GTK sono molto descrittivi. -Non appena si capisce come funzionano le cose, non è -difficile dedurre il modo d'uso di un widget semplicemente guardando la -dichiarazione di funzione associata ad esso. Aggiungendo a questo qualche -spunto tratto dal codice di altri non dovrebbero esserci problemi. - -Quando avrete raggiunto una comprensione globale di tutte le funzioni -di un widget non documentato, considerate la possibilità di scrivere -un tutorial su di esso, in modo che altri possano beneficiare del -vostro lavoro. - -<!-- ----------------------------------------------------------------- --> -<sect1> Controlli di intervallo (Range Controls) - -<!-- ----------------------------------------------------------------- --> -<sect1> Anteprime -<!-- -(Potrebbe essere necessario riscrivere questa parte per conformarsi allo stile -del resto del tutorial) ---> -<p> -Le anteprime servono a un certo numero di cose in GIMP/GTK. La più -importante è questa: a risoluzioni molto alte le immagini possono -facilmente occupare diverse decine di megabyte di memoria; ogni operazione -su immagini così grosse può richiedere molto tempo. Se per la -scelta di una data modifica vi occorrono 5-10 tentativi (cioè 10-20 -passi, poiché è necessario ripristinare l'originale se si -è commesso un errore), possono volerci letteralmente delle ore per -fare quella giusta - se non si rimane a corto di memoria prima! Coloro che -hanno passato ore in camera oscura conoscono la sensazione. In questi casi -le anteprime sono utilissime! - -Ma la seccatura dell'attesa non è l'unico caso. Spesso è utile -confrontare la versione precedente con la successiva affiancandole, o almeno -alternandole. Se si sta lavorando con grandi immagini e ritardi di una decina -di secondi un confronto efficace è quantomeno difficile da fare. -Per immagini di 30 mega (4 pollici per 6 pollici, 600 punti per pollice, 24 bit) -tale confronto risulta impraticabile per la maggior parte degli utenti. In -questo caso le anteprime sono di grande aiuto! - -Ma c'è di più. Con le anteprime è possibile scrivere -plug-in per ottenere addirittura anteprime di anteprime (per esempio, la -simulazione del pacchetto di filtri). Questi plug-in possono così -fornire un certo numero di anticipazioni di quel che si otterrebbe applicando -certe opzioni. Un simile approccio funziona come una tavolozza di anteprime, -ed è molto efficace per piccoli cambiamenti! - -Non è finita. Per alcuni plug-in può essere necessario un -intervento umano in tempo reale specifico per ogni immagine. Nel plug-in -SuperNova, ad esempio, vengono chieste le coordinate del centro della -futura supernova. Il modo più semplice per fare questo è -senza dubbio quello di mostrare un'anteprima all'utente chiedendogli di -selezionare interattivamente il centro. - -Infine, un paio di applicazioni tipiche. Le anteprime possono essere usate -anche quando non si sta lavorando con grandi immagini. Per esempio, sono -utili quando si stanno calcolando dei pattern complicati (date un'occhiata -al venerabile plug in ``Diffraction'' e a molti altri!). Altro esempio: -date un'occhiata al plug-in di rotazione della mappa dei colori (in allestimento). -Le anteprime possono anche essere usate per visualizzare in un plug-in -piccoli logo o, addirittura, l'immagine dell'Autore! - -Quando non usare le anteprime - -Le anteprime non vanno usate per grafici, disegni ecc., poiché per -queste cose GDK è molto più veloce. Le anteprime vanno usate -solo per immagini derivate da un'elaborazione! - -Le anteprime possono essere inserite dappertutto. In un vbox, in un hbox, -in una tabella, in un bottone, ecc. Sicuramente però hanno il loro -look migliore se bordate con delle cornici (frame). Le anteprime non hanno -bordi propri e appaiono piatte senza (naturalmente, se quel che si vuole -è proprio un aspetto piatto...). I bordi possono essere creati con -delle cornici. - - [Image][Image] - -Le anteprime sono per molti aspetti simili agli altri widget in GTK (con -tutto ciò che questo implica), con l'eccezione di avere una -caratteristica in più: è necessario che siano riempite con -qualche tipo di immagine! Inizialmente parleremo solo dell'aspetto GTK -delle anteprime e successivamente discuteremo di come riempirle. - -Semplicemente: - -<tscreen><verb> - /* Crea un widget di anteprima, - inizializzane le dimensioni - e visualizzalo */ -GtkWidget *preview; -preview=gtk_preview_new(GTK_PREVIEW_COLOR) - /* Alternativamente: - GTK_PREVIEW_GRAYSCALE);*/ -gtk_preview_size (GTK_PREVIEW (preview), WIDTH, HEIGHT); -gtk_widget_show(preview); -my_preview_rendering_function(preview); -</verb></tscreen> - -Come già detto, le anteprime hanno un buon aspetto dentro le cornici, -quindi: - -<tscreen><verb> -GtkWidget *create_a_preview(int Width, - int Height, - int Colorfulness) -{ - GtkWidget *preview; - GtkWidget *frame; - - frame = gtk_frame_new(NULL); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); - gtk_container_border_width (GTK_CONTAINER(frame),0); - gtk_widget_show(frame); - - preview=gtk_preview_new (Colorfulness?GTK_PREVIEW_COLOR - :GTK_PREVIEW_GRAYSCALE); - gtk_preview_size (GTK_PREVIEW (preview), Width, Height); - gtk_container_add(GTK_CONTAINER(frame),preview); - gtk_widget_show(preview); - - my_preview_rendering_function(preview); - return frame; -} - -</verb></tscreen> - -Questa è una semplice anteprima. Questa funzione restituisce la cornice -``madre'', in modo che sia possibile metterla in qualche altro posto nella vostra -interfaccia. Naturalmente è possibile passare alla routine la cornice -madre come parametro. In molte situazioni, comunque, il contenuto di un'anteprima -viene aggiornato continuamente dall'applicazione; in questi casi potreste -preferire passare alla funzione ``create_a_preview()'' un puntatore -all'anteprima, ottenendone così il controllo dopo. - -Un'avvertimento più importante che potrebbe un giorno risparmiarvi -tanto tempo perso: a volte è preferibile etichettare le anteprime; -ad esempio, è possibile etichettare l'anteprima contenente l'immagine -originale come ``Originale'' e quella contenente l'immagine modificata come -``Modificata''. Potrebbe capitarvi di impacchettare in un vbox l'anteprima -insieme con l'etichetta associata. L'insidia inattesa sta nel fatto che se -l'etichetta è più ampia dell'anteprima (cosa che può -accadere per una varietà di motivi da voi non prevedibili, come il -fatto che la dimensione dell'anteprima viene decisa dinamicamente, o la -dimensione del font), la cornice si espande e non risulta più -perfettamente aderente all'anteprima. Questo stesso problema probabilmente -può verificarsi anche in altre situazioni. - - [Image] - -La soluzione è quella di mettere l'anteprima e l'etichetta in una -tabella 2x1 e di legarle insieme chiamando la funzione gtk_table_attach con -i seguenti parametri (questa è una delle varianti possibili, -naturalmente; l'importante è che non ci sia GTK_FILL nella seconda -gtk_table_attach): - -<tscreen><verb> -gtk_table_attach(GTK_TABLE(table),label,0,1,0,1, - 0, - GTK_EXPAND|GTK_FILL, - 0,0); -gtk_table_attach(GTK_TABLE(table),frame,0,1,1,2, - GTK_EXPAND, - GTK_EXPAND, - 0,0); -</verb></tscreen> - -Ed ecco il risultato: - - [Image] - -Altri suggerimenti - -La maniera più semplice per rendere cliccabile un'anteprima è -quella di metterla dentro un bottone. Questo ha anche l'effetto di aggiungere -un bel bordo attorno all'anteprima, il che rende superfluo metterla in una -cornice. - -Questo è tutto per quel che riguarda GTK. - - -Completare un'anteprima - -Per impratichirci con le basi del completamento delle anteprime, creiamo -il seguente disegno (trovato per tentativi): - - [Image] - -<tscreen><verb> -void -my_preview_rendering_function(GtkWidget *preview) -{ -#define SIZE 100 -#define HALF (SIZE/2) - - guchar *row=(guchar *) malloc(3*SIZE); /* 3 bits per dot */ - gint i, j; /* Coordinates */ - double r, alpha, x, y; - - if (preview==NULL) return; /* Di solito aggiungo questo per */ - /* evitare piantamenti stupidi. */ - /* Probabilmente bisognerebbe */ - /* assicurarsi che tutto sia stato*/ - /* inizializzato con successo */ - for (j=0; j < ABS(cos(2*alpha)) ) { /* Siamo dentro la sagoma? */ - /* glib.h contiene ABS(x). */ - row[i*3+0] = sqrt(1-r)*255; /* Definisce il Rosso */ - row[i*3+1] = 128; /* Definisce il Verde */ - row[i*3+2] = 224; /* Definisce il Blu */ - } /* "+0" è per allineamento */ - else { - row[i*3+0] = r*255; - row[i*3+1] = ABS(sin((float)i/SIZE*2*PI))*255; - row[i*3+2] = ABS(sin((float)j/SIZE*2*PI))*255; - } - } - gtk_preview_draw_row( GTK_PREVIEW(preview),row,0,j,SIZE); - /* Inserisce "row" in "preview" a partire del punto avente */ - /* coordinate (0,j) prima colonna, j-esima riga, per SIZE */ - /* pixel verso destra */ - } - - free(row); /* libera un po' di memoria */ - gtk_widget_draw(preview,NULL); /* indovina cosa fa questo? */ - gdk_flush(); /* e questo? */ -} -</verb></tscreen> -Coloro che non usano GIMP probabilmente hanno già visto abbastanza -per fare molte cose. Per gli utenti GIMP c'è ancora qualcosa da -aggiungere. - -Anteprima dell'immagine - -Probabilmente è opportuno tenere pronta una versione ridotta dell'immagine, -grande quanto basta per riempire l'anteprima. Questo può essere fatto -selezionando un pixel ogni n, dove n è il rapporto tra la dimensione -dell'immagine e la dimensione dell'anteprima. Tutte le operazioni successive -(compreso il riempimento dell'anteprima) sono fatte solo sul ridotto numero -di pixel selezionati. Di seguito è riportata un'implementazione della -riduzione dell'immagine (si tenga presente che ho preso solo lezioni basilari -di C!). - - -(ATTENZIONE: CODICE NON VERIFICATO!!!) - -<tscreen><verb> - -typedef struct { - gint width; - gint height; - gint bbp; - guchar *rgb; - guchar *mask; -} ReducedImage; - -enum { - SELECTION_ONLY, - SELCTION_IN_CONTEXT, - ENTIRE_IMAGE -}; - -ReducedImage *Reduce_The_Image(GDrawable *drawable, - GDrawable *mask, - gint LongerSize, - gint Selection) -{ - /* Questa funzione riduce l'immagine alla dimens. scelta per l'anteprima */ - /* La dimensione dell'anteprima è determinata da LongerSize, cioè la più */ - /* grande delle dimensioni. Funziona solo per immagini RGB! */ - gint RH, RW; /* Altezza ridotta e larghezza ridotta */ - gint width, height; /* Larghezza e altezza dell'area da ridurre */ - gint bytes=drawable->bpp; - ReducedImage *temp=(ReducedImage *)malloc(sizeof(ReducedImage)); - - guchar *tempRGB, *src_row, *tempmask, *src_mask_row,R,G,B; - gint i, j, whichcol, whichrow, x1, x2, y1, y2; - GPixelRgn srcPR, srcMask; - gint NoSelectionMade=TRUE; /* Assumiamo di trattare l'intera immagine */ - - gimp_drawable_mask_bounds (drawable->id, &x1, &y1, &x2, &y2); - width = x2-x1; - height = y2-y1; - /* Se c'è una SELEZIONE, ne abbiamo avuto gli estremi! */ - - if (width != drawable->width && height != drawable->height) - NoSelectionMade=FALSE; - /* Controlliamo se l'utente ha una selezione attiva. Questo */ - /* diventerà importante dopo, alla creazione di una maschera ridotta */ - - /* Se si vuole l'anteprima dell'immagine intera, annulla quanto sopra */ - /* Naturalmente, in assenza di una selezione, questo non cambia nulla */ - if (Selection==ENTIRE_IMAGE) { - x1=0; - x2=drawable->width; - y1=0; - y2=drawable->height; - } - - /* Se si vuole l'anteprima di una selezione con parte dell'area */ - /* circostante bisogna espanderla un po'. */ - if (Selection==SELECTION_IN_CONTEXT) { - x1=MAX(0, x1-width/2.0); - x2=MIN(drawable->width, x2+width/2.0); - y1=MAX(0, y1-height/2.0); - y2=MIN(drawable->height, y2+height/2.0); - } - - /* Così si determinano larghezza e altezza dell'area da ridurre. */ - width = x2-x1; - height = y2-y1; - - /* Le linee seguenti determinano quale dimensione deve essere il */ - /* lato più lungo. L'idea è presa dal plug-in supernova. Ritengo */ - /* che avrei potuto pensarci da solo, ma la verità va detta. */ - /* Brutta cosa il plagio! */ - if (width>height) { - RW=LongerSize; - RH=(float) height * (float) LongerSize/ (float) width; - } - else { - RH=LongerSize; - RW=(float)width * (float) LongerSize/ (float) height; - } - - /* L'intera immagine viene "stirata" in una stringa! */ - tempRGB = (guchar *) malloc(RW*RH*bytes); - tempmask = (guchar *) malloc(RW*RH); - - gimp_pixel_rgn_init (&srcPR, drawable, x1, y1, width, height, FALSE, FALSE); - gimp_pixel_rgn_init (&srcMask, mask, x1, y1, width, height, FALSE, FALSE); - - /* Prendine abbastanza da contenere una riga di immagine e una di maschera */ - src_row = (guchar *) malloc (width*bytes); - src_mask_row = (guchar *) malloc (width); - - for (i=0; i < RH; i++) { - whichrow=(float)i*(float)height/(float)RH; - gimp_pixel_rgn_get_row (&srcPR, src_row, x1, y1+whichrow, width); - gimp_pixel_rgn_get_row (&srcMask, src_mask_row, x1, y1+whichrow, width); - - for (j=0; j < RW; j++) { - whichcol=(float)j*(float)width/(float)RW; - - /* Nessuna selezione = tutti i punti sono completamente selezionati */ - if (NoSelectionMade) - tempmask[i*RW+j]=255; - else - tempmask[i*RW+j]=src_mask_row[whichcol]; - - /* Aggiungi la riga alla lunga stringa che ora contiene l'immagine */ - tempRGB[i*RW*bytes+j*bytes+0]=src_row[whichcol*bytes+0]; - tempRGB[i*RW*bytes+j*bytes+1]=src_row[whichcol*bytes+1]; - tempRGB[i*RW*bytes+j*bytes+2]=src_row[whichcol*bytes+2]; - - /* Mantieni anche la trasparenza (alpha) */ - if (bytes==4) - tempRGB[i*RW*bytes+j*bytes+3]=src_row[whichcol*bytes+3]; - } - } - temp->bpp=bytes; - temp->width=RW; - temp->height=RH; - temp->rgb=tempRGB; - temp->mask=tempmask; - return temp; -} -</verb></tscreen> - - -La seguente è una funzione di anteprima che usa lo stesso tipo -ReducedImage! Si noti che usa una finta trasparenza - se ne è presente -una, tramite fake_transparency che è definita come segue: - -<tscreen><verb> -gint fake_transparency(gint i, gint j) -{ - if ( ((i%20)- 10) * ((j%20)- 10)>0 ) - return 64; - else - return 196; -} - -</verb></tscreen> -E adesso la funzione per l'anteprima: -<tscreen><verb> -void -my_preview_render_function(GtkWidget *preview, - gint changewhat, - gint changewhich) -{ - gint Inten, bytes=drawable->bpp; - gint i, j, k; - float partial; - gint RW=reduced->width; - gint RH=reduced->height; - guchar *row=malloc(bytes*RW);; - - - for (i=0; i < RH; i++) { - for (j=0; j < RW; j++) { - - row[j*3+0] = reduced->rgb[i*RW*bytes + j*bytes + 0]; - row[j*3+1] = reduced->rgb[i*RW*bytes + j*bytes + 1]; - row[j*3+2] = reduced->rgb[i*RW*bytes + j*bytes + 2]; - - if (bytes==4) - for (k=0; k<3; k++) { - float transp=reduced->rgb[i*RW*bytes+j*bytes+3]/255.0; - row[3*j+k]=transp*a[3*j+k]+(1-transp)*fake_transparency(i,j); - } - } - gtk_preview_draw_row( GTK_PREVIEW(preview),row,0,i,RW); - } - - free(a); - gtk_widget_draw(preview,NULL); - gdk_flush(); -} - -Funzioni Applicabili - -guint gtk_preview_get_type (void); -/* No idea */ -void gtk_preview_uninit (void); -/* No idea */ -GtkWidget* gtk_preview_new (GtkPreviewType type); -/* Descritta precedentemente */ -void gtk_preview_size (GtkPreview *preview, - gint width, - gint height); -/* Permette di ridimensionare un'anteprima esistente */ -/* Pare che un bug in GTK renda disordinato questo */ -/* processo. Un modo di rimettere le cose a posto */ -/* è quello di ridimensionare manualmente */ -/* la finestra contenente l'anteprima dopo aver */ -/* ridimensionato l'anteprima. */ - -void gtk_preview_put (GtkPreview *preview, - GdkWindow *window, - GdkGC *gc, - gint srcx, - gint srcy, - gint destx, - gint desty, - gint width, - gint height); -/* No idea */ - -void gtk_preview_put_row (GtkPreview *preview, - guchar *src, - guchar *dest, - gint x, - gint y, - gint w); -/* No idea */ - -void gtk_preview_draw_row (GtkPreview *preview, - guchar *data, - gint x, - gint y, - gint w); -/* Descritta nel testo */ - -void gtk_preview_set_expand (GtkPreview *preview, - gint expand); -/* No idea */ - -/* Nessun indizio per le seguenti, ma dovrebbero */ -/* essere standard per la maggior parte dei widget */ -void gtk_preview_set_gamma (double gamma); -void gtk_preview_set_color_cube (guint nred_shades, - guint ngreen_shades, - guint nblue_shades, - guint ngray_shades); -void gtk_preview_set_install_cmap (gint install_cmap); -void gtk_preview_set_reserved (gint nreserved); -GdkVisual* gtk_preview_get_visual (void); -GdkColormap* gtk_preview_get_cmap (void); -GtkPreviewInfo* gtk_preview_get_info (void); - -E' tutto! - -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1> Curve -<p> - -<!-- ***************************************************************** --> -<sect>Il Widget EventBox<label id="sec_The_EventBox_Widget"> -<!-- ***************************************************************** --> -<p> -Alcuni widget gtk non sono associati a finestre X, sicché -semplicemente disegnano sui loro genitori. Per questo motivo essi non possono -ricevere eventi e se sono sovradimensionati non vengono troncati, ma rischiano -di sovrapporsi, generando confusione. Se si vuole di più da questi -widget si può ricorrere agli EventBox. - -A prima vista il widget EventBox potrebbe sembrare completamente inutile. Non -disegna nulla sullo schermo e non risponde a nessun evento. Tuttavia ha -una funzione: fornire una finestra X al suo widget figlio. Ciò -è importante in quanto molti widget GTK non hanno una finestra X -associata. Se questo da una parte risparmia memoria e migliora le prestazioni, -dall'altra introduce degli svantaggi: un widget senza una finestra X non -può ricevere eventi, e non taglia in alcun modo il suo contenuto. -Sebbene il nome ``EventBox'' (casella di eventi) enfasizzi la funzione di -gestione degli eventi, il widget può essere usato anche per -limitare la dimensione dei widget figli (ma anche per altro: si veda -l'esempio seguente). - -<p> -Per creare un widget di tipo EventBox: - -<tscreen><verb> -GtkWidget* gtk_event_box_new (void); -</verb></tscreen> - -<p> -All'EventBox si può aggiungere un widget figlio: - -<tscreen><verb> -gtk_container_add (GTK_CONTAINER(event_box), widget); -</verb></tscreen> - -<p> -The following example demonstrates both uses of an EventBox - a label -is created that clipped to a small box, and set up so that a -mouse-click on the label causes the program to exit. -Il seguente esempio mostra entrambi gli usi di un EventBox - si crea -un'etichetta limitata da un rettangolo piccolo, fatta in modo che -cliccando con il mouse su di essa il programma termina. - -<tscreen><verb> -/* eventbox.c */ - -#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); - - /* Crea un EventBox e lo aggiunge alla finestra principale */ - - event_box = gtk_event_box_new (); - gtk_container_add (GTK_CONTAINER(window), event_box); - gtk_widget_show (event_box); - - /* Crea una etichetta lunga */ - - label = gtk_label_new ("Click here to quit, quit, quit, quit, quit"); - gtk_container_add (GTK_CONTAINER (event_box), label); - gtk_widget_show (label); - - /* Limitane le dimensioni */ - gtk_widget_set_usize (label, 110, 20); - - /* E collega ad essa una azione */ - 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); - - /* Un'altra cosa per cui si ha bisogno di una finestra 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; -} -</verb></tscreen> - -<!-- ***************************************************************** --> -<sect>Selezionare gli Attributi dei Widget<label id="sec_setting_widget_attributes"> -<!-- ***************************************************************** --> -<p> -Qui si descrivono le funzioni per la gestione dei widget. Esse possono essere -usate per impostarne lo stile, il padding, le dimensioni, ... - -(Forse andrebbe fatta un'intera sezione sugli acceleratori). - -<tscreen><verb> -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); -</verb></tscreen> - - -<!-- ***************************************************************** --> -<sect>Funzioni periodiche, di I/O e di attesa<label id="sec_timeouts"> -<!-- ***************************************************************** --> -<p> -<!-- ----------------------------------------------------------------- --> -<sect1>Funzioni periodiche -<p> -Probabilmente vi sarete chiesti come far fare qualcosa di utile a GTK -durante la chiamata alla gtk_main(). Ci sono diverse possibilità. -Usando le seguenti funzioni si possono creare funzioni che vengono chiamate -periodicamente. - -<tscreen><verb> -gint gtk_timeout_add (guint32 interval, - GtkFunction function, - gpointer data); -</verb></tscreen> - -Il primo argomento è il numero di millisecondi tra le chiamate alla -funzione. Il secondo è la funzione periodica, mentre il terzo -rappresenta i dati che vengono passati alla funzione. Il valore restituito -è un'etichetta che può essere utilizzata per fermare la chiamata -periodica, passandolo alla funzione: - -<tscreen><verb> -void gtk_timeout_remove (gint tag); -</verb></tscreen> - -La chiamata periodica si ferma anche se la funzione periodica ritorna zero -o FALSE. Naturalmente questo vuol dire che se si vuole che la funzione periodica -continui ad essere richiamata, essa deve restituire un valore non nullo, -cioè TRUE. - -La dichiarazione della funzione periodica dovrebbe essere come questa: - -<tscreen><verb> -gint timeout_callback (gpointer data); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Controllo dell'I/O -<p> -Un'altra utile caratteristica di GTK è la possibilità di fargli -controllare che siano verificate certe condizioni su un descrittore di file -(come quelli restituiti da open(2) o socket(2)). Questo è utile in -particolar modo per le applicazioni di rete. La funzione è la seguente: - -<tscreen><verb> -gint gdk_input_add (gint source, - GdkInputCondition condition, - GdkInputFunction function, - gpointer data); -</verb></tscreen> - -Il primo argomento è il descrittore che si desidera venga controllato, -mentre il secondo specifica quale condizione si vuole che GDK controlli. -Questa può essere una tra: -<p> -GDK_INPUT_READ - Chiama la funzione quando ci sono dati pronti per la lettura -nel descrittore di file. -<p> -GDK_INPUT_WRITE - Chiama la funzione quando il descrittore di file è -pronto per la scrittura. -<p> -Come sicuramente avrete già intuito, il terzo parametro è la -funzione da chiamare quando la condizione specificata è soddisfatta, -mentre il quarto rappresenta i dati da passare a questa funzione. -<p> -Il valore di ritorno è un etichetta che può essere usata per -fermare il controllo di GDK sul descrittore di file, usando la seguente -funzione: -<p> -<tscreen><verb> -void gdk_input_remove (gint tag); -</verb></tscreen> -<p> -La funzione da richiamare va dichiarata così: -<p> -<tscreen><verb> -void input_callback (gpointer data, gint source, - GdkInputCondition condition); -</verb></tscreen> -<p> - -<!-- ----------------------------------------------------------------- --> -<sect1>Funzioni di attesa (``Idle'') -<p> -Cosa fare se si ha una funzione che si vuole venga chiamata quando non -sta accadendo nient'altro? - -<tscreen><verb> -gint gtk_idle_add (GtkFunction function, - gpointer data); -</verb></tscreen> - -Questa fa si che GDK chiami la funzione specificata quando non c'è -nessuna altra operazione in corso. - -<tscreen><verb> -void gtk_idle_remove (gint tag); -</verb></tscreen> -<p> -Non ci soffermeremo sul significato dei parametri in quanto del tutto analoghi -ai precedenti. La funzione puntata dal primo argomento della gtk_idle_add -viene chiamata non appena se ne presenta l'opportunità; come -negli altri casi, se essa restituisce FALSE non viene più chiamata. - -<!-- ***************************************************************** --> -<sect>La gestione delle selezioni -<!-- ***************************************************************** --> - -<!-- ----------------------------------------------------------------- --> -<sect1> Overview - -<p> - -Le <em>selezioni</em> sono un tipo di comunicazione tra processi -supportato da GTK. Una selezione identifica un frammento di dati; per -esempio, una porzione di testo selezionata dall'utente in qualche modo, -magari con il mouse. Su un display solo un'applicazione alla volta -(il <em>proprietario</em>) puó essere proprietaria di una -particolare selezione, sicché quando un'applicazione richiede -una selezione il precedente proprietario deve comunicare all'utente che -la selezione è stata ceduta. Altre applicazioni possono richiedere -il contenuto di una selezione in diverse forme, chiamate <em>obiettivi</em>. -Ci può essere un numero qualsiasi di selezioni, ma la maggior parte -delle applicazioni X può gestirne solo una, la <em>selezione -primaria</em>. - -<p> -Nella maggior parte dei casi per una applicazione GTK non è -necessario gestire esplicitamente le selezioni. I widget standard, -come quello di Ingresso, hanno già la capacità di -chiedere la selezione se necessario (p. e., quando l'utente -seleziona sul testo), e di recuperare il contenuto di una selezione -di un altro widget o di un'altra applicazione (p. e., quando l'utente -clicca il tasto centrale del mouse). Ci possono comunque essere dei -casi nei quali si vuole dare ad altri widget la capacità di -fornire la selezione, o si vogliono recuperare degli obiettivi non -supportati direttamente. - -<p> -Un concetto fondamentale necessario per comprendere la gestione delle -selezioni è quello di <em>atomo</em>. Un atomo è un intero -che identifica univocamente una stringa (su un certo display). -Certi atomi sono predefiniti dal server X, e in alcuni casi in <tt>gtk.h</tt> -ci sono costanti corrispondenti a questi atomi. Per esempio, la costante -<tt>GDK_PRIMARY_SELECTION</tt> corrisponde alla stringa ``PRIMARY''. -Negli altri casi bisogna usare le funzioni <tt>gdk_atom_intern()</tt> -per ottenere l'atomo corrispondente ad una stringa, e <tt>gdk_atom_name()</tt> -per ottenere il nome di un atomo. Sia le selezioni sia gli obiettivi sono -identificati da atomi. -<!-- ----------------------------------------------------------------- --> -<sect1> Recuperare le selezioni - -<p> - -Il recupero di una selezione è un processo asincrono. Per iniziare -il processo, si chiama: -<tscreen><verb> -gint gtk_selection_convert (GtkWidget *widget, - GdkAtom selection, - GdkAtom target, - guint32 time) -</verb</tscreen> - -Questo <em>converte</em> la selezione nella forma specificata -dall'obiettivo <tt/target/. Se possibile, il campo <tt/time/ -dovrebbe essere il tempo dell'evento che ha attivato la selezione. -Questo aiuta a far si che gli eventi avvengano nell'ordine in cui -l'utente li ha richiesti. Se comunque non fosse disponibile (per -esempio, se la conversione è stata attivata da un segnale di -``cliccato''), allora si può usare la costante -<tt>GDK_CURRENT_TIME</tt>. - -<p> -Quando il proprietario di una selezione risponde ad una richiesta, -un segnale ``selection_received'' (selezione ricevuta) viene inviato -alla vostra applicazione. Il gestore di questo segnale riceve un -puntatore ad una struttura <tt>GtkSelectionData</tt>, che è -definita nel modo seguente: -<tscreen><verb> -struct _GtkSelectionData -{ - GdkAtom selection; - GdkAtom target; - GdkAtom type; - gint format; - guchar *data; - gint length; -}; -</verb></tscreen> -<tt>selection</tt> e <tt>target</tt> sono i valori da voi specificati -nella chiamata <tt>gtk_selection_convert()</tt>. <tt>type</tt> è -un atomo che identifica il tipo di dati restituiti dal proprietario della -selezione. Alcuni valori possibili sono ``STRING'', una stringa di -caratteri latin-1, ``ATOM'', una serie di atomi, ``INTEGER'', un intero, ecc. -La maggior parte degli obiettivi può restituire solo un tipo. -<tt/format/ ci dà la lunghezza delle unità (per esempio caratteri) -in bit. Di solito, quando si ricevono i dati non ci si cura di questo. -<tt>data</tt> è un puntatore ai dati restituiti, e <tt>length</tt> -è la lunghezza dei dati restituiti, in byte. Se <tt>length</tt> -è negativo allora si è verificato un errore e non è -stato possibile recuperare la selezione. Questo può avvenire se -nessuna applicazione era proprietaria della selezione, o se si è -richiesto un obiettivo non supportato dall'applicazione. Viene garantito -che il buffer sia un byte più lungo di <tt>length</tt>; il byte -in più sarà sempre zero, in modo che non sia necessario -ricopiare le stringhe solo per farle terminare con zero. - -<p> -Nell'esempio che segue viene recuperato l'obiettivo speciale ``TARGETS'', -che è una lista di tutti gli obiettivi in cui può essere -convertita la selezione. -<tscreen><verb> -/* gettargets.c */ - -#include <gtk/gtk.h> - -void selection_received (GtkWidget *widget, - GtkSelectionData *selection_data, - gpointer data); - -/* Gestore di segnale chiamato quando l'utente clicca nel bottone */ -/* "Get Targets" */ -void -get_targets (GtkWidget *widget, gpointer data) -{ - static GdkAtom targets_atom = GDK_NONE; - - /* Prende l'atomo corrispondente alla stringa "TARGETS" */ - if (targets_atom == GDK_NONE) - targets_atom = gdk_atom_intern ("TARGETS", FALSE); - - /* E richiede l'obiettivo "TARGETS" per la selezione primaria */ - gtk_selection_convert (widget, GDK_SELECTION_PRIMARY, targets_atom, - GDK_CURRENT_TIME); -} - -/* Gestore di segnale chiamato quando il proprietario della selezione */ -/* restituisce i dati */ -void -selection_received (GtkWidget *widget, GtkSelectionData *selection_data, - gpointer data) -{ - GdkAtom *atoms; - GList *item_list; - int i; - - /* **** IMPORTANTE **** Controlla che il recupero sia riuscito */ - if (selection_data->length < 0) - { - g_print ("Selection retrieval failed\n"); - return; - } - /* Make sure we got the data in the expected form */ - if (selection_data->type != GDK_SELECTION_TYPE_ATOM) - { - g_print ("Selection \"TARGETS\" was not returned as atoms!\n"); - return; - } - - /* Stampa gli atomi ricevuti */ - 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); - - /* Create the toplevel window */ - - 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); - - /* Crea un bottone che l'utente può cliccare per ottenere gli obiettivi */ - - 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; -} -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1> Fornire una selezione - -<p> -Fornire la selezione è un po' più complicato. Bisogna -registrare i gestori che verranno chiamati quando viene richiesta la -propria selezione. Per ogni coppia selezione/obiettivo che si gestirà -occorre una chiamata a: - -<tscreen><verb> -void gtk_selection_add_handler (GtkWidget *widget, - GdkAtom selection, - GdkAtom target, - GtkSelectionFunction function, - GtkRemoveFunction remove_func, - gpointer data); -</verb></tscreen> - -<tt/widget/, <tt/selection/, e <tt/target/ identificano le richieste -che questo gestore soddisferà. <tt/remove_func/, se non è -NULL, verrà chiamato quando il gestore di segnale viene rimosso. -Questo è utile, per esempio, per linguaggi interpretati ai quali -serve di tener traccia di un conteggio di riferimento per <tt/data/. - -<p> -La funzione di richiamo ha la forma: - -<tscreen><verb> -typedef void (*GtkSelectionFunction) (GtkWidget *widget, - GtkSelectionData *selection_data, - gpointer data); - -</verb></tscreen> - -La GtkSelectionData è la stessa di prima, ma stavolta siamo -responsabili di riempire i campi <tt/type/, <tt/format/, <tt/data/, -e <tt/length/. (Il campo <tt/format/ qui è effettivamente -importante - il server X lo usa per capire se occorre che i byte -dei dati vengano scambiati o no. Di solito sarà 8 - cioè -un carattere - o 32 - cioè un intero.) Questo viene fatto -chiamando la funzione: - -<tscreen><verb> -void gtk_selection_data_set (GtkSelectionData *selection_data, - GdkAtom type, - gint format, - guchar *data, - gint length); -</verb></tscreen> -Questa funzione si prende cura di fare propriamente una copia dei dati -in modo che non ci si debba preoccupare di conservarli (è opportuno -evitare di riempire a mano i campi della struttura GtkSelectionData). - -<p> -Quando richiesto dall'utente, richiederete la proprietà della selezione -chiamando: - -<tscreen><verb> -gint gtk_selection_owner_set (GtkWidget *widget, - GdkAtom selection, - guint32 time); -</verb></tscreen> - -Se un'altra applicazione richiede la proprietà della selezione, -riceverete un evento di azzeramento della selezione (``selection_clear_event''). - -Come esempio di fornitura della selezione, il programma seguente aggiunge -la funzionalità di selezione a un bottone di attivazione. Quando il -bottone viene premuto, il programma richiede la selezione primaria. -L'unico obiettivo supportato (oltre a certi obiettivi come ``TARGETS'' -fornito dalla stessa GTK) è l'obiettivo ``STRING''. Quando viene -richiesto questo obiettivo, viene restituita una rappresentazione stringa -del tempo. - -<tscreen><verb> -/* setselection.c */ - -#include <gtk/gtk.h> -#include <time.h> - -/* Richiamata quando l'utente attiva la selezione */ -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); - /* se il richiamo della selezione è fallito, si riporta il - bottone nello stato non premuto */ - if (!*have_selection) - gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON(widget), FALSE); - } - else - { - if (*have_selection) - { - /* Prima di annullare la selezione mettendone a NULL il proprietario, - controlliamo se siamo i veri proprietari */ - if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window) - gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY, - GDK_CURRENT_TIME); - *have_selection = FALSE; - } - } -} - -/* Chiamata quando un'altra applicazione richiede la selezione */ -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; -} - -/* Fornisce come selezione il tempo attuale */ -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)); - /* Quando si restituisce una singola stringa, non occorre che finisca - con NULL. Questo verrà fatto automaticamente */ - - 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); - - /* Crea la finestra di livello superiore */ - - 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); - - /* Crea un bottone a commutazione che agisce come la selezione */ - - 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); - - gtk_widget_show (selection_button); - gtk_widget_show (window); - - gtk_main (); - - return 0; -} -</verb></tscreen> - -<!-- ***************************************************************** --> -<sect>La glib<label id="sec_glib"> -<!-- ***************************************************************** --> -<p> -La glib fornisce molte funzioni e definizioni utili pronte all'uso quando si -creano applicazioni GDK e GTK. Qui verranno elencate tutte, con una -breve spiegazione. Molte sono duplicati delle funzioni standard della libc, -e quindi per queste non si scenderà nei dettagli. Questa vuole essere una -lista di riferimento, in modo che si sappia cosa è possibile usare. - -<!-- ----------------------------------------------------------------- --> -<sect1>Definizioni -<p> -Le definizioni per gli estremi di molti dei tipi standard sono: - -<tscreen><verb> -G_MINFLOAT -G_MAXFLOAT -G_MINDOUBLE -G_MAXDOUBLE -G_MINSHORT -G_MAXSHORT -G_MININT -G_MAXINT -G_MINLONG -G_MAXLONG -</verb></tscreen> - -Ci sono anche le seguenti definizioni di tipo. Quelle rimaste non specificate -sono dipendenti dall'architettura. Si ricordi di evitare di fare affidamento -sulla dimensione di un puntatore se si vuole la portabilità! P.e., un puntatore -su un Alpha è lungo 8 byte, ma 4 su un Intel. - -<tscreen><verb> -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 -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Liste a doppio collegamento -<p> -le seguenti funzioni sono usate per creare, gestire e distruggere liste a -doppio collegamento. Si assume che il lettore sappia già cosa sono le liste -collegate (linked list), poiché descriverle è fuori dagli scopi di -questo documento. Naturalmente non è necessario conoscerle per l'uso -generale di GTK, per quanto conoscerle sia comunque interessante. - -<tscreen><verb> -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); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Liste a collegamento singolo -<p> -Molte delle funzioni per le liste a collegamento singolo sono identiche alle -precedenti. Eccone una lista completa: -<tscreen><verb> -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); - -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Gestione della memoria -<p> -<tscreen><verb> -gpointer g_malloc (gulong size); -</verb></tscreen> - -Questa è una sostituta di malloc(). Non occorre controllare il valore -restituito, in quanto lo fa già questa funzione. - -<tscreen><verb> -gpointer g_malloc0 (gulong size); -</verb></tscreen> - -Come la precedente, ma la memoria viene azzerata prima di restituire un -puntatore ad essa. - -<tscreen><verb> -gpointer g_realloc (gpointer mem, - gulong size); -</verb></tscreen> - -Riloca ``size'' byte di memoria che inizia a ``mem''. Ovviamente, la memoria -dovrebbe essere stata allocata precedentemente. - -<tscreen><verb> -void g_free (gpointer mem); -</verb></tscreen> - -Libera la memoria. Facile! - -<tscreen><verb> -void g_mem_profile (void); -</verb></tscreen> - -Emette un profilo della memoria usata, ma occorre ricompilare e reinstallare -la libreria aggiungendo #define MEM_PROFILE all'inizio del file glib/gmem.c. - -<tscreen><verb> -void g_mem_check (gpointer mem); -</verb></tscreen> - -Controlla che una locazione di memoria sia valida. Occorre ricompilare e -reinstallare la libreria aggiungendo #define MEM_CHECK all'inizio del file -gmem.c. - -<!-- ----------------------------------------------------------------- --> -<sect1>Timer -<p> -Funzioni legate ai timer... - -<tscreen><verb> -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); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Gestione delle stringhe -<p> -Un'accozzaglia di funzioni per la gestione delle stringhe. Sembrano tutte molto -interessanti, e probabilmente migliori per molte caratteristiche delle funzioni -standard del C per le stringhe, ma necessitano di documentazione. - -<tscreen><verb> -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, - ...); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Funzioni d'utilità e di errore -<p> -<tscreen><verb> -gchar* g_strdup (const gchar *str); -</verb></tscreen> - -Funzione sostitutiva della strdup. Copia i contenuti originari delle stringhe -in memoria appena allocata, restituendo un puntatore ad essa. - -<tscreen><verb> -gchar* g_strerror (gint errnum); -</verb></tscreen> -Si raccomanda di usare questa gunzione per tutti i messaggi di errore. E' molto -più graziosa, e più portabile di perror() o di altre. L'output di solito ha la -forma: - -<tscreen><verb> -nome programma:funzione fallita:file o altre descrizioni:strerror -</verb></tscreen> - -Di seguito un esempio di una chiamata di questo tipo usata nel nostro -programma Hello World: - -<tscreen><verb> -g_print("hello_world:open:%s:%s\n", filename, g_strerror(errno)); -</verb></tscreen> - -<tscreen><verb> -void g_error (gchar *format, ...); -</verb></tscreen> - -Visualizza un messaggio di errore. Il formato è come quello di printf, -ma prepone ``** ERROR **: '' al messaggio e termina il programma. Da usare solo -per errori gravi. - -<tscreen><verb> -void g_warning (gchar *format, ...); -</verb></tscreen> - -Come la precedente, ma prepone ``** WARNING **: '' e non termina il programma. - -<tscreen><verb> -void g_message (gchar *format, ...); -</verb></tscreen> - -Visualizza ``message: '' e poi il messaggio. - -<tscreen><verb> -void g_print (gchar *format, ...); -</verb></tscreen> - -Sostituta di printf(). - -L'ultima funzione: - -<tscreen><verb> -gchar* g_strsignal (gint signum); -</verb></tscreen> - -Visualizza il nome del messaggio del sistema Unix associato al numero di -segnale. Utile nelle funzioni generiche di gestione dei segnali. - -Tutte le funzioni elencate sono più o meno prese da glib.h. Se qualcuno volesse -documentare qualche funzione, mandi una email all'autore! - -<!-- ***************************************************************** --> -<sect>I file rc di GTK -<!-- ***************************************************************** --> - -<p> -GTK ha un suo modo di trattare le preferenze delle applicazioni, usando -i file rc. Questi possono essere usati per scegliere i colori di quasi tutti -i widget, e possono anche essere usati per inserire delle pixmap nello sfondo -di alcuni widget. - -<!-- ----------------------------------------------------------------- --> -<sect1>Funzioni per i file rc -<p> -All'inizio della vostra applicazione dovrebbe esserci una chiamata a -<tscreen><verb> -void gtk_rc_parse (char *filename); -</verb></tscreen> -<p> -passando come parametro il nome del vostro file rc. Questo farà si che GTK -analizzi tale file e usi le impostazioni di stile per i tipi di widget ivi -definite. -<p> -Se si desidera avere un insieme speciale di widget che abbia uno stile diverso -dagli altri, o qualsiasi altra divisione logica dei widget, si chiami -<tscreen><verb> -void gtk_widget_set_name (GtkWidget *widget, - gchar *name); -</verb></tscreen> -<p> -passando un widget appena creato come primo argomento, e il nome che gli si -vuole dare come secondo. Questo consentirà di cambiare gli attributi di -questo widget per nome tramite il file rc. -<p> -Effettuando una chiamata come questa: - -<tscreen><verb> -button = gtk_button_new_with_label ("Special Button"); -gtk_widget_set_name (button, "special button"); -</verb></tscreen> -<p> -allora a questo bottone viene dato il nome ``special button'' ed esso può essere -riferito per nome nel file rc come ``special button.GtkButton''. [<--- Verificatemi!] -<p> -Il seguente esempio di file rc imposta le proprietà della finestra principale, -e fa si che tutti i figli di questa finestra ereditino lo stile descritto -dallo stile ``main button''. Il codice usato nell'applicazione è: - -<tscreen><verb> -window = gtk_window_new (GTK_WINDOW_TOPLEVEL); -gtk_widget_set_name (window, "main window"); -</verb></tscreen> -<p> -Lo stile viene definito nel file rc usando: - -<tscreen><verb> -widget "main window.*GtkButton*" style "main_button" -</verb></tscreen> -<p> -che assegna a tutti i widget GtkButton nella finestra principale lo stile -``main_buttons'' secondo la definizione data nel file rc. -<p> -Come si può vedere, questo sistema è molto potente e flessibile. Usate la -vostra immaginazione per trarre il massimo vantaggio da esso. - -<!-- ----------------------------------------------------------------- --> -<sect1>Il formato dei file rc di GTK -<p> -Nell'esempio che segue viene illustrato il formato del file GTK. Si tratta -del file testgkrc dalla distribuzione del GTK, a cui sono stati aggiunti -vari commenti e varie cose. Potete includere questa spiegazione nella -vostra applicazione per consentire all'utente di personalizzarla finemente. -<p> -There are several directives to change the attributes of a widget. -Ci sono diverse direttive per cambiare gli attributi di un widget. -<itemize> -<item>fg - Assegna il colore di primo piano di un widget. -<item>bg - Assegna il colore di sfondo di un widget. -<item>bg_pixmap - Inserisce nello sfondo di un widget una pixmap. -<item>font - Sceglie il font da usarsi con il dato widget. -</itemize> -<p> -Inoltre ci sono diversi stati in cui può trovarsi un widget, e si possono -assegnare diversi colori, pixmap e font per ogni stato. Essi sono: -<itemize> -<item>NORMAL - Lo stato normale di un widget, quando il mouse non si trova su -di esso, quando non è premuto, ecc. -<item>PRELIGHT (evidenziato)- Quando il mouse si trova sopra al widget -verranno usati i colori assegnati per questo stato. -<item>ACTIVE (attivo) - Quando il widget è premuto o cliccato esso sarà attivo, -e verranno usati gli attributi assegnati da questa etichetta. -<item>INSENSITIVE (insensibile)- Quando un widget viene reso insensibile, -e non può essere attivato, prenderà questi attributi. -<item>SELECTED (selezionato) - Quando un oggetto viene selezionato, prende -questi attributi. -</itemize> -<p> -Quando si usano le parole chiave ``fg'' e ``bg'' per assegnare i colori dei -widget il formato è: -<tscreen><verb> -fg[<STATE>] = { Rosso, Verde, Blu } -</verb></tscreen> -<p> -Dove STATE è uno degli stati visti prima (PRELIGHT, ACTIVE ecc.), e Rosso, -Verde e Blu sono valori nell'intervallo 0 - 1.0; { 1.0, 1.0, 1.0 } rappresenta -il bianco. -Devono essere in formato float, o verranno visti come 0, sicché un ``1'' diretto -non funziona, deve essere ``1.0''. Uno ``0'' diretto va invece bene, poiché poco -importa se non viene riconosciuto: valori non riconosciuti vengono considerati -0. -<p> -bg_pixmap è molto simile al precedente, tranne per i colori che vengono -sostituiti dal nome di un file. - -pixmap_path è una lista di percorsi separati da ``:''. In questi percorsi vengono -cercate le pixmap specificate. -<p> -La direttiva font è semplicemente: -<tscreen><verb> -font = "<font name>" -</verb></tscreen> -<p> -dove l'unica parte complicata è immaginare la stringa del font. Allo scopo -può servire usare xfontsel o una utilità analoga. -<p> -``widget_class'' assegna lo stile di una classe di widget. Queste classi sono -elencate nell'introduzione ai widget sulla gerarchia delle classi. -<p> -La direttiva ``widget'' assegna un insieme di widget dal nome specificato ad -un dato stile, annullando qualsiasi stile assegnato per la data classe di widget. -Questi widget vengono registrati nell'applicazione usando la chiamata -gtk_widget_set_name(). Questo consente di specificare gli attributi di un -widget singlarmente, piuttosto che assegnando gli attributi di un'intera classe -di widget. E' opportuno documentare tutti questi widget speciali in modo che -gli utenti possano personalizzarli. -<p> -Quando la parola chiave ``<tt>parent</>'' viene usata come un attributo, il -widget erediterà gli attributi del suo genitore nell'applicazione. -<p> -Quando si definisce uno stile si possono assegnare gli attributi di uno -stile definito precedentemente a quello nuovo. -<tscreen><verb> -style "main_button" = "button" -{ - font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*" - bg[PRELIGHT] = { 0.75, 0, 0 } -} -</verb></tscreen> -<p> -Questo esempio prende lo stile ``button'' e crea un nuovo stile -semplicemente cambiando il font e il colore di sfondo dello stato ``prelight'' -nello stile ``button''. -<p> -Naturalmente, molti di questi attributi non sono applicabili a tutti i widget. -E' veramente un semplice problema di buon senso. Tutto quello che potrebbe -applicarsi, dovrebbe. - -<!-- ----------------------------------------------------------------- --> -<sect1>Esempio di file rc -<p> - -<tscreen><verb> -# 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> - - -# Ecco una lista di tutti gli stati possibili. Si noti che alcuni non sono -# applicabili a certi widget. -# -# NORMAL - Lo stato normale di un widget, quando il mouse non si trova su -# di esso, quando non è premuto, ecc. -# -# PRELIGHT (evidenziato)- Quando il mouse si trova sopra al widget -# verranno usati i colori assegnati per questo stato. -# -# ACTIVE (attivo) - Quando il widget è premuto o cliccato esso sarà attivo, -# e verranno usati gli attributi assegnati da questa etichetta. -# -# INSENSITIVE (insensibile)- Quando un widget viene reso insensibile, -# e non può essere attivato, prenderà questi attributi. -# -# SELECTED (selezionato) - Quando un oggetto viene selezionato, prende -# questi attributi. -# -# Dati questi stati, è possibile assegnare gli attributi dei widget in -# ognuno di questi stati usando le seguenti direttive. -# -# fg - Assegna il colore di primo piano di un widget. -# bg - Assegna il colore di sfondo di un widget. -# bg_pixmap - Inserisce nello sfondo di un widget una pixmap. -# font - Sceglie il font da usarsi con il dato widget. -# - -# Questo è uno stile chiamato "button". Il nome non è veramente importante, -# in quanto viene assegnato ai veri widget alla fine del file. - -style "window" -{ - # Questo inserisce nella spaziatura attorno alla finestra la pixmap - # specificata. - #bg_pixmap[<STATE>] = "<pixmap filename>" - bg_pixmap[NORMAL] = "warning.xpm" -} - -style "scale" -{ - # Mette il colore di primo piano (il colore del font) a rosso nello - # stato "NORMAL". - - fg[NORMAL] = { 1.0, 0, 0 } - - # Inserisce nello sfondo del gadget la stessa pixmap usata dal suo genitore. - bg_pixmap[NORMAL] = "<parent>" -} - -style "button" -{ - # Questo mostra tutti i possibili stati per un bottone. L'unico che - # non è applicabile è lo stato "SELECTED". - - 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 } -} - -# In questi esempio ereditiamo gli attributi dello stile "button" e poi -# alteriamo il font e il colore di sfondo quando evidenziato per creare -# un nuovo stile "main_button". - -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 } - - # Questo seleziona come pixmap di sfondo per il toggle_button quella del - # suo widget genitore (definita nell'applicazione). - 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" - -# Queste assegnano ai tipi di widget gli stili definiti prima. -# I tipi di widget sono elencati nella gerarchia delle classi, ma probabilmente -# dovrebbero essere elencati in questo documento come riferimento per l'utente. - -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" - -# Questo assegna lo stile main_button a tutti i bottoni che sono figli della -# "main window" (finestra principale). Questi devono essere documenati per -# potersene avvantaggiare. -widget "main window.*GtkButton*" style "main_button" -</verb></tscreen> - - -<!-- ***************************************************************** --> -<sect>Scrivere un proprio Widget -<!-- ***************************************************************** --> - -<!-- ----------------------------------------------------------------- --> -<sect1> Panoramica -<p> -Anche se la distribuzione GTK contiene molto tipi di widget che possono -coprire molte necessità basilari, può essere necessario costruirsi -un proprio widget. GTK usa molto l'ereditarietà tra i vari -widget e, di solito, vi è un widget che si avvicina a quello che ti -servirebbe, ed è spesso possibile creare un nuovo widget con poche linee -di codice. Ma prima di iniziare il lavoro su un nuovo widget, vediamo -se qualcuno non lo ha già creato. Questo eviterà un duplicazione -di lavoro e farà sì che i widget non-GTK puri siano minimi, così da -aiutare sia chi crea il codice che chi l'interfaccia per applicazioni GTK -molto grosse. D'altra parte, quando hai finito di scrivere un widget, -annuncialo a tutto il mondo così che le altre persone ne possano -beneficiare. Il miglioro modo dove farlo è la <tt>gtk-list</tt>. - -I sorgenti completi per i widget di esempio possono essere presi dallo stesso -sito da cui avete scaricato questo tutorial, oppure da: - -<htmlurl url="http://www.msc.cornell.edu/~otaylor/gtk-gimp/tutorial" -name="http://www.msc.cornell.edu/~otaylor/gtk-gimp/tutorial"> - - -<!-- ----------------------------------------------------------------- --> -<sect1> L'anatomia di un widget - -<p> -Per creare un nuovo widget è importante aver capito come gli ogetti -di GTK lavorano. Questa sezione è solo una breve spiegazione. Guarda la -documentazione di riferimento per maggiori dettagli. - -<p> -I widget GTK sono implementati in un modo orientato agli oggetti, -anche se usando il C standard. Questo aumenta notevolmente la portabilità -e la stabilità, specialmente per le correnti generazioni di compilatori C++; -comunque questo significa che chi scrive un widget deve fare attenzione -ad alcuni dettagli di implementazione. L'informazione comune a tutte le -istanze di una classe di widget (ad esempio: a tutti i bottoni) è memorizzata -<em>class structure</em>. C'e' solamente una copia di questo in cui -sono memorizzate le informazioni riguardanti i segnali della classe -(assomiglia ad una funzione virtuale in C). Per supportare l'ereditarietà -il primo campo della struttura di una classe deve essere una copia della -struttura della classe genitore. La dichiarazione della struttura della -classe GtkButton è: - -<tscreen><verb> -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); -}; -</verb></tscreen> - -<p> -Quando un bottone viene trattato come un contenitore (ad esempio quando viene -ridimensionato) si può fare il cast della struttura della sua classe con la -GtkContainerClass, e usare i campi rilevanti per gestire i segnali. - -<p> -C'è anche una struttura per ogni widget che viene creata -ad ogni istanza. Questa struttura ha campi per -memorizzare le informazioni che sono differenti per ogni volta che il widget -viene istanziato. Chiameremo questa struttura la <em> struttura -oggetto</em>. Per la classe Bottone, questa ha l'aspetto: - -<tscreen><verb> -struct _GtkButton -{ - GtkContainer container; - - GtkWidget *child; - - guint in_button : 1; - guint button_down : 1; -}; -</verb></tscreen> - -<p> -Si noti che, similmente alla struttura della classe, il primo campo -è la struttura dell'oggetto della classe madre, così che, se necessario, si può fare il -cast di questa struttura con quella dell'oggetto della classe madre. - -<!-- ----------------------------------------------------------------- --> -<sect1> Creare un Widget composto - -<!-- ----------------------------------------------------------------- --> -<sect2> Introduzione - -<p> -Un tipo di widget a cui potreste essere interessati è un widget che -è semplicemnte un aggregato di altri widget GTK. Questo tipo di -widget non fa nulla che non possa essere fatto creando un nuovo -widget, ma fornisce un modo conveniente per inscatolare elementi -dell'interfaccia utente per poi riutilizzarli. -I widget FileSelection e ColorSelection della ditribuzione standard -sono esempi di questo tipo di widget. - -<p> -Il widget di esempio che creeremo in questo capitolo è il -Tictactoe, un vettore 3x3 di bottoni a commutazione il quale emette -un segnale quando tutti e 3 i bottoni di una riga, colonna o di una -diagonale sono premuti. - -<!-- ----------------------------------------------------------------- --> -<sect2> Scegliere la classe madre - -<p> -La classe madre per un widget composto e' tipicamente la classe -contenitrice che racchiude tutti gli elementi del widget composto. -Per esempio, la classe madre del widget FileSelection è la classe -Dialog. Visto che i nostri bottoni sono inseriti in una tabella, è -naturale pensare che la nostra classe madre possa essere la GtkTable. -Sfortunatamente, così non è. La creazione di un widget è diviso -tra 2 funzioni : la funzione <tt/WIDGETNAME_new()/ che viene invocata -dall'utente, e la funzione <tt/WIDGETNAME_init()/ che ha il compito -principale di inizializzare il widget che è indipendente dai valori -passati alla funzione <tt/_new()/. Widget figli o discendenti possono -chiamare, solamente, la funzione del loro widget genitore. -Ma questa divisione del lavoro non funziona bene per la tabella, la -quale, quando creata, necessita di conoscere il numero di righe e -colonne che la comporrà. A meno che non vogliamo duplicare molte delle -fuinzionalità della <tt/gtk_table_new()/ nel nostro widget -Tictactoe, faremmo meglio a evitare di derivarlo dalla GtkTable. Per questa -ragione lo deriviamo invece da GtkVBox, e uniamo la nostra tabella -dentro il VBox. - -<!-- ----------------------------------------------------------------- --> -<sect2> Il File Header - -<p> -Ogni classe di widget ha un file header il quale dichiara l'oggetto e la -struttura della classe del widget, comprese le funzioni pubbliche. -Per prevenire duplicati di definizioni, noi includiamo l'intero file header fra: - -<tscreen><verb> -#ifndef __TICTACTOE_H__ -#define __TICTACTOE_H__ -. -. -. -#endif /* __TICTACTOE_H__ */ -</verb></tscreen> - -E per far felici i programmi in C++ che includono il nostro file header, in: - -<tscreen><verb> -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ -. -. -. -#ifdef __cplusplus -} -#endif /* __cplusplus */ -</verb></tscreen> - -Insieme alle funzioni e alle strutture, dichiariamo tre macro -standard nel nostro file header, <tt/TICTACTOE(obj)/, -<tt/TICTACTOE_CLASS(klass)/, e <tt/IS_TICTACTOE(obj)/, i quali rispettivamente -fanno il cast di un puntatore ad un puntatore ad un ogetto od ad una struttura -di classe, e guarda se un oggetto è un widget Tictactoe. - - -Qui vi è il file header completo: - -<tscreen><verb> -/* 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__ */ - -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect2> La funzione <tt/_get_type()/ - -<p> -Continuiamo ora con l'implementazione del nostro widget. Una funzione -basilare di ogni widget è la funzione <tt/WIDGETNAME_get_type()/. -Questa funzione, quando chiamata la prima volta, comunica a GTK la classe -del widget, e ottiene un identificativo univoco per la classe del -widget. Chiamate successive restituiscono semplicemente l'identificativo. - -<tscreen><verb> -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; -} -</verb></tscreen> - -<p> -La struttura GtkTypeInfo ha la seguente definizione: - -<tscreen><verb> -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; -}; -</verb></tscreen> - -<p> -I campi di questa struttura sono abbastanza auto-esplicativi. -Ignoreremo, per ora, i campi <tt/arg_set_func/ e <tt/arg_get_func/: -hanno un ruolo importante, ma ancora largamente non -implementato, nel permettere ai linguaggi interpretati -di settare convenientemente le opzioni del widget. -Una volta che il GTK ha completato correttamente una copia di questa -struttura, sa come creare un oggetto di un particolare widget. - -<!-- ----------------------------------------------------------------- --> -<sect2> La funzione <tt/_class_init()/ -<p> -La funzione <tt/WIDGETNAME_class_init()/ inizialiazza i campi della -struttura della classe del widget, e setta ogni segnale della classe. -Per il nostro widget Tictactoe ha il seguente aspetto: - -<tscreen><verb> - -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; -} -</verb></tscreen> - -<p> -Il nostro widget ha semplicemente il segnale ``tictactoe'' che è -invocato quando una riga, colonna o diagonale è completamente premuta. -Non tutti i widget composti necessitano di segnali, quindi se stai -leggendo questo per la prima volta, puoi anche saltare alla prossima sezione, -dal momento che a questo punto le cose diventano un po' complicate. - -La funzione: -<tscreen><verb> -gint gtk_signal_new (const gchar *name, - GtkSignalRunType run_type, - GtkType object_type, - gint function_offset, - GtkSignalMarshaller marshaller, - GtkType return_val, - guint nparams, - ...); - -</verb></tscreen> - -crea un nuovo segnale. I parametri sono: - -<itemize> -<item> <tt/name/: Il nome del segnale. -<item> <tt/run_type/: Se il segstore predefinito viene eseguito prima o dopo -di quello dell'utente. Di norma questo sarà <tt/GTK_RUN_FIRST/, o <tt/GTK_RUN_LAST/, -anche se ci sono altre possibilità. -<item> <tt/object_type/: l'identificativo dell'oggetto a cui questo segnale si -riferisce. Esso sarà anche applicato agli oggetti discendenti. -<item> <tt/function_offset/: L'offset nella struttura della classe di un -puntatore al gestore predefinito. -<item> <tt/marshaller/: una funzione che è usata per invocare il gestore -del segnale. Per gestori di segnali che non hanno argomenti oltre -all'oggetto che emette il segnale e i dati dell'utente, possiamo usare -la funzione predefinita <tt/gtk_signal_default_marshaller/ -<item> <tt/return_val/: Il tipo del valore di ritorno. -<item> <tt/nparams/: Il numero di parametri del gestore di segnali (oltre -ai due predefiniti menzionati sopra) -<item> <tt/.../: i tipi dei parametri -</itemize> - -Quando si specificano i tipi, si usa l'enumerazione <tt/GtkType/: - -<tscreen><verb> -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, - - /* sarebbe bello poter togliere alla fine i prossimi due */ - GTK_TYPE_SIGNAL, - GTK_TYPE_C_CALLBACK, - - GTK_TYPE_OBJECT - -} GtkFundamentalType; -</verb></tscreen> - -<p> -<tt/gtk_signal_new()/ restituisce un identificatore unico intero per il segnale, -che memorizziamo nel vettore <tt/tictactoe_signals/, che -indicizzeremo usando una enumerazione. (Convenzionalmente, gli elementi dell'enumerazione -sono i nomi dei segnali, in maiuscolo, -ma qui ci potrebbe essere un conflitto con la macro <tt/TICTACTOE()/, -quindi l'abbiamo chiamato <tt/TICTACTOE_SIGNAL/ - -Dopo aver creato un nostro segnale, abbiamo bisogno di dire a GTK -di associare il nostro segnale alla classe Tictactoe. Lo facciamo -invocando <tt/gtk_object_class_add_signals()/. Settiamo quindi a NULL -il puntatore che punta al gestore predefinito per il segnale -``tictactoe'' a NULL, indicando che non ci sono azioni predefinite. - -<!-- ----------------------------------------------------------------- --> -<sect2> La funzione <tt/_init()/ - -<p> - -Ogni classe di Widget necessita anche di una funzione per inizializzare -la struttura dell'oggetto. Usualmente questa funzione ha il ruolo abbastanza -limitato di assegnare ai campi della struttura i valori predefiniti. -Per widget composti, comunque, questa funzione crea, anche, -i widget componenti del widget composto. - -<tscreen><verb> - -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]); - } -} -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect2> E il resto... - -<p> - -C'è un'altra funzione che ogni widget (eccetto i Widget di base come -GtkBin che non possono essere instanziati) deve avere : la funzione -che l'utente invoca per creare un oggetto di quel tipo. Questa è -convenzionalmente chiamata <tt/WIDGETNAME_new()/. In alcuni widget, -non nel caso del nostro Tictactoe, questa funzione richiede degli -argomenti, e fa alcune operazioni basandosi su di essi. Le altre -due funzioni sono specifiche del widget Tictactoe. - -<p> -<tt/tictactoe_clear()/ è una funzione pubblica che resetta tutti i -bottoni, nel widget, allo stato iniziale (non premuto). Notate l'uso -di <tt/gtk_signal_handler_block_by_data()/ per impedire che il nostro -gestore dei segnali venga attivato quando non ce n'è bisogno. - -<p> -<tt/tictactoe_toggle()/ è il gestore del segnale che viene invocato -quando l'utente preme il bottone. Esso guarda se vi è -qualche combinazione vincente che coinvolge i bottoni premuti, e nel -caso ci fosse, emette il segnale ``tictactoe''. - -<tscreen><verb> -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; - } - } -} -</verb></tscreen> - -<p> - -E finalmente un programma di esempio che usa il nostro widget -Tictactoe: - -<tscreen><verb> -#include <gtk/gtk.h> -#include "tictactoe.h" - -/* Invocato quando una riga, colonna o diagonale e' completata. */ -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); - - /* Crea un nuovo widget Tictactoe. */ - ttt = tictactoe_new (); - gtk_container_add (GTK_CONTAINER (window), ttt); - gtk_widget_show (ttt); - - /* E gli aggancia il segnale "tictactoe" */ - gtk_signal_connect (GTK_OBJECT (ttt), "tictactoe", - GTK_SIGNAL_FUNC (win), NULL); - - gtk_widget_show (window); - - gtk_main (); - - return 0; -} - -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1> Creare un widget a partire da zero - -<!-- ----------------------------------------------------------------- --> -<sect2> Introduzione - -<p> - -In questa sezione impareremo meglio come i widget si mostrano sullo schermo -e interagiscono con gli eventi. Come esempio, creeremo -un widget di quadrante analogico con un puntatore che l'utente -può trascinare per assegnare il valore. - -<!-- ----------------------------------------------------------------- --> -<sect2> Mostrare un widget sullo schermo - -<p> -Ci sono alcuni passi che sono necessari nella visualizzazione sullo -schermo. Dopo che il widget è stato creato con una chiamata a -<tt/WIDGETNAME_new()/, sono necessarie alcune altre funzioni: - -<itemize> -<item> <tt/WIDGETNAME_realize()/ è responsabile della creazione di -una finestra X per il widget se ne ha una. -<item> <tt/WIDGETNAME_map()/ è invocata dopo che l'utente ha -chiamato <tt/gtk_widget_show()/. E' responsabile di vedere se il -widget è attualmente disegnato sullo schermo (<em/mappato/). Per -una classe contenitore, essa deve anche creare chiamate alle -funzioni <tt/map()/> per ogni widget figlio. -<item> <tt/WIDGETNAME_draw()/ è invocata quando -<tt/gtk_widget_draw()/ viene chiamata per il widget o per uno dei suoi -predecessori. Esso fa sì che l'attuale chiamata alla -funzione di disegno del widget disegni il widget sullo schermo. -Per la classe contenitore, questa funzione deve eseguire le -chiamate alla funzioni <tt/gtk_widget_draw()/ di ogni suo widget -figlio. -<item> <tt/WIDGETNAME_expose()/ è un gestore per l'evento di esposizione -per il widget. Esso crea le chiamate necessarie alle funzioni di disegno -per disegnare la porzione che si è resa visibile. Per le classi -contenitore, questa funzione deve generare gli eventi di ``expose'' per -tutti i widget figli che non hanno una propria finestra (se essi hanno -una loro finestra, sarà X che genererà i necessari eventi di expose). -</itemize> - -<p> -Potete notare che le ultime due funzioni sono molto simili, ognuna è -responsabile per il disegno del widget sullo schermo. Infatti molti -tipi di widget non sanno relamente la differenza tra le due. -La funzione di predefinita <tt/draw()/ nella classe widget, semplicemente -genera un sintetico evento di ``expose'' per l'area da ridisegnare. -Comunque, alcuni tipi di widget possono risparmiare tempo distinguendo -le due funzioni. Per esempio, se un widget ha piu' finestre X, allora -visto che l'evento ``expose'' identifica solo la finestra esposta, -esso può ridisegnare solo la finestra interessata, cosa che non è -possibile per chiamate a <tt/draw()/. - -<p> -I widget contenitori, anche se essi non farebbero differenze, -non possono semplicemente usare la funzione <tt/draw()/ perchè per i -loro widget figli la differenza potrebbere essere importante. Comunque, -sarebbe uno spreco duplicare il codice di disegno nelle due -funzioni. La convenzione è che questi widget abbiano una funzione -chiamata <tt/WIDGETNAME_paint()/ che disegna il widget, che è poi -chiamata dalle funzioni <tt/draw()/ e <tt/expose()/ - -<p> -Nell'approccio del nostro esempio, visto che il widget, ha -una sola finestra, possiamo utilizzare il modo piu' semplice -ed usare la funzione predefinita <tt/draw()/ e implementare -solamente la funzione <tt/expose()/. - -<!-- ----------------------------------------------------------------- --> -<sect2> Le origini del widget Dial - -<p> -Come tutti gli animali terresti sono semplicemente varianti del primo -amfibio, i widget Gtk tendono ad essere varianti di altri widget, precedentemente -scritti. Così, anche se questa sezione è intitolata ``Creare -un widget a partire da zero", il nostro widget inizia in realtà con il codice -sorgente del widget Range. Questo è stato preso come punto d'inizio -perche' sarebbe carino se il nostro widget avesse la -stessa interfaccia del widget Scale il quale è semplicemente una -specializzazione del widget Range. Così, sebbene il codice sorgente e' -presentato sotto in forma definitiva, non si deve pensare che sia stato -scritto <em>deus ex machina</em> in questo modo. Se poi non avete familiarità -con il funzionamento del widget Scale dal punto di vista di chi scrive -un'applicazione, potrebbe essere una buona idea guardare indietro prima -di continuare. - -<!-- ----------------------------------------------------------------- --> -<sect2> Le basi - -<p> -Una parte del nostro widget potrebbe essere simile -al widget Tictactoe. In primo luogo, abbiamo il file header: - -<tscreen><verb> -/* 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; - - /* Politica di update (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */ - guint policy : 2; - - /* Bottone correntemente premuto o 0 altrimenti */ - guint8 button; - - /* Dimensione della componente Dial. */ - gint radius; - gint pointer_width; - - /* ID del timer di update, o 0 altrimenti */ - guint32 timer; - - /* Angolo corrente. */ - gfloat angle; - - /* Vecchi valori dell'aggiustamento così sappiamo quando - * qualcosa cambia */ - gfloat old_value; - gfloat old_lower; - gfloat old_upper; - - /* L'oggetto adjustament che memorizza i dati per questo dial */ - 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__ */ -</verb></tscreen> - -Essendoci più cose da fare con questo widget, rispetto al precedente, -abbiamo più cambi nella struttura dati, ma le altre cose sono -abbastamza simili. - -Dopo aver incluso i file di header e aver dichiarato alcune costanti, -dobbiamo fornire alcune funzioni circa il widget e la sua -inizializzazione. - -<tscreen><verb> -#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 - -/* Dichiarazioni di funzioni successive */ - -[ omesse per salvare spazio ] - -/* variabili locali. */ - -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, - (GtkArgSetFunc) NULL, - (GtkArgGetFunc) 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); -} -</verb></tscreen> - -Notate che questa funzione <tt/init()/ fa meno rispetto all'analoga del -widget Tictactoe, essendo questo un widget non composto, e la -funzione <tt/new()/ fa di più, essendoci un argomento. Inoltre, -notate che quando memorizziamo un puntatore all'oggetto Adjustment, -incrementiamo il conteggio dei suoi riferimenti(e corrispondentemente -lo decrementato quando non lo usiamo più) così che GTK può tener traccia di -quando è possibile distruggerlo senza causare guai. - -<p> -Inoltre, ci sono alcune funzioni per manipolare le opzioni del widget: - -<tscreen><verb> -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); -} -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect2> <tt/gtk_dial_realize()/ - -<p> -Abbiamo ora raggiunto alcuni nuovi tipi di funzione. In primo luogo, -abbiamo una funzione che crea la finestra di X. Noterete che viene -passata alla funzione <tt/gdk_window_new()/ una maschera che -specifica quali campi della struttura GdkWindowAttr non sono vuoti -(ai rimanenti campi può essere dato il valore predefinito). Anche -il modo con cui la maschera degli eventi del widget creata non è -complicato. Chiameremo <tt/gtk_widget_get_events()/ per sapere la -maschera degli eventi che l'utente ha specificato per questo widget -(con <tt/gtk_widget_set_events()/) e aggiungeremo gli eventi che ci possono -interessare. - -<p> -Dopo aver creato la finestra, settiamo lo stile e lo sfondo, -e creiamo un puntatore al widget nel campo dei dati utente (user data) -del GdkWindow. Quest'ultimo passo permette a GTK di mandare gli -eventi della finestra al widget corretto. - -<tscreen><verb> -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); -} -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect2> Negoziazione della dimensione - -<p> -Prima di visualizzare per la prima volta la finestra, e se il -layout della finestra cambia, GTK chiede ad ogni widget, incluso nella -finestra, la propria dimensione. Questa richiesta è fatta dalla -funzione <tt/gtk_dial_size_request()/. Non essendo il nostro widget -un contenitore, e non avendo dei veri limiti per la propria -dimensione, restituiamo semplicemnte un valore ragionevole. - -<tscreen><verb> -static void -gtk_dial_size_request (GtkWidget *widget, - GtkRequisition *requisition) -{ - requisition->width = DIAL_DEFAULT_SIZE; - requisition->height = DIAL_DEFAULT_SIZE; -} -</verb></tscreen> - -<p> -Dopo che tutti i widget hanno restituito una dimensione ideale, viene -calcolata la disposizione della finestra e ad ogni widget figlio è -notificata la propria dimensione attuale <!--ndMichel : che può essere diversa -da quella restitutita con la funzione sopra -->. Usualmente, questo sarà -almeno quanto richiesto, ma occasionalmente può essere più piccolo. -La notifica della dimensione viene fatta dalla funzione - <tt/gtk_dial_size_allocate()/. Notate che questa funzione è utilizzata -anche quando la finestra X del widget è spostata o modificata come -dimensione. - -<tscreen><verb> -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; - } -} -</verb></tscreen>. - -<!-- ----------------------------------------------------------------- --> -<sect2> <tt/gtk_dial_expose()/ - -<p> -Come menzionato sopra, tutto il lavoro di questo widget viene fatto nella -gestione dell'evento ``expose''. Non c'è molto da notare su questo eccetto -l'uso della funzione <tt/gtk_draw_polygon/ per disegnare il -puntatore con un'ombreggiatura a tre dimensioni in accordo con il colore -memorizzato nello stile del wiget. - -<tscreen><verb> -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; - - /* Draw ticks */ - - 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); - } - - /* Draw pointer */ - - 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; -} -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect2> Gestione degli eventi - -<p> - -Il resto del codice del widget manipola vari tipi di eventi, e non -è differente da quello che può essere trovato in molte applicazione -GTK. Due tipi di eventi possono verificarsi: l'utente può -clickare sul widget con il mouse e trascinare per muovere il puntatore, -o il valore dell'oggetto Adjustmente può cambiare a causa di alcune -circostanze esterne. - -<p> -Quando l'utente clicka sul widget, noi vediamo se la pressione -era veramente vicina al puntatore, e se così, memorizziamo il bottone -premuto dall'utente con il campo <tt/button/ della struttura del -widget, e prendiamo tutti gli eventi del mouse con una chiamata alla -funzione <tt/gtk_grab_add()/. Successivi movimenti del mouse causano il -ricalcolo dei valori di controllo (fatto dalla funzione -<tt/gtk_dial_update_mouse/). Dipendentemente dalla politica che abbiamo -stabilito, gli eventi ``value_changed'' possono essere generati -istantaneamente (<tt/GTK_UPDATE_CONTINUOUS/), dopo un certo tempo aggiunto -con la funzione <tt/gtk_timeout_add()/ (<tt/GTK_UPDATE_DELAYED/), o -solamente quando il bottone del mouse e' rilasciato -(<tt/GTK_UPDATE_DISCONTINUOUS/). - -<tscreen><verb> -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); - - /* Determina se il bottone premuto era dentro la regione del puntatore: - lo facciamo calcolando la distanza parallela e - perpendicolare dal punto dove il bottone del mouse e' stato premuto - alla linea passante per il puntatore. */ - - 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); - } - } - } -} -</verb></tscreen> - -<p> -Cambiamenti esterni all'Adjustment sono comunicati al nostro widget -dai segnali ``changed'' e ``value_changed''. Il gestore per -queste funzioni chiama <tt/gtk_dial_update()/ per validare gli -argomenti, calcolare il nuovo angolo del puntatore e ridisegnare il -widget (chiamando <tt/gtk_widget_draw()/). - -<tscreen><verb> -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; - } -} -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect2> Possibili Miglioramenti -<p> - -Il widget Dial, da come l'abbiamo costruito, è lungo circa 670 linee -di codice C. Anche se questo potrebbe sembrare un po' troppo, abbiamo -realmente fatto un bel po' con quel tanto di codice, specialmente -considerando che molta della lunghezza è costituita da file header e -commmenti. Comunque ci sono alcuni miglioramenti che potrebbero essere -fatti a questo widget: - -<itemize> -<item> Se tu provate questo widget, troverete che ci sono alcuni lampeggiamenti -quando il puntatore viene trascinato in giro. Questo -perchè l'intero widget è cancellato ogni volta che il -puntatore viene mosso, prima di essere ridisegnato. Spesso, il modo migliore -per gestire questo tipo di problema è il disegnare il tutto su una -pixmap non visibile, poi copiare il risultato finale sullo schermo -in una passata sola (il widget ProgressBar viene disegnato in questo -modo). - -<item> L'utente potrebbe essere abilitato ad usare le frecce su e giu per -incrementare e diminuire il valore. - -<item> Potrebbe essere carino se il widget avesse i bottoni per -incrementare e decrementare il valore di step. Anche se potrebbe essere -possibile usare dei widget Bottone incorporati per questo, possiamo anche -far sì che il bottone sia auto-ripentente quando premuto, come le frecce -in una barra di scorrimento. Molto del codice per implementare questo tipo di -comportamento può essere trovato nel widget GtkRange. - -<item> il widget Dial potrebbe essere fatto/creato dentro un widget -contenitore con un singolo widget figlio posizionato all'inizio tra i -2 bottoni menzionati prima. L'utente potrebbe poi aggiungere o una etichetta -o un widget ``entry'' per mostrare il valore corrente del dial. - -</itemize> - -<!-- ----------------------------------------------------------------- --> -<sect1> Impararne di più - -<p> -Fin qui abbiamo esposto solo una piccola parte di tutto quello che serve -per creare un widget. Se volete davvero scrivere un vostro widget, la -miglior risorsa di esempi è lo stesso codice sorgente GTK. Chiedete a voi -stessi alcune cose su come deve essere il widget che volete scrivere: è -un widget contenitore? dovrà avere una propria finestra? è una modifica di -un widget precedente? Trovate poi un widget simile e iniziate a fargli -delle modifiche. -Buone Fortuna. - -<!-- ***************************************************************** --> -<sect>Scribble, Un semplice esempio di Programma di Disegno -<!-- ***************************************************************** --> - -<!-- ----------------------------------------------------------------- --> -<sect1> Panoramica - -<p> -In questa sezione, creeremo un semplice programma di disegno. Durante -questo processo, esamineremo come gestire gli eventi generati dal mouse, -come disegnare all'interno di una finestra e come disegnare in modo migliore -usando una pixmap di supporto. Dopo averlo creato, lo amplieremo aggiungendo -il supporto per i dispositivi XInput, per esempio le tavolette grafiche. -Il GTK fornisce delle routine di supporto grazie alle quali risulta piuttosto -semplice ottenere informazioni estese, come la pressione o l'inclinazione. - -<!-- ----------------------------------------------------------------- --> -<sect1> Gestione degli Eventi - -<p> -I segnali di GTK che abbiamo discusso finora si riferivano ad azioni di -alto livello, ad esempio la selezione di un elemento di un menù. Però, a volte -è utile sapere qualcosa su cose che si svolgono a livello più basso livello, -come possono essere il movimento del mouse o la pressione di un tasto. -Ci sono segnali di GTK anche per questi <em>eventi</em> di basso livello. -I gestori di questo tipo di segnali hanno un parametro caratteristico in più, -che è il puntatore ad una struttura che contiene informazioni riguardo -all'evento. Per esempio, ai gestori di eventi che riguardano dei movimenti, -si passa un puntatore ad una struttura GdkEventMotion, che è fatta (in parte) -così: - -<tscreen><verb> -struct _GdkEventMotion -{ - GdkEventType type; - GdkWindow *window; - guint32 time; - gdouble x; - gdouble y; - ... - guint state; - ... -}; -</verb></tscreen> - -<tt/type/ avrà il valore del tipo di evento, in questo caso -<tt/GDK_MOTION_NOTIFY/, <tt/window/ rappresenta la finestra in cui l'evento -si è verificato. <tt/x/ e <tt/y/ forniscono le coordinate dell'evento e -<tt/state/ specifica lo stato dei modificatori nel momento in cui l'evento -si è verificato (cioè, specifica quali tasti modificatori e tasti del mouse -erano premuti in quel momento). E' un OR bit per bit dei seguenti valori: - -<tscreen><verb> -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 -</verb></tscreen> - -<p> -Come succede per gli altri segnali, per determinare cosa deve accadere in -corrispondenza di un evento, si chiama <tt>gtk_signal_connect()</tt>. Ma -è anche necessario far sì che GTK sappia di quali eventi vogliamo essere -informati. A questo fine, chiamiamo la funzione: - -<tscreen><verb> -void gtk_widget_set_events (GtkWidget *widget, gint events); -</verb></tscreen> - -Il secondo campo specifica gli eventi che ci interessano. Si tratta dell'OR -bit per bit delle costanti che identificano i diversi tipi di eventi. La lista -dei tipi di eventi è la seguente: - -<tscreen><verb> -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 -</verb></tscreen> - -Per chiamare <tt/gtk_widget_set_events()/, si devono fare alcune osservazioni -sottili. In primo luogo, la si deve chiamare prima che sia stata creata la -finestra X per il widget GTK. In pratica, ciò significa che la si deve -chiamare subito dopo aver creato il widget. In secondo luogo, il widget -deve avere una finestra X associata. Molti widget, per ragioni di -efficienza, non hanno una propria finetra, e vengono mostrati nella -finestra madre. Questi widget sono: - -<tscreen><verb> -GtkAlignment -GtkArrow -GtkBin -GtkBox -GtkImage -GtkItem -GtkLabel -GtkPixmap -GtkScrolledWindow -GtkSeparator -GtkTable -GtkAspectFrame -GtkFrame -GtkVBox -GtkHBox -GtkVSeparator -GtkHSeparator -</verb></tscreen> - -Per catturare degli eventi per questo tipo di widget, si deve fare uso -del widget EventBox. Si veda a questo proposito la sezione su -<ref id="sec_The_EventBox_Widget" name="The EventBox Widget">. - -<p> -Per il nostro programma di disegno, vogliamo sapere quando il pulsante del -mouse è premuto e quando viene mosso, quindi specificheremo -<tt/GDK_POINTER_MOTION_MASK/ e <tt/GDK_BUTTON_PRESS_MASK/. Vogliamo anche -essere informati su quando è necessario ridisegnare la nostra finestra, -quindi specifichiamo <tt/GDK_EXPOSURE_MASK/. Anche se vogliamo essere -avvertiti con un evento ``Configure'' se la dimensione della nostra finestra -cambia, non è necessario specificare il flag <tt/GDK_STRUCTURE_MASK/, dal -momento che questo viene specificato automaticamente per tutte le finestre. - -<p> -Risulta, conunque, che specificando semplicemente <tt/GDK_POINTER_MOTION_MASK/ -si crea un problema. Ciò infatti fa sì che il server aggiunga nella coda un -un nuovo evento di movimento ogni volta che l'utente muovoe il mouse. Immaginate -che ci vogliano 0.1 secondi per gestire uno di questi eventi, e che il server -X metta in coda un nuovo evento ogni 0.05 secondi. Rimarremo ben presto indietro -rispetto al disegno dell'utente. Se l'utente disegna per 5 secondi, ci metteremmo -altri 5 secondi prima di finire dopo che l'utente ha rilasciato il pulsante del -mouse! Vorremmo quindi che venga notificato un solo evento di movimento per -ogni evento che processiamo. Il modo per farlo è di specificare -<tt/GDK_POINTER_MOTION_HINT_MASK/. - -<p> -Quando specifichiamo <tt/GDK_POINTER_MOTION_HINT_MASK/, il server ci notifica -un evento di movimento la prima volta che il puntatore si muove dopo essere -entrato nella nostra finestra, oppure dopo ogni rilascio di un pulsante del -mouse. Gli altri eventi di movimento verranno soppressi finché non richiediamo -esplicitamente la posizione del puntatore con la funzione: - -<tscreen><verb> -GdkWindow* gdk_window_get_pointer (GdkWindow *window, - gint *x, - gint *y, - GdkModifierType *mask); -</verb></tscreen> - -(c'è anche un'altra funzione, <tt>gtk_widget_get_pointer()</tt>, che ha -un'interfaccia più semplice, ma che non risulta molto utile dal momento -che restituisce solo la posizione del puntatore, senza dettagli sullo -sato dei pulsanti.) - -<p> -Quindi, il codice per assegnare gli eventi per la nostra finestra, avrà l'aspetto: - -<tscreen><verb> - 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); -</verb></tscreen> - -Teniamo per dopo i gestori di ``expose_event'' e ``configure_event''. Quelli di -``motion_notify_event'' e ``button_press_event'' sono piuttosto semplici: - -<tscreen><verb> -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; -} -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1> Il widget Area di Disegno (DrawingArea) e il procedimento per Disegnare - -<p> -Vediamo ora il procedimento per disegnare sullo schermo. Il -widget da usare è l'Area di Disegno (DrawingArea). Essenzialmente si -tratta di una finestra X e nient'altro. E' una tela bianca su cui possimo -disegnare tutto quello che vogliamo. Per crearne una usiamo la chiamata: - -<tscreen><verb> -GtkWidget* gtk_drawing_area_new (void); -</verb></tscreen> - -Per specificare una dimensione predefinita, si puo fare: - -<tscreen><verb> -void gtk_drawing_area_size (GtkDrawingArea *darea, - gint width, - gint height); -</verb></tscreen> - -Come è vero per tutti i widget, si può modificare questa dimensione -predefinita, tramite la chamata a <tt>gtk_widget_set_usize()</tt>, e -questa a sua volta può essere modificata dall'utente ridimensionando -manualmente la finestra che contiene l'area di disegno. - -<p> -Si deve notare che nel momento in cui creiamo un widget DrawingArea, siamo -<em>completamente</em> responsabili di disegnarne il contenuto. Se ad -esempio la nostra finestra viene prima nascosta e poi dinuovo portata in -primo piano, otteniamo un evento di ``esposizione'' e doppiamo ridisegnare -ciò che era stato precedente nascosto. - -<p> -Dover ricordare tutto quello che era disegnato sulla finestra in modo da -poterlo ridisegnare successivamente, può essere, come minimo, noioso. -In più, può essere spiacevole dal punto di vista visivo, se delle porzioni -dello schermo vengono prima cancellate e poi ridisegnate passo per passo. -La soluzione per questo problema è di usare una <em>pixmap di supporto</em>. -Invece di disegnare direttamente sullo schermo, disegnamo su un'iimagine -conservata nella memoria del server ma che non viene mostrata; quindi, quando -l'immagine cambia o ne vengono mostrate nuove porzioni, copiamo sullo schermo -le parti corrispondenti. - -<p> -Per creare una ppixmap fuori dallo schermo, usiamo la funzione: - -<tscreen><verb> -GdkPixmap* gdk_pixmap_new (GdkWindow *window, - gint width, - gint height, - gint depth); -</verb></tscreen> - -Il parametro <tt>window</tt>specifica una finestra GDK dalla quale questa -pixmap prende alcune delle sue proprietà. <tt>width</tt> e <tt>height</tt> -specificano le dimensioni della pixmap. <tt>depth</tt> specifica la -<em>profondità di colore</em>, cioè il numero di bit per ogni pixel, per -la nuova pixmap. Se alla profondità è assegnato il valore <tt>-1</tt>, questa -verrà posta identica a quella di <tt>window</tt>. - -<p> -Creiamo la pixmap all'interno del gestore di ``configure_event''. Questo evento -è generato ogni volta che la finestra cambia di dimensione, compreso il -momento in cui viene creata per la prima volta. - -<tscreen><verb> -/* Pixmap di supporto per l'area di disegno */ -static GdkPixmap *pixmap = NULL; - -/* Creare una pixmap della dimensione appropriata */ -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; -} -</verb></tscreen> - -La chiamata a <tt>gdk_draw_rectangle()</tt> inizialmente rende bianca l'intera -pixmap. Fra un momento ne riparleremo. - -<p> -Il gestore dell'evento ``esposizione'', copia quindi la porzione appropriata -della pixmap sullo schermo (determiniamo qual è l'area da ridisegnare usando -il campo event->area dell'evento di esposizione): - -<tscreen><verb> -/* Ridisegna sullo schermo a partire dalla pixmap di supporto */ -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; -} -</verb></tscreen> - -Abbiamo quindi visto come tenete aggiornato lo schermo con la nostra -pixmap, ma come facciamo per disegnare delle cose interessanti sulla -pixmap? Ci sono un bel po' di funzioni nella libreria GDK di GTK che -servono per disegnare su superfici <em>disegnabili</em>. Una superficie -disegnabile è semplicemente qualcosa su cui si può disegnare un'immagine. -Può essere una finestra, una pixmap o una bitmap (un'immagine in bianco e -nero). Abbiamo già visto sopra due di chiamate, -<tt>gdk_draw_rectangle()</tt> and <tt>gdk_draw_pixmap()</tt>. La lista -completa è la seguente: - -<tscreen><verb> -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 () -</verb></tscreen> - -Per ulteriori dettagli su queste funzioni, vedete la documentazione di -riferimento nei file header <tt><gdk/gdk.h></tt>. -Tutte queste funzioni hanno i medesimi primi due argomenti. Il primo -è la superficie disegnabili su cui disegnare, il secondo è un -<em>contesto grafico</em> (GC). - -<p> -Un contesto grafico incapsula delle informazioni riguardo a cose come -il colore di sfondo e di primo piano e lo spessore della linea. -GDK ha un ampio insieme di funzioni per crare e modificare contesti grafici, -ma per tenere le cose semplici useremo solo dei contesti grafici predefiniti. -Ogni widget ha uno stile associato (che può essere modificato agendo su un -file gtkrc). Questo, fra le altre cose, contiene un certo numero di contesti -grafici. Alcuni esempi di come accedere a questi contesti grafici sono -i seguenti: - -<tscreen><verb> -widget->style->white_gc -widget->style->black_gc -widget->style->fg_gc[GTK_STATE_NORMAL] -widget->style->bg_gc[GTK_WIDGET_STATE(widget)] -</verb></tscreen> - -I campi <tt>fg_gc</tt>, <tt>bg_gc</tt>, <tt>dark_gc</tt>, e -<tt>light_gc</tt> sono indicizzati tramite un parametri di tipo -<tt>GtkStateType</tt>, che può assumere i valori: - -<tscreen><verb> -GTK_STATE_NORMAL, -GTK_STATE_ACTIVE, -GTK_STATE_PRELIGHT, -GTK_STATE_SELECTED, -GTK_STATE_INSENSITIVE -</verb></tscreen> - -Per esempio, per <tt/GTK_STATE_SELECTED/ il colore di sfondo predefinito -è blu scuro e quello di primo piano bianco. - -<p> -La nostra funzione <tt>draw_brush()</tt>, che efettivamente disegna sullo -schermo, diventa quindi: - -<tscreen><verb> -/* Disegna un rettangolo sullo schermo */ -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); -} -</verb></tscreen> - -Dopo aver disegnato il rettangolo sulla pixmap, chiamiamo la funzione: - -<tscreen><verb> -void gtk_widget_draw (GtkWidget *widget, - GdkRectangle *area); -</verb></tscreen> - -che notifica a X che l'area data dal parametro <tt>area</tt> deve essere -aggiornata. X poi genererà un evento di esposizione (che può essere combinato -con le aree passate da diverse chiamate a <tt>gtk_widget_draw()</tt>) che -farà sì che il nostro gestore dell'evento di esposizione, copi le porzioni -rilevanti sullo schermo. - -<p> -Abbiamo a questo punto creato tutto il programma di disegno, tranne che -per qualche dettaglio irrilevante come la creazione della finestra principale. -Il codice sorgente completo è reperibile dove avete ottenuto questo tutorial, -oppure da: - -<htmlurl url="http://www.msc.cornell.edu/~otaylor/gtk-gimp/tutorial" -name="http://www.msc.cornell.edu/~otaylor/gtk-gimp/tutorial"> - -<!-- ----------------------------------------------------------------- --> -<sect1> Aggiungere il supporto per XInput - -<p> -Al giorno d'oggi è possibile acquistare dei dispositivi abbastanza a buon -mercato, come tavolette grafice, che permettono di disegnare con una -espressività artistica molto semplificata rispetto ad un mouse. -Il modo più semplice per usare questi dispositivi è di sostituirli -semplicemente al mouse, ma in questo modo si perdono molti dei loro -vantaggi, come: - -<itemize> -<item> Sensibilità alla pressione -<item> Sensibilità all'inclinazione -<item> Posizionamento infra-pixel -<item> Ingressi multipli (per esempio, uno stilo che contiene sia una ``matita'' -sia una ``gomma'') -</itemize> - -Per ulteriori informazioni sulle estensioni XInput, vedere l'<htmlurl -url="http://www.msc.cornell.edu/~otaylor/xinput/XInput-HOWTO.html" -name="XInput-HOWTO">. - -<p> -Se esaminiamo, per esempio, la definizione completa della struttura -GdkEventMotion, possiamo vedere che contiene dei campi per il supporto -delle informazioni estese dai dispositivi. - -<tscreen><verb> -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; -}; -</verb></tscreen> - -<tt/pressure/ fornisce la pressione sotto forma di un numero decimale -compreso fra 0 e 1. <tt/xtilt/ e <tt/ytilt/ possono assumere valori -compresi fra -1 e 1, corrispondenti al grado di inclinazione in ciascuna -direzione. <tt/source/ e <tt/deviceid/ specificano il dispositivo per il -quale si è verificato l'evento in due modi distinti. <tt/source/ da alcune -semplici informazioni sul tipo di dispositivo, e può assumere i valori: - -<tscreen><verb> -GDK_SOURCE_MOUSE -GDK_SOURCE_PEN -GDK_SOURCE_ERASER -GDK_SOURCE_CURSOR -</verb></tscreen> - -<tt/deviceid/ specifica invece un identificativo numerico univoco per il -dispositivo. Questo può essere a sua volta utilizzato per avere ulteriori -informazioni sul dispositivo tramite la chiamata a <tt/gdk_input_list_devices()/ -(vedi sotto). Il valore speciale <tt/GDK_CORE_POINTER/ viene usato per identificare -il dispositivo di puntamento principale (di solito il mouse). - -<sect2> Abilitare le informazioni estese - -<p> -Per far sì che GTK sappia che ci interessano le informazioni estese dai -dispositivi, basta aggiungere un'unica linea al nostro programma: - -<tscreen><verb> -gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_CURSOR); -</verb></tscreen> - -Dando il valore <tt/GDK_EXTENSION_EVENTS_CURSOR/, diciamo che ci interessano -gli eventi relativi alle estensioni, ma solo se non dobbiamo disegnare da noi -il nostro cursore. Si veda più sotto alla sezione <ref -id="sec_Further_Sophistications" name="Ulteriori Sofisticazioni"> per ulteriori -informazioni sul modo si disegnare i cursori. Potremmo anche dare i valori -<tt/GDK_EXTENSION_EVENTS_ALL/ se vogliamo disegnare il nostro cursore o -<tt/GDK_EXTENSION_EVENTS_NONE/ se vogliamo tornare alle condizioni predefinite. - -<p> -Comunque, non finisce tutto qui. Non ci sono estensioni abilitate per difetto. -Abbiamo bisogno di un meccanismo per permettere agli utenti l'abilitazione e -la configurazione delle estensioni dei loro dispositivi, GTK fornisce il -widget InputDialog per automatizzare questo processo. La seguente procedura -mostra come gestire un widget InputDialog. Crea la finestra di dialogo nel -caso non sia presente, mentre la porta in primo piano in caso contrario. - -<tscreen><verb> -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); - } -} -</verb></tscreen> - -(Notate come gestiamo questo dialogo. Con la connessione del segnale -``destroy'' ci assicuriamo di non tenerci in giro il puntatore al dialogo -dopo che lo abbiamo distrutto, cosa che potrebbe portare ad un errore di -segmentazione.) - -<p> -L'InputDialog ha due pulsanti, ``Close'' e ``Save'', i quali non hanno alcuna -azione predefinita assegnata ad essi. Nella funzione precedente, abbiamo -fatto in modo che ``Close'' nasconda la finestra di dialogo, e abbiamo nascosto -il pulsante ``Save'' dal momento che in questo programma non implementiamo il -salvataggio delle opzioni di XInput. - -<sect2> Usare le informazioni estese - -<p> -Una volta abilitato il dipositivo, possiamo usare le informazioni estese -che si trovano nei corrispondenti campi delle strutture che descrivono gli -eventi. A dire il vero, l'utilizzo di questi campi è sempre sicuro, perché -sono tutti posti per difetto a valori ragionevoli ancje quando la gestione -degli eventi estesi non è abilitata. - -<p> -Un cambiamento che dobbiamo fare è di chiamare <tt/gdk_input_window_get_pointer()/ -invece di <tt/gdk_window_get_pointer/. Ciò si rende necessario perché -<tt/gdk_window_get_pointer/ non restituisce le informazioni esetese. - -<tscreen><verb> -void gdk_input_window_get_pointer (GdkWindow *window, - guint32 deviceid, - gdouble *x, - gdouble *y, - gdouble *pressure, - gdouble *xtilt, - gdouble *ytilt, - GdkModifierType *mask); -</verb></tscreen> - -Quando chiamiamo questa funzione, dobbiamo specificare l'identificativo -del dispositivo e la finestra. Normalmente questo identificativo lo si -ottiene dal campo <tt/deviceid/ della struttura dell'evento. -Questa funzione restituirà valori ragionevoli nel caso che la gestione -degli eventi estesi non sia attivata (in questo caso, <tt/event->deviceid/ -avrà il valore <tt/GDK_CORE_POINTER/). - -Quindi, la struttura di base dei gestori degli eventi relativi alla -pressione di bottoni e ai movomenti non cambia molto - abbiamo solo -bisogno di aggiungere il codice necessario per tenere conto delle -informazioni estese. - -<tscreen><verb> -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; -} -</verb></tscreen> - -Avremo anche bisogno di fare qualcosa con queste nuove informazioni. La -nostra nuova funzione <tt/draw_brush/ disegna con un colore diverso per -ogni <tt/event->source/ e cambia la dimensione della linea in funzione -della pressione. - -<tscreen><verb> -/* Disegna un rettangolo sullo schermo, con la dimensione dipendente - dalla pressione e il colore dipendente dal tipo di dispositivo */ -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); -} -</verb></tscreen> - -<sect2> Trovare ulteriori informazioni su di un dispositivo - -<p> -Come esempio del modo di trovare altre informazioni su di un dispositivo, -il nostro programma stamperà il nome di ogni dispositivo che genera un -evento di pressione di un pulsante. Per avere il nome di un dispositivo, -chiamiamo la funzione - -<tscreen><verb> -GList *gdk_input_list_devices (void); -</verb></tscreen> - -che restituisce una GList (un tipo di lista collegata che si trova nella -libreria glib) di strutture di tipo GdkDeviceInfo. La definizione di -GdkDeviceInfo è la seguente: - -<tscreen><verb> -struct _GdkDeviceInfo -{ - guint32 deviceid; - gchar *name; - GdkInputSource source; - GdkInputMode mode; - gint has_cursor; - gint num_axes; - GdkAxisUse *axes; - gint num_keys; - GdkDeviceKey *keys; -}; -</verb></tscreen> - -La maggior parte di questi campi rappresentano informazioni di configurazione -che potete ignorare a meno che non implementiate il salvataggio della -configurazione di un XInput. Quelle che ci interessano sono <tt/name/, che -è semplicemente il nome che X assegna al dispositivo, e <tt/has_cursor/. Anche -<tt/has_cursor/ non è informazione di configurazione, e indica, nel caso -abbia valore ``falso'', che dobbiamo disegnare da soli il nostro cursore. Ma -dal momento che abbiamo specificato <tt/GDK_EXTENSION_EVENTS_CURSOR/, -possiamo anche non preoccuparcene. - -<p> - -La nostra funzione <tt/print_button_press()/ scorre semplicemente la lista -che è stata restituita finché non trova il valore corretto, e poi stampa -il nome del dispositivo. - -<tscreen><verb> -static void -print_button_press (guint32 deviceid) -{ - GList *tmp_list; - - /* gdk_input_list_devices restituisce una lista interna, così poi - non dobbiamo liberarla */ - 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; - } -} -</verb></tscreen> -Questo completa i cambiamenti necessari per usare gli XInput nel nostro -programma. Come per la prima versione, i sorgenti completi sono prelevabili -da dove avete prelevato questo tutorial, oppure da: - -<htmlurl url="http://www.msc.cornell.edu/~otaylor/gtk-gimp/tutorial" -name="http://www.msc.cornell.edu/~otaylor/gtk-gimp/tutorial"> - -<sect2> Ulteriori sofisticazioni <label id="sec_Further_Sophistications"> - -<p> -Anche se ora il nostro programma supporta XInput pittosto bene, gli mancano -alcune caratteristiche che probabilmente vorremmo mettere in una applicazione -completa. In primo luogo, probabilmente all'utente non farà piacere dover -configurare i propri dispositivi ogni volta che lanciano il programma, per -cui dovremmo dare la possibilità di salvare la configurazione dei dispositivi. -Ciò può essere fatto scorrendo la lista restituita da <tt/gdk_input_list_devices()/ -e scrivendo la configurazione su di un file. - -<p> -Per tornare allo stato salvato la prossima volta che il programma viene -eseguito, GDK mette a disposizione delle funzioni per cambiare la configurazione -dei dispositivi: - -<tscreen><verb> -gdk_input_set_extension_events() -gdk_input_set_source() -gdk_input_set_mode() -gdk_input_set_axes() -gdk_input_set_key() -</verb></tscreen> - -(La lista restituita da <tt/gdk_input_list_devices()/ non dovrebbe -essere modificata direttamente.) Un esempio di come fare può essere -trovato nel programma di disegno gsumi (disponibile da <htmlurl -url="http://www.msc.cornell.edu/~otaylor/gsumi/" -name="http://www.msc.cornell.edu/~otaylor/gsumi/">). Sarebbe bello -avere alla fine un modo standard di recuperare le informazioni per tutte -le applicazioni. Questo probabilmente appartiene ad un livello un po' -più elevato ripetto a GTK, forse alla libreria GNOME. - -<p> -Un'altra notevole omissione a cui abbiamo accennato precedentemente è il -fatto di non disegnare il cursore direttamente. Piattaforme diverse da -XFree86 non permettono in questo momento di usare contemporaneamente un -dispositivo sia come puntatore principale sia direttamente da una -applicazione. Vedere <url url="http://www.msc.cornell.edu/~otaylor/xinput/XInput-HOWTO.html" -name="XInput-HOWTO"> per ulteriori informazioni. Ciò significa che le -applicazioni che vogliono rivolgersi al pubblico più ampio dovranno prevedere -di disegnare esse stesse il proprio cursore. - -<p> -Un'applicazione che voglia disegnare il proprio cursore dovrà fare due cose: -determinare se il dispositivo corrente necessita che venga disegnato un -cursore, e determinare se il dispositivo corrente è in prossimità. (Se il -dispositivo è una tavoletta grafica, un tocco di finezza è fare sparire -il puntatore quando lo stilo viene sollevato dalla tavoletta. Quando c'è -contatto fra lo stilo e la tavoletta, si dice che il dispositivo è ``in -prossimità".) La prima cosa viene fatta scorrendo la lista dei dispositivi, -come abbiamo fatto per trovare il nome del dispositivo. La seconda cosa -viene ottenuta selezionando gli eventi ``proximity_out''. Un esempio di -disegno del proprio cursore si trova nel programma 'testinput' incluso nella -distribuzione di GTK. - -<!-- ***************************************************************** --> -<sect>Consigli per scrivere Applicazioni GTK -<!-- ***************************************************************** --> - -<p> - -Questa sezione è semplicemente una raccolta di saggezza, una -guida di stile e un aiuto per creare buone applicazioni GTK. E' totalmente -inutile per ora perché è solamente un appunto. - -Usa autoconf e automake! Sono tuoi amici :) Ho intenzione di fare una -piccola introduzione su di loro qui. - -<!-- ***************************************************************** --> -<sect>Contributi -<!-- ***************************************************************** --> - -<p> -Questo documento, come molti altri grandi software là fuori, è stato -creato da volontari. Se sai tutto quello che c'è da sapere su GTK e non -lo hai trovato qui allora considera la possibilità di contribuire a questo -documento. - -<p> -Se decidi di contribuire, ti prego di trasmettere il tuo lavoro a Tony Gale, -<tt><htmlurl url="mailto:gale@gtk.org" -name="gale@gtk.org"></tt>. Inoltre, ricorda che l'intero documento è -``free'', e che ogni tua aggiunta sarà considerata allo stesso modo. -Per questo motivo le persone possono usare porzioni dei tuoi esempi nei loro -programmi, copie di questo documento possono essere distribuite all'infinito, -ecc... -<p> - -Grazie. - -<!-- ***************************************************************** --> -<sect>Credits -<!-- ***************************************************************** --> -<p> -Voglio qui ringraziare le persone che seguono, per il loro contributo -alla stesura di questo testo. - -<itemize> -<item>Bawer Dagdeviren, <tt><htmlurl url="mailto:chamele0n@geocities.com" -name="chamele0n@geocities.com"></tt> per il tutorial sui menù. - -<item>Raph Levien, <tt><htmlurl url="mailto:raph@acm.org" - name="raph@acm.org"></tt> -per il "hello world" alla GTK, l'immpacchettamento del widget, e in generale -per tutta la sua saggezza. -Lui ha anche donato una casa per questo tutorial. - -<item>Peter Mattis, <tt><htmlurl url="mailto:petm@xcf.berkeley.edu" -name="petm@xcf.berkeley.edu"></tt> Per il più semplice programma GTK e l'abilità -di farlo. :) - -<item>Werner Koch <tt><htmlurl url="mailto:werner.koch@guug.de" -name="werner.koch@guug.de"></tt> per la conversione da testo semplice a SGML -e la gerarchia delle classi di widget. - -<item>Mark Crichton <tt><htmlurl url="mailto:crichton@expert.cc.purdue.edu" -name="crichton@expert.cc.purdue.edu"></tt> per il codice della "MenuFactory" -e per la parte sull'impacchettamento nelle tabelle del tutorial. - -<item>Owen Taylor <tt><htmlurl url="mailto:owt1@cornell.edu" -name="mailto:owt1@cornell.edu"></tt> per la sezione del widget EventBox -(e il patch alla distribuzione). Lui è anche responsabile per il codice -e il tutorial delle selezioni, come per la sezione sulla scrittura di un -proprio widget, e l'applicazione d'esempio. Grazie di tutto Owen. - -<item>Mark VanderBoom <tt><htmlurl url="mailto:mvboom42@calvin.edu" -name="mailto:mailto:mvboom42@calvin.edu"></tt> per il suo meraviglioso lavoro -sul Notebook, Progres Bar, Dialogs e File selection. Grazie molto Mark. Sei -stato di grande aiuto. - -<item>Tim Janik <tt><htmlurl url="mailto:timj@gtk.org" -name="mailto:timj@gtk.org"></tt> per il suo grande lavoro sul widget List. -Grazie Tim :) - -<item> Michael K. Johnson <tt><htmlurl url="mailto:johnsonm@redhat.com" -name="johnsonm@redhat.com"> </tt> per le informazioni e il codice dei menu -a comparsa. - -</itemize> -<p> -E a tutti voi che avete fatto commenti e avete aiutato a raffinare questo documento. -<p> - -Thanks. - -<!-- ***************************************************************** --> -<sect> Dichiarazione di Copyright e Licenza -<!-- ***************************************************************** --> -<p> -A questa traduzione, Copyright (c) 1997-1998 di Michel Morelli, -Daniele Canazza e Antonio Schifano, si applica la medesime licenza -prevista dal lavoro originale di Ian Main e Tony Gale. Segue la traduzione -di quelle disposizioni e la loro versione originale. In caso di discordanze -fra traduzione e versione originale, fa fede quest'ultima. -<p> -Il GTK Tutorial è Copyright (c) 1997 Ian Main. - -Copyright (c) 1998 Tony Gale. -<p> -E' permesso fare e distribuire copie non modificate di questo manuale, -sotto la condizione che la dichiarazione di copyright e queste disposizioni -siano riportate su tutte le copie. -<p>E' permesso fare e distribuire copie di versioni modificate di questo -documento, sotto le stesse condizioni previste per la copia non modificata, -e che questa dichiarazione di copyright sia inclusa esattamente come -nell'originale, e che l'intero lavoro risultante sia distribuito sotto -i termini di una licenza identica a questa. -<p>E' permesso fare e distribuire copie di traduzioni di questo documento in -altre lingue, sotto le stesse condizioni previste per le versioni modificate. -<p>Nel caso si intenda includere questo documento in un lavoro pubblicato, -si prega di contattarne il curatore, che cercherà di mettere a -disposizione le informazioni più aggiornate. -<p>Non c'è garanzia che questo documento sia rispondente ai propri -propositi. Esso viene semplicemente fornito come una risorsa "free" (libera e -gratuita). In quanto tale, gli autori e i curatori delle informazioni contenute -in esso, non possono dare alcuna garanzia nemmeno sul fatto che tali informazioni -siano accurate. - -<p>--------------------- -<p> -The GTK Tutorial is Copyright (C) 1997 Ian Main. - -Copyright (C) 1998 Tony Gale. -<p> -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. -<P>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. -<P>Permission is granted to copy and distribute translations of this -document into another language, under the above conditions for modified -versions. -<P>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. -<P>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. - -</article> - diff --git a/docs/tutorial/gtk_tut_packbox1.eps b/docs/tutorial/gtk_tut_packbox1.eps deleted file mode 100644 index 0f40171c2a..0000000000 --- a/docs/tutorial/gtk_tut_packbox1.eps +++ /dev/null @@ -1,7262 +0,0 @@ -%!PS-Adobe-3.0 EPSF-3.0 -%%Creator: (ImageMagick) -%%Title: (1.eps) -%%CreationDate: (Thu Jul 27 12:44:55 2000) -%%BoundingBox: 0 0 362.429 161 -%%DocumentData: Clean7Bit -%%LanguageLevel: 1 -%%Pages: 0 -%%EndComments - -%%BeginDefaults -%%PageOrientation: Portrait -%%EndDefaults - -%%BeginProlog -% -% Display a color image. The image is displayed in color on -% Postscript viewers or printers that support color, otherwise -% it is displayed as grayscale. -% -/buffer 512 string def -/byte 1 string def -/color_packet 3 string def -/pixels 768 string def - -/DirectClassPacket -{ - % - % Get a DirectClass packet. - % - % Parameters: - % red. - % green. - % blue. - % length: number of pixels minus one of this color (optional). - % - currentfile color_packet readhexstring pop pop - compression 0 gt - { - /number_pixels 3 def - } - { - currentfile byte readhexstring pop 0 get - /number_pixels exch 1 add 3 mul def - } ifelse - 0 3 number_pixels 1 sub - { - pixels exch color_packet putinterval - } for - pixels 0 number_pixels getinterval -} bind def - -/DirectClassImage -{ - % - % Display a DirectClass image. - % - systemdict /colorimage known - { - columns rows 8 - [ - columns 0 0 - rows neg 0 rows - ] - { DirectClassPacket } false 3 colorimage - } - { - % - % No colorimage operator; convert to grayscale. - % - columns rows 8 - [ - columns 0 0 - rows neg 0 rows - ] - { GrayDirectClassPacket } image - } ifelse -} bind def - -/GrayDirectClassPacket -{ - % - % Get a DirectClass packet; convert to grayscale. - % - % Parameters: - % red - % green - % blue - % length: number of pixels minus one of this color (optional). - % - currentfile color_packet readhexstring pop pop - color_packet 0 get 0.299 mul - color_packet 1 get 0.587 mul add - color_packet 2 get 0.114 mul add - cvi - /gray_packet exch def - compression 0 gt - { - /number_pixels 1 def - } - { - currentfile byte readhexstring pop 0 get - /number_pixels exch 1 add def - } ifelse - 0 1 number_pixels 1 sub - { - pixels exch gray_packet put - } for - pixels 0 number_pixels getinterval -} bind def - -/GrayPseudoClassPacket -{ - % - % Get a PseudoClass packet; convert to grayscale. - % - % Parameters: - % index: index into the colormap. - % length: number of pixels minus one of this color (optional). - % - currentfile byte readhexstring pop 0 get - /offset exch 3 mul def - /color_packet colormap offset 3 getinterval def - color_packet 0 get 0.299 mul - color_packet 1 get 0.587 mul add - color_packet 2 get 0.114 mul add - cvi - /gray_packet exch def - compression 0 gt - { - /number_pixels 1 def - } - { - currentfile byte readhexstring pop 0 get - /number_pixels exch 1 add def - } ifelse - 0 1 number_pixels 1 sub - { - pixels exch gray_packet put - } for - pixels 0 number_pixels getinterval -} bind def - -/PseudoClassPacket -{ - % - % Get a PseudoClass packet. - % - % Parameters: - % index: index into the colormap. - % length: number of pixels minus one of this color (optional). - % - currentfile byte readhexstring pop 0 get - /offset exch 3 mul def - /color_packet colormap offset 3 getinterval def - compression 0 gt - { - /number_pixels 3 def - } - { - currentfile byte readhexstring pop 0 get - /number_pixels exch 1 add 3 mul def - } ifelse - 0 3 number_pixels 1 sub - { - pixels exch color_packet putinterval - } for - pixels 0 number_pixels getinterval -} bind def - -/PseudoClassImage -{ - % - % Display a PseudoClass image. - % - % Parameters: - % class: 0-PseudoClass or 1-Grayscale. - % - currentfile buffer readline pop - token pop /class exch def pop - class 0 gt - { - currentfile buffer readline pop - token pop /depth exch def pop - /grays columns 8 add depth sub depth mul 8 idiv string def - columns rows depth - [ - columns 0 0 - rows neg 0 rows - ] - { currentfile grays readhexstring pop } image - } - { - % - % Parameters: - % colors: number of colors in the colormap. - % colormap: red, green, blue color packets. - % - currentfile buffer readline pop - token pop /colors exch def pop - /colors colors 3 mul def - /colormap colors string def - currentfile colormap readhexstring pop pop - systemdict /colorimage known - { - columns rows 8 - [ - columns 0 0 - rows neg 0 rows - ] - { PseudoClassPacket } false 3 colorimage - } - { - % - % No colorimage operator; convert to grayscale. - % - columns rows 8 - [ - columns 0 0 - rows neg 0 rows - ] - { GrayPseudoClassPacket } image - } ifelse - } ifelse -} bind def - -/DisplayImage -{ - % - % Display a DirectClass or PseudoClass image. - % - % Parameters: - % x & y translation. - % x & y scale. - % label pointsize. - % image label. - % image columns & rows. - % class: 0-DirectClass or 1-PseudoClass. - % compression: 0-RunlengthEncodedCompression or 1-NoCompression. - % hex color packets. - % - gsave - currentfile buffer readline pop - token pop /x exch def - token pop /y exch def pop - x y translate - currentfile buffer readline pop - token pop /x exch def - token pop /y exch def pop - currentfile buffer readline pop - token pop /pointsize exch def pop - /Helvetica findfont pointsize scalefont setfont - x y scale - currentfile buffer readline pop - token pop /columns exch def - token pop /rows exch def pop - currentfile buffer readline pop - token pop /class exch def pop - currentfile buffer readline pop - token pop /compression exch def pop - class 0 gt { PseudoClassImage } { DirectClassImage } ifelse - grestore -} bind def -%%EndProlog -%%Page: 1 1 -%%PageBoundingBox: 0 0 363 162 -userdict begin -%%BeginData: -DisplayImage -0 0 -363.429 161.829 -12 -530 236 -1 -0 -0 -30 -030209 -0d0c2b -24212c -040555 -010179 -262569 -7a7b7b -070785 -231e9b -7b7987 -746ed4 -7d837c -817e88 -887ce0 -848677 -918f9b -9996a3 -b0aeb6 -a19eab -bdbac4 -bdb9f4 -c1bec9 -c3beff -d4d2dc -d8d5e1 -e1dee9 -f6f4f9 -e3e4dc -c5c9c0 -807e7f -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000300030004000300040004000400040007000700040004000700070007000700 -070004000400040004000400040004000400040003000300040004000300030004000700 -040004000400040004000400070004000400040004000400040004000400070007000700 -070004000400040004000400070004000400040004000400040004000400040004000400 -040003000400040004000400040004000400040004000300040004000400040004000400 -040004000400040004000400040003000400040004000400040004000400040004000300 -040004000400040004000400040004000400040004000400040003000400040004000400 -040004000400040004000300040004000400040004000400040004000400040004000400 -040003000400040004000400040004000400040004000300040004000400040004000400 -040004000400040004000400040003000400040004000400040004000400040004000300 -040004000400040004000400040004000400040004000400040003000400040004000400 -040004000400040004000300040004000400040004000400040004000400040004000400 -040003000400040004000400040004000400040004000300040004000400040004000400 -040004000400040004000400040003000400040004000400040004000400040004000300 -040004000400040004000400040004000400040004000400040003000400040004000400 -040004000400040004000300040004000400040004000400040004000400040004000400 -040003000400040004000400040004000400040004000300040004000400040004000400 -040004000400040004000400040003000400040004000400040004000400040004000300 -040004000400040004000400040004000400040004000400040003000400040004000400 -040004000400040004000300040004000400040004000400040004000400040004000400 -040003000400040004000400040004000400040004000300040004000400040004000400 -040004000400040004000400040003000400040004000400040004000400040004000300 -040004000400040004000400040004000400040004000400040003000400040004000400 -040004000400040004000300040004000400040004000400040004000400040004000400 -040003000400040004000400040004000400040004000300040004000400040004000400 -030004000400030000000100000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001b001a0017000800040004000700070007000700 -080007000700070007000700070007000700070007000700070007000700070007000700 -040007000700070004000800070007000700070007000700080004000700080004000700 -040007000700080008000700070007000700070007000700070007000800070007000700 -070007000700070008000700040007000700070007000700070007000700070007000700 -070008000700070007000700070007000700040008000700040007000700070007000700 -070007000700070007000700070008000700070007000700070007000700040008000700 -040007000700070007000700070007000700070007000700070008000700070007000700 -070007000700040008000700040007000700070007000700070007000700070007000700 -070008000700070007000700070007000700040008000700040007000700070007000700 -070007000700070007000700070008000700070007000700070007000700040008000700 -040007000700070007000700070007000700070007000700070008000700070007000700 -070007000700040008000700040007000700070007000700070007000700070007000700 -070008000700070007000700070007000700040008000700040007000700070007000700 -070007000700070007000700070008000700070007000700070007000700040008000700 -040007000700070007000700070007000700070007000700070008000700070007000700 -070007000700040008000700040007000700070007000700070007000700070007000700 -070008000700070007000700070007000700040008000700040007000700070007000700 -070007000700070007000700070008000700070007000700070007000700040008000700 -040007000700070007000700070007000700070007000700070008000700070007000700 -070007000700040008000700040007000700070007000700070007000700070007000700 -070008000700070007000700070007000700040008000700040007000700070007000700 -070007000700070007000700070008000700070007000700070007000700040008000700 -040007000700070007000700070007000700070007000700070008000700070007000700 -070007000700040008000700040007000700070007000700070007000700070007000700 -070008000700070007000700070007000700070007000500020019001a001a001b001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001c00000000001a00 -17001c00170017001c001b0017001700170017001700170017001700150017001b001800 -0a0007000400040004000400040004000400040004000400040004000400040004000400 -030004000400040004000400040004000700070007000400050004000700040007000400 -070007000400040007000700070004000400040004000400040004000400040004000400 -040004000400040004000400040004000700040004000400040004000400040004000700 -040004000700040004000400040004000400040004000400040007000400040004000400 -040004000400040004000700040004000700040004000400040004000400040004000400 -040007000400040004000400040004000400040004000700040004000700040004000400 -040004000400040004000400040007000400040004000400040004000400040004000700 -040004000700040004000400040004000400040004000400040007000400040004000400 -040004000400040004000700040004000700040004000400040004000400040004000400 -040007000400040004000400040004000400040004000700040004000700040004000400 -040004000400040004000400040007000400040004000400040004000400040004000700 -040004000700040004000400040004000400040004000400040007000400040004000400 -040004000400040004000700040004000700040004000400040004000400040004000400 -040007000400040004000400040004000400040004000700040004000700040004000400 -040004000400040004000400040007000400040004000400040004000400040004000700 -040004000700040004000400040004000400040004000400040007000400040004000400 -040004000400040004000700040004000700040004000400040004000400040004000400 -040007000400040004000400040004000400040004000700040004000700040004000400 -040004000400040004000400040007000400040004000400040004000400040004000700 -040004000700040004000400040004000400040004000400040007000400040004000400 -040004000400040004000700040004000700040004000400040004000400040004000400 -040007000400040004000400040004000400040004000700040004000700040004000400 -040004000400040004000400040007000400040004000400040004000400040004000700 -040004000700040004000400040004000400040004000400040004000700040004000400 -0400030001001a0017001700170017001c001c0017001700170017001700170017001700 -1b0017001700170017001c0017001700170017001b0017001c0017001700170017001700 -170017001c0017001700170017001c001c0017001700170017001c001c0017001b001700 -17001c00170017000f00000000001a0017001b0006000000000000000000000000000000 -000000000000000000001700170018000d00040004000400040004000400040004000400 -040003000300030003000300040004000400040004000400040004000400070004000700 -040007000300030007000800040004000700030004000700070007000400070003000300 -040004000400040003000400040004000300040004000300040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400030000001a001c000f000e0006000e000f00 -0e000b000e000600060006000b000e0006000e001c001700170006000600060006000600 -06000e00060006000b000e0006000e000e000e001c00170017000e00060006000f000600 -0e000600060006000e00060006000e0006000e0017001c000600000000001a0017001700 -11001a001a001a001a001a001a001a001a001a001a001a001a001a001c0017000a000800 -040004000400040004000400040004000400040003000300040004000400040007000400 -040004000400040004000700070007000700040003000400040004000400070004000400 -040003000700070004000300040004000400040004000400040004000400040004000400 -040004000400040004000700070004000400070004000700070004000700070004000700 -070004000700040007000700070004000700040007000700040007000400070004000700 -070004000700070004000700070004000700040007000700070004000700040007000700 -040007000400070004000700070004000700070004000700070004000700040007000700 -070004000700040007000700040007000400070004000700070004000700070004000700 -070004000700040007000700070004000700040007000700040007000400070004000700 -070004000700070004000700070004000700040007000700070004000700040007000700 -040007000400070004000700070004000700070004000700070004000700040007000700 -070004000700040007000700040007000400070004000700070004000700070004000700 -070004000700040007000700070004000700040007000700040007000400070004000700 -070004000700070004000700070004000700040007000700070004000700040007000700 -040007000400070004000700070004000700070004000700070004000700040007000700 -070004000700040007000700040007000400070004000700070004000700070004000700 -070004000700040007000700070004000700040007000700040007000400070004000700 -070004000700070004000700070004000700040007000700070004000700040007000700 -040007000400070004000700070004000700070004000700070004000700040007000700 -070004000700040007000700040007000400070004000700070004000700070004000700 -070004000700040007000700070004000700040007000700040007000400070004000700 -070004000700070004000700070004000700040007000700070004000700040007000700 -040007000400070004000700070004000700070004000700070004000700040007000700 -070004000700040007000700040007000400070004000700070004000700070004000700 -070004000700040007000700070004000700040007000700040004000400040004000400 -00001a00170006001a001a001a001b001a001a001a001a001a001a001a001a001a001c00 -1a001c0017000e001a001a001a001a001a001a001a001a001a001a001a001a001a001c00 -1a001b001c0006001a001a001a001a001a001a001a001a001a001a001a001a001a001c00 -1a0017000e00000000001a001c0017000600000000000000000000000000000000000000 -00000000000017001c0017000a0004000400030004000400040004000400040004000400 -040004000400040007000700070004000400040004000400040007000700070004000400 -03001a000700080004000400040004001a00030004000700030007000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -0400040004000400040004000400030001001a00170006001a001b0017001c0017001700 -17001700170017001c00170017000e001a0017001b000e001a0017001c0017001b001c00 -17001b001c001c0017001700170006001a001c0017000e001a001c001c001b001c001700 -17001c0017001a0017001c001c000e001b0017000600000000001a00170017001b001a00 -1a001a001a001a001a001a001a001a001a001a001b001a001c0017000a00050004000400 -040004000400040004000400040004000400040004000700070007000400040004000400 -0300040004000400070007000400030003001a000300030004000400040004001a000300 -040004000300030004000400040004000400040003000400040004000400040004000400 -040004000400040004000400040004000700040004000700040004000400040004000400 -040004000400040004000400040004000400040004000400040004000700040004000700 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000700040004000700040004000400040004000400040004000400040004000400 -040004000400040004000400040004000700040004000700040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400070004000700 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000700040004000700040004000400040004000400040004000400040004000400 -040004000400040004000400040004000700040004000700040004000400040004000400 -040004000400040004000400040004000400040004000400040004000700040004000700 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400070004000700040004000400040004000400040004000400040004000400 -040004000400040004000400040004000700040004000700040004000400040004000400 -040004000400040004000400040004000400040004000400040004000700040004000700 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000700040004000700040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400070004000700040004000400040004000400 -040004000400040004000400040004000400040004000400040004000700040004000700 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000700040004000700040004000400040004000400040004000400040004000400 -040004000400040004000400040004000700040004000700040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400030001001a00 -170006001a001700110017001c001c001c001c0017001c001c001700170006001a001c00 -170006001a0017001b001100170017001c001700170017001c001b001c0006001a001700 -170006001a0017001700170017001c001b001700170011001b00170017000e001a001700 -0b00000000001a001c001700060000000000000000000000000000000000000000000000 -000017001c0018000a000400040004000400040004000400040004000400040007000700 -040004000400040004000400030004000400030003000300030003000300040003001a00 -0400040004000300030004001a0005000400030003000500040004000400040004000400 -030004000400040004000400040004000400040004000700040007000400040004000400 -040004000400040004000400070004000400040004000700040007000400040004000700 -040004000700040004000400040004000400040004000400070004000400040004000700 -040007000400040004000700040004000700040004000400040004000400040004000400 -070004000400040004000700040007000400040004000700040004000700040004000400 -040004000400040004000400070004000400040004000700040007000400040004000700 -040007000400040004000400040004000400040004000400070004000400040004000700 -040007000400040004000700040004000700040004000400040004000400040004000400 -070004000400040004000700040007000400040004000700040004000700040004000400 -040004000400040004000400070004000400040004000700040007000400040004000700 -040004000700040004000400040004000400040004000400070004000400040004000700 -040007000400040004000700040007000400040004000400040004000400040004000400 -070004000400040004000700040007000400040004000700040004000700040004000400 -040004000400040004000400070004000400040004000700040007000400040004000700 -040004000700040004000400040004000400040004000400070004000400040004000700 -040007000400040004000700040004000700040004000400040004000400040004000400 -070004000400040004000700040007000400040004000700040007000400040004000400 -040004000400040004000400070004000400040004000700040007000400040004000700 -040004000700040004000400040004000400040004000400070004000400040004000700 -040007000400040004000700040004000700040004000400040004000400040004000400 -070004000400040004000700040007000400040004000700040004000700040004000400 -040004000400040004000400070004000400040004000700040007000400040004000400 -04000400040004000700030000001a00170006001a001b0017001c00170017001b001c00 -17001c0017001700170006001a001b001c0006001a001c001c0000000000000000000000 -00000000000011001b000e001a001c00170006001a001b00060000001c001c001c001700 -1700000006001c00170006001a0017000600000000001a001700170017001a001a001a00 -1a001a001a001a001a001a001a001a001a001a00150017000d0007000400040004000300 -03001a0003001a001a001a0004000700030003001a001a001a001a000300030004000300 -1a001a001a001a000300030003001a000300040004001a00030004001a0003001a001a00 -1a0003000300040003001a001a001a001a00030003001a001a000300040004001a001a00 -040004000400040004000400070004000400040007000400040004000400040004000400 -040004000400070004000400070004000700040004000400040004000400040004000400 -040004000700040004000400040007000400040007000400040007000400070004000400 -040004000400070004000400040004000700040004000400040004000400070004000400 -070004000700040004000400040004000400040004000400040004000700040004000400 -040007000400040007000400040004000700040007000400070004000400040007000400 -040004000400040004000400040004000400070004000400070004000700040004000400 -040004000400040004000400040004000700040004000400040007000400040007000400 -040007000400070004000400040004000400070004000400040004000700040004000400 -040004000400070004000400070004000700040004000400040004000400040004000400 -040004000700040004000400040007000400040007000400040004000700040007000400 -070004000400040007000400040004000400040004000400040004000400070004000400 -070004000700040004000400040004000400040004000400040004000700040004000400 -040007000400040007000400040007000400070004000400040004000400070004000400 -040004000700040004000400040004000400070004000400070004000700040004000400 -040004000400040004000400040004000700040004000400040007000400040007000400 -040004000700040007000400070004000400040007000400040004000400040004000400 -040004000400070004000400070004000700040004000400040004000400040004000400 -040004000700040004000400040007000400040007000400040007000400070004000400 -040004000400070004000400040004000700040004000400040004000400070004000400 -070004000700040004000400040004000400040004000400040004000700040004000400 -0400070004000400070004000400040007000400040004000400030000001a0017000e00 -1a0017001c0017001c001c0017001c0017001c0017001c001c0006001a00170017000600 -1a001c001700000000000000000000000000000000001700170006001a001c001c000e00 -1a001b001c000000000017001b001700000000001b001c00170006001a00170006000000 -00001a001c00170006000000000000000000000000000000000000000000000000001700 -180014000a000800070004000400030003001a001a00030003001a001a00030003001a00 -1a000300050019001a00030003001a001a00010003001a001a00040003001a0004000400 -1a000300040003001a001a00040003001a001a00030004001a001a00040003001a001a00 -040003001a000500030003001a0003000400040004000400040004000400040007000400 -040004000400070004000700040007000400070004000400040004000400040004000400 -070004000700040004000700040007000700040004000400040007000400040004000400 -040004000400040004000400040004000700040004000400040007000700040004000400 -040007000400070004000400040004000400040004000400070004000700040004000700 -040007000700040004000400040007000400040004000400040004000400040004000400 -040004000400040007000400040004000400070004000700040007000400070004000400 -040004000400040004000400070004000700040004000700040007000700040004000400 -040007000400040004000400040004000400040004000400040004000700040004000400 -040007000700040004000400040007000400070004000400040004000400040004000400 -070004000700040004000700040007000700040004000400040007000400040004000400 -040004000400040004000400040004000400040007000400040004000400070004000700 -040007000400070004000400040004000400040004000400070004000700040004000700 -040007000700040004000400040007000400040004000400040004000400040004000400 -040004000700040004000400040007000700040004000400040007000400070004000400 -040004000400040004000400070004000700040004000700040007000700040004000400 -040007000400040004000400040004000400040004000400040004000400040007000400 -040004000400070004000700040007000400070004000400040004000400040004000400 -070004000700040004000700040007000700040004000400040007000400040004000400 -040004000400040004000400040004000700040004000400040007000700040004000400 -040007000400070004000400040004000400040004000400070004000700040004000700 -040007000700040004000400040007000400040004000400040004000400040004000400 -040004000400040000001a001c000f001a001c0017001c0017001b001b001c0017001700 -1c001700170006001a00170017000e001a00170017000000000000000000000000000000 -00001700170006001a001700170006001a00170017001700000000001c00000000001700 -1c001b001c000e001a001c000600000000001a0017001c001b001a001a001a001a001a00 -1a001a001a001a001a001a001a001a00170016000a000800070004000300040003001a00 -03000300030003001a0003000300030001000300010003001a00030001001a0003000300 -030003000400030003001a0005001a0004000300040003001a0003000300030003001a00 -040003001a0003000300030001001a000300040003001a0004001a000300030004000400 -040004000400040004000400040004000400040004000700040004000400040004000400 -070004000700040004000700040007000400040004000400040007000400040004000400 -040004000400040004000700040007000400070007000400040007000700040007000400 -040007000400040004000400070004000400040004000400070004000700040004000700 -040007000400040004000400040007000400040004000400040004000400040004000700 -040007000400070004000700070004000400040004000400040004000400040004000700 -040004000400040004000400070004000700040004000700040007000400040004000400 -040007000400040004000400040004000400040004000700040007000400070007000400 -040007000700040007000400040007000400040004000400070004000400040004000400 -070004000700040004000700040007000400040004000400040007000400040004000400 -040004000400040004000700040007000400070004000700070004000400040004000400 -040004000400040004000700040004000400040004000400070004000700040004000700 -040007000400040004000400040007000400040004000400040004000400040004000700 -040007000400070007000400040007000700040007000400040007000400040004000400 -070004000400040004000400070004000700040004000700040007000400040004000400 -040007000400040004000400040004000400040004000700040007000400070004000700 -070004000400040004000400040004000400040004000700040004000400040004000400 -070004000700040004000700040007000400040004000400040007000400040004000400 -040004000400040004000700040007000400070007000400040007000700040007000400 -040007000400040004000400070004000400040004000400070004000700040004000700 -040007000400040004000400040007000400040004000400040004000400040004000700 -04000700040007000400070004000400040004000400030000001a001c000e001a001700 -17001c001c00170017001c0017001c0017001b0017000e001a0017001c000e001a001700 -1c0000001c0017001700170011001b000000170017000e001a001c001b0006001a001700 -17001c00170000000000000017001c001700110017000e001a0017000600000000001a00 -1c0017000600000000000000000000000000000000000000000000000000170017001400 -0a000700070004000400030003001a0003000400030003001a000100030001001a001a00 -1a001a001a00010003001a0003000300040004000300030003001a001a00040004000300 -030003001a0003000300030003001a00030004001a0003000300030003001a0004000400 -030003001a00040003000300040004000400040007000400070004000700040007000400 -040004000400040007000400070004000400040004000400040004000400040004000700 -040004000400040004000400070004000700040004000700040004000400040004000400 -040004000400040004000400040004000400040004000400070004000400040007000400 -070004000400040004000400040004000400040004000700040004000400040004000400 -070004000700040004000700040004000400040004000400040004000400040007000400 -070004000700040007000400040004000400040007000400070004000400040004000400 -040004000400040004000700040004000400040004000400070004000700040004000700 -040004000400040004000400040004000400040004000400040004000400040004000400 -070004000400040007000400070004000400040004000400040004000400040004000700 -040004000400040004000400070004000700040004000700040004000400040004000400 -040004000400040007000400070004000700040007000400040004000400040007000400 -070004000400040004000400040004000400040004000700040004000400040004000400 -070004000700040004000700040004000400040004000400040004000400040004000400 -040004000400040004000400070004000400040007000400070004000400040004000400 -040004000400040004000700040004000400040004000400070004000700040004000700 -040004000400040004000400040004000400040007000400070004000700040007000400 -040004000400040007000400070004000400040004000400040004000400040004000700 -040004000400040004000400070004000700040004000700040004000400040004000400 -040004000400040004000400040004000400040004000400070004000400040007000400 -070004000400040004000400040004000400040004000700040004000400040004000400 -070004000700040004000700040004000400040004000400040004000700040004000400 -0400030001001a00170006001a001b001c001b00170017001c001b0017001c001b001100 -17000e001a001c0017000e001a001c001700000017001c001c0017001c001c0000001700 -1c000e001a001c00170006001a0017001c0017001c00000000000000170017001c001700 -170006001a0017000600000000001a00170017001b001a001a001a001a001a001a001a00 -1a001a001a001a001a001b001c001b000d000800070007000400030003001a0004000400 -030003001a00010003001a001a000400030003001a00010003001a000300040007000700 -0400030003001a000400190004000400030003001a0003000300030001001a0004000400 -1a0003000300030003001a0004000400030004001a000400030003000400040004000400 -040004000700040004000400070004000400040004000700040004000400040007000400 -040004000400040007000400040004000400070004000400040004000400040004000400 -070004000400070004000400040004000400040004000400070004000400070004000400 -040004000400040004000400040004000400040007000400040004000400040007000400 -040004000400070004000400040004000400040004000400070004000400070004000400 -040004000400040004000400040004000700040004000400070004000400040004000700 -040004000400040007000400040004000400040007000400040004000400070004000400 -040004000400040004000400070004000400070004000400040004000400040004000400 -070004000400070004000400040004000400040004000400040004000400040007000400 -040004000400040007000400040004000400070004000400040004000400040004000400 -070004000400070004000400040004000400040004000400040004000700040004000400 -070004000400040004000700040004000400040007000400040004000400040007000400 -040004000400070004000400040004000400040004000400070004000400070004000400 -040004000400040004000400070004000400070004000400040004000400040004000400 -040004000400040007000400040004000400040007000400040004000400070004000400 -040004000400040004000400070004000400070004000400040004000400040004000400 -040004000700040004000400070004000400040004000700040004000400040007000400 -040004000400040007000400040004000400070004000400040004000400040004000400 -070004000400070004000400040004000400040004000400070004000400070004000400 -040004000400040004000400040004000400040007000400040004000400040007000400 -040004000400070004000400040004000400040004000400070004000400070004000400 -040004000400070004000400040004000400040001001a0017000b001a001c0017001c00 -1c00170017001c00170017001c001b001c0006001a0017001c000e001a00170017000000 -1b001b00170017001700170000001b001c0006001a001700170006001a0017001c001b00 -0000000017000000000017001b00170017000e001b0017000600000000001a001c001700 -06000000000000000000000000000000000000000000000000001c001c0017000a000700 -070007000400040003001a0004000300040003001a00030003001a000300030003000300 -1a00030003001a0003000300030004001a00050003001a00030004001a00030003000300 -1a0001000300030001001a00040004001a0003000300030001001a000400040003001a00 -04001a000400030004000400040004000700040004000400040004000400040004000400 -040004000400040004000700040004000700040004000700040004000700040004000400 -040007000400070004000700070004000400040004000400040007000400070004000700 -070004000400040004000400040007000400070004000400070004000400040004000700 -040004000700040004000700040004000700040004000400040007000400070004000700 -070004000400040004000400040007000400070007000400040007000700040004000400 -040004000400040004000400040004000400040004000700040004000700040004000700 -040004000700040004000400040007000400070004000700070004000400040004000400 -040007000400070004000700070004000400040004000400040007000400070004000400 -070004000400040004000700040004000700040004000700040004000700040004000400 -040007000400070004000700070004000400040004000400040007000400070007000400 -040007000700040004000400040004000400040004000400040004000400040004000700 -040004000700040004000700040004000700040004000400040007000400070004000700 -070004000400040004000400040007000400070004000700070004000400040004000400 -040007000400070004000400070004000400040004000700040004000700040004000700 -040004000700040004000400040007000400070004000700070004000400040004000400 -040007000400070007000400040007000700040004000400040004000400040004000400 -040004000400040004000700040004000700040004000700040004000700040004000400 -040007000400070004000700070004000400040004000400040007000400070004000700 -070004000400040004000400040007000400070004000400070004000400040004000700 -040004000700040004000700040004000700040004000400040007000400070004000700 -070004000400040004000400040007000400070004000400040004000400040004000300 -00001a0017000f001a001c001b0000000000000000000000000000000000170017000600 -1a00170017000e001a00170017000000110017001c001c001c0017000000170017000600 -1a001b001c0006001a0011001700000000001c001c001c00000000001c001c0017000e00 -1a0017000600000000001a0017001c0017001a001a001a001a001a001a001a001a001a00 -1a001a001a001a00170018000a000700040007000300030003001a001a00030003001a00 -1a00030005001a001a00030003001a001900050003001a001a00030001001a001a000300 -01001a000300040003001a00050003001a001a00030003001a001a00030004001a001a00 -030003001a001a00030004001a000500030003001a000300040004000700040004000400 -070004000400040007000400040004000400040007000400040004000400070004000400 -040004000700040004000400040007000700040004000400040004000400070004000400 -040004000700040004000400040004000400070004000400040004000700040004000400 -040004000400040007000400040004000400070004000400040004000700040004000400 -040007000700040004000400040004000400070004000400040004000700040004000400 -040004000700040004000400070004000400040007000400040004000400040007000400 -040004000400070004000400040004000700040004000400040007000700040004000400 -040004000400070004000400040004000700040004000400040004000400070004000400 -040004000700040004000400040004000400040007000400040004000400070004000400 -040004000700040004000400040007000700040004000400040004000400070004000400 -040004000700040004000400040004000700040004000400070004000400040007000400 -040004000400040007000400040004000400070004000400040004000700040004000400 -040007000700040004000400040004000400070004000400040004000700040004000400 -040004000400070004000400040004000700040004000400040004000400040007000400 -040004000400070004000400040004000700040004000400040007000700040004000400 -040004000400070004000400040004000700040004000400040004000700040004000400 -070004000400040007000400040004000400040007000400040004000400070004000400 -040004000700040004000400040007000700040004000400040004000400070004000400 -040004000700040004000400040004000400070004000400040004000700040004000400 -040004000400040007000400040004000400070004000400040004000700040004000400 -040007000700040004000400040004000400070004000400040004000700040004000400 -0400070004000400040004000400030000001a00170006001a0017001700000000000000 -00000000000000000000170017000e001a0017001c0006001a001c001c00000000000000 -000000000000000000001100170006001a00170017000e001a001a000600000017001700 -170017001700000006001b001c0006001a001c000600000000001a001700170006000000 -000000000000000000000000000000000000000000001c001b0016000a00080007000400 -0400030003001a0003001a001a001a0004000700030003001a001a001a0003001a001a00 -030003001a001a001a001a000300040003001a000400030004000300190004001a000300 -1a001a001a0003000400030003001a001a001a001a00030003001a001a00030003000400 -1a001a000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400030001001b00 -170006001a001c001c0017001c001b00170017001c00170017001c001c0006001a001700 -170006001a00170017001c0017001c0017001c00170017001c001b001c000e001a001700 -17000b001a001c0017001c001c0017001c00170017001c0017001c0017000e001a001700 -0600000000001a001c001c0017001a001a001a001a001a001a001a001a001a001a001a00 -1a001a00150019000a000500040004000300040003001a00040003000400030004000400 -040003000300030003000400040003000400040004000300030004000400030004000400 -040004000400040003000400040004000400040003000400040004000300040004000300 -030003000400040003000400040004000400030004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000700 -07000700040004000400030001001a00170006001a001c001700170017001c0017001c00 -17001c00170017001c0006001a001c001c0006001a00170017001c0017001c0017001700 -1c001c00170017001c0006001a001c00170006001a001700170017001c001c0017001700 -17001700170017001c0006001a0017000600000000001a00170017000600020000000000 -0000000000000000000000000000000000001c00190014000a0008000400040007000400 -04001a000300030007000700040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -0400040004000400040004000400040004000400070004000300030001001a0017000b00 -1c000b0006000b00060006000e000e000600060006000e0006000e001a00170017000f00 -1c000b000600060006000e0006000e000600060006000e0006000e001a001b001c000600 -11000e000b000f00060006001d00060006000e00060006000e000e001a001b0006000000 -00001a001700170017001b001a001a001a001a001a001a001a001a001a001a001a001a00 -160018000d000400040008000400040004001a0004000800040004000400040007000400 -070007000700040004000700040004000400040007000700040004000700070004000400 -040004000400040007000700040004000700070004000700070007000700040007000700 -040004000700040004000700040007000400070004000700070007000400040004000400 -070004000400070007000400040004000400070004000400040004000400040007000400 -040004000700070004000400040007000400040007000700040007000700040007000400 -040004000400040007000400040007000700040007000400040004000400040007000700 -040004000400070004000400040004000400040007000400040004000700070007000400 -070007000700070004000400040004000700040004000700070004000400040004000400 -070007000400040004000400070004000400070007000400040004000400070004000400 -040004000400040007000400040004000700070004000400040007000400040007000700 -040007000700040007000400040004000400040007000400040007000700040007000400 -040004000400040007000700040004000400070004000400040004000400040007000400 -040004000700070007000400070007000700070004000400040004000700040004000700 -070004000400040004000400070007000400040004000400070004000400070007000400 -040004000400070004000400040004000400040007000400040004000700070004000400 -040007000400040007000700040007000700040007000400040004000400040007000400 -040007000700040007000400040004000400040007000700040004000400070004000400 -040004000400040007000400040004000700070007000400070007000700070004000400 -040004000700040004000700070004000400040004000400070007000400040004000400 -070004000400070007000400040004000400070004000400040004000400040007000400 -040004000700070004000400040007000400040007000700040007000700040007000400 -040004000400040007000400040007000700040007000400040004000400040007000700 -040004000400070004000400040004000400040007000400040004000700070007000400 -070007000700070004000400040004000700040004000700070004000400040004000400 -040004000300030001001a00170017001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001c001c001c001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001c0017001c001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a0011000600000000001a0017001100170017001b001c0017001700 -17001700170017001700170015001400190018000a000300040003000300030003000500 -030003000300040004000300040004000400030004000300040003000400030004000300 -040004000300040003000400030003000400040003000400030004000300030003000400 -030003000400030004000300040004000400030004000400030003000400030004000300 -040003000400030003000400040003000400040003000300040004000300040004000300 -040003000400040003000400040003000400030003000300030004000300040004000300 -040004000300030004000400040004000300030004000300040004000300030004000400 -040004000300030004000300040004000300040004000300040003000400040003000400 -040003000400030003000400040003000400030004000300030004000400030004000400 -030003000400040003000400030004000400030004000300040003000400040003000300 -040004000300040004000300040003000400040003000400040003000400030003000300 -030004000300040004000300040004000300030004000400040004000300030004000300 -040004000300030004000400040004000300030004000300040004000300040004000300 -040003000400040003000400040003000400030003000400040003000400030004000300 -030004000400030004000400030003000400040003000400030004000400030004000300 -040003000400040003000300040004000300040004000300040003000400040003000400 -040003000400030003000300030004000300040004000300040004000300030004000400 -040004000300030004000300040004000300030004000400040004000300030004000300 -040004000300040004000300040003000400040003000400040003000400030003000400 -040003000400030004000300030004000400030004000400030003000400040003000400 -030004000400030004000300040003000400040003000300040004000300040004000300 -040003000400040003000400040003000400030003000300030004000300040004000300 -040004000300030004000400040004000300030004000300040004000300030004000400 -040004000300030004000300040004000300040004000300040003000400040003000400 -040003000400030003000400040003000400030004000300030004000400030004000400 -03000300040003000300030003000300030003000300030000001a00170017001c001700 -170017001700170017001c00170017001700170017001b0017001c001700170017001700 -17001c0017001700170017001700170017001c001c001700170011001700170017001700 -17001700170017001b0017001700170017001c001c00170017001b000600000000001a00 -1b0017001b00060006000b000e000b000600060006000600060006000e000e0006000600 -090001000100010001000100000000000100010001000100000001000000000001000000 -010000000000000000000000010001000000000000000000010000000000000001000000 -000000000100010000000100000000000000000001000000000000000000010000000100 -000000000000010000000000000000000100000000000000010000000000010000000000 -000001000000000000000000010001000000000001000000000001000000010000000100 -000001000100000000000000010001000000000000000000010000000000000001000000 -000001000000000001000000010000000000000000000000010001000000000000000000 -010001000000000001000000000000000100010000000100000000000000000001000000 -000000000100000000000100000000000000010000000000000000000100000000000000 -010000000000010000000000000001000000000000000000010001000000000001000000 -000001000000010000000100000001000100000000000000010001000000000000000000 -010000000000000001000000000001000000000001000000010000000000000000000000 -010001000000000000000000010001000000000001000000000000000100010000000100 -000000000000000001000000000000000100000000000100000000000000010000000000 -000000000100000000000000010000000000010000000000000001000000000000000000 -010001000000000001000000000001000000010000000100000001000100000000000000 -010001000000000000000000010000000000000001000000000001000000000001000000 -010000000000000000000000010001000000000000000000010001000000000001000000 -000000000100010000000100000000000000000001000000000000000100000000000100 -000000000000010000000000000000000100000000000000010000000000010000000000 -000001000000000000000000010001000000000001000000000001000000010000000100 -000001000100000000000000010001000000000000000000010000000000000001000000 -000001000000000001000000010000000000000000000000010001000000000000000000 -010001000000000001000000000000000100010000000100000000000000000001000000 -000000000100000000000100000000000000010000000000010000000100010001000100 -01000000010011000e000e00060006000f000c000e000600060006000600060006000600 -060006000600060009000600060006000e000b00060006001d000600060006000f000600 -060006000f000e000f000600060006000f000600060006000b0006000e0006000e000600 -0b0017001c0017000600000000001a001700170017000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -010000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000100000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000001c0017001c000600000000001a0017001c00 -170000001c001700170017001700170017001700170017001b001c001c001b0017001700 -1a0017001700170017001b001c00170017001700180018001b0018001800180017001b00 -18001800180018001700170018001700180018001800170018001b001800170018001800 -170017001b00180018001b00180018001800180018001800180017001b00180018001800 -180018001b001800180018001800180018001800180017001b0018001800180018001800 -1b001800180018001700170018001b001800170018001800170017001b00170018001700 -180018001800180017001700180017001800180018001800180018001800170018001b00 -1800180018001b001b001700180018001800180017001700180017001800180017001700 -18001b001800170018001800170017001b00180018001b00180018001800180018001800 -180017001b00180018001800180018001b00180018001800180018001800180018001700 -1b00180018001800180018001b001800180018001700170018001b001800170018001800 -170017001b00170018001700180018001800180017001700180017001800180018001800 -180018001800170018001b001800180018001b001b001700180018001800180017001700 -18001700180018001700170018001b00180017001800180017001700180018001b001b00 -180018001800180018001800180017001b00180018001800180018001b00180018001800 -1800180018001800180017001b00180018001800180018001b0018001800180017001700 -18001b001800170018001800170017001b00170018001700180018001800180017001700 -180017001800180018001800180018001800170018001b001800180018001b001b001700 -18001800180018001700170018001700180018001700170018001b001800170018001800 -170017001800180018001b00180018001800180018001800180017001b00180018001800 -180018001b001800180018001800180018001800180017001b0018001800180018001800 -1b001800180018001700170018001b001800170018001800170017001b00170018001700 -180018001800180017001700180017001800180018001800180018001800170018001b00 -1800180018001b001b001700180018001800180017001700180017001800180017001700 -18001b00180017001800180017001700180018001b001b00180018001800180018001800 -1800170018001b0018001800180018001b001b0017001700180018001800180018001800 -170017001700170018001700180019001700170017001700170017001700170017001700 -170017001700170018001400170017001700170017001700170017001b00170017001700 -170017001700170017001700170017001700170017001b001c0017001700110000001c00 -170017000600000000001a0017001700170000001b001700170017001700170017001700 -1700170017001b0017001700170017001700170017001b00170017001800170017001800 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170018001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001800180018001800180018001700170019001700170018001800170017001700 -170017001700170017001700170017001700170017001700170019001700170017001700 -18001700170017001700170017001700170017001700180017001700170017001b001700 -1700170017001b0017001b000000170017001c000600000000001a00170017001c000000 -170017001700170017001700170017001700180018001600180018001800180018001800 -170017001700180018001800180018001b00170017001700170017001700170017001700 -17001700170017001b001700170017001700170017001700170017001700170017001800 -170017001700170018001700170017001700170017001b001700170017001b0017001700 -1700170018001700170017001700170017001b001700170017001b001700170017001700 -1700170017001700170017001700170017001700170017001b001b001700170017001700 -1700170017001700170017001800170017001700170017001b0017001700170017001700 -17001b001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001800170017001700170018001700170017001700170017001b00 -1700170017001b00170017001700170018001700170017001700170017001b0017001700 -17001b001700170017001700170017001700170017001700170017001700170017001700 -1b001b001700170017001700170017001700170017001700180017001700170017001700 -1b001700170017001700170017001b001700170017001700170017001700170017001700 -17001700170017001700170017001700170017001800170017001b001700170018001700 -170017001700170017001b001700170017001b0017001700170017001800170017001700 -1700170017001b001700170017001b001700170017001700170017001700170017001700 -1700170017001700170017001b001b001700170017001700170017001700170017001700 -1800170017001700170017001b001700170017001700170017001b001700170017001700 -170017001700170017001700170017001700170017001700170017001700170018001700 -1b0017001700170018001700170017001700170017001b001700170017001b0017001700 -1700170018001700170017001700170017001b001700170017001b001700170017001700 -1700170017001700170017001700170017001700170017001b001b001700170017001700 -1700170017001700170017001800170017001700170017001b0017001700170017001700 -17001b001700170017001700170017001700170017001700170017001700170017001700 -17001700170017001800170017001b001700170018001700170017001700170017001b00 -1700170017001b0017001700180017001700170017001700180018001800180018001700 -170017001700170017001800170017001700180017001800170018001800170018001800 -180017001800170018001700170018001700170017001800170017001700180018001800 -170017001700170017001b0017001700170017001700170017001c00000017001c001700 -0600000000001a0017001c00170000001700170017001700170017001700170017001800 -180019001600180018001800180017001700170017001700180018001800180017001700 -170017001700170017001b0017001b001700170017001700170017001700170017001700 -1b0017001700170017001700170017001b00170017001700170017001800170017001800 -17001700170017001700170017001b001700170017001700180017001700180017001700 -170017001700170017001b001700170017001700170017001b0017001700170017001700 -170017001700170017001b001b00170018001700170017001b0017001700170017001700 -17001700170017001b00170017001700170017001700170017001b00170018001b001700 -17001b0017001700170017001b0017001700170017001700170017001b00170017001700 -17001700180017001700180017001700170017001700170017001b001700170017001700 -180017001700180017001700170017001700170017001b00170017001700170017001700 -1b0017001700170017001700170017001700170017001b001b0017001800170017001700 -1b001700170017001700170017001700170017001b001700170017001700170017001700 -17001b00170018001b00170017001b0017001700170017001b0017001700170017001700 -170017001700170017001700170017001800170017001800170017001700170017001700 -17001b001700170017001700180017001700180017001700170017001700170017001b00 -1700170017001700170017001b0017001700170017001700170017001700170017001b00 -1b00170018001700170017001b001700170017001700170017001700170017001b001700 -17001700170017001700170017001b00170018001b00170017001b001700170017001700 -1b0017001700170017001700170017001700170017001700170017001800170017001800 -17001700170017001700170017001b001700170017001700180017001700180017001700 -170017001700170017001b001700170017001700170017001b0017001700170017001700 -170017001700170017001b001b00170018001700170017001b0017001700170017001700 -17001700170017001b00170017001700170017001700170017001b00170018001b001700 -17001b0017001700170017001b0017001700170017001700170017001700170017001700 -170017001800170017001800170017001700170017001700170018001700170017001700 -170018001800180018001700170017001700170017001700170017001800180018001700 -170018001700180018001700180017001700180018001700170017001800180018001800 -170017001700170018001800170018001800180018001700170017001700170017001700 -170017001700170000001c00170017000600000000001a00170017001700000017001700 -170018001700170017001800170018001800180018001800180018001700170017001700 -17001700170018001800180017001700170017001b001700180018001700170017001700 -170017001700170018001800180018001800180017001800170017001700170017001700 -180018001800180017001800180017001700180017001700170017001700170017001b00 -1800180017001800180017001700180017001700170017001700170017001b0017001800 -18001800180017001800180018001b001700170017001700170017001700170017001700 -170017001700170018001800170017001800170018001800170017001700170017001700 -170017001b00170017001700170017001700170017001800180018001800170018001800 -170017001700170017001700180018001800180017001800180017001700180017001700 -170017001700170017001b00180018001700180018001700170018001700170017001700 -1700170017001b001700180018001800180017001800180018001b001700170017001700 -170017001700170017001700170017001700170018001800170017001800170018001800 -170017001700170017001700170017001b00170017001700170017001700170017001800 -180018001800170018001800170017001700170017001700180018001800180017001800 -180017001700180017001700170017001700170017001b00180018001700180018001700 -1700180017001700170017001700170017001b0017001800180018001800170018001800 -18001b001700170017001700170017001700170017001700170017001700170018001800 -170017001800170018001800170017001700170017001700170017001b00170017001700 -170017001700170017001800180018001800170018001800170017001700170017001700 -1b0017001800180017001800180017001700180017001700170017001700170017001b00 -1800180017001800180017001700180017001700170017001700170017001b0017001800 -18001800180017001800180018001b001700170017001700170017001700170017001700 -170017001700170018001800170017001800170018001800170017001700170017001700 -170017001b00170017001700170017001700170017001800180018001800170018001800 -170017001700170017001700180018001800180017001800180017001700180017001700 -170017001800170017001700170017001700170017001700170017001700170017001700 -170017001700170017001800180017001800170018001800180018001700180017001700 -180018001700180018001700180017001800180018001800170017001800180018001700 -1800170017001700170017001700170017001700170017000000170017001c0006000000 -00001a0017001700170000001b0017001800180017001700180018001800170018001800 -180017001700170017001700170017001700170017001800180018001700170017001700 -170017001700170017001700170017001b00170017001700170017001800170017001700 -180017001b00170017001700170017001800170018001700180017001700170018001700 -170017001700170017001700170017001800170018001700170017001800170017001700 -170017001700170017001700170017001800170017001700180017001700170018001700 -1700170017001700170017001b0017001700170017001700180017001800170017001700 -1800170017001700170017001700170017001b0017001700170017001700170017001700 -170017001800170017001700180017001b00170017001700170017001800170018001700 -180017001700170018001700170017001700170017001700170017001800170018001700 -170017001800170017001700170017001700170017001700170017001800170017001700 -1800170017001700180017001700170017001700170017001b0017001700170017001700 -1800170018001700170017001800170017001700170017001700170017001b0017001700 -170017001700170017001700170017001800170017001700180017001b00170017001700 -170017001800170018001700180017001700170018001700170017001700170017001700 -170017001800170018001700170017001800170017001700170017001700170017001700 -170017001800170017001700180017001700170018001700170017001700170017001700 -1b0017001700170017001700180017001800170017001700180017001700170017001700 -1700170017001b0017001700170017001700170017001700170017001800170017001700 -180017001b00170017001700170017001800170018001700180017001700170018001700 -170017001700170017001700170017001800170018001700170017001800170017001700 -170017001700170017001700170017001800170017001700180017001700170018001700 -1700170017001700170017001b0017001700170017001700180017001800170017001700 -1800170017001700170017001700170017001b0017001700170017001700170017001700 -170017001800170017001700180017001b00170017001700170017001800170018001700 -1800170017001700180017001700170017001700170017001b0017001800180018001700 -170017001700170017001700170017001700170017001700170018001700180018001800 -180017001700170018001700180017001700180018001700180017001800180018001800 -1700170018001700170017001800180017001800170017001700170017001b0017001700 -170017000000170017001c000600000000001a0017001c001c0000001700170017001700 -170018001800170018001800180016001800180017001700170017001700170017001700 -18001800180017001700170017001b00170017001b0017001b001700170017001b001700 -17001700170017001b001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001b00170017001b00170017001700170017001700 -1700170017001700170017001b00170017001b001700170017001700170017001b001700 -17001b0017001700170017001700170017001700170017001700170017001b001b001700 -17001700170017001700170017001b0017001700170017001700170017001b0017001700 -17001700170017001700170017001700170017001b00170017001b001700170017001700 -170017001700170017001700170017001700170017001700170017001b00170017001b00 -1700170017001700170017001700170017001700170017001b00170017001b0017001700 -17001700170017001b00170017001b001700170017001700170017001700170017001700 -1700170017001b001b00170017001700170017001700170017001b001700170017001700 -1700170017001b001700170017001700170017001700170017001700170017001b001700 -17001b001700170017001700170017001700170017001700170017001700170017001700 -170017001b00170017001b00170017001700170017001700170017001700170017001700 -1b00170017001b001700170017001700170017001b00170017001b001700170017001700 -1700170017001700170017001700170017001b001b001700170017001700170017001700 -17001b0017001700170017001700170017001b0017001700170017001700170017001700 -17001700170017001b00170017001b001700170017001700170017001700170017001700 -170017001700170017001700170017001b00170017001b00170017001700170017001700 -1700170017001700170017001b00170017001b001700170017001700170017001b001700 -17001b0017001700170017001700170017001700170017001700170017001b001b001700 -17001700170017001700170017001b0017001700170017001700170017001b0017001700 -17001700170017001700170017001700170017001b00170017001b001700170017001700 -170017001700170017001700170017001700170017001700170017001b00170017001b00 -170017001700170018001800180018001800180018001800170018001800180018001800 -170018001800170017001700170017001700180017001700180018001800170017001800 -170017001700180018001700170017001700170017001800170018001700170017001700 -1700170017001700170017001700170017001c0000001700170017000600000000001a00 -170017001700000017001700170017001800180018001700170018001800180018001800 -170017001700170018001800180018001800170017001700170017001700170017001700 -1700170017001700170017001700170017001700170017001700170017001b0017001700 -180017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -17001700170017001700170017001700170017001700170017001700170017001b001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -1700170017001b0017001700170017001700170017001700170017001700170017001700 -170017001700170017001700180017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -17001700170017001b001700170017001700170017001700170017001700170017001700 -1700170017001700170017001700170017001b0017001700170017001700170017001700 -170017001700170017001700170017001700170017001700180017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -17001700170017001700170017001700170017001b001700170017001700170017001700 -1700170017001700170017001700170017001700170017001700170017001b0017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170018001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -17001700170017001700170017001700170017001700170017001700170017001b001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -1700170017001b0017001700170017001700170017001700170017001700170017001700 -170017001700170017001700180017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700180018001800180018001800 -180018001800180018001800180018001800180018001700180018001700170017001700 -180017001700170017001700180017001700180018001700170017001800170018001800 -170017001700170017001800170017001700170017001b00170017001700170017001700 -0000170017001c000600000000001a0017001c0017000000170017001700180017001700 -180018001800170018001700170017001700170018001700170018001700170018001700 -170017001800170018001800170017001700170017001700170017001700170017001700 -170017001800180017001700170017001700170017001800170017001700170017001700 -170017001b00170017001700170017001700170017001700170018001700170017001700 -1b0017001700170017001700170017001700170017001800170017001700170017001700 -1700170018001700170017001700170017001700170017001b0017001700170017001700 -170017001700170017001700170017001700170018001700170017001700170017001700 -170017001700180017001700170017001700170017001700170017001700170018001700 -170017001700170017001700170017001b00170017001700170017001700170017001700 -1700180017001700170017001b0017001700170017001700170017001700170017001800 -170017001700170017001700170017001800170017001700170017001700170017001700 -1b0017001700170017001700170017001700170017001700170017001700170018001700 -170017001700170017001700170017001700180017001700170017001700170017001700 -170017001700170017001700180017001700170017001700170017001b00170017001700 -1700170017001700170017001700180017001700170017001b0017001700170017001700 -170017001700170017001800170017001700170017001700170017001800170017001700 -1700170017001700170017001b0017001700170017001700170017001700170017001700 -170017001700170018001700170017001700170017001700170017001700180017001700 -170017001700170017001700170017001700170017001700180018001700170017001700 -170017001b00170017001700170017001700170017001700170018001700170017001700 -1b0017001700170017001700170017001700170017001800170017001700170017001700 -1700170018001700170017001700170017001700170017001b0017001700170017001700 -170017001700170017001700170017001700170018001700170017001700170017001700 -170017001700180017001700170017001700170017001700170017001700170017001700 -180017001700170017001700170017001b00170017001700170017001700170017001700 -170018001800180017001700180017001700170018001800180018001800180017001700 -170017001700170018001700180017001800170017001700170018001800170017001800 -170017001700180017001800170017001800170017001700170018001700170017001700 -1700170017001700170017001700170000001700170017000600000000001a0017001c00 -170000001700170017001700180018001700180018001800170017001700170017001700 -170017001800180018001800180017001700170017001800170017001700170017001700 -1b0017001800170018001700180017001700170017001800170017001700170018001700 -180017001700180018001700170018001800170017001700170017001800170018001800 -170017001700180017001800180017001700170017001700180017001800180017001700 -1700180018001700170017001b0017001700170017001800180017001700170018001700 -170017001700170018001800180017001700180018001b00170017001700170018001800 -17001800170017001700170018001b001700170018001700180017001800170017001700 -1b0017001700170018001700180017001700170018001800170018001800170017001700 -170017001800170018001800170017001700180017001800180017001700170017001700 -1800170018001800170017001700180018001700170017001b0017001700170017001800 -180017001700170018001700170017001700170018001800180017001700180018001b00 -17001700170017001800180017001800170017001700170018001b001700170018001700 -1800170018001700170017001b0017001700170018001700180017001700180018001800 -170018001800170017001700170017001800170018001800170017001700180017001800 -180017001700170017001700180017001800180017001700170018001800170017001700 -1b0017001700170017001800180017001700170018001700170017001700170018001800 -180017001700180018001b00170017001700170018001800170018001700170017001700 -18001b0017001700180017001800170018001700170017001b0017001700170017001700 -180018001700170018001800170018001800170017001700170017001800170018001800 -170017001700180017001800180017001700170017001700180017001800180017001700 -1700180018001700170017001b0017001700170017001800180017001700170018001700 -170017001700170018001800180017001700180018001b00170017001700170018001800 -17001800170017001700170018001b001700170018001700180017001800170017001700 -1b0017001700170018001700180017001700180018001800170018001800170017001700 -170017001800170018001800170017001700180018001700170017001700170017001700 -170017001700180018001800170017001700170018001700170017001800170017001700 -180018001700170017001700180017001700180017001800170017001700180017001700 -180018001700170017001700170017001700170017001700170017001700170000001c00 -170017000600000000001a00170017001700000017001700170017001800180018001800 -180017001800170017001700170017001800170017001700180017001700180017001700 -170017001700180018001700180017001800180017001800180018001700180017001800 -180017001700180017001800170018001700170017001700190017001800170018001700 -180017001800170018001800180017001800170017001700170017001700170017001900 -170017001800170017001800170018001800170017001800170017001700180017001700 -180017001700170018001700170018001800170019001700170018001700170018001800 -170018001700170017001800180018001700190017001800170017001700180018001700 -170019001800170018001700180017001800180018001700170017001700170015001900 -170017001800170018001500190018001500170018001800180017001800180018001700 -180017001800180018001700180018001800180018001700180018001800170017001700 -180017001800170018001800180017001800170018001700180017001800170018001700 -180017001800170018001700180017001800170018001700180017001800170018001700 -180017001800170018001700180018001800170018001700180017001800170018001700 -180018001800170018001700180018001800180018001700180018001800170018001700 -180017001800170018001700180018001800170018001800180017001800170018001700 -180017001800170017001700180017001800170017001700180017001800170018001700 -180017001800180018001700180017001800180018001700180017001800170018001700 -180017001800180018001700180017001800170018001700180017001800170018001700 -180017001800170018001700180017001800170018001700180017001800170018001800 -180017001800180018001800180017001800180018001700180017001800180018001700 -180018001800180018001700180017001800170017001700180017001800170018001800 -180017001800170018001700180017001800170018001800180017001800170018001700 -180017001800170018001700180017001800170018001700180017001800170018001700 -180018001800170018001700180017001800170018001700180017001800170018001700 -180017001800180018001700180017001800170018001700180017001800170018001700 -170017001700170017001700170017001800170017001700180017001700170017001800 -170018001700170017001800180017001700170018001700170018001700170017001800 -17001800170017001700180017001700180018001700170017001700170017001b001800 -17001700170018001700170000001b0017001c000e00000000001a001c00170017000000 -170017001700170018001700170017001700170017001800190017001900170018001700 -170018001900170017001700170017001700170018001700180017001700170017001800 -180017001800170017001800190011001900190017001700170017001800170017001700 -180017001300180018001700170019001700180017001800170018001800180015001900 -180017001900170019001800180013001900170017001900170019001700170019001700 -170017001900170017001700180018001700180017001800180017001800190018001800 -130017001900170017001900180017001900170018001900170017001700170018001800 -170017001700170017001700170017001700170017001800170017001700180017001700 -170017001700170017001700190017001900170015001900170017001700170018001a00 -170017001700180017001700170018001700170017001700170017001700170017001700 -170018001700170017001800170017001800170018001700180017001800170017001700 -170017001800170018001700170017001700170018001700170017001700180018001700 -170017001700180018001700170017001700180018001700170018001700170017001700 -170017001700170018001700170018001700170017001700170018001700170017001700 -170018001700170017001800170018001700170017001800170017001700170017001800 -170017001700180017001800170017001700180017001700170017001700180017001800 -170018001700180017001700180017001700180017001700170017001700180017001700 -170017001800170017001700170018001700180017001700170017001800170017001700 -170018001800170017001700170018001700170017001800180017001800170017001700 -170018001700170017001700170017001700170017001700170017001700180017001700 -170018001700170017001700170017001700170017001700170017001700170017001800 -170017001800170018001700180017001800170017001700170017001800170017001800 -170017001700170018001700170017001700180018001700170017001700180018001700 -170017001700180018001700170018001700170017001700180017001700170017001800 -170017001700180018001700170017001700180017001700170017001700170017001800 -170017001700170017001800170017001800170018001700180017001800180017001700 -180018001700170018001800180017001700180017001800170017001700170018001700 -180017001700180017001800170017001700180017001800170017001800170017001700 -1800170017001700170017001800170018001800170017001700170000001c001c001700 -0e00000000001a0017001c00170000001700180017001800180017001700180017001700 -170017001700170017001800170017001800170015001900170017001800170018001700 -170018001800170017001800180017001700190017001800190017001700170017001500 -170017001900170017001800180017001700170019001700170018001700170017001700 -1700180017001800150018001a0013001700180017001700150015001900190017001800 -190017001700180018001500170017001700190017001700180017001800170017001900 -180018001700180018001300170017001900180017001900170017001700180013001800 -1700170018001800170017001700170018001800180019001900170018001a0017001700 -180018001700170017001700180017001800170019001700170019001700170017001700 -190017001900190017001700190013001700170017001700170017001700170018001700 -180017001800170018001700170017001700170017001700170017001700180017001800 -170018001700180017001700170018001700180017001700180017001700180018001800 -170017001700170017001800180017001700170017001800170017001700180017001800 -170017001700170018001700180017001700180018001700170017001700170018001700 -180017001700170018001700170017001700170017001700170017001700180017001800 -170018001700180017001700170017001700170017001700170018001700180017001800 -170018001700170018001700180017001800170017001700170017001700170017001700 -180017001800170017001700180017001800180017001700170017001700180017001700 -180017001800180017001700170017001700180018001700170017001700170018001800 -170018001700170018001700170017001700170018001800180017001800170018001700 -180017001700170017001700170017001700170018001700180017001800170018001700 -170017001700180017001700180017001700180017001800170018001700180017001700 -170018001700180017001700170017001800170018001800170017001700170017001800 -180017001700170017001800170017001700180017001800170017001700170018001700 -180017001800170017001700170017001800180017001800170017001700180017001800 -170017001700180017001700180017001800170017001800170017001800170017001800 -180017001700180018001700180017001800170018001700180017001800170018001700 -180017001800170017001800170018001700170017001700180017001800170017001700 -180017001800180017001700170017001700170017001700170018001700180017001800 -1700170017001700000017001c0017000e00000000001a00170017001700000017001700 -170018001800170017001700170018001800170017001700190017001700170000001800 -190000001a00170015001900170017001800170017001700180017000000170017001900 -130017001700000017001800180018001900170017001800180019001700180017001700 -180017001900170018001700190017001700170018001700190015001800190017001700 -170017001a0017001700170017001900150017001900170017001900170018001b001800 -17001800170017001800000018000000000000000000000000001a001800190013001800 -000015001900170018001700010017001800180018001500180017000000000000000000 -190017001700010000000000000000000000170017001800180017001700170018001700 -170017000100000000001700180000001500190015001700170018001900180017001800 -180017001700180018001700180017001700170018001700170017001700180018001700 -170018001800170018001700180017001800170018001700170018001800170017001700 -170018001700180017001700170017001700180018001800170017001700170018001800 -170017001700180017001800170017001700180018001700170017001800170017001800 -170017001700180018001700170017001800170018001700170017001700180018001700 -170018001800170017001700170018001700170017001800170018001800170017001800 -180017001700170017001800170017001700180017001800170018001700180017001800 -180017001800180017001800180017001700170018001700180017001700170017001700 -170018001800180017001700180017001700170017001700170018001800180017001700 -170017001800180018001700170017001700170017001800170017001800180018001700 -170017001800170017001700180017001700170017001800180017001700180018001700 -180017001700170018001700170017001700180018001700170018001700170018001700 -180017001800170018001700170018001800170017001700170018001800170017001700 -170017001700180018001800170017001700170018001800170017001700180017001800 -170017001700180018001700170017001800170017001700180018001800170017001700 -170017001700180017001800170017001700180018001700170018001700170018001700 -180017001700180017001800170017001700180017001700170017001800170017001700 -180017001700170017001800180017001700170018001700170018001700170017001800 -180017001700170018001700180017001700170017001700170018001800180017001800 -17001700180017001800170017001800170017001700170000001c0017001c000e000000 -00001a001b001c0017000000170017001700170017001800180017001700180018001700 -180017001700170018001900000017001900000017001700170017001700180018001700 -170018001800170000001800130017001900170019000000190017001700170013001900 -170017001700170017001700190017001800170017001500190018001300180017001800 -170017001700180017001700180017001500190017001700180019001700170019001500 -180018001800170019001700150017001700170018001800000017001800000018001900 -170017001500170018001700180000001700000019001700170017000000180017001500 -170019001700000019001700190017000000170017000000170019001700180017001800 -170018001800170017001700180017001700000017001700180000001800190001001500 -180017001900170017001900170017001800170017001800170017001700170017001800 -170017001800180017001700180017001700180017001700170017001700180017001800 -170018001700170017001800180018001700170017001700180017001700180018001700 -170017001800170017001800170017001800170017001800170017001800170017001800 -180017001700170018001700180017001800180018001700170017001700180017001700 -180017001700180017001700180017001700180017001700180018001700170018001700 -170017001700170018001700170018001700170018001800170017001800170017001700 -180017001800170018001700180017001700180017001700170017001700180017001800 -170017001800170017001800180017001700170017001700170018001700170018001800 -180017001700170017001700180017001700180017001700170017001700180018001800 -170017001800170017001700170017001700180017001700170018001700170018001800 -170017001800170017001800170017001700170017001800170017001800180017001700 -180017001800170018001800170017001700180017001800170018001700170017001800 -180018001700170017001700180018001800170017001700170017001800170017001800 -170017001800170017001800170017001800170017001800180017001700170018001700 -180017001700170017001700170018001800170017001800170017001800170017001700 -180017001800170018001800170017001800170018001700170017001800170017001800 -180017001800180017001700180017001800170018001800170018001800170017001700 -180017001700180017001700170018001800170017001800170017001800170017001800 -180017001700170017001700180017001700170017001800170017001800180017001700 -1700170000001c00170017000e00000000001a001c001700170000001700170017001700 -170018001700180018001700180017000000000017000000170000000000000017000100 -170017000100170018001700170017001800170017001700000018000100000017001900 -170000001700010000001700190017001a00000000000000190017000000170017001900 -170000001700170019001700180017001700170000001900000000001a00170019001700 -00000000000017001700000017001a001700000017001700170000001800190018001900 -170017000000170017000000180017001900180019001700170018001800000018000000 -170019001900170000001700190019001700170018000000190017001700190018001800 -190000001900170018001700170017001700170017001700180017001800170017000000 -170019001900000019001500000017001700170017001700180017001800170018001700 -170018001700180017001800170017001800170017001700180017001800170017001800 -170018001700180018001700180017001800170018001800170017001700170017001800 -180017001700180017001700170018001700180017001700170017001800170018001700 -170018001700180017001700170017001700170018001700180017001700170017001700 -170017001800180017001700180017001800170017001800180017001800170017001800 -170018001700170017001800170017001800170018001700180017001700180017001800 -170017001700180017001700180017001700180017001800170018001700180017001800 -180017001800180017001700170017001800170018001700170018001700170018001800 -170018001700170018001700170017001700170018001800170018001700170017001700 -180017001800180017001700170017001700180017001700180017001800180017001700 -170018001700170018001700170017001800170018001700170018001700180017001800 -170017001800170017001700180017001800170017001700170017001700180018001700 -180017001800170018001800170017001700170017001800180017001700170017001700 -180018001700180017001700170017001800170018001700170018001700180017001700 -170017001700170018001700180017001700170018001700180018001700170018001700 -170018001700180017001700180017001800170017001700170017001700180018001700 -170018001800170017001800170017001700170017001700170018001800170017001700 -170017001700170017001700180017001800170017001800170018001700170017001700 -170017001800170018001700170018001700170018001800170018001800170017001700 -1700170018001700180017001700170017001700000017001c0017001d00000000001a00 -170017001700000017001700170018001800180017001800170017001700000019001700 -000001001300190000001700180000001800000017001700170017001700180017001700 -170018000000000017001700000017001800000000001700170000001700170000001700 -180018000000130018000000170017000000190015001900180017001700170018001800 -000000001900170000001700170000001900170017000000190000001700170019000000 -180017001700000019001700110019001700000019001700190000001800170017001700 -170018001900170000001700180018000000170017001700010017001700170017001700 -170019000000000019001300170017001700000018001700170018001900180018001700 -170018001700180017001700180000001800170017000100180017001800000017001800 -000019001700170017001800170017001700170018001700180017001800170018001700 -170017001700180017001700170017001800170017001800170017001700180017001800 -170017001800170017001700170018001800170017001800180017001700170017001700 -180018001800180017001700170017001700170017001700180018001800170017001800 -170018001700170017001800180017001800170018001700180018001700170017001700 -170017001700180017001700170017001800170017001700170018001700180017001800 -170018001700170017001700180017001700170017001800170018001700180018001700 -180017001800170018001700170017001700170017001800170018001800180017001700 -170017001700170017001800170017001800170018001700180017001700170017001800 -170017001700170018001800180018001700170017001700180017001700170017001800 -170018001700180017001700180017001800170018001700180017001700170017001800 -170017001700170018001700180017001800170018001700170017001700180017001700 -170018001800170017001800170017001700180017001800170017001800170017001700 -170018001800170017001700170018001700170017001700180018001800180017001700 -170017001700170017001700180018001800170017001800170018001700170017001800 -170018001700170018001700170017001700170017001700180018001700180017001700 -170018001800170017001700170017001700170018001700170018001800170017001800 -180017001700170017001700170018001800170018001700170018001700180017001700 -170017001800170018001700170018001800180017001700170017001700170018001700 -180017001700170017001700170017001700170017001800180017001700170017001700 -000017001c0017001d00000000001a0017001c0017000000170017001700170018001800 -180017001700180018000000170018001700000019001700000019001700000000001700 -170017001700180018001700170018001800170000001900170018000000180017000000 -170018001900000018001800000019001700170000001900170019000000000018001700 -170018001500180017001900170017000000180017001700000018001700000017001700 -180000001500190000001800170000001700180000001700170018001900170019000000 -170018001700000000000000000000001900170017001700000018001700170000001800 -170019000000180017001800190017001800170017001800000000001700170017000000 -000000000000000000001700180017001700180017001700170018001700000017001700 -180000001700190017000000180018001800170017001800170017001700180018001700 -170017001700170018001700170017001800180017001700170018001800170017001700 -180017001700180018001700180017001700180017001700180018001700170017001800 -170017001700180018001700180017001700170017001700170018001700180018001700 -180017001700170018001700170018001700170017001800170018001700170018001700 -170017001700170017001800170018001800170017001700170018001800170017001700 -180018001700170017001800170017001700170017001800180017001700170018001800 -170017001700180017001700170018001700180017001800170018001800170018001800 -170017001700180017001700170018001700180018001700170017001800170017001700 -180017001700170018001800170017001800170018001700170017001700170017001800 -170018001700170018001800170017001700180017001700170018001700170017001700 -180017001700170018001800170017001700180018001700170017001700170018001700 -170017001800180017001700170018001700180017001700180017001700180018001700 -180017001700180017001700180018001700170017001700180018001700170018001700 -180017001700170017001700170018001700180018001700180017001700170018001700 -170018001700170017001800170018001700170017001800170017001700180018001700 -180017001700170017001700170018001700180017001700180018001700180018001700 -170018001700170017001800170018001700170018001800170018001700180017001700 -180017001700180017001700170018001800170017001700180017001700180017001700 -170018001700180018001700180017001700170018001800170018001800170017001700 -180017001700180018001700170017000000170017001c001d00000000001a0017001700 -170000001700180018001800170017001700170018001700180000001800190017000000 -190017000000170019000000000017001800180017001700190017001700190017001800 -000018001700180000001700190000001700170018000000180017000000180017001900 -000017001900170000000000190015001900190017001700190017001700190000001800 -180017000000180018000000000000000000000017001700000017001800000018001700 -000017001900170017001800190000001800170018000000170018001700170017001900 -170017000000000000000000000017001700170000001700180018001500190017001800 -170017001900180000001900180000001700180017001700180017001700170018001700 -180017001800170019000000180018001900000017001800180000001700180017001700 -170017001800170017001700180017001700180017001800170017001800180017001700 -180017001700170018001700170018001800170017001700170017001700180017001800 -170017001800180017001700170017001800170017001800180017001700180018001700 -170018001800170017001700170018001700180018001700170017001800170017001700 -180017001800170018001800170017001700180018001700170017001800170017001700 -180017001700180017001700170018001700170018001800170017001800170018001700 -170018001700170017001800170017001800180017001700180017001800170018001700 -170018001700170018001800170018001700180017001700170018001800170018001700 -170017001800170017001800170017001700180017001700180018001700170018001700 -180017001700170017001700170018001700170018001700180017001700170018001800 -170017001700170018001800170018001700170018001800170017001800170017001700 -180017001700180017001800170017001800180017001700180017001800180017001700 -170018001800170017001700170017001700180017001800170017001800180017001700 -170017001800180017001700180017001800170017001700170017001700180017001700 -170018001700180018001700170017001800170017001700180017001800170017001700 -180017001700180017001700170018001700180018001700180017001700180017001700 -170018001800170017001700180017001700170018001700170017001800170017001800 -180017001800180017001700170018001700170017001800170018001700170017001700 -180017001800170017001700180017001700170018001700170017001700170017001800 -17001700180017001700170017001700170017001800180017001b001700170000001700 -1b001c000600000000001a001c001c001700000017001800180017001800180018001700 -180017001700000017001800180000001800170000001a00170000001500000018001700 -180017001800170017001800170017000000190017001700000019001700000019001700 -1900000017001a0000001700170019000000170019000000190019000000190017001500 -190017001700180018001700000018001700170000001700170000001700170019001800 -170019000000170000001800000019000000170018001700190015001900000017001700 -170000001700170018001700190015001800000017001700190018001800000017001700 -000019001700170019001700170000001700180017001800000019001700000019001700 -170017001900170019001700170017001700170017001700170000001700170017000000 -170017001700000017001800190017001700180017001700180017001800170017001800 -170017001800170017001700170018001700170018001700180017001700180017001700 -180018001800180017001700170017001800170017001700170018001800170017001800 -170017001700180017001700170018001700170017001800180018001700170017001700 -170017001700180017001700180017001800170017001700170017001700180017001800 -170017001800180017001700180018001800170017001800170018001700170018001700 -170017001700180017001700180017001700180017001800170017001800170017001700 -170018001700170017001800170018001700180018001700170017001700170017001800 -180017001700170017001700170017001800180018001700170018001700180017001700 -180017001700170017001800170017001700170018001800180018001700170018001700 -180017001700170018001700170017001700180018001700170017001700170018001700 -170017001700180017001700180017001800170017001800170017001800170017001700 -170018001700170017001700170018001700180017001700180018001800180017001700 -170017001800170017001700170018001800170017001700170018001700170017001700 -180018001800180017001700180018001700170017001700170017001700180017001700 -180017001800170017001700180017001800170017001800180018001700170017001700 -170017001800170017001800170018001700170017001800180017001700180018001700 -170018001800170017001800170017001700170017001700170018001700180017001800 -170017001700180017001800180017001800170017001700180017001700170018001800 -170017001800180017001800170018001700180018001700170017001b00170018001700 -18001800170017001700170000001c001c0017001d00000000001a001c00170017000000 -170018001800180017001700170018001700170015000100170017000000000017001800 -000017001800000019001700010018001800170017001900170017001900170000001700 -190018000000170018000000000019001700000018001800000019001700170000001700 -000018001700180017000000170019001700170019001500170017000100170017001800 -000018001900000017001900170000001900130017000000110019001800000017001900 -150018001800170018000000180018001700000018001700190018001700180017000000 -170017001300190017000000180018000000170018001800170017001800000019001700 -170018000000170017000100170017001800170017001900170017001800180017001700 -190017001700000018001700190000001700190018000000190017001700170018001700 -170018001700180017001700170017001800180017001700170017001700180017001800 -170018001700170017001700170018001700170017001700180017001800180017001700 -170017001700180018001700170018001800170017001700180017001700170018001700 -170017001700170018001700180017001700180017001700180018001700180017001700 -170018001800170018001800170017001800170018001700180017001800170017001700 -170017001800170018001700180017001700170017001700180018001700170017001700 -180017001800170018001700170017001700170018001800170018001800170017001700 -170017001700180018001700170017001700170018001700170018001700180017001700 -170017001700170018001700180017001800170017001700170017001800180017001800 -170017001700170018001700170018001700170017001800170018001700170017001800 -180017001700170018001800170017001700170017001800170018001700180017001700 -170017001800180017001700170017001700180017001800180017001800180017001700 -170018001700170017001700180017001800180017001700170017001700180018001700 -170017001700170018001800170018001700170017001700180017001700170018001700 -180017001700180017001700180018001700180017001700170018001700180017001700 -170017001700170018001700180017001700180017001700170017001800170018001700 -170017001800170017001700180017001700170018001700170018001800170017001800 -180017001800180017001700180017001800170017001700180017001700180017001700 -170018001700180018001700180017001800170018001700180018001700170017001700 -170017001700170017001700170018001800180017001700170017000000170017001c00 -0600000000001a0017001700170000001700170017001800180018001700170017001800 -170017000000000017000000190017000000000017000000170017001800000018001700 -170018001700150017001800000017001700180000001900170000001800000000001700 -180017001900000000000000170018000000170019001700170000001800170019001500 -180019001700180000001700180019000000170017001900000000000000170019001700 -180000001900150019000000170017001900170017001900170000001700170019000000 -17001800150017001700170017000000170019001a001700180000001300180000000000 -000000000000180017001a00000000000000000018001700170000000000000000000000 -000017001800170000001900170017001500190017001800000000000000180017001700 -170000001700180000001800170019001700180017001700170018001800170017001700 -170018001800180017001700170018001700170017001800180017001700170018001700 -170018001700170017001700170018001800180017001700170018001700170017001800 -180017001700180018001700170018001800170017001800170017001800170017001800 -180017001700170017001700170018001700180017001700170017001700180018001700 -170017001800170017001700170018001800170017001700180017001700170018001800 -180017001700170017001800180017001700170018001700170017001800180018001700 -170017001700170018001700180017001800180017001700180017001800170018001800 -180017001700180017001700180017001700180018001700170017001800170017001700 -180018001800170017001700170017001800170017001800170017001700170017001800 -170018001700170018001800170017001700170018001800170017001700180018001800 -170017001700180017001700170018001800170017001700170018001800180017001700 -170018001700170017001700170018001700170018001700170018001700170017001700 -170018001800180017001700170017001800180018001700170017001700170018001700 -170018001700170017001800170017001800170017001800180017001700170017001700 -170018001700180017001700170018001800170017001800170017001800170017001800 -170018001800170017001700180017001800170017001800180017001700180018001700 -170018001700170017001800170018001700170017001700170018001700170018001700 -180017001700170017001700170018001700180017001700180017001700170018001700 -170017001700170017001800180018001700180017001b00170017001800170017001700 -1700170017001b000000170017001c000600000000001a00170017001700000017001700 -170017001700180018001800170017001900170017001700190000001700170017001900 -170017001900170017001900170018001900150019001a00170017001900180017001700 -190017001900170018001500190019001700180017001700180017001900150017001700 -18001700170017001900170017001a001700170019001900170018001800130017001700 -170017001900180019001700150019001700170019001700170017001700180017001800 -19001700180017000100170017001700170017001a001800170019001700190017001700 -170017001700170019001700170019001500190017001800180017001500190017001700 -170018001900180018001700170018001100190017001900000017001800170017001700 -170018001800170019001700190017000000170018001700000017001800170017001800 -170017001700180018001700180017001700170017001700170018001700180017001700 -170018001800170018001800170017001700170018001800180017001700170017001700 -170018001700170018001700170018001800170017001700180017001700170018001700 -170017001800170018001700170017001700170017001800180018001700170018001700 -180018001800170017001700170017001800170018001700180018001700180018001700 -170017001800170018001700170017001700170017001800170018001800170017001700 -180017001800170017001700170017001700180018001700170017001800170017001700 -180017001700170018001700170017001700170017001800170018001700170017001800 -180017001700170018001700180017001700170017001700170018001800180017001700 -170017001800180018001700170018001700170018001700170017001800170017001800 -170017001800170017001700170017001700180017001800170017001700180018001700 -180017001700170017001700170018001800170018001800180017001700170018001800 -170017001700170018001800180017001700170017001700170018001800170017001700 -170017001700180018001800170017001700170018001800170017001800170018001700 -170017001700170017001800180018001700170017001800170017001700180018001700 -170017001800170018001700170017001700180018001700170017001800170018001700 -170017001800170017001800180017001700180018001700170018001800170018001800 -180017001700170017001800170017001800170017001800180017001700180017001700 -180017001700170018001700180017001800180018001700170017001700170018001700 -170017001700170017001800170017001700170017001700000017001700170006000000 -00001a0017001c0017000000170017001700180018001800170017001700180015000000 -1900170019000000170017001700190013001900170018001b0017000000000000000000 -000000000100170017001700170017001900190017001700170019001700170017001700 -180018001700170017001700170019001900170019001900000000000000000000000000 -0000130018001700170018001a0017001700180017001700170019001900150017001800 -170015001900170017001700190018001700180017001900000019001700190017001800 -170017001800170017001700190017001700190017001700170017001700170017001900 -170017001700180019001800170018001800170017001500170018001700170019001800 -170000001700180017001700180018001800180015001900170017001700170001001500 -190000001700190018001700170018001700180017001700170017001700170018001800 -170018001700170017001800170018001700170017001700170017001700180018001700 -170017001700170018001800170018001700170018001700170018001700170017001800 -180017001700180018001700170018001800170018001700170017001800170018001800 -170017001700170017001800170017001700170017001700180018001700180018001700 -170017001700170017001700170017001800170018001700170017001800170018001800 -170017001700170017001700180017001800170017001700180017001800180017001700 -180017001800170018001700180017001800170018001700180017001800170017001800 -170017001700180017001800170017001700170018001700180017001700170018001700 -180018001700170017001700170018001800170017001700180017001700180017001800 -170017001700180017001700170017001800170017001700180018001700180017001700 -170018001700180017001700170017001700170018001800170018001700170017001700 -170017001700170018001800170017001700180018001700170017001700170018001800 -170018001700170017001700180017001800180017001700170017001700180018001700 -170017001800170018001700170017001800170018001800170017001700170017001800 -170018001700180017001700170017001800170018001700170017001800170017001700 -170017001800170018001700170018001800170017001800170017001700180017001700 -170018001700170017001700170017001700170018001800170017001800170018001700 -170018001800170017001800170018001700170017001800180017001700170017001700 -170017001800180017001800180017001700170017001700180017001700170017001700 -1700170000001c001c0017000600000000001a0017001c00170000001700180017001700 -1800170017001700170018001a0015000000000000001900150019001800170019001700 -170017001700170018001900190017001800190015001800170017001900170015001700 -180017001700170017001800180018001700170019001900170018001800170017001800 -170017001800190018001800170017001700190017001700190017001500170018001700 -1900170017001700170019001700180018001700170015001a0017001700170017001800 -170017001800000018001700170018001700180015001900190013001800180017001700 -180017001800170017001900180017001800180017001800150017001700150017001900 -180017001900180017001700190017001900170018001700190018001700170018001800 -170017001700190017000000170017001700190019001700110019001700170018001700 -180017001700180017001800170017001800170018001700170017001800170018001700 -170018001700170017001800180017001700170017001800170017001800170018001700 -180017001700180018001700170017001800170017001800170018001700180017001800 -170017001700180017001800170017001800170017001700170018001700180018001700 -180017001800170017001700170017001700180018001700180017001700180017001800 -170017001700180017001800170017001800170018001700170018001700180017001700 -170018001700180017001700180017001700170018001800170017001800180017001700 -180018001700170018001800180017001800170017001700180017001800170017001800 -170018001700170017001800170018001700170018001700170017001700180018001700 -170017001700170017001700170017001800180017001700180018001800180017001700 -170018001700170018001700180017001700170018001700180017001700180017001800 -170017001800170018001700170018001800170018001700180017001700170017001800 -180017001700170017001800170017001800170018001700170018001700180017001700 -180017001700170017001800180017001700170017001800170017001700180017001800 -170017001800170017001700170018001700170018001700180017001700180017001800 -170017001700180017001800180017001700180017001800170017001700170018001700 -170018001800170017001800180017001700180018001700170018001800170018001700 -180017001800180017001700170017001700170017001700170017001700170018001800 -170017001700170017001800180017001800170018001700170017001700170017001b00 -17001700170018001700170017001700170017000000170017001c000600000000001a00 -170017001700000017001800180018001800180018001800170017001700180017001800 -180017001800180017001700180017001700170017001700170017001700170018001700 -180018001700170017001700180018001700170018001700180017001700190017001700 -170018001700170018001900170019001800170017001700170017001800170017001700 -170017001800170017001800170017001700180017001700190017001800180017001700 -190017001700180019001700180017001700170018001700170019001700170018001700 -170017001700190017001700180017001700180017001900170015001700180017001800 -170018001700190017001800170017001700170017001800170019001700190017001700 -180017001800170017001800170018001700190017001700190017001800170017001700 -170017001900170018001700170017001800170017001800170017001800170017001700 -180017001800170017001700180017001700180018001800170017001700170018001800 -170017001800170017001700180017001700180017001700170018001800170017001800 -170017001700180017001800170017001700180017001800170017001700180017001700 -180018001700170017001800170017001800170017001700180018001700180018001700 -170018001800170017001800170017001700180017001800170017001700180017001700 -180017001700180017001700170018001700180017001700170018001800180018001700 -170017001800170017001700180017001700170018001700170017001700170018001700 -180017001700170018001700170018001700170017001800170018001700170017001800 -170017001800180017001700170017001800180017001800180017001800170017001700 -180017001700170017001700170018001700170018001700170017001800170018001700 -170017001800170017001800170017001800170017001700180017001700180017001700 -180017001700170018001800170017001700170018001800170017001800170017001700 -180017001700180017001700170018001700170018001800170017001700170018001800 -170017001700180017001800170017001700180017001700180018001700170018001700 -170017001800170017001800170017001700180017001800170017001800170017001800 -170017001700180018001700170018001700170017001800170017001700180017001700 -170018001700180017001700180017001700170017001700170018001700180018001700 -170018001800170018001700170017001800180017001800170018001700170018001700 -1700170018001800170018001700170017001700180017001b0017001700170017001700 -00001c0017001b000e00000000001a001b001c0017000000170017001800180017001700 -18001800170018001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a0012001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a0010001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a000f001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a000f001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a0010001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a000c00170017001800 -170018001700180017001700180017001800170017001700180017001700180017001700 -170018001700170018001800170017001800170017001700180017001800170017001700 -180017001700170017001700170018001700170017001800170018001800170018001800 -170017001700170018001800170017001800170017001700180017001800170018001800 -170017001700180017001700180017001800170018001800170017001800170017001700 -180017001700170018001800170017001800170017001800170017001800180017001700 -170018001700170017001800170017001800170017001800170017001700180018001700 -170017001800170017001800170017001800170017001700180017001700170018001800 -170017001800170017001700170018001700180017001700170018001700170018001800 -170017001800170018001800170017001700180017001700180017001800170018001800 -180017001700170018001700170017001800170017001700180017001700170017001700 -180017001800170018001800170017001700180017001700180017001700170017001700 -180017001800180017001800170017000000170017001c000600000000001a001c001700 -1700000017001700170018001700170017001700170018001a0018001900170018001800 -18001b00170017001b001700170017001700170018001800170018001800180018001900 -180017001900170019001700180017001800180018001800180018001800190017001700 -180018001800190018001800170017001800180017001700180018001800190018001800 -180018001800190017001700180018001800190018001800190017001900170018001700 -18001800180018000f001a00190018001900170019001300170018001700170018001800 -170018001800180017001700180018001800190018001800180018001800190017001700 -180019000f001a00180018001800170018001900170018001800180018001b0017001800 -170017001700170017001700170017001b0018001b001700170018001800180017001700 -180018001800190018001800180018001800190010001a00180017001900170017001700 -170018001700190017001700170017001800190013001700130019001900170018001500 -19001a001700180018001900190017001800150019001800180017001700170019001700 -1800150017001900170019000f001a001900180018001700170018001a00170019001700 -180017001900170017001700190018001700190019001500180019001700180019001700 -18001900170017001700170017001900170019001a001700190017001900170017001700 -180019000f001a001800180018001900190017001700170017001900170019001b001700 -17001700170017000f001800170017001700180017001800180017001800170017001700 -180017001800170017001800170018001700170018001700170017001700180017001700 -180017001800170017001700180017001700170018001800180018001700170018001800 -170017001700170017001700170017001700180018001700170017001700180017001700 -180017001800170017001700170017001700180017001800170018001800170017001700 -170017001700180017001700180017001800170018001700170017001700180017001700 -170017001800170017001700170018001700180017001800170017001800170018001700 -170018001700180017001700170017001800170018001700170018001700180017001700 -180017001800170018001700170017001700180017001700170018001700170017001800 -170018001700170018001700170017001700180017001700170017001700180017001800 -170018001800170017001700170017001700170018001800170017001800180017001700 -180018001700170018001800170018001800170017001700170017001700180017001800 -170018001800170017001b00170017001700180017001700170018001700170000001c00 -1c0017000600000000001a00170017001700000017001700170018001800180018001800 -170017001a001900180017001700180017001700170017001c0017001b0017001b001700 -170017001700170017001700170017001700180017001900170019001700170018001700 -170017001700170017001700170017001700170017001700170017001700170018001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -1700170017001900170019001700190017001700170018000f001a001900170017001700 -180018001900170019001900170017001700170018001700170017001700170017001700 -17001700170017001700170017001700170019000f001a00190017001900170019001900 -170017001700170017001800180017001700170017001b0017001b001700180017001700 -170017001700170018001700170017001700170017001700170017001700170017001700 -0f001a001700170019001700180017001900170018001900170017001900190017001900 -180017001a00170017001900170018001700150018001700190015001700180017001900 -180017001900180017001700180018001800190018001700180017000f001a0017001800 -190017001800170017001700170017001700180017001900170018001500170017001800 -170017001700170018001700170017001700170019001900170017001800170018001700 -17001700170017001700190017001700170019000f001a00190017001700180017001700 -1700170017001900170017001700170019001800170019000f0018001800170017001800 -170014001700180017001700170018001700180017001700170017001800170018001700 -180017001700170017001700180018001700180017001700170018001700180017001800 -170017001700170018001700170017001800170018001700170018001700170017001800 -180017001700170017001700180018001700180017001700170018001800170018001800 -170017001700170017001700170018001800170017001700180018001700180017001700 -180017001700170017001700180018001800180017001700170017001700180017001700 -180017001800180017001700170017001700170018001700180017001700180017001800 -170017001700170017001700180018001700180017001700180017001700170017001700 -180018001800170018001700170017001800170018001800170017001700170017001800 -170018001800170018001800170017001700170017001700170018001800170018001700 -180017001800170018001700180017001800170018001700180017001700170017001700 -170018001800170018001800170017001700170017001700170017001700170018001700 -1800180017001700170017000000170017001c000600000000001a0017001c0017000000 -18001800180018001700170017001700170017001a001900170017001700180017001800 -170017001800170017001700130017001800180018001800180018001800180018001700 -170017001700170018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800170017001700170019001800 -170019000f001a0018001700180018001700170017001900150017001900180018001800 -180018001800180018001800180018001800180018001800180018001800180017001800 -0f001a00180017001700170017001700170017001900170018001700170017001b001b00 -17001500170017001700170018001b001700170018001800180018001800180018001800 -1800180018001800180018001800180010001a0017001700170017001700170017001800 -180018001700190017001300170018001700170017001900170017001700190019001700 -170019001700180019001700190015001700170017001900190019001300190017001800 -17001700180018000f001a001700190017001700170018001700190017001a0017001700 -190017001700170019001900170018001700190017001700190019001700170017001800 -170017001700190018001900170019001700190017001a00170017001800180017001800 -0f001a001800170019001700180019001700170018001300180017001700170017001700 -150017000c00180018001800170018001700180017001700170018001700180017001700 -170018001800170017001700180017001700170018001800180017001700170017001700 -170018001700180017001700170017001800170017001800170017001700180017001700 -180017001700180018001800170017001700170018001800180017001700170017001700 -170018001700180017001700170017001700180018001800170018001700180017001700 -180017001700170017001700170018001700170018001800180017001700170017001700 -170018001800180017001700180017001700170017001700170018001700180018001700 -170017001800170017001800170017001700180018001700180017001700170017001700 -170018001700170018001800180017001700170017001700180017001800170017001700 -170017001700180018001800170017001700180017001700170017001700180018001800 -170018001700180017001700180017001700170018001700170017001800170017001700 -180017001700170018001800170018001700180017001700170017001700180018001800 -1700180017001700170017001700180018001800170017001700170000001c0017001700 -0600000000001a0017001700170000001700170017001700180017001800170018001700 -1a0017001c001700170017001700170017001b00170017001b0017001b00170017001700 -170017001700170017001700170017001800180018001700180017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -17001700180018001800170018001700170018000f001a00180017001800180018001900 -170017001800190017001700170017001700170017001700170017001700170017001700 -170017001700170018001800170018000f001a0017001700170019001700180017001700 -1700170017001700170017001700170017001b0017001b00190017001700170017001700 -17001700170017001700170017001700170017001700170017001700170017000f001a00 -180018001700190017001700180017001700130019001700170019001800170018001900 -19001300190017001900150017001800180013001b001700170017001700190017001900 -17001900150019001900170018001700190017001700180010001a001700170017001900 -17001700170017001700170017001900170017001a001700170018001700170017001700 -180018001500170019001900170017001900170018001500190017001700150017001700 -170017001500190018001800170018000f001a0017001700170017001700170017001300 -1b001700170017001b00190017001800190017000f001800180018001700180017001800 -180017001700180017001700180017001700180018001700170017001800170018001700 -170017001700170017001800180017001700180017001700180017001800180017001700 -170017001800180017001700180017001800170017001700170017001800170017001800 -170017001700170017001800180018001700170018001700180018001800170017001700 -170017001700180017001700170018001700170017001800180018001700170018001700 -170017001700170017001800180017001700170017001700170018001700170018001800 -180017001700170017001800180017001700170018001700170018001700170017001800 -180017001700170017001800180018001700170018001700170017001700170017001800 -170018001700170018001700170018001800170017001700170017001700180018001700 -180018001800170017001700170017001700180017001700170018001700170018001700 -180017001800180017001700180017001800170018001800170017001700180017001700 -170018001800170017001700170017001800170017001700180017001700170018001800 -17001700170017000000170017001c000600000000001a001c001c001700000017001700 -180017001700180017001800170017001a001b001700170017001b001700170017001700 -170017001700170018001700170017001700180018001800180017001700180017001700 -170019001700170017001700170018001800180018001700170018001700180017001800 -170017001800180018001800170017001800180017001700170018001800180018001700 -170018001700180017001800170018001700180017001500180019001700170017001800 -0f001a001900170018001700170019001700170017001700170019001800180018001800 -17001700180018001700170017001800180018001800170017001800170019000f001a00 -18001700190011001800180018001800170017001700170018001b00170017001b001700 -17001b0013001900170017001c001b001800180018001800170017001800180017001700 -1700180018001800180017000f001a001700170018001700170018001700190017001700 -180017001800170017001700170018001700170019001700170018001900170017001700 -190017001800170017001700170017001700170018001900170018001700170017001500 -170019000f001a0018001700190013001900170018001800170019001700170017001700 -170017001700170019001800170019001700170018001700170017001700170017001900 -17001700190017001900180018001900170019001500170017001800170019000f001a00 -180017001700180017001700190017001700170018001700170017001700150019001700 -0f0018001700170017001800170018001800170017001800170018001700170017001700 -170017001800170018001700170017001800170018001800170017001800170017001800 -170018001700170017001700170018001800170017001700180017001800170017001700 -180017001700180017001700170017001800170018001800170017001700170017001800 -170017001700170017001700180018001700180017001800170018001700180018001800 -170017001700170017001800170017001800170018001800170017001700170018001800 -170018001700170018001700170017001700170018001800170017001700170018001700 -180017001700180017001800170017001700170018001800170017001700170017001800 -170017001800170018001800170017001700170018001700180017001700180017001700 -180018001700180017001700170017001700170017001700180018001700180017001800 -170018001700180017001800180017001700170017001700170018001800170017001700 -170017001700180017001800170018001700180017001700180018001700180018001700 -18001700170017001800170018001700170017001700170000001c001700170006000000 -00001a001c0017001700000017001700170017001800180018001700170017001a001b00 -170017001700170017001700170017001b0000001700180000001b001700170017001700 -170017001700170018001700170002001700130017001800170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170019001700 -170002001700130017001800170018000f001a0018001700170017001900000017000000 -170017001800170017001700170017001700170017001700170017001700170017001700 -1700170017001700170019000f001a001800170013000200170017001700180017001700 -17001700170017001b00180011000000170017000200130017001b001700170017001700 -170017001700170017001700170017001700170017001700170017000f001a0019001700 -170000000100000000000000000017001700180017001700000017001900180017001900 -000017001700170017001800170017000100000000000100170017001900000000000000 -00000000000017001900190017001900170018000f001a00190017001500020000000100 -000000000000170018001900170017000000190018001500190017000000170018001700 -180017001900170000000000000000001800190015000000000001000000000000001700 -1800190017001700170019000f001a001800170018001700010000000000190017000000 -17001b001700170019001700180018000f00170018001700170018001700180017001700 -170017001700170018001800180017001700180017001800170017001700180017001800 -170017001800170017001700170017001700170018001800170017001700180018001700 -170017001700180017001700170018001700180017001700180018001800180017001700 -170017001800170017001700170018001700180018001700180017001800170018001800 -170017001800180017001700170017001800170017001700170018001700180017001800 -170017001800170017001800170017001800170018001700180017001700170017001800 -170017001800170017001800170018001700170017001700180017001800170017001800 -170017001800170017001700170018001700180017001800170017001800170018001800 -170017001700170017001700170018001700170018001700180017001700180018001700 -180017001800170018001800170017001800180017001700170017001700170017001800 -180017001700170017001700170018001800170018001800170017001800180017001700 -180017001800170017001700170017001700170017001700170017001700170017001700 -17001700000017001c001c000600000000001a0017001700170000001700170017001700 -1800180017001800180017001a0017001700170017001700170017001800170017000000 -170017000000170017001700180017001700170017001700170019001700000018001900 -170018001700170018001700170017001700170018001700170017001700170017001700 -170017001800170017001700180017001700170018001700170017001700170018001700 -170017001700170018001800170019001700000018001900170018001700190010001a00 -180017001800190000001500190000001800180019001700170017001800170017001700 -180017001700170018001700170017001700170019001800170018000f001a0018001700 -1900000019001800170018001700170017001b0017001700170017001700000017001900 -00001b001700170018001700180017001700170017001700180017001700170018001700 -17001700170017000f001a00170017001900000013001800170017001800170019001700 -170000001700000017001800170017000000170018001800170017001800000017001700 -170017000000170017000000170018001800190015001800170017001800170017001700 -0f001a001700170019000000190017001800180017001900150017001700000018000000 -180019001500180000001800180017001800170017000000170019001700170000001500 -19000000190017001800180017001a001500170019001800170018000f001a0018001800 -1700000017001700190000001900170000001c001700170019001700190015000f001700 -180017001700180017001800170018001800170018001700170017001800170017001800 -170017001700180017001800170017001700180017001700170018001800170018001700 -170017001800180017001700170017001800180017001700170018001700180017001700 -180017001700170017001700170018001700180017001700180018001700170017001800 -170017001800170017001700170017001700180017001700170018001700180017001700 -180018001700170017001800170017001700180017001700170017001800170017001700 -180017001700170018001800170017001800170018001700170018001700170017001800 -180017001700170018001700170018001700180017001700180018001700170017001800 -170017001700180017001700170017001700180017001800180017001700170018001700 -170017001800170017001800170017001800170017001700170017001700180017001700 -170018001800180017001800170018001700170018001800170018001700180017001700 -170017001700180017001700170018001800170017001700180018001700180017001700 -1700180017001800180018001700170017001700000017001c0017000600000000001a00 -170017001700000017001700170017001700180017001800170017001a001b0017001700 -1b0000000000170000001b00000000000000170000001700170000001900170018001800 -170017001700170017000000170000000000170019001700180000000000000017001800 -000017001800170018000000170018001700170018001700180018000000190000000000 -190017001900170000000000000017001900170018000000000000001700170019000000 -1700180000001800180017000f001a001800170018001800000017001700000017000000 -000019001900170018000000000000001700170000001700180017001800000017001800 -170018001700170010001a00180017001700000017000000000017001900170000001700 -170017000000180000000000000000000000000018001700000000000000170018001700 -0000190000000000180017001800170018001900150019000f001a001900180017000000 -180018001700170017001700180017001700000017000000170019001700180000001800 -190017001800170017000000190017001800170017001700180000001700170018001700 -190017001700190017001700180017000f001a0017001800170000001700180017001800 -170018001700170018000000170000001700180017001800000018001700170018001900 -170000001800170017001900170019001700000018001700170019001800170017001700 -170018001700170010001a00180017001700000018001700170000001700170000001700 -1700170017001700170017000f0017001700170017001800170017001700170017001800 -170018001800170017001700180017001700170018001700180017001700170018001700 -170018001700170017001800170018001800170017001700180017001700170018001700 -170017001800180017001700180017001800170017001700170017001700180017001800 -170017001800180017001700180017001800180017001700170018001800170017001700 -180017001700170017001700180017001800170017001700180018001700170017001700 -180018001800180017001700170017001800180017001700170018001700180017001700 -170017001700180017001800170017001700170018001700180017001700170017001700 -180017001800170017001700180018001700170017001700180018001700180018001700 -180017001700170018001700170018001700170017001800180017001800180017001700 -170018001800170017001700180017001700170017001700170018001700170018001700 -180017001800180017001700170018001800170017001700180017001700170017001700 -170018001700170018001700170017001700170017001700180018001700170017001700 -000017001c0017000600000000001a001b001c0017000000170017001700170018001800 -17001800170017001a00170017001b000000170017000000000017001700000017001700 -000017000000180017001700170017001700190019001800170000000000170017000000 -170017000100150018001700000017001800000017001900000015001900170017001800 -170018001700190000000000190017000000190017000000170017001900000017001700 -000017001700180000001900170000001900000019001700170019000f001a0017001900 -180000001900170017000000000017001900000017001800000015001900170000001700 -1800000018001900000017001800170017001700170017000f001a001800170017000000 -0000170017000100170017000000170017001b0000001800170000001b00170000001b00 -170000001700170017000000170018000000000017001800000019001700190013001900 -170017000f001a0017001700190000001800170018001900190013001900170000001900 -180017000000170015001700000017001700180017001700190017000000000017001800 -19001800150000001700180017001700170017001900150019001700170017000f001a00 -170017001700000019001700180017001700170017001700000019001800170000001700 -180018000000190019001700150017001700170000000000170019001700180017000000 -1700170019001700170017001700180017001700170017000f001a001800170018000000 -1700170017000000170018001700000017001700000017001b0017000f00170017001700 -170018001700180018001800170017001700170017001700170018001700170018001700 -180017001700170018001700180017001700180018001800170017001700170017001700 -170018001700170018001700180017001800170017001700170018001700170017001700 -180018001800180017001700170017001800170017001700170018001700170017001700 -170018001700180017001700180018001700170018001800180017001800170017001700 -180017001700170017001800180017001700170017001700170018001800170017001700 -170018001700170017001800170018001700180017001700170018001700180018001700 -180017001700170018001700180017001800170017001700180017001700170017001800 -180017001700170017001700170017001700170018001800180017001700180017001800 -170017001700170017001700170018001700180017001700180018001700170018001800 -170018001700180017001800180017001700170017001700170018001700180017001700 -18001800170017001800180017001800170018001700180018001700170017001b001700 -1800170018001700170017001700170000001c0017001c000600000000001a0017001c00 -1700000017001800180018001800170018001700180017001a0017001b00150000001700 -1700170000001b0017000000170017000000000018001700170017001900170018001700 -170017001900000017001800180000001900170000001800180017000000180019001700 -000000001800190017001800150018001700170018001800000017001500190000001700 -1a0017001800180017000000170018000000170017001700180017001700000000001800 -19001500180017000f001a00170017001900000017001700190000001800170017000000 -190017000000190019001700000018001900170000000000180019001700170019001800 -170017000f001a0019001700190000001800170017000000170017000000150017001700 -00001b001b00000017001700000017001700000017001800190000001900180000001500 -19001700000018001800170019001700190017000f001a00170019001700000000000000 -0000000017001900170017000100170017001900000017001a0018000000180017001800 -170017001800170017001800000000001700170018000000000000000000000000001700 -1900180013001800170019000f001a001900190018000000000000000000000019001800 -170018000000180017001700000017001500170001001500170017001800170018001800 -170019000000000018001700190000000000000000000000000019001700170019001800 -170017000f001a001900170017000000190017001700000017001700180000001b001700 -15001700190017000f001700170017001700180017001700170017001800170018001700 -170018001700170018001800170018001700170017001800170018001700170017001700 -170017001800170018001700170018001700170018001800170018001700170018001700 -170017001700170018001800170018001700170017001700180017001800180017001700 -170017001700180017001800180017001800180017001700180017001800170018001700 -180017001700180017001700170018001700180017001700170018001800170017001700 -170017001700180018001700170017001800170018001700170017001800170018001700 -180017001700170018001700170018001700170017001800170018001700180017001700 -170018001700180017001700170018001800170017001700180017001700180017001800 -170017001700170017001700180017001800170017001800180017001800180017001700 -180017001800170018001700180017001800180017001700170017001700170017001800 -180017001800180017001700180017001800170018001700180017001800180017001700 -170017001700170017001700170017001700180018001700170017001700170000001700 -1c0017000600000000001a00170017001700000017001700180018001700170017001800 -170018001a00170017001900000018001700180000001700170000001700170000000000 -170019001700150017001700180017001700190017000000190017001900000017001900 -0000170017001700000017001700170000000000170017001700190018001a0017001700 -180017000000190019001700000017001700190000000000000000001800170000001700 -1900170017001800180000000000190015001a00180017000f001a001800180017000000 -190019001500000017001700180000001700190000001700170017000000180017001700 -00000000170018001700180013001700180018000f001a00170018001700000018001800 -190000001700170000001b0019001700000017001c00020017001700000017001b000000 -170017001700010017001700000019001800170000001700170017001500170017001800 -0f001a001700170018000000130019001900170019001300170019000000000000000000 -000018001700170000001700170017001900170017001900190017001700170000001800 -170001001900170019001700170017001800180019001700170019000f001a0017001700 -180000001800190017001800170017001900170000000000000000000000170019001900 -000018001800170019001900150017001900170017001700000015001700000017001900 -17001900180013001900170013001700180018000f001a00170017001800000017001700 -1700000017001b0019000000170018001b001700170017000f0017001800180017001800 -170018001700180017001700180017001700180018001700170017001700170017001800 -170018001700170017001800180017001700180017001700180017001700180018001700 -170017001700170017001800170017001800180018001700170017001700170018001700 -170018001700170017001700170018001800180017001700170018001700170017001700 -170018001800170017001700180017001700170017001700170018001700180017001700 -180018001700170017001700180018001800180017001700170017001800180017001700 -180017001800170017001700170017001800170018001700170017001700170017001800 -170018001700170017001700170018001700180017001700180018001700170017001700 -180018001800170017001800170017001800170017001800180017001700170018001700 -170018001700170017001700170018001800170017001700180017001700170017001700 -170018001800180017001800170018001700170017001700170018001800170017001700 -18001700170017001700170017001800180018001700180017001b001700170018001700 -1800180017001b001700170000001c00170017000600000000001a001b001c0017000000 -17001700180017001800180017001700180017001a001b00180017000000110019001500 -00001700170000001b001700000017000000170018001900170019001700170015001700 -180000001900170017000000180017000000190017001800010017001800000019001700 -000017001800170018001100190017001700190000001800170018000000170017000000 -190018001700000017001900000018001900170017001900170000001900000019001700 -1900170010001a0018001800170000001700170018000000170017001700000018001500 -000019001500180001001700170000001900170000001700170017001900190017001700 -0f001a001700180017000000180017001700000013001a00000017001700170000001700 -190000001800170000001700170000001900170018000000170017000000190017001700 -000017001800180017001800170018000f001a0019001700180000001900170017001700 -170017001900000019001800180017001900000017001700000019001a00170015001800 -180000001800170019001700000019001700000017001800170017001900180017001700 -17001700180017000f001a00170017001900000017001700180018001900170019000000 -170018001300190018000000170017000000170017001700180017001800000018001700 -190018000000190017000000170015001800170019001800170017001900190017001700 -0f001a001700170018000000170017001900000017001700170000001700170015001b00 -170017000f00170017001700170018001700180017001700180017001800170017001700 -170017001700180018001800170017001700180017001700170018001800170017001700 -180017001800170017001700170017001700180018001800170017001800170017001700 -170017001700180018001800170017001700170018001800180017001700170017001700 -170018001800170018001800180017001700170017001700180017001800170018001800 -180017001700180017001700180017001700170018001700170018001700170017001700 -180017001700180017001700170018001700170018001700170018001700180017001700 -180017001700180018001700170018001700170018001700180017001700180017001700 -180017001700170018001700170018001700170017001700170018001700180017001700 -170018001800170017001700180017001800170018001800180017001700170017001700 -180017001800170018001800180017001700170017001700180017001800170018001800 -180017001700170017001700180017001800170018001800180017001700170017001700 -1800170017001b0017001700170017001800170017001700170017000000170017001c00 -0600000000001a001c001700170000001700170017001700170017001800170017001700 -1a0018001700170000001b0017000000000017001b000000150018000000180017000000 -170018001700170019001300180018001700000000001900170000001800170000001900 -170017000000170000001700170015001700000018001700180019001800190015001700 -000000001700170000001900180000001700180017000000170017000100130017001800 -00001700170000001800170000001900180017000f001a00170015001900000018001800 -170000000000190017000000190017000000190018001700000017000000170017001700 -170000001800180013001a001700130010001a0017001700190000000000180017000000 -1900150000001b0017000000000018001800000015001b00000017001700000017001900 -17000000170017000000170017001700000017001800170017001700170017000f001a00 -170019001700010017001800170017001800170017000000190017001800170017000000 -180017000000170017001300180017001700000017001700170015000000150019000000 -1700170017001700170017001800170017001900170017000f001a001700190018000000 -170019001700170017001900190000001800190017001700150000001700190000001700 -190017001800180017000000170017001700180000001700180000001800170019001700 -170017001800170013001a001700130010001a0017001700180000001900190017000000 -19001700170000001800170017001900170017000f001700180017001700180017001800 -180017001800170017001700180017001800180017001700170017001700180017001800 -170018001700170017001700180017001800170017001700180017001800180017001700 -170017001700180017001700180017001800180017001700170017001700180018001700 -170017001700170018001800170018001700170017001700170017001700170018001800 -170018001800170017001700170017001800170017001800170018001700170017001800 -170017001700170018001700170018001700170017001700180017001700170018001700 -180017001700180017001700180017001800170017001800180017001700180017001800 -170017001800170017001800170018001700170017001800170017001700170018001700 -170018001700170017001800170018001700170017001700180017001800170017001700 -170017001700170018001800170018001800170017001700170017001700170018001800 -170018001800170017001700170017001700170018001800170018001800170017001700 -170017001700170018001800170018001800170017001700170017001800170018001700 -170017001700170000001c001c0017000600000000001a00170017001700000017001700 -170017001700180017001700180018001a0017001b001b001700000000001b0000001700 -170000000000170000001700180018000000180017001700170019001700170018000000 -170000000000190017001700180000000000000017001900000017001900180018000000 -180017001700180018001800190017000000170000000000190013001900190000000000 -000017000000150017000100000000001700190018000000170017001900000017001900 -0f001a001700190018000000170017001800000013000000010017001800170019000000 -000000001700190000001700190018001800000018001700000017001900190010001a00 -170018001700000017000000000017001b0017001700000001001c0000001b001c000000 -00001700000000001b001800000000000000170017001900000018001700170000001800 -1700170001001700180017000f001a001700170017000000170017001900170017001800 -170000001300190018001700180000001700190000000000000001000000170019001700 -000000000000000019001700190000000000000000000000000017001700170000001500 -1700170010001a0017001800130000001700170019001800170017001700000017001700 -170018001900000019001700000000000000000000001900170017000000000000000000 -170017001700000000000000000000000000190017001700000017001900190010001a00 -17001800170018000000000000001900150017001b000000170017000000170017001700 -0f0017001700180017001800170018001700180017001700170018001700180017001700 -180017001700170017001800170017001800170018001700170018001700180017001700 -170018001700180017001700180017001700170017001800170018001700180017001700 -180017001700170017001800180017001700170017001800170017001800170018001700 -170018001800170018001700180017001700170017001700170018001800170017001700 -170017001700170018001800170017001800180018001800170017001700170018001800 -180018001700170018001800170017001700170017001700180018001700170017001700 -170017001700170017001700170017001800180017001700170017001700170018001800 -170017001800180018001800170017001800170018001700170017001800170018001700 -170018001700180017001700170018001800170018001700180017001700170017001700 -170018001800170018001700180017001700170017001700170018001800170018001700 -180017001700170017001700170018001800170018001700180017001700170017001700 -170017001700170017001800170017001700170017001700000017001700170006000000 -00001a0017001c001700000017001700170018001800170017001800170017001a001700 -19001700170019001800170000001700170017001b001700170017001700170017001700 -180018001700170017001900170017001900190017001700170017001800180017001800 -170017001700180017001700170017001700180018001700170017001800180000001800 -170019001700180018001700180017001700190017001900170017001900170017001700 -170019001700190017001700180017000f001a0018001700170018000000190017001700 -180019001300190017001700180018001700170017001700170018001700170017001700 -1700180000001700170017000f001a001800170017001900170018001800170017001700 -170018001700170019001700180017001800170017001b00170017001900170017001700 -170017001700170019001700180017001800190000001800180017000f001a0018001700 -180017001800170017001800170017001700180018001700170018001700170018001700 -170019001800170019001700190018001700170017001900170017001900170019001700 -17001700190017001800170000001800180017000f001a00180017001900170017001900 -150017001700190015001800190017001700180017001900170017001700180017001700 -190017001900170017001800170017001900180017001900180017001700180018001700 -1900170000001700170017000f001a001800170018001700180017001700170019001700 -000018001700170000001700170019000f00170018001700170018001700180017001700 -170018001700180017001700170018001700170018001800170017001800170017001700 -180017001700180017001700170018001700180017001700170018001700170018001800 -170017001700180017001700170018001700170018001800170017001700170018001800 -170017001800170017001700180017001700180017001700180017001700170018001800 -170018001700180017001700170018001800170018001700170017001800170017001700 -170017001700180018001700170017001700170017001800170017001700180017001800 -180017001700170017001800170018001800170017001800180017001800170017001700 -170018001800170018001700170017001800170017001700170017001700180017001700 -180017001800170017001700180017001700180017001700170018001700180017001700 -180017001700170018001800170018001700180017001700180017001700170018001800 -170018001700180017001700180017001700170018001800170018001700180017001700 -180017001700170018001800170018001700170017001700180017001700170017001700 -17001700000017001c0017000600000000001a001c001700170000001800170018001700 -1700180017001700170018001a0017001800180000001500190018000100170019001500 -190018001900150018001800170000000000000000000000000000001700170018001700 -170017001800170017001700180017001700170018001700170017001700180000000000 -000000000000000000001700000017001700170017001800170017001800170017001700 -17001800170018001700170017001800170018001800170018001700180017000f001a00 -190018001700180000001800170017001800170017001800180017001700190017001800 -180018001700190018001900150019001700010018001800180018000c001a0018001800 -180018001700180017001700140018001800170017001700170017001700170018001800 -180018001800170017001800180018001700180018001800180018001800180018000000 -17001800190017000f001a00180018001700180017001800170019001700170018001700 -190017001700170018001800180018001800180017001800170018001800180018001800 -170017001700170018001800180018001800180018001400190000001500190017001900 -0f001a001800180017001800180018001800170018001800180017001800170017001700 -180018001800180018001700170017001800180018001800180018001800180018001800 -180018001700180018001700170018001700000017001700180017000f001a0018001700 -17001800150019001800150019001800000015001800000017001800190017000c001800 -190017001800170017001800180018001800180018001700170017001700170017001800 -170018001700180017001700170018001700170018001700170017001700180017001800 -170018001700170018001700170017001700180018001900170018001700170018001800 -180017001800180017001700170018001700170018001700180017001800180017001700 -170018001700170018001700180017001800180017001700170018001700180018001700 -170019001800170017001800170017001800170018001700170018001700170018001700 -180017001700180017001700180017001800170017001800170017001800170018001700 -170018001700170018001700180017001900150017001800150019001700180017001800 -180018001700180017001700170017001800170018001700170017001800170017001800 -170017001700180017001700180018001700180017001800190017001700170017001700 -180018001700170017001700170017001700170017001700170018001700180018001800 -170017001800170018001700170017001800170017001800170017001700170017001700 -170017001800170017001800170018001700170000001700170017000e00000000001a00 -170017001700000017001800180017001700170018001800170017001a00180018001900 -170001000000000015001900170018001900150018001800170017001900170017001900 -170017001900110019001700170018001800170018001800180018001800180018001800 -170018001800170017001900110019001800190015001700190018000000170018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -1800180018001800180018000f001a001800180017001800170000001900170018001800 -170018001700170017001700170017001700170017001700150019001900150019001500 -18001800180018000f001a00180018001800180018001800180018001800180018001800 -180018001800180018001800140017001700180018001800180018001800180018001800 -1800180018001800180017001900150017001900150019000f001a001800180017001800 -170018001800190018001800190014001700150018001800180018001800180018001800 -180018001800180018001800180018001700180018001800180018001800180017001900 -170018001800150019001800180017000f001a0019001700170017001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800170017001800170019001900 -180018001800180010001a00190018001700190018001800170019001500000018001900 -180019001800180015001900100018001800170016001700170018001800150018001800 -180018001800190017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001800180017001700170017001700170018001700180017001800 -180017001700170017001700170018001700180017001800180017001700170017001700 -170018001700180017001700170017001700180018001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170018001800 -180019001700180017001800180018001700170018001800170017001800170018001700 -170017001800170018001700170018001700180017001700180017001700170017001700 -170018001800170018001900170017001700170017001700170017001700170017001700 -180018001700180017001700170018001800170017001800170017001800170018001700 -170018001700180017001800170017001700170017001800170018001700180017001700 -00001c0017001c000e00000000001a0017001c0017000000170018001700180018001800 -17001800180017001a001900150015001900170017001900190017001700180018001700 -190018001800170015001700190019001700180019001900170018001700180018001700 -170017001700170017001700170017001700170017001700190017001800190018001700 -190019001500190017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170018000f001a0018001700 -180017001700180018001700170019001800180018001800170018001900180018001900 -1800190014001700180015001800190015001800140018000c001a001800170017001700 -170017001800170017001700170017001700180017001700170017001800180018001800 -1800170017001700170017001700170017001700170018001800150019001a0017001800 -170017000f001a0017001700180018001700170017001700170017001700170019001800 -170017001800140017001700180018001700170018001400170017001800180017001700 -170017001700170018001600150015001800170018001a0014001800180017000f001a00 -180018001800180017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -1900170017001800170018001500170017001800170017000c001a001700170017001700 -14001900180017001a001900180018001800180015001900180015000c00180018001700 -180018001700180019001800180018001800170017001700180018001800180018001800 -180017001800180018001800180018001800180018001800180018001800180018001700 -180018001800180018001800180018001800170018001700170018001800170017001800 -180017001800180017001700170017001700170017001800180017001800180017001700 -170017001700170017001800180017001800180017001700170018001800170017001800 -180018001800180017001800180018001800180018001800170018001800180018001800 -180018001700180018001800180018001800180017001800180018001800180018001800 -170018001800180018001800180019001800180018001800170018001400180017001700 -180017001800170017001800170017001700180017001800170017001700170018001700 -180017001700180017001800180018001700170017001700170018001800180018001700 -170017001700170017001700180018001700170017001700180017001700180018001700 -170018001700180017001800170017001700170018001700170018001700170017001800 -18001700180018001700170017001700000017001c0017000e00000000001a001c001700 -1700000018001700170018001700180018001700170017001a0013001900170015001a00 -170018001500170019001900150018001900170017001800180017001700170017001700 -150019001500190017001700170018001700180018001800170018001800180018001700 -170017001900170019001500170017001900170015001700190015001800170018001700 -170018001800180018001700180018001800180017001800180018001700180018001800 -18001800180019000f001a00180017001800180018001700170018001300190015001800 -180018001700170019001400150017001700190018001500190019001700170017001900 -1800190012001a0018001800180018001800180018001800180019001800180018001800 -180018001800180017001700170018001800180018001800180018001700180018001800 -18001800170018001700130018001800180017000f001a00180017001800190017001900 -190018001700180017001700180018001800180018001800180018001900190018001800 -180018001800180019001900180018001800180018001800180019001900180019001700 -1900150018001800170017000f001a001700190017001800180018001800180017001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001700170019001800170018001900180017001900 -1700180010001a0018001800190018001500180019001700170015001500190019001500 -1a001800180018000c001700180018001800180018001700170017001500180017001800 -180018001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170018001700 -190017001700180017001700170018001700170017001700170018001800180017001800 -170018001700170017001700170018001800180017001800170018001700170017001700 -170018001700180018001700170017001700180017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700190014001800 -180018001800180017001700170017001800180018001700170017001700180017001800 -170017001700180018001700170017001800170017001800170017001700170018001700 -170017001700170017001700170018001700170017001700170017001700170019001800 -180018001900170015001800170018001700170017001800170017001700180018001700 -170017001800170018001700180017001700180018001800170017001700170000001c00 -1b0017001d00000000001a00170017001700000017001700180017001700170017001700 -180018001a00180018001800190015001800180019001800180018001800180015001800 -170017001900170018001700190017001900180017001700180018001700170017001800 -170017001800180018001700170017001800170017001700190018001700190017001700 -1a0017001700190017001800180018001700170017001800180018001800170018001800 -18001800170017001800180017001800180018001700180012001a001700170017001700 -170019001700170019001900190017001700170017001800180018001800190018001700 -170018001800190018001900180019001800180012001a00180018001700170019001800 -180018001800180018001800180018001700180018001800180018001800180018001800 -180018001700170018001800180018001800180017001900150018001800180015001900 -12001a001800170018001800180018001500170018001800180018001700170017001800 -180018001800180018001900170018001800180018001800180019001400180018001800 -1800180018001800180019001700170017001700190017001700180012001a0017001800 -170017001700170017001700180018001800180017001700170017001800180018001700 -170017001700170018001800180017001700180018001800170018001700170017001900 -170015001900140013001800170018001700170012001a00180017001800180019001900 -150017001900180019001900180019001900180018001800100017001900180018001800 -180018001800180019001900180018001800180018001800180017001700170018001800 -170018001800180017001700170018001800180018001700170018001800180017001700 -180018001800170018001800170017001800180018001800170017001800170018001800 -180017001700170017001700170018001700170017001800180017001700170017001700 -180017001800170018001800180017001700170017001700180018001800170017001700 -170017001700180018001800180017001700170017001800180018001800170017001700 -170018001800180018001700170017001700180018001800180017001700170017001800 -180018001800180018001800180017001800170018001800180017001800180014001800 -180018001800170017001800170017001800170017001800180017001700170018001700 -170017001800180017001800170017001700190018001700170017001700180017001700 -170017001700170017001700170017001700170018001800180019001700180018001700 -180017001800170017001800180017001700180017001700170017001700170017001800 -18001800170017001700170000001c0017001c000e00000000001a001b001c0017000000 -17001700180017001800170018001700170017000c0011000c000f000c00120010000f00 -10000c000c000c00120010000c0012000f000f000f000f000f000f000f000f000f000f00 -0f000f00100012000f000f000f000f000f000f000f0010000f000f000f000c0010000f00 -0f0010000f000f000f000f000f000f0009000f000f000f000f000f000f0010000f000f00 -0f000f000f0010000f000f000f000f000f000f000f000f000f0010000f000f000f000f00 -0f000f00060011000f000f000f000f000f000f000f0012000f0009000c0010000f000f00 -0f00100009000f000f000f0012000c000c0010000c000c000c0010000c000c000c001000 -0c0012000c000c000c000c000c000c0010000c000f000c000c0010000c000c000c000c00 -10000c000c000c00100010000f000f000f000f000f000c000f000f000f000f000f000f00 -0f000f000f0012000f000f000c0010000900120010000f000f000f000f000f000f000f00 -120009000f0010000f000f000c000c000c000c000c000c000c000c000c000c000c000c00 -0c000c000c000c000f000c000f000f000c000c000c0010000c00100010000f000c001200 -0c0010000f000f000900100010000f0010000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f0010000f000f000f000f000f000f000f000f000f000f000f000f00 -0f0010000f000f000f000f000f0010000f0010001000100010000f000f000f000f000f00 -090012000f000c000c000c000c00100010000f000f000c000c000c000c000d000c000c00 -10000c001200170018001900180017001800180015001700180018001700170017001700 -180018001800180018001800180018001800180018001800180017001800180018001800 -180018001800180018001800180018001800180018001800180018001900190017001800 -170017001700170017001700170017001700170018001800170018001700180017001800 -170018001700170018001800170018001800170017001700170017001700170018001800 -170017001700180019001900170017001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800190015001800180018001800 -170018001700180018001700170018001800180018001700170018001700180017001700 -170017001700170018001700180017001800170017001700170017001800180015001800 -1800170019001800170018001800170017001b0018001700180017001700190018001800 -150018001800180017001700170018001700180017001700180017001700170018001700 -170018001800170017001700180017001700180017001700170017000000170017001c00 -1d00000000001a0017001c00170000001800180014001800180017001800170017001800 -190015001900170018001700140018001500190019001900170015001700170018001700 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a0011001700180017001400180017001700 -180018001900170018001800180018001800180017001800190018001800180018001800 -1800180019001800180018001800180018001800170019001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a00120017001700170017001800180019001900 -180018001800180018001800190019001800180018001800180018001800180018001800 -180018001800150019001800170017001500180019001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -0f001700190018001800180018001800170018001800180016001a001800130018001800 -1700190019001700180017001a0015001500190014001800180018001800170018001800 -170019001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001900120018001700170018001800170018001800170018001700 -180017001800180017001700180018001700170018001700180017001700170017001700 -170018001800170018001700180017001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001900110018001800180018001400180017001800170017001700170017001800 -170017001700170017001700180018001800170017001800170018001700170017001800 -17001800180017001700170019001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001200170017001500180017001800170017001700 -180018001700170017001800180017001700180017001700170017001700170018001800 -170017001700170000001c00170017001d00000000001a00170017001500000017001800 -180017001800180017001700180017001800170019001500190018001500190019001800 -170019001700140018001700180017001a00170018001700190017001800180017001900 -170018001800170018001800180018001800180018001800170018001800170019001700 -180017001700180018001800170017001900170018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001700 -19001700170018001700170017001b001800190017001900170017001700180017001900 -0c0017001800180017001900170017001800170018001900180017001800180018001700 -140018001800180018001800180018001600180018001800180018001600180018001800 -170019001a00190018001700180018001800180018001800180018001800180017001800 -190018001800180015001900190017001700180018001700190018001700180018000f00 -170017001800180018001800180019001800180016001800180018001800190017001700 -170017001700180018001800170017001700170018001800170018001700190018001700 -17001a001900180019001b00170018001800180018001800170017001700170018001800 -180018001800180018001800180018001800180018001800180017001800180018001800 -180018001800180018001900180019000900190014001800180014001800170018001700 -170017001800170018001800180018001700180017001800180018001800190018001400 -18001800150018001800180018001800170019001a001900180017001700170018001800 -180018001800180017001700180018001800180018001800180018001800180018001800 -180018001700170018001700180018001800170018001800180018000c00180017001800 -180017001700180017001700180017001700170017001700170018001700170017001800 -18001700170017001800180017001800170018001700170018001700170017001a001900 -170017001800180018001800180018001800180017001800180017001800180018001800 -180018001800180018001800180018001700170017001700180018001800180018001800 -180018001800180018001800170017001800170019000c00170018001800190015001800 -180018001700170018001700180017001700180018001700180017001700170018001700 -1700180017001700170018001700180017001700180017001800170017001a0019001700 -18001800170018001700180017001b00180017001700180017001800170019000c001400 -180018001700180017001800180017001700170017001800180017001700170018001700 -1800170017001700170018001700170017001700170017000000170017001c0006000000 -00001a001b001c0017000000170017001800170018001800170017001700180018001800 -18001700180018001400180017001800180018001800180017001700190017001a001800 -190017001700180018001700190015001800170017001800190018001700170018001900 -170017001800170017001700180018001700170017001700180017001700170017001800 -170017001800170019001700170017001700180017001700170018001700170017001900 -170017001800170019001700190017001700170017001700170017001700170017001700 -170017001700170018001800180014000c00180015001800180018001700180017001700 -180018001700180014001700180017001700180018001800180017001700180018001800 -18001800180018001800170017001800140019001a001800170015001900170017001700 -18001b001700170017001700180017001700180017001900170017001700180018001700 -17001700180018001700180017000f001800170018001700180018001800170017001800 -170018001800180017001700180017001800140018001700180014001800180017001700 -1700180018001800170018001800180019001a00170017001b0018001700170017001800 -1b0017001800170017001700180018001700170019001300190017001800170018001700 -17001700180017001800170018001900170018001400180017001800180018000f001700 -180018001700170018001700180017001700180018001800180018001800180018001700 -170018001400170018001700170018001800180018001700170018001800180017001700 -1a0018001700190017001800170017001800170017001900170017001900180017001700 -180018001700180018001700170017001800170018001700180017001800170018001800 -17001700170017000f001800170018001700170018001700180018001700170017001800 -180017001700170018001700170017001700170018001700180017001800180017001700 -1800170018001700180018001a0018001700180017001900170018001700170017001900 -150017001700190018001900150017001700190017001700180017001800170018001800 -170018001800170018001800170018001700170017001800170018001700180017001700 -18000c001800180018001800180018001800170018001400180018001700170017001700 -170018001700180018001700170017001800170017001700180017001700170018001800 -170018001700180017001a001800170018001800170018001b0017001700170018001800 -170017001b001700170017000f0017001800170017001800180017001700180018001700 -170018001800170017001800170017001700170017001b00170017001800170017001700 -1700170000001c001b001c000600000000001a001c001700170000001700170017001700 -170018001700170018001700180018001800170018001700180018001800180017001400 -1800180017001800170019001a0019001700170017001700170019001700170019001700 -190017001700190019001700170017001300180017001900170017001700170019001700 -180018001700190017001900180015001800190018001700170018001700180017001800 -170018001700170018001700170017001700190018001700170017001700170018001700 -1b0017001700180017001700170017001b0017001700170019001500190018000c001900 -1a0017001800180018001800170017001800170018001800180017001700180018001800 -170017001800170018001800170017001800180018001700170018001800170018001900 -1a001700190019001500190017001700170017001a001500170017001700190018001700 -1b00170017001b0018001700180017001a001700170017001700180017000f0018001700 -180017001800180017001700180017001700180017001700180017001700180017001800 -180017001700170018001800170017001700170017001800170018001800170017001a00 -17001800170015001b001700190011001700170017001900170018001900170017001700 -170019001700170017001700170017001b00130017001900180019001700170019001800 -1700190017001800170017000f0017001800180017001700180014001700180017001700 -180018001400180018001700180018001800180018001700170018001800180017001700 -180017001800180017001700180019001a00170017001800170017001700180018001700 -170017001800180017001700170019001800170019001700170018001700180017001700 -1900180017001800170017001700180019001800170017000f0018001700180017001700 -170017001700170017001800170018001700170018001800170017001800180017001800 -180017001700170017001700170018001800170017001700170017001a00190017001500 -1800170017001800180017001700170019001800190017001900150019001a0017001700 -170018001800180017001700180017001700170018001700170017001800170017001800 -1800190015001900180018001800170019000c0018001800180015001800180018001700 -180017001800180018001700180018001700170017001700170017001700180017001700 -18001700180017001800170017001700170017001700180019001a001700170017001700 -170017001700170017001700170017001700180017001900190017000f00180017001800 -180017001700170018001700170017001800170017001700180017001700180017001700 -1700170018001700180018001700170017001700000017001c0017000600000000001a00 -170017001700000017001700180014001800170017001800170018001800180018001700 -180018001800170018001700170017001700170018001700180017001a00150017001900 -19001700170017001800170017001800170018001800170017001700180015001a001700 -180017001900150018001500190017001700180017001500180017001700190017001700 -17001800190012001a001700170017001800170018001800170017001700170017001800 -17001700190018001b0017001700170017001700170017001b0017001700170018001900 -180017001500170018001800100018001500180018001700170017001700170014001800 -180017001700170018001800170017001800180017001700180017001800180018001800 -170017001700170017001700180017001a00150019001800180015001800170017001700 -170018001700170017001700170017001700180017001800180018001400190013001800 -180018001700180017000f00180017001800170018001800170018001800170018001800 -180017001700170017001700180018001800170018001800170018001800170018001700 -17001800140018001800170019001a0019001700170015001900170017001b0017001700 -1700170017001700170017001b00170017001700170017001700170017001b0017001900 -170015001800170017001800180018001900130017001800170017000f00170018001700 -180017001800180017001800170018001700170018001700170017001700180018001700 -17001700180018001700170018001800170017001800170017001800170018001a001900 -190017001700170018001700180017001a00170017001700190017001900180015001700 -190017001900170018001700170019001700180017001900170019001800170017001700 -170017000f00170017001800170017001700180018001700180018001700170018001700 -180017001800170018001700170017001700170017001800180017001700170017001700 -17001800180017001a001800190017001900170017001900190017001900170017001500 -1700180018001700170017001500180017001800180015001700170018001a0018001700 -17001800170019001700180017001800190015001a001500150018001700190018000d00 -180018001800170018001800180018001700180018001800170017001700170018001700 -180017001700180017001700180018001700180017001700170018001700180018001800 -1700170017001a0018001700190019001100190019001c001b0017001500180017001700 -170017001700170010001800150019001700170017001800170017001700180017001700 -170018001800170017001800170017001700170017001800170018001700170017001700 -0000170017001c000600000000001a0017001c0017000000170018001800170018001800 -180017001800170018001800170017001700170018001800180017001700180018001800 -18001700170017001a001800190015001700170018001700180017001700150018001700 -190017001700190017001700170017001700170017001700180019001800170018001300 -1a0017001800190017001700180019001700190018001700170017001800170017001700 -170017001700180015001900190017001800190013001800170017001900170017001a00 -11001b00170013001b0017001700180013001b0018001a00180015001200190017001800 -180017001800180018001700170018001800170017001700180017001700170014001700 -18001700180018001700170018001800140018001800170018001800180018001a001800 -18001500190018001700170018001700130017001b001700180017001700180017001700 -18001100170018001900170017001700150017001800180017000f001800170018001700 -160018001800170014001800180017001800180016001700180018001800170017001800 -1700170018001800170018001700180018001800180018001800170017001a0017001700 -180019001700170017001700170017001a00170017001700170018001700170017001700 -170018001700170017001c001700170017001b0017001800170019001300170017001900 -17001800170018000f001700180017001700180018001800180017001700180018001700 -170018001700170017001800180017001700170018001700170017001400170018001700 -1800180018001700170018001a0017001800170019001700170017001900170013001700 -180017001500190015001700190017001700180015001900170017001700170017001700 -17001a00150019001700180018001500180017000f001800170018001700170017001800 -170017001700170017001800180017001700170018001700170017001800180017001800 -1700180017001700180018001700180017001800170017001a00170017001a0018001900 -170017001700180017001800170019001800180019001700190017001900180017001800 -15001a001700170017001800170017001700190017001700180017001800170018001500 -18001800190017001900150018000c001800180018001700180018001700170017001700 -170018001800180017001800170017001800170017001800180017001700170017001700 -170018001700180017001700170017001800170018001a0018001700190017001a001700 -17001700170017001800170017001b001900170018001700100019001500180017001800 -1800170017001800180017001700180018001700170017001800170017001b0017001700 -180017001700180017001b001b001700000017001c001b000600000000001a0017001700 -170000001700170018001700170018001800170018001700170017001700180018001800 -1700180018001800170017001700170018001800180017001a00180015001a0018001700 -17001800170017001a000000170019000000190015001700190018001700180019001700 -170017001700000018001800170018001700190017001700170018001700170018001300 -170018001800180017001700180018001800170017001700190018001500170017001700 -19001700170017001700170017001700170017001b001700170011001700000017001700 -1500150018001a000c001500190019001700180018001800180018001700180017001800 -180018001400170017001800180018001800170017001700170017001700180018001800 -1700170018001700150017001a00190015001a001900170000001700000017001b001800 -17001b001700170017001700170017001b00170018001700170017001900180018001900 -1700180017000f0017001700180018001800170018001800180017001800180017001800 -180017001700180018001800180017001700180018001700170017001800180017001700 -18001800180017001b001a001700170017000000180017001b0017001700170013001700 -1700170017001700170000001800170000001300170017001b00170017001b001b001300 -1700180015001800190018001800180017001800170018000f0017001800170018001800 -180017001800140018001700180017001700170018001800180017001700180018001800 -1400170017001800180018001800170017001700170017001a0015001a00190015000100 -000000000000000000000000190000000000000000000000170019001500000017001700 -1900150000001700190000000100000000000000000015001900170017001a0017001700 -0f0018001700180017001700180017001800180018001700170017001700170018001700 -180017001800180017001700170018001700170017001800170017001700180017001700 -170018001a00180017001500000000000000000000000000190017001700170017000000 -17001a001700170018000000170017001900170017001800190000000000000000001500 -1800170000000000000000000000020015001900170018001500190019000c0017001700 -180017001800170017001800180018001700170018001800170017001800170018001700 -170017001700170017001800180018001700170017001700180018001700180017001700 -18001a00170019001700170000000000000017001b000000170017001700170017001700 -190018000c00170018001700170018001700170017001800170017001700180018001700 -170018001700170017001b00170017001700180017001700170017001700170000001700 -1c001c000600000000001a001c001c001700000017001700170018001700170017001800 -170018001700180018001800170017001700170017001800180018001700170018001800 -170019001a00170019001700150018001700170017001800170000001700180000001700 -180019001700170018001700170018001900170019000000170019001700170018001500 -190017001800170017001900170018001900180017001700180017001700170017001700 -18001800170017001900180017001800180018001700180017001a001c00170017001700 -1700170017001a0017000000170017001900190017001800100017001700170017001700 -180018001700180017001800180018001700180018001800170017001800180018001800 -180017001700170017001800170018001700170018001400190019001a00180015001700 -190000001700180000001700170017001700170017001700170017001900170017001700 -170017001900190015001700170017001800180017000f00180017001800140017001700 -170017001700170018001700180018001700180017001400180018001700170018001700 -17001700180018001700180018001800180018001800170017001a001b00170019000000 -17001b0017001b00170017001b0017001b001700170017001b00000013001b0000001b00 -170017001700170017001700170017001800170019001300180018001700170018001800 -170018000f00170018001700180017001800180017001800180018001800180018001700 -180017001700180018001800170018001800180017001700180018001800180017001800 -17001700170017001a001800190017001800180000001800170017001800000017001900 -170017000000170019000000180017001700190000001700170000001700180017001900 -170019001700180017001500170017000f00170017001800170017001700170017001700 -170017001800180017001800180017001700170017001700170018001700180017001800 -17001800170018001700180017001800170018001a001700170019000100170019001700 -190011001800190017001900000018000000170017001700180000001700190017001800 -170018000000190019001300190000001700190001001700180017001800170018001800 -180017001900170018000c00170014001800170018001700180018001700180017001800 -180018001800170018001700170017001800170018001800170017001700170017001800 -1800170017001700170017001800180019001a0019001700170000001700190017000000 -17001700000017001700170018001700170017000c001700180018001800170017001800 -180017001700180018001700170017001800170017001800170017001700170018001700 -17001700170017001700170000001700170017000600000000001a001c00170017000000 -170017001700180017001700170018001800170017001700180018001700180018001700 -17001800180017001700170018001800180018001a001700170019001900000000001700 -020013000000010000001700000017001800000017001900180017001800170017001800 -170000001900000000001800190018001800000000000000170017000000180017001700 -170000001800170017001700170018001700170000001900000000001700180017001800 -0000000000001700170017001700000000000000180013001700000017001b0000001500 -1a0014000c00190018001800170017001800140017001800170017001700170018001800 -180018001700180017001800170018001800180018001800170017001800180017001700 -18001800170017001a00180019001900150000001b001700000017000000000013001700 -1b0017000000000000001b00170000001900180015001900000017001900170018001800 -17000f001700170018001700170016001800180018001700180017001800170018001700 -170017001700180018001700180017001400180017001800180017001700170018001800 -1800170017001a00170017001700000018000000000017001700170000001b0017001700 -000017000000010000000000000000001700170000000000000017001700180001001700 -00000000180018001700190017001800180017000f001700180017001700170017001800 -170018001700170017001800170017001800140017001800170017001800180018001800 -1700180017001800170018001800180018001800170018001a0017001700170017001700 -000019001700170019000000190017001700190000001900170000001700190018001700 -00001800180000001700180017001700170017001700180019001800180017000f001800 -170018001700170017001800180017001800170018001700170017001700170017001800 -180017001800180017001700180018001700170018001800170017001800180017001700 -1a0019001900170000001800170017001700190017001700170017000000170000001700 -180017001700000019001700180017001900170000001900170019001700180018001700 -00001700190017001900150018001800150019001700180018000c001800180017001700 -180017001800170017001800170017001800180017001800170017001700180017001800 -170017001800170017001700170018001700180017001800180017001800170017001a00 -170017001a000000170017001b0000001800170000001700170018001500190017001700 -120017001700170018001700170018001800170017001800170017001700180018001700 -170018001700170017001700170018001700170017001700170017000000170017001700 -0600000000001a0017001700170000001700170018001800170018001700170017001700 -180018001400180017001700180017001800180017001800170017001800180017001800 -1a0018001700190000001700170000000000190017000000170018000000180000001800 -170017001700180018001700170018001700000000001700180000001700180000001800 -170017000000170018000000180018000000170017001700180018001700170018001700 -0000000017001700000018001700000017001700170000001700170000001b0017001700 -000019001700000017000000180019001500170010001400180017001800180017001800 -180018001700170017001700170017001800180018001700170017001700180018001800 -1800180017001700180017001800180018001700180018001a0018001500190001001700 -170017000000000017001700000017001700000017001700190000001800170000001700 -1900000019001800140019001700180017000f0017001700180017001800180017001800 -170017001700180018001700180018001700180018001700180017001700180018001800 -17001800170017001700170017001700180018001b001a00170017001700000000001700 -1700000017001b000000170017001700000017001700000017001b000000170017000000 -17001700170000001b001700000000001700170000001700190017001700180017001800 -0f0017001800170017001800170018001800180017001700170018001800180018001800 -170017001700170017001700180018001800170017001700170018001800180018001800 -170017001a00170017001900170018000000170019001800170000001700180017001800 -000018001700000018001700170017000000170019000000190017001700170018001700 -1700170017001800170017000f0017001700180017001700170018001700170018001700 -170017001800180017001800170018001700170017001700170018001700170017001800 -170017001700180017001700170018001a00170018001700000019001500190017001700 -170019001700000018001700170000001700170019000000180017001800170019001700 -190000000000170018001700180018000000180017001700170019001500190017001800 -180018001800100018001800170017001800180018001700180017001700170018001800 -170017001700180017001800170017001700180017001700180018001700170017001800 -17001700180017001700170018001a001900170017000000190018001700000017001700 -180000001700170000001700180017001000180019001700170017001800170017001700 -18001700170018001800170017001700180017001b001700170017001800170017001700 -170017001700170000001c001c001c000600000000001a00170017001700000017001700 -170017001800180017001700170018001800170017001800170017001700180017001700 -170018001800170017001800190017001a00170019001700000017001800170000001800 -170000001900180000000000170017001800170018001700170017001800170017000000 -17001800170001001700170000001700170017000000170017001b00000000001b001700 -17001b001700170018001700180018000000170017001700000017001800170017001b00 -17000000180017000000170017001c001700170017000000000017001700190015001800 -0f0018001700170017001800180017001800170018001700180017001800180017001700 -170018001700170018001700180017001800180017001800170017001700180017001700 -180017001a00170017001800000019001800170000001700180017000000170019000000 -170019001700000019001700170000000000190017001700190017001700180017001000 -180018001800170017001700180017001800170017001700180017001700170018001700 -180017001700180017001700180017001700170018001800170018001700180017001700 -17001a0017001b001700000017001b001700000017001700000017001700170000001700 -170000001700190000001b00170000001700190017000000170017000000170017001700 -000017001700180017001800170019000900180017001800180017001800170017001800 -170017001700180018001700170018001700170018001700170017001800170017001700 -18001700170018001800170017001700180018001a001700170017001800170000001700 -170019001700000000000000000000001700170017000000170017001800170000001700 -170000000000000000000000000017001900170017001800180017000c00180018001800 -170018001800170018001800170017001700180017001700180017001800170018001800 -18001700170017001800170017001700180017001700170018001700170017001a001800 -170017000100000000000000000017001900170017000000170017001700010018001700 -180000001900170017001700170018001700170018000000000019001700170000000000 -000000000000000017001700180017001800180017000f00170017001800170018001700 -180018001700180017001800170017001800170017001800170017001700180017001700 -1800180017001800170018001700180017001800170017001800170018001a0018001800 -170000001700170019000000170018001700000018001700170018001700190009001800 -170018001700180017001700170018001700170017001800180017001700180017001700 -180017001700170018001800170017001700180017001500000017001c00170006000000 -00001a001b001c0017000000170017001700170018001800170017001700170017001700 -18001700170018001800170017001800180017001700170018001700170019001a001700 -170018000000190017001700000018001700000017001700010000001700170018001800 -15001a0019001700170017001700010017001700170000001b0018000000170017001700 -000017001700170000000000170017001b00110017001900170017001800170000001700 -170019000000170017001800000000000000000017001b00000017001800170017001700 -1b0000000000170018001800180018001200180015001900170017001700180017001800 -170018001700170017001700170018001700180017001800180017001700170017001700 -17001700180018001700170018001800170019001a001700180017000000170017001800 -000019001700170000001800170000001900150017000000170019001800000000001700 -19001800170017001700180017000c001800180018001700180017001800170017001800 -180017001700180018001700170018001700180017001800180017001800170018001700 -1700170017001700170018001800170017001a001b001700170000001100170018000000 -17001b000000170017001700000017001b00000017001700000017001800000017001700 -17000000170017000000170017001900000017001700170017001900170017000f001900 -170017001800170018001700180017001700180018001700170017001800170017001800 -170018001800170017001800180017001700180017001700170018001800170018001800 -1a0017001700170018001700000018001700190017000000170017001700000019001800 -170000001700180017001b00000017001700000017001800170015001900170015001900 -17001700180017000f001800180018001700180017001700170017001700180017001800 -170018001800170017001700170017001700170018001800170017001800180017001700 -1800180017001700180018001a001a001700190000001900170017001900170017001800 -170000000000000000000000130019001700000019001700190019001700130018001800 -180017001800000018001700010017001800180017001800170017001700170018001700 -17000f001700180017001700180017001700170017001700170018001800170018001700 -170018001700180017001700180017001700170017001700170018001700170017001800 -180017001800170017001a00190018001700000019001700170000001700170019000000 -1800170017001900170017000f0019001700170018001700170018001800170017001800 -180017001700170018001700170018001700170018001700170018001800170017001800 -1700170000001c001b001c000600000000001a0017001c00170000001700180017001800 -180017001700180018001700170018001800170017001800170017001700180017001700 -1700180018001700170017001a0018001900170000001700170019000000170017000000 -170019000000170000001700180017001900130017001700170017001700000018001700 -1b00000017001700000017001b00170000001800190000001b0017000000170018001900 -180017001700170018001800000019001700130000001900170000001800170017000000 -1b001500000018001700170017001b00170000001700000019001700190015000c001700 -190018001800170018001700170017001800170017001800180017001800180017001700 -170017001700170017001800180017001800170017001700180017001700170018001700 -1a0017001900190000001900180018000000190019001700000018001700000017001b00 -1700000017001700000018001800000015001700170019001800180018000f0014001800 -180018001700180017001700170017001800170017001700180017001800170018001700 -170017001700170017001700180018001700180018001700170017001700170017001a00 -170017001b0000001b0018001800000017001700000017001700170000001b0017000000 -170017000000170017000000170017001700000017001700000018001700170001001900 -1700170018001700180018000f0017001700170017001800170017001800170017001800 -170017001700180018001700170018001700170018001700170017001800170017001800 -180017001700170018001700180017001a00180018001700180017000000170018001700 -170000001900180017001800000015001700000017001b0017001700000017001a000000 -1b00170017001900180017001a00180019001700170017000f0018001700180017001800 -170018001800170018001800170017001700170017001700170018001800170018001700 -180017001800170018001700180017001800170018001700180017001a00130019001900 -000017001700170017001700190017000000130018001700170019000000170019000000 -170018001700170018001900000017001700180017000000190017000000190011001900 -1800190017001800180018001800170017000f0017001700170017001800170017001800 -180017001700170017001700170017001700170018001700180017001700180017001800 -18001800170017001800180017001700170017001700180017001a001700170019000000 -130018001300010019001300180000001700170018001700180018000f00170017001700 -180017001700180018001700170018001700170017001800180017001700180017001800 -1700180017001700180017001700170017001700000017001c0017000600000000001a00 -170017001700000017001700180018001700170017001700170018001800170017001700 -180017001700180018001700170018001800170017001700180017001a00170017001800 -000018001700000000001900170000001700170000001800170000001700170017001900 -170018001800170017000000000017001700000013001a00000017001700170000001800 -000019001700170017000000170018001700170019001900150017000000000019001700 -00001700180000001700180017000000170018000000170017001b000000170017000000 -1700170000001900180019000f0019001500170017001800170018001800180017001800 -170018001700170017001700170018001800180017001800170018001700170018001700 -180017001800170018001700170019001a00190011001700000017001700170000000000 -13001b000000190018000000170017001800000019000000180017001900190000001900 -170015001800180018000f00180018001800170017001700170018001800170017001800 -180017001700180017001800170018001800170018001800180017001700170017001700 -18001700180017001800180018001a001800170017000000000017001700000017001700 -00001b001700000000001700170000001b00170000001700170000001700130018000000 -1b0017000000170017001800000017001800170017001700170017000f00170019001700 -170017001700180017001700180017001700180018001700170017001800170018001700 -17001800180017001700180017001700170018001800170017001800180017001a001700 -17001700180017000000180017001700170000001700170017001b00000017001b000000 -170017001700170000001700170000001700170019001800150018001700150018001700 -180014000f00180017001800170017001700180017001700170017001700180018001800 -170018001700180017001700180017001700170018001700170017001800170017001700 -18001700170017001a001700180017000000170017001700170017001700170001001900 -170018001700170000001700170000001800170017001700180017000000180018001700 -180000001700170000001700190017001700170019001700170017001900170017000f00 -170017001800170018001700170017001800170018001700180018001700180018001700 -170017001800170017001800170017001700170018001700170017001800170018001800 -1700170018001a0017001700190000001900170019000000170017001700000017001700 -17001700170017000f001700190017001700170018001700170017001800170017001800 -180017001700170018001700170018001700170018001700170018001700170017001700 -00001c001b001c000600000000001a001b001c0017000000170017001700170018001800 -180017001700180018001700170018001800170017001800170017001700180017001700 -17001800180019001a001700190018001500000000001700000015001900000000001900 -000019001700180000001900190017001700190017001700180000001700000000001800 -180017001b00000000000000170018000000170017001700170001001700170019001700 -150018001900190000001800000000001a00170017001700000000000000190000001700 -1b0000000000000011001700170000001900170017000000170018000f00150019001900 -170018001700170017001700180017001800170018001800180017001700170017001700 -17001800170017001700180017001700180017001700170018001800170017001a001700 -1a0017000000170019001800000017000000000017001700190017000000010000001700 -17000000180015001800150001001300190000001700180017000f001800180018001700 -180017001700180017001700180017001800170017001800180017001800170017001800 -1700170017001700180017001800170017001700180017001700170019001a0017001800 -170000001800000000001b00170019001700000000001700000019001700000000001700 -000000001700170000000000000017001500180000001700180017000000170018001700 -00001800170017000f001700170017001800170017001700180017001700180018001700 -170017001700180017001700180017001700170018001700170018001800170017001700 -1800170017001700180017001a001700180017001800170000001a0013001a0018000000 -190017001700170000001700180017000000000000000000170017001700000000000000 -00000000000018001700170001001800180018000c001800170018001400180018001700 -180018001800170017001700170017001700180017001700170018001700170018001700 -1800170018001800170017001800170018001700180018001a001a001700170001001700 -170017001700180017001900000017001700170018001900000019001700000000000000 -000000001800170019000000000000000000170018001900000000000000000000000000 -19001700190000001700170017000f001700180017001700180017001800170017001700 -180017001700170017001800180017001700170018001700170017001800180017001800 -170017001700180017001700170017001800170017001a00180019001700170000000000 -0000180017001900180000001800170000001800170017000f0017001700170017001800 -180017001700180018001700170018001800170017001800170017001700180017001700 -1700180018001800170017001700170000001c0017001c000600000000001a001c001700 -170000001700170017001800180018001700180017001700170017001800170017001700 -1800170017001800180017001700180018001700170018001a001700170015001a001500 -170017000000170017001800170017001800170019001700180018001700170017001700 -15001a001700180019001700170018001500170017001b00170017001700170015001900 -180017001900130019001800190017001800190015001700000017001900170017001800 -1800170017001b00150018001700170017001b00170017001a0018001700190015001700 -18001500180018000f001800170019001700170018001800180017001800170017001700 -170017001700170018001800170018001700180017001800170018001800170018001700 -1800170017001700170018001a0017001900180017000000170017001700180018001800 -190018001800170017001700170019001900180018001900180017001800190018000000 -1800180017000c0018001400180017001800170017001800170018001700180017001800 -170017001700180017001800170018001800170018001800170017001800170018001700 -180017001800170017001a0019001800190011001700170018001700170017001b001700 -17001700170017001800170017001700170019001b0017001700150017001b0019001800 -1800190017001900170017001800170000001700170019000f0017001700180018001700 -180017001800170017001800170017001800180018001700170018001700180018001700 -170018001700170017001800180017001700180018001700180017001a00170017001700 -1800170019001700180013001700180017001900170018001b0013001700170017001700 -170017001700170018001700180017001800170017001900190015000000150018001800 -100018001700180017001800170017001700170017001700180018001700180017001800 -170018001700180017001800180017001700170017001700170018001800170017001700 -170017001a00170017001900170017001800190017001700170018001800170019001700 -190015001900170017001800190017001700170018001700170017001800170017001700 -180015001900180017001a001500190017001800180000001800180017000f0017001700 -180017001800170018001700180017001800170018001700170017001700170018001700 -180017001800170017001700170017001800180017001700180018001800170018001700 -19001a001800170017001900180017001900180019001700000017001700170000001700 -170019000f00170017001800180017001700170018001700170017001800170017001700 -180017001700180017001800170018001800180018001800170017001700170000001700 -170017000600000000001a00170017001700000017001700170017001800180017001800 -180017001700180018001700170018001800170017001800170017001700180017001700 -190017001a00170018001800000018001900150000001700170019001700170017001700 -170019001700000000000000000001000000000017001500190017001900170018001800 -150017001700190017001800190015001700170019001800000000000000000000000000 -010017000000170017001900170017001900170018001800170019001700170018001700 -1900150017001700180017001700180018001800170018000c0019001900150018001700 -170017001700170017001800170018001800170018001700180017001800180017001700 -180018001700170017001700170018001700180017001700190017001a00170017001800 -170000001700190019001500170018001300190017001700190018001800180013001800 -180017001500180019001300010018001800180018000f00180017001800170017001700 -170017001700170018001700170018001800170017001800180017001700170017001700 -1700180017001800170017001800180017001700180018001b001a001700170017001700 -1a0017001800170018001700170017001900170017001700170017001700170019001700 -170017001700170019001700150017001700130018001700190017001700000017001900 -170017000f00170019001700170017001700170017001700170017001700180017001700 -180017001700180017001700180017001700180017001700170017001800170017001700 -18001700180017001a001800170017001700170018001700180019001700180018001700 -1900110015001a0017001b0017001700170018001b001700170017001900170018001700 -170017001800000019001700180017000f00180017001800170018001700180018001700 -180017001800170018001800170017001800180017001700170017001700170017001800 -18001700170017001700170017001800180017001a001800180017001700170017001700 -180017001700180018001700170013001700180018001800170019001700190017001900 -170018001900170017001800190017001800190017001700170017001900170018001700 -000017001900170017000f00170017001800170018001700170017001800180017001700 -180018001800170017001800170018001700170017001800170018001800170017001700 -1800170017001700170017001700180017001a0017001700180015001700180017001700 -17001800000017001900000017001900170017000f001700190017001700170017001800 -170017001700180017001700170018001800170017001800170017001700180017001700 -18001800170018001700170000001c0017001c000600000000001a0017001c0017000000 -170017001700170018001800170017001700180018001700170017001800170017001700 -18001700170018001800170017001800170018001a001700190018001700000000000100 -170018001900150018001800180017001900170017001700190017001700170018001800 -170018001700170017001800170017001900170017001700190017001700170017001700 -180017001700170019001700170019001700180000001700170017001700170018001800 -170019001800170017001700180017001700170017001b00170018001800170017001900 -170019000f00170018001800180017001800170018001800170017001700180017001700 -180017001700170017001700170018001700170017001800180018001700170017001800 -17001700170018001a001800170017001800170000001700180018001800180019001700 -180018001700170018001700190018001800170019001700170019001700170018001800 -18000c001800180018001700170018001800170018001700170018001700170017001800 -170017001700180018001700180018001700170017001700180017001700170018001700 -1700170017001a00190017001b0018001700170017001900170017001b00170017001700 -170017001700170017001b001700180017001b0017001700180019001700170017001900 -170019001700170019001700170017001700170010001800170017001700180017001800 -170018001800170017001700180017001700170018001700180017001700180017001700 -1700170018001700170018001800170017001800180018001a0018001700170018001700 -17001800170017001700180017001900170017001900170018001700170018001b001300 -17001700180018001700180017001900170017001700180018001900140017000c001800 -170018001700180017001800170017001800170017001700170017001700180017001700 -170018001800180017001800170018001700170018001800170018001700180017001700 -1a0017001900170017001700170017001700170018001700170017001800190018001700 -170017001700170018001700170017001700180015001800190017001700170018001800 -17001800180019001700170018001700170018001700180017000f001700170017001700 -180017001800170017001700180017001700170018001700170018001700170017001800 -170018001700170018001700180017001800170018001700180018001700170017001a00 -17001700190017001a001700170017001800000017001700170018001700170017001700 -100018001700170017001800180017001700180018001700170018001800170017001700 -18001700180017001800180017001700180018001700180017001700000017001c001c00 -0600000000001a0017001700170000001700180017001800180018001700170017001800 -170017001700180017001700180017001800170018001700180017001800180018001700 -1a0017001700190017001900180018001700180017001800170018001700180017001700 -180017001700170018001700180017001800170018001800170018001800170018001800 -180018001700170017001800180018001800180017001700170017001800170017001700 -180017001700180018001700170017001700170017001700180017001800170018001700 -18001800170017001700180017001700180017000f001700170018001800180017001800 -170018001700180018001800180017001800170018001700170017001800170017001900 -1700180018001800170018001700180017001800180017001a0017001700190017001700 -170017001700180018001700170017001800170017001800180017001700170018001700 -1800170018001800170017001700170018000f0018001900180018001800170018001700 -180017001800180018001800180018001800180018001800170018001700180017001700 -170018001700180017001800170018001800180017001a00170017001900170017001700 -170017001700170017001700170017001800170018001800170017001700180018001700 -170018001700170018001800170017001800170017001700180017001700170019001700 -0f0017001700170018001700180017001800170018001800180018001700180017001800 -170018001700180017001700180017001900170018001700180017001800170018001800 -190017001a00170018001900170018001700180017001700180017001700170018001700 -180017001800170018001700180017001700170018001700170018001700170018001700 -180018001800180018001500100018001800180017001700180018001800170018001700 -180017001800170018001700180017001800180017001800170017001800170019001700 -180018001800180017001800180017001a00180017001700170018001800170017001700 -180017001700170018001700170018001700170018001700170017001800170017001800 -170017001700180018001700170018001700170017001800170017001700170018001700 -1700180017000f0017001700180017001700170018001700180017001800170018001800 -170018001700170018001700190017001700170017001800180017001800170018001800 -17001800180017001800170017001a001900170019001700170017001700170018001700 -170017001800170017001700190017000f00170017001700180017001800170018001700 -180018001800180017001800170018001700180018001800170017001800180015001800 -170017001700170000001c0017001c000600000000001a001c001c001700000017001800 -180017001700180017001700170017001800170017001800170017001700170017001700 -170017001700170017001700180018001a00180017001700170018001700180018001700 -180017001700170018001800170018001800170018001700170018001700170017001800 -170018001700180017001800180018001800180017001700180018001800180018001800 -170017001700180018001800180017001700180017001700180018001800170017001700 -170017001700180017001800170018001700170017001800170018001700170018001700 -0f0018001700180017001700170017001700170017001700170017001700170017001700 -170017001700180017001700180018001800180017001700170017001700170017001700 -170017001a00190017001800170019001700170017001700180018001800170017001800 -170017001800180018001700180018001800180018001800180017001800180018000c00 -150018001700170017001700170017001700170017001700170017001700170017001700 -180015001700170018001700180019001700170017001700170017001700170017001700 -17001a001700170018001700180018001700170017001700170017001800170017001800 -170017001700180017001800170018001700170018001800180018001700170017001700 -180017001800170017001700170017000f00170017001800170017001700170017001700 -170017001700170017001700170017001700170017001700180019001700170017001800 -17001700170017001700170017001700170017001a001800180018001700180018001800 -170018001800170018001700170018001700170017001800170018001800180018001700 -170018001800180018001800170018001700180018001800190018001000150017001800 -180018001700170017001700170017001700170017001700170017001700170017001700 -17001800190019001700170017001700170017001700170017001700170017001a001900 -170018001800170017001700170017001700170018001700180017001800180017001800 -180017001800170017001800170017001800180017001800170018001700170018001800 -170018001800170018001700170018001700170018000f00170017001700170018001900 -170017001700170017001700170017001700180019001900170017001700180017001700 -1700170017001700170017001700170017001700170017001700170017001a0017001700 -18001700180018001700170017001700180017001800170017001700170017000f001700 -170018001700170017001700170017001700170017001700170017001700170017001700 -1700170018001700170018001700180017001b0017001700000017001c00170006000000 -00001a001c00170017000000170018001700170018001800180017001800170018001700 -19001900170017001800170017001800170018001700180018001800170018001a001800 -180018001700180018001800180017001800180018001800180018001800180018001800 -180018001800180018001800180018001800180017001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180019001700180017001200170017001700170018001700180017001800 -180017001800180018001800180017001800170019001700170017001800170018001700 -17001800170018001700180018001700170017001a001900190018001700180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180019001800170012001800190018001800170018001700180017001800 -180018001800180018001800180017001800180017001700190017001700180017001700 -1800170018001700180017001800180019001a0017001700180017001900180017001700 -170017001700180018001700180018001800180018001800180018001800180018001800 -180018001800180017001800170018001700180018001700180017001800170010001700 -170017001700180017001800170018001800180017001800180018001700180018001700 -170017001700190017001800170018001700180017001800170018001800180017001700 -1a0018001800170017001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800150012001700180018001700150018001800180018001800170018001700 -170018001700180017001800180018001800170017001800170018001700170018001800 -1800180018001700180017001a0019001800180017001700180017001700170017001800 -170018001800170018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800170018001800180018001800 -170010001800170017001700170017001700180017001800170018001800180017001500 -170018001700180017001800170018001800170018001800180018001800170017001800 -180018001800180019001a00170017001800170019001800170017001800170017001800 -180017001800170018001700100017001700170017001800170018001700180018001800 -170018001700180017001800180017001700170019001700150018001800180017001700 -1700170000001b001c001c000600000000001a0017001700170000001700170018001800 -180017001700170018001700170017001700180017001700170017001700170017001700 -17001700180018001800170012000f000c000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f0010000f000f000f000f000f000f000f000f000f000f000f001000 -0f000f000f000f000f000f000f0010000f000f000f000f000f000f000f0010000f000f00 -0f000f000f000f000f0010000f000f000f000f000f000f000f0010000f000f000f000f00 -0f000f000f000f000f000f000f0010000f000f000f000f000f000c000f0012000f001700 -180019001700170017001700170017001700170017001700170018001700170017001700 -190013001800180018001700190018001700170017001700170017001700170019001700 -12000f000c000f000f000f000f000f000f000f000f000f000f0010000f000f000f000f00 -0f000f000f0010000f000f000f000c000f000f0010000f000f000c0012000c0015001700 -170019001700170017001700170017001800180017001700170017001700170017001800 -190018001700180017001700170019001700170017001700170017001700180011001100 -0f0010000f000f0010000f000f000f000f000f000f000f000f000f000f0010000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f00100012000f0017001700180017001700170017001700170018001800 -170017001700170017001700170017001900170017001900180015001800180017001700 -1700170017001700180018001900170012000f000f000f000f000f000f000f000f001000 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000c000f000f000f000f000f000f0010001000100017001900190019001800 -170017001700180017001700170017001700170017001700170017001800180019001700 -1700180018001500180017001700170017001800170017001700170010000f000f000f00 -0f000f00100010000f000f000f000f000f000f000f000f000f000f000f0010000f000f00 -0f000f000f000f000f000f000f000f000f0010000f000f000f000f000f000f000f001000 -0f000f000f000f000f000f000f000f0010000f0017001700180019001800170017001700 -170017001700170018001800190017001700190018001700190018001700170017001700 -170017001700180017001700170017001700170017001800110011000f000f000f000f00 -10000f000f000f000f000f000f000f000f000f000f000f00100012000f00170017001800 -170017001700170017001700180018001700170017001700170017001700170019001500 -190017001800180018001800170017001700170000001c00170017000600000000001a00 -170017001700000017001700180018001800170017001700180017001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a0011001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a0011001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a0011001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a0012001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a0011001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001900110017001800180018001700170017001b0017001c00 -000017001c001c000600000000001a0017001c0017000000170017001700170018001800 -18001700180017001a001800180018001800170018001700170017001700180017001700 -180017001800190017001800170017001700170019001800180018001800180018001900 -180018001900180019001800180018001800180018001900180018001800180018001800 -180018001800190018001800180018001800180018001900180018001800180018001800 -180019001800180018001800180018001800190018001800190018001800180018001800 -190019001800180019001800190018001800180018001800180019001700180019001700 -180017001700170017001700180018001700170018001700180017001700170017000c00 -1a0017001800190017001900180017001700170017001700180018001800190017001700 -170017001700170018001800180018001800190018001800180018001800180018001900 -180018001800180018001800180018001800180018001800170017001800180017001800 -170017001700180017001700180017001800170017001700170017001700170017001800 -09001a001900170017001700170017001800180017001700180017001800170018001900 -180018001900180019001800180018001800180019001900180018001900180019001800 -180018001800180019001900180018001800190019001800180018001800180018001900 -180018001900180017001800190017001700170017001800170017001800170018001700 -1700170017001700180018001700190019001700190009001a0018001700170017001800 -170017001800170019001900170017001700170017001700180018001900180019001800 -180018001900180018001800180018001900190018001800180018001900180018001800 -180018001800180018001800180018001800180017001800170017001800190017001700 -180017001800170017001700170017001700180017001700180017001800180018001700 -180009001a00180017001700170017001700170017001700190018001900190017001700 -180018001900180018001800180018001800190018001800190018001900180018001800 -180018001800190018001800190018001800180018001900180018001900180019001800 -180018001800180018001900170017001900170017001800190019001700170017001800 -17001700180017001700190017001700180009001a001800170018001700170018001800 -170017001700170017001700180018001700170019001800170018001900190019001800 -190018001800180018001800180019001800180019001800170018001900170017001700 -1700180017001700180017001800170017001700170017001800180019000f0015001800 -1800170018001700170017001700170000001c0017001c000600000000001a0017001c00 -1700000017001800180017001800180017001800170017001a0019001800180018001800 -180017001800180018001800170018001800180017001700180019001700180018001900 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170018001700170017001700170017001700180017001700170017001700 -170017001800170017001700170017001700170017001700170017001800170017001700 -170017001800180018001800180018001800180018001800180018001800180018001800 -18001800180018001800180018000f001a00180017001700170017001800180018001800 -180018001800180017001700180019001700190017001900180017001700170017001700 -170017001800170017001700170017001700170018001800170017001800170017001700 -190019001800170017001700170017001800180018001800180018001800180018001800 -180018001800180018001800170019000f001a0019001700170017001800180018001800 -180018001800180018001800180017001700180017001700180017001700170017001700 -170017001700170017001700180017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170018001800170018001800 -180018001800180018001800180018001800180018001800180018001700170017001700 -19000f001a00180018001800180018001800180018001800170017001800190017001800 -17001b001700170017001700170017001700170018001700170017001700170017001700 -170017001700170017001700170017001700170018001800170017001700170018001800 -180018001800180017001700180018001800180018001800180018001800180018001800 -1800180018001800180017001700170019000f001a001800170018001800180018001800 -180018001700170018001800170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001800170019001800 -170017001700170018001800180018001700180018001800180017001700170019000f00 -1a0017001800180018001800180018001800180018001800180018001800180018001800 -180017001800170017001800170017001700170017001700170017001700170017001700 -170017001700180018001700180018001800180018001800180018001800180018001800 -180018001800180018000c0017001800170017001700170017001b001700170000001700 -17001c000600000000001a00170017001700000017001800170017001800180017001700 -170018001a00180017001700180018001800170017001700170018001700170017001700 -180018001800180017001800170017001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180017001800180018001800 -180018001700180018001800180017001800180017001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180017001800170017001800 -1700170017001700170017001700170017001700170018001700170017000f001a001800 -170017001900170017001800170017001700170017001700190017001700170017001800 -170017001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001700180017001700180018001800180017001700 -170018001700170017001700180018001700170017001700170018001700170010001a00 -190018001700180017001700170017001700170017001700170018001800170017001800 -170018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800170018001700170017001700180017001700170017001700180017001700 -1700170018001800170017001800170017000f001a001700170017001700180017001700 -170017001800170017001700170018001700170018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180017001700140018001800180018001700170017001700 -170018001700170017001700170018001700170017001700180017001900180017001000 -1a0018001700170017001700170017001700170017001700170018001700180019001700 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001700170018001800180017001900170017001700180017001700 -17001700170017001900170017000f001a00180017001700170017001800170017001700 -180017001700170018001700170017001700180019001700170018001700180018001800 -180018001800180018001800180018001800180018001700180017001700170017001800 -17001700170017001700180017001700170017001700170019000c001900190015001700 -1b001700170017001700170000001c00170017000600000000001a001b001c0017000000 -17001700170017001700180017001700170017001a001700170018001700170017001700 -180017001700170018001800170018001400180018001800170017001800170017001700 -1700180017001b0015001700180017001800170018001700170018001700170017001800 -180018001700170017001700170017001700190017001800180018001700180017001700 -170018001700180018001700170017001800170017001700170017001700170018001700 -180017001700170017001800180017001700180017001700180015001900170018001800 -180017001800170017001800170017001700180017001700180017001800170017001800 -170017001800180018000c001a0019001700180017001800170017001700170018001800 -170017001700180017001700170018001700170017001800170018001700180017001900 -170018001800170017001800180017001700190017001800180017001800170017001700 -190018001700170017001700170018001800170017001700180017001700180017001700 -1700180018001700180018000f001a001700180018001800180018001800180017001800 -180018001800170017001700180017001700180018001700170018001700170018001700 -180017001700180017001700180017001700170018001800170017001900170018001700 -180017001700190017001700180017001800180018001800170017001700180017001700 -170018001700170018001800170017001700170018001800180018001800180018000f00 -1a0018001800180017001800170018001800170018001700170017001800170017001800 -180017001800170018001700170018001800170017001700190017001800170018001700 -170017001700170017001700170018001800170017001700170018001800170018001700 -170018001800170017001800170017001700180017001700180017001800170018001800 -17001700170018001800170018000c001a00180018001800180018001800170018001800 -170017001800170017001700180017001800170018001700180017001700180018001700 -170017001900170018001700180017001700170017001700170017001700180018001700 -170017001700180018001700180017001700180018001700170017001800170018001800 -1700170018001700170018001700170017001800170018001800170018000f001a001800 -180017001700180018001700170017001700170018001700170017001800170017001700 -170019001700170018001800190017001800170017001900170017001700190017001700 -180017001900170017001700170017001800170018001800170017001700180017001700 -1800180017000f0017001800180017001800170017001700170017000000170017001c00 -0600000000001a001c001700170000001700170017001800170018001700180018001700 -1a0018001700180017001700170017001800170018001700170017001700170017001800 -180018001700170017001700180018001700170017001c001a0017001700170017001900 -17001900170017001700180019001700150017001b001700170017001700180018001800 -17001700180015001800170018001a0013001700180017001700190013001a0015001900 -170019001800170017001700190017001700170018001700180017001900170017001800 -170019001700190015001900170018001800170015001a00170018001700170017001800 -18001700180017001700180018001700170018001400180018000c001a00180017001800 -170018001700180018001700170017001700180017001800170018001700170018001700 -170017001900170017001800170017001800180017001800180017001700180017001700 -180017001700180017001800190017001500170017001700180018001700170017001800 -180017001700180018001700170018001800170017001700180017000f001a0017001800 -180017001800170017001800140018001700180017001700180017001800170017001800 -170017001900170017001700170019001700170017001700170018001800170017001900 -170017001800190017001700170017001700170017001700180017001700170017001700 -180017001700190017001800170018001700170018001700170017001700180018001700 -17001700170018001800180018000f001a00180018001800170018001800170018001800 -170017001800170018001700170018001700180019001700190015001900170017001900 -180017001900170018001700170018001900170015001700190017001800170018001900 -170019001700170017001700180018001800150018001700170017001700180017001800 -1700180018001700170017001700170017001800180018001800180019000c001a001800 -180018001700170018001700170017001700180017001700180017001800170017001800 -19001700190015001900170017001900180017001800170018001700170018001b001700 -150017001900170018001700180019001700190017001700170017001800180018001500 -180017001800170017001700170017001700180017001700180017001700180018001700 -170017001800170018000f001a0018001400180018001800180018001800170018001800 -170017001800180017001700180017001900130018001700170018001700180019001700 -190017001700180017001800170017001700170017001700170017001800170017001700 -170017001700180017001800170018001700180017000f00170018001700170018001700 -1700180017001700000017001c0017000600000000001a00170017001700000017001700 -170018001800180018001700180017001a00170017001800170017001700180017001700 -180018001700180018001700170018001800180017001700180018001500190017001700 -180017001300000017001700000017001800170017001800170018001700180018001900 -130001001700190017001700170017001800190018001900180017001500170019001700 -170017001700170019001700190017001900170017001800190017001700170018001700 -170019001700170018001800180017001900180017001700180000001800170017001900 -180017001800150017001800170017001700170017001800140018001800170018001800 -1700170018000f001a001800170018001700180018001700180017001700170017001800 -170017001800170018001800170017001700170017001700000017000000170019001700 -1700170017001700170018001900150018001800170017001700170015001a0018001700 -190017001700170018001700170017001800170017001800180017001700180017001700 -17001800180018000f001a00170018001700170017001700180018001700170018001800 -170018001700180017001700170017001700180017000000170017001800170017001800 -180018001700170017001900190000001900170000001700180019001900170018001900 -180013001900170018001100190018001700180019001700170017001800170018001800 -1700170017001700170018001800170017001700170017001800180018000f001a001800 -180017001700170017001800170018001700180017001800170017001700170019001300 -170019001700000000000000010000000000000018000000000001000000000017001700 -190000001700170017001700000017001700000000000000000001000000170018001800 -170018001800170018001700180017001700170017001700180018001800170018001700 -170018001800180018000c001a0018001800170018001700170017001800180017001700 -1800180017001800170017001a0015001500190017000000000000000000000000000000 -180000000000010000000000170017001900000017001700170017000000170017000000 -000000000000010000001700180018001700180017001700180018001800170018001700 -17001800180017001700180017001700170018001800180018000f001a00180018001700 -170017001700180017001700170017001700180017001700170018001700180017001900 -170017001900000000000000170018000000170018001800190015001a00170017001700 -180017001700180017001700170018001800170018001800170017001700170017001800 -17000f0017001800180017001800170017001700170017000000170017001c0006000000 -00001a0017001c001700000018001800180018001700170017001800170018001a001700 -170018001700180017001700180017001700170017001700180017001800180017001700 -18001700170017001900170015001900170017001b000000180015000000170015001900 -180017001700180017001800180019001700000018001500190019001700170017001700 -190015001300190017001800170017001700180018001500180017001500190017001800 -180019001300180017001900170018001800170017001800170017001700170017001900 -170017001800000019001800180017001700180018001900170017001700180018001800 -170017001800170018001800170017001800180018000f001a0018001700180017001800 -170018001700180018001800170017001800170017001700170017001700180019001700 -170000001700180000001700170017001900180018001800170017001700180017001500 -190017001900180017001700150019001900170018001700170018001800170017001800 -1700170017001700180017001700180018001700180018000f001a001700180017001700 -170017001800170018001800180017001700180017001700170018001800170017001700 -180000001700190017001800180017001800170017001700180017001700000017001900 -00001800150017001700170017001700170019001700170017001a001700180015001800 -170017001800170017001700170017001700180018001800170017001700170018001800 -170018001800180018000f001a0018001800170017001700170018001700180017001800 -1700170017001800180017001700190019001700170013001a0017000000190019001700 -170000001800170017001700010017001800000018001700190017000000170019000000 -19001900170015001a001700170019001500170017001700180017001700170018001800 -17001800170017001700170018001700170018001800170018000f001a00180018001800 -180017001700180017001700180017001700170017001700170018001700190019001700 -170015001a00170000001900190017001800000018001700170017000100170019000000 -1800170019001700000017001900000019001900170015001a0017001700190015001700 -170018001700170017001700180017001800170017001700180017001700180017001800 -1800180018000f001a001800180017001700170017001800180018001700180017001800 -170018001700180018001700180017001800170000001700170019000000180018000000 -180017001700170017001900150018001700190017001700170018001700180017001700 -1700170017001800170017001700180017000a0018001700180017001800170017001700 -1700170000001c00170017000600000000001a0017001700170000001700170018001700 -1800180017001700170018001a0018001700180017001800170017001700170017001800 -180018001700180018001800170017001700180018001700170000000000170000001700 -000000000000170000001800190000001700180017001800170018001700170019000100 -180000000000170018001700190000000000000019001700000019001700180017000000 -18001a001700170017001700170018000000170000000000190018001800170000000000 -000018001500190017000000000000001700190018000000170017000000170017001900 -170017001700180017001700170017001800170017001700170018001800180018001700 -18000f001a00180017001900170018001800170017001700170017001700180017001700 -180018001800170017001700170019001700000018001700000017000000000017001700 -170017000000000000001700190000001500190017001700000017001900150017001700 -180017001700180018001700170017001800170017001800170017001700180018001700 -180018000f001a0018001800170017001800170017001700170018001700180017001800 -170017001700180018001700180017001900000017000000000019001700170000001700 -170017000000190000000000010000000000000019001700000000000100170019001700 -000017000000000015001700190017001700170017001700180018001800170017001700 -17001700180017001700180017001700170018001800180018000c001a00180017001800 -180017001700180018001700170018001700170017001800180017001700170017001800 -180017001700180000001700190018001700000017001900170017000000190017000000 -18001800170019000000190017000000170017001800180017001700170017001a001700 -180017001800170018001700180017001700170018001700180018001700170017001800 -1700170018000f001a001800170018001800180017001800180018001700170017001800 -180018001700170017001700170018001800170017001800000017001800190017000000 -170019001700170000001900170000001800180017001900000019001700000017001700 -1800180017001700170017001a0017001700170018001700180018001700170018001700 -170018001800170017001800170018001800180018000c001a0018001700180018001700 -180018001800170018001800170017001700180017001700170017001700180017001900 -000018001800170000001700170000001700170017001900170017001800180018001500 -180017001700180017001700170018001800170017001700180018001700180018000f00 -18001700180017001800180017001700170017000000170017001c000600000000001a00 -1c001c001700000017001700170017001700180018001800170017001a00180017001800 -170018001700180018001800170017001700170017001700170018001700170017001700 -170017000000180017000000000017001700010017001700000019000000180019001700 -1800170017001800170017001700000000001a0017000000180017000000190017001700 -000017001900000017001700000019001700170017001700170018001700170000000000 -170017000000170017000100170015001900000019001700010017001700170000001900 -170000001700010017001800170017001700190017001700180018001800170018001700 -1800180017001700180018001400170018000f001a001800170018001700180017001700 -180018001700180017001700180017001700170017001700180018001700170000001500 -180017000000010019001700000018001800000017001800170000001700180000001700 -180000001700190018001900170017001900170017001700170018001800170017001800 -18001700170018001800170017001700180018000f001a00180018001700170018001700 -170018001700170018001700170018001700180017001700170017001700170018000000 -010017001800000018001700000017001700180000001700170000001700180000001700 -180000001800170018000000190017000000000019001700000017001700180017001800 -180017001700170017001700180018001700180017001700170017001800170017001700 -1800170018000f001a001800170017001800180017001700180018001700180017001800 -170017001700170019001700170018001700180017001800000015001800170017000000 -170017001700170001001300190000001700170019001700000017001700000017001900 -170017001900180018001500180017001800170017001700180017001700170018001800 -170017001700170017001800170017001800170018000f001a0018001700180017001700 -170018001700180018001800170017001700170017001800190018001700180017001800 -170018000000170018001700170000001700170017001700010013001900000017001700 -190017000000170017000000170019001700170019001800180015001800170018001800 -170017001700170017001800170017001800170017001700180017001700180018001700 -19000c001a00180018001700170018001400170018001800170017001700180018001700 -170018001800180017001700170017000000170017001900000019001700170000001700 -190000001900180017001700180019001700180017001800170018001700180017001700 -18001800170017001700180018000f001800180018001700180017001700170017001700 -00001700170017000600000000001a001c00170017000000170017001700180017001800 -17001700180017001a001800180018001700170017001700170018001700180017001800 -180017001700180018001800180017001700180000001800190017000000170017000000 -190017000000000017001700170017001800170018001800170017001800000019001700 -1800000017001a0000001700190019000000170018001700000000001700180017001800 -170018001900150017001a00000017001900190000001700170017001900190017000100 -130019000000170017001900190017001700000000001700170017001900170019001500 -180017001700170017001700170018001800170018001700170018001700180018000f00 -1a0018001700180018001800180017001700170018001700180017001800170017001700 -170018001700170019001800000019001700170000001700170017000100170017000100 -170017001900000018001900170000000000150017001800170017001800170017001900 -180017001700170018001700170018001800170017001800170017001700180018001800 -0f001a001700180018001800170018001700180018001800170017001700170018001700 -180017001700180017001900170000001700190013000000170018000000190017001700 -000019001700000018001700000019001700000018001700170000001900170000001700 -1700170000001a0017001700180017001800170017001700170018001700170017001700 -180018001800180017001700170018001800180018000c001a0018001700170017001800 -180018001700180017001700180017001800170017001800170017001700170017001800 -180017000000190017001700190000000000000000000000170018001700000018001800 -170018000000170019000000000000000000000000001700180019001700180017001700 -180018001700170018001800170017001700180018001700180017001700180018001800 -18000f001a00180018001800180017001800140018001800170017001800170017001700 -170018001500170017001700170017001900170000001900170017001900000000000000 -000000001700180017000000180018001700180000001700190000000000000000000000 -000017001800190017001800170017001700180018001700180017001700180018001700 -1700180018001700170018001800180018000f001a001800180017001700170017001800 -180017001800170018001700180017001700170017001800190017001900180000001800 -170018000000190017001900000018001700170018001700190018001900150018001800 -1700170018001800170017001700180017001700180017001700180017000f0017001800 -180017001800170017001700170017000000170017001c000600000000001a0017001700 -1700000017001700170017001700180017001800170018001a0018001800180017001700 -170017001700170017001800170017001800170018001800170018001800170017001800 -000017001700170000001b00170000001700190000000000190017001700180017001700 -190017001700180017000000170017001800000017001700000018001700170000001800 -170017000000000019001500170018001700170017001800170017000000170017001800 -000018001800170000000000000000001900170000001800170017001700170018000000 -000017001700170018001700170018001800170018001700180018001700170018001700 -18001700170017001800170018000f001a00180017001800170018001700180018001700 -170017001800170017001700180018001700170018001700170018000000170017001800 -000017001700170000001700170000001700180018000000170017001900000000001800 -180017001800180017001800180017001700180018001700170018001700170017001700 -180017001700180018001700180017000f001a0017001800180018001700180018001800 -180014001700180018001700170017001800170017001800170017001800000017001700 -190000001700190000001700180019000000170019000000170017000000170019000000 -170019001700000017001700000017001800180000001700170019001700180017001700 -180018001700170018001700180017001700170017001700170018001700180018001700 -18000f001a00180018001800180018001800140017001800180017001700170018001700 -170018001700190017001700180015001900170000001700180018001700000018001700 -170000001700180018000000170017001800170000001900170000001900170017001700 -190017001700180017001700170018001700170017001800170017001700180017001800 -1700170018001700170018001800180018000f001a001800180017001700170018001700 -180018001700180017001700180018001700170017001900170017001700170019001700 -000017001800180017000000180017001700000017001800180000001700170018001700 -000019001700000019001700170017001900170017001800170017001700180017001800 -170017001800170018001700170017001800170017001700170018001800170018000c00 -1a0014001800180018001700170018001700180017001700180017001700170017001700 -170018001700170017001700000018001800170000001700170017000000170018001800 -170017001900170018001700170017001700180017001700170018001700170018001700 -170017001700180017000f00180017001700170018001700170017001700170000001700 -1c0017000600000000001a00170017001700000017001700170017001700180018001700 -180017001a00170017001800170017001700180018001700170017001800180017001800 -180017001800180017001700170017000000170017001b0000001b001700000017001700 -000017000000170017001700180017001700170018001800170000001700180019000000 -180018000000190018001700000018001700000017001700000017001700180017001700 -170017001700180000001700180017000000180017000000170018001700000017001800 -000017001800180017001700170000001700000018001700170018001800170017001800 -1700180017001700180017001800180018001700180018001800170018000f001a001800 -180018001700180018001700180017001800170017001700180018001700170017001800 -170017001700170000001900170018000000170017001700000018001800000017001700 -190000001900170000001700170000001800170018001800170018001800170017001700 -180017001700170018001700170017001800170017001800170017001800180010001a00 -140018001700180018001800140018001700170018001700170018001700170017001800 -170017001800170017000000170017001900000017001900000017001900170001001700 -170000001700180000001700190000001700170019000000170018000000170017001700 -000017001800170018001700170017001800180017001700180017001700180018001800 -1800170017001700170018001800180018000f001a001800170018001800170018001700 -170018001700180017001700170018001700170018001800170018001700180018001700 -000018001700170018000000150019001700180000001300190000001700170017001800 -000017001700000019001700170017001800190015001900170017001700170017001800 -170018001800170018001700180017001800180017001700180018001800180018000c00 -1a0018001700180017001700170018001700170017001700180017001700170018001800 -170017001700180018001700170017000000180017001700180000001500190017001800 -000013001900000017001700170018000000170017000000190017001800170018001900 -170019001700170018001800170017001800170017001700180017001700180018001700 -17001800170018001800180018000f001a00180017001800180018001800180017001700 -180017001800170018001800170017001700180017001800170017000000170018001700 -000018001700170000001800190013001800190017001700190017001800170017001700 -17001700170018001800170017001800170017001700180018000f001700170018001700 -1800170017001700170017000000170017001c000600000000001a001b001c0017000000 -17001700170017001800180017001800170018001a001700170018001700180017001700 -180017001800170017001700170017001800170018001700170017001800170000001700 -180000000000170017000000170019000000170019000000170018001700190019001700 -17001700170000000000170017000000170017000000170017001a000000170000001800 -170019001700000017001800170017001900170017001700000000001700190000001700 -180000001700180017000000180017000000170018001700000017001800000018001700 -010017001800180013001900170017001700180018001700180017001400170018001800 -180017001700180018000f001a0018001700180017001800170018001700180017001700 -180017001700170017001800170018001700180019001800000018001700180000000000 -180018000000170017000000180019001800000018000000190019001700180000001800 -190017001700180011001900180017001700180018001700170018001800170017001800 -1800170017001800180018000f001a001700180017001700170017001800170017001800 -180018001700180017001800170017001800170017001700170000000000170017000000 -170019000000170017000000000017001700000017001700000018001800000017001900 -170001001900170000001800180017000000190017001900170017001800170017001700 -170018001700170018001800170017001700170018001800170017001800180018000f00 -1a0018001700170018001800170017001700180017001800170018001700170018001700 -170017001800180017001700170017000000170017001700190000001700170018001700 -000019001700000019001800170018000000190019000000180018001700180017001700 -180017001700180018001800170017001700170017001700180017001700170017001700 -17001800180018001800180019000c001a00180018001800170017001800180017001700 -180017001800170018001700170017001700180017001700170017001800170000001700 -170017001900000017001700180017000000190017000000190018001700180000001900 -190000001800180017001800170017001700170017001800170017001700180017001800 -1800170017001800170017001700170018001700170017001800140018000c001a001800 -180018001700140018001800170018001800170017001700170017001700180017001800 -170017001800180000001900170017000000170017001a00000015001700190017001700 -180017001700180017001700180018001800180017001700180017001700180017001800 -1700180017000f00170018001800170018001700170017001700170000001c0017001700 -0600000000001a0017001c00170000001700180018001800180017001800170018001700 -1a0018001700180017001700170017001700170018001800170018001800170018001800 -170017001800180017001700170000000000170000001700190000000000170000001700 -170017000000170017001700170017001700170017000000170000000000170019001700 -1a0000000000000019001800000018001700170018000000180017001800170017001700 -180019000000170000000000180018001700170000000000000018000000190017000000 -0000000017001700190000001800170017000000170017001a0015001800180017001700 -17001700170018001800180017001800180017001700180018000f001a00180017001800 -170018001800170018001700170018001700180017001700170018001700170018001700 -150019000000180019001500000019000000000018001700170018000000000000001900 -170000001700150019001700000017001700000017001700190017001800170017001800 -180017001700180018001700170018001800170017001800180017000c001a0017001800 -170018001700180018001800180017001700180017001700180017001800180017001700 -170019001900000017000100000018001700170017000000000017000000190017000000 -010017000100000017001900000000000000150017001800000018001700190000001700 -170017000100170018001700170017001700170018001800170018001700180017001800 -17001700170018001800170018000f001a00180018001700170018001700170018001800 -170017001800170018001800170017001800180018001700180017001700180000001800 -170019001500000018001700170017000000170019001700000000000000000017001500 -180000000000000000000000000019001900170001001800170017001800170018001700 -1700180017001700180018001800170018001700170014001800180018000f001a001800 -180017001800180018001700180017001700180017001700180017001700170018001700 -180017001700180017001800000018001700190015000000180017001700170000001700 -190017000000000000000000170015001800000000000000000000000000180018001700 -010018001800170018001700170017001800170017001800180017001700180018001700 -170018001800170018000f001a0018001800170017001700170017001800170017001700 -180018001800170018001700170019001800170018001700170000000100000017001800 -170017000000180018000000170017001800170018001700170018001700170017001700 -180017001700170017001700170018001700180017000f00180017001800170018001700 -17001700170017000000170017001c000600000000001a00170017001700000017001700 -180018001700170017001800170018001a00180017001800170018001700180018001700 -170017001700170018001700170018001800180017001700170018001700170017001700 -000017001500180019001700190018001700180017001700170015001a00170017001900 -170017001800170018001700130019001700170015001900170019001700180019001800 -170018001800170018001700170019001500170000001700180018001700180017001a00 -170017001900170019001500190017001700190017001700170019001700170018001700 -190015001700170017001700180017001800180017001700170018001800180017001800 -1700170018000f001a001800180018001700180017001800170018001700180017001700 -180018001700170018001700170017001900170018000100170019001900150017001900 -170017001700170019001700170017001800170018001900170017001700180018000000 -170017001900170017001800170017001700180017001700170018001700170017001700 -18001700180018000c001a00170018001800170017001700170018001800170017001700 -180017001700170017001700170018001900130017001700180017001900180018001700 -1700170017001700190015001b001700150017001700190015001800190011001a001800 -170019001800170018001500190017001700180000001700170017001800180018001700 -1700170017001800170018001700170018001700170018001800170018000f001a001800 -170018001800140017001800180017001800170017001700170017001700180017001700 -180017001800170017001800170017001700180019001800170017001900170017001700 -180018001900170017001700180018001700190018001900170019001700170017001900 -000018001700180017001700180017001700180017001800170017001700170018001700 -170018001800170018000c001a0018001600180018001600180018001700180017001700 -170018001700170018001800170017001800170017001800170017001700170017001800 -190018001700170019001700170017001800180019001700170017001800180017001900 -180019001700190017001700170019000000180017001700180017001800170017001800 -17001700170018001800170017001700180018001800180018000f001a00180018001700 -170018001800180018001700170018001700170017001700180017001800150019001700 -170017001700180017001700170017001900000019001700190000001800180017001700 -180017001700170018001700170018001700170017001800180017001700170017001800 -18000f0017001800180017001800170017001700170017000000170017001c0006000000 -00001a001b001c001700000017001700180017001800180017001700180017001a001800 -180018001700170017001700170017001700180018001800170018001700170017001700 -170018001700170000001700170018000000170019001700170019001500170018001900 -180000000000000000000100000000001700190017001800190018001900170017001700 -180019001700170019001500180017001900170000000000000000000000000000001a00 -000017001700190017001800170015001500180017001700190019001700170017001900 -180018001900180018001900170018001300190017001a00170017001700180017001700 -180017001800170017001700180017001700170018000f001a0018001700180018001800 -180017001800170017001800180017001700170017001800170017001700180017001700 -190000001700190015001a00180017001700180018001700170018001800170019001500 -190015001700190018001700000017001900180017001800170018001800170017001800 -1800170017001800180017001700180018001700180018000c001a001700180017001800 -180018001800170017001700180014001700170018001800180017001700170017001900 -180019001700170019001300180017001700170019001800170018001500180018001a00 -150017001a00150017001800170017001500180018001800170018001800170019000000 -190019001800170017001700170017001800180018001700180017001800170018001700 -170017001800170019000c001a0018001800170017001800170018001700180017001700 -180018001800170017001700180018001700170018001700170017001700180017001900 -170017001700180015001a00170018001700130019001900170017001900170017001500 -170017001700170019001700170000001900190017001700180017001800170017001700 -17001700170018001800180017001700170018001800180019000c001a00180017001800 -170018001800180017001700180017001700170018001700170017001700180018001700 -17001800180017001700180017001900170017001700180015001a001700180017001300 -190019001700170019001700170015001700170017001700190017001700000019001900 -180017001700170018001700170017001800170017001700180017001700180017001800 -1800170018000f001a001700180018001700170017001700180018001700180018001700 -180018001700170018001900170019001900180019001500180018001800180017000000 -170018000000190017001700180017001700170018001800170017001700170018001800 -1800170017001700180018001700180018000f0018001700170017001700170017001700 -1700170000001700170017000600000000001a001c001700170000001700170017001700 -1700170018001700170017001a0018001800180017001800170017001800180017001700 -170017001700170017001800170017001800170018001700170000000000000015001700 -180017001800170017001800180017001800170019001800180017001800170017001800 -170017001800150017001700190017001700170018001700170017001700180017001800 -17001800170017001900190017001800000019001700170019001500170019001a001300 -190017001500180017001900190017001700130019001500170017001700170018001700 -170015001800180017001700180017001800170018001700170017001700170017001700 -17000f001a00180017001800170018001700180017001700170017001700170017001800 -170018001700180017001800170019001800170001001800170017001700180017001700 -170018001800170017001700170019001700190019001500130019001800180018001700 -180017001700170017001800170017001700180017001700170018001700170017001700 -180017000f001a0017001800170017001800170017001800180018001800180018001700 -170017001700170018001700170018001700180017001900170018001700170017001900 -130019001700170019001800150017001700170015001800170019001700170019001700 -170017001700170017001700170019001800170017001700180017001800180017001700 -18001700180017001700180017001800170018001800170019000c001a00180017001700 -180017001700180017001800180017001700170017001700180018001700170017001800 -170018001800170019001700190017001700180017001700190015001800180017001900 -170017001800170017001700190017001900180017001800130018001900170018001300 -180017001800170017001700180017001800180017001700170017001700180017001800 -1800170018000f001a001800180017001700180017001800180018001800170018001700 -180017001800170017001700170017001700170017001700190017001900170017001800 -170017001900150018001800170019001700170018001700170017001900170019001800 -170018001300180019001700180015001800170018001700170018001800170017001800 -180017001700180017001700170017001800170018000f001a0017001700180018001800 -170018001700180018001700170017001700170017001800170014001700150019001500 -190017001800170017001800000019001900170019001700170019001700190017001800 -170017001700180018001700170017001700170018001800170017001700180018000f00 -17001800170017001800170017001b001700170000001c0017001c000600000000001a00 -170017001700000017001700170017001700180017001700180018001a00170017001800 -170017001700170017001800170017001700170018001700180018001800170017001800 -170017001800170017001700190018001700170015001900170017001300190017001800 -170017001700170017001900180017001900130019001900170017001800170019001700 -180017001900170017001700190017001900130018001700170017001800170019001800 -170019001700170018001700170017001700170018001800180017001300170019001900 -170018001800170019001700170018001a00170017001700170017001700170017001800 -1800180017001800170018001800180018000f001a001800170018001700180018001800 -170018001800170017001800170018001700170017001800170017001800170011001900 -170017001700170017001700170017001700170017001700180019001700180017001700 -180019001900170015001700180017001500190018001700170017001800170017001700 -18001700170017001800170017001700180018000f001a00170018001700170018001800 -170018001700170018001800170017001800170017001800170017001700170018001700 -170018001400180017001800180013001900170017001800180017001800170018001a00 -170018001700170017001700180017001800170018001500180019001800170018001700 -170018001700170017001700170018001800170017001700180017001800180017001800 -1800180018000c001a001800180018001800170017001800180014001700170018001700 -170018001700180018001700170018001800170018001800170018001500180019001500 -190017001800170018001800170017001900170017001700170017001500190017001700 -170017001900170014001900170019001700170017001700170018001700170017001700 -170017001700170018001700170018001800180018000f001a0018001700180017001700 -180017001800180017001700180017001700170018001700180017001700180018001700 -170018001700180015001800190015001900170018001700180018001700170019001700 -170017001700170015001900170017001700170019001700150019001400190017001700 -180017001700170018001700170017001800170017001700180017001700180018001800 -18000f001a00180017001800180018001700170018001800170017001700170018001700 -18001700170019001900190013001a001700170017001900180017001700190015001900 -150019001700170017001300190018001800170017001800170017001800170017001800 -17001700170017001700180017000f00170018001800170017001700170017001c001700 -00001700170017000600000000001a0017001c0017000000170017001700180018001700 -17001800170017001a001800170018001700180017001700180017001800170018001700 -180018001800180018001700180017001700170017001700190017001700170017001800 -180017001700170019001700180017001700190017001800180017001800180017001700 -170017001700170017001800180017001800190015001800190017001700190017001900 -180017001900170018001800170017001700180014001800170017001800180017001800 -180017001800170019001700180017001800170017001700170017001900170015001900 -180018001800170018001700180018001700180018001800170018001800180018001000 -1a0018001700180017001800170017001700180018001700180017001800170018001700 -180017001800170017001800180017001700170019001700180018001800170017001800 -180017001700180018001700180017001800170017001700190017001800190017001400 -180017001800170018001700180017001800170018001700180017001800180018001800 -10001a001700180017001700140018001800180017001700180017001800170018001700 -180017001800170017001800170017001800170017001700170017001700190017001700 -190017001700190018001700180017001700170018001700180017001800170018001700 -170019001700170017001700180018001800170018001700180018001800170018001700 -180018001800170018001800140018001800170018000c001a0018001800170017001800 -170017001800180018001700180017001800170018001700180018001800170018001700 -180018001700190017001900170018001700180017001800170017001800170017001800 -170017001700190017001800170018001800170017001700180017001700180018001700 -180018001800170018001700180018001800170018001700180018001700180018001800 -19000c001a00170018001700180017001800170018001800180017001800170018001700 -180017001800170018001700180017001800170017001900170019001700180017001800 -170018001700170018001700170018001700170017001900180018001700180018001700 -170017001900170017001800180017001800170018001700180017001800170018001700 -1800170018001800170018001800180018000f001a001800180018001700170017001700 -180018001800180018001700180017001800170017001800170017001900130018001800 -170018001700170017001800180017001800170019001700170019001700170018001700 -1800170018001700180017001800170018001700180017001800180017000f0018001700 -170017001b001700170017001700170000001c0017001c000600000000001a0017001700 -1700000017001800180017001800170017001800170018001a0019001800180018001800 -180018001800170018001800160017001700170018001700180018001800170018001800 -180018001800170018001700180018001700180017001400170018001800170018001800 -170017001800180018001700170018001700170018001700180018001800180018001800 -180018001600170018001700180018001800170018001700180018001800180018001700 -180018001700180017001400170018001800170018001800170017001800180018001700 -170017001800170018001700170018001800170018001700180018001800180018001700 -180018001800170018001800180010001a00170015001900170018001800180017001700 -170018001700180018001800180017001700180018001800170017001800170018001700 -170018001800180018001700180018001600170018001700180018001800170018001700 -180018001800180018001700180018001700180017001400170018001800170018001800 -170017001700180018001800170019000f001a0017001700170018001800180018001800 -180018001800170018001700180018001800170018001700180018001800180018001700 -180018001700180017001400170018001800170018001800170017001800180018001700 -170017001800170017001800170017001800170017001800180018001800170017001700 -1800140018001800170017001800170017001800180018001800170015001a0018001400 -190012001a00170018001700170018001800180018001700170017001800140018001800 -170017001800170017001800180018001800170018001700170017001700180017001700 -180017001700180018001800180017001700170018001400180018001700170018001700 -170018001800180018001700180018001800170018001800170017001800170017001800 -18001800180017001400190017001400190010001a001700180017001700180018001800 -180017001700180017001400170018001800170018001800170017001800180018001700 -180018001700170018001700180018001800180017001700170018001800170018001700 -180018001800170018001700180018001800180018001700180018001700180017001400 -170018001800170018001800170017001700180018001800150019001800170019001000 -1a0017001800180018001800180018001800180018001700180018001800170018001700 -180018001800180018001700180018001700180017001400170018001800170018001800 -170017001800180018001700180018001700170018001700180018001800170018001700 -180018001700170017000f00180017001700170019001800170017001700170000001700 -1c0017000600000000001a001c001c001700000017001800180018001700170018001700 -1800170012000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f001000090011000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00100009001200 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f0010000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000c0010000c000f001000090012000f000f000f000f000f000f000f00 -0f000f0010000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f0010000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f0010000f000f000f000900 -12000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f0010000f000f000f00090012000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f0012000f001800190018001500 -180018001700170017001700000017001b001c000600000000001a001c00170017000000 -170018001700180017001800170018001700180017001700170017001800170017001700 -180017001700170017001800180018001700170017001700180017001700170016001800 -180018001700170018001700180018001700180018001700160017001800180017001700 -180017001700180018001700180017001700170018001700180017001700170017001800 -170017001700170017001700180017001700170016001800180018001700170018001700 -180018001700180018001700160017001800180017001700180017001700180017001700 -180017001700180017001700180018001700170018001700180016001700170017001700 -180017001700170018001800170018001700140018001700180018001800140018001700 -160017001800180017001700180017001800170017001700180017001700170017001700 -180018001700170018001700170017001700170017001700180017001700170016001800 -180018001700170018001700180018001700180018001700160017001800180017001700 -180017001700180017001900180017001700170018001700180017001700170014001800 -180017001700170017001700180017001700170016001800180018001700170018001700 -180018001700180018001700160017001800180017001700180017001700180018001700 -170018001800170018001800170017001700170018001700170017001800180017001800 -180017001800170017001700170017001800170017001700180018001800180017001900 -170017001700170017001700180017001700170018001800170018001800170018001700 -170017001700170018001700170017001800170018001700170017001800180017001700 -170017001800170017001700180018001700180018001700180017001700170017001700 -180017001700170018001700170018001700170018001700170017001700170018001700 -170017001800180017001800170019001700170017001700170017001800170017001700 -180018001700180018001700160017001800180017001700180017001700180017001700 -180018001700170017001700180018001700140018001800180018001700170017001700 -180017001700170016001800180018001700170018001700180018001700180018001700 -160017001800180017001700180017001700180017001700170018001700190017001800 -180017001700170017001700180017001700170017001700180017001700170016001800 -180018001700170018001700180018001700180018001700160017001800180017001700 -180017001700180017001700180018001700170017001700180018001800160017001700 -1800170014001500180018001800170018001800170017001700170000001c001b001c00 -0600000000001a0017001700170000001700170017001800170017001700170018001700 -180018001800180018001800180018001800180018001800180018001800180018001800 -180017001800170018001700180018001800180017001800180017001800180018001800 -180018001800180018001800180017001800180018001800180017001800180017001800 -180018001800180018001800180018001800180018001800180017001800170018001700 -170018001800180017001800180017001800180018001800180018001800180018001800 -180017001800180018001800180018001800180018001800170018001800180018001800 -180017001700170018001800180017001800170018001700170019001400180018001800 -180018001700180018001800180018001800180017001800180017001800180018001800 -180017001800180018001800170018001800180018001800180018001800180018001800 -180017001800170018001700170018001800180017001800180017001800180018001800 -180018001800180018001800180017001800180018001800170017001900170017001700 -170017001800180018001800170018001800180018001800180017001800170018001700 -170018001800180017001800180017001800180018001800180018001800180018001800 -180017001800180018001800180017001800180018001800170018001700180018001800 -180018001800170018001800180018001800170018001800170018001800180018001800 -180017001800180017001800170019001500180017001800180018001800180018001700 -180018001800180018001700180018001700180018001800180018001800170018001800 -180018001800180018001800170018001800180018001800180017001800180018001800 -180017001800180017001800180018001800180018001700180017001800180018001800 -170018001700180018001800180018001800170018001800170018001700190015001800 -170018001800180018001800180017001800180018001800180018001800180018001800 -180017001800180018001800180018001800180017001800170018001800180018001800 -180018001800180018001800180017001800170018001700170018001800180017001800 -180017001800180018001800180018001800180018001800180017001800180018001800 -180017001700180017001900140018001800180017001800170018001700180018001800 -180017001800170018001700170018001800180017001800180017001800180018001800 -180018001800180018001800180017001800180018001800180018001800180017001800 -170018001800180018001800180017001800180019001900180017001800180018001800 -170017001700170000001c0017001c000600000000001a00170017001700000017001700 -180018001800170017001800170018001700180017001700170017001700170018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001700180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001700180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180017001800180018001800180018001800180018001800180018001800180018001800 -180018001700180014001800170019001700180018001800180018001800180018001800 -180018001800170018001800180018001800180018001800170018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001700180018001800180018001800180018001800180018001800180018001800 -180018001800170018001800170018001700180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001700180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800170018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180017001800170018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001700180017001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001700180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001700180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -15001900170017001700170017001800170017001700170000001c001c00170006000000 -00001a0017001c0017000000170017001800170017001700180017001800170017001700 -170017001700170018001800160018001800180018001600180017001800180018001800 -180017001700180017001800180017001800180017001600180017001800170018001800 -180018001700170017001700170018001700180017001800180018001700180017001800 -180018001700180018001800170016001800180018001800180017001700180018001800 -180017001800180017001600180017001800170018001800180018001700170017001700 -170018001700180017001800170018001800180018001800170017001800160018001800 -180018001800180018001800180017001700180017001800180018001700190015001800 -170018001800180018001800180018001700180017001700170018001700180017001800 -180017001800180018001800180017001700180018001800170016001800180018001800 -180017001700180018001800180017001800180017001600180017001800170018001800 -180018001700170017001700170018001700180018001700170018001700190017001800 -160018001800180017001800180018001800180018001800180017001700180018001800 -180017001800180017001600180017001800170018001800180018001700170017001700 -170018001700180017001700180018001800180018001700180018001800180017001800 -180018001800170017001800180018001600180018001800180018001700180018001800 -170018001700170018001400180018001800180018001800170018001800180018001700 -170018001800180016001800180018001800180017001800180018001800180018001700 -180018001700180018001800180018001700180018001800180017001700180018001800 -160018001800180018001800170018001800180017001700170018001800180018001800 -180018001800180017001800180018001700180017001800180014001800180018001800 -180018001700180018001800180017001800170018001800180018001700170017001700 -170018001700180017001700180018001800180018001800160018001800180018001600 -180017001800180018001800180017001700180018001800180017001800180017001600 -180017001800170018001800180018001700170017001700170018001700180017001800 -180018001700140018001800180016001800180018001800180018001800180018001800 -180017001700180018001800180017001800180017001600180017001800170018001800 -180018001700170017001700170018001700180017001700170018001700180018001800 -180017001700180018001800180014001800190018001700180018001700180017001700 -1700170000001700170017000600000000001a0017001c00170000001700180018001800 -170017001700180017001700170017001700170017001800180018001700170018001800 -180018001700170018001800180018001700180018001800180018001700180017001800 -180018001800180017001800180018001800180018001800170018001800180018001800 -180018001700180018001800170018001700180018001800180018001800170018001800 -180018001700180018001800180018001700180017001800180018001800180017001800 -180018001800180018001800170018001800180018001800180018001700180017001800 -180018001700180018001800180018001700180018001800180018001700180018001800 -170017001800180017001800150017001800180017001800180018001800180018001800 -180017001800180018001800180018001800180017001800180018001800170018001800 -180018001700180018001800180018001700180018001800180018001700180017001800 -180018001800180017001800180018001800180018001800170018001800180018001800 -170018001400180017001800170017001700170018001800180018001800170018001800 -180018001700180018001800180018001700180017001800180018001800180017001800 -180018001800180018001800170018001800180018001800180017001800180018001800 -170018001800180018001800170017001800180017001800180018001800180017001800 -180018001800180017001700170017001700180017001700170017001800180018001800 -180018001700170018001800170018001800180018001800170018001800180018001800 -170017001700170017001800180018001800180018001700180018001800180017001700 -180018001700180018001800180018001700180018001800180018001700170017001700 -170017001800180018001800180017001800180018001800170017001800180017001800 -170017001700170018001800180018001800180017001700180018001800180017001800 -180018001800180018001800170018001800180018001800180018001700180017001800 -180018001700170018001800180018001700170018001800180018001700180018001800 -180018001700180017001800180018001800180017001800180018001800180018001800 -170018001800180018001800170018001700180017001700180017001700180018001800 -180018001700180018001800180018001700180018001800180018001700180017001800 -180018001800180017001800180018001800180018001800170018001800180018001800 -180018001800180018001800180018001800170018001800180018001800180019001500 -19001500190018001800180017001700170017000000170017001c000600000000001a00 -170017001700000018001700170017001800180018001700180018000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -100010000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f0010000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f00100010000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f0010000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f00100010000f000f000f000f000f000f0010000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f0010000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -100010000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f0010000c0010000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f00100010000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f0010000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f001000 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f00100010000f000f00 -0f000f000f0010000f000f000f000f000f000f000f000f000f0010000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f00100010000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f0010000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f00100010000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f0010000f000f000f000f000c0010000f000f000f000f000f000f00 -0f000f000f0010000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f0010000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f00100010000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f0010000f000f000c001000 -0c0010000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -100010000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f0010000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000c001900170018001700150018001700180017001700 -00001c001c001c000600000000001a001b001c0017000000170017001800170018001800 -17001700170017001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a0019001700 -1700170018001700170017001700170000001c0017001c000600000000001a001c001700 -170000001700170018001700180017001700170018001700180018001800170018001700 -1b00170018001800170017001800180018001b0017001700180018001800190017001700 -1800180018001700180017001b00170017001800170017001800180018001b0017001700 -18001800180019001700170018001800180017001b001800180017001700170017001800 -180018001800180017001700180018001800190017001700180018001800170018001700 -1b00170017001800170017001800180018001b0017001700180018001800190017001700 -1800180018001700180017001b00170017001800170017001800180018001b0017001700 -180018001800190017001700180018001800170018001800180017001700170017001700 -180018001800180017001700180018001800190017001700180018001800170018001700 -1b00170018001800170017001800180018001b0017001700180018001800190017001700 -1800180018001700180017001b00170017001800170017001800180018001b0017001700 -1800180018001900170017001800180018001700180017001b0017001800180017001700 -1800180018001b0017001700180018001800190017001700180018001800170018001700 -1b00170017001800170017001800180018001b0017001700180018001800190017001700 -180018001800180017001700180018001800180018001900170017001800180017001800 -18001800170017001b0018001800180018001b0017001700180018001800170018001800 -170017001800180018001800180019001700170018001800170018001800180017001700 -1b0018001800180018001b00170017001800180017001700180018001700170018001800 -1b0018001800180017001700180018001700180018001800170017001b00180018001800 -18001b001700170018001800180018001800180017001700180018001b00180018001800 -170017001800180018001800180018001800170018001800180018001800190017001700 -1800180017001800170017001800180018001b0017001700180018001800190017001700 -1800180018001700180017001b00170018001800170017001800180018001b0017001700 -1800180018001900170017001800180018001700180017001b0017001700180017001700 -1800180018001b0017001700180018001800190017001700180018001800170018001700 -1b00170017001700170017001800180018001b0017001700180018001800190017001700 -1800180018001700180017001b00170017001800170017001800180018001b0017001700 -1800180018001900170017001800180018001700180017001b0017001700180017001700 -1800180018001b001900180017001700170018001800170017001b001700170000001700 -1c0017000600000000001a00170017001700000017001700180018001700170018001800 -170017001800170017001700180017001700170017001700170017001700170017001700 -170017001700170017001700170017001800170017001700180017001700170017001700 -170017001700170017001700170017001700170017001700170017001800170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001800170017001700180017001700170017001700170017001700170017001700 -170017001700170017001700170017001800170017001700180017001700170017001700 -170017001700170017001700170017001700170017001700170017001800170017001700 -180018001700170017001700170017001700170017001700170017001700170017001700 -170017001800170017001700180017001700170017001700170017001700170017001700 -170017001700170017001700170017001800170017001700180017001700170017001700 -170017001700170017001700170017001700170017001700170017001800170017001700 -180017001700170017001700170017001700170017001700170017001700170017001700 -170017001800170017001700180017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170018001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700180017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001800170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001800170017001700180017001700170017001700 -170017001700170017001700170017001700170017001700170017001800170017001700 -180017001700170017001700170017001700170017001700170017001700170017001700 -170017001800170017001700180017001700170017001700170017001700170017001700 -170017001700170017001700170017001800170017001700180017001700170017001700 -170017001700170017001700170017001700170017001700170017001800170017001700 -180017001700170017001700170017001700170017001700150017001700170018001800 -17001700170017001700170000001b001c001c000600000000001a0017001c0017000000 -180018001700170017001700170017001700180018001800180018001800180017001700 -180018001800180018001800180018001700170017001700180018001800180018001800 -180018001800180017001700180018001800180018001800180018001700170017001700 -18001800180018001800180018001800180017001b001700180018001800180018001800 -180018001700170017001700180018001800180018001800180018001800180017001700 -180018001800180018001800180018001700170017001700180018001800180018001800 -180018001800180017001700180018001800180018001800180018001700170017001700 -18001800180018001800180018001800180018001b001700180018001800180018001800 -1800180017001b0017001700180018001800180018001800180018001800180017001700 -180018001800170018001800180018001700170017001700180018001800180018001800 -180018001800180017001700180018001800180018001800180018001700170017001700 -180018001800180018001800180018001800180017001700180018001800180018001800 -180018001700170017001700180018001800180018001800180018001800180017001700 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800170017001800180018001800 -180018001800170018001800180018001800180018001700180018001800180018001800 -180018001800180018001800180018001700170018001800180018001800180018001700 -180018001800180018001800180017001800180018001800180018001800180018001800 -180018001800180018001700180018001800180018001800180017001800180018001800 -180018001800170018001800180018001800180018001800180018001800180018001800 -180017001800180018001800180018001800180018001800180018001800180017001700 -180018001800180018001800180018001700170017001700180018001800180018001800 -180018001800180017001700180018001800180018001800180018001700170017001700 -180018001800180018001800180018001800180017001700180018001800180018001800 -180018001700170017001700180018001800180018001800180018001800180017001700 -180018001800180018001800180018001700170017001700180018001800180018001800 -180018001800180017001700180018001800180018001800180018001700170017001700 -180018001800180018001800180018001800180017001700180018001800180018001800 -1800180018001800180018001700170018001800170017001700170000001c0017001700 -0600000000001a0017001700170000001700170018001700180017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001b00 -17001b0017001c00000017001c001c000600000000001a001c001c001700000017001700 -180018001800170018001700170018001800180018001700170017001700170017001700 -1700180017001700170017001b0017001700170017001700170017001800180018001700 -1700170017001700170017001700180017001700170017001b0017001700170017001700 -170017001800180018001700170017001700170017001700170017001800180018001700 -1b0017001700170017001700170017001800180018001700170017001700170017001700 -1700180017001700170017001b0017001700170017001700170017001800180018001700 -1700170017001700170017001700180017001700170017001b0017001700170017001700 -170017001800180017001700170017001700170017001700170017001800180018001700 -170017001700170017001700170017001800180018001700170017001700170017001700 -1700180017001700170017001b0017001700170017001700170017001800180018001700 -1700170017001700170017001700180017001700170017001b0017001700170017001700 -170017001800180018001700170017001700170017001700170018001700170017001700 -1b0017001700170017001700170017001800180018001700170017001700170017001700 -170018001700170017001700170017001700170017001700170017001700170018001700 -170017001700180018001700170018001700170017001700170017001800170017001700 -170017001700170018001800170017001700170017001700180018001700170017001700 -180017001700180017001700170017001700170018001700170017001700170017001700 -180018001700170017001700170017001700170017001700180018001800180017001800 -170017001700170017001700180017001700170017001700170017001800180017001700 -170017001700170017001800170017001700180018001800170018001700170017001700 -170017001700180017001700170018001800170017001800170017001700170017001700 -1700180017001700170017001b0017001700170017001700170017001800180018001700 -1700170017001700170017001700180017001700170017001b0017001700170017001700 -170017001800180018001700170017001700170017001700170018001700170017001700 -1b0017001700170017001700170017001800180018001700170017001700170017001700 -1700180017001700170017001b0017001700170017001700170017001800180018001700 -1700170017001700170017001700180017001700170017001b0017001700170017001700 -170017001800180018001700170017001700170017001700170018001700170017001700 -17001700170018001800170017001700170017001700170000001c0017001c0006000000 -00001a001c00170017000000170017001800180018001700170018001800170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001800180018001800180017001700170017001b00 -170017000000170017001c000600000000001a0017001700170000001700170018001800 -180017001800170017001700170017001700170017001700170017001700170018001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170018001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170018001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170018001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170018001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170018001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170018001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170018001700 -170017001700170018001700170017001700170017001700170017001700170017001700 -170017001700170018001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -180017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001800170017001700170017001700170018001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170018001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170018001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170018001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170018001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170018001700170017001700170018001700 -170017001700180017001700170017001700170000001c00170017000600000000001a00 -170017001700000017001700170017001800180017001700170018001700170017001700 -180017001700170017001700170017001b00170017001700170017001800170018001700 -180017001700170019001700190017001700170018001700170019001800170019001500 -180017001700180017001800170017001900170018001800170015001900170017001800 -170017001700180019001700190015001900170017001700190017001700170018001800 -150019001700170019001700180017001700170018001700180017001700180017001800 -170018001800170019001700170019001700170017001800170017001700170017001800 -170019001800170017001b00150018001800180018001700180018001700180017001b00 -170017001700170019001700170018001700170018001700180018001700170017001700 -180017001700180018001700170017001800170017001700180017001700180018001700 -170017001800170017001700180017001700180018001700170018001700170017001800 -170017001700180018001700170018001700170017001800170017001700180017001700 -180017001700180018001700170017001800170017001700180017001700180018001700 -170017001800170017001700180017001700180018001700170017001800170017001700 -180017001700180018001700170018001800170017001800180017001700180018001700 -170018001800170017001800180017001700180018001700170018001800170018001700 -170017001800170017001700180017001700170018001700170017001800170017001700 -180017001700170018001700170017001800170017001700180017001700180018001700 -170018001800170017001800180017001700180018001700170018001800170017001800 -180017001700180018001700170018001800170017001800180017001700180018001700 -170018001800170017001800180017001700170018001700170017001800170017001700 -180017001700170017001700170018001700170018001700170017001800170017001800 -180017001700170018001700170017001800170017001800180017001700170018001700 -170017001800180017001800170018001700170018001700170017001800180017001800 -170018001700170018001700170017001800180017001800170018001700170018001700 -170017001800180017001800170018001700170018001700180017001800180017001700 -170018001700170018001700180017001800180017001700170018001700170018001700 -170018001700170018001700180017001800180017001700170018001700170018001700 -180017001800180017001700170017001700170017001800180017001700170017001700 -00001700170017000e00000000001a001b001c0017000000170017001700170018001800 -17001700170017001b001700180017001700170017001700000017001700000011001900 -1b0017001700170017001800170018001700180000001800170015001800180017000000 -1700190018001500170019001700180017001a0017001700190017001700180015001900 -170017001900180017001700170017001700180018001700170019001700180018001700 -170019001500180018001700150017001900170017001700170017001700180017001700 -180000000000000000000100000000000000170000000000000000000100170017001700 -000017001800190017000000170017000000000000000000000000001700190017001800 -17001800170017001800170018000000000000001a001700000018001800170017001900 -170017001400170017001700180017001700180017001700170018001800170017001800 -180017001700180017001700170018001800170017001800180017001700180017001700 -170017001800170017001800180017001700180018001700170017001800170017001800 -180017001700180018001700180017001700180017001700170018001800170017001800 -180017001700180017001700170018001800170017001800180017001700180017001700 -170018001800170017001800180017001700180017001700170018001700170017001800 -170017001700180017001700170018001700170017001800170017001700180017001700 -170018001700170017001800170017001800180017001700180018001700170018001800 -170017001800180017001700180018001700170018001800170017001800180017001700 -180018001700170018001700170017001800170017001700180017001700170018001700 -170017001800170017001700180017001700170018001700170017001800170017001800 -170017001700180017001700170018001700170017001800170017001700170018001800 -170017001800180017001700180018001700170018001800170018001800170017001800 -180017001800170017001800170017001700180018001700170018001800170017001800 -170017001700180018001700170018001800170017001700170017001700180018001700 -180017001800170017001700170017001700180018001700180017001800170017001700 -170017001700180018001700180017001800170017001700170017001700180018001700 -180017001700170017001700170018001700180017001800180017001700170017001700 -170018001700180017001800180017001700180017001800180017001700170017001700 -170018001700180017001800180017001700170017001700170018001700170017001700 -1800170018001800170018001700170000001c001c0017000e00000000001a0017001c00 -1700000017001800170018001800170017001800180017001700170017001b0017001700 -1b00170000001b0017000000180017001c00170017001700180017001800170018001700 -000017001800190017001700170000001700190017001900170015001700190017001500 -170019001700190017001700190017001900190017001800170017001700190017001700 -170019001700170017001700180017001700190017001800170017001900190017001800 -170018001900180017001800170019000000190019001800170000001700170019001800 -000019001700190013000000190017000000170017001700180000001800170000001800 -17001b0017001500170017001800170018001700180018001800170000001b0017001700 -000019001700000017001700170017001700180018001800170017001800170017001800 -180017001700170018001700170017001800170017001800180017001700170018001700 -170017001800170017001800180017001700180018001700170018001700170017001800 -170017001700180018001700170018001700170017001800170017001800170017001800 -180017001700170018001700170018001800170017001800180017001700170018001700 -170018001800170017001800180017001700170018001700170018001800170017001800 -180017001700170018001700170017001800170017001700180017001700170018001700 -170017001800170017001700180017001700170018001700170017001800170018001700 -180017001800170018001700180017001800170018001700180017001800170018001700 -180017001800170018001700180017001800170017001800180017001700180018001700 -170018001800170017001800180017001700180018001700170018001800170017001800 -180017001700180018001700170018001800170017001800180017001700180018001700 -170018001800170018001700180017001800170018001700180017001800170018001700 -180017001700170017001800170017001700170018001700170018001800170017001700 -180017001700180018001700170018001800170017001700180017001700180017001800 -170018001800180017001700170017001700180017001800170018001800180017001700 -170017001700180017001800170018001800180017001700170017001700180017001800 -170018001800180017001700170017001700180017001800180017001800180017001700 -170017001700170017001800180017001800180017001700170017001700170018001700 -170017001700170018001800180017001800170018001700170017001700170018001800 -180017001800170017001700180017001700180018001800170017001700170000001b00 -170017000e00000000001a00170017001700000017001700180018001700170017001700 -1700180017001800000000001b0000001700000000000000170000001700190000001700 -170017001700180017001800170018000000190000000000170018001700000017000000 -00001700190017001a000000000000001900180000001700180017001700000017001700 -170017001900170017001800000017000000000017001900170018000000000000001700 -170000001800170019000000180019001700000017001800180017001800170001001700 -170017001700000019001700170018000000180017001700190000001800170000001700 -18001700170000001700180000001700170017001b001800170018001700180017001800 -18001800180017000000170017001700000017001b000000180019001700170017001900 -180019001800170017001800170017001700180018001700170018001800170017001800 -170017001700180018001700170018001800170017001800170017001700180018001700 -170017001800170017001800180017001700180018001700170017001800170017001800 -180017001700180017001800170017001700180018001700170018001700170017001800 -170017001700180018001700170018001700170017001800170017001700180018001700 -170018001700170017001800170017001700180018001700170018001800170017001800 -180017001700180018001700170018001800170017001800180017001700180018001700 -170018001800170018001700170017001800170017001700180017001700170018001700 -170017001800170017001700180017001700170018001700170017001800170017001700 -180017001700170018001700170017001800170017001700180017001700170018001700 -170017001800170017001700180017001700170018001700170017001700170017001800 -170017001700180017001700170018001700170017001800180017001700170018001700 -170017001800170017001700180017001700170017001700180017001800180017001800 -170018001700170017001800180017001700180017001700170018001700170017001800 -180017001700180017001700170018001700170017001700180017001800180017001700 -170018001700170017001700180017001800180017001700170018001700170017001700 -180017001800180017001700170018001700170017001700180017001800180017001700 -170018001700170017001700170018001800180017001800170018001700170017001700 -170018001800180017001800170017001800180017001800170017001700170018001700 -170017001800180017001800170017001700170018001700170017001700180018001700 -18001800170017001700170000001c001c001c000e00000000001a001b001c0017000000 -17001700170017001800180018001700170018001700000018001b000000000017001700 -000017001b00000017000000180017001700170017001800180018001700180000000000 -180017000000170017000000000017001900000018001700000017001700170000001700 -190000001700180000001700150018001700170018001800180018000000010017001700 -000017001800000017001900170000001900000017001800170000001700190017000000 -190017001700190017000000170017001800190019000000170019001700170000001700 -190018001700000017001700000019001700180017000000170018000000170017001700 -170017001700170018001700180017001800170017001800000017001700190000001700 -18001b000000170017000000180017001700150017001800170018001800170017001800 -180017001700170018001700170018001800170017001700180017001700170018001700 -170018001800170017001800180017001700180018001700170018001700170017001800 -170017001700180018001700170018001700170017001800170017001800170017001800 -180017001700180018001700170018001800170017001800180017001700170018001700 -180017001800170017001700170018001700180018001700170018001800170017001700 -180017001700170018001700170017001800170017001700180017001700170018001700 -170017001800170017001700180017001700170018001700170017001800170018001700 -180018001700170018001700180017001800180017001700180017001800170018001800 -170017001800170018001700180018001700170017001800180017001700180017001700 -170018001800170017001800170017001700180018001700170018001700170017001800 -180017001700180018001700170018001800170017001700180017001700180017001800 -170017001700170018001700180017001800180017001700180017001800170018001800 -180017001700170017001700180017001700170018001700170018001800170017001800 -180017001700180018001700170018001800170017001700180017001700170018001800 -170018001700170017001800170018001700180017001800170018001700170017001700 -180017001700170018001800170018001700170017001800170018001700180017001800 -170018001700170017001700180017001800170018001800180017001700170017001700 -170018001700170017001800180017001700170017001700180017001700180017001700 -170017001800170018001700180017001800170018001700170017001800170018001800 -1700170017001700170017001700170018001800170017001700170000001c001c001700 -1d00000000001a001c001700170000001700170017001800180018001700180017001700 -1b0000001700170018000000180017000000170018000000000017001700170018001800 -170017001700170017001700000019001700170000001800190000001700170019000000 -170017000000170017001a00000018001700190000000000180017001800190019001700 -170017001700180000001700180011000000180018000000190018001700000018001700 -000017001700000018001500000017001700180018001700180000001800180018001300 -190000001800170018001900000000000000000000001700180017000000190017001700 -190000001800170000000000000000000000000017001800170018001700180017001700 -170018000000170017001c0000001b001700170000001700190015001700180018001900 -180017001800170017001800180017001700180018001700170018001700170017001800 -180017001700180018001700170018001700170017001800170017001700170018001700 -170017001800170017001800180017001700180018001700170017001800170017001800 -180017001800170017001800170017001700180017001700170018001700170017001800 -170017001700180018001700170018001700180017001800180018001700170017001700 -170018001700170017001800180017001700180018001700170018001800170017001800 -180017001700180018001700170018001800170017001800180017001700180018001700 -170018001700180018001700170017001700170017001800180017001700170017001700 -170018001800170017001700170017001700180018001700170017001700170017001800 -180017001700170018001700170018001800170017001700180017001700180018001700 -170017001800170017001800180017001700170018001700170018001700170017001800 -180017001700180017001700170018001800170017001800180017001700170017001700 -170018001800170017001700170017001700170018001800170018001800170018001700 -170018001700170017001800170017001700180017001700170018001700170017001800 -180017001700180018001700170017001700170018001800170017001700180017001700 -170018001700170018001800180017001800170018001700170017001700170018001800 -170017001700180017001700170018001700170018001800180017001800170017001700 -170017001700170018001800170018001700180017001800170018001700170018001800 -170018001800170017001800170018001800180017001700180017001700170018001700 -170017001800180017001700170017001700180017001700170018001800170018001800 -170017001700170000001c00170017000e00000000001a00170017001700000017001700 -170017001800180017001800180017001700000017001b00170000001c001b0000001700 -170000000000170017001b00170018001700180017001800180017000100170017001900 -000018001700000018001700170000001900170000001800170017000000180017001700 -0000000017001800170017001700170018001900180017000000170017001a0000001700 -170000000000000000000000170017000000170017000000180019000000170017001700 -190015001900000017001700190017001700000017001800170015000000170019001700 -00001900170018000000170019001700170000001700170000001b001500170017001700 -17001700180017001800170017001700170017000000170017001b000000170017001700 -0000170017001a0017001700170017001700180017001800170018001700180017001700 -180017001700180018001700170017001800170017001700180017001700180018001700 -170018001800170017001800180017001700180018001700170018001700170017001800 -170017001700180018001700170018001700170018001700170018001800170017001700 -180017001700170018001700170017001800170017001700180017001700180018001700 -170018001700170018001700180017001700170018001700170017001800170017001800 -180017001700180018001700170018001800170017001800180017001700180018001700 -170018001800170017001800180017001700180017001700170017001700180018001700 -170017001700170017001800180017001700170017001700170018001800170017001700 -170017001700180018001700170018001700170017001800180017001700180017001700 -170018001800170017001800170017001700180018001700170018001700170017001800 -180017001700180018001700170017001800170017001800180017001700170017001700 -170017001700170017001800180017001700170017001700170018001800170018001700 -180017001700170017001700180017001700180018001700170017001800170017001700 -180017001700170018001700170017001800170017001800170018001700180018001700 -170017001800180017001700180018001700170018001700170017001700170017001800 -170018001700180018001700170017001800180017001700180018001700170018001700 -170017001700170017001800170018001800170018001700180017001800180017001700 -180018001700170018001700180017001700170017001700180017001700170017001700 -170018001700170018001800170017001800180017001700170018001800170018001700 -17001700170017001700180018001700170017001b0017000000170017001c001d000000 -00001a0017001c0017000000170017001700170018001800170017001800170017000000 -17001700180000001b00170000001900170000001b000000180017001700170017001800 -170017001800170000001700190017000000190017000000170018001700000017001700 -000017001900150000001700170001001700180000001800170017001700190015001800 -180018000000180017001700000018001900000018001700170017001700170000001900 -000017000000180000001900190017001700180019000000180017001700190017000000 -170018001900180000001700180017001700000017001800000017001700190017000000 -17001700000017001900180017001b001700170017001800170017001800170017001800 -0000170019001700000019001700180000001a0013001700180017001700180017001700 -180017001800170018001700180017001700180017001700170018001800170017001800 -180017001700180017001700170018001700170017001800180017001700170018001700 -170017001800170017001800180017001700180018001700170017001800170017001800 -170018001700170017001800180017001700180018001700170018001800170017001800 -180017001700180017001700170018001700170017001800170017001700180018001700 -170018001800170017001800170017001700180017001700170018001700170017001800 -170017001700180017001700170018001700170017001800170017001700180017001700 -180018001700180017001800170017001800180017001800170018001700170018001800 -170018001700180017001700180018001700180017001800170017001800170017001800 -180017001700170018001700170018001800170017001700180017001700180018001700 -170017001800170017001800180017001700170017001700170018001800170017001800 -170017001700180017001700170017001800180017001800170018001700170018001800 -170018001700180017001700180017001700170018001800170018001700180017001700 -170018001800170017001800180017001700180018001700170018001800170017001800 -170017001700180017001700180017001800170017001700180017001700170018001700 -180017001800170018001800170017001700180017001700180017001800170017001700 -180017001700170018001700180017001800170018001800170017001700180017001700 -180017001700170017001700170018001700170017001800180017001700170018001800 -170018001700170018001800170018001700180017001800170017001700180017001700 -170018001700180017001700180017001800170017001700180017001700170017001700 -17001700000017001c0017000600000000001a0017001700170000001700180017001800 -180018001700170017001700180000001b00170000000000170017000000170018000000 -170017000000170019001700170019001700170018001700000017001800170000001700 -190000000000190017000000170019000000180017001700000017000000170018001800 -190000001800170017001800170017001700170000001700170018000000170018000000 -170017001700000018001700170000001700170017000000170018001700190017001700 -190000001700170017001900170000001700180017001700000017001900170019000000 -180017000000190017001700190000001700170000001b00170017001700180017001800 -180018001700180017001700170018000000170017001b00000018001900130000001700 -180019001700180018001700180017001700180018001700170017001800170017001800 -180017001700170018001700170018001800170017001800180017001700170018001700 -170018001800170017001800170017001700180019001700170017001700170018001800 -170017001800170017001700170018001700180017001800170017001700180017001800 -170017001800170018001700170018001700180017001700180017001700170017001800 -170018001700170017001800180017001700180018001700170018001800170017001700 -180017001700170018001700170018001800170017001800180017001700170018001700 -180017001700180017001700180018001700170017001800170017001800170017001700 -170018001700180017001800170017001700180017001700180017001700170017001800 -170018001700180017001700170018001700190017001800180017001700180017001700 -170018001700170017001800170017001700180018001700170018001700170017001800 -180017001700170018001700170018001700190017001700170018001700170017001700 -170018001700170018001700170017001700180017001800170018001700170018001700 -170017001700180017001800170018001700170017001800170018001700170018001700 -180017001700180017001700190017001800170017001700180018001700180017001800 -170018001700170017001800170017001700170018001700170017001800180017001700 -180017001700170018001800170018001800170017001800180017001800170017001800 -180017001800180017001700170018001700180017001800170018001700170018001700 -180017001900170017001800170019001700170017001700170017001700180017001700 -170017001800170017001700180017001800170018001700180018001700170017001700 -1700170017001700180018001700170017001700000017001b001c000600000000001a00 -1c001c001700000017001700180017001700180017001700170018001700170000000000 -170000001700170000000000170000001700170017000000170017001700170018001800 -170018000000170017001500020019001700000019000000000019001700150019000000 -000000001800190000001800170017001500000019001700170019001900170019001800 -000019001800170000001900170017000100000000001700170018001900000019001800 -170000001800170019001700190019001500000017001900180017001700020017001300 -170019000000180015001800150000001900170017000000000001000000180017001700 -000000000000000000000000170017001700000017001700170018001800180018000000 -000000001700170017001900010017001800000017001800140018001700180017001700 -170018001800170017001800170017001700180018001700170018001700170017001800 -170017001700180018001700170018001700170017001700180017001700180018001700 -180017001800180017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170018001800170018001700170017001700180017001700170018001700 -170017001700170017001800180017001700180018001700170018001700170017001800 -170017001700180018001700170018001900170017001800170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700190018001700170017001700 -170017001700170018001700170018001800170017001800180017001700180018001700 -170017001800170017001800180017001700180018001700170018001700170017001800 -170017001700190018001900170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170018001800180017001800170017001700 -180017001700170017001700170018001700170018001800170017001800180018001700 -180017001800170017001700180017001800170018001700170017001700170017001800 -170017001700180019001700170018001700170017001700170017001700170017001700 -170017001700170017001700170017001700170018001800170019001700190017001700 -170017001700180017001800170018001800180017001700180018001700170018001700 -170017001700170017001800170017001b00170018001700180018001700170017001700 -00001c001c0017000600000000001a001c00170017000000170018001700170018001800 -180017001700180017001b0017001700170000001700170017001b0017001b001b001700 -170018001800170018001700170017001700180017001700180019001700150019001700 -170017001700180017001900190017001800190017001700190017001700170019001700 -1700170017001700170018001700190017001800170019001a0015001800170017001800 -170017001800170017001900170018001700190017001800170017001800180018001900 -000017001700170017001500170019001700170017001700190017001900180018001700 -170017001700170017001800170018001700170017001b00180017001800170017000000 -180019001700190017001500170017001b00180017001800170000001100190017000000 -190015001900180017001800180017001700170018001700170018001800170017001700 -180017001700180018001700170018001800170017001700180017001700180018001700 -170018001800170017001800170017001700170017001800180018001700170018001800 -180018001800180018001800180017001800180018001800180018001800180017001800 -180018001800180018001800180017001800180018001800170017001700170018001700 -170018001700170017001800170018001700180018001700170017001800170017001800 -180017001700180018001700170017001800170017001700180017001700180018001700 -170019001700170018001800180018001800180018001800180018001800180018001800 -180018001800170018001800180018001800180018001800180018001800180018001800 -180017001700170019001900180018001900170017001800180017001700180017001700 -170018001700170017001800170017001700180018001700170018001700170017001700 -180017001700180018001700170019001700170017001700170017001800180018001800 -180018001800180018001800180018001800180018001700180018001800180018001800 -180018001800170018001800180018001800180018001800170018001800180018001800 -170017001700170017001800170018001700180017001800180018001700170018001700 -170017001800170017001700170017001700180017001800170018001700170017001800 -170018001700180018001700170017001800170017001700180017001700180017001700 -180018001800180018001800180018001800170018001800170018001800180018001800 -170019001700180018001800170017001800170017001800180017001700170017001700 -170018001700170017001800170017001800180018001700180017001700170017001700 -170018001800180017001b00170017000000170017001c000600000000001a0017001700 -170000001700170018001800180017001700170018001700170000001300190017000000 -17001700170017001c001800170017001900170000000000000000000100000000001700 -170018001700170017001900170018001800170018001700180017001500190018001300 -190019001800170017001800180018000000000000000000000000000000170018001900 -110018001700180018001800180017001700190019001700170019001700130019001800 -170017001700190018001500170017000000180017001700180019001800170017001700 -190017001900170017001800170017001800170019001900180019001700170017001900 -17001b001300190017001700000018001700170019001500190017001800170017001700 -17001900180000001a001800000019001800180017001800170017001700180018001700 -170018001700170017001800180017001700180017001700170018001700170017001800 -180017001700180017001700170018001800170017001700180017001700180017001700 -170017001700170017001800170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001900180018001800190017001700170017001800180017001800170017001800 -170018001800170017001800170017001700180017001700170018001800170017001800 -180017001700180017001700180017001700180017001700180017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170018001700 -180017001700170018001700170018001800170017001800180017001700180018001700 -170017001800170017001800180017001700180017001700170018001700180017001700 -180018001700180017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001900180019001800170019001700170017001800 -170017001700170018001700180017001800170018001700180017001800180017001700 -170018001700170018001800170017001700180017001700170018001800170017001800 -180017001800170017001800170017001800170017001700170017001700170017001700 -170017001700170017001700170017001700190017001700180017001700180017001700 -180017001700170018001800170018001700180017001800170018001700180017001700 -170017001800170017001b001700170018001700170017001700170017001b0000001700 -170017000600000000001a00170017001700000017001700170018001800170018001800 -170017001700170000000000000017001b00170017001b00170017001800170017001b00 -180017001900170017001900170017001700170017001900180019001700170017001800 -170017001800190019001500170019001700170017001700180017001700170017001700 -170017001900190018001800170018001900170019001700170018001700170017001700 -170019001900170019001900170017001800190019001700180017001700190017000000 -180017001700170017001700180017001700180015001800180017001900170015001900 -11001b001700170017001800180013001700180017001700170017001800180018001700 -180017001900190017001900180017001800150000001700150018001900170015001900 -180018001800170017001700180017001700170018001700170017001800170017001700 -180017001700180018001700170017001800170017001800180017001700180018001700 -170018001800170017001800170019001800170017001700170018001700170018001800 -180017001800180017001700180018001800170018001800170017001700180018001800 -180017001700180018001800170017001700180017001700170017001800180018001900 -170017001800170018001700170017001700180018001700170017001800170017001700 -180017001700180018001700170018001800170017001700180017001800170018001700 -170017001700170017001800180018001700170017001800180018001800170017001800 -180018001700180018001800170017001700180018001800180017001800170018001800 -190018001700170017001700190019001800170017001800180017001700180018001700 -170018001700170017001800180017001700180018001700170018001800170017001800 -180017001700180017001800170017001700170017001700170018001800180017001700 -170018001800180018001700180017001800180017001700180018001800170018001800 -170017001800180018001700180018001700170017001800180018001800170017001700 -170017001700170017001700170017001800180017001800170017001700170018001700 -170017001800180017001800170018001700180017001800170018001700180017001800 -170018001700170018001700170017001800170018001700180017001700170017001700 -180018001800170017001800180018001700170017001800180018001800170017001800 -170017001800170018001800180017001800170018001700180017001800180017001700 -170018001700170017001700180017001800180017001700170017001700170017001800 -1700170017001700170017000000170017001c000600000000001a0017001c0017000000 -170017001800170017001800170017001700170019001800170017001900170017001b00 -1700130017001700180019001b00150018001900180017001800170013001a0018001700 -190015001700170019001700190017001700170018001800170019001800170017001800 -190019001700180019001700180018001700170017001700150018001700190019001700 -180018001800180018001900170019001800150017001800170013001900180017001700 -130019001500190019001500170017001700190017001900170019001700170017001700 -19001700170018001700180019001700190017001800170017001700170017001b001700 -1a001700170019001500180019001700170017001800150017001b0017001b0017001700 -190019001900170019001800190015001900190017001800180017001700180018001700 -170018001800170017001800180017001700180017001700170018001800170017001800 -170017001700180017001700170017001800170017001700180017001500180017001700 -190019001700170018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800170018001800 -170019001800180015001700180018001800170018001700170017001800170017001700 -170018001800170017001800180017001700180017001700170018001700170017001800 -180017001700180018001700170017001700180019001900180018001800180018001700 -180018001800180018001800180018001800180018001800180018001800170018001800 -180018001800180018001800180018001700170017001900170018001500170017001700 -180017001700170018001700170017001800170017001800180017001700170018001700 -170017001800170017001800170017001700180017001700180017001700170019001700 -170019001800180018001800180017001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800170018001800180019001700180017001800170017001700 -170017001800180018001700180017001800170017001700170017001700180017001700 -170018001700170017001800170017001700180018001700170018001800170017001800 -180017001800170017001800190019001800180018001800180018001800180018001800 -180018001800180018001800190017001800170018001700170018001800170017001700 -180017001700170017001700170018001700180017001800180018001700170017001700 -1700180017001700170017001800170017001700170017001700170000001c001c001700 -0600000000001a0017001c00170000001700180017001800180017001800170017001700 -1a001a001a001a001a001a001a001a001a001a001a001a001b001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a0019001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a000f001800180017001a00150017001700 -180015001800170018001700170018001800170019001700180017001700170018001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001000180015001400 -170017001800170017001700180017001700170018001700170017001800170017001800 -180017001700170018001700170018001800170017001800180017001700180018001700 -170018001800170019001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a00120015001700150017001800 -170017001700180017001700180017001700170018001700170018001800170017001800 -180017001700170018001700170017001800170017001800170017001700170017001900 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a0012001700170018001800170017001800180017001700180018001700 -170018001700170017001800180017001700180018001700170018001800170017001800 -1800170017001700180019001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a0012001700170017001800170018001800170017001700170017001700180017001800 -170018001800180017001700180018001700170018001800170017001800180017001700 -180017001700180018001700170018001700170017001800180019001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001900120018001800 -170018001700170017001700180018001700170018001800180017001800170018001700 -170017001700170017001800180017001800170017001b00170017001700180017001b00 -17001700170017000000170017001c000600000000001a00170017001700000018001700 -180017001800170017001800170018001a0017001b00170017001b001700170017001700 -180017001b00170017001800180019001800180017001700180018001700180017001700 -190017001700180017001700170015001700190019001700180017001700190017001900 -170017001900170019001700170019001900180018001700180019001700180018001700 -180018001900180017001700190017001700180017001800170019001700170018001800 -0f0019001500180017001700170017001700190017001800170017001700190017001700 -18001700180017001700190019001a00190017001900170017001b001700170019001700 -180018001700170018001700180017001800180017001700170017001900170019001800 -18001800180018000c001900180018001800170017001800180017001700180018001700 -170018001800170017001800170017001700180018001700170018001700170017001800 -17001700170018001800170017001700180017001700180018001a001900170018001700 -170017001800170018001800180017001800180018001700180018001800170018001800 -180018001800180018001800180018001800180018001800180018001800180017001900 -180019000c00150018001800180017001700180017001800170017001700180018001700 -170018001700170017001800170017001700180018001700170018001800170017001800 -170017001800170017001700170019001a00190018001800180018001800180018001800 -180018001800180018001800170018001800180018001800180018001800180018001800 -1800180018001800170017001900180017001800170019000c0017001800170017001700 -180017001700170018001700170017001800170017001800180017001700170018001700 -170017001700170017001800170017001700180018001700180017001a00190019001800 -180018001800180018001800180018001800180018001800180018001700170018001700 -180018001800170018001800180017001800180018001700180018001800170018001800 -1700180018001700170018001700170019000c0018001800170018001700170018001700 -180017001800180017001700170018001700170017001700180017001700170018001700 -170017001800170017001700180017001700180017001700170018001700170018001700 -170017001700190019001900180018001800180018001800180018001800180018001800 -180018001800170018000f00170018001700190017001700170018001700170017001800 -170017001700170018001700170017001800180017001800170018001700170018001700 -17001700170017001800170017001700170017001700170000001c0017001b0006000000 -00001a001b001c001700000017001700180018001700170018001800170018001a001900 -1700170018001700170017001700170017001b0017001700170017001700170017001900 -150019001700170017001700170019001700170018001700170019001800170017001800 -170018001700170018001700180018001700170017001700180017001700180017001700 -170017001700180017001700170017001700170018001700170017001700180017001800 -170017001700170018001700180017000f00170017001800170018001700170018001700 -1700180017001700180018001700180017001700180017001700170017001a0018001700 -170018001700170018001900170017001700180017001800170017001700180017001800 -1700170018001700180017001700170017001800170017000f0017001800180018001700 -170018001800170017001800180017001700180018001700170018001800170017001800 -180017001700170018001700170017001800170017001800180017001800180017001700 -1700180019001a0017001700190018001700170017001800190017001800180015001800 -170017001700170019001500190017001900170017001700170017001900170017001700 -17001900170018001700170017001700170018000f001700180018001400170018001700 -170017001700180017001700180017001700170018001700170018001800170017001700 -18001700170017001800170017001800180017001700180018001700170017001a001800 -180017001800170018001700190017001800130019001700180017001700170018001700 -170017001700170017001800170017001700180017001900170018001800180017001800 -160018000f00180018001800170017001800180018001800180017001700180017001700 -170018001700170017001800180017001700180018001700170018001800170017001700 -18001700170018001a001700180018001800170018001700170017001900170017001800 -170018001800170019001700170018001700170018001700170017001900180017001700 -15001900170017001b001700170017001700170019001700170017001800170018000f00 -170017001700170018001800170018001700180017001700180017001700170018001800 -170018001700170017001800170017001700180017001700170018001700170017001800 -1800170017001700180017001700170018001700170017001a0018001900170017001900 -17001700190017001700170019001700170017001800180019000c001700180018001700 -180017001700180018001800170018001700170018001800170017001700180017001700 -18001700180017001800180017001700170017001b001700180017001800180017001700 -170017000000170017001c000600000000001a001c001700170000001700170017001800 -1700170017001700170018001a00130017001700170017001b0017001c001a0013001700 -17001b0013001b0017001700170017001700170018001700170017001700180017001700 -190017001900170015001900150017001700170018001700180017001900170018001700 -170017001800190019001700170018001700180019001500170019001800170018001800 -17001900170019001800150019001700180017001900170017001900180018000f001700 -170018001700180018001700170018001700170017001700170018001700180018001700 -180017001700170017001a00170019001800170018001900180013001900170019001700 -1900170015001900170018001700170017001700170017001b0017001800170017001800 -170017000c00170018001700170018001700170017001800170017001700180017001700 -170018001700170017001800170017001700180018001700170018001800170017001800 -170017001700170017001700170018001700180017001a00170018001700150019001700 -190013001700170018001900180019001900170017001700170019001700170017001700 -170017001900150017001900170019001800150019001700170019001700180017001700 -0f0017001800170018001800180017001700180018001800180017001700180018001700 -170018001700170017001800180017001700180018001700170018001700170017001800 -1700170018001700170018001a0018001700190017001900170019001700170017001900 -130017001900170018001700170017001800170017001800170017001800180019001800 -17001700190013001800180017001800180018000c001800180018001800170014001800 -180017001700170018001700170018001800170017001800180017001700170018001700 -1700180017001700170018001800170018001700170018001a0018001800170015001900 -190017001800180015001900150019001900180018001800170017001800170017001800 -180018001700190017001500170019001800170017001700170019001800170018001b00 -15001900170017001800170017000f001700180018001700170017001700170017001800 -180017001800170018001700170017001700170018001800170017001800180017001700 -180018001700170018001800170017001700180018001700170018001700180018001700 -170017001a00180017001900180017001700170015001900180017001300190017001700 -1900150018000c0017001700180017001800180018001800170017001800180017001700 -170017001700180017001800170018001800170017001700170017001700180017001700 -170017001700180018001800170017001700170000001c001c0017000600000000001a00 -170017001700000017001700170018001800180018001800170017001a00180018001900 -1c00170017001700170017001700150017001b00170018001800180018001a0017001500 -150019001900190017001800150018001700170015001700190017001900170017001800 -190017001700180015001900170018001800170017001700170017001a00130017001700 -170018001700170017001700170018001700150017001700170019001700150019001700 -1700170018001700180017000f0018001700180017001800180017001700180018001700 -17001700180017001800170018001700170018001900170019001a001700170017001700 -1700170017001a0017001700170017001300170019001700190017001700180019001700 -170017001300190017001800170018001700170010001700180018001700180018001700 -170018001800170017001800180017001700180018001700170018001800170017001700 -180017001700170018001700170018001800170017001800180017001800180017001700 -19001a001900170018001700190017001700190018001800170017001800170015001700 -190017001700170017001700180017001700190017001900170015001800170017001900 -180018001900130017001800170017000f00170018001800180018001700170018001800 -170017001800170017001800180017001700180018001700170017001800170017001800 -180017001700180018001700170017001700170018001700170018001a00180017001700 -190013001700170018001800170018001800180018001700180017001800170018001700 -170018001700180017001500170017001700170019001800170018001700180018001800 -0c0018001800170018001700180018001800170017001800180017001700180017001700 -170018001700170017001800180017001700180018001700170017001800170017001700 -170018001a00170018001700190017001700170017001800170018001900150019001800 -110019001700170017001800170017001700170018001700180018001900170017001700 -170017001b001300170017001700180017001700170017001700170017000f0017001800 -170018001700180018001800170017001700170017001800170018001700180018001700 -170017001800170017001700180017001700170018001700170017001800170017001700 -18001700170018001700170018001700170017001a001800190017001700170018001700 -180017001900170018001700170017001500190018000c00170017001400170018001700 -140018001700170018001700180017001800170018001700180017001700170017001700 -180018001800170018001700170017001700170018001700180018001700170017001700 -0000170017001c000600000000001a0017001c0017000000180018001800180017001700 -17001700170017001a001700170017001b00170017001700170017001800170017001700 -180017001500190017001300190018001900170013001700180017001700190017001800 -190017001700180017001700180017001700170018001900190017001800170017001700 -190015001900180011001a0018001700190017001700190017001700180013001a001700 -180019001700170017001900170017001700170019001800180017000f00180017001800 -170018001700180017001700170018001700170017001800170018001700180017001700 -1800170019001a0017001900170019001700170017001700150017001900170019001700 -1700180015001700180017001700170017001b001b001700170017001700180017001700 -0f0018001800180017001700170018001700170017001800170017001700180017001700 -170018001700170017001800180017001700180018001700170018001700170017001800 -1700180017001700170017001700180017001a0017001700180019001700170017001700 -170017001900170019001700170019001700170018001800170019001700180017001700 -17001700170019001700180017001900170017001700180017001700170017000f001700 -180017001800170018001800170018001800180017001800170017001700180017001700 -170018001800170017001800170017001700180017001700170018001800170017001700 -17001700180018001a001800190017001800190018001900170017001700170017001800 -170019001700170017001700190017001700180017001700190018001800170017001900 -130018001700180017001800180018001000180018001700170018001700170018001800 -180017001700170018001700170018001800170017001800180017001700170017001700 -17001800180017001700180018001700170018001a001700180017001900170019001700 -19001300190017001800170017001800190017001800170017001700170017001a001800 -1700190017001700170017001900180018001800190017001b0017001b00130018001700 -170017001800170017000f00170017001700180017001700170017001800170018001800 -170017001700180017001700180017001800170018001700180017001800170018001700 -180017001800170017001800180017001700180017001700170017001800170017001700 -1a0018001700190017001700170017001700170017001800170017001700170019001700 -19000c001700180018001700180018001700170017001700180018001800170017001700 -180017001700170018001800170018001700170017001700180017001700170017001700 -1700180017001700170017001700170000001c00170017000600000000001a0017001700 -1700000017001700170017001800170018001700180017001a001b001700170017001700 -1700170017001b0017000000170017000000170019001700170019001500190017001800 -190018001500000019001700170017001500190019001700170018001700180017001900 -150015001700180017001800170018001800170017001900180017001800170017001800 -180017001700180017001800170018001700170017001800180019001700000019001800 -13001700180018000f001800170018001400180018001700180017001700170017001700 -180017001800170018001700180017001700180018001a00170019001700170017000100 -1700000019001700170017001500190019001700170018001800180017001b0013001700 -170018001700180017001800180018000c00170018001700180017001700180018001700 -170017001800170017001800180017001700170018001700170017001800170017001700 -180017001700180018001700170018001800170018001800180017001700170018001a00 -170018001700000017001700190017001900170015001800170017001700150017000000 -190017000000150018001800180017001700180019001500170019001500180019001800 -1800170018001800140018000f0017001800170017001800170017001800170017001700 -170018001800170017001800180017001700180018001700170017001800170017001700 -1800170017001800180017001700180018001700170017001a0018001800000000000000 -000000000000000017000000000000000000000019001800190000001700170017001700 -000019001700000000000000000000000000170017001800170018001800170010001800 -170017001700180017001700180018001800170017001800180017001700180017001700 -170018001700170017001800180017001700170018001700170017001800170018001800 -1a0018001800180000000000000000000000010017001700190019001700000017001900 -150019001800000017001800150017001700170018000000020000000000190017001700 -00000000000000000000010017001700170017001800170018000f001700170017001700 -180018001700180017001700170018001700180017001800170018001700170018001700 -170017001800180017001700180017001700170018001800170018001800170017001700 -180017001700170018001700170018001a00180017001700170000000000000017001900 -0000170017001700190017001800170019000d0018001900180017001800170018001700 -180018001400180018001800180017001800170018001700180017001700170018001700 -180018001700170017001700170018001700170018001800170017001700170000001700 -1c0017000600000000001a001c001c001700000017001700180017001700180017001800 -170017001a0017001b0017001700170017001700170017001b00000017001a0000001700 -170018001700170017001800170017001700180018000100170017001700170017001800 -170017001700170017001700190017001800190017001900190017001700180017001800 -170018001700170017001900170018001700170019001700170017001800150019001700 -1900170017001700190000001700170019001900180018000c0018001700180017001800 -1700180017001800170017001b0017001700180017001800170018001700180018001800 -17001a001700150017001900000017001900000017001800170018001700180017001700 -170017001700170018001700170018001700190018001700170018001700180010001700 -180017001700180017001700170018001800170017001800170017001700180018001700 -170018001800170017001800180017001700180017001700170018001700170017001700 -17001700170017001800180017001a001900170019000000170019001500190017001700 -180018001b001700170017001900000015001b0000001900180017001700170017001700 -180017001800180019001300170017001700170018001800180018000f00170018001700 -180017001700180018001700170018001700170017001800170017001700180017001700 -170018001800170017001800180017001700180017001700170018001700170018001700 -170017001a00180017001700190017000000170019001700180000001900180017001800 -000017001700000017001700180017000000170017000100170017001800170017001900 -1700180017001800180017000c0018001800140018001800170017001800170017001700 -180017001700170018001700170018001800170017001800180017001700180018001700 -170018001800170018001700170018001a00180018001700000019001700180018001700 -180017001700180000001900000017001700180017000000180017001900180017001800 -0000190017001700190000001700190000001b0017001700170017001700170017001700 -1800170018000f0017001700180017001700170017001700180018001700170017001800 -170017001700180018001700180017001800170017001700180017001800170018001700 -17001700170017001700180018001700170018001700180018001700170018001a001800 -180019000000180015001700000018001800000017001800150017001700170018000c00 -180018001800170018001700170018001800170017001800180018001800170017001700 -180017001700170018001800170017001700170017001800170017001800170017001700 -18001800180017001700170000001c00170017000600000000001a001c00170017000000 -17001700170017001800180018001700170017001a001700170017001b00000000001700 -000017000000000000001700000017001800000019001700190018001700180018001700 -170000001700000000001700190017001700000000000100170017000000180017001900 -170000001900170017001700180017001800170000001900000000001900180017001900 -000000000000190019001800180000000000000019001700170000001700180000001700 -180018000f00180017001800170018001800170018001800170017001700170018001700 -1800170018001700180017001700170017001a0018001700190017000000180015000000 -17000000000017001b0017001700000000000100170017000000170017001b0017000000 -1b00170017001800180018000f0018001800170017001800180017001700170018001700 -170018001800170017001700180017001700170018001700170017001800170017001800 -1800170017001800180017001700180018001700180017001800170018001a0018001800 -1700000019000000000017001700170000001b0017001700000017000000010000000000 -000000001700170001000000000017001700180000001700000000001800180017001900 -17001800180018000c001800180018001800170018001400170018001700180018001700 -170017001800170017001700180017001700170018001700170018001800170017001800 -18001700170017001700170018001700170017001a001800190017001700170000001700 -180017001700000017001700190018000000190018000000170018001700170000001800 -170000001900170017001700190017001700180017001800170017000c00180017001800 -180017001700170018001700170018001800170017001800180017001700180017001700 -17001800170017001700170018001700170017001800170018001700180018001a001700 -180017000000170017001700170019001900170017001800000018000000190019001700 -170000001700170018001700190017000000190017001700180017001700170000001700 -1700170017001b001b001700180017001800170018000f00170018001700180017001800 -180017001700170018001800170017001800180017001700170017001700180017001800 -170018001700170017001800170018001700180018001700170017001800170017001800 -1700170018001700170018001a0018001700170000001700180018000000170017000000 -170017001800190019001700180010001800180018001700180017001700180017001700 -170017001700180017001700180018001700170018001800170017001700180018001700 -18001700170017001800170017001800170018001700170017001700000017001c001c00 -0600000000001a0017001700170000001700170017001700180018001700180018001700 -1a0017001800170000001700170000000000170017000000170017000000170000001700 -170017001700170017001700170019001800000000001800170000001700180000001700 -170017000000180017000000170017000000190017001800170018001700180017001700 -000000001800180000001700170000001800180019000000170018000000180018001700 -00001700190000001700000017001800180018000c001800170018001700180017001800 -18001b001700170017001700170018001700180017001800170018001700190018001a00 -150019001700000017001900180000000000170018000000170018000000170017001700 -000018001700000017001700000018001700180018001800180018000c00180018001800 -170017001700180018001700170018001700170017001800180017001700180018001700 -170018001800170017001800170017001700180017001700170018001700180017001700 -180017001700170018001a00170019001700000000001700170000001700190000001700 -17001800000017001700000017001b000000170018000000170017001700000018001700 -0000000017001800000017001900170017001800180018000f0017001800170017001800 -180018001700180018001800170018001800170017001800180017001700180018001700 -170018001700170017001800170017001700180018001700170018001800170017001700 -1a0018001700170017001800000018001700190018000000190017001700170000001700 -170000001800170017001700000017001700000017001800180017001800170018001800 -17001800170017000f001800170018001800170017001700180018001800170017001700 -180017001700170018001700170018001800170017001800180017001700180018001700 -1700180017001700180018001a0017001800170000001700190018001700170017001800 -170000001800170017000000170018001900000017001800170017001700180017000000 -000017001700170019001800000017001900170017001700170017001700170018001700 -18000f001700170017001800170017001800170018001700170017001800170017001700 -180017001800180017001700170018001700170018001800170017001700180017001700 -170018001800170017001800170017001700170018001700170018001a00180018001700 -0000190017001700000018001700180000001800170000001700170018000c0017001800 -180014001800180018001800170017001800170018001700170018001700170017001800 -170017001700180017001800170017001800170018001700170017001700170017001800 -1700180017001700000017001c0017000600000000001a00170017001700000017001700 -170017001700180017001800170017001a00170018001700000017001b00170000001700 -170000001b00170000000000170019001800180017001700170017001700190017000000 -170017001800000017001700000017001900170000001800180017000000000017001800 -170018001800170017001800180017000100170017001700000017001900170018001700 -170000001700170000001700180018001800170018000000000017001800170018001800 -0c0018001700180017001800170017001800170017001700170017001800170018001700 -17001700180018001700180018001a001800170017000000170019001700000017001700 -190000001700170000001700190017000000170017001700000000001b00170017001700 -17001700170019000c001800170018001800170017001700180017001700180018001700 -170017001800170017001700180017001700180018001700170018001800170017001700 -18001700170018001800170018001800170017001700180017001a001700170017000000 -170019001700000017001700000017001700170000001700170000001700190000001800 -170000001700190017000000170017000000170017001700000018001700190017001800 -170019000c00180017001900180018001800180017001700170017001700180018001700 -170018001800170017001800180017001700170018001700170017001800170017001800 -180017001700170017001700170018001a00180019001500190018000000150019001700 -170000000000000000000000170018001700000018001700170018000000170019000000 -0000000000000000000017001800190015001800180019000c0018001800180018001400 -180017001800180018001700170018001700170017001800180017001700180018001700 -170018001800170017001800180017001700180018001700170018001a00170018001800 -000000000000000000001700180018001700000017001700190000001800180018000000 -190017001700170017001700170018001700000000001700170017000000000000000000 -0000000017001700170018001900170018000f0017001900170017001800180017001800 -170018001700180017001700170018001700170017001800170018001700170018001700 -170017001800180017001800170018001700170018001700170017001800170017001800 -18001700170017001a001800170017000000170019001700000017001700170000001800 -170015001900170018000c00180018001800170018001700180017001800140018001800 -170017001700170018001700170017001800170018001700180017001800180017001700 -170017001700170017001b00180017001700170017001700000017001c00170006000000 -00001a001b001c001700000017001700170017001800180017001800170017001a001700 -1b00170000001b0017001800000018001700000017001700000000001700150018001800 -1900170018001800180015001700000017001a0017000000180017000000170017001700 -0000180017001900000000001a0013001800180017001900170017001700170000001900 -180017000000190018001700000000000000000017001700010018001700180017001700 -190000000000180018001700180016000f00180017001800140018001700180017001800 -1700170017001700170018001700180018001700170017001700180017001a0017001700 -170000001700170015000000190017001500000018001800000017001700170000001700 -1b00170000000000170017001b00170017001800170017000f0019001700180017001800 -180017001700180017001700170018001800170017001800180017001700180017001700 -170018001700170017001800180017001700180017001700170017001700170017001800 -1700180017001a001900170017000000130017001800000018001b000000170017001700 -000018001800000017001700000017001800000017001700170000001700180000001700 -170019000000170018001800170019001800150010001900150018001800180018001700 -170017001800180017001700170018001700170017001800170017001700180018001700 -17001800180017001700180017001700170018001700170018001700170018001a001800 -170017001700170000001700170017001900000019001800170001001700170018000000 -180018001800180000001900170000001800170017001800180018001700180018001900 -190019000c00170017001700180017001800180017001700170017001800170017001800 -180017001700170018001700170017001800170017001700180017001700170018001700 -17001700170018001a001800180017000000170018001700170019001500180019000000 -000000000000000019001700150001001700170019001900170018001800170017001800 -170000001800170000001700170017001700180017001800170017001700180017000c00 -190017001800170017001700170017001700180017001700180018001700170018001800 -170017001700180018001700180017001800170017001700170017001700180018001700 -1700180018001700170018001700170018001700170018001a0018001800170000001700 -17001800000018001900170000001700170019001700170019000c001800180018001700 -180017001800170018001700180018001800170018001800170017001800180017001700 -1800170017001700170017001700180017001b0017001700180017001800180017001700 -1700170000001c0017001c000600000000001a0017001c00170000001700180018001800 -1800170018001700180017001a00170017001b0000001b00170018000000170017000000 -170017000000170000001900180013001800170017001800190019001800000018001700 -170000001700170000001900170017000000170017000000170018000000190017001800 -170015001a00180011001900000019001700170000001500190000001800180017000000 -19001700000019001700170017001700170000001900000017001700180018000f001800 -170018001700180018001700180017001700170018001700170017001800170017001800 -170018001800190018001a00180017001b00000018001700180000001800170019000000 -170017000000180017001700000017001700000018001700010017001700170018001700 -180019000f00170017001800170017001800170017001800180017001700170018001700 -170017001800170017001800180017001700180018001700170017001800170017001800 -180017001700180018001700180018001700170018001a00170017001900000019001900 -1700000017001700000018001700170000001900170000001700170000001b0017000000 -170017001800000017001700000018001700170001001900150017001900140019001900 -0f0017001700180017001800170017001800180018001700180017001700170018001700 -170017001800170017001700180017001700180018001700170018001800170017001700 -1700180018001700170018001a0018001700180018001700000019001700190019000000 -170017001700190000001700170000001700170017001700000017001900000019001700 -18001700170017001800150019001700140018000c001900170018001800180018001700 -170017001700180018001700170018001700170017001800180017001700180018001700 -1700180018001700170018001800170018001700170018001a0017001800170000001900 -170018001800180017001700000019001700170019001800000018001800010017001700 -170017001700170000001700180019001700000017001700000017001900170017001b00 -17001700190015001900150019000f001800140017001800170018001800180017001700 -180017001700170018001700170017001800180017001700170017001700180017001800 -170018001800180017001700180017001700180018001700170018001700170018001700 -170018001a0018001700170000001800170017000000170017001900000017001a001500 -170018001800100018001800170017001800180018001800170018001800180017001700 -170017001700180017001700170018001700170018001800180017001800170017001700 -1700170017001800180018001700170017001700000017001c0017000600000000001a00 -170017001700000017001700180018001700170017001800170018001a00170017001700 -000017001700000000001700170000001700170000001900170000001900190017001900 -170017001500190017000000000018001700000017001900000018001500180000001700 -000018001700150019000000170017001700190017001700190017000000000017001800 -000019001700000019001700190000001700190000001700190015000000170017000100 -1700170000001900180018000f0018001700180017001800170018001700180017001800 -17001800180018001700180017001800170017001700180017001a001700190019000000 -170019001700000000001700170000001700190000001900150018000000170000001900 -17001b00150000001800180017001800170018000c001700190017001800170017001800 -170017001700180018001700170018001800170017001800170017001700180017001700 -170018001800170017001800170017001700180017001800170017001700170017001800 -18001a00190017001700000000001700170000001700180000001b001700000000001700 -170000001900170000001800170000001800150018000000190017000000170017001700 -000017001800170015001800170018000c00140019001700180017001700180018001800 -140017001700180018001700170018001800170017001800180017001700180017001700 -170018001700170017001800180017001700170018001700170018001a00180017001800 -180018000000190017001700150001001b00180019001700000017001800000017001800 -180017000000180017000000170019001700180017001800190018001900150019001900 -0c0018001700170017001800180018001800170018001700170017001800170017001800 -180017001700170018001700170017001800170017001700180017001700170017001700 -170018001a00170018001700000019001700180017001700190017000000180018001700 -18001700000018001800000018001b001800180017001700000018001700180018000000 -170018000000190017001800180013001800170015001a001800150018000c0017001900 -170018001700170017001700180017001800170018001700180017001800170017001700 -180017001800180017001700170018001700170017001700180017001700180017001700 -17001800170017001700170017001700180018001a001800170019000000180015001800 -000017001800180000001700170017001900170018000c00180018001800170018001800 -170017001700170017001800180018001700180017001800170018001700180017001800 -1700170017001700180017001700170017001700180017001700170017001b0017001700 -00001c00170017000600000000001a001b001c0017000000170017001800170018001800 -17001700180017001a0017001b0017001700000000001700000017001800000000001900 -000017001700170000001700170017001700170018001700170000001800000000001700 -180015001700000001000000170018000000170019001800170000001800170017001700 -170015001700170000001800000001001700170019001500000001000000170000001700 -19000000000000001a00150018000000180015001a000000180017000c00190018001800 -170018001700180017001700170017001800170017001800170018001700180017001800 -1800190018001a0017001700150001001700170019000000180000000000180018001500 -17000000000001001700170000001700110017001b000000170017000000180017001700 -100018001700180018001700170018001800170017001800180017001700170018001700 -170018001800170017001800180017001700170018001700170018001800170017001800 -1800170018001800180017001700180019001a0017001800170000001900000000001a00 -170019001700000000001700000019001700000000001700000000001700170000000000 -000017001500190000001700170017000000170019001700010018001800170010001800 -180018001700170018001800170018001700180017001700180017001700170018001700 -170018001800170017001700180017001700170018001700170018001800170017001700 -18001700170017001a001800170017001700170002001700170017001a00000013001a00 -150018000000170017001800000000000000000018001700170001000000000000000000 -010017001500180000001900150018001200170018001800170018001700170018001800 -180017001700180018001700170018001700170017001800180017001700180017001700 -17001800180017001700180018001700180018001a001800180018000100170017001700 -170017001700190000001500190018001800190000001900170000000000000000000000 -1700170017000000000000000000190017001b0000000000000000000000000018001700 -180000001500190019000f00190017001700170018001800170018001700170017001700 -180017001700170018001800170018001700170017001700180017001700170018001800 -170018001700170017001800180017001700180018001700170018001800170017001700 -1a0018001800150017000000000001001700170017001700000017001700000018001800 -18000c001700180017001700180018001700180018001800170017001800180018001800 -170017001700180017001700170017001800170018001800170017001700170017001b00 -170017001800180017001700170017000000170017001c000600000000001a001c001700 -1700000017001700170017001700170018001700170017001a0017001800130017001700 -13001700000017001700170018001b001300190017001900170019001700190018001700 -170017001700170017001700180019001800190019001700150017001700190017001700 -1700170018001800190017001800170017001a0017001900000017001700170019001500 -17001a001700150017001800170017001700190017001700150019001900170018001900 -13001900180014000f001800180018001700180017001700180017001700170017001700 -170017001700180017001700170018001700170017001a00170018001a00150000001900 -170017001700170017001700180019001900180017001700170018001b0017001a001700 -170018001700190000001700170019000f00170017001800170018001700170017001800 -170017001700180018001700170018001700170017001800170017001700180018001700 -170018001700170017001800170017001700170017001700170017001800170017001a00 -19001800190013001700170019001700150018001b001700180017001800170019001800 -180018001700180019001700170015001800190019001800180019001700190017001700 -180018000000170018001900100015001700180017001800170018001700170017001800 -180017001700180018001700170018001700170017001800180017001700180018001700 -1700180017001700170018001700180018001700170018001a0018001800170018001800 -130018001700180015001a00170017001900170018001700180018001700170017001700 -180018001900150018001a0017001700180018001900170001001900190015000c001900 -170017001800170018001700180018001700170018001700170017001800170017001800 -180017001700170018001700170018001800170017001700180017001800170017001800 -1a0018001800170015001900170017001700170017001700170019001700170018001300 -190018001900150017001800170018001900170018001900170017001a00150017001800 -1800190017001b001700180017001900190000001a00180015000f001800180018001700 -170017001700170018001800180017001800170018001700170017001700170018001800 -180017001800170018001700170017001700170018001800170017001700180017001700 -170018001700170018001700170017001a00180018001900190018001700170017001800 -1900000019001700190000001700180018000c0017001800180014001800170018001800 -170018001700180018001800170017001700180017001800170018001800180017001700 -170017001700180017001700170017001800170018001700170017001700170000001c00 -1c0017000600000000001a00170017001700000017001700170017001700180017001700 -180018001a00170017001a00000017001a00170000001b0017001b001800150018001700 -190011001800000000000000000000000000000017001700170018001700170017001500 -15001900180018001700170017001a001700170017001700000000000000000000000000 -00001700000017001700170017001700170015001a001900170019001700190017001700 -1700190017001800170018001700170017001700180018000c0018001800180017001800 -180018001700170017001800170017001800180017001700180018001700170019001700 -18001a001700170017001800000017001800190019001700170018001700150015001900 -1800170017001700170017001500130019001b001700000017001900170018000c001700 -190017001700180018001700170018001800170017001700180017001700180018001700 -170018001800170017001700180017001700180018001700170018001800170017001800 -18001700180017001800170019001a0017001700170017001a0017001900170019001700 -150018001900170017001700170017001700170019001700180017001800180019001700 -150017001800130019001700190017001300000018001900150018000c00180019001700 -140018001800180017001800170017001800170017001800180017001700180018001700 -170017001800170017001800180017001700180018001700170017001700180018001700 -170018001a00170017001700170017001a00170017001700170017001700170017001700 -170019001700170019001700170019001700170017001700170017001800170017001900 -170000001700150018001800100014001800180018001700170018001800180017001800 -180017001700180018001700170018001700170017001800180017001700180017001700 -170018001800170018001700180018001a00170018001700180017001700190017001700 -180018001700180017001800190019001800170017001900170017001700190017001700 -170017001700180017001800190015001700130017001700170019001700180000001700 -170019001500120015001800170018001700180018001700170017001700170017001800 -170018001700180018001700170017001700170017001800170018001700180018001700 -17001700180017001700170018001700170017001700170018001700170017001a001800 -180015001500190018001700170017001700000017001700000018001800170018000c00 -170018001700170018001800180017001700180017001700180018001800170018001700 -180017001700170017001700170018001800170018001700170017001700170017001800 -17001700170017001700170000001700170017000600000000001a0017001c0017000000 -17001700170018001800170017001800170017001a001b00170017001700000000000000 -170017001700170017001b00170017001700190017001800170018001700170017001700 -180017001900170017001700190017001900190015001700180017001700170017001900 -170018001900170017001900170018001700190000001800170019001700170019001800 -150017001800150018001700170017001700170017001700180017001700190017001800 -180017000f00180018001800140018001700170017001800170017001700180017001700 -1800170017001700180017001700170018001a0017001900170017001900000017001700 -170019001700170019001700190018001700170019001700170017001800180017001700 -170017001700170017001700100018001700170017001700170018001700170017001800 -180017001700180017001700170018001700170017001800180017001700180017001700 -1700180017001700170018001700180017001700180017001700170017001a0019001700 -190018001500180015001900170018001900170017001800170017001700180017001800 -170018001700190017001700180019001700180018001900170019001700170019001700 -170018001800170010001900170018001800180018001700170018001800180017001800 -170017001700180017001700170018001800170017001800170017001700180017001700 -17001800180017001700170017001700170018001a001700170019001700180015001700 -180017001700180018001700180017001700180018001700170017001700170017001700 -1700190017001700170018001700170017001a0015001800180019000c00180018001700 -170018001700170017001400180017001700170018001700170017001800170017001800 -18001700170017001800170017001800180017001700170017001700180018001a001700 -180017001700190017001700170017001700170017001700180017001700170015001900 -170018001700190018001700170017001800170018001500180017001700190017001b00 -180018001700170017001800180017001800180018000c00180019001700180017001700 -180017001800170018001800170017001700180017001700180017001800170018001800 -170017001700180017001700180017001800170017001800180017001700180018001700 -1700180018001700170017001a0018001900170019001800170017001900170000001800 -17001900170017001700170018000d001700170018001700180017001800170018001700 -170017001800180017001700180017001700170018001800170018001700180017001700 -18001700170017001700180017001800170017001700170017001700000017001c001700 -0600000000001a0017001700170000001700180017001800180017001800170018001700 -1a0017001700180018001800170018001800170017001800170017001700170018001800 -170017001700170017001800180018001800180018001700170017001800180018001700 -180018001800170017001700170017001800180018001700180018001800180018001700 -170018001700180018001700180018001800170017001700170017001800180018001700 -18001800180018001800170017001700170017000f001700180017001800190018001700 -180017001800170018001800180017001800170018001700180018001800170017001a00 -170018001700180017001800170017001800180018001800170018001700170018001800 -180018001800170017001800170017001700180017001700180017000f00180017001800 -180018001800170018001700180017001800180018001700180017001800170017001800 -170017001800170019001700170017001700180017001800170018001800180018001700 -180017001800170017001a00190017001900170017001700170017001800170018001800 -170018001700180017001700170018001800180017001800180017001800180018001800 -1700180018001700180018001800180017001700180017000f0018001700180018001700 -180017001800170018001800180018001700180017001800170018001800170018001700 -170017001900170017001700170017001800170018001700180019001500190017001700 -1a0017001800180018001800180017001700170018001800180017001800180018001700 -170017001700170018001800180017001800180018001800180017001700170018001800 -150019001800180010001700180018001800170018001700180017001800180017001800 -180017001800170018001700180018001800170017001800180018001800170018001700 -1800170017001700190017001a0018001700180017001700180018001800170017001700 -180018001800180018001700170017001800180017001800170018001700170017001800 -180018001800180017001700170017001800170017001800180017001900170017001700 -17000f001700180017001700170018001800170018001700170017001700170019001700 -170018001800180018001700180017001800170018001800170018001800170018001700 -180017001800170018001700180018001700180017001900170017001a00170018001700 -1700170018001800180018001700170017001700180018001800180018000c0018001700 -190018001700170018001800180017001800170018001700180018001700180018001700 -180017001800180017001800170018001700180018001800170017001800180015001800 -18001800170017000000170017001c000e00000000001a001c001c001700000018001800 -180018001700180017001800170018001a00180017001800170017001700190017001800 -170017001800180018001800180018001700180017001800180017001800180018001800 -170017001800170018001700180018001800180018001800170017001800170018001700 -180018001800180018001800170017001700170018001700180018001800180018001800 -170017001800170018001700180018001800180018001800170017001800170017001700 -0f0017001900170017001700170017001700170017001700170017001700170017001700 -17001700170017001700170018001a001700190017001700170017001700170018001800 -180018001700170017001800180018001700180017001800170017001800180017001800 -17001700180017000f001800170018001700170017001700170017001700170017001700 -170017001700170017001700170018001800190017001700170018001700170017001700 -17001700170017001700170017001700170017001700170017001a001700170018001700 -180018001800180017001800170017001700180018001800170018001700180018001800 -180017001700170017001800180018001800170017001700180018001800180017001700 -180017000f00180017001800170017001700170017001700170017001700170017001700 -170017001700170017001700170018001900170018001700170017001700170017001700 -170017001700170017001900170017001a00170018001800180018001700170018001700 -180017001800180018001800180018001700170018001700180017001800180018001800 -180018001700170018001700150018001800190018001800100015001700170017001700 -170017001700170017001700170017001700170017001700180017001800180017001800 -170019001700170017001700170017001700170019001800170017001a00180017001700 -180018001800180017001700170017001800180018001800170017001800170018001800 -170017001800180017001800170018001800180017001800180018001800180017001800 -1800170017001700170018001800190018000f0017001700170017001700170017001700 -170017001800190017001800170017001900170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -17001800170018001a001800180017001800170018001800180018001800180017001700 -180018001800180019001000180015001800180018001900170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170018001800170017001800170018001800180017001700000017001c0017000e000000 -00001a001c0017001700000018001700180017001700170018001700180017001a001800 -180018001700180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001700180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001700170018000f00180017001700170019001700180017001800 -1700180018001800170018001700180017001800180018001800180018001a0017001700 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001900170018001700120017001700170018001700 -180017001700180018001700180018001800180018001700180017001700170017001800 -170017001700180017001800170018001700180018001700180018001800180018001700 -1800170019001a0017001700180017001900180018001800180018001800180018001800 -180018001800180018001800180018001800180017001800180018001800180018001800 -170018001800180018001800190017001800170012001700170017001700180017001800 -170018001800180017001800170018001700180018001700180019001700170017001700 -17001700170018001800170018001800180018001900180017001700170018001a001800 -180018001800180018001800180017001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180017001800190018001900 -150015001200180018001800180018001800170018001700180017001700180018001800 -180018001700170018001700170019001700170018001800180018001800170018001700 -17001700170017001a001800180018001800180018001800180018001800180018001800 -180018001800180018001700180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800170018001700170017001000 -170017001700180018001700180018001800180017001700170019001500170019001700 -180018001800180018001700180017001800170017001800180018001800180017001800 -1700180017001800180018001800180017001700170018001a0018001800180017001800 -180018001800180018001800180018001800180018001800150012001900170018001700 -170015001800180018001800180017001800170018001700170018001800180018001800 -170018001700180017001800180017001400170019001700140018001800180017001800 -1700170000001c00170017000e00000000001a0017001700170000001700170018001800 -17001700170018001700180012000f000f000f000f0010000f000f000f000f000f000f00 -0f000f000f0010000f000f000f000f000f000f000f000f000f000f000f0010000f000f00 -0f000f000f000f000f000f000f000f000f0010000f000f000f000f000f000f000f000f00 -0f000f000f0010000f000f000f000f000f000f000f000f000f000f000f0010000f000f00 -0f000f000f000f000f000f000f000f000f0010000f000f000f000f000c00120009001900 -190017001800190017001700170017001700170018001800170017001700170017001700 -1800180019001700150011000f000f0010000f000f000f000f000f000f000f000f001000 -0f000f000f000f000f000f000f0010000f000f000f000f000f000f000f0010000f000c00 -0f0012000f00170018001900170017001700170017001700170017001700170017001800 -170017001700170019001700170019001800170019001900170017001700170017001700 -1700170017001700170018001700170017001700110011000f000f000f000f0010000f00 -0f000f000f000f000f000f000f000f000f000f000f0010000f000f000f000f000f000f00 -0f000f000f000f00100010000f000f000f000f000f000f000f0010000f000c000f001200 -0f0017001800190017001700170017001700170018001800170017001700170017001700 -170017001300190017001900180017001800190017001700170017001700170017001800 -17001800190019001800170012000c000f000f000f0010000f000f000f000f000f000f00 -0f000f000f000f000f0010000f000f000f000f000f000f000f000f000f000f000f001000 -0f000f000f000f000c000f000c000c000f0010000f001700170017001700180017001700 -170017001700170017001700170017001700180017001800190015001700190017001700 -17001700170018001700170017001700170017001700170012000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f0010000f000f000f000f000f000f000f000f00 -0f000f000f0010000f000f000f000f000f000f000f000f000f000f000f0010000f000f00 -0f000f000f000f000f000f0012000f001800190017001700170017001700170017001800 -170018001700190018001700170017001700170017001800170017001700170017001700 -170017001700170017001800170017001700170017001700180018001700180019001800 -1800170012000f000f000f000f000f000f000f000f0010000f000f000f000f000f000f00 -0f00100012000c0017001700180019001800180017001700170018001700170017001700 -170017001700170017001700170018001700170017001700170017001700170019001500 -190018001700180018001700170017001700170000001c001c001c001d00000000001a00 -170017001700000017001700170017001800170018001700180017001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a0012001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001100 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a0012001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a0019001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a0011001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a0011001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a0011001700180018001800180018001700180017001700 -000017001c0017000600000000001a0017001c0017000000170017001800180017001700 -17001700170018001a001800190018001700180018001900180018001800190018001800 -190018001900180018001800180018001800190018001800190018001900180018001700 -180018001800180018001900180018001900180018001800180018001800180018001800 -190018001900180018001700180018001800180018001900180018001900180018001800 -180018001800180018001800190018001900180018001700170017000f001a0019001900 -180017001700170017001800170017001800170017001700170018001700170018001700 -180018001900190018001800180017001800180018001900180018001900180018001800 -180019001800180019001800180018001800190018001800190018001800180018001800 -170018001900170018001700170017001700170018001800170017001800170018001700 -170017001700190018001700180009001a00180018001700170017001700170018001800 -170017001800170018001700170017001900180017001800190019001900180019001800 -180018001800180018001900180018001900180019001800180017001800180018001900 -180018001800180018001800180019001800180019001800180018001800180017001800 -190017001700170017001800170017001800170018001700170017001700170018001800 -0c001a001900180018001900180017001700180017001700180018001700170018001800 -190018001900190017001700180018001900180019001800180018001800180018001800 -18001900180018001900180018001800180018001800180018001800190018001b001800 -180018001700170017001700190018001700190017001700180017001800170017001700 -170017001700170018001800170017001800170017000f001a0018001900180017001700 -180017001800170017001700170017001700180017001800180018001900180018001800 -180018001800190018001800190018001900180018001800180018001800180018001900 -180018001900180018001800180018001800190018001800190018001900180018001800 -170018001700180019001800190017001700180017001700180018001700170019001700 -180017001900180009001a00170017001800170018001700170017001700170017001700 -180018001700170017001700170018001700170018001700180018001900180019001900 -17001700180018001800190018001800190018001800180018001900180018001b001800 -170017001800170017001800190019001700170018001700180017001700170017001700 -1700170018001800170017001800170017001700170017001800180019000c0015001800 -180017001800180017001800180015000000170017001c000600000000001a0017001c00 -1700000017001800170018001700180017001800170018001a0018001700170017001700 -170018001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170018001700 -170017001700170018001700170017001700170017001700170017001700170017001700 -170017001700170018001700170017001700170018001700170017001700170017001700 -170017001800180012001a00170017001700170018001800180018001700180018001800 -180018001800180017001800180018001700170017001700170018001700190017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700180018001700180018001800180018001800180018001800 -1800180018001800180018001800180018001800170017001700170019000f001a001700 -180018001800180018001800180018001800180018001800180018001800180018001700 -180017001700180017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170018001800180018001800170018001800180018001800180018001800 -180018001800180018001800180018000f001a0017001700170017001700170018001800 -180018001800180018001800170017001700170017001700180018001700170017001700 -170017001700170017001700170017001700170017001700180017001700170017001700 -180017001700170017001700170017001700170019001900180017001700170017001700 -180018001800180018001800180018001800180018001800180018001800180017001700 -180010001a00180017001700180018001800180018001800180018001800180017001700 -180018001800170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001900170017001700170017001800170018001800 -1800180018001800180018001800170017001700170018000f001a001800180018001800 -180018001800180018001800180018001800180018001800180018001800180017001800 -180017001700170017001700170017001800180017001700170017001700170017001700 -170017001700170017001700170017001800170019001800170017001700170018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180019000c00180018001700140018001800170018001700170000001c00 -170017000600000000001a00170017001700000017001700180018001700180017001800 -170017001a00180017001800180018001700180018001800180018001800170017001700 -180018001800180018001800180018001800180018001800180018001700170018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001700170018001800180018001800180018001800180018001800180018001800 -1800180018001800180018001800180017001700180017000f001a001800180018001800 -170017001700180017001700170017001700170017001800170017001700170018001800 -170018001700170017001700180018001800180018001800180018001800180018001800 -180018001700170018001800180018001800180018001800180018001800180018001700 -180017001700180017001700170017001700170017001700170017001700180017001700 -170017001800170017000f001a0018001700180017001700170017001700170017001700 -170017001700180017001700170018001900170017001800170018001800180018001800 -180018001800180018001800180018001800180017001700180018001800180018001800 -180018001800180018001800180017001700170018001800180018001800170018001700 -17001700170018001700170017001700170018001700170017001700170017000f001a00 -170017001900190017001700170017001700170018001700170017001800180017001900 -170017001800170018001800180018001800180017001700180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180017001700 -170017001700180018001700180017001700170017001700170018001700170018001700 -1700170018001700170017001800180017000f001a001700170019001700170017001700 -170018001700170017001800190017001900170018001800180018001800180018001800 -180018001800180018001800180018001800170018001800180018001800180018001800 -180018001800180017001800180018001800180018001800180018001800180017001700 -170019001700170018001800170017001700170018001700170017001700170017001900 -1700170012001a0017001700170017001700180017001700180017001700170018001700 -170017001700170017001800170017001700170017001800170019001700170018001700 -180018001800180018001800180018001800180018001800180017001700170018001700 -170018001700180017001800170017001700170017001800170017001800170017001700 -18001700170017001700180017001700170017001700170018000c001900180015001700 -1900170017001800170017000000170017001c000600000000001a001b001c0017000000 -17001700170018001800180017001700180017001a0019001b0017001700180017001700 -170017001700190017001700170017001700180018001700170017001700170018001700 -1700170017001700180017001800170017001b00170017001b001700180017001b001700 -180017001900170019001700180017001700170017001700170017001800170017001700 -1b00170017001900170017001700170017001700170015001b0017001700170019001700 -180017000f001a0017001800180018001700170018001700170018001800170017001800 -180017001700170018001700170017001800180017001800170018001700190017001700 -18001900170017001b0013001b0017001700170018001700170018001700170017001700 -180017001700180017001700170018001700170018001700180017001800170018001800 -17001700180017001800170018001800170017001800170018000f001a00180018001700 -170018001700170018001700170018001700170017001800180017001800180015001700 -18001700190017001900170017001700170017001700170017001b001700170019001700 -17001b001800170017001700170018001800170017001700170017001800170017001800 -180018001800170018001800170017001800170017001700180017001700170018001700 -1800170018001700180018000f001a001700180018001700170018001800170017001700 -180017001700170018001700170018001700170018001700170017001800170017001700 -170017001700170017001700170017001700180017001800170017001700170017001700 -17001900170017001b001700180017001700170018001700170017001800180017001700 -180017001700170018001800180017001700180018001700170018001800170018000f00 -1a0018001700180018001700170018001700170017001800180017001700180018001700 -17001700180017001900170017001b0017001700170017001b0017001700180017001700 -1b00130018001b0017001700170018001700170017001700170017001b00170018001700 -170017001700180019001700170017001700180017001800170017001800170017001800 -18001700170018001700170018001700170017000f001a00170018001700170017001800 -170017001700180018001700180017001700170017001800180017001700170018001700 -170018001700170018001700170017001700180017001700170017001700170017001700 -170017001800170017001700180017001800170017001800170017001700180017001700 -170018001700170018001700170017001800170017001700180017001700180017001700 -1800170018000c0018001800180018001800180017001b001700170000001c0017001c00 -0600000000001a001c001700170000001700170018001800170018001700170017001700 -1a0017001700170018001800170019001700170013001b001b0017001900170019001700 -170019001500190015001900170017001b0017001700170017001b001700190018001500 -170017001500190017001700170017001800170017001700150017001700180018001700 -1a00170017001b0017001800190015001800170017001900170017001700170017001700 -170017001700170018001500170017001800170010001a00170018001700170018001700 -170018001700170017001800170017001700180018001700170018001800170017001700 -170017001700180018001900170017001b0011001700190013001a001700170017001500 -190017001800170018001700170018001700170017001800170018001700170018001700 -170018001800170017001700170017001700180018001700170017001700170017001800 -1800180018000f001a001800170018001700180017001800180017001800170017001800 -180017001700170017001900190019001500190017001700170017001500190017001700 -18001700170017001b001700180017001700170019001800190017001700170017001800 -17001b0017001b0017001700170017001800170017001700170017001700180017001800 -180017001700180018001700170018001800170017001700170017000f001a0017001800 -180017001700180017001700180018001700170018001800170018001700180017001800 -18001700170017001700190017001b0017001700170017001700170015001a0017001700 -180019001700170017001700190018001b0011001b001900170017001700190017001700 -180017001800170017001700180017001800170018001700170017001700170018001700 -17001700180017001800170018000f001a00180017001800170017001800170017001800 -180017001700170018001700170018001700170019001700180017001700170017001b00 -1700170015001700170017001b0017001900170018001700170017001700190018001900 -170018001700170018001700170018001800170018001700180018001800180017001700 -170017001700170017001700180017001700170018001700170018001800170017001700 -10001a001700180017001800170017001800170017001700170017001800180017001700 -170017001700180018001700170018001800170018001700170018001800170018001800 -1700170017001b0017001700170017001800170017001800190017001700180017001800 -180017001700180018001700170018001800170017001800170017001800180017001700 -180018001700180017001800170018001800170018001000180018001800170018001800 -1700170017001700000017001c0017000600000000001a00170017001700000017001700 -180017001800170017001700180018001a00190019001700170017001700130017001700 -1a000000110017000000170017001700170017001b0017001b0017001700180017000000 -17001700170017001800170017001700180017001b001700170017001800180017001700 -1700170018001b0019001100180017001500180017001800170017001a00170017001700 -1b0015001a0011001900170017001b00170018001700000017001b0017001b0018001700 -0f001a001700180017001700180017001700180018001700170017001800170017001700 -180017001700180017001800170018001800180017001700180013000000190000001800 -1800170017001700170017001a0017001300170018001700170019001900170017001800 -170017001800170018001800170017001700170017001700170018001800170017001700 -170017001700180018001700170018001700170018000f001a0018001800180017001700 -170017001700170018001700170018001700170017001800170017001700170018001700 -000019001900150019001800170017001b00170018001700170017000000190013000200 -15001900150019001b001700190017001700170017001700170017001b00170017001700 -180018001800170018001700170017001800170017001700180017001700170017001700 -17001800180017000f001a00170018001800170017001700180017001800170018001700 -180017001800180017001700170017001700170017000000000000000000000000000000 -170000000000000002000000180017001700000019001700170018000000170017000000 -000000000000000000001700170017001700180017001800170018001700170017001800 -1700180017001800170018001800170017001800180017001800170018000f001a001800 -170018001700180018001700170018001700170017001800180017001700180017001700 -170019001100170001000000000000000100000000001700000000000000000000001900 -170017000000190017001300170000001900170000000000000000000000000019001700 -170018001700180017001700180017001800170018001800170018001800170017001800 -1800170017001700180018001800170010001a0017001700180017001800180017001700 -180017001700180017001800170017001800170017001700180017001700180017001800 -170018001700170018001700150019001700170000000000000017001b00000018001b00 -170017001700170018001700180017001800170017001800180017001700180018001700 -170018001800170018001700180017001800170018001800170017001700170017001700 -18000c0018001800180017001800180017001700170017000000170017001c0006000000 -00001a0017001c001700000018001800180017001700170018001700170017001a001700 -15001a0011001b001900180018001700170000001b001900000019001700170017001700 -1700170015001b0017001700170000001700180017001800170018001700170017001700 -17001700170017001700150017001700170018001700170017001b001b00180017001b00 -170017001b00130018001700170017001800170017001900170017001700170018001700 -190000001700190017001500170017000f001a0017001800170017001700180017001700 -170018001800170017001800180017001700180017001700170018001700170017001700 -18001700170000001700180000001700170019001800170017001700170018001b001700 -170018001800170017001800180017001800170017001700170017001700180018001800 -170018001700180017001700180018001700180017001800170017001700180018001700 -18000f001a00170017001700170018001800180017001800170017001800170017001800 -180017001700190017001900180017000000170015001b00170017001b00170017001700 -170017001800170000001700170000001900170018001700170017001700170017001700 -170017001700180015001900170018001700170017001700180017001800170017001800 -1800170017001800180018001700180017001800170017000f001a001700180018001800 -170018001800170017001700180017001700170017001700170018001800180017001800 -17001b001700170000001900170018001700000017001700170017000000170017000000 -170019001b00170000001700180000001900150018001700170017001800180017001700 -170018001700170018001800170017001700180017001700180017001700170018001700 -170017001800170018000f001a0018001700180018001700170017001800170017001800 -1800170017001700180017001800170018001700180017001b0013001700010017001500 -1b0018000000170017001b0018000000170018000000170017001b001700000017001800 -000019001700170017001900170019001700190015001800170018001700170018001700 -170018001800170017001700180017001700170018001800180017001700180010001a00 -180017001700170017001700170018001800170017001800170017001700180017001800 -180017001700180017001700180017001800170018001700170018001900170019000100 -170018001700000017001700000018001900170017001700170018001700180017001700 -180017001700170018001700170017001800170018001700170017001800170017001700 -1700170017001800180018001700180018000c0018001800180017001800160018001700 -1700170000001c0017001c000600000000001a0017001700170000001700170018001700 -1700170017001700170017001a0017001700170019000000000017000000170000000000 -00001800000017001700000017001b001700170017001700180017001b00000017000000 -00001b0017001500170000000000000017001b000000170017001a001700000019001300 -1b001c001800170017001100000017000000000019001700170017000000000000001700 -1b0017001700000000000000170017001700000017001c00000018001800180010001a00 -170018001700170017001700180017001700180018001700170018001800170017001700 -18001700180017001800180017001800170018001b000000170017000000170000000000 -170017001700170000000000000017001900000018001700170018000000180017001700 -180018001800170017001700170017001700180017001700170018001700170017001800 -1700170017001800170018001700170018000f001a001800180017001700170017001700 -180017001700180017001700170018001800170017001700190017001700170000001900 -0000000017001b0013000000170017001b00000017000000000000000000000000001700 -170000000000000017001700170000001b00000000001700190015001700170018001700 -180018001700170018001700170017001700170017001700170017001700180017001700 -170018000f001a0017001800180018001700180017001700180017001800170018001800 -180017001700170017001700180017001700170017001b00000017001700170017000000 -190017001700170000001b00170000001700170017001700000017001700000017001b00 -170019001700170017001800170018001700180017001800170018001700180017001800 -17001800170017001700180018001700170018001800170018000f001a00180017001800 -180017001700180018001700170018001700170017001800180017001800180017001700 -18001700170017001800000017001b001700170000001b0017001700180000001b001700 -0000170017001700190000001a0011000000170017001b00170017001800170019001700 -190017001700170018001700180017001700170017001700170018001800170017001800 -1700170018001800170017000f001a001700170018001800180017001700170017001700 -170018001800170017001700170018001800170017001700180017001700180017001800 -17001700170017001800170017000000170017001700000017001b000000170011001b00 -1c0017001800170018001700170018001800170017001800180017001700180018001700 -170017001800170018001700180018001800170017001700170017001800170018000c00 -180018001800170018001800180018001700170000001700170017000e00000000001a00 -1c001c0017000000170017001800180017001700180017001b0017001a00170017001700 -00001900170000000000170017000000170017000000170000001b001700170017001700 -17001700170017001700000000001700180000001b001800000018001100170000001800 -17000000170017000000170017001b00170017001800170017001a000000000018001700 -00001b00170000001c0017001900000017001800000017001b0017000000170017000000 -1b00000017001800180018000f001a001700180017001700180017001700180017001700 -170018001700170017001800180017001700180017001700170017001800170018001700 -00001700170017000000000018001b000000170018000000170017001900000017001900 -000018001800000019001700180017001700170017001700170017001700180017001800 -170018001700180017001800170018001700180017001800170018001800180018000f00 -1a0018001700170018001800170018001800170018001700170018001800170017001800 -180019001700170018001900000000001700170000001700190000001700170017000000 -1b0017000000170018000000170017000000170017001700000017001b00000000001700 -170000001700190018001800170017001700170017001800170018001800170018001800 -17001700170018001700180017001800170018000f001a00170018001800180017001800 -170018001800170017001700170017001700170018001800170018001800170018001700 -170017000000170017001b00170000001700170017001900000017001700000017001b00 -1b0017000000170017000000170017001700170017001b00170017001700180017001700 -170018001700170017001800170017001700180017001800180017001700170018001700 -1800170018000f001a001900170018001700170018001700170017001800170017001800 -1800170017001800170017001700170017001b00170017001b0000001700170017001700 -00001b001700170017000000170017000000170017001b00170000001700170000001700 -180017001700180017001800170017001800170018001700180017001700170018001700 -1700180018001700170017001800170018001800170017001700170010001a0018001700 -170017001700170018001800170018001700170017001800180017001700170017001800 -18001700170018001800170018001700170017001700170017001b001700000017001700 -170000001700170018000000190017000000170017001800170017001800170017001700 -180017001700170018001700170017001700180018001700170017001700170017001700 -18001800170018001800170018000f001800180018001700180018001700180017001700 -00001c001c001c000600000000001a001c00170017000000170017001800180017001700 -17001800170017001a001b0017001700000017001700170000001b001700000017001700 -000000001700170017001700170017001b001c0017001b001700000017001b0013000000 -17001700000017001b0017000000170017001700000000001b0017001700170017001c00 -170017001700170000001b00170017000000170017001700190019001700000017001700 -000017001700170013001a0017000000000017001b001700180017000f001a0017001800 -170017001800170017001800180017001700170018001700170017001800170017001800 -170017001700180017001800180017000000170017001b00000017001700170000001700 -170000001b00180015000000170018001800000000001800180017001800170017001700 -170018001700170018001800170017001800180017001700180018001700170018001800 -17001700170018001700170018000f001a00170018001700180017001700170017001700 -180017001700180017001700170017001500170017001700190017000000170017001b00 -000019001700000017001b00170000001c00170000001b001700000017001b0000001700 -1b0017000000170017000100170017001800000017001700170017001700180018001700 -180017001700170018001700170018001700170018001800170017001800180017001700 -0f001a001800180018001700180018001700170017001700170018001800170018001700 -180017001700170017001700170017001700180000001700170017001700000000000200 -000000001b00170017000000170017001700170000001700190000000000000000000000 -000017001800180017001700180018001700170018001800170017001800180017001700 -170018001700170017001800180017001800170018000f001a0018001700180017001800 -180017001700180018001700170018001700170018001700180017001700170017001700 -170017001700000017001b00170017000000000000000000010013001700170000001700 -170017001700000017001b00000000000000000000000000190019001500180018001700 -170018001700170017001800170018001700180017001700170018001800170017001800 -180018001800170010001a00180017001700170017001800170017001800170018001700 -180017001700180018001700170017001800170017001800170018001700180017001800 -1700170018001700170000001700190017000000170017001b0000001700170017001700 -180017001700180017001700170018001700170017001800170017001700180017001700 -1700170017001800180017001800170018001700170017001700170018000f0017001800 -180017001800170017001700170017000000170017001c000600000000001a0017001700 -1700000017001700180018001800180018001700170017001a0017001700170000001700 -1b00170000001700170000001b0017000000000018001700170017001700170017001700 -1700170017000000170017001b0000001700180000001b00170017000000170017001700 -000000001700170017001700170017001700170017001700000017001700170000001700 -1700170000000000000000001b00170000001b0017001700170017001700000000001700 -17001700170017000f001a00170018001700170017001800170017001700180018001700 -170018001800170017001800170017001700170018001700180017001800170000001700 -170017000000170017001700000017001b00000017001800170000001800170017000000 -000017001700180017001700180018001700170017001700170017001700180017001700 -1700180017001700170018001700170017001800170017001800180018000f001a001700 -180017001700170018001800170018001700170018001700170018001800170018001700 -170018001700180000001700170018000000170017000000170017001700000017001700 -00001700170000001900130000001b00170017000000170017000000170017001b000000 -170018001700180017001800170017001800170018001700170018001700170018001800 -170017001700180017001700170018000f001a0017001800170017001700180018001800 -1700180017001800170017001800170017001700180018001700180017001b001c001700 -000017001b00170017000000170017001700000013001900170000001700170017001700 -0000170017000000180017001b0017001700170017001700180017001700170018001700 -170017001800170017001700180017001800170017001800180017001700170018001700 -18000f001a00180017001800180017001700170018001700170017001800170017001800 -180017001800180017001700170017001700170017000000170017001700170000001700 -1b00170000001b00170017000000170017001b0017000000170017000000170017001700 -170019001700170019001800170019001700170017001800170018001700180018001700 -17001800180017001700170017001800180018001700180010001a001700170018001800 -170017001800170017001700180017001800170018001800170018001800170017001800 -1700170018001700180017001800170017001700170017001b000000170018001c000000 -180017001700000017001800170017001700180018001700170018001800170017001800 -180017001700180018001700180018001700180017001800170017001800170017001700 -180018001700180018000c00170017001800170018001800170017001700170000001c00 -170017000600000000001a00170017001700000017001700170017001800180017001700 -170018001a00170017001900000018001700170000001b00170000001800170000001700 -000017001700170018001700170017001900170018000000170017001900000017001700 -000018001700170000001700170000001700170000001700180017001700180019001700 -170017000000170017001700000018001800000017001700170000001700180000001700 -1700170017001900170000001800000017001800170017000f001a001700180017001700 -170017001700170017001700170017001800170018001700170017001700170018001800 -17001700170018001700180000001b0017001700000017001800180000001b0017000000 -1b0017001700000018001800000017001700000018001700190013001800190017001700 -190017001700170017001700180017001700170017001700170018001800170017001700 -170017001800170018000f001a0017001700170017001700170017001700170017001700 -180017001700170018001700190017001700170017001700000017001700170000001700 -170000001700170017000000180017000000170019000000170018000000180017001700 -00001800170000001700170017000000170017001900150018001900150017001b001700 -17001700170017001700180017001700170017001700170018001700180017000f001a00 -170018001800170017001700170017001700170018001700180017001800170017001700 -170017001b00170018001500190017000000190017001700180000001b00170017001900 -000018001700000017001700170017000000170018000000180017001700170019001500 -180015001800170018001700170017001700170017001700180017001700170017001700 -1700170018001700180017001800180017000f001a001b00170018001700170018001700 -170017001700170017001700170017001700170018001800170018001700170018001500 -19000000170017001b001700000019001700170017000000170017000000180017001700 -170000001800170000001700170017001700170017001700170017001700170018001700 -180017001700170017001700170017001700180017001700170017001700180018001800 -1700170010001a001b001800170017001700170018001700180017001800170017001700 -17001700170017001700170018001700180017001800170017001700170017001b001700 -150019001800000017001700170000001700170017000000180017001b00170017001700 -170017001700170017001800180017001700170017001800170017001700170017001700 -18001700180017001800170017001700170017001b00170018000f001800180018001400 -1800180017001700170017000000170017001c000600000000001a001b001c0017000000 -17001700170017001800180017001700170017001a001700170017000000150019000000 -00001700170000001800170000001700180000001b001700170018001700190017001700 -18000000010017001700000017001b000000170019001900000017000000170019001700 -170000001700170017001a00130019001900170000000000180018000000170017000000 -180018001700000017001700000019001700170000001700170000001700170000001700 -180017000f001a0017001800170017001700170017001700170017001700170017001700 -170017001800170017001700170017001700170017001700180017000000170018001700 -010000001700170000001100170000001700170018000000170000001900170017001800 -000017001700190017001700180017001700170017001700180018001700170018001700 -17001800170017001700170017001800170017001800170018000f001a00170017001700 -170018001700170017001b00180017001700180017001700170018001700190017001b00 -17001700010000001b001800000017001700000018001800000000001800170000001700 -180000001b00180000001700170017000200110017000000170018001100010017001700 -170019001700170018001800170017001700170017001700180017001700170017001700 -1700170017001800170017000f001a001700180018001800170018001700170017001700 -170018001700180017001800170017001700170017001700180017001800180000001800 -180017001c00000017001800170017000000170017000000170018001800180000001700 -170001001700170018001900130019001900190019001c00190017001700180017001700 -170017001700180017001700170017001700170017001800170018001700170017000f00 -1a0017001700170018001700170018001700170017001800170017001700180017001700 -1700170015001700170017001b001b001800000017001700180018000000180018001700 -1700000017001b00000017001b0017001900000017001900000019001700190017001b00 -17001700170017001b001700170017001700170017001700170017001700170018001700 -170017001700170017001800180017001700170010001a00180017001700170017001700 -1b0017001700170017001700170017001700170017001700170017001700180017001800 -170018001700170017001700170017001900170017000000170019001700000019001700 -180000001700180017001800170017001700170018001800170017001700170017001700 -170017001700170017001700170017001700180017001800170018001700170017001700 -1700170018000f001700180017001700180017001800180017001700000017001c001700 -0600000000001a0017001c00170000001700180017001800180017001700180018001700 -1a001900190017001700000000001b000000170017000000000018000000190017001700 -000019001700180018001700180017001800000017000000000017001b00110017000000 -00000000170018000000170017001700170000001b001700170017001900130019001700 -000017000000000017001800170018000000000000001700000017001a00000000000000 -17001800170000001700170019000000180017000f001a00170018001700170017001800 -170017001700170018001700170017001800170017001700170017001700180017001700 -17001700170018000000170018001800000019000000000018001a001700170000000000 -000017001800000015001900190015000000170018000000170017001b00170018001700 -170017001800170018001700170017001700170017001700180017001700170017001800 -1800170018000f001a001800170017001700170017001700170017001700170017001700 -170017001700170017001700190017001900150000001700000000001800180017001800 -0000000017000000170017000000000017000000000017001b0000000000000017001800 -19000000170017001a000000170017001800000015001800190017001700170017001800 -180017001800170018001700170017001700170018001700170017000f001a0017001700 -170017001700170017001800170018001700170017001700170017001700170017001700 -170017001700170017001700010017001800170019000000170017001700170000001900 -170018000000000000000000170017001b00000000000000000000000000170017001900 -000018001800170019001700180017001800170017001700170017001700180017001800 -17001700170017001800170018000f001a001b0017001700170017001700170017001700 -1700170018001700170018001700170017001800170019001b0017001700170013000100 -17001700170017000100170018001700170000001b001700170000000000000000001900 -18001700000000000000000000000000170017001700000015001b001800170017001700 -170017001700170017001700170018001700170017001700170018001700180017001700 -0f001a001700170017001700170017001700170017001700170017001700170018001700 -170018001700180017001700170017001700170017001700170017001700170015001900 -1700150000000000000017001700170017000000180018000000170017001b0017001700 -170018001700180017001800170017001700180017001700170018001700180017001700 -170017001700170017001700180017001700180018000f00170017001700170018001700 -17001700170017000000170017001c000600000000001a00170017001700000017001700 -180018001700170017001700170018001a00170017001700190019001700180000001700 -170018001800170017001700190017001800180019001100180017001700170013001900 -17001700170018001b001800170017001700170017001700170017001700180017001800 -170018001900150019001800130017000000170017001b00170017001700170019001700 -1700190018001700170017001a0017001800150017001900180019001500170018001700 -0f001a0017001800170017001700170017001700170017001b0017001700170017001700 -170018001700170017001700170017001700170017001800170000001700170019001300 -170018001700170017001700170018001700170018001700190015001700190017001700 -1b0000001700180017001700180017001b00170017001700180017001700180017001700 -170017001700170017001700170018001800170018000f001a001800170017001b001700 -170017001700170017001700170017001700170018001700180019001c00180017001700 -190017001700190017001700170017001900170017001900170019001700180019001500 -1700180017001900190017001700170017001700180017001700170017001b0019000000 -180018001700170018001700170017001800170017001800170018001800170017001700 -17001800170017000f001a00170018001700170017001700180017001800170017001700 -1700170017001700170017001b0017001700170018001800170018001100180017001b00 -170017001800170017001800170017001700170019001700170019001700170017001700 -19001800170019001700170017001b000000180017001700170017001800170017001700 -1800170017001700180017001800170017001700170017001700170017000f001a001700 -170017001700170017001700170017001800170017001700180017001700170018001700 -170017001700170019001900190013001700180018001700110018001700180017001700 -1900170017001a00110019001900170015001a00170017001b0018001900170018001700 -190000001700170017001700170017001700180018001700170017001800170017001700 -170017001700170017001800170017000f001a0017001700170017001700170017001700 -170018001700170018001700170017001800170018001700170017001700170017001700 -170017001b00170017001700180017001900180018001800170018001700170000001700 -170018000000170017001700170018001700170017001800180017001700180017001700 -170017001800170018001700170017001700170017001700170017001700180017001700 -18000f00170018001800170018001700170017001700170000001c001700170006000000 -00001a001b001c001700000017001700170017001800180018001700170018001a001700 -180019000000150017001900000019001700180017001700170017001300170019000000 -0000000000000000000000001a0015001700190018001700170017001700180017001900 -170017001800190018001100180017000000000000000000000000000000180001001900 -180017001700180018001700170018001700170017001700190015001800170017001900 -190017001500170019001800180018000f001a0017001900170017001700180017001700 -170017001800170017001800170017001700180018001700180017001700170018001700 -1700170017000000170015001a0019001700170017001900190018001800170017001700 -170018001800170017001800180018000000190017001700170017001700170017001700 -170018001700170017001700180017001800170017001800170017001700180018001700 -18000f001a00180017001700170017001800180017001800170017001800180017001800 -180017001700170018001700170017001300190018001700170017001800170017001800 -1900110017001700180015001a0017001700170017001900170017001700170019001700 -170017001700170018001700000019001800170019001800180017001800170017001700 -1800170018001700180017001800170017001700180018000f001a0017001b0018001700 -170018001700170018001700170018001700170017001700170018001700170018001700 -18001700170018001a001800170018001800190017001700170017001900170018001700 -170017001800170017001700170017001700170018001700190017001900000019001500 -190015001700190017001700180017001700170018001700170017001800170017001800 -170017001700170017000f001a0018001700180017001700180018001800170017001800 -170018001800170017001800170018001900170017001700170017001700190018001700 -170017001a00170017001700170017001700170017001700170017001700170018001500 -170017001800140017001800170017000000170017001800170018001700170017001800 -180017001700170017001700180017001800170017001700180017001700170010001a00 -170017001700170018001800170018001700180017001700170018001800170017001700 -180017001700180017001700170017001700180017001700180017001900170017001700 -170017001900170017001700000017001900000017001900170017001700180018001700 -170017001700170017001800180017001700180017001700180017001700180017001700 -1700170017001800170017001800170018000f0017001700180017001800170017001700 -170017000000170017001c000600000000001a001c001700170000001700170017001800 -1800180017001800170017001a0019001700150017000100000000001700170017001700 -190017001700170018001b0017001700170017001700180015001b001700180017001700 -150019001900170019001700180013001700170017001700170017001800190017001700 -1700170018001700190018000000150017001b0017001700170017001800170019001900 -17001800170017001800180017001700190013001900170017001700180018000f001a00 -17001b001700170017001700170017001800170017001800170018001700180017001700 -170017001700180018001700170018001700170018001700000017001700170017001700 -18001700130017001900170017001700170017001800190019001700170017001b001700 -170019001700190015001800170017001700170017001700170017001800170018001700 -1700180017001800170017001800170017000f001a001700170017001700180018001700 -180017001800170017001700170017001700180017001700170017001700190017001700 -170019001700170017001800180017001700190019001700180019001500170019001700 -170017001300170017001800170017001700170017001700170017001900150017001900 -170019001500180018001700180017001800170017001700170018001700180018001700 -170017000f001a0017001800180017001700180017001700170017001700170018001700 -180018001700170017001700180017001700170017001800170015001800150017001800 -170018001700170017001700170018001b00170017001800170017001900170018001700 -150017001700170017001700170019001700190017001500180017001700170018001700 -17001800170017001700170017001700180017001800170018000f001a00190017001800 -180017001700170017001700180017001800170017001700180017001700180017001700 -170017001700170017001700170017001700180015001700180017001700170017001900 -170017001900170015001700190019001700190017001800190017001700190017001700 -170017001700180017001800170017001700170017001700170017001800180017001800 -1700180017001800170018000f001a001700170017001700180017001700170017001800 -170018001700170017001700170017001700170017001700180017001800180017001700 -170017001800170017001800170018001700170018001500180000001700150018001700 -170018001700180018001700170017001700170017001800170017001700170018001700 -170017001700170017001700180017001800180017001700180017001700180018000f00 -170018001800170018001700170017001700170000001700170017000600000000001a00 -170017001700000017001700170017001800180017001800180017001a00190017001700 -180017001800140019001700190017001700170019001700170017001800180018001700 -180017001900180017001700190017001900150017001700170018001700190019001700 -170018001700180017001700170017001700170017001700180017001900190017001700 -170017001700170017001700170017001700180017001800170017001900170017001900 -1700170018001900180017000f001a001700180017001700180017001700170018001700 -170018001700170018001700180017001700180017001700180017001700170018001700 -170017001700190013001900190017001700190017001900170019001800180018001500 -180017001700180015001900130019001700170017001300190018001700180018001700 -180017001700170017001800170017001700170018001700170017001800170017000f00 -1a0017001700170017001700170017001700180018001700170018001800170017001700 -180017001700190017001700180017001700170017001700170017001700170017001700 -170017001500190017001900170017001700170018001900180017001800170017001900 -170017001900170015001900170017001700130019001800170017001800180017001700 -18001700170018001800170018001700170017000f001a00170018001700170017001700 -170017001700180018001800170017001700170018001700170017001700180018001900 -180019001500180019001800170017001700170018001700170017001700170017001700 -170017001700170017001700170018001700180017001800170018001700170017001700 -170019001700180017001700180017001700180017001700170018001800180017001700 -1700170018000f001a001800170018001800170017001700170018001800170017001700 -170018001700170017001700170017001700170017001900180017001800180018001900 -150019001900180017001800170017001700170017001700180018001300170017001800 -170017001700170017001700130017001900170017001700180017001800170017001800 -170017001700180018001700170018001700170018001700170017000f001a0018001700 -170018001700180018001700170017001800170018001700170018001700170017001800 -180018001700170017001700180017001700170017001800180017001500190017001800 -170019001700170017001900180018001700180017001800170017001700180017001800 -180017001700170017001800180017001700170017001800180018001700170017001700 -18001700170017001700180017000f001700180018001700180018001700170017001700 -0000170017001c000600000000001a0017001c0017000000170017001700170018001800 -17001700170018001a001700170017001700170018001700170019001300170017001700 -170017001800170017001700170017001800170017001800170017001900170017001900 -180017001700170018001700170018001700180017001700180017001700170017001700 -170019001700180015001800170018001700170017001700170017001700170017001700 -170017001700170017001800180017001700190015001800180017000f001a0017001800 -170017001800170018001700170018001700170018001700170017001800170017001700 -180017001700180018001700170018001800170017001700170017001700170018001700 -180017001700170018001700170019001700170017001800190017001800170019001700 -170019001700170017001700170018001700170018001800170017001700180018001700 -17001700170018001700170018000f001a00170018001700180017001800180017001700 -170018001700170017001800180017001700180017001700170019001700170017001700 -170017001700180018001700170017001700170019001800150017001700190017001700 -170017001700180017001900170017001700180017001700180017001800170017001900 -170014001800170017001700180017001700170017001700180017001700170018001700 -0f001a001700180018001800170017001700170017001700170017001700180017001800 -170017001700180017001700150019001700170018001900150019001700180019001700 -170018001700170017001800170017001700170017001700170019001700190017001700 -170017001900150019001700170019001700170017001700170018001700180017001700 -170017001700170017001700170018001800170018000f001a0018001700180017001700 -180018001700170017001800170018001800170017001800170017001700170017001700 -170017001700170017001b00170017001800190014001800170018001700170017001700 -170018001700170017001900170017001700180017001700190017001700180017001700 -180017001700170018001700170017001700180018001700170017001800170017001800 -17001800170017000f001a00180017001700180017001700180017001800170017001700 -180017001700170017001700170017001700170017001800170018001700170017001800 -17001700170017001a0013001700190017001700180017001b0017001700180017001700 -170017001700180017001800170017001700170018001700180017001700180017001700 -1700170017001700170018001700180017001700170018001700170017000f0017001700 -18001700180017001700170017001700000017001c0017000600000000001a0017001700 -1700000017001800170018001800180017001700170018001a0019001700170017001700 -170017001700180018001700170018001800170017001700170018001700180017001700 -180017001700180017001800180017001700180017001700170018001700170017001700 -180017001800180017001800170017001700180018001700170017001800170017001700 -170018001700180017001700180017001700180017001700180017001700180018001700 -18001700170019000f001a00170018001700180018001700170018001700180018001700 -180017001800180017001800170018001700180017001800180018001700180017001800 -170017001700180017001800170017001700180017001800180017001700170017001800 -180017001700170017001800170017001700180018001700170017001700180017001800 -18001700180017001800180017001800180017001400190017001500190010001a001700 -180017001700180017001800180017001800170017001800170018001800170017001800 -170017001700180017001700170017001700180017001800180017001700170017001800 -180017001700170017001800170017001800180017001800170017001700180017001800 -170017001700170017001800180017001700180017001800170017001700180017001800 -1700170018001700180018001700180012001a0019001500190017001700180018001700 -170017001700180017001700180017001700180017001800180017001700170017001800 -180017001700170017001800170017001700180018001700170017001700180017001800 -170017001700180017001800180017001800170017001700170018001700180017001700 -180017001700180017001800180017001400180018001700170018001700180018001700 -170012001a00170018001800170017001700180017001800180017001700180017001700 -170017001700170017001700180017001700180017001700180017001700180018001700 -170017001700170017001800180017001800180017001800180014001800170018001800 -170017001700170017001800140018001800180018001700180017001800180018001800 -17001700180017001700180018001400190017001800170012001a001800180017001700 -180017001700180017001800180017001800170018001800180017001700170017001800 -170017001800170017001800170018001800170017001700170018001800170017001700 -170018001700170017001800180017001700170017001800170018001800170017001700 -170018001800170017001700180017001700170017001800170017001800170017001800 -170018001800170017000f00180017001800170019001800170017001700170000001700 -17001c000600000000001a001c001c001700000017001800180017001700180017001700 -1700170010000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f001000090012000f000f0010000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f0010000f000f001000090012000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f0009001200 -0f000f0010000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f00090012000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f0010000c00 -10001000090012000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f0012000f001800190017001400 -18001800170017001700170000001c00170017000600000000001a001c00170017000000 -170018001700170018001800180017001800170017001700140018001800180017001700 -180017001700180018001600170018001700180017001800170017001800170017001700 -170017001800180014001700180018001400170018001800180017001700170018001700 -170017001800170017001700170017001800180016001700180018001400170018001800 -170017001700170017001700170017001800170017001700170017001800180014001700 -170018001700170014001700180017001800170017001800170017001800180018001700 -140018001800170017001800180017001700170018001700180017001800180014001700 -180018001700170017001800170018001700170018001700170017001700170018001800 -160017001800180017001700180018001700170018001700180018001700170018001800 -170018001700170018001700170017001800170017001800170019001700170018001700 -170018001700170018001800170017001700170018001800140017001800180014001700 -180018001800170017001800170018001700170018001700170017001700170018001800 -160017001800180017001700180018001700170017001700170018001700170018001700 -170017001800170018001700170018001800180017001700180017001700170018001700 -170017001700170018001800180018001400180018001700170017001800180018001400 -180017001600180018001700170018001700170018001800170017001700170018001800 -160017001800180017001700180018001700180017001700180018001700170018001700 -170017001700180018001600170017001700180017001800170017001800170017001700 -170017001800180014001700180018001700180018001700170017001700180017001700 -180017001700180014001800180017001800180017001700180018001700170018001800 -140018001800170018001700170017001800180017001700170017001800170017001700 -170018001800180017001800170017001700170018001800170018001700160017001700 -170017001700180017001700170017001800180017001800170016001800170018001700 -170017001700170017001800180017001800190017001800180017001800170017001700 -170017001600180018001800170018001700170018001800180014001800170016001800 -180017001700180017001700180018001700170017001700180018001600170018001800 -170017001800180017001700180017001800180017001700180018001700170017001700 -180018001600170018001800140017001800180017001700180017001700180017001700 -180018001700130018001800180017001800180017001700170017000000170017001c00 -0600000000001a0017001700170000001700170018001800180017001700170018001700 -180018001800180018001800170018001700180018001700170017001800170018001800 -180018001800170018001800170018001800170018001800170018001800180018001800 -180018001600180018001800180018001800170018001800180018001700160018001800 -170017001800180018001800180018001800160017001700170018001800170018001800 -170018001800170018001800170018001700180019001700170017001800180018001700 -180018001700180018001800170017001800180018001700180018001800180017001800 -170018001800180018001800180018001800180018001600170017001800180018001700 -180018001800180017001600180018001700170018001800170016001800180017001800 -180017001800180018001800180018001800170018001800180016001700180018001700 -170018001700190014001800180017001800180018001800180018001700180018001700 -180018001700180018001800180018001800180016001800170018001800180018001700 -180018001800180017001600180018001700170018001800170016001800180017001800 -170017001800180018001700180018001700160018001800180018001800180018001800 -180017001800180018001800180017001800180018001800180018001800170017001800 -180017001800180018001800180018001800180018001800180017001800180018001700 -180018001800180017001600180018001700170018001800170016001800180017001800 -180018001800180018001700180018001800170018001700180018001700170017001800 -180018001800180018001800170018001800170018001800170018001800180018001700 -180018001700180017001800180019001700180017001800180018001800170018001800 -180017001800180018001800180018001800180018001800180018001800180018001800 -170018001800180018001800170018001800180018001800170018001800170018001800 -180018001800170017001800180017001800180018001800180018001800180017001800 -180017001700180018001800180018001700180018001800170018001700170018001800 -180017001800180018001800170018001700180017001800180018001800170018001800 -180018001800180018001800180018001800170018001800180017001800180018001800 -170016001800180017001700180018001700160018001800170018001800170018001800 -180018001800180018001800170016001800180017001700180018001800180018001800 -180016001800170018001800180017001800180019001900180018001800180018001700 -17001700170017000000170017001c000600000000001a00170017001700000017001700 -180018001800170017001700180017001700180018001800170017001700180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180017001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001700 -180018001800180014001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -160018001800180018001800180018001700180017001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800170018001800180018001800180018001800 -180018001800180017001700170018001700180018001700180018001800170018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180017001800180017001700 -180017001800180018001800180018001800180018001800180016001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800170017001800180017001900180018001800180018001800180018001800 -180018001800180018001800180018001800180018001700180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001700180018001800180018001800180018001800180018001800 -150018001700180017001700170017001700170017001700000017001700170006000000 -00001a0017001c0017000000170017001700170018001800180017001800170017001700 -180017001400170018001800180018001600180016001800180017001800180018001800 -180018001700170018001800180016001700180017001600180017001800170018001800 -180018001800170017001800180017001700180018001800180018001800170017001600 -180017001800180018001800180018001800170017001700180018001800180018001800 -180016001700180018001800180014001700180018001800170018001800170017001800 -180017001700180018001600170018001800180018001800180017001700170018001800 -170018001800170018001700180018001800180018001700170018001800170017001800 -180018001800180018001700170016001700170018001800180018001600180018001700 -180018001800170017001800180018001700170017001800180018001700180017001800 -180015001800180018001700180018001800170017001800180018001800160017001800 -170016001800170018001700180018001800180018001700170018001800170017001800 -180018001800180018001700170016001700170018001800180018001800160018001800 -170017001800180018001800160018001800180018001800180018001800170018001700 -180018001800180018001700180018001700180017001800170017001800180014001800 -180017001800170018001700180018001800180017001800170018001800170017001800 -180018001800180018001700170016001700170018001800180018001800160018001700 -170018001800180018001800180018001600170017001800160018001800170018001800 -180017001700180018001800180016001700180017001600180017001800170018001700 -180017001800140018001700180017001800170018001700180017001800180017001800 -180018001700170018001600170018001800180018001800170018001700170018001800 -180018001700180017001800170017001800180018001700170018001800180018001700 -170018001800180017001800180018001700170017001800180018001800170017001800 -180018001800180017001800180017001700180017001400170018001800140018001800 -180018001700180018001700170018001800180018001800160018001800180018001700 -180017001800180018001800170018001700180018001700170018001800180018001800 -180017001700160017001700180018001800180016001800180017001800180018001700 -170018001800180018001800180017001700160018001700180018001800180018001800 -170018001700180018001700170018001700170018001700170017001700170017001700 -17001c00000017001c0017000600000000001a0017001c00170000001700180018001700 -180018001700180017001700170017001800170017001800180018001800170017001700 -180018001800180018001800180018001800180018001700180018001800180018001700 -180018001800180018001800180018001800180017001800180018001800180018001800 -180018001700180017001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001700180017001700180015001800 -170017001700170017001800180018001800180018001800180018001800180018001800 -180018001800180018001700180018001800180018001800180018001800180018001800 -170018001800180018001800180018001800180017001800170018001800180018001800 -180018001800180018001800170018001800180018001800180017001800180018001800 -180018001800180017001800170018001400170018001800170018001800180018001800 -180017001800180018001800180017001800180018001800180018001800180018001800 -170018001800180018001800180018001800180017001800170018001800180018001800 -180018001800180018001800180018001800180018001800180017001800180018001800 -180018001800180018001800170017001800180018001800170018001800180018001800 -180017001800170019001700170019001400170018001800180018001800180018001800 -170018001800180018001800180018001800180017001800170018001800180018001800 -180018001800180018001800180018001800180017001800170018001800180018001800 -170018001800180018001800180018001800180018001700180018001800180018001700 -180018001800180018001800180018001800180017001700170017001800170018001800 -180017001600180018001800180018001800180017001800180018001800180018001800 -180018001800180018001700180018001800180018001800180018001800180018001800 -180018001800180018001800160017001800180017001800180018001800180018001800 -180018001800180016001700180018001700180018001800180018001800180018001800 -180017001700170017001700170018001800180018001800180018001800180018001800 -170018001700170017001800180018001800180018001800180018001700180018001800 -180018001800180018001800170018001700180018001800180018001800180018001800 -180018001700180018001800180018001800170018001800170018001700180018001800 -180018001800180018001800180018001700180018001800180018001800180019001700 -180017001800180017001700170017001700170000001700170017000600000000001a00 -170017001700000017001800170017001800180017001700170018000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f0010000f000f000f000f0010000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f001000 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f001000 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000c000f0010000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f0010000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f00100010000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f0010000c000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00 -0f000f000f000f000f000f000f000f000f000f000f000f0010000f000f000f000f000f00 -0f000f000f000f000f000f000f000f00180017001900170017001b001700170017001700 -00001c00170017000600000000001a001b001c0017000000170017001700170017001800 -17001700170017001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a0018001700 -170017001700170017001700170017000000170017001c000e00000000001a001c001700 -170000001700170017001800170018001700180018001700180018001800180017001700 -180018001800180017001800180018001800190017001700180018001800190018001800 -180018001800190017001700180018001800190018001800180018001800190017001700 -180018001800190018001800180018001700180018001800180019001700170018001800 -180019001800180018001800180019001700170018001800180019001800180018001800 -180019001700170018001800180019001800180018001800180019001700170018001800 -180019001800180018001800180019001700170018001800180019001800180018001700 -170017001800180018001b00170017001800180018001900180018001800180018001900 -170017001800180018001900180018001800180018001900170017001800180018001900 -180018001800180018001900170017001800180018001900180018001800180018001900 -170017001800180018001900180018001800180017001800180018001800190017001700 -180018001800190018001800180018001800190017001700180018001800190018001800 -180018001800190017001700180018001800190018001800180018001800190017001700 -180018001800190018001800180018001800190017001700180018001900190018001900 -180017001700180017001700180018001800180017001700180018001800180018001800 -180018001700180017001700170018001800180017001700180018001800190018001800 -180018001800190017001700180018001800190018001800180018001800190017001700 -180018001800190018001800180018001800190017001700180018001800190018001800 -180018001800190017001700180018001800190018001800180018001800190017001700 -180018001800190018001800180018001800190017001700180018001800190018001800 -180018001800190017001700180018001800190018001800180018001800190017001700 -180018001800180018001800180018001800170018001800180018001800180018001700 -180018001800180018001800180017001800180018001800180018001800170018001800 -180018001800180018001700180018001800180018001800180017001800180018001800 -180018001800170018001800180018001800180018001700170018001800180017001700 -180018001800190018001800180018001800190017001700180018001800190018001800 -180018001800190017001700180018001800190018001800180018001800190017001700 -180018001800190018001800180018001800190017001700180018001800190018001800 -180018001800190018001700170017001700170018001700170018001700170000001c00 -1c0017000e00000000001a00170017001700000017001700170018001800180018001700 -180017001700170018001700170017001700170018001800170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001800180017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700180017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170018001800 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -180018001700170018001700170017001700170018001700170017001800180018001800 -180018001800180018001800170017001800180018001800190017001700170018001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170018001800170017001800180017001700 -180018001700170018001800170017001800180017001700180018001700170018001800 -170017001800180017001700180018001700170018001800170017001800180017001700 -180018001700170018001800170017001800180017001700180018001700170018001800 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170018001800 -1700170017001700170017000000170017001c000e00000000001a0017001c0017000000 -180018001800180017001700170018001700180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001700170017001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001700 -170017001900170018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -180018001800180018001800180018001800180018001800180018001800180018001800 -1800180018001700170017001700170018001800170017001700170000001c0017001700 -1d00000000001a0017001700170000001700170018001700180018001700170017001800 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001800 -180018001800180018001800170017001800170017001700170017001700170017001700 -170017001700170018001800170017001700170019001800170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170018001800 -17001700170017000000170017001c000e00000000001a001c001c001700000017001700 -170017001700180018001800170017001700170018001800170017001800180017001700 -170018001800180018001700170018001700180017001800170018001800180018001800 -170017001800180017001700170018001800180018001700170018001700180017001800 -170018001700170017001800180018001800170017001800170018001700180017001800 -180018001800180017001700180018001700170017001800180018001800170017001800 -170018001700180017001800180018001800180017001700180018001700170017001800 -180018001800170017001800170018001700180017001800170017001700180017001800 -170017001700180017001800170018001700180018001800180018001700170018001800 -170017001700180018001800180017001700180017001800170018001700180018001800 -180018001700170018001800170017001700180018001800180017001700180017001800 -170018001700180017001700170018001800180018001700170018001700180017001800 -170018001800180018001800170017001800180017001700170018001800180018001700 -170018001700180017001700170018001800180018001800170017001800180017001700 -170018001800180018001700170017001800180017001700170018001800180018001800 -180018001800190018001800180019001800180018001800170018001800190018001900 -150017001800180018001800170017001800180017001700170018001800180018001700 -170018001700180017001800170018001800180018001800170017001800180017001700 -170018001800180018001700170018001700180017001700170018001800180018001800 -170017001800180017001700170018001800180018001700170018001700180017001800 -170018001800180018001800170017001800180017001700170018001800180018001700 -170018001700180017001800170018001800180018001800170017001800180018001800 -170017001800180017001700180018001700170018001800170017001800180017001700 -180018001700170018001800170017001800180017001700180018001700170018001800 -170017001800180017001700180018001700170018001800170017001800180017001700 -180018001700170017001800170018001700170018001800180017001800180017001700 -170018001800180018001700170018001700180017001800170018001800180018001800 -170017001800180017001700170018001800180018001700170018001700180017001800 -170018001800180018001800170017001800180017001700170018001800180018001700 -17001700170017001700180017001700170017001700170000001c00170017001d000000 -00001a001c00170017000000170017001700180017001800170017001800170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -17001700170017001700170017001700170017001700170017001700170019001a001a00 -1a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a001a00 -1a001a001a001a001a001a001a001a001200170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001800170018001800180018001700170017001800 -17001700000017001c001c001d00000000001a0017001700170000001700170017001700 -170018001700180017001800170017001800170017001700180017001700170018001700 -170017001700170018001700170018001700170017001700170017001800170017001700 -180017001700170018001700170017001700170018001700170017001700170017001800 -170017001800170017001700170017001800170017001700170017001700180017001700 -180017001700170018001700170017001800170017001700170017001800170017001800 -170017001700170017001700180017001700170018001700170017001800170017001700 -170017001800170017001700170017001700180017001700180017001700180017001700 -180017001700170017001700170018001700170018001700170017001800170017001700 -180017001700170017001700180017001700180017001700170017001700170018001700 -170017001800170017001700180017001700170017001700180017001700170017001700 -170018001700170018001700170017001700170018001700170017001700170017001800 -170017001800170017001700180017001700170018001700170017001700170018001700 -170018001700170017001800170017001800170017001700180017001700170018001700 -1700170017001700170019001a0019001900170017001700180018001b00180018001800 -18001800180018001800180019001800180018001900180017001800170019000f001700 -170017001800170017001700180017001700170018001700170017001700170018001700 -170017001700170017001800170017001800170017001700180017001700170018001700 -170017001700170018001700170018001700170017001800170017001800170017001700 -180017001700170018001700170017001700170018001700170017001700170017001800 -170017001800170017001700180017001700170018001700170017001700170018001700 -170017001700170017001800170017001800170017001700180017001700180017001700 -170017001800170017001800170017001700170018001700170018001700170017001700 -180017001700180017001700170017001800170017001800170017001700170018001700 -170018001700170017001700180017001700180017001700170017001800170017001800 -170017001800170017001800170017001700180017001700170017001700170018001700 -170017001700170018001700170017001700170017001800170017001800170017001700 -180017001700170018001700170017001700170018001700170017001700170017001800 -170017001800170017001700180017001700170018001700170017001700170017001700 -1700170017001800180018001700180017001700000017001c0017000600000000001a00 -170017001700000017001700170017001700180018001700180017001700170017001800 -170017001700180018001700170017001800180017001800180017001800180017001700 -170018001800170017001700180017001700170018001800170018001700180017001700 -180018001700180017001800170017001800180017001800170018001700170018001800 -170018001700180017001700170017001700180017001700170018001800170017001700 -180018001700180018001700180018001700170017001800180017001700170018001700 -170017001800180017001800170018001700170018001800170018001700180017001700 -180018001700180017001800170017001800180017001800170018001700170017001700 -170018001700170017001800180017001700170018001800170018001800170018001800 -170017001700180018001700170017001800170017001700180018001700180017001800 -170017001800180017001800170018001700170018001800170018001700180017001700 -180018001700180017001800170017001700170017001800170017001700180018001700 -170017001800180017001800170018001700170018001700180017001700170018001700 -170017001800170018001800170018001700180017001700170018001a00170019001500 -180018001800170017001800170018001700180017001900170018001700180017001800 -1700180018001800170017000f0017001700180018001700180017001800170018001800 -170018001700180017001700180018001700180017001800170017001700170017001800 -170017001700180018001700170017001800180017001800170018001700170018001700 -180017001700170018001700170017001800170018001800170018001700180017001700 -180018001700180017001800170017001700170017001800170017001700180018001700 -170017001800180017001800170018001700170018001700170017001700170017001800 -170017001700180017001800180017001700170018001700170017001800170017001800 -180017001700180018001700170017001800170017001700180017001700180018001700 -170018001800170017001700180017001700170018001700170018001800170017001800 -180017001700170018001700170018001700170018001700180017001700170017001800 -170017001700180018001700170017001800180017001800170018001700170018001700 -170017001700170017001800170017001700180018001800170018001700180017001700 -180018001700180017001800170017001700170017001800170017001700180018001700 -1700170018001800170018001700170017001700170017001800180017001b0017001700 -000017001b001c000600000000001a001b001c0017000000170017001700170018001800 -170018001700180018001800170017001800180017001700180017001800170017001700 -170017001700170017001700170018001700180017001700180018001700170018001800 -170017001700170017001800180017001700170017001700170018001800170017001700 -170017001700180018001700170017001700170017001800180017001800180017001700 -180018001700170018001700180017001700170017001700170017001700170017001800 -170018001700170018001800170017001800180017001700170017001700180018001700 -170017001700170017001800180017001700170017001700170018001800170017001700 -170017001700180018001700180018001700170018001800170017001800170018001700 -170017001700170017001700170017001700180017001800170017001800180017001700 -180018001700170017001700170018001800170017001700170017001700180018001700 -170017001700170017001800180017001700170017001700170018001800170018001800 -170017001800180017001700180017001800170017001700170017001700180017001800 -180017001700170018001800170017001800180017001700170017001700170017001800 -18001700170019001a001900130019001700170017001900190017001700170019001700 -180017001900170017001700180017001700170015001900190017000f00180017001700 -170017001700170017001700170017001700170017001800180017001700170017001700 -170018001800170018001800170017001800180017001700180017001800170017001700 -170017001700180017001800180017001700170018001800170017001800180017001700 -170017001700170017001800180017001700170017001700170018001800170018001800 -170017001800180017001700180017001800170017001700170017001700180018001700 -180017001800170018001800170017001800180017001700170017001700180018001700 -170018001800170017001800170017001700180017001700170018001800170017001800 -180017001700180017001700170018001700170017001800180017001700180018001700 -170018001700170017001800170017001700180018001700170018001700180017001800 -180017001700170018001800170017001800180017001700180017001800170017001700 -170017001700180018001700180017001800170018001800170017001800180017001700 -170017001700170017001800180017001700170017001700170018001800170018001800 -17001700180018001700170018001700180017001700170017001700170017001b001700 -1800170018001800170017001700170000001c001c0017000600000000001a0017001c00 -170000001700180018001800180017001800170018001700170018001700180017001800 -170018001700170018001800170018001800170017001800180017001800180017001700 -180017001800170018001700180017001700180018001700170017001700170017001800 -180017001700170017001700170018001800170017001700170017001700180018001700 -170017001700170017001800170018001700180017001800170017001800180017001800 -180017001700180018001700180018001700170018001700180017001800170018001700 -170018001800170017001700170017001700180018001700170017001700170017001800 -180017001700170017001700170018001800170017001700170017001700180017001800 -170018001700180017001700180018001700180018001700170018001800170018001800 -170017001800170018001700180017001800170017001800180017001700170017001700 -170018001800170017001700170017001700180018001700170017001700170017001800 -180017001700170017001700170018001700180017001800170018001700170018001800 -170018001800170018001700170017001700170018001800170017001700180017001700 -1700180017001800180017001700170017001700170017001a0017001800170018001700 -170017001700180017001800190017001700190017001700180017001900170017001800 -18001700170017000f001700180017001700180017001800170018001700180018001700 -170017001700170017001800180017001700170017001700170018001700180017001800 -170018001700170018001800170018001800170018001700170017001700170018001800 -170017001700180017001700170018001700180018001700170017001700170017001800 -180017001700170017001700170018001700180017001800170018001700170018001800 -170018001800170017001700170017001700170018001800170018001700180017001800 -170018001800170017001700180017001700180018001700170018001800170017001700 -180017001700170018001700170018001800170017001800180017001700170018001700 -170017001800170017001800180017001700180018001700170017001800170017001700 -180017001700180018001700170017001700170018001800170018001700180017001800 -170018001700170018001800170018001800170017001700170017001700170018001800 -170018001700180017001800170018001700180018001700170017001700170017001800 -180017001700170017001700170018001700180017001800170018001700170018001800 -170018001800170017001700170017001700180018001800170017001700170000001700 -17001c000600000000001a00170017001700000017001700180018001700170017001800 -170018001700170017001800170017001700180018001700170017001700170018001700 -170018001700170017001700170018001800170017001700180017001700170017001700 -180017001800170018001800170017001800170018001700180018001700170018001700 -180017001800180017001700180017001800170018001800170017001700180017001700 -170018001800170017001700170017001800170017001800170017001700170017001800 -180017001700170018001700170017001700170018001700180017001800180017001700 -180017001800170018001800170017001800170018001700180018001700170018001700 -180017001800180017001700170018001700170017001800180017001700170017001700 -180017001700180017001700170017001700180018001700170017001800170017001700 -170017001800170018001700180018001700170018001700180017001800180017001700 -180017001800170018001800170017001800170018001700180018001700170017001800 -170017001700180018001700170017001700170018001700170017001800180017001800 -170017001700180017001800170018001700180017001700180017001800170018001800 -190019001a00190019001700190017001800180018001700170019001300190017001800 -1900170017001700170018001800170018001700190017000f0018001800170017001800 -170017001700180017001700180017001800170018001800170017001800170018001700 -180018001700170017001800170017001700180018001700170017001700170018001700 -170017001800180017001800170017001700180017001800170018001700180017001700 -180017001800170018001800170017001800170018001700180018001700170017001800 -170017001700180018001700170017001700170018001700180017001800180018001700 -170017001700170017001800170017001700180017001800180017001700180017001700 -170018001700170017001800180017001700180018001700170018001700170017001800 -170017001700180018001700170018001800170017001800170017001700180017001700 -170018001800170017001800180017001700180017001700170017001800180017001800 -170017001700170017001800170017001700180018001700170017001700170018001700 -180017001800180018001700170017001700170017001800170017001700180017001700 -180017001800170018001800170017001800170018001700180018001700170017001800 -17001700170018001800170017001700170017001800170017001b001700170018001700 -170017001700170017001b000000170017001c000600000000001a001b001c0017000000 -170017001800170018001800170017001800170018001800170018001700180017001700 -170017001700180018001800170018001800170018001800180017001700170017001700 -180017001800170018001800180017001700170018001700170017001800170017001700 -180017001700170018001700170017001800170017001700180017001700170018001700 -170017001800180017001800170018001700170017001700170018001800180017001800 -180017001800180018001700170017001700170018001700180017001800180018001700 -170017001800170017001700180017001700170018001700170017001800170017001700 -180017001700170018001700170017001800170017001700180018001700180017001800 -170017001700170017001800180018001700180018001700180018001800170017001700 -170017001800170018001700180018001800170017001700180017001700170018001700 -170017001800170017001700180017001700170018001700170017001800170017001700 -180017001700170018001800170018001700180017001700170017001700180018001800 -170018001700180017001700170017001800170018001800170017001700180017001700 -18001700170017001800170017001700190015001a001700170017001700180000000000 -000000001800170017001700180017001700170019001700190000001700180000001800 -170017001200150017001800170017001800170017001700180017001700170018001700 -170017001800170017001700180017001700170018001800170018001700180017001700 -170017001700180018001800170018001700180017001700170017001800170018001800 -170017001700180017001700180017001700170018001700170017001800170017001700 -180017001700170018001800170018001700180017001700170017001700180018001800 -170018001700180017001700170017001700180018001800170018001700180017001700 -170018001800170017001700180017001700170018001700170018001800170017001800 -180017001700170018001700170017001800170017001800180017001700180018001700 -170017001800170017001700180017001700180018001700170018001800170017001700 -180017001700180017001700170017001800170018001800170018001700180017001700 -170017001700180018001800170018001700180017001700170017001700180018001800 -170018001700180017001700180017001700170018001700170017001800170017001700 -180017001700170018001800170018001700180017001700170017001700180018001800 -170018001700170017001700170018001700170017001700170017000000170017001700 -0600000000001a001c001700170000001700170017001700170017001800170017001700 -170017001700170017001800180017001800180017001700170017001700170017001700 -170017001700170018001800170018001800170017001700170017001800170018001700 -180017001800170018001700180017001800170018001700180017001800170018001700 -180017001800170018001700180017001800170017001700170017001700180018001700 -180018001700170017001700170017001700170017001700170017001800180017001800 -180017001700170017001700180017001800170018001700180017001800170018001700 -180017001800170018001700180017001800170018001700180017001800170018001700 -180017001700170017001700170018001800170018001800170017001700170017001700 -170017001700170017001700180018001700180018001700170017001700170018001700 -180017001800170018001700180017001800170018001700180017001800170018001700 -180017001800170018001700180017001800170018001700170017001700170017001800 -180017001800180017001700170017001700170017001800170018001800180017001700 -170017001700180017001800170018001800170018001700180017001800170017001900 -1a0018001800170017000000180019001700170000001900170018001500180017001700 -17001800170017001800170000001900190018000c001700180017001700180017001700 -180017001800170018001700180017001800170018001700180017001800170018001700 -170017001700170017001800180017001800180017001700170017001700170017001800 -170018001800180017001700170017001700180017001800170018001800170018001700 -180017001800170018001700180017001800170018001700170017001700170017001800 -180017001800180017001700170017001700170017001800180017001800180017001700 -170017001700170017001800180017001700170017001800180017001700180018001700 -170018001700170017001800170017001700180018001700170018001800170017001800 -170017001700180017001700170018001800170017001800180017001700180017001700 -170018001700170017001800180017001700180017001800170018001800180017001700 -170017001700170017001800180017001800180017001700170017001700170017001800 -180017001800180017001700170017001700170017001800180017001800170018001700 -180017001800170018001700180017001800170018001700170017001700170017001800 -180017001800180017001700170017001700170017001700170017001800170017001700 -170017001700170000001c001c0017000600000000001a00170017001700000017001700 -170017001700180017001700180018001700180018001700170017001700170017001800 -170018001700180018001700170018001800170018001700180017001700170017001700 -170018001800170017001700180018001700170018001800170017001800180017001700 -180018001700170018001800170017001800180017001700180018001700170018001800 -170018001800170017001700170017001700180017001800170018001800170017001800 -180017001800170018001700170017001700170017001800180017001700170018001800 -170017001800180017001700180018001700170018001800170017001800180017001700 -180018001700170018001800170017001800180017001800180017001700170017001700 -170018001700180017001800180017001700180018001700180017001800170017001700 -170017001700180018001700170017001800180017001700180018001700170018001800 -170017001800180017001700180018001700170018001800170017001800180017001700 -180018001700180018001700170017001700170017001800170018001700180018001700 -180017001700170017001700170018001800170018001700180017001700170017001700 -180018001700170018001800170018001a00170019001900000019001700180017001700 -190000001700180001001700170019000000150018000000170001000000000015001a00 -0c0019001800170017001800170018001700180017001700180018001700170018001800 -170017001800180017001700180018001700180018001700170017001700170017001800 -170018001700180018001700180017001700170017001700170018001800170018001700 -180017001700170017001700180018001700170018001800170017001800180017001700 -180018001700180018001700170017001700170017001800170018001700180018001700 -170017001700170017001800170018001700180018001700170017001700170018001700 -170017001800170017001800180017001700180018001700170017001800170017001700 -180017001700180018001700170018001800170017001700180017001700170018001700 -170018001800170017001800180017001700170018001700170017001800170017001800 -180017001700170017001700170018001700180018001700170017001700170017001800 -170018001700180018001700170017001700170017001800170018001700180018001700 -170017001700170017001700180018001700170018001800170017001800180017001700 -180018001700180018001700170017001700170017001800170018001700180018001700 -17001b0017001700170018001700170017001700170017000000170017001c0006000000 -00001a0017001c0017000000170017001700180018001700170018001700170017001700 -180017001800170018001800170017001700180017001700180017001700180017001700 -180017001700170018001800170018001700180017001700180017001700170018001700 -170017001800170017001700180017001700170018001700170017001800170017001700 -180017001700170018001700170017001700170018001700180017001800180017001700 -170018001700170018001700170018001700170018001700170017001800180017001800 -170018001700170018001700170017001800170017001700180017001700170018001700 -170017001800170017001700180017001700170018001700170017001800170017001700 -170017001800170018001700180018001700170017001800170017001800170017001800 -170017001800170017001700180018001700180017001800170017001800170017001700 -180017001700170018001700170017001800170017001700180017001700170018001700 -170017001800170017001700180017001700170017001700180017001800170018001800 -170017001700180017001700180017001700170018001800170018001700180017001700 -18001700170017001800180018001700170017001800170017001700170017001a001900 -170017000000170018001700170018001700000018001700000018001900170000001900 -170000001800170000001800190015000c00170017001700180017001700180017001800 -180017001700170018001700170017001800170017001700180017001700170017001700 -180017001800170018001800170017001700180017001700180017001700170018001800 -170018001700180017001700180017001700170018001800180017001700170018001700 -170017001800170017001700180017001700170017001700180017001800170018001800 -170017001700180017001700180017001800170018001800170017001700180017001700 -180017001800170018001800170018001800170017001800170017001700180017001700 -170018001800170017001800180017001700180017001700170018001700170017001800 -180017001700180018001700170018001700170017001800170017001700180018001700 -170018001800170017001800170017001700170018001800170018001700180017001700 -180017001800170018001800170017001700180017001700180017001800170018001800 -170017001700180017001700180017001800170018001800180017001700170018001700 -170017001800170017001700180017001700170017001700180017001800170018001800 -170017001700180017001700180017001700170017001700180017001b00170017001700 -1700170000001c0017001b000600000000001a001c001700170000001800170017001800 -180018001700180017001800180018001700180017001800170017001800170017001700 -180018001700180018001700180018001700170017001800170017001800170018001700 -180018001800170017001700180017001700170018001700170017001800170017001700 -170017001700180017001700170018001700170017001800170017001700180018001800 -170018001700180017001700180017001700170018001800170018001800170018001800 -170017001700180017001700180017001800170018001800180017001700170018001700 -170017001800170017001700180017001700170017001700170018001700170017001800 -170017001700180017001700170018001800180017001800170018001700170018001700 -170017001800180017001800180017001800180017001700170018001700170018001700 -180017001800180018001700170017001800170017001700180017001700170018001700 -170017001700170017001800170017001700180017001700170018001700170017001800 -180018001700180017001800170017001800170017001700180018001700180017001800 -170017001800170018001700180018001700170017001800170017001700170018001700 -1700170018001700170017001a0017001800180000001700170017001800170018000000 -170017000000170017001b00000017001b0000001700170000001800170018000c001900 -170017001700170018001800170017001700170017001800170017001700180017001700 -170018001700170017001800180018001700180017001800170017001800170017001700 -180018001700180017001800170017001800170018001700180018001700170017001800 -170017001700170018001700170017001800170017001700180017001700170018001700 -180017001700170018001800170018001700180017001700180017001700170018001700 -170017001800180017001800170018001700170018001700170017001700170018001700 -170017001800170017001800180017001700170018001700170017001800170017001800 -180017001700170018001700170017001800170017001700180017001700170018001700 -170018001800170017001700180017001700180017001700180017001800170018001800 -170017001700180017001700180017001700170018001800170018001700180017001700 -180017001700170018001700170017001800180017001800170018001700170018001700 -170017001700170017001800170017001700180017001700170018001700170017001800 -180018001700180017001800170017001800170017001700180018001700180017001700 -17001700180017001800180017001800170017000000170017001c000600000000001a00 -170017001700000017001700180018001700170018001700180017001700170017001700 -170018001800170018001700180017001700170017001700170017001700170017001800 -170018001700180018001700170017001700170017001700180018001700170018001800 -170017001800180017001700180018001800180017001700180018001700170018001800 -170017001800180017001700170017001700170017001800180017001800170018001700 -170017001700170017001700170017001700180017001800170018001800170017001700 -170017001700170018001800170017001800180017001700180018001700170018001800 -180018001700170018001800170017001800180017001700180018001700170017001700 -170017001700180018001700180017001800170017001700170017001700170017001700 -170018001700180017001800180017001700170017001700170017001800180017001700 -180018001700170018001800170017001800180018001800170017001800180017001700 -180018001700170018001800170017001700170017001700170018001800170018001700 -180017001700170017001700170018001700180018001700170017001700170017001800 -170018001700180018001800170017001800180017001700170017001a00170017001800 -000017001800170000001700170000001b00170000001700170017000000170017000000 -190019000000170017001700100017001700180018001800180017001700180018001800 -170017001800180017001700180018001700170018001800170017001700170017001700 -170018001800170018001700180017001700170017001700170018001700180018001700 -170017001700170017001800170018001700180018001800170017001800180017001700 -180018001700170018001800170017001800170018001700170017001700170017001800 -180017001800170018001700180017001800170017001700170017001700180018001700 -180017001800170018001700170018001800170017001800170017001700180018001700 -170018001800170017001800170017001700180018001700170018001800170017001800 -180017001700180018001700170018001700170017001800180017001700180017001800 -170018001800170017001700170017001700180017001800170018001800170018001700 -170017001700170017001800180017001800170018001700180017001800170017001700 -170017001700180018001700180017001800170018001800170017001800180017001700 -180018001700170018001800170017001700170017001700170018001800170018001700 -18001700170017001700170017001b001700170017001800170017001700180017001700 -00001c001c0017000600000000001a0017001c0017000000170017001800170017001700 -170018001700180017001800180017001700170017001700170017001800180017001800 -180017001700180018001700180018001700170017001700170017001700180018001700 -180017001800170018001700180017001800170018001700180017001800170017001800 -170018001700180017001800170018001700180017001800170018001700180018001700 -170017001700170017001700180018001700180018001700170018001800170018001800 -170017001700170017001700170018001800170018001700180017001800170018001700 -180017001800170018001700180017001700180017001800170018001700180017001800 -170018001700180017001800170018001800170017001700170017001700170018001800 -170018001800170017001800180017001800180017001700170017001700170017001800 -180017001800170018001700180017001800170018001700180017001800170018001700 -170018001700180017001800170018001700180017001800170018001700180017001800 -180017001700170017001700170017001800180017001800180017001800170017001700 -170017001800180018001700180017001800170017001700170017001700180017001700 -17001800190017001a0017001a0017000000180017001700170000001b00000017001700 -0000170017001b0000001700180000001500180000001700190015000f00170018001700 -140018001800180017001700170018001700180017001800170018001700180017001800 -170018001700180017001800180017001700170017001700170017001800180017001800 -180017001800170017001700170017001800180018001700180017001800170017001700 -170017001700180017001700170018001700170017001800170017001700180017001700 -180018001700180018001700170017001700170017001700180018001700170018001800 -170018001800170017001700170017001700170018001800180017001700180018001700 -170018001800170017001700180017001700180018001700170018001800170017001700 -180017001700180018001700170018001800170017001800180017001700180018001700 -170017001800170017001800180017001700170017001700180018001800170018001700 -180017001700170017001700180018001700180018001700170017001700170017001700 -180018001700170018001800170018001800170017001700170017001700170018001800 -170018001700180017001800170018001700180017001800170018001700180017001800 -180017001700170017001700170017001800180017001800180017001700170017001700 -180017001800180017001700170017000000170017001c000600000000001a001c001700 -170000001700170018001800170017001800170018001700170017001800170018001700 -180018001800170017001700170017001800170017001800170017001700170017001800 -180018001700180017001800170017001800170017001700180017001700170018001700 -170017001800170017001700170017001700180017001700170018001700170017001800 -170017001700180017001700180017001800170018001800180017001700170017001700 -180017001700180017001700170017001700180018001800170018001700180017001700 -180017001700170018001700170017001800170017001700180017001700170017001700 -170018001700170017001800170017001700180017001700170018001700170018001700 -180017001800180018001700170017001700170018001700170018001700170017001700 -170018001800180017001800170018001700170018001700170017001800170017001700 -180017001700170018001700170017001700170017001800170017001700180017001700 -170018001700170017001800170017001800170018001700180018001800170017001700 -170017001800170017001700180018001700180017001700170017001800170017001700 -1800180017001800170018001700180017001800170017001a0018001300170017000000 -170017001b001700000017001b0017000000170017000000000017001700000019001900 -00001900170019000c001700180018001800170017001800180018001700170017001800 -170017001700180017001700170018001700170017001800170017001800170018001700 -180018001800170017001700170017001800170017001700180018001700180017001700 -170017001800170017001700180018001700180017001800170018001700180017001800 -170018001700180017001800180017001700170017001700180017001800170018001800 -180017001700170018001700170017001700170018001700180017001800180018001700 -170017001700180017001700170018001700170017001800180017001700180017001700 -170018001700170017001800180017001700180017001700170018001700170017001800 -170017001700180017001700170018001800170017001800170017001700170018001800 -170018001700170017001700180017001700170018001800180017001700170017001700 -180017001800170018001800180017001700170018001700170017001700170018001700 -180017001800180018001700170017001700170017001800170017001700180017001700 -170018001700170017001800170017001800170018001700180018001800170017001700 -170017001800170017001700170017001700180018001800170017001700170000001c00 -170017000600000000001a00170017001700000017001700170017001700170017001800 -170018001800170017001700180017001700170017001700170018001800180017001800 -180017001800180018001700170017001700170017001800170017001700180017001700 -180017001800170018001800170017001800170018001700180018001800180017001800 -170018001700170018001800170018001700180017001700180017001700170018001700 -170017001700170017001800180018001700180018001700180018001800170017001700 -170017001700180017001700170018001700170018001700180017001800180017001700 -180017001800170018001800180018001700180017001800170017001800180017001800 -170018001700170018001700170017001800170017001700170017001700180018001800 -170018001800170018001800180017001700170017001700170018001700170017001800 -170017001800170018001700180018001700170018001700180017001800180018001800 -170018001700180017001700180018001700180017001800170017001800170017001700 -180017001700170017001700170018001800180017001800170018001700170017001700 -180017001800170018001700180017001800170018001800170017001700180017001700 -170017001a00170019001800190018000000000000000000170000001700170019000000 -0000170000001800180000001700170000000000170017000c0019001700170018001800 -180017001700180018001800170018001700180017001700180018001700180017001800 -170017001800170017001700180017001700170017001700170018001800180017001800 -170018001700170017001700180017001800170018001700180017001800170018001800 -170017001700180017001700180018001700170017001800170017001700170017001800 -180018001700180017001800170017001700170017001800170017001700180018001800 -170018001700180017001700170017001700180017001800180017001700180018001700 -170018001800170017001700180017001700170018001700170018001800170017001800 -180017001700180018001700170018001800170017001800180017001700180018001700 -170017001800170017001800170017001700170018001700180017001800170018001700 -180017001700170017001800180018001700180017001800170017001700170017001800 -170017001700180018001800170018001700180017001700170017001700180018001800 -170018001700180017001700180018001700180017001800170017001800170017001700 -180017001700170017001700170018001800180017001800170017001800170017001700 -1800180017001700170017000000170017001c000600000000001a0017001c0017000000 -170017001800180017001700170018001800170018001700180017001800170018001700 -180018001700170017001700170017001700170017001700170017001800180017001800 -170018001700180017001800170018001800170017001700170017001700180018001700 -170017001700170017001700170017001700180018001700170017001700170017001800 -180017001800170018001700180017001800170018001800170017001700170017001700 -170017001700170017001700180018001700180017001800170018001700180017001800 -180017001700170017001700170018001800170017001700170017001700170017001700 -170018001800170017001700170017001700180018001700180017001800170018001700 -180017001800180017001700170017001700170017001700170017001700170018001800 -170018001700180017001800170018001700180018001700170017001700170017001800 -180017001700170017001700170017001700170017001800180017001700170017001700 -170018001800170018001700180017001800170018001700180018001700170017001700 -170017001700180017001800180018001700170018001700170017001800170017001700 -170017001700180018001700170018001700190019001800190018001700170017001b00 -170017001800170018001700170017001800170018001800190017001700190017001900 -170018001000180018001700170018001400180018001800170017001700170017001800 -180017001700170017001700170018001800170018001700180017001800170018001700 -180018001700170017001700170017001700180017001800180018001700170018001700 -170017001800170017001700170017001700180017001800170018001700170017001800 -170018001700180018001800170017001700170017001700170018001800170018001800 -170017001800180017001700170017001700170017001800180017001800180017001700 -170017001700180017001700170018001700170017001800180017001700180018001700 -170018001700170017001800170017001700180017001700170018001700170017001800 -170017001700180017001700170018001800170017001800170018001700180018001800 -170017001800170017001700180017001700170018001800170017001700170017001700 -170018001800170018001800170017001800180017001700170017001700170017001800 -180017001800180017001700170017001700170017001800180017001700170017001700 -170018001800170018001700180017001800170018001700180018001700170017001700 -1700170018001700170017001800170018001700170017001700170000001c0017001700 -0600000000001a0017001c00170000001800180018001700180018001700170018001700 -170017001800180017001700180018001700180017001800170018001800170017001800 -180017001800170018001700180018001700170018001800170017001700170017001700 -170018001800170017001700170017001700180018001700170018001800170017001700 -170017001700180018001700170017001700170017001700180018001700170018001800 -170018001700180017001800180017001700180018001700180017001800170018001800 -170017001800180017001700170017001700170017001800180017001700170017001700 -170018001800170017001800180017001700170017001700170018001800170017001700 -170017001700170018001800170017001800180017001800170018001700180018001700 -170018001800170018001700180017001800180017001700180018001700170017001700 -170017001700180018001700170017001700170017001800180017001700180018001700 -170017001700170017001800180017001700170017001700170017001800180017001700 -180018001700180017001800170018001800170018001700170017001700170017001800 -170017001800180017001700180018001800170018001700180017001700170018001700 -1a00190011001900170019001700180017001700180017001b0017001700170017001900 -19001700150019001900130015001a00170017000f001700170018001800170018001800 -170017001700180018001700170017001700170017001800180017001700170017001700 -170017001800180017001700180018001700180017001800170018001800170018001700 -170017001700170017001800170017001800180017001700180018001800170018001700 -180017001700170018001700180017001800170017001700170018001700180017001800 -180017001700170017001700170018001700180017001800170018001700180018001700 -170017001700170017001800170018001800170017001700180017001700170018001700 -170017001800170017001800180017001700180018001700170017001800170017001700 -180017001700170018001700170017001800170017001700180017001700170018001700 -170018001800170017001700170017001700180017001700180018001700170018001800 -170018001700180017001800180017001700170017001700170018001700180017001800 -170018001700180018001700170017001700170017001800170018001700180018001700 -170017001700170017001800180017001700170017001700170017001800180017001700 -180018001700180017001800170018001800170017001700170017001700170017001700 -1700170017001700000017001c001c000600000000001a00170017001700000018001800 -140018001800170018001700170017001800170017001700180017001700170017001700 -170018001700170018001700170018001700170018001700170017001700170017001800 -170017001700180018001800170018001700180017001700180018001700180017001800 -170017001700170018001700180017001800180017001700180017001800170018001800 -180017001700170018001700170017001700170017001800170017001800170017001800 -170017001800170017001700170017001700180017001700170018001800180017001800 -170018001700170018001800170018001700180017001700170017001800170018001700 -180018001700170018001700180017001800180018001700170017001800170017001700 -170017001700180017001700180017001700180017001700180017001700170017001700 -170018001700170017001800180018001700180017001800170017001800180017001800 -170018001700170017001700180017001800170018001800170017001800170018001700 -180018001800170017001700180017001700170017001700170018001700170018001700 -170017001800180017001800170018001700180017001700170018001700170017001700 -180017001700170017001700170019001a00170019001700170017001700170018001700 -170017001700170017001700170017001700180019001500170019001800140018001800 -0f0018001700180017001700180017001700170017001700180017001800170018001800 -170017001800170018001700180018001800170017001700180017001700170017001700 -170018001700170018001700170017001800180017001800170018001700180017001700 -170018001700170017001700180017001700170018001800170017001800170017001700 -180018001700170017001800170017001800170018001700180018001700170017001800 -170017001700180017001700180017001800170018001800170017001700180017001800 -180017001700180018001700170018001800170017001800170017001700180017001700 -170018001800170017001800180017001700180018001700170018001800170017001800 -180017001700180018001700170018001700170017001700180018001700180017001800 -170018001700170017001800170017001700170017001800170017001800170018001700 -180018001700170017001800170017001700180017001700180017001800170018001800 -170017001700180017001700180017001800170018001800170017001800170018001700 -180018001800170017001700180017001700170017001700170018001700170018001700 -170017001700180017001800180018001700170017001700000017001c00170006000000 -00001a001b001c0017000000170017001800180017001700170017001700180017001700 -170018001700170017001800180017001700170018001800170018001800170018001800 -170017001700180018001700170017001800170017001700170017001700180017001700 -180017001800170018001800170017001700180018001700170017001800180017001800 -170018001700170018001700170017001700170017001800170017001700180018001700 -170017001800180017001800180017001800180017001700170018001800170017001700 -180017001700170017001700170018001700170018001700180017001800180017001700 -170018001800170017001700180018001700180017001800170017001800170017001700 -170017001700180017001700170018001800170017001700180018001700180018001700 -180018001700170017001800180017001700170018001700170017001700170017001800 -170017001800170018001700180018001700170017001800180017001700170018001800 -170018001700180017001700180017001700170017001700170018001700170017001800 -180017001700170018001800170018001700180017001700180017001800170017001700 -18001700170017001800170018001700180017001800180017001700180017001a001700 -180019001700180017001700170017001700170017001700170017001700170017001700 -170017001800180015001800180018001000170018001700170018001800180017001700 -180017001700170018001800170018001700180017001700180017001700170017001700 -170018001700170017001800180017001700170018001800170018001700180017001700 -180017001800170017001700180017001700170018001700180017001800170018001800 -170017001700180017001700180017001800170018001800170018001700180017001700 -180018001700180017001800170017001800180017001800170018001700170018001800 -170018001700180017001700170018001800170017001800180017001700180018001700 -170017001800170017001700180017001700180018001700170018001800170017001800 -180017001700180018001700170018001800170017001800180017001700170018001700 -170018001700170018001700180017001700170018001700180017001800170018001800 -170018001700180017001700180018001700180017001800170017001800180017001800 -170018001700170018001800170018001700180017001700180017001700170018001800 -170018001700180017001700180017001700170017001700170018001700170017001800 -180017001700170018001800170018001700170017001700170017001800180017001700 -17001700000017001c0017000600000000001a001c001700170000001700170017001800 -180018001800170017001800180018001700170018001800170017001800170018001700 -170017001700170017001700170017001700180017001800170017001800180017001700 -180018001700180017001800170018001800170017001700170017001700180017001800 -180017001800170017001700170017001700180018001700180017001800170018001800 -170017001800180017001700180017001800170017001700170017001700170017001700 -170018001700180017001700180018001700170018001800170018001700180017001800 -180017001700170017001700170018001700180018001700180017001700170017001700 -170018001800170018001700180017001800180017001700180018001700170018001700 -180017001700170017001700170017001700170017001800170018001700170018001800 -170017001800180017001800170018001700180018001700170017001700170017001800 -170018001800170018001700170017001700170017001800180017001800170018001700 -180018001700170018001800170017001800170018001700170017001700170017001800 -170018001800170017001700180018001700170018001800170017001800170017001700 -1700170017001800170017001a0019001800180017001800170017001700180018001800 -180018001700180018001700180018001800180015001800180019001900190010001500 -180018001700170017001800180018001800170018001700170017001700170017001800 -180017001800170018001700180018001700170018001800170017001800170018001700 -170017001700170017001800170018001800170017001700180018001700170018001800 -170017001800170017001700170017001700180017001800170018001800170017001700 -170017001700170017001800180017001700170017001700170018001800170017001700 -170017001700180018001700170017001700170017001800180017001700170017001800 -170017001700180017001700170018001800170017001800180017001700180017001700 -170018001700170017001800170017001700180017001700170018001700170017001800 -170017001700180018001700170018001700180017001800180017001700170018001800 -170018001700180017001800170017001700170017001800180017001700170017001700 -170018001800170017001700170017001700180018001700170017001700170017001800 -180017001800170018001700170017001700170017001800180017001800170018001700 -180018001700170018001800170017001800170018001700170017001700170017001700 -1b0017001700180018001700170017001700170000001c0017001c000600000000001a00 -170017001700000017001700170018001700170017001700170017001700180017001800 -170018001700180017001700180018001700180018001700170018001800170018001800 -170017001800170018001700180017001800170018001800170017001700170017001700 -170018001800170018001800170017001700170018001800170018001800170017001700 -170017001700170018001800170018001700180017001800170018001700170018001800 -170018001800170017001800180017001800180017001700180017001800170018001700 -180017001800180017001700170017001700170017001800180017001800180017001700 -170017001800180017001800180017001700170017001700170017001800180017001800 -170018001700180017001800170017001800180017001800180017001700180018001700 -180018001700170018001700180017001800170018001700180018001700170017001700 -170017001700180018001700180018001700170017001700180018001700180018001700 -170017001700170017001700180018001700180017001800170018001700180017001700 -180018001700180018001700180017001700170017001700180018001700170017001800 -170017001700180017001700180018001800170018001700170017001a00180018001700 -170017001700170017001700180018001800180017001700170017001800180018001800 -180019001800180015001500120018001400180018001700170018001800170017001700 -180018001700180018001700170017001700170017001700180018001700180017001800 -170018001700180017001700180018001700180018001700180017001700170017001700 -180018001700170017001800170017001700180017001700180018001800170018001700 -180017001800170017001700180018001700180018001700170017001700170017001800 -180017001700170017001700170018001800170017001700170017001700180018001700 -170017001700170018001700170017001800170017001700180017001700170018001700 -170018001800170017001800180017001700170018001700170017001800170017001700 -180017001700170018001700170017001800170017001700180017001700180018001700 -170017001700170018001800170017001800170018001700180017001700180018001700 -170017001700170017001800180017001700170017001700170018001800170017001700 -170017001700180018001700170017001700170017001700180018001700180018001700 -170017001700170017001700180018001700180017001800170018001700180017001700 -180018001700180018001700170017001700170018001700180017001700170017001700 -000017001c0017000600000000001a0017001c0017000000180018001800170018001700 -170018001800170017001700170018001700170017001800180017001700170017001700 -180017001700180017001700170017001700180018001700170017001800170017001700 -170017001700180018001800170018001700180017001700170017001700180018001700 -170017001700170018001700180017001800180018001700170017001700170017001800 -170017001700180018001700170017001700170018001700170018001700170017001700 -170018001800170017001700180017001700170017001700170018001800180017001800 -170018001700170017001700170018001800170017001700170017001800170018001700 -180018001800170017001700170017001700180017001700170018001800170017001700 -170017001800170017001800170017001700170017001800180017001700170018001700 -170017001700170017001800180018001700180017001800170017001700170017001800 -180017001700170017001700180017001800170018001800180017001700170017001700 -170018001700170017001800180017001700170017001700180017001700170018001800 -170018001700170017001800170018001700180017001800170018001700170017001700 -180017001900170012000f000f000f0010000f000f000f000f000f000f000f000c000c00 -0f000c000f000f000c000f000f000c000c000f000c000f000c0012001000170018001700 -180018001700170017001800180017001700170017001700180017001800170018001800 -180017001700170017001700170018001700170017001800180017001700170017001700 -180017001700170018001800170018001700170017001800170018001700180017001800 -170018001700170017001700180017001700180017001800170018001700170017001700 -180017001800170018001800170017001800170018001700180018001700170018001700 -180017001800180017001700180017001800170018001800170018001800170017001800 -180017001700180018001700170018001700170017001800170017001700180018001700 -170018001800170017001800180017001700180018001700170018001800170017001800 -180017001700180017001700170017001800180017001800170017001700180017001800 -170018001700180017001700180017001800170018001800170017001800170018001700 -180018001700170018001700180017001800180017001700180017001800170018001800 -180017001700170017001700180017001800170018001800180017001700170017001700 -1700180017001700170018001800170017001700170017001800170017001b0017001700 -170018001800180017001b001700170000001c00170017000600000000001a0017001c00 -170000001700170018001700170017001700170017001800180018001700180017001800 -170017001700170017001800180018001700180018001700180018001800170017001700 -170017001800170018001700180018001800170017001700170017001800170017001800 -170018001700180017001800170017001700180018001800170018001700180017001700 -170017001700180018001800170018001700180017001700170017001700180018001800 -170018001800170018001800180017001700170017001700180017001800170018001800 -180017001700170017001700180017001700180017001800170018001700180017001700 -170018001800180017001800170018001700170017001700170018001800180017001800 -170018001700170017001700170018001800180017001800180017001800180018001700 -170017001700170018001700180017001800180018001700170017001700170018001700 -170018001700180017001800170018001700170017001800180018001700180017001800 -170017001700170017001800180018001700180017001800170017001700170017001800 -180018001700180017001800170017001700170018001700180018001700170017001800 -170017001700170018001700180018001700170017001700150018001900190018001500 -180018001800180018001800180018001800180018001800180018001800180019001900 -170018001700170015001800180018001700170018001800180018001700170017001800 -180018001700180017001800170017001700170017001800180018001700180017001800 -170017001700170017001800180018001700180017001800170017001700170018001700 -180018001700170017001800170017001700170018001700180018001700170018001700 -180017001800170018001700180017001700170018001700170017001800170017001700 -180017001700170018001700170017001800170017001700180017001700170018001700 -170017001700170018001700170017001800170017001800180017001700170018001700 -170017001800170017001800180017001700170018001700170017001800170017001700 -180017001700170018001700170018001800170017001700180017001700180017001700 -170017001800170018001800170017001800170018001700180017001700170018001700 -170017001800170017001700180017001700170018001700170017001800170017001700 -180017001700170018001700170017001700170017001800180018001700180017001800 -170017001700170017001800180018001700180017001800170017001700170017001800 -180018001700180017001b00170017001700170017001700170017001700170000001700 -17001c000600000000001a00170017001700000017001700180018001700170018001800 -170017001700170017001700170018001800170018001800170017001700170017001700 -170017001700170017001700180018001700180018001700170017001700170017001700 -180018001700180018001700180017001800170018001700180017001800180017001700 -170017001700170017001800180017001800180017001700170017001700170017001800 -180017001800180017001700170017001700170017001700170017001700170018001800 -170018001800170017001700170017001700170018001800170018001800170018001700 -180017001800170018001700180018001700170017001700170017001700180018001700 -180018001700170017001700170017001700180018001700180018001700170017001700 -170017001700170017001700170017001800180017001800180017001700170017001700 -170017001800180017001800180017001800170018001700180017001800170018001800 -170017001700170017001700170018001800170018001800170017001700170017001700 -170018001800170018001800170017001700170017001700170018001700180018001800 -170017001700170017001800170018001700180018001800170017001700170017001800 -180019001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700140017001700180019001800180018001800180017001700 -180017001800140018001800170017001700170017001700170018001800170018001800 -170017001700170017001700170018001800170018001800170017001700170017001700 -170018001700180018001800170017001700170017001800170018001700180018001800 -170017001700170017001800170018001700180017001800170018001800170018001700 -180017001800170018001700180017001800170018001700180017001800170018001700 -180017001800170018001700180017001800170018001700170018001800170017001800 -170017001700180018001700170018001800170017001800170017001700180018001700 -170018001800170017001800180017001700180018001700170018001700170017001800 -180017001700180017001800170018001800180017001700170017001700180017001800 -170018001800170018001700180017001800170018001700180017001800170018001700 -180017001800170018001700180017001800170018001700180017001800170018001800 -170017001700170017001700170018001800170018001800170017001700170017001700 -170018001800170018001800170017001700170017001700170017001700170018001700 -18001700170017001700170000001c001c0017000600000000001a0017001c0017000000 -170017001800180018001800170018001700180017001800180017001700170017001700 -170018001700180017001800180017001700180018001700180017001800170017001700 -170017001700180018001700180017001800170017001700170017001700180017001800 -170018001700180017001800170018001700180018001700170017001700170017001800 -170018001700180018001700170017001700170017001800170018001700180018001700 -170018001800170018001700180017001700170017001700170018001800170018001700 -180017001700170017001700170018001700180017001800170018001700180017001800 -170018001800170017001700170017001700180017001800170018001800170017001700 -170017001700180017001800170018001800170017001800180017001800170018001700 -170017001700170017001800180017001800170018001700170017001700170017001800 -170018001700180017001800170018001700180017001800180017001700170017001700 -170018001700180017001800180017001700170017001700170018001700180017001800 -180017001800170017001700170017001700180018001700180017001800170017001700 -170017001700180018001700180017001700170017001900170018001700190017001800 -180018001800180018001800180018001800180018001800180018001900180018001700 -170017001700140017001700180018001700170018001800170018001700180017001800 -180017001700170017001700170018001700180017001800180017001700170017001700 -170018001700180017001800180017001800170017001700170017001700180018001700 -180017001800170017001700170017001700180018001700180017001800170018001700 -180017001800170017001700180018001700170018001800170017001800180017001700 -180018001700170018001800170017001800180017001700180018001700170018001800 -180017001700180018001700170018001800170017001700180017001700180018001700 -170018001800170017001700180017001700180018001700170018001800170017001800 -180017001700180018001700170017001800170017001800180017001700170017001700 -170018001800170018001700180017001800170017001700180018001700170018001800 -170017001800180017001700180018001700170018001800170017001800180017001700 -180018001700170018001800170018001700180017001800180017001700170017001700 -170018001700180017001800180017001700170017001700170018001700180017001800 -180017001700170017001700170018001700170017001700170017000000170017001700 -0600000000001a001c001700170000001700170017001800180018001700170017001800 -170017001800170018001700180018001700170017001800170017001800170017001800 -170017001800170017001700180018001700180017001800170017001800170017001700 -180018001700180018001700180017001800170018001700170017001700180017001700 -180017001800170018001800170017001700180017001700180017001800170018001800 -170017001700180017001700180017001700180017001700180017001700170018001800 -170018001700180017001700180017001700170018001800170018001800170018001700 -180017001800170017001700170018001700170018001700180017001800180017001700 -170018001700170018001700180017001800180017001700170018001700170018001700 -170018001700170018001700170017001800180017001800170018001700170018001700 -170017001800180017001800180017001800170018001700180017001700170017001800 -170017001800170018001700180018001700170017001800170017001800170018001700 -180018001700170017001800170017001800170017001700180018001700180017001800 -170017001800170017001700180018001700180017001800170017001800170019001800 -170018001700180017001700170017001700170017001700170017001700170017001700 -170017001700140017001800180018001800170018001800180018001800170017001800 -170017001700170017001800170017001800170018001700180018001700170017001800 -170017001800170018001700180018001700170017001800170017001800170017001700 -180018001700180017001800170017001800170017001700180018001700180017001800 -170017001800170017001800170018001700180017001800180017001700170018001700 -170017001800170017001700180017001700170018001700170017001800170017001700 -180017001700170018001700170017001700180017001700170018001700170017001800 -180017001700180017001700170018001700170017001800180017001700180017001700 -170018001700170017001800170017001700180017001700170018001800170017001800 -170017001700170018001800170018001700180017001700180017001700180017001800 -180017001700170018001700170017001800170017001700180017001700170018001700 -170017001800170017001700180017001700170018001700170017001700170017001800 -170017001800170018001700180018001700170017001800170017001800170018001700 -180018001700170017001800170017001800170017001700170018001700180017001700 -1700170017001700000017001c0017000600000000001a001b0017001700000017001700 -170017001700180018001700170018001700180017001700180017001700170018001700 -180018001700170018001700170017001800180017001700180017001700180017001800 -180017001800170017001800170017001800170017001700180018001800180017001700 -180017001800180018001700170018001700170018001700170018001800170017001700 -170018001700170018001700170017001800180018001800170017001800170017001700 -180018001700170018001700170018001700180018001700180017001700180017001700 -180017001700170018001800180018001700170018001700180018001800170017001800 -170017001800170017001800180017001700170017001800170017001800170017001700 -180018001800180017001700180017001700170018001800170017001800170017001800 -170018001800170018001700170018001700170018001700170017001800180018001800 -170017001800170018001800180017001700180017001700180017001700180018001700 -170017001700180017001700180017001700170018001800180018001700170018001700 -170017001800180017001700180017001700180017001800180017001800170017001800 -170017001800170017001700180018001800180017001700180017001800170017001800 -180017001700170017001700180017001800180017001700180017001700180018001700 -170017001800170017001800170018001700170018001800170018001700170018001700 -170018001700170018001700170017001800180018001800170017001800170017001800 -170018001800170018001700170018001700170018001700170017001800180018001800 -170017001800170017001800170018001800170018001700170018001700170018001700 -170017001800170017001800180017001700170017001700180017001800180017001700 -180017001700180018001700170017001800170017001800170018001700170018001800 -170018001700170018001700170018001700170018001700170017001800180018001800 -170017001800170017001800170018001800170018001700170018001700170018001700 -170017001800180018001800170017001800170017001800170018001800170018001700 -170018001700170018001700170017001800170017001800180017001700170017001700 -180017001800180017001700180017001700180018001700170017001800170017001800 -170018001700170018001800170018001700170018001700170018001700170018001700 -170017001800180018001800170017001800170017001800170018001800170018001700 -180018001800180017001700180017001800170017001800000017001700170006000000 -00001a001c001c001c0000001c001b001700170017001700180018001800180017001700 -180018001800180018001800180018001800180017001700180018001800180018001800 -170017001800180018001800180018001800180018001800180017001800180018001800 -180018001800180017001800170017001800180018001800180018001700170018001800 -180018001800180018001800180018001800170018001800180018001800180018001800 -170018001700170018001800180018001800180017001700180018001800180018001800 -180018001800180018001700180018001800180018001800180018001700180017001700 -180018001800180018001800170017001800180018001800180018001800180018001800 -180017001800180018001800180018001800180017001800170017001800180018001800 -180018001700170018001800180018001800180018001800180018001800170018001800 -180018001800180018001800170018001700170018001800180018001800180017001700 -180018001800180018001800180018001800180018001700180018001800180018001800 -180018001700180017001700180018001800180018001800170017001800180018001800 -180018001800180018001800180017001800180018001800180018001800180017001800 -170017001800180018001800180018001800180018001700180018001800180018001700 -180018001800180018001800180018001800170018001800180018001800170018001700 -180018001800180018001800180018001800170018001800180018001800180018001800 -170018001700170018001800180018001800180018001800180018001800170018001800 -180018001800180018001800170018001700170018001800180018001800180018001800 -180018001800170018001800180018001800180018001800180018001800180018001700 -180018001800180018001700180018001800180018001800180018001800170018001800 -180018001800170018001700180018001800180018001800180018001800170018001800 -180018001800180018001800170018001700170018001800180018001800180018001800 -180018001800170018001800180018001800180018001800170018001700170018001800 -180018001800180018001800180018001800170018001800180018001800180018001800 -180018001800180018001700180018001800180018001700180018001800180018001800 -180018001800170018001800180018001800170018001700180018001800180018001800 -180018001800170018001800180018001800180018001800170018001700170018001800 -180018001800180018001800180018001800180018001800180018001800170017001900 -1700170000001b001c0017000600000000001a0017001b00170000001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001800 -170017001700170017001700170017001b001700000017001c001b000600000000001a00 -17001c001c000000170017001700170017001700180018001800180018001b0017001700 -180018001800180018001800180018001b0017001700170018001800180018001b001700 -170017001800180018001800180018001800180017001b00170017001800180018001800 -18001800180018001b0017001700170018001800180018001b0017001700170018001800 -18001800180018001800180017001b001700170018001800180018001800180018001800 -1b0017001700170018001800180018001b00170017001700180018001800180018001800 -1800180017001b0017001700180018001800180018001800180018001b00170017001700 -18001800180018001b001700170017001800180018001800180018001800180017001b00 -17001700180018001800180018001800180018001b001700170017001800180018001800 -1b001700170017001800180018001800180018001800180017001b001700170018001800 -1800180018001800180018001b0017001700170018001800180018001b00170017001700 -1800180018001800180018001800180017001b0017001700180018001800180018001800 -180018001b0017001700170018001800180018001b001700170017001800180018001800 -180018001800180017001b0017001700180018001800180018001800180018001b001700 -170017001800180018001800180018001700170018001b00180018001800180017001700 -180018001800180018001800170017001800180018001800180018001700170018001800 -18001800180018001800180017001b001700170018001800180018001800180018001800 -1b001700170017001800180018001800180018001800180017001b001700170018001800 -1800180018001800180018001b0017001700170018001800180018001800180018001800 -17001b001700170018001800180018001800180018001800180018001700170018001b00 -180018001800180017001700180018001800180018001800170017001800180018001800 -18001800170017001800180018001800180018001800180017001b001700170018001800 -1800180018001800180018001b0017001700170018001800180018001800180018001800 -17001b0017001700180018001800180018001800180018001b0017001700170018001800 -18001800180018001800180017001b001700170018001800180018001800180018001800 -180018001700170018001b00180018001800180017001700180018001800180018001800 -170017001800180018001800180018001700170018001800180018001800180018001800 -17001b0017001700180018001800180018001800180018001b0017001700170018001800 -180018001800180018001800180018001800180018001800180018001b00170017001700 -00001b001c001c000600000000001a00170017001b0000001b001b001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -17001700170017001700110017001b00000017001c0017000600000000001a001c001c00 -170000001c00170017001700170017001800180018001800170017001700170017001700 -170017001800180017001700170017001700170018001800170017001700170017001700 -170017001700170018001700180017001700170017001700170017001700170018001800 -170017001700170017001700180017001700170017001700170017001700170017001700 -180018001800180017001700170017001700170017001700180018001700170017001700 -170017001800180017001700170017001700170017001700170017001800170018001700 -170017001700170017001700170017001800180017001700170017001700170018001700 -170017001700170017001700170017001700170018001800180018001700170017001700 -170017001700170018001800170017001700170017001700180018001700170017001700 -170017001700170017001700180017001800170017001700170017001700170017001700 -180018001700170017001700170017001800170017001700170017001700170017001700 -170017001800180018001800170017001700170017001700170017001800180017001700 -170017001700170018001800170017001700170017001700170017001700170018001700 -180017001700170017001700170017001700170018001800170017001700170017001700 -180018001800180017001700170017001800180018001700170017001700170018001800 -1800180017001700170017001b0018001800170017001700170017001700170017001700 -180017001800180017001700170017001700170017001700180018001700170017001700 -170017001700170017001700180017001800170017001700170017001700170017001700 -180018001700170017001700170017001700170017001700180017001800170017001700 -170017001700170017001700180018001800180017001700170017001800180018001700 -1700170017001700180018001800180017001700170017001b0018001800170017001700 -170017001700170017001700180017001800180017001700170017001700170017001700 -180018001700170017001700170017001700170017001700180017001800170017001700 -170017001700170017001700180018001700170017001700170017001700170017001700 -180017001800170017001700170017001700170017001700180018001800180017001700 -170017001800180018001700170017001700170018001800180018001700170017001700 -1b0018001800170017001700170017001700170017001700180017001800180017001700 -170017001700170017001700180018001700170017001700170017001700170017001700 -1800180018001800170017001700170017001700170017001b001b001700170000001c00 -170017000600000000001a00170017001100000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000001c00170017000600000000001a0017001c0017001c00 -1c001b00170017001700170017001700170017001700170017001700170017001c001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -1700170017001700170017001700170017001700170017001c0017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001c00170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -17001700170017001c001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -1c0017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001c00170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -17001700170017001700170017001700170017001c001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -1700170017001700170017001c0017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001c00170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001c00170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001c00170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001c00170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001c00170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001c00170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001700170017001700170017001700170017001700170017001700170017001700 -170017001c00170017001700170017001700170017001700170017001700170017001700 -17001700170017001700170017001700170017001700170017001700170017001c001c00 -0600000000001a001c0017001c001c001700170017001c0017001c001700170017001c00 -170017001c001c001700170017001700170017001700170017001c001700170017001700 -1700170017001c001700170017001700170017001c001c0017001700170017001c001c00 -170017001700170017001700170017001700170017001700170017001700170017001c00 -1700170017001700170017001c001c0017001700170017001c001c001700170017001700 -17001700170017001700170017001700170017001700170017001c001700170017001700 -170017001c001c0017001700170017001c001c0017001700170017001700170017001700 -1700170017001700170017001700170017001c001700170017001700170017001c001c00 -17001700170017001c001c00170017001700170017001700170017001700170017001700 -170017001700170017001c001700170017001700170017001c001c001700170017001700 -1c001c001700170017001700170017001700170017001700170017001700170017001700 -17001c001700170017001700170017001c001c0017001700170017001c001c0017001700 -1700170017001700170017001700170017001700170017001700170017001c0017001700 -17001700170017001c001c0017001700170017001c001c00170017001700170017001700 -17001700170017001700170017001700170017001c001c00170017001700170017001700 -1c00170017001c0017001700170017001c001c0017001700170017001c001c0017001700 -1700170017001c0017001c0017001700170017001c001c00170017001700170017001700 -170017001700170017001c001700170017001700170017001c001c001700170017001700 -1c001c001700170017001700170017001700170017001c001700170017001c0017001c00 -17001700170017001c001c0017001700170017001700170017001700170017001c001c00 -1700170017001700170017001c00170017001c0017001700170017001c001c0017001700 -170017001c001c00170017001700170017001c0017001c0017001700170017001c001c00 -170017001700170017001700170017001700170017001c00170017001700170017001700 -1c001c0017001700170017001c001c001700170017001700170017001700170017001c00 -1700170017001c0017001c0017001700170017001c001c00170017001700170017001700 -17001700170017001c001c001700170017001700170017001c00170017001c0017001700 -170017001c001c0017001700170017001c001c00170017001700170017001c0017001c00 -17001700170017001c001c00170017001700170017001700170017001700170017001c00 -1700170017001700170017001c001c0017001700170017001c001c0017001c001c001700 -17001c001c0017001c00170017001c000600000000001a00170017001700170017001700 -170017001700170017001c001700170017001700170017001c0017001700170017001c00 -17001700170017001700170017001c0017001700170017001700170017001c0017001700 -170017001c00170017001700170017001c0017001700170017001c001700170017001c00 -1700170017001c0017001700170017001700170017001c0017001700170017001c001700 -17001700170017001c0017001700170017001c001700170017001c001700170017001c00 -17001700170017001700170017001c0017001700170017001c0017001700170017001700 -1c0017001700170017001c001700170017001c001700170017001c001700170017001700 -1700170017001c0017001700170017001c00170017001700170017001c00170017001700 -17001c001700170017001c001700170017001c0017001700170017001700170017001c00 -17001700170017001c00170017001700170017001c0017001700170017001c0017001700 -17001c001700170017001c0017001700170017001700170017001c001700170017001700 -1c00170017001700170017001c0017001700170017001c001700170017001c0017001700 -17001c0017001700170017001700170017001c0017001700170017001c00170017001700 -170017001c0017001700170017001c001700170017001c001700170017001c0017001700 -170017001c0017001700170017001c00170017001700170017001c001700170017001700 -1c00170017001700170017001c0017001700170017001700170017001700170017001c00 -170017001c0017001700170017001c0017001c0017001700170017001700170017001c00 -17001700170017001c00170017001700170017001c0017001700170017001c0017001700 -170017001700170017001700170017001700170017001c00170017001c00170017001700 -17001c0017001c0017001700170017001c0017001700170017001c001700170017001700 -17001c0017001700170017001c00170017001700170017001c0017001700170017001700 -170017001700170017001c00170017001c0017001700170017001c0017001c0017001700 -170017001700170017001c0017001700170017001c00170017001700170017001c001700 -1700170017001c0017001700170017001700170017001700170017001700170017001c00 -170017001c0017001700170017001c0017001c0017001700170017001c00170017001700 -17001c00170017001700170017001c0017001700170017001c0017001700170017001700 -1c0017001700170017001700170017001700170017001c00170017001c00170017001700 -17001c0017001c0017001700170017001700170017001c0017001700170017001c001700 -170017001700170017001700170017001c0017001700170017001c00170017000e000000 -000012000e000600060006000b0006000600060006000600060006000600060006000600 -0600060006000600060006000600060006000600060006000e000b000600060006000600 -060006000600060006000600060006000600060006000600060006000600060006000600 -060006000600060006000600060006000600060006000600060006000600060006000600 -060006000600060006000600060006000600060006000600060006000600060006000600 -060006000600060006000600060006000600060006000600060006000600060006000600 -060006000600060006000600060006000600060006000600060006000600060006000600 -060006000600060006000600060006000600060006000600060006000600060006000600 -060006000600060006000600060006000600060006000600060006000600060006000600 -060006000600060006000600060006000600060006000600060006000600060006000600 -060006000600060006000600060006000600060006000600060006000600060006000600 -060006000600060006000600060006000600060006000600060006000600060006000600 -060006000600060006000600060006000600060006000600060006000600060006000600 -060006000600060006000600060006000600060006000600060006000600060006000600 -060006000600060006000600060006000600060006000600060006000600060006000600 -060006000600060006000600060006000600060006000600060006000600060006000600 -060006000600060006000600060006000600060006000600060006000600060006000600 -060006000600060006000600060006000600060006000600060006000600060006000600 -060006000600060006000600060006000600060006000600060006000600060006000600 -060006000600060006000600060006000600060006000600060006000600060006000600 -060006000600060006000600060006000600060006000600060006000600060006000600 -060006000600060006000600060006000600060006000600060006000600060006000600 -060006000600060006000600060006000600060006000600060006000600060006000600 -060006000600060006000600060006000600060006000600060006000600060006000600 -060006000600060006000600060006000600060006000600060006000600060006000600 -060006000600060006000600060006000600060006000600060006000600060006000600 -060006000600060006000600060006000600060006000600060006000600060006000600 -060006000600060006000600060006000600060006000600060006000600060006000600 -060006000600060006000600060006000600060006000600060006000600060006000600 -060006000600060006000600060000000000020000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -%%EndData -end -%%PageTrailer -%%Trailer -%%BoundingBox: 0 0 362.429 161 -%%EOF diff --git a/docs/tutorial/gtk_tut_packbox1.gif b/docs/tutorial/gtk_tut_packbox1.gif deleted file mode 100644 index bae3da207869c7f86cb26e3abdc6195717a6d627..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 52480 zcmWh!XHXN|5=|&c2q6RrJ@np-AfZX`MXFMjE+QfzA|PrY^ct!VdX=hl>4x4R6qOP& zARr?00ipsze7^hR&i>dvvopJUcV^FCBNIckiaRsaKHxV1KtlzNjE?m3_Uaw%rJ?fN z+T5Cc-;3mmq@jvIaS75;saKXa(7=6r2lxFwhNl;{_K&w<aF&$J1RA&o44&d2?1hAe z4EHZhPyRE1($>;VS|IK3?IYn{DRJ2}RH&s%5@}&8GV~vy&B^&iTW{~u>Uc=-Gz}Ee zJ334Q^*};#C^jJ!bNcWk3CXMx8Jdk`W8T{Q34_KJ=2lLRF490lk?=6m>Q+p2+VsK) z7(C?S*9DR-=49_8B`s@sas&qQpn+aP!jmGOMGp5*!9Xw+SE00|(*BPNB%CYd*_OYb zKa45{$)(Xy-?p^+&wpze)jvSe*4{syJ2X(+-tOVZVDj|rVoXvP41Q~RnB?!*JH2qy z+c9)OIUXLI9-iDMtzXbkBWbAo_jmS%1*K`I^s_SyLn1<GpwdgT`!FaB$!xX1b5dAb zy|w;rX@QiTmMJWrcXIN_KOm&HZ+dumDJCXt>+}B7!n822bVGI9(&9f)P%t)qVNw6y z?h|3&6n~!&(<5iYlf5A!k5F6<{sBvo&r%{I$V+P<P;8aMqgyZp8p#$3V+%pD@xY+D z!-EYls2dEb6!R<!21P}Nj89LKgn6^uUiEIRllH&;oSyn`xc@?!w{m)MnuaR7vb=5o zcpnDOo}M0VYZ*o|`KKfm(ojj0-k(H<#|%#{!D#)Fh-?^Dc4X*3HUEpti<p=g7+gOj z*dGRcjAHwDUtgM?Us|{z&3>;eZU_m82nqNXN+c3mn37f)`78zoLL#}$VNhgtT4Bty zl;P2n;lW-Q^q-+V4G2mDa^Kq7q5;LAcm-%cs+HCC{yx3?zeq4<1dKU$dbW)Q6yDa+ zO?pq-KiESud!!^~(SU@PW=W*?TagiwG$5N3%Ei+9FpBM8lITZ9q-^c{EW}q$Pc9;v zLrCk}F>z@y=CG54Kf|-rNahqIGq-=hJs2n+#%vA)g_G7vz5RnQX1C$dsqEZRB%Afp zdy+KZ-}!$n03Z}V5s(8?$}oThr^590N?}nj#1(#RK#<@_0@IWiKjCP@Fr9<Xa@xw! z(;$&u!Dq=KQ+VoytY=3dT~_rp9{pgiZQ{zExuR=WDxUM!8mkKZbV-XzWbI<r^#a`@ z$@aSWOcA5V1RZ&*!PfwqXa;q}h<5WGhVq|WH#SzHsqan{(O1J|nA`R<$ph5pDo&-K zyI7+#`B;-IA5?M3a+Bv!jKs374tPNLNh}j_LcZ2IjwkjGKW}50;oadRzWQ4;-R<8# zG<i-HTl92%U+aAMZGEQa&3~U-Y;6fQ&^avd;GU@bsltHuo#1b)RU_2hB%7ILx!2gD z_qU&(6jJ8TUp`<wlX&vW%jE4dc6NmAHC2vGor1~pxwh@+xo=aR=KPwmGE}G0&l-R+ z>r^sORcL!HJmtE4{3!-`!*?T=!>48=4i&n)5zikdzL_AL>${mK>i6T*6*8_V8AZAf zGNmi`YBoz%@yWQ(_VVK4q{RNdKzz8Z8*W5vs!(uDLSu5k6QyzWY))3k@+dw0NnnM6 zOB^zA+<_)zAXXIbHXnn5w=6Lk!Q0P>Sf&*M6IGKo(!!)O&=4T(@3C!T!k|nemK4M0 zw_BDVTDM!Ca+Rwb&qrjAWBUX_Xmja%MVM6Uy97g+UIq?XR>z~tM_=lrGL2;F-rGzm zQl1nZTWEfs4jLEvS&28Q4PW{U3^zyGjb)!pe<*r%RCsK{{$=S)LyY&~3qI4|3g`uh zBs%ZQ9WDX>mlfnVse{g~+<OOIs5;2}6))o8EV@b>9Q7!;S&v>TZb{Mg)|etYNXGV1 zh!E@+a<j-~v50C^>l1_qq?JNa#OZjBoL?73^wE`>2vs@G8++H_hBbcl-o=Wo1cYEr z7&}r9rsT(@e@rW>m}*y&QuNHOl_w}}&FPMwGsrlG*qBK?iD@27dt%N6Qdip_u;l%H za6~Qh(uE1EwFg|8;hoz3VWH9kLEMZuBXSo7$Bi!<&{Mp#-SpWW?cdSAf{@px@W^b~ zWQx&{qo=M2`MdnsNDzB<x~X_C<O<!sOLY6S6nVO>?fr{~5XPw#HD0B{{bqWtYnDM! zrHdu%CUJA3;udfDVb*mV*VgCH@1FR&<9ZxPn=q%_2Dns#X8<hOEHLy!>;}AXVtRcw zJBr?@6DMz`C$wK7YJv(!v3w@S%TZ3ZZifBn(?4tyLX?xjKJ!|al>b0#Tg}W#fbvCf zSMK}U66PIodNP0;Kmgz_`%5<(0DPb#Xh{eB8NHUVXT{#mWC2S?#6?36Q-t>$;n&6i z*U%1NNn9y>j-T*jPdi!|r%f9nq(d&Y1~VVbusmvt)>BIu60RY0QqWtFD;gOw$DBtA z#^!=us1L7P5oPcvIPgBzvQU+`0KGl{n-x;co76`O_&UELdrT`I3iG<_L!(Wo4y1S5 z7l_`ZTX;cG!f{>bamHY1qag$U70nTrW|@j^a)Z&c1`8Fcp<&%C1!yk~usAOpF^A%S zgdkzMM;Lc{qb6$eYF#hkFhfq`rgSDmDO`vnoB8I%<c;oNz4RdhV;D|bVse1yW~U7< zbihEG`932+o?eG0lQtAJm`Xxdqx74>SPl>V{oMt{1Z{eLLNoH_^jNU8F%?e&kUq5( z0wlY~3fp<mI4^T^g=~OmAv!>7{wOUZW>Wvy=z%At69}D>PwvaW2L4_a6E@O@3mi7W zgbs({d$`$~YA0og`ywnKMY^~c07fsDsXv5`8qD2oV>sWP=LO*y0T-UoUj@3fqZRYg z=H^JvNs)J3+A*E-CLSR)0HNu5fG$5lTfz<q#cE^tac*4DQZcw$4aNtDK}AD_ReAHH zkoZg*U*j#!%tM^og)OZvZo^P=gZjRkRJd6Fn!$VgjgGqZ#=xibE+0)lbiRM|Ds)Eb z*6)Z9{d@0TM_$&uQJXmsxI&xaWu!gW>z7AGuZjqqVUkzTvA_^dO~*W4Hm^4fw`EO& zjchzQ<OvD#(nA<`2tX$HC>=;O5#p6dvCgDq^sBH{BK7dmv;zRpJq|K384??9o;Y|D z*$(eW7!)$%pfNnB4t$M)Tr<?3QyeelnRAP?nr~tZ7T0bN7sAL^>qMv25?E{qH}pSD zt^ZOy2+F9h7KiC{YXSr+)HbWQpVsmMwmd`im}8%x%^QlD%o;&MMtNz1lOh9!=+BuA zEP#ho5nD@~Ao+M9<|Et8Y26z6HiASW2E-dEoRLy_M<hWqRxRWO&HT?82_tPPTK_0i zJ%5y8W@$2$h91P_V}h8ERs6%cg+61;mQ42TPUDF>I2}yXag`tEdideRx348AOjF8F z0EYXF$f?p`k}OqN&i`ATmZAxeUzN6+=|J9?)9NshTi+wlx8&)Ma$rE_X>JcRIHFYc ztiUP`gDiHCVY~2BfYOox5egtNSmr~GvfOC8(E>m<ZQlnmIW+o>daNgLrfCYlnqOMB zd)lY&+4pq6Yw~GtxUKokVe$NZho!$UKFoYMV>`KNF<)F`GM%Gl`!S$14rG~eE$_V` z@1q(cnx%(A&j4gLB4kLxh?QM+2T3b}q2i4NF5Ss~NTUG|0E+ghFoy}2V($H>Ga{tO z9LfaJSb>E#6zth7u|hcnFZ%mOFyDe;Fk0g{lYRCu?g69)4g?3RoeCLp42Bpp(_Wr% zOHCAcglHwPrc+L>0V;YKJnev?^cGCib3oZ$cej{~lbl$HO&(wV+V@}^0=-)szs_R4 z9$)^EsCJ@_mBZJB&w+!zae>#ZE`sQmSPu^CoG<r67fpGNt%34xfY7FgxBujI+3>cf zF}dGP-}Pt*>+Mb>9)!4ZP^_t+!R~5WW|mBfX-KP*qNPH%#yDs;Fgn^^5RnZ@V4F@< zUUP~t?vBZpnB3W<E#)|OPGd*q_1Wx0%8z13&0Qn8^Mx$RN%eKjy_>Jk-?vhJzDn2p zXs8Q7z0gAfYf89e71GxKP<{jc#M4xtJyA~4V<=>f;vyWn3HpEL2|oof=_4@ft$S?k zrA~Q33IfRM6~(P~n*3<jB|%qOpj##^ODup$jdO#vh(>FDWY*6(U;In?HK#@S{rWHE z$KSscb_@WGp>n{`gkeB=7)U1ux{QIHV&EK62y_&)c+@(zc*jdRM|t*lI`VDgsHtXH zToXN?Lv#om&%<Wkm)dfdg6van5A{8Lf^m%Q#A`Q0u#N~2o&b%-(Y<za(O0G_2?=}} z9b!!@9*`Lm6&+)`9AnuTW3?P(jgGZ(h_wrgy^$B|&>8Er9P4r#dy6B^4ISs<5a$&Z z=aU!b+ZpFq6Vq-4-*Pi;S7FE~r@ladlnJ0`Zr*$I@gsHs8&B_t@s3Z8?~e$pQO^0n z!36mAR(fTC5HQ5Xu?Z&E@)Q{=aw{0pt_{O4Bs$^1Zw~3@52^Uv==cC|K3r0I6O@mT zRC}7##F5;BPHuBZ?g&fn%uDX>OzvGy?mtZ?aHI^PQ-&Q<M#ECZ6H@94Ne!o95q@Ae z0uX-)pCCf@-BRD9;rfA*Z?$RK<>4jesmo!h`iBgD{8XP08Rj3;f7XVz6QO?EuwE6o zc~dHoAoN7u-HiahAlrnTsQYZNc_CmEqTcs#wvc=rv<nAY!NJdP2+j;<)eNL#23vRr zM}7uZcm|&~$V(o9dCUMy^bZj>R~=yk4LDr@uxCxMU<CDrJcTw%TsR3WEUHcSgh-dP zOZVx+m5(?o#bZWYPNBcr*@mjw#*W!0;n}7u+2&{2W}G>e5;<0?IX4`0987YY!gHMS zb6n1HZgJ+is^+?x<a#*f`iAHF-OcsS&%NK38xWq8a>%%O$k@vde|E?i94K-|fGCr} zo>p1Wj#&|$+U1IQ%3t9I`Kr3LFLb+J=+V*G5+GAVkPFs;y7|$~t=k!peBEG?B7U_e z6AXHpj7^^E&oI=_<ny=*_*W8njdTUC9kZHE3R-Iu+7k=jNPxR03VK!w2xkR@5(UF| z3r1=S#=aIza28If7LJ}3j?)!QN)%0-6wPuLEvpu-P#lZa!i!eVib!<D>zu_~ss(*y za70bQ0YBKq?FIgjF}&-=ll&Kd4~v5laC~XrkFR-uakQt7FM_S8(flRBZX$BQHZ9Zu zM}Y0smj(rN`Nu1H!9;q0?J~A*JjWh*cY>aqSVkh^xepn6xXSs@%X%fsc_hnw@0JVW z%SE8&;-=+N&<dfta&AJof?oyNsX{KITtltm+FrT#YPn)Wg_2~YAy=hAcZKm}rCCJf z^}0$mXqByGm8NN>eNxp;e1-FQg-KnN-ei^gUX>-j%HzE1j#IVkYNcIwwKcTb*R=Y+ zS~bsP!ILJS02$oJ59X>%IIJxT$Cq*7Us8e*REHBUpW@3RBWj-Ry`(wMtCRo(2=E(M z-2=S5MMoHRbV?H<%D#jbbCbd0re*bC3;3O0*5K=ECkyH#>KY>I>eb3$@71-amA9?d zHJsPA;_KU2>%0Bxdz0$xy6cCa4I_K?eO&c}(E8!YhS9x-@$QDVT#Zc;_3yYEK14K3 z;v0$GjWcSE>*oz*zs67ahAqigJ4ub(TvQuGya1r$31=P0<jW-AniG7DU^jk~@UqOQ zCYh@)g0n1LO?VdLC|^UZK?OjV7CdVLmYBXyaD2@`Up{Hl+-%ZZ?bOVb+>9z{=DpY4 z9p22>(=1%jEcm2FguX>+tyw&o(jv;;BLA&La;in5r$vFjRqkG^;=NW?vsQJpR!y@O zE$3Ek^;X^FR>QRx<Ed7YC#`CKS{%x2eZ{gblU|&hGYZI;Bt*Rak^dqI-!549qVg^; zP`&o5M{W6Mn{>x)r~0z`6+FHhD2foO<g9H;Y?e!Y!(aa<{9eJ6Z*NrB-n5^+!LGeg znR@g5N#~+TC#Jq7daaZ9PiK;IXQEVB?o?+MeOCf^XWo;pxNluKYhC4kx+=K4Rqs`Z zL4_W#W;>L>_`y|@*o}8AcyS4>Iq`daB+=ww|AOAIwj6-9+_aHrZc3bd8MBwi#9gjG zQIf_fgq!HCpzC9<%bs)YTcW7<-TT(Nyw<x=(D!kw@BO#F4f_5y?!M3W`nR9--IMD7 zTHp80tpC5{{-gT-g>U^o|MVR{dHcoe?fZLgFO%P1sP|E%2mlSjzWQ4b?CtqlKkY>y zcT;UdQgKvLajaw=gH(xt)9WL(rkiW{apyV?`~X#fNRn?y9_Jl%51aI_;L5uLPxtcJ z)|#s7UI=v8Iw%U?j2_a-8d4z*X<Q7cqlVQqhObEv8<-Dkrwkhw4jYk%%`b+{P$Q-q zBbL%5_U0p2DI+%uM{bfvTrNhOQKL>8qqn3-z0F6j{~KqO#&b=A1jwWQgi*|1H{X7D zd%?gD)7OB4?xXyH@wFbx9uRxArV04xrSqR&ujCpo=<9Lyw`nj!dhgqe!u~9m30&kv zX39i%!$fZ3L~-v#32CBKW3t?3vM_S8EM>B?VY1phuYP4b2~rcbH}HnO`L%T3mHn4* z_PY^gQ?V|C`+*(Il^qHT`16SNC;8*py&5L9o-=$|t5jW5N;{Y7OgLvv0@uuZ<jgx% z&HKU`@_xsAjoD@Yo*mN6?(_^1HT%_kwz+<0aewCcVs^h__Mmt6i~rn@l(_}z**_OE zUwUVL!-$tI#Ph=0eQDxfms#3I;`eFd;r<+>#oU<&5#c(=W-$-CKcD0>(BeFEB$4fq zIgYI@AD06E!Bbu*Lpx&YUi@<E$$*vs3%Yxqn^dT<J(yZ$iJpjk_y#~IxQV{93%EfB z?^{s^5#Y1Vb(Ey`efiSOQaUsO?(nUIgjvEP!0DX{53H#Fbia0_e;>gK-)y3<KU>t2 z0S5u7;-OTwPix{N-vwMQddigUPcUo};6aCs{A4(uxM0UawT~!A<36AX@B>6$MCw9t zDgN%vV$$j2A1+V?0<Kj=yJ<xofuRl~7vLJlN-sMQ$?ebZ?aliuHTS2h`c_{yuD;S- zt+rTg<XNrhd(nJ<we52CO5~b)(Q4cMwT7a#w=!!jGNkgpwSlLk{!|h{b8WJ5b;gx6 zN6{qpekb*E4t7U=?35T{n(PRqU*afem;ShfG+RB)ACR+n{fDbSqNuw^zV-&FS39$o za^7(#l{&r=OeMJzRQmq<_tyuLQ=0^a@Gkm??BLsE_=D1fO$6wG0RN*_dedrop8z5r zE``RdP)C3xO5d3@f;TbL1^@<S0F_4m(ncv*o*8sG!(b-^7r;>4$iVHs!yhHaKR|#a z`d>!?HtNn2HmsJT8|maSKWNRsQ~O?5*1ovi_j;fB?m^&^6*GJvu~poJH=A8<>)qxs zCv_IJyI2mn-uehg8}P9lx^*kd?b%L$;*MAUjtB1-vGbk#x4t+R?{J}ZLesubyk);U zw)_%7`7*%pCG^@3_SWvR*)K7&gQJD7+gAoVRF|fEYnZqe8dugiOvfmuU$c1^wHpT} z9h<H$l&Z?~wx?|W?n*!$<e_o21^|(W%LK*70ZR%<XZ^F1ELcqzEE!-F--qwJR%-Vu z!S*8=O{TkzfPdqJyKApl%ls2SXarb|vZzT}+Hb;3^9mWuZrb&edu8DxNHEJR`A=O! z80G_!0x}5PA9`}Y?vfRO0pp8Q|Eqm>K>UQiq-|}S0!R&gnOVAZkf*_O2)v&6#^TU| z;gB@5>QH~^Hg$NpclZnX;m6s3EPNkXZyz$t9n!sSXG%Zfy}gQfPC2?&a74{`Ec*Nq zdHWdj>5%KcW1jRw;n&Asp4QYcl+et+W|TV=;CkQRwR5mK#qe#H-MlC5)q=s_-3m?N z!x{e}7(h6w40mh!5hpnRI~c$Z-va<15%weaSEU=9B%aacG5{_Ro9I$79<Z@V{N!!% z-VwJH|D7&OqV%Hl-CxA^A1?T#Qaa~Gusaz{M8F-J$i!POY#BD7^Z>p@x)A^%^gsAH zKO9iHqVtMQTKoN94E4gRpEPCfHu&klQFQrP1GjlrP7r5aGd`}DjMvhrZRfUr_H_zh z-zmdyx7HUjrvH(aF6rSb=;I@GF<zA3UyHnTA^Y@V=o9G!rSZ@7gPMNE%ktEV#RnJf zK3$A7UbM?yEL^{M`}Shx@8#^=<-qel<m;CoWIB@77e~#>m!`d``|bPJ$;01jGU0;} z7gHINi;Z3M0QZ=W#jc+LfYSDRH`xHelruU3v2s*EaA4EWfC1d#vEkqb0Aqww2@Srg zaUo_stAM(_Rg=X6)<$InpNy=C8?mTs9Z1Jzv52O1-VeGq$rP`E(n4(<?gAy@Vm&Gb zx(O`ovphZW&k8qjcbPDD&w~AyPG6d!FoA%RrR6F*?L|R_?dcO1qgSGF%3i3E4Wl%2 zA@{+1^6%HnTAX8p<eCkM8udXEL|x-6F?~Be?qL#T>P$|5GL`AFvSC?OY=Kzu5O3JH z^23nGZIE>%9ACcwuAQe_RukQ^H`f?6v~E$@ar9v@>rej7>eWNiP}y%EUYEyv-$q{Y zJ)YI<{%>vO&5vIc?u)bR>UZ>UX~A#waw=4`#~v)pM`khq<peSGuURTiw+uk0YXt|5 zsma-~3Fw4e%@#K>=Fb7Qw4N58ijWUoQ!|D~47$hjwke)Wr*{e8O%MevTT@}4ryOtb z1Ez7wMS+``qY|#jI^&o5@FXL+<{_Yzqr(msPc8gcqL!nHFsYm75$e<c(j1=G%i`Ju zOqgl}hE?c>o)A5SaQMwJo}fS+5b#LegYtzBao(EJ+MyKwIW<2i%)0RTumn|ns=Shk z5(AU6iOMHg<ZOHPFLmPl;45{D1q!)GuF6P3=D~u2j3&~~LSkfY(d;+<qeWADnVfgF zMzQVIj<(D>wl?=ukvDJJ=A?Zve`?Ua=qA9E+wbw%pu-+UTd=ET`IyE0#{0n5nT|zE zDJvBUbpL_S0~ILqP1xMW@u66luCYLzSI;W~SK2(b$b)h^$fG#uKrh^WVf&vfpqHu? zgc=W1Kq+o5|F8hOLUYt;eH!-@(_;#K*_i3$5oWA4Nc40ISdHFKMpJ^mjdl4=>Y{x8 z0NOIy+XOwhh_Tm8P^)fkt8D8i#e+lIMGhO#Sm}3KQH#w8o|2kY5>lDp4lLRge(<w? zX>a<Ox?O)*>p_Z=0ZU)RBK=VDt8Xp8)z$mkCM>^xyCCjx9Z=7t&3*4~OymC6^^>>Y zzn+!ZC*KHtzk2Qu)f=K7G>-U0-fyZpFmDPjyG-xwSNV*xxumgW7>HNwl__tv80ucC z`3>MtcD0N`lxbSlHkIG$`}soek=rQUM$J|B$FBm<8;OiTq<s2qrM1i`p8TDb)K4V` ze$cNCTu`ugS<Ibpe2U9K>pT|PiX8eecP675MqrKZ3JAZH&q^rJJN+yKoC+$;t=Bty zEndmd{MRkvYk-td%e;x~=agcRq6B^6hwp;9O<^o=OeFTAI=EJ!?^YCKp^1JRODQ0U zJaNXf1Al?S(uZmZoGgYoXYK|!I)OY+x<OowbfG)Qc3g-4*<p+_Y6B{FI>ZiYj+d!) zXR;3)MwJue7*e?I2{Kp062HaNm!(G{y&LLH=&k#q7HnE*Ce?ji{&I2S7}7gjgR-f# z4IS2b)k7YDbC1-3#&i1NV$sAS0sgabLTDLB5I>zF{|eD`)Q09U$F_M-O;icZ2wV~7 z_gug+dH4b#)QE#f59$f~wt%_vR%$YXo7mOYg^|ho9(tF@w|+UyD>6F{=SF4F!9yl; zGo)evUSg=#AjP*UP$d4|N4i=4(w|aE=Jl$Rc64?4@Hcmor0`sLQN?eb7K`qS+N&`h zaorOo4-CZ$r?P!iZ$6y8m${ffu_b!touft2<d34YhC6EiO;|2Q9cZ3Jt@`fU7Lzff zrSto<mFHh1t#zzRxe6Job{0#)2EMwmuWsnm#p%57$9(sXVqB7}U_lzAf}6hi=q)Nv zRW~ZIaWI%&doWE6*&rt8#BzK>)e`7CXd$U+=d8`ou0`JP3Jx3kJx*lHU(!ZB!x)zN zPo`;wWlE;2#)%$#OlWUn_%_0*c~_&6ZPNw@oQo!Xfzho9a+I*#0-b0}ys&+>geY}p zL0yOl<?4G(oZs9$KdWsR@olhJQ*0TddzX(xAdh782d4%W+CL6&4Ljnp?Crf-N0!e{ z#9AE-%e|QXtPCc-Z?0_Lr&n0JNu=s%F802Eccv<H2P4|1+BL1$Tq6TDth~y(<@7QH zD|5R_6s>A~lWVOV7iTvs|Ee~Mxi=&Q7o$jphG2!8sQOd9%Wn0%BpYPYumC!-tXIy! z?1BL89MBGj)`BBykkF)6YJ-|Z-<qD(2ccX9P-Em6b?s>Ibq!IeO=B+K(Lpg{pfL+c zo7QeTuqCRGE@wPThwXwK@3Cu4_iUL~;!CBO&WJusFu&dnT|-tBS`VbAmpp6yrjhbR z)Ysk<EA~Jhd6nxn$VLt1x-R)f^8QoHtKtKU8Bvj2yi%$mIy=spp7vfU$6@2Pw_0+l zrt78Y!>6>KDQ3N%-j=_YZ|ydluEkm}Lu;CxB&jOy+jK+rZ^)wN^=lv5<die`t(EAT zvk<Y;*<Ns{D2fSUqHt1L-rQs$eeJ6WIs}v{O>@i;<U;Sv&mwj)vm_qOw8VXID4OD{ zCautH&9+WZdZghay+7{2uyZ0<a+L;bP-DxW6i3Y)2n>IWUZ(Kd3IVKCq*zyPE1U{^ z>dF>|J@Cy>JrQiSQSqLKEX@&Nl@4ZiJ4*WT#^@_w@HAZYnyS2yA8^wKgisz^ecY*T z?EJ`6`)E;&)Mla5xAF8p-<clLP^wD*WuF1&$J$luza4#RuEoz=xl7J=*c4d}44qw# zbnNXIA2sdDsC>Q=jmVh;wR+1gxcIR1;(2<Q2VGX0qHL}#Fxf8;!Yy`zriu{LKEiQc z*sc@7M0H`pG>Q6p=}6WyqTWqrZqOr)8~Y<-yKK>Ux*%+?;>Qy`hA>H_&RJPx_i%z} zHpX;-h<t(1n~ZF|6PG%?0aui7dS4K4it7AYs~)|aww}z=>b6xI7d=`G^S)Q~9bJ;p zUS8kSfCrsJmAMTbrYiqDl{D<XmNvJu$*y)bofZBg?{D>v2xG*!80F-L<9_cpcltT; z$+MFNxxPCbj7^)P#UWHPH;OO1#2I+oIvR3Xvp;{<@*lkyP)yH`{4<@FG?^9(XyS3d zg<eRB+Nw}j<TN+|ME_vbGdXc{upvHUD(%hFf1rp|7p1DcqWR$YSZDP0$i2iuol!>R zx9tYAf>>AoVGCnAELT)gwUtCDN50wsorOI0Pfu{FRaPYj?7A`3buUTYN<?*>>XDU1 zp-t82@GL<zr)w)`ZIZB_YUkB8wpllZegQ<B5L$j!G#T5#PE*4{!~URN<xsomBS9w& zE5^C6gZVSS?JvXEro$_(E1)r$1kvS)5#%@56`N)dypR%#r05D(GOp33(mUe5s5PWc zqWv9HrwCH%$&7*X3>n<2OFb!?XrXPVuE#;LIj8Yq5NZ)e&L#quV4EyW2FVV{Cf9K0 zBvA)Iu$+zzt`W5eqDZB7?MD9VZqHbP8%K?NW-AdYBO#<k7K+a+2^5c3a|0u4lu+YP z+-^k%NA}CZ7&&<Z<$(mrd90m3lrKmUn-P_jNG(oOzS4<(Q%a|4{Fd1>uUtJ2kBds# zh_R<fkdC=m@oa0hxn21hckOC4rUdUbbcS=|C(UZ^`{&FHz~rgN{7wv4q>RQE4Q00s zYdFUqc#Q?R82Q<aJ)F)BQyL4hLlOrxy;qD#6g3=yN{qag%G#o!>RGelJOKQfJ~x27 z_7JDlS|d#m*Ig@Bn<&1`94`UE&jG5_&%t^FNz+#JfBuLE07MHry8|H#8A?b*7IihG zIzb-U_9H`u4vYu{-}FnW06-rTP3+F;zRc4VLZYOJnStbrOkZe4g8nnKxZXgND}b-H z>FV41EC&9!$;9O9uq5f4iHr%Vb9LjM4ft9VtEj&WIibKIk)7Q|Q`yUi*+!*9W9*Hv ziouyo3bx#TYO2$J>i)kGVC&T56I3S+N7r=vfO+X)h}qi)vwlVM-jr$od~-n>9$E7O zpGq^OhI03Lbb62GUAokby_a0QDHLVtu0pix4t7X6`bB>wEpKV;YTL}p@C>PUX06h~ zsfPL^X@-oP-4M21Z<zVCKciL(BumfkkSw-OEY>P#zP8PT1<tOA%&wkbR)=RvZL=F& zz^$!W(*EoLYW6$L?0;<*N63E)bDv2TKS>t64zr(-mVY9zJ6XjVaux@2q$=sRj9{-! zuJp|dv;r*zF^X2fCo)v_RzuUdAPcMJD6814)__W@v7}t;M=D>{6#-uxfSTf4Q@Et2 zD+?>BAbYcz5Mz&S`W<XhVgpZ>8&=XZQH@xY!4%Ixj!Pzk5X6jFH=_%F{j$TJ`@uB} zItyyHHt`-ZhA2J+ic+G(1ZJ$kzMM=#cT(9y<Ij??0<??5EMUXPcr|%m<`tX-Ed#Ft zlDCV+SQ1g;Vk4HCu)So=1FSZs5p`S55ClZY5wT4X5-54<R7e!sZP8i}YQGt6cM;8V z2JtG5JyoE`N-*<AC7B5gBdn^ftundV#&3k{BXCNO1M9+;ncC>%H#m_}-op%KbjMOz zhWOM#ZIH{?>w`_{uLlMOdl^}NmUGffn*whbf3=^uu&3=#^K75?`e={1l)C*9=KVd_ z*Is4zWXi&EW`Ri$dD+RcmOEYBtTc>%S6LmR8cS!bx?HF^wTv-oOwifWQq7Cz%8O3I zfLKV4aufm6isi=Vw96P)hgSI{C55CKW30*dx6dWAR8FfhIhNnmC?y*^us$rV=17qS zL_MjROp?cP=0~HKV_SA_M9lzsi80R|l=ZCRhvl<f3BV#2<ish&_-P6s9aaz#?}{)? z#$+b>E>c6|AD7a~l0k)Td_`^?wmbwu093szK}SJNoQdnwY*lhTiRDj1%%ynEKGc4Y z`Y{<)7s8uK#Htd~U1ng<orn+ot@aMB77%ZMvCj80og*upNeRv&Q_dLu`S@?n_wWkv zqI3?Z6@PNS*?b>cjyN+b4(ZL%zBG7;#PHtzT4G2)=cDwg(%7(%3<3OfX<qRX;?We> zu$uUVs^XT(HAMD%9wfQ7`@M+q2iELGp6qHO6ZURX%sb<3swjCJ@M$1#*^`fG>T5cQ zc20oQa})i5)A(>&dKi(jWyU(b^yBi#t)N}7lY{-CHNCx}frfaN`e{N@U~vni#6A{u zyGIF+8J6gx;*HYQ%dpGy=1?8yuuY9G3{SRcV9$=AmdiJ=NT478$H3lQtU3W6N+_Uk zOUgXRoNPJXiA33tv|hWZ&lRru`<wUMl#cUQ-J8i}1TnC%z8}tBTgSTi(2D<+*g))X z_4r?*`dTt+&hOtRFd$GAPG5ne=kBOfV9<rXwVw%;6cR$yesH{*TcG#2ib4w$X6KQo z_vH{S`cw0Vp*r;x;>uNG@118)>nT0zAwRpRNb!)n`nhyoq-lvs^%TUr>?rw@F2zCF zRnJr5s^|Gxyvi(Hj=6<a<T_#~5m%KyFY;N>a4YZ><OG?>t6|PQ#tN2djdntsh&I@E zLN`kiSE;IyDodLbQqLq&E!52^5O4p3)2<xKQ>Il#$S)h;lA!|^^t6A>z}kUIREVFy zhu}55<6oY}ODa(F=0_`W#`)~cWth$QNs#(K_I>oUlJJ|l&q{n#<kQpWbC=@m8|r+2 zhp}TMOAtG@W^AGHup&CMoWkGFnOPu>oJYx4PcA30TYpIOg0N6PdQN0xVv%V8*|?R% zISpo{tU#}NNaH@3^W4gJ>0xi|Xm8vz-{|-G*c&V+Rj{k`*aWwUtYF_bpCO$f@GIra z`-j>o_j@9|!EkYUcxSZ4GT`uR;d$V#*y^wN>aR*<AkT`a155nXuO36%^g#e%k6N+) zWoA!zR$vfk#_pE!34m7~`53UIGC;>Eo^0(A&u}Oa;704~05_>;3B~kiC^Da9QFpec ze$KFS>4H=$YNss6o>B4X={U>GLgl!wB^00;b2Y{<&5-Y{a^yGO=5F-!?oZN)5A|yd z>c5XedSDVekqc9kwl+6{-~p}-Wac!#?M9B!G=-C0%9x?-2Nw@j7xO=*u`8vMc^a!% zwcAz9^!an*<U6UH>&OYL)loC|r3ZnPThyz?#b8j<(cJ`3dHTWS`%$j%j;v{&AV3Ro zDq#Y(<tS?=dKf((FXc<!Xa;yn2Km<9lo|be6cA7_M6Ku+b=lQ@mYGo|-fquYzYYgS zpc9&@r_A=6RB&=hXYt3NC_!TY;1rA9m9I5U&hKo00{}dmkC7lyUvX>0CakEV6M)w< zEj1O|IY73>Qs=UA8ewv94p+@p2rM*Vzjof6jpW-QBNL5ZXtDYW=$wx_dU)@M^Um5@ zOAzPlF)kw_EW+i>@yjmPvf$$P0jjODD-`l`yF2rtcUWb{<NT4~{mBV5Z7a11*`=C} zebU)@v_#&dv^-TC8bm$8h4_})>}DHQzNq@>$JGzJN?`hwQip9?Gn6>UkSp0RL<oJ8 z4oI(HlIr)yII%i#{Yhg&5&+|h0RhATs>=?NPNL}BUVH;U5pkf7buylXAE}p=eq5EZ zA$fi`0l|-5M1UU=9Ub(mwtJiMt*WexU-vj9Gx#chyC<LRl}s~CgNS*wB_rP`e*)%B z$vXpY)xKb_y;(xea8`z09Z%{7S+^rMhS|)$65adzL(M0CG5NT-e+|7?V&?zpn~$q` zyniYS95HmCjeFaj8#;Y^8~u|)oPGxjUaF8$U8c@fk6j3OrL@TC<W@q3PJk*<b4PI+ zypU@ma+WT~R&@tf5K9_1<MMPQg2wC4HY$$3zQA@W(Wyh)9wrFig?y37QwB0@_~6qe zK^j)fP5cKQi!lsMr@39swihBir9hN7hav&XLAUmVxAJOD7`Flypz|hoa{?5Y2(a0; z4+eW-_85@J8#O>42yl{LvP0f}OQ8KkO70x3pl>7MNDnRKZ;zn`+O~zgW%14j939mH zS%InQV)@Nlew;w4{MY)zPiLiq5?XH9gK#G5i{Pe<xB;Sd>GE1n;b;f20%u0Lhin0h zq)vd11hOwAr!FYt*Y&2;$C%(&B2O=#R1S4EDnuH7kx=WWH4uNht=l$?U-{Hjb9ZKk zzU@h91#Jek69g+U9^XZdyXp{_ZIZ~I!DL;h?+5}!<Q;g5Cu)gjON)bmljpQ=Aq|Av zHw);x(3v}fz|R567eEY^6liPUBN}Jd=s+)@kqmcMP{mP_(V%Ze#ba*quO)+uU(oN4 zQAYqETER))8CYt7N+?t31W<mP51{IJ0XP+dYY!)*FUZSmM(`f@wyl_Xy&XQ@fP?jz zpbu8*oq=PaLGDI|a0n`RYqt!-?^1|HCn4+0e(?1KMkMWKu;{`Soi>&?B&xsg!9$&f zVyP+oZBj(6)X>HmyCutL;DgW&ZK<@P6lvvU&Mo!;u@*HW;NcZ#1-O<-a3`lbdpwU~ zT<~E2&!NDfw=XxhwBbh&zPx34rsSF1x>8#>ab4<3ZdQ1!_F}OLhRs4X`0HY!{qtNH zzD;|jR_+7*DR*eVOsm|Vj*FA8pNp!~f5hEi33(7Vm-wd(#@Q0QSwySG>*D&;JK*EU zy)WO-6eAWJN+ji^{XU>m+CsliG6y~SkD=`<8Dg8qrw%{@sB}qgN}Qe%998xV5dgPr z2jm6@YZy^V3xF#&30ZQG%#{TI{=1*)0Qge`DAtuTcEY2q8GA$F?{L(Z*C%6ELlgzj zwCHA#1tiacIBXKiVmZ7!%hb^PBFu18dpoQ;Adp5o9<&E!h(k;?(*yi@knw0Q<c1{! zAi?v7MqG22p~l}{YgWLBTMSqUAA_AphWl+!=#bpn9U#i`qIb|2C>j7K0A)MR9qcaz z=M4(eriZ(E#8@jFD1}=&|B4z;V>Td;Y{YETcvgzWiza1=DJNuYWoF0OQi~Sv3yWx} zTK-$4RMuvhWuzKGvOHeN>BzcYmvObokC-FsdS|NIh@>^5Ti@_-(Zff^cUcj<-Z2+? z&$Xi{>P10Nk-(eAKyvvSm-oo3&zjeV@5020(&n415i2df<h*|;tq~~_KbZtR@jB9o z7yE2PKIW9!-?zcsB%#{O^d1@<W?8x?cxLNFkdK7YwRvo@D51CSSUC+jMbgB4o?Zy$ zYk6<*SF366+W4}&CxA;fDhIHc8@Q+;8=Dp^HRncW1r6`B>@LM}S;mnx^-X>IA`4`( zBwWj|rfo{$0yz*re1B^%1*J^ZNf-4U30kpu92>+Ax1K1YhL4cSYWWV30!C>s@c9Pl zk+#MOBb6S#cd}l+28?j4etT-82QJlPm3Nedg?Mv*ga{aVafJFM87G_WB#)6~s>Xv( zk48xK_bkjFAw*(x7ge2>viW-WhwvzWr5pMF84~IF_q)CeQ&4_?i{oznn9==o@QCr| zb<)og@9TXJX2+gf-or;}<)4;+&6V>RRQ~YFZ!EQ>IQX^Zomasm?~cDiMDHEf@Z*<_ zf4|>jpT%)RZt3w|w>P_TyvPXmt7g0sQ^ugqY^AsC9uugK3w&IwQ`c)lop4cM?llP1 z)cwqwlp?RhHJ(&3jpSN<<Q;$%Al)8Bpp&+0v^I(QTqn#~)Lh%5AqtD*0IV+S<blo| zXwttOft(JW&wTDUYEHw-3ZVduhb<)j3bP=8vZgVdi2#J~59$<o8KAQ2NCp}@?5!7{ z?Ht@`vjrDeQNwz00}dN=uI-#SUqR9RFufb0!#bhM6kj7WK_7AzsUxmzfx3wU>ML1` zs>fD?H0?}L+?(-QNkcq*0xqa>4%XhB1hGah@S1UX>2p|x<M8C|%j_)aZ@cwQGj+Lg zW9*H$k{I)9qxj_VZKwB8Kdwv)?#ShzY1|QAlvr}wq5Rs`{L%%|{51dKf#~O{gT#3E zBgq-xa`uAN({IlKi{^evYD~2Eh8v)Cgx9jU>0x!Xn#OVtDg_Y_4W%=4&l{YpL9(cZ zZ9-Y<bjmdbXkU{zINZ2a#xtW;VTqo)^4u=v)l`6M_B6P^rAAEBHXJNA!z{{N6L~R6 zen9Vp)J2ncB|u)$qODQD6p9s#$cd9Eo}@_mn&5erb`c54C~77hUo6#@&|(O!6dnNd z9Gqvoj<#SiJvE|J$7ff_+!r(YHtBHy5G@dY3Gsq_e7Zge=M36qXe}Qw-Wg@Tu5T>^ zJ_FAs9cGEgQgeX@bnLGpbw~5=vYX^gc_ks1xM1yJ2!-u&7=4E2k{f#vVHu^(l9ng_ zpW5UVczdal*4OdTXaDKV_%$Z>ZQC2Q&v<<IFR^uAUcb??UeOq^`-SURlh$?7cCIrf zvDfG8vGOSkIT%DO`;#ylIl92tnb0byijprm>iR<UU&ZXixQ?W)I6zCDxr)mxidU_L zKcPjDogt`6pCd!Z9G)p28dlChi5q~%?dS?LgwV?55eC>LV{4cbYeD}$Jcx3IAY?Cw zbQqkfs^lLt4GhY>eX%gieWCsaOP+tk3H7McPh=YXXv*wPuwu$SEWH{=TgJgOF4i2T z%695g<0Ie&Ar08R0FX0pXh4XvB6K_=_SQ)@RvY8w6tsZ?eV%bG$`>b!a?zo)c{0Rk z9rtoR=`+JE1^k9X^a$fUL7Ke5Y+h(^3h^s&#PNs@uoM()BdBjCq8}&2BigjI^x(;d zA0p-HBGY7j#`#&HkRFcj{Ui-1)r=e0D<mwq&7K=B6qMai8d_|8huKkw{qd16yJ>ki z{jH70>t=Q8cK>|m6}P{X&G)<^Uh*;C1J_>O2!Z$p#iG3iT65|l#&99{$YEOrzr=RK z2`(pE-bZm0=Tz6Z$!W4)g+okCTEDuVtCzdQmr{|;r&Ja%pEs~(Rc7GHUmoAepBkFn zoWLhqks~T0M$gV<%vOG!K~UIn_phD1^EeuNi)BrI(os0!MTY>mNCI`0>dgZfGu|#y zi2iH$!}q0L95kG9gZDW*#cumlPhMicL4jO1-}kZ5CJNPB4rTByTNkx9d98ycx~xuv zzCY2cOH`*bvU5@76p*Wy&{{RPc@^-&t$8#IzBuja@>J_<0Q>DVFALS8$1+jw|6Osv zIkSBB^U;3^;O`YTD1RCU4mg_Mx;pfsEP87myFAwI?tXaZmG+icze_pzS;4LM)iaB4 z2h$_i4@~&OzOiJ0TB4LUQ<i<k-NdP77`$l3g_q^6yB8E_bhctce4)CxRQp!?pCKae z+St07jZtn1ASQ^Hfz0vt^=cn>`17BiGNA&?f*&O(8tVqKYc&mAfq%Or8$@6TlI}4W zIi`O6>if=o`MlvWBg2(752Qus=X3az{vrJB-t(g8%I}W1oK-f{9uvzeP$Y(vw{tvU zw@R+GvKtHJ+^#E)<&y_-UjSr~AI6$=*TxCjy$R1PARZ|<I#St!>|At|K793F{Hqk- z8pw4gfx5ZR#g~GLZKYW}-3R$K$ALkM`Dof$|Eaq9IF)ydC-T?tdV|Xx-}!PHa?uvs zx|L{WuhT`7!!Y3IZIE?4z9adYj5ePFkYg9UwuGf(4HI+Cqt$E8;Ide49;@5tNWF6M z0C#87cp$BMAU66`$A&WoG_H+4EwHrubYfj%fMRp~$6bq?ph&>6%NPTP;g<O_9=L~q z<!v6PnAF1Jn98K3$lGs<Xm8?ZpS>e+BcuL1)3Nit4dn&<jWa@eA*XbLKVvcIJi(uw zw7gzGDRLBVjqYX9*bi%Cnj<88@2!&<f>?2u>}EMNs~d`g5pt2C)1-5&Emo9cE+1KL zP%21~+*tz^dPvB6@+(#pxx`tWu7mtNfB`W}69jf+6Z7obXe6KF7B?jCR&ogP=hNX( z&Ghn&RaK@re{ryDnDbA8<lq^epuELC7ts2~M^|aX_H7#qQK;YCR<`f6&fw>7u4~n8 zj<p$1nwv%K%4UDhZqW@If>uj)T)cqQQ?|bJp%%#-K{p4q*CUO2L)z%W=XFt?snLLu zDT5h1OroQUbyXnF$}N?)JVmF2;ip2HHN*hhJHXQ$HA^dEd$meuOZ)P!ZabQRT5ZNs z+Z}>2kw_%l|FlC@3f*{0&4>`zu`G9#+%W22*J_IDX!lMo)kmEI)WvV337d@fDJUIN z5$+}f^So`xbpvP6j<6qdbKpBchMde{{$H9UKgvYh)O>(@x9|EI_nU~YyS!tJ#exqB zw^r#spZ;sK3;9ht+gASwcqeC<0_|Zk58R8t{Qb)nL+Tly{wP*I$5H+k>{|gd2C79R z9Ya5JP+M5mdLP-oc;bFA`Q^Ln`aZIOtkBv@wPP<zs?g*6Wy!s#rPrK5%l2i*`Efi8 z_!9Zyzvc!4K?dbT_&-(xgyF@;CcSGbEZ4rW07!1^3xh06!Z)k96YMQ<_T2FO!7*t= zvoK~?-@*r(;Bapp^X?&5;B5}lG(_gZ<4Ewid3r#&A&O9L*+jMLHp54mhxj9z?E?+Q zH!y0xRO}8_d}P*NLD=}gU9EBP)QB2%)An&rG2&p?wn-Pg?`Q;Ms;Y!?uMmsEmlQ{9 zQbi>sW_L3?46=HGIH<lIdeEr1REc&y4eBlzP%HQK_H6AMqXBUu9CRy)nj1qWdesye z6lE2uGwmBEi6IcI4SxiU4B=kb?l6~aWa`Me+U!dB3LEtw#`O(@o;5KBT-_+<@+!IN zcUcKy?;LVHjFUa*>s4aWYrunZh22C)EXCt=EE6nyNiNlHm*VRH;D+V?0Px+|<3?d> zgSnSE>{3c5s0Q)RF0SnjzDv^<V^s^5(PG`rhRsc*aV~}w2XyL<Q|+}Si3hjvkNH2m zYzDy_^ms_llS&30;{bTC4v9pI436PzsQD!kE80W_8IO`X#dL%lQa&c1H-7%cLr)No zf9>XR#;Svo)-DK)LTg7I4KrL}EfqyhHA{<@1&#gA0a=Cl;EQ9?1fWc5LeWWW__7nL zUqkczV(mPrz4$mED>LLYN{(a4!#ts;7ii?d{j+&ni+^b0q8Keu%M)s*##ukRivLXm zd(t%KVs*RLoF>$YOMW2z<94#g=??AsMrgU;>~VwqrGGh9*>)`Grugmt4WsY*Y$qan zNVP00FMiL!eM{ky<M24T7T1dAJA}@c!1=65QA*0|mD;gex_nz0NnvUf5ukYST|ErI zP&uG}s>?MUC0VHh=O1F^A5!Vn<BHVdA`;a3hfpx=wvX&i|BzZ`6c}-!LL{i91W55y zZ~Gj4nguGthPKOPzfr#L)yeL790=eBRoq_fQ5xlX^`yjgx%l<CDs{9HFp|5nTMHO) znD)`E4j1v29P+`@v!PG24~_(}lGDIV!J$pi>z{+K_RC*=-62rbyaJyL32?mHQj|Tc z9#9k3I|M!W75e&TUBFM>2fuw@Us3|#r-M7yI#NW;r(b$nZ3lal`=56LKKH-cse1ra zk>8P&{j;F0g?#Ws5DPhc{ZsNkvQHqK5(YR7kW)ORQn$MUG>mgCq#Gs0defALNY16i zfgBPS^X<l<wiUcEq{^Y)Xt?XjMrm{P80Ab_r(ZNIn)Pq?x_9BkvA6<k&X=DGacl>6 z3)>w_!v1x2eQ90!04am`>&ay2l7tfrMIUjE=rF}#CC+cujjjWl=PZ$i%_Dwc?OXTJ zBPn@6+P%Vhf0{HZJ{ckv<3%(7-yjWGivV}90HY!!&9Q(=i;$M0FrOmhk`5nw+TLQ* zz00)Um7Dq&w+5|%AEre%4hvfv5HxDxFF5A=Fd*~;BZeDv6#m?dd?B0b^n2-EQ24@F zc>*t>MT|%#Rna0}(E_e<ru5%eyqlIQ;$+j$IcgXfD@N9-BoBC4ee$J?;cQYAV!Wav z)gmUXP4_b;q|C`|aI|l0sv96C|LBVP!&cadj?xX$$B@<iqPV|aW8K8n{&51|mE)`G z!92rye9IFy-M71!=~)Nw)vPCx1Yu8g&9o%$3AhrBke}MO_0eu2YsA6uev)sLwr$~N z9C=5vKUPB0KrJ|SYC&Hz5v<H*WTH~>zUxFFN?YK&zCiPU4I!p<m_{lLBSy!kj`NwY z;bRXo9Bce`-u~(A>HfSz8soS&Fb;c!3*j$UxXbG5oO0u6SHF7`11=o<FDTBI9$)%> zxCoju<PRxQGiM-DsLYY6%0-E0zf<_vADPF$e9!X`RXJ2Z))uCla<tp&EdJEqzT$=3 zao$?<{a7jHwjdnwQN#4=9lNXEW>;gk0Net!wLve{KGF~2D$79T8et(2jo4DhUtX^} z{NDWX#y&!q-n}tC_czEexNS8&l3bS)DzNRsy5KpP_FkPM_I|=%=vIfx)%E(iEtCpQ zE%un=%GcZC&Tt3-OOTw0g?Sh_ZrYjJc#XJ1Xng{eYob+N^-J0E8aj5xWMYQhe5q9A z2kGZn&nq*Ck+4A6>Z0ft0~@<W5D3yq&A98qG_K7MW?Z#w;BQ8As7wo4`P6#0Bfrek zTdwdd=6IjNS^r$`w;x%XCoi_T@P5Ky<ebvSJPd%z!+cxc=S;_xfok=|tRZFPi+`BM z{!@Rn6?B7xR;AO_T-YAcrZV1}(wXby>Fk^Z*irS6smULs4UleJU;Q5dbU=&0xs+Ey z&f$iL;NV#0KqbZ8gwxB&$cMzFP6X<P^x#u0c{OL`Y;Xn&Vp_h`<4(ll^raX#>;i<O zVPF2koVLY5o|bHx?I%kY!R*2*%x$mLCx`zJ5Y~1mvxX<p0yN-(Mp>nrC`bvCggA_e zVPrvD;K<Tcjyezysq~~&W}N&Wh`E8uPJqBcxx^a)!Gx3$Sm}X2>_jSk1PtJSCzLGL zZa6wkcdwIL{`SRzb!SLP>;$jG1B&c~De=P;=%yK<k0!K9y1^@;eTU#-YA9D8_FZvw zm)ct!L>BPF<3Pg|AdZXx)?o|=JD9;PTt*gf1D%|)83c|vT);+Xf>amRga@9WMLBe1 z@kCawHQ@j)a6t<pMS?pLc!vR)u|rZp31ocCRT#unph$Z|#Z`(cIN{bma%ZR=TCh>b zvX@{S5{|By#IUuAP`)4s%>`pvhEePSM_|RLTLeECBl;ya^rW`)tcz<PHx34QwziKP z@PiyofvCQPJ2b_T4`Fu{i*_ttvusy)Wq};Cq;q#{e$(o|!;?<X0v><>G*moS%ZRrD zCD_#dL8L%Dig;2KO-6_0VcRT?9&kb(j1aSU#`G-+I~D*)Sdl?sO%@=9JD9<kYgihP zg$g^Lug_jOIiLAOPu%bTjcA5ZFh)WYKseYrH}FFaCxlR-gy1A*y&^;JdF;PSKJi3m z>@^G!3WR{KTYtpaA^pP?NJLi9$6;iFCWQt=yj<-dV`7?d!D)Pq&$IG(k1ca}aoq)_ zwA)i`N(~e}hyfLcaD)ei^CdP3nYfg);zfACcV`5XFA1l>sL#Go$4-19uG&Q$kjW{D zinVPBDPaYQa1ft78;+<Oj+ik(ys4p2ToyBOhRF#bC!9Dra{NHt;Ai5)ivJ)!l=J>? z14oJ!|1Er2gBA{UIAnamp{GWHe?@TMs3AuaJ9ae0)rb@EVF-?LCU*3>0cg>R5xL3P z1AyJGEJOeRpta`|I{-;Tgo_xFXvBpJ{b&ukwPzh1Z;G%Bfg=l!a5ZW;#PLv1I5{A~ zWeLYloH#ukap?2J?w_78a>UJjW74k1k3@^;sT=bOj(=gG{mbG>pXDNN<ka}5&s_*l z;fm0R(=a1gh+11`WHWZd?8gz=#1ThJ+}p(L<lqojBwSs0i05tytO=!7KX^d+!H6v4 zKQ=&Z)BYIytHRh`<*=ib<sY}dh_hso<Eh5nw&CM&V;6@Vw=AM<>d_?bU;Z3CH0KII zx`evR?zV|w3u~*R<gm@VFm_|dof`B2;h*_l@*|EcA|nnO5P}N>H2zGw(33FeORR>7 zepu+AhW>dBD2j?|?I(;j+Ne9MXo1TU9FAir92_+HXBTz)!Xb>wWD+NgctUHd22JDu zZAiWdgDEjN{0oP=*FwUML7(KnswjtCdkCZIeA*3%BI1yv4tA#4B@Au~2xk}b!r3Ve zaqw`68$XhQ2%|OC%<)j7M3Q3{BTmU;mvN$^Wf!La$g#VQwgV3=u|DdJmJqJ+#2s-? zddQPwL<B%46en~iPQK&-fImOxibE5k3L5eYzP5A-#~7h;QnYZ?{t@k=_ok4;9c~yY z;vZLW;D-x2)KNv+osQD3Hi;a|=phBYlY@&IcyI@gH+pks3Z~5XM<*P)*@Yi7`Xa17 zcUU<t#)SNENL&RI^v*T1Zu2f8cW4QRky<e-U_LqYnSwm|<S@b=cG@Un3U20-qmwwo zs6kzEWWY7X80Daj<#972_rQ-}TZpLFBC3N6Ptc+#Dl(!1z>}Z>_#+&5iU43gJ+1(t zKLC7=3KPuEt>YnNFzO8>qE=Rv&@y30GfWpZs;(qC!XP>-J^pJ7fN<ieAq#Pep@}8o zZ~&kfB>)KHMX94o;G}RaixZh}7HY^3o(vxMqO#Q#YHW@EAQA^kw`vHwFsHe}s0McQ z5GR>`SlNYf8h7-LsMTWzyH<Ag$bwR-V$b5LPQh((Ebefgdpte3fG{M!GyxzBKQdhj zIJfwsFAg$v3a23vO(xtw9H3#$BE-B4M-x5V;zpdLCgkAGW#!<9gK6bmNqQPI0U<gC z5kwd$=eqkU;fUghgBDh%B#yqt!D&-y$}Y;(6f+QpFnI6;prq%VmbnO2-ojn}6jHDS ziKhT2bB2U!0F8&Z0|)td$Sw*1fFig90GR=fqq0!1khtRt8M)S0kP$Ns+RQ;RYuw^I z^%gnMA~@~In`O8#Els#XdT-MM8Mt8=7HXn+%<=vUippcIhs*&fyCMstR7aMf<VaC7 zTAd$wU>6)HK|{Dg#aT9>4geqzM|smk2YbW9mD~Xb#aNQjroaV1utPcw(Uq6B(hyJ` zOe7ddU78X#sHE&BPMU~-IGAVz5aewyT-wD<Jg`ZDIiw?HEaag~d9#On@KUq06sF1+ z6vx~wEZtd9sJKywyqpC9WMD@E?f^9<SY=3WBO&*OWIGm8D=|SsjIHnh95Qq*QLX|2 zCQfpapiSW)`FIxqA~1y_*zO;B`+_GlfsB}NWjh#L9D@*+pxR7?9h!)TIN~6aV(6h( z88bo{rZ9yXL@f?AIL1!!U`KTT#~}a{nEw4_HcyB)&X!Z4#Xl?tfN!SfUHQlh0CoYj zHUzCHQ45bdu&Fox)Ic4GiAWAvHc_7JFlO4xNM9O8B`Ue<T6vR!kn&cSzJ;y^m;f07 z+EXMUF~>4Q$szZ)*0n=PhbV=Lh}c}SrmdC4EpvRK8Nv}wh$&$|G;!6@Oa=k~$RG?0 z#6d(d1sWWHz#)CAj~@=_hpfbCOc@yz*LYGL$@v75LyR8}-qs$Cvcm|=bKrh_A*AZ? z&St7J%8VY8l%+`O6i}gE7OavKcv{t#5}_GS+|(!Ig(E6)Vv0D(aKyW8q&ID0Eg6Di zylGj6wZ#-prp`E)sMy6-wb}(n{;y)YW+`)8wvz+!!jXo!ATE&*?FvP)%eWAPpd?`k z0d5fpfHutJ7{Fo5KUmm7r9F{^VR-9ws&gHhc1I&Lo#<|MfrF4{s=0Capd6;q*ji<Q zfMqgXc&<__GH3#Mn$T4t{V)u@dJ4M-t7#AA84>XS<!(yLCu?byH-|XGBo8qjD*&J$ zZm<Cdg^JGA9#Rm8(1<n)LDU#=1Qd^e(GTMh2lCLOABWJ#2moa5u2{$)RM97IuSJXi zd9n*V3~pRr(g<~HW?EI!NKgu+T;xLX4<5{lTE^9;iFLw{erQN7-bo57rCLUoHL6yp zh@C4h<y^kbrcB_eZ&7&uBFi`wffigSK&`kSlR2{XRJ~+Kj085Mog#)E^k~X4)blO? zFB2LwIS!2Y0{}L>hzto0hb#18JCiu0b2Z>bod942O&pDI$Pn1}DqC5uP>ykwJL5*g z6Okjb1*CIf3ITWF+Ku_47y!^!duoYSh|pPF)uu1ZdQz0iV#LQfIEEZd7y)*iq78Ji z-El$60gd*v03qGQkr{G~LAvEdp18z|!i4QFgOPO_VVx|wN5rhL_8<7P3ech=hq+}c zIE*!RvxBCIH^gr);TXoJCd;y6nGr{iiD?;=LW_v-0~17JhdT7a6q+a@MQ4>4dZpK7 zx8MQdL6aU6Ta5k?8xyXwxzkaOVaAa#6E;l3=0U-06_zO)n~56<#~VfmqZ}Q`j5Mx# zW=#ycr&Nk6R@q%fN*U%-2D;Z=BBEl|aiKq$<ZYVZ8%@R+22aH4AJL%)0;g4gcX2~L z&Ip4|MoK57g~JmsBGQ5L#t;Dl;20n^15!U`lVx^JBfhu{4z5d0use>%Gc%MSdt?&m zZPHajDm@w8Q8G*fhqVAmG%FPJqA!s>xZ3u0=V_^teAA);{HWCx{xPj7=)q|xIR?m# zz>iAvgBzJT4CjtPB{?DnBXPn*8s6|ia9J>1R|VTva_p0E5RrnYM^W*@S}Q#y#Tl+P z8B;>q7XCjJK?WdzNfusA9Yx*-E0bH3EN|>5Y{?ViVLqHqI(~{Dbmf|Y<_h9qT5xVB zD&tlJXf7l{G{m7uwBkZCuw~SQHCBd}@@*j;qRR@4ayUX0cp!ALfDE#)R<uIIsN@0h z02u~@^SDM$3dw6au3VG?Qbb`=DkabO>mx+M&%k4nGK*0B0RMQStAvDrEJO*O3#p2s z;J)Vyq(>v1hD(gcx$<EbSPdEgpcDFO15U*zLZF#+BMgq=4fw%UOsoL(p}2s9$fl(? zrmPj@Kn8?`bx06w_$pk;h+fRdBxnHy%s>W&CMIk}25QA2jNrK#YefKn6>6mhKx8!* z{^F^!3UXG4s=}-~w9EFY;~$7f4pOK9j>8D<L!&eU0Mu(w63hq?h#UUPRX*nr*d{pe zfP{vDkh*LKH%@Y@YL*1>=N^KHu8Or1$|0Ps#s1-+tU?t5EK}+L0L<XscA^G6ffeQ= zES{=2$Vm4Rg_MTnD}LhhFe2nuh=7X358h1={NNb$;U5?b2k61Ultw0);|-MNB#?)R z0N@R_;Q?j9WD-MQa)=@bhm_bvBL?NmctYrij_4+07id8f6zdEA;R+-{5BP`-)F`3c z;RmQB-yF%tY(_?G3T#5^6n3GrxGp^sEKNXSBRXR2B8PDtA{GAuw=#ze7LXnOYTybp zCN!SwxGD~4Hh>?LAPll`7feW_TF5D;C4t!C4QQxVoDC0<3J074z(Pu!Hh>*Ef#Le5 zR@@>EkbxzD1N_R-w6aFW0+Fyjk0$&F2Q+{k%8Mh9;TW!fh4Lw}1PCC*0wq%HEu@1D z8d4;{$V`3>DeO|{%4Sgzg9nx?D&)p#^3HZ#QT?VRDKrY8w2>WfYa^IKI5Z)OaNrvz zX7j}6>mba{*s)O-A{EP|c;><qizL6ChJd)?FhYtO;xIgVvp4u5E3#r3YU4%pihE|0 zMsCVGa_nn%hr6<X6|xdnDvlqDAz609D)8VRiXkUV0#$59E{>rF!h!xIQ|2w|;&a{r zfu5=^CyPub^3BEwO{$F|5##LgrlkPVE~*jVh6FZOLr0*>9H)+&{7fl6Xb<)P&tPdK z7a}Px==&;SBJn96hU85ekF}O0Di~2F^e7?wgQ1uLXt*ICYT%nPWeSRc9kPHZlwe9c zK@PTsfb!-T*u$&<Knch&w_<G@E=3#hk>Sz+MdsqKJdR8-O9u-P>s;g~HNgk00+TqY z@iZX}+@W}U#t+gatcK$czJP$DQ~!EHI%;#OenLYbN6W5G4`{)?ATTNh0~%VdR^Tw< z5-tmrpz+wDGjxj$000jR;}|-yA8u_>a!ljwlH+2@2g8ipy#Av%0H6-8pbiAc9YDk? z=mZyyASznZD;uwu1}OyoKqJ1SO#ze?lcG=<luRU*jCdeOCBY9q2ZUINfw+Ny=!5YX zkVuxvRDpzO8qXw%&u{!-4kV(iz-T35CiB4TBE#$<RL~FTvGts0iSh;?i-AbwfCjoI z2WKWIeqtihq)-4rCTWs(ssaFZC$LoM&9aS*h=Lz*;G$}v2za0fsAQVrf+3E>KN90Y zKtL0&fEE&J%F5(05+g74<O<BdGU8w`abQ77rg(HBnqnfxY6w-H%PxKdbcz5m+)EsC zNd6LK>U!c(h5~iMWX2d&CmJRV>t@#8$}cu{*4jrm{)VJYcOp~7kt{B&_Q-^t&ZtnR z2_wRQ7D$K#zF>s-K{WV@Eo1_G8ZHjpVHeopFybI|{vrGLDL9l!4xj-UX5y_ZLPi2H z<FpJ;adZ3>r8oj5Eeg&g#`ZAuVkAIjLU16V1Sy}ul8_K-|0D@J!-PTn6Gw7wY*6uY zri?l05$+t~4f=zR0K_Cdr>+nKHn@TQ<i!(8g)j2vR6H<8AXQUj)+1z=drr{b{J;!6 zH5`^?3c#^2xS;KhEF9LhZQXPtoK{>AWe2Zq51hfyM8QJ!EMfSQuX0jyBZ4LBAYhIN zE!qwmX02ceQg5K9*>HC?aE=@BKz!VR#oi$P4D6yX)n->SMNtjuBw9>Xl1%|iW=ITA zINBly;$VHj2rtdV2jw<L`mJoEc6qEqLy)H6D#O)6hcXI|4Im^AzJLsV%&8hAib63I z6(vI-w7!yY#`^U_Y;;FA=Fq}`5mHSfW<n?GBSg)h2o6IIzF=df3@i~?9NxiM2!~Tb zcx$Szl(LO=!t5szCv;KeXN4miIN%E8jzTnogg!~i5Q9oUAOs4M!K|zyc7@lfRJ3$Y z9WPV&B7!&Yks**%@&@-K112#XY(A9dEHr^%cOo%NCp1_B8o$Rb8gc`8u3YlXuc&ia z25ab8#%{R*X?_t<p2-hbXoq{a>9+oidv=mWL<@Id(s*Xlv!()5e&RZ41YywCI{l3~ zdgL#{pxGqBy#_5Y2DdH@uSkrj;kY5uW>9*VLr4%ur!sIg`oj`S&@Rg3B#1&2^6Md{ zARIa<i$F&wz5#)L43&bIQ-ltT{L@W6A`7@{uDArm#3xA_LM8;VG+v}G9E=U9L>#lt zCBa5rV`D7jbO*tv4&vll_+bi`gfRH2J~X0P^h-17qdqnySC+^<(P;xU!BOpELBfbp zo;GH!xsd2g;GE93=0-^Z+IjGA3SK#*`9dcgf{R%JkS|U;5T`Et&z9<vY_<<>H*(76 zqT*uWKOll@%S0yVjdBm;4gT~ZhB6SAV=P9RWOeH@b`51G$E9Yy?8~;tZu_JL;^xuj zh?}7kANygh==MgcjVvJ72Qwy8Ds%{Kvd=QFs)!kJo>V&45b5SB6$>gH9dwr13EOT- zl&1}drY%vB)*LHB2fN~CfKGfIEDO>=utK5)5BY1zkz7-xJV3%Ha0LV!hD#EP9SadW zX3U}Qry<gS4P@CT3NH90yK^GDF5N;eT8vPL?u=2?E>g1lw#TW9@#8e2Aao@S)I?B% zk3WP?>@qk5lX=RpH6-4;ecQuzV(dS2(5Y*x*J|Lfli2%4u_KVK1RugAHi;6EZnQ(9 zBxa4af^OGfcD%R8{wt`tQ3^R6Jm4WJsWSP4Q&43{xP&l7y97I@FGia`h6q)fPCdFB zJ#+<YevVTHMX?KRk~UzJ2C2)I!p^picEC2l92zX}EdvQ>3$KiFctbjp+r~a(=*&^< zK;pV8LO@K*%UtAUh&RNSd&N-+bqpn>{{-or`^Ig2ztwodmvJsG#BBq+oyyUcfat9( zE-u1bjT?i<Z<{cN<S#V*%ff*N?t@5#!!ZmQW>(sa{?kyT1547Nw<*Ui8l&tOA|~9z zE^f`a&!&Bz8_dwvBI{CN#^Me9fCfN77}s3NojWm_E_BEIA;ygQ0=z4z)xg6js=&oo zzXoz}K(`70DLBsdAsR!?NvJVyZOO@8$<>$#IC3uZJA}U+Rl+=AZamN_{fb$G&fawo zgitDGQqK-X=t?kTgheE<yCLlP%9Tv$zUGJ%8>-0U#{@(`CgL`XuslYwbF!5`h)z1$ znzxZISP{b&)<Ksi5-d*qhnNR3@Pi3$tRr+ipRhZ>#hckLa<5zR*?i%fon6EOamG01 znHxe#R#IKxpbjv?Ei7ZSTie`kJ!=Hsx|IxU=&lB?-Fq@sIx(w}LW4Q>!@jeP1jn7% zL!xuq#HA1!(F1<MK4OrH;MybNEhYzB>HOj63RRHKMI<{OEaO%VMOa81*g=8`5&5(c z`6B)Y1>wo@E(ob2usce^N8&pkQVrY>Jb?#dOn)&l%nm-`k7swfMS3ayYxl!Cz-F^L znd?AV+eaBFsAL2F_S7e20dgP*JfI(tVeQiZ8QT8s-Jb2^9`5OW?d|^V<zDXLe(w3c z?(2T;J>VVEz!%b>KHTEeojPNMBTlZ|xy%0SJ)rI5zVG$k?Ij=Yk>ML?fNi}eWDuWn zgu}@<B2Ju}6P_RqQ2!hH;T!D!@BN<gFCXyJ9uCr=NId`Z8KN$dty&u2sUIKh)gJbR z|Mf9{?P(wl8X})C5%)EsE<%)F_go{^VHk#??O9*)v40pQ|Mj_l_}!icU~_Kr>HgH6 zzovVi`8lBv(x4yGK=rTR?W^DI13wLD-}afm`Q1x;`T~J8VtIF=c>w|d09w1U>;fR? zpPvnE<Rsi6hnB>N6f4r=L8}hMcosW){0K5+M~o6lUZiM}mM4)N<2|9p@uWwL8Yk9d zDRW{<k~~tfjMoQeMu{4IRy2uJCrFYjg(@W)^ybl_6Jw5in$xI7o^`Z-L`sV4)r(%8 znk9<TE7ApGh4Re#v8mZN)WZ2u=*N#7ZgLKu+H;DCKw5itu><gLgI<S<|H+9bPEO=- za>7x*Y*}&~$~9_G7ANkXxDcaDlQxZ-v}(|&TeD7G8n)`zvuV2)7Y+yR{>znn^X4rl z8Le>Qa1hUoSu<zP30<##4tjKm>7zmP@^hRGj>?vibMJ0B1ddj;Hh1^k8@C^EtZ?A? z$4d0w5dT8>p)DQ1eR1pOix!O=XupB?TW@mcCI>4b&=P`om*KFP9Gy`n8g#X>c42<g zZP*|iAYd0x2oVkl9(o8W$RLTi`QhGOIQT~&Y4yoQqlK`AQ-e4luv1(d-<5dcf(;T# zByz?{23j2d@yBF;0t#3lW<<vEO%0OC5duUG?O_BvqU<uxU<GA?5JdLrrC3Bhh6Y-5 z^@%2#mE!1e;6FZQrb%TwP?l#nd&<%0pLy=`XBK@GdMKZIDhlZSqK$^5iDf#l;U}em zvSFx0NIDi-r&oH~DGnacA_sPIWC7}x>}Xc!h=MvAsAZS#;+`CA>=G$)lEDe;l9joW z1})-r_Gz(sIaVro*!j^=cezelDWsM4i5{PnCB$N>-1xzbuc=PP4m&s?Ln^OV{v#)y z@7?+6p3=U1S)aL9TUlhfDP-B3F)pd^o8g3uL$IZ8@MdWAg;QUi-1+vWpNcx%?q#n+ z94od6%E69Z-LeVizv2qaFUK6mSZZVr5r|$E*DADKzx#@;kT^LYeCvyQ$*~6jr|c5g zV1*q<@M0k(ge5IFWbDvC*J`Tic5&ih<v;&zJT<>mherN&w^{$Q_0?QgE%JKuZ5tWc z>+Qv+IH)qscH5eMLn_94EX}sl;)okH%wBISc8u$3f?LT>yG?jyG<c%qm2MM<L!>X> zCAC74{}<oB1T*>O<dcUc+S-~fR=B2jrojW@**=~3*I^rcm)Mx|Cwc3keW(d(d4*2+ zdmxbR5a^mJeOE#+YR);wdxs2m@@zWf>2|&|tvl(@;~ow-jen}S)EswiGVV<O<3Sua zfS}2d4(;L$JA3RA=0H3j)Lf}@q#2Q3kqwQdL-^~(fA7iea-bT-fgf^+10J?>w<~2P zG`q432(qvyI6<vm;c!Q%a+D|jJm_SVSq}~XIQ|(Ngy9V}0FbzF^dg8XWMF!+50>~x zt_I;oAu6n)LOzEj;+zm_aR8iga-+6z81O)N;EO}V$H5gUv4#WFpB%^q0uAOxF$=lf zz-|Z{KLAb~nur4zu4f#;)k#2jm>ZL7;D<Owk&FCM;QScVLKfyPj@(iOE!dDI7Y>a+ zI3&#pO(vc`ZN@mb$)H`BH$KT6&{I6xP9Ehrv?}J$K0~u39$%=KNNOpPlF<Y!bakJ` zS!R$?{1>;b#kh?9<BN<e&KsGw!uiE<kN1&-C8>x@Izr@z?C4@bMDwD%3Ggy=E1wW4 zv&1GYF)zsAAHwv4EN7e|3t14%K=wdQ{={e!P4$V}43oyk#3W{p1cQifR`riC@PHlM z5JwU8P=mRJ%N;%{0tn#QH1~voK1IMy9O`g|1BFWuMesxz^uP}Bg&{Hsb;!|<)<cA` zLtRDa;l08T4{<4TlX9#gx$GCBhqx(!Y0^@u8X5;Hb&EL2ii|JCp`<z0APkieS7f-Q zt(@YtRQMv7u4Fk!`SAr!n##>C5=bY?fZ#w}tSCQ<^M*+A17XAZ$I;mKulHOjmRd5Y z3L{A_C(@CH<NODY^w7nFvLl{8!T~=T7X~}wpa^n!1FCXk9ChsCUy{*H7;umUt}<q@ zuasm6!YaRI<!>){fe1HvWCjTSsx_YOkb^s(nuWOP!JT#8p>gcW*W!p{p>}c1wuZ{Y z&*c%Z5W!;{-{_cyxMLT3xWcf?_tecql}9x=S^^z{+KtLjg|_UU$&dvA^<|-b1StqY zXxKl8#Lb9{4eISUxsZc8q!YU+LUR8BfZR|<H&u0q9=<@2x_X93?!Z9^)X}Xl;K8n% zfJivzriU;LFgGN`(q!ml(-*~IwBm3F0PZ$X9N-}iG<6KJZm8IyHH2KfNC+G1Bfrl% zxG{QJRc-*F3B=eeGnQpAxbP4Tj5_8G7`s{0UQDzVrU{A)X-HxfLtMVx@JeK;4Ac?| zCyd2G4*+<>Vg9OzIEemBd{>Y`0k^T)C8P0ot&828`e&a}Rk))j&0l>yQG|om;1~kI zgg_2#W_l<A0DfSHfiDBzRTbmRe?UlqLEtniS2=hXt|j<rQDGcMcgOq#vzW;Y05c2Z zA8S@Ko863%%EVa?WT3O1-JvV`y*RdS`f5V7oZ)2kuZj@q?R_Of<Td{l0C=!qemx-> zjcyvo<3y7mkik=gnHFd1!=^O}lZC_7=aBRvSP0^#G?O(}au7)qQU5X9c&=&+05IS& zH1W=>`j#681i)Nz;E59cD-K1tgBjD)W~J#@h<38AxOmh<H)6~<S-=4q$or3_;($(j zOw0=RINT?aO8!^jv|LafD?U5`ptr@~j(c30vG;^Q9da;((<+M4&Dal17{1^9Bxft1 zvI35R7OMP;&Ajlg34wh%&{V^VgJW<OG;6JET)9w(-2AmTotE(%yDHWVgtdxxNt35y zi!n2(!%78}0|4l$3Gj{<V@eR0x8<M*JYeF!-mYvIJP{6l?APDT{<$pa$G^kIZCQfG z@y8*;4l~Gr>9DSL5B+dpnzEznIJkO#w@zdnVEXG}A3HcP3~()tTJ0<Z_|P1iG(WiG zk2MG{J7nPPzH>u|@jT!}PktqmHI{#>IMz>*t6b*p!nusi@M0LGIN%1He{QE?IGnL? zBY;;R{)Z6<G!|~J0E&wq;t)t~CMpmz%+1?EbUF^+plgRB1owg;pb-Qj!Z?uW7{w4E zc>e`rtk(dY*uo(l?-Rr0&=8hH8>;+j0R3WY2gCqyMrE=Pf=a{u7!|Dn9*zNjMX)N9 z_dT>mRQTglk<k#&1aPt^KaFExhjCz<zzv8I8UUaNl~!j0p?w1J2S5e@ARrJm&_!X_ zJ<zmgS0+c|Fe)}ibg|S#_GKlyp$R-v3<qQ!;YD%bP-Gz{8u3(ZHBbzGfCt49DN5rB zH-#-$Ml^3!MfL$Vf#yt$;b62^gFsY+;!q54m4o4+4%pFy76^nXHH3eaNR^R<9A{Gg z4u&m!A!tx|NB%QvH-vIS(`s0EU<w9e;m~jx18YFUSvvMR4%m9llq@&o7<-UD2Jvfv zaTusYYTcAH2=h5QhEvYASO-QXMu0IaP#I(p2W+Me2tz)#5@G=Gg-=&}N>+JR*Gm`} zE|(EF#o!EVP<fuA1lVR^dXNQ5;1CMuMGHp{5Trw9ka%P#Nv<VurWZ+^ax;%qPG;2x z2LxX9&~5Gk0Ad$nAGT_(B4h|dGWUaFjnN$8kbq1BaJ1Jyd;tP>0RWN^b>6m(qCo~3 z17dx5KnErn7|4Up5C?v6469-s&Qnfi*JWRIA9iFW#CCH2COI($SV{(7riT7^O2ZC* z5CLD1f#c^R;e~hXpjUWS9C1Y<Zr5z2)>x$iR%<s&E%|r}F<{VELF@ot2UIGE!B-i% zkqL!&l#yJ}7hrhs54*r=q1Tcb=0Yq;Dh$zfGKMU7;Yu4229=j5I8Y38qi}M7c|IZ` z|DXq0)^VUmdZhwQg6MPxAquL;da`s#^5adzB{ZLdk`8uYcavNPF?j-kCKOmcn<pB7 zkWzi833WgQ3l@sygLltGa}Y9Bp0IGx(06{YP<r4FAV3dS(0AbgK}JR<#UL$8Mo?Ag zdNG(R6ebxLW+piFVEywV7$^r^5RiFNb(-LdTxW#Epafx{L*-K$bpA4kO}KuX1Vsvn zi49n5ni6gyC<8^{i^caMJP0*^a5VBLe|q6<c+g{30suL8LN|kgv2$ALC>e0GfX=3A z&*%s1RWGe6Pkkp4bJknzPz)9%E@V&x?m%X9MrIJCWJ*|tY*>D}WJgk%Sdr&oL$h9= z!5{o+bpSvHb0#jDFrRm0Z}(|tmA0P{!VV)xT(j0`pcev`^f`xwWiG~EmL(2kzzx0S zZTt{;y<{All~Qjvh|vgC&7>F4<YLJs3d`j)&edlmC5f4)DLRI7n3zcbkSYFn7z@UM z^QJVI#v+G-F~uhi3U^h^$Ah3qf+oWw7;_Aj!3vqTrPxPl{;<<Xi#9Bkbs)6&b1yhW zw>EI%NHjfXk{uUbxls&XiV!>~8Qjog2_+E40Yoen4iF)ZZO2m&!3O8pJ0&-I<3wHJ z0DvHQk4jn`dDy4dMq~*UVh&+veP<=wr)+2EbDHu<atc(E1S9hE51NovA_Py#r5i%n zIC$4r;Z;CkP;E{ZZ^J}YvX^*jC}Z;>8KWYHZ)mCxkp;0TX7@NO^0z9Xnx_obtNbV- zb3+_jvTNI-sKN6>rGi+Fmp_*1W$IBG2Zm`wxC?B65bhBUv_g~JvZx+cqRf<Q$Hi;x zP!Ot@P1u5o(gjknrD-Twd!Sl91yF5=fiP?qX~ePqP<zohY*t`(S#1g?e|W%&JSZ*` zM2YrBlw_hb&&7j)V`q_fU{?o3t71g4!$KQCY#&7&V$^`H%2S{Noe7brB3pcp<86nb z31k9T3{)H!NoBxkY#Byl*dbvr8<#iaBkXVtS+D_b7K&-a4^=m2ERtNI2q}jdikd<O z;&mi$_+V{_Q?b=T<au@t;dV*WY-h_q-sT5^1pr?}9LIo}d#V@qrkPiFH0D(VPNt*( zxfm#@KP@z%ZR<a5Xly&iJkHk}WWWWOMya;7r%^h#LK|!5rCpSPUBF3F>KFo1D2J{W zw<DEO|4@%PcqDmP1UMiA{2(G1*`W_HPMZEwNqG?hIuIFB1FBi@C5>nph(TOK!x!R! zY}HjPkjg^OB@h7Q4Dh#beHSN)<6(T5T;V_luZj?O5D&>!3{g5}xsebgqzRRW2_Rr# zTq_xPw;erplLvBOct8)U;!bojdM8<&;z|n}XCG`>HYD{%#nE?MWN(?rX3p1|tEfic zRX_lv0dL@pkB5@K(;x|0VMK+b!4pdtDG-_f0?xp-x>;#=vAt{t!TCiG?ofFn2>{Tb zUmC_!iYk_hp_IgBYrW&G!9y}A_po6rP#73u1E!sEaJ4vMK;mK;>t~XT<%U4Dk_CEp zE$ODo+dB_yU=DQ{XoZ2p!h?EXz5Wui#Emnr!BdcQ>KKhN#ZK#Xt&=~z#SioZ0G<$a z$M7$8z-sX%2Y9AEjG-@y6`tbCQx}#rdmsnt)30K(GYHYc{u2?1N{O-eVheFeMpS`_ zp`>QOdx(J@$6!@8mk`BQ18atL;oz8L<_-pSH|29+JVKK~WMB#h0P%69bLOx(umNR; zMxh8beCQAcMO=gyQk<lAy?`*3ShLWygbuN4cH&*`IdbiEW^_UZ{P1-l#s*S*Qgj2L zYaGaO`cqZJEI>6*eAH%$!)9xiNdHg_4Tphvrvx=12_a};08k9N*>_6w1|Sv!>_B`~ zjJO{PNg|q#A*EW(9AgPl{tUR`4!o)~kiu%q=M3B@2X|0>_^f~KL7T9JxS#{a;aa+Y zwyOQJVYv%B1S1CxomMz0(Ph++n81mc`JNlCWWKn=3XOQZ6G<bjjEcp<bs7Tgl|~W* z0NfX!ys8@uXD8wXxw6+~FI0M^a#S$Jqr1?E*)&u|w-7^$bc5(|`;%D6BDK4q4}vE^ zR|P4<QU_VkMd_P$k#Pri5>IdKm5mb`$EOKqfCs%dlE%^2T{KZPX}&u`fJ&2JN+V8> zx6|rqj&buz_aVSHGpr%-mEthZ>OgL=$}}=igRwRz2@wucK*|L~yG9v~p@tpgB1R<Y zgo1{28xRNjkYY;y_K$3eBhZXiB<O`j=nhxl2~Z;g3YLA8VPG@`O-WmJHLQ~UyQ)ET zTEa?p`NP{o-9~0`Ej`lL<5gEyb)PdEiVTEPD2K%-IY)>!OQY*-;7lJ?G*w50VP>Ey zJrV{P!y<n022<KYcN2=a3wg!H%ovtGO8KZL88mcwAo^8v$JZ$Rj8+G1#t7mvH|vaq z{5K4gh`r{c?!$UPnqmJd8I)+l1iM1sn$HD<5OMHWGH?eQP+%D?5Nj4*@MJv@5^O!9 z#9Xj>vvp=Y?g?aID1?+wToAQLBxLWQ8_!okSCCSkVA6+c#s1qM?)SD-$Y;R=X$z(g zNr*yFgDU>Ik#%5})_C9y6{I$N6nQn;X$p~mOgl%CG*~)zd05w*{nSfX$3-UQ4n7bD zyHE$7!9{Wq2JO^15K>0fM!~lWo~xQiY#UUZbh?OGr<P^f<5dIUwjKH)#ttzzg6=pI z<r&_l4w{B^ptED`J<=5xx(fZsPmLv&WkBPF2beAgn(j2(8U`wJH1GtS`K^M7o0>eW zxFl^WqDGoJ1|b53UyEctPRF%$(p#ay4*0_~e9?fU2TeN47dpVB)#Nk51_0YKN#mrv zP@Q2_2&tg6eaY1=0wj<R1*;rQbE1(ax_N5sP;Z)2Z-CPuUF6xthf*_T2A%-iDVCnk z7yfMT)YmFQ>EVC}G+L0MJ2XR=Y$}b$<5<P<6atzc3EQz$^ci(gJA(ow17T1E6kN2* zhGTXL(iuD)=<3*A-QFiBLc{V<l=udixhi5jez@^h{6N9??gvK|i%Mc8&;;ORhsMpV zs^r8!<vrcxno`i<W5nSOv1>0l(k7NAMB6b}LnbbC#TPvcdEVM*Lqp&oI_}g?z@Fm5 zbV4f>NNxy%8$5zPn1)27HDu+};!NXMUA=@HrK%=LYBxJDS@>3ewF@bQ!bltjF3b)_ zW>76-IaEkAGiG`i?huN+;mt)R@pC(`$2=l#lnEWT;vpgYPypOuC}I~HSJ3Hl{!oM% z(_USqk<eg2cwh$i$;U@jZ<vW2B^3D%Jzh1KF|;Ch;t)`AfNAbw*)<4mANSGey^_c* z4u&lA<>#{XF?m;D20U^tEV~c_iBLGe4S&V_SNf$R^l|LR-bgo`Zf?wwT#&$ozdRxu z?(hZBup{mfpZ@?5o<QL6Q$vm%aqMu&!4U?Bo`ehiY>-3IkDPxPCsw@Jaf6?4w0a$! z$VN^Gk_Z1?%-B-nK^#TIxvK#UkGNg##MKDrDa%1Q>}o7L$j%cxJbE<6k<(FSQ>ZCV zUJRj1BuA(hF&-3$aO+B-6l2b;@rIwcEOGwv^rT6pP<KGty+NvH7t??KAy$Gth>{{o zKOIAaG}+YYMQ#-_ehe4KU7RAGnzDNwj$x5FVdD5<C+A9>g%neAn^<}S*kOVFgv+>f z4}dJ9b`b#pfYzQ}>;U|;c(P(%T5{O@3#YYX-n^v^Hzm%_Ou~cQ#DxpDbfBEZ;l!;L zM=`G^?KL(Rha4gfJ9c`wfTr9ON4P9(a17P70ms7a;X<&Jv1>I-P0#{?DJ}?V>LUbw zb4oa5f<s6@<vcPCt8j3LLlY1*(W5wVx?-)X`Ys}fIQZhIL7expkdQP4o$`x~2DM9x zDyUEb>_AO$0D&Pn+zN*$88q2Nof-xr?mf58lZc_}&TFcMf4cr-jz$~#0_-DkJP1y? z-t@B3w=chJY^f9dcn=5g;yTf?0TBui#Kw9g?VuK0WKlW58cZon)3iFUv^m*uhs>_d z1dpjT<!Do!H+zgTKnd+UuEx^z^lbw+TC9;d?ZDGRChXqha3vhriDMTwpaG#c=Dzf! zwT_BICM9uPlEWExcFAI#+GyG3lq>+y=p&Ubs)H#%YF#j^rdT~JDnFTB_E|rT%Sttp zs0B(}Ypab4C~3o8?V=6(p{2To`07^NZ@tBqTXx}H(492u7><oO$7MF$c$ee1BY6#b zc3-DzP)Cy*WLSp>XZsCUs>9%w3cG%1gvwxqWuU>{X8z?JI9hEj{uf++`!zV6q-fy5 zqy;5r*W$nkb{HxUkXa2oofLcRls&Sb%{JVE%_}Rv{Gef&Z&XPG8Dx}3X6dJyUK(nq zqn_GotgRmA>NJL_nrp4AmilY5sV@6zud#-@>$S&@`t7Ux`Q?c;JlNXltKnAL>Z!Lz zChfPy20L%C_g-3+b?jK+@2<x-JB`8(e|m7i#kQPq$0fHKaaF$Q2L@jNXZ&)>A&=T` z(FaF8@2m^Q{Atcr>8BN6GAG^j%o}e!?Y<#LJ$KPtCtGU7ll~kIzl9gRZ>hazJMhXW z-+O^!xFHCS5V~p&SJ`;AP1jw7WiivOxM3rU{^C{wST*+BcmI8X-<RM0Yv;HBe*E)S zpA}6M(ggne$uE8Z1mOE}6aqhh2TcUT-vA5PKn6DJA4_3}{RHMf24*mT%ZV9lG%+X) zwl9PlB%ufexEkVsu!JjQ9|obq1)1PrI$hBj08a6%pWP-4x=D<+h{c=^0ZeAlf*8ym zwyucz%UVPv;>TvTM0l|w4mWAacBmCFk3F%7*J2_Y{BWW4i42QOj9JU1WyUL#5oS=4 z4?EO>hcY%%h)`Uk8MSCfByvy(^3jAkxR8;MIkAaFlvo<k$U$i_Dp`H3!6E60$Cs^( zi`@!L9H7ycC|M>WyD$RJ_TW8V=}K7sU{Z-itVkWfsIPr{c~vXvr^=YYQX{MsAuDa! z%3B5|m%7Ad3s<5SY{61~E2$8q2BoZ6_R@mtyJa(dIX_yeW-r<c3=W2qtX>K;o5OS^ zFP-_1XtIQX$PtGQwo@x*A!nP~bRRIcSxfgtQzP7D<vAa;9dLT{o%h2hF!9+<eG2n5 z`<&%AwTCZk5^$clbZ0VmsZaLVl8V>~$8Z!Q2OHwBS9>^xZoDF)j1*@zZqelh4}(BI zp!7;qd6&S5rP9ElbVezSX-#Q*Qv|wDFg2}T%m9PZm-eMEharv(ZW1y2kufkI!KqDE z`lps6m02idRE`(|sr9w6r*Zy7YF90o)tNC>IPbYgf!gWRrP2sbfGo{TiTc#GwotBT z6yXAUgoEU`m44jnjR}1URk#iirSDP=OhshT0s&HuU2V!>@nlmIUT~!}MM#GNgdLP* zWDmI7gD60`3sK79PJh~#N~}n(l??QUT47~DiPe>ffCVf|)Lv%ksK%lB#y3N=*3fb* zPQJ)?n^0lR1QX(s)E<Z{7|CpNmAFOVvc$Q*y;5pt`@&PsmRQ6h4R0;-+5;swwp=1t zd3WpF@v7Fk<9*2liK7YeLKiBn74FBtyCC6yH?@el2yBC@TQ|KITO|1|Y5lw2m!M=% z1>M(PY`a>~_?M0zeEx58K02oZr&pZw-LO^^j9y~3)>=5ggOUt%(TtuVhdm2cVpx^g ziVVYRs)*V*D5txr-FR|Z<64e)JUAblPRK%@9OR7r;~NuM$AeSFFqGE0e)tW@r9*O+ zl}zOz8_sio8-@q^LE|7#dC5P<GMTe{W9OZ&X=!-JIy_+IFqe7AW~TF*4VPozna;^< zcC*y3JZ2ydS<Fj5bC`X%W)HYI&44!Zpp87|KO^}YXhPFvHERTRh~ksI0&TFEtJ}=d zLe!%sb*W8#YE-9M)vIQ8t6lwSSjSq{v!->eZGCH8=UUgh=5?=q{cBnrYZt}YfMqDM zGhMAXH@mr!{(}3&8?_RvG{{j<Q1P^>YiC>9q+MyXqYbZa-$>iv_IA0$eMfGmd)x{_ z_qw}1MtHZoUwZkdwe3yrbGw_g5;AwY@9k}9vm4(3&Nso;EiQxmp}X6bSHi8$u7aCs z1K^>lCJ*8ap6%kZS@86Jo01rkg*@bz5qZf?esYwjoMa?ddCOh?a+t?l<};^x&24^j zoabEUJKs6Wc@7kxznmS^K?pHxn1x+<cB9MY&8DDIt9pV{>gj~~tD<B}U^;l}QU@p0 zxBe<G?WOBnzdF~U-j!OBhBRIud)v#tb+eP5?QdU6cf)>n<lsG7a_4*8ua3^Y2VU=R zhdbc@4IlW!Cm!*OSN!1z4|cKBUGj6MJlV7EcEC@5?25;`KgkaFR~4P{ix0cPd)eJq zR^IQ0U%cJ<Zgq9$UG{oc{nV|lcGIuD@6-GTH;6-{*4U7vpS_{@^d(xLgKHNQvkb|b ze~{;={Q1*oKE*^%ee731`9N8I_Pt;I?|;AMKM6nhDb{^CpdbAuFTZ8fe}4G8KmO^T z|NG^CfBFaA<n1?q`N36wA2C1sLpk#6zm==M`6C$}Ksof|zvpW}>yv{8q`nA@xdP0- z<*PvDGr$O>4(;fQW5c+l10@y%fS>{l-T<es_`H^oI*j1DuZY1GWI+~`!55@K8eIOt z6~sXv>_H!N2_Uq=AOt7h`#~dw!67_CC0s%#96}jv!XMnh9xOs56v7vz!Wx{xBaFes za6%~T!SW%y8?-_%yuvC>!W;xA%K$q+*`!YD9!?7_-lCIe`8hkhLp;nwJ={Y+>_b2N zLqH5foQskU$qS-8h}Xy!72BvCVzwFqi!O{olCc$AAwx+_xiW0IGHi`M+(b!q!aK}F zL8LiP<iwo|!jr2+Oti#QyhN2NMOPd|SA<1R)I=*3IhRNb^x+W1I0)g}wC|Ba<)Dx$ zV22He3ptpAUGTjPm;!^K6FSKV(Kr=%0D)cTz0S}BZb%P@fRgiY2g{g`DgHQ*8n6q| z%0O<2gDlVk%>W9ffQgvUgM&B^rsxd(5Uqts3>@HwbqtDASqq}z$8#)zQjvqq=)%)L zzJr*8^h=CRsDWL;fn691(E>Tq5DkRPh>S$O6y(T++(?Ur#)|^U#n8x-^hlHJNRm{^ zlU&J<Jjsg`$%{<Mmt;wstjU=C4U|+!jBH7tyr`V?j?);*j?77yq)C}f%8~TRo1{sk z1WJ<xN~H`+kvvMCR7#S(sE$kt(GbC1SvuWlI>7)64$zFw;D+VH6>b24E8u`m*htX; z0B)!OJiq~W(2a0_h%m@YQ;~zCn2RvT3C#!xg(wwRxes<o3wEd#{+K9&`{0Hv*o6&Q zM)ZluLaB|~poiK}f*QaC%uE10u#94eNIj?lGU$q9z|7Rl0%#Boz?g_B001KZfI83( z#MFd02ntQmgshCXYNJD}*e=xC$&lQLjku@}6Dm+s&g5K9=WI^sj7H*wN#?B1=d@1k zNl2>HNg7fx;S5fv^hkvJ$?q&rro>5Z-@&Yq+;?mEx#BuRaXE#i!}@LCL@fHv=t zgGAI7;`6le@eaLU2WNza+>i_aFazBv#xQ`DDOt-Li34s35CE_$d8~nU3<D<dgn}>& z#GH<a(1Xrc3hTpxi93(P(2zLLj>XIwaR>uX000?q2WzVSP=@#i03Zl;xB>up15K#V zaEQnpwM}kN#xU54Rw69`h=T=OQaLz=P#L-oX&9%V#82FcS$c}l+lqkM3oW&!ENzL< z6H_1@(=a_#FD28jh_^H~(=<g>H(eKJ`j$0q4M1{Gd1*S313795!Y#eicw;RrMMX+n zr)l9*dD9j<9aJoZ7ni6O(MZ7s=}JXZwiaU|I*CmHh|L<9O#omAXQ%-V000osQ^oLu zC9RDbAPr%ujc}lgc&H6bfQE1YfQSr=2(XN<*pS5pfN&@V*ocD;*-U;w)%n1I-9Qsx zy$||O0_=d29{mwy{fCK^f!%mgj9>>%pohA&)l&YUQ8|bUir6-}OutQaha8nhZ6yd3 z{SAspj4BBeuc(p)=?cH#2m~?Jp+r8v7@B(>*Nym#OCcqJz1J@(Sj9M4f+bjeZP*0) z*9oZ;d=1zMNsOV4SmZkmy^vUYRg90Y*o@WJ(2Ed<?UQl!SC4hrkbPG$L0OdO*p0>5 zas7>$O%RJ!*_&nAeZAQ)fmyHES$8#!6r{JN^Vr==zc<u4PUE;yI#}eWflZAA0B8et zz)^$5v`x)Vmhi>h5C<|~joMg>-9Xg<fm%OM2LPx6bPWfG*h>`o2V}*Bpg4viz^I`J zgH+9tT2)&)C<ZiP2UYph!bDa)@QH9BgZ_k>4<+af0MLU0sa1t2297fbZrH|`NRVR4 z2xtI+x?D?xC<Y{Lr0d$+MYU4diV8JdBjH-pIvrD7s#DliQ`v>nGA&bPS>4km)2(f< zVj0xk#oc1Lu9UD-LFJ1nxm}j{i`M83;BBwsP0}jeFyJj+Mm^nvYAtXfUgULN?!{fw zeF{A7UXl5sNK_vb%N3si%iUl&cN7+d0Dw-w+c3~nU4++(?NM!Y1{CpCGfCSlC<cs( zQAKeFG5~;xhy%L#2X;UpVG)NbI0n2T19j+;97WX-_)&2vf@8qY`v{OfxDRpo0(5N% zanJ(*C}35+kR`<fIWS?I0Dxnd{!Ptfh<kMkVF3ZWEr1h|+w=Iq&`4Q<^;s_&*nXAR zushj@omhljVkK^3iGAXTjp8I$*ozg|DZZ4Zv)3#>i7npPdBs;QP7r`qJ1#C_q4naK zwO@-^-q2IyjTqv3UD%T?8Y_Nd-w<MyRbDYxjKn~@Fb-IL1!FqC6g%GInypwu9%Gtq zjp9s@;JYEE{T`$fmOS2zwfqNl1b{GrhBl~yESSyolgAjm2qi!m6UL4Yt{@pj)}0WC zA+6P~RbU0K5ENktC=G`?@KvY<0AT&vwd@QsuuC%F5i=+PbTtTM0f1zY1H4TNc2I&+ z@!GWDhaZL3`S^!0aERsp+b?2q-)^YT#PC(4pt$sb-YYd-*X>>7Jzg37-Pk?TEQMz; zmFGV-Q`+sVQ69o&Io;bbjz?9j*`2T6eF<p6-Z3qjmbj65=EO$@-`CaN)Fsq&9@*BV z(<*(5?`2&-6;lQiXpH{ECAwqq?Tw4V6^#NKrV}@E@x={bhqaVQ0N{XNLD%!35{|G{ zr2v4q@YRGk2BCn`DS}dL#VDpI4o^7JC{bn#eh33*4ea<)sWsciUD3kKQ8^e2RNaM{ z5Qkz=2nt3BUp2^ZI0o%-2F;L2d0YquQ?5@n1H3f@en3`FxP!*%FQe61kq#66q*%P3 zS&eNvy#5k+-Ru4<4q_}e*e~wuyrx+t=4(Li3j3vElSMuj0b>?P!HWgiK{jIF80>ug zSLE<(g-ckM_>xbfh>rEy!1h>^ZMu8K<2spa#HLr|13|)$t=P`j+{Rb^bk{C+*To*= zKb=_*bB#~!ng2At1Sy}amCeevRjCaMBlw3YpoqAr5IG=&62mC5&CwbFV5wb*TK!cS zabbIOJ^%;-Ax)MFC5{~J3NonL5U5bJ=#R!A0~Ilqurv{5EyuhxV2mP?FfieZSkl}O zErqCMvRX_d;D;$N;fE-K3S|$=>gaRkU4rH?gXWRvlOc$Higqqk4F|etj*@u(Xe+hn zbvBdbBmN2x|J`TtQjob_PQi$-P?GB9-r-GBl6cb+whRgaUj;K>hR*PSR;+ZMN3Zti zMGaFo-4_f`iTB_UgdhsvC1{pFlM0~>8PRCoooD5J3X9c>uDqf2Md?e;isjag-S||D zN?S_Cs6Pq{6!8yRm4hNk022vj0C0x$xC1>v;h6vcD6otoC<YO=kN4P&93`>F)mF_^ z=Bk!~_sG%47z!D{+s0T?O*jKQD1v_=;IWYKLD^*%xK=rsO(Spy0HBAUsMVcV3K>Gy z+Q5m(pa+BS)eA;sm~~mw{#dV2W5uv-w8N`|_=%OiPTew3sWkQ;y4*76<CZmK{S0j? z{`ZgwEHJ4A%4Da?0E0k$zx%j|&Oo0(;cV0nWR?ZNgbfNbNep3qN0PZn^V%+GJWgik zu0mv#%YNBt?^r8t;yxx~YbOe9C%Jf6$_`-?i3~k?o$ZOW)0rg+7~`bGjAUP#<WC!N z%BI#`a0Z~rha#PVZ3KB!;fx-kp_yP?qG%-S&;t`e5j-GKjJS|z6cV(cw8rp+p(xeq zU=oIKh!&<u8*kxa;D>NXjJ>1_l6wzmz^huu^BlR3EJ(+HzzlBC0WwHOQ$ZMioPsQ9 z2xs_$Ojd_>{Alnkdl@e+fnH}rwDE%vV`{6djDY*`>Ox?$JM7TbuF&e=Xv2#ZuCs@j z{taLh6Xy{>mV4JzIB?PnbvpcFgImzRf!qW+e&*=m&G3%KZn;=Yuh<T?t2_Qm!K)kX z^jfbuAr1Jzjw~pY`~>mRbzSXkL(7k?aO4UTU$~Xf9=MMa4>yVZl-(y6E!_T!ffC7# zI&&QgOK}4*CC~>?2%p5@hYbjWd{|Wl1y)|xOrJKBSC0!2mdLKS0zJTiFYtsnfDRN9 zhc+OCVz7Rmjsp##G#R3y$Jk4GbWCs*3TSvy?9gfKK#?=adVq){2ah;{dTPjUheIGc zIcC^RDdH)M9020N_=$rj&Mq8sYW#DE1Ar$#0C0r!6Hbnw4RSX83-ND5%bGO)Z^{Yr zQjWNnGiTb28B@+bO>)AqqsUVZOQuerLXGMtDpMRd#QlqdwC7ZpJ$1so*)r!&oIPR6 zB)YQaQmSs5PHp;@smr4^a9|wj5-eG6Oa1Bu>xY|7Iex=omD$rH)wojSK6N}djyQLV zcd;D$RWn(^dx5(2`;{zOp#N5eY#Z5WT*vI(ttHCspUts*cLpBnG_}jII#WAiw`<op z003wW&jNsGV5TAc@-t$bT>)-WpsnP_uSS7?ck$GCqn4c?t2k<Wgsmy7o+5JG?P6C$ zlU8=@PG`a6&N7bso@yMFg*ckjAdY={XoSNX;e;U$4ti+fQ8=(!gdhHcSN(I5I6b|= zP7!*1A)y>NOrg&Pe(i!9Rw;#pgFA9e;TI1201yTjS%q^~O3pbpRcb$GMwDZ;HI*7< zgvk*H4n}PdPDph%7iDKJ*+!*UFtM`|QB@h{hml13$YV%Eh7=c(G<oC~J4UgiQ*F03 z=aQUOzB!du;e<nxl6BEGrk6spwq>7CP32=x4cW&MPCDU6=bTqIDkV)!$(KcJbZwa_ zkYff}q-2~Dsi;S^2`2}6INkPWS0OnWP6%xM=;fb-8rjoXTlyuJOM3v2#V)51VH_=c zoWc$OGd0zm9C}P)svg{gA;&I7;D8x4W;Cb=UO4=7g(u?d(*E8q^u1R@o;ro0hd3$y zqb)lRdbwdv?A(EplI(2AEjN0Eqiz_lg>yw5uz46q5$<S&Cp-M=v8<MOK;s-w>Wr9E z77ZOW1v?Y5gKd&phQI}k+;JmL97?|DAQ$S!DU??^fri^p%>njTmrND0BDYSa)stUB zEd?}IJpGelNIeN<r^)VZ=$K460j3v~HHXzwYU{H4pg=$q_S0a@9qnb$M8V`GOj=sz zPR?fA)^=!LqYCrWhVkSVxf`Y>bkJCN-F44J^Bs86KW&(yIC|h=n%ql0{ic=3mUiV> ze*MYl;g*3Nv`mAEjkq{S5)E_QeC5Wd#C1WLX>faF{!!d<$t_3Qq+okO3lFr|j=S!( z=#e`Qb?i=y54gvpJMgy~k2~`56p#BGv^1YP?!Zs4JoL19g1qk9+uqNHHN<ltzSM%m zle}>hD4ZtT&_aFi&ENif`@7#B5Ae0y4m>h)aN(q&t--}pgOZD%GF2#_YycY8lV0!| z=)ea$unzI)LqkAPwg84IR-pov)3%fntmvT*!-F6ROUS_A`9e!R`V*iw_$OHzX@yKd z3=Z1IJrm+Ehdl5^JQi@2B1!Cku>zE*Feou0)g?QA2;m5GsE0meh$j^JO_*pkE2r3M zC!k_fT>x;3U1T9x$JqlIkL40Ju!M`WFbq=u7!!^S^ydw`xXV9q@TwgBgBxr(O%2fJ z2ew=!9B~LidBU&(bpQxYaY&bZP=*68TtyQhIL~6_pa}<=Yd{-_5T1DA0mO}IK+Ag9 zN+wj5yAb9oJct83;-HBQu(Cx=5eItK6*9!^h9fxe%7#3Em9rEka&+U1S*9cwzrds^ zeu#%F#o>pBFe;i%ktSKHNlj_C2r=(?7gru9C(e*AW};zE(D0<7hIJ*KR9fex+Nn-= zUIhfSj6)8<Ca0i)#bu<C*`iL<6J|2zn$sMpH3=$Ec1|T6NODIG9K=uCfW|in)Qi<# z);O0$@iZ-ZgA5GnQL^CR8@OE3Y~21PQ8?-5h_~@WnD$_Vq!33~U{p?*dIKn02n0qS ziBS!>QGhJu3YYCsS3`Q@4o$T3BRi`YN=DQoaR_LZ1wsj1cCjJM{1KN~s$)kwDKC`_ zBLs*^NnIqf&eZt9s&b%3LZPFiQl4k29$|}LX5+syA;U>w`d^@`7$!3bDo{g_Q5}v# znWMZ*D|QS64$vqEHngXi6<f)9oFWi$@S{0?$SYSSRj31Mimzn~)Rxk+5?Y`xLN$O* z9IhZ9)~xF(h^e4QSc!u_u7{=j`>Zmb5-PtAu!@ZO2Q6?3)!4SOO_<#fKNupAEadd5 zNC`t6(h9EAY#_Nu`AS}8xc<TnN^G=d0-$)2xT+tb7B3%5QVk5U5)edjx7$4+O9?0> zPR(*Dq1jTZnBqk+ig8%+0f1-sxdB>Sfg9Yw3<u;>3inLGVD8{XqPA<PHHCm1g4|d* zJ_HgFWDW-)z(G{4a*%gf6_M;v$GWb<5Ai7JLlIh5767CYWU%x!ZklK^qxPFi7S{~! zz}JL}z!3;}qQhpu1BK}(qpr3E$AlCeK9N<kiw?6hE*ndsYEWDfH#a<A&_qhAdomET zgdK0Vq#WSO1!xo@95DU|wJ1!nLd{{1E18O<A_}Q~?w5<xq{V3tq7H6Qa$#2(5h^Xk z7?ez?GPIO4(^4YV{yZ;=G@QH5mCI65vRtjWAt}NehP;qFXapJ<qH2FO<e+phNDiLx zh*j?(<izSD4yP&8Fm{wrRQWlWdie>kagrL#tuZ|3SyK(5p_MDBV_at72OBW05<*HY z+gdhVrZ5FqIRs}ou0zf#XgZYfuGKnv2*YqN;}>>oYzkHpN0P(PM+DW8AF*|hR<>rc zwS1_R9;v}p*inZo6g(uDF;!2(@Q*C<D-32($%dj84jhlwY~AkdkKVvoT5w@aENO2Y z8j>gXz@}jtf{$SW4jZ=Q^&f1oX$%8c#Uk?6xB49s4-k0~SFU(Nc`}f2Vkw`{^_$N9 zX;B>wmht`m5pu_%B~uXZTXm`zO(nz)0h4jy9wNW$DpxTTRq=EhkNm4ASx^^G_AH0} z^;U>t0%D(fgsZrSV~ssow@Th+m^V-h2dKc%gf3~H0pWlfN5xZ~*1duFq>188$*WIV z$nhiAoktv(`*2yc){O9jC+^sQJ3!ymaBSr5aM5erfoOFs?!2z#+zGGPL976iQ8~Gi z6fJ773x1fPj<cyjjG6_Xg9XeodSJ&FMg;M9E&o3JnC-<}G}kO8iMlx8gbz;R%52tA zAD%$7$Ni9n4uu0V2zu=P*r3T5hQ-Q@yGRW`W(K+qM9!Lsejp75`Fva--E0=9Wtq?D zm!JL(8_g`mXgJ3vAqP)93sHaoMf`_H%-CxfNE`@AjXm7L$dX2oT~17ed`(GUNYrRh z%}{v8I;oLEFqs}Kk*WMc^=+6XRZPXSl0z-a7gU#yJyxD6isOuis(jPasGwT#L~%{U zK{QNzxDiiG1T8g0cGW>`Q3?oXi&adUuIa%QjEX{~gnR|l<jmhbQ4Io-Ax%7qA0Qi3 z99EVHhmIfybghIckcF$%iMEvnw;4$Q{RUGw!xy!VO!-Re?3ke7)WUtl!xcacIKwW4 z!E!)@$mjtVxWiq1OC-twNHECBRE2~1fhX9=h=jqA9adKKM}Lfn1y+(OnooxSfd0B% z0eZaMRICf1?L=R78)Aq<JaB_L9Gw#2!7-o@Q&3k<iJcs9fW5&8b!7@N>=9Y))u-&$ zZUEK>IfqQRNe%hWu`E#^$$>sVm4Y=yF$~!;P>T+pOc-ngwdlblVNFhO){fBE+-aU@ zwNP9n(`jvparh${0Dws-fj_=MMgRcDgu_V~i$4MY8K6f9tcOm(ozy|b{|t((1Q3tR z4*SpzLjnLj5QVlRWEjLlDaOHacpbig1OOy}ar8$Gc%&rk0%7bzNQ6MI{h{T3+Ynu& z+#QfjdC*!lTt)mrF}wyDNQ=X8%K)+=&#(kN+80K`-mS>q>~xWEgpshY{*JMnn+V<n zEg)L8_(iic+d;+y0C2;I9R*MwMT6jg64XFcagvtc%Xx5vKp+faT;jHn*?Zi`&m9F~ zgu#Ch3?AqK0DuI%gu^gwfS!5Hn1n?EuA(OJ08&f{0CYsJq+*NorKuoVPmLbJSPIOE z;OUG-7KM{G`b3<34Ffs_2=GoHIVAct%q}R28yzNf#iD^Q1(_XJRxH|SWXUbcmz(He zVT=ap(9O%pMcxgB9LRts000|6LxG%xGyMZ%8jJZ<1fKkXAF!DwKtopPM75z2E|$&_ zD(9Sxlb|Kxjub-=QW6N@ODrB_i<ksd$-rCz0A=8T3;;mC7=b|keC9vwf-O#-Q#4Kr z>cnQy1Ty*Aazd2G=|%{w(ZG-a4qQPv6hlk^K!k)|mR#JP;Szdk8nCJ6Zmb3Yx)eKz zLQK6*8JQPU&;p`NfpP2tJuKuwq9g#g0|@9^VufCS0>Cj$2znR?Js_1utQ}0U(nr{q zv5Z82X2?mpq}ci6=&=JCM94wj7{%>~mFQw0<_RsVizna#8C-;s9z%d$Vs?Jyl5#^9 zG-7`?giXdAoorl?U?UL~5CN4&67qy}PHBAHD0~>pE_`Gg_+ysPgK?OOI~)T{7DG?e zz@3d?iArObQXN!S(P)KAP_5Mlc!E`h0~x5*KafGR^yB^;jKq2z#Yt3zR#*}%;Z|Ji z4^2SjrDf!3A`O-|@tMR-S!xC4ZQ#Icy;vSC6SsaYfr*;rZ1vBc%Qm6A>3<Y>V~ z0hO1{<s;p-P31XBvekeQFkLasM?k`nf=nKtT~bZ7Ue!HC7VTHA=%arL;<ynDSL$j_ z5XOOZBvC+WMKp^MWakeNiGkc!LtaENjL3&t(n**^tiA|JTq3_{LNQcGfJ!G;jD(Y% z#A$r!Np`0l$w63oiK_$+*~njRJQXdJB22yuoObEM8U>+NgtYjmQ?bP`l%~XJqdpZA z3K|m{HicJwSwaSAcG~7a@`Mpk1ZKL!a)?8KM*gfb83)J$%+pQ9%pH&kqQ%r~nwYL< zej&yh*`PQ$gQ*BaEH;EmkeL~I$<i(@xHMI4iB)$gir0R|ak3}ltloQ0#fPd3q-hu? z(2^fGq*WXXTa*W!Zi%iPWOY;vQ27%};FzLJO{3fdve2v4{90kKkX%^kDxSnj$f`*! z31Xgx-r^D(Ny$YCMT#C#0}>#(2?vZKhm8KKSs}-493-~%3O6Vuqh`cXXo;M$Lor;; zN#Y6N=InrE?QJ39RqVnakeMGC!D>0l9t9}eI*5T(Z9o!9wSj2|jVaj>4NhT2fNmlt z6o~UCq#)&Nd`O2X{)`;FK{5;oy_%H_{`DaTfyx0vXk5?&e1*d?9PcsMM;kzdqGCp` zcme=4%W`Oi)lR1+9fQKQ%Kl1TOPps#_UQom$)6etErfs`G}qL!gA6=xLr#ZBSi~#^ z<dnj2fNof9A%io`PH(wh=4IY)L?%(JkzW`GKpq1gaEm6GYm(IPNN9z37>FORLPd}P z#`vRjEG=UA6Ec7!5y8-w{Ho?z5#}|HxUQ8>Naz0LZ2A=g+AYWc5|Uoo6lmGqyvCjY z-fQjs3hrfraugUF3Iz{zOht48i~v9<$ZQr!haBV#j%3J;aA-Kx0Uk)~auA$FEDS(; zLJ<tbB|1lcYQ#wp1^{R=ElEQD;xdIg7>CJ_$HlQ!|E_FRBFm1Q1}$hp7$hXVM4~|4 z!7(iCM^uE#z-dn{Uy^(TGOXE7_(<do7FnQXSr`*g$VE%=PP70(a8fYIzDqI4n-PQo z2+)JR1tdS1MA0zsF1!KNI@2KGfih=Fq1@9RI@#D>l-n588s$ii7-^PFt+r?aNS231 z{84tEhed=#gjh!Q-j+BZ14aa)0!9tgNOLr^P~PpCFmeNd03O2JFaUH&5&Qvqc;Z4N z1uebtKPZ8z*hebP&}n!8O8D!}L5l1Rp{G?1P7qKut&t3WM1DdDV%7kfwr*VD;od@u z5z@1YKE-VS$0@MRxWWDoIdR*83CBMGb5Bul7PNt3AZ9Ge!4>ob4RH&#R;{V1sT&I{ zV)Umh;la0T!$~qmF@(W7FJ&xd=Zi?yF#u@#eQCzgg=ENGuBZzN*O9E^K!+~Na%^c& zXu>i0mtTM+<lTikr~)*p?;Ts7Z^6*45U`la0S_?6VXhz4!sIR~$3esnTFOB&7=<`o zvFh5#AFSJmC~+L9f>B6ap@b<BS)&o<<34`gWX9rzd~8FUq)~9`3?U_e0%LzXlO^c^ z2;hMqq=CuS<K~HRW|$Q@#g=pSgpbyxWt_Hsyg_zu2n&RssUT^KXyAPw3kMLNu2ENg z%fJq!2U^)<dH(gJ3u(&Sgvq$-#PY677C3CW1SHJj%iCF+Q})P?bn8^^gzSaNRRWk+ z4j8h0ZAc)8cPvLm977>$3;;w-EJDbW%2+Goff6jtNibGGo&+8!@v*GLK`aX!7zaW4 zs3pI_T_7faCP@)6He_!p^)jZO!3<N-vRLGVSi@$Lj6_B(q=)aHi;qM_cmhO3V&b(5 z4tM~4(4#Y}=A1<HqmYJ%mq~`KQp9TKauBZ`C<oM5#IqbrMQjU+g8&)W;z35zx`@L! zv=UiKlo1LBVf?GjENCv`9oh~}>J|Y#@CQ2_L&@~Yh8T<V0?3Gzj8^!;hr~fLm}s1c zX@9+q{-ImVyo%ba)=>>COk?-&8jr+6jGZ``V>$-tNHk*N2@F)ZD#5)2erhg*o_V01 zxl)VnlUUOlwfLQnNY(O@t->9})kf^D=IrWRQ?ucg?1B-Lo9@n(n-_+nm??ppa&~fu zaU7<(n0rkUMN=too4!jC7z-vSfl(ml8(i>dn2IphKm?2gJrKkq0l*(jrxNhPVGewj zNBLj|BrLa`I&pSr#Q`+rT@ADsJs`z8n*<qTh`bl65=3oSJ26pI>Ppanab~1h1+g{O zT^Up5ve1I9Pigo>n{k-L8(8vk*t{kvL7Qp<wHzd-#{oZ7Dw&;peT8s#_vvc<77}^> z9%}8o9PmM4POwDe%!j@ULoVH;`XeTI2o%qUFA!Yog|XGGd}KVRa}-xkU_zTYl@kZv zVzUy#`(s+=ym81tb9p3M)+b{*^pd;{xbl_U`S)H?l*I63N&*1A-)wg#q`W|5POw=$ z_GDDhtCRKCRYo<28w=$;)}O#c?@d9pIP#5Z40O4}6&%Exp~Rj15FSa|`u$6!4MY}j zi(<7|9kj@YuEZkMKpoV8y|r2xL}v{c*~^&$v^D0D>lkgw9y0C3Xyk~OWk@^}0U5Xh z9{dm`A&4K${>fy4FJ{3M^ii)Yix*dn0q$YUyv$7#;aJ#Q5zvBVctZ2BLH7QGM0G96 zd1y;{XhL2B1iLVD;^_G&&J#O5;r`+910Y;Db;xSS5hrJZoDdp0Zuqw`;|4$6MwaA; zQR6?6898dC<;Pt(apJDv*o6a+CpnsM@RW(8MmRq;X6nI%L#LmEdbnW1A%jb@I2<=t zMd=ZwpOq*tc9nBdj-PNAX)%;jLk~M~|IV@t=g#ehD|$4&!P77tj+k;hg{wP|8;$~U z1_N~$2Y@GWc#z=;;U_Fcl^v;Goec8h<dY#j$_YEUGg*sz;`j;UHV$HUe)Is~ha(&^ z&;MkK)yih2R^1-4hMw&i_*S-ZoSoXWYa9Row051!0>Cp!j%=CBiT>AyUp#gI;_RBj zEzA^x+i)lcKt}m7P270O0U;+$5p_6Vi>py*thnvy0UT2<2O@E@_{Wbditq#ng79KT z4n5?k4-e1Ak^>pB#1RTO$bchoI5`M}Mk!h}VX!=lQd0|ue~Jj>4f+@g1H3EDz~MPR z-Uve+58h%ULk~5Kj4c9zn@y=AgCvrqlRUzKmJrxsN0WF6sv!<GaMa^H$bzDh3vTkl z;f*4Sfb5H&=&Hd88}Z07oH&Gn49>`aRLa94J%dch-#(LrAzC&VD~oVE@q-<$H2G?z zxA=6h!9y)_i_pBnfe4R`*3l%+IDG`NP9Hn$ku#RWp~a#H{%g?0lZxDN$D+L4c|$*i zK+vQH8ET-7PoTgILq$2**~LL_0Kns|8rBI4G&qB#b6Fvo)euiSJv)h{usq^Zj+fvo zVn*2hsR01U0KnlwIfe=6F@~(VQ%-h&EcK#{sNEDL0DnD&2<2$mW0&Vj&D5m?F(3{A zXSm72Gj`&r;Uv3YgI299-1M-gIB<9}jzR;CNgSJeqD=+>+|k6%U0@wZ92`fI@E^7K z<XEg>M8Y-HuWZg}ql-3*2nQa*fo3ek!qMR^w_tN8){JeMVv77|<4lu&#CeY-m9$EU zH{DM1N;;gez8cgzVv6Hi6=h&21P8fbi)S`)0O240iJ#Q#CV~{M!DL7`h*}&>JHl<Z z&b;>OqRmw5Y@>QZpyeNuHE|~>*lrSVts2PnH7o}8n@Xz`BT}aZHV*Q@s?r0`ZL6v> zlb2nx(A^1W%_}05)v@q!(~n({W{Wcq!-#{{g}z(M*Mshi%@2oozv^nQyT<71jW&Z` zBsp2qaPbG<N?Ma~73NdJ3d2G-Q`Ak8jI+e`1g@%;cX5WDJ+eq{xqf$n4sppcB9)=F z7~JqTklBa;Bcq$JBu;>Es@`M5;s*yhuz=NrAOzVpzyY?-58^-uPvDj!&S-@|-1tXk zEOL;GWQ!>5a7Y0sSip@;Mp~W`P<N2AERX(-WP~5A+6^C-g#@MLAS1j;W`Zb=B!z<( z7jsiY3iz1^&gp><d<?)KxH)#zFdWso)=5@IMB<fdEIm013D?pwJV0Yav_M;Q?gYUp zHt{hMjEn_K$gr{WV=M-|;TUyj5q^|0NFN*`XWkQsFpw$>;&`J14G0+tQW1hj>QqXS z=c}>E#xW%f;&9lKA{B0OEjY}KC^?g)A_7GZSzw16;nYG0UT}OK@C?}wm63~Fjf@`Z zT~|JmB(R9X51LRPfQ*xcd@YAx+ks&LKSGOJDkU#PTBHOQ$Pof+#DLb6BLSUPK%wNu zDvh+3*23X|?}^1uz~Rx5#sZ~L{r+QO1590Ibc3hF4N(&<O9L=Z2%HI}b3)><7!xlt zmVZhJTmSUgQNjU*szp$MY$;#8DpR_a>1UtDOXo)OBf|tGXrsX40&ErsObI4Vp4yC4 z>6%C=&*<SIX{bm@H`*1-Jt(B~0g5xju?y^36QX;{)Nr2ZMiO#G9D3je4QPc>gIXj( z7iyDJu~k)n+Ucnpc@4UpInQ;$DQ9W$l`R=XQ?vRrgApm0`;5SjEbM`P%*lekNU{}{ z)FG6$S<45B=!ZDI@_^VBZ2RQtzzzHroAs<pI4zh!jkHg&ILK%XHn5s*Qp=G+nh8=E zBqRn-Q6%-OUR^_IB8wPH{tmks3ue+sJrHh$A3o7fW?GxR5Gq9^Z>R%XE_AuR5@?VI z(ajVeLr1?Ja4Pm$M?_Xz(aH?5V?harTXa?#f(XbnIEcqB8GAs(9v88N1t(6$!4Ew6 z;&8TQDF|J95f!?nBkc7Of#Q)OVEz@n$Mvgjc&T3C!i%?>l!+X&fCm}`^0p*t=fxC) zHrhT|bswzW5R-SY?AF(@g$-{F;83pA7HTE5b!~2-$42*zOcOI%r)L0Q9DM03nE(I_ zkCf$yb*KUvX+TClkTHxL|5(R5M#hkdTx263`Nv3B@{ohPWGClf9j!<WRB3w9m%@h= z$WVoloowVLH~Aa>IiLX?HrSA}+G!zQ3d7~j3>*#gAq_N0!#DczjV1$m7<Wzsm%H3! z4|t#-a7Y6?%-m+r%;iB*1!+3hlNz9`BL{t!^pVrx0c7Oh8{b$*8XRS4g5cl|0@Y|b zM<@p_P~#ha=5v?7jAtOf`p!QP@}@gRQzObCMM3ejm4_ryiy14@laBK@+=(<#n>7v> zfK519fvbzW?^kfuS99*COX{J77ImP-wztg#Zhsrx;THF}$z5)9mzxI*;DIN!eQt2` zz}xV4_q@OD1A2ek+uN=~AF_S#ZvQ*q{`R-M1?~%41iatmu7hp`-tc-0oCkH_M8d}% z@H)i9;Tisaw<iux?s#YW2^t6Y!V!M&c5}Pr4SxeQcvRgLx42)&+}B(I(3v=K2(PyU zW{QN%&kTlOCO}tY(1|{DqXS*&NiVw6ht71TFa1L7_y#RxFwlfv-Jr}B3Vk{z7IZ=V z=tM_)(~T|@sV0=UXiq!2k|%;DX<hAF&rg0f%Nd{Z)3zDZd)WCdbiektTu&9e+LKX- zOkR$Og5N9-Qlkm8&jj+3m;B@@5BVB^0Bz*jMM2>{c;=$>8{5sK;1fUKj!FLMM<3<g zA^Z`tUuYxrNt@iYo?M=U!0oi}Jl1Isbov~|@s*!E(8EC#zszKbw8#4L4H^dzaDgh2 zIsOT>_i&219>-t#+ln&}1*i~&gAKdDI?;B*C-Qgy{N^7E`qz(8_LqNX?JxiQ9aVpp ziDMmQsR4Wm2d@&Yg^T`YEfOUD;4l3O@clGF{LI352&Vx7Y_FzEg^+<%g2=xB$tyC5 zT|7_ynC}3|Pw)`tHxk6ZO3--v;U%7gPg;*NBEl^Kg&U-*`(}_&XwWZe5C?BC?c4#R zyiSHJkOlvN8{mrul4!bGuhvp4l-wfmJh1&Z(4cgHN1l-U2#`+_iO?{xGaS#S{6H0& zq=<^h{~QpITreWm<3eoE1`Vo{PRK37aIb>UzcMHXd}=3F2sqkm7epbh<VTq@{z6k+ zf;Q-bHb%%04>1fy2#^#ph!_z78*!6_FcINU5+BhLD^Umug#r(P%?zz$)Ita=ViFf| z6ftov4r0KLZI<{X4S3*P&Mb?10>BW_5Kj>iNfD3`F$T*h6+MjtGta_8%6LkH&=`Ud zj}a0t5gBc<s*GpRJh3OzV7tC2q&h~nB9Rt_C=9dl5N%NzccM*rtDo#d{6YXOcA*GW zaifGQK~%^XlMxeZaau~{8P#z%JRlDG1_YMv*;*_MkYn2V1v=^~aIz(-R4FF1U?em_ z55gcnCg&?6#=X`81Rw_o2BJHrq`cf@2;%?*(&B{1f+RqoX|n4=K=NY#yaYZn#!FHp zBPg&JQOd+*^0k1(Nit>^EXG&jKp*mvMBY%F7$TdN$AAi}CEi6Grmn<{GNteYCkP@8 zkS0Zj!XYfDXxao}G;b_!!Y16SP2K|!?L;P9Vl3rg4oKyes);P^<c4+uo>HiAhQlL> z!Y#9?5R2~(YM=((VFN%)I@oBQ0uwR{=L;`{K+FdvhAAW1!3;7_trRAVRLdQT0BO`h zEg~X=c%myS;zBxREQSMw#;L@jrCQRUNoEo?*RmyMqk25UElE;9@?sywL3g?YsB8`p zbJJRO^J;n%XZ!#ec;x$@$TQ$)5Bu;Gwqu(Lh!%7JBjExX;3EDE%pjEvg2D9QK*B%| z#Lp&%ut92IM)r>#Y5*EA0%7z6F8HA$=p#G!uK?5n8j9c~*r5Oz<~&sh2TlS9_yIiF zf&xpWPJ*jcNa$Kv6Kp(T7tmrGHlQKn0dKy=3?d^|5+qM-=7p|>B``F=<b`<tGc>_s zi~tdO6oxu`G6d8UKHgvo8tfl-K^@wVGLxzp35`4%v?7KuBpz%)cS)CmL?mER2*ZMp z0*pgaLP8Z#5BOm)RPZ8-!0<*x{89_1pg{xlfCEwsEj(pF=_Fbts##d#A2ty{Ica8k zw0HEta>TC)=;K!y#w6XrhYmsqaKIq+00{CkP8s52F8;=NwxV5HGdirsGfY!8c{G=f zDpWMYYUqQ&?uHw<;WZc}4*J4JrH?mt(>Hmu#Q0<wK0_vQCbeJ=AnQjUt?hZ@!5tW7 zK*FFRJi!^Rz+V0*910*D8nRTJK_vH56sLk!P(*|_fE{A60Q8_t;A2JO;2#s>E8O7< z;z1u8lO2F2L7*co-oP_})X<^@D}KX>uHYEl0RW<_c-SExb^$P^>qG{Ohc>0goW)L@ z#UsA(dgcU3GGaKOgebD$7~%jL!oU;$fgj|6RZi$R`ZWQ1vIwAIA+Ur`>n1JeC0kol zDS=5cUXghMb#KhWKmNlAl!FDl2S6CCL~5WI{>%eC#=>hnBP4DHC8h^@TyN?O(<<@= zP<6v!VU-?~Ksj_4I+P;<lmlq~0RXI39{?mK%;P+U)>jNuT2`k>djo3*wF2uzlFq7k zELDA2gd4y`IkKQNl1e>~Bbzvdlk}u)J;Yus78!&h1X2v0JVOup5XJ;@nH-3>Xdw%p zwFD;h_ricXph0ACN-fNFDl7s3B*tdkVLs2|CbCE$)&f}Ci5ucTJm>>hY9h5V16cH9 z7b?<nj-dupB@8wKCKbs{TQ6%wR5Z6^^9C{wSj8<B25AxrHh5yKz9vUkHY7|UdU)q7 zKZA8JqfDzJV@M+$j)5Pvvj}v+46<_mK<EPi4rOSwU<%$NJbZ;sEhkG~OAeh@hA5;g zj0kuUB}tgYW@cj{03;u$)rSZTI>Z4wrYu~`Ll3S%aphnNdI!OZgqduTsIHZ9WWt7w z)O!gcCw~WL*<nq~V=<rsejn#>`J#J#C^0<haoE8V)<j8qGcr{7h3F(4(vhW1(7$%G zdN`yn`5_LJ;6c~{SN(QUJ>-O(c5qSxR9j1DB&vF10}uzSB<|-Fs_*(}4pBA$H%g3D z9t2zux8}?PTybCn0ALE5SA@QTg11A)dIbQKpsm2QWwc{x?Y9Q<!B?(839$HKx#1X` z;cx|HJ4zN|ra;F0HbuZU92ow=#OwrMHZ)mqAOgZ63zXnF0N_@9rDLI^Jcw#s&bMjX zm1>7X`UX=ePq>jwEJ(C793o^~03ZScwg?WF8wvmb!r*6rRyh~~0F1y0QcGBHpbY?E z7d+t#=GClLs#E^+F#iRT5%bxC6<iO7K>)xEHV;4|)L__wAEv+=LiKyn0%3MTLspg` zRW~#(B4+C(aRLccJj8OoLkQ)VFlfXGY$7j2<{yk;Kq!+Qpy3MOhaX}hi_l^(??j@M zWR$Ljcd7+^_4kpjmTH@aBP<L$ZbHUHxdy%f8fFSCZmv_#)}f{6dxKLW+!jOZ<v8bd zJGiJvz9NaA11{KjuKtwZAHskho+D%2ik1HnKv=+iai9~NVG6F`eYm08w!>H4VHddJ zJ8GaCQW-7);60T<AHY+_%3~J>qYchNiUB}{UNU@}*0xwDb?Zcd0K_eYr44jiij7(! zAR=UD0szu?I#A~-Dr$AUmm9wDN2DVwu-UX?usn)^z+kxm3`PgGgH;Y!j(<gvvjAM6 zmym@v3(SB{dcy=+hj&!s3uS_fhGT2a_iS;Bpr=4Eghdnh0a&o(eiR}tAYvDiItzeR z4k9#ddz62v+G?&vDL7*jQ!#%6Y>Y61(1LYYWz0kFXDT4o84#xCxS>1=8C<8}VR?&C zCWbPsM~8J|{xal%P@Sv)`Y*L{iCJ`q8w@53gr#Maxjv6UJO&eeI3kB{IJ#APIAX(7 zZ)y6Bz&S>hIh+GJDuah;A!CHrGvxTEX>K4NRfXapV9fwr2D=C%VE@orJdEI0ghiNx zbP5K-HARLbVYy}Ez`qTq1_YcPVmclMS$7J#bXAsvqh(W;r+0t@A_OB`eFc^Q#DV=5 zMU-PL@`+Afh)9aGYUPA@lG0BGR7)?TPHu%(kY-#cIF&}Z0REv3c%=;-Bz|F8$$do< zrr^5YdsAsjTS5GHg=AZy#fD2IRQ!jlZzYuzKsnG9KxjIrp+l7YgN+H<NBop|LhLs% z!<u>i>Zk$?T244W-SRB#WnqlmlqDeyGD3>wfIr(H3jmjs`-3|yQb6>#BzUNr(@Sdk zxyCn2QD-A7G6FWhg&>~eJw!RDgJVOQ)@+*yG<Wxg)^?(SsiK)$eq@ec{N<J!2-~O^ zKm?X`g?1{GBOhwux)TOO+hG3y_dCYLEp1z9+v?XvNc@ISz(bXlkyeDHcnHDbKk(P7 z0hFHgCwjP|Q@mo1<v<DelfLD+2BzSC5~O<|;z3sSf7zNU&ia=Cc&#aepJQ)xZbgvs zchF(lt(F;_g|-0nfjhul{KA!>FPvM)uvA=DaO_x-68pQsBC>PxSC(0Eg|=nnzzF_& z(yE2<IoQIszavAybhV3=s!8lHAwx`0sJiBHhFRh(g7kib@WMygCIEnpb->USMrfx1 zT*Sjy)WPxS!*V=4ZLg-WXQp>TIEkH`;p3$<ULH@bMU>g06T-j<T9o4(BGdy6-gDTl z@~5#Q19_l{fu;|Bgm~Ki5r3@0Ui~16z4#=88~_-B9k#ya;uy;102*#Sj%#i^+Og&U zWI$jUb_F907-3RcG~~-;uIL+FJ!A-ryykYhj(?ym@Ob7QIY<t%PGUPqg4~5~LTG;* zE^b}pHQtkP02=NBh`7=7XJdr8Vd}WC)DFi(%uEP%0De6q<b~EzMCLiN0RCK6NQ!xz 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 Tn3Tzxq{*6`!2|$+fB*nHitGVL diff --git a/docs/tutorial/gtk_tut_packbox1.jpg b/docs/tutorial/gtk_tut_packbox1.jpg deleted file mode 100644 index 3cd6053ca673431ca6abfd9798365279fa3a9d78..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24613 zcmeFZcU)6hw>};^p%Z$O8X-Y?FDgYa34#zpFVdCXq^U^n9TJLw0up+MKtPb*i&CXY z3B^Lk0xIf{nQ`WwJNLf#-rwi@?>#vrJLj<WUhCOw@3YTZ&&kjEpKAaHgf?6oKtx0Y za5;Ygel7tt0hHwA6y#)-6ciLdASD$IGc64@H4O)diJqB<llKA-CpR~rkhn0Pz$HO$ zZV?5@B}pk+Sy^6TrOS%as^T)T(!W(g1Ox(UsA<?~Y1yUux%s94e{Vm#0F0D?U1AUk zkpO_0k%)wm=w}~*8$bjgCMF>Q{A(j2BPAyyrldGOYry~@A|WOwrJ$q(k`R-S0RcqB zB%}aFG7vcvGrxe8Au7Fiij_@T-2jQ6W)YN;lQ;6co0frTXk4d|)v)#U3&Twc`PADL zf;Ek`?87569UPxxyZdHlx6Ui)JO}Cb?O#p*Ry!H_`MFDsMCVOWod1!L{nCw*h?o?_ zB84oRBw^-fGO+dTCR5i4ORN962%tIFpO}$^5pWeShEiptd0EY!Dw)sYzQ7;|8FaEe zoU=4=q!P+{?6jE<S3-vbBv<;M@#fs|T*x;0379wf7?;Z${<bagb(TC2v(w_|``<Ja zZn-9ftmoY79Yp<j5pr_!6OjKC@MGM-?5kl|wD#l;&Ks8$Xp%SHBj$D$-EfchA_f-p zn}6`(=vM-FHiJ_3zmf$%`PjbyO!JV<uWfmq;!2}g?&84N;-JKtZ|(QNWLz-k{?k@f z(N<mmh28eNC3!1HoOku3Z=Xz>?|-v8zWx2tcRHrcGgUFn*_)4N%QfGYU;6TXeHdnW z`*`bZ{MT*nokNv^{HGH){H5<kja99^xSklzp=Y<0qO9Lw%9om|c8By*M!N~f)>)57 zf-#}6{&51h<6>H^69^QAZD6q5VH#kszni%7s(rQJ;_GVr_3yPme!wvwSi1e%1+EAc z&0$Yo+X64JI!!I2^>)lBN|w&9e?5Xy*KMc;Pc2;Arrz7)>d~z97!2T9GGRGkJQMZR zm}Vl<w6K&VJRT(gV=kwo2Xw+1Yf6TI2$_eykEs;6gng5i-+th{&heVjHZyaMd7ADi zhkIY4SYaAeEf7IPQ1iT^zrFKjxMy6aKET55$4|g8=J>&zlVIYU-vKqb7Jaq;ZA^Xh zzVA{;&T!?z_l0}kE53D_%r2P`nyo$=#ssMEKIF}?dVR5{)3#&!R^39-v4y{@t6acp zmYMt4_|@6(JFuls-_Q69oUW*Ur274hfZ21Lu;1iWEBWoM2BQ9dU;cXxJoqPB-tllx zj&T|%+aio<!@?!;diV{z&P}m?{OqvM(m?L=YI6Ic>kQ{*VTYGP>2l(o<=v7eayNu! z5*n$Mkg6{7br;M}pUhqD{r(d`ml<;R`|w%_%blNqpMaZ<i)G((yYjA~TEgy}8crx< z6stIL0ZER#Pk!9W->5jf=hv*4!qsXeY;Q?0s1BhUSrm8Axh}t%u>1t<=KT}!*>hCq zC*XwT$cl5c?4{xXzV}#GtTfj^W679<1BwW%CuLJ$a8+D;q_X><{Dw{2Wr*0I=AIb4 zCQzd%e26dc6*oOwCXT3Rkze4($x%Bsa{z<S11z4vKaNDDe;uI|ODtw~BvjXuIL?2i z$>eo+S6-oIq}G^17MIDs<%{T3FBmaSe0%!nOo~Js!=K=4p+`Q9RPTu6*e9yTo$k6; z1@lgpKGCq~`RIetNtUfPrs*1K0$(f68|Y(B)vBn~^U5>io^n(O#f~X3B##y@Tc$^r z<Dy6hSy!G_j0pb(h<7D3;>_PpnYmK;u-^s-Q0Y(wJq32}BXsnl%x*OUTdBWSt|mUB zm$Wz5Q;7vrIs-wLL=X)mNQS42w(H@06HDK9a`1=JhhMPH)~Oz5afRj=GuLlspJhvN zIA<HaV!XE7IxMOaizjNtKYCZ)-}&)zddMfu&Yu7%Hsav=+k?%Gp8ya47EWY(3i{nP z8<x`|syB{FYpcQj64%h<(I_~u`4eQSD1de|{Q(YJ`|*BhvaQtNmJQ{s6#uK2g^;|3 zJRN7g!#!8|T#utC@7`9JRE(L7IyN;gJ)ijwYM!c<4XB<DiEUfrX$z?ORruH;8geUk zYnCRneR8Em_lLlaoBz9&#y<)>Qy)uT5tRHi!G9P1vyP7)kWZ({R))R*<}CC*d$N`O zu<JO_&fQglc=Mn~{-1>o353h}$$u*fDYH}ZyZIk=`lZ~tP9=rs3ad(+f4F|{wZdsa zb^TK5pM_eTsYlU*S*XMRYu4lcKyLfX-_L#Ze|D+g{jE`V?||3BzU7u(uh52<<O5}< zHZG;v!Ke$;b9q{sA6Rooy)lz*Tb2*aUpreq^vvD-^7Kel61iyTgx$@Q_z5UHl4xey z*=cDweW@d&7om&b7*7*qbUHD18<cO6oA3)f^TSQy9gA=h4)r15>EnXyp4_thCY<n| z*HM{X7JLX=SIiKF0z`=XRNdDvNQk+kOU!8v0&AoRBd-ch;|zq-rS8(c`3ZPpXlwec za*#7d;X2s%MTJVO^u`C=TI7~S6-hi`VRAs#uVI#XHG1CU_}!B@PV61k#^eWleb4V6 ztjd-s9Y%n@Om{w*ivO6%8}t)!Jw%xIn=h`_IG182WO8+Q@W=9=hmrfdfds-nt}JmG zc;NcPUo}8K(jjOdechW6LsQH;^Z0^AKH(jiMkiqEq+YJu33VeKyFLjnj82zHC*;#f z^zg|NGZet_V?=Fe^bCy#=Cv&QZiUl0JtzZmqm`x*LRWY;DsiBhWl=tYX3#M9B}O8A z>R!|P(%-n<k#@a-QSvk2VEVF8C}`5RN6$A0N)1DLh#O=x=V4{tjY?%ok~<1_`ivOe zUVP>cOi-SSHxGungM+l)x*_K2ipFEiREX%W&u+8j?d&yoaP@N_V&UE%S`ani#I3+w zy31WpUK>rk4fQ2Sir$-BI5erNcB<@|0~haz<@({QX-~E{Ubo8_7N_}1Gw+%uw#}6l z##jKo*N#UxAZ%-IOd&*$U?Hz??XSY{LVhaCxyPZ=d6$MQi$Y^391-bRtQh9RVRINC z`T!^-5}9rC)N|-Y3)qh6orl|cDUOI=Km|J&KSdAJa#0%bAyyC)OisGf?e~T)9_HkW z<TgAe?0zu~T25+S7(&%h>92+t6`-n?;tg$D<Ahz~V?Iepv-zM^^D1#CpvO|)_V#uX zc0_oVgelW%f@crPImmw4Lv+f|9u<X0v-ThOIf;W+84!A(9O0xNU5xo7n{Ds2#M?PL zBW8y+)4GsAFy!-K_%H$nM@G#c;T;E>VHNhEJn#Ox@(jWYv1&kh(M$Wq2_pvhjQQHU z)6r5O&s6rF*pk}g9sZlLqt*OWAnQAqs!OI=o+#k(<PM<-1)g{9Q?ltKl$lMK=h;V` znHVXI`o}io%&C<hAhbo@1?l4X+&N}i#uSnZ#zKoW2f^=vrr}9t)jdT8rNas^QKL|V zZn(MuU|aj;>0}x$(I@m^Fcb+l%ItM0kA5K5-H;ip>VSPvvCo>_{>E0a*BcpiBlD~M zAfg*GrjA4h)_@|b{qf@&B7A8mMe9^}-;s&n{mWtU?=L<d?!}P~i#X4grdX{r3(6gv zT7MR(k=nLu=2a>dn<h3*ZB9=|H8G1}Q^}8!S*T|KM1v#orm-GN%r`FD0lBuZ<69x} z78d63ms@xfF4u10PV`NN2lMSYFJU7^=^Q^7!5?Jg(6@<)QX~?WsMqoBbmM0$zTh9c zaUAc@_J#oC#4gDrX-9Num3+VLuOEBhj5-VJ9D4GsJfx4Dse;|@ToTj2QJJGHASO}% z-7q*6SE`u%+=wexA7MkrQLB%?L}*wfc#bC;t9WV2Jrxt9#zwmg%CLKIm%Vy}J^pBe zae=`e^fh%ENTV2Y!Hucc{cOQf3E+hlQSx9Y%IK+5<kZ_7({)oRHowZ_{P?47Om$-u zbK#aedil8`0!Zq0^^S*}(?0O>i6$K()|wN1(bU~d<T-Pe=CEE<t+;+2fJ1?gbma_6 zAZJQkpQvv3R-_6q_k@Yn5Rc|q`sqQGdgnT6LVdm{=-)D~n^TDE1Y^PalNa0;Oz+cX zGGm*XBj&sj6U0+G6rsd7X}s_X3U#lf`bSVDsnfQ{+3zSKEdbONeF+${G|vSHo}5r& z5H3!GhWk4;kSa+KXzG?7A$zW2J<rNS-rQ_aa=;Q<(|xedmO0EbQbdbPlw%sc#hLmQ zP)$uIRSL$6HY1VG!rqvsc>yaqizZJ`^R%;_t~p4L#yzwQ#gakj+mF0t(}8$3WDi=6 zBJ}zm(S0>6<o{`}fOOK<)ox8+1<6_eeG2x!U^aM#!S0rFz`-L!?o;)+2k%y&JL})m zrtjc=+L@8^y>)T9Qa9q@>R&5CX!EYL!*Gza7135Gs~XYuQKJ_dW7?_B7akF;w4X`` zIxW7Tc0UR-ru@F_)KekbAZ<NZ)Cy(JsY5QKqvzqs458`{WK_qv8im?jbfo2BM)225 zmOKlJs&ZZN&B7zyhgLT}ud_)*=o8;Vad8Mu1Vs3rzAF4R#jECW?#6r>{Zi%^O7rma z_0;J*es|hhz>ew{&n!k*K88@$c59gTMtTFi=6d3}ov&4~oNB4}?uTiaHRf+-JQ^7z zuf$5S2y*pjN)CGt`2roQlr`NUx;P2h#OMtlR;qN(NI=;Aa;0c@`T}>P(rsm@TvW2z zN=`KwLnQ7UO;omo1d}zGWeC|zWn3fRr#ut0hiS@d5DzcVv&X+-%O#J2#2q?za;(}H zuiAv`tM_<BiAG+14}+}kYpFL`K`%!5E*AStd>ofQH>5+xeC|=HeA3oz``&gBXEXN@ zp>tNQ724)gcAC_mlIT4PT~D!f0_Q>JHM8SQcw!2ao9A!qr=o02p_%E2w}^X2tefZ9 z_&fK`HNEFls0VrMTQ?2v<u7^pe$vkaF%qtO+JY8+`-A1fskioUv@lQa<D8hmCH)dQ z_V-JO%=c{U*u)A5%%O~S&={!Bw`}a2>L`fFh!tn<U$3&Q`;=z+EMWrEuJM7m+GP<B zW-|cW+DlJ`7Q7a0e|rN%!A*tA@L~1{E^ix%NNJ447hij{gB8Q>B(5<-bPy=uGE&F2 zo{bcsO#pTc`qykpeUGuiz29_^Q+V;@wzg&S>Z8xNmKEF$e`<*rd7Cs+Z(i;Ld8#g4 zGmg)8{?=I`0$D56l%}$*qvUPM>y-@Vbx9jlnU-C2_zk~1^O4|Mn8T&6puk5*A~hPB zg5~D;xS1U!Z?o}~&rlmxm{Rgap0yh%cZqOU_Sx;=<P2Y8Ms*5c8*>fAPe3_eX-F#z z`Q+WQN3?j=qsPovUgc7G^-u+F`N~*)VfILV3V60qTyauCf1Tfvit8*M&O23KFlx_m zNjJX3A&5bzTD;E*fu1BE3|xNTS8DT;c}}q>w-;P5r&#sIVb~i-+RBJXLxXSoYv5!x z14z@Jh$Z`Ie~@8Te89ov2=~SxEg9C-yjMb|`M4?M_x4-X$8$))opZ#?z4K^Q#S1Z7 zK&zIcL*tBRqqn5fh;NK@*;5BlWD*MA_GQ<&3W6|j;wvbDjmUzMeGCBUeivi91gV0O zNN;D>fm<SLnH|4e5~McOsUH*Na|st;)7jnvfTFCf(J9A&)teQ}^eu75!M5_>J$kuj z1J9SC)E11X_Oh@C8M?JE%wlmc=NtTYR6=Rzu{b(9bv(02$K*R#ZHlnoKGws&{NB`^ z*g#QJ1Zdu??8zdPxo7an)q%3H5N=oUp2KPWFA$w^>1mj4DGw4;F>aIDtqM0F9HHv# zKW}#5^LUO5++8(obywjPA>K?~gO5<8B&0mtK%LG&WO66(UcYz4Cnnc?^STDAB%?uD zq6d*qBy@4};j7Hq2?cUr{Iwh4RtdOeIYhHzQyLRlsFbffBhP^0HzT>`rB3H59Gm7P z^_hme)V;=SA0Lf;`gq;N)J>=~2|A$x<73WUnUh<2C@ndM+|7{&ARG8;u^wVB_3{W1 z71|A0N8ZKMN9)``AV><@F>W@sIy0@=@edhrBLLC{)tc_a4X~LkBRjZwhV6j+5#;63 zCAres7=m8^wY(a|*ki$=lrEz@4Gqnb%}DOY;EL^Tjra-cEDaA)9~P)H-POkE431B# z+#@FFCZ>F0KIlqX+hA<`ctoNoqvK7<)-nVOI*z8Tr`F~H8!?>gbkDP>DQCh?TEMop z{f9*3U_ac+H86OK^@a(#UjwK7=Y9y+5;u40VD_$}lRz)K?Zazl2n`yvG|v;7x;5ks z8qCjMYz0Pe9Uo<M`mZ(mg7kPu81pY`Ce@8r`fY{7fjVO80iN=JS1{#kdFr2}d+LQC zkTIRZV#!=fdSIUrQ)m3iSLid?g1=t$J1!d87Ax-@N)3i|EJRxw0HBk;8ILvem2{I} z$aK;hxZob8JQIMNLSex|k;16OfU<c{ihj=(Rw?h2?GFC3Y4k?gEM^9KJKW>?CpJWe z_cLkKW7$-i4c*SDmUsc5NH%s5$&Q(ZrlV3L_gr1`_s=+&d28Bu8`B!*(&9!XtUUgv zxT==)({AydRRi-6mCDTGYU@{?-mmC?`a!deo{Q$QxcvuvTM_pm<a%4LN4Z#JX8f|6 zdh6?f0LufwOKU-$LRO*n&GPzbj;J9oc;Yvz*<vdM!Z_8Kd}oXN725{eP((4jkJs>0 zB}gMZudkC%6Nu|N%+pX;Ijs#TYWlK$Esvf%A}Z1P2AgELrpXo2?tv8uQImWrlH2$4 z^2IHG2#iA=@Y)9HH=X&!(R;z)E#LA?;kKJ6R}YT%^{uuy-YPAY<XyahFQ~-vsO$+- z3|BIjQRv+g@tGZBOPp90;hp0we?K3nm|tDV(sZP<P^dDzdYQ@DM(5v5I#uc^f(zX8 zz$CDQ=D@}AAcU=L-Ds|!76s){k>B_s63(VT0<F^C9Qy>fZJEz3HS^}b<4xy;NZ0Bn z<ylMNv0MM~x&I4uNLPg}$31C#EgLasZ<j}ST`Xd@LL|e1IjkE(X{bd1NZYD!c7^xA z?N-|LGb#f!S*!^2zui?)REC2HGRW_{f$ph$RET)aX<EhSvXV3Tp3bZrXRuk(y5otz z?)0+X^w8+M(fj@Z5iunh{PsJ~SzgHA#N3v-+uv^hjaqEY;s@+mA1Iyy3t`9v4=F)? zf=2SkH||}PT+|8k=m-Lfis(YNd$i;$bH}Dg{w9|xbTKsmV7x{V-v}{hG4xWs%IXc0 zqUBByTh2jlmTXk3^W}Gyo8S(90`85*G1wk4a<VdKPfk8al5S>*Twb0hoA(s@2{0e- z1J{#-godrPQ&*0Ogwh)T08eBbA3z+=2Y^?QIY)E02Ht0soANI&VT#wJyRXr!)x*-g zTzEG;!%n=&J<T}$^Knr6kJiVp)y4Vx1fa6Z5NZ3Gg~cE@F{*kzUbKFN=m#b#Y~zM~ zwp)-`Vsa}-*6TZ<f=O>8TQXxn88Iz>7YQTM*tO@fCqpp_-AA=vRMNlrPPvrzQYz3q zP7MZIK}6LAFbsNX9Y(VRew6`9H}acp#O{fp#l(g08PkTRW_Sp?fAS7e9S^a5;ZgZ| zibk%i3O3jNHbh=~K5?VwP&do}WqQ+=Jfeo&h=Dc^7ofP!Q5Li=M&*ufZqTP{#CGpF z0_fNc<l(v>M3@s&waDE!KY+jcUT(9#DRb+U%u>xKLlXF*B|PdX>pg0sq^Fhy)FSgd ziF7y`z^_1LEX*%&l>DBWyble2Y1`Txh`-$W_)_f6CtL8cqJ9)*SrQk$g`2<^2Hrc7 z)GIyv9<Yv3uFyIFfXp6O%<fu$E3G=HV8C*(lVc!%ol9W6n%`y213k|@LQ0+HG8h0a zD3r`cRP`Pk_l~AA_dIoU9E>wJCb~&R;#1wKZfV?R;Ix@#;YVA+)jCHNs*_adg*(mq z)~|j1Ig{J=OzxGLH<;S}9u5o_=wmQyXCxHy=o}MNL+i2xtJTEFr~qi5clxBf%W49R z&`O3YhiO&wPnxm1r@BWNzAvjEAMG_g8!Nt>yJxH`BGsG~l$e|mT!DrnQZej$q178Q z)%0Ji;0AWnk9s9LaBH~25;$!$kwyHNhJL8KpGaz|szcaD!QQXFc}lC8HFMg#dpw1P zbZsc1Q{jNTZ(UHMn1d_kWeLScS#hx5+oacXcs|b~Es*(Y$VGP>%oY)#yeD$I*(ZPL zgyv~6`<?V1qF3nV#)J}?c+Ge<Fia!d2Vajd(SVzfS>P{DY5NKw1SJ=ux0W26$DiCz zf&hN3?$^Yl3D#olo-C1344CEsuCR8|6Hb}fzSIxyl3y<vCIW$CUelEqhmCFVWS*m) zQI6(cbYoA3e*)4xf0!82Vpr@1i&tH8b=n86!=KMOOjXqXiN#yoj`7rTua)^DWB-|I zGZCYB4@HY4wANYV7guQvsTdHZlT)ZDm%O93a>qkNjko0|0R9tz3uu4r)LC=8#q^$L zl2rKRm>j`HY+Lr1Fa`LGnB6b{Q-&suOxi3nf8)K!#TFsvy<~efn!1$SoE}BuG=r{U zxK0K~PEqN`DzGlQgE>qx#$J6I`~2<~&N%qJV4|$!Mpnyc)UvQe5WbeVTACa3e0#hq zm+=iqUr{Z-!<D;tweJS&irIbXR1B*zm-+OAA)QDEWEAFZIBcXc8Q5Ty|Es$CEm2b% zxZ=Hh&Al=R7J|jzS!Sjj)55En9<9{ZRSWdgw?7{oc}3RD<8F=viwpaWP=!*Bz^HJ? z>BLn5#^&FT?Kdrd0?<a+^}qFKH`+a1#3-yQ44@+3giN`{<XP-0j;!kdy}?3-Glgo5 z?jwk9ij#24s*%95DsqMy3%65^oW?s2E>lx(k*m-E(QY<*ZjCpiW|B*W`u5HBj)hHF z%^|h&aug!dSRdmBFh0t0<~??9tetS(G5q1m#^mGcEtq#jHi&MqUz*nt0vxM8L9jjl z{MvKJe8wF-Ahe!+t!eELRAr_cTc#Ml3o5Y;#N_J{hyis}t*UlQ$MWCvANt-hfAT^1 z*QfbzFrOdtX>SIQcEp&^<~dhjHKp;G0~uJ0ugq~oA#y%r(DiZp$9Uw$8fMkYS;aIk zHSIRIJH>bLm&P!S*w=R#2S@MGX5GG(_iC>6Y(^=%zK@K!WWvaFnZzdWCm@U^g=~02 z@@cGg3eWN!Fopl7P)Tp_Or&SWiN)6`g=b@5Y)=@~GZ4ry1Tx&7r!O7o#)uDpA2RO! z%Vw8S?!GqzgE_s2rv}9x{PfR_1durh<l>SpUaV#_>v~3f8@vyz-m~D3G7e4+>KZjL zeNYWG$JjceNzlU4MND_GP<f?*sELVArP}J7UrK&`R%jn>KXIk-%QVRXJ!sI31iOjI zZp0(HI)UJ#@Z5ccWAp3@$$id`+U!o!k28zV;tm-+Rb8PBte{GKQ4N(?JJ{)rXFcGT zmVfjR(+^jxv;@KshMb!HhP|{VeLF!&S44vZ;VukKUu+~}BVq%}ZvggLCs`ogspVA- zV-XMb8s2%6Jlqk%3hlSVhJ1Z_1B10er>Ysi1xIL8zW4i@z6|cZb?IQ$$YCxVjdg%p zX=ajU_IIf)!&H6(s<lkBxA}I-`dm~fAENpTqZu}^O-{6s9#jE_LAtp{DE~88trsho z^4a!t+|}(OpK;~rnc_F5P$DSRve-ij0yK+mib(pJzg1G%tDQ%P-kgkD$A12SeYMVT zRK!3r)&Z*&@P>c8cr^AK9sitVGOn;s1OkPN@P#XOUr^R}LZS<d{uLpvb&2=vbrbz^ z_eEb4@)`Z5jVF{+68S18<B-4N#$}fU{~jMM={|Y-G2r+-HQ1tJfwAzXLhZ|rdO*l# zx8ZyXBseR#L6HMB|BCn|Q4N!)Z_V>H)uZYKRSGtrdBy<D09$ZKy;Up>eBDc~YHjRh zzmq7lvpz57;I;G(@k-=|HptAl+=j;%Zosz8tY1qK>q$?+S{%JuC<3daO7R^Geq*Y7 zd)P`&??c}`{!eJm0Wz|COrhP8Uo2j}>_HayC-3ZdXw|eAQVKO=ZyU{!8$JuvM_hdL z;q*iHgG3%t_uVVjFPjLGtI1g)Gd~U_Dy$u|Nca*sq>^48gE~;XUc_srYuJ8tAvV~N zym^2+ZvB0XytM65=E_2q?cmI`y>pNRcMYjXUX+s7lnlv3+A5pd*EZ{^_(2@j{1MtZ z?3%^sLU~7snYYUKNp-k>YXh;*meGuV$FDm7)cYINz}<A}gXR(Te&RfRm}n1{pD)Ax zy`c@!w_$+sv!Z!xQHkr4&e}KbRNf|DD11IeH5;Hm6+RQ?LB`pXV5J@)9JV&MQxWi3 zaFV{Nq<keX<=T~o2))}{^?c=?kV{Q1%|_T3DPip4)5|q#bBcN0qGQFmbmaPK)^_9% z!C@~37kh)#rJh!Z^W(PS325_?si|-bgilPpAAEm`$-NJ{ESB&OIQVP_7n@^?JWB7- zw6U5!*D`}OgsSxSCtKuNzcQ-v-FfOAJ(cwsZG@qMQKn=iMr@cJ8*626S$(ZvEQrU5 z{ZXn(EYISggLnu_X96fGe2j~~guLsZFt45}u?o2Uvf13QBC#2qnF~iQ>qwJSAOIT% zlzj9Yf`J>A52}2UKT^091uEi%6u>}tfi9@r3!amFo1-US@(QoG=@Olwm^GD10uzBC z5=3oaj+`<Tm?IOVzO<C+NFg`-prDGL-MOy_5|PQ>>Pt}FNdOO8(>rP=MIIulx8G9< zMS9aL^E~;7(d6xO?E48tmWfiBQ4bBv;BD3-%QQJHeo@kkL)0s*0sQiCB0lKJoj)(t zhA#PUVn1r`h>YDWJmK-z$TUWm4B3kSKo34_Rj5q&BNvhlRzmlXW4{}7j>|&B$fx4! zF0@J|tD4XuvhryEu==}b$2nSW>1N5a)774c>oEz^NkzOYzNmg9yZ}>r+ndAVu>hj$ z`8V$c;}MtaE^kF`A$*M{s%bB*ug$2^^V~&Qgu()(nYVySG7<Nm#y8(aZX`fKsbrym zeqk?G-Y=L}zs!VbXC|=@2x=sbs!+$@rtjqd->e2aWBG0uz5RkrEmt&=K~d$ztiP)i z7u&BHE#FJekaoExosf_W*$V))WDb*92bv`v)AlM**v_g<OumhoGyJn=<BsUHW68i% zt|{iIr_?>%@u!ZW=ICdV9+8o+H5ZKt&yQ@MSKBLp+gI~P1wYmxl<U>!NuZuqf|a5- z?AtbyXLEjecMVsfJi7g3QB@gI?b?HO2VTw>>9Og*ITX)1MAG#m&pz4Xw6qYrMMFWE zQ!RA$2vRhW4FfhP;8gwxZsi>5@1}eD7fvodyzza@xI`9pHSEp+TdV@e(A2ut*?s1X z`&fPED^kYJ=;Aal1?r>y>ijjrOzJWk3}huT*bh8t-=RqSBKp@Lv(QT(3C$efT$Zh; zU_{{=MiSg3#W4JLpg{1I`JGBuD%J+An1}=w?a~Q1SOy7I=7;Q(<ueX?$PLoi5=A|q zg)t9M$6KzGz#9L(f6WR_zs+W0@R+83>KOh^NlHfUhvrB@+e&bI$wEF7cLxv|#k27c zRm@dJg-hE1aK$vZ54BhtM7YfGb!1!Be^I=AnA&{V+73Ac;|e8=J-}RdK{eZ>eG61j zjoeQ=h!)EPu>J-Ps-w;pF{W5z1fY%*+5YT|E5!W3N$L7M5}dkD^4l{@d$=I{2^}{+ z?NR!Ii;nsP=iDSBlrO0pmvD6OeY>zvlKjm`Z;qg0w1#_6w7qgOYm6JZS>K`_NGWl# zE3AhrCH`Gs`$oK3_UjqA{P`T}H>>i3@!Ty8ID48xKw*uEvf4q}fseMdolvDjvo*>u z>q@DNi;8w?B!W*aNcCO1D3=6}A4$9+x4hRj)_!?`v|-JF)wmG_Z%`*w0x0+TcC)qo zs`5`y({etR)k6$0TlGpl&}FnhXRz8w%1_{C#DH$^v+g#dGY833xlHN!?~_<W*GI4K z*&G$cFmL0^5X!MbMAs#auZ1Jx$t{QxGg>|H%FF-ik>9T`4BaPW4;njzjWS^Mi?(?Q zK`sVJjMotH*0m$2E9P0EzeD@mFxE=_Acpneu|oqzh`aa^#|MY*-(Am#@ozp#Y7|z? z;E1?SmqCweS!>IBIXx<(nPuyqY78pMpJ2HKIdpG3Va>Eh2Nb9nF_n7{QbiUM*#M;A z%VaS>9Lb9W#hI(1(24rD>0rWfFT^mc3D3(x7VRife$3R((W}EpEIoU6`&RHg-AGC! z%+d%lClmD^?dMP`x$G8T>Al$a>#Bq4{m)ah0SJk0<gV;A{?kv2ivE_zuxxl61l1=6 z;0kUHVy@l#F{`Vv-pq2=cAKDG?%zAA_*Zbj{?AndlpgjUmIuyte+xPozm9AOF~7gX z@)ID(q9gpNv~#8QOIbzKozu*0JDn~ESWJw7@{{h>zI8Y%w15ldv5=9v(8WDwXqOuq z`qam;-8h9pYZZOGp=0;JRHRqPwv{J+DNe_Owa1WGf)mMQLfaRW`&8c544QC*i#taK zCgmo!{j#O#%3?n77O{+L@?tuussNALZdi(5D?$W9jFQuJ9+D^6P21I)2&f9@JNr{W z)5F#4mjhCG)MSGhN2dkbKg_3jUCGKf*EcShc1Md~St(7Om7)zhBLNUS>vX{l_I5bC zlQ1z&AadS2CO_e_ha$RM$O>WzBt1BKvf3FRQS>qG?Yqq7JXIO7j=ZLcb`cTS-KLl3 zp=)Jg!isuc<R39dC{JfQuea$~d&V?YRkqJT6AkZzE>*+b-O+~{nd#gxA%I3K2g0Ke zozIz6o|@%&Bj}Z%I(^%kVPdqg@esU)T3}dTlnN>wiBdqN$v%`ds~+>Y7AK7?<+ey+ zzHc9oV61{5G&Itqdx&7%EYK6EQ1k<nTlb*c8N9dsOu$8T4Pn7uY0u=Uy~K&|WST)G z0dQVdX7r2tmMD-t!|RM%4s>by+>O}gZ;&+>pG%k24ce~z+i$QV{4dGShkhiVDH<uZ zqjrZQ;*8bMbp_~>FGwPJgrR9&liwHi8o~3qwhH?$5x!vlKrBngtsZ^A5pAMh$(ULx zGDhVl5;u*d)XPwaP>sD~F##!Ax;9e-<EOH|%|Q|xj!vhu3xwg>l)N3C=`MbbAt?4r zrg30wJ;o#W=_!~m*GkL9BDIZ7BW&|k&_KetO+J?+Q*P?=LacK+G;_?hQmpCyNJ2d6 zQ>pR%uJgpQqR)IJ`lEKjbv-s=8q}Aa$X%@-=kO-dK}Yx~h7~rZ1|XAAV%=D&jEZK7 zy)Q~8lR5``VdjlC@>84yU>z(Xf;VZm=Q`pb9JmBl68+WGX6B~muef-p4FO{~6nQ<i zEH~{wNW!)J+Li$#`RaT3kk-|K^9aS@cZ1p!mDAA*AuL3_V#9QTZ?thG68qjpCyHJ_ z@~O&%;ttgJUW<h>0hDp~0C~`tF8!<sljZpN@)Jk@*D;1o`P#vH&%ci4G`#-_c>COa zu7xVSj!4==kmc|&?DD|HEVBT?*x;gh2)-T&aW0|?SXSz}NnWz=p8t5st)u16;^&_L z*SQ_PdsPcQF5h2-xn(y01W-rm+g0l1CUL5Ku&oBB9<MiXn3`GkDK?J^ta%uy4>j7T zDK&UJ?-};HA%9DQ;Rq&*U`3%Tmb!$f6Ha%phE@zcQX-b}suI`ti;^ZdY?&M7yL!)> z&yn?uzb776LS7<PEBBiB<*(MgEalnn9Bpc&T(vJ!%sqjBMqPd_RQsr_<MbM!{u~jm z3#2J|qKAv+P<d4#ucFC14rxR+CuRB2pDo$WIH5@`Cc05>2ak4{&iQVuM=)+cUmTXd zN%|UowEIaX?#_&*-rYF8;mnn34n`r_=}`F(d{t->h6iG{WEvv?FNB9D(Qb%gO9=M) zaO^<X{^JYJ40;K#-9y+?B-o$t`LJT_>o?=rivyRaY3ypBvxg{;*gppW$eIpdYjg}_ zKxCCx@}P`%(Rf}t6eHCnt|L9ys|Q$Ix$_h{+x8}W5o!3KnXS$UqkqB=)RV9fx37|L zL(C&n8A`T9AOrg#mMlp;Ulcurt1Nc&-KF-+<+@`%FU!ZE;Osb2(=0}Q!ju~h%gu*; zY6mzBv>30JtWsa-F+|!I#u;3gxf1<aTu@4bn+ytp3yQ{Vz*fDVzfvrpY|hML5x+a^ z!|kIy^R2C^W=y5pomB&rS7=t-_C{*8-+4B=z4t{c(Rbwbn8!6ttD_@AKeAjzw`E%g zu6Hb!kD%~^LnqK!QkU-@!rzw9*r14{Th)C(0r#JTZ^2QbtPe~|Bs1sxgu3;O?KbZ= zqqLF_+%%$ER^z|ncc5rakQBFWHRojcl=rRyq8~L<42gAXYwk|miIk6&hLfo);0*xY zN!yKw%XYq%y&8_HXV>dZ><Uj7bUdC<*(+noN})dG68!K(q}%*P>&5q1NLXc6S)ts4 zPl2OlLJ5_k&^u1AJHs0SEP^|u?xsDReC@BfH=N#=<ro(m+z?)3NfRB&4~Os-FglW~ zgD$z>5jk>m@%4S2(lVCZHITuis#qR0gR6^az$)W1_Hu_uU~B|#3v$x^HY!XrL3($c zb4=sn#M-g~>HDR&kl^Iwfc?6D>qPnHN07cZ7wy1%@sIM2>pff&RJz@Y78{ss()#Fm zhDUC2YsFSeu0YSCazrc|z~J_GcNkESSW1MRTWi34;+Bb$8vpI{xQN`tR;KU!52-O= z?b=rYA+0aEeTpks60V3&v+KCofo#e|rF@hvpaO#d&HNfm2mQgzei#HTkUje1T+*GH zcZ#1yuyz%WNaj9yD+`+ezaB0P4x#XZ++~qa#eolIryf#rv$loOj~@!oSJvx)+r_rr za+b<RhEHRZP+6(Prx1BJ@8t|XUZMof3)C!hss@pcGa#*53`SPQW3}5%rTY15PaACV z?fx_V&zo>Norb=?D+}s|;^dmD48`bFeaeQg!#Gy?Cg#9q86~Eb|0ht5e}O9SKY%*- zzW}v`>HEYVpw1COI{pCFq!_ds6%{pLUH!^oFqs<w3f&oUD<gR(NiAf_=p|11+8C1% ztM1AeS+<WUX5sG>6LQjcS<ob6O<0G+>q)shNi9*F-vS@=lk3DiG~c=&6|X=vs~kze zqdDH7{}cn^NZ%Res*-lXBSYnyWO0h=SlQ+wWCq5;G89JPtrE+2L50zawqO5Qm?8-y zXlIJyY(_6%iV%v+Y+&sI0?1h8hn7>N`2+Z`F?q%aSa_uiE5`^ybj%x)sff`qHF-85 zsjw8FQf!EHG2$W`Ymh{-%yK;O{gaX9Up&5QzHi~r%~qdRROTKoQT?!zITA#*{+GNG zGm~PQZ<AkDz9{|#Eag{^G|gZ6_%Qj0-qp`<Tzx7%dho3=BI&o&^^R}M`j_X@zIp9! zRnffoWNZ1|qjN$=fU*-#q<lR3!#=)dR>rpdTa75rcnOtkHIY*?EtnNh;w(@q&-J2> z@C^0qpDf&O9`D~BmoNQtE}IVZ{X^!)yyumj_&uZMsdIky!HsE`kgW5R_`j3Q`Vw&O zzmWZ-LEP2R)@j)^!(X~O^#+|-nz&Rq|K4D(;n}l%890kl-AeE)mc<(4x~^2x9isb0 zQr0rQ->i|k7JL7-dIA4IJ?D^Lrt$no(<F}fH;#<ZDp)872ew13F{(e5wPi0iuV z>*2;<eC_v?C;q{fN?+9azr*i;)yO{;{AJw#Ap3`L<=oFY&H?188|&Iz8f08zdFI!C zz%Tgq)h|dZ-OGRc*86`{Hl?NKrtrkC|3A6T@74;Tw*TmzoIkqbciENyy=?1mJ^Pm| z_J`HqWVPL7Bvt&6`uzJnUVEwx!G7Q-{?Mdi=?~{R_mgM;t)Kj6<}ag4{uFgi`%UPa z@^bFN|E2c-v*o|TD1>tAl_6>I<i74^yf^ouJu+p-@)s7>%{koXKC1h>ImPjL^S}3w z;UA;O$i1oacMX0YfUy5G@_u*k|3S3)cjfH{Xt0sH@2NaCqsX>fg;qmSg5N*>E3#`c zg3K(!mX%*m%<x6YJmj*yHCpme$Yp#<^xxjZJ^5FR_a8TL(UrT~l4nDY!iX442%v(e zDz3-{L&yU%E)lXQNZx8a+AGjx>`@ZSfVY-j58qI_mA^HR?D)eMoc;X~eL&fE&>fQC z{vOunLJkV=CY3JF$S4ii$S#|S4{2797??K}I*ZU$hR=@XWENLO7ZV%$cGo2pDO$p` z1r53!>Xt}UaS*ts3o;jIU<QF8XOQZo9`zhr1r4?NxFmbpw;)5Yk8BQar>EJ2v9;!l zkDTjs^q6{(356y^N-%+)!%Cmq^i!zk3n8rCa}zekXbmK)cr}o8NM8PE{wILMYPRUq zWnB(vkSnzq*?yUFF)-T{hLm{pt%s>IC4iUbj$vntofk%2sARpu++TX}5!Gx<Q+tU9 z3ivFC%9n*EryG|xXmw%AZ2mm`CKjn@3Ary=t!}IS4r-{|hLK({SV?VQ4%h8LwfBk} z`p+e-j}4@8;K!p^M!lPs3xr-1QOGSJ=suFp^Bus*i=&>V7O2L|J1c(#_wD4NEzQG6 zWX=Qlh!kA2co7T;F!d;SLmRZ9=nJ~wBNOkZ+*MWq^@O&RLQ^6ysf|BV;ECE5c{1p& z?G5i!ptp&M9f-;tnR`~FLwwSafw_4r&MbQ8;zCkdcYXFmTcRjK&(mub33p{bI;z%T z%c>nJt#e<y7!X)H+KteOWSHyLGuiv9ANCNb#Y$<S!F4M}VR>7CrexZo*U!K0bB^BA zP1NnPP9atX8cr28W!VhrxQSKU=p@4qSutXDR7fJuQA>30iE$2xm?|FVa?lgKDb%s< zx+x)|6Dr!R*C3^@cgRig&|$7`CAlXhHfOw<WC2Y;I)WBiE4R%pphFn0iuVAf91~T+ zAjYt3o`z|e(J%Oi-R}pkwQWCmf7r5W-ZAJk{w&s1()&&Rg~4uTmpcSdpI;k>p_q@~ zql#D|ytt{@lELtaqyllpy3MWv_5(ZU$Vi4$$c$FL9f_D?E#;*WVxzOsytC|~;O!~r zo6zgy>YiQcrWe64A#EI})Ds97vNY4JhIL@FE_Vr0joi>?R9Yz4Dpp?PG~W-vl4%Jn zTg1<P{0X2E)S6TRWhQZY>k@WV#3g;MC2DvF<=7+PI?m#?(2)^K5-1%?qK~ptRo(%! zc8`)!+>RZdbw#7#{)hPnV<E1QM5`Nsxt=*jve;8!+Imct@{)jW+56qa+zXe_$V5Cl zc}{nV#n{7WKO&N+Bl!8zDq=3q`E#F}=c>vY;II+0bQmjXJgvRP)NZVzY|G(yJ_#kp z7B*?^i&nNSV#{UCw~PsT>lxmHUd?+em0o*H5mAcWv8^y2Af-E&P^-9T=t`8P$2?ER z@4i&sZ<g(U;S2_I{$i&yf}CqX5dz8)P=3C$1-@J%%LP8_Tx+y(R%Bd8(K^r*lsS`V zPiFb*vBjv@MZ`Jb3>01o=GUv)D}^%CAt?d0mE?Uq{dM@ju;gen3}X%ucDEdkoX##j z)Lx@<dk~-!)za6&!B7PM%-nLpJ}J}G?;W^L3laOgnhJ_QUZSh!hZtXrupt8V^rS^z zVfRp9`0PKQz#<CO6q6O(QZNu*seVO7ybMBw_n@)FzwPCIbfzE+Ho$>5-@%V2MkIFO z)f>4_<v#(kzZc@p3;*U|vRSGAB06t}Obx7V5mnoNru7Fs$6te)a9r|gB_LPd53BPZ zQi_H@?g;!>hx`LwxF!g>K)l{oxCe~H>k3k|`giSW-a2~_8)o)&VMOS^{9xvRAa{2@ zJo<Wm$$jMZXMwW(9|zCx)E@o)U{ZIv2sKh1=Lkde)VSSDI3ZE*|AQw4u}Y0nY%j;1 z<ZsXLIRB%X-x{GTw*)(zf`u5Ek+9<k`=0=B%a;&@KJ;IiK@*&o!g|fG$e&eAruU0T z_N<BgZ`<g<sLiMgX@7s34LWV}?Zv;Aq1Df59^7V)h#E0o5HzVWA8KH(DyN9VnR1uu z_RqPYmn{?G3zS`1hNH6USAvU{DJ%jD`}m#H58W6LVtD4tl&BuAcq6x@OR18}_rwKT z)Zz=`q%@AmG8bXq?q!t<Ahev_czSxBkt0nBZfFrK!#p`}0InOcgZI>x9dr8iHxqQ| z-guMotJFl5S+7M=TLgD`dV}k)K!paZ>!Vf$y7(?xpR?59xNff4deU%OqtU5A#fS2r zd8Ev%EuD%f07$&3VH^?-P-4h8Z5tkuNl0ru`*x{H`1?iSX1Jfq(nD2>l{vvalS((N z=msf?y-fj#83a9|QD7Lf>?>9?6p4smFY8?fE&63WYIscL1%^Lg+umf52^uDe(%Qjq zUl<VJ!yor9q(_NJH=Iv+jv9F+0w|AMp;SGGd9SD~d)5eHCz{TDr0@GwhN@+HdTIB& zj;c(L<_v)H2E^rCHomX>9Qhl$Y;$6-Ki(MeRv(y|C=KNrbtEa{zSOfYv5^%ub%p&i z`P;z@`j!hpbTVbmgAvW@l(YOm=$Z&t&})r_Wm}($=zc6g|F8^^b45dN;GAWn+%XJC zhHJfuwbBe)R-AZ0updD?-(2mw;P)tBZ*05sa--wS)|}I5PqW3=dZ5btEZzamzC&~) zne^fV-N<67H5Y#q2~L_wX)3gO(@P^v;3r_9#Fwl;FGg;8tmUG^%*aDg>1Agsn4=hZ zUu3bE%F8Tqkc3;_wREkgZR#;{EODH#^69sSmKgK=R)7uriy-5?l3}B+ks_jc`I@*X z5tsfOl1&g?J;(fkeAU<E<9vXS5LYNC6ptVEaRce1Z0G63A_WAG9z}mU`dm!@ID0GJ zK{+N)91YQeArT76?CYS6?y6ERj@Of-Jnp9>d9gJ8>LbPcqhkHaQNmGaP^eoJF;=Mb zb11~j#Gqs4_9#6*ez@w+%7M&Q%(9llY?+BPuZ#Qz>)<}wQOEx3{xUEG1{6vU485RC zsFw|=#@EEX=*>YQcgqgyqAsPTV&y?V+==B3^Vqvchf&5ORyHC;>`Wil7Gciitw)Vd zed0<<2{%t61N%dlfsFy&z4Lw7*e;mfm)6IU8(V11x|JD*Iv|p!9nyhgxpWNAJH<)A z3tW4LzxPyunyr^B^n(woxRXPzofXE$kybTgA>S581|RJi$ArBIU_?icxko$kU$~zF z>8Ic_RDKNb6hqS$cr{YrR!O#Iu&7T^&uApSHBqkg2}Wt`K@pQ9-zNPSIPNMEnJW^8 zlvurZMeD^EEu=>GYESVuSsdRuI<?B7`TXJpT5Nc)&vd`g7@@`{A}sGXKU)=WD|qPN z<Rs7>AAct~vV;{YPO}Tn2c=)GuqaPP0o(KnU0GqI)z=Dyggn6-uT+wQjo%3Yk2lwm zk{j%osWcpzhoC@n{{Y6!cLbp->Vp;@j9W1{DWN+P|MtHjDb?yszoof~$)4JjE?HMz z8t)IpI;XDdp2)j9%%>=(hxL%6c5O`a1VNT2{O1e1E`k;Gw}o9+e7f5C!p<i$FQ>a> zvft?K<O4fdk+H@)e2LeYR66SGOX_;wIS~)HLlm$9-%S$H>ANrQR6ln4>{_?`R#qbf zXy9mzt5z6`#A|Dbn3=$Y5-ad)xp#Y-5~v1_zwwG%vd;VATxQVt{8u7SfGC6y`s$pz zRR7xO$V+L@PD+10rLMP6=%)K7zGx%<zEzjlR)gBB$E@}bBD}`CZSks!Jc+am)Ebjf z>vY#1NMouIR@n*~8Xkpv(4$*{b*t+Boe#3VuwC6^$uMQi4?f{jfnFKs_ePbPPOw!N z%%<n{de^`99&~w8eNHMJLe+ntIeYZuU0H?ckM|FCL+-wGMb<y?%X4p+%M+yYwOo23 zO*mpHdFu|lNl8wN_KRBva^FAe;G9w#Avc_NbFf{yS4d$XhPW^P(jIHxFs~cGdz0Qv z=s;j#{H?fBvE&g$@%!vJ{wSfc<?{Z9g6sQ@E}cg#h>2J^E}=PrE>8}<i<^aVVxbMw z>C9N6O0nTf)v$Uz`J764=<O5rpMXgBZxTPI=A~V)ezSh@_&lUdX!+Qg+_rw&EEU_< z!qKyKk;<`y8{fJ^=jc8wk9D9~JR?>c-&{3)-b2U<P8_8_U*S76f3LKz_S{j?(>2x! zw4{DRShx7>%1NH6#KdH=|8_fN$h@>e=%z*K9iYXCH?-d7Fr68&{$prGL_TO`?MbHV zK}my4Ju)9XlX#Rl>VCt$1pO@hy+)efe5l%Zj^GH0S)3U<QHDg9u|PvmzFSP^Yr(P# z)Q_?^Bf>ve)N9sEYorqTA}%kB(*#P->#W1_TDTFYykQO<2<ZXfu)W<+h5f_L4V`cf zbMvw095ifbrwk~ncAUzrRxgzKn3N_<^3FtJ*W{Tvh%u(ymC-}+Jk895#_EZHm6BbF z)%BnMQ0|E<^3aZo8P?hP>{z;(`Yqa`!Um5GDMxY&^NAu>h=*83UuPwf?VqPOglPvq znYX9kvKMz<MZI6@WJ>|>5jt9CAJQi446yRtU?&Km^|5jiDo3x}7I@tX9Q0YKV90os zT0NV-&7^nY<yUqptW*URmRWs~qh`LM$<=*HW-hPRLjxZgeygCw>p{0AVn+JTe@O(W z#NEg4m9_m;AS3P0Y%xC=G3Q97PXz<;Qj(ssiYD3}@x2J3iMT-1j66l&78?X%gr&8S zBkC$$suB`B=J1oikV_8<J0_D!?7rmeJ{Km(d7a;mfw2U}eDEg`L5L|?<blD)x;N9{ zMyH)lhD8Mb&`z=m|5#GZmj=L^Ml2sQMi|<Vc6VhkP`04qkB7a=?Z1_Ok^4Sv@Tcb& zymEL)U1cZ1FPT~<g>3|$B=jlr1ej!r2Due~^9=y2omwPCyN#)^y4V9>Z6=9a!H*`F zlJ%C8qDwvtF(<xT2C7rlbr>VM-aLyP(R7mUm0?J^JcuSlB$emi1Sn*VQ0Oa~MK$IR zN&q7eeufSsDI9tO{oZ8lF#(}Vv~|(AtY#!@^AwV(Ep<(QnHga9R|5K<q_Tf3&i+ix z{;wBje~S@TKO@<@TI;LY{Nc7jlcwwH)?aLgx}$c3)9fC8tti}3ki->zE81^{E^5X| zb+Q0&dH6`i^Y^+f?;2#M88qqaYRL=NH7>Bpzq7`<gHLw%25N&}vgQx^UrQB#nmMBI zH?qTTsdWtZb?fs4WZHk7fP8gy<FC|DRCJ@%nk7QcdF)4Bskf*Zg2^FQINYQ7bgDYz zA9Nige2UGq&sxKlU*BHGiRpkX)=PQ6R^0e_0seV=9}#xg!bLM>d-@a5z@D3JXSbD0 zw=%@n+MSXk^b}gXmvh=5+TdY?F;<8DlVo73ICrs1kZy63#RpUCm^#7=!m{z`+>dX$ z6?2{tT((cHT%J;x@5SOjnz{`~fu%OtO363QAA6}QI!>oUW-+Kzzmdn`QE9>dplspZ ze%0R>=A@`Mu!p5Vq}le;M@&b0!?0*PTBM8xqNHbV_drRHpm$a1T~H6H-_C_FPNbkB zGG9X{IVKZ(@r2K18qMU#=t?sJ<RZP8o&oV_$BGQ$Ue4A!O%lf32e+znrAAcF2{NW* zfuJiswY@II1({<$HRnvKHdU%{<V<R$P=@2+n1}nuglc%(RK%Y&mq)+2B{O#R*<(4T zI+Lk!uzrEz%;f;qObh3_5;>(A5SEzB3{Mnb{$e-OF#U7Z3f(G*u36C3)wDSM!(t0V zZ<qtA5Ln%{(G?FC_!4L_4CE63#Z*fg;6hm6GcZO$_yn$4OVcOa9yYr0BE{)@<U;3> ziYxBk1o`Nr#of7|fc0Uwg_FPw3nnPgAJi$sKR6d<<?8<}=fb}76aLA*@1bSQ$6tad zJ@6na3d~0hAd1&pyL9yf#7G>j801@y4}kPoROtP-xyLV%41rHg4;KVf4|e9Z-CG z>C-Qw;V;sO(WT#*xAy-n^EN-^!c>))40u;8c3gUfM)w;2CxB91X4p-UylOeD{o-e( zAt6UnEZ5vGF#d$P&^m3z1v#~UVJPK-4g(gSBUDY_##N``185@t5MThg!bagmk!=n; zD<5m#=P8dr8)h)OZ_SKtn+%9T(+)u#Er!Qfo<X<;FxD;X?vS8&U^D&V(AaZw;}y9l zU<b!@HqiS)mm)0bIWOoprpaXbXj+b+t2flUSP{uU$&pT58?tKUTI@Mvd-l4vSC{;p zy~lIT-m77$M4-$Au?`GW3u6iiJPR=iCo^{o-u=^+ThqJ+v5e~q#ikiI;7J$NH8>Of z9H||^5OBKB!v9yyl|VzezhM+YZk8cs$;dV%Q}!mVP%?-ZGuA=2$~N}UBvID6#Y|%< zs=-WU8T-EE+SgRdM2JwbOE;9#e_V9qw&;KEJ@=eBXU?4O{oe2W-rxJZ-<;p`yibQm z&m{l+lo^}AwV`QT!~mqli{}hjM41s3c?$=0G|(+g@)09|?7ATctlKj@u55IfNC#TE z3dOC<zoKp8%#_=#v;94s>WiXL&!^NmRrdK0XE9@JthIeH;m~|LzE|cR5?x#6LK%-V zN3dzYEjjNqgViKdCl(qacDtgGrCf1hB%(AJDC43Ru5zYkD5I6eD-1B5Kp==qY#tg9 z2KkUNMrBm4nCq#5TQn+$$1jT}qVsW#;_du4B5=ZP(URD>%&5w|j3p+;RnrTntDNmI zDagoqp+F@Ft};AV3kDLm1NX=2bGzBNuds9)3I%{1*+CGHB$(dp0p*F1l*i3pr*h;- zyfG+D-4`Z9mS5nqvdB<(oYTSIVlax?3T~ozR%)sDy#dtbKfSJCsM9Db@22<zmKbHO zq}BkiBy2Bjmx|B36Ae$WvZZ4fQ{g<$XxG^@ELP(%evI?-qsz87IyKM5=6F&GvE7Wo z+k2veHOC>YUgzXfd{^Q%;g_+XNO$?;pGIbccWFamgKcLEqAq5ch2&Nwqp%?umqG<d z`o*)N_L}7vf+2f+Une$$EoeRFfneIJfvYeVAR46W!;U4=R~zWfe=w==$-Imqxh3Y! zN37<Jyv&Ny)L~g>3g4laYhd+LrG(ELx7n1NPPVF8-%TbnuhMW=$xG=YLK5Le0{J}m z)HUdHh9sZi*WfS$+E-M0$!fPufCLz>R2wf!nb+PFD>ve(d8R|6(2@yOg8{<`r1R;W zmaK=$EoL_R>4@W{lN%gEJwd~OWU^%Rmt3yvG@4whI>Z>NbuQy{>ItX`?JEszaHJ(^ zC{>Mvff^JjgyaldK+1m)mxE8N*&g}z6Wy}<Mn=?knNcB%F^Bzow6Dqx9P`(UGdCx~ zT#J01L13*y4%u|!Qap(w25R=j?{n|va7{e8?Qn^k^I**d!IxcdA6<k)7za_u%g-!~ zuM}B_;dDXO5VYl*B>cslKI3#woR{(j{9s+#eg=JE&w*UGK@_dU2^L*&KN|`)SpuU6 z3TrH0#z2Zr*g}5gJ$$Dr0wS+{pdMups)>#f=8oTwCNhL^!JZ*+t_9+vMFO=3E5kFj zalk#L3!YZt_)8X9N^v4hptda?MI~Umq3ukg<vLZ0eES1)nx5#^Or;x5jsEsqf0#nL z4nW`5C(M_{QCkHWv(7Ep!>@Q!F3iPqdfp}9zRnDBRMW|`G5TqYt%aL(Gyu(m39|7r ztGJh!*X<ft=&EehJ8`BLorO$*=vkLcOXI11&)w4{6xV=q!Zs;KEF8AT<Um_tuKKC6 zhG|lHWGQbmJwg{+bk8)Jy;{epD)suqMzrefnq2r|Qmi?~;;Kt5_9|}-cqqLa!D0wh z>kMWMN?4153ZKa7*M8Sr$)1K!*Z3yVCv4iDp0@@bg)<%%-07|v{0Q$r+sG^&lJwlY zKg#7e!2uo|#A<vPC<;=%mw0hfBh=`<1U;2|M;NIdn=8WBDo-L*3eu}f-^l=}(G_4x zWYq3T_reovkvX-Iae$@1rQOrsBJ`6UXRqOkJd3KP2`fu$rrC^gC^vs74*D1>reoeg za5n%XYtUyG!+_9mMl-aUct_N_)!5^R>{`b3R-m)gO$vXKMZA{CBFK_&p@$^4oz->O z^)lg10wLw0*h|HTmJqg5-WaT;8-KeJb{CL2Kx^HlWXcjx8oCx*b>~lD0t?1`N-K<A zN)*lw|6ZtT5g1aPVImJ<crFe;aqJK<BBx^_)jT#rr!|`_EsE!{WuGeZH(uyki$apN zI-DAmA_#f9G;rMBdG3&wF(>e4HG?2B8o)E*njlP8p|5)8rfdo@K7BOZZ#>UB5sRxp zk9ln>tD1db(NOHBJk`B!z3pvY#rMcZv?Vox;na)^!RN_b9PA<0>MX5l;1*AM#f)p2 zYcX^fuR^=h=)Ogl`_FG>uVCaTMw=j@h)=K@9ZO^nQ@;vWEthPv0&lN?prox~!ujQJ zRbfPh*VY5oaA^X$PBHn|RGDMZYX$5$z}jwB+U_YO&-JcNg6hM33vAW>vKBYNxhF2m z`1=aVhzPpW)2*yI+lAqMSl}Y`B#k<zP?Bd)#oYd-Ya-y;HYS`qvyCdbq5d^M3lS&E zS7H}CS;Q8p*J3t<PgyX@8O%sr=MTpz$5o<B7zGHNO^tn^B;QFdY*jrJZR}QSY~;zs z(v&v7?gTr_ogZzj7fe6V#W^#tV4uGm^RbBdL{b9ZM)o;(&sO@scVuXev0PUV61BvF zNE@$xbC2`$Kq1)$!sm%Gq9hz<Dkmk{+zSvD&Lf3t`6ZhWEK4Z9^;rAkoU7uZIB{M2 z`I;XVM#pw=c{k$uJvANyDduq}d#S}(X;yuBMq#f9!ELZo^HhuDzMhDPw$Kmuckyr3 z$)NU`_Q4Q!*Hk4bn8{{3h#DO_qjl|loj;6HkNMqEj`~I#<cxnaawO-uEf-dd1-9J) z8WL3yWEYRKTmR%R)R#ghad$oM4~Ty*g%dUGS<2zT2dPpXO#Sm#=3glVww=h+>z?p1 zz{6MbDU-z|vSvp^H#@rK8^-Dir!^Ye<8d{nrL4!cO!Y`J93MarT#?xf;xt|u-^Utm z$Y};A=v(%uI$1;v@@lmEg2W`0)|K~H8r3Cm**YV8^%ZKg$!AV*dUzEf`}%cty`E@d z`4iEEsn=5#M)y7sDWkrsMU|WN-S^_fGMYdL4TYzPD)`=V0wcMW#W<E_Lzdpwe;!y- zTZkn5?BPdCZXNR*m$Vv|&X!$L`uL}uZzMD)wNy<O;}SI~zt-tpGtN7c>rN_!*-U8r zNSV@0Cv7QoprGwFX#dg>BrKlp?hNBS#*i0pqCU|H1YWbU-aoeK1GQoocj9B}ZrcYb zN1h@qE*H-b-XpT{xiOacfW%ZordoHsMyN*d6_OujziDFkE4XD%Pc2^?FM&c36TK6S zhwnf2n!D0nv4C;xzG{nqPqYS_yJRc@PuH`J5IIQG1c5$M$dbE6)ANa_J+w{HePlcv zG3X5Qd|!a#5&cDh^SFLLPi>OPPiKB3$@#yRb=mp)Wj(qiHM3MRUtjfa92Q8`F^{CN zCxm46?iu`5%^MuKAO3RW{>;Hu$u(rraWV)&1KGS#CJJ>7C7ElrhccZbUtWlW69k^{ z-1AUd{ly9=u-4aS)Alf@>r=vfbafK^3kWaiUCS~w>*^j|6&dKqVK^Ji6!`1Sn>7R- zBw@K4*F<0U`M1(W=G3$DLI=5Wit}z4?TFohvEn=7*|*~@MCmH@n!ce!ClM{)%qS`e zHKhRR1*+?XijFhc9rtvPAEoiI0r~la(uy9ALzwoxac!3K%BQu<2M#_K>Xp?S=3FGs zjxbP)Ws~*lZg|V(wcZq*MTFoh8XXE4B_uatd^dAr<|%h)bG8c^C4oF<br{-{xtcb2 zUTBDaCk0vBC52{6T^k5O(QcHPrhBmZ3qYieDSq{{es&S{gV{xamNLalrvwV}#He-! zJJ92=sWbR1jE>A;dc{`K<-LNIz9ykFd_|ozACYH;lt#R?r{`sav+vl%(*{1ua=c<B zS+*+;W@mnU_eW9Ng;zA$Vvwm;FDAXlf2;Ml|GBj59nZ@{_s*(RBCT1c?vrnL@6!4( z(sxr=<&|pGyLRN9)#&uIL)#aGtkZ7$__+bG0a1H9OsdP?jGVmA{O}Xq0pH>F`v<nA zEPCVqX8Q4;Gv!?nSq<PPyawRDAL|!hf5P-90{HJue~^JM7WT)neqMraCaYC-tk;Ua z(e@LaUCUd<WET67OkmE7_i6Jc=K}V;A-+F2tpDM?*|7Q_fo=GoH|?|6-JsKrTmCzd z{##x@C%`RN?7Lb0A_3p9yc)LL1T4lQR+@nH?BTCBfxoqjA6stJ=f<!8Ut7{zWe)$1 zXCU$e>nI^7bKA|N{X^l$_C=GS0wl{?@u7=S*d}WpS_i$m+Ck6$*+B~kj(=&`gt~-i W-xQnUN}N1EPOI^05+|5^>iQp9F`7F7 diff --git a/docs/tutorial/gtk_tut_packbox2.eps b/docs/tutorial/gtk_tut_packbox2.eps deleted file mode 100644 index e023a027e9..0000000000 --- a/docs/tutorial/gtk_tut_packbox2.eps +++ /dev/null @@ -1,5428 +0,0 @@ -%!PS-Adobe-3.0 EPSF-3.0 -%%Creator: (ImageMagick) -%%Title: (2.eps) -%%CreationDate: (Thu Jul 27 12:47:03 2000) -%%BoundingBox: 0 0 294.543 146 -%%DocumentData: Clean7Bit -%%LanguageLevel: 1 -%%Pages: 0 -%%EndComments - -%%BeginDefaults -%%PageOrientation: Portrait -%%EndDefaults - -%%BeginProlog -% -% Display a color image. The image is displayed in color on -% Postscript viewers or printers that support color, otherwise -% it is displayed as grayscale. -% -/buffer 512 string def -/byte 1 string def -/color_packet 3 string def -/pixels 768 string def - -/DirectClassPacket -{ - % - % Get a DirectClass packet. - % - % Parameters: - % red. - % green. - % blue. - % length: number of pixels minus one of this color (optional). - % - currentfile color_packet readhexstring pop pop - compression 0 gt - { - /number_pixels 3 def - } - { - currentfile byte readhexstring pop 0 get - /number_pixels exch 1 add 3 mul def - } ifelse - 0 3 number_pixels 1 sub - { - pixels exch color_packet putinterval - } for - pixels 0 number_pixels getinterval -} bind def - -/DirectClassImage -{ - % - % Display a DirectClass image. - % - systemdict /colorimage known - { - columns rows 8 - [ - columns 0 0 - rows neg 0 rows - ] - { DirectClassPacket } false 3 colorimage - } - { - % - % No colorimage operator; convert to grayscale. - % - columns rows 8 - [ - columns 0 0 - rows neg 0 rows - ] - { GrayDirectClassPacket } image - } ifelse -} bind def - -/GrayDirectClassPacket -{ - % - % Get a DirectClass packet; convert to grayscale. - % - % Parameters: - % red - % green - % blue - % length: number of pixels minus one of this color (optional). - % - currentfile color_packet readhexstring pop pop - color_packet 0 get 0.299 mul - color_packet 1 get 0.587 mul add - color_packet 2 get 0.114 mul add - cvi - /gray_packet exch def - compression 0 gt - { - /number_pixels 1 def - } - { - currentfile byte readhexstring pop 0 get - /number_pixels exch 1 add def - } ifelse - 0 1 number_pixels 1 sub - { - pixels exch gray_packet put - } for - pixels 0 number_pixels getinterval -} bind def - -/GrayPseudoClassPacket -{ - % - % Get a PseudoClass packet; convert to grayscale. - % - % Parameters: - % index: index into the colormap. - % length: number of pixels minus one of this color (optional). - % - currentfile byte readhexstring pop 0 get - /offset exch 3 mul def - /color_packet colormap offset 3 getinterval def - color_packet 0 get 0.299 mul - color_packet 1 get 0.587 mul add - color_packet 2 get 0.114 mul add - cvi - /gray_packet exch def - compression 0 gt - { - /number_pixels 1 def - } - { - currentfile byte readhexstring pop 0 get - /number_pixels exch 1 add def - } ifelse - 0 1 number_pixels 1 sub - { - pixels exch gray_packet put - } for - pixels 0 number_pixels getinterval -} bind def - -/PseudoClassPacket -{ - % - % Get a PseudoClass packet. - % - % Parameters: - % index: index into the colormap. - % length: number of pixels minus one of this color (optional). - % - currentfile byte readhexstring pop 0 get - /offset exch 3 mul def - /color_packet colormap offset 3 getinterval def - compression 0 gt - { - /number_pixels 3 def - } - { - currentfile byte readhexstring pop 0 get - /number_pixels exch 1 add 3 mul def - } ifelse - 0 3 number_pixels 1 sub - { - pixels exch color_packet putinterval - } for - pixels 0 number_pixels getinterval -} bind def - -/PseudoClassImage -{ - % - % Display a PseudoClass image. - % - % Parameters: - % class: 0-PseudoClass or 1-Grayscale. - % - currentfile buffer readline pop - token pop /class exch def pop - class 0 gt - { - currentfile buffer readline pop - token pop /depth exch def pop - /grays columns 8 add depth sub depth mul 8 idiv string def - columns rows depth - [ - columns 0 0 - rows neg 0 rows - ] - { currentfile grays readhexstring pop } image - } - { - % - % Parameters: - % colors: number of colors in the colormap. - % colormap: red, green, blue color packets. - % - currentfile buffer readline pop - token pop /colors exch def pop - /colors colors 3 mul def - /colormap colors string def - currentfile colormap readhexstring pop pop - systemdict /colorimage known - { - columns rows 8 - [ - columns 0 0 - rows neg 0 rows - ] - { PseudoClassPacket } false 3 colorimage - } - { - % - % No colorimage operator; convert to grayscale. - % - columns rows 8 - [ - columns 0 0 - rows neg 0 rows - ] - { GrayPseudoClassPacket } image - } ifelse - } ifelse -} bind def - -/DisplayImage -{ - % - % Display a DirectClass or PseudoClass image. - % - % Parameters: - % x & y translation. - % x & y scale. - % label pointsize. - % image label. - % image columns & rows. - % class: 0-DirectClass or 1-PseudoClass. - % compression: 0-RunlengthEncodedCompression or 1-NoCompression. - % hex color packets. - % - gsave - currentfile buffer readline pop - token pop /x exch def - token pop /y exch def pop - x y translate - currentfile buffer readline pop - token pop /x exch def - token pop /y exch def pop - currentfile buffer readline pop - token pop /pointsize exch def pop - /Helvetica findfont pointsize scalefont setfont - x y scale - currentfile buffer readline pop - token pop /columns exch def - token pop /rows exch def pop - currentfile buffer readline pop - token pop /class exch def pop - currentfile buffer readline pop - token pop /compression exch def pop - class 0 gt { PseudoClassImage } { DirectClassImage } ifelse - grestore -} bind def -%%EndProlog -%%Page: 1 1 -%%PageBoundingBox: 0 0 296 147 -userdict begin -%%BeginData: -DisplayImage -0 0 -295.543 146.743 -12 -431 214 -1 -0 -0 -20 -030209 -0e0e2d -010178 -050555 -7a7b7b -070786 -231e9b -7975a3 -827e8f -8f8c98 -a5a2ad -bdbac5 -c1bec9 -d4d1db -d8d4e1 -e1dee9 -f5f3f9 -e4e4dc -c6cac0 -82847b -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000300030002000200020002000200020005000500020005000500050005000500 -020005000200020002000200020002000300030003000200020002000300030005000200 -020002000200020002000200020005000200020002000200020002000200050005000500 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020003000200020002000200020002000200020002000200 -020003000200020002000200020002000200020002000200020003000200020002000200 -020002000200020002000200020003000200020002000200020002000200020002000200 -020003000200020002000200020002000200020002000200020003000200020002000200 -020002000200020002000200020003000200020002000200020002000200020002000200 -020003000200020002000200020002000200020002000200020003000200020002000200 -020002000200020002000200020003000200020002000200020002000200020002000200 -020003000200020002000200020002000200020002000200020003000200020002000200 -020002000200020002000200020003000200020002000200020002000200020002000200 -020003000200020002000200020002000200020002000200020003000200020002000200 -020002000200020002000200020003000200020002000200020002000200020002000200 -020003000200020002000200020002000200020002000200020003000200020002000200 -020002000200020002000200020003000200020002000200020002000200020002000200 -020003000200020002000200020002000200020002000200020003000200020002000200 -020002000200020002000200020003000200020002000200020002000200020002000200 -020003000200020002000200020003000200020002000200030001000100000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -100010001000100010001000100010001000100010001000100010001000100010001100 -10000e000600050005000500050005000500050005000500050005000500050005000500 -050005000500050005000500050005000500050005000500050002000600050005000500 -050005000500060002000500060002000500050005000500060005000500060005000500 -050005000500060005000500060005000500050005000500050005000500050005000500 -050005000500050005000500060005000500050005000500050005000500050005000500 -060005000500050005000500050005000500050005000500060005000500050005000500 -050005000500050005000500060005000500050005000500050005000500050005000500 -060005000500050005000500050005000500050005000500060005000500050005000500 -050005000500050005000500060005000500050005000500050005000500050005000500 -060005000500050005000500050005000500050005000500060005000500050005000500 -050005000500050005000500060005000500050005000500050005000500050005000500 -060005000500050005000500050005000500050005000500060005000500050005000500 -050005000500050005000500060005000500050005000500050005000500050005000500 -060005000500050005000500050005000500050005000500060005000500050005000500 -050005000500050005000500060005000500050005000500050005000500050005000500 -060005000500050005000500050005000500050005000500060005000500050005000500 -050005000500050005000500060005000500050005000500050005000500050005000500 -060005000500050005000500050005000500050005000500060005000500050005000500 -050005000500050005000500060005000500050005000500050005000500050005000500 -06000500050005000500050005000600050006000500030001000f001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001200000000001000 -0d0012000d000d00120011000d000d000d000d000d000d000d000d000d000d000e000d00 -070006000500050002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020005000200020003000500020006000200 -050002000200020005000500020002000200020002000200020002000200020002000200 -020002000200020002000200020002000500020002000200020002000500020002000200 -020002000200020005000200020002000500020002000200020002000200020005000200 -020002000500020002000200020002000200020005000200020002000500020002000200 -020002000200020005000200020002000500020002000200020002000200020005000200 -020002000500020002000200020002000200020005000200020002000500020002000200 -020002000200020005000200020002000500020002000200020002000200020005000200 -020002000500020002000200020002000200020005000200020002000500020002000200 -020002000200020005000200020002000500020002000200020002000200020005000200 -020002000500020002000200020002000200020005000200020002000500020002000200 -020002000200020005000200020002000500020002000200020002000200020005000200 -020002000500020002000200020002000200020005000200020002000500020002000200 -020002000200020005000200020002000500020002000200020002000200020005000200 -020002000500020002000200020002000200020005000200020002000500020002000200 -020002000200020005000200020002000500020002000200020002000200020005000200 -020002000500020002000200020002000200020005000200020002000500020002000200 -020002000200020005000200020002000500020002000200020002000200020005000200 -0200020002000500020002000300030005000200030001001000110012000d0012000d00 -0d0012000d00110012000d000d0011000d000d0012000d000d0011000d0012000d000d00 -120011000d000d00120012000d000d000d000d00120012000d000d000d00120012000d00 -0d0012000d000d000d000d00110012000d00120012000d000d0009000000000010000d00 -110004000000000000000000000000000000000000000000000000000c000d000e000700 -050005000500020002000200020002000200030003000200030003000300030003000200 -020002000200020002000200020005000200020005000300030002000600020002000500 -020002000200020006000300020002000300020003000200020002000200020003000200 -020003000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -0200020002000200020002000200020005000300010010000b0004000900040013001300 -04000400040013000400040004000400090013000d000d00120013001300130004000400 -040004001300040004001300130004000400130012000d000d0004001300040013000900 -13000400130004000400130013000400040009000d00120013000000000010000d001200 -120010001000100010001000100010001000100010001000100010000d000d0007000600 -020005000200020002000200020002000200020003000300020002000200050002000200 -020002000200020005000500050005000500020003000200050002000200050002000200 -020003000500020002000300020002000200020002000200020002000200020002000200 -020002000200020002000200050005000200050002000500050005000200050005000200 -050005000200050005000500020005000500050005000200050005000200050002000500 -050005000200050005000200050005000200050005000500020005000500050005000200 -050005000200050002000500050005000200050005000200050005000200050005000500 -020005000500050005000200050005000200050002000500050005000200050005000200 -050005000200050005000500020005000500050005000200050005000200050002000500 -050005000200050005000200050005000200050005000500020005000500050005000200 -050005000200050002000500050005000200050005000200050005000200050005000500 -020005000500050005000200050005000200050002000500050005000200050005000200 -050005000200050005000500020005000500050005000200050005000200050002000500 -050005000200050005000200050005000200050005000500020005000500050005000200 -050005000200050002000500050005000200050005000200050005000200050005000500 -020005000500050005000200050005000200050002000500050005000200050005000200 -050005000200050005000500020005000500050005000200050005000200050002000500 -050005000200050005000200050005000200050005000500020005000500050005000200 -050005000200050002000500050005000200050005000200050005000200050005000500 -020005000500020002000200020002000300010010000d00130010001000100010001000 -10001000100010001000100010001000120010000d001200130010001000100010001000 -100010001000100010001000100010000d00100012001200090010001000100010001000 -10001000100010001100100010001000120010000d00040000000000100012000d000400 -0000000000000000000000000000000000000000000000000d0012000d00070002000200 -020002000200020002000200020002000200020002000200020005000500050002000200 -020002000200050005000500050002000200030010000500060003000200020002001000 -020002000500030002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -02000200020002000200020002000300010010000d000400100011000d000d0012000d00 -12000d000d00120012000d000d00090010000d000d00130010000d000d000d0012000d00 -12000d000d0012000d0012001200130010000d000d00040010000d000d000d0012000d00 -12000d000d000d000d0012001200130010000d0004000000000010000d000d0011001000 -10001000100010001000100010001000100010000f0010000c000e000700060005000500 -020002000200020002000500020002000200020002000500050002000500020002000200 -030002000200020005000200020003000300100003000200020002000200030010000300 -020002000200030002000200020002000200020002000200020002000200020002000200 -020002000200050002000200020002000200020002000200020002000200020002000200 -020002000500020002000200050002000200020002000200020002000200020002000200 -020002000200020002000200020002000500020002000200050002000200020002000200 -020002000200020002000200020002000200020002000200020002000500020002000200 -050002000200020002000200020002000200020002000200020002000200020002000200 -020002000500020002000200050002000200020002000200020002000200020002000200 -020002000200020002000200020002000500020002000200050002000200020002000200 -020002000200020002000200020002000200020002000200020002000500020002000200 -050002000200020002000200020002000200020002000200020002000200020002000200 -020002000500020002000200050002000200020002000200020002000200020002000200 -020002000200020002000200020002000500020002000200050002000200020002000200 -020002000200020002000200020002000200020002000200020002000500020002000200 -050002000200020002000200020002000200020002000200020002000200020002000200 -020002000500020002000200050002000200020002000200020002000200020002000200 -020002000200020002000200020002000500020002000200050002000200020002000200 -020002000200020002000200020002000200020002000200020002000500020002000200 -0500020002000200020002000300010010000d00130010001200120012000d0011000d00 -0d000d000d000d000d001200130010000d000d00040010001200110012000d000d001200 -0d000d000d00120011001200130010000d000d0004001000110012000d000d0011001200 -1200110012000d000d000d00130010000d0004000000000010000d000d00040000000000 -00000000000000000000000000000000000001000c000c000e0007000500050005000200 -020002000200020002000200020005000500020002000200020002000200030002000200 -020002000200030003000300020003001000020002000200030003000200100002000300 -020003000300020002000200020002000200030002000200020002000200020002000200 -020002000200020005000200050002000200020005000200050002000200020005000200 -020002000200020002000200020002000200020005000200050002000200020005000200 -050002000200050002000200020002000200020002000200020002000200020005000200 -050002000200020005000200050002000200020005000200020002000200020002000200 -020002000200020005000200050002000200020005000200050002000200020005000200 -020002000200020002000200020002000200020005000200050002000200020005000200 -050002000200020005000200020002000200020002000200020002000200020005000200 -050002000200020005000200050002000200050002000200020002000200020002000200 -020002000200020005000200050002000200020005000200050002000200020005000200 -020002000200020002000200020002000200020005000200050002000200020005000200 -050002000200020005000200020002000200020002000200020002000200020005000200 -050002000200020005000200050002000200020005000200020002000200020002000200 -020002000200020005000200050002000200020005000200050002000200050002000200 -020002000200020002000200020002000200020005000200050002000200020005000200 -050002000200020005000200020002000200020002000200020002000200020005000200 -050002000200020005000200050002000200050002000200020002000200020002000200 -020002000200020002000300010010001200040010000d000d000d00120012000d001200 -0d00120012000d001200130010000d001200130010000d000d0000000000000000000000 -00000000000012000d001300100011000d000400100012001300000012000d000d000d00 -1200000004000d001200130010000d00130000000000100012000d001100100010001000 -10001000100010001000100010001000100010000d000d00070006000500050002000300 -020010000300100010001000020005000300030010001000100010000300030002000300 -100010001000100003000300030010000300020002001000030002001000030010001000 -100003000300020003001000100010001000030002001000100003000200020010001000 -020002000200020002000200050002000500020005000200020002000500020002000200 -020002000200020002000200050002000200020005000200050002000200020002000200 -020005000200020002000200020002000200020002000200050002000500020002000200 -050002000500020005000200020002000500020002000200020002000200020002000200 -050002000200020005000200050002000200020005000200050002000200020002000200 -020002000200020002000200050002000500020002000200050002000500020005000200 -020002000500020002000200020002000200020002000200050002000200020005000200 -050002000200020002000200020005000200020002000200020002000200020002000200 -050002000500020002000200050002000500020005000200020002000500020002000200 -020002000200020002000200050002000200020005000200050002000200020005000200 -050002000200020002000200020002000200020002000200050002000500020002000200 -050002000500020005000200020002000500020002000200020002000200020002000200 -050002000200020005000200050002000200020002000200020005000200020002000200 -020002000200020002000200050002000500020002000200050002000500020005000200 -020002000500020002000200020002000200020002000200050002000200020005000200 -050002000200020002000200020005000200020005000200050002000500020005000200 -02000200020002000300010010000d00040010000d000d00120012000d000d000d000d00 -120012000d000d00130010000d0012000400100012001100000000000000000000000000 -000000000d0012001300100012000d00130010000d001200000000000d00120011000000 -000012000d000d00040010000d0004000000000010001200120004000000000000000000 -000000000000000000000000000000000c000e000d000700060005000500020002000300 -100010000300030010001000030002001000100003000300100010000300030010001000 -010003001000100002000300100002000200100003000300030010001000030003001000 -100003000200100010000200030010001000020003001000020003000300100003000200 -020005000200020005000200020002000200020002000200050002000200020005000200 -050002000500020005000200020002000500020002000200020005000200050002000200 -020005000200050002000500020005000200050002000200020002000200020005000200 -020002000200020002000200050002000200020005000200050002000500020005000200 -020002000500020002000200020002000500020002000200020002000500020005000200 -050002000500020005000200020002000200020005000200020002000200020002000200 -050002000200020005000200050002000500020005000200020002000500020002000200 -020005000200050002000200020005000200050002000500020005000200050002000200 -020002000200020005000200020002000200020002000200050002000200020005000200 -050002000500020005000200020002000500020002000200020002000500020002000200 -020002000500020005000200050002000500020005000200020002000200020005000200 -020002000200020002000200050002000200020005000200050002000500020005000200 -020002000500020002000200020005000200050002000200020005000200050002000500 -020005000200050002000200020002000200020005000200020002000200020002000200 -050002000200020005000200050002000500020005000200020002000500020002000200 -020005000200050002000200020005000200020002000200020002000200020002000200 -0200020002000300010010000d00130010000d00110012000d000d00120012000d000d00 -120011000d001300100012000d00130010000d0012000000000000000000000000000000 -00000d000d00130010000d00120004001000120012000d00000000001200000000000d00 -0d000d00120013001000120004000000000010000d000d00110010001000100010001000 -100010001000100010001000100010000d000e0007000600050005000300020003001000 -030003000200030010000300030003000100030001000300100003000300100003000300 -030003000200030003001000020010000200030002000300100003000300030003001000 -020003001000030003000300010010000300020003001000020010000300030002000200 -020002000200020002000200020002000500020002000200020002000500020002000200 -050002000200020005000200050002000200020005000200020002000200050002000200 -020002000200020002000500020002000200050002000200050002000200020002000200 -020002000500020002000200020002000500020002000200050002000200020005000200 -050002000200020005000200020002000200020005000200050002000500020002000200 -050002000200020002000200050002000200020002000200020002000500020002000200 -020002000500020002000200050002000200020005000200050002000200020005000200 -020002000200050002000200020002000200020002000500020002000200050002000200 -050002000200020002000200020002000500020002000200020002000500020002000200 -050002000200020005000200050002000200020005000200020002000200020005000200 -050002000500020002000200050002000200020002000200050002000200020002000200 -020002000500020002000200020002000500020002000200050002000200020005000200 -050002000200020005000200020002000200050002000200020002000200020002000500 -020002000200050002000200050002000200020002000200020002000500020002000200 -020002000500020002000200050002000200020005000200050002000200020005000200 -020002000200050002000200020002000200020005000200020002000200020002000200 -020002000300010010000d00040010000d000d0012000d000d000d000d000d000d001200 -0d001200040010000d000d00040010001100120001000d00110012000d0011000b000000 -12000d00040010000d000d00130010000d000d000d001200000000000000120012000d00 -0d000d00040010000d00040000000000100012000d000400000000000000000000000000 -0000000000000000000000000d000d000d00070006000600050002000300030010000300 -020003000300100001000100010010001000100010001000010003001000030003000200 -020003000300030010001000020002000300030003001000030003000300030010000300 -020010000300030003000300100003000200030003001000020003000300020002000500 -020002000500020005000200050002000200020005000200050002000200020005000200 -020002000500020002000200020002000500020002000500020002000200050002000500 -020005000200020002000500020002000200020005000200020002000500020005000200 -050002000200020005000200050002000200020005000200020002000500020002000200 -020002000500020002000200050002000500020002000200020002000200020005000200 -020002000500020005000200020002000500020005000200050002000200020005000200 -050002000200020005000200020002000500020002000200020002000500020002000500 -020002000200050002000500020005000200020002000500020002000200020005000200 -020002000500020005000200050002000200020005000200050002000200020005000200 -020002000500020002000200020002000500020002000200050002000500020002000200 -020002000200020005000200020002000500020005000200020002000500020005000200 -050002000200020005000200050002000200020005000200020002000500020002000200 -020002000500020002000500020002000200050002000500020005000200020002000500 -020002000200020005000200020002000500020005000200050002000200020005000200 -050002000200020005000200020002000500020002000200020002000500020002000500 -020002000200050002000500020002000500020002000200050002000200020002000200 -02000300010010001200130010000d000b001100120012000d000d0012000d000d001200 -0d001300100012000d00040010000d00120000001200120012000d001200120000000d00 -0d00130010000d000d00130010000d000b000d000d000000000000000d000d0012001200 -0d00130010000d0004000000000010000d000d0011001000100010001000100010001000 -10001000100010001000110012000e000700060002000200020003000300100002000200 -030003001000030003001000100002000300030010000100010010000300020002000500 -020003000300100002001000020003000200030010000300030003000100100003000200 -100003000200030003001000020002000300020010000200030002000200020002000200 -020002000200020005000200050002000200020002000200050002000500020002000200 -050002000200020002000200050002000500020002000200020002000500020005000200 -020005000200020002000500020005000500020005000200020002000200020005000200 -050002000200020002000200050002000500020002000200050002000200020002000200 -050002000500020002000200050002000200020002000200050002000500020002000200 -050002000500020005000200020002000200020005000200050002000200020002000200 -050002000500020002000200050002000200020002000200050002000500020002000200 -020002000500020005000200020005000200020002000500020005000500020005000200 -020002000200020005000200050002000200020002000200050002000500020002000200 -050002000200020002000200050002000500020002000200050002000200020002000200 -050002000500020002000200050002000500020005000200020002000200020005000200 -050002000200020002000200050002000500020002000200050002000200020002000200 -050002000500020002000200020002000500020005000200020005000200020002000500 -020005000500020005000200020002000200020005000200050002000200020002000200 -050002000500020002000200050002000200020002000200050002000500020002000200 -020002000200050002000500020002000200020002000200050002000200020002000200 -0300010010000d00040011000d001100120012000d000d000d000d001200120011000d00 -040010000d000d001300100012000d00000011000d000d0012000d000d0000000d001200 -130010000d000d0004001000110011001200000000000d00000000000d0011000d001200 -130010000d00130000000000100012000d00040000000000000000000000000000000000 -0000000000000000120012000d0007000500050002000200020003001000030003000200 -030010000300030010000300030003000300100003000300100003000300020002001000 -020003001000020003001000030003000300100001000300030001001000020002001000 -030003000300010010000200020003001000050010000300030002000200020002000200 -050002000500020002000200020002000500020005000200020002000200020005000200 -020002000500020005000200020002000200050002000500020002000200020002000200 -020005000200020002000200020002000200020002000200050002000500020002000200 -020002000500020005000200020002000200020005000200020002000500020005000200 -020002000200020005000200020002000500020005000200020002000200020005000200 -020002000200020002000200050002000500020002000200020002000500020005000200 -020002000200020005000200020002000500020005000200020002000200050002000500 -020002000200020002000200020005000200020002000200020002000200020002000200 -050002000500020002000200020002000500020005000200020002000200020005000200 -020002000500020005000200020002000200020005000200020002000500020005000200 -020002000200020005000200020002000200020002000200050002000500020002000200 -020002000500020005000200020002000200020005000200020002000500020005000200 -020002000200050002000500020002000200020002000200020005000200020002000200 -020002000200020002000200050002000500020002000200020002000500020005000200 -020002000200020005000200020002000500020005000200020002000200050002000500 -020002000200020002000200050002000500020005000200020003000200020002000300 -010010000d00130010000d000d00000000000000000000000000000000000d0012000400 -10000d001200040010000d00120000000b000d00120012000d0012000000120011000400 -10000d000d00130010000d001200000000000d0012000d00000000000b000d000d001300 -10000d0013000000000010000d0012001100100010001000100010001000100010001000 -10001000100010000e000e00070006000200020002000300030010001000030003001000 -100003000300100010000300010010001000020003001000100003000100100010000300 -010010000300020002001000020003001000100003000300100010000300020010001000 -030003001000100003000200100003000300030010000300020002000200020002000500 -020002000500020002000500020005000200020005000200050002000200020005000200 -050002000200020005000200050002000500020002000500020002000500020002000500 -020002000200050002000200050002000200050002000500020002000500020002000500 -020005000200020005000200050002000200020005000200050002000200020005000200 -050002000200020005000200050002000200020005000200050002000200020002000200 -050002000200050002000500020002000500020002000500020005000200020005000200 -050002000200020005000200050002000200020005000200050002000500020002000500 -020002000500020002000500020002000200050002000200050002000200050002000500 -020002000500020002000500020005000200020005000200050002000200020005000200 -050002000200020005000200050002000200020005000200050002000200020005000200 -050002000200020002000200050002000200050002000500020002000500020002000500 -020005000200020005000200050002000200020005000200050002000200020005000200 -050002000500020002000500020002000500020002000500020002000200050002000200 -050002000200050002000500020002000500020002000500020005000200020005000200 -050002000200020005000200050002000200020005000200050002000500020002000200 -020005000500020002000500020002000200020002000200020002000200020003000100 -10000d00130010000d001200000000000000000000000000000000001200120013001000 -0d000d00040010000d001200000000000000000000000000000000000b000d0013001000 -0d001200130010000a000900000011000b000d000d000d000000130012000d0004001000 -120004000000000010000d000d0004000000000000000000000000000000000000000000 -000001000b000e000e000700060005000200020003000300100003001000100010000300 -020003000300100010001000030010001000030003001000100010001000030002000300 -100002000300020003001000030010000300100010001000030002000300030010001000 -100010000100020010001000030003000300100010000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200030001001000 -0d00130010000d0012000d0012000d000d000d0012000d000d000d000d00130010000d00 -1200130010001100120012000d000d000d0012000d0012000d000d000d00130010000d00 -1200130010000d0012000d00120011000d00120012000d0012000d001200040010000d00 -040000000000100012000d000d0010001000100010001000100010001000100010001000 -100010000c000e0007000600050005000200020003001000020003000200030002000200 -020002000200030002000300020003000200020003000200030002000200020003000200 -020002000200020002000300020003000200020003000300020002000300020002000300 -030003000200020002000200020002000300020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020005000200020002000300010010000d00 -130010001200120012000d0012000d000d001200120011000d001200130010000d000d00 -130011000d00120012000d0012000d00120012000d0012000d0012000400100012000d00 -0400100012000d0012000d0012000d000d0012000d0012000d0012000900100012000400 -00000000100011000d000400000000000000000000000000000000000000000000000000 -0d000f000c00070006000500050005000200030010000300030002000500020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -020002000200020002000200020002000200020002000200020002000200020002000200 -02000200020002000200020002000200020005000200020002000300010010000d000400 -120013001300040004000400090004000400130004000400130013001100120012000400 -1200090013000400040004001300040013001300040013001300090011000d0012001300 -120013000400130004001300130004000400040004000400040004001000110004000000 -000010000d000d000d001100100010001000100010001000100010001000100010001000 -0e000e000700020005000600020002000200100005000600020002000200020005000200 -020002000200020002000200050002000200050005000500050005000200050002000200 -050005000200020005000500020002000500050002000200050002000200050002000500 -050005000200020002000200050005000200020005000500020002000200020002000500 -050002000200050005000500050005000200050002000200020005000200020005000200 -020005000200050002000500020005000200020002000500020002000500020002000500 -020005000200020005000500020002000200020002000500050002000200050005000500 -020002000500020002000200050005000200050002000500020002000200050002000200 -050002000200050002000500020002000200050002000200050005000200050005000200 -020005000200020002000200050005000200020002000200050005000200050002000200 -020005000200020005000200020005000200050002000500020005000200020002000500 -020002000500020002000500020005000200020005000500020002000200020002000500 -050002000200050005000500020002000500020002000200050005000200050002000500 -020002000200050002000200050002000200050002000500020002000200050002000200 -050005000200050005000200020005000200020002000200050005000200020002000200 -050005000200050002000200020005000200020005000200020005000200050002000500 -020005000200020002000500020002000500020002000500020005000200020005000500 -020002000200020002000500050002000200050005000500020002000500020002000200 -050005000200050002000500020002000200050002000200050002000200050002000500 -0200020002000500020002000500020002000300030003000100010010000d0012001000 -100010001000100010001000100010001000100010001000100010000d000d000d001000 -100010001000100010001000100010001000100010001000110010000d000d000d001000 -100010001000100010001000100010001000100010001000100010001200040000000000 -10000d0012000d000d0011000d000d000d000d000d000d000d000d000d0012000d000f00 -0e0007000200020002000200030003000300030003000300020002000300020003000300 -020002000200030002000300020003000200030002000200030002000300020003000200 -020002000300020003000200020003000200020003000200020002000300020003000200 -030002000300020003000200020003000200030002000300020002000200030002000300 -020003000200030002000200030002000300030002000300020002000300020002000300 -020002000300020003000200030003000200030002000200030002000200030002000200 -030003000200030002000300020002000200030002000300020003000200030002000300 -020003000200020003000200020003000200020003000300020003000200020003000200 -020003000200020003000300020003000200020003000200020003000200030002000300 -020002000200030002000300020003000200020002000200030002000300030002000300 -020002000300020002000300020002000300020003000200030003000200030002000200 -030002000200030002000200030003000200030002000300020002000200030002000300 -020003000200030002000300020003000200020003000200020003000200020003000300 -020003000200020003000200020003000200020003000300020003000200020003000200 -020003000200030002000300020002000200030002000300020003000200020002000200 -030002000300030002000300020002000300020002000300020002000300020003000200 -030003000200030002000200030002000200030002000200030003000200030002000300 -020002000200030002000300020003000200030002000300020003000200020003000200 -020003000200020003000300020003000200020003000200020003000200020003000300 -020003000200020003000200030003000300030001000100000010000d0012000d001200 -0d00120011000c000d000d0012000d0012000d000d000d0012000d0012000d000d000d00 -0d000d0012000d0012000d000d000d0012000d000d000d000d000d000d0011000d001200 -12000d000d0012000d0012000d000d000d000d00120012000d000d000900000000001000 -0d000d001100040004001300130013001300040004001300040004001300130004000400 -070003000100010000000100000000000100010001000100000000000100000000000000 -010000000000000001000100000000000100000000000000000000000100010000000000 -000000000100000000000000010000000000000001000000010000000000000000000000 -000000000100010000000000000000000100010000000000010000000000000001000100 -000000000100000000000000010000000100000001000000000000000100000001000000 -000000000000000001000000010000000100000000000000010000000100000000000000 -000001000000010000000000010000000000000001000100000000000100000001000000 -000000000100010000000000000000000100000001000000010000000000000001000000 -010000000000000001000000000000000100010000000000000000000100000000000000 -010000000000010000000100000000000100000000000000010000000100000001000000 -000000000100000001000000000000000000000001000000010000000100000000000000 -010000000100000000000000000001000000010000000000010000000000000001000100 -000000000100000001000000000000000100010000000000000000000100000001000000 -010000000000000001000000010000000000000001000000000000000100010000000000 -000000000100000000000000010000000000010000000100000000000100000000000000 -010000000100000001000000000000000100000001000000000000000000000001000000 -010000000100000000000000010000000100000000000000000001000000010000000000 -010000000000000001000100000000000100000001000000000000000100010000000000 -000000000100000001000000010000000000000001000000010000000000000001000000 -0000000001000100000001000100010001000000000000000b0009001300130013001300 -040004000800090004000400040004001300040009001300130004000900040004000400 -080008000400040004001300130013000400040004000400040004000400040008000800 -040013000400040013001300040004001300040011000d00120004000000000010000d00 -12000d000000000000000000000000000000000000000000000000000000000000000100 -000000000000000000000100000000000000010001000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000100000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000d000d000d0013000000000010000d001200 -0d0000000d000d000d000d000d000d000d000d000d000d00120012000d0011000d000d00 -10000d000d0012000d0011000b000d000e000e000e000e000e000d000e0011000e000d00 -0e000e000d000d000e0011000e0011000e000e000e000e000d000d000e000e000e000e00 -0e000e000e000e000e000d000e000e000e000e000e000e00110011000e000e000e000e00 -0d000d000e000e000e000e000d000d000e0011000e000d000e000e000d000d000e000e00 -11000d000e000e000e000e000e000e000e000d000e000e000e000e000e000d0011000e00 -0e000e000e000e000e000e000e000d000e000e000e000e000e000d0011000e000e000e00 -0d000d000e0011000e000d000e000e000d000d000e0011000e0011000e000e000e000e00 -0d000d000e000e000e000e000e000e000e000e000e000d000e000e000e000e000e000e00 -110011000e000e000e000e000d000d000e000e000e000e000e000e000d0011000e000e00 -0e000e000d000d0011000d000d0011000e000e000e000e000e000e000e000d000e000e00 -0e000e000e000d0011000e000e000e000e000e000e000e000e000d000e000e000e000e00 -0e000d0011000e000e000e000d000d000e0011000e000d000e000e000d000d000e001100 -0e0011000e000e000e000e000d000d000e000e000e000e000e000e000e000e000e000d00 -0e000e000e000e000e000e00110011000e000e000e000e000d000d000e000e000e000e00 -0e000e000d0011000e000e000e000e000d000d0011000d000e0011000e000e000e000e00 -0e000e000e000d000e000e000e000e000e000d0011000e000e000e000e000e000e000e00 -0e000d000e000e000e000e000e000d0011000e000e000e000d000d000e0011000e000d00 -0e000e000d000d000e0011000e0011000e000e000e000e000d000d000e000e000e000e00 -0e000e000e000e000e000d000e000e000e000e000e000e0011000d000e000e000e000e00 -0d000d000e000e000d000d000d000e0011000d000d000d000e000d000d000d000d000d00 -0d000d000f000d000d000d000e000d000d000d000d000d000e000d000e000d000f000e00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000e000e000d000d00 -0d000d000d000d000d000d000d00000012000d000d00130000000000100011000d000d00 -00000d000d000d000d000d000d000d000d000d000d000d0011000d000d000e000e000e00 -0d000d0011000d000d000e000d000e000f000d000d000d000d000d000d000e000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000e000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000e000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000e000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0e000d000d000d000d000d000d000d000d000d000d000d000d000d000d000e000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000e000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000e000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000e000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000e000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000e000d000d0011000d000f000d000e000d000e000e000d001100 -0d000d000d0011000d000d000d000d000e000e000d000d000e000e000d000e000c000e00 -0d000e000e000e000d000d000d000e000d000d000d000e000d000e000d000d000d000d00 -0d000d000d000d000d000d0000000d001200120013000000000010000d000d000d000000 -0d000d000d000d000d000d000d000d000d000e000d000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000d000d000e000d000e000e0011000d00 -0d000d000d0011000d000d000d000d000d000d000d000d000d000d000e000d000e000d00 -0d000d000e000d000e0011000d000d000d000d000d000d000e000d000d000e000d000d00 -11000d000d000d000e000d000e000d0011000d000d000e0011000d000e000d000d001100 -0e000d000d000d000d0011000d000d000d0011000d000d000d000d000e000d000e000d00 -0d000d000d0011000d000d000d0011000d000d000d000d000e000d000e000d000e000d00 -0e000d0011000d0011000d000d000d000d0011000d000d000d000d000d000d000d000d00 -0d000d000e000d000e000d000d000d000e000d000e0011000d000d000d000d000d000d00 -0d000d000d000d000e000d0011000d000e000e000d000d000e000d000d000d000d001100 -0d000d000d0011000d000d000e000d000d000d000d0011000d000d000d0011000d000d00 -0d000d000e000d000e000d000d000d000d0011000d000d000d0011000d000d000d000d00 -0e000d000e000d000e000d000e000d0011000d0011000d000d000d000d0011000d000d00 -0d000d000d000d000d000d000d000d000e000d000e000d000d000d000e000d000e001100 -0d000d000d000d000d000d000d000d000d000d000e000d0011000d000e000e000d000d00 -0e000d000d000d000d0011000d000d0011000d000d000d000e000d000d000d000d001100 -0d000d000d0011000d000d000d000d000e000d000e000d000d000d000d0011000d000d00 -0d0011000d000d000d000d000e000d000e000d000e000d000e000d0011000d0011000d00 -0d000d000d0011000d000d000d000d000d000d000d000d000d000d000e000d000e000d00 -0d000d000e000d0011000d000d000e000d000d0011000d000d000d000d000d000d000d00 -0d000d000d000d000e000e000e000e000e000e000e000e000e000e000d000d000d000d00 -0d000d000e000e000e000e000e000e000e000e000d000e000e000e000e000e000e000e00 -0e000e000e000d000e000d000e000d000e000e000e000e000d000d000d000d000d000d00 -0d0011000d000d000d0000000d000d00120013000000000010000d000d000d0000000d00 -0d000d000d000d000d000e000d000e000e000e000e000e000e000f000e000e000e000e00 -0e000e000e000e000e000e000e000e000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000e0011000d000d000d000d000d0011000d000d000d000d000d000d00 -0e0011000d000d000d000d000e000d000d000d000d000d000d000d000e000d000d000d00 -0d000e000e000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000e000d000d000d000d000d000d000d000d000d000d0011000e000d000d000d000e00 -0d000d000d000d000d000d000d000d000d000d0011000e000d000e000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000e0011000d000d000d000d000d001100 -0d000d000d000d000d000d000e0011000d000d000d000d000e000d000d000d000d000d00 -11000d000d000d000d000d000d000d000d000d000e000e000d000d0011000d000d000d00 -0d000d000d000d000d000d000d000e000d000d000d000d000d000d000d000d000d000d00 -11000e000d000d000d000e000d000d000d000d000d000d000d000d000d000d0011000e00 -0d000e000d000d000d000d000d000d000d000d000d000d000d000d000d000d000e001100 -0d000d000d000d000d0011000d000d000d000d000d000d000e0011000d000d000d000d00 -0e000d000d000d000d000d0011000d000d000d000d000d000d000d000d000d000e000e00 -0d000d0011000d000d000d000d000d000d000d000d000d000d000e000d000d000d000d00 -0d000d000d000d000d000d0011000e000d000d000d000e000d000d000d000d000d000d00 -0d000d000d000d0011000e000d000e000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000e0011000d000d000d000d000d0011000d000d000d000d000d000d00 -0e0011000d000e000d000d000e000d000d000d000d000d000e000e000d000d000d000d00 -0d000d000d000e000e000e000e000e000e000e000e000e000d000d000d000d000d000d00 -0d000e000e000d000e000d000e000d000e000d000d000d000d000d000e000e000e000d00 -0e000e000e000e000e000e000e000e000d000d000e000e000e000d000d000d000d000d00 -0d000d000d000d00000012000d000d0004000000000010000d0012000d0000000d000d00 -0d000d000d000d000d000e000e000d000e000e000e000e000d000e000d000d000d000d00 -0d000d000d000d000e000e000e000e000e000e000e000e000e000e000e000d000d000d00 -0d000d000e000e000d000d000e000e000e000e000d000e000e000e000e000e000e000d00 -0d000d000e000d000d000d000d000e000d000e000e000e000d000d0011000d000e000d00 -0d000d000d000e000e000e000e000e000e000d000d000d000e000e000d000d000e000e00 -0e000d000d000e000e000e000e000e000e000e000d000e000d000e000e000e000e000d00 -0d000e000e000e000e000e000e000e000d000e000d000e000d000d000d000e000e000e00 -0e000e000e000d000d000d000d000d000e000e000d000d000e000e000e000e000d000e00 -0e000e000e000e000e000d000d000d000e000d000d000d000d000e000d000e000d000e00 -0e000d000e000e000d000d000d000d000e000e000e000d000d000d000e000d000e000d00 -0e000e000e000e000e000e000e000d000d000e000e000e000e000e000e000e000d000e00 -0d000e000e000e000e000d000d000e000e000e000e000e000e000e000d000e000d000e00 -0d000d000d000e000e000e000e000e000e000d000d000d000d000d000e000e000d000d00 -0e000e000e000e000d000e000e000e000e000e000e000d000d000d000e000d000d000d00 -0d000e000d000e000d000e000e000d000e000e000d000d000d000d000e000e000e000d00 -0d000d000d000d000d000d000e000e000d000d000e000e000e000d000d000e000e000e00 -0e000e000e000e000d000e000d000e000e000e000e000d000d000e000e000e000e000e00 -0e000e000d000e000d000e000d000d000d000e000e000e000e000e000e000d000d000d00 -0d000d000e000e000d000d000e000e000e000e000d000e000e000e000e000e000e000d00 -0d000d000e000d000d000d000d000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000d000d000e000d000d000e00 -0d000d000e000e000d000d000e000d000e000d000d000e000e000e000d000e000e000d00 -0e000d000d000d000e000e000d000d000e000d000e000e000d000d000d000d000d000d00 -11000d000d00000012000d00120004000000000010000d000d000d00000011000d000d00 -11000d000d000d000e000d000e000e000e000e000e000d000d000d000d000d000d000d00 -0e000d000d000d000d000d000d000d000d000d000d000e000d000e000d000e000d000d00 -0e000d000d000e000d000e000d000e000d000d000d000e000d000d000d000d000d000e00 -0d000e000d000d000d000e000d000e000d000e000d000d000e000d000d000d000d000d00 -0d000e000d000d000d000e000d000e000d000d000d000e000d000d000e000e000d000e00 -0d000e000d000e000d000d000d000e000d000d000e000d000d000e000d000e000d000e00 -0d000e000d000d000d000e000d000d000e000d000d000d000d000e000d000d000d000e00 -0d000e000d000e000d000d000e000d000d000e000d000e000d000e000d000d000d000e00 -0d000d000d000d000d000e000d000e000d000d000d000e000d000e000d000e000d000e00 -0d000e000d000d000d000d000e000d000d000e000e000d000e000e000d000d000d000e00 -0d000d000d000e000d000e000d000e000d000e000d000d000d000e000d000d000e000d00 -0d000e000d000e000d000e000d000e000d000d000d000e000d000d000e000d000d000d00 -0d000e000d000d000d000e000d000e000d000e000d000d000e000d000d000e000d000e00 -0d000e000d000d000d000e000d000d000d000d000d000e000d000e000d000d000d000e00 -0d000e000d000e000d000e000d000e000d000d000d000d000e000d000d000e000e000d00 -0e000e000d000e000d000e000d000d000e000e000d000e000d000e000d000e000d000d00 -0d000e000d000d000e000d000d000e000d000e000d000e000d000e000d000d000d000e00 -0d000d000e000d000d000d000d000e000d000d000d000e000d000e000d000e000d000d00 -0e000d000d000e000d000e000d000e000d000d000d000e000d000d000d000d000d000e00 -0d000e000d000d000d000d000d000e000d000e000d000e000d000e000d000e000d000e00 -0e000e000e000e000e000e000e000e000e000e000d000d000d000d000d000e000d000d00 -0e000d000e000e000e000e000e000e000e000e000d000e000e000e000d000d000e000e00 -0d000e000e000d000e000d000e000d000e000d000e0011000d000d000d000d000d000d00 -0d000d00000012000d000d0004000000000010000d0012000d0000000d000d000d000d00 -0d000e000e000e000e000e000e000e000e000e000d000d000d000d000d000d000d000d00 -0e000e000d000d000d000d000d000d000d000d000d0011000d000d000d000d000d000d00 -11000d000d000d000d0011000d000d000d0011000d000d000d000d000d000d000d000d00 -0d000d000e0011000d0011000d000d000d000d000d0011000d000d000d000d000d000d00 -0e000d000d0011000d000d000d000d000d0011000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000e000d000d0011000d000d00 -0d000d000d000d000d000d0011000d000d000d000d0011000d000d000d0011000d000d00 -0d000d000d000d000d000d000d000d000e0011000d000d000d000d000d000d0011000d00 -0d000d000d000d0011000d000d000d000d000d000d0011000d000d000d0011000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0e000d000d0011000d000d000d000d000d000d000d000d0011000d000d000d000d001100 -0d000d000d0011000d000d000d000d000d000d000d000d000d000d000e0011000d000d00 -0d000d000d000d0011000d000d000d000d000d0011000d000d000d000d000d000d001100 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000e000d000d0011000d000d000d000d000d000d000d000d00 -11000d000d000d000d0011000d000d000d0011000d000d000d000d000d000d000d000d00 -0d000d000d0011000d000d000d000d000d0011000d000d000d000d000d000e000e000e00 -0e000e000e000e000e000e000d000e000d000e000e000d000e000e000d000d000e000d00 -0e000d000e000d000d000d000e000d000e000d000e000d000d000d000d000e000d000d00 -0d000e000d000e000d000e000d000e000d000e000e000e000e000d000d000d000d001100 -0d0000000d0012000d0013000000000010000d0012000d00000011000d000d000d000e00 -0e000e000e000e000e000e000e000e000d000d000d000d000d000e000e000e000e000e00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d0011000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d0011000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d0011000d000d000d00 -0e000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -11000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d0011000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000e000d000d000d000d000d00 -0d000d0011000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d0011000d000d000d000d000d000d0011000d000d000d000d000d000d000d000d00 -0d0011000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d0011000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d0011000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0e000d000d000d000d000d000d000d0011000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d0011000d000d000d000d000d000d0011000d000d00 -0d000d000d000d000d000d000d0011000d000d000d000d000d000d000d000d000d000d00 -0d0011000d000d000d000d000d000d000d000d000d000d0011000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d0011000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000e000d000d000d000d000d000d000d0011000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d0011000d000d000d00 -0d000d000d0011000d000d000d000d000d000d000d000d000d000d000d000d000e000d00 -0e000e000e000d000d000d000d000d000d000e000e000e000e000e000e000d000e000e00 -0d000d000e000e000d000d000e000d000e000d000d000d000e000e000d000d000e000e00 -0d000d000d000e000d000e000d000d000e000e000e000d000e000e000d000d000d000d00 -00000d000d00120013000000000010000d000d000d0000000d000d000d000e000d000e00 -0d000e000d000e000e000d000d000d000d000d000d000d000e000e000e000e000e000e00 -0d000d0011000d000e000d000d000e000d000d000e000d000d000d000d000d000d000d00 -0d000d000d000d000e000d000d000d0011000d000e000e000e000e000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000e000d000d000d000d00 -0d000d000d000d000e000e000e000e000d000d000d000d000e000d000e000e000d000d00 -0d000d000d000e000e000d0011000d000d000d000e000d000e000e000d000d000d000d00 -0d000e000e000d0011000d000d000d000d000d000d000d000d000d000d000d000e000d00 -0d000d000d000d000d000d000d000d000d000d000e000d000d000d0011000d000e000e00 -0e000e000d000d000d000d000d000d000d000d000d000d0011000d000d000d000d000e00 -0e000d000d000d000e000d000e000e000d000d000d000d000e000e000e000e000d000e00 -0e000d000e000e000d000d000d000d000d000e000e000d0011000d000d000d000e000d00 -0e000e000d000d000d000d000d000e000e000d0011000d000d000d000d000d000d000d00 -0d000d000d000d000e000d000d000d000d000d000d000d000d000d000d000d000e000d00 -0d000d0011000d000e000e000e000e000d000d000d000d000d000d000d000d000d000d00 -11000d000d000d000d000e000e000d000d000d000e000d000e000e000d000d000d000e00 -0e000e000e000e000d000d000e000d000e000e000d000d000d000d000d000e000e000d00 -11000d000d000d000e000d000e000e000d000d000d000d000d000e000e000d0011000d00 -0d000d000d000d000d000d000d000d000d000d000e000d000d000d000d000d000d000d00 -0d000d000d000d000e000d000d000d0011000d000e000e000e000e000d000d000d000e00 -0d000d000d000d000e000d000d000d000d000d000e000e000e000e000d000d000d000d00 -0d000d000d000d000d000d000d000e000e000e000e000e000e000e000d000d000d000e00 -0d000d000d000e000d000d000d000e000d000e000e000d000d000e000e000d000e000e00 -0e000d000e000d000d000d000e000d000d000e000e000e000d0011000d000d000d000000 -12000d000d0004000000000010000d000d00120000000d000d000e000d000e000e000e00 -0d000d000e000e000d000d000d000d000d000d000d000e000e000e000e000e000d000d00 -0d000d000d000e000e000d0011000d000d000e000e000e000e000e000d000e000d000d00 -0e000e000d000e000e000e000d000d000d000e000d000d000e000e000d000e000d000e00 -0e000e000d000d000d0011000e000e000d000e000d000e000e000d000e000e000e000d00 -0d0011000d000d000e000d000e000d000e000e000e000d000d000e000e000d000d000e00 -0e000d0011000d000e000d000d000e000e000d000d000e000e000d000d000e000e000d00 -11000d000e000d000d000e000e000d000e000e000e000d000d0011000d000e000e000e00 -0e000e000d000e000d000d000e000e000d000e000e000e000d000d000d000e000d000d00 -0e000e000d000e000d000e000e000e000d000d000e000d000d000e000d000e000e000e00 -0d000d000d000d000d000e000e000d000d000e000e000d000e000d000e000e000e000d00 -0d000e000e000d000d000e000e000d0011000d000e000d000d000e000e000d000d000e00 -0e000d000d000e000e000d0011000d000e000d000d000e000e000d000e000e000e000d00 -0d0011000d000e000e000e000e000e000d000e000d000d000e000e000d000e000e000e00 -0d000d000d000e000d000d000e000e000d000e000d000e000e000e000d000d000e000d00 -0d000e000d000e000e000e000d000d000d000d000d000e000e000d000d000e000d000e00 -0d000e000e000e000e000d000d000e000e000d000d000e000e000d0011000d000e000d00 -0d000e000e000d000d000e000e000d000d000e000e000d0011000d000e000d000d000e00 -0e000d000e000e000e000d000d0011000d000e000e000e000e000e000d000e000d000d00 -0e000e000d000e000e000e000d000d000d000e000d000d000e000e000d000e000d000e00 -0e000d000d000e000e000d0011000d000d000d000e000e000e000d000d000d000d000d00 -0d000d000d000d000d000d000e000d000e000e000e000d000d000d000e000e000d000e00 -0d000e000d000e000d000e000d000e000d000d000e000e000d000d000e000d000d000d00 -0e000d000e000d000e000d000e000e000d000e000d000e000d000d000d000d0000000d00 -0d00120004000000000010000d000d000d0000000e000e000d000e000e000e000e000e00 -0e000e000e000d000d000d000d000d000d000d000d000d000e000d000d000e000d000d00 -0d000d000e000e000e000d000e000e000e000d000d000e000e000e000d000d000d000d00 -0e000d000d000e000d000e000d000e000d000d000d000d000f000d000d000d000e000d00 -0e000d000e000d000e000d000d000d000e000d000e000d000d000d000d000e000d000f00 -0d000e000e000d000d000e000d000e000e000d000e000d000d000e000d000e000d000d00 -0d000d000d000d000e000d000d000e000e000d000f000d000d000f000d000d000e000d00 -0d000d000d000d000e000d0011000e000d000f000d000e000d000d000d000f000d000d00 -0d000e000e000d000e000d000e000e000e000d000e000d000e000e000e000d000f000d00 -0f000d000e000d000d000d000f000d000d000e000d000d000d000d000e000d000e000e00 -0e000d000e000d000e000d000e000d000e000e000e000d000e000d000e000d000e000e00 -0e000e000e000d000e000e000e000e000e000e000e000d000e000e000e000e000e000e00 -0e000d000e000e000e000e000e000e000e000d000e000e000d000d000e000d000e000e00 -0e000d000e000d000e000e000e000d000e000d000e000d000e000e000e000d000e000e00 -0e000d000e000d000e000d000e000e000e000d000e000d000e000d000e000d000e000e00 -0e000d000e000d000e000d000e000d000e000d000e000e000e000d000e000d000e000d00 -0e000d000e000d000e000e000e000e000e000d000e000e000e000e000e000e000e000d00 -0e000e000e000e000e000e000e000d000e000e000e000e000e000e000e000d000e000e00 -0d000d000e000d000d000e000d000d000d000e000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000e000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000e000e000d000e000d000e000d000e000e000d000e000e000d000e000d00 -0d000d000d000d000e000e000e000e000e000e000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000d000e00 -0d000d000d000e000d000e000d000e000d000e000e000d000e000d000d0000000d001200 -0d000400000000001000120012000d0000000d000d000e000e000d000e000d000d000d00 -0d000d000f000e000d000f000d000e000d000d000e000f000d000e000d000e000d000d00 -0d000d000e000d000e000e000d000d000e000e000d000e000d000d000e000f000b000f00 -0f000d000d000e000d000e000d000e000d000e000e000b000e000d000d000d000f000d00 -0f000d000d000d000e000e000d000c000f000f000d000e000d000f000e000f000b000f00 -0d000d000f000d000f000d000d000f000d000e000c000f000d000e000d000e000e000d00 -0e000d000f000e000d000d000e000d000d000d000d000f000c000d000f000e000d000f00 -0d000e000e000d000d000e000d000f000e000d000d000d000d000d000e000d000d000d00 -0d000d000e000e000d000d000d000e000d000d000e000d000d000d000e000d000f000e00 -0d000d000d000f000d000d000e000d000d000e000f000d000d000f000e000d000d000e00 -0d000d000d000d000e000e000d000d000d000e000d000e000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d0011000d000e000d000d000e00 -0d000d000e000d000d000e000d000d000e000e000d000e000d000d000e000d000d000e00 -0d000d000e000e000d000e000d000e000d000d000d000d000e000e000d000d000d000e00 -0d000e000d000d000d000d000e000e000d000d000d000e000d000e000d000d000d000d00 -0e000e000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000e00 -0d000d000e000e000d000e000e000e000d000e000d000d000d000d000e000e000d000d00 -0d000d000e000e000d000d000d000e000d000e000d000d000d000d000e000d000e000d00 -0e000d000d000e000d000d000e000e000d000e000d000e000d000d000e000e000e000d00 -0e000e000e000e000d000d000e000d000d000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000e000d000e00 -0e000e000d000e000d000d000d000e000e000d000d000d000d000d0000000d000d001200 -040000000000100012000d000d0000000d000e000d000e000e000e000e000d000d000e00 -0d000d000d000d000e000e000d000d000e000d000c000f000d000d000e000d000d000e00 -0d000d000e000d000d000e000d000d000d0010000d000e000f000d000e000d000d000d00 -0d000d000f000d000d000d000e000d000d000d000f000d000d000d000d000d000d000d00 -0d000e000d000d000d000e0010000b000d000f000d000d000c000c000f000e000d000e00 -0e000d000d000e000e000d000d000d000d000f000d000d000e000d000e000d000d000e00 -0e000e000d000d000e000c000d000d000f000e000d000f000e000d000d000f000c000f00 -0d000d000e000e000d000d000d000d000e000e000e000f000f000d000d0010000d000e00 -0e000e000d000e000d000d000d000e000d000d000f000d000e000d000e000d000d000f00 -0e000d000d000e000d000e000e000d000d000d000d000d000d000f000e000e000d000e00 -0d000e000e000d000e000e000d000e000d000e000d000e000d000e000d000e000e000d00 -0e000d000d000e000d000e000e000d000e000d000d000e000d000e000e000d000e000d00 -0d000e000d000e000e000d000e000d000d000e000e000d000d000d000e000d000d000e00 -0e000d000e000d000d000e000d000d000e000d000d000d000e000d000e000d000d000e00 -0d000d000e000d000d000d000d000e000d000e000e000d000e000e000d000e000d000e00 -0d000e000d000e000e000d000e000e000d000e000d000e000d000e000d000e000e000d00 -0e000e000d000e000e000d000e000d000d000e000d000e000e000d000e000d000d000e00 -0d000e000e000d000e000d000d000e000d000e000e000d000e000d000d000e000d000e00 -0e000d000d000e000d000e000d000e000d000e000d000d000e000d000d000e000d000e00 -0e000d000e000e000d000e000d000e000d000e000d000e000d000d000e000d000e000d00 -0e000d000d000e000d000d000e000d000d000d000d000e000d000e000d000e000d000d00 -0e000d000d000e000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000d000d000d000e000e000d00 -0d000d000e000d000d000e000d000d000e000d000d000d000d0000000d000d000d001300 -0000000010000d000d000d0000000d000d000d000e000e000e000d000e000d000e000e00 -0d000e000e000f000e000d000d0000000e000f00000010000d000b0011000e000d000e00 -0e000d000e000e000d0000000d000d000f000b000d000d0000000d000e000e000e000f00 -0d000d000e000e000f000d000e000d000d000e000d000f000d000e000d000f000e000e00 -0d000e000d000f000d000e000f000d000e000d000d0010000d000d000d000d000f000d00 -0d000f000d000d000f000d000e000f000e000d000e000d000d000e0000000d0000000000 -00000100000000000f000e000e000b000e0000000d000f000d000e000d0001000d000e00 -0e000e000d000e000d0000000000000000000f000d000d00010000000000000000000000 -0d000e000d000e000e000e000d000e000d000d000d000f0000000f000e000f000d000d00 -0000000000000e000d0000000f000f000d000e000f000d000d000d000d000e000d000e00 -0d000d000e000d000d000d000d000e000d000e000d000e000d000e000d000d000e000d00 -0e000e000d000e000d000d000e000d000e000e000d000e000d000d000e000d000e000e00 -0d000e000d000d000e000d000e000e000d000d000e000e000d000d000d000e000d000d00 -0e000d000e000e000d000d000e000d000e000d000e000d000e000d000e000e000d000d00 -0e000d000e000d000e000e000d000e000d000d000e000d000d000d000d000e000d000e00 -0d000e000d000d000e000d000d000d000d000e000d000e000d000e000d000d000e000d00 -0d000e000d000d000e000d000e000e000d000e000d000d000e000d000e000e000d000e00 -0d000d000e000d000e000e000d000e000d000d000e000d000e000e000d000e000e000d00 -0e000e000d000e000e000e000d000e000d000e000e000d000e000e000d000e000d000d00 -0e000d000d000d000d000e000d000e000d000e000d000e000e000d000e000d000e000d00 -0e000e000d000d000e000d000e000d000e000e000d000e000d000e000d000e000e000d00 -0e000e000d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000e000d000d000d000d000e000d00 -0e000d000e000d000e000d000e000d000d000e000e000d0000000d001200120013000000 -000010000d000d000d0000000d000d000e000e000d000e000e000d000e000d000e000d00 -0e000d000d000d000e000f0000000d000f0000000d000d000e000d000e000d000e000d00 -0e000d000e000d0000000f000b000d000f000d000f0000000e000d000e000d000c000f00 -0d000d000d000d000d000d000e000d000e000d000d000d000e000d000b000f000d000e00 -0d000d000d000f000d000d000e000d000d000f000d000e000e000f000d000d000f000c00 -0e000e000e000d000f000d000d000d000d000d000e000f0000000d000e0000000e000f00 -0d000d000d000d000e000d000e0000000d0000000f000d000d000d0000000e000d000b00 -0d000f000d0000000f000d000f000d0000000d000d0000000d000f000d000e000e000e00 -0e000d000e000d000e000d000d000e000f000000000000000c000d000c000e0000000d00 -0e000d0000000f000c0000000d000d000f000c000f000d000e000d000d000e000d000e00 -0d000e000d000e000e000d000d000e000d000e000d000e000d000e000d000d000d000e00 -0d000e000d000e000d000d000d000e000d000e000d000e000d000d000d000e000d000e00 -0d000e000d000d000d000e000d000e000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000e000d000e000d000e000d000e000d000e000d000e000e000d000d000e000d000e00 -0d000e000d000e000d000e000e000d000e000d000d000e000d000e000d000e000d000e00 -0d000e000d000d000d000e000d000e000d000e000d000d000d000e000d000e000d000e00 -0d000d000d000e000d000e000d000e000d000d000d000e000d000e000d000e000e000e00 -0d000e000e000d000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000e000d000d000e000d000e000d000e000d000e000e000d000e000d000e000d00 -0e000d000e000d000e000e000d000e000d000e000d000e000d000e000d000e000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000d000e000d000e000e000d000e000d000d000d00 -0e000d000d000d000d000e000e000d000d000d000d0000000d0012000d00040000000000 -100012000d000d0000000d000d000e000d000d000e000d000d000d000e000f000d000000 -00000d0000000d000000000000000d0001000d000d0001000d000d000e000d000e000d00 -0e000d000e0000000e00010000000d000e000d0000000d00000000000e000f000d001000 -0000000000000f000d0000000d000d000f000d0001000d000d000e000d000d000d000d00 -0d0000000f000000000010000d000f000d000000000000000d000d0000000d000f000d00 -00000e000d000d0000000e000f000e000e000d000d0000000d000d0000000e000d000f00 -0e000f000d000d000e000e0000000d0000000d000e000f000d0000000d000f000f000d00 -0d000f0000000e000d000d000f000e000e000f0000000f000d000e000d000d000d000d00 -0d000d000e000d000e000d000d000d000d000f0000000d000f000e000e0000000d000d00 -0d0000000d00100000000e000e000d000d000d000d000d000e000e000d000e000d000e00 -0d000e000d000d000e000e000d000e000d000e000d000e000d000d000e000e000d000e00 -0d000e000d000d000e000e000d000e000d000e000d000d000e000e000d000e000d000e00 -0d000d000e000e000d000e000d000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000e000d000d000e000d000e000d000e000d000e000d000e000d00 -0d000e000d000e000d000e000d000e000d000e000d000d000e000e000d000e000d000e00 -0d000e000d000e000d000d000e000d000e000e000d000e000d000e000d000e000d000e00 -0d000d000e000e000d000e000d000e000d000d000e000e000d000e000d000e000d000d00 -0e000e000d000e000d000e000d000d000e000e000d000e000d000e000d000d000e000e00 -0d000d000e000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000d000e000e000d000e000d000e000d000e000d000d000e000d000e000d000e000d00 -0e000d000e000d000d000e000d000e000d000e000d000e000d000e000d000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000e000d000d000e000d000e000e000d000d00 -0e000d0011000e000d000d000d0011000d000d0000000d000d000d001300000000001000 -0d0012000d0000000e000e000d000e000e000e000d000e000d000e000d0000000f000d00 -000001000b000e0000000d000e0000000e0000000d000e000e000d000e000d000e000d00 -0e000d00000000000d000d0000000d000e00000000000d000d0000000d000d0000000d00 -0e000e0000000b000e0000000d000d0000000f000c000f000e000d000d000d000e000d00 -000000000e000d0000000d000d0000000f000d000d0000000f0000000e000d000f000000 -0e000d000d0000000e000d000b000f000d0000000f000d000f0000000e000d000d000d00 -0d000e000f000d0000000d000e000d0000000d000d000d0001000d000d000d000d000d00 -0d000f00000000000f000c000d000d000d0000000e000d000d000e000f000e000d000e00 -0d000e000e000d000d000e000d000d000d0000000d000f000d000d0000000f000e000d00 -00000e000c000e0000000f000d0000000f000d000f000d000d000e000d000e000d000e00 -0d000e000e000d000d000e000d000e000d000e000d000d000e000d000d000e000d000e00 -0d000d000e000d000d000e000d000e000d000d000e000d000d000e000d000e000d000d00 -0e000d000d000e000d000e000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000d000e000d000d000e000d000e000d000e000d000e000d000e000d00 -0d000e000d000e000d000e000d000e000d000e000e000d000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000d00 -0e000d000d000e000d000e000d000d000e000d000d000e000d000e000d000d000e000d00 -0d000e000d000e000d000d000e000d000d000e000d000e000d000d000e000d000d000e00 -0e000d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0e000d000d000e000d000e000d000e000d000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000d000e000d000e000d000e000d000e000d000e000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000d000e000d000e000d000e000d000d00 -0d000e000d000e000e000d000d000d000d00000012000d00120004000000000010000d00 -0d000d0000000d000e000e000e000e000d000e000d000e000d000e0000000d000e000d00 -00000f000d0000000f000d00000000000d000d000d000d000e000d000e000d000e000d00 -0e0000000e000d000e0000000e000d0000000d000e000e0000000e000e0000000f000d00 -0d0000000f000d000f00000000000e000d000d000d000d000e000d000e000d000d000000 -0e000d000d0000000e000d0000000d000d000e0000000c000f0000000e000d0000000d00 -0e0000000d000d000f000e000d000e0000000d000e000d00000000000000000000000f00 -0d000d000e0000000e000d000d0000000d000d000f0000000f000d000d000e000d000d00 -0d000d000d00000000000d000d000e000000000000000000000000000d000e000d000e00 -0d000d000e000d000d000e000d000e0000000d000d000f000e0000000e000d000e000000 -0f000d000e0000000d000d000e000d000e000e000d000e000d000e000d000e000d000e00 -0d000d000e000e000d000e000d000e000d000e000e000d000e000e000d000e000d000e00 -0e000d000e000e000d000e000d000e000e000d000e000e000d000e000d000e000e000d00 -0e000e000d000e000d000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000e000d000e000d000d000e000d000e000d000e000d000e000d000e000d00 -0d000e000d000e000d000e000d000e000d000d000e000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000e000d00 -0e000e000d000e000d000e000e000d000e000e000d000e000d000e000e000d000e000e00 -0d000e000d000e000e000d000e000e000d000e000d000e000e000d000e000e000d000d00 -0e000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000d00 -0e000e000d000e000d000e000d000e000d000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000d000e000d000e000d000e000d000e000d000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000d000e000d000e000d000e000d000e000e000e00 -0d000e000e000d000d000d000d000d0000000d000d000d00040000000000100012000d00 -0d00000011000e000e000d000e000d000d000e000e000d000e0000000e000f000d000000 -0f000d0000000d000e00000000000d000e0011000d000d000f000d000d000e000d000d00 -00000d000d000e0000000d000f0000000d000d000e0000000e000d0000000e000d000e00 -00000d000e000e00000000000e000d000e000f000d000d000f000d000d000f0000000e00 -0e000d0000000d000e00000000000000000000000d000e0000000d000d0000000d000d00 -00000d000f000d000d000e000f0000000e000d000e0000000d000d000d000d000d000e00 -0d000d00000000000000000000000e000e000d0000000d000e000e000d000e000e000e00 -0d000e000f000e0000000e000e0000000d000e000e000d000e000d000d000d000e000d00 -0e000d000e000d000d000e000e0000000d000e000d000d0000000d000e000e0000000d00 -0d000f0000000e000d000d000e000d000e000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0d000e000d000e000d000e000d000e000d000e000d000e000e000d000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000d00 -0e000d000d000d000d000e000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000d000e000d000e000e000e000e000d000d000e00 -0d000d000e000d000e000d00110000000d000d000d0004000000000010000d000d001200 -00000d000e000e000e000e000e000e000d000d000e000e0000000d000e000e0000000e00 -0d00000010000d0000000c0000000d000d000f000d000e000d000d000d000d000d000000 -0e000d000d0001000e000d0000000f000d000e0000000d00100000000d000d000f000000 -0d000e0000000f000f0000000f000d000c000f000d000d000e000e000d0000000f000d00 -0d0000000d000d0000000d000d000f000e000d000f0000000d0000000d0000000f000000 -0d000e000d000f000b000f0000000d000d000d0001000d000d000e000d000f000d000f00 -00000d000d000f000e000e0000000d000e0000000e000d000d000f000d000d0000000d00 -0e000d000e0000000e000d0000000e000d000d000d000f000d000f000d000d000d000d00 -0d000d000d000f000d000e0000000d000d000e000e0000000d000d000f0000000d001000 -0b0000000d000e000f000d000d000d000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000e00 -0d000e000d000e000d000e000d000e000d000e000d000d000e000d000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000e000d00 -0e000e000e000d000d000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000e000d000e000d000e000e000d000e000e000e000d00 -0e000d000d000d000d000d00000012000d00120004000000000010000d0012000d000000 -0d0011000e000d000e000d000d000d000e000d000d0000000d000d00000000000d000e00 -00000d000e0001000e000d0001000e000e000d000d000f000d000d000f000d0000000d00 -0e000e0000000d000e00000000000f000d0000000e000e0000000f000e000d0000000d00 -00000e000d000e000d0000000d000f000d000d000f000d000d000d0001000d000d000e00 -00000e000f0000000d000f000d0000000e000b000d0000000b000f000e0000000d000f00 -0d000e000e000d000e0000000e000e000d0000000e000d000f000e000d000e000d000000 -0d000e000b000f000d0000000f000e0000000d000e000e000d000d000f0000000f000d00 -0d000d0000000d000d0001000d000d000e000d000d000f000d000e000e000e000d000d00 -0f000d000d000e000d0000000f000e000d000d0000000d000e000e0000000d000e000e00 -00000d000d000d000d0010000d000d000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000e000d000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000e000d00 -0d000e000d000e000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000d000e000d000d000e000e000e000d00 -0d000d000d000d000d0000000d000d000d0004000000000010000d000d000d0000000d00 -0d000e000d000e000e000e000e000e000e000d000d00000000000d0000000f000d000000 -00000e0000000d000d000e0000000f000d000d000f000d000d000d000e0000000d000d00 -0f0000000f000d0000000e00000000000d000e000d000f000000000000000d000e000000 -0d000f000d000d0000000d000d000f000b000e000f000d000f0000000d000e000f000000 -0d000d000f000000000000000d000f000d000e0000000f000c000e0000000d000d000e00 -0d000d000f000d0000000d000d000f0000000d000e000c000d000e000d000d0000000d00 -0e0010000d000f0000000c000e00000000000000000000000e000d001000000000000000 -00000d000d000d000000000000000000000000000d000e000d0000000e000d000d000d00 -0f000e000d000d0000000f000b000f000d000e000000000000000f000f000c000f000000 -0d00100000000c000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000d000e000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000d00 -0e000d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000d000d000e00 -0d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000e000d000d000e000e000e000e000e000d00 -11000d000d000d00000012000d000d0013000000000010000d000d000d0000000d000d00 -0e000e000d000e000e000d000e000d000f000d000d000d000f0000000d000d000d000f00 -0d000d000f000d000d000f000d000e000f000c000e0010000d000d000f000e000e000d00 -0f000d000e000d000e000d000e0010000d000d000d000d000e000d000f000d000e000d00 -0e000d000e000d000f000d000d0010000d000d000e000e000d000e000d000b000d000d00 -0e000d000e000e000f000d000d000f000d000d000e000e000d000d000d000e000d000e00 -0e000d000e000d0001000d000d000d000d000d0010000e000d000e000d000f000d000d00 -0c000e000d000e000f000d000d000f000d000f000d000e000d000d000b000f000d000d00 -0d000d000f000e000e000d000d000f000b000f000d000e0000000d000f000d000d000d00 -0d000d000e000f000d000f000d000d000d000e000d000f000d000d000d0000000d000d00 -0d00000010000d000b000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000d000e000d000e00 -0d000e000d000e000d000e000d000e000e000e000d000d000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000d00 -0e000e000e000d000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000e000d000d000e000d000e000e000d000d000d000e000d000d00 -0d000d000d0000000d000d00120013000000000010000d0012000d0000000d000d000d00 -0e000e000d000d000e000d000d000b0000000f000d000f0000000e000d000d000f000b00 -0f000d000d000f000d0000000000000000000000000001000d000d000e000d000d000f00 -0e000d000d000e000f000d000d000d000d000e000e000d000d000d000d000e000f000e00 -0d000f000f0000000000000000000000000000000b000f000d000d000f0010000d000d00 -0e000d000d000d000f000e000c000d000e000d000d000f000d000d000d000f000e000d00 -0e000d000f0000000f000d000e000d000e000d000d000e000d000d000e000f000d000d00 -0f000d000d000d000d000d000d000d000e000d000d000d000e0010000e000d000e000e00 -0d000d000c000d000e000d000d000f000e000d0000000d000e000d000d000e000f000e00 -0d000e000e000d000d000d000d000d000e000e000e000f000e000d0000000d000f000000 -0d000d000f000d000f000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000e000d000e000d000e00 -0d000e000d000e000d000e000d000d000e000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000d00 -0d000d000e000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000d000e000e00 -0d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000e000e000e000d000d000e000d000e000d000d000e000d000d000d000d00 -0d000d00000012000d000d00040000000000100012000d000d0000000d000d000e000d00 -0e000e000e000d000d000e0010000c000000000000000f000c000f000f000d000f000d00 -0d000e000d000e000e000f000f000d000e000f000d000e000e000d000f000d000d000d00 -0f000d000d000d000d000e000e000e000d000d000e000f000d000e000e000d000d000e00 -0d000d000e000e000e000e000e000d000d000f000d000d000f000d000d000d000e000d00 -0f000d000d000d000d000f000d000e000e000e000d000d0010000d000d000d000d000e00 -0e000d000f0000000e000d000e000e000d000e000d000f000f000b000e000e000d000d00 -0e000d000e000d000d000f000e000d000e000f000d000e000d000c000e000d000e000f00 -0f000e000e000e000d000d000f000d000f000d000f000d000f000e000d000d000d000f00 -0e000d000f000f000e000d000f000d000d000e000b000e0000000e000e000d000e000e00 -0d000d000d000d000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0e000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000e000e000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000d000e000d000e000d000e00 -0d000e000d000e000d000e000e000d000e000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0e000d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000e000d000d000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000e000d000e000e000d000d000e000e000d000e000e000d000d000d000d00 -0d0000000d001200120004000000000010000d000d000d0000000d000e000e000e000e00 -0e000e000d000e000d000d000e000d000e000e000d000e000e000d000d000e000d000d00 -0d000f000d000d000e000d000e000e000d000d000e000d000d000d000d000d000e000d00 -0d000e000d000d000d000d000f000d000e000d000e000d000d000e000f000d000e000f00 -0d000d000d000d000d000f000d000d000d000d000d000f000d000d000f000e000d000d00 -0e000d000d000e000d000e000e000d000d000e000d000d000d000e000d000f000d000d00 -0d000f000d000d000f000d000d000f000d000d000d000d000f000d000d000e000d000d00 -0e000d000e000d000d000d000d000d000f000d000e000d000e000d000e000d000d000d00 -0d000d000e000d000f000d000e000d000d000e000d000e000d000d000e000d000d000d00 -0f000d000d000f000f000d000d000e000e000d000d000d000f000d000e000d000e000d00 -0e000d000e000e000d000e000d000e000d000e000d000e000d000e000d000d000e000e00 -0e000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000d000e000d000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000d000d000e000d000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000e000d000e000e000e000d000d000e000d000e000e000d000e000d000d00 -00000d000d000d0004000000000010000d000d000d0000000d000d000d000d000e000d00 -0d000d000e000d000e000d000d000e000e000d0010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -1000100009000e000e000e000d000e000d000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000d0010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100009000e000e000d000d000e000d000e000e000e000e000e000e000d00 -0e000e000d000d000e000d000e000d000d00100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100009000e00 -0d000e000e000e000d000e000d000e000e000e000e000e000e000d000e000d000e000d00 -0e000d000e00100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -10001000100010001000100010000a000e000d000e000e000d000e000d000e000e000e00 -0d000e000d000e000d000e000e000e000d000d000d000e00100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100009000e000d000e000e000d000d000e000d000d000e00 -0d000d000e000d000d000e000d000e000d000e000d000e000f000d001000100010001000 -1000100010001000100010001000100010001000100010001000100010000a000e000e00 -0e000e000e000d000d000e000e000e000e000d000d000e000d000d000d000d000d000000 -0d0012000d0004000000000010000d0012000d0000000d000d000e000d000e000e000d00 -0e000d000e000e000d000d000e000d000d0010000f000f000e000e000f000d000d000f00 -0e000d000d000d000d000d000e000d000e000f000e000f000e000f000e000e000d000d00 -0d000d000f000d000d000d0011000d0011000d000d000e0011000e000e000d000d000f00 -0e000e000f000e000e000f000e000e000f000d000d000f000e000f000e000f000e000f00 -0e000e000d000f000e000e000e000f000e000f000d000d000d000d0011000d000f000e00 -0e0009000e000e000e000d000e000d000d000d000e000d000e000d000e000d000e000d00 -0d000e000d000e000d000d0010000d000d000b000f000f000e000d000f000d000d000f00 -0e000e000f000e000e000e000f000e000e000f000e000e000f000d000d000f000e000e00 -0f000e000e0009000e000e000d000d000e000d000e000e000e000e000e000e000e000e00 -0e000d000d000d000d000e000d000d0010000e000d000f000d000f000d000e000d000e00 -0d0011000e000d000d0011000d000d000d000d000d000d0011000d0011000d000d000f00 -0e000e000f000e000e000f000e000e000f000d000d000f000e000f000f0007000e000e00 -0e000e000d000e000d000e000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000f0010000e000d000d000f000e000d000d000d000d0011000d000f000d0011000f00 -0b000d000d000d0011000d000e000d000e000d000e000f000d000d000d000d000e000d00 -0f000e000d000d000d000f0009000d000d000e000e000e000d000e000d000e000d000e00 -0e000e000e000e000e000e000d000e000e000d000e0010000e000e000e000d000d000d00 -11000d0010000d000d000f000d000d000e000f000d000e000e000f000d000d000f000f00 -0d0011000e000d000d000d000d000d000f0011000d000d000d0011000d000d000f000d00 -0f000e000e000d000f000f0009000d000d000e000e000d000d000d000e000e000d000d00 -0e000d000e000e000d000e000d000e000d000e000d000d000f0010000e000d000e000f00 -0e000f000f000d000f000d000d000d000f000e000d000e000e000f0008000d000d000e00 -0e000e000e000e000d000d000e000d000e000e000d000d000d000d0011000d0000000d00 -12000d0013000000000010000d0012000d0000000d000e000d000e000e000e000d000e00 -0e000d000e000d000d000e000d000d0010000d000d000d000d000d000d000d000d000d00 -0f000f000d000e000f000d000e000d000d000d000d000d000d000d000d000d0011000d00 -0f000e000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d0011000d0011000f000d000d000e000d00 -09000e000e000e000d000e000d000d000e000d000e000d000e000d000e000d000d000d00 -0e000d000e000d000f0010000e000e000f000d000d000d000f000f000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d0009000e000e000e000d000e000d000e000e000e000e000d000e000e000e000e00 -0e000d000d000d000e000d000d0010000d000e000d000f000d000f000d000d000e000d00 -0d000d000d000d000d000d00110011000d000e000d000d000e000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d0007000e000e000e00 -0e000d000d000e000e000d000e000e000e000d000e000d000e000d000e000d000e000d00 -0d0010000d000e000f000d000f000f000e000d000d000d0011000d000d000d000d001100 -0e0011000d000d000e000d000f000f000d000d000d000f000d000d000e000f000d000d00 -0e000f000d000d000d0009000e000d000e000e000d000e000d000e000d000e000e000e00 -0d000e000d000e000e000d000d000d000e000d0010000d000e000d000d000d000d000d00 -0d000f000d000d000d000f000f000e000c000d000d000e000d000f000d000d000d000e00 -0b000f000d0011000d0010000f000a00110011000e000d0011000d000e000e000d000e00 -0d000f000d000d000d0009000d000d000e000d000d000e000e000d000d000e000d000e00 -0e000d000d000e000d000e000d000e000d000e000e000d0010000e000e000e000d000d00 -0e000d000f000d000d000e000d000f000e000e000e000e000e0009000e000f000e000d00 -0e000d000e000e000d000e000e000d000d000e000d000d000d000d000d0000000d000d00 -120004000000000010000d000d000d0000000d000e000d000e000e000e000e000d000e00 -0d000e000d000d000e000e000e0010000e000e000e000e000e000e000e000e000e000d00 -0d000e000d000d000f000d000e000e000e000e000e000e000e000e000e000d000d000d00 -0e000d000d0011000d000e0011000d000d000d000d000d0011000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000d000d000d000d000d000d000e000e000900 -0e000e000e000d000e000d000d000d000e000d000e000d000e000d000e000d000d000d00 -0d000f000d000e0010000d000d000e000d000d000d000d000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e0009000e000e000e000d000e000d000e000c000e000e000e000c000e000e000e000e00 -0d000e000d000e000d000e0010000e000d000d000d000d000d000e000e000d000d000e00 -0d000d000d0011000d000d0012000e000d000d0011000d000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000f0007000e000e000e000e00 -0e000d000e000e000e000d000e000e000e000d000e000d000e000d000e000d000e000e00 -10000b000d000e000d000d000d000d0011000e000d000d000f000e000d000d000d000d00 -0d000f0012000d000d000d000e000e000e000e000c000d000d000d000d000f000e000d00 -0d000e000f000e0009000e000e000e000d000e000e000e000e000e000e000e000d000e00 -0e000e000d000e000e000e000e000e000e0010000e000f000d000d000d000d0011000f00 -0b000f000d000e000d000d000e000e000d000f000d000f000d000d000d000e000e001100 -0d000d000d000d000d000d0010000c000d000d000d000d000d000d000d000e000e000d00 -0d000e000f000d0009000f000e000e000d000d000d000d000e000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000d000f0010000d000d000d000d000d000d00 -0f000d000f000e000f000d000d000f000e000e000e000e0009000e000d000e000e000e00 -0e000d000e000e000d000d000e000e000d000d000d000d000d000d00000012000d000d00 -040000000000100012000d000d0000000d000e000d000e000e000e000d000d000e000d00 -0e000d000d000d000e000f0010000e000d000d000d000d000d000d000d000d000d000e00 -0d000f000e000d000f000d000d000d000d000d000d000d000d000d000d0011000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d0011000d000d000d000d000d000d0009000e00 -0e000e000d000e000d000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e0010000d000f000d000d000d000f000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -09000d000e000e000d000e000d000e000e000e000e000e000e000d000e000d000d000d00 -0e000d000e000d000d0010000d000d000e000f000e000d000e000d000d000d000d000d00 -0d000d000d000d000d000e000d0011000d000d0011000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000e0008000e000d000d000e000e00 -0e000d000e000e000e000d000e000d000e000d000e000d000e000d000e000d000d001000 -0f000d000f000d000f000d000e000d000d000d000d0011000b00110011000d000e000d00 -12000e000d000e000d000d000e000d000e000e0010000d000e000d000d000d000d000e00 -0d000d000e0009000f000e000e000d000d000e000e000e000e000e000d000e000d000e00 -0e000e000d000e000d000e000e000d0010000f000d000d000d000d000d000d000d000d00 -0f000d000d000d000d000f000d000d000d000d000d000f000e000d0011000a000d000d00 -0d0011000d000d000d000d000d00110011000d000d000e000d000d000e000e000d000e00 -0d000d000e0009000f000d000d000d000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000f000d00100010000d000f000d000e000e000f00 -0e000d000d000d000f000d000d000d000d000d000e0009000e000d000d000e000e000e00 -0d000e000e000e0011000d000d000d000d000d000d000d00110000000d000d000d000400 -0000000010000d000d000d0000000d000e000e000d000e000e000e000d000d000e000f00 -0e000d000d000d000f0010000e000e000e000e000e000e000d000e000e000d000e000d00 -0e000d000e000d000e000e000e000d000d000e000d000d000d000f000b000d0011000d00 -11000d000d000d000d000d000d000d000d000d000d000e000e000d000e000e000d000e00 -0d000e000e000e000e000e000d000e000e000e000e000d000d000e000e000d000e000e00 -0e000e000e000d000d000d000d0011000b000d0011000e0011000d000d0009000e000e00 -0e000d000e000d000d000d000e000d000e000d000e000d000e000d000d000d000d000e00 -0d000e0010000d000d000e000f000d000d000f000e000e000e000d000e000e000d000e00 -0e000e000d000e000e000e000e000e000d000d000e000e000d000d000e000d000e000900 -0e000d000d000d000e000d000e000d000e000d000e000e000e000e000e000d000d000e00 -0d000e000d000e0010000d000e000d000d000d000f000d000d000d000d000d0011000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000e000e000d000d000e000d00 -0e000e000e000e000e000e000d000e000e000d000e0009000f000e000e000e000e000e00 -0e000d000e000e000e000e000e000d000e000d000e000d000e000d000e000f0010000e00 -0f000e000d000f000d000d0011000d000e000d000c0010000d000d000e000d000d000e00 -0d000d000d000e000d000f000d0011000f000d000d000f000d000f000d000d000e000e00 -0e000e0009000e000d000d000e000e000e000e000d000e000d000e000e000e000d000d00 -0e000e000d000e000d000d000e0010000d000d000f000d000d000d000d000e000e000d00 -0d000f000d000d000d000d0010000d000e000d000d000e000d000d0010000d000d000d00 -12000e000e000d000d000d000d000d000d0011000d000f000d000f000d000d000d000e00 -0e000d0009000e000d000d000d000e000e000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000d000f0010000d000d000d000d000e000d000e000d00 -0d000d000d000d000f000d000e000e000e000e0009000e000d000e000d000d000e000e00 -0d000d000e000e000e000d000e000d000d0011000d000d00000012000d00120004000000 -000010000d0012000d0000000d000d000d000e000e000e000d000e000e000d000e000e00 -0e000d000d000d0010000e000d000d000d000d000d000d000d000d000e0000000f000d00 -00000f000d000d000d000d000d000d000d000d000d000d000b0001000d000d000d000e00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000b0001000d000d000d000e000d000e0009000d000e000e00 -0d000e000d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0d0010000f000d000d000e000d0000000d0000000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d0009000d00 -0e000e000e000e000e000e000e000e000e000d000e000e000e000d000e000d000e000d00 -0e000d000e0010000f000d000d0001000d000b000d000e000d000d000d000d000d000d00 -0d000d001100000011000d00000011000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000e000f0009000f000e000e000d000d000d000e00 -0e000e000e000d000d000e000e000d000e000d000e000d000e000d000d0010000b000d00 -00000000000000000000000000000d00010000000000000000000d000d00110000001100 -0d000d000e0000000d000f000000000001000000000001000b000f000e000d000d000d00 -0d0009000e000d000d000e000e000e000d000e000e000e000e000e000d000e000e000d00 -0e000e000d000e000e000d00100011000e000d000000000000000000000000000d000d00 -0d000f000d0000000d000d000e000b000f0000000d000e000d000d000d00110011000000 -0000000000000e000d000d000000000000000000000001000b000f000e000d000d000d00 -0d0009000e000d000d000e000e000d000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000d0010000f000e000d000e000000000000000d000e00 -00000e000d000d000d000e000e000d000e0009000e000d000d000e000e000e000e000e00 -0d000e000e000e000e000d0011000d000d000d000d0000000d000d000d00040000000000 -10000d000d00120000000d0011000e000d000e000e000e000d000d000e000d000e000e00 -0d000d000e0010000e000d000d000e000d000d000d000e000d000e0000000d000d000000 -0d000d000f000e000d000e000d000d000d000d000d000f00000011000e000d000e000d00 -0d000d000d0011000d000d000d000d000d000d000e000d000e000d000d000d000d000d00 -0d000e000d000d000d000e000d000e000d000e000d000e000d000e000d000d000e000d00 -0d000d000d000d000d000e000000110011000d000e000d000d0009000e000e000e000d00 -0e000d000d000d000e000d000e000d000e000d000e000d000d000e000d000e000d000d00 -10000e000f000d000e0000000e000e0000000d000e000d000e000d000d000d000d000d00 -0d000d000e000d000e000d000d000e000d000e000d000e000d000d000d0009000d000e00 -0e000e000e000d000e000d000e000d000e000e000e000d000e000d000d000e000d000e00 -0d000e0010000d000f000d0000000e0011000d000e000d000d000d000d000d000d000d00 -0d000e0000000d000d0000000d000d000d000e000d000e000d000e000d000e000d000d00 -0d000e000d000d000d000e000d000e000e0008000e000d000e000e000e000e000e000d00 -0e000e000d000e000d000d000e000d000e000d000e000d000e000d0010000f000e000d00 -0d000f00000011000c0011000d0000000d000e000e000d0000000d000e0000000d000d00 -11000d0000000d000d0000000d000d000f000f000c000f000d000d000e000e000d000e00 -09000e000e000d000e000e000d000e000e000e000d000e000d000e000d000e000e000e00 -0e000e000d000d000e0010000d000d000f0000000d0011000d000e000e000e000e000d00 -0d0000000d0000000c000f000f000d0000000f000d000e000d000d000d0000000e000d00 -0e000d00000011000d0000000d000d0011000f000d000f000d000d000e000e000d000d00 -09000f000d000d000e000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000d000e0010000e000d000e0000000e000e000d0000000d000e00 -00000d000d000e000e000e000e000e0009000f000e000e000d000d000e000d000e000e00 -0d000e000e000e000d000d000d000d000d000d0000000d0012000d001300000000001000 -0d000d000d0000000e000d000e000d000e000d000d000e000d000e000d000e000e000d00 -0d000e0010000f000d000d000d00000000000e0000000e000000000000000d0000000f00 -0d0000000d000d000d000d000e000e000d000d000d0000000d00000000000d0011000d00 -0d000000000000000e000d0000000d000e000d000e0000000e000d000f000d000e000d00 -0d000f0000001000000000000e000d000e000d000000000000000d000d000d000e000000 -000000000d000d000d0000000d000d0000000d000e000d0009000e000d000e000d000e00 -0d000e000e000d000e000d000e000d000e000d000d000d000d000d000e000d000f001000 -0e000d000d000f0000000f000d0000000f00000000000d000d000e000d00000000000100 -0d000e0000000c0010000d000e0000000d000d000d000e000f000d0009000e000e000d00 -0d000e000d000e000e000e000e000d000e000e000e000d000e000d000e000d000e000d00 -0d0010000e000e000d0000000d00000000000d000d000e0000000d000d000d0000000d00 -0000000000000000000000000d000d000000000000000f000d000d0000000e0000000000 -0e000d000d000e000f000d000e000e0009000e000e000e000d000e000d000e000d000d00 -0e000e000d000e000d000e000d000e000d000e000d000d000f0010000e000e000d000e00 -0e0000000d000d000d000d0000000d000d000d000d0000000e000d0000000d000d001100 -0d0000000f000d0000000d000e000d000d000f000d000d000f000d000e000d000e000700 -0e000e000e000d000e000e000d000e000e000e000d000e000d000e000e000e000e000e00 -0d000e000d000d0010000d000d000d0000000d000d000d000e000d000d000e000d000e00 -00000d0000000d000f000d000e0000000d000e0011000d000d000d0000000d000e000d00 -0d000d000d00110000000d000d000d000d000f000d000d000f000d000e000d000d000900 -0d000e000e000d000e000d000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000f000d0010000f000d000d0000000f000e000d0000000d000d000000 -0d000e000c000f000d000c000e0009000d000e000d000e000d000e000d000e000e000d00 -0d000d000d000e000d000d000d000d000d0000000d0012000d0004000000000010001200 -12000d0000000d000e000d000e000e000e000e000d000e000e000d000e000d000d000d00 -0d0010000e000d000f0000000d000f00000000000d000e0000000d000d0000000d000000 -0d000e000d000e000e000d000e0010000d000d00000000000d000d0001000d000d000000 -12001100110000000d00110000000f000f0000000d000d000e000d000e000e000d000e00 -0d00000000000e000e0000000d000e0000000f000d000e0000000d000d0000000f000d00 -0f0000000d000d0000000d0001000d000d000e000d0009000e000e000d000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000d000e000d000e000d000e0010000e00 -0d000e0000000d000d000d00000000000e000d0000000e000d0000000f000d000e000000 -0d000e0001000d000e0000000f000f000d000f000d000e000d0009000e000e000e000e00 -0e000d000e000e000e000e000e000d000e000d000e000d000d000e000d000e000d000d00 -10000f000f000d00000001000d000d0000000d000d00000011000d000e0000000d000e00 -00000f000d00000010000d0000000e000d000f0000000f000e00000000000d000e000000 -0d000f000d000c000f000e000d0009000e000e000e000d000e000e000d000e000e000d00 -0e000e000e000e000d000e000d000e000d000e000e000f0010000d000d000d000d000d00 -00000d000e000d000d0000000d0011000e000d0000000d000e0000000d000f000d000e00 -00000b000e0000000d000f000f000e000e000f000d000d000f000b000f000e0007000e00 -0e000e000d000e000e000e000e000d000e000e000d000e000e000d000e000d000e000e00 -0d000e000d0010000e000d000d0000000d0011000e000e000f000f000d000e0000000f00 -0d000d0000000d000d000d0000000f000d000c000f000e000d000d00000000000d001100 -0d000d000f0000000d000d000e000d000d000f000d000d000e000b000e000d0009000d00 -0d000d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000d000d0010000d000f000d0000000d000d000e0000000e000d000d000000 -0d000d0001000e000e000f0007000e000e000e000e000e000e000e000d000e000e000d00 -0d000e000d000d000e000d000d000d0000000d000d001200040000000000100012000d00 -0d0000000d000e000e000d000e000d000d000d000e000d000d000e000e000e000d000d00 -10000e000d000d0000000d000d000d0000000e000e0000000d000f00000000000e000e00 -0d000d000d000e000e000d000d000d00110000000e000d000d0000000d000e0000000d00 -0d000d0000000e000b000d00000000000d000d000e000e000e000d000d000e000e000d00 -00000f000c000f0000000f000d000d000f000d000d0000000d000f0000000d000f000d00 -0d000f000d00000000000d000f000d000d000e0009000e000e000e000d000e000d000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e0010000d000f00 -0d0000000e000f000d0000000e000f000d0000000f000d0000000d000e000d0000000f00 -0c000d00000000000e000b000e000e000d000d000d000e0009000d000e000d000d000e00 -0d000e000e000d000d000e000e000e000e000d000d000d000d000d000e000d000f001000 -0d000d000f0000000d000e000e0000000e00110000000d000d000d00000011000d000000 -11000d0000000b000f0000000d000e000e0001000d000d0000000d000e000f0000000e00 -0e000c000f000d000e000d0009000e000d000e000d000e000d000e000e000e000e000d00 -0e000d000d000e000d000e000d000e000e000d000d0010000d000d000f000f000e000000 -0d000d000d000d00000000000000000000000b000d00110000000d000d000e000d000000 -0f000e000000000000000000000000000d000e000e000d0010000d000e0007000e000e00 -0e000d000e000e000d000e000d000d000e000e000d000e000d000e000e000d000d000d00 -0e000e0010000d000e000d00000000000000000000000d000e000d000e0000000e000e00 -0d0000000d000e000d0000000e000e000d000d000d000d000d0011000d00000000000e00 -0d000d000000000000000000000000000d000e000d000d0010000d000d0009000d000e00 -0e000d000e000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e0010000e000d000f0000000f000d000d0001000d000e000e0000000e00 -0f000b000e000d000e0009000e000e000e000d000d000e000e000d000e000d000e000d00 -0e000e000d000e000d000d001100000012000d000d0013000000000010000d000d000d00 -00000d000d000e000e000e000e000e000e000d000e000d000d000d000d000d000e001000 -0e000d000e0001000d000e000e0000000d000d0000000d000f00000000000d000d000e00 -10000d000c000f000f000d000d000d0000000d000e00110000000e000d00000011000d00 -0d0000000d000f0011000000000010000e000d000d000c000f000d000d000d000d000000 -0d000f000d0001000b000f000f0000000100000001000d000d0000000e000d000e000e00 -0d000d00000000000d000d000d000e000d0009000e000e000e000d000e000d000d000d00 -0e000d000e000d000e000d000e000d000d000e000d000e000d000f0010000d000f000d00 -00000d000e000d0000000e000d000e0000000e000d0000000f000d000d0000000d000e00 -0f00000000000e000d000d000e000f000d000d000e0009000e000e000e000d000e000d00 -0e000e000e000e000d000d000e000e000e000d000d000e000d000f000d000e0010000d00 -0f000d0000000e000d000f0000000d000e0000000d0011000d0000000d00110000000d00 -0d0000000d000f0000000d000d000c0000000d000d0000000f000d000d0001000e000e00 -0f000d000e000e000d0009000e000d000e000d000e000e000e000d000e000e000e000e00 -0e000e000d000e000d000e000d000d000e000d0010000d000d000d000d000d0000000d00 -11000d00110000000b000d001100000011000d000d00000011000b0011000d0000000e00 -0d0000000d000e000f000d000d000e000e000d000d000c000d000e0009000e000e000e00 -0c000e000e000e000e000e000e000e000d000e000e000e000d000e000e000e000e000e00 -0d00100011000d00110000000b000d000f000d000d000e000f000d000100000000000000 -00000e000e000d0001000f000b000d000e0011000d000d000c0011000d000d0000000e00 -0d0000000e000c0011000d000d000e000e000d000e000d000d000d0009000d000e000d00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000d000d0010000f000d000b0000000d000d000d0000000f000d000e0000000d000d00 -0f000f000c000f000a000d000e000d000e000e000d000e000e000e000e000d000e000e00 -0d000e000d000d000d000d00000012000d00120013000000000010000d000d000d000000 -0d000d000d000e000e000e000d000e000d000e000d000e000e000d000d000e0010000e00 -0d000e0000000f000e000d0000000e000d0001000d000c0001000d0000000e000d000d00 -0d000f000d000b000d000f000d0000000e000c000d0000000b00110000000d000d000d00 -00000e000d0000000d000f0000000f000d000f000d000d000d000e000e000f0000000d00 -0d000d0000000d000f0000000d000d000d0000000d000e0001000d000d000d000d000d00 -11000000110000000e000f000d000e0009000e000e000e000d000e000d000d000e000d00 -0e000d000d000e000d000d000e000d000e000d000e000d000d0010000d000d000d000000 -0e000d000e0001000e000d000d0000000d000f0000000d000d000e00000010000d000000 -0e000d00000010000e000e000b000f000d000d0009000e000d000e000d000e000d000e00 -0e000d000e000e000e000d000e000e000e000d000e000d000e000d000e0010000d000d00 -0e0000000f000d000d0000000e000d00000010000d000d0000000d000d00000011000d00 -00000e000d0000000e000f000f0000000d000e0000000d000f000e0000000d000d000d00 -0f000d000e000e0009000e000d000e000d000e000e000d000e000d000e000e000e000e00 -0d000e000d000e000d000e000d000d000e0010000d000f000d000d000e0000000d000d00 -0d000d000000110011000d000d0000000d000d0000000d000d000d000f0000000d000d00 -00000f000d000d000e000f000d000d000f000f000e000e000e0009000e000e000e000d00 -0e000d000e000e000e000e000d000e000d000e000e000e000d000e000d000d000e000d00 -10000d000e000d00000011000f000d000f000e000b000e0001000d000d000d000d000e00 -00000d000d0000000d000f000d000d000d000d0000000d000d000d00110000000e000d00 -00000d000d0011000d000e000d000d000e000e000d000e000d0009000d000e000e000d00 -0e000d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0e000d0010000d000d000e0001000d000d000f0000000d000f000d0000000e000e000e00 -0d000e000d0009000d000e000e000d000e000e000e000e000e000e000d000e000d000e00 -0d000d000d000d000d0000000d0012000d00130000000000100012000d000d0000000d00 -0d000e000d000e000e000e000d000d000d000d000e000d000d000d000f0010000e000e00 -0e0001000d000f00000000000e000d0000000d000e0001000e000d0000000f000f000d00 -0d000f000d000d000d0011000000000011000d00000011000c0000000d0011000d000000 -0e00000011000d000e000d0000000f000c000d000f000f000d000d000d00000000000f00 -0e0000000f000d0000000d000d000f0000000d000f0000000d000f000e0000000d000d00 -00000d000d0000000e000e000d0009000d000e000e000d000e000d000d000d000e000d00 -0e000e000d000e000e000d000d000e000d000e000d000d0010000d000d000e0000000d00 -0f000d00000000000f000b0001000d000d0000000e000d000e0000000d0000000d000d00 -0f000f0000000d000f000d000e000f000e0009000e000e000d000d000e000e000e000e00 -0e000d000e000e000e000d000e000d000d000d000d000e000d000e0010000e000d000d00 -000000000f000d0000000d000d0000000b001000000000000d000d0000000d000d000000 -0d000d0000000e000d000d0000000d000f0000000d000d000e0000000f000e000e000c00 -0e000e000e0009000e000d000e000d000e000e000e000e000e000e000e000e000e000e00 -0d000e000d000e000d000d000e000d0010000f000e000e000f000e0000000e000d000e00 -0d0000000d000d000d000f0000000d00110000000e000d000d000d0000000f000d000000 -0d000f000d000f000d000d000c000f000c000e000f000e0009000e000e000e000d000e00 -0e000e000d000e000d000e000e000e000d000d000e000e000d000e000e000d000d001000 -0d000f000d0000000d000d000d000d000f000d000d0000000d000d000f000d000e000000 -0e000f0000000d000d0011000d000d000d0000000d000d000d000d0000000d0011000000 -0d000d000d000f000d000d000d000e000d000d000e000e0009000d000e000d000d000e00 -0e000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000d00 -0d0010000e000e000f0000000f000d000f0000000d000d000f0000000d000f000c000e00 -0e000d0009000d000e000d000e000e000d000e000d000e000e000d000e000d000d000d00 -0e000d000d000d0000000d000d000d0013000000000010000d0012000d0000000d000e00 -0e000d000e000e000e000d000e000d000d000e000e000d000d000d0010000e000d000d00 -0d00000000000e0000000d001100000000000d0000000d000d000d0000000b000f000d00 -0d000e000f000d000d0000000d00000000000d0011000d000d000000000000000d001100 -00000c000e000d000e0000000d0010000d000c000e000d000e000d0000000d0000000000 -0d000c000f000e000000000000000e0000000d000d000000000000000d000e0011000000 -0d000d000e0000000d000f0009000e000e000e000d000e000d000d000e000d000e000d00 -0d000e000e000d000d000d000d000d000e000d000e0010000e000d000f0000000d000e00 -0d0000000d00000001000d000c0011000f000000000001000d000d0000000d000d000d00 -0d0000000e000e0000000d000e000d0009000e000e000e000d000e000d000e000e000e00 -0e000e000e000d000e000d000e000d000e000d000e000d000d0010000d000d000e000000 -0d00000000000f000d000d000e00000000000e00000011000d00000000000e0000000000 -11000d000000000000000d000e000e0000000e000d000d0000000d000d000d0000000e00 -0e000d0009000e000d000e000d000e000e000d000d000e000d000e000e000e000d000e00 -0d000e000e000d000d000e000d0010000f000c000d000e000c0001000d00110012000d00 -00000d000d0011000d0000000d000d000f0000000000000000000f000d000d0001000000 -00000000000000000f000e000c0000000f000c000e0009000e000e000e000d000e000e00 -0d000e000e000e000e000e000d000e000e000e000e000e000d000e000d000e0010000f00 -0d000d0000000d000d000f000d000f000e000d0000000e000d000d000d000d0000000d00 -0e00000000000000000000000d000d000d0000000000000000000d000d000d0000000000 -00000000000000000f000e000d0000000f000d000d0009000e000d000e000d000e000d00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000f00 -10000f000d000d000e000000000000000e000f000d000d0000000e000d00000010000c00 -0f0009000d000e000d000e000e000e000d000e000e000d000e000e000d000e000d000d00 -11000d000d00000012000d00120004000000000010000d000d000d0000000d000e000d00 -0e000e000e000d000e000d000e000d000d000d000d000d000d0010000d0011000c000f00 -0d000d000d0000000f000d000d000f000e000d000d000d000e000d000f000d000d000e00 -0d000f000d000d0011000d000e000d000e000d000e000e000d000d000d000f000d000d00 -0e000e000d000e000d000d000d000d000f000d000e000d000d0000000d000f000d000d00 -0e000d000e000d000f000d000e000e000d000e000e000d000e000d000d000d000d001100 -0d000d000e000e000d0009000e000e000e000d000e000d000d000d000e000d000e000d00 -0d000d000e000d000d000e000d0011000d000e0010000e000d000d000d0000000d000e00 -0d000f000f000d000d000e000d000d000e000e000d000d000e000d000d000f000d000d00 -0f000d000d0000000e000d000e0009000e000e000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000d000e000d000e000d000d0010000d000e000d000d000f00 -0e000d000d0011000d000d000d000e0011000e000d000d000e000e000d0011000d000d00 -0d000d000f000b000f000d000d000f000d000d000d000d000f000d000e0001000d000e00 -0d0009000e000d000e000d000e000e000d000e000d000e000d000e000e000e000d000e00 -0d000d000e000d000e000f0010000d000d000f000d000f000d000e000d000e000f000d00 -0e000e000d000d000d000d000d000d000d000f000d000e000d000d000e000d000e000d00 -0e000e000f000d000d000f0000000d000e000e0007000e000e000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000e000e000e000d000d000d000d0010000d000e00 -11000d000e000d000d000e000d000e000d000d000d000d000e000e000d000d000f000d00 -0e000e000d000e000d000d000f000d00120011000d000e000d000d0011000d000e000d00 -0e000d000f000d000d000d0000000d000e000d0009000d000e000d000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d001000 -0d000f000d000f000d000d000f000d000d000d0001000d000e000e0000000d000e000d00 -09000e000d000e000e000e000d000e000e000e000d000e000e000e000e000d000d000d00 -0d000d0000000d000d000d00040000000000100012000d000d00000011000e000e000d00 -0e000d000d000e000d000e000e000d000e000d000e000d0010000d000d000f0000000d00 -0d000d0000000e000e000d000e000e000d000e000d000e000d0000000000000000000000 -000000000d000d000e000d000e000e000d000e000e000d000e000e000d000e000e000d00 -0d000e000d000d0000000000000000000000000000000d0000000f000d000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000d000d000d000d000d00 -0e000d000e000e0009000e000f000d000e000d000d000e000e000d000e000e000e000e00 -0e000d000d000d000d000d000d0011000d0010000d000d000d000f0000000f000d000d00 -0e000e000d000e000d000e000e000e000e000d000e000d000e000e000d000e000e000d00 -0d0000000d000e000e000d0009000e000e000d000e000e000d000f000e000f000d000f00 -0d000e000e000e000d000d000d000d000f000f000e0010000e000d000e000d000e000e00 -0d000e000d000d000d000d000e000d000e000e000d000e000e000d000e000e000d000e00 -0e000e000e000e000e000e000e000e000e000e000e000d000f0000000d000f000f000e00 -09000e000e000e000e000d000d000e000e000e000e000f000d000e000e000e000e000d00 -0e000d000e000d000e0010000d000d000e000d000d000e000e000d000e000e000d000e00 -0e000d000e000e000d000e000e000d000e000e000e000e000e000e000e000e000e000e00 -0d000e000e000d0000000e000d000e000d000a000e000d000e000d000e000e000d000c00 -0e000e000d000e000e000e000e000d000e000d000e000d000e000d0010000f000f000d00 -0e000d000d000e000d000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0d000d000d000e000e000e000e000e000d000d000e000e000d000e000e000d000d000d00 -0d000e000e000d0000000e000d000e000d000a000d000d000e000d000e000e000e000d00 -0e000e000d000e000e000d000e000d000e000d000e000d000f000d000d000d0010000d00 -0e000d000d000f000d000d000f000d000d0000000f000e0000000c000f000e000d000900 -0f000d000d000e000e000e000e000f000c000e000d000d000e000e000d000d000d000d00 -110000000d000d000d0004000000000010000d000d00120000000d000e000e000e000e00 -0e000e000d000d000e000e000d000e000d000d000d0010000d000f000d000d0000000000 -01000d000d000e000e000e000e000e000e000e000e000f000d000f000d000d000f000d00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000d00 -0d000d000f000c000e000e000f000d000f000e000d0000000c000e000d000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000f000e000e00 -0e000e000e0009000e000d000d000f000d000d000e000e000d000e000e000e000d000e00 -0d000d000d000d000e000d000e000d0010000e000d000d000e000d0000000f000d000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000d000e00 -0d000d000d000d000f0009000d000e000d000e000d000d000e000c000e000d000e000e00 -0e000e000d000e000e000d000d000d000d000d0010000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000d000f000d000e000d000c000e000e000d000d000900 -0e000e000e000e000d000e000e000e000e000c000e000d000e000e000e000d000e000d00 -0e000d000e000d0010000d000d000e000e000d000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000f00 -0d000e000d000c000f000d000e000e0009000e000d000f000d000e000d000f000e000e00 -0d000d000e000d000e000d000e000d000e000d000e000d000e0010000e000e000d000f00 -0d000d000d000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0f000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000f000f00 -0d000e000d000d000e000d000e000d0009000d000d000f000d000e000d000d000d000e00 -0e000d000d000e000d000d000d000d000d000e000d000e000e000d000d0010000d000f00 -0e000d000d000d000d000d000e0000000f000d000d000d0010000d000d000f0008000d00 -0e000e000e000e000e000d000d000d000e000d000e000e000e000d000e000d000d000d00 -000012000d00120004000000000010000d0012000d0000000d0011000e000d000e000d00 -0d000e000e000d000d000d000e000d000e000f0010000e000d000f000d000d000e000e00 -0d000e000d000d000d000d000d000d000d000d000d000d000f000d000e000f000d000d00 -0d000e000d000e000d000e000e000d000d000d000d000e000e000d000d000e000e000e00 -0d000d000e000e000d000d000e000d000d000f000d000f000d000d000d000d000d000d00 -0d000d000d000e000d000e000d000d000d000d000e000d000d000d000d000d000d000d00 -0d000d0009000d000f000d000e000e000d000d000e000d000e000e000e000d000d000e00 -0d000d000d000f000d000d000d0010000d000f000f000d000d000d000e000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000e000d000f001000 -0d000d000d000d0009000e000f000d000e000e000e000e000e000e000e000d000d000e00 -0e000d000e000d000e000d000e000d000e0010000d000d000d000d000d000d000d000d00 -0e000d000d000d000d000d000d000e000e000d000d000e000d000e000e000d000d000d00 -0d000e000d000e000d000d000d000d000e000d000e0010000d000e000f000e0009000f00 -0e000e000e000e000d000e000e000f000e000e000f000e000d000e000d000e000d000d00 -0d000e000f0010000f000d000d000d000d000d000d000d000d000d000e000d000d000e00 -0d000e000e000d000d000d000d000e000d000e000d000d000d000d000d000d000d000d00 -0d000d0010000f000c000e000d0008000d000d000e000e000e000e000d000d000d000d00 -0e000e000d000e000e000d000e000d000e000d000e000d0010000d000e000d000f000e00 -0d000e000e000d000e000d000d000d000d000d000d000d000e000d000d000d000d000d00 -0e000d000d000d000d000e000d000d000d000e000e000d000d000d000e000d000d000d00 -0d000d0010000e000d000d000d0009000d000d000d000e000d000e000d000d000d000f00 -0e000d000d000e000e000e000f000e000f000d000d000d000e000e0010000d000d000d00 -0e000f000e000e000d000d000e000d000d000f000d000d000d000d000f000a000d000e00 -0e000e000e000e000f000e000f000e000e000e000d000e000d000e000d000d000d000000 -0d000d000d0004000000000010000d000d000d0000000d000d000e000e000d000e000e00 -0e000d000e000d000d000d000d000d000f0010000d000b000e000e000d000d000d000d00 -0d000e000e000e000e000e000e000e000e000e000d000d000d000e000d000d000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000d000d000d00 -0d000f000d000d000f000f000d000f000d000e000d000d000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e0009000d000e000d000d000d000d000d000e000e000d000e000e000d000d000e000e00 -0e000d0011000d000d000d0010000d000f000b000d000f000d000d000d000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000d000e000d000b000e00 -0d000e000d0009000d000e000d000e000e000e000d000e000e000e000d000d000e000d00 -0d000d000d000e000f000f000d000d0010000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000d000e000d000f000b000e000e000d000c0009000e000c00 -0e000d000e000e000e000e000e000e000d000e000c000e000d000e000d000e000d000e00 -0d000d0010000d000e000e000e000d000d000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000d000e000d00 -0f000b000d000f000e000f0009000e000e000d000d000d000d000d000e000d000d000e00 -0e000c000d000d000e000d000e000d000e000d000e0010000d000d000d000e000d000d00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000d000e000e00 -0e000b000d000f000d000f0009000e000e000d000d000d000d000e000e000d000d000e00 -0d000d000e000d000d000d000d000d000d000d000d000d000e0010000f000d000d000d00 -0d000c000e000d000d000e000d000e000d000e000f000f000c000c0009000e000d000e00 -0e000e000e000d000d000e000c000e000d000e000d000d000d000d000d000d0000001200 -0d000d0013000000000010000d000d000d0000000d000d000d000e000d000e000d000e00 -0e000d000d000d000f000e000f000f0010000d0010000d000d000f000d000e000f000d00 -0f000e000e000e000d000e000e000e000d000d000d000e000d000e000f000e000e000e00 -0e000f000d000e000d000e000e000e000e000e000e000e000e000e000f000e000d000e00 -0d000d000d000d000d000d000f000e000d000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000f000e000e000e000d000f000e000e000e000e000e000e000e00 -09000d000f000e000d000d000e000d000e000e000d000d000e000e000d000e000d000e00 -0d000e000d001100110010000d000f0010000d000d000f000d000e000d000e000e000d00 -0f000e000e000e000e000e000d000e000f000e000e000e000d000f000c000d000f000f00 -0d000f0009000d000e000e000e000d000e000e000d000d000e000e000e000e000d000d00 -0f000d000d000d000d000f000f0010000e000e000d000e000f000e000e000e000d000d00 -0e000e000e000e000e000e000e000e000e000f000d000e000d000e000e000e000e000e00 -0e000e000e000e000d000f000d000d000d000d000f000d000d000d000a000f000e000e00 -0d000d000f000e000d000d000d000d000f000f000d000e000d000e000d000e000d000e00 -0f0010000d000f000d000d000d000d000f000e000e000e000d000e000e000d000d000e00 -0e000e000e000e000e000e000e000e000e000f000e000e000e000e000f000d000d000f00 -0d000d000f000d000c0009000e000f000d000f000e000f000e000e000e000d000e000e00 -0e000f000e000d000e000d000e000d000e000d0010000f000f000d000e000d000d000d00 -0e000d000e000d000f000e000e000e000e000e000d000e000e000e000e000e000e000d00 -0e000d000f000e000e000e000d000e000d000e000e000e000e000e000f000d000d000e00 -0d000c000f000d000d0009000d000e000d000f000d000f000e000e000d000d000f000d00 -0d000e000e000e000d000e000e000e000e000f000d000d0010000f000e000d000f000f00 -10000b000f000f000d000d000e000f000d000c000d000e000e0009000f000d000f000e00 -0d000e000d000e000f000f000d000e000d000e000d000d000d000d000d0000000d000d00 -120013000000000010000d0012000d0000000d000d000e000d000e000d000e000d000d00 -0e000e000d000f000e000d000b000a000900040009000900090009000900090009000900 -0900090009000900090009000900090009000a0009000900090009000900090009000900 -09000900090009000900090009000900090009000900090009000900090009000a000900 -0900090009000a0009000400090009000900090009000900090009000900090009000900 -090009000900090009000900090009000900090009000900090009000900090009000a00 -0d000f000f000d000d000f000f000c000e000d000d000e000e000d000e000e000e000d00 -0d000d000d000c000a0009000400090009000a0009000900090009000900090009000900 -090009000900090009000900090009000900090009000900090009000a00090009000900 -09000a000d000e000e000e000d000e000e000f000f000c000e000d000e000e000e000d00 -0d000e000d000f000e000b000a0009000900090009000900090009000900090009000900 -090009000900090009000900090009000900090009000900090009000900090009000900 -090009000900090009000900090008000a00090009000900090009000d000d000f000e00 -0e000d000e000e000f000e000f000c000e000e000e000e000d000e000d000d000e000b00 -0b0009000900090009000900090009000900090009000900090009000900090009000900 -090009000900090009000900090009000900090009000900090009000900090009000a00 -0900090009000a0009000c000f000e000e000e000e000d000d000d000e000d000e000f00 -0c000d000e000d000e000d000e000d000e00090009000900090009000900090009000900 -090009000900090009000900090009000900090009000900090009000900090009000900 -090009000900090009000900090009000900090009000900090009000900090009000a00 -0900090009000a0009000d000e000e000f000d000e000d000d000d000d000e000e000d00 -0d000d000d000d000e000e000e000d000e000e000d000a00090009000900090009000400 -0b000900090009000900090009000a000900080009000a0008000e000f000d000e000e00 -0f000e000f000c000e000d000d000e000d000d000d0011000d000d00000012000d000d00 -040000000000100012000d000d0000000d000d000e000e000e000e000d000e000e000d00 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -10001000100010001000100010001000100010001000100010001000100010000f001000 -1000100010001000100010000a000e000f000d000e000d000d000e000d0011000e001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -10001000100010001000100010001000100010000a000e000d000d000f000e000f000d00 -0d000d000f00100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -1000100010001000100010000a000d000e000d000e000d000d000d000e000d000e001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010000a00 -0e000d000e000d000e000d000e000d000f000f0010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -10001000100010001000100010001000100010000a000d000e000d000e000e000d000e00 -0d000e000e00100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010000a000d000e000e000e000d000d000d000d000d000d0000000d00120012000400 -0000000010000d000d000d0000000d000e000e000e000e000e000e000d000d000e001000 -0f000e000e000d000d000d000f000d000f000d000d000d000f000d000f000e000e000f00 -0e000e000f000d000d000d000d000e000d000d000e000d000f000e000f000e000e000f00 -0e000e000f000e000e000f000e000e000f000d000d000f000f000d000d000f000f000d00 -0e000d000e000e000d000f000d000d000e000e000e000f000e000e000e000f000e000e00 -0f000e000e000f000e000e000f000e000e000f000e000e000f000e000d000f000e000d00 -0d000f000d000f000d0009000d000f000d000d000d000d000e000d000d000e0010000d00 -0d0011000d000e000e000e000c000f000e000f000d000f000e000e000f000e000e000e00 -0d000f000e000e000f000e000e000f000e000d000e000e000d000d000e000d000e000f00 -0e000d000e000e000e000e000e000e000e0007000f000e000e000e000c000d000d000e00 -0d000e00100010000d000f000e000e000f000e000e000f000e000e000e000f000e000e00 -0e000f000e000e000f000e000e000f000e000e000f000e000e000f000e000e000f000d00 -0d000d000e000d000e000d000f000d000d000e000f000e000d000e000e000f000e000f00 -0e000d000e000c000f0008000e000d000e000d000e000d000e000d000e000f0010000f00 -0f000d000d000f000e000e000e000f000e000e000e000d000d000e000e000f000e000e00 -0e000f000e000e000f000e000e000f000e000e000e000e000d000f000e000d000e000e00 -0d000e000f000d000d000e000e000f000e000e000d000d000e000d000f000f0007000d00 -0e000d000e000d000e000d000e000d000d0010000f000e000d000f000f000f000e000e00 -0f000e000e000f000e000f000e000e000f000e000e000e000d000f000e000e000f000e00 -0e000f000e000f000e000e000f000e000e000e000d000f000d000e000e000d000f000f00 -0d000e000f000d000d000d000d000f000e0009000d000f000d000d000d000d000e000d00 -0e000e0010000f000f000d000d000d000f000f000f000d000d000d000e000d000d000d00 -0f000f000d000d000e000f000d000e000d000e000f000d000e000f000e000d000e000c00 -0f0007000e000e000e000d000d000e000d000d000d000d0000000d000d000d0004000000 -000010000d000d000d0000000d000d000d000e000d000d000d000e000d000d0010000d00 -0d000e000d000d000d000e000d000d000e000d000f000d000d000d000d000e000e000d00 -0d000e000d000e000d000d000d000d000e000d000d000d000e000d000d000e000d000d00 -0e000d000d000d000d000e000d000f000d000d000d000e000e000d000d000d000e000d00 -0e000d000d000d000e000e000d000e000d000d000d000d000d000d000d0011000d000d00 -0e000d000d000e000d000d000d000e000d000d000e000e000d000d000e000d000e000d00 -0e000d000d000e0009000e000d000e000d000e000d000e000d000e000d0010000d000d00 -0d0011000d000f000d000d000d000b000f000d000e000d000e000f000d000d000d000e00 -0e000d000d000d000d000f000d000d000d000e000f000d000d000d000e000d000e000e00 -0d000e000d000e000d000e000e000d0009000e000e000e000d000e000d000e000d000e00 -0d0010000d000e000e000d000e000d000e000d000e000d000d000d000d0011000d000d00 -0e000d000d000f000d000d000d000d000d000d000e000d0011000d000d000d000d000d00 -0d000d000d000d000e000d000e000d000e000e000d000e000e000d000e000d000e000e00 -0d000e000e000d0007000e000d000e000d000e000d000e000d000e000d0010000d000d00 -0d000e000d000d000d000d000e000d000d000e000d000d000e000d000c0011000d000d00 -0e000d000d000f000d000d000d000e000e000d000d000e000d000d000e000e000d000d00 -0e000e000f000e000e000e000e000e000e000d000e000e000e000e000d0009000e000d00 -0e000d000e000d000e000d000e000e0010000d000d000d000e000d000e000e000d000d00 -0d000d000e000d000d000f000d000d000e000d000d000d000e000d000d000d000d000e00 -0d000d000d000d000d000d000d000e000d000d000d000e000d000d000d000e000d000d00 -0d000e000d000e000d000e000d000e0009000d000e000d000d000e000d000e000d000e00 -0d0010000f000d000d000e000d000e000d000e000d000d000e000d000d000d000d000d00 -0e000d000e000d000e000e000f000d000e000d000e000e000e000e000d000e000e000e00 -09000e000d000d000d000e000d000e000d000d000d0000000d0012000d00040000000000 -10000d0012000d0000000d000d000d000d000e000e000e000d000e000d0010000d000d00 -0e000d000e000d000d000f000d000d000e000d000d000f000d000e000e000d000f000d00 -0f000d000d000f000d000e000d000b000e0010000d0011000d000f000d000d000d000b00 -11000d000f000e000d000e000d000d000f000e000d000d000d0010000d000d000d000c00 -0e000f000d000d000e000f000d000e000d000d000f000d0011000e000b000e000f000d00 -11000d000d000d000e000e000d000f000d000d000d000d000e000d000e000d000e000d00 -0e000e000d0009000d000e000e000d000e000d000d000d000e000d0010000d000d000d00 -0d000f000f000d000d000f000f000d000f000d000d000d000d0010000c000e000d000d00 -0f000e000d000e000d000d000f000e000d000d000d0010000d000d000d000e000e000e00 -0e000e000d000d000e000e000e0009000e000e000e000d000e000d000e000d000d000d00 -10000d000e000d000e000d000e000d000e000d000e0011000e000d000e000e000d000c00 -0f000e000d000d000d000e000d000d000e000d000f000d000e000d000d000f000e000d00 -0d000e000f000d000d000e000d000e000e000e000d000d000e000d000d000d000e000d00 -0e000e000e0009000e000e000d000e000d000e000d000e000d000e0010000d000d000d00 -0e000d000d000e000f000d000d000d000e000d000d000b000f0010000d0011000d000d00 -0e000d000d0011000f000d000d000d000d000e000d000d0011000d000d000d000d000f00 -0d000c000e000d000d000e000e000e000d000e000d000e000e000e0009000d000e000d00 -0e000d000e000d000e000e000e0010000e000e000d000e000d000d000f000f000d000d00 -0d000d000d0011000b000f0011000d000f000d000f000d000d0010000d000d0011000d00 -0d000e0011000d000d000d000d000d000d000e000e000d000e000d000e000d000d000e00 -0d000e000d000e000d000e000d0009000d000d000e000d000e000d000e000d000e000d00 -10000e000d000d000e000d000e000e000e000e000f000f000d000d000d000e000d000e00 -0e000d000f000f000c000e000e000e000f000c000e000e000e000d000e000e000d000900 -0d0011000e000e000d000e000d000d000d000d0000000d0012000d001300000000001000 -0d0012000d0000000d000e000e000e000e000e000d000e000e000d0010000e000d000e00 -0d000e000d000e000b000e000e000d000e000d000d000e000e000d000d000e000d000d00 -0e000d000d000d000d000e000e000d000d000d000f000d000d0011000b0010000d001100 -0d000d000d000d000d000e000d0011000e000e000d000e000b000e000d000e000f000e00 -0d000d000e000d000e000d000d000d000d000d000d000d000d000e000d000d000d000d00 -0d0011000e000d000d000d000e000d000e000d000d000e000e000d000e000d000e000d00 -0d000e0009000e000d000e000d000e000d000e000e000e000d0010000d000d000d000d00 -0d000d000d000d000e000d000d000d000e000d000e000e000d000f000d000d000d000e00 -0d000d000d000e000d000e000e000d000d000f000b000e000e000e000e000d000e000d00 -0d000e000e000e000e000d0009000e000d000e000d000e000d000e000d000e000e001000 -0d000e000e000d000e000d000e000d000e000d000d000d000e000b000d0011000d000d00 -0e000d000f000d000d000f0011000d000d000e000d0011000d000d000d000d000e001100 -0e000b0011000d000d000e000e000e000d000e000e000d000e000e000e000e000d000e00 -0e000d0009000e000d000e000d000e000d000e000d000e000e0010000f000d000d000d00 -0e000d000d000d000d000d0011000d000d000d000f000d000d000d000d000d000d000d00 -0f000b000d000d000d000d000e000d000d000d000d000f000d000d000e000e000c001000 -0e000e000f000e000c000e000e000d000e000d000e000e000e0009000e000d000e000d00 -0e000d000e000d000e000d0010000e000d000d000e000d000d000d000d000d000d001100 -0d000d000d000f000d000c000d000e000d000d000d000d000c0010000d000b000d000f00 -0d000d000e00110011000d000e000d000f000b000f000d000b000e000d000f000d000e00 -0d000e000d000e000d000e0009000d000d000d000d000e000d000d000d000e000e001000 -0e000d000d000e000d000d000d000d000d000d000d000d000e000f000d000f000f000d00 -0d000d000e000d000f000c000e000e000e000d000e000e000d000e000e000d0009000e00 -0e000e000e000d000d000e000d000d00110000000d000d00120004000000000010000d00 -0d000d0000000d000e000d000e000e000e000d000e000d000e0010000e000d000e000d00 -0d000d000d000e000d000d000d000f000e000e000d000d000e000e000d000d000d000e00 -0d000e0010000d000d000f000f000d000d000b000f000d000d000f000c000d000d000e00 -0d000d000e000d000d000e000b000d000f000f000d000d000d000d000d000d000d000d00 -0d000e0010000d000e0011000b000f000d000d000f000d000d000e000d000e000d000f00 -0d000d000d000d000f000d000d000e000e000e000d000d000e000d000e000d000e000e00 -0d0009000d000e000d000d000e000d000e000e000e000e0010000d000d000d0011000f00 -0e000f000e000d000d000e000d000d000d000e000e000b000d000f000d000f000d000d00 -0f000d000d000e000b000d000e000f000d000d000d000d000d000e000e000e000e000e00 -0e000d000e000e000e0009000e000d000e000d000e000d000e000d000d000e0010000d00 -0e000d000e000d000e000d000e000d000e000d000e000f000f000d000d000d000d000d00 -11000d000d0011000d000c000d000e000d0011000b0011000e000d000d000d000e000e00 -0e000e000e000d0011000d000d000e000e000e000e000d000e000e000e000d000e000e00 -0e0009000e000e000d000e000d000e000d000e000d000e0010000e000d000d000e000e00 -0d000e000e0011000e000d000d000d000d000d000e000d000d000d000d0010000d000d00 -0f000f000d000d0011000b0011000d000e000d000d0011000d000d000d000e000e000c00 -0f000f000c000f000e000e000d000e000e000e000d000e0009000d000e000d000e000d00 -0e000d000e000e000d0010000d000e000d000e000d0010000d000d000d000e000d000e00 -11000d000d000e000d000f000d000e000d000e000e000d000d000d000d000d000d000f00 -0d000e000b000d000f000d000d000e000d000e000f000e000d000e000d000e000d000e00 -0d000e000d000e000d0009000d000d000e000d000e000d000e000d000f000e0010000e00 -0d000d000e000f000d000e000d000d000d000d000f000d000e000e000b000d000e000e00 -0e000e000f000e000e000e000e000f000e000e000e000d000e000e000e0009000d000e00 -0d000d000e000d000d000d000d000d00000012000d000d00040000000000100012000d00 -0d0000000d000e000e000e000e000d000e000e000e000d0010000e000d000f000d000d00 -0d000e000e000f000e000f000e000d000e000d000e000d0000000d000e0000000b000f00 -0d000d000d000f000d000c000e0011000e000e0000000d000d000e000d000d000d000d00 -0d000d000d0012000f000d000e000d000e000d000e000f000d000f000f000d000e000e00 -0d000c000e000d000d000e000d0011000d000d000d000d000d0010000b00110011000c00 -0d000e000d000e0000000d000d000f000d000d000e000d000e000d000e000d000e000e00 -09000e000e000e000d000e000d000d000d000d000d0010000e000e000d000d000d000d00 -0d000e000d000f000d000d0000000e0000000d000f000d000d000e000d000d000d000e00 -0d000d000f000e000d000d000d000d000e000f000e000e000e000e000d000e000d000d00 -0e000e000e000d0009000e000d000e000d000e000d000e000d000e000d0010000e000f00 -0e000d000e000d000e000d000e000e0000000f000c000e000d000e000d0011000d000d00 -0e000d000d000e00000011000d0000000d000e000d000d000f000d0011000d000d000d00 -0d000d000d000d000e000e000e000d000e000e000e000d000e000e000d000e000d000d00 -09000e000d000e000d000e000d000e000d000e000e0010000e000d000d000d000d000d00 -0d000d000d0000000000000000000000000000000e00000000000000000000000d000d00 -0d00000011000d0011000d0000000d0011000000000000000000000001000c000f000c00 -0d000e000f000c000e000d000e000d000d000e000d0009000e000d000e000d000d000e00 -0e000d000e000d0010000e000e000d000e000d000b000d000d000d000000000000000000 -0000000000000e00000000000000000000000d000d000b0000000e000d0011000d000000 -0d000f000000000000000000000001000d000e000d000e000d000e000d000e000d000e00 -0d000e000e000d0009000e000d000e000d000e000d000d000d000e000d0010000e000d00 -0d000e000d000d000d000d000f000f0010000b000000000000000e000f0000000e000d00 -0e000e000b000f000d000e000d000e000e000e000d000e000d000e0009000e000d000e00 -0e000d000d000d0011000d000d0000000d000d000d0004000000000010000d000d000d00 -00000d000e000e000d000e000d000e000d000d000d0010000f000d000e000d000e000d00 -0d000d000d000e000d000b000f000d000d000f000d0000000d000f0000000d000e000e00 -0f000d000d000e000d000d000d000d000d0000000d000d000d000d0011000d0011000d00 -0d0011000d000d000d000d000d000f000d000d000d000d000d000e000d000d000d000e00 -0f000d000e000d000d000d000d000f000d0011000d000d000b000f0011000b0011000d00 -0d000e000d0000000d000e000d000d000f000d000e000d000e000d000e000d000e000900 -0e000e000d000d000e000d000e000d000e000d00100011000d000d000d000f000f000e00 -0e000d000d000e0000000d000f0000000e000e000d000d000d000d000e000d000d000f00 -0d000d000d000d000d000f000e000d000d000d000d000d000d000e000e000e000e000e00 -0d000e000d0009000e000d000e000d000e000d000f000d000e000d0010000d000e000d00 -0e000d000e000d000e000d000d0000000e000d000d0011000d000d000d000d000e000d00 -11000c000f0000000d000d0000000d000e000d000d000d000d000d000d000e000d000d00 -11000d000d000e000d000e000e000d000e000e000e000e000e000d000e000d000d000900 -0e000e000d000e000d000e000d000e000d000e0010000d000d000e000e000e000d000d00 -0d000d000d001100120000000e0011000d000e0000000d000d000d000e0000000d000d00 -00000d000e000d000d0000000d000e0000000b000d000d000d000d000e000e000f000e00 -0c000f000d000e000d000e000d000e000e000e0009000d000e000d000e000e000e000d00 -0e000e000d0010000d000d000d000e000d000f000d0011000d000d000d000e0000000d00 -0d0011000e0000000e000d000d000d0000001100110000000d000d000d000d0000000d00 -120000000d0011000d000d000d000d000e000d000d000f000d000d000e000e000d000e00 -0d000d000e0009000d000e000d000d000e000d000e000d000e000d0010000e000d000d00 -0e000d000f000e000d000d000d000b0001000d000f000d0000000d000e0000000d000d00 -0d000f000e000d000e000c000d000e000e000d000d000e000d0009000d000d000e000d00 -0e000d000d000d000d000d00000012000d00120004000000000010000d0012000d000000 -0d000d000d000d000e000e000d000d000e000e0010000d000d000e000d000d000d000d00 -0f000d000d000e00000000000d0000000d000000000000000d0000000e000d0000000b00 -0f000d000e000e0011000d000d00110000000d00000000000d000d0011000d0000000000 -000011000d0000000f000d000d000f0000000d000f000d000d000d000f000d000d000000 -0f000000000011000d000d00110000000000000010000d000d000e000000000000000d00 -0d000d00000010000d0000000f000d000e000d000e000d000e000d000d000e0009000e00 -0e000e000d000e000d000e000d000e000d0010000d000d000d000d000d000d000d000d00 -0f000e000d0000000f000d0000000e00000000000d000d000f000d000100000000000f00 -0d0000000e000d000d000f0000000d0011000d000e000e000e000d000d000e000d000e00 -0e000d0009000e000d000e000d000e000d000d000d000e000e0010000d000e000e000d00 -0e000d000e000d000e000d0000000d00000000000d000d000d0000000d0012000d000000 -0d0000000000000000000000000011000d000000000000000d000e00120000000d000000 -00000d000e000d000e000d000e000e000d000e000e000e000d000e000e000e0007000e00 -0d000e000d000e000d000e000d000e000e0010000d000d000d000e000d000d000d000e00 -0d000d000d000f0000000d000d000d000d0000000e0011000d00110000000d0011000000 -0d000d000d000d0000000d000d0000000d0011000e000d000e000e000d000d000e000e00 -0d000f000e000e000e000d000e000d000e0009000e000d000e000e000d000e000e000d00 -0e000e0010000e000e000d000d000d000d000d000e000d0011000d000f0000000d001100 -0d000d0000000e000d0011000e0000000d000d0000000d000d000d000d0000000e000d00 -00000d000d000d000f000d000e000d000d000f000d000d000e000d000e000d000d000e00 -0e000d0009000d000d000e000d000e000d000d000d000e000e0010000e000d000d000e00 -0d000e000d000d000e000e000e0000000d000f000e0000000d000f0000000f000e000f00 -0c000e000e000e000f000d000d000e000d000d000e000e0009000e000d000e000d000d00 -11000d000d000d000d0000000d000d000d0004000000000010000d000d00120000000d00 -11000e000e000e000d000e000e000e000d0010000d000d000e000d000d000d000d000d00 -0e000d0000000e000d00000000000e000d0000000d000e0000000d0000000d000f000d00 -0d000e000d000e000d000e000d00000000000d000d0000000d000d0000000d000d000e00 -000011000d0000000d000e0000000f000e000d000e000d000e000d000d000d0000000000 -0d000e0000000d000d0000000e000d000d0000000d000d0000000d000d000e0000000d00 -0d0000000d0000000e000d000e000d000e000d000e000e000d000e000e0009000e000d00 -0e000d000e000d000e000e000d000d0010000e000e000d000d000d000d000e000e000d00 -0d0000000d000d000e00000000000d000d0000000d000d0000000d000d000f0000000f00 -0d0000000d000f0000000e000e000d000e000d000e000e000d000e000e000d000e000e00 -0e0009000e000e000e000d000e000d000e000d000e000e0010000d000e000d000e000d00 -0e000d000e000d000e00000000000d000d00000011000d0000000d000d000e0000000d00 -110000000e000d00000011000d00000011000d000d0000000d001100000000000e000d00 -00000e000d000e000e000e000d000e000e000e000e000d000e000e000d0009000e000e00 -0d000e000d000e000d000e000e000f0010000d000d000d000e000e000d000f000d001100 -0d000d000d0000000d000d000e00110000000e000d000d000d0000000d000d0000000d00 -0d0011000d0000000d000d0000000d000d000d000d000e000d000e000e000d000e000e00 -0d000e000d000e000d000d000e000e0009000d000e000d000d000e000d000d000e000e00 -0e0010000e000d000d000e000d000d0011000c0011000d000d000d0000000d000d000d00 -110000000d000d000d000d0000000d000f0000000d0011000d000d0000000d000d000000 -11000d000e000d000f000d000e000d000d000d000d000d000e000d000d000e000d000d00 -0e0009000d000d000d000d000e000d000e000e000e000d0010000e000d000d000e000d00 -0e000d000e000e000d000f0000000e000d000d0001000d000e000e0000000e000c000100 -0f000d000e000e000d000e000e000d000e000e000e0009000e000e000d000d000d000d00 -0d000d000d000d0000000d0012000d0013000000000010000d000d000d0000000e000e00 -0d000e000e000e000d000e000d000e0010000d000d000e000d000d000d000d000d000d00 -0e0000000d000d000d0000000e000d0000000e001100000000000d000d000d000d000d00 -0d000d000e000d000d000d0000000d0011000d0000000d00110000000d0011000d000000 -11000d000d00000000000d000e000e000d000d000d0011000d000d00110000000e000d00 -0e0000000d0011000d000d000d00110000000d000d0000000d000d000d000d000e000d00 -000000000d000e000d000d000d000d000d000d000d000e000d000e0009000e000e000e00 -0d000e000d000e000e000e000e0010000e000d000d000d000d000d000e000e000d000f00 -00000f000e000d0000000d000e000d0000000d00110000000d000f000d00000011000d00 -0d000000000011000d000d000d000d000e000e000e000d000d000e000e000e000e000d00 -09000e000e000e000e000e000d000e000d000e000d0010000e000e000e000d000e000d00 -0e000d000e000d0000000d000d000e0000000d000d0000000d000e000d0000000e000d00 -000011000d0000000e000d0000000d000d000d0000000d000d0000000d000d000e000000 -0e000e000f000e000e000f000c000e000d000e000d000e000e000e0009000d000d000e00 -0d000e000d000e000d000e000d0010000d000d000d000e000d000d000d000d000e000d00 -0d001000000011000d000d000e00000000000000000000000d0011000d0000000d000d00 -0d000d0000000d000d0000000000000000000000000010000d000d000d000d000d000e00 -0e000d000e000e000e000e000e0009000e000e000e000d000d000e000d000e000e000d00 -10000e000e000d000e000d000d000e000d000d000e000d000d0000000d000d000d000d00 -000000000000000000000d000d000d0000000f000d000d000d0000000d000d0000000000 -00000000000000000d000d000f000d000e000e000e000e000d000e000e000e000e000e00 -09000e000e000e000d000e000d000e000e000e000d0010000e000e000d000e000d000f00 -0d000d000d000d000e0000000d000d000f0000000d000d000e0000000e000f000d000e00 -0e000e000e000e000e000e000d000e000e000e0007000e000d000e000e000d000e000d00 -0d000d000d0000000d000d000d000400000000001000120012000d0000000d000d000e00 -0e000e000e000e000d000e000d0010000e000d000e000d0011000d000d0011000d000d00 -00000d000d00110000000d000d0000000d000d00000001000d000d000d000d0011000d00 -0d000b000d000d000d00000011000b000d0001000d000d0000000e000b000d0000000d00 -0e000e00000000000d000b000d0011000d000b0011000d000d000d0000000d000e000d00 -00000d000e000e0000000000000000000f000d0000000d000d0011000b000d000f000000 -00000d000e000d000d000d000d000d000d000d000d000d000d0009000d000e000d000d00 -0e000d000e000e000e000e0010000e000e000e000d000d000e000d000d000e000d000000 -0d000d000e00000011000d000d0000000e000d00000011000c000d0000000d000e000d00 -000000000d000e000d000d000d000d000e000e000e000e000e000e000d000e000d000900 -0e000e000e000d000e000d000e000d000d000e0010000d000e000d000e000d000e000d00 -0e000d000e0000000d0011000d0000000e000d00000011000d000d0000000b0011000000 -0b000f0000000d000d0000000d000d000d00000011000d0000000d001100120000000c00 -0f000c000e000e000d000e000f000d000e000d000e000e000e0009000e000e000d000e00 -0d000e000d000e000d000e0010000d000d000d000e000d000d000e000d000e000d000d00 -0c0000000b000e000d00110000000e000d000f0000000d000d000e00000011000d000d00 -0d0000000d000d0000000d000d000d000d000e000c000d000d000f000d000d000d000e00 -0d000e000e000e000e000e0009000e000e000d000e000e000d000e000d000e000d001000 -0e000e000d000d000d000d000d000d000d000d000d000d0000000c0010000d000e000000 -11000d000d0000000d0011000e00000011000d0011000d0000000d000d0000000d000e00 -0f000d000d000d000e000e000d000e000d000e000d000e000e000e000d000e000d000900 -0e000e000e000d000e000d000e000d000e000e0010000e000d000d000e000e000d000d00 -0f000d000d000d00000011000d000e0000000e000d000e0000000e000d000e000e000e00 -0e000e000c000e000e000d000e000e000d0009000e000d000d000d000e000d000e000d00 -0d000d00000012000d001200040000000000100012000d000d0000000d000e000d000e00 -0e000e000d000e000d000d0010000d000d0011000d000d000d000d000d0011000d000000 -11000d000d0000000d000d0000000d000b0000000d0000000b00110012000d0011001100 -0e000d0011000d0000000d000d000d0000000d000d0000000d0011000d0000000d000d00 -00000d000d0000000d0011000b000d000f000d000d000d000e0000000d000d0011000000 -0d000d0000000d000d000d0000000d000d0000000e000d000d0011000d000e0000000d00 -01000d000d000d000e000d000d000d000d000e000e000d0009000e000e000e000d000e00 -0d000e000e000e000d0010000e000d000e000e000e000d000d000d000f00100000000f00 -0e000d0000000e000f000d0000000e000d0000000d0011000d0000000d000d0000000e00 -0d0000000d000d000d000f000d000e000e000e000d000e000d000e000e000d0007000e00 -0e000e000d000e000d000e000d000e000d0010000e000e000d000e000e000e000e000d00 -0e000d0000000d000d000d0000000d000d0000000d000d000e0000000e000d0000001000 -0e0000000d00110000000d0011000d0000000d000d00000011000d000c0001000e000d00 -0e000f000e000e000e000d000e000e000d000e000e000d0009000e000d000e000d000e00 -0d000e000d000e000e0010000f000d000d000e000e000d000d000d000d000e000d000d00 -01000e000d000f000c0000000e000d000e000d0000000d000d0000000d00120011000e00 -00000d000d0000000d0011000e000d000f000d000d000e000c000f000c000f000e000d00 -0e000d000e000e000e0007000e000e000e000d000e000e000d000d000e000d0010000d00 -0e000d000f000d000d0011000d000e000e000e000e00000011000b000f000e0000000d00 -0e000d000b0000000d000d0000000d000d000e000d0000000d000d0000000d000d000d00 -0e000f000d000e000e000e000e000e000e000e000e000e000d000e000e000e0009000e00 -0e000e000d000e000d000e000e000e000d0010000e000e000d000e000f000d000d000d00 -0d0011000f0000000d000e000d0000000d000e000d0000000e000d000f000d000d000e00 -0e000f000e000e000d000e000e000e0009000e000e000e000e000e000d000d000d000d00 -0d0000000d000d000d0004000000000010000d000d000d0000000d000d000e000d000e00 -0e000d000d000d000e0010000d000d000d000d000d000d000d000d000d000d0000000d00 -0e000000000011000d0000000d00110000000d000d0000000d000d000d000d000d000d00 -0d000d000e000000000011000d00000011000e0000000d000d000d0000000f0000000e00 -0e000d000d000000110011000d000d000d000d000d000d000000000011000d0000000d00 -110000000e000d00110000000d00110000000d000d00110000000d000e0000000f000d00 -00000d000d000d0011000d000d000d000e000d000e0009000e000e000e000e000e000d00 -0e000d000e000d0010000e000e000e000e000d000e000e000f000a000d0000000d000d00 -0d00000000000b000f00000011000e0000000d000d000d0000000f0000000d000d000f00 -1100000011000d000d000e000e000e000e000e000e000e000e000e000d0007000e000d00 -0e000d000e000d000e000d000d000d0010000e000e000e000d000e000d000d000e000d00 -0e00000000000d000e0000000d000e0000000d001100000000000d000d0000000d000d00 -000011000d0000000d000d000d0000000d000d0000000d000f000d0000000e000e000c00 -0e000e000d000e000f000e000e000d000e000e000e0009000e000e000d000e000d000e00 -0d000e000d000e0010000e000d000d000e000e000d000d000d000d000d000d000d000000 -0d000e000d000f0000000d000f000d000e0000000d000d0000000d000f000b000d000000 -0d000f0000000d000d000d000f000d000d000e000d000f000e000e000d000e000e000e00 -0d000d000e000e0007000e000e000d000e000d000e000e000e000f000e0010000d000e00 -0d000e000d000b000d000d000d000d000f000e0000000e000d000e000d0000000d000e00 -0e00110000000d000e0000000f000f000d000d00000012000d0000000d000d000f000d00 -0c000f000d000d000d000f000d000e000d000e000d000e000e000e000d0007000e000d00 -0e000d000e000d000e000e000e000d0010000e000e000d000e000d000d000e000d000d00 -0d000b0000000d000d000d0000000e000d000f0000000f000d000e000c000f000f000c00 -0e000e000e000d000e000e000e0009000e000e000e000d000d000e000d000d000d000d00 -000012000d000d0013000000000010000d000d000d0000000d000d000d000e000e000d00 -0e000d000e000d0010000e000d000e000d000e000d000d000d000d000f000e0000000000 -0e0000000d000d00000000000d0000000f000e000d00000010000e000e000d000d000f00 -0d000d0000000d00000000000d000d000e000d000000000000000d000d0000000d000e00 -0d000d0000000d000d000d000d000d000d000e000e0000000d00000000000d000f000d00 -0c000000000000000e0000000d000e000000000000000e000e000d0000000e000d000f00 -00000e000d000e000e000d000d000e000e000d0009000e000e000e000d000e000d000e00 -0d000e000d0010000e000d000e000e000e000d000d000d000f000d0000000e000f000e00 -00000d00000000000d000d0011000d000000000000000d000d0000000d000d000d000d00 -00000b00110000000d000e000d000e000e000d000d000e000e000e0009000e000d000e00 -0d000e000d000e000d000e000e0010000d000d000d000e000e000d000e000d000e000d00 -00000d000000000011000e000e000e00000000000d0000000e000d00000000000d000000 -00000d000d000000000000000d0011000d0000000d000d000e0000000e000e000e000000 -0e000f000c000c000e000e000d000e000e000d0009000e000d000e000d000e000d000e00 -0d000e000e0010000e000d000d000e000d000d000d000e000e000d000d000d0001000d00 -0d000e000d0000000e000f000d000d0000000d000d00110000000000000000000d001100 -0d000000000000000000000001000d000e000d0000000d000d000e000e000d000e000d00 -0e000e000e0009000e000e000d000d000e000d000d000e000e000d0010000e000d000d00 -0e000d000f000f000d000d000d000d000b0001000d000f000d000d0001000d000d000d00 -0d0000000d000f000f0000000000000000000e0011000d00000000000000000000000000 -0e000d000f0000000c000e000d000e000d000e000e000e000d000e0009000e000e000e00 -0d000e000d000e000e000e000d0010000e000e000d000e000e000d000d000d000e000d00 -10000d000000000000000d000f000d000f0000000c000e0000000f000d000d000f000e00 -0e000e000d000e000d000d0009000e000e000e000d000e000d000d000d000d000d000000 -0d000d001200040000000000100012000d000d0000000d000d000e000d000e000e000d00 -0d000d000e0010000e000d0011000d000d000d000e000f000d000d000f000d000f000d00 -00000e000d000d000d000f000d000d000d000f000d000c000d000d000d000d000d001100 -0d000e000e000d0011000b00100011000d000d000e000d000f000e000d000e0011000d00 -0d000d000d000d000d000e000d0011000d000b0000000f000d000d000d000d000e001100 -0e000d000f000d0011000e000f000d000d000d000d000d000f000d000d000f000d000d00 -0e000e000d000d000d000e000d000d000d0009000e000e000d000d000e000d000e000d00 -0e000e0010000e000e000e000e000d000e000d000d000f000e000d0000000d000d000d00 -0d000e000e000f000e000e000d000d000d000d000e000f000e000d000d000e000d000d00 -11000d0000000d000e000e000e000d000e000e000e000e000e0009000e000d000e000d00 -0e000d000e000d000d000e0010000d000e000d000e000d000e000d000e000d000e000d00 -11000e000b0011000e000d000d000d000d000d000d000c000f000e000d000d000e000d00 -0d0011000d000e000c000d000d000d000d000e000d000d000d000e000f000d0001000d00 -0e000e000f000d000e000d000e000e000e0009000e000e000d000e000d000e000d000e00 -0d000e0010000d000d000d000e000d000d000d000e000f000d000e000e000b000f000e00 -0d000f000e000d000d000f000f000d000d000d000e000d000d000d000d000d000d001100 -0c0011000e000d000f000d000e000d000d00000010000d000f000e000d000e000e000e00 -0e000e0009000e000d000e000e000d000e000e000d000e000d0010000e000e000d000e00 -0d000d000d000d000f000d000d0010000c000d000c000d000f000d000d000e000e000d00 -11000d000c000d000f000d000e000f000d000d000e000d000f000d0011000c0010000d00 -0e000e0000000f000e000e000e000e000e000e000d000e000d0009000e000e000e000d00 -0e000d000e000e000e000e0010000e000e000d000e000d000e000e000d000f000d000d00 -0d000d000d000d000f000e000f0000000f000f000d0001000e000f000c000c000f000e00 -0e000d000e000e000d0007000e000e000d000d000d000d000d0011000d000d0000001200 -0d000d0004000000000010000d0012000d0000000e000e000e000d000e000d000d000e00 -0d000e0010000e000d000e000d000d000d000d000d000e000c0000000d000d0011000000 -0d000d000d000d000d000d000e000f000d00110000000000000000000000000000000d00 -11000d000e000d000e000d000d000e000f000e000f000e000b000e000d000d000d000d00 -0e0000000000000000000000000000000e0000000d000f000d0011000d000e000d000d00 -0c000f0011000d000d000d000d000d000f000e000f000c000e000d000c0010000e000e00 -0d000d000d000e000d000d000d000e0009000e000e000d000d000e000d000e000e000e00 -0e0010000e000d000d000e000f000d000e000d000d000e000d0000000d000f000f000d00 -0e000e000b000e000d000d000f000e000e000e000b000e000d000d000d000e000f000b00 -00000e000e000e000d000d000e000e000d000d000e000d0007000e000e000e000d000e00 -0d000e000d000e000d0010000d000d000e000d000e000d000e000d000e000d000e000e00 -0e000e000f000d0011000d000e000d000e000d0010000d000d000d0011000d000d000e00 -0d000d000f000f000f000d000d000d000e000e000d000d000f000c0000000d000e000e00 -0e000c000e000e000d000e000e000e0009000e000d000e000d000e000d000e000d000e00 -0e0010000d000d000d000e000e000d000d000d000f000d000d000c000f000d000e000e00 -0d000d000f000d000e000b0011000e000d000d000d000d000e000d000e000c000d000f00 -0d000d000d000d000d000d000d0000000e000e000b000d000e000d000e000d000e000e00 -0e0009000e000d000e000d000e000d000d000e000e000d0010000d000d000d000e000d00 -0f000d000d000e000d000d000d000e000e000e000d000d000e000d000d000d000d000d00 -0f000d000e000f000c000e000d000d0010000b000e000e000e000d000f000d000e000e00 -00000d000f000d000d000e000d000e000d000e000d000e0009000e000e000e000d000e00 -0d000e000d000e000d0010000e000e000d000e000d000f000e000d000d000f000e000d00 -0d000e000e000d000e000d0000000e000e0000000e000c000e000e000f000e000d000e00 -0d000e000e000e0009000e000e000e000e000d000d000d000d000d000d0000000d001200 -120004000000000010000d000d000d0000000e000d000e000e000e000e000e000d000e00 -0d0010000e000d000e000d000d000d000d000d000d0011000d000000000000000f000d00 -0d000d000d000d000d000e000d000e000d000e000e000d0011000d000d000d000f000d00 -0e000d000d000e000e000d000e000d000d000f000d000f000d000d0011000d000d000d00 -0d000d000d000d000d000d000e000d0000000d000d000d000d000e000d000d000f000e00 -0d000d000d0011000d000e000d000d000e000c000f000d000f000e000e000c000e000d00 -0e000e000d000d000e000e000d0009000e000d000e000d000e000d000e000e000e000e00 -10000e000d000d000e000d000d000d000f000d000d000f000d0000000d000e000e000e00 -0e000f000d000e000e000d000d000e000d000f000d000d000d0011000d000d000f000d00 -0d000e000d000e000e000e000d000e000e000e000e0007000e000e000e000d000e000d00 -0e000d000f000e0010000d000d000d000e000d000e000d000e000d000e000d000d000e00 -0d000d000e000d000d000d000e000d000d000e000d000d000d000d000d000d000d000d00 -0f000d000d000d000d000e000d000d000f000d000e000e000e000e000e000d000e000e00 -0e000e000e000d000e000e000e0009000e000e000d000e000d000e000d000e000d000f00 -10000d000d000d000e000e000d000e000d000e000d000f000e000d000d000d000e000f00 -0d000d000d000d000f000d000d000e000d000d000e000d000d000d000f000d000d000e00 -0f000d000e000e000d000d000e000d000e000e000e000e000d000e000d000e000e000e00 -09000e000d000d000e000d000d000e000d000e000e0010000d000e000d000e000d000d00 -0d000e000d000d000f000d000d000d000d0011000d000e000d000e000d000e000d000d00 -0f000d000d000e000d000e000e000d0011000d000d000d000e000e000e000e000e000e00 -0f000d000e000e000d000e000e000e000e000e000d0007000d000e000e000e000e000e00 -0e000e000e000d0010000e000e000d000e000e000d000d000d000d000e000d000d000d00 -0e000d000e000e0000000e000e000e000f000d000d000e000e000e000e000e000e000d00 -0e000e000e0009000e000d000e000d000d0011000d000d000d00110000000d000d000d00 -040000000000100012000d000d00000011000e000e000d000e000d000d000e000e000d00 -10000f000d000d000e000e000e000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000e000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000e000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000e000d000d000e000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000e000e000e000d000d000d000d000e000d000d00 -0e000e000d000e000e000e0009000e000d000d000e000d000e000e000e000e000d001000 -0d000e000d000e000e000d000e000d000d000e000e000e000d000d000d000d000e000d00 -0d000e000e000d000d000d000e000d000d000d000d000d000e000d000d000d000d000d00 -0d000d000d000e000d000e000e000e000e000d0009000e000e000e000e000e000d000e00 -0d000e000d0010000d000e000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000e000e000e000e000e000d000e000d00 -0e000e000c000e000e000e0009000d000d000d000e000d000d000e000e000d000d001000 -0d000d000f000d000d000d000e000e000d000e000d000e000e000d000e000d000e000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000e000e000d00 -0d000d000d000d000d000d000d000d000d000d000d000f000d000d000d000e000e000900 -0e000d000d000e000d000e000d000e000f000d0010000d000d000f000d000e000e000e00 -0e000e000d000e000e000e000d000d000d000d000d000d000e000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000e000d000e000e000e000d000e000d000e000e00 -0e000e000d000d000e000d000e000d000d000e0009000e000d000d000f000d000e000e00 -0f000e000e0010000d000e000d000f000d000d000d000d000e000d000d000e000e000e00 -0e000d000e000d000d000d000d000e000d000e000d000e000e000e000e000e000d000e00 -0d000e0009000d000d000d000e000d000d000e000d000d000d0000000d0012000d000400 -0000000010000d000d00120000000d000e000e000e000e000e000e000d000d000e001000 -0e000d000d000d000d000d000d000d000d000e000d000e000d000e000e000e000e000e00 -0e000e000e000d000e000e000e000e000e000e000e000e000e000d000d000d000d000e00 -0e000d000e000e000e000e000e000e000e000e000d000e000d000e000d000e000d000e00 -0e000e000e000e000e000e000e000e000d000e000e000e000e000e000e000e000e000d00 -0d000d000d000e000d000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e0009000e000e000e000e000d000e000d000d000d000e0010000e00 -0f000d000d000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000d000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000f000d0009000d000d000e000e000e000d000d000e00 -0e000e0010000d000d000e000e000e000d000e000e000e000d000d000d000e000e000e00 -0e000e000e000e000d000e000e000e000e000e000e000d000e000e000d000e000e000e00 -0e000e000d000e000e000e000e000e000e000e000e000e000e000e000e000e000e000d00 -0e000e000f000f000e0009000d000e000e000d000e000e000d000d000e000f0010000d00 -0d000f000d000e000d000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000d000e000d000e000e000e000e000e000e000e000e000e00 -0d000d000d000d000d000e000d000d000e000d000f000d000f000e000d000e0007000e00 -0d000e000d000d000e000e000d000d000d0010000f000d000e000d000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000d000e000e000e000e00 -0e000e000e000e000e000e000d000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e0009000e000e000e000e000d000e000d000c00 -0d000e0010000e000e000d000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000d000e000e000f000e00 -0e0009000d0011000e000d000e000e000d000d000d00110000000d0012000d0013000000 -000010000d0012000d0000000d0011000e000d000e000d000d000d000e000d0010000f00 -0e000e000e000e000e000e000d000d000d000d000d000d000d000d000d000d000e000e00 -0d000d000d000d000d000d000d000d000d000d000e000e000d000d000d000d000d000d00 -0d000d000d000d000d000e000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000e000e000d000d000d000d000d000d000e000d000d000d000e000e000d000d00 -0d000d000d000d000d000d000e000e000e000e000e000e000e000e000d000d000e000e00 -0e000d000e000e0009000d000d000e000e000d000e000e000f000e000f0010000d000e00 -0e000e000d000d000e000e000e000d000e000e000e000d000d000e000d000e000d000d00 -0d000d000d000d000d000e000d000d000d000d000d000d000d000d000e000e000d000d00 -0e000d000d000d000e000e000d000c000a000e000e000e000e000d000d000d000e000d00 -0f0010000e000e000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0e000e000d000d000d000d000e000d000d000d000d000d000d000d000d000d000e000e00 -0d000d000d000d000e000d000d000d000e000e000e000e000e000e000e000d000e000e00 -0d000e000c000c000a000e000d000e000e000d000d000e000e000d000f0010000d000d00 -0d000d000d000d000e000e000e000e000d000e000e000e000d000d000e000e000e000e00 -0e000e000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000e000d000f000e000d000d000a000e000d00 -0d000e000e000d000e000d000d000d0010000f000e000e000d000d000d000d000e000e00 -0e000e000e000e000d000e000d000e000d000d000e000d000e000e000e000e000d000e00 -0d000d000d000e000d000d000d000d000e000e000d000e000d000d000d000d000e000e00 -0e000e000e000e000d000d000d000d0007000d000e000e000e000d000e000e000f000f00 -0f0010000d000d000e000e000e000e000d000e000d000e000d000d000e000e000e000e00 -0e000e000e000d000e000d000e000d000d000e000e000e000d000e000e000e000c000c00 -0a000e000e000e000d000e000d000e000d000d000d0000000d000d001200040000000000 -10000d000d000d0000000d000d000e000d000e000e000e000e000e000e00090009000900 -090009000900090009000900090009000900090009000900090009000900090009000900 -090009000900090009000900090009000900090009000900090009000900090009000900 -090009000900090009000900090009000900090009000900090009000900090009000900 -090009000900090009000900090009000900090009000900090009000900090009000900 -090009000900090009000900090007000700070009000900090009000700090009000900 -0700070007000a000d000d000d000e000e000e000e000f000e000c000a00090009000900 -090009000700090009000900090007000700090009000900090009000900090009000900 -090009000900090009000900090009000900090009000900090009000700090007000900 -090009000900070007000700090009000d000e000e000e000e000f000d000e000d000d00 -0a0009000900090009000900090009000900090009000900090009000900090009000900 -090009000900090009000900090009000900090009000900090009000900090009000900 -090009000900090009000900090007000900090009000900090009000800090009000800 -090009000a0009000e000e000d000d000d000e000d000d000e000b000a0009000a000900 -090009000900090009000700070007000900090009000900090009000900090007000900 -090009000900090009000900090009000900090009000900090009000900090009000900 -0900090009000900090009000900090009000900090009000800090007000e000d000e00 -0d000d000e000d000d000f000d000a000900090009000900090009000800090009000900 -070007000700090009000900090009000900090009000900090008000900090009000900 -090009000900090009000900090009000700090007000900090009000900090007000700 -07000900090007000900090009000a000d000e000e000e000d000e000e000f000d000c00 -0a0009000800090009000900090009000900090009000900090009000900070007000700 -09000900090009000900090009000900070009000700070009000800090009000a000900 -0d000d000d000e000e000d000d000d000d000d00000012000d000d000400000000001000 -0d000d000d0000000d000d000e000e000d000e000e000d000d000e000e000d000e000e00 -0d000d000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000d000e000e000e000e000e000e000d000d000d000e000e000d000e000f000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000d000f000e000d000d000e000e000d000f000d000f000d00 -0d000d000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000f000e000e00 -0d000d000c000e000d000d000e000d000d000e000d000d000f000d000d000d000d000d00 -0e000d000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0d000e000e000e000e000e000f000e000d000e000e000e000f000e000e000d000d000d00 -0e000d000d000e000d000d000d000e000f000f000e000d000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000c000f000e000e000e000e000e000d000e000e000e000e00 -0e000e000f000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000d000c000e00 -0e000d000e000d000d000d000d0011000d0000000d000d000d0004000000000010000d00 -12000d0000000d000d000d000e000e000d000d000d000e000d000e000e000e000e000d00 -0d000d000d000e000d000d000d000d000d000d000d000d000d000d000d000e000d000d00 -0d000d000d000d000d000d000d000d000d000e000d000d000d000d000d000d000d000d00 -0d000e000d000d000d000d000d000e000d000d000d000d000d000d000d000d000d000d00 -0d000e000d000d000d000d000d000d000d000d000d000d000d000e000d000d000d000d00 -0d000d000d000d000d000e000d000e000d000d000d000e000d000d000e000d000d000e00 -0e000e000e000e000e000e000e000e000d000d000e000e000e000e000d000d000d000d00 -0d000e000e000d000d000e000d000d000d000e000e000e000d000d000d000d000e000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000e000d000d000d000d00 -0e000e000d000d000e000e000e000d000d000e000f000e000d000e000d000f000d000e00 -0e000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000e000d000d000d000d000d000d000d000d000d000d000e000f00 -0f000e000e000e000d000d000e000e000d000e000d000d000d000d000e000e000e000e00 -0d000d000d000e000e000d000d000d000d000d000d000d000e000d000d000e000e000e00 -0d000d000d000d000d000d000d000d000e000e000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000e000d000d000e000e000e000e000d000d00 -0e000e000d000e000f000d000e000d000d000d000d000e000d000d000d000d000e000d00 -0d000d000d000e000d000e000d000d000d000d000d000d000d000e000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000e000e000e000e000e000d000e000e000d000d000e000e000e000e00 -0d000d000c000e000d000e000d000e000d000d000e000d000d000e000d000e000e000e00 -0d000d000d000d000d000d000d000e000d000d000d000d000e000f000e000e000e000d00 -0e000d000e000d000d000d000d000d00000012000d001200040000000000100012000d00 -0d0000000d000d000e000d000e000e000e000d000e000e000e000d000e000e000d000d00 -0e000d000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000d000e000d000e000e000e000e000e000e000d000e000e000e000d000f000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000d000e000d000e000d000d000d000d000d000d00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000d000d000d00 -0d000d000d000e000e000d000d000e000e000d000d000d000e000d000d000e000d000d00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000d0011000d000e00 -0e000e000e000d000d000e000e000e000e000e000e000e000e000d000d000e000e000d00 -0d000e000d000d000d000f000d000e000d000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000d000d000d000d000e000e000e000e000e000d000d000e000e00 -0e000f000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000d000e000d000e000d000d000e00 -0d000d0011000d000d000d000d0000000d000d000d0004000000000010000d000d000d00 -00000d000e000e000e000e000e000d000e000e000e000e000d000e000e000e000e000e00 -0e000e000e000d000d000e000d000d000e000d000d000e000d000e000e000e000d000e00 -0d000d000e000d000d000e000e000e000e000d000d000e000d000d000e000d000e000e00 -0d000d000e000e000e000e000e000d000d000e000d000d000e000d000d000e000d000e00 -0e000d000d000e000d000d000e000d000d000e000d000e000e000e000d000e000d000d00 -0e000e000e000e000e000e000e000d000e000e000d000e000e000e000e000e000e000e00 -0d000e000e000d000e000e000e000e000e000d000e000e000e000d000e000e000e000e00 -0e000e000e000e000d000e000e000d000e000e000e000e000d000e000d000e000e000d00 -0e000d000e000e000d000d000d000d000d000e000e000e000d000e000e000d000e000e00 -0e000e000d000d000d000e000e000e000d000d000e000d000d000d000e000f000d000d00 -0d000d000d000d000d000e000e000d000e000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000e000d000e000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000e000e000e000d000d000e000d000d000d000d000e000d000e000e000d000f00 -0e000e000d000d000e000d000e000d000d000d000e000e000d000d000e000d000e000d00 -0e000e000e000e000e000e000e000e000e000e000e000d000d000e000e000e000e000d00 -0d000e000d000d000e000d000d000e000d000e000e000e000d000d000d000d000d000d00 -0d000d000d000d000e000e000d000e000e000e000e000e000d000e000d000d000e000e00 -0d000e000e000d000e000d000e000d000d000e000e000e000e000d000e000e000e000e00 -0e000e000e000e000d000e000e000d000d000e000d000e000e000e000d000e000e000d00 -0d000d000d000e000d000e000d000d000e000d000e000e000d000e000e000d000d000e00 -0d000e000e000e000d000e000e000d000e000e000e000e000e000d000e000e000e000d00 -0e000e000e000e000e000e000d000d000d000d000e000e000d000e000e000d000d000e00 -0e000d000d000d000e000e000e000d000e000e000e000e000e000e000e000e000d000d00 -0d000d000d000d000d000d0000000d0012000d0013000000000010000d000d000d000000 -0d000d000d000d000e000d000d000d000e000d000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000f000e000e000d000e000e000e000e000e000e00 -0e000d000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000f000e00 -0e000d000e000d000e000e000e000e000d000e000f000e000e000d000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000f000e00 -0e000d000e000e000e000e000e000e000e000d000f000e000e000e000e000d000e000e00 -0e000e000e000e000f000e000e000d000e000e000e000e000e000e000e000e000d000d00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000d000e000e000e000e000e000e000e000e000e000e000d00 -0d000d000d0011000d00000012000d00120004000000000010000d0012000d0000000d00 -0d000e000d000e000e000d000e000d000e00090009000900090009000900090009000900 -090009000900090009000900090009000900090009000900090009000900090009000900 -090009000900090009000900090009000900090009000900090009000900090009000900 -090009000900090009000900090009000900090009000900090009000900090009000900 -090009000900090009000900090009000900090009000900090009000900090009000900 -090009000900090009000900090009000900090009000900090009000900090009000900 -090009000900090009000900090009000900090009000900090009000700090009000900 -090009000900090009000900090009000900090009000900090009000900090009000900 -090009000900090009000900090009000900090009000900090009000900090009000900 -090009000900090009000900090009000900090009000900090009000900090009000700 -090009000900090009000900090009000900090009000900090009000900090009000900 -090009000700090009000900090009000900090009000900090009000900090009000900 -090009000700090009000900090009000900090007000900090009000900090009000900 -090009000900090009000900090009000900090009000900090009000900090009000900 -090009000700090009000900090009000900090009000900090009000900090009000900 -090009000900090007000900090009000900090009000900090009000900090009000900 -090009000900090009000900090009000700090009000900090009000900090009000900 -090009000900090009000900090009000900090009000900090009000900090007000900 -090009000900090009000900090009000900090009000900090009000900090009000900 -090009000900090007000900090009000900090009000900090009000900090009000900 -090009000900090009000900090009000900090007000900090009000900090009000700 -090009000900090009000900090009000900090009000900090009000900090007000900 -090009000900090009000900090009000800080009000a000b000e000e000d000e000e00 -0d000d000d000d0000000d0012000d0004000000000010000d0012000d0000000d000e00 -0d000e000e000e000d000e000e000d001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010000f000d000e000e000d000d000e00 -0d000d000d0000000d000d000d0013000000000010000d000d000d0000000d000e000d00 -0e000e000e000e000d000e000d000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000d000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000f000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000d000e000e000e000e000e000e000e000e000e000e000e000d000e00 -0e000f000e000f000e000e000e000e000e000e000d000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000f000d000e000f000e000e000e000e000e00 -0e000e000e000f000e000e000e000e000e000e000d000e000e000e000e000e000e000e00 -0e000e000e000e000d000e000e000f000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000d000e000e000e000e000e000e000e000d00 -0e000e000e000e000e000e000e000d000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000d000e000d000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000d000d000d000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000d000e000e000e000e000e000e000e000e000e000e000e000e000e000d000e000e00 -0e000e000e000e000e000d000e000e000e000e000e000e000e000d000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000d000d000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000d000e000e000e000e00 -0e000e000e000e000e000e000e000d000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000d000e000e000e00 -0e000e000e000e000e000e000e000e000e000d000d000e000d000e000d000d000d000d00 -0d000d0000000d000d000d00130000000000100012000d000d0000000d000e000d000e00 -0e000e000d000d000e000d000e000d000e000e000e000e000e000e000f000e000e000e00 -0e000e000e000e000f000e000e000e000e000e000e000e000e000e000e000e000f000e00 -0e000d000e000e000e000e000e000e000d000e000f000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000d000e000e00 -0d000e000e000e000e000e000f000e000e000e000e000e000e000e000f000e000e000e00 -0e000e000e000e000e000e000e000e000f000e000e000d000e000e000d000e000e000e00 -0e000e000e000e000e000e000d000e000e000e000d000e000d000e000f000e000e000d00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000d000e000d000e000e000d000e000d000e000e000e000e000e00 -0d000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000f000e000d000d000d000e000f000f000d000e000d000e000d000d000d000d00 -0d00000012000d00120004000000000010000d000d000d0000000d000e000e000d000e00 -0e000e000d000d000e000e000d000d000d000d000d000d000d000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000e000d000d000e000e000e000d00 -0d000d000e000d000d000d000d000d000d000d000e000d000e000d000e000d000e000e00 -0e000d000e000d000e000d000e000d000e000d000d000e000e000d000e000d000e000d00 -0e000d000d000d000d000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000e000d000d000e000e000e000d000d000d000e000d000e000d000d000d00 -0d000d000e000e000d000e000d000d000e000d000e000d000e000e000e000d000d000e00 -0d000d000d000d000d000d000d000d000e000d000e000d000e000d000e000d000e000d00 -0d000e000e000d000e000e000d000d000d000d000e000d000d000e000e000e000d000e00 -0d000d000e000d000e000d000e000e000e000e000e000e000d000d000d000e000e000d00 -0e000e000e000e000e000d000e000e000e000e000e000e000e000e000e000d000e000e00 -0e000e000e000d000e000e000d000e000e000e000e000e000d000e000d000d000e000d00 -0e000e000e000e000e000e000e000d000e000e000d000e000e000e000e000e000e000d00 -0e000d000e000d000e000d000e000e000e000e000e000e000d000e000d000e000d000e00 -0d000e000e000e000e000d000e000d000e000d000e000d000e000e000e000e000e000e00 -0d000e000d000e000e000e000d000e000e000e000e000d000e000e000e000e000e000e00 -0e000e000e000d000e000e000e000e000e000d000e000e000d000e000e000e000e000e00 -0e000e000d000e000d000e000d000e000e000e000e000e000e000d000e000e000d000e00 -0d000e000e000e000e000d000e000e000e000d000e000d000e000e000e000e000e000e00 -0d000e000c000e000e000d000e000d000e000e000e000d000e000e000e000d000e000d00 -0e000e000e000e000e000e000d000e000d000e000e000e000d000e000e000d000e000d00 -0e000e000e000d000e000d000e000e000e000e000e000e000c000e000e000e000e000e00 -0e000d000d000e000e000e000d000d000c000e000d000e000d000e000d000d000d000d00 -00000d000d000d0004000000000010000d0012000d0000000d000d000d000e000e000e00 -0d000e000e000d000d000e000e000d000d000e000d000d000e000d000d000d000e000d00 -0e000d000d000d000e000d000e000d000e000d000d000e000e000d000e000d000e000d00 -0d000d000e000d000d000e000d000d000e000d000d000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000d000e000d000e000e000d000e000d000e000d000d000e00 -0d000d000d000d000e000d000d000d000e000d000e000d000d000d000e000d000e000d00 -0e000d000d000e000e000d000e000d000e000d000e000d000d000e000d000e000d000e00 -0e000e000d000e000d000e000e000d000e000d000e000d000d000e000e000d000d000e00 -0e000d000d000e000d000d000e000d000e000d000e000d000e000d000d000e000d000e00 -0e000d000e000d000d000e000e000d000e000d000d000d000e000d000e000e000d000e00 -0e000d000e000d000d000e000e000e000e000e000d000e000e000e000d000e000e000e00 -0e000e000e000e000e000e000e000d000e000d000e000e000e000d000e000d000e000e00 -0e000e000d000e000e000d000d000e000e000e000e000e000e000d000e000d000e000d00 -0e000e000e000e000d000e000d000e000e000e000e000d000e000e000e000e000e000e00 -0d000d000e000d000e000d000e000e000e000e000e000e000e000e000d000e000e000e00 -0e000e000e000e000e000e000d000d000e000d000e000d000e000e000e000e000d000e00 -0d000e000d000e000e000e000e000e000e000e000e000e000e000d000e000d000e000e00 -0e000d000e000d000e000e000e000e000d000e000e000d000d000e000e000e000e000d00 -0d000e000d000e000d000e000e000e000e000e000d000e000d000e000d000e000d000e00 -0e000e000e000e000e000d000e000d000e000d000e000d000e000e000e000e000e000e00 -0e000e000c000e000e000e000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000e000e000e000d000e000d000e000d000e000e000e000e000e000e000e000e000d00 -0e000d000e000d000e000d000e000e000e000e000e000e000e000e000e000e000c000e00 -0e000e000e000d000e000e000e000e000e000e000d000d000e000e000d000d000d000000 -0d0012000d0004000000000010000d000d00120000000d0011000e000d000e000e000e00 -0d000d000e000e000d000d000e000d000d000d000d000d000e000e000d000d000e000d00 -0e000e000d000d000e000d000e000d000e000e000d000d000e000d000e000d000e000e00 -0d000d000e000d000d000d000d000d000e000e000d000d000e000d000e000d000e000d00 -0e000d000e000d000e000e000d000e000e000d000e000d000e000d000d000e000d000d00 -0e000d000d000d000e000e000d000d000e000d000e000e000d000d000e000d000e000d00 -0e000e000d000d000e000d000e000d000e000d000e000d000d000e000d000d000d000e00 -0d000e000d000e000d000d000e000d000e000d000e000d000d000d000e000e000d000d00 -0e000d000d000d000d000d000e000d000e000d000e000d000e000e000d000e000e000d00 -0e000d000e000e000d000d000e000d000e000d000d000d000e000e000d000e000d000d00 -0e000e000e000e000d000e000e000e000e000e000d000e000d000e000e000d000e000d00 -0e000e000e000d000e000e000e000d000e000d000e000d000e000d000e000d000e000e00 -0e000e000e000d000e000e000e000e000e000d000e000d000e000e000e000e000d000e00 -0e000e000e000e000d000e000d000e000d000e000e000e000e000e000e000d000e000e00 -0e000e000e000e000d000e000e000e000e000e000d000e000d000e000e000d000e000e00 -0e000e000e000d000e000e000e000e000e000e000d000e000e000e000e000e000d000e00 -0d000e000e000e000d000d000e000e000e000d000e000e000e000d000e000d000e000d00 -0e000d000e000d000e000e000e000e000e000d000e000e000e000e000e000e000d000e00 -0d000e000e000e000e000d000e000e000e000e000e000e000e000d000e000e000e000e00 -0e000e000e000d000e000d000e000e000e000e000d000e000e000e000e000e000e000e00 -0e000e000e000d000e000e000e000e000e000e000e000e000e000e000e000e000d000e00 -0e000e000e000e000d000e000d000e000e000e000d000e000e000e000e000d000e000e00 -0e000e000e000e000d000e000e000e000e000e000d000e000d000e000e000e000e000d00 -0e000e000e000e000d000d000d000e000e000d000e000d000d000e000d000d0000001200 -0d000d0013000000000010000d000d000d0000000e000d000e000d000e000d000d000e00 -0d000e000e000d000d000d000d000d000d000d000d000d000d000d000d0011000d000d00 -0e000d000d000e000d000e000e000d000e000e000d000e000d000d000d000e000d000d00 -0d000d000d000d000d000e000d000e000d000d000d000d000f000d000e000d000e000e00 -0d000d000e000d000e000e000d000d000d000d000d000d000d000d000d000d000d001100 -0d000d000d000d000d000e000d000e000d000d000d000d000d000d000d000e000d000d00 -0e000d000d000d000d000d000d000d000e000d000f000d000d000e000d000d000d000e00 -0d000d000d000d000d000d000f000e000d000e000d000e000d000d000d000e000d000d00 -0d000e000d000d000d000e000e000d000d000e000d000d000d000d000e000d000d000f00 -0d000d000d000d000e000c000f000e000d000d000d000e000d000e000d000e000d000e00 -0d000e000e000e000e000e000e000e000e000e000e000d000d000e000d000e000e000e00 -0e000d000e000d000e000d000d000e000e000e000e000e000d000e000e000e000e000d00 -0e000d000e000e000e000d000e000e000d000e000e000d000d000e000d000e000e000d00 -0e000d000e000d000e000e000e000d000e000d000e000e000e000e000e000e000e000e00 -0d000e000d000e000d000e000d000e000e000d000e000e000d000e000e000d000e000d00 -0e000e000e000e000e000d000d000e000d000e000e000e000d000e000d000e000d000e00 -0e000e000d000e000e000e000e000d000e000d000e000d000d000e000e000e000e000e00 -0d000e000e000e000e000d000e000d000e000e000d000e000d000d000e000e000d000e00 -0d000e000d000e000e000d000e000d000e000e000d000e000e000d000e000d000e000e00 -0e000e000e000e000e000e000d000e000d000e000d000e000d000e000e000e000e000e00 -0e000d000e000e000e000e000d000e000e000e000e000d000d000e000d000e000e000e00 -0d000e000d000e000d000e000e000e000d000e000e000e000e000e000e000e000e000e00 -0d000e000d000e000d000e000d000e000e000e000e000e000e000e000d000e000e000e00 -0c000e000c000e000e000e000d000e000d000e000d000d000d0011000d0000000d000d00 -12000400000000001000120012000d0000000d000e000d000e000e000e000e000d000e00 -0e000d000d0011000d0011000d000f000d000d000e0011000d000e000d000e000d000d00 -0e000d000d000d000d000d000d000d000e000e000d000d000d000d000d0011000b001100 -0f000d000d000d000d0011000d000d000d000d000d000b000e000e000d000d000f000d00 -0e000d000e000d000e000e000d000d000f000e000d000e000d0011000e000f000c000f00 -0d000d000f000d0011000d000d0011000d000d000d000e000d000d000d000d000e000d00 -0f000d000e000d000d000d000e000e000e000d000d000f000b000d000f000e000d000f00 -0d000e000f000d000d000d000d000f000e000d000d000d000d000d000d000d000d000d00 -0d000d0011000e000d000d000e000e000d000e000e000f000e000d000d000f000d000f00 -0d000d000e000d000d000d000d000e0010000e000d000e000d000e000d000e000d000e00 -0d000e000d000d000e000d000e000d000e000e000e000e000d000e000d000e000d000e00 -0d000e000e000d000e000e000e000e000d000e000d000e000e000e000d000e000d000e00 -0e000d000e000d000e000d000e000e000e000e000d000e000e000e000e000e000e000e00 -0e000e000e000d000e000e000d000e000e000e000d000e000d000e000d000e000d000e00 -0e000e000d000e000d000e000e000d000e000d000e000e000e000e000d000d000e000d00 -0d000e000d000e000e000e000e000e000e000e000d000e000e000e000e000e000e000d00 -0e000e000e000e000d000e000d000e000e000d000e000e000e000e000d000e000d000e00 -0e000e000d000e000d000e000e000d000e000e000d000e000e000d000e000e000e000e00 -0d000d000e000e000e000e000e000e000d000e000d000e000e000e000e000e000d000e00 -0d000e000d000e000d000e000e000e000d000e000d000e000e000e000e000d000e000e00 -0e000e000e000d000d000e000e000d000e000d000e000e000e000e000e000e000d000e00 -0e000e000e000e000e000d000e000e000e000e000d000e000d000e000d000e000d000e00 -0e000e000d000e000d000e000e000e000e000e000d000e000c000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000d000d000d000d000d000d00000012000d000d00 -040000000000100012000d000d0000000d000e000e000d000e000d000d000d000e000d00 -0d000d000d000d000d000d000d000d000e000d000d000e000d000d000e000d000d000e00 -0d000d000d0011000d000e000d000d000d000f000d000e0011000d000d000d000d000d00 -0d000d000f000d000d000d000e000d000d000d000f000d000d000e000d000d000d000d00 -0d000e000d000d000d000e000f000b000d000f000d000d000c000c000f000e000d000e00 -0f000d000c000e000f000d000d000d000d0011000d000d0011000d000d000d000d000f00 -0d000e000d000d000e000d000d000d000f000e000d000f000e000d000d000f000c000f00 -0d000d000e000e000d000d000d000d000e000e000d0011000f0012000d0010000d000e00 -0d000e000d000e000e000d000d000e000e000d000f000d000d000f000d000e000d000d00 -0e000d000f000f000d000d000f000b000d000e000d000e000d000e000d000e000d000e00 -0e000e000e000e000e000d000e000d000e000d000e000e000e000d000d000d000e000e00 -0e000d000e000e000d000e000d000e000e000e000e000e000d000d000e000e000e000d00 -0e000d000e000d000e000e000d000e000d000e000d000e000d000e000e000d000e000e00 -0d000e000e000e000d000e000d000e000d000e000e000e000d000e000d000e000d000e00 -0d000e000e000e000d000e000e000d000e000e000d000e000d000e000e000d000e000e00 -0d000e000e000d000d000e000d000e000e000e000e000e000d000e000d000e000e000d00 -0e000d000d000d000e000e000e000d000e000e000d000e000d000e000e000e000e000e00 -0d000d000e000e000e000d000e000d000d000e000e000e000e000d000e000d000e000e00 -0e000e000e000d000e000e000e000e000d000e000e000d000e000e000d000e000e000e00 -0d000e000d000e000d000e000d000e000e000e000d000e000e000e000e000c000e000e00 -0e000e000e000e000e000d000e000e000e000d000d000e000d000e000e000e000e000e00 -0d000e000d000e000e000d000e000d000d000e000e000e000d000e000d000e000d000e00 -0d000e000e000e000d000e000e000e000c000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000d000e000d000e000d000d000d000d000d0000000d0012000d000400 -0000000010000d000d000d0000000d000d000e000e000e000e000e000e000d000e000d00 -0d000d000d0011000d000d000d0000000e000f00000011000d000c0011000d000d000d00 -0d000d000d000d00110000000d000d000f000b000d000d0000000d000d000e000e000f00 -0d000d000e000e000e000d000d000d000d000e000d000f000d000e000d000f000e000d00 -0d000f000d000f000c000e000f000d000d000d000d0010000d000d000d000d0011000d00 -0d000f000d000d0011000d000d000e000e000d000d000d000d000d0000000d0000000000 -000000000000000011000e000f000c000e0000000d000f000d000e000d0001000d000e00 -0e000d000d000d000d00000000000000000011000d000d00010000000000000000000000 -0d000e000d000d000e000d000d000d000e000d000d000000000000000d000e0000000d00 -0f000d000d000d000d000e000e000e000d000e000d000e000d000e000d000e000e000e00 -0d000d000e000e000e000e000e000e000e000d000e000e000e000e000e000e000d000d00 -0e000e000d000e000e000e000e000e000d000e000d000e000e000e000d000e000e000d00 -0e000e000d000e000d000e000e000e000e000e000d000e000d000e000e000d000e000e00 -0d000e000d000e000d000e000e000d000e000e000d000e000e000e000d000e000e000e00 -0e000e000d000e000e000e000d000e000d000e000e000e000e000e000e000e000d000e00 -0e000d000e000e000d000e000e000e000d000e000d000e000d000e000e000e000d000e00 -0e000e000e000e000d000d000e000e000d000e000e000e000e000e000d000e000d000e00 -0e000e000d000e000e000d000e000e000e000d000e000e000e000e000e000e000d000e00 -0d000e000e000d000e000d000e000d000e000e000e000d000d000d000e000e000d000e00 -0e000e000d000e000e000e000e000e000d000e000e000e000e000e000e000c000e000e00 -0e000e000e000e000d000e000d000e000d000e000d000e000e000e000d000e000d000e00 -0d000e000e000e000d000e000e000d000e000e000d000e000e000e000d000e000e000e00 -0e000e000d000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000d000d000e000d000d000d000d000d00110000000d000d000d0013000000 -000010000d000d000d0000000d000d000d000e000e000e000d000e000d000e000e000d00 -11000d000d000d000d00110000000d000e0000000d000d000d000d000d000d000d000d00 -0d000d000d000d0000000e000b000d0011000d001100000011000d000d000d000c001100 -0d000d000d000d000d000d000e000d000e000d000d000d000e000e000b000e000d000e00 -0d000e000d000f000d000d000e000d000d000e000d000d000d000e000d000d000f000b00 -0d000d000d000d0011000d000d000d000d000d0011000e0000000d000e0000000d001100 -0d000d000d000d000d000d000d0000000d0000000f000d000d000d0000000f000d000b00 -0d000f000d00000011000d000f000d0000000d000d0000000d0011000d000e000d000d00 -0d000d000e000d000d000e000d000d000d0000000d000d000d0000000e000f0000000d00 -0e000d000f000d000d000f000d000e000d000e000d000e000d000e000d000e000d000e00 -0e000e000d000d000d000e000e000e000e000d000e000e000d000e000d000d000e000d00 -0e000e000e000d000e000d000d000e000d000e000d000d000d000e000d000d000e000e00 -0e000e000d000e000e000e000e000e000d000e000e000e000e000e000e000d000d000e00 -0e000d000e000e000e000d000e000e000d000e000e000e000d000e000e000e000e000e00 -0d000e000e000e000e000e000d000e000e000e000e000d000d000e000d000e000e000e00 -0e000d000d000e000e000e000d000e000e000e000d000e000e000e000d000e000e000d00 -0d000e000d000d000e000d000e000e000e000d000e000d000d000e000d000e000d000d00 -0d000e000d000d000e000e000e000d000e000d000e000e000e000e000d000e000e000e00 -0d000e000e000d000e000e000e000d000e000e000d000e000e000e000d000e000e000e00 -0d000e000e000e000e000e000d000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000d000e000e000d000e000e000e000d000e000e000e000d000e00 -0e000e000d000e000e000d000e000e000d000e000e000e000d000e000e000e000e000e00 -0d000e000e000e000d000e000e000e000d000e000d000e000e000e000e000e000e000e00 -0e000e000e0011000d000d000d000d000d000d000d00000012000d001200040000000000 -100012000d000d0000000d000d000e000d000e000e000e000d000d000d000e000d000000 -00000d0000000d000000000000000d0000000d000d0000000d000d000d000d000d000d00 -0d000d000d0000001100000000000d000f000d0000000d00000000000d000f000d001100 -00000000000011000d0000000d000d0011000d0000000d000d000e000d000e000d000d00 -0d0000000f000000000010000d0011000d000000000000000d000d0000000d000f000d00 -00000d000d000d0000000d00110011000e000d000d0000000d000d0000000d000d001100 -0e000e000d000d000f000e0000000d0000000d000e000f000d0000000d000f000f000d00 -0d000e0000000d000d000d000e000e000e001100000011000d000d000d000d000d000d00 -0e000d000e000e000d000d000e000d0000000d000f000f0000000f000d0000000d000e00 -0e000e000d000e000d000e000d000e000d000d000e000e000d000e000d000e000e000e00 -0d000d000d000e000d000d000e000e000e000d000e000e000d000d000e000e000e000d00 -0e000d000e000d000e000e000e000e000e000d000d000e000e000e000e000d000e000e00 -0d000e000e000e000e000e000e000e000e000e000d000d000e000e000e000d000e000e00 -0e000d000e000e000e000d000e000d000e000e000d000e000d000e000d000e000d000e00 -0e000d000d000e000d000e000e000e000d000e000e000e000e000e000e000e000e000d00 -0e000e000d000e000d000e000e000e000d000e000d000e000d000e000e000e000d000e00 -0d000d000e000e000e000d000e000d000e000d000e000e000e000e000e000d000d000e00 -0e000e000e000d000e000e000e000e000e000e000e000e000e000e000e000d000e000d00 -0d000e000e000d000e000e000e000d000e000e000d000d000e000d000e000e000d000e00 -0d000e000d000e000d000e000e000d000d000d000e000d000e000e000e000c000e000e00 -0e000e000d000e000e000e000d000e000d000e000d000e000e000e000d000e000d000e00 -0d000e000e000e000d000d000e000d000e000e000d000e000d000e000d000e000d000e00 -0e000d000d000e000e000e000d000e000e000e000e000e000d000e000d000e000e000e00 -0c000e000e000d000d000d000d000d0011000d0000000d000d000d000400000000001000 -0d0012000d0000000d000e000d000e000e000e000d000e000e000d000d00000011000d00 -000000000b000e0000000d000e0000000d0000000d000e000d000d0011000d000e000d00 -0d000d00000000000d000d0000000d000e00000000000d000d0000000d000d0000000d00 -0d000e0000000b000e0000000d000d0000000f000c000f000d000d000d000d000e000d00 -000000000f000d0000000d000d00000011000d000d000000110000000d000d0011000000 -0d000d000d00000011000d000b000e000d00000011000d00110000000e000d000d000d00 -0d000d000f000d0000000d000e000e0000000d000d000d0000000d000d000d000d000d00 -0d0011000000000011000b000d000d000d0000000d000d000d000d0011000d000d000e00 -0e000d000d000e000d000d000d0000000e000d000d0001000e000d000e0000000d000e00 -00000f000d000d000d000e000d000e000e000d000e000d000d000e000e000e000e000e00 -0e000e000d000e000e000e000e000e000e000e000e000e000e000d000e000e000e000e00 -0d000e000d000e000e000e000d000e000e000e000e000d000e000e000e000e000e000e00 -0e000d000e000d000e000e000d000e000d000e000e000d000d000d000e000d000e000d00 -0e000d000e000d000e000e000e000d000e000e000e000e000d000e000e000e000e000e00 -0d000e000e000e000e000e000d000e000e000d000e000e000d000e000e000e000e000e00 -0d000e000d000e000e000d000d000e000d000e000d000e000d000e000d000e000e000e00 -0e000d000e000e000e000e000d000e000d000e000e000e000d000e000e000e000e000d00 -0e000e000e000e000e000d000d000e000d000e000e000e000d000e000e000e000d000d00 -0e000d000e000d000e000d000e000d000e000e000e000e000e000d000e000e000e000e00 -0d000e000e000e000e000e000d000e000e000d000e000e000e000e000e000e000e000e00 -0e000c000e000d000e000e000d000e000d000e000e000d000d000e000d000e000d000e00 -0d000e000d000e000e000e000e000d000e000e000e000e000d000e000e000e000e000e00 -0d000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000d000e00 -0d000e000e000d000d000d000d000d000d0000000d0012000d0004000000000010000d00 -0d000d0000000d000e000e000d000e000e000e000d000e000d000e0000000d000e000d00 -000011000d00000011000e00000000000d000d000d000d000d000e000d000d000d000d00 -0d0000000e000d000d0000000e000d0000000d000e00110000000e000e00000011000d00 -0d00000011000d000f00000000000e000d000d000e000d000e000d000e000d000d000000 -0e000d000d0000000d000d0000000d000d000d0000000c00110000000e000d0000000d00 -0d0000000d000d000e000e000d000e0000000d000e000d00000000000000000000001100 -0d000d000e0000000e000d000d0000000d000d00100000000f000d000d000e000d000d00 -0d000d000d00000000000d000d000e000000000000000000000000000d000e000d000e00 -0d000e000d000d000d000d0000000d000d000d0000000d000e000d0000000d000d000e00 -0d000d000e000e000d000e000d000d000e000d000d000e000d000e000d000e000e000d00 -0e000e000d000d000e000d000e000d000e000e000d000e000d000e000e000e000e000e00 -0e000e000e000e000d000e000e000e000d000e000e000e000e000d000e000d000e000d00 -0e000d000e000e000e000e000e000e000e000e000d000d000e000e000e000e000e000e00 -0e000e000e000e000d000e000e000e000d000e000d000e000e000e000d000e000d000e00 -0d000e000d000e000d000e000e000d000e000d000d000e000e000e000e000e000e000e00 -0e000e000e000e000d000e000d000e000e000e000e000e000e000e000e000e000d000e00 -0d000e000e000e000e000e000e000e000e000e000d000e000e000e000d000e000e000e00 -0e000d000e000e000d000e000d000e000d000e000e000e000e000e000e000d000e000e00 -0e000e000e000e000e000e000e000e000d000e000d000e000e000e000d000e000d000e00 -0e000e000d000e000d000e000d000d000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000d000e000e000e000e000e000e000d000e000d000e000e000e000e000e00 -0e000e000e000e000d000e000e000e000d000e000d000e000e000e000d000e000d000e00 -0d000e000e000e000e000e000c000e000e000e000e000e000c000d000e000e000d000e00 -0e000e000d0011000d000d000d000d00000012000d000d00130000000000100012000d00 -0d00000011000e000e000d000e000d000d000e000d000e000e0000000e000f000d000000 -0f000d0000000d000e00000000000d000e0011000d000d000f000d000d000f000d000d00 -00000e000d000e0000000d000e0000000d000d000e0000000e000d0000000e000d000e00 -00000d000e000d00000000000f000d000e000f000d000d000f000d000d000f0000000e00 -0e000d0000000e000e00000000000000000000000d000d0000000d000e0000000e000d00 -00000d000d000d000d000e000f0000000e000d000e0000000d000d000d000d000d000e00 -0d000d00000000000000000000000e000e000d0000000d000e000e000d000e000d000e00 -0d000d000f000e0000000e000e0000000d000d000d000d000e000d000d000d000e000d00 -0e000d000e000d000f0000000e000e000e0000000e000e000d0000000d000e000d000d00 -0d000d000d000d000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000d000e000e000e000d000e000e000d000e00 -0e000d000d000e000d000e000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000d000e000d000e000e000d000e000d000d000e00 -0d000e000d000e000d000e000e000d000e000e000e000e000e000e000e000e000d000e00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000d000e00 -0d000e000d000e000d000e000e000d000d000e000e000d000e000d000d000d000e000e00 -0e000d000e000e000d000e000e000d000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000e000d000e000e000e000e00 -0e000e000e000e000d000e000e000d000e000e000d000e000e000d000e000d000e000d00 -0e000d000e000d000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000e000d000e000d000e000d000d000e000d000d000e000d000d000e00 -0e000e000d000e000d000e000d000e000d000e000e000e000e000e000e000e000d000e00 -0e000e000d000e000d000d000d0000000d0012000d0004000000000010000d000d001200 -00000d000e000e000e000e000e000e000d000d000e000e0000000d000e000e0000000e00 -0d00000010000d0000000b0000000d000d0011000d000f000e000d000d000d000d000000 -0e000d000d0000000e000d0000000e000d000e0000000d00100000000d000d000f000000 -0d000e0000000e000f0000000f000d000c000f000d000d000e000d000d0000000e000d00 -0d0000000d000d0000000d000d000f000e000d000f0000000d0000000e0000000f000000 -0d000e000d000f000b000f0000000d000d000d0001000d000d000e000d000f000d000e00 -00000d000d000f000e000e0000000d000e0000000e000d000d000f000d000d0000000d00 -0e000d000e0000000e000d0000000f000d000d000d000f000d000f000d000d000d000d00 -0d000d000d000d0000000d000d000d0000000d000e000d0000000d000e000f000d000d00 -0f000d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000d000e000e000e000d000e000d000d000e000d000d00 -0e000e000d000e000d000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000e000e000e000e000d000e000d000e000e000e000e00 -0e000e000d000d000e000d000d000d000e000d000e000e000d000e000d000d000d000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000e000d000e00 -0d000e000d000e000d000d000e000d000d000d000e000d000d000d000e000e000e000d00 -0e000d000d000e000d000d000e000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000d000e000d000d000d000e000d000e000e00 -0d000e000d000d000d000e000d000d000e000d000e000e000e000d000e000d000e000e00 -0e000e000e000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000d000d000d000e000e000d000e000d000d000e000d000e000e000d000e00 -0e000e000d000e000d000d000e000e000e000e000d000e000e000d000e000e000d000d00 -0e000d000d000d000d000d0000000d000d00120004000000000010000d0012000d000000 -0d0011000e000d000e000d000d000e000e000d000d0000000d000d00000000000d000e00 -00000d000e0001000e000d0001000e000d000d000d0011000d000d000f000d0000000d00 -0e000e0000000d000e00000000000f000d0000000f000e0000000f000e000d0000000d00 -00000e000d000e000d0000000d000f000d000d000f000d000d000d0001000d000d000e00 -00000e000f0000000d000f000d0000000e000b000d0000000a000e000e0000000d001000 -0d000e000e000d000e0000000e000e000d0000000e000d000f000e000d000e000d000000 -0d000d000b000f000d0000000f000e0000000d000e000e000d000d000f0000000f000d00 -0d000d0000000d000d0001000d000d000e000d000d000f000d000d000e000e000d000d00 -0f000d000d0000000e000d000f0000000d000f000e0000000f000d000d000d000d000d00 -0e000d000d000e000e000d000e000d000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000d000e000d000e000d000d000e000d000d000e000d00 -0e000d000d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000e000d000e000e000e000d000e000e000e000d000e000e000e000d000e00 -0e000d000e000e000d000e000e000e000e000d000d000e000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000d000e000d000e00 -0d000e000d000e000e000d000d000e000e000d000d000e000d000d000e000d000e000d00 -0d000e000d000d000e000d000e000d000d000d000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000e000d000e000e000d000e000e000e000e000d000d000e00 -0e000d000e000d000d000e000e000d000e000d000e000d000e000e000e000e000e000d00 -0e000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000d000e000e000d000e000e000e000d000e000e000d000e000e000d000e000e000e00 -0e000e000e000e000e000e000d000e000d000e000e000e000d000e000d000d000e000d00 -0d000d000d000d000d00000012000d000d0013000000000010000d000d000d0000000d00 -0d000e000e000d000e000e000e000d000e000d000d00000000000d0000000f000d000000 -00000e0000000d000d000e0000000f000d000d000e000d000d000d000e0000000d000d00 -0e00000010000d0000000e00000000000d000e000d000f000000000000000d000e000000 -0d000f000d000d0000000d000d000f000c000e000e000d000f0000000d000e000f000000 -0d000d000f000000000000000d000f000e000e0000000f000b000f0000000e000d000e00 -0d000d0011000d0000000d000d000f0000000d000e000c000d000e000d000d0000000d00 -0e0010000d000f0000000c000e00000000000000000000000e000d001000000000000000 -00000d000d000d000000000000000000000000000d000e000d0000000f000d000d000d00 -0f000d000e000000000000000f000d000d000d0000000d000e0000000e000d000f000d00 -0e000d000d000d000e000d000e000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000e000d000e000d000d000e000d000e000d000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000e000d000e000e000e000d000e000e000e000d000e000e000e000d000e000e000d00 -0d000e000d000e000d000e000e000d000e000e000d000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000e000d000e000d000e00 -0d000e000d000d000e000e000d000e000d000e000d000e000e000d000e000d000d000e00 -0d000e000d000d000e000d000e000d000e000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000d000d000e000d000e000d000e000e000d000e000e000d000d00 -0e000d000e000d000e000d000e000e000e000e000e000d000e000d000e000e000e000d00 -0e000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0e000e000d000e000d000e000e000e000d000d000e000d000d000e000d000e000e000e00 -0e000d000e000d000e000e000e000e000d000d000e000e000d000e000e000d000e000e00 -0d000d000d000d0000000d000d00120013000000000010000d000d000d0000000d000d00 -0d000e000d000e000d000e000e000d000f000d000d000d000f0000000d000d000d000f00 -0d000d000f000d000d000f000d000e000f000c000e0010000d000d000f000e000e000d00 -0f000d000f000e000e000d000f000f000d000d000d000d000e000d000f000d000d000d00 -0e000d000e000d000f000d000d0010000d000d000f000f000d000e000d000b000e000d00 -0d000d000e000e000f000d000d000f000d000d000f000d000d000d000d000f000d000e00 -0e000d000f000d0000000d000d000d000d000d0010000e000d000f000d000f000d000d00 -0c000e000d000e000f000d000d000f000d000f000d000e000d000d000b000f000d000d00 -0d000d000f000e000e000d000d000e000b000f000d000f0000000d000e000d000d000d00 -0d000e000e000d000e000d000f000d0000000d000e000d0000000d000e000d000e000d00 -0e000d000e000d000d000d000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000e000e000d000e000d000e000d000e000d000e000e000e00 -0d000e000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000e000e000e000d000e000e000d000e000e000e000e000d000e000e000e000e000d00 -0d000e000d000d000d000e000d000e000d000e000d000e000d000e000e000d000e000d00 -0e000d000d000e000e000d000e000d000e000d000e000d000d000e000d000e000d000e00 -0d000e000d000e000d000e000e000d000d000e000d000e000e000e000d000e000d000e00 -0d000e000d000e000e000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000d000e000d000e000d000d000e000d000d000d000e000d000e000d000e000d000e00 -0d000e000e000d000e000d000e000e000e000e000e000e000e000d000e000e000e000d00 -0d000e000d000e000d000e000d000e000d000e000d000e000e000d000d000e000e000d00 -0d000e000d000d000e000d000d000d000e000d000e000d000d000e000e000e000e000e00 -0e000d000e000e000d000e000d000e000e000d000d000e000e000e000d000e000d000d00 -0d000d000d0000000d0012000d0004000000000010000d0012000d0000000d000d000e00 -0d000e000d000e000d000d000e000c0000000f000d000f0000000e000d000d000f000b00 -0f000d000d000f000d0000000000000000000000000000000d000d000e000d000d000e00 -0f000d000d000d000f000d000d000d000d000e000e000d000d000e000d000d000f000e00 -0d000f000f0000000000000000000000000000000b000f000d000d000f0010000d000d00 -0e000d000e000d000f000e000b000d000e000d000d000f000d000d000d000f000e000d00 -0e000d000f0000000f000d000e000d000e000d000d000d000d000d000e000f000d000d00 -0f000d000d000d000d000d000d000d000e000d000d000d000e0010000e000d000e000d00 -0d000d000c000d000e000d000d000f000e000d0000000d000e000d000e000e000f000e00 -0e000b000f000e000d000d000d0001000c000f0000000d000f000f000d000d000e000d00 -0d000d000e000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000d000d000e000d000e000d000e000d000e000d000d000d000e00 -0d000d000e000d000e000d000e000d000d000d000e000d000e000d000e000d000e000e00 -0d000e000d000e000e000d000e000e000d000e000d000e000e000e000d000d000e000e00 -0d000d000e000e000d000d000d000e000d000e000d000e000d000d000e000d000e000d00 -0e000d000d000d000e000d000e000d000e000d000e000e000d000e000d000e000d000e00 -0d000e000d000e000d000d000e000e000d000e000d000d000d000e000d000e000d000e00 -0d000e000d000d000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000d000e000d000e000e000d000d000e000e000d000d000d000e000d000e000d000e00 -0d000e000e000e000e000d000e000d000e000d000e000e000d000d000e000d000e000e00 -0d000e000d000e000d000e000d000e000d000e000d000d000e000e000d000d000d000e00 -0d000d000e000d000e000e000d000d000e000d000d000e000d000d000e000d000e000e00 -0e000e000d000e000e000e000d000e000e000e000d000d000e000d000d000d0011000d00 -0d000d0000000d000d000d00130000000000100012000d000d0000000d000d000e000e00 -0e000e000d000e000e000d0010000c000000000000000e000c000f000f000d000f000d00 -0d000e000d000e000e000f000f000d000d000e000d000d000e000d000f000d000d000d00 -0f000d000d000d000d000e000e000e000d000d000e000f000d000e000e000d000d000e00 -0d000d000e000f000e000e000d000d000d000f000d000d000f000d000d000d000f000d00 -0f000d000d000d000d000f000d000e000e000d000d000d0010000d000d000d000d000e00 -0e000d000f0000000e000d000e000e000d000e000d000f000f000b000e000e000d000d00 -0e000d000e000d000d000f000e000d000e000e000d000e000d000c000e000d000e000f00 -0e000d000f000e000d000d000f000d000f000d000e000d000f000e000d000d000e000e00 -0d000d000d0010000d0000000d000e000d000f000e000d000b000f000d000e000d000e00 -0e000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0e000e000e000e000d000e000e000d000e000d000d000d000e000d000e000d000d000e00 -0e000d000e000d000e000d000d000e000e000d000e000d000e000d000e000d000e000d00 -0e000e000e000d000d000e000d000e000e000e000d000e000e000d000e000e000e000e00 -0e000d000e000e000e000d000d000e000e000d000d000d000e000d000e000d000e000d00 -0d000e000e000d000e000d000e000d000e000d000d000e000d000e000d000e000d000e00 -0d000e000d000e000e000d000d000d000e000e000d000e000e000d000e000d000d000d00 -0e000d000e000d000d000e000d000e000d000e000d000e000e000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000e000d00 -0e000e000e000e000e000e000e000d000e000e000e000d000d000e000e000d000d000d00 -0e000d000e000e000e000e000e000d000e000e000e000e000e000d000e000d000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000d000e000e000e000d000e000e00 -0d000e000e000d000d000e000d000d000e000d000d000e000e000e000e000d000e000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000d00 -110000000d001200120004000000000010000d000d000d0000000d000e000e000e000e00 -0e000e000d000d000e000d000e000d000e000e000d000e000e000d000d000e000d000d00 -0d000f000d000d000e000d000e000e000d000e000e000d000d000d000d000d000e000d00 -0e000e000d000e000d000d000f000d000e000d000e000d000d000e000f000d000f000e00 -0d000d000d000d000d000e000d000d000d000d000d000e000d000d000f000d000d000e00 -0e000d000d000e000d000e000e000d000d000e000d000d000e000e000d000f000d000d00 -0d000e000d000d000f000d000d000f000d000d000d000d000f000d000d000e000d000d00 -0e000d000e000d000d000d000e000d000e000d000e000d000e000d000e000d000d000d00 -0d000d000f000d000f000d000f000e000d000e000d000e000d000d000e000d000e000d00 -0e000d000d000f000d000e000d000d000e000d000d000f000d000e000d000e000d000d00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000d000e000e00 -0e000e000e000e000d000e000e000d000e000d000e000d000e000d000e000d000d000d00 -0e000d000e000d000e000e000f000d000e000d000e000d000e000d000e000d000e000e00 -0d000d000e000e000e000e000e000e000d000e000e000d000e000d000d000e000e000d00 -0e000d000d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000e00 -0e000d000e000d000e000d000e000d000e000e000d000e000d000e000d000e000d000e00 -0d000e000d000d000d000d000d000e000e000e000d000e000e000d000e000d000e000d00 -0e000d000e000d000d000e000d000e000d000e000d000e000e000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000d000e000d00 -0e000d000d000e000e000d000e000d000d000d000e000d000e000d000e000d000e000e00 -0e000d000e000d000e000e000e000e000e000d000e000e000e000d000e000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000e000e000e000e000e000e00 -0d000e000d000e000d000e000e000d000e000e000d000e000d000e000e000d000d000e00 -0d000e000e000e000e000e000d000e000e000e000e000d000e000d000e000d000d000d00 -000012000d000d0004000000000010000d000d000d0000000d000d000d000e000d000d00 -0d000e000d000d000d000d000e000d000e000d000e000d000e000e001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -1000100010001000100010000a000d000d000e000d000d000e000d000e000d000e000d00 -0d000e000d000e000d000e000d000e000e00100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -10001000100010001000100009000e000d000d000d000d000d000e000d000e000d000e00 -0d000e000d000d000e000d000e000d000d00100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -1000100010001000100010001000100010001000100010001000100010000f0009000e00 -0e000e000e000e000e000d000e000e000e000e000e000d000d000d000d000d000e000d00 -0f0010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010000a000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000d000d000e000e001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -1000100010000a000e000d000d000e000d000e000e000e000e000e000d000e000d000e00 -0d000e000d000e000d000d00100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010000a000d000d000e00 -0e000e000e000e000d000e000e000e000e000d000e000d000d000d000d000d000d000000 -0d000d000d0004000000000010000d0012000d0000000d000d000d000d000e000e000e00 -0d000e000d000e000d000d000e000d000d000d000e000d000d0010000f000d000d000e00 -0e000d000f000f000f000d000d000d000e000d000d000f000f000e000d000f000e000d00 -0f000e000f000d000d000d000e000f000e000e000f000d000d000f000e000d000d000e00 -0f000d000d000f000e000f000e000e000f000d000d000f000e000d000d000e000e000d00 -0d000f000e000f000e000e000f000d000d000f000e000d000f000f000f000d000d000d00 -0e000e000f000f000f0009000d000e000e000d000d000d000e000d000e000d000e000e00 -0d000e000d000e000d000e000d000e0010000d000d000d000e000f000e000d000d000e00 -0f000d000f000e000e000f000e000f000e000f000e000e000d000e000e000e000e000f00 -0e000e000f000e000e0009000e000e000e000e000d000e000d000e000d000e000d000e00 -0d000e000d000d000d000e000d000e0010000e000d000f000d000f000d000e000d000f00 -0e000e000e000f000e000f000d000d000d000d000d000d000e000d000f000d000d000f00 -0e000e000f000e000e000f000e000f000e000e000e000e000d000e000e0007000e000e00 -0e000e000e000d000e000e000d000e000d000d000e000d000d000e000d000e000d000e00 -10000d000d000d000f000d000d000f000e000e000c000e000f000d000f000f000e000d00 -0d000d000e000d000d000e000d000e000e000d000f000f000d000e000e000e000e000f00 -0e000f000f000e0009000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000e000d0010000e000f000d000e000e000e000f000d000e000f00 -0d000d000f000f000d000f000d000f000d000d000d000e000f000d000f000e000e000f00 -0f000e000e000d000f000d000f000e000f000d000e000d000d000f000d000e000e000e00 -0e000e0009000d000d000e000d000e000e000d000e000d000d000e000d000e000d000e00 -0d000e000d000f000d0010000d000e000f000d000d000e000e000e000e000d000f000e00 -0d000f000d000d000d000d000d000b000f000e000e000f000f0009000e000e000e000e00 -0e000e000d000e000e000e000d000e000d000d000e000d0011000d000d000d0000001200 -0d00120004000000000010000d0012000d0000000d000e000e000e000e000e000d000e00 -0e000d000d000e000e000d000d000e000d000e000f000f0010000f000d000d000d000e00 -0e000d000d000d000f000e000f000e000f000d000f000d000d000e000e000d000e000d00 -0d000d000f000e000f000e000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000e000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000e000d000d000d000f000e000f000e00 -0d000d000d000d0009000e000e000d000d000e000e000d000d000d000d000e000e000d00 -0d000d000d000e000d000e000d0010000f000d000e000f000f000d000f000d000f000e00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d0009000e000f000e000d000d000d000e000d000e000d000e000d000e00 -0d000d000e000d000f000e000e0010000d000e000d000f000d000f000d000d000d000d00 -0d000d000d000d000d000d000f000f000d000e000d000d000f000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000e000e000d000d000d000e0007000e000e000e00 -0e000d000e000d000d000e000e000e000e000e000e000d000e000d000e000d000e001000 -0f000f000e000d000e000d000f000d000e000d000d000d000d000d000d000d000f000e00 -0e000e000e0010000d000d000f000e000d000d000d000e000f000f000d000d000d000d00 -0e000d000f0009000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000d000d000e000d0010000e000e000d000d000d000e000d0010000d000d000f00 -0f000d000d000d000d000e000d000d000f000d000f000e000d000d000d000d000d000d00 -0d000d000f000d000d000d000d000d000e000d0010000d000d000f000e000e000e000e00 -0e0009000e000f000d000e000e000d000e000e000d000e000d000e000d000e000d000e00 -0d000e000d000d0010000f000f000d000d000d000e000e000e000d000d000b000e000f00 -0d000d000e000f000d000d0010000d000d000d000d000d0009000e000e000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000d000d0011000d0000000d000d00 -0d0004000000000010000d000d000d0000000d000e000d000e000e000e000d000e000d00 -0e000e000d000d000e000e000d000e000d000d000e0010000f000d000f000e000e000d00 -0d000f000e000d000d000d000d000d000d000f000f000d000d000d000e000d000e000e00 -0f000d000d000d000d000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000d000d000f000e000d000d000d000d000e00 -0e000d000d0009000d000e000d000e000d000e000d000e000d000e000d000d000e000d00 -0e000e000d000e000d000e0010000f000f000f000b000d000f000d000d000d000d000d00 -0e000f000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000d000f0009000e000d000d000e000e000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000e000e0010000e000d000d000d000d000d000e000e000e000e000e00 -0e000e000e000e000e000d000d000e000d000d000f000d000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e0009000e000e000e000e00 -0e000d000e000e000e000e000d000e000d000d000d000e000d000e000d000f0010000d00 -0e000e000d000d000f000d000e000d000f000d000d000f000d000f000d000d000f000d00 -0d000d000b000d000d000d000d000f000d000d000d000d000d000e000e000e000d000d00 -0d000f0009000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000d000e000e0010000f000f000e000e000d000e000e000d000d000d000d000f00 -0d000d000e000d000f000f000d000d000d000d000d000d000e000f000e000d0010000b00 -0f000e000d000e000e000f000d000d000e000d000d000d000e000e000e000e000d000e00 -09000e000e000d000e000e000e000d000e000e000d000e000d000e000d000e000d000e00 -0d000f000d0010000e000d000d000d000d000d000d000e000e000d0010000d000d000d00 -0f000d000f000d000d000d000d000e000e000d000d0009000e000e000d000e000e000e00 -0d000e000e000e000d000e000d000e000d000d000d000d000d000d00000012000d000d00 -130000000000100012000d000d0000000d000e000e000e000e000d000e000e000e000d00 -0d000e000d000e000d000e000e000d000d000d0010000f000d000e000d000d000e000d00 -0d000d000d000f000f000d000f000e000d000d000d000d000d000d000e000d000d000d00 -0d000f000f000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000e000d000d000d000d000f000f000d000d000d00 -0d000d0009000d000e000e000d000e000d000e000d000e000d000e000e000d000d000e00 -0d000e000d000e000d0010000d000d000d0010000e000d000e000f000d000e000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000e0009000e000d000d000e000f000d000e000d000e000d000e000d000e000d000d00 -0d000d000e000d000d0010000d000d000e000f000e000d000e000d000d000d000d000d00 -0d000d000d000d000e000e000d000f000e000d000f000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000e0009000e000d000e000e000e00 -0d000e000e000e000e000e000e000e000e000d000e000d000e000d000e0010000f000b00 -0e000e000d000d000d000d000d000e000d000d000e000d000e000d000f000d000e000d00 -0d000f000d000f000e000b000f000d000e000d000d000f000d000d000e000d000d000d00 -0d0009000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000e0010000d000e000e000d000f000d000d000b000f000d000d000d000e00 -0d000e000e000d000d000e000e000f000d000e000e000d000d000d000d000d000d000e00 -0d000d000e000d000d000f000d000e000b000f000d000d000e000d000e000e000e000900 -0e000d000e000d000e000e000e000e000d000e000d000e000d000e000d000e000d000e00 -0e000e0010000f000e000d000f000d000f000f000d000d000f000d000c000e000f000d00 -0f000c000e000f000d000f000e000d000e000e0009000e000e000e000e000e000d000e00 -0e000e000d000e000d000e000d000e000d000d000d000d000d0000000d000d0012001300 -0000000010000d000d000d0000000d000e000e000d000e000d000e000d000d000d000e00 -0d000d000e000e000d000d000e000e000f0010000f000d000f000d000d000f000d000d00 -0d000e000b000f000e000d000f000d000d000e000e000d000d000f000d000d000d000e00 -0b000f000e000e000e000e000e000e000d000e000e000d000e000e000e000e000d000e00 -0e000e000e000e000e000e000d000e000e000e000e000e000e000e000d000e000e000e00 -0e000e000e000e000d000e000e000f000d000d000d000e000b000f000e000d000d000d00 -0e0009000d000e000e000d000d000e000d000e000d000d000e000e000d000e000d000e00 -0d000e000d000f0010000f000b000f000d000d000e000f000b0011000f000e000f000d00 -0d000e000e000d000d000e000e000d000e000d000e000d000e000e000e000e000d000d00 -0e0009000e000e000d000d000d000e000d000e000d000e000d000e000d000d000d000d00 -0d000e000d000e0010000d000e000d000d000e000f000d000d000e000e000e000e000e00 -0e000d000d000d000e000d000e000d000d000d000e000e000e000d000e000d000e000d00 -0e000e000e000d000d000d000e000e000d000d000e0009000e000e000e000e000e000e00 -0e000e000d000d000e000e000e000d000d000e000d000e000d000d0010000e000e000f00 -0d000d000d000f000d000d000f000d000e000d000e000d000e000d000d000d000f000d00 -0d000d000d000f000f000d000d000e000f000d000d000d000d000e000e000e000d000f00 -09000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000e00 -0d000d000d0010000d000e000d000d000d000e000f000d000d000f000e0010000c000e00 -0d000c000f000d000e000f000c000f0011000e000e000d000d000f000d000e000d000d00 -0e000d000d000d000d000e000f000d000d000f000e000d000e000e000e000f0009000e00 -0e000e000e000d000e000e000e000e000d000e000d000e000d000e000d000e000d000d00 -0f0010000e000d000d000d000d000d000d000d000f000d000d0010000e000d000f000d00 -0f000d000e000e000d000d000d000e000e0009000d000e000e000e000d000e000e000e00 -0d000e000d000e000e000e000d000d000e000d000d000d00000012000d000d0004000000 -000010000d0012000d0000000d000d000d000d000e000e000d000d000e000e000d000d00 -0e000d000d000d000e000d000d000d0010000e000d000e000d000d000d000e000f000e00 -0c0001000d000d0000000b000e000f000e000d000d000e000d000e000f000e000c000100 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000e000f000e000c0001000d000d000d000e000e000e00 -09000d000e000d000e000d000e000d000d000d000e000d000d000e000d000e000d000e00 -0d000e000d0010000d000f000f000f000f0000000b0001000d000d000d000e000d000e00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000e000f00 -09000f000e000e000d000d000d000e000d000e000e000d000e000d000e000d000e000d00 -0f000e000e0010000f000d000d0001000d000b000d000e000d000d000d000d000d000d00 -0d000d000e0000000f000d0000000f000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000e000e000e0009000f000e000e000e000d000d000e00 -0e000d000e000d000e000e000d000d000d000d000e000d000e0010000e000d0000000000 -000000000000000000000d00000000000000000000000d000d000f0000000d000e000d00 -0f0000000d000d000000000000000000000000000d000d000d000d000d000d000e000900 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0d000e0010000e000e000e000000000000000000000001000d000d000d000d000f000000 -0f000d000d000d000b0001000d000d000d000e000d000e000f0000000000000000000e00 -0e000d000000000000000000000001000d000d000d000e000e000d000e0007000e000d00 -0d000e000e000e000e000e000e000e000d000e000d000e000d000e000d000e000d000e00 -10000d000d0010000d000f0000000f000e000d000d000d000000000000000d000d000000 -0d000e000d000d000d000e000e000e0009000d000e000e000e000e000e000e000e000e00 -0e000e000e000d000d000d000d000e000e000d000d0000000d0012001200040000000000 -10000d000d00120000000d0011000e000e000e000d000e000e000e000d000d000e000d00 -0e000e000d000d000e000e000e0010000f000d000e000e000d000d000e000d000d000f00 -00000f000d0000000d000f000d000e000e000e000d000d000e000d000d000f0000000f00 -0d000d000d000e000d000d000d000e000d000d000d000e000d000d000d000e000d000d00 -0d000e000d000d000d000e000d000d000d000e000d000d000d000e000d000d000d000e00 -0d000d000d000e000d000d000e000d000d000f0000000f000d000d000e000d000d000900 -0d000e000d000d000e000d000e000d000e000d000e000e000d000e000d000e000d000e00 -0d000e0010000d000d000d000d0000000d000f0000000f000d000d000f000d000e000d00 -0e000d000d000e000d000d000e000d000d000e000d000d000e000d000d000d000d000900 -0d000d000e000e000e000e000d000e000d000d000e000d000e000d000d000d000d000e00 -0e000e0010000d000f000d0000000e000f000d000f000d000e000d000d000d000d000e00 -0d000e0001000d000d0000000d000d000d000e000d000d000e000d000d000e000d000d00 -0e000d000d000e000d000e000e000e000e0007000e000d000e000e000e000e000e000d00 -0e000d000e000e000e000d000d000e000d000e000d000e0010000e000e000d000d000e00 -00000d000e000e000e0000000f000d000f000d0000000d000e0000000e000d000f000d00 -00000d000e0000000d000f000d000d000e000e000d000d000d000e000d000f0009000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000d000e00 -0f0010000d000e000e0000000f000d000d000d000e000d000e000e000d0000000d000000 -0d000e000d000f0000000f000e000d000e000d000d0000000e000e000d000f0000000d00 -0d0000000f000d000d000d000e000d000e000e000e000e000e000e0009000e000d000e00 -0e000d000e000e000e000e000e000e000d000e000d000e000d000e000d000e000d001000 -0d000d000d000000000000000d000d000e000d0000000e000d000d0000000d000f000000 -0d000d000e000d000e000d000d0009000e000e000d000e000d000e000d000e000d000e00 -0d000e000e000d000e000e000d000d000d000d0000000d000d000d000400000000001000 -0d000d000d0000000e000e000e000d000e000e000e000d000d000e000d000e000d000e00 -0d000e000d000e000e000d0010000d000d000d000f00000000000d0000000d0000000000 -00000e0000000d000d0000000d000d000e000d000d000d000d000d000e0000000d000000 -00000c000f00110012000000000000000e000f0000000d000e000d000d0000000e000d00 -0d000e000e000d000e000d0000000d000000000011000d000d000d000000000000001100 -0d000d000d000000000000000e000d000e0000000e000e0001000f000d000e0007000d00 -0e000e000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0d0010000e000d000e000d0000000d000d0000000d00000000000d0011000d000d000000 -000000000e000d0000000d000d000d00110000000d000d000d000e000e000d0009000e00 -0d000e000d000e000d000d000e000e000e000d000e000d000e000d000d000d000e000d00 -0d0010000d000d000d0000000d00000000000d000d000e0000000d000e000d0000000d00 -0000000000000000000000000d000d0000000000000011000d000d0000000d0000000000 -0d000d000d000d000f000d000d000d0009000e000d000e000d000e000d000e000e000d00 -0e000e000e000e000e000d000d000d000e000e000d0010000f000d000e000d000f000000 -0d000e000d000d00000011000f000d00110000000d000d0000000d000d000e000e000000 -0d00110000000e000d000f000e000d000f000d000e000f000d000e000d0009000e000e00 -0e000e000e000d000e000d000d000e000d000e000d000d000e000e000e000d000d000e00 -10000d000e000d0000000d000e000d000d000e000e000d000d000d0000000d0000000d00 -0d0011000d0000000d000d000d000d000d000d0000000d000d000d000d000d000f000d00 -0000120011000d000d000e000d000d000d000f000d000e000d0009000e000e000e000e00 -0e000e000e000e000e000e000e000d000e000d000e000e000d000e000e000d0010000e00 -0e000d000e000d0000000d0011000d000e0000000d000e000e0000000d000d0000000d00 -0d0011000e000f000c000f0007000e000e000e000e000e000c000e000e000e000c000e00 -0e000e000e000d000d000d000d000d000d0000000d0012000d0004000000000010001200 -12000d0000000d000d000d000e000e000e000d000d000e000d000e000d000e000d000d00 -0d000e000d000d000f0010000d000e000f0000000d000d00000000000e000d0000000b00 -0f000000110000000d000d000d000d000d000d000d0011000d000d000000000011000d00 -00000d000d0000000d000e000e0000000d000e0001000d000d0000000d000d000e000d00 -0d000d000e000d000d00000000001100110000000d000e0000000d000d000f0000001100 -0d0000000e000d000e0000000d000e0000000e0000000c000f000e000e000a000d000e00 -0e000e000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000f00 -100011000e000d0000000e000d000d00000000000d000d0000000d000d0000000d001100 -0d0000000d00110000000d00110000000b0010000d000d000d000e000e0009000e000e00 -0e000d000e000e000e000d000e000d000e000e000e000e000d000e000d000e000d000e00 -10000f000d000d00000001000d000d0000000d000d00000011000d000e0000000d000d00 -00000f000d00000010000d0000000e000d000e0000000f000d00000000000d000e000000 -0d0011000d000d000f000d000d0009000e000d000e000d000e000e000e000d000e000e00 -0d000e000e000d000d000e000d000e000d000e0010000d000f000d000d000d0000000f00 -0d000d000e0000000e000d000d000d0000000d000e0000000d000d000d000d0000000d00 -0d0000000d000d000d000d000d000e000c000f000c000e000d000f0009000e000e000d00 -0e000d000e000d000e000e000d000e000e000e000e000e000d000e000d000d000e001000 -0d000e000d00000010000d000f000f000c000d000d000d0000000d000e000d0000000f00 -0d000d0000000d000d0011000d000e000d000d00000000000d000d000d000e000d000000 -0d000d000d0012000d000e000d000d000c000e000e000d0009000e000e000e000e000e00 -0d000e000d000e000d000d000d000d000e000d000d000e000d000e000d0010000e000e00 -0d000d000d0000000f000d000b000d0000000d0011000e0000000d0011000b0001001200 -0d0001000c000f000d0009000f000c000e000e000e000e000e000e000e000e000e000d00 -0e000d000d000d000d000d000d00110000000d0012000d00130000000000100012000d00 -0d0000000d000e000e000d000e000e000e000d000d000e000d000e000e000d000e000d00 -0d000e000e000d0010000f000d000e0000000f000d000d0000000d000e00000010000c00 -0000000011000d000d000d000d000d000d000d000d000d000d0000000d000d000d000000 -0d000d000000110012000d0000000d000d000e00000001000d000e000e000d000d000e00 -0e000d000e000d0000000d000d000d0000000d000d000d000d0011000d00000012000e00 -00000d000d000d000e000e000d00000000000d000d000b000f000f0004000f000d000e00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e001000 -0d000d001100000011000d00110000000d000d000d0000000d000d0000000d000d000d00 -00000d000b000d00000000000e000f000d000d0011000d000e000e0009000e000e000e00 -0d000e000e000d000e000e000e000d000e000e000e000d000e000d000d000e000d001000 -0d000d000f0000000d000d000e0000000e000e0000000d000d000d00000011000d000000 -1100110000000b000f0000000d000e00110000000d000d0000000d000d000e0000001100 -0d000c000f000d000d000d0009000e000d000e000d000e000d000e000e000d000e000d00 -0e000e000d000d000e000d000e000e000e0010000e000d000e000e000f0000000e000e00 -0d000e00000000000000000000000d000d000d0000000d000d0011000b0000000f000d00 -0000000000000000010000000d000e000e000f000e000f000e0009000e000e000e000d00 -0d000d000d000e000d000e000d000d000d000e000d000e000e000d000d000e0010000e00 -0f000d00000000000000000000000e000f000d000d0000000d000d000f0000000d000d00 -110000000e000d000d0012000d000d000d0011000d000000000011000d000d0000000000 -00000000000000000d000e000f000d000f000f000e0009000e000e000e000d000d000e00 -0e000e000e000e000d000d000e000e000d000e000e000d000e000d0010000d000e000d00 -0f000d0000000d000d0011000d0000000d000d000d0000000e000d000d0000000d000e00 -0d000d000e000e0008000e000e000e000e000e000d000e000e000e000d000e000d000e00 -0d000d0011000d0011000d000d0000000d000d00120004000000000010000d000d000d00 -00000d000d000d000e000e000e000d000e000e000d000e000d000d000e000d000e000d00 -0e000e000d0010000d000d000d0000000e000d001100000011000d0000000d0011000000 -000011000d0011000d000d000d000d000d000d000d000d0000000d000f000d0000000d00 -0d0000000d000f000f0000000d000d000f00000000000d000e000d000e000e000d000e00 -0d000d000d0000000b000f00110000000f000d000d0000000000000000000e000d000000 -0d000e000d000d000d000e00010000000e000f000e000f000c0009000d000e000e000e00 -0d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000f0010001100 -0d000d0000000d000d000d0000000d000d00110000000d000d00000011000d000d000000 -0d000e000f00000000000d000d000d000d000d000d000e000e0009000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000e000d000d000d000e000e000e0010000e00 -0f000d0000000e000d000f0000000d000e0000000d000f000d0000000d000e0000000d00 -0d0000000d000f0000000e000d000c0000000d000d00000011000d000d0000000d000d00 -11000d000d000d000d0009000e000d000e000d000e000e000e000d000e000d000e000e00 -0d000d000d000e000d000e000d000d0010000e000c000f000e000d0000000d000e000f00 -0b00000011000d000d0000000d000d000d0000000d000d000d00100000000d000d000000 -0d000d000d000d000d000e000e000e000d000d000c000f0007000e000d000d000e000e00 -0d000e000d000e000d000d000e000e000d000e000d000e000d000d000e0010000e000e00 -0d00000010000d000f000e000e000d000d000d000000000000000000000011000d000d00 -00000d0010000e000d0011000d000d000d000d000d000d0000000d000e0000000d000d00 -0d000d000d000d000d000d000d000e000e000e0007000f000e000e000e000d000d000e00 -0d000e000d000d000e000e000e000e000d000e000e000f000e0010000d000e000d000e00 -0d0000000d000e000d000d0000000d000d000e0000000b000d00110000000d000d000f00 -0e000d000d000a000e000c000e000e000e000e000e000e000e000e000e000e000d000d00 -0d000d000d000d000d000d00000012000d000d0004000000000010000d000d000d000000 -0d000d000e000e000d000e000e000d000e000d000d000e000d000e000e000d000e000d00 -0d000e0010000e000e000f0000000d000e000d0000000d000c0000000d000e0000000f00 -00000e000d000f000e000d000d0011000b0011000d0000000d000d000d0000000e001100 -00000d000d000e0000000f000d0000000d000d0000000d000d000e000d000e000d000e00 -0d000e0000000d0011000d0000000d00110000000d000f000d0000000e000d0000001100 -0f000d000d000d000e0000000e0000000d000e000c000f0009000f000d000d000e000d00 -0d000e000e000d000e000d000e000d000e000d000e000d000e000d000f0010000f000d00 -0d0000000d000d000d0000000e000d000d0000000b00100000000e000d000d0000000e00 -0d0000000f000b00000011000d000d000d0011000d000d0007000e000e000e000d000e00 -0e000d000e000d000e000e000e000d000d000d000d000d000e000d000d0010000d000d00 -0e0000000f000d000e0000000e000d00000010000d000d0000000d000d0000000f000d00 -00000e000d0000000d000f000f0000000d000d0000000d0011000e0000000d000d000d00 -11000d000e000e0009000e000e000e000d000e000d000e000e000d000d000e000d000e00 -0e000d000e000c000e000e000d0010000d000e000d000e000d0001000d000d000e000f00 -00000d000e000d000f0000000d00110000000e000d000f000d0000000f000d0000000d00 -0e000d000e000d000e000d000f000f000e000e000e0008000e000d000e000d000e000e00 -0d000e000e000d000d000e000d000d000e000d000e000d000d000e0010000d000e000d00 -00000b000d000e000d000e000d000f0000000d000d000f000e000b0000000d000d000000 -0e000b000d0011000d000e0000000d0011000d000d0000000e000d0000000d000e000d00 -11000e000d0011000e000f000e000e000e0007000e000d000d000e000e000e000d000e00 -0e000e000e000d000e000e000e000e000e000d000e000d0010000e000d000d000e000d00 -01000d000d000d000d0000000d000d000d00000011000e000d0000000e000d000c000d00 -0f000e0007000e000e000e000e000e000e000e000e000e000e000e000e000e000d000d00 -0d0011000d000d000d0000000d000d000d00040000000000100012000d000d0000000d00 -0d000e000d000e000e000d000e000d000e000e000d000e000d000d000d000d000e000e00 -0d0010000d000e000c0000000f000d00000000000e000d0000000d000d0000000e000f00 -00000d000d000d000e000d000d0011000e000f000000010012000d00000011000d000100 -0d001100120000000c0001000e000d000d000e0000000e000d000e000d000e000d000e00 -0d00000001000d000d0001000e000d0000000d000e000d0000000d000e0000000d000d00 -0d0000000f000c0000000f000d0000000d000f000d0007000c000f000e000e000d000e00 -0d000d000e000d000e000d000e000d000e000d000e000d000e000d0010000d000d000f00 -00000e000d000f00000000000f000d0000000f00120000000d000f000d00000011000000 -0f000d000f000f0000000d000d000d000d000e000d0009000e000e000e000d000d000d00 -0e000e000e000e000d000e000e000e000d000d000d000e000d000e0010000e000e000d00 -000000000f000d0000000d00110000000b000f00000000000d000e0000000d000d000000 -0d000d0000000e000d000d0000000d000f0000000d000d000f0000000f000e000d000d00 -0e000e000e0009000e000d000e000d000e000e000e000d000e000e000e000e000e000d00 -0d000e000d000e000e000e0010000f0011000d000e000d0000000e000f000b000d000000 -0e000e000d000d0000000d000d0000000e000d0011000e0000000d000d0000000f000d00 -0f000d000f000e000e000e000c000e000f000d0009000e000d000e000d000e000d000d00 -0e000d000d000e000e000e000d000d000e000e000d000d000e0010000d000e000d000000 -0e000e000d000d000d000e000d0000000d000d000d000d00100000000e00110000000f00 -0e000e000d000d000d0000000d000e000d000e0000000b000f00000011000e000e000d00 -0d000d000d0010000c000e000e000f0009000d000d000e000d000e000d000e000e000e00 -0d000d000e000e000e000e000e000d000e000e000d0010000e000e000d000e000d000000 -0e000d000d00100000000f000d000d00000011000f000d0001000d000d000e000d000e00 -0f0007000c000f000e000e000d000e000c000e000e000e000e000e000e000d000d000d00 -0d000d000d000d00000012000d00120004000000000010000d0012000d0000000e000e00 -0e000e000d000e000d000d000d000e000d000e000d000e000d000e000d000d000d000d00 -10000d000e0010000b00000000000d0000000d000f00000000000d0000000d000d001100 -00000d000e000d000f000d000d000d000d0000000d00000000000f000d000c000e000000 -000000000d000f0000000d000f000f000d0000000e000d000d000d000e000d000e000d00 -00000d00000000000e0011000b000f000000000000000d0000000e000d00010000000000 -0d000d000e0000000c000e00100000000e000e000a000e000c000e000e000d000d000e00 -0e000d000e000d000e000d000e000d000e000d000e000d000f00100011000e000d000000 -0e000d000d0000000e00000000000d000f000d000d000000000000000d000f0000000c00 -0d000e000d0000000e00110000000e000e000d0007000e000d000e000e000e000e000d00 -0e000d000d000e000e000d000d000d000e000d000e000e000e0010000d000d000e000000 -0d00000000000f000d000d000e00000000000e00000010000d0000000000110000000000 -0e000d000000000000000d000e000d0000000f000d000d0000000d000d000d0000000e00 -0e000d0009000e000d000e000d000e000d000e000d000e000e000e000d000e000e000d00 -0e000d000e000d000e0010000e000c000d000d000d0001000d000d0011000e0000000d00 -0d000e000d0000000d000d000d0000000000000000000d000d000d000100000000000000 -000000000f000d000e0001000c000c000e000a000e000d000e000e000d000d000e000d00 -0e000d000e000d000d000e000e000d000e000d000e000e0010000e000e000d0000000e00 -0e000d000d000d000e000d000000110011000d000d000e0000000d000d00000000000000 -000000000d000d000d0000000000000000000e000f000d00000000000000000000000000 -0d000f000c0001000c000d000d0009000e000e000e000e000d000e000d000e000d000e00 -0e000d000d000d000d000e000e000d000e000d0010000d000d000d000e000d0000000d00 -0d0012000d0011000000000000000e000d000d000d0000000f000d0000000e000e000d00 -0a000e000c000d000e000e000e000e000c000e000d000e000d000e000e000d0011000d00 -0d000d000d0000000d000d000d0004000000000010000d000d000d0000000d000d000e00 -0d000e000e000e000d000e000d000e000d000e000d000e000d000e000d000d000f001000 -0d000e000d000e000e000d000d0000000d000d000e000d0011000d000d000e000e000d00 -0d000d000e000d000d000d000d000d000d000d000d000d000f000d000e000d000d000e00 -0d000f000d000e000d000d000d000f000d000d000e000d000e000d000e000d000e000000 -0d000d000d000e000d000d000d0011000d000d000e000d000d000f0012000d000d000d00 -0d000f000d000e000f000c000f000d000e0007000f000d000e000e000e000d000d000d00 -0e000d000e000d000e000d000e000d000e000d000e000d0010000d000d000d000d000000 -0d000d000f000d000e000d000d000d000e000d000d000d000d000f000d000d0011000d00 -0d000d000f000d000d0000000d000e000e0009000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000d000d000d000f000e000e0010000e000f000d000d000f00 -0e000d000d0011000d000d000d000d000e000e000d000d000e000e000d0011000d000d00 -0e000d0011000b000f000d000d000f000d000d000e000d0011000d000d0000000d000e00 -0d0009000e000d000e000d000e000e000e000e000e000e000d000e000e000e000d000e00 -0d000e000d000d0010000d000d000e000e000d000d000f000d000d000e000d000d000d00 -0d000d000f000e000d00110011000d000d000f000d000d000e000c000d000f000d000d00 -0e000e000f000e0000000e000f000d0009000e000d000d000d000e000e000d000e000d00 -0e000e000d000e000e000d000e000e000d000d000f0010000d000e000d000d000e000d00 -0d000f000e000d000d000d000d000d000e000d000d000d000d000d000e000e000d000e00 -0e000d000f000d000d000d000d000d000d000d0011000d000f000f000d000d000f000c00 -0d000f0000000f000e000e0009000d000e000d000e000e000e000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000e0010000d000e000d000d000d000d000d000d00 -11000d000d000f000d000d000f000d000d0000000e000c000f0000000e000d000d000700 -0e000e000e000e000e000e000e000e000e000e000e000e000e000d000e000d000d000d00 -0d000d0000000d0012000d00130000000000100012000d000d00000011000e000e000d00 -0e000d000d000e000d000e000d000e000d000e000d000e000d000e000d000d0010000e00 -0d000d0000000e000d000d0000000d000d000d000e000e000f000d000d000f000d000000 -0000000000000000000000000d000e000e000d000d000d000d000e000d000e000e000e00 -0d000d000d000d000d000e000d000e0000000000000000000000000000000d0000000d00 -0d000d000e000e000f000d000d000d000d000e000e000d000e000e000d000d000d000e00 -0d000e000e000d000e000e000d000e0009000d000f000d000e000d000d000e000d000e00 -0d000e000e000d000e000d000e000d000e000d000e0010000f000d000d000e0000000e00 -0d000e000d000e000e000d000e000d000e000e000d000d000e000d000e000e000d000e00 -0d000d000f0000000d000e000e000d0009000f000d000e000e000e000d000e000d000e00 -0d000e000d000e000d000f000e000d000d000d000e0010000f000d000d000d000d000d00 -0e000e000e000e000e000d000e000d000d000d000d000d000d000e000d000e000d000e00 -0e000d000e000e000e000d000d000d000d000e000d000d000f0000000d000e000f000d00 -09000e000d000e000e000e000e000e000e000e000e000d000e000e000d000f000d000d00 -0d000d000f0010000f000d000e000e000e000d000d000d000e000d000e000e000e000d00 -0d000d000e000e000e000e000d000e000d000e000d000d000d000d000e000d000e000e00 -0e000d0000000e000e000f000d0009000d000e000d000d000e000d000f000d000e000d00 -0e000d000e000d000d000e000d000d000d000d0010000e000d000d000d000d000d000d00 -0d000e000e000d000d000d000d000d000d000d000d000e000e000e000e000d000e000d00 -0e000e000e000e000e000d000d000e000d000e000d000d000e000d000e000e000e000d00 -00000e000f000c000e0009000e000d000d000e000e000e000d000e000d000e000e000d00 -0d000e000d000d000e000e000d000d0010000d000d000d000d000e000d000e000d000e00 -0d000e000d000e000e000c000e000f0000000f000d0000000e000e000d000d0009000f00 -0e000e000d000e000e000e000e000e000d000e000d000e000e000d000d000d000d000e00 -0d0000000d0012000d0004000000000010000d000d00120000000d000e000e000e000e00 -0e000e000d000d000e000e000d000e000d000e000d000e000d000f000d0010000d000f00 -0e000d000000000001000d000d000f000d000d000d000c000d000e000e000f000b001000 -0d000f000f000f000c000f000d000d000d000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000d000d000f000d000d000f000c000f0000000b000e00 -0f000d000c000d000e000e000e000e000e000e000e000e000e000d000d000e000e000e00 -0e000e000e000e000d000d000e0009000c000e000d000e000d000d000e000e000d000d00 -0d000d000e000d000e000d000e000d000e000f0010000d000f000f000e000d0000000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000d000f000d00 -0d000d000b000e000d000f000f0009000d000c000d000e000e000e000e000e000d000e00 -0e000e000e000d000e000d000d000f000d000e0010000f000d000e000e000d000d000d00 -0d000e000e000e000e000e000e000e000f000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000f000d000f000d000e000d000c000e000e000e000e000900 -0e000d000e000e000d000e000d000e000d000d000e000e000d000d000d000d000d000f00 -0e000f0010000d000d000d000d000e000e000e000e000e000e000e000e000e000e000e00 -0f000e000e000e000e000e000e000e000e000d000d000d0011000e000e000e000e000d00 -0f000d000d000f000d000d0007000e000f000e000e000f000d000d000d000e000d000d00 -0e000d000e000e000d000d000e000e000e0010000d000d000e000d000e000e000d000e00 -0e000f000e000d000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000d000f000f0007000e000d000e000e000d000d000e000e000e000e000e000d000e00 -0e000d000d000d000d000d000d0010000d000f000d000d000d000e000e000e000e000e00 -0e000e000e000d000f000d0000000f000d000d000f000d000e000e000e0007000c000e00 -0f000e000e000e000d000e000d000e000e000e000d000d000e000e000d000d0011000d00 -00000d000d00120004000000000010000d0012000d0000000d0011000e000d000d000e00 -0e000d000e000d000d000e000d000e000d000e000d000e000d000f0010000f000d000d00 -0d000e000d000e000d000d000d000e000d000d000e000f000d000d000d000d000e000d00 -0d000d000d000e000d000d000e000e000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000f000d000d000f000e000d000d000f000d000d00 -0e000f000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000f000d000e000d0009000e000e000e000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000d0010000f000c000e000d000d000e000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000e000d000d000d000e000d00 -0d0010000d000d000c000f0009000f000e000d000e000d000e000e000d000e000e000e00 -0d000e000e000e000d000d000d000d000d0010000d000d000e000f000e000f000f000e00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0e000e000d000d000d000d000d000d000e000d000e0010000d000d000e000e0009000e00 -0d000e000e000e000e000d000e000e000e000d000d000e000e000e000d000d000d000d00 -0d0010000e000e000d000e000e000d000d000d000d000d000e000e000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000c00 -10000d000e000e000d000a000d000d000d000d000d000d000f000e000d000e000d000d00 -0e000d000d000e000d000d000d000d0010000e000f000e000d000d000d000d000d000d00 -0d000e000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000e00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000e000c00 -0e000f000c0009000f000e000e000e000d000e000e000e000d000e000e000d000d000e00 -0d000e000e000e000f000e0010000d000d000d000f000f000d000d000d000d000d000d00 -0d000d000d000d000d000d000e000f000d000d000e000e000d000d0009000e000e000d00 -0d000e000d000e000e000e000e000e000e000e000d000d000d000d000d000d000d000000 -12000d000d0013000000000010000d000d000d0000000d000d000e000d000e000d000e00 -0e000d000e000e000d000e000d000e000d000e000d000d000e0010000d000f000d000d00 -0e000d000f000d0011000e000d000d000f000d000d000d000e000e000e000d000e000f00 -0d000d000e000d000d000d000d000e000e000e000e000e000e000e000e000d000e000d00 -0e000e000e000e000e000d000d000d000f000d000c000e000e000e000d000d000d000d00 -0d000d000d000e000e000e000e000e000e000e000e000d000d000e000d000e000e000e00 -0e000d000d000d000d0009000e000d000e000e000d000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000f0010000d000f000b000f000d000d000d000e000d00 -0e000e000e000e000e000e000e000e000e000d000e000e000e000e000d000e000d000f00 -0b000d000e000e000f0007000e000e000e000e000e000e000d000e000d000e000d000e00 -0e000d000e000d000d000e000d000f0010000d000e000d000d000d000d000d000e000e00 -0e000e000e000e000e000e000e000e000d000e000d000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000d000e000d000f000b000e000e000e000e0009000e000d00 -0e000e000e000d000e000e000d000d000e000e000e000d000e000d000d000d000d000f00 -10000d000d000d000d000d000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000f000e000d000d000d000d000e000e000e000e000f000d000b00 -0f000e000e000d0009000f000e000d000d000d000d000e000f000e000d000e000d000d00 -0d000e000d000f000e000d000e0010000f000e000d000e000e000e000e000d000d000d00 -0e000e000e000d000e000e000e000e000f000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000f000d00 -0f000f000a000c000d000e000d000e000d000e000d000e000e000e000d000e000e000d00 -0d000e000d000d000f0010000f000d000d000d000d000e000e000e000d000e000e000e00 -0e000f000e000f000e000d000d000d000d000d000e000d000e0009000d000e000e000e00 -0d000e000d000e000d000e000d000e000e000d000d000d000e000d000d000d0000000d00 -0d00120013000000000010000d000d000d0000000d000d000e000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000e000d0010000d000d000d000f000d00 -0f000c000f000d000d000f000f000d000e000f000f000d000e000f000e000e000d000d00 -0d000d000d000d000d000e000f000e000e000e000e000e000e000e000e000e000e000f00 -0e000e000e000d000d000f000e000d000e000e000e000d000d000d000f000f000e000d00 -0d000e000f000e000e000e000e000e000e000e000e000e000e000e000e000e000d000e00 -0d000d000e000c000a000e000e000e000e000e000d000e000d000e000d000e000e000d00 -0e000d000e000d000e000d000d0010000d000e000f000d000f000d000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000f000d000d000d000d00 -0f000d000f000d0008000e000e000e000d000d000e000e000e000e000d000e000d000e00 -0d000e000e000d000d000e000e000f000d000f000f000d000d000e000d000e000d000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000d000f000d000d000d000d000f000d000d000d000a000e000e000d00 -0e000d000e000d000d000e000e000e000d000e000d000e000e000d000d000e000f000f00 -0d000e000f000f000d000e000d000d000e000e000e000e000e000e000e000e000d000e00 -0e000e000e000e000e000e000d000d000e0011000e000e000e000e000d000e000d000e00 -0f000d000f0009000d000d000e000e000e000e000e000d000d000e000e000d000e000d00 -0e000d000d000d000d000e0010000e000f000d000d000d000d000e000f000e000d000d00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000d000f000e000e000e000e000e000e000f000e000e000e000e000d000f000d000c00 -0e0007000d000e000e000e000e000e000d000e000d000e000e000d000d000d000d000d00 -0d000d000d000e0010000e000f000e000f000f000e000e000e000f000e000e000e000d00 -0d000d000d000d000e000f000e000d000e000e000d000e000a000e000e000e000d000e00 -0e000e000d000e000d000e000e000d000e000e000e000d000d000d000d0000000d001200 -0d0004000000000010000d0012000d0000000d000d000e000e000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000d000d00080009000900090009000a000800 -0a0009000a000800090009000900090009000a0008000900090009000900090009000a00 -09000a000900090009000900090009000900090009000900090009000900090009000900 -09000900090009000a000900090009000900090009000a00090009000900090009000900 -090009000900090009000900090009000900090009000900090009000900090009000900 -09000a000a0009000b000e000e000e000d000e000d000e000d000e000d000d000e000d00 -0e000d000e000d000e000e000a00090009000900090009000a0009000900090009000900 -09000900090009000900090009000900090009000900090009000900090009000a000900 -09000800090009000f000c000e000d000e000e000d000e000d000e000d000e000d000d00 -0e000d000d000d000d000b000a0009000900090009000a00090009000900090009000900 -090009000900090009000900090009000900090009000900090009000900090009000900 -090009000900090009000900090009000a000900090009000a0009000d000f000c000f00 -0f000d000e000e000e000e000d000e000e000d000e000d000d000d000d000d000a000900 -090009000900090009000900090009000900090009000900090009000900090009000900 -0900090009000900090009000900090009000900090009000900080008000a0009000900 -09000a0008000e000e000f000c000e000e000e000d000e000d000d000e000d000e000e00 -0d000d000e000d000d000a00090009000900090009000900090009000900090009000900 -090009000900090009000900090009000900090009000900090009000900090009000900 -0900090009000900090009000900090009000900090009000900090009000a0009000700 -07000e000e000e000d000e000d000e000d000e000d000e000d000e000d000d000e000f00 -0f000e000d000a0009000900090009000900090009000900090009000900090009000a00 -0900090008000a00080009000a000900090008000a0008000e000e000d000e000e000e00 -0d000e000d000e000e000d000e000d000d000d000d000d000d000d0000000d000d000d00 -130000000000100012000d000d0000000d000d000e000e000e000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000f000d0010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010000f000b000e000e000e000d000d000e000e000d000d000d000e000d000e000d00 -0e000d000e000d000d000f00100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -10001000100010000a000d000c000e000d000e000e000e000d000e000d000e000d000d00 -0d000e000e000f000e000d000f0010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -1000100010001000100010001000100010001000100010001000100010000a000d000c00 -0e000e000e000e000e000d000e000e000d000d000d000e000d000f000d000d000d000f00 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010000a000e000d000d000e000d000e000e000d000d000e000d000e00 -0d000e000e000f000d000d000f000e001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100009000c000e000f000d00 -0e000e000d000e000d000e000d000e000d000e000d000d000d000e000d000f0010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -10001000100010001000100010001000100010000a000d000e000e000d000e000d000e00 -0d000e000d000e000e000d000d000e000d000d000d000d00110000000d00120012000400 -0000000010000d000d000d0000000d000e000e000e000e000e000e000d000e000d000e00 -0d000e000d000e000d000e000d000d000f0010000d000e000d000f000d000e000e000d00 -0f000d000e000f000d000e000f000d000e000e000e000e000d000d000d000f000f000d00 -0d000e000e000e000e000f000e000e000f000e000e000e000f000e000e000f000e000e00 -0f000e000d000f000e000d000f000e000d000e000e000d000d000f000d000f000e000e00 -0e000f000e000e000f000e000e000e000e000e000e000f000e000e000e000e000d000d00 -0f000f0009000d000e000d000d000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000e000d0010000d000f000d000e000e000e000e000f000e000f000e000f00 -0e000f000e000e000e000e000e000e000e000e000e000d000e000d000f000d000e000e00 -0e000e000d0007000e000e000d000e000e000e000d000e000e000e000e000e000d000e00 -0e000d000d000e000f000e0010000f000d000f000e000d000f000f000e000e000e000e00 -0f000f000e000e000e000e000e000f000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000d000f000d000f000d000d000e000e000f000e000e0009000e000f000e00 -0d000e000d000e000e000e000d000e000d000e000e000d000d000e000e000d000f001000 -0f000f000d000e000e000e000e000e000e000e000f000e000e000f000e000e000e000e00 -0e000e000d000f000e000e000e000e000e000f000e000d000f000d000f000d000e000d00 -0e000d000e000e0009000d000d000d000e000e000d000d000e000d000d000e000d000e00 -0d000d000e000d000d000f000d0010000f000d000e000e000f000e000d000e000e000e00 -0e000e000e000f000e000e000e000f000e000e000e000f000e000f000e000e000e000e00 -0e000f000e000e000f000e000e000f000e000e000e000e0007000f000e000e000f000c00 -0e000e000d000e000d000e000e000e000e000e000d000e000d000d000e0010000f000d00 -0f000e000f000d000d000e000e000e000f000e000e000f000e000e000e000e000f000d00 -0e000d000f000e000d000e000f000e000e0009000e000e000e000e000e000e000e000e00 -0d000e000e000e000e000e000d000d0011000d000d000d00000012000d000d0004000000 -000010000d000d000d0000000d000d000d000d000e000d000d000d000e000d000d000e00 -0d000e000d000e000d000e000d000e0010000d000e000d000d000d000d000d000d000e00 -0e000d000d000e000d000d000f000d000d000e000d000d000d000e000e000d000d000e00 -0c000e000e000d000d000e000e000d000d000d000e000d000d000d000e000d000d000d00 -0d000d000d000d000e000d000d000e000d000f000d000e000d000d000d000d000d000d00 -0f000d000d000e000d000d0011000d000d000d000d000d000d000d000d000e000d000f00 -0c0009000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000d000e0010000d000e000d000d000d000d000d000e000e000d000d000d000e00 -0d000f000e000d000d000e000d000e000d000d000e000d000e000e000d000e000d000e00 -0e000e0007000d000e000d000e000d000e000e000d000e000e000e000d000e000d000e00 -0d000e000e000d000d0010000e000e000d000e000d000e000d000d000d000e000d000e00 -0d000e000d000e000d000d000f000e000e000d000d000d000f000d000e000d000d000d00 -0d000f000d000e000d000d000d000d000e000d000e000e000e0009000d000e000e000d00 -0e000e000e000e000e000e000d000e000d000e000e000d000e000d000e000d0010000e00 -0d000d000f000d000d000e000d000e000d000e000d000e000d000d000d000e000f000d00 -0f000d000d000d000e000d000e000e000d000e000e000d000d000e000d000d000e000d00 -0e000e000e0009000e000e000e000e000e000d000e000d000e000d000e000d000e000e00 -0e000d000e000e000d000e0010000d000d000e000d000e000e000d000d000f000d000d00 -0e000d000d000d000d000d000d000e000d000e000d000d000d000d000e000d000d000e00 -0e000e000d000e000d000d000d000e000d000d000e0009000e000e000e000d000e000e00 -0e000e000e000e000d000e000e000e000d000d000e000d000d000e0010000d000d000e00 -0d000d000d000d000d000d000d000f000d000d000d000d000d000e000e000d000e000d00 -0d000f000d000e000d000e000e000e0007000d000e000d000e000d000e000e000d000e00 -0e000e000d000e000d000e000d000d000d000d000d00000012000d001200040000000000 -10000d0012000d0000000d000d000e000d000e000e000d000e000d000e000e000d000e00 -0d000e000d000e000d000d000d0010000d000d000f000e000d000e000e000d000d000d00 -0f000d000d000d000d000b000d000e000d000e000e000e000d000d000f000d000d001000 -0b000d000e000f000d000d000f000e000d000d0010000d000e000d000d000e000e000f00 -0d000e000d000d000e0010000d000d000d000e000d000d000f000e000e000e000d000d00 -0d000e000d000f000d000d000d000d000d000f000d000d000d000d000d000d000d000e00 -09000f000d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000e000d0010000d000e000f000e000d000d000f000e000b000f000d000f000d000f00 -0d000d000f000d000d000d000d000d000d000e000d000f000d000e000d000e000e000e00 -0e0009000e000e000d000e000e000e000d000e000e000e000d000e000d000e000d000e00 -0d000d000e000e0010000d000f000d000d0010000c000d000f000d000d000d000d000e00 -0d000d000f000d000e000d000b000e000e000f000d000d000e000d000f000e000d000d00 -0d000e000d000d000f000e000e000e000d000e000e000e0007000d000e000d000e000d00 -0d000e000d000e000d000e000d000d000d000d000e000d000e000d000f0010000e000e00 -0d000e000d000d000e000f000d000d000d000d000d000e000f000d000f000d000e000c00 -0f000f000f000d000d000e000d000c000e000d000f000e000e000d000e000d000f000e00 -0e000e0009000e000e000e000d000d000e000d000e000d000e000d000d000e000d000d00 -0e000e000d000e000d0010000f000f000e000d000d000d000d000f000b000f000e000d00 -0f000d000e000d000d0010000d000d000f000d000d000f000f000d000d000d000d000e00 -0d000e000e000d000e000e000e000d000d000e0009000e000e000d000d000e000e000e00 -0d000e000d000e000e000e000d000e000d000e000d000d000f0010000e000e000d000d00 -0f000f000d000e000d000e000d000d000f000d000e000c000d000d000d000d000d000d00 -0e000d000e000e000e000e000e0009000e000e000d000e000e000e000d000e000e000e00 -0d000e000d000e000d000d0011000d000d000d0000000d0012000d000400000000001000 -0d0012000d0000000d000e000d000e000e000e000d000e000e000d000d000e000d000e00 -0d000e000d000e000f000d0010000f000d000d000d000d000d000e000c000e000e000d00 -0f000f000d000d000e000d000e000f000d000d000e000d000e000d000d000d000e000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000e000f000c000d000d00 -0d000e000e000d000d000d000e000d000d000e000d000d000d000d000d000d000e000d00 -0e000d000d000d000e0011000d0011000f000d000f000d000e000e000e0010000d000800 -0d000f000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0f000d0010000e000d000d000d000d000d000d000d0010000d000d000d000d000b000d00 -0f000d000f000d000d000e000f000d000d000e000d000f000d000e000d000e000d000e00 -09000e000e000e000e000e000d000e000d000e000e000d000d000e000d000e000d000e00 -0e000d000e0010000e000d000d000d000e000d000d000e000e000d000f000e000d000e00 -0e000d000d000f000d000e000e000d000f000d000e000d000d000d000e000d000e000d00 -0d000e000d000d000d000d000e000d000e000e000e0009000d000e000e000d000e000e00 -0d000e000e000e000e000d000e000d000e000d000e000d000f000d0010000d000d001000 -0d000f000e000d000c000e000f000e000f000d000c000f000f000d000d000e000f000d00 -0d000d000d000f000d000e0010000d000d000e000e000b0010000d000d000d000e000e00 -0d0009000e000d000e000e000e000d000e000d000d000d000d000d000d000e000e000d00 -0e000d000d000e0010000f000d000d000d000f000d000e000d000f000d000b000d000e00 -0e000d000d000d000b0010000e000b000d000f000d000d000e000f000f000d000e000e00 -0f000b000f000d000b000e000d000f000d0007000d000e000e000d000e000e000d000e00 -0d000e000d000e000d000e000d000e000d000d000d000d0010000f000f000b0010000d00 -0b000d000d000d000d000d000f000d000d000d000f000f000d000e000d000d000f000e00 -0d000d000d000e000d000e0009000e000e000e000e000e000d000e000d000e000e000d00 -0d000d000e000e000d000d000d0011000d0000000d000d000d0004000000000010000d00 -0d000d0000000d000e000d000e000e000e000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d0010000f000d000e000d000e000e000d000e000f000d000d000d00 -0d000d000d000e000f000d000d000f000e000d000d000d000f000d000d000d000d000e00 -0d000e000d000d000f000d000e000e000d000e000f000d000e000d000f000e0010000d00 -0c000f000f000d000d000d000d000d000d000d000e000e000e000d000e000d000f000d00 -0e000d000d000d000d000d000d000d0011000c0011000d000e000d000b000f0009000f00 -0d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0d0010000e000d000e000d000f000d000d000d000d000d000d000f000d000f000d000d00 -0d000d000d000e000d000d000d000e000e000e000d000e000d000d000e000e000d000900 -0e000e000e000e000e000d000e000e000e000d000e000e000d000e000d000e000d000d00 -0e000d0010000d000f000d000d000d000e000f000b000e0010000b000d000d000d000d00 -0d000e000d000d000d000e000d000b000e000d000d000e000e000d000e000d000d000d00 -0d000d000e000e000e000e000d000e000e000e0009000d000e000e000e000e000d000e00 -0e000e000d000d000e000d000e000d000e000d000e000d000f0010000f000d000e000c00 -0d000d000d0011000d000e000d000d000d000d000e000d000d000d000e000d000e000e00 -0d000e000d000d000d000b000f000d000d000e000e000d000d000f000d000e000e000d00 -09000e000e000e000d000d000e000d000e000d000e000d000e000e000d000d000e000d00 -0e000d000e0010000d000d000d000e000d000d000f000e000d000f000e000f000d000e00 -0d000e000e000e000d000d000d000d000d000f000d000e000b000d000f000d000d000d00 -0d000e000e000e000d000e000d000e0009000e000e000e000d000e000e000e000d000e00 -0d000e000d000e000d000d000d000e000d000d000d0010000d000d000e000d000e000f00 -0f000d000d0010000d000d000d000d000f000d000d000f000d000d000f000b000d000d00 -0d000d000e000e000d0009000e000e000e000e000e000d000e000e000e000d000e000d00 -0d000e000e000d000d000d000d00110000000d000d000d00040000000000100012000d00 -0d0000000d000e000d000e000e000e000d000d000e000d000d000e000d000e000d000e00 -0d000e000d000d0010000d000e000f000d000d000d000d000f000d000d000d0000000e00 -0d0000000d000d000f000d000d000d000e000d000f000b000f000f0000000e000e000d00 -0d000e000e000d000d000e000d000d000f000d000d000d000f000d000d000d000d000f00 -0d000b000e000f000d0010000d000d000d000e000f000d000f000d000d000f000f000b00 -10000d000d000d000d000d000d000e0000000e000f000d000d000f000d0009000d000e00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000d000e00 -10000d000e000f000d000d000d0000000d0000000f000d000d000d000d000e000e000d00 -0d000e000d000e000d000f000c000d000d000e000d000e000d000e000e000e0009000d00 -0e000d000e000e000d000e000e000e000d000e000d000e000d000e000d000e000d000d00 -0e0010000f000d000f00100000000e000d000e000d000e000f000d000e000d000e000d00 -0f000d0001000d000d0000000f000f000d000d000e000d000d000d000d0010000d000d00 -0d000e000f000d000e000d000e000d000e0009000e000e000d000e000d000e000e000e00 -0d000e000d000e000e000d000e000d000e000d000f000d0010000d000d000d0001000000 -000000000000010000000d00000000000000000000000f000e000d0000000d000b001000 -0c0000000d000f000000000000000000000000000d000e000d000e000e000e000e000900 -0e000e000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000e00 -0d000e000f000f000d000e0000000100000000000000000000000e000000000000000000 -00000d000d000b0000000f000e000f000d0000000c001000000000000000000000000100 -0d000e000d000e000d000e000e0009000e000e000e000d000e000e000e000e000e000d00 -0e000e000d000e000d000e000e000d000d000d0010000e000d000d000e000e000d000c00 -01000d000c000e000e000e000000000000000d000d0000000f000d000e000d000f000d00 -0d000e000e000e0009000e000e000d000e000e000d000e000e000e000d000e000e000d00 -0d000e000d000e000d000d000d00000012000d00120004000000000010000d000d000d00 -00000d000e000e000d000e000e000e000d000d000e000e000d000e000d000e000d000e00 -0d000e000e0010000d000d000d000d000e000f000d000d000d000f000f0000000d000d00 -01000d000e000d000f000d000d000f000d000d000d000e000b0000000f000d000f000d00 -0e000d000d000f000d000d000f000d000d000e000d000d000e000e000f000d000d000e00 -0d000d000d000e000d000d000f000e000d000e000d000d000d000f000b000e000f000b00 -0d0011000d000d000d000d000d0000000d000d000e000e000d000d0009000e000d000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000e000e001000 -0d000d000d000d000e0000000d000f0000000d000e000d000e000d000e000d000d000e00 -0d000d000e000e000d000e000e000d000f000f000d000d000e000e000e0009000d000e00 -0d000e000e000e000d000e000d000e000e000e000d000e000d000d000e000e000d000f00 -10000d000e000d000c0000000f000f000e000d000d000d000e000c000f000e000f000b00 -0f0000000d000e0000000d000d000d000f000d000d000e000d000e000d000d000f000d00 -0d000f000d000e000d000e000d000e0009000e000e000e000e000e000e000e000d000e00 -0e000e000d000d000e000e000d000d000e000d000f0010000f000d000d000d000d000f00 -00000d000d000d000f0000000d000d000d000d0000000d000e0000000e000e000e000d00 -00000f000d0000000d000e000e000d000e000d000e000d000d000e000e000e0009000e00 -0d000e000d000d000e000d000e000d000e000d000d000d000e000d000e000d000e000e00 -0d0010000d000f000e000d000d000e0000000d000d000f000e0000000f000e000d000d00 -00000f000f0000000d000d000d000d0000000d000d0000000d000e000d000d000d000d00 -0e000d000d000f000d000e0009000e000e000e000d000e000e000e000d000d000e000e00 -0e000e000e000e000d000e000d000d000e0010000f000e000d000f000d00000000000000 -0f000e000d000f0000000d000e000e0000000d000d00000010000d000d000d000e000d00 -0e000e000e0009000d000e000e000e000e000e000d000e000d000e000e000e000e000d00 -0e000d000d000d000d000d0000000d000d000d0004000000000010000d0012000d000000 -0d000d000d000e000e000e000d000e000e000d000d000e000d000e000d000e000d000e00 -0d000d0010000f000e000d000f000d00000000000d0001000d000000000000000d000000 -0e000d0000000d000d000e000d000d000f000d000f000f0000000e00000000000f000e00 -0d000f000000000000000d000f0000000e000d000d000e0000000b000f000d000e000e00 -0e000d000d0001000d00000000000f000b000f000d000000000000000e000e000d001000 -0000000000000d0011000d0000000e000e0000000f000d000f0009000d000e000e000d00 -0e000d000e000d000d000d000e000d000e000d000e000d000e000d000d000d0010000f00 -0e000d000f000d0000000f000c0000000d00000000000d000f000d000d00000000000100 -0d000d0000000e000d000f000d0000000f000d000d000e000e000e0009000e000e000d00 -0e000e000d000e000e000e000e000d000d000e000d000e000e000d000d000e000d001000 -0f000d000e00100000000e00000000000e000f000d0000000d000d000d0000000f000000 -000000000000000000000d000f000000000001000d000e000d0001000d00000000000f00 -0b000f000e000d000e000e000e0009000d000d000e000e000d000e000e000e000e000d00 -0d000e000d000d000d000e000d000d000e000d0010000e000d000f000d000e000d000000 -0f000d000e000f0000000e000d000e000e0000000d00100000000e000e000d000e000000 -0d000d0000000f000d000d000f000d000e000d000f000d000e000e000e0009000e000d00 -0e000e000e000d000e000d000e000d000d000d000e000d000e000d000e000d000d000e00 -10000d000e000d000e000d000f0000000e000f000d000d0000000e000d000f000e000000 -0d000d0001000d000d000e000d0000000f000d0000000e000d000e000f000d000e000d00 -0d000f000d000d000e0009000e000d000e000d000e000e000e000e000e000e000e000e00 -0e000e000d000d000e000d000d000e0010000d000d000f000e000d000d000f0000000d00 -0e000d000d0000000d000d000d0000000e000e0000000d000d000f000d000e000d000e00 -0e000e0009000e000e000d000e000e000d000e000e000e000e000d000e000e000d000d00 -0e000e000e000d000d0000000d0012000d0004000000000010000d000d00120000000d00 -11000e000d000e000e000e000d000d000e000e000d000e000d000e000d000e000d000d00 -0f0010000f000d000f000d0000000d000f00000000000d000e0000000f000d0000000d00 -00000e000d000d000d000d000e000d000d000d000d00000000000e000e0000000d000d00 -00000e000e000e0000000d000e0000000d000e0000000d000f000d000e000e000d000e00 -0d000e00000000000d000d0000000d000d0000000e000d000e0000000e000d0000000d00 -0f000d0000000d000d0000000d0000000e000d000e000e0009000e000e000d000e000d00 -0e000d000e000e000d000d000e000d000e000d000e000d000e000d000f0010000f000d00 -0e000d0000000d000f000e00000000000d000e0000000d000e0000000d000d000d000000 -0e000e0000000d000d0000000f000d000e000d000e000e000e0009000e000e000d000e00 -0d000e000d000e000d000d000e000e000d000e000d000d000d000e000e000d0010000d00 -0d000d000e00000000000d000e0000000d000e0000000e000e000e0000000d000e000000 -0f000d0000000d000f0000000f000e000d0000000d000e00000000000d000d0000000d00 -0d000e000d000e000d000e0007000d000e000d000d000e000e000d000e000d000e000e00 -0d000d000e000e000d000e000d000e000d0010000d000d000d000f000d000d0001000c00 -0e000d000d0000000d000e000d000d0000000f000c0000000d000d000e000e0000000e00 -0f0000000d000d000e000d000e000d000d000d000d000e000e000d0009000e000e000e00 -0d000d000e000d000e000e000d000d000d000d000e000d000e000d000e000e000d001000 -0f000c000f000d000d000d0000000d000d000d000f0000000d000e000d000d0000000d00 -0f0000000d000e000d000d0000000d000d0000000f000d000d000d000f000d000e000d00 -0d000d000d000e0007000d000d000d000d000e000e000e000d000e000d000e000d000e00 -0d000d000d000e000d000d000e0010000d000d000d000d000e000e000e0000000f000d00 -0f000d0000000d000e000e0000000d000d000e0000000d000d0000000d000d000e000d00 -0e0009000e000e000e000e000d000e000d000e000d000d000e000e000e000d000d000d00 -0d000d000d000d00000012000d000d0013000000000010000d000d000d0000000e000d00 -0e000d000e000d000d000e000d000e000d000d000e000d000e000d000d000e000e000d00 -10000f000e000c00100000000d000d00100000000d000d0000000d000e00000000000d00 -0e000e000d000e000e000d000d000e000d000d0000000e000d000e0000000e000d000000 -0e000d000e0000000d000f000e00000000000d000e000f000d000d000d000d000f000d00 -0d0000000d000f000d0000000e000d000e000d000d000f0000000e000e0000000e000b00 -11000d000d000e00000000000d000f000d000d000d0009000e000d000d000e000d000e00 -0d000d000d000e000e000d000e000d000e000d000e000d000d000d0010000d000f000d00 -0e0000000d000f000d0000000d000e000f0000000d000d0000000d000f000d0000000e00 -0d000d00000000000e000d000d000e000e000e000e000f0007000f000d000e000d000e00 -0d000e000e000e000e000e000d000e000d000e000d000e000d000e000e0010000f000d00 -0d000d0000000d000d000e0000000d000d0000000e000d000e0000000e000e0000000f00 -0d0000000e000d0000000d000d000d0000000d000e0000000d000f000d0000000e000d00 -0d000e000e000e000e0009000d000f000e000d000e000e000d000e000e000d000e000d00 -0e000d000e000d000e000d000e000d0010000e000f000d000e000d000d0000000d000f00 -0d000d00000000000000000000000d000d000e0000000d000d000f000d0000000e000d00 -0000000000000000000000000e000d0010000d000e000e000d0007000e000d000e000d00 -0e000e000e000d000e000d000d000d000e000d000e000d000e000d000e000d0010000e00 -0f000d000f000d000e0000000e000e000d000d00000000000000000000000d000d000d00 -00000f000d000d000d0000000e000d000000000000000000000000000d000d000f000d00 -0e000e000d0009000d000e000e000d000e000e000d000e000d000e000e000e000e000e00 -0e000d000e000d000d000d0010000e000d000d000d000d000d00100000000f000d000e00 -0d0000000d000d000e0000000e000e000d0000000d000d000e000e000d000e000d000e00 -07000e000e000e000d000e000e000d000e000d000e000e000d000e000d000e000d000d00 -0d0011000d0000000d000d0012000400000000001000120012000d0000000d000e000d00 -0e000e000e000e000d000e000e000e000d000d000e000d000e000e000d000d000f001000 -0b000d000f000d0000000e000e000b0000000f000e0000000f000d00000001000d000d00 -0e000e000d000d000f000d000d000d000e0000000d000e000e0000000f000f0000000e00 -0d000d0000000e000d000f00000000000d000d000d000f000d000f000d000d000e000e00 -00000d000d000d0000000d000d000d0001000000000000000d000d0000000d000d000d00 -0d000e000d00010000000e000e000f000d000d0008000e000d000e000d000e000d000d00 -0e000e000d000d000e000d000d000e000e000d000e000e000d0010000d000d000d000d00 -00000d000e000c0000000f000d000d0000000e000d0000000d000d000d0000000e000f00 -0e00000000000d000e000f000d000e000f000e000c00090010000d000d000e000d000e00 -0e000d000e000d000d000e000d000e000d000e000d000e000d000d0010000e000d000e00 -0d0000000d000e000e0000000f000e0000000e000e000f0000000e000d0000000d000d00 -00000d000e0000000d000d000e0000000e000d0001000d000d000f0000000d000e000e00 -0e000e000e000e0007000f000e000d000e000d000e000e000e000e000d000d000e000d00 -0e000d000e000d000e000d000d0010000d000e000d000e000d000e0000000e000d000d00 -0f0000000d000d000e0000000e000e000d0000000d000f000c000f0000000e000d000000 -0d000d000d000e000e000d000f000c000f000e000e000e0009000e000e000e000d000e00 -0d000d000e000e000d000d000d000d000e000d000e000d000e000d000e0010000e000d00 -0d000d000d000d0000000c0010000d000e0000000f000e000e0000000d000f000e000000 -0f000d000f000d0000000d000d0000000d000f000f000d000e000d000d000d000d000e00 -0d000e0009000e000e000d000d000e000e000e000d000e000e000d000e000d000d000d00 -0e000e000d000d000d0010000e000e000d000e000d000c000c0000000c000d000d000e00 -00000e000d000d0000000d000d000e0001000d000d000d000d000d000e000e000e000900 -0d000e000d000e000e000d000e000e000e000d000d000e000e000e000d000d000d000d00 -0d000d00000012000d000d00040000000000100012000d000d0000000d000e000e000d00 -0e000d000d000d000e000d000d000e000d000d000d000e000d000e000d000d0010000e00 -0e000d000d0000000d000e000f0000000e000e0000000e000d0000000e0000000e000d00 -0d000f000e000d000e000e000e000d0000000f000d000d0000000e000d0000000d000d00 -0d0000000e000d0000000f000e0000000f000e000e000d000d000d000e000d000d000000 -0d000f000d0000000e000f0000000c000f000e0000000e000e0000000d0011000e000d00 -11000d0000000f0000000d000d000d000e000a000c000f000e000d000e000d000e000d00 -0e000e000e000d000d000e000d000e000e000d000e000f0010000f000e000d000f000000 -0e000d000f0000000e000d000f0000000d000d0000000e000d000d0000000e000d000000 -0e000d0001000d000d000d000e000c000f000f0009000d000d000e000d000e000e000d00 -0e000e000d000e000d000e000d000e000d000e000d000e000f0010000e000d000d000e00 -00000f000d000d0000000d000d0000000d000d000d0000000e000d0001000d000e000000 -0d000f0000000f000f000d0000000d000d0000000d000d000d0000000e000d000f000c00 -0f000c000f0009000e000d000e000d000e000e000d000e000d000e000e000d000e000d00 -0e000d000e000d000e000d0010000e000d000d000e000d000d0000000e000e000f000d00 -00000d0010000c000f0000000e000d0000000f000e000d000d0000000d000e0000000d00 -0d000e000d000e000d000d000d000e000e000e000e0009000e000e000e000d000e000e00 -0d000e000d000d000e000e000e000d000e000d000e000d000e000d0010000f000f000e00 -0e000d000f0000000f000c000f000e0000000d000e000d000b0001000d000d0000000e00 -0d000e000d0000000d000e0000000d000d000d000d000f000d000e000e000e000e000d00 -0d0009000e000e000e000d000e000e000d000e000e000d000e000e000d000e000d000d00 -0e000d000d000e0010000f000e000d000d000e000f000d0001000e000e000d000e000000 -0d000e000d0000000d000e000e0000000d000d000f000d000d000e000d000e0009000e00 -0e000e000e000d000e000d000d000e000e000e000d000e000d000e000d000d000d000d00 -0d0000000d0012000d0004000000000010000d000d000d0000000d000d000e000e000e00 -0e000e000e000d000e000e000d000e000e000e000d000e000d000e000e0010000f000e00 -0d000e0000000d000d00000000000d000d0001000d000f0000000e000d0000000d000d00 -0d000e000d000e000d000d000d00000000000e000d0000000f000e0000000d000e000e00 -00000e0000000b000d000e000d0000000c000d0010000d000d000e000e000e0000000000 -0d000d0000000e000d0000000f000d000d0000000e000b0000000d000d000d0000000d00 -0e0000000d000f0000000d000f000e0008000e000d000d000e000d000e000d000e000d00 -0d000e000d000e000e000e000d000e000e000b000d0010000e000d000f000f0000000d00 -0f000d00000000000e000d0000000d000f0000000e000d000e0000000d00000010000d00 -0e000d0000000e000d000d000e000d000e0009000d000f000d000d000e000e000e000d00 -0e000e000d000e000d000e000d000e000d000e000d000d0010000d000f000d000d000000 -00000e000d0000000e000e0000000d000e00000000000d000d0000000d000d0000000f00 -0e0000000e000c000d0000000d000d0000000d000e000d0000000d000f000d000f000e00 -0c000e0007000d000e000e000d000e000d000e000e000e000e000d000e000d000e000d00 -0e000e000d000d000d0010000e000e000d000e000d000d0001000d000d000d000d000000 -0d000d000e000d0000000e000f0000000d000d000e000d0000000d000f0000000e000e00 -0d000f000e000e000d000d000d000e000e000e0009000e000e000e000d000d000d000e00 -0e000d000d000d000d000d000e000d000e000d000e000d000e000f000d000d000d000d00 -11000e0000000e000d000e000d0000000d000e000e000f0000000d000e0000000f000f00 -0d000e0000000d000e0000000d000f000f000d000d000e000d000d000d000f000d000e00 -09000d000e000e000d000e000d000d000e000e000e000d000e000e000d000d000e000e00 -0d000d000e0010000e000d000d000d000d000e000d0000000e000f000d000d0000000d00 -0f000d0000000d000d000d0000000d000f000d000d000d000e000e000d0009000e000e00 -0e000e000e000e000d000e000e000d000e000d000d000e000d000d000d000d000d001100 -00000d000d000d0013000000000010000d000d000d0000000d000d000d000e000e000e00 -0d000e000d000e000e000d000e000d000e000d000d000e000f000d0010000d000d000d00 -0f000d00000000000e0001000c000f00000000000d0000000d000d000e0000000e000d00 -0e000e000d000f000d000d0000000e00000000000e000d000d000e000000000000000e00 -0f0000000f000e000f000d0000000e000d000d000d000f000d000d000d0000000e000100 -00000e000d000e000f000000000000000d00000010000d000000000000000e000d000d00 -00000d000c000f0000000d000c000a000e000e000d000e000d000d000e000d000d000e00 -0d000e000d000e000e000e000d000e000f000f0010000e000d000d000d0001000d000d00 -0f0000000e00000000000d000e000c000d000000000001000d000d0000000d000b000d00 -0f0000000d000d0001000e000d000d0009000e000e000e000e000d000e000e000e000e00 -0d000e000d000e000d000e000d000e000d000e000d0010000e000d000f000d0001000e00 -000000000e000d000d000e00000000000d0000000e000d00000000000d00000000000e00 -0d000000000001000d000d000f0000000d000e000d0000000d000d000e0000000c000e00 -0e0009000f000e000e000e000d000e000e000e000e000e000e000d000e000d000d000e00 -0d000e000e000e0010000d000d000d000e000d000d0000000e000e000e000e0000000f00 -0d000d000e0000000d000d00100000000000000000000e000d000d000000000000000000 -000000000c000d000f0000000e000e000e0009000e000e000e000d000e000d000e000d00 -0d000d000d000d000e000d000e000d000e000d000e000d00100010000e000d000d000d00 -0d0001000d0010000d000d0001000d000d000d000d0000000d000f000f00000000000000 -00000e000f000d000000000000000000000000000f000d000f0000000d000d000e000900 -0e000e000e000d000e000e000e000d000e000e000e000e000d000e000d000d000e000d00 -0d000d0010000e000d000e000e000d000d000e0001000d000b000e000f000d0001000000 -00000e000e000e000d0000000e000d0000000f000d000e000e000e0009000e000e000d00 -0d000e000d000e000e000e000d000d000e0011000d000d000d000d000d000d000d000000 -12000d001200040000000000100012000d000d0000000d000d000e000d000e000e000e00 -0d000d000d000d000d000d000e000d000e000d000d000d000d0010000e000d000d000f00 -0d000d000f000e0000000f000d000e000f000d000e000d000d000f000d000f000d000d00 -0d000e000b000d000e000d000f000d000d000e000d000e000e000d000d000f000d000e00 -0d000f000d000b0010000d000d000e000e000e000d000d000e000e0000000d000c000d00 -0e000f000d000d000d0010000d000d0011000d000d000d000d000d000d000d000e000f00 -0d000f000c000e000d000f0009000d000f000e000d000e000d000d000d000e000d000e00 -0d000d000d000d000d000e000d000d000d0010000f000e000e0010000b0000000f000d00 -0d000d000e000e000d000e000f000f000d000b000d000d000e000f000d0010000e000d00 -0e000d000f0000000d000e000f0009000c000d000e000e000e000d000e000e000e000e00 -0d000e000d000e000d000e000d000e000d000e0010000d000d000d000f000c000d000d00 -0d000e000e000e000e000d000d000d000d000d000d000e000e000f000d000d000d000d00 -0d000f000d000d000f000d000f000f000e000b000f000f000d000f00000010000e000c00 -09000f000e000e000d000e000e000e000e000e000e000d000e000d000e000e000e000e00 -0d000e000e0010000d000e000d000e000d000e000e000f000d000c000d000f000d000f00 -0d000e000d000e000d000d000d000d000f000e000d000d000f000d000d000f000d000f00 -0d0010000e000d0000000e000e000e0009000e000e000e000d000e000e000d000e000d00 -0e000d000d000d000e000d000e000d000e000d000e0010000d000d000f000e000d001000 -0c000d000c000d000e000d000d000f000e000e000f000d000b000e000f000d000e001000 -0d000d000e000d000f000d000f000c000f000d000e000e0000000e000e000e0009000e00 -0e000e000d000e000e000e000e000d000e000e000e000e000d000d000e000e000d000d00 -0d0010000e000d000d000f000d000e000e000b000f000f000d000e000d000e000e000d00 -0e000e000d0000000d000e000e0001000d000e000e000e000e0009000d000e000e000e00 -0e000e000e000e000e000e000e000e000e000d000d000d000d000d0011000d0000000d00 -0d000d0004000000000010000d0012000d0000000d000e000e000d000e000e000e000d00 -0e000d000d000e000d000e000e000d000d000e000d00100010000f000d000f000d000000 -0e000d000d0001000d000d000f000d000d000e000d000f000b000e000000000000000000 -0000000001000f000d000d000d000f000d000d000d000d000f000e000d000d000f000d00 -0f000e000d000d000d0000000000000000000000000000000d0000000e000f000e000d00 -0d000e000e000d000d000d000e000e000d000e0011000d000d0011000d000e000c000e00 -0c000f000d000f000d0009000d000d000d000e000d000d000e000d000d000e000e000d00 -0e000d000d000e000e000e000f000d0010000e000d000d000d000e0000000d000e000f00 -0f000d000e000e000d000c000d000f000e000e000d000e000d000d000d000b000f000e00 -0d0000000e000f000c000e0009000e000f000d000d000e000e000e000e000e000e000e00 -0d000e000d000e000d000e000d000e000e0010000f000e000d000e000e000f000d000f00 -0d000d000d000d000f000d000f000d000d0010000d000d000e000e000d000f000d001000 -0d000d000d000e000f000d000d000d0010000c000e000e0000000d000d000e000c000a00 -0d000d000e000e000e000d000e000d000e000e000e000d000e000d000e000d000e000d00 -0e000d0010000e000d000d000e000d000d000d000d000e000e000e000d000d000e000d00 -0e000d000d000e000e000e000e000e000c000f0010000c000d000d000d000d000d000f00 -0c000e0000000d000e000e000e0009000e000e000e000d000d000d000e000d000e000e00 -0d000d000e000d000e000d000e000d000e000d0010000d000f000d000d000d000d000e00 -0e000e000d000d000d000d000d000d000e000d000f000e000e000f000c000e000d000d00 -10000b000e000e000e000d000f000d000e000d0000000d000f000d000e0009000d000e00 -0e000d000e000e000d000e000e000e000e000e000e000e000d000e000e000d000d000e00 -10000f000d000d000f000d000d000c000f000d000d000e000f000d000d000d000e000d00 -0e000d0000000e000d0000000d000d000d000e000e000e0009000e000e000d000e000d00 -0d000e000e000e000e000d000d000e000e000d000d000d000d000d000d0000000d001200 -0d0004000000000010000d000d000d0000000d000e000d000e000e000e000d000e000d00 -0e000e000d000e000d000d000e000d000d000d000e0010000d000d000e000d000e000000 -000000000d000d000f000d000e000d000d000e000d000f000f000c000f000d000d000d00 -0d000d000d000e000f000e000d000e000e000e000d000d000d000e000e000c000f000d00 -0d000e000e000e000d000d000e000e000e000d000e000d0000000d000e000d000f000d00 -0e000e000d000e000d000d000e000d000d000d000d000e000d000f000d000e000e000f00 -0d000e000c000f0009000d000e000e000d000e000e000d000e000e000d000d000e000d00 -0e000e000d000e000e000d000d0010000d000d000f000d000d000f0000000d000d000d00 -0e000d000d000e000d000f000e000d000d000f000d000e000d000f000e000d000d000e00 -0d000e000e000e000d000a000e000d000d000e000e000d000e000e000e000e000e000e00 -0d000e000d000e000d000e000d000d0010000d000e000f000c000f000c000d000d000d00 -0e000e000d000d000d000e000e000d000d000d000f000c000e000d000d000f000c000d00 -0d000d000d000d000e000d000d000d000e000d000e000e000e000d000e000e0009000e00 -0e000d000e000d000e000d000e000e000e000d000e000d000e000d000e000d000e000e00 -0e0010000d000e000d000e000d000d000e000e000d000e000e000d000e000d000e000d00 -0e000e000d000f000d000d000e000e000d000c000f000d000e000d000e000e000d000f00 -0e000d000d000e000e000e0009000e000e000e000d000e000d000d000e000e000d000e00 -0e000d000e000d000e000d000e000d000e0010000d000f000d000d000f000d000d000d00 -0d000f000d000f000d000e000d000e000d000d000f000d000d000d000d000e000e000d00 -0f000e000d000e000d000e000d000e000e000e000e000d000e000e0007000e000d000e00 -0d000e000d000e000e000d000e000e000e000e000e000d000e000e000d000d000e001000 -0e000e000d000e000e000e000e000d000d000d000e000d000e000d000e000d000d000e00 -00000d000d000d000e000e000d000d000e000e000e0009000e000e000d000d000e000d00 -0e000e000e000d000e000e000e000e000d0011000d000d000d000d00000012000d000d00 -130000000000100012000d000d00000011000e000e000d000e000d000d000e000d000e00 -0e000e000e000d000e000d000e000e000e000d0010000e000e000f000d000e000d000d00 -0d000e000e000d000e000d000e000d000d000d000d000d000e000d000e000d000e000e00 -0e000d000d000d000e000d000d000d000d000e000e000d000e000d000e000d000d000d00 -0d000e000d000d000d000d000e000d000e000e000e000d000e000d000e000e000d000d00 -0d000d000e000d000d000d000e000d000d000e000d000d000d000d000d000e000e000d00 -0d000d000e0007000e000e000e000e000e000e000d000e000d000e000e000d000e000d00 -0e000e000e000d000e000d0010000d000d000f000d000e000e000e000d000d000e000d00 -0d000d000d000d000d000e000e000d000e000d000e000d000d000d000d000d000e000d00 -0e000d000f000d0009000e000e000e000e000e000e000e000d000d000e000d000d000e00 -0e000e000d000e000e000e000d0010000e000c000f000d000d000d000d000d000e000d00 -0e000e000e000e000e000d000e000d000e000d000e000d000d000d000d000e000e000d00 -0e000e000d000d000d000d000d000d000d000e000f000e000d000d000d0009000e000e00 -0d000e000e000e000e000d000e000d000d000e000e000e000d000e000d000e000e000d00 -10000e000e000f000c000f000d000d000d000e000e000d000e000d000e000d000d000d00 -0d000d000e000d000e000d000e000e000e000d000d000d000e000d000d000d000d000e00 -0e000d000d000e000e0009000d000f000d000e000d000e000e000e000e000d000e000d00 -0e000d000d000e000e000e000e000e0010000f000d000e000e000e000e000d000d000d00 -0d000d000e000e000e000e000d000e000e000d000d000d000d000e000e000d000e000d00 -0d000d000e000d000d000d000d000e000e000d000e000d000d0009000e000e000f000e00 -0e000e000e000e000e000e000e000e000e000d000e000e000c000f000d000d0010000d00 -0e000d000d000d000d000d000d000d000d000d000d000d000d000d000e000e000e000d00 -0e000d000d000d000e000d000e000d000f000d0009000e000e000e000e000e000e000e00 -0d000e000d000e000d000d000e000e000d000d000d000d00110000000d000d000d000400 -0000000010000d000d00120000000d000e000e000e000e000e000e000d000d000e000e00 -0e000d000e000d000d000d000e000e000e0010000e000e000e000d000f000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000d000e000e00 -0e000e0009000d000d000e000e000e000d000e000e000e000e000e000d000e000e000d00 -0e000e000d000e000e0010000f000e000e000c000f000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000d00 -0c000e000c0009000e000e000e000e000e000d000e000e000e000e000e000e000d000d00 -0e000e000e000e000e000d0010000e000d000f000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000f000e0009000d000d000e00 -0e000e000d000d000e000d000e000e000d000e000d000e000d000e000d000e000d001000 -0f000e000e000d000f000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000f000e000d0007000c000e000d000e000e000d000e000d000e000e000e000e000d00 -0e000d000d000d000e000d000e0010000e000d000e000d000d000d000d000d000d000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e0007000e000c000d000e000e00 -0f000e000e000e000e000e000e000e000e000e000e000d000f000d000e0010000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000d000c000e000c0009000e000d000e000e000e000e000d000e00 -0e000e000e000d000e000e000e000d000e000d000d000d00000012000d00120004000000 -000010000d0012000d0000000d0011000e000d000e000d000d000e000e000d000e000d00 -0e000d000e000d000e000d000d000e000f000f000e000e000d000e000e000e000e000e00 -0d000e000d000e000e000e000e000e000e000e000e000e000d000e000e000e000e000e00 -0d000e000d000e000e000e000e000e000e000e000e000d000d000e000e000d000e000e00 -0e000e000d000e000e000e000e000e000e000e000d000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000d000e000e000e000e000e000e000e000e000f000e000e00 -0d000a000e000e000e000e000d000e000d000e000d000e000e000e000d000e000e000e00 -0d000e000d000e0010000f000f000e000e000e000e000d000d000d000d000e000d000d00 -0e000e000e000e000d000e000d000e000e000e000e000e000e000e000e000e000f000f00 -0e000d000a000e000e000e000e000e000d000d000e000e000d000e000d000e000e000e00 -0d000e000d000e000f0010000d000d000e000d000e000d000d000e000e000e000e000e00 -0e000e000d000d000d000d000e000e000e000d000d000d000e000e000e000d000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000c000a000e000e000e000d00 -0d000e000d000e000e000e000e000e000e000e000d000e000d000e000d000e000f000f00 -0f000e000d000e000e000e000e000e000d000e000d000e000e000e000e000e000e000e00 -0e000e000d000e000e000e000e000e000d000e000d000e000e000e000e000e000e000e00 -0e000d000d000a000e000f000e000e000d000e000e000e000d000e000e000d000e000e00 -0d000e000e000e000e000d0010000f000e000e000e000e000e000e000d000d000e000e00 -0e000e000e000e000e000e000e000e000e000e000d000d000d000e000e000e000e000e00 -0e000e000d000e000e000e000e000e000e000e000d000a000f000e000e000e000d000d00 -0e000e000e000d000d000e000d000e000e000e000d000e000d000f000f000e000d000e00 -0e000d000e000e000e000e000d000d000d000e000e000d000e000e000d000e000e000e00 -0e000e000e000e000f000f000e000d000a000e000d000d000d000e000d000e000e000e00 -0d000e000e000e000d000e000d000e000d000d000d0000000d000d000d00040000000000 -10000d000d000d0000000d000d000e000e000d000e000e000e000d000e000e000e000d00 -0e000e000e000e000e000f000d000a000900080009000900090009000900090009000700 -090009000900070009000900070009000900090007000700090007000900090009000900 -070009000900090009000700090009000700090009000900090009000900090009000900 -090009000900070009000900070009000900090007000900090009000700070007000900 -090007000900090007000900090009000900070009000900090007000900090007000900 -07000e000e000e000d000e000e000e000d000e000e000d000e000e000d000e000d000e00 -0d000f000d000a000900080007000a000900090009000900090009000900090007000900 -090009000900070009000900090007000900090007000900090009000700090007000700 -090007000c000d000e000e000e000e000e000d000e000d000e000e000d000e000d000e00 -0e000e000e000b000b0009000900090007000a0007000900070009000900070009000700 -070009000700090009000900090009000900090007000900090009000700090007000900 -07000900090009000900090009000700090009000900090009000d000e000d000d000e00 -0e000e000d000e000d000d000e000e000d000e000e000e000e000e000c000a0007000700 -090009000900090009000900090007000900090009000700090009000700090009000900 -070007000900070009000900090009000700090009000900090007000900090007000900 -07000a0009000c000e000d000e000e000d000e000d000e000e000d000e000e000d000d00 -0e000d000e000e000e000900090009000900090009000900090009000900090009000700 -090009000700070009000900090009000900090007000900090009000900070009000900 -090007000900090007000900090009000700090007000c000d000e000e000e000d000e00 -0d000d000e000e000d000e000d000d000e000f000e000e000c000a000700090009000900 -090009000900090007000900090009000900090009000900090009000900090009000700 -090009000900070007000900090009000c000e000e000e000d000e000e000e000d000e00 -0e000e000d000e000d000d000d000d000d000d00000012000d000d001300000000001000 -0d000d000d0000000d000d000d000e000d000e000d000e000e000d000e000d000e000d00 -0e000d000e000e000d000d000d000e000f000f000e000c000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000f000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000f000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000f000f000e000e000d000c00 -0f000d000e000e000d000e000d000e000d000e000e000d000e000e000d000e000e000e00 -0d000d000c000f000f000f000e000c000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000f000e000e000e00 -0c000f000e000e000e000e000d000e000e000d000e000e000e000e000d000e000e000e00 -0e000e000f000d000d000d000d000d000e000d000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000f000e000e000e000c000f000d000e000d000e000e00 -0d000e000d000e000e000e000d000e000d000e000d000e000d000d000d000e000f000f00 -0e000c000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000f000e000e000e000e000e00 -0e000d000f000e000c000d000d000e000d000e000e000e000e000d000e000e000e000e00 -0d000e000d000d000e000d000e000e000d000d000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000d000f000e000e000e000e000d000e000d00 -0e000d000d000e000d000e000f000e000d000c000d000f000f000f000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000f000e000e000e000c000f000f000e000e000e000e000e000d000e000d000e00 -0d000e000d000e000d000d000d000d000d0000000d000d00120013000000000010000d00 -12000d0000000d000d000e000d000e000d000e000d000d000e000e000e000d000e000d00 -0e000d000e000e000f000d000e000d000d000d000e000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000e000d000d000d000d000d000d000e00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000e000d000d000e000d000d000d000d000d000d000d000d000e000e000d000f00 -0c000d000d000e000d000e000d000e000e000e000e000e000d000e000e000e000e000e00 -0f000d000e000c000d000e000e000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000e000e000e000d000d00 -0e000d000d000d000d000e000d000e000e000d000e000d000e000e000e000e000e000e00 -0e000e000d000d000e000d000d000e000e000d000d000d000d000d000e000d000d000d00 -0d000e000e000d000d000d000e000e000e000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000e000e000e000f000d000d000e000e000d000e00 -0e000e000e000e000d000e000e000e000d000e000e000e000f000d000e000d000d000d00 -0e000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000e000e000e00 -0e000e000e000e000f000e000e000e000e000e000e000d000e000e000e000d000e000e00 -0e000d000e000e000d000e000e000d000d000d000d000d000d000d000d000d000d000d00 -0d000e000d000d000d000d000d000d000d000d000d000e000d000d000d000d000d000d00 -0e000d000d000d000d000d000d000d000c000e000d000d000e000e000e000e000e000e00 -0e000e000d000e000d000d000d000e000e000e000e000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000e000d000d000d000d00 -0d000e000d000e000d000d000e000d000d000e000d000e000d000e000e000d000e000d00 -0d000e000d000d000d0011000d000d00000012000d000d00040000000000100012000d00 -0d0000000d000d000e000e000e000e000d000e000e000d000e000e000e000e000e000e00 -0e000e000c000d000e000f000d000f000e000f000e000e000e000e000e000e000f000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000f000e000f000e000d000e000d000d000e000d00 -0e000e000e000e000e000e000d000e000e000d000d000e000e000d000e000e000d000d00 -0e000f000d000e000e000f000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000f000e000e000e000e000e000e000e000e000e000d000d000e000e000e000e00 -0e000e000e000e000d000e000e000e000e000e000e000d000e000d000d000e000e000e00 -0d000d000e000d000d000e000d000d000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000f000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000f000f000e000d000e000d000d000e000d000e000d000d000e000e000e00 -0d000d000e000e000e000e000d000e000e000e000c000e000e000f000e000e000e000f00 -0e000e000e000e000e000e000f000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000d00 -0d000c000d000d000e000e000d000e000e000e000e000e000d000e000e000d000e000d00 -0e000d000e000d000e000e000d000d000e000d000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000f000e000e000e00 -0e000e000e000e000e000e000f000e000f000e000e000e000d000e000e000d000e000e00 -0e000d000e000d000e000e000d000e000e000e000f000f000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000f000e00 -0d000e000e000e000e000e000e000e000d000e000e000e000e000e000e000d000e000e00 -0e000d000d000d000d000d000d0000000d001200120004000000000010000d000d000d00 -00000d000e000e000e000e000e000e000d000d000e000d000e000d000e000d000e000d00 -0e000e000e000e000e000d000f000c000e000e000d000e000e000d000d000d000e000e00 -0e000e000d000e000e000d000d000d000e000d000e000e000d000e000d000d000e000e00 -0d000d000d000d000e000e000e000d000d000d000d000d000e000d000d000e000d000e00 -0d000d000d000e000d000d000d000e000d000e000d000d000e000d000d000e000d000e00 -0e000d000d000e000d000e000d000d000e000d000d000d000e000e000e000e000e000e00 -0d000e000d000e000d000e000e000d000e000e000e000d000e000e000e000e000e000d00 -0e000d000f000c000e000d000e000d000d000e000d000e000e000e000d000e000e000d00 -0d000d000e000e000e000e000d000e000e000d000d000e000e000e000e000e000d000e00 -0d000d000e000e000e000d000e000d000e000e000d000e000e000d000e000e000e000d00 -0e000e000d000d000e000e000e000e000d000e000e000d000d000d000d000e000d000e00 -0e000d000d000d000d000e000d000e000e000d000d000e000e000e000d000e000e000d00 -0d000d000e000d000d000d000e000d000d000e000e000d000e000e000e000e000d000e00 -0e000e000d000e000d000e000d000e000d000f000e000e000e000d000f000c000e000e00 -0d000e000e000d000d000d000e000e000e000e000d000e000e000d000d000d000e000d00 -0e000e000d000e000d000d000e000e000d000d000d000d000e000d000d000d000e000d00 -0e000e000d000e000d000e000e000e000e000e000e000e000e000e000d000e000e000d00 -0e000e000d000e000e000d000e000f000e000d000d000e000d000e000e000e000d000e00 -0e000d000e000e000d000d000e000d000d000e000d000e000d000d000e000e000e000e00 -0d000d000d000e000d000e000d000e000e000e000e000d000e000e000e000d000e000e00 -0e000e000e000d000e000d000e000d000d000e000d000d000d000d000e000d000d000e00 -0d000e000e000e000d000e000d000d000d000d000d000e000d000e000d000d000d000e00 -0e000e000e000e000d000e000d000e000e000d000e000d000d000e000e000e000e000d00 -0d000e000d000d000d000d0000000d000d000d0004000000000010000d000d000d000000 -0d000d000d000e000d000d000d000e000d000d000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000d00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000d000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000d000d000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000d000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000d000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000d000e000e000e000e000d000e000e000e000e000e00 -0e000e000e000e000e000d000e000e000e000e000e000d000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000d000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000d000e000e000e000e000d000e000e000e000e000e00 -0e000e000e000e000d000e000e000e000e000e000e000e000e000e000d000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000d000e00 -0e000e000d000d000e000d000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000d000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000d000e000d000e000e000e000e000e000e00 -0e000e000e000e000e000e000c000e000f000e000e000d000e000e000d000d000d000e00 -0d000e000d000d000d0000000d0012000d0004000000000010000d0012000d0000000d00 -0d000d000d000e000e000e000d000e000d00090009000900090009000900090009000900 -090009000900090009000900090009000900090009000900090009000900090009000900 -090009000900090009000700090009000700090009000900090009000900090009000900 -090009000900070009000900090009000900090009000900090009000900090009000900 -090009000900090009000900090009000900090007000900090009000900090009000900 -090009000900090009000900090009000900090009000900090009000900070007000900 -090009000900090009000900090009000900090009000900090009000900090009000900 -090009000900090007000900090009000900090009000900090009000900090009000900 -090009000900090009000900090009000900090009000900090009000900090009000900 -070009000900090009000900090009000900090009000900090009000900090009000900 -090009000900090009000900090009000900090009000900090009000900090009000900 -090009000900090007000900090009000900090009000900090009000900090009000900 -090007000900090009000900090009000900090009000900090009000900090009000900 -090009000900090009000900090009000900090009000900090009000900090009000900 -090009000900090009000900090009000900090009000900090007000900090007000900 -090009000900090009000900090009000900090009000900090009000900090009000900 -090009000900090009000900090009000900070007000900090009000900090009000900 -090009000900090009000900090009000900090009000900090009000900090007000900 -090009000900090009000900090009000900090009000900090009000900090009000900 -090009000900090009000900090009000900090009000700070009000900090009000900 -090009000900090009000900090009000900090009000900090009000900090009000700 -090009000900090009000900090009000900090009000900090009000900090009000900 -090009000900090009000900090009000800080009000a000b0011000e000e000d000e00 -0d000d000d000d0000000d0012000d0013000000000010000d0012000d0000000d000e00 -0e000e000e000e000d000e000e000d001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -1000100010001000100010001000100010001000100010000e000e000e000d000d000e00 -0d000d00110000000d000d00120004000000000010000d000d000d0000000d000e000d00 -0e000e000e000d000e000d000e000e000e000e000e000e000e000d000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000d000e000e000e000e000d000e000e000d000e000e000e000e000e000e000e00 -0e000e000d000e000d000e000e000e000d000e000e000e000e000e000e000e000d000e00 -0e000e000e000e000e000d000d000e000e000d000d000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000d000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000d000e000e000e000d000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000d000e000e000e000e000e000e000e000d000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000d000d000e000e000e000e000d000e000d000e000e000e000e00 -0e000e000e000e000d000e000e000e000e000e000e000e000d000e000e000e000e000e00 -0e000e000e000e000e000d000e000e000e000e000e000e000d000e000e000e000e000e00 -0e000e000e000d000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000d000e000e000e000e000d000e000e00 -0d000e000e000e000e000e000e000e000d000e000e000e000e000e000e000e000e000e00 -0e000e000d000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0d000e000e000f000e000e000e000e000e000e000e000d000d000d000e000d000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000d00 -0e000e000e000e000e000e000e000d000e000e000e000e000e000e000e000e000e000d00 -0e000e000e000e000e000e000e000e000f000e000e000e000f000e000d000e000d000d00 -0e000e000d000e000e000f000e000e000e000e000e000e000d000e000e000e000e000e00 -0e000d000e000e000e000e000e000e000d000d000d000e000d000d000e000d000d000d00 -0d000d00000012000d000d00040000000000100012000d000d0000000d000e000e000e00 -0e000d000e000e000e000d000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000d000e000e000d0011000e000e000e000e000e000e000e000e00 -0d000e000d000e000e000e000e000e000e000d000e000e0011000e000e000d000d000e00 -0e000e000d000e000d000e0011000d000e000e0011000e000e000d0011000e000e000e00 -0e000e0011000d000d000e000d0011000e000d000e000e000e000d000e000d000e001100 -0d0011000e000e000e000e000e000e000e000d000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000d000e000e000d0011000e000e000e000e00 -0e000e000e000d000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000d000d000e000e000d000e000d000e000e000e000e000e000e000e00 -0e000e000e000d000e000e000d000e000e000d000e0011000e000e000d000e000e000e00 -0e000e000e000e000e000e000e000e000e000d000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000d000e000e000d001100 -0e000e000e000e000e000e000e000e000d000e000d000e000e000e000e000e000e000d00 -0e000e0011000e000e000d000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000d000e000e000d0011000e000e000e000d000e000e00 -0d000e000e000d000e0011000d0011000e000e000e000e000e000e000e000d000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000d000e000e000e000e000e000e00 -0d000d000e000d000e000d000e000d0011000d000d000e000e000e000e000e000e000e00 -0e000e000e000e000d000d000d000e000f0010000d000e000e000d000d000d0011000d00 -0d0000000d000d000d0004000000000010000d000d000d0000000d000e000e000d000e00 -0d000e000d000d000d000e000e000e000e000e000e000d000d000d000e000d000e000e00 -0e000e000e000e000d000d000d000d000d000d000d000d000d000e000d000d000d000d00 -0e000d000d000d000d000d000d000d000d000e000d000d000d000d000d000d000d000d00 -0d000d000e000d000d000e000d000d000d000d000d000d000d000d000d000d000e000d00 -0d000d000d000d000d000d000d000d000e000d000e000d000d000d000e000d000d000d00 -0d000d000d000d000d000e000d000d000e000d000d000e000e000e000d000d000e000e00 -0e000e000e000e000e000e000d000e000d000e000e000d000e000e000d000d000d000e00 -0e000d000d000e000e000d000e000e000d000d000d000d000d000d000d000d000d000e00 -0d000d000e000d000d000e000e000e000e000e000d000d000d000e000d000e000d000e00 -0e000e000e000e000d000e000d000e000d000e000d000e000e000e000e000e000e000e00 -0d000d000d000d0011000e000e000d000d000d000d000d000d000d000d000e000e000d00 -0d000d0011000e000e000d000d000d000e000d000d000d000d000d000e000d000e000e00 -0e000d000e000d000e000e000e000e000d000d000d000e000e000e000e000e000e000e00 -0e000d000e000d000e000d000e000e000e000e000e000e000d000d000d000d000d000d00 -0d000d000d000e000d000d000d000d000e000d000d000d000d000d000d000d000d000e00 -0d000d000d000d000d000d000d000e000d000e000d000e000e000e000e000e000e000d00 -0e000e000e000d000e000e000d000e000e000e000e000d000e000d000e000d000e000e00 -0e000e000d000e000d000e000d000d000d000d000d000d000d000d000d000e000e000d00 -0d000d000e000d000d000d000d000d000d000d000d000e000d000d000e000d000d000e00 -0e000e000e000e000d000e000d000d000e000d000e000e000e000e000e000e000e000e00 -0d000d000e000d000e000e000e000e000e000e000e000d000d000e000e000d000d000d00 -0d000d000e000d000d000d000e000e000d0011000d000e000e000e000e000d000e000e00 -0d000e000d000e000e000e000d000d000c000d000e000d000e000d000d000d000d000d00 -000012000d00120004000000000010000d0012000d0000000d000d000d000d000e000e00 -0d000d000e000e000e000e000e000e000d000e000d000e000e000d000d000e000e000e00 -0e000e000d000d000d0011000d000d000d000d000d000d000e000d000e000d000e000d00 -0d000d000d000d000e000d000e000d000e000d000d000d000e000d0011000d000e000d00 -0e000d000d000e000d000d000e000e000d000e000e000d0011000d0011000d000e000d00 -0d000d000d000d000d000e000e000d000e000d000e000d000d000d000d0011000d000d00 -0d000d000d000d000e000d000d000d000d000e000e000e000d000e000e000d000e000d00 -0e000e000e000e000d000e000e000e000d000d000e000e000d000e000e000e000d000e00 -0d000e000e000e000e000d000d000d000d0011000d000d000d000d000d000d000e000d00 -0d000d000d000e000e000e000e000e000e000e000e000e000d000e000e000e000e000e00 -0e000e000e000e000e000e000d000e000d000e000e000e000e000e000e000e000e000d00 -0d000e000e000d000e000d000d000d000d0011000d000d000d000d000d000d000d001100 -0e000d000e000d000d000d000d000d000d000d000e000e000e000d000e000d000e000d00 -0e000d000e000d000e000e000e000e000e000d000e000d000e000e000e000e000d000e00 -0d000e000e000d000d000e000e000e000e000e000d000d000d0011000d000d000d000d00 -0d000d000e000d000e000d000e000d000d000d000d000d000e000d000e000d000e000d00 -0d000d000e000d0011000d000d000e000d000e000e000e000e000e000e000d000d000e00 -0d000e000d000e000e000e000e000d000e000d000e000d000e000e000d000e000e000d00 -0e000d000e000d000e000e000d000d000d000d000e000e000e0011000e000d000d000d00 -0d000d000d0011000d000d000d000d000d000d000e000d000d000d000d000e000e000e00 -0e000e000e000e000e000e000e000d000d000e000e000e000e000e000e000d000e000e00 -0d000d000e000e000d000e000e000d000e000e000e000d000d000d000d000e000d000e00 -0e000d000e000e000e000d000d000d000d000d000d000e000e000e000e000d000e000e00 -0e000e000d000d000d000e000e000f000d000e000d000d0011000d000d000d000d000000 -0d000d000d0004000000000010000d000d00120000000d0011000e000e000e000d000e00 -0e000e000d000d000e000e000e000e000e000e000d000e000e000e000e000e000e000e00 -0d000e000d000d000d000d000e000e000d0011000e000d000d000d000d000d000e000d00 -0d000e000d000d000d000d0011000e000e000d000e000d000d000d000d000e000e000d00 -0d000e000e000e000d000e000e000d000d000d000d000d000d000d000e000d000d000d00 -0d0011000e000d000d000e000e000d000d000d000d000d000d000d000d000d000e000e00 -0d0011000e000d000d000d000e000d000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000d000d000e000e000e000d000e000e000d000e000d000e000e000e00 -0d000e000d000e000e000e000d000d000d000d000e000e000d0011000e000d000d000d00 -0e000d000e000d000e000e000e000e000d000e000d000e000e000d000e000d000e000e00 -0e000e000d000e000d000e000e000e000d000e000e000e000e000e000e000e000e000d00 -0e000d000d000d000d000d000e000d000d000d000d000d0011000d000d000d000d000d00 -0d000d000d000d000e0011000d000e000d000e000d000e000e000d000e000e000e000e00 -0e000e000e000d000e000d000e000e000e000e000e000d000e000e000e000e000e000e00 -0d000e000e000e000e000e000e000e000d000e000d000d000d000d000e000e000d001100 -0e000d000d000d000d000d000e000d000d000e000d000d000d000d0011000e000e000d00 -0e000d000d000d000d000d000e000e000e000d000e000e000e000e000d000e000e000d00 -0e000d000d000e000d000e000e000d000e000d000e000d000e000e000d000d000e000e00 -0e000e000e000d000d0011000d000e000d000e000d000d000d000d000d000d000e000d00 -0d000d000d000d000e000e000d0011000e000d000d000d000e000d000e000d000e000e00 -0e000e000d000e000d000e000e000e000d000e000e000e000e000e000e000d000e000d00 -0e000d000e000e000d000d000e000e000e000e000e000e000d000e000d000d000e000e00 -0d000d000d000e000d000d000e000d000e000d000e000e000e000e000e000d000e000d00 -0e000e000e000e000d000d000d000e000d000d000d000d000d000d000d000d0000000d00 -12000d0013000000000010000d000d000d0000000e000e000e000d000e000e000e000d00 -0d000e000d000d000e000d000e000d000e000d000e000d000e000d000e000d000d000e00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000d000d000e000d000d000e00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000e000e000d000d000e000d000e000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000d000d000d000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000e00 -0d000e000e000e000d000d000e0010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010000900 -0d000d000d000e000d000e000d000e000d000e000d000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000d000e000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000e000d000e000e000d000e000d000d000e000e000d000e000e00 -0d000e000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0d000e000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000d000d000d000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000e000d000e00 -0e000d000d000e000d000e000e000e000d000d000e000d000d000d000d0000000d000d00 -0d000400000000001000120012000d0000000d000d000d000e000e000e000d000d000e00 -0d000e000d000d000e000d000d000d000e000e000d000d000e000d000e000e000d000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000e000d000d00 -0e000d000e000e000d000d000e000e000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000e000d000d000e000e000d000e000d000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000e000d000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000e00 -0d000d000e000e000e000e0010000d000d000d000e000f000e000d000d000d000d000e00 -0f000d000e000e000e000d000f000e000e000d000f000f000d000e000d000e0009000e00 -0e000e000d000e000d000e000d000e000d000e000d000d000e000d000d000d000e000e00 -0d000d000e000d000e000e000d000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000e000d000d000e000d000d000e00 -0d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000e00 -0d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000e000d000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000d000e000d000d00 -0e000e000d000e000d000e000e000d000d0011000d000d000d000d00000012000d001200 -040000000000100012000d000d0000000d000e000e000d000e000e000e000d000d000e00 -0d000e000e000d000d000e000d000e000d000e000d000d000d000e000d000e000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000d000e000e000d00 -0e000e000d000e000d000e000d000e000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000d000d000e000d000e000d000d000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000e000d000e000d000e000d000e000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000d000e000e000d00 -0e000d000d000e000d00100010000d000e000f000f000d0010000d000f000d0010000b00 -0e000d000d000f000f000d000e000e000c000d000f000d000d000f000d0009000d000d00 -0d000e000d000e000d000e000d000e000d000e000e000d000d000e000d000e000d000e00 -0d000d000d000e000d000e000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000d000e000e000d000d000d000d000e000d000e000d000d000e000d000d000e00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000d000e00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000e000d000e000d000e00 -0d000e000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000d000e000d000e000e000d000d000e000d000d000e000d00 -0e000d000d000d000e000e000e000d000d000d000d000d000d0000000d000d000d000400 -0000000010000d000d000d0000000d000d000d000e000e000e000d000e000e000d000e00 -0d000d000e000e000d000e000d000e000d000e000d000e000d000e000d000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000e000e000d000e000e000d000e000e000e00 -0d000e000d000e000d000e000d000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000e000d000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0d000e000d000e000d000e000d000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000e000e000d000e000e00 -0d000e000e000e0010000e000e000f000b000d000f000c000d000d000d000d000f000f00 -0e000d000d000b0010000d000d000e000e000d000e000d000f000d0009000d000d000e00 -0d000e000d000e000d000e000d000e000d000d000e000e000d000e000d000e000d000e00 -0d000e000d000e000d000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000e000d000e000d000e000d000e000d000e000d000d000e000d000e000d000d000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000e000d000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000d000e000d000e000d000e00 -0d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000e000d000e000d000d000d000e000d000e000d000d000e000d00 -0e000d000e000e000e000d000e000d000d000d000d000d00000012000d000d0013000000 -000010000d000d000d0000000d000d000e000e000d000e000e000d000e000d000d000e00 -0d000e000d000e000e000d000d000e000d000e000d000e000d000e000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000d000e000e000d000e000e000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000e000d000e000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000d000e000e000e000d000e00 -0e000d000e0010000d000d000d0010000e000d000e000d000f000d000f000e000b000f00 -0e000f000f000d000d000d000f000d000e000f000d000d000d0009000e000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000e000d000d000e000d000e00 -0d000e000d000e000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0d000e000d000e000d000e000d000e000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000d000e000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000d000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000d000d000d000e000d000e000d000e000e000d000e000d000e000d00 -0e000d000e000e000d000d000d000d000d000d000d0000000d000d001200040000000000 -100012000d000d0000000d000d000e000d000e000e000d000e000d000e000e000d000d00 -0e000e000d000d000e000e000d000e000d000e000d000e000d000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000e000d000d000e000e000d000d000e000e000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000d000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000e000d000d000e000e000d000d00 -0e000f0010000e000b000f000d000d000e000e000e000d000f000d000d0010000c000d00 -0d000d000f000d000c000f000d000e000b000f000e000f0009000d000d000e000d000e00 -0d000e000d000e000d000e000d000d000e000e000d000d000e000e000d000e000d000e00 -0d000e000d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0d000e000d000e000d000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000e000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000e000d000d000d000e000d000d000e000d000e000d000e000d00 -0e000d000d000d000e000d000d000d0011000d00000012000d000d000400000000001000 -0d0012000d0000000e000e000e000e000d000e000d000d000d000e000d000d000e000d00 -0d000d000e000d000d000e000d000e000d000e000d000e000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000d000e000e000d000d000e000d000d000d000e000e000d00 -0d000e000e000e000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0d000e000e000d000e000e000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000d000e000d000d00 -0d000e000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000d000d000e000d000d000e000e000d00 -0d0010000d000f000f000f000f0000000000000000000e000f000d000e000d000e000e00 -0d000d000d000f0000000f000d0001000d000d000f0009000d000d000d000e000d000e00 -0d000e000d000e000d000d000e000d000d000d000e000d000d000e000d000e000d000e00 -0d000e000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000d000e000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000d000e000d000d000d000e000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000e000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000e000e000d000e000d000d000d000d0000000d001200120004000000000010000d00 -0d000d0000000d000d000e000d000e000e000e000d000e000d000d000e000d000e000e00 -0d000d000e000e000d000e000d000e000d000e000d000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000e000d000d000e000e000d000e000e000e000d000e000d000e00 -0d000e000d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000e00 -0d000d000e000d000d000e000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000e000d000e000d000e00 -0d000e000d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000e000e000d000e000e000d000d000e000e00 -10000d000d000d000d0000000d000e000d000e0000000d000d000d000f000d000d000e00 -0d000d000d000f000d00100000000e000d000d0009000d000f000e000d000e000d000e00 -0d000e000d000d000e000d000e000e000d000d000e000e000d000e000d000e000d000e00 -0d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000e000d000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000e000d000e000d000e000d000e000d000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000d000d000e000d000e000d000e000d000e000d000e000d000e000e00 -0e000d000e000d000d000d000d00110000000d000d000d00040000000000100012000d00 -0d00000011000e000e000d000e000d000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000d000e000d000e000d000e00 -0d000e000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000d000e00 -0d000e000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000d000e000d000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000d000e000d000e000d000e000d000e000f001000 -0e000e000f0000000d000e000e000d000e000d0000000d000e0000000d0010000d000000 -0e000d0000000d000000000000000d000d0009000f000d000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000d000d000e000d000e000d000e000d00 -0e000e000d000e000d000e000d000e000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000d000e000d000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000d000d00 -0e000e000d000d000d000d000d00000012000d000d0004000000000010000d000d001200 -00000d000e000e000e000e000e000e000d000d000e000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000e000d000e000e000e000d000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000e000d000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000e000d000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000e000d000e000d000d000d000e000d000f0010000d00 -0d000d0000000d000d000d000d000f000d0000000f000e0000000d000b000f0000000c00 -0f0000000e000d0000000e000d000d0009000c000f000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000e000e000d000e000d000e000d000e000e00 -0d000e000d000e000d000e000d000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000e000d000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000e00 -0d000d000e000d000d000d0000000d0012000d0004000000000010000d0012000d000000 -0d0011000e000d000d000e000e000d000e000d000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000e000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000d000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000d000d000e000d000e000d000d000e000d0010000f000f00 -0d0000000f000d000d000f000d000d0000000e000d0000000f000e000d0000000f000d00 -00000d000f0000000d0010000d0009000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000d000e000e000d000d000e000d000e000e000d00 -0d000e000e000e000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000d000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000e000d000e00 -0d000d000d000d000d0000000d000d00120004000000000010000d000d000d0000000d00 -0d000e000d000e000d000e000e000d000e000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000d000e000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000e000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000e0010000d000e000f00 -00000d000d000e0000000d000f0000000c000e0000000d000d000d0000000e000d000000 -0f000d0000000f000c000d000a000d000e000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000e000d000e000e000e000d000e000d000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000e000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000e000e000e000e000d00 -0e000d000d000d00000012000d000d0004000000000010000d000d000d0000000d000d00 -0e000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000d000e000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000d0010000f000b000e000000 -0d000f000d000d0000000d0000000f000d0000000d000f000e0000000c000e0000000d00 -0e0000000b000f000e0009000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000d000e000d000e000d000e000e000e000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000d000e000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000d000d000e000d0011000d00 -0d000d000d0000000d000d00120004000000000010000d0012000d0000000d000d000e00 -0e000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000e000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000e000d000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000d000d000e000e0010000d000f000e000c000100 -0d000f000d000f0000000e000d000d0000000e000d00000000000e000d0000000f000d00 -00000f000d000d0009000d000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000e000d000e000e000e000d000d000e000e000e000d000e000d00 -0e000e000d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000e000d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d0011000d000e000d000d000d00 -0d001100000012000d000d00040000000000100012000d000d0000000d000d000e000e00 -0e000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000d000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000d000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000d000e000e000d000f0010000f000d000d000e000d000000 -0000000000000d0000000d000f000d00000000000e0000000d000e0000000d000e000000 -00000d000f0009000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000d000d000e000d000d000e000d000e000e000e00 -0d000e000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000d000d000d000d000d000d00 -0d0000000d000d000d0004000000000010000d000d000d0000000d000e000e000e000e00 -0e000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000e000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000e000d000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000e000d000d000d000d0010000d000e000e000d000e000d000d00 -0e000d000e000e000d000d000f000e000d000e000e000d000e000e000d000d000d000d00 -0e000e0009000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000e000e000d000e000e000d000e000d000e000d000e00 -0d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000e00 -0d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000d000d000d000d000d000d00 -00000d0012000d0004000000000010000d000d000d0000000d000d000d000d000e000d00 -0d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000e000e000e000e000e000d000d000e0010000c000f000e000e000d000e000e000e00 -0d000e000d000d000e000e000d000e000d000d000e000e000d000e000e000d000e000d00 -0d000a000d000d000e000e000e000e000d000e000e000e000d000e000e000e000e000d00 -0e000e000d000e000d000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000e000d000e000d000d000d000d000d000000 -0d0012000d0004000000000010000d0012000d0000000d000d000e000d000e000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000e00 -0e000e000e000e000d000e000e000e0010000e000f000d000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000d000e000d000e00 -09000e000e000d000e000d000e000e000d000d000e000e000d000d000e000d000e000e00 -0d000d000e000e000d000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000e000e000e000d000d000e000d000d000d0000000d00 -0d00120004000000000010000d0012000d0000000d000e000d000e000e000e000d000e00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000e000e000e000e000e000d0010000f000e000d000e000e000e000e000d000d000d00 -0d000d000d000d000e000d000e000d000e000d000d000d000e000e000e000e000e000700 -0e000e000e000e000e000d000e000e000d000e000d000e000e000d000d000e000e000d00 -0e000e000e000e000d000e000d000e000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000d000d000e000d000e000d000d000d000d00000012000d00 -0d0013000000000010000d000d000d0000000d000e000d000e000e000e000e000d000e00 -0d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000e00 -0e000e000d000e000d000e0010000e000e000d000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000d000c000e000d000f0007000e00 -0d000d000e000e000e000d000e000e000d000e000d000d000e000e000e000d000d000e00 -0d000e000e000e000d000e000d000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000e000e000d000e000d000d000d000d000d0000000d000d001200 -130000000000100012000d000d0000000d000e000d000e000e000e000d000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000e00 -0d000e000e000e0010000f000d000e000e000d000e000e000d000d000e000e000e000e00 -0d000e000e000d000e000e000e000e000e000d000f000f000e000e000e0009000e000e00 -0d000e000d000e000e000d000d000e000d000e000e000d000e000e000d000d000d000e00 -0d000e000e000e000d000e000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000e000e000e000e000d000d000d000d0000000d0012000d000400 -0000000010000d000d000d0000000d000e000e000d000e000e000e000d000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000e000d000e00 -0e000d000e000b000a0009000a0009000900090009000900090009000900070009000900 -09000900070009000700090009000900090008000800070009000a0008000c000d000e00 -0d000e000d000e000e000e000d000e000e000d000e000e000e000e000d000d000d000e00 -0d000e000e000e000d000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000d000d000e000d000d000d0000000d000d000d0013000000 -000010000d0012000d0000000d000d000d000e000e000e000d000e000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000e000d000e000d000d00 -0e000d000f000e000d000d000e000d000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000f000e000e000d000d000d000f000f000e000e00 -0e000d000e000d000d000e000e000e000d000d000d000d000e000e000e000d000d000e00 -0e000d000d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000d000d000d000e000d000d000d000d00110000000d0012001200040000000000 -10000d000d00120000000d0011000e000d000e000e000e000d000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000e000e000e000e000d00 -0e000d000d000e000d000d000e000e000e000d000e000e000e000e000e000d000e000e00 -0e000e000e000e000d000d000d000e000d000e000e000d000f000e000d000d000e000e00 -0e000e000e000e000d000d000e000e000d000e000e000d000d000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000e000d000d0011000d000d000d00000012000d000d000400000000001000 -0d000d000d0000000e000d000e000d000e000d000d000e000d000e000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000d000e000d000e000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000d000e000d000e000d000e000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000d000e000d000e000d000e000e000d000e000d000d000e000e000d000e000d00 -0e000e000d000e000d000e000e000e000e000e000e000e000e000e000e000d000d000e00 -0e000e000e000d000e000e000e000e000d000e000e000e000e000e000d000e000d000e00 -0e000e000e000e000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000d000e000d000e00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0d000e000d000e000d000e000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000d000e000d000e00 -0d000e000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000e000d000d000d000d000d000d000d0000000d000d000d0004000000000010001200 -12000d0000000d000e000d000e000e000e000e000d000e000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000e000d000d000d000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000e000e000e000d000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000e000e000e000d000d000e000d000e000e000e000e000e000e000e000e000e000e00 -0d000e000d000e000d000e000d000e000d000e000e000e000d000d000d000e000d000e00 -0d000e000e000d000d000e000e000e000e000d000e000d000e000e000d000e000d000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000d000d000e000e00 -0d000d000e000d000e000d000e000d000e000d000e000d000e000e000d000d000d000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000e00 -0e000e000d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000e000e000e000d000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000e00 -0e000e000d000d000d000e000d000d00000012000d001200040000000000100012000d00 -0d0000000d000e000e000d000e000d000d000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000d000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000d000e000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000d000d000e000d00 -0e000d000e000d000e000d000e000d000d000e000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000d000e000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000d000e000e000d000e000e00 -0e000e000d000e000e000e000e000e000d000e000e000d000e000d000d000e000e000e00 -0d000e000e000e000d000e000d000e000e000e000e000d000e000d000e000d000e000e00 -0e000d000e000d000e000d000e000d000e000d000d000e000d000e000d000e000d000e00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000d000e000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000d000d000e000d000e000d000e000d000e000d00 -0e000d000d000e000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000d000e00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000d000d000e000d00 -0d000e000d0011000d000d000d0000000d000d000d0004000000000010000d000d000d00 -00000d000d000e000e000e000e000e000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000e000d000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000e000d000d000e000d00 -0e000d000e000d000e000e000d000e000d000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000e000d000e000d000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000e000e000e000d000e000d000e000d000e000d000e00 -0d000e000e000e000d000e000d000e000e000d000e000e000d000d000e000d000e000d00 -0e000e000e000e000d000e000d000d000e000e000e000e000e000e000e000d000e000e00 -0e000d000e000d000e000d000e000d000e000e000d000e000d000d000d000e000d000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000e000d000d000e000d000e000d000e000d000e000e00 -0d000e000d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000e000d000e000d000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000e000d000d000e000e00 -0d000d000d000d000d000d00000012000d000d0013000000000010000d000d000d000000 -0d000d000e000e000e000e000d000e000d000e000d000e000d000d000e000d000e000d00 -0e000d000e000d000d000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000d000e000d000d000e000d000e000d00 -0e000d000e000d000d000e000d000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000d000e000d000d000e000d000e000d000e000d000e000d000d000e00 -0d000d000e000d000e000d000e000d000e000d000d000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000e000e000d000e000d000e000d000e000d000e000d00 -0e000d000d000e000d000e000d000e000d000d000e000d000e000d000e000d000e000d00 -0e000d000e000e000e000d000e000d000e000d000e000d000e000d000e000d000d000e00 -0d000e000d000e000d000d000e000e000e000d000e000e000e000e000e000e000e000d00 -0e000e000e000e000d000e000d000d000d000e000e000e000e000e000d000e000d000e00 -0e000e000d000e000d000e000e000d000d000e000d000e000e000e000d000e000e000e00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000d000e00 -0d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000d000e00 -0d000d000e000d000e000d000e000d000e000d000d000e000d000d000e000d000e000d00 -0e000d000e000d000d000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000e000e000d000e000d000e000d000e000d000e000d000e000d000d000e000d000e00 -0d000e000d000d000e000d000e000d000e000d000e000d000e000d000e000e000e000d00 -0e000d000e000d000e000d000e000d000e000d000d000e000d000e000d000e000d000d00 -0e000d000e000d000d000e000d000d000e000d000e000d000e000d000e000d000d000e00 -0d000d000e000d000e000d000e000d000e000d000d000d000e000d000e000d000d000e00 -0d000d000d000d000d0000000d000d001200040000000000100012000d000d0000000d00 -0d000e000e000e000e000e000d000d000d000e000d000e000e000d000e000d000e000d00 -0e000d000e000e000d000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000e000d000e000e000d000e000d000e000d00 -0e000d000e000e000d000e000e000d000e000d000e000d000e000d000e000d000d000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000e000d000e000e000d000e000d000e000d000e000d000e000e000d000e00 -0e000d000e000d000e000d000e000d000e000e000d000d000e000d000e000d000e000d00 -0e000d000e000d000e000e000d000d000e000d000e000d000e000d000e000d000e000d00 -0e000e000d000e000d000e000d000d000d000d000e000d000e000d000e000d000e000d00 -0e000e000d000d000e000d000e000d000e000d000e000d000e000d000e000e000d000e00 -0d000e000d000d000d000d000e000e000e000d000e000e000e000d000e000e000e000e00 -0d000e000d000e000e000e000e000e000e000d000d000e000d000e000e000e000d000e00 -0e000e000e000e000d000e000e000e000d000e000d000e000e000d000e000e000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000e000d000e00 -0e000d000e000d000e000d000e000d000e000d000d000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000e000d000e00 -0e000d000e000d000e000d000e000d000e000e000d000e000e000d000e000d000e000d00 -0e000d000e000e000d000d000e000d000e000d000e000d000e000d000e000d000e000e00 -0d000d000e000d000e000d000e000d000e000d000e000d000e000e000d000e000d000e00 -0d000d000d000d000e000d000e000d000e000d000e000d000e000e000d000d000e000d00 -0e000d000e000d000e000d000e000d000e000e000d000e000d000e000d000d000d000d00 -0e000d000e000e000d000e000e000d000e000d000e000d000e000d000e000e000d000e00 -0e000d000e000d000e000d000e000d000e000e000d000d000e000d000e000e000d000d00 -0d000d000d000d00000012000d000d0004000000000010000d0012000d0000000d000e00 -0d000e000e000e000d000e000e000d000e000e000e000e000e000d000e000e000e000d00 -0e000d000d000e000d000d000e000d000e000d000e000d000e000e000e000d000e000d00 -0e000d000e000e000e000d000e000d000e000e000e000e000e000d000e000e000e000d00 -0e000d000e000e000e000e000e000d000e000e000e000d000e000d000d000d000d000d00 -0e000d000e000d000e000d000e000e000e000d000e000d000e000d000e000e000e000d00 -0e000d000e000e000e000e000e000d000e000e000e000d000e000d000e000e000e000e00 -0e000d000e000e000e000d000e000d000d000e000d000d000e000d000e000e000e000d00 -0e000d000e000e000d000e000e000d000e000e000e000d000e000e000e000d000e000d00 -0d000e000d000e000d000d000d000d000e000d000e000e000e000d000e000d000e000e00 -0d000e000e000d000e000e000e000d000e000e000e000d000e000d000d000e000d000e00 -0d000d000d000d000e000e000e000d000d000e000e000e000e000e000e000e000e000e00 -0e000e000e000d000d000e000d000e000d000e000e000e000d000e000e000d000d000d00 -0d000d000d000e000e000d000e000e000e000e000e000e000e000e000e000e000e000d00 -0e000d000e000e000e000d000e000d000e000d000e000d000d000e000e000e000e000e00 -0e000d000e000e000e000d000e000d000d000d000d000d000e000d000e000d000e000d00 -0e000e000e000d000e000d000e000d000e000e000e000d000e000d000e000e000e000e00 -0e000d000e000e000e000d000e000d000e000e000e000e000e000d000e000e000e000d00 -0e000d000d000e000d000d000e000d000e000e000e000d000e000d000e000e000d000e00 -0e000d000e000e000e000d000e000e000e000d000e000d000d000e000d000e000d000d00 -0d000d000e000d000e000e000e000d000e000d000e000e000d000e000e000d000e000e00 -0e000d000e000e000e000d000e000d000d000e000d000e000d000d000d000d000e000d00 -0e000d000e000e000e000e000e000d000e000e000e000d000e000d000e000e000e000e00 -0e000d000e000e000e000d000e000d000d000e000d000d000e000e000e000e000e000d00 -11000d00110000000d001200120004000000000010000d000d000d0000000d000d000d00 -0d000e000d000d000d000d000d000d000d000d000d000e000d000d000d000d000e000d00 -0e000d000d000d000d000d000e000d000e000d000e000d000d000d000e000d000e000d00 -0e000d000d000d000e000d000e000d000d000d000d000e000d000d000d000d000e000d00 -0e000d000d000d000d000e000d000d000d000d000e000d000e000d000d000d000d000d00 -0e000d000e000d000e000d000d000d000e000d000e000d000e000d000d000d000e000d00 -0e000d000d000d000d000e000d000d000d000d000e000d000e000d000d000d000d000e00 -0d000d000d000d000e000d000e000d000d000d000d000e000d000d000d000d000e000d00 -0e000d000d000d000e000d000d000d000d000e000d000d000d000d000e000d000e000d00 -0d000d000d000e000d000d000d000e000d000d000d000d000e000d000e000d000d000d00 -0e000d000d000d000d000e000d000d000d000d000e000d000e000d000d000d000d000e00 -0d000d000d000d000d000d000d000d000d000d000d000e000d000d000d000d000d000d00 -0d000e000d000e000e000d000e000e000e000d000d000e000d000d000d000d000d000e00 -0e000e000e000d000e000e000d000d000d000d000d000d000d000d000d000d000e000d00 -0e000d000d000d000e000d000e000d000e000d000d000d000d000d000d000d000d000e00 -0d000d000d000d000e000d000e000d000d000d000d000d000e000d000e000d000e000d00 -0d000d000e000d000e000d000e000d000d000d000e000d000e000d000d000d000d000e00 -0d000d000d000d000e000d000e000d000d000d000d000e000d000d000d000d000e000d00 -0e000d000d000d000d000e000d000d000d000d000e000d000e000d000d000d000e000d00 -0d000d000d000e000d000d000d000d000e000d000e000d000d000d000d000e000d000d00 -0d000e000d000d000d000d000e000d000e000d000d000d000e000d000d000d000d000e00 -0d000d000d000d000e000d000e000d000d000d000d000e000d000d000d000d000e000d00 -0e000d000d000d000d000e000d000d000d000d000e000d000e000d000d000d000d000e00 -0d000d000d000d000e000d000e000d000d000d000d000d000d000d000d000d000e000d00 -0d000d0000000d000d000d00040000000000100012000d000d0000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -0000000012001200120013000000000010001100120012000d001100120012000d000d00 -0d0012000d0012000d000d000d0012000d000d000d0012000d0012000d000d000d001200 -0d0012000d000d0012000d0012000d0012000d000d000d0012000d0012000d0012000d00 -0d000d000d000d000d0012000d000d000d0012000d0012000d000d000d0012000d001200 -0d000d000d0012000d0012000d000d000d0012000d0012000d000d000d000d0012000d00 -12000d0012000d000d000d0012000d0012000d0012000d000d000d000d000d0012000d00 -12000d000d0012000d000d000d0012000d0012000d000d000d0012000d000d000d001200 -0d0012000d000d000d0012000d0012000d000d000d000d000d0012000d000d000d001200 -0d0012000d000d000d0012000d0012000d000d000d0012000d0012000d000d000d001200 -0d0012000d000d000d000d000d000d000d0012000d000d000d0012000d0012000d000d00 -0d0012000d0012000d000d000d0012000d0012000d000d000d0012000d0012000d000d00 -0d000c000d000d000b000d0012000d000d0012000d000d000d0012000d0012000d000d00 -0d0012000d000d000d0012000d0012000d000d000d0012000d0012000d000d0012000d00 -12000d0012000d000d000d0012000d0012000d0012000d000d000d000d000d000d001200 -0d000d000d0012000d0012000d000d000d0012000d0012000d000d000d0012000d001200 -0d000d000d0012000d0012000d000d000d000d0012000d0012000d0012000d000d000d00 -12000d0012000d0012000d000d000d000d000d0012000d0012000d000d0012000d000d00 -0d0012000d0012000d000d000d0012000d000d000d0012000d0012000d000d000d001200 -0d0012000d000d000d000d000d0012000d000d000d0012000d0012000d000d000d001200 -0d0012000d000d000d0012000d0012000d000d000d0012000d0012000d000d000d000d00 -0d000d000d0012000d000d000d0012000d0012000d000d000d0012000d0012000d000d00 -0d0012000d0012000d000d000d0012000d0012000d000d000d000d000d000d0012000d00 -12000d000d0012000d000d000d0012000d0012000d000d000d0012000d000d000d001200 -0d0012000d000d000d0012000d0012000d000d000d000d0012000d0012000d000d001200 -0b0011000d00110004000000000010000d001100120012000d000d000d0012000d000d00 -0d000d0012000d0012000d000d00120012000d000d000d000d0012000d000d000d000d00 -12000d000d00120012000d000d0012000d0012000d00120012000d000d0012000d001200 -0d00120012000d000d0012000d000d000d000d0012000d0012000d000d000d000d001200 -0d000d000d000d0012000d0012000d000d000d000d0012000d000d000d00120012000d00 -0d0012000d0012000d00120012000d000d0012000d0012000d000d0012000d000d001200 -12000d000d0012000d000d000d000d0012000d0012000d000d00120012000d000d000d00 -0d0012000d000d000d000d0012000d000d00120012000d000d0012000d000d000d000d00 -12000d0012000d000d000d000d0012000d000d000d000d0012000d0012000d000d000d00 -0d0012000d000d000d00120012000d000d0012000d000d000d000d0012000d0012000d00 -0d000d000d0012000d000d000d000d0012000d0012000d000d000d000d0012000d000d00 -0d000d000d000d000d00120012000d000d0012000d000d000d000d0012000d0012000d00 -0d00120012000d000d000d000d0012000d000d000d000d0012000d000d00120012000d00 -0d0012000d0012000d00120012000d000d0012000d0012000d00120012000d000d001200 -0d000d000d000d0012000d0012000d000d000d000d0012000d000d000d000d0012000d00 -12000d000d000d000d0012000d000d000d00120012000d000d0012000d0012000d001200 -12000d000d0012000d0012000d000d0012000d000d00120012000d000d0012000d000d00 -0d000d0012000d0012000d000d00120012000d000d000d000d0012000d000d000d000d00 -12000d000d00120012000d000d0012000d000d000d000d0012000d0012000d000d000d00 -0d0012000d000d000d000d0012000d0012000d000d000d000d0012000d000d000d001200 -12000d000d0012000d000d000d000d0012000d0012000d000d000d000d0012000d000d00 -0d000d0012000d0012000d000d000d000d0012000d000d000d000d0012000d000d001200 -12000d000d0012000d000d000d000d0012000d0012000d000d00120012000d000d000d00 -0d0012000d000d000d000d0012000d0012000d0012000d000d0012000d0012000d001100 -120012000d0004000000000010000d000d000d000d000d000d0012000d0012000d000d00 -12000d0012000d00120012000d000d0012000d00120012000d0012000d000d0012000d00 -120012000d000d000d0012000d000d000d0012000d000d000d0012000d000d000d001200 -0d000d00120012000d0012000d000d0012000d0012000d0012000d00120012000d001200 -0d000d0012000d0012000d0012000d00120012000d0012000d0012000d000d000d001200 -0d000d000d0012000d000d000d0012000d000d000d0012000d000d00120012000d000d00 -120012000d0012000d000d0012000d0012000d00120012000d000d0012000d0012001200 -0d0012000d000d0012000d00120012000d000d00120012000d0012000d000d0012000d00 -12000d0012000d00120012000d0012000d000d0012000d0012000d0012000d0012001200 -0d0012000d0012000d000d00120012000d0012000d000d0012000d0012000d0012000d00 -120012000d0012000d000d0012000d0012000d0012000d00120012000d0012000d000d00 -0d000d000d0012000d000d00120012000d0012000d000d0012000d0012000d0012001200 -0d000d0012000d00120012000d0012000d000d0012000d00120012000d000d000d001200 -0d000d000d0012000d000d000d0012000d000d000d0012000d000d00120012000d001200 -0d000d0012000d0012000d0012000d00120012000d0012000d000d0012000d0012000d00 -12000d00120012000d0012000d0012000d000d000d0012000d000d000d0012000d000d00 -0d0012000d000d000d0012000d000d00120012000d000d00120012000d0012000d000d00 -12000d0012000d00120012000d000d0012000d00120012000d0012000d000d0012000d00 -120012000d000d00120012000d0012000d000d0012000d0012000d0012000d0012001200 -0d0012000d000d0012000d0012000d0012000d00120012000d0012000d0012000d000d00 -120012000d0012000d000d0012000d0012000d0012000d00120012000d0012000d000d00 -12000d0012000d0012000d00120012000d0012000d0012000d000d00120012000d000d00 -120012000d0012000d000d0012000d0012000d00120012000d000d0012000d0012001200 -0d0012000d000d0012000d0012000d0012000d000d0012000d000d000d0012000d000d00 -0d000d000900000000001200130004001300040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004000400040004000400 -040004000400040004000400040004000400040004000400040004001300040013000400 -040004000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -00000000 -%%EndData -end -%%PageTrailer -%%Trailer -%%BoundingBox: 0 0 295 146 -%%EOF diff --git a/docs/tutorial/gtk_tut_packbox2.gif b/docs/tutorial/gtk_tut_packbox2.gif deleted file mode 100644 index ed70b422dca4f769a17b346ff9c5b26e6ea81746..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43000 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 diff --git a/docs/tutorial/gtk_tut_packbox2.jpg b/docs/tutorial/gtk_tut_packbox2.jpg deleted file mode 100644 index f711901bbf41502836a0da49620433925c6c69ec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19530 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 ISGNoQ2jeJA82|tP diff --git a/docs/tutorial/gtk_tut_table.eps b/docs/tutorial/gtk_tut_table.eps deleted file mode 100644 index 89c14231c1..0000000000 --- a/docs/tutorial/gtk_tut_table.eps +++ /dev/null @@ -1,1262 +0,0 @@ -%!PS-Adobe-3.0 EPSF-3.0 -%%Creator: (ImageMagick) -%%Title: (3.eps) -%%CreationDate: (Thu Jul 27 12:47:52 2000) -%%BoundingBox: 0 0 104.6 76 -%%DocumentData: Clean7Bit -%%LanguageLevel: 1 -%%Pages: 0 -%%EndComments - -%%BeginDefaults -%%PageOrientation: Portrait -%%EndDefaults - -%%BeginProlog -% -% Display a color image. The image is displayed in color on -% Postscript viewers or printers that support color, otherwise -% it is displayed as grayscale. -% -/buffer 512 string def -/byte 1 string def -/color_packet 3 string def -/pixels 768 string def - -/DirectClassPacket -{ - % - % Get a DirectClass packet. - % - % Parameters: - % red. - % green. - % blue. - % length: number of pixels minus one of this color (optional). - % - currentfile color_packet readhexstring pop pop - compression 0 gt - { - /number_pixels 3 def - } - { - currentfile byte readhexstring pop 0 get - /number_pixels exch 1 add 3 mul def - } ifelse - 0 3 number_pixels 1 sub - { - pixels exch color_packet putinterval - } for - pixels 0 number_pixels getinterval -} bind def - -/DirectClassImage -{ - % - % Display a DirectClass image. - % - systemdict /colorimage known - { - columns rows 8 - [ - columns 0 0 - rows neg 0 rows - ] - { DirectClassPacket } false 3 colorimage - } - { - % - % No colorimage operator; convert to grayscale. - % - columns rows 8 - [ - columns 0 0 - rows neg 0 rows - ] - { GrayDirectClassPacket } image - } ifelse -} bind def - -/GrayDirectClassPacket -{ - % - % Get a DirectClass packet; convert to grayscale. - % - % Parameters: - % red - % green - % blue - % length: number of pixels minus one of this color (optional). - % - currentfile color_packet readhexstring pop pop - color_packet 0 get 0.299 mul - color_packet 1 get 0.587 mul add - color_packet 2 get 0.114 mul add - cvi - /gray_packet exch def - compression 0 gt - { - /number_pixels 1 def - } - { - currentfile byte readhexstring pop 0 get - /number_pixels exch 1 add def - } ifelse - 0 1 number_pixels 1 sub - { - pixels exch gray_packet put - } for - pixels 0 number_pixels getinterval -} bind def - -/GrayPseudoClassPacket -{ - % - % Get a PseudoClass packet; convert to grayscale. - % - % Parameters: - % index: index into the colormap. - % length: number of pixels minus one of this color (optional). - % - currentfile byte readhexstring pop 0 get - /offset exch 3 mul def - /color_packet colormap offset 3 getinterval def - color_packet 0 get 0.299 mul - color_packet 1 get 0.587 mul add - color_packet 2 get 0.114 mul add - cvi - /gray_packet exch def - compression 0 gt - { - /number_pixels 1 def - } - { - currentfile byte readhexstring pop 0 get - /number_pixels exch 1 add def - } ifelse - 0 1 number_pixels 1 sub - { - pixels exch gray_packet put - } for - pixels 0 number_pixels getinterval -} bind def - -/PseudoClassPacket -{ - % - % Get a PseudoClass packet. - % - % Parameters: - % index: index into the colormap. - % length: number of pixels minus one of this color (optional). - % - currentfile byte readhexstring pop 0 get - /offset exch 3 mul def - /color_packet colormap offset 3 getinterval def - compression 0 gt - { - /number_pixels 3 def - } - { - currentfile byte readhexstring pop 0 get - /number_pixels exch 1 add 3 mul def - } ifelse - 0 3 number_pixels 1 sub - { - pixels exch color_packet putinterval - } for - pixels 0 number_pixels getinterval -} bind def - -/PseudoClassImage -{ - % - % Display a PseudoClass image. - % - % Parameters: - % class: 0-PseudoClass or 1-Grayscale. - % - currentfile buffer readline pop - token pop /class exch def pop - class 0 gt - { - currentfile buffer readline pop - token pop /depth exch def pop - /grays columns 8 add depth sub depth mul 8 idiv string def - columns rows depth - [ - columns 0 0 - rows neg 0 rows - ] - { currentfile grays readhexstring pop } image - } - { - % - % Parameters: - % colors: number of colors in the colormap. - % colormap: red, green, blue color packets. - % - currentfile buffer readline pop - token pop /colors exch def pop - /colors colors 3 mul def - /colormap colors string def - currentfile colormap readhexstring pop pop - systemdict /colorimage known - { - columns rows 8 - [ - columns 0 0 - rows neg 0 rows - ] - { PseudoClassPacket } false 3 colorimage - } - { - % - % No colorimage operator; convert to grayscale. - % - columns rows 8 - [ - columns 0 0 - rows neg 0 rows - ] - { GrayPseudoClassPacket } image - } ifelse - } ifelse -} bind def - -/DisplayImage -{ - % - % Display a DirectClass or PseudoClass image. - % - % Parameters: - % x & y translation. - % x & y scale. - % label pointsize. - % image label. - % image columns & rows. - % class: 0-DirectClass or 1-PseudoClass. - % compression: 0-RunlengthEncodedCompression or 1-NoCompression. - % hex color packets. - % - gsave - currentfile buffer readline pop - token pop /x exch def - token pop /y exch def pop - x y translate - currentfile buffer readline pop - token pop /x exch def - token pop /y exch def pop - currentfile buffer readline pop - token pop /pointsize exch def pop - /Helvetica findfont pointsize scalefont setfont - x y scale - currentfile buffer readline pop - token pop /columns exch def - token pop /rows exch def pop - currentfile buffer readline pop - token pop /class exch def pop - currentfile buffer readline pop - token pop /compression exch def pop - class 0 gt { PseudoClassImage } { DirectClassImage } ifelse - grestore -} bind def -%%EndProlog -%%Page: 1 1 -%%PageBoundingBox: 0 0 106 77 -userdict begin -%%BeginData: -DisplayImage -0 0 -105.6 76.8 -12 -154 112 -1 -0 -0 -20 -020206 -05062d -040555 -020175 -2b3361 -7b7a79 -080786 -232098 -79788d -7672cd -81827d -8c8a94 -a6a4ae -d4d1da -d7d4e1 -e1deea -f8f7fa -e1e5e8 -bfbdc7 -817ea0 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000200020003000300030003000300030003000300030003000300030003000300 -060006000600060006000600060006000300060006000600060006000600060002000200 -030003000600060006000600060006000300030003000300030003000300030003000300 -030003000300030003000300030003000300030003000300030003000300030003000300 -030003000300030003000200000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000001000100010001000100010001000 -1000100010001000100010001000100010001000110010000e0007000300060006000600 -060007000600070003000300060006000600070006000600060006000600060006000300 -070006000600060006000600060003000700030006000600060006000600060006000600 -060006000600060006000600060006000600060006000600060006000600060006000600 -060006000600060006000600060006000600060006000600060006000600030001001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -12000000000010000d0012000d000d0012000e000d000d000d000d000d000d000d000d00 -0d000d000d000d0009000600030003000300060003000300030003000300020002000200 -030003000600030006000300030006000300030003000600030003000300030003000600 -020003000300060003000300020003000600060003000300030006000300030006000300 -060003000300060003000600060006000300030006000600030006000300060003000600 -06000600030003000600060003000300010010000d000d000d000d000d00120012000d00 -0d000d000d000d000d000d000d000d000d000d001200120012000d000d000d000d000d00 -0d000d000d0012000d000d0012000d000d000d000d000d000d000d000d000d0012000d00 -0d0012000d000d000d000d000d000d000d000d000a000000000010000d00110005000000 -000000000000000000000000000000000000000000000d000d000d000900030006000300 -030003000300060003000300020002000200030002000300030003000300030003000300 -060003000200020003000200020003000600060003000300030003000300030002000200 -030006000300030003000300030003000300030003000300030003000300030003000300 -030003000300030003000300030003000300030003000300030003000300030003000200 -0100100012000b000a0005000a000b000a000a000a000a000a000a000500050005000500 -0d000d0012000a000a0005000500050005000a00050005000a000a000a000a000a000a00 -12000d0012000a00050005000b000500050005000a0005000a00050005000a0005000a00 -0d00120005000000000010000d000d001200100010001000100010001000100010001000 -100010001000100012000e00090006000300060007000300030003000200020002000200 -030002000300030003000300030003000300030002000300030003000300030003000300 -030006000300020003000600060003000300030006000600060003000600060006000600 -030006000600060006000600030006000600060003000600060006000300060003000600 -06000600060003000600060006000300060002000000100012000a001000100010001000 -11001100110011001000100010001100100012001000120012000a001000100010001000 -100010001000100010001000100010001000120010000d00120005001000100010001100 -1000100010001000100010001100100010000d0010000d000a0000000000100012000d00 -05000000000000000000000000000000000000000000000000000d000d000e0009000600 -030003000300030010001000100010001000100010001000100003000200030007000300 -030002000700070010000300030003000300030007000700100003000300030006000300 -030003000600060003000300030003000300030003000300030003000300030003000300 -030003000300030003000300030003000300030003000300030003000300030003000300 -03000200010010000d000a001000110012000d000d000d000d000d000d000d000d000d00 -0d000a0010000d0011000a0010000d0012000d000d000d000d000d0012000d000d000d00 -12000a00100012000d000a00100012001200110012000d000d000d000d0011000d001200 -12000a001100120005000000000010000d000d0011001000100010001000100010001000 -1000100010001000110010000d000d000900060003000300030006000200030003000200 -100002000200030007000300030002000300060003000300030002001000030003000600 -060006000300030010000200030006000300030003000300060006000300030003000300 -060006000300030006000300030003000300060006000300030006000600030003000600 -0600030006000300060006000300030006000300030003000000100012000a0010001200 -12000d0012000d0012001200120012000d0012000d000500100012000d000a0010000d00 -11000c000d000d0012000d00120011000d0011001200050010000d000d00050010000d00 -0d000d000d001200110012000d000c0011000d000d000a0010000d000b00000000001000 -12000d0005000000000000000000000000000000000000000000000001000d0012000e00 -090006000600030003000300060002000200030010000200030003000300030003000200 -030003000200020003000300100002000300020002000300030003001000020003000200 -030003000300030006000600030003000300060003000300060003000300060003000600 -060003000300060003000300030006000300030006000300030006000300030006000300 -03000600060002000100100012000a0010000d000d0012000d000d000d000d000d000d00 -0d000d000d00050010000d0012000a00100012000d000000000000000000000000000000 -00000c0011000a0011000d000d000a0010000d000500000012000d000d0012000d000000 -05000d0012000a0010000d0005000000000010000d000d000d0010001000100010001000 -1000100010001000100010001000100012000d0009000600030003000300030003000300 -030002001000020002000300030002000200100011001000100002000300020010000200 -100010001000020002000300100002000300020010001000100010000200030003000300 -030003000600030003000600030003000600030003000600030003000600030003000300 -06000300030006000300030003000600030003000600030003000200000010000d000a00 -10000d0012000d000d0012000d0012000d0012000d0012001200050010000d000d000500 -10000d000d00000000000000000000000000000000000d000d000a0010000d0012000a00 -100011001200000000000d0011000d0000000000110012000d00050010000d0005000000 -000010000d000d0005000000000000000000000000000000000000000000000000001200 -0d0012000900060006000300060003000300030003000200100002000300030002000200 -100010000200020010001000020002001000100002000100100010000200020010000200 -020010001100040001001000100002000300030003000600030003000300030006000600 -060003000600030003000600060003000600030003000600060003000600030003000300 -0600060003000600030003000100100012000b00100012000d000d000d000d000d001200 -0d000d000d000d000d00050010000d0012000500100012000d0000000000000000000000 -0000000000000d001200050010000d000d00050010000d000d000d000000000012000000 -00000d00120011001200050010001200050000000000100012000d001100100010001000 -100010001000100010001000100010001000100012000d00090007000300030003000600 -030003000300030010000200020003000300020001000200020002000200100003000200 -110002000100020002001000020002001000020002001000020002000100020010000300 -020003000300060003000600060003000600030003000300060003000600030003000600 -030006000600030003000300060006000600030006000300030006000600020000001000 -0d000a0010000d00120012000d000d000d0012000d0012000d0011000d00050010000d00 -0d000a0010000d001200000012000d000d000d001200110000000d000d000a0010001200 -0d00050010000d000d0012000d000000000000000d0012000d0012000d000a0010000d00 -0a0000000000100012000d00050000000000000000000000000000000000000000000000 -00000d000d000d0009000300060003000600060003000300030003001000030003000600 -030003000200100010001000100010000200030010000200020002000200100003000200 -100002000200100010000f00100010001000030003000300030003000600030003000600 -030003000600030003000600030006000300030003000600030003000300060003000300 -03000600030003000600030003000200000010000d000500100011001200100012000d00 -120011001200120011000c001200050010000d001200050010000d000d00000011001200 -0d0011001200120000000d0012000a00100012000d000a0010000d000d0011000d000000 -000000000d000d0012000d000d00050010000d000a000000000010000d000d000d001000 -10001000100010001000100010001000100010001000100012000d000900070003000600 -060006000300030003000200100002000300030006000300100010000200020002001000 -030006001000020003000200020010000300020010000200020010000200020002000200 -030003000200030003000600030003000600030003000600030006000300030003000600 -030003000600030003000600030006000300030003000600030003000600030003000300 -0100100012000a00100012000d00120012000d0011000d0012000d000d0011000d000500 -10000d000d000a00100012000d0000001100110012000d000d000d000000110012000500 -10000d000d000a0010000d0012000d00000000001100000000000d0011000d000d000a00 -10000d000a000000000010000d000d000500000000000000000000000000000000000000 -0000000000000d000d000d00090006000600060006000600030003000300020010000200 -060003000600030011000200020002000100100002000200100002000200020002001000 -030003001000020003001000020002000200020003000300060003000600030003000600 -030006000600030003000300060006000600030003000600030006000600030003000300 -0600060006000300030006000300060006000200000010000d000a00100012000d000000 -00000000000000000000000000000d000d000a001000120012000a0010000d000d000000 -0c001100120012000d000d0000000d0011000a0010000d0012000a00100012000d000000 -0000120012000d0000000000120012000d000a0010000d0005000000000010000d001200 -0d0010001000100010001000100010001000100010001000100010000d000e0009000600 -030006000600030003000300030002001000020003000300030002001000100001000200 -100010000300030010001000010002001000100002000200100002000200100010000200 -010010001000030003000300060003000600030006000300060003000600030006000300 -060003000600030006000300060003000600030006000300060003000600030006000300 -03000300010010000d00050010000d000d00000000000000000000000000000000000d00 -1200050010000d000d000a0010000d001200000000000000000000000000000000001200 -0d00050010000d0012000a0011001000050000000d000d000d000d000d00000005001100 -120005001000120005000000000010000d000d0005000000000000000000000000000000 -0000000000000000000012000d000d000900060006000300060003000300030003000300 -100003000300060003000300010010001000100001001000100003001000020010001000 -100002000200030010000200030002001000100010001000020003000300060003000600 -030003000300030003000600030003000300030003000600030003000300030003000600 -030003000300030003000600030003000300030003000200010010000d00050010000d00 -12000d000d0011000d00110012001100110012000d00050010000d0012000a0010000d00 -0d000d000d0012000d000d000d000d001200110012000a0010000d000d000a0010001200 -12000d0012000d0012000d0011001200110012000d000a0011000d000500000000001000 -12000d000d00100010001000100010001000100010001000100010001000100012001100 -090003000300030003000300030003000300030003000300030003000300030002000300 -030002000200030003000300030003000200030002000300030003000300030003000300 -030003000200030003000300030003000300030003000300030003000300030003000300 -030003000300030003000300030003000300030003000300030003000300030003000300 -0300030003000200000010000d000500100012000d000d0012000d0012000d0012000d00 -0d000d000d000500100012001200050010000d000d0012000d000d0012000d000d001200 -0d000d0012000500100012000d00050010000d0012000d00120012000d000d0012000d00 -0d0012001200050010000d0005000000000010000d000d00050001000000000000000000 -000000000000000000000000000012001100120009000700030003000300030003000300 -030003000300030003000300030003000300030003000300030003000300030003000300 -030003000300030003000300030003000300030003000300030003000300030003000300 -030003000300030003000300030003000300030003000300030003000300030003000300 -03000300030003000300030003000300030003000300030003000200000010000d000a00 -12000500050005000a0005000500050005000500050005000500050010000d000d000a00 -1200050005000500050005000500050005000a000a0005000500050010000d0012000a00 -0c000a000a000a000a0005000a0005000a000a00050005000a000a0010000d0005000000 -0000100012000d000d001000100010001000100010001000100010001000100010001000 -0e000e000900030003000700030003000300030003000300030006000300030006000300 -060006000300030006000300030006000300060003000300060006000600030003000600 -030003000300030006000300060006000300030006000300030003000600030006000600 -030006000600030006000300030003000600060006000600060003000600060003000300 -060003000600030006000200000010000d00120010001000100010001000100010001000 -1000100010001000100010001000120012000d0010001000100010001000100010001000 -100010001000100010001000100012000d00120010001000100010001000100010001000 -1000100010001000100010001000120005000000000010000d00120012000d000e000d00 -0d000d000d000d000d000d000d000d0012000e000e000e00090002000300030002000200 -020002000200020002000300030002000300030003000200030003000300030002000300 -020003000300030002000300020003000200030003000300030003000200030002000300 -030002000300030003000300030003000200030003000200030003000300030003000300 -030002000300020003000300020003000300020003000300030003000300020000001000 -0d00120012000d000d000d000d000d000d000d000d000d000d000d00120011000d001200 -0d000d000d000d000d000d000d00120012000d000d0012000d000d000d000d000d001200 -0d000d00120012000d000d000d000d000d000d000d000d000d000d00120012000d001100 -05000000000010000e000d001100050005000a000a0005000a0005000800050005000500 -08000a000500080008000200010001000100000000000000000000000100010000000100 -010000000100000001000000000001000000010001000000000001000100000001000100 -010000000100000000000100000001000000010000000100000001000000010000000100 -000001000100000001000000000001000100000000000100000001000000010000000100 -00000100010000000100000001000000010012000b000b000a0005000b000b0005000a00 -0500050008000800050005000500050005000a000a000a00050005000a0005000a000a00 -0a000a000a000a000b000500050005000b000a000b0008000a000a000a000a0005000a00 -0b000500050005000a000a000a000d0012000d0005000000000010000d000d000d000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000001200 -0d00120005000000000010000d0012000d0000000d000e000d000d000d000d000d000d00 -0d000d000d0012000d0011000e000e0010000d0011000d000d000d000d000d000d000d00 -0e000e000f000e000f000e000f000f000d000e000e000e000e000e000e000e000e000e00 -0d000d000e000e000e000e000e000e000d000d000f000d000f0011000e000e000e000e00 -0e000e000e000d000e000e000e000e000e000e0011000d000e000e000e000e000e000e00 -0e000d000f000e000e000e000e000e000e000e000d000d000e0011000e000d000d001100 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d0011000d000e000d000e000e000e000e000d0011000d000d00 -0d000e000e000e000d000d000d001200000012000d000d0005000000000010000d000d00 -0d0000000e000d000d000d000d000d000d000d000d000d000d0011000d000d000e000e00 -0e000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000e000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000e000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d0011000d000d000e000e000d000e000e000d000e000e000e000e000e00 -0d0011000d000d000d000d000d0011000e000e000d000e000e000e000e000e000d000d00 -0d000e000e000e0012000e000d000d000d000d000e000e000d000d000d00110012001100 -00000d0012000d0005000000000010000d000d00120000000d000d000d000d000e000d00 -0d000d000d000e000e000e000f000e000e000f000e000e000d000d000d000d000e000e00 -0e000e000e000d000d000f000d000d000d000d000d000d000d000d000d0011000d000d00 -0e000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000e00 -0d000d000d000d000d000d000d000d0011000d000d000d000d000d000d000e000d000d00 -0d000d000d000d000d000d0011000d000d000d000d000f000d000d000e000e000e000e00 -0e000e000e000e000e000e000e000e000d000d000d000e000e000d000e000e000e000e00 -0e000e000d000e000d000e000e000e000d000e000d000e000d000e000d000e000e000d00 -0e000e000e000d000e000d000d000d000d000d0000000d000d000d000500000000001000 -0d000d000d0000000d000d000d000d000e000d000e000d000e000e000e000e000e000e00 -0e000e000e000e000d0011000e000e000e000f000e000f000e000d000d000d000d000d00 -0d000d000d000d000d000f000d000d000d000d000d000d000d000d000d000d000e000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000f000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000e000e000e000e000d000e000d000d000e000d000e000e000e00 -0e000d000e000e000e000e000e000d000e000e000e000e000e000d000e000d000e000d00 -0e000d000e000e000e000e000e000d000e000e000e000d000d000e000d000e000d000e00 -0d000d0000000d000d000d0005000000000010000d000d000d0000000d000d000d000d00 -0d000e000e000e000e000d000e000e000d000d000e000e000d000d000d000d000d000d00 -0e000e000e000e000e000e000d0011000d000f000d000e000e000e000e000d000d000d00 -0e000d000e000e000e000e000d000e000f000d000e000e000e000e0011000e000d000e00 -0e000e000e000e000e000e000e000e000d000d000f000d000d000d000e000e000e000e00 -0e000e000e000e000e000e000d000d000f000d000d000d000d000e000e000e000e000e00 -0e000e000d000e000e000e000d000e000e000e000e000e000e000e000e000e000d000e00 -0e000d000e000d000e000e000e000e000e000e000d000e000e000e000e000e000e000e00 -0e000d000e000e000e000e000e000d000e000e000d000d000000120012000d0005000000 -000010000d000d000d0000000d000d000d000d000e000d000e000e000e000d000e000e00 -0d000d000d000d000d000d000d000d000d0011000e000e000e000e000e000d000d000d00 -0d000d000d000d000f000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000e000d000d000e000d000d000d000e000e000e000d000e000d00 -0e000d000d000d0011000d000d000d000d000d000e000e000e000d000e000d000e000d00 -0d000d0011000d000e000e000d000e000e000e000e000d000e000d000e000d000e000d00 -0e000e000e000d000e000d000d000e000e000e000e000e000d000e000e000e000d000e00 -0e000d000e000e000e000e000d000e000d000e000e000e000e000d000e000e000e000d00 -0d000e000d000d0000000d0012000d0005000000000010000d000d000d0000000d000d00 -0d000d000d000e000e000e000e000e000e000e000e000d000d000d000d000d000d000e00 -0e000e000e000e000e000e000d000d000d000d000d0011000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000e000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000e000d000e000d000e000d00 -0e000d000d000d000e000d000d000e000e000e000e000e000e000d0000000d000d000d00 -0a000000000010000d000d000d0000000d000d000e000d000e000e000e000e000e000e00 -0e000e000e000d000e000d000d000d000e000e000e000e000e000e000e000e000d000d00 -0d000d000d000d000d000d000d000d000d000d000e000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000e00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000e000d000d00 -0d000d000d000d000d000d000d000d000d000d000e000d000d000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000d000e000d000e000d000e000d000e000d000e000d000e000e000e00 -0d000e000e000e000e000d0000000d000d000d0005000000000010000d0012000d000000 -0d000d000d000e000e000e000e000e000e000e000e000e000e000d000d000d000d000d00 -0e000e000e000e000e000e000e000e000d000e000d000d000d000d000d000d000d000d00 -0d000d000e000d000e000d0011000d000d000e000d000d000f000d000e000d000e000e00 -0e000e000e000d000e000d000e000d000e000e000d000d000d000d000e000d0011000d00 -0e000e000e000d000e000d000e000e000d000d000d000d000e000d0011000d000e000e00 -0e000d000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e00 -0d000e000d000e000d000e000d000e000d000e000d000e000d000e000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000d000e000e000e000d000d0000000d00 -0d00120005000000000010000d000d000d0000000d000d000d000d000e000d000d000e00 -0e000e000e000e000d000d000d000d000d000d000d000e000d000e000e000e000d000e00 -0d000e000e000d0011000d000e000e000e000d000d0011000e000e000e000d000e000d00 -0d000d000f000e000e000d000e000d000e000d000e000e000e000e000e000e000e000d00 -0e000e000e000e000f000d000e000e000d000d000d000e000e000e000e000d000e000e00 -0e000e000f000d000e000e000d000d000d000e000d000e000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000d000e000d000e000d000e000d000e000d000e000d000e00 -0e000d000e000e000e000e000d000d00000012000d000d0005000000000010000d000d00 -0d0000000d000d000d000d000d000e000d000e000d000e000e000e000d000d000d000d00 -0d000e000d000d000e000d000e000d000d000d000e000d000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000d000e000e000e000e000e000d000e000e000e000d00 -0e000e000e000d000e000e000e000d000e000e000e000d000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000d000e000d000e000d00 -0e000d000e000e000e000e000e000e000d000e000d000e000e000d000e000e000e000e00 -0d000d000e000e000e000d000e000e000e000d000e000d000e000e000d000e000e000d00 -0e000e000d000e000d000e000e000e000d000e000e000e000d000d000e000e000d000d00 -00000d000d000d0005000000000010000d000d000d0000000d000d000e000e000e000e00 -0e000e000e000e000e000d000e000e000e000e000e000e000e000e000e000e000e000d00 -0e000d000e000e000d000e000d000e000e000d000e000d000d000e000d000e000d000e00 -0d000e000d000e000d000e000e000d000d000e000d000e000e000e000e000d000e000e00 -0d000e000e000e000d000e000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000e000e000e000e000e000e000e000d000e000d000e000e000e00 -0d000e000e000e000d000e000e000d000d000e000e000e000e000d000e000d000e000d00 -0d000e000e000d000d000e000d000e000e000d000e000d000d000e000e000d000d000e00 -0d000e000d000e000e000e000d000d000d000d0000000d000d0012000500000000001000 -0d0012000d0000000d000e000e000e000e000e000e000d000e000e000e000e000e000e00 -0e000e000d000d000d000e000d000e000e000e000d000e000e000e000e000e000d000e00 -0e000d000d000d000e000e000e000d000e000e000d000e000e000e000e000e000e000e00 -0e000d000e000e000e000d000e000d000e000d000e000d000e000d000e000d000d000e00 -0e000e000d000e000e000e000d000e000e000e000d000e000e000e000e000d000d000e00 -0e000d000d000e000e000d000e000d000e000d000e000e000e000d000e000d000e000e00 -0d000d000d000e000e000d000e000e000e000e000e000e000e000e000e000d000e000e00 -0e000e000d000e000e000e000e000e000e000e000e000e000d000e000e000d000e000d00 -0d000d00000012000d00120005000000000010000d000d000d0000000d000e000e000e00 -0e000e000e000e000e000d000d000e000d000d000d000e000e000e000e000e000d000e00 -0d000e000e000e000d000d000e000d000e000d000e000e000e000e000e000d000e000e00 -0e000d000e000e000d000d000e000d000d000e000e000e000e000d000e000d000e000e00 -0e000e000e000d000e000e000e000d000e000d000d000e000e000d000d000e000e000d00 -0d000e000e000d000d000e000e000e000e000d000e000e000e000d000d000e000d000e00 -0e000e000e000d000e000d000e000e000d000e000e000e000e000e000d000e000d000e00 -0d000d000e000d000d000e000d000e000e000d000d000e000e000d000e000d000d000e00 -0d000d000e000d000e000d000e000e000d000e000d000d00000012000d000d0005000000 -000010000d000d000d0000000e000e000e000e000d000e000d000d000e000d000d000e00 -0e000e000e000d000e000e000e000d000e000d000e000d000e000d000e000e000e000e00 -0d000e000d000e000e000d000d000e000d000d000e000d000e000d000e000e000d000e00 -0e000e000d000e000d000e000d000e000d000e000d000d000e000e000d000e000e000e00 -0e000e000d000e000e000e000d000e000e000e000d000e000e000e000d000e000d000e00 -0e000d000d000e000e000e000e000d000d000e000d000e000e000d000e000e000d000d00 -0e000e000e000d000e000d000e000d000e000e000e000e000e000d000d000e000e000e00 -0e000d000d000e000e000e000e000d000d000e000e000e000e000e000d000e000d000e00 -0d000d000d000d0000000d000d000d0005000000000010000d0012000d0000000d000e00 -0e000e000e000e000e000e000e000e000e000e000d000e000e000e000d000d000d000e00 -0e000d000e000e000d000e000e000d000d000e000d000e000e000e000e000e000e000e00 -0e000e000e000e000e000d000e000d000e000e000d000d000e000d000e000e000d000e00 -0e000d000e000e000e000d000e000d000d000e000d000e000d000e000d000e000e000d00 -0d000e000d000e000d000e000e000d000e000d000e000e000e000e000d000e000e000e00 -0e000e000e000d000e000e000d000e000e000e000d000d000e000e000e000e000e000d00 -0e000d000d000e000d000e000e000e000e000d000e000e000e000e000d000e000e000e00 -0e000d000e000d000d000e000d000e000e000e000d000d000d000d0000000d000d000d00 -0a000000000010000d000d000d0000000d000e000e000e000e000e000d000e000d000e00 -0e000d000d000e000d000e000e000e000e000e000e000e000d000d000e000e000e000e00 -0d000e000e000e000d000d000d000e000e000d000d000e000d000e000e000e000d000e00 -0e000d000d000e000e000e000d000d000e000e000e000e000d000e000d000e000e000e00 -0d000e000e000e000e000e000d000e000e000e000e000e000e000e000d000e000e000e00 -0d000e000d000e000e000d000d000e000d000e000e000d000d000e000d000e000d000e00 -0e000d000e000e000e000d000d000d000e000e000e000d000e000e000e000e000e000d00 -0e000d000d000e000e000d000d000e000d000e000e000e000e000e000d000e000e000e00 -0d000d000d000d000d000d000000120012000d0005000000000010000d000d0012000000 -0d000e000e000e000e000e000e000e000d000e000d000e000e000e000d000e000d000e00 -0e000d000d000e000e000e000e000d000d000e000e000d000e000d000e000e000d000e00 -0d000e000e000e000d000e000d000e000e000d000e000e000e000e000d000e000e000e00 -0e000d000d000e000e000e000d000e000d000e000e000e000d000d000e000d000e000e00 -0d000e000d000d000e000d000e000e000d000d000e000e000d000e000e000d000e000e00 -0e000d000e000d000e000e000d000e000e000e000d000e000e000d000e000e000e000e00 -0d000e000d000e000e000d000e000d000e000d000e000e000d000e000e000d000e000e00 -0d000e000d000e000d000e000e000d000e000d000e000e000d000d0011000d0000001200 -0d000d0005000000000010000d0012000d0000000d000e000d000e000d000e000d000e00 -0e000e000e000d000e000e000d000e000d000e000e000e000e000f000d000e000f000d00 -0e000e000e000e000e000e000e000e000e000d000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000d000e000e00 -0e000e000e000e000d000d000e000e000f000e000e000d000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000d000e000e000e000e000e000e00 -0e000e000e000d000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000d000e000d000e000e000d000e000e000e000d000e000d000e000d000e000e000e00 -0e000d000d000e000d000d000d000d0000000d000d000d000a000000000010000d000d00 -0d0000000e000e000e000d000e000e000d000e000d000e000e000d000d000e000d000e00 -0e000e000d000d000e000e000d000d000e000d000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000f000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000f000e000d00 -12000e000d000f000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000f000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000d000d000e000e000f000e00110012000e000d00 -0d000e000d000e000e000e000e000e000d000d000e000e000e000d0011000d000d000d00 -00000d000d000d000a000000000010000d0012000d0000000d000e000d000e000e000e00 -0e000d000e000d000e000e000d000e000e000e000e000d000e000f001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -10001000100010001000100010001000100010000c001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -10001000100010001000100010000c000e000e000d000e000e000e000d000d000e000d00 -0d000e000d000e000e000e000d000d000d000d0000000d0012000d000a00000000001000 -0d000d000d0000000d000e000e000d000d000e000d000e000d000e000d000e000e000e00 -0e000d000d000e000d000e0010000f000e000d000d000d000e000e000e000e000e000e00 -0e000e000e000e000e000e000f000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000f000e000e000e000e000d00 -0e000e000b0010000d000f000e000e000e000e000f000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000f000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000d000f000e000e000f000e000800 -0d000e000e000e000e000d000e000e000e000e000e000e000d000e000d000e0011000d00 -0d000d00000012000d000d000a000000000010000d000d000d0000000d000d000e000e00 -0e000e000e000e000e000e000d000e000e000d000e000d000d000e000e000e0010000f00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000e000e000b0010000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000e000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000e000e000f000b000d000e000d000d000e000d000d000e00 -0d000e000e000d000e000d000e000e000d000d000d000d0000000d000d0012000a000000 -000010000d000d000d0000000d000d000e000e000e000e000d000e000e000e000e000e00 -0d000e000e000e000e000e000d000d0010000e000e000e000f000f000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000d000e000d000b0010000e000d000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000f000e000e000e000e000d00 -0d000b000e000e000e000e000e000e000e000e000e000d000e000e000e000d000e000d00 -0d000d000d000d00000012000d000d000a000000000010000d0012000d0000000d000e00 -0e000d000e000d000d000e000d000e000e000d000e000d000d000e000e000d000e000e00 -10000d000e000d000d000d000d000e000e000e000d000e000d000e000d000e000d000e00 -0d000e000e000e000d000e000d000e000d000e000d000e000d000e000e000e000d000e00 -0d000d000d000e000d000e000d000e000e000e000e000e000d000e000b0010000d000d00 -0d000e000d000e000d000e000e000e000d000e000d000e000e000e000e000d000e000e00 -0d000e000d000e000d000e000e000e000d000e000d000e000d000e000d000e000e000e00 -0e000e000d000d000d000d000d000d000e000d000d000b000e000d000e000d000d000e00 -0e000d000d000e000d000e000d000e000e000e000d0011000d000d0000000d000d001200 -05000000000010000d000d000d0000000e000e000d000e000e000e000e000e000d000e00 -0e000d000e000e000d000e000e000e000e000d0010000e000e000e000e000e000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000d000f000d000f000b0010000d000e000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000d000d000e000d000e000d000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000d000d000d000d000d000d000e000e000d00 -0f000f000d000b000e000d000e000e000e000d000e000d000e000e000d000e000e000e00 -0d000d000d000d000d000d0000000d000d000d000a000000000010000d000d000d000000 -0d000d000d000e000e000d000d000e000d000e000d000e000e000e000d000d000e000d00 -0e000d0010000d000e000d0000000e000e000d000d000f000d000e000d000e000d000d00 -0d000d0000000d000f0000000d000f000d000d000e000e000e000e000d000f000d000d00 -0e000d000e000d000d000f000d000e000e000d0000000d000e000e000d000d000b001000 -0d000e000d0000000d000e000d000d000d000e000d000d000e000d000e000d000e000000 -0e000e0000000d000e000d000d000f000d000d000f000d000d000f000d000d000e000d00 -0e000d0011000d000d000d000000000000000d000e000e000d000b000e000e000d000d00 -0e000e000e000e000d000e000e000d000d000e000e000e000d000d000d000d0000001200 -0d000d0005000000000010000d001200120000000d000e000e000e000e000e000e000e00 -0e000d000e000e000d000e000e000e000e000e000e000d0010000d000e000f0000000e00 -0d0011000d000d000e000d000e000d000e000f000d000e0000000d000f0000000e000f00 -0d000f000d0012000e000d000f000d000d0010000d0012000f000d000e00120010000d00 -00000000000011000e000e000d000e000b0010000d000e000f00000012000e000d000f00 -0d000d000e000d000d000e000e000d00100000000d000f0000000e000f000d000e000d00 -0e000d000d000d000f0012000e0011000f000d000d000e000d000d00120000000d001100 -0d00000012000f000d000c000e000d000e000e000e000d000d000e000e000d000e000e00 -0e000d000d000e000d0011000d000d00000012000d00120005000000000010000d000d00 -0d0000000d000e000e000d000e000d000e000e000d000e000e000d000e000e000d000e00 -0d000e000e000e0010000d000f000d0000000e00000000000d000f00120000000f000d00 -0d0000000d000000000001000000000000000d000e000000000001000d000e000d000000 -0d00000000000f000d000d000d0011000d000d000f000d0000000d000e000d000d000d00 -0b0010000d000e000d0000001100000000000d000d000e0000000d000f000e0000000d00 -0000000000000000000000000d000f000000000000000f000d000e0000000f0000000000 -0d000e0011000d000d000e000d000d000d000d000d0000000f000e0012000b000e000e00 -0e000e000d000d000e000e000d000e000d000e000e000e000d000e000d000d000d000d00 -00000d0012000d0005000000000010000d000d000d0000000d000e000d000e000d000e00 -0e000d000e000d000e000e000e000d000e000e000d000e000e000e0010000e000d000e00 -000000000d000e0000000f000e0000000d0011000d00000011000d0000000d0011000000 -0d000e0000000e000e00120000000d000f000000000011000d0000000d000e000d000d00 -0d000d000d000e0000000f000e000d000d000e000b0010000d000e000e00000000001100 -0d0000000d000d0000000d000d000d0000000d000d0000000e000d0000000f000d000000 -11000d00120000000f000d00000000000d000f0000000d000d000d000d000d000d000d00 -0d00110000000d000f000e000e000b000e000e000d000d000e000e000e000d000e000e00 -0d000e000d000e000e000e000d000d000d000d0000000d000d000d000500000000001000 -0d000d000d0000000d000d000e000e000e000e000d000e000e000e000d000e000e000e00 -0e000d000e000e000d000e0010000e000f000d00000012000e000d0000000d000d000000 -0d000d000e0000000d000d0000000d000f00000012000f0000000d000d00110000001100 -0d0000000d000d000e0000000d000d000d000f000d000e000e000d0000000e000e000e00 -0d000e000b0010000e000e000d0000000d000e000e00000011000e0000000f0011000d00 -000011000d0000000e000d0000000f000d0000000d000d000e0000000f000d0000000f00 -0d000e0000000f000d000d000e000d000d000d000f0000000d000f000e0012000f000b00 -0e000d000e000e000e000d000e000e000d000e000d000e000e000d000e000d000d000d00 -0d000d0000000d000d000d0005000000000010000d000d000d0000000e000d000e000e00 -0e000e000e000e000d000d000e000e000d000d000d000e000e000d000e000d0010000d00 -0e000f0000000e000d00110000000d000e0000000d000e000d0000000d00110000000d00 -0d00000011000d0000000d000d000d0000000d000d0000000e000d000d0000000d000f00 -0d000d000d000e000d000e0000000e000e000e000e000e000b0010000d000e000d000000 -11000d000d0000000d00120000000d0012000e0000000d000e0000000d000d0000001200 -0f0000000d0011000d0000000d000d0000000d000d000d0000000d000e000d0011000e00 -0d000d0000000e000f000d000d0010000d000b000e000e000d000e000e000e000d000d00 -0d000e000e000d000e000e000e000d000d0011000d000d00000012000d00120005000000 -000010000d0012000d0000000e000e000e000d000e000e000e000d000e000e000e000d00 -0e000e000e000e000e000d000e000e0010000d000f000d0000000f000e000d0000000d00 -0d000000120011000d0000000d000d0000000e000d0000000d000d00000011000d000d00 -00000d000d0000000d000d00110000000d000d000e000d000d000d000d000e0000000e00 -0e000e000e000e000b0010000d000e000d0000000d000d000d0000000d000d0000001100 -11000d0000000d000d0000000d000f0000000f00120000000d000d00110000000e001100 -00000d000d000d0000000d000d000f0012000d00110000000e000d000f000f000d000d00 -0f000b000e000d000d000e000d000e000e000e000e000e000e000e000d000d000e000e00 -0d000d000d000d0000000d000d000d0005000000000010000d000d000d0000000e000e00 -0e000e000e000e000d000e000d000e000d000e000d000e000d000d000e000e000d000e00 -10000f000d000d00000000000d000d00000011000d00000011000d00000000000d001100 -00000d000e0000000d00110000000d000e000d0000000e000d0000000d000d000d000000 -0f000d000d000d000e000e000e000e0000000f000e000d000e000e000b0010000d000e00 -0e00000000000e000d00000011000d0000000d000d000000000011000d0000000d000d00 -00000d00110000000d000d000d00000012000d0000000d000d000e0000000d000f000d00 -0d0011000d0000000e000d000e0012000f000e000d000b000e000e000e000e000d000e00 -0d000e000e000d000d000e000e000e000e000d000d000d000d000d00000012000d000d00 -05000000000010000d000d000d0000000d000d000d000e000e000e000e000e000d000d00 -0e000e000e000d000d000e000e000e000d000e0010000d000e000d0000000d0000000000 -0e000d000d000e00000000000e0000000d000e00000000000f00000000000d000d000000 -000000000e000d000e0000000d000d000e0000000d000d000e000f0012000e000e000e00 -01000e000e000e000e000d000b0010000d000e000e0000000d00000000000d0011000d00 -0d00000000000d0000000e000d00000000000d00000000000d000d000000000000000e00 -0e000d0000000d000d000e0000000d000e000d000d000e000d0000000000000000000000 -0d000e000e000c000e000d000e000e000d000e000d000e000e000e000d000e000d000e00 -11000d000d0011000d000d0000000d000d00120005000000000010000d000d000d000000 -0d000d000e000e000e000e000d000e000e000e000e000d000e000e000e000e000d000e00 -0e000e0010000e000f000f000d000f000d000d000d000d000d000e000d000e000d000d00 -0f000d000e0012000d000e000d000e0012000d000f0012000e000f000d000e000f000d00 -0e000e000f000e000d000e000f000e000d000f000d000f000e000d000d000d000b001000 -0d000e000e000e000d000d000e000d000e000d000e000d000d000d000d000e000e000d00 -0d00110012000e000e000d000d000d000e000d000e000f000d000d000d000e000e000e00 -0d000f000f000d000e000f000f000e000e000d000f000e000e0008000e000e000d000e00 -0d000e000e000e000d000d000e000e000e000d000d000d000d000d000d000d0000000d00 -0d000d0005000000000010000d0012000d0000000d000e000e000d000e000e000d000e00 -0e000e000e000d000d000e000e000d000d000e000f000d0010000d0012000e000f000d00 -0d000d000d000d000e000d000e000e000e000e000d000e000d000f000e000e000d000e00 -0d000d000d000e000d000e000e000d000d0012000f000d000d000e000e000e000e000d00 -0d00120011000e000f000d000e000e000c0010000e000f000d000e000e000e000e000e00 -12000f000e000d000f000d000e000d000f000d000e000f000d000d000f000d000d001100 -0e000d000f0012000e000d000f000d000e000d000f000d000d000f0012000e000d000d00 -0e000e000e000f000e000c000e000e000d000e000e000e000e000d000e000e000e000d00 -0e000d000d000d000d000d000d000d0000000d000d00120005000000000010000d000d00 -0d0000000d000e000d000e000e000e000e000e000d000e000e000e000d000e000d000e00 -0e000e000d000e0010000f000d000e000d000f000e000d000f000d000d000e000d000e00 -0d000e000d000d000e000d000d000e000d000d0011000d000d000e000e000e000e000d00 -0f000f000e0012000e000e000e000e000d000e000f000f0012000f000d000d000d000d00 -0b0010000d000d000e000d000f000e0012000d0011000d000d000e000d000d000e000e00 -0e000e000d000d000f000d000e000d000d000d000e000f000e000e000d000e000e000d00 -0d000e000e000e000e000e000e000d000d000f000d000d000e000f0012000b000e000d00 -0e000e000e000d000d000e000e000d000e000d000e000e000d000d000d0011000d000d00 -000012000d000d0005000000000010000d000d000d0000000e000e000e000e000e000d00 -0e000e000e000e000d000e000d000e000e000d000e000d000d000f000f000d000f000d00 -0e000e000d000e000d000f000f000d000f000d000e0012000f000f000e0012000f000e00 -0f000d000e000e000f000e000f000d000d000f000d000e000e000f000e000e000d000d00 -0e000e0012000f000d000e000e000f000e000e00130010000e000e000e000e000e000e00 -100012000e000d000d000e000e000d000f000e000d000f000f0012000f000f000e000d00 -0e000f000f000e000e000e000e000d000e000d000e000e0012000e000e0012000f000e00 -0e000f000e000e000e000e000e0009000e000e000d000d000d000e000e000e000e000e00 -0d000e000d000d000d000d000d0011000d000d0000000d000d000d000a00000000001000 -0d0012000d0000000d000e000e000e000d000e000e000e000e000d000d000e000e000e00 -0e000e000e000d000e000e0010000d000f000d000e000d000e000f000d000d000d000d00 -0f000e000e000e000e000e000e000e000e000e000d000e000e000e000d0012000f000e00 -0e000e000e0012000f000d000e000e000e000f000e000f000d000e000f0012000d000f00 -0d000e000b0010000e000d000e000d000e0012000f000f00120010000e000d000d000e00 -0e000e000f0012000e000e000d000d000f000e0012000f0012000e000f000e000d000d00 -0f000e000e000d000e000e000e000e000e000d000e0012000f000f000e0012000e000b00 -0e000d000e000e000e000e000d000d000d000e000e000d000d000d0011000d000d000d00 -0d000d0000000d000d000d0005000000000010000d000d000d0000000d000e000e000e00 -0e000d000d000e000d000e000e000e000e000d000d000d000e000e000e000d0010000d00 -0d000e000d000e000e000d000f000f000e000f000d000e000d000f000d000e000f000f00 -0e000f000d000d000d0010000f000e000e000f000d000f000f000f0012000f000f000e00 -0d000e0012000e000f000d000f000f000d000e000d000e000c0010000f000d000e000f00 -0e000f000d000d000f0012000d000f000e000f000e000e000d000f000e000e000f000f00 -12000d000f000d0010000e000d000f000e000e000d000e000f000d000e000e000e000e00 -0d000f000f000d000e000f000e000e000f000c000e000e000d000e000d000e000d000e00 -0e000e000e000d000d0011000d0011000d000d000d000d000000120012000d0005000000 -000010000d000d00120000000d000e000e000e000d000e000e000d000e000d000e000d00 -0d000e000e000e000d000e000e000e000b000b000c000b000b000b000b000b000b000b00 -13000b000b000b000b000b000b000b000b000b000b000b000b000b000b0008000b000b00 -0b000b000b000b0013000b000b000b000b000c000b000c0013000b000b000b000b000b00 -0b0008000c000b0008000b000c000b000b000b000b0013000c0008000c000b000b000b00 -0b0013000b000b000b0013000c0013000b000b000b0013000c000b00080008000c000b00 -0b0008000c000b0013000c000b000b000b000b000c00080008000c000b000b000b000c00 -0b0008000e000d000e000d000e000d000e000e000d000d000e000e000d000d000d000d00 -0d000d000d00110000000d000d00120005000000000010000d0012000d0000000d000e00 -0e000e000e000e000e000d000d000e000e000d000e000e000e000d000d000e000e000e00 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010001000100010001000100010001000 -100010001000100010001000100010001000100010000c000e000e000d000d000e000e00 -0e000e000d000e000e000d000d000e000e000e000d000d000d000d0000000d000d000d00 -05000000000010000d000d000d0000000e000e000e000e000d000e000e000e000e000d00 -0e000e000d000d000d000e000e000e000e000d0010000f000e000e000d000d000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000f0012000f000e000d000d00 -0d000d000d000e000d000d000f000f000f000d000d000d000e000f000e000d000f000e00 -0e000e000e000e000d000e000e000e000e000e000e000e000e000e000e000e000d000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000f000f000e000e00 -0f000e000e000b000e000d000e000e000e000d000d000e000e000d000e000e000e000d00 -0d000e000d000e000d000d0000000d000d00120005000000000010000d0012000d000000 -0d000e000e000e000e000e000d000e000e000e000d000e000e000e000e000e000e000d00 -0f000e0010000f000e000e000d000e000e000e000d000d000e000e000d000d000e000e00 -0d000d000e000e000e000d000e000e000d000d000e000e000d000d000e000e000d000d00 -0e000e000d000d000d000e00120011000d000f000d0010000e000f000f000d0012000f00 -0d000e000d000e000f000d0012000d000e000d000d000d000e000e000d000e000d000e00 -0e000e000d000d000d000d000e000e000d000e000d000e000e000e000d000d000d000d00 -0d000d000d000d000e000d000e000e000e000d000e000e000f000b000e000e000e000e00 -0d000d000e000e000d000e000d000e000e000e000d000e000e000d000d000d0000001200 -0d00120005000000000010000d000d000d0000000d000e000e000e000e000e000d000e00 -0d000e000d000e000d000e000e000d000e000d000e000e0010000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000f000f000d00 -0d000e000d0012000e000d00120010000e000d000e000d000d000d000d000d0011000f00 -0d000f000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000d000e000d000f000b000e000e000d000d000e000e000e000d000e000e000d000e00 -0d000e000e000e000d000e000d000d00000012000d000d0005000000000010000d000d00 -0d0000000d000e000e000d000e000d000e000d000e000e000e000e000e000d000e000d00 -0e000e000d000e0010000e000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000f0012000e000f000d000f000d000f000e000f0010001200 -0d000e000d000e000d000f000e000f0012000f000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000e000e000e000e000e000d000e0013000e000d00 -0e000e000e000d000e000e000d000e000d000e000e000d000e000d000d000d000d000d00 -00000d000d000d0005000000000010000d000d000d0000000d000d000d000e000d000e00 -0e000d000e000d000e000d000d000e000e000d000d000e000e000e0010000f000d000e00 -0e000d000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000d000e0012001000 -12000d000f0012000f000e000f00120012000f000d000f000e000d000e000e000d000d00 -0d0012000f000f000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000d000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000b000e000e000d000e000e000e000d000d000d000e00 -0e000d000e000e000e000d000d000d000d000d0000000d000d000d000a00000000001000 -0d0012000d0000000e000e000e000e000e000e000e000e000e000d000e000d000e000e00 -0e000e000d000e000d000e0010000e000d000e000e000d000d000d000d000e000d000d00 -0d000d000d000d000d000e000d000d000e000d000d000d000d000e000d000d000d000d00 -0d000d000d000e000d000d000d000d000d000d000d000f000e0000000000000000000f00 -0e000d000d000d000d000d000d000f0012000f0000000d000f0000000e000d000e000d00 -0e000d000e000d000e000d000d000d000e000d000e000d000d000d000d000d000e000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000e000e000d000e000b00 -0e000d000d000e000d000e000e000e000e000e000e000e000d000d000e000e000d000d00 -0d000d000000120012000d0005000000000010000d000d000d0000000d000e000d000e00 -0e000d000e000e000e000e000e000e000e000d000d000e000e000e000e000f0010000f00 -0d000e000e000d000e000e000d000e000e000e000e000e000e000e000d000e000e000d00 -0e000d000e000e000d000e000e000e000e000e000e000e000d000e000d000e000e000e00 -0f000d000d000d0000000e000e000f000d0000000f000d000e000e000e000d000d000f00 -0e000d000f000e000f0000000e000d000e000d000e000d000e000d000e000e000e000d00 -0e000d000e000e000d000e000e000e000e000e000d000e000d000d000e000d000e000d00 -0e000e000e000d000e000e000e000e000f000b000e000e000e000e000d000e000d000e00 -0e000d000d000e000e000e000e000d000d000d0011000d00000012000d000d0005000000 -000010000d000d000d0000000d000d000e000e000e000e000d000d000e000d000d000e00 -0d000e000e000d000e000e000e000d0010000d000e000d000e000d000e000e000d000e00 -0d000d000e000e000d000e000e000e000d000e000d000e000e000e000d000e000d000d00 -0e000e000e000d000e000e000d000e000d000e000e000d000f0000000f000f000d000e00 -0e000d0000000e000e0000000f000d000f0000000f00120000000e000000000000000e00 -0d000d000f0012000e000d000d000d000e000e000e000d000e000e000e000e000d000e00 -0e000e000d000e000d000e000d000e000d000e000d000e000e000d000e000e000e000e00 -0e0013000e000d000e000e000d000e000d000e000d000e000e000e000e000d000d000e00 -0d000d000d000d0000000d000d000d000a000000000010000d001200120000000d000e00 -0d000e000e000d000e000e000d000e000d000e000e000e000d000e000e000d000e000d00 -10000e000e000d000e000d000e000d000e000e000e000e000e000d000e000e000d000e00 -0e000d000e000e000e000d000e000e000e000e000e000d000e000e000e000d000e000d00 -0e000e000f000d000e0000000d000d000e000e000e000e0000000d000d0000000d000f00 -120000000d00110000000e000e0000000f0012000e000e000d000d000d000e000e000e00 -0e000d000e000d000e000d000d000e000e000d000d000e000e000d000e000d000e000d00 -0e000d000e000d000e000d000e000d000e000e000e0013000e000e000d000e000d000e00 -0e000e000e000e000d000d000e000e000e000e0011000d000d000d0000000d000d000d00 -0a000000000010000d000d000d0000000d000e000d000e000d000e000e000d000e000d00 -0e000e000d000d000e000e000e000d000e000d0010000d000e000d000e000d000e000e00 -0d000d000d000e000e000d000e000d000d000e000e000e000d000d000e000e000d000d00 -0d000e000e000d000e000e000d000e000d000e000e000d000d000e000d0000000d000f00 -0e000e000d000e0000000d000f0000000e000d000e0000000d000d0000000f000d000000 -0e000e000f000d0012000f000e000d000d000e000e000d000d000e000e000e000e000e00 -0e000d000d000e000e000e000d000d000d000e000d000e000d000e000e000d000e000e00 -0e000e000e0013000e000e000e000d000e000e000e000d000d000e000e000e000d000e00 -0e000d000d000d000d000d0000000d0012000d000a000000000010000d000d000d000000 -0d000e000e000d000e000d000e000e000d000e000d000e000e000e000d000d000e000e00 -0e000d0010000d000e000d000e000d000d000e000e000e000e000d000e000e000e000d00 -0e000e000d000e000e000e000d000e000e000e000e000d000e000e000e000d000e000d00 -0e000d000e000e000d000e000d000000110012000e0000000f000e0000000d000d000000 -0d000d000d0001000d000d0000000e000f0000000f000e000d000e000f000d000d000e00 -0e000d000e000e000e000e000d000d000d000d000e000e000e000e000d000d000d000e00 -0e000d000e000d000e000d000e000d000e000e000e000e000e000b000e000d000e000e00 -0e000d000d000e000d000e000d000e000e000d000e000d0011000d000d000d0000001200 -0d000d000a000000000010000d000d000d0000000d000d000e000e000e000e000e000d00 -0d000e000e000e000e000d000e000e000d000e000e000d0010000d000e000d000e000d00 -0d000e000e000d000e000e000d000e000e000e000d000d000e000e000d000e000d000e00 -0e000d000e000e000d000e000d000e000d000e000e000e000d000e000d0011000e000000 -0e000f000e000d0000000d0000000e000e0000000f000d000e0000000d000f0000000e00 -0d0001000d000d000f000d0012000f000e000e000e000d000e000d000e000e000e000e00 -0e000e000e000e000d000e000d000e000e000e000d000d000e000e000d000e000e000d00 -0e000e000e000e000e0013000e000e000d000d000e000e000d000e000e000e000e000d00 -0e000d000e000e000d000d000d000d0000000d000d0012000a000000000010000d000d00 -0d0000000e000d000e000e000e000e000d000e000e000e000d000d000e000e000d000e00 -0d000e000e000d0010000d000e000d000e000d000e000d000e000e000d000e000d000e00 -0d000e000e000e000d000d000e000e000e000d000e000e000d000e000d000e000e000d00 -0e000d000e000d000e000d000e0012000f000e0000000e000d000e000d0001000e000d00 -0f0000000e000d00000000000f000d0000000e000d0000000e000f0012000d000f000d00 -0d000e000e000e000e000d000e000d000d000e000e000d000d000e000e000d000e000e00 -0d000d000d000e000d000e000e000d000e000e000e000e000e000e000e000b000e000e00 -0e000e000d000d000e000e000e000d000e000e000e000d000e000d000d000d000d000d00 -000012000d000d000a000000000010000d0012000d0000000e000e000d000e000e000e00 -0e000e000e000d000e000d000d000e000e000d000e000e000d000d0010000d000e000d00 -0e000d000e000d000d000e000e000e000e000e000d000e000e000d000e000e000e000d00 -0e000d000d000e000e000e000e000e000d000e000d000e000e000e000d000e000f000e00 -12000e000f0000000000000000000d0000000d000d000e00000001000f0000000d000e00 -00000e000f000000000012000e000f000f0012000e000d000d000d000e000e000e000e00 -0d000e000d000d000e000e000e000e000d000d000d000d000d000e000e000d000e000d00 -0e000e000e000e000e000e000e000b000e000d000e000d000e000e000e000d000e000d00 -0d000e000e000e000d000e000d0011000d000d0000000d000d0012000500000000001000 -0d000d000d0000000e000e000e000e000e000e000e000d000e000d000e000e000e000e00 -0d000e000e000d000e000d0010000d000e000d000e000d000e000e000e000e000d000d00 -0e000d000e000d000e000e000e000d000e000d000e000e000e000e000d000d000e000d00 -0e000d000e000d000e000d000e000d000d000f000f000e000d000e000e000e000e000d00 -0f000d000d000f000d000e0012000f000d000e000e000e000e000d000f000d000e000d00 -0d000e000e000e000e000e000e000d000d000e000e000d000e000e000e000d000d000e00 -0e000e000e000d000e000e000d000e000d000e000e000d000e000e000e000e000e000b00 -0e000d000e000e000e000d000e000d000e000e000e000d000d000e000e000d000d000d00 -0d000d0000000d000d000d000a000000000010000d000d000d0000000d000d000d000e00 -0e000d000e000e000d000e000e000e000e000e000e000e000e000e0012000e000f000e00 -0e000d000d000e000e000e000d000d000e000e000d000e000e000d000e000d000e000e00 -0d000e000e000e000e000d000e000d000e000e000d000e000e000d000e000e000e000d00 -0d000d000e000e000e000d000d000d000e000e000d000d000d000e000e000e000d000d00 -0e000e000e000d000e000d000e000e000d000e000d000e000e000e000d000e000e000e00 -0d000e000e000e000e000d000e000e000e000d000d000e000e000d000e000e000e000e00 -0d000e000e000e000d000f000d000d000e0013000e000e000d000e000e000d000e000d00 -0e000e000e000d000d000e000e000e000d000d000d000d00000012000d000d0005000000 -000010000d000d000d0000000d000d000e000e000d000e000e000e000d000e0012000e00 -0e000e000e000e000e000e000e000e000f000e000f000e000d000d000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000d000e000d000d00 -0e000b000d000e000e000d000e000e000e000d000e000d000e000e000e000e000d000e00 -0d0011000d000d00000012000d00120005000000000010000d0012000d0000000d000e00 -0e000e000e000e000e000d000e000e000e000e000e000e000e0012000e000e000f000e00 -0f000e000e000e000e000f000d000e000d000d000e000e000d000e000d000d000d000e00 -0e000e000d000d000e000e000e000e000d000d000d000e000d000d000d000d000e000d00 -0e000e000d000e000d000e000d000e000d000d000e000d000e000e000d000e000d000e00 -0d000d000d000e000d000e000d000d000e000e000d000e000d000d000d000e000d000d00 -0e000e000d000d000e000d000d000d000e000e000d000d000e000d000e000d000d000d00 -0e000e000d000e000e000e000e000e000e000e000e000b000d000e000e000e000d000d00 -0e000e000e000d000d000e000e000d000d000e000d000d000d000d0000000d0012000d00 -05000000000010000d000d000d0000000d000e000e000e000e000e000e000e000e000d00 -0e000e000e000e000e000e000e000e000e000e0010000f000e000d000d000d000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000d000e000e000e00 -0e000e000e000b000e000e000d000d000e000e000e000d000e000e000e000d000e000d00 -0e000e000d000d000d000d0000000d000d000d0005000000000010000d000d000d000000 -0e000e000e000e000d000e000d000e000e000d0012000e000e000e000e000e000e000e00 -0e000e000f000e000f000e000f000f000e000e000e000e000d000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0d000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0d000d000e000e000e000e000e000e000e000e000e000e000e000e000e000e000d000d00 -0e000e000e000e000e000e000e000e000e000e000e000e000d000d000d000e000e000e00 -0e000e000e000d000e000e000d000e000e000e000d000e000d000c000e000d000e000e00 -0d000e000e000e000d000e000d000e000e000d000e000d000d000d000d000d0000000d00 -0d000d0005000000000010000d0012000d0000000d000e000e000d000e000e000e000d00 -0e000e000e000e000e000e000e000e000e000e000e0012000c001300130013000b001300 -0b000b000b000b000b000b000b000b000b000b000b001300130013000b000b000b000b00 -0b000b001300130013001300130013000b0013000b0013000b000b000b000b0013000b00 -0b000b000b000b000b00130013000b0013001300130013000b000b000b00130013001300 -0b0013001300130013000b00130013001300130013000b000b0013000b0013000b000b00 -130013000b00130013000900130013000b000b000b000b000b000b000b000b000b000b00 -0b00130013000c000b0008000e000d000e000d000e000e000d000d000d000e000e000e00 -0e000e000e000d000d0011000d000d00000012000d00120005000000000010000d000d00 -0d0000000d000e000e000e000e000e000d000e000d000e000e000e000e000e0012000e00 -0e000e000e000e000e000e000f000e000e000d000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000e000d000d000e000e000e000e000e00 -0d000e000e000d000d000e000e000e000d000d000d000e000e000e000d000d000d000d00 -00000d000d000d0005000000000010000d000d00120000000d000e000e000e000e000e00 -0e000e000d000e000e000e000e000e000e000e000e000e000e000e000e000e000e000d00 -0e000e000e000e000e000e000e000e000e000e000e000e000d000e000d000e000e000e00 -0d000e000d000e000d000d000d000e000e000e000e000e000e000e000d000d000e000e00 -0e000e000e000e000e000e000d000d000e000e000e000e000d000d000e000e000e000d00 -0d000e000e000e000d000d000e000e000e000e000d000e000e000e000e000e000d000e00 -0d000e000e000d000d000e000d000e000d000e000e000e000e000e000e000e000d000e00 -0e000e000e000e000e000e000d000e000d000e000e000d000e000e000e000e000e000d00 -0e000e000e000d000d000e000d000d000d000d00000012000d000d000500000000001000 -0d0012000d0000000d000e000e000e000e000e000d000e000e000e000e000e000e001200 -0e000e000e000e000e000d000e000d000e000e000e000e000e000d000e000e000d000e00 -0d000e000e000e000e000e000d000e000d000e000d000e000e000e000e000e000e000d00 -0e000e000e000e000d000e000d000e000e000e000e000e000e000e000e000e000e000e00 -0d000e000e000e000e000e000e000e000d000e000e000e000e000e000d000e000d000e00 -0d000e000e000e000e000e000d000e000e000e000e000e000e000e000d000e000e000d00 -0e000d000e000e000e000e000e000d000e000e000e000e000e000d000e000e000d000e00 -0e000d000e000d000e000d000e000d000d000e000e000d000e000d000d000e000d001100 -0d000d0000000d000d00120005000000000010000d000d000d0000000d000e000e000d00 -0e000d000d000e000e000d000e000e000e000e000e000e0012000e000e000e000e000e00 -0e000e000d000e000e000e000e000d000e000e000e000e000e000e000e000e000e000d00 -0e000d000e000d000d000e000e000d000e000e000e000e000d000e000e000e000e000d00 -0e000d000e000d000d000e000e000d000e000d000e000d000e000e000e000e000e000e00 -0e000d000e000d000d000e000e000d000d000e000e000e000e000d000e000d000e000e00 -0e000d000d000e000e000d000e000e000d000e000e000e000e000e000d000e000e000e00 -0e000d000e000e000d000e000e000e000e000e000d000e000d000e000d000e000e000d00 -0e000e000d000e000e000e000e000d000d000d000d000d0000000d000d000d0005000000 -000010000d0012000d0000000e000e000d000e000d000e000d000e000d000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000d000e000e000d000e000d000e000e00 -0d000e000e000e000d000d000e000d000e000e000e000e000d000e000e000e000e000e00 -0e000d000d000e000e000d000e000e000d000e000e000e000e000e000e000e000d000e00 -0e000e000d000e000d000e000e000d000d000e000e000d000d000e000d000e000e000e00 -0e000e000e000e000e000d000d000e000e000e000d000e000e000e000e000e000e000e00 -0e000d000e000d000d000e000e000d000e000d000e000e000e000e000e000d000e000e00 -0d000e000e000d000d000e000e000e000e000e000e000d000d000e000d000e000d000d00 -0d000d000d000d0000000d000d0012000a000000000010000d000d000d0000000d000d00 -0e000d000e000e000e000d000e000d000e000e000e0012000e000e000e000e000e000d00 -0e000d000e000e000e000d000e000e000e000d000e000d000d000e000e000e000e000e00 -0e000e000e000e000e000e000d000e000e000d000e000e000e000e000e000e000e000d00 -0e000d000d000e000d000e000d000e000e000d000e000d000e000e000e000e000e000e00 -0e000e000e000e000e000d000e000e000e000e000d000e000d000e000e000e000e000d00 -0d000e000e000e000d000e000e000e000d000e000d000e000e000e000e000e000d000e00 -0d000e000e000d000e000e000e000e000e000e000e000e000d000e000e000e000e000d00 -0d000e000e000e000e000e000d000e000d000d000d0011000d000d00000012000d000d00 -05000000000010000d000d000d0000000d000e000d000e000e000e000d000e000e000e00 -0e000e000e000e000d000e000e000d000d000e000d000e000e000e000d000e000e000e00 -0e000e000e000e000e000e000d000e000e000d000e000e000d000e000d000e000e000d00 -0e000e000e000e000d000e000d000e000e000e000e000e000e000e000d000e000e000e00 -0d000e000e000d000d000e000e000e000e000e000e000e000e000e000e000d000d000e00 -0e000e000d000e000e000e000e000e000e000e000d000e000d000e000e000d000d000e00 -0e000d000e000e000e000e000d000e000e000e000e000d000e000e000e000e000e000e00 -0e000e000e000d000d000e000e000d000e000d000d000e000d000d000e000d000d000d00 -11000d000d0011000d000d0000000d000d000d0005000000000010000d000d000d000000 -0d000d000e000d000e000e000e000e000d000e000e000e000e000e000e000e000e000e00 -0e000d000e000e000d000e000e000d000e000e000e000e000e000d000d000e000e000d00 -0e000e000e000d000e000d000e000e000e000e000e000e000e000e000e000e000e000d00 -0e000e000e000e000e000d000e000e000e000d000e000e000e000e000e000e000d000e00 -0d000e000e000d000e000d000e000e000e000e000e000d000e000e000e000d000e000d00 -0e000d000e000d000e000d000e000e000e000e000e000e000e000e000d000e000e000e00 -0e000e000e000e000e000e000d000d000e000d000e000e000d000e000e000e000d000e00 -0e000e000e000e000e000e000e000e000d000d000d000d000d000d000d000d0000000d00 -0d000d0005000000000010000d0012000d0000000d000e000d000e000e000e000e000e00 -0e000e000e000e0012000e000e000e000e000e000e000e000d000e000e000e000e000e00 -0e000e000d000e000e000e000e000e000d000e000e000e000e000e000d000e000d000e00 -0d000e000e000e000e000d000e000e000d000e000d000e000e000e000d000e000e000e00 -0e000e000e000e000e000e000e000e000e000e000d000e000e000e000d000e000e000e00 -0e000e000e000e000e000e000d000e000d000e000e000d000d000e000d000e000e000e00 -0d000e000e000d000d000e000e000d000e000d000e000e000e000d000d000e000e000d00 -0e000e000e000e000e000d000e000d000e000d000d000e000e000d000d000e000d000e00 -11000d000d0011000d000d000d000d000000120012000d0005000000000010000d000d00 -0d0000000d000e000e000d000e000e000d000e000d000d000e000e000e000e000e000d00 -0d000e000e000d000e000e000e000d000e000d000e000d000e000d000e000d000e000e00 -0d000e000d000e000e000d000e000e000e000d000e000d000e000e000e000e000d000e00 -0e000d000e000d000e000e000e000d000d000e000e000e000e000e000d000e000e000d00 -0e000d000e000d000e000d000e000d000d000e000e000d000d000e000d000e000e000d00 -0e000e000e000e000e000e000e000e000e000d000e000e000d000e000d000e000e000e00 -0d000e000d000e000e000e000e000e000d000e000e000e000d000e000d000e000e000d00 -0e000e000d000e000d000e000e000e000d000e000d000d000d000d000d000d000d001100 -00000d000d00120005000000000010000d0012000d0000000d000d000e000e000e000e00 -0e000e000e000e000e000d000e000e000e000d000e000e000e000e000e000e000d000e00 -0e000d000d000e000d000e000e000e000d000e000e000d000e000e000d000e000d000e00 -0d000e000e000e000d000d000e000d000e000d000e000e000e000e000e000e000d000e00 -0e000e000d000e000d000e000d000e000e000e000e000d000d000e000d000e000e000e00 -0d000e000d000e000e000d000d000e000e000e000d000e000d000d000e000d000e000d00 -0d000e000e000d000e000e000e000e000e000e000d000e000e000d000d000e000d000e00 -0d000e000e000e000d000d000e000d000d000e000d000e000e000e000d000e000e000d00 -0e000e000d000e000d000e000e000e000e000d0000000d000d000d000500000000001000 -0d000d00120000000d000d000d000d000e000e000e000e000e000e000e000d000e000e00 -0d000e000d000e000e000e000d000e000e000d000e000e000e000d000e000d000e000e00 -0e000e000d000e000e000d000e000d000e000d000e000e000d000e000e000e000e000e00 -0d000e000d000e000e000e000d000e000e000e000d000e000e000d000e000e000e000e00 -0d000d000e000e000e000d000e000e000d000e000e000d000e000e000e000e000e000d00 -0d000d000e000e000e000e000d000e000d000d000e000d000d000e000d000e000e000e00 -0d000e000e000d000e000e000e000d000e000d000e000e000d000e000e000e000e000e00 -0e000d000e000d000e000e000e000e000d000e000e000d000e000d000e000d000e000e00 -0d000d0000000d000d000d0005000000000010000d000d000d0000000d000d000e000e00 -0e000e000e000e000e000e000d000e000e000d000e000d000e000e000d000d000e000e00 -0d000e000d000e000d000e000e000e000e000e000d000d000e000e000e000d000d000e00 -0e000e000e000d000e000e000d000e000d000e000e000d000e000e000d000d000e000e00 -0e000d000e000e000d000e000e000e000e000d000d000e000d000e000e000e000e000d00 -0e000e000d000e000e000e000d000e000e000e000e000e000e000e000e000d000e000d00 -0e000d000d000e000e000d000e000e000d000d000e000e000d000e000d000e000d000e00 -0e000d000e000d000e000e000d000e000d000e000d000e000e000e000e000e000d000d00 -0e000e000e000d000d000e000e000d000e000e000e000d00000012000d00120005000000 -000010000d000d000d0000000d0011000d000d000e000e000d000e000e000d000e000d00 -0e000e000d000e000d000e000e000e000e000d000e000e000d000e000e000d000e000e00 -0d000e000e000e000d000d000e000e000e000e000e000d000e000e000e000d000e000e00 -0d000e000d000e000d000e000e000e000e000d000e000e000e000d000e000d000d000d00 -0e000e000e000e000d000e000e000e000e000e000e000d000e000d000e000d000d000e00 -0d000e000e000d000e000d000e000e000d000e000d000e000e000e000d000e000d000e00 -0e000e000e000d000e000e000d000e000e000e000e000d000e000e000e000d000e000e00 -0d000e000e000d000e000d000d000e000e000e000d000d000e000e000e000e000e000e00 -0d000e000d000d00000012000d000d000a000000000010000d000d000d0000000d000d00 -0d000d000d000d000e000e000e000e000e000e000e000e000e000e000d000e000e000e00 -0d000e000e000e000e000e000e000d000e000d000e000d000e000e000e000e000e000e00 -0e000d000e000d000e000d000d000e000e000e000e000e000d000e000d000e000e000e00 -0e000e000e000d000e000d000e000e000d000e000e000e000e000e000e000d000e000e00 -0e000d000e000d000d000e000e000d000e000e000e000e000d000e000d000e000d000e00 -0d000e000e000d000e000e000d000e000d000e000e000e000e000e000e000e000e000e00 -0e000e000e000e000e000d000d000e000e000e000e000e000d000e000d000e000d000e00 -0e000e000e000e000e000e000e000d000e000e000d000d000d000d0000000d000d001200 -05000000000010000d0012000d0000000d000d000d0011000e000e000d000e000e000e00 -0e000e000e000e000e000e000e000d000e000d000e000d000e000e000e000d000d000e00 -0e000e000d000e000e000e000e000e000e000e000d000e000e000e000e000e000e000d00 -0e000e000e000d000e000d000e000d000e000e000e000e000e000e000e000e000e000d00 -0e000e000e000e000e000d000e000e000d000e000e000e000e000e000e000e000e000e00 -0e000e000d000e000e000e000e000e000e000d000e000e000d000e000d000e000e000d00 -0e000d000e000e000e000e000e000e000e000e000e000d000e000d000e000e000e000d00 -0e000e000e000d000e000d000e000e000e000e000e000e000e000e000e000e000d000e00 -0d000e000d000d000d000d0000000d000d000d000a000000000010000d000d000d000000 -0d000d000d000d000d000d000d000e000e000e000d000d000e000e000e000e000d000e00 -0d000e000d000e000e000e000d000e000e000d000e000e000e000e000e000e000e000d00 -0e000e000e000d000e000e000e000e000d000e000e000e000e000e000e000e000e000e00 -0d000e000e000e000e000e000e000e000d000e000d000e000e000e000d000e000e000e00 -0e000e000e000e000e000e000e000d000e000d000e000e000e000e000e000e000e000e00 -0d000e000e000e000e000e000e000e000e000e000e000e000d000e000e000e000e000e00 -0d000e000d000e000d000e000e000e000d000e000e000e000e000e000d000e000e000e00 -0d000e000e000e000e000d000e000e000e000d000e000d000d000e000d000d0000000d00 -0d0012000a000000000010000d000d000d0000000d000d000d000d000e000e000d000d00 -0d000d000d000e000e000e000e000e000e000d000e000e000e000e000e000e000e000e00 -0d000e000e000e000e000e000e000d000e000e000e000e000d000e000e000d000e000d00 -0e000d000e000e000e000e000e000e000e000e000e000d000e000e000d000e000e000e00 -0e000d000e000e000e000e000e000e000e000e000e000d000d000e000e000e000d000e00 -0d000e000e000e000e000e000e000e000e000d000e000d000e000e000e000e000d000e00 -0e000e000e000e000e000d000e000e000e000d000e000e000e000d000e000e000e000d00 -0e000d000e000e000e000e000e000e000e000e000e000e000e000d000e000e000e000e00 -0d000e000e000e000e000d000d000d00000012000d000d000a000000000010000d000d00 -120000000e000d000d000d000d000d000d000d000d000d000e000d000d000d000e000e00 -0d000d000d000e000d000e000d000e000e000e000d000d000d000e000e000e000d000d00 -0e000d000d000d000e000e000d000d000d000e000e000e000d000d000d000d000e000e00 -0e000e000d000d000d000d000e000d000d000d000e000e000e000e000d000d000d000e00 -0e000e000d000d000e000d000d000d000e000e000e000e000d000d000d000e000e000e00 -0d000d000e000e000e000e000d000d000d000d000e000e000e000e000d000d000d000d00 -0e000d000d000d000e000e000e000d000d000e000d000e000e000e000e000e000d000d00 -0d000e000e000e000d000d000e000e000d000d000e000e000d000d0011000d000d000d00 -000011000d0012000a000000000010000d0012000e0000000d000e000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000e000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000e000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000e000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0e000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d0011000d0000001200120011000500000000001000 -0d000d000d00000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -0000000000000d000d0012000a000000000010000d0012000d000d0012000d000d000d00 -0d000d0012000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d0012000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d0012000d000d000d000d000d0012000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d00 -0d000d000d000d000d000d000d000d000d000d000d000d000d0012000d000d000d000d00 -0d000d000d000d000d000d0012000d000d000d000d000d0012000d000d000d000a000000 -000011000d000d0012000d000e000d000d0012000d0012000d00120012000d000d000d00 -12000d000d0012000d0012000d0012000d000d000d000d0012000d000d0012000d001200 -0d0012000d000d000d000d0012000d000d0012000d0012000d000d000d0012000d001200 -12000d000d000d000d00120012000d000d0012000d0012000d000d000d000d0012000d00 -0d0012000d000d000d000d000d000d000d0012000d000d000d000d0012000d000d001200 -0d000d000d000d000d000d000d000d000d0012000d0012000d0012000d000d000d001200 -12000d000d0012000d000d0012000d000d0012000d0012000d0012000d000d000d001200 -0d000d000d0012000d000d000d0012000d000d000d0012000d000d000d0012000d000d00 -0d000d000d000d0011000d001200120005000000000010000d000d000d0012000d000d00 -0d000d000d000d000d000d000d000d000d0012000d0012000d000d0012000d0012000d00 -12000d000d0012000d0012000d000d0012000d0012000d0012000d000d0012000d001200 -0d000d0012000d000d0012000d000d000d0012000d000d000d0012000d000d000d001200 -0d000d0012000d0012000d000d0012000d0012000d000d000d0012000d00120012000d00 -12000d0012000d000d0012000d0012000d000d000d0012001200120012000d000d000d00 -0d000d0012000d000d000d000d0012000d000d000d0012000d000d000d0012000d001200 -0d000d0012000d0012000d0012000d000d0012000d0012000d000d000d0012000d000d00 -12000d000d0012000d0012000d000d0012000d0012000d000d000d000d0012000d000d00 -0a000000000011000500050005000b0005000a000500050005000a000500050005000a00 -050005000a000500050005000a0005000a000a00050005000a0005000500050005000500 -0a0005000a000a00050005000a0005000a000500050005000a0005000500050005000500 -0a00050005000a0005000500050005000a000500050005000a000a00050005000a000500 -05000500050005000500050005000500050005000a000a00050005000a00050005000500 -05000500050005000a000a0005000a0005000500050005000a0005000500050005000500 -050005000a00050005000500050005000a000500050005000a0005000a000a0005000500 -050005000500050005000500050005000500050005000500050005000a00050005000500 -05000a000a000a000a000500050005000a00050005000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000 -0000000000000000 -%%EndData -end -%%PageTrailer -%%Trailer -%%BoundingBox: 0 0 105 76 -%%EOF diff --git a/docs/tutorial/gtk_tut_table.gif b/docs/tutorial/gtk_tut_table.gif deleted file mode 100644 index 09af1302a955d8e0b18cbcf42043411f4a3269b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10056 zcmWkyc|6nqAOF~9n_aFYgytxBIdfJc<W5nDib$?}C6!||GutqXkUM9NT%jB}<{qKZ z2rW${BwtB|<ooOQ{_pjCJznqQ`Fy?}kN5k1*2+R(&oc)I27Unm1Oy?F2;M&4eLd|E zkURI|nt}{@WTFox;*Ax-mOiP5fc}Py5Ri_yPy5;?w{KuAJuMxA@a`LK54{%(0ZGvl z$XF3FXLe+5X^lIvh(eGd2xF9pS<{Ob5Cmjv_csI-Nw~+xA_$zZ*MtZ<os!3${luN% zq7Y%+k9$%gfAK{rvC_UyPG1iPB@&jGQ_(lfB}5aXBpE0~CIn%Rf+ESJ)X)$D3KSR` zG{T+buC0HSk~Hq?e8rvHlafj2OuUnlltO{X5YYL(pL>17%P7PZDUo!nh}qumR$x#7 zXJTt@b1yxulyHwgPfls??8IWQi?e^vg&i3ffq()RKQ3S;-KE5EO||VPj1=~7ErO0h zpirPtdU75L;iRCFjzR>INwIxBBUlk{2<Y#ki-A6UBg3yCAT`e4Ev@dgzvv@Ja~D_l zMuw+GhWD@{PJ6q1p&@s+Hn$f)uAvZE2owQ<Ugu1VV8tXLP$~puMyI5!X?YW(>Fu3s zBLjOVgbpF3Z)<anJGQp9z8B~p80gcq_;G7wfP)nwlonKD5$OstSqd@=BV)^XnNRw9 z_6Ya5oWFG4%L@(R5F*G5M@z9Hfz?l%7U#Colhf0a^EhK$glIAfiVY2+ul=1fD3lyc z?;Ge#&&&&r2!%iuuwpdM-0QW~Z``Rx6ebaZF-D1*ZSC(tp!W$89C|_?cW#M0^$vvz zhhUt@lr$97KQyF|JICex1)($u^a2Xwi50Wl+yBOy+9O1SFV1~gTv}{uc!9;xP#6>n zN<d-GlPR%SF?Y_?Vxa%X$k<4G8*^lAa_i?VXX;g;fBWLn4puBwK`sxAA@mJ!q{PzG zGfN@Rzl;T9#nMrjz`nmSLDjHgPJ8=%i%V-L%-@t5Js};7N#~4lv0{M`5UQ`I4+8q@ zTdC3~O%M<r0y0id%Yz^SL+=qFAO(5?9V<fT%yQP2wzv~(5QG^@#8wUXJO1Ab0DK?# z0f@tS$nIF!Y1AJ0-{A})A^8)b;=-e(M5G*rMbm^Bg9P=0+QZ5`;R#BIpBPs*9I?qX zS5XkJxGB+-3qU@O7&yqDBSoNAAs*VF(S`i5Db424N&_LALhCCRM!DcSu_!j_)1aVQ z)EBujhs-aa>SMmd(WmFZ(-fiHJs@`Sg#}IXXV!QPUjX<Wx*mj-v2CfJ?}igvv~C7z zE(|gx9OJm@{ul39h~LZ%tUbGElp+{YyWnaKI=K{WwNsV@J1oK>GneGOlXR|WNiCO{ zt3s+78>d8wH~&rORISh2=`{T^%pa!A`-GT>&BdwyQ@6H~f4=0`zr5c4f4H&##5Y}Q ziT;*-)J{^sk2Cin^TpC59o5f%|1Lc98ST6uurYo$YRl8)aFi*$1*+S*cRfjH*+83N zP~l<HZ4YVf9p!sS18fo4IEGDVB+i7WkL!MucgETK4ASx^1eS6NsnZm5rYF99A$d;N zfiG^%1&5b7pDvrAd1It-QTg5o4t*>@$q&Zwq+(?vaiikGz_BrugWD-vaZ!G(wuWYJ zhErxYS$oQ|+stHg&y<9vhl@#g-Q~&-DvXDUg4E|LriJ*fWBD+*g>;)u5HfKNQfBm1 zW=P|?E4PJHvM9}iDFNblW@PW`Oky>cs!e27#)tzhx>TOPjM4tm1~CB$n{CZDsL9O9 z;Rl^>Ns$IikR1>BIrI|YLg$^5L~lDe+9}`1zw;GJ7s1D#D$_Z;azH)wJVIaAyoqU? zo%vLlZ#(M^MRQ49$&O^|aOTjhfJLvdTQ{WS$d5X!Wg*8Z)GT`>Z#Zn*V9V@d`BhBW z%@%^Dmfy~tI?2E>$xS=g$3*U*8b~on!VB3Qe6VZbe!@I`bHr*`-wY2QCc0dZ!`uRF zEu6W+TsPs-GqtTtJ&q>2kX)~R9b+kdTvS)Z^**DC5r(AJkYz7SrK`I8u$E|+h^l~X zmONSaXVJ%3;X@vtNjf{kjYRDe87fKA5!+<ZgIrs7-#%u>B>h$JM<++K7B~}(;WKA+ zbEP3>XNe(APG^W81+&xD*x3lXB2AmTq+vc&DJHdj)4KQA1Adqq_MC1w(Y%u*<zOLg z-0t^|*#&sOqO_gPkTgX*f7x7o^u85Kc-~Yk+yZeDwGCFrdV=B8PGAyRgz1=so;338 z4JO&t4>sWR`7ZpE<yB>%d!x_w1M~UU*ypz{=#A78dnR-oNNZ_C|LTD0Yh6$|Rhel| z0aHK*SnsDIJ$-QjOhB*JB-8pzHypz2pN9jW18{k9d%#3E2S!q3gCTN(SA`Rp)p(wl z80i&%*+jE^k$N}cd<Eq|1GFv5cH!Xu^HkB7v+~dH^D%>r{Zf>LwvkG-uRxauTm>qZ zgy=ZqFA5aMta}_vx{K1n=>xi2!sOs1Ul3{UE(tHoA`d}I!1g@y$$DY>>Af=t?UhLS zA8{xMw;TG5Nmb(pD`}gS8qthP<;;6n>tUs!y9^77Ophep_7YD5Tu5a*_{DDanAE-- z1-n`zc@5wlG!BNw`9G38g;#fhRlN2`93@NGR-9x;;DGA!gxl^V-gM*mvHCmwTH7Vq z*QTDrO}|p)XtL5cAq(L=y-|OFFK)WU^cc#j_g{Do238;224%<Iw~9UO^BvG#S4?u` zs@?~_zXs;`0KfJU5AgoBdH3=|oq~EFKw;bbUlA9E5t{<D-;t}`W)d%(ePq1%v()v0 z(^U%{2>&UWBRpjF?dkQB<L~Bl1c*dAI9N^_>#WxS79=>8<cCC356I~7J$O%nT!=hp zF9-nFwp2|x?AYTD!Y?SJ#{zz{hK@rTC{U|j5S16Jeo*|S-b$LJ2$%0J$yEduAq)A= zibLoV$#OaXq*vKo`=`gm1^gg7$`;~wYlEt)amIjW<t=}(^6mO|h0_>LQqaX&D2ASV z1+7{v)X9svRtP$92@D(~+%|No4@l=1n3miH04H9##}_F$+=9wZin^_A>Onk$(-g_e zfIuSQ`&Pm}o|uSjFeQ&I17H3ocvF}N+;^FmUdJUu_2)5<-2B3H24Q2mYl^3zof9sB zT01G=l_G>#T2&{&^4=2?CtJXxnX))OyKxLloTy(?iVZgqIunsKAdp-LJ-!|DboLNN zn2Dz}k_siI3T2L4%R;{x2rAGQ`nOGKQ;!TTw4S_du3PbJP5|p5DZbs!=l#Rz*@3TD zbn`23m1^>-Rm;{t<CfoAQY8P!TCKdVPXvwf6<$+l^6JA4=qHRP9&lNu&m*j?u0NH2 z2!WkFY9(O&vtAvZNChrdP>!$R>AO-yh_l$0%s8PFyGlJ$Q_PTM%Z(gc!%P0CT)utH z+RW#62;V@kV}HjJe+X_irg0-5&j)=52Rp4AaosDe(^S1p5A7-p{TR==Sx*7*vcLeX zsr1OnSVIq{<au!>>SztZD|FV{p+1yj>=C2o;_-%IA;O>K0KF*`+W_DP$+u-8Mw*|d z1o-(NDts^vcUb{7fmG}KcFRu5$U0W?a>{bA_;s$hmQ=~J1DK6KU%f-=UG=0!tLKml zpH`+ur?$uynn?oid9i<Kg1QxakAG&xNcLyN%7zui&f|gvyWs=D-cD(h?UxF`f6Yuj znGMqK-@HHe+o=bWgTt^zi0iokk#}P(%rhMAQej7^rwnb=gF-hR4(RNQG*O6?7I0(6 zL6u5AhX7_oOw#~K+G!qjUa1l_kQFnUKaX-`fJCi5zy=%VV-QY72y;cl@rPHpo*eH0 zo%_d-Q)d68(kOrReDm&PrHr6p1z6~2&xNtUQ(!xqsc4n&g|r;3pI!Q&uf*jh&CPi_ zVcG;+Y&mh##{sIPY-(lSFzaL!hwxw4QUvV`j6W^xT9euT#z@&)xG53<wDfMSv-Un6 zKaG9$zzdfR`(twI`0j)#M7kS<Kh>x&D^vPX@RDz=kk7f_Gj3i0K_6-~!3O)Ufx$KK zXjKh1<wPM>cV(wvmGPReg<sfapA*zc>)KnE|8Hk#kpE}h{^6*#GhRQt^!bi?;~>VI z{k=6nPM0lD{r;vCSi6Z1Aa4-hC;vO3#p^yET~D{m3BpYVBfs(iAh;}4|AA>RND>E= zWI!c7BBz96yceQPiJ;FnW1drEn#yAu2V)L|#o)4HWGy3`agdM=#J3RQmLkM&1Ifmt z*$n6!4%WO8b)tpDVPZHN2+e7@A`|mL5%Ovf(|8}W5RClM7ld$v;rRg}keP!okw%28 z;p6@=L4FRAeoT-W8=|xkcWoOfMgz5IP_Bzpyj&;;!YE2O%7F^XEjT5}lH#L8^>d+$ zWkFq8q^?40G>f!F1w~|0U0rCzZR-Aqo3yxXD&8!>l!rN?8&)EZE>D+HVUZ*q;+$!4 zKO$U`2(l~WvlBuTF+pD2F&-{4UfXe1tc2R_gu3a3nwEqHIHie|5H(HxP|g=+8E`_0 zMx9PnXC?Y=L@B}1q^!8X7Se~eREiQLLJ0RC47iIov=@(SqS8$_i0_su6)cb>5&nk( zEvLnNnvOY4OIQg@SoKZ*Qjxq7mVBUsrs_gtPLsB?XllMGTVb(_S#g5P#1Z|-bsTK7 z7~dy!JUxu?p9n2-n?fKWg$<|}TAbiC<={??t8a|NP-@fL)Q#;JTxHB>R`P0A94m`9 zn3a;nA}I;QcH#HwtuFK*N;EzA!|g1(DHAg;e%yuyyB?YZU8Y9SV(zeDQZw;NL^$sk zc@rj^xt)GNBICPWhJ#DSMXL;Ffw;>nv`DyFq-8Rpg@lLDe3Uca!DZFqH10NIz>*Py zH(U5AQ%;sqrIDgpNlg|3VwQ1A9tnqONljvL<VsRpcoro)i{_d&1D6%tj%umTyuQuw z6UxSuNtyz20j*RP+-%g6{#z;bq{L+;M}u;cNZqEY`^E@<Onoe#l~|e8Ad%Z-kV|pR z?heZ&W@QId=2Ek$o%)fHtfa<+v5_wPw_R;SLvA1?@?LEtd|N4g*{S|niCXa~Q`z~` z`^pcw1`peJ@_Q@tc{5ZlJe#ncmMoAdO-t$a%Z7@RU6%_+_31s?aqB{d->}FV^W<Yg zDMbCOW#3G3%K(Zv!_T!aFq{T!D}*8#0ttnf)k41T?4F(Dy~=sFl(KJSQ@_LM%kd;X z0s1Fpa^oZNsIHLBhGYoNm9_j>3_-gkPRpKQ95YDy5}(ZUEvaas8qAg$u9ln}E)iTw zRY-VreLLG@CAFi4l-ZhNE)X3slkM*pb7SV=n=Hn9_v8O8%lc@kQCXRt@!0{bbUW)J zMtr_P#1o(4QZGZsy44e3Npj<0qHbI2dF$f4Z6z;Vv#+-ndAer)P<R9o@%t0?#mB=_ ze5?wk^&dA;NT~+pr*jHVtrkA4Dv|IjXABn^RHaJKCWR*CF6~5-XfgRKrPJ}L9)^## z5yf~j&`D)4C6z<zEhKbU#Wh5goNLjs>_jce0{`$*+uf(jl}{9M@&i}1CEA{pt!9hw z7Rz1ETgj$QAf8;aDlV~(ye{$hn@Ex~g#l_PPK~ed6DU4dS@ohV)g!0&V0h6lR#BdH zjrer=Xhe}LqD1y`RZl`S$FPK%lSs{}abP8eN|L|dEVEHMRPLJopG)TZ7Lu%FrdU{P z>Pq5rYbo8o=xjp4W_Ho0UlG=*<X~j%HN)By37I!nGYr~llj2DR{`=+O@QSZ7j!L^V zX+Kgla?(aso?v%NX$hG#IZu6NGDnA#`YIbVth3E>QV$xG>{vfG*v%BnEs(IvY<GF) z>Qc53dI~TYp;k{9^&140o)jdMI{`J35@niIjpo+R|Fq>;&cYS^qqACH%o#8|63c)3 zzGzX-tJ|okW5Zv;YSex={y;R6tSdrzn5L=1s|hulDljt|3EvXi!i+U`X^r}g$azZm ztL!kfHNz+>=TKWA5?vPzYW&PshX*MZw&s3m%QtFkh-`iGrEM1W@{RM$r~rmi7_u%H zb6V)3<WRM!TS|?8y*BcYeM=(8Fs0unS&<0K7FG!pQJLD0?3m8&n0?vt_NjzLJ^zve z!nV6((XEsFTik-td7mvnpyisnl{gtja#b4L-f8gKlH#(mmv_pIlp$roDBLh6)9vLG zH)f_0v*>9n)Rqb6GV1`cA`yI-iE(1QEJ$P`3C!nD38;})RA3u+gro?d%K@`n+0SrB znQUK21Q~zjRl8|GO#g3UjT@{2*~(Bo^v4Ed#O*cP?lrU}8>{u5s_r!fTDpkfC0y(p zyU%{F@0=~j&bZISy$^5OZ#RPO*hUNjh|iTtp00H|k`-II#c`J#e^qqt>St=Zz=p$+ zgN&l<hL1z{p8C5Ewk>Cc5<nruwp9<z{^@1XrXnkLM3TKh(6D-NJEFWmIXf)4tz8Kg z;vh&E${sg-Sg}(DkFS5*Qg*;UMhRZ*M{K*^_|Q<Cw7#9}kuzK=RT!npBr?fn`ZXsc z8P$L9b_vP8@iFCUuojKjxs84^>q=+0;;+KG&msoqFVpe`a=y$^)|g~t78qJp*eNm4 zmM}VN92sRBOZ32)`DV6R$IKXyO<Rve?KRh^!p=Div8%d9a)u_Rd+KiIytHg7w9WMM z!#vtRuJJGezED%9U{Y}Qe*41+9AuD(sg4vd&1&TYqt5QdRzwDc1fxRIU>uKl(+vUM z9x{XhTib~J`iuFpImu{wACvQid^D+TjVWknJJInQEWyMW;~+ZS=;n>s7r2qprwtmB z3~)@@uYkf)LUa3e^HMMg`So=zZm1%XE`mm{Z-AS5m=a^mX?=8^(0CFK7LS81Fa>>r zK{COxlnU575q1nNTevZ<=rCCki3(vrk4z65xgyqivFpJgf^lS>2h@xPI~@#?U=DJa zQvn(n01s-$qt|i#q0(Rr)n~q{uR#+%4Q=gjc82=fGAoR_n;9)BVUNQ+pb&kGLh$3v zx3F~vOpl3a2@X&5Xfq84w}OE^W^W4-9RQ$@zyYpMh9_XnuAlwv5&q>q$UY3&rNK{u zMfmTl!z2Kpq!70B3mH{2<r9pQ(7<qlk;cIwob+2dfaY#MoSv4C9^%}vZG1&fyE<G8 z2(WH^#gwq$>(#$OC870`&^`=62M(;j0D0rTbYO1h!@}5b{`j^TXmmL5<&Bkbp%4)0 zHqvJUT|bY(edVqELf6$74|;?J{s9Apk>K&c5*+MC>zPZ8=^i`&5;{0)xY|FWVpGa6 zx4OM)wtZ)<juQ;J%j}PT_nxAM(ML}_aVicVl6`_vX=QA{BU*0*oE&AHW;|K(YDRr~ zYGn|;tbzV`i)R^z;%9;*f{_XUV2lTSz>NbQ&=3umunkNUui|15X+JO;bmJ7JmH|DE z=U?r}l(wpyO?WeCe354K$>QXPv#R8zdX9iE&xgTXh_Y6`$unlMIYi6{G{C7plV*<A z)0hhh26O%(4Z=XxZv3xc#U9aI0o-^<A&f(u4bVUj7Q+4wM(P3R1qNWLjcDN^ZUr%b z`ZFohgB&7%GcadQLnkrO_t|jI;Dw;sCs`+xlvfvit<`F|S4(ch^8S7qMuQ|^zy%y+ zna5X4BzI|G*4fZn709JR*heZ7;C(DN0}a`Mbo3)ROms>Gp(kEr<&n`dO&6gHpICUb zW8q?w`lsce{I}y_%E_p-IHaufp)d_}2oF)VzW+9a4WITvF1wZ-ipVsHD*o|wWLtG4 zpq+Xq2=bX79nO5L92EB1gFlmc+n&V@aCpxNesePJjWH4VZ~cd}gqP7@F-OG79x~Ae z&sILyGseFn7^ACt!9hVX#|46|1Ukke)yKPnKSNJNa(PhFK4h5otRv^y``Ve%?1v|i zmHn!%?D{?>p$S!g9=?xT9-0L1<^t010XtBm^zl7=Q2o3>lE$K6;RJsk^n>w4>%(^; zME<XeLgiNRK*#BpU~IrY{NWCVoYAp%;o(`%Z`JSup9wX(my6a%mp5)T&hJ#VMSzqT z@Xz;9=VgxHh)1Frq$B$O3Wbb^t|K1phk_1W8CMKOu?u63q{p>@{I7!;PY=l5nrKtr zj-tci0FO7FBTGIEzDs`)nse~LT6S_+n^qWV;&hK98?JFufGG6K(5T)p`8goFNYn%X znt-ecn#j23=b(=jIZuPiwoLFuHmz9#2213u7|P8&A(^#VUh%*gR*iF#eSNPySu)<O zC3wi-=;z70d><`VYNPOFNwKw-){vofNR#;8iT3ugt+(phVfu5$_iQjzUM^%-_r&r= z+q?z)Y6FX}lT#LMpZ5IwFgcfSl1gQ%`sd*ZG@;*@=y3cjPlEpuJoPAy*iSW`*qZ=$ z9xZg4PIpw@v4tNnP@D?c_x`=v_x7(>hg$nA?d9FsSM$S6%)cj!7Q97xLUM(l>u{!L zv`p>3Uh=<Sx%T8|+WUSR_Q#K!+Ph5?&gub<cUrf8xXMlw8}xt5q0Eyc51r_Pt9$hg znQm3j%O~N8M+hRvoa(w|ueJ-SU+2&yjkkqCg8n-CvIh5p4CX5rOFhh<T5yS0$vV@X zW|b{h+cvU35lPS!ftHL|ev65)ez7}OV=Rtg--pSf3zKhS1SL`oiiD+fTh_>V8xe8R zXczc1Vc+0+pUSbT=aF!+>%8M~3ETek;~lf2bjedoMoQ26f8JR;i0yMaC)d8EMa{{Z zim=Aqa|ssccb?$wr$}<_*-V332eWaMp0)Qk2u{C;aVU?}P=@h!;VGdX^(=fA51JrS zn%(GxxI@xKx92acR(OUsm2XHUNh?U?m8KpIW+L$vnMhl>uY*!!$FGmM|7wVox>giX zCBOVD=c)dYm1m)K!DfJK?@$xJXx;wF?3{PHyl}LOhZ6>u9B!U)D~5#bJs9-O3=UmR zr#^<{S|Z^FM`P@gxyGI*7U!(JA+#69o`YzytGt_I7Pjf~21h?J!Gg#X*;VpO$vgBq z<=5?68h$=1^v-Rp7yY#6k&-oAIvL=niWfVS7bpe_cs;t(Q~yc8p(hMPRRqotiaFrJ ziy>~&`*RXPQum<!kZfhE@JA7We0_(c+W9_V|54&Imv#s|PZfC>KF6ParNH5H{1v4g zg8=+>q1`~yz?t2E{9Xsej4OdAMoSrXOdGAs*N)uzhawko4tGrWg5^{^6D1~}$d2rn zl3%UpmAWHG&D$J0UTz#RqDUotXZ_2Qy7TJrIr4WSxd-icCe7>I@4nJ~WPEShO%G&E zi~aOvWT0NkHis_wy<tIPP)d8TL#ku|J{p!Dax$UdZDRX!Idy+W>ZBJn-)34sr51jt zcuC~2QQpPrYrlTK-rIa#9#Z$G>dosD_|2>TeCyJ!IuN|Qs6Eoz6J?%v)xAtc#luHu z^py>0|3C{KdU*-*CfGb?ksa$S1r}V(g34QJlslV!f(aX30-Nib4rAl&73=$VcI7mO z>lybiOS*3el{ZrymcmvwdwgFsJ~TF`m>ccLdKb>0dAm_cGufM0PacN{`7Xi&cKG;n z<yA!ppQLPiVuk$p%{((;<`S(e;qcAGsd|>&r0duXyvb=s<yrX^&y@Y(8{*`R)r(!b zNOP!?u=z82xoAk~jRrl|n(F|AY^ETKOh+A-wN;i4>4&L*N0yb&i~F#Ko`GChb~2j` zvVw_R(oNaBPJ%J%*%Kegj3Xj@L0;EDV(6q_jJH`{I%Qg1@4|1$tLqmYJ#ajCJbZr# zc?~1Vf4rsFzv4o!Xx2P`EdzX7sWn|?*6(ar9_obGU71dFV^*)b{oSkGB<JeXe<I(w zX{>xM(1q9HV67?hTX&59b5ghzU44czT*|c9s(%>m9V2^p0&d(60@n3?O<E6{-gD?i z?FCbF#L^BXq&mR)zA9K8=c{^NO1sn=P_T{*5l$4QBx})cc*{9TZ0f8ZP}msBwl#2E zolK8AzY{0LElP#(@x;5>$+pIgrPrKfz12!9mEWB`LK{)e^Y63KkpG^gS)=n{Ew5zY zqX1r2x6b&NDCz9wIHt#bQtr*!qaU`#RME>U=`c3p>h!ZWqTA_(>%L1$WZpieQ*u-4 zv?T*QzWeBV>BW4L33&blkg#xGL5?}`YF!Q5dtZ*?Ma!M6_HXIYp5)U|PxJp?=zK1z z{+|fj4t{~c`Q%Bba^31lKlz|<;QI{V5Wt25Ij*@jggCdKp_32fB8{Ic*{i?mMtXT= zxKhk~Y@c2DRI`2dvEfhu)0cV@WvmP(l4!c}3LA+&o<D33RcYtG$~bT>D;*~5yQBlX zRTngg9k*EKI}vfKPHG^gq!9i>YkBmjhTq+6;_9H7C~^hyquBaVn@E|=optYG$k7xt z1<TL3t1XXAHM6eXkHBy$4;d3dCxa88CwUx4v=qgOwR*{)`dZOr+t{+7@<g<<@5)9T zsqgVQv&n*o!a=^bCdXo&P896$IrdqqaEHRg9z>5^F`T@7^?8WnBc(zMrWmQD!`c&D za+`Yp=d8rRMtMQo5$0JPdEvoby+{5RUq5h9hbCxb#zmx7{{Gl9Jojg;p`NV4+OtVT zJa9hQsO7kRVsCuj9+k4%z37kLK^${|3a<0Ik8BU89$JLg?P-8b)W0Ks_h*-u{m^jy z9g_V?e<1G(RLg2o;{Bgb!w;tV<#XS96=XzY%BdU9c~$Rv9a<7$Qr@u6oeuNsY?zW> z6Cd<14@ORPew+!@_YJitQV;KuB#ZCfA@=_{&pt+#d%=2EAb)~;a6hQBLGYff&*P^7 zIue+JA(~Q_|G?a7^r_wl)k(7Nw-a@35~KzHoVY)kCcGa0gfK&>eVU%*E!`aPY?bWA zxMu#PdUZJ2eRN@7>Wtzbr>OZ+m^G^*k|S`a?$chlfn`aP|Da1=ahOc&tGhwQn@y}U z{-KYHZ!P;muT^LKiPdAQ#anlHAAd~u5E-61TTV6p=QOsc(X0OIN$SX*g3yMD$+~F$ zr*90tc)fl7wz>Al+PdOP3(&A?#9kHsRm8%Xd*vo@>f_#VZ6Z7(PMAwBeyljLK|M?O zD7<2YSJ~g7Q};ryHY{M(quz&8rdbfL3#&&vq7|;~#MwK*GJ$<_^~u|#f)^i0OqI<2 zc={k})$_yd^xLa>&E-++*B)fA7Sg0wS-E%0c5M=a32i@SR=b?{@3wZzc}y1dG==VO zt~fv5ecQEvt>LuidWy(#HGPKEbzbvbqZ7T6V`(pc6l{66?#b4#kOl7X!Jn+y-gJI9 z^XJFo2m1>j{`)<6`uD==KffV-dtH1eJQ%|K-IxO`N@OeJt!aFh_-fr7s;aa)-79O2 zHjy>G2DlY8wi10BBw8JS5=C{0I%yd@nk={0zHpSqdUs>pO|ZsB2R7w7LWN4Ljj3t0 zgNBAlo~IeEo$)SdxD|DFW9Jd>siT}zic-~&0(3<}4MH~eQD{psN?5I`QA!G_mZ_}O zVbt(u6VDDX%J3=@sqWTw>OBDwJD_H=PwW+=%jls_N`#td+x8kcHq+Scr;I9Jk<`9b zRciOOVa@s^oXm{94UN2e_1ZhB!DiLJnGy=8wzLF2hnV|To$kmErJ}wQp{?uk{dr$b z{SohH2=oh-m_2`Lb|g>3Do@6Yqjy-RtGJ~4ha)OUzi-#m&}q-`5z?sXY47*>wyNJu zPcsVxg#m4P>p`;tkI<J|dGNr?%3JK7r)kH~+ykAlGENAb19{+Ufa&U;?iI(P%sbtc zNb@g=CO&~hQoXfNU{lzFcxqx*xLfBzv$NNo1`h7$Rr*N{hDr@yrT10;ZmV=W`=s}9 zn@!y@Go5zinJ|^SJ@I4F?ksZODJ6mhi)3)*JL}q-5!u_+$H|g)y+~z6u=}I*7`Q+e z08nIu7&TKTy7_}rnY_KTsX9k|)`ntHtjas5ebk=cAz5~cH&j=FPh|-Jyd#4yQZAKD ziu;gEd+UE%qSb0AxVN=Oz6^gvwAHA+sIj$5FgR^&T90uz5MhH2^oh7FTB0l5ouTnU z`{nR7a!9<6>QveJOmnoVDn+=H+0^X#6#s)rOUJ(2Jap_ojggPqCw_;^1BnOpC*ZE# z$oszKE0>4C4zzM(o!+5b$=s^JRgLU7!~403rqz8V-I8tXTpPWdVHNE>*W4p4_^VJ= zn`}p&w0Elh3<}N|&RfeUdn4#Fqeo@i+!C?vQfQV$jx48Z1?Jg0r`G?pI<nv=E0~+b zyPVP<pJB_D4?;AAtBPvmr5Li)USst<7l!f<S;RWEu4wnBzO;(nV>LCN%d)B3Q80gq zWnGoBU<V9p-=-#h%O94rXEN;yep}MLTPwW=b2ghpOWA^EHYXz;fTV#`lvUp|2QHsO z`+{vBFQa_qi7J>4N1s*NI_C%(S~EI(Qi>Jg-C96aOCk?uE@=BXbm^=NB#1Wy0sW~` z)?QLWUe)K3N#_Xd4tKWLM^5hdALtmmPCsVgF}$Ney~d#228btcd|D!oS92atX*kZL zH`iT1c6Fh4sb@ep%F;8HUU@k$qiXERY`lE8V}bsgDe)4`i8nupZ=7+XCo=R{LdSHY zYTfEVS3!WcORRtp|4B=t5uV>^gCDSr=l4%(U#_Z6gR2T(d}Ca2LHeR2deX^!5@I-c z;Rnb0%H*XZlNWDXgnmRCF!`OsU;v(9b%S3?iKfn<N5V~AKXQp|SV6*1d7Dr9T)gCC zcgZ*D(#`y-n>ClnJ(mLRP6ftI-FklMR@9}SA5%fkrv&j8r&?le*HieEz$XD9B@A|o z7whL6J12qSLF^4IQU3cb;OHODQT)>n-oK4L;u3?NCaF)yK7SbV<83s*3+3W8*^VBs zE>8aQmeTJMUo)L}#Kmt~iTWoYb%QuGP3^(Mym>LY;xK<EDN#6?CxsGm0gFs$<k-P; z(PKGrGdcP3+0!$RJ6s?4yXNp;E|Q+je?F7Vb}ha#TX1DI@9)EO)U`tT^5gfeJ@b6t z3<{q(fPh~zaEZN!=a&tG6`<{T+zejcjPCZ#bN<=psM(fVZrO2eDH+h_sLSmgZrNpS ztr_p0e|^__!!4hm+kNrfeSJU{A9u|K9I(xQa~t%&AvRJemf*mDQ-dPGa`)o7k4|z& zez=dl=dusHKR==S{*C#SarFDwy6-37b0_XzVN1W~m|uB&<Na9v6>id%QFZWnA$~+5 u;H3oi5+Xu0rWVZS7B9|yx-qwOckXlC+;YZMAlMmjfnJ{k-$%m%qyGV)xK+mh diff --git a/docs/tutorial/gtk_tut_table.jpg b/docs/tutorial/gtk_tut_table.jpg deleted file mode 100644 index 9240b0c5515076fed668131ae7122a0939ccb31b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3890 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 diff --git a/docs/tutorial/package_tutorial.sh b/docs/tutorial/package_tutorial.sh deleted file mode 100755 index 4f54f63f41..0000000000 --- a/docs/tutorial/package_tutorial.sh +++ /dev/null @@ -1,99 +0,0 @@ -#! /bin/sh -# package_tutorial.sh - Package up the tutorial into various formats -# Copyright (C) Tony Gale 1999 -# Contact: gale@gtk.org -# -# NOTE: This script requires the following to be installed: -# o SGML Tools -# o Latex -# o DVI tools - -TARGET=`pwd`/gtk_tut.sgml -GIFS="`pwd`/*.gif" -EXAMPLES=`pwd`/../examples - -PATH=`pwd`:$PATH - -DATE=`date '+%y%m%d'` - -# Check top level directory -if [ ! -d gtk_tutorial ]; then - if [ -e gtk_tutorial ]; then - echo "ERROR: gtk_tutorial is not a directory" - exit - fi - mkdir gtk_tutorial.$DATE -fi - -cd gtk_tutorial.$DATE - -# SGML Format -echo -n "Copy SGML and GIF's.... " -if [ ! -d sgml ]; then - if [ -e sgml ]; then - echo "ERROR: html is not a directory" - exit - fi - mkdir sgml -fi - -(cd sgml ; cp $TARGET . ; cp $GIFS .) -echo "done" - -# HTML Format -echo -n "Formatting into HTML.... " -if [ ! -d html ]; then - if [ -e html ]; then - echo "ERROR: html is not a directory" - exit - fi - mkdir html -fi - -(cd html ; sgml2html $TARGET ; cp $GIFS .) -echo "done" - -# Text Format -echo -n "Formatting into Text.... " -if [ ! -d txt ]; then - if [ -e txt ]; then - echo "ERROR: txt is not a directory" - exit - fi - mkdir txt -fi - -(cd txt ; sgml2txt -f $TARGET 2>&1 > /dev/null ) -echo "done" - -# PS and DVI Format -echo -n "Formatting into PS and DVI.... " -if [ ! -d ps ]; then - if [ -e ps ]; then - echo "ERROR: ps is not a directory" - exit - fi - mkdir ps -fi - -(cd ps ; sgml2latex --output=ps $TARGET > /dev/null) -(cd ps ; sgml2latex $TARGET > /dev/null) -echo "done" - -# Copy examples -echo -n "Copying examples" -cp -R $EXAMPLES . -(cd examples ; make clean ; rm -rf CVS */CVS) -echo "done" - -# Package it all up -echo -n "Creating packages.... " -cd .. -tar cvfz gtk_tutorial.$DATE.tar.gz gtk_tutorial.$DATE -echo "done" - -rm -rf gtk_tutorial.$DATE - -echo -echo Package gtk_tutorial.$DATE.tar.gz created. -echo