RFCP logo

REBOL for COBOL programmers

VID for COBOL programmers

Date written: 15-OCT-2015
Date revised: 04-MAR-2019

This is documentation for the REBOL Video Interface Dialect re-ordered
in a way to accomplish two goals. One goal is to get a person going right
away writing programs. The other goal is to provide a complete reference
so a person can know all the possible things that can be done with VID.
This is the same information provided in two documents on the REBOL web
site, "Beginner's Guide to REBOL Visual Interfaces" and
"REBOL/VIew/VID Developer's Guide." What this document offers is a slightly
different angle of view. If the documentation on the REBOL site seems
confusing, try here for an alternate approach. If this document seems
confusing, try the REBOL web site. Everyone has a different paradigm in
their heads. A tutorial is very good for getting a person going fast,
but not as good for a reference. A reference is good for looking up
things you have forgotten, but not as good for learning if you have no
prior exposure.

Important note: The ultimate goal of this document would be a complete
VID reference manual. However, the official VID documentation seems
to be incomplete. In addition, some of the GUI concepts and operations
are, shall we say, "outside the scope" of the authors' experience and
understanding. So this document was created by reading the official
documentation plus the code for the graphical objects, and by
experimenting. The adjectives to describe this document might be
"correct," "adequate," and "incomplete." "Correct" means that nothing
was put in that was not tested and found to be correct. "Adequate"
means that the document is complete enough so a person can use it to
write VID program and use all the VID styles. "Incomplete" means
that things that could not be understood or made to work were left out
deliberately in the interest of a cleaner result.

Contents:

1. The target audience and references
2. The really really basic basic overview overview
3. Preparation for using this documentation
3.1 Get REBOL/View running on your computer
3.2 Set up a test area
3.3 Possible problems
4. Overview of doing windows in REBOL
4.1 Putting a window on the screen
4.2 Making the window items do stuff
4.3 Getting data from a window
4.4 Positioning items in windows
5. VID terminology
5.1 Keyword
5.2 Style
5.3 Face
5.4 Facet
5.5 Variable
5.6 Styledef
6. Overview of all styles (the things you put on windows)
7. Facets: The attributes of styles
7.1 Size facet: Specifying the size of a style
7.2 Text facet: Putting text on a style
7.3 Color facet: Coloring a style
7.4 Image facet: Putting a picture on a style
7.5 Action facet: Making a style do something
7.6 Character facet: Creating a shortcut key
7.7 Font facet block: Controlling font appearance
7.8 Edge facet block: Framing a style
7.9 Para facet block: Formatting text paragraphs
7.10 Feel facet block: Advanced look and feel
7.11 Effect facet block: Decorating a backdrop
7.12 Rate facet: Timing things
7.13 Data facet: Loading data
7.14 Pane facet: Making sub-layouts
8. Positioning items (styles), and other attributes
8.1 Below: The default positioning
8.2 Return: Starting a new row (or column)
8.3 Across: Left-to-right positioning
8.4 At: Absolute positioning
8.5 Tab: Lining things up
8.6 Tabs: Setting tab stops
8.7 Space: Space between styles
8.8 Pad: One-time spacing
8.9 Indent: Horizontal spacing only
8.10 Guide: Window margins
8.11 Size: Specifying the window size
8.12 Origin: The window starting point
8.13 Backcolor: Coloring the whole window
9. Styles: The things you put on windows
9.1 Banner
9.2 Title
9.3 Vh1 through vh4
9.4 H1 through h4
9.5 Label, vlab, lbl, lab
9.6 Text, body, vtext, txt, code, tt
9.7 Info
9.8 Image
9.9 Box
9.10 Button
9.11 Btn, btn-cancel, btn-enter, btn-help
9.12 Bar
9.13 Icon
9.14 logo-bar
9.15 Led
9.16 Arrow
9.17 Progress
9.18 Field
9.19 Area
9.20 Text-list
9.21 List
9.22 Drop-down
9.23 Rotary
9.24 Choice
9.25 Toggle, tog
9.26 Check, check-mark, check-line
9.27 Radio, radio-line
9.28 Scroller, slider
9.29 Sensor
9.30 Anim
10. Functions: Doing things with the styles
10.1 Center-face
10.2 Layout
10.3 Stylize
10.4 View
10.5 Unview
10.6 Viewed?
10.7 Show
10.8 Hide
10.9 Get-face, set-face
10.10 Alert
10.11 Request-file
10.12 Request-dir
10.13 Request-color
10.14 Request-date
10.15 Request-text
10.16 Request-pass
10.17 Request-list
10.18 Request-download
10.19 Request
10.20 Flash
10.21 Inform, hide-popup
10.22 Load-image
10.23 Focus, unfocus
10.24 Dump-face
10.25 In-window?
10.26 Clear-fields
10.27 Size-text
10.28 Caret-to-offset
10.29 Offset-to-caret
10.30 scroll-para
10.31 Insert-event-func, remove-event-func
10.32 Editor
10.33 Browse
10.34 Launch
11. Hacking around
12. Some common operations
12.1 Putting a clock on a window
12.2 Basic data entry
12.3 Get a valid date in a field
12.4 Scrolling a text field
12.5 Scrolling a layout
12.6 Embedding an image
12.7 Getting all file names of a particular type
12.8 Using the clipboard
12.9 Playing a sound and showing progress
12.10 Playing an alert sound
12.11 Playing a key click sound
12.12 Changing languages
12.13 Saving the window position
12.14 Generating VID
13. Appetizers
13.1 List-view: enhanced list style
13.2 Area-scroll-style: enhanced area style
13.3 Layout-1.8.r: GUI layout builder
13.4 Gui-crud-app-builder.r: GUI program generator
13.5 Toolt4vid.r: Tool tips
13.6 Easy-vid.r: VID documenting itself
13.7 Rebolusers.r: More than just data entry
14. Source code for styles
14.1 face
14.2 blank-face
14.3 IMAGE
14.4 BACKDROP
14.5 BACKTILE
14.6 BOX
14.7 BAR
14.8 SENSOR
14.9 KEY
14.10 BASE-TEXT
14.11 VTEXT
14.12 TEXT
14.13 BODY
14.14 TXT
14.15 BANNER
14.16 VH1
14.17 VH2
14.18 VH3
14.19 VH4
14.20 LABEL
14.21 VLAB
14.22 LBL
14.23 LAB
14.24 TITLE
14.25 H1
14.26 H2
14.27 H3
14.28 H4
14.29 H5
14.30 TT
14.31 CODE
14.32 BUTTON
14.33 CHECK
14.34 CHECK-MARK
14.35 RADIO
14.36 CHECK-LINE
14.37 RADIO-LINE
14.38 LED
14.39 ARROW
14.40 TOGGLE
14.41 ROTARY
14.42 CHOICE
14.43 DROP-DOWN
14.44 ICON
14.45 FIELD
14.46 INFO
14.47 AREA
14.48 SLIDER
14.49 SCROLLER
14.50 PROGRESS
14.51 PANEL
14.52 LIST
14.53 TEXT-LIST
14.54 ANIM
14.55 BTN
14.56 BTN-ENTER
14.57 BTN-CANCEL
14.58 BTN-HELP
14.59 LOGO-BAR
14.60 TOG

1. The target audience and references

The target audience for this document is someone in one of the following groups.

When you read the official VID documentaion, you will spot things like, "VID can make various window items such as..." followed by a list of things VID can do, but it doesn't really say that this is all the things it can do. Or, you might see something that says some feature is explained in some other document, and be unable to find that other document. This document tries to rework the main VID documents into a form that says, this is VID, this is all of VID, this is what VID can do, and this is how you do it.

However, since this document is based on existing VID documentation, it is NOT going to accomplish the above goals. It can't provide any new information. What it can do is present what documentation is available and what information can be discovered into a reference-manual-like format that can provide a stable platform for writing REBOL GUI programs. What "stable platform" means is that you can use it to find quickly if VID can do something and how to do it, without having to hunt around and experiment. It also means that you can pretend that this is the truth, the whole truth, and nothing but the truth about VID. Of course this is not true, but because this document contains only stuff we can find and verify, you can pretend it is a complete manual. That is useful because having a manual you can use handily and trust makes writing programs faster because you can reduce the trial and error.

Since the goal of this document is to complement existing documentation and not to replace it or compete with it, you really should go to the REBOL web site, click the "Documents" links at the top, look for the link to REBOL 2 documentation, and see what is there. You also should read some very detailed instruction material by a well-known REBOL programmer who has used REBOL for real live money-making enterprises (which shows, by the way, that REBOL can be used for real live applications). The following documents are almost in the category of "required reading."

A Beginner's Guide to REBOL Visual Interfaces (VID)

REBOL/View VID Developer's Guide

REBOL/View Graphics - Face Contents

REBOL/Core Users Guide

REBOL Function Dictionary

Creating Business Applications With REBOL

The Easiest Programming Language: REBOL

Starting to Learn Computer Programming with Rebol

Rebol For Programmers

And finally, there is a web site for REBOL programmers that contains a lot of sample programs. It would be redundant to mention them here, so you should go there and look around. A few are mentioned, however, at the end of this document to point out that REBOL/View and the Video Interface Dialect have a lot more capability than is obvious from reading this document.

REBOL Programmer web site rebol.org

2. The really really basic basic overview overview

GUI in REBOL is done by describing windows in the program code, using various keywords and values. It does not use a drag-and-drop style of screen building. It uses language, because that is one of the design goals of REBOL's creator.

There are keywords for the various things you might want to put on a window, like buttons and fields.

Where relevant, items on a window can be given names, so that attributes of those items can be referred to in program code. For example, a field can have a name, and then one would use that name to refer to the contents of the field, or maybe to set a value in the field.

There are other keywords to modify the appearance of things on a window, like its color, size, or maybe font size if the item is text.

There are keywords to control the positioning of things on a window if you don't want the default top-to-bottom left-to-right placement.

All these keywords are put into a code structure like this:

view layout [
    (screen-description-keywords)
]

This document tries to describe all those screen description keywords, in an orderly manner that should seem familiar to someone who has read programming reference manuals.

This "manual" as it were can't be quite like a traditional language reference manual because some of the syntax elements of a traditional manual are not compatible with documentation on the internet (like the less-than/greater-than angle brackets) or are already claimed as part of the REBOL syntax (like the square brackets and the curly braces). So we will have to make do with what we have and hope that context makes things clear.

3. Preparation for using this documentation

This document will have a lot of examples, but it will not show the output of the examples. The reason for that is that documentation with images is harder to maintain. Therefore, if you want to see the output of examples, you should read this document on a computer with REBOL/View present. Installation is optional. Then you can create a test script, paste the examples into it, and run them. More specifically:

3.1 Get REBOL/View running on your computer

Download it from the www.rebol.com. It comes as an executable. When you first run it, it will ask if you want to install it. The recommended procedure is to do so, because if you do, then testing will be easier. You will be able to double-click a script file and run it. If you don't install, then put the executable somewhere convenient.

3.2 Set up a test area

Exactly how you do this is up to you, but here is an idea. Put the REBOL executable into some folder somwehere. If you installed it, and you use Windows, it will be in "C:\Program Files (x86)\rebol\view" but we won't use that as an example because if you use Windows 7 there might be some security fussing you would have to do to get permission in place test scripts in that area. Of course you could have the REBOL interpreter in one place and your test scripts in another, but this is supposed to be a simple example to use as a basis for something else of your own choosing. For the sake of example, let's say the test area is a folder called "C:\REBOLtest."

This folder also will be where you place REBOL scripts that you will be testing. Keep in mind that if you installed REBOL you will be able to run scripts by just double-clicking them, but in either case, installed or not, you want to get things set up for running a test script. So do two things.

Make a test script. This is a REBOL program into which you will paste code from this document. You will use the same script over and over, pasting new code over the old. Of course you don't have to do it this way; this is just an idea. The test script could be called VIDtest.r and could look like this:

REBOL [
    Title: "VID test harness"
]
;; Paste test code below this line and run this script. 
view layout [
    banner "test"
]

The other step would be to make it easy to run the test script. For Windows, a simple idea is to make a DOS batch file to run it. It could look like this:

C:\REBOLtest\rebol.exe -i -s --script %VIDtest.r

The "-i" switch means don't install REBOL. The "-s" switch means don't give a security check message. The "--script" switch identifies the script you want to run. This script name could be a full path name to a script in some other folder.

Put this DOS batch file in the test area. Give it name, maybe something like "VIDtest.bat." When you have made that DOS batch file, test it by double-clicking it. REBOL should run and produce a little window in the upper left corner of the monitor. If it works, you are ready to test examples. Examples will be given without the REBOL header. You will open VIDtest.r in a text editor, paste in test code in the indicated spot, save the file, double-click the batch file and see the results. If some test program is an example you want to save, you could use the "save as" feature of the text editor to save that version of VIDtest.r under a different name and then re-open VIDtest.r to continue testing other code.

Alternatively, if the above is too fussy, you can run the REBOL interpreter, activate its command console, and, to test your scripts, enter the command

do %VIDtest.r

Then, when you are done viewing the results, close the test window, not the command console. For the next test, you will be able to go to the command console and press the up-arrow key, the "do" command will reappear, press "enter" to run the test again.

3.3 Possible problems

With Windows 7, problems of an unknown nature have been experienced if files are not on the local computer, but are on, perhaps, a network drive. Also, REBOL 2 is a 32-bit program, and so on Windows 7 it might be necessary to locate some option for "32-bit mode" or something like that. Unfortunately, REBOL 2 is not under development anymore, so if you get some strange error you are a bit on your own for fixing it. All examples in this document have been run on at least one computer running Windows 7. One would expect no problems with Windows XP. For GNU/Linux, you would write a one-line shell script similar to the DOS batch file and might have to do a bit of fussing with permissions. As for Macintosh, the author of this document does not have easy access to a Macintosh. Theoretically, things should work. The Crossover Office product is not "free as in beer" but does not cost much, and is an idea for using REBOL on Macintosh.

4. Overview of doing windows in REBOL

A REBOL program (as well a program in other interpreted languages like Python) is referred to as a "script" because it is a file of instructions that are executed starting at the beginning of the script and proceeding to the end, generally. So what do you do if you want the script to display a window? What you do is use syntax in the language to define the window and the things on it, and then later in the script perform a function to display that window. The Video Interface Dialect (VID) is that syntax used to define a window.

4.1 Putting a window on the screen

The VID code that defines a window is a bunch of keywords (like "button") and attributes (like "red") that define the items in the window. There also are other key words for positioning the window items. These keywords and attributes are written in a block, that is, inside square brackets, and then passed to a function (the "layout" function) to transform them into a displayable entity. Then that displayable entity is displayed with another function (the "view" function). That's why you see in the examples something like this:

view layout [
    button red
]

The block that contains the syntax of "button red" is the VID code. That block is passed to the "layout" function to make the window, which then is passed to the "view" function to show the window.

Code like the above example, where the window is defined, created, and displayed, in practically one line of code, is how a lot of examples are done, for conciseness. In real life one might want to organize the code a bit more, and do something like this:

MAIN-WINDOW: layout [
    button red
]
view MAIN-WINDOW

One could go even further, like this:

MAIN-WINDOW-CODE: [
    button red
]
MAIN-WINDOW: layout MAIN-WINDOW-CODE
view MAIN-WINDOW

but you don't often see that. Sometimes too much "organization" is just too much.

4.2 Making the window items do stuff

An item on a window is made to do something when "clicked" by putting a block of code after its definition, like this:

view layout [
    button red [print "clicked"]
]

That block of code can be anything. More specifically, it can be a lot of code, so often, to keep things organized, one might code it like this:

BUTTON-CODE: does [
    print "clicked"
]
view layout [
    button red [BUTTON-CODE]
]

What this means is that when you click the red button you call the function BUTTON-CODE to do something. This technique can tidy up the code so you can put all your button functions in one area, all your windows in another area, and have the layout code easier to read by the absence of all the procedure code. But none of that organizaional stuff is necessary.

4.3 Getting data from a window

A window is an interface with a person, and one common operation of that interface is to get data entered by a person. This is done by giving the screen items names, and referring to those names, in various ways depending on the kind of window item. For example, for a simple field, you could have this:

view layout [
    FIELD-1: field 100
]

FIELD-1 (note the colon) is the name of the field. With that name, you now can refer to the contents of the field. The exact syntax for doing that varys with the kind of window item. For a field, there is a function to get its value. For example:

view layout [
    FIELD-1: field 100 [print get-face FIELD-1]
]

Notice that you can have a code block attached to a field. What this means is that when you press the "enter" key after entering data, the code block will be executed. The code block gets the value of FIELD-1 by means of the "get-face" function which requires the name of the field as an argument. You also can do other things with the values of fields and similar data entry items. You could copy them from the window, print them, build html pages with them, store them in database or files, and so on.

4.4 Positioning items in windows

A design philosophy of REBOL is to make simple things easy and complicated things possible. In the area of making windows, how this is expressed is that in the layout block, you can just code the things you want on the window, that is, buttons, fields, etc., and REBOL will put them there in a reasonable way. If you don't like that way, then you can do something more complicated like specifying exactly where you want them, with appropriate keywords. The default way of positioning items is to put one below the other. Of course that can't go on forever, so you can cause the positioning to go back to the top of the window and start a second column, with the positioning keyword of "return." For example:

view layout [
    button "button 1"
    button "button 2"
    button "button 3"
    return
    button "button 4"
    button "button 5"
    button "button 6"
]

If you don't like the default arrangement and prefer the "left to right top to bottom" way, you can invoke that with the keyword "across" near the top of the layout code. Then the "return" keyword will create a new row instead of a new column. For example:

view layout [
    across
    button "button 1"
    button "button 2"
    button "button 3"
    return
    button "button 4"
    button "button 5"
    button "button 6"
]

There is a keyword to explicitly specify the default positioning. That keyword is "below." If you like to specify every detail, including the default ones, you would put "below" in place of "across" in the above example.

There are other keywords to affect positioning. The above two are presented to show the concept. The othe keywords will be presented later. The concept is that you use keywords to control positioning.

5. VID terminology

REBOL has its terminology for the items on windows, and we should use it in the interest of all speaking the same language. This terminology is explained in the official VID documentation on the REBOL web site. In brief:

5.1 Keyword

The words like "above" and "below" explained previously, used to control positioning on the layout, are called "keywords."

5.2 Style

An item on a window is called, generally, an "interface object" or "face" for short. All these objects inherit various characteristics from a "master face" to make them similar and have their own characteristics to make them different. In other words, any item on the screen, like a button or a field, is a different style of an interface object. So, the term used for the words that identify things in a window is "style." For example, the word "button" is a "style" of interface object, or a "style" for short.

5.3 Face

As mentioned above, an item on a window is called an "interface object" or "face" for short. In "the literature" as it were, you will see an item on a window referred to a "face" as well as a "style." You also will see the entire window referred to as a "face." It seems that all windows and window objects are descendents, so to speak, of a master "face" object, which leads to the use of "face" to refer to anything on a window.

5.4 Facet

Any style on a window can have an assortment of attributes. For example, a button can have a color, a field can have a length. The words that indicate these attributes are called "facets." So the coding of "button red" means that on the window there is a red button, or, a button "style" with a color facet of "red."

5.5 Variable

Any style on a window can have a name attached so that you can refer to it in the code. This name is called a "variable." In the earlier example of "FIELD-1: field 100" there is a field "style" with a length "facet" of 100 pixels, named for later reference with the "variable" of "FIELD-1."

5.6 Styledef

It is possible (a bit more advanced topic) to define custom styles. For example, there is syntax to define a red button so that instead of always having to code "button red" you could code a shorthand for that. This syntax is called a "styledef" and is a topic deferred to the advanced section of VID usage.

A nomenclature change can be a nuisance. In the beginning, just remember that the things in a window are called "styles" and their attributes are called "facets."

6. Overview of all styles (the things you put on windows)

This is just an overview

This section is just an overview of all the items you can put on a window. It is not the details. The details are later.

This section shows, by example, all the styles that are available. In other words, these are all the things you can put into a window. They are presented in code examples for you to try. These are not functioning examples except for the fact that the code does run and produce a window. The purpose of these examples is to inform you of all the things (styles) that are available for constructing a GUI interface. There is only enough other code to make the window work (that is, appear on the screen).

Might want to adjust your test harness...

In the example below, and in all following examples, the "view layout [" and the ending square bracket at the end of the layout are omitted. This saves just two lines of code per example, but over hundred of examples this is hundreds of lines. You might want to adjust your test script to include those lines, so that you can paste the following examples between those lines.

To assist in running the examples, you could copy and save the following program. Then, when you want to test one of the examples, you still would copy it to the clipboard, but instead of pasting it into your test harness, you would just double-click the following program which you saved somewhere. What this program does is "load" the clipboard, which turns the clipboard contents into a REBOL block. Then it feeds that block to the "layout" function and "view"s the resulting window.

REBOL [
    Title: "Run clipboard VID example"
]
VID-CLIP: load clipboard://
view center-face layout VID-CLIP

Some of the examples below require code outside the layout code. For those, you will have to paste them under just a REBOL header and not inside a layout block. To assist in running those, you could save the following program to a name of your choosing, and then copy the code samples to the clipboard and run the program below. What this program does is, again, load the contents of the clipboard to a block, and then run that block as if it were a REBOL program (which is it). This is an example of how REBOL mixes code and data. The data read from the clipboard is code, the "load" function brings it in as a block, and the "do" function executes it.

REBOL [
    Title: "Run clipboard VID example"
]
VID-CLIP: load clipboard://
do VID-CLIP

The following styles were obtained by interrogating the REBOL intperpreter itself, using a script from Carl's blog. The script is:

foreach [name obj] system/view/vid/vid-styles [
    print [name "-" obj/doc/info]
]

You can paste above code into a script of your own to save for future use, or you can paste it into the REBOL console and run it for immediate results.

Here is a script to make a window using each one of these, so you can see generally what they look like. Remember to paste it between an opening line of "view layout [" and and ending line of "]". Logically, this is one script, however, because there are so many styles and monitor sizes can vary, the code is broken down into several scripts so the generated window doesn't overflow the physical screen size.

Here are styles that are generally used for decorating the window, that is, pictures, labels, text. The first word of each line is the style. What follows each style is enough facets to show what the style looks like.

banner "banner: Banner text"
vh1 "vh1: Video heading 1"
vh2 "vh2: Video heading 2"
vh3 "vh3: Video heading 3"
vh4 "vh4: Video heading 4"
title "title: Title text"
h1 "h1: Document heaading 1"
h2 "h2: Document heaading 2"
h3 "h2: Document heaading 3"
h4 "h4: Document heaading 4"
h5 "h5: Document heaading 5"
label 300 "label: for dark background left aligned"
vlab 300 "vlab: label for dark forms right aligned"
lbl 300 "lbl: label for light backgrounds left aligned"
lab  300 "lab: label for light backgrounds right aligned"
text 300 "text: basic text"
body 300 "body: body text"
vtext 300 "vtext: video text"
txt 300 "txt: document text"
code 300 "code: monospaced text"
tt 300 "tt: typewriter text" 
info 300 "info: non-entry text field" 
return
image http://www.rebol.com/graphics/reb-logo.gif
box 20x20 red
bar
icon
logo-bar 40x100
led
arrow 
progress 300x16

Here are styles that are generally used for entering data or making things happen.

button 
field 100 
area 100x60 
text-list data ["item 1" "item 2"] 
list 200x50 [across text 80 text 80] data [
    ["item 1-1" "item 1-2"] 
    ["item 2-1" "item 2-2"]
]
return
drop-down rows 5 "choice 1" "choice 2" "choice 3" "choice 4" "choice 5"
rotary "choice 1" "choice 2" "choice 3" "choice 4" 
choice "choice 1" "choice 2" "choice 3" "choice 4" 
toggle "on" "off" 
tog "on" "off"
btn
btn-enter
btn-cancel
btn-help 
check
check-mark
check-line
radio
radio-line
scroller 200x16
slider 200x16

Here are two other styles that can be useful. The "key" style doesn't really put anything on the window, but defines a "hot key" so that if you press that key something will happen. The sensor defines an invisible area on the window. If the area is invisible, it is hard to hit it with a mouse. So, you could give it a size of 0x0 and assign a hot key to it, or you could make it really big so you can't miss it.

key #"k" [print "k pressed"]
sensor 100x100 [print "sensor activated"]

There are two styles used for window backgrounds. Here is the one for using a scaled image as a background. We have to include some other items to make the window big enough to show the effect.

backdrop http://www.rebol.com/graphics/reb-logo.gif
box 500x16 red
box 16x500 green

Here is the style for filling the background with a tiled image.

backtile http://www.rebol.com/graphics/reb-logo.gif
box 500x16 red
box 16x500 green

The above items are what you have available to create a visual interface. The above lists are just summaries, to show all the possibilities. Following chapters explain in detail how to use each one.

And finally there is a style for creating sub-layouts within layouts. This is called "panel" and takes a block of VID code as an argument:

view layout [
    panel 300x200 beige [
        button "button 1"
        button "button 2"
    ]
]

7. Facets: The attributes of styles

Why we are explaining facets before styles

A later chapter is going to list all the styles that you can put on a window. For any style, you can specify attributes ("facets" as explained in this chapter), AND, many if not all the facets can apply to multiple styles. That is the reason that facets are explained first. When you get to the explanations of the styles, we can say that a style has a "text facet" and you will know what that means, and we will not have to explain the "text facet" every time it occurs.

As mentioned above, a GUI window is composed of styles of interface objects, the buttons, fields, and so on. In a GUI window, you are going to want to specify attributes of these sytles, that is, things like size, color, font. Those attributes are specified by words called "facets" written after the style name, like "button red" for a red button. In the chapter that describes styles in detail, it will be necessary to indicate which facets can be used with a given style. To make that easier, this chapter explains all the facets. This is similar to the railroad diagrams used to describe programming languages. In other words, you might have something like:

---> button ---> (color-facet) ---
             |------------------^

which would indicate that the word "button" could be followed by an optional "color-facet" whatever that was. The "color-facet" would be defined elsewhere, so that its definition would not have to be repeated for every situation where a colof-facet was called for. This chapter defines all those facets, and these descriptions will be referred to in later chapters where relevant.

Two things complicate the following definitions. Number one, it is hard to use the traditional angle brackets in an html document. Number two, the traditional square brackets used in documentation to indicate optional items can't be used clearly in REBOL documentation because the square brackets are part of REBOL syntax. In addition, parentheses can be used in certain VID situations to indicate REBOL code that is to be executed. What we will do is use parentheses to indicate things that are defined elsewhere, and if the item being documented uses parentheses as part of its syntax, we will expalain that on a case-by-case basis.

7.1 Size facet: Specifying the size of a style

Syntax: (horizontal-dimension)x(vertical-dimension)

Here is an example of our documentation difficulties and how we are resolving them. The above specification is not quite accurate. The vertical dimension is optional, and if omitted, will be calculated automatically or given a default value. So a more correct specification would be

(horizontal-dimenstion) [ x (vertical-dimension) ]

which indicates that the vertical dimenstion is optional. But we don't want to use the square brackets because they have meaning in REBOL. We could do this:

---> (horizontal-dimension) --|------------------------------>
                              |--> x (vertical-dimension --|

but the problem with this method is the effort to draw it. Also, it must be confessed, there is a bit of mental effort in breaking down things into the railroad diagram entities in the most useful way. The primary goal of documentation is to make something people can understand and use, and not necessarily to perform an exercise in logical purity, unless the logical purity is necessary for adequate understanding.

The size facet is used in a number of places, such as button size, field length, window dimenstions. For example:

box 50x50

7.2 Text facet: Putting text on a style

Syntax: " (any-text) " or { (any-text) }

The text facet is what you use to specify the text of a heading, or a text field, or the label on a button, any text that appears anywhere. You just type the text after the style name. Optionally, you can use a word as a text facet if that word refers to text from elsewhere. For example:

text "Sample text in a text area"
text {This is a longer multi-line text item.  REBOL will make
    the required amount of space for it.}

You also could have coded something like

text text-from-elsewhere

where text-from-elsewhere would be coded elsewhere in the program, maybe like this:

text-from-elsewhere: "Text to display on window"

You will see later that the text facet can be used in a surprising number of places besides text fields and button labels.

7.3 Color facet: Coloring a style

Syntax: (red-value).(green-value).(blue-value) or (color-word)

The color facet is used to color many things. The red-value, green-value, and blue-value are numbers from 0 to 255 indicating the amount of each color. You also may use a predefined color. the colors are (presented in an example of colored boxes):

across
box 90x50 black      "black"
box 90x50 coal       "coal"
box 90x50 gray       "gray"
box 90x50 pewter     "pewter"
box 90x50 silver     "silver"
box 90x50 snow       "snow"
box 90x50 white      "white"
box 90x50 blue       "blue"
box 90x50 green      "green"
box 90x50 cyan       "cyan"
return
box 90x50 red        "red"
box 90x50 yellow     "yellow"
box 90x50 magenta    "magenta"
box 90x50 navy       "navy"
box 90x50 leaf       "leaf"
box 90x50 teal       "teal"
box 90x50 maroon     "maroon"
box 90x50 olive      "olive"
box 90x50 purple     "purple"
box 90x50 orange     "orange"
return
box 90x50 oldrab     "oldrab" 
box 90x50 brown      "brown"  
box 90x50 coffee     "coffee" 
box 90x50 sienna     "sienna" 
box 90x50 crimson    "crimson"
box 90x50 violet     "violet" 
box 90x50 brick      "brick"  
box 90x50 pink       "pink"   
box 90x50 gold       "gold"   
box 90x50 tan        "tan"    
return
box 90x50 beige      "beige"  
box 90x50 ivory      "ivory"  
box 90x50 linen      "linen"  
box 90x50 khaki      "khaki"  
box 90x50 rebolor    "rebolor"
box 90x50 wheat      "wheat"  
box 90x50 aqua       "aqua"   
box 90x50 forest     "forest" 
box 90x50 water      "water"  
box 90x50 papaya     "papaya" 
return
box 90x50 sky        "sky"    
box 90x50 mint       "mint"   
box 90x50 reblue     "reblue" 
box 90x50 base-color "base-color"        
box 90x50 yello      "yello"  
return

If you don't like the predefined colors and want to create your own with a color tuple, you can, at the REBOL console, enter the function "request-color" to bring up a color requestor dialog window. You operate three sliders for red, green, and blue, click the OK button, and get back the color tuple for the color you created.

7.4 Image facet: Putting a picture on a style

Syntax: (Name-of-image-file) | (url-address-of-image-file) | (word-referring-to-image-file)

The image facet is how you get an image onto a style on a window. In the most obvious situation, you have

image %picture.jpg

In the above code, the word "image" is a style, namely, the "image" style, and "%picture.jpg" is the image facet applied to that style, in other words, an image that will be placed on that image style. That might sound a bit confusing until you see

button "test" %picture.jpg

in which case you will get a button with the text "test" printed on it AND the picture in the file picture.jpg as a background on the button. The image facet can be applied to some surprising things.

7.5 Action facet: Making a style do something

Syntax: [ (REBOL-code) ]

The action facet is a block, written after the style name, containing REBOL code that is executed when you click on the style, or maybe, in the case of the field style, press the "enter" key. For example:

button "Click" [print "Button pressed"]

In addition, you may provide a second action facet to be executed on a right click:

button "Click" [print "left"] [print "right"]

The code in the action facet can be long. It might be more helpful to put a function name in the block, and then define that function elsewhere. It is not required, but it will make the window layout cleaner.

7.6 Character facet: Creating a shortcut key

Syntax: REBOL character code

A REBOL characer code is a pound sign followed by a character in quotes, as in: #"t" for the letter "t."

The character facet is a way to specify a single keystroke that will be detected and interpreted as a mouse click. It is like the familiar shortcut keys in many window systems. For example:

button "test" #"t" [print "left"]

7.7 Font facet block: Controlling font appearance

Syntax: font [ (font-attributes) ]

(font-attributes) is a block of word-value pairs. The word is one of the items below with a colon after it. The value depends on the word, as follows:

name: font-serif | fons-sans-serif | font-fixed

size: (integer)

style: none | [ bold | italic | underline ]

color: (color-tuple) | (color-word)

align: none | 'left | 'right | 'center

valign: 'top | 'bottom | 'middle

offset: (pair)

space: (pair)

shadow: none | (pair)

Explanation and default values:

name: This is a system-independent font family chosen from the values shown. The default is font-sans-serif.

size: This is a point size value. Default is 12.

style: If used, must be one of the indicated values. The values are specified in a block, however, if you want to use just one, like bold, you may specify it without the square brackets but you must put the single quote in front to make it a REBOl work, as in: style: 'bold. Default is none.

color: You may make your own color with a color tuple, or use a pre-defined REBOL color word. Default is black.

align: This controls the horizontal alignment of the text within the size of the are where the text is placed. Note that the value must be a REBOL word as indicated by the single quote in front of the left/right/middle choice. Default is left.

valign: This controls the vertical alignment, similar to the horizontal alignment controlled by "align." Default is top.

offset: It appears that this is supposed to be for positioning text with more control that just the align and valign options. However, it does not seem to work.

space: This controls extra space, in pixels between letters, or between lines of multi-line text. Default is 0x0. Values my be negative to compress text.

shadow: This creates a shadow effect on the text, as if a light were shining on it from some direction. Positive values project to the right and negative to the left. For the vertical direction, negative projects up and positive down. An example follows.

Example:

text 600x100 "This is some test text set with all default values" 
    font [
        name: font-sans-serif
        size: 12
        style: none
        color: black
        align: none
        valign: none
        offset: 2x2
        space: 0x0
        shadow: none
    ]
text 600x100 "This is text with all values non-defualt" 
    font [
        name: font-serif
        size: 24
        style: [bold italic underline]
        color: red
        align: 'center
        valign: 'middle
        offset: 10x10
        space: 4x4
        shadow: 4x4
    ]

Here is a special example to show the shadow only because of the number of combinations.

text "No shadow" font [size: 40 shadow: none]
text "Right only" font [size: 40 shadow: 6x0 ]
text "Left only" font [size: 40 shadow: -6x0 ]
text "Up only" font [size: 40 shadow: 0x-6 ]
text "Down only " font [size: 40 shadow: 0x6 ]
text "Right and up" font [size: 40 shadow: 6x-6 ]
text "Right and down" font [size: 40 shadow: 6x6 ]
text "Left and up" font [size: 40 shadow: -6x-6 ]
text "Left and down" font [size: 40 shadow: -6x6 ]

A note about the font facet concept: It might be best not to think too hard about this. A "text" style is a graphical item on the window. The actual value of the text is the "facet." The "font" facet is called a "facet," but if you follow out that definition and consider that the "font" facet is applying to the actual text, which itself is a "facet" of the text "style," then you have the "font" facet being a facet of a facet. Accept that desinging a language probably is not an easy job when you get down to the actual details, and that some logical purity might have slipped through the cracks.

7.8 Edge facet block: Framing a style

Syntax: edge [ (edge-attributes) ]

(edge-attributes) is a block of work-value pairs. The word is one of the items with a colon after it. The value depends on the word, as follows:

size: (pair)

color: (color-tuple) | (color-word)

effect: 'bevel | 'ibevel | 'bezel | 'ibezel | 'nubs

Explanation and default values:

size: A pair, in pixels. The x value is the thickness of the vertical edges, and the y value of the horizontal.

color: Standard color tuple or word, for the color of the edge.

effect: These are shown in the following examples. Note that the official VID documentation says the "effect"can be a block, but in actual practice that does not work, and you must use the REBOL word to describe the effect.

Example:

box 100x60 "bevel" edge [size: 10x10 color: red effect: [bevel]] 
box 100x60 "ibevel" edge [size: 10x10 color: red effect: [ibevel]] 
box 100x60 "bezel" edge [size: 10x10 color: red effect: [bezel]] 
box 100x60 "ibezel" edge [size: 10x10 color: red effect: [ibezel]] 
box 100x60 "nubs" edge [size: 10x10 color: red effect: [nubs]] 
return
box 100x60 "bevel" edge [size: 10x10 color: green effect: 'bevel]
box 100x60 "ibevel" edge [size: 10x10 color: green effect: 'ibevel]
box 100x60 "bezel" edge [size: 10x10 color: green effect: 'bezel]
box 100x60 "ibezel" edge [size: 10x10 color: green effect: 'ibezel]
box 100x60 "nubs" edge [size: 10x10 color: green effect: 'nubs]

7.9 Para facet block: Formatting text paragraphs

Syntax: para [ (paragraph-attributes) ]

(paragraph-attributes) is a block of word-value pairs. The word is one of the items with a colon after it. The value depends on the word, as follows:

origin: (pair)

margin: (pair)

indent: (pair)

scroll: (pair)

tabs: (integer) | (block of integers)

wrap?: true | false

Explanation and default values:

origin: An offset in pixels from the upper left corner of the style that contains the text. Default is 2x2.

margin: This is an offset for the right and the bottom of the text in a face (a style). It is like a "buffer zone" to keep the text a certain number of pixels from the right and the bottom of the face. It is not obvious of the text is too big for what holds it, but an example below shows how it works. Default is 2x2.

indent: The x part of the pair is the offset of the first line of a paragraph, that is, the number if pixels by which the first line is indented. The y part is the number of pixels between paragraphs. Default is 0x0.

scroll: An offset, left-right and up-down, of the text in within the style. This attribute usually is change dynamically to control scrolling of text in a style. You change the x or y value, and then re-display the style, and the text is moved. Default is 0x0.

tabs: This is a single number, or a block of numbers, for setting tab stops inside a style that can contain text. Default is 40 for tab stops every 40 pixels.

wrap?: This is a true/false value that controls whether or not text in a face (style) will be wrapped, or just run off to the right. Default is false.

Example follows. Note that this example includes the "view layout" line because of the need for some test text. This text is just something copied from an internet news story. There are two paragraphs, separated by pressing the "enter" key. If the "enter" key doesn't make it through all the layers of the internet, you might have to type it manually after "U.S Army Recruiting Command." It is possible that you also will have to re-type the text to eliminate line-feeds after all lines except the one where you want the paragraphs to separate. Otherwise, every line of text will be its own paragrpah.

TEST-TEXT: {In about five years, so many young Americans will be grossly 
overweight that the military will be unable to recruit enough qualified 
soldiers. That alarming forecast comes from Maj, Gen. Allen Batschelet, 
who is in charge of U.S. Army Recruiting Command.
Of the 195,000 young men and women who signed up to fight for our country, 
only 72,000 qualified. Some didn't make the cut because they had a 
criminal background, or a lack of education, or too many tattoos. 
But a full 10% didn't qualify because they were overweight.}
view layout [
area 100x200 TEST-TEXT
area 100x200 TEST-TEXT para [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    scroll: 0x0
    tabs: 40
    wrap?: false
]
area 100x200 TEST-TEXT para [
    origin: 20x20
    wrap?: true
]
return
area 300x200 TEST-TEXT para [
margin 20x20
indent: 20x20
wrap?: true 
]  
area 300x200 TEST-TEXT para [
indent: 20x20
wrap?: true
scroll: -30x-30 
] 
]

Here is an example to show just the tab attribute. In the string in the code, the words in the string are separated by a single tab. If the tab character didn't make it through all the layers to get to your example, you might have to re-type the TEST-TEXT line and place a single tab after aatab, bbtab, and cctab. That is done as you might imagine, by pressing the "tab" key on the keyboard. Note that this example includes the "view layout" line because there is a line of code outside of the layout, needed to create the example.

TEST-TEXT: {aatab   bbtab   cctab} ;; single tab between words
view layout [
area 700x100 TEST-TEXT para [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    scroll: 0x0
    tabs: 100
    wrap?: false
]
area 700x100 TEST-TEXT para [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    scroll: 0x0
    tabs: [150 350 550]
    wrap?: false
]
]

Here is an example of just the margin. As above, you almost certainly will have to re-type the text so that it is two long lines with a line feed after "U.S Army Recruiting Command." What you will see then will be two text areas with two paragraphs of text. The margin feature will not be obvious because the text is too big for the boxes, but, if you put the mouse pointer into each box and use the down arrow to move to the bottom of each area, you will see the 20-pixel buffer at the bottom of the second box.

TEST-TEXT: {In about five years, so many young Americans will
be grossly overweight that the military will be unable to recruit 
enough qualified soldiers. That alar    ming forecast comes from 
Maj, Gen. Allen Batschelet, who is in charge 
of U.S. Army Recruiting Command.
Of the 195,000 young men and women who signed up to fight for our 
country, only 72,000 qualified. Some didn't make the cut because 
they had a criminal background, or a lack of education, or too 
many tattoos. But a full 10% didn't qualify because they were 
overweight.}
view layout [
area 300x200 TEST-TEXT para [
    origin: 2x2
    margin: 2x2
    indent: 20x20
    scroll: 0x0
    tabs: 40
    wrap?: true 
]
area 300x200 TEST-TEXT para [
    origin: 2x2
    margin: 20x20
    indent: 20x20
    scroll: 0x0
    tabs: 40
    wrap?: true 
]
]

7.10 Feel facet block: Advanced look and feel

Advanced "look and feel" operations are a bit outside the scope of this document, which is intended to cover enough of the basic VID features to do useful things. REBOL has the ability to do many fancier things, like detecting mouse-overs, responding to timers for animation, having windows modify themselves before being displayed. Someone interested in that should read:

REBOL/View Graphic System Reference

How to Handle User Interface Events

In summary, the "feel" facet will be the keyword "feel" followed by a block that contains functions for doing advanced things. These functions are activated at various times in the processing of a window.

7.11 Effect facet block: Decorating a backdrop

Syntax: effect [ (effect-attributes) ]

(effect-attributes) are words that indicate some processing to be done on the image you are "effecting." This image can be the backdrop of a whole window, or the backdrop on some item, like a button. The block can contain any number of words, and the effects are applied in order. Some words require arguments, as indicated.

Because there are so many words, and any number can be used at one time, the number of permutations is huge. So examples of all combinations is not reasonable possible. In addition, the words are documented in the REBOL/View VID Developer's Guide linked at the front of this document, so reproducing that information here is not productive unless we have any additional information to present. The words are summarized below. Effects are not necessary to provide functionality in your program; they are for appearance. You could experiment at your leisure while still writing productive REBOL programs.

As an idea for experimenting, find some picture for testing and put it into your test area. Then make a test script like this:

size 600x480
backdrop %TestImage.jpg
    effect [
        aspect
]

The code above creates a window 600 by 480 pixels and puts your picture into the background. The single specified effect, "aspect," preserves the "aspect ratio" so that the picture looks correct. When you have this test script ready, add more effect words after (or in place of) "aspect" and see what happens.

(effect-attributes) in summary: (Note that these are not name-value pairs like in, for example, the para effect. The colon in the examples below are just like you would us a colon normally and are not part of the VID syntax.)

fit: Expand or shrink the image to fit the face.

aspect: Expand or shrink the image to fit, and preserve aspect ratio.

extend (offset-pair) (distance-pair): Extend an image by starting it at the location indicated by the offset-pair and extending it a number of pixels in the x and y directions as indicated by the distance-pair.

tile: Tile the image in it the face to which it is applied.

tile-view:

clip: Clip the image to fit the face.

crop (offset-to-start-pair) (size-of-clip-pair): Crop the image by starting at an offset indicated by the first pair, and taking a cropping of a size indicated by the second pair.

flip (direction-pair): Flip the image as indicated by the direction-pair. The direction-pair can be 1x0 for horizontal, 0x1 for vertical, 1x1 for both.

rotate (degrees): Rotate 0, 90, 180, or 270 degrees as indicated by the supplied number of degrees.

reflect (direction-pair): Reflect the image around an axis through the middle of the image, either a horizontal axis or a vertical. The direction-pair can be 1x0, 0x1, or 1x1.

invert: Reverse the colors of the image, like making it into a negative.

luma (integer): Lighten or darken the image based on the integer, which may be positive or negative.

contrast (integer): Increase or decrease the contrast.

tint (integer): Change the tint based on the integer.

grayscale: Make the image black and white.

colorize (color-tuple):

multiply (integer) | (color-tuple) | (image-file-name):

difference (image-file-name):

blur:

sharpen:

emboss:

gradient (pair) (color-tuple) (color-tuple):

gradcol (pair) (color-tuple) (color-tuple):

gradmul (pair) (color-tuple) (color-tuple):

key (integer) | (color-tuple):

shadow (integer) | (color-tuple):

arrow (color-tuple) | (color-word): Generates a big arrow on the underlying face.

cross (color-tuple) | (color-word): Generates a big cross on the underlying face.

oval (color-tuple) | (color-word): Generates a big oval on the underlying face.

tab:

grid (spacing-pair) (offset-pair) (thickness-pair) (color-tuple): This puts a grid on the face. The (spacing-pair) is the number of pixels between lines. The (offset-pair) is an offset from the top left corner, if you don't want the top left grid rectangle to start at the top left pixel. The grid, however, will go all the way to the edge. The (thickness-pair) is the thickness of the lines in pixels. The (color-tuple) is the color of the grid lines (which might not work).

draw [ (draw-dialect-block) ]: This allows you to draw custom stuff on the face. There is a special REBOL dialect for drawing that is beyond the scope of this document. Check this link: REBOL/View Draw Dialect 1.3

7.12 Rate facet: Timing things

Syntax: rate (seconds) | (elapsed-time)

seconds: An integer for a number of seconds.

elapsed-time: A time (hh:mm:ss) to wait between time interrupts.

It appears that the "rate" can be applied to any style, and a timer interrupt will take place according to the time specified. Now, what to do with that interrupt. This is a case where the "feel" facet can be used. The "engage" option in the "feel" facet catches the timer interrupt. This seems to be a somewhat common operation in REBOL. Here is an example of how it works.

box 200x200 red rate 00:00:01
    feel [
        engage: [
            print "interrupted"
        ]
    ]

As for how to use it in a real situation, the "engage" function can be quite involved. This operation is at the heart of some of the clock demos available on the internet. If you set a rate of 1, meaning one second, then, the engage function can, at that time, display the current time. What this accomplishes is to refresh a display of the current time every second, giving the appearance of a running clock.

7.13 Data facet: Loading data

Syntax: data [ (data-block) ]

The (data-block) is a block of whatever data is appropriate for the stle of face. Data is not a concept that makes sense for all styles. However, it appears you can load the data facet for all styles, it just doesn't have any use outside of a style where it does have use. A common use is the text list, as follows: (Don't paste this inside a layout block as you have done for other samples.)

LIST-DATA: [
    "text line 1"
    "text line 2"
    "text line 3"
]
view layout [
    across
    text-list 200x300
        data LIST-DATA
]

7.14 Pane facet: Making sub-layouts

There is a special style, and a special facet to go with it, for making layouts within layouts. The style is "panel" and the facet is "pane," although one does not use the keyword "pane." Instead, one supplies a block of VID code as an argument after the "panel" keyword, as shown below:

BUTTON-PANE: [
    size 196x396
    below
    button "Button 1" [print "Button 1"]
    button "button 2" [print "Button 2"]
    button "button 3" [print "Button 3"]
    button "button 4" [print "Button 4"]
    button "button 5" [print "Button 5"]
    button "button 6" [print "Button 6"]
    button "button 7" [print "Button 7"]
    button "button 8" [print "Button 8"]
    button "button 9" [print "Button 9"]
]
view layout [
    across
    TEXT-INPUT: area 200x400
    CONTROL-BUTTONS: panel 200x400 beige 
        BUTTON-PANE     
        edge [size: 4x4 color: red effect: 'bevel]
    return
    button "Button 0" [print "Button 0"]
]

8. Positioning items (styles), and other attributes

Why we are explaining positioning here

As with facets, we are explaining how to position things on windows before we explain what you actually CAN position on a window. The reason for this is so that when we make examples of the various styles, any positioning keywords we might need to make the examples work will be familiar.

If you start writing the VID code, placing items on the window without caring where they go, they will go in a default order which is top to bottom, on into eternity. To override that default placement, you use various keywords, explained below.

8.1 Below: The default positioning

If you specify the keyword "below" in the VID code, then from that point on, a new style will be placed below the previously-defined one.

below
button "button 1"
button "button 2"
button "button 3"

You may leave off the word "below" if you like because that is the default.

8.2 Return: Starting a new row (or column)

If you keep adding items to a window you will run out of room, so to go back to the top, use the word "return."

below
button "button 1"
button "button 2"
button "button 3"
return
button "button 4"
button "button 5"
button "button 6"

8.3 Across: Left-to-right positioning

If you prefer to think left-to-right first, you can use the word "across" to make things go that way. With "across," the "return" keyword will start a new row instead of a new column.

across 
button "button 1"
button "button 2"
button "button 3"
return
button "button 4"
button "button 5"
button "button 6"

8.4 At: Absolute positioning

If you don't want to take the automatic positioning, you can specify exactly where to put things with the "at" keyword. In the following example, we will place 100-pixel boxes every 100 pixels.

at 0x0     box  100x100 red
at 100x0   box  100x100 green
at 200x0   box  100x100 blue
at 0x100   box  100x100 black
at 100x100 box  100x100 white
at 200x100 box  100x100 beige 
at 200x100 text 100 "text on top"

Note that one could use the "at" keyword to place one style on top of another.

8.5 Tab: Lining things up

One way to line up things is with the "tab" keyword. This will advance the positioning to the next tab stop. Where are the tab stops? They are at default locations, and can be set with the "tabs" keyword.

across
label "Field 1"
tab
FIELD-1: field 200
return
label "Need longer label"
tab
FIELD-1: field 300

8.6 Tabs: Setting tab stops

In the above example, the "tab" keyword did not line up the fields because the tab stops were too close together. You can specify tab stops with the "tabs" keyword. If you want just a standard number of pixels between each tab stop, you specify that number as an integer. If you want more specific tab stops, you can provide a block of integers. Tabs are either horizontal tabs (as you probably would think of them) if the automatic positioning is set to "across," or vertical tabs if the automatic positioning is set to "below."

tabs 100 
across
label "Field 1"
tab
FIELD-1: field 200
return
label "Need longer label"
tab
FIELD-1: field 300

Notice that the above example is the same as the prior example except that the number of pixels between tab stops is large enough so that the single "tab" keyword goes out to a tab stop that is the same for both fields.

8.7 Space: Space between styles

There is a default number of pixels between items on a window, which can be change with the "space" keyword. The attribute of "space" can be a pair to adjust horizontal and vertical positioning, or it can be just an integer in which case it will apply in the direction currently in use for automatic placement (across or below).

across
button "button 1"
button "button 2"
return
button "button 3"
button "button 4"
return 
space 50x50
button "button 5"
button "button 6"
return
button "button 7"
button "button 8"

8.8 Pad: One-time spacing

You can insert some space between one style and the next (horizonatlly or vertically) with the "pad" keyword followed by either a pair (for both directions) or an integer (for whatever direction you are going, across or below).

across
button "button 1"
pad 100x100
button "button 2"
return
button "button 3"
button "button 4"

8.9 Indent: Horizontal spacing only

The "indent" keyword adds horizontal space.

across
button "button 1"
indent 100
button "button 2"
return 
button "button 3"
button "button 4"

8.10 Guide: Window margins

The "guide" keyword followed by a pair can be used to set a margin inside a window, sort of like margins on a page.

across
guide 100x100
button "button 1"
button "button 2"
button "button 3"
return
button "button 4"
button "button 5"
button "button 6"
return
below
button "button 7"
button "button 8"
button "button 9"
return
button "button 10"
button "button 11"
button "button 12"

This example shows (to some, at least) how it can be easy to get confused with the various placement options. If you are trying to make a basic functional layout, it might be best to take a basic boring approach to doing it. Specify "across," maybe set some tab stops, and then start laying out a window left-to-right top-to-bottom, and don't do fancy things unless you must. Realize that there are no perfect choices, only choices and trade-offs, and if you want to be fancy you might have to suffer mentally with some complexity.

8.11 Size: Specifying the window size

When you start specifying things you want on a window, the final window size will be whatever it takes to hold whatever you specified. If you want to make sure the final window is a certain size, you can specify that.

size 600x480
across
button "button 1"
button "button 2"
return
button "button 3"
button "button 4"

8.12 Origin: The window starting point

When you start specifying items in a window, they will start near the top left corner, 20x20 pixels in. That origin point can be changed. Note that this is not the place on the screen where the window is displayed, but rather the place inside the window where the styles are displayed.

size 600x480
origin 100x100
across
button "button 1"
button "button 2"
return
button "button 3"
button "button 4"

8.13 Backcolor: Coloring the whole window

VID has a default gray color for windows. Than can be controlled with the "backcolor" keyword.

backcolor tan   
label "Data field"
field 200 
button "button 1"

9. Styles: The things you put on windows

This chapter explains all the styles of interface objects, "styles" for short, that you can put in windows. That means the fields, buttons, check-boxes, and such that comprise a GUI. We are trying to make this description as complete and correct as possible so you could use it as a reference manual for a "target" language for writing programs. In other words, if you want to write a program to do something, you could look at this document and see exactly what VID can do, and how to make it do it, and decide if you want to use VID.

If your investigation of REBOL is starting here...

Remember that this document does not describe REBOL. It describes that part of REBOL that is used for making windows. The target audience of this document is someone who knows REBOL but needs a clear idea of exactly what can be accomplished with VID. The non-GUI part of REBOL is described in great detail on the REBOL web site. Attention should be directed to the documentation mentioned at this start of this document.

This chapter will contain a section for each style of interface object that can be put on a GUI window. For each style, we will try to provide:

Because of the way REBOL is written, all styles of interface objects are like instances of a master interface object, a "face." That means that potentially all of the facets could apply to any style of a face. In other words, you could put an image on a button, you can make some action happen when you enter data in a field; things that might make sense. As much as possible, all possible combinations will be noted.

An exception to the principle of complete examples

We are not going to try to explain whether or not the "effect" facet is available for a style, unless it is something really commonly used. The reason for that is that there are so many combinations of effects. Take as a given that you probably can apply an effect to any style if it seems to make sense, and then try it if you like. There are just too many combinations to try to document all combinations for all styles. The effects seem to be mainly for decoration, and you don't need decoration to make a functioning program.

Another facet we will not explain is the "feel" facet. Because this facet is used for things like detecting window events, you should assume that it can be applied to anything on a window. Then, if you think you want this facet, put it on the style and use the REBOL documentation to create the feel, as explained in the documentation noted above under the "feel" definition. Once again, this area is too large to provide documentation for every combination.

At some point it might be helpful to perform the following exercise. Make a folder somewhere; doesn't matter where. Copy the following script to an editor, save it, and run it:

REBOL [
    Title: "Extract code for all VID styles"
]

;; [---------------------------------------------------------------------------]
;; [ This is a little utility program for extracting the code behind all the   ]
;; [ VID styles and writing the code for each style into a text file named     ]
;; [ <style-name>.txt.  These files then can be examined with a text editor.   ]
;; [---------------------------------------------------------------------------]

CODE-FILENAME: none  ;; will generate name based on style word (dot-txt) 

CODE-DIR: request-dir
if not CODE-DIR [
    alert "No folder selected for output"
    quit
]
change-dir CODE-DIR
foreach [STYLE-WORD STYLE-CODE] svv/vid-styles [
    CODE-FILENAME: copy ""
    CODE-FILENAME: to-file rejoin [
        to-string STYLE-WORD
        ".txt"
    ]
    write CODE-FILENAME STYLE-CODE
]
alert rejoin [
    "Code files created in " 
    CODE-DIR
]

When you run it, it will ask for a folder. Select the one you created. You will get an alert box indicating that the program is done, and in that folder you will see the source code for all the styles, one style per file, with the file name being the style name. It appears that a lot of REBOL is written in REBOL. If you stare at these file enough, you could start to get a vague idea of how things work. If you are handy with programming, you might get a clearer idea.

9.1 Banner

The banner style is generally used for some big text like a window heading.

Commonly-used facets:

banner "Default window heading text"
banner "Non-shadowed text" font [shadow: none size: 36]
banner "Banner colored by color word" black 
banner "Text can be clickable" [print "left-clicked"] [print "right-clicked"]
banner "Banner with surrounding space" 500x100

9.2 Title

The title style is another option for window text.

Commonly-used facets:

title "Default title text"
title "Titles can be made small" font [size: 12]
title "And clickable" [print "left-clicked"] [print "right-clicked"]

9.3 Vh1 through vh4

The video heading styles are for some variations of the kinds of text available for dressing up a window.

Commonly-used facets:

vh1 "Video heading 1 default appearance"
vh2 "Video heading 1 default appearance"
vh3 "Video heading 1 default appearance"
vh4 "Video heading 1 default appearance"
vh4 "vh4 can be big" font [size: 36 shadow: none]
vh1 "vh1 can be small" font [size: 12 shadow: none]
vh2 "All can be clicked" [print "left-clicked"] [print "right-clicked"] 
vh3 "And of course colored" red

9.4 H1 through h4

The document heading styles are for some variations of the kinds of text available for dressing up a window.

Commonly-used facets:

h1 "Document heading 1 default appearance"
h2 "Document heading 1 default appearance"
h3 "Document heading 1 default appearance"
h4 "Document heading 1 default appearance"
h4 "h4 can be big" font [size: 36 shadow: none]
h1 "h1 can be small" font [size: 12 shadow: none]
h2 "All can be clicked" [print "left-clicked"] [print "right-clicked"] 
h3 "And of course colored" red

9.5 Label, vlab, lbl, lab

These styles are different looks for labels for things, usually fields. The label and vlab styles are left- and right- justified labels for dark backgrounds. The lbl and lab styles are for left- and right- justified labels on light backgrounds.

Commonly-used facets:

label "Default label style"
vlab "Default vlab style"
lbl "Default lbl style"
lab "Default lab style" 
label "Longer labels need sizes" 500
vlab "vlab is right justified" 500 font [size: 16]
lbl "Actions are allowed" 500 [print "left-clicked"] [print "right-clicked"] 
lab "lab is right justified also" 500 
label "label styles can be colored" 500 red

9.6 Text, body, vtext, txt, code, tt

These styles are used for putting text on the window. The styles that are not "text" are basically "text" styles with some pre-defined features for common uses.

The key word "as-is" can be used if a text style is big enough to hold multiple lines, and you have multiple lines each terminated by a line-feed. The "as-is" will make those line breaks happen in the text area.

Commonly-used facets:

text 500 "Default text style"
body 500 "Default body style"
vtext 500 "Default vtext style" 
txt 500 "Default txt style"
code 500 "Default code style"
tt 500 "Default tt style"
text 500x40 "The text styles can be colored" blue
body 500x40 "Fonts can be controlled" font [size: 24]
vtext 500x40 "Text can be clickable" [print "left-clicked"] [print "right-clicked"] 
txt 500x40 "Space on window can be set"

9.7 Info

This style is used for text in a field-like border that makes it look like a grayed-out entry field, which it is not. It is used for displaying text.

Commonly-used facets:

info 500 "Informational text in a field-like box."
info 500 red "Color facet will color the field, not the text."
info 500x40 "Font size can be controlled" font [size: 24]
info 500 "info field can have only left-click actions"
     [print "left-clicked"] [print "right-click does not work"]

9.8 Image

This style puts an image on a window. The source of the image is specified by the image "facet," which is a file name or a url that points to an image file. You may use jpeg, bmp, or gif images.

Commonly-used facets:

image 100x100 http://www.rebol.com/graphics/reb-logo.gif red
    "test" font [color: blue]
    [print "left-clicked"] [print "right-clicked"]

There is a bit of definitial fuzziness here that might cause confusion. It might be best not to expect definitional purity, but to accept what works. A "text" style is the word "text" followed by the text "facet" which is the actual text. The "font" facet is another facet which can be applied to the "text" style to specify attributes of the text. So really, the "font" facet is a facet of another facet, namely, the text facet, and not a facet of the "text" style. This shows up more clearly in the "image" sytle which can have a "text" facet, namely, some text on top of the image, and that "text" facet can have its own "font" facet to change, for example, the color. This might be confusing if you are looking for a clean and rigorous heirarchy where styles have facets. How can an image have a "font" facet since an image is not text? This seems to be related to the idea that all styles are variations of a master "face" or "interface object," and so any style can have all possible facets in theory, but not all facets make sense so not all will work. But a surprising number will. So if you are making a window and wonder if you can put a picture on the window and some red text on top of it, just try it because it might work

9.9 Box

This style puts a box on a window. You can use it for a box to put stuff in, or you can use a colored box like a bar if you make it long and narrow.

Commonly-used facets:

As noted above, because of the design of VID, almost all facets can be applied to almost all styles, so the "rate" facet could be applied to any style besides a box. However, other styles have specific main uses, so the box is a good candidate for applying a timer if you have a need for that kind of operation.

across
box red 600x20 "A long and narrow box can be used as a bar"
return
box green 20x300 
box 200x200 http://www.rebol.com/graphics/reb-logo.gif
box "default" [print "left-clicked"] [print "right-clicked"] 
box 100x100 beige "some text" font [color: black shadow: none]
return 
TIMER: box 300x40 black rate 1 feel [engage: [TIMER/text: to-string now show TIMER]]

9.10 Button

The button style is a clickable button.

Commonly-used facets:

Size, color, and text examples:

button "Default look"
button 200x100 red "Large button, default text"
button 500x100 blue "Long button, larger text"
    font [size: 20 align: 'left shadow: none colors: [255.0.0 0.255.0]]
    edge [size: 4x4 color: green effect: 'bevel]
button 200x60 %TestImage.jpg

Note that you will have to provide your own picture called "TestImage.jpg" to show an image on a button. Note also the "colors" attribute, which is not clearly mentioned in the official documentation. This attribute controls the color of the text when the button is displayed, and the color the text changes to when the mouse moves over the button.

There is another attribute of the font facet that seems to work on Windows and might or might not work on other platforms. If you use the Windows control panel to get into the "fonts" area, you can see a list of fonts, listed by name. Those names can be used to control the font of the button text as shown in this example:

banner "Button font and color test"
button 300x40 "Default"
button 300x40 "Times New Roman" font [
    colors: [255.0.0 0.255.0]  
    name: "Times New Roman"
    size: 20
]
button 300x40 "Bauhaus 93 Regular" font [
    colors: [255.0.0 0.255.0]  
    name: "Bauhaus 93 Regular"
    size: 20
]
button 300x40 "Brush Script MT Italic" font [
    colors: [255.0.0 0.255.0]  
    name: "Brush Script MT Italic"
    size: 20
]
button 300x40 "Haettenschweiler Regular" font [
    colors: [255.0.0 0.255.0]  
    name: "Haettenschweiler Regular"
    size: 20
]
button 300x40 "Showcard Gothic Regular" yellow font [
    colors: [0.255.0 0.0.255]  
    name: "Showcard Gothic Regular"
    size: 20
]
button 300x40 "Quit" [quit]

Action examples:

button "button 1" 
    #"b" 
    [print "Left click"] 
    [print "Right click"]

9.11 Btn, btn-cancel, btn-enter, btn-help

These are buttons with some attributes pre-set, for specific uses. That does not mean that they can't have other facets set, or that they can't have other uses. It means they are pre-made buttons for some uses that are so common you are highly likely to need one of these buttons.

Commonly-used facets:

Examples:

btn "Click" [print "btn left click"] [print "btn right click"]
btn-cancel  [print "btn-cancel left click"] [print "btn-cancel right click"]
btn-enter  [print "btn-enter left click"] [print "btn-enter right click"]
btn-help  [print "btn-help left click"] [print "btn-help right click"]
btn 100
btn-cancel 100 
btn-enter 100 
btn-help 100

Remeber again, that because all styles are descendents of a master interface object, you can specify other facets for these pre-made buttons, but why use a pre-made button if you want to make it into something different?

9.12 Bar

This is a basic horizontal bar, for window decoration.

Commonly-used facets:

Examples:

bar
bar 300
bar 200x30
bar red

9.13 Icon

This style displays a specified image file as a standard-size icon with a caption.

Commonly-used-facets:

Examples (You will have to provide your own image file):

icon %testimage.jpg "test image" 
    [print "Left click"] [print "Right click"] 
icon 100x100 %testimage.jpg "test image" 
icon 150x150 %testimage.jpg "test image" 
    font [color: black size: 20]

Note again. You can control some facets of the icon, but why bother. VID is very handy for quick GUI windows. If you insist on tweaking every little attribute of everything, you are negating some of the benefits of VID.

9.14 logo-bar

This appears to be the REBOL logo in a vertical bar of a fairly fixed size.

Commonly-used facets:

None discovered at this time.

Examples:

logo-bar

9.15 Led

This is a little indicator button. It has a color of either red or green that toggles when left-clicked.

Commonly-used facets:

Examples:

led  [print "Left click small"] 
led 50x50 [print "Left click big"]

9.16 Arrow

This is a pre-defined graphic of an arrow similar to a "play" button or a navigation arrow. The direction of the arrow is specified by the keyword "up," "down," "left," or "right."

Commonly-used facets:

Examples:

arrow 
arrow 50x50
arrow 50x50 left
arrow 50x50 down
arrow 50x50 right
arrow 60x60 red [print "Left click"] [print "Right click"]

9.17 Progress

This is a progress bar like you are used to seeing on many applications.

Commonly-used facets:

The way this is used is that you set the "data" facet to a number from zero to one, and then refresh the progress bar with the "show" function.

Example (This is a complete program, so don't put this inside the "view layout." Put underneath a REBOL header.)

DELAY-COUNTER: 0
DELAY-LIMIT: 3        ;; 6.5 SECONDS
CHECK-DELAY: does [
    DELAY-COUNTER: DELAY-COUNTER + 1
    if DELAY-COUNTER > DELAY-LIMIT [
        DELAY-COUNTER: 0
    ]
]

PROGRESS-COUNT: 0
PROGRESS-END: 100000
PROGRESS-MSG: ""
PROGRESS-RUN: does [
    repeat n PROGRESS-END [
        PROGRESS-COUNT: PROGRESS-COUNT + 1
        CHECK-DELAY
        if (DELAY-COUNTER = 0) [
            PROGRESS-MSG: copy ""
            PROGRESS-MSG: rejoin [
                "Counting at "
                to-string PROGRESS-COUNT
                " of "
                to-string PROGRESS-END
            ]
            set-face PROGRESS-TEXT PROGRESS-MSG
            PROGRESS-BAR/data: n / PROGRESS-END
            show PROGRESS-BAR
        ]
    ]
]

view layout [
    PROGRESS-BAR: progress 620x40 white red
    PROGRESS-TEXT: h1 400
    button "Go" [PROGRESS-RUN]
]

9.18 Field

There is, on the REBOL web site, a very thorough article on how to use fields. It is much more detailed than what you see below.

This is the commonly-used sytle for entering short data items.

Commonly-used facets:

font: This controls the size of the text that is displayed as it is typed into the field.

edge: This allows for borders around the field.

There also are shortcut alignment words, as shown in the example.

Other facets can be used, but don't necessarily make sense. The "action" facet will cause some action to be performed when the "enter" key is pressed or when you move out of the field after entering text into it. You can put an image in the field background. If you want more than a basic field for data entry, do read the article about fields on the REBOL web site. You will note, at the end of the document, promises of more documentation to come, that never seemed to arrive. If you are not a designer, you can do more with fields than you can imagine.

Examples:

field 200 beige red
field 300x40 font [size: 16 style: 'bold]
field "left" left
field "center" center
field "rignt" right
field 200x40 "top" top
field 200x40 "middle" middle
field 200x40 "bottom" bottom

The obvious question that comes up is, how does one get one's hands on the data from a field. This is done be accessing the "text" facet. One assigns a name to a field, and then refers to field-name(slash)text, as shown in the examples below. It seems that in later versions of REBOL, a special function came into being called "get-face," with a matching one called "set-face" for changing the text facet. Note in the examples the use of the "copy" function. This seems to be related to the fact the words in REBOL are not "variables" in the same way they are in other languages. A word "refers" to a value, but does not "contain" it.

Examples:

across
label "FIELD-1"
FIELD-1: field 200 "Initial value"
return
label "FIELD-1-VALUE"
FIELD-1-VALUE: text 200
return
label "FIELD-2"
FIELD-2: field 200
return
button 200 "Show FIELD-1" [
    FIELD-1-VALUE/text: copy FIELD-1/text
    show FIELD-1-VALUE
]
return
button 200 "FIELD-1 := FIELD-2" [
    FIELD-1/text: copy FIELD-2/text
    show FIELD-1
]
return
label "FIELD-3"
FIELD-3: field 200 "Initial value"
return
label "FIELD-3-VALUE"
FIELD-3-VALUE: text 200
return
label "FIELD-4" 
FIELD-4: field 200
return
button 200 "Show FIELD-3" [
    set-face FIELD-3-VALUE copy get-face FIELD-3
]
return
button 200 "FIELD-3 := FIELD-4" [
    set-face FIELD-3 copy get-face FIELD-4
]

9.19 Area

As noted under "field," there is a more thorough document on the REBOL web site about text styles.

This is a style used for entry of larger amounts of text, like paragraphs of it.

Commonly-used facets:

There are two other words used to control text. The key word "wrap" indicates that text will be wrapped inside the area so lines of text don't run out of the area on the right side. The key word "as-is," which is the default state, indicates that the text will not wrap.

Examples (Put this under a REBOL header):

TEST-TEXT-1: {
The obvious question that comes up is, how does one get one's hands
on the data from a field.  This is done be accessing the "text" facet.
One assigns a name to a field, and then refers to field-name(slash)text,
as shown in the examples below.  It seems that in later versions of
REBOL, a special function came into being called "get-face," with a
matching one called "set-face" for changing the text facet.
Note in the examples the use of the "copy" function.  This seems to
be related to the fact the words in REBOL are not "variables" in the
same way they are in other languages.  A word "refers" to a value, 
but does not "contain" it.  
}
view layout [
    label "Default area size"
    AREA-1: area "Default area size"
    label "Another size with default text, not wrapped"
    AREA-2: area 300x200 as-is green black TEST-TEXT-1
    label "Area with wrapped text"
    AREA-3: area 300x200 wrap TEST-TEXT-1 font [size: 16]
]

To get and change the contents of an area, refer to the "text" facet. As with the "field," note the use of the "copy" function. Note also that when setting a value in a large text area, one must set an item called "line-list" as shown in the example below.

TEST-TEXT-1: {
The obvious question that comes up is, how does one get one's hands
on the data from a field.  This is done be accessing the "text" facet.
One assigns a name to a field, and then refers to field-name(slash)text,
as shown in the examples below.  It seems that in later versions of
REBOL, a special function came into being called "get-face," with a
matching one called "set-face" for changing the text facet.
Note in the examples the use of the "copy" function.  This seems to
be related to the fact the words in REBOL are not "variables" in the
same way they are in other languages.  A word "refers" to a value, 
but does not "contain" it.  
}
TEST-TEXT-2: {
Other facets can be used, but don't necessarily make sense.  The "action"
facet will cause some action to be performed when the "enter" key is
pressed or when you move out of the field after entering text into it.
You can put an image in the field background.  If you want more than
a basic field for data entry, do read the article about fields on the
REBOL web site.  You will note, at the end of the document, promises of
more documentation to come, that never seemed to arrive. 
If you are not a designer, you can do more with fields than you can
imagine.  
}
view layout [
    AREA-1: area 500x300 wrap TEST-TEXT-1
    CONTENTS: text 500x300 wrap 
    button "Load text 1" [
        AREA-1/text: TEST-TEXT-1
        AREA-1/line-list: none
        show AREA-1
    ]
    button "Load text 2" [
        AREA-1/text: TEST-TEXT-2
        AREA-1/line-list: none
        show AREA-1
    ]
    button "Show contents" [
        CONTENTS/text: copy AREA-1/text
        CONTENTS/line-list: none
        show CONTENTS 
    ]
]

9.20 Text-list

This is a style used for picking things from a list. The list is a block of single text items.

Commonly-used facets:

Examples:

label "Default text-list size"
text-list
label "Other text-list attributes"
text-list 400x100 green black 
    font [size: 16 name: font-fixed]
    data [
    "Item 01-01"
    "Item 01-02"
    "Item 01-03"
    "Item 01-04"
    "Item 01-05"
    "Item 01-06"
    "Item 01-07"
    "Item 01-08"
    "Item 01-09"
    "Item 01-10"
    "Item 01-11"
    "Item 01-12"
    "Item 01-13"
    "Item 01-14"
    "Item 01-15"
    "Item 01-16"
    "Item 01-17"
    "Item 01-18"
    "Item 01-19"
    "Item 01-20"
]

To load a list, set the "data" refinement and re-show the list. To get the item that is selected from the list, use the "picked" refinement:

LIST-1-DATA: [
    "Item 01-01"
    "Item 01-02"
    "Item 01-03"
    "Item 01-04"
    "Item 01-05"
    "Item 01-06"
    "Item 01-07"
    "Item 01-08"
    "Item 01-09"
    "Item 01-10"
]
LIST-2-DATA: [
    "Item 02-01"
    "Item 02-02"
    "Item 02-03"
    "Item 02-04"
    "Item 02-05"
    "Item 02-06"
    "Item 02-07"
    "Item 02-08"
    "Item 02-09"
    "Item 02-10"
]
view layout [
     label "Default text-list"
     LIST-1: text-list data LIST-1-DATA [
        set-face CONTENTS copy LIST-1/picked
    ]
    CONTENTS: info 200
    button "Load list 1" [
        LIST-1/data: LIST-1-DATA
        show LIST-1
    ]
    button "Load list 2" [
        LIST-1/data: LIST-2-DATA
        show LIST-1
    ]
]

If you are adding to the list as the program runs, then it seems that if you put more data into the list than was there initially, you have to make an adjustment to the built-in scroller. In the following example, Click the "Load list 2" button first, and you will see that the scroller is inoperative. Then click the "Load list 3" button which loads a larger block of data and also has a line of code to adjust the scroller. You should see that the scroller now works. If you go back to loading either "list 1" or "list 2," you will see that the scroller remains operative.

LIST-1-DATA: [
    "Item 01-01"
    "Item 01-02"
    "Item 01-03"
    "Item 01-04"
    "Item 01-05"
    "Item 01-06"
    "Item 01-07"
    "Item 01-08"
    "Item 01-09"
    "Item 01-10"
]
LIST-2-DATA: [
    "Item 02-01"
    "Item 02-02"
    "Item 02-03"
    "Item 02-04"
    "Item 02-05"
    "Item 02-06"
    "Item 02-07"
    "Item 02-08"
    "Item 02-09"
    "Item 02-10"
    "Item 02-11"
    "Item 02-12"
    "Item 02-13"
    "Item 02-14"
    "Item 02-15"
    "Item 02-16"
    "Item 02-17"
    "Item 02-18"
    "Item 02-19"
    "Item 02-20"
]
LIST-3-DATA: [
    "Item 03-01"
    "Item 03-02"
    "Item 03-03"
    "Item 03-04"
    "Item 03-05"
    "Item 03-06"
    "Item 03-07"
    "Item 03-08"
    "Item 03-09"
    "Item 03-10"
    "Item 03-11"
    "Item 03-12"
    "Item 03-13"
    "Item 03-14"
    "Item 03-15"
    "Item 03-16"
    "Item 03-17"
    "Item 03-18"
    "Item 03-19"
    "Item 03-20"
]
view layout [
     label "Default text-list"
     LIST-1: text-list data LIST-1-DATA [
        set-face CONTENTS copy LIST-1/picked
    ]
    CONTENTS: info 200
    button "Load list 1" [
        LIST-1/data: LIST-1-DATA
        show LIST-1
    ]
    button "Load list 2" [
        LIST-1/data: LIST-2-DATA
        show LIST-1
    ]
    button "Load list 3" [
        LIST-1/data: LIST-3-DATA
        LIST-1/sld/redrag LIST-1/lc / max 1 length? LIST-3-DATA
        show LIST-1
    ]
    button "Quit" [quit]
]

9.21 List

The list style is a general style for multi-column lists of data. Because it is more general than a text-list, it is more complicated. There is a very thorough lesson on using lists at this link:

Creating Multi-Column GUI Text Lists (Data Grids) From Scratch

To create a list, you use the "list" keyword followed by three things.

The first thing is a size pair, since there is no default size.

The second thing is a block that is a mini-layout defining the items in a row of the list. It uses regular layout keywords. Usually there is the keyword "across" to cause the list columns to run across the window, because that is the kind of thing we are trying to create with a list. Other facets can be specified, like fonts, and also action facets to cause things to happen when list items are clicked.

The third thing is a block of blocks, identified by the keyword "data". Each block in that data block contains items that match the columns defined in the layout block. This example shows this basic setup:

LIST-DATA: [
    ["Item 01-01" "Item 02-01"]
    ["Item 01-02" "Item 02-02"]
    ["Item 01-03" "Item 02-03"]
    ["Item 01-04" "Item 02-04"]
    ["Item 01-05" "Item 02-05"]
    ["Item 01-06" "Item 02-06"]
    ["Item 01-07" "Item 02-07"]
    ["Item 01-08" "Item 02-08"]
    ["Item 01-09" "Item 02-09"]
    ["Item 01-10" "Item 02-10"]
    ["Item 01-11" "Item 02-11"]
    ["Item 01-12" "Item 02-12"]
    ["Item 01-13" "Item 02-13"]
    ["Item 01-14" "Item 02-14"]
    ["Item 01-15" "Item 02-15"]
    ["Item 01-16" "Item 02-16"]
    ["Item 01-17" "Item 02-17"]
    ["Item 01-18" "Item 02-18"]
    ["Item 01-19" "Item 02-19"]
    ["Item 01-20" "Item 02-20"]
]
view layout [
    label "No default list size"
    across
    DEMO-LIST: list 200x200 [
           across
           text 100 [print ["clicked " value]]
           text 100 [print ["clicked " value]]
        ]
        data LIST-DATA
]

As seen in the above example, the data block has more data than will fit in the list window, and no scroll bar is provided. To fix that, you have to manage it yourself. Here is how.

In the layout, replace the "data" block with a function, called "supply." This function will be executed when you "show" the list, and it will be executed for each "cell" so to speak, that is, for row 1 column 1, then row 1 column 2, then row 2 column 1, row 2 column2, and so on. Two variables will be available during that process. The variable "count" refers to the row being filled, and the variable "index" refers to the column being filled. You use "count" and "index" along with the "pick" function to pull data items out of a block of blocks, and use the keyword "face" to refer to the current item of the list being filled. This is shown in the example coming up.

Because you are using the "supply" function to load the list, you can make use of that by using a scroller to adjust the starting point in the block of data. The scroller's value, identified by the keyword "value," contains a number from zero to one. Multiplying the total length of the data block by the scroller's value (which is a fraction between zero and one) will give a starting point for pulling data out of the data block. You can add that starting point to the "count" variable in the "supply" function.

As a final thing to remember, as shown in the example below, what happens you hit the end of the data block before the list is filled? This is handled by checking for "none" when picking a row of data. If you get "none," set that data item you are trying to fill to "none" and exit the supply function.

This example tries to show all of the above:

STARTING-DATA-ROW: 0 
LIST-DATA: [
    ["Item 01-01" "Item 02-01"]
    ["Item 01-02" "Item 02-02"]
    ["Item 01-03" "Item 02-03"]
    ["Item 01-04" "Item 02-04"]
    ["Item 01-05" "Item 02-05"]
    ["Item 01-06" "Item 02-06"]
    ["Item 01-07" "Item 02-07"]
    ["Item 01-08" "Item 02-08"]
    ["Item 01-09" "Item 02-09"]
    ["Item 01-10" "Item 02-10"]
    ["Item 01-11" "Item 02-11"]
    ["Item 01-12" "Item 02-12"]
    ["Item 01-13" "Item 02-13"]
    ["Item 01-14" "Item 02-14"]
    ["Item 01-15" "Item 02-15"]
    ["Item 01-16" "Item 02-16"]
    ["Item 01-17" "Item 02-17"]
    ["Item 01-18" "Item 02-18"]
    ["Item 01-19" "Item 02-19"]
    ["Item 01-20" "Item 02-20"]
]
view layout [
    label "No default list size"
    across
    DEMO-LIST: list 200x200 [
           across
           text 100 [print ["clicked " value]]
           text 100 [print ["clicked " value]]
        ]
        supply [
            count: count + STARTING-DATA-ROW 
            ;; Pick the row to load, if none, set cell to "none" and exit
            if none? PICKED-ROW: pick LIST-DATA count [face/text: none exit]
            ;; Use index to pick data out of current row, then set cell value
            face/text: pick PICKED-ROW index  ;; "face" refers to current cell
        ]
    slider 20X200 [    ;; Code executed when slider is moved
        STARTING-DATA-ROW: (length? LIST-DATA) * value
        show DEMO-LIST
    ]
]

Because the "list" style is analyzed so thoroughly in the above link, no more documentation is presented here. Because of the layout block that is part of the "list" definition, and the fact that is is VID layout code, you can have lists of other things besides text. You could have a list of buttons, for example, and the buttons could have actions. Because of the "supply" function that loads the list, you can take various actions depending on the values of "count" and "index." A common example is to vary the color of the cell being loaded, so that maybe for the even rows you use one color and the odd rows another. Many ideas are presented in the above linked document.

9.22 Drop-down

This is the regular drop-down list. The data comes from a block which may be coded in-line for small lists or may be elsewhere for longer ones.

Commonly-used facets:

size: The horizontal size can be set, but trying to use a pair does not give expected results.

rows: This seems to be how to set the number of items if you want more than the default of 4.

color: One or two colors may be specified for text and background.

data: This is a block used to populate the list.

font: This controls the appearance of the chosen item, but not the items in the list when you drop it down.

action: You may take action as soon as an item is chosen, or you may not, and just refer to the choice later.

text: This is the facet used when you want to refer to the item that was chosen from the list.

It seems that the vertical size of the drop-down list can be controlled with the "rows" facet, but it will not go down beyond the bottom of the window. So, in the example below, there is a box below the drop-down, just so that the resulting window has enough vertical size to allow the list to drop down far enough to show the choices.

Example (Use under a REBOL header.):

DROP-DOWN-CHOICES: [
    "Choice 01"
    "Choice 02"
    "Choice 03"
    "Choice 04"
    "Choice 05"
    "Choice 06"
    "Choice 07"
    "Choice 08"
    "Choice 09"
    "Choice 10"
    "Choice 11"
    "Choice 12"
    "Choice 13"
    "Choice 14"
    "Choice 15"
    "Choice 16"
    "Choice 17"
    "Choice 18"
    "Choice 19"
    "Choice 20"
]
view layout [
    CHOICE-LIST: drop-down 200 green black data DROP-DOWN-CHOICES  
        [set-face SELECTED-CHOICE CHOICE-LIST/text]     
        font [style: 'bold size: 14] rows 10
    box 200x200 yellow 
    SELECTED-CHOICE: text 200 
]

The above example shows how a drop-down is populated when a layout is created. It is possible to change the contents at run time. It seems that the drop-down style has a function (reset) to clear its contents, and it seems that the contents are referred to by the word "list-data." Modifying a drop-down could be done like the following example. This is a complete script. Note the two lines in the LOAD-SUBCAT function that reset the drop-down and load the list-data. Note also the "set-face" line that sets the visible part of the drop-down to the first line of the list of selections.

REBOL []
CATEGORIES: [
    "ActiveDirectory" ["ResetPassword" "UnlockAccount"]
    "Laptop" ["LoginFailure" "XXX" "yyy"]
    "Phones" ["NewCord" "xxx" "yyy"]
]
SUBCATS: []
LOAD-SUBCAT: does [
    SUBCATS: copy [] 
    SUBCATS: copy select CATEGORIES get-face MAIN-CATEGORY
    MAIN-SUBCAT/reset
    MAIN-SUBCAT/list-data: SUBCATS
    set-face MAIN-SUBCAT SUBCATS/1
]
MAIN-WINDOW: layout [
    MAIN-CATEGORY: drop-down 150 data (extract CATEGORIES 2) [LOAD-SUBCAT]
    MAIN-SUBCAT: drop-down 150 
    button "Quit" [quit]
    box 150x100 ;; So drop-down will show 
]
view center-face MAIN-WINDOW

9.23 Rotary

This is an item similar to the drop-down, except that it is a button, and every click of the button rotates through a list of choices.

Commonly-used facets:

size: The size can be set similarly to setting a button size.

color: One or two colors may be specified for text and background.

data: This is a block used to populate the list.

font: This controls the appearance of text on the button.

action: You may take action as soon as an item is chosen, or you may not, and just refer to the choice later.

text: This is the facet used when you want to refer to the item that was chosen from the list.

Example (Put this under a REBOL header.):

ROTARY-CHOICES: [
    "Choice 01"
    "Choice 02"
    "Choice 03"
    "Choice 04"
    "Choice 05"
    "Choice 06"
    "Choice 07"
    "Choice 08"
    "Choice 09"
    "Choice 10"
    "Choice 11"
    "Choice 12"
    "Choice 13"
    "Choice 14"
    "Choice 15"
    "Choice 16"
    "Choice 17"
    "Choice 18"
    "Choice 19"
    "Choice 20"
]
view layout [
    CHOICE-LIST: rotary 200x50 green black data ROTARY-CHOICES  
        [set-face SELECTED-CHOICE CHOICE-LIST/text]     
        font [style: 'bold size: 14] 
    SELECTED-CHOICE: text 200 
]

9.24 Choice

This is another way to get a data item from a window. A "choice" style looks like a button, and when you click the button all the specified choices appear below it for selection.

Commonly-used facets:

size: The size can be set similarly to setting a button size. If you specify a vertical size, all the choices that appear will have that size, but the list will not extend below the bottom of the window.

color: It appears that only one color can be specified, and that is for the background color of the choice button.

data: This is a block used to populate the list.

font: This controls the appearance of text on the button.

action: You may take action as soon as an item is chosen, or you may not, and just refer to the choice later.

text: This is the facet used when you want to refer to the item that was chosen from the list.

Example (Put this under a REBOL header.):

CHOICE-CHOICES: [
    "Choice 01"
    "Choice 02"
    "Choice 03"
    "Choice 04"
    "Choice 05"
    "Choice 06"
    "Choice 07"
    "Choice 08"
    "Choice 09"
    "Choice 10"
    "Choice 11"
    "Choice 12"
    "Choice 13"
    "Choice 14"
    "Choice 15"
    "Choice 16"
    "Choice 17"
    "Choice 18"
    "Choice 19"
    "Choice 20"
]
view layout [
    CHOICE-LIST: choice 200 green data CHOICE-CHOICES  
        [set-face SELECTED-CHOICE CHOICE-LIST/text]     
        font [style: 'bold size: 14]
    box 200x500 beige 
    SELECTED-CHOICE: text 200 
]

9.25 Toggle, tog

This is a way of obtaining "either/or" kind of input. A toggle looks like a button, and you specify two values. When you click the toggle, the text facet changes to the value on the toggle button, and then the visible value on the button changes to the other specified value.

It appears that the "tog" style is a toggle with some appearance attributes set, probably ones that are more commonly used.

Commonly-used facets:

size: The size can be set similarly to setting a button size.

color: It is appropriate to specifiy two color values, because the toggle, by nature of its two-valued state, needs two colors to differentiate the states.

font: This is used to specify attributes of the text on the button. It appears that not all values work.

action: You may take action as soon as an item is chosen, or you may not, and just refer to the choice later. Both left-button and right-button actions may be specified.

text: This is the facet used when you want to refer to the item that was chosen from the list. It is the text printed on the button.

Example:

TOGGLESWITCH: toggle 200x50 red green "ON" "OFF" 
    font [size: 20 color: black]
    [set-face SELECTED-CHOICE TOGGLESWITCH/text]   
    [set-face RIGHT-CLICK-CHOICE TOGGLESWITCH/text]   
SELECTED-CHOICE: text 200
RIGHT-CLICK-CHOICE: text 200   
tog "ON" "OFF"

9.26 Check, check-mark, check-line

These are check boxes for yes/no kind of data. The "check" style is a box that can be modified a bit with size and color. The "check-mark" and "check-line" appear to be "check" styles with some attributes pre-set.

Commonly-used facets:

color: For a "check" you can specify different colors for "checked" and "un-checked." Colors do little or nothing for the other styles.

data: This is a true or false value that is set when the item is checked or un-checked.

Examples:

across
CHECK-1: check 40x40 tan yellow [print CHECK-1/data]
return
CHECK-2: check-mark [print CHECK-2/data] 
return 
CHECK-3: check-line [print CHECK-3/data]

9.27 Radio, radio-line

The radio button is something for mutually-exclusive choices. The radio-line style seems to be the same as a radio button.

Commonly-used facets:

data: This is a true or false value depending on whether or not the button is checked. It seems that there is a difference between un-checked and never checked. A button that never has been checked has a value of none.

Examples (Put this under a REBOL header):

SHOW-ALL-VALUES: does [
    print ["RADIO-1: " RADIO-1/data]
    print ["RADIO-2: " RADIO-2/data]
    print ["RADIO-3: " RADIO-3/data]
    print ["RADIO-4: " RADIO-4/data]
    print "----------------"
]
view layout [
    RADIO-1: radio
    RADIO-2: radio
    bar
    RADIO-3: radio 
    RADIO-4: radio
    bar
    button "Show all values" [SHOW-ALL-VALUES]
]

In the above example, the buttons are mututally exclusive for the whole window. Often, one wants more than one group of buttons. This can be done by using a word to group buttons, as shown in this example:

SHOW-ALL-VALUES: does [
    print ["RADIO-1: " RADIO-1/data]
    print ["RADIO-2: " RADIO-2/data]
    print ["RADIO-3: " RADIO-3/data]
    print ["RADIO-4: " RADIO-4/data]
    print "----------------"
]
view layout [
    RADIO-1: radio of 'GROUP-1
    RADIO-2: radio of 'GROUP-1
    bar
    RADIO-3: radio of 'GROUP-2
    RADIO-4: radio of 'GROUP-2 
    bar
    button "Show all values" [SHOW-ALL-VALUES]
]

9.28 Scroller, slider

The scroller and slider are two variations of the same thing, that bar with the thing you grab and drag to scroll through some thing that is too big to show entirely in whatever you are trying to show it in. Usually, that means a block of text that is long, so that you have to scroll down to see it all. The scroller and slider differ in the presence of the arrows at the ends.

Commonly-used facets:

size: Normally one would set the lengh of the scroller/slider to match the length of what is being scrolled, and set the width to something that is grabbable with a mouse pointer, like around 16 pixels.

data: This is a numeric value that varies from zero to one as the slider is operated.

action: An action block is executed every time the slider moves so much as a pixel.

Examples (Put this under a REBOL header):

SHOW-SCROLLER-3-VAL: does [
    set-face SCROLLER-3-VAL to-string SCROLLER-3/data
]
SHOW-SLIDER-4-VAL: does [
    set-face SLIDER-4-VAL to-string SLIDER-4/data
]
view layout [
    across
    SCROLLER-1: scroller [set-face SCROLLER-1-VAL to-string value]
    tab
    SLIDER-1: slider [set-face SLIDER-1-VAL to-string value]
    tab
    SCROLLER-3: scroller [SHOW-SCROLLER-3-VAL]
    tab
    SLIDER-4: slider [SHOW-SLIDER-4-VAL]
    return
    SCROLLER-1-VAL: text 40
    tab
    SLIDER-1-VAL: text 40
    tab
    SCROLLER-3-VAL: text 40
    tab
    SLIDER-4-VAL: text 40
]

Another question that will come up is, can one do horizontal scrolling? If the scroller is wider than it is high, it appears that VID can make the proper adjustment.

across
SCROLLER-1: scroller 200x16 [set-face SCROLLER-1-VAL to-string value]
SCROLLER-1-VAL: text 40
return
SLIDER-1: slider 200x16 [set-face SLIDER-1-VAL to-string value]
SLIDER-1-VAL: text 40

The next obvious question is, what does one actually DO with a slider or scroller? The answer is, it depends. In general, there is some item on a window that one wants to scroll through, and there is an action block on the slider. The action block is executed every time the scroller moves, and the value of the scroller, from zero to one, is available in the "data" facet. The program has to use that value to find out where the scrollable item is to be positioned, at the beginning (a data value of zero), at the end (a data value of one), or somewhere in the middle. Then the program has to calculate what part of the scrollable item should be showing, set the visible part of the data to the correct value, and re-show the scrollable item using the "show" function. Exactly how that is done varies with the kind of data item being scrolled. Examples later in this document will show some ideas.

Here is a very basic example to show the idea. Since a progress bar uses a value from zero to one to show progress, and a slider or scroller gets a value from zero to one as it is moved, we can make a simple demo to get the value from a slider and use it to set the value of a progress bar.

PROGRESS-BAR: progress 400x40
PROGRESS-SLIDER: slider 400x40
    [PROGRESS-BAR/data: PROGRESS-SLIDER/data show PROGRESS-BAR]

9.29 Sensor

The sensor is an invisible thing on the window. Because it is invisible it is hard to click on it. The sensor is another good candidate for the "rate" facet for taking action at time intervals.

box 100x100 red
sensor 0x0 rate 00:00:05 feel [
    engage: [
        alert "Time is up"
        quit
    ]
]

9.30 Anim

The anim is a way to make something like an animated GIF. It uses a block of image file names to rotate through those images on the screen at a specifiec rate.

Commonly-used facets:

rate: This seems to be slightly different than the regulare "rate." It appears to be an integer that represents the number of times per second that the image will change. This can be shown by specifying a rate of 1 and watching the image change about once a second. Specifying a larger number makes it change faster.

frames: This appears to be a special facet related to the anim style. It is a block of file names of image files. The indicated images will be shown in the style, change as specified in the rate.

Examples:

anim rate 1 frames [
    %GreenCheck.png
    %RedX.png
]

In the above example, the images specified in "frames" are basiclly some image file just "lying around" when this example was created. To run the example for yourself, you will have to find your own images. The number is not limited to just two as shown in the example. You can use more. An upper limit is not known at this time. The "rate" of 1 will change the image every second. A higher number will change it faster.

10. Functions: Doing things with the styles

The previous chapter listed all the things that one can put on a window, but that is not the full story of a graphical interface. Besides the "layout" function which transforms VID dialect code into a displayable window, and the "view" function which displays a window created by "layout," there are other functions used for making a GUI work. This section explains those functions.

This document should not be your only source of VID knowledge. Refer to the REBOL function dictionary where there is a section of REBOL/View functions, and refer to the VID manual mentioned at the beginning of this document. The reason for that is that the official documentation is not totally complete or clear, and the goal of this manual is to make something that IS complete and clear, which is an impossible goal. So to make it clear if not complete, things that are not understood are not mentioned.

In the examples to follow, paste them under a REBOL header and not inside the "view layout" structure as you did for the style samples. The stuff inside a layout block is VID code and not REBOL code, but the functions to follow are REBOL functions and NOT VID code, so they do not belong inside a layout block.

10.1 Center-face

This function is mentioned at the beginning because it is used to center a displayed window in the middle of the screen. Some examples below work better if centered. No example is provided here. Look for this function to be used in the examples for the following function. When you see it, know that it is there to cause the window to appear in the middle of the screen.

10.2 Layout

This function takes a block of VID code and returns an interface object that can be viewed with the "view" function. The result of the "layout" function can be piped right into the "view" function or it can be set as a value of a word, and then the word can be viewed.

Here is a basic example:

MAIN-WINDOW: layout [
    button red
    button red
]
view MAIN-WINDOW

If you don't like the default position of up in the corner, you can center it with the center-face function as explained above.

Notice that there is a default amount of space around the edges of the window. Sometimes you might not want this. It can be eliminated with the "tight" refinement:

MAIN-WINDOW: layout/tight [
    button red
    button red
]
view center-face MAIN-WINDOW

Notice that "tight" refers just to the space around the edges. If you want things right up next to each other, you can control the spacing with the "space" keyword:

MAIN-WINDOW: layout/tight [
    space 0x0
    button red
    button green
    return
    button yellow
    button blue
]
view center-face MAIN-WINDOW

10.3 Stylize

The "stylize" function allows you to make a style sheet, which is a set of styles with pre-defined facets so you don't have to code things over and over again. The function takes a block of styles, similar to the "layout" function, but the styles are given labels. Then, in a the "layout" function, you can place those custom styles. Here is a basic example. Note that the style sheet is defined with the "stylize" function, and then invoked in a layout with the "styles" keyword.

LOCAL-STYLES: stylize [
    WINDOW-HEADER: banner yellow font [shadow: none size: 30]
    GO-BUTTON: button 40x40 green
    STOP-BUTTON: button 40x40 red
]
MAIN-WINDOW: layout [
    styles LOCAL-STYLES 
    WINDOW-HEADER "Custom style window"
    GO-BUTTON
    STOP-BUTTON
]
view center-face MAIN-WINDOW

10.4 View

The "view" function has been shown, because it was necessary to show anything else. There are a few options.

In this example, the border and title bar are eliminated, and the outer border can be resized. If you use these options, you better provide your own "close" button because there won't be one on the window.

MAIN-WINDOW: layout/tight [
    space 0x0
    button red
    button green
    return
    button yellow
    button blue
    return
    button "quit" [quit]
]
view/options center-face MAIN-WINDOW [no-title no-border resize]

If you do use the title bar, the text can be specified:

MAIN-WINDOW: layout [
    button red
    button green
    return
    button yellow
    button blue
    return
    button "quit" [quit]
]
view/title center-face MAIN-WINDOW "Custom title window"

If you want to specify where the window should be placed on the screen, you can use the "offset" refinement of the "layout" function:

view layout/offset [
    size 600x480
    across
    button "button 1"
    button "button 2"
    return
    button "button 3"
    button "button 4"
] 300x300

10.5 Unview

The "unview" function closes a previously-viewed window. This would be used perhaps with the "/new" refinement of the "view" function which would open a new window, which would be closed later by "unviewing" it. "Unview" by itself will close the most-recently-opened window. "Unview/all" will unview all windows. "Unview/only? with a window name will unview a specified window. For example (Put this under a REBOL header since it has several layouts.):

GREEN-WINDOW: layout [
    box 200x200 green
    button "Unview me" [unview/only GREEN-WINDOW]
]
RED-WINDOW: layout [
    box 200x200 red
    button "Unview me" [unview/only RED-WINDOW]
]
MAIN-WINDOW: layout [
    button 200 green "View green window" [view/new GREEN-WINDOW]
    button 200 green "Unview green window" [unview/only GREEN-WINDOW]
    button 200 red "View red window" [view/new RED-WINDOW]
    button 200 red "Unview red window" [unview/only RED-WINDOW]  
    button 200 "Unview whatever" [unview]  
    button 200 "Unview all" [unview/all]  
    button 200 "Quit" [quit]    
]
view center-face MAIN-WINDOW

10.6 Viewed?

This is a function for testing if a windows is in view. You might use this if you had some complicated program with many windows and interactions that moved from window to window.

GREEN-WINDOW: layout [
    box 200x200 green
    button "Unview me" [unview/only GREEN-WINDOW]
]
RED-WINDOW: layout [
    box 200x200 red
    button "Unview me" [unview/only RED-WINDOW]
]
MAIN-WINDOW: layout [
    button 200 green "View green window" [view/new GREEN-WINDOW]
    button 200 green "Unview green window" [unview/only GREEN-WINDOW]
    button 200 green "Green window status" [print viewed? GREEN-WINDOW]
    button 200 red "View red window" [view/new RED-WINDOW]
    button 200 red "Unview red window" [unview/only RED-WINDOW]  
    button 200 red "Red window status" [print viewed? RED-WINDOW] 
    button 200 "Unview whatever" [unview]  
    button 200 "Unview all" [unview/all]  
    button 200 "Quit" [quit]    
]
view center-face MAIN-WINDOW

10.7 Show

The "show" function is what you use to change things on a window. You can "show" a whole layout, or you can "show" individual items on a layout. To reference a layout or a style that you want to show, you have to assign the item to a word, that is, give a name to the layout or style.

TEXT-DISPLAY: text 500
TEXT-FIELD: field 500
button 500 "Change text to field value" [
    TEXT-DISPLAY/text: copy get-face TEXT-FIELD
    show TEXT-DISPLAY
]

If you have update a bunch of styles and want to show them all, you don't have to code one "show" function for each; you may put the style names in a block and "show" the block.

10.8 Hide

The "hide" function is used to make a style invisible. The style is not permanently removed; it can be shown again. As with "show," you may hide a single style, or specify a block of style names and hide them all with one call to the hide function.

TEST-BOX: box 200x200 red [print "Box still is here"] 
button "Show box" [show TEST-BOX]
button "Hide box" [hide TEST-BOX]
button "Show window" [show MAIN-WINDOW]

10.9 Get-face, set-face

It seems that later versions of REBOL/View added special functions for accessing the certain values of certain styles. It appears that these apply mainly to sytles that hold text. Earlier documentation indicates that the text facet of a style is accessed with (style-name)/text. To set the text facet, one sets (style-name)/text and "shows" the style. Now, with the "set-face" function, the setting of the value and the showing of the style are one operation. The "set-face" function as a "no-show" refinement to suppress the re-showing. With get-face, note that one must use the "copy" function or one obtains a reference to the sytle instead of the value of it.

TEST-FIELD-VALUE: none
MAIN-WINDOW: layout [
    ENTRY-FIELD: field 400
    ENTRY-VALUE: info 400
    button "Test" [
        TEST-FIELD-VALUE: copy get-face ENTRY-FIELD
        set-face ENTRY-VALUE TEST-FIELD-VALUE
    ]
]
view center-face MAIN-WINDOW

10.10 Alert

This function is used for popping up a message that the operator must respond to. The official documentation says that the only choice for responding to an alert message is "OK," but a little trial an error indicates that you can add a second button to the alert message that will return a "false" result as shown in the example:

ALERT-MSG-1: "An alert message"
ALERT-MSG-2: "can be constructed"
alert "Basic alert message"
alert rejoin [
    ALERT-MSG-1
    " "
    ALERT-MSG-2
]
ALERT-RESULT: alert "Alert function returns what?"
print ALERT-RESULT
GO?: alert [
    "OK to continue?"
    "OK"
    "Cancel"
]
if not GO? [
    alert "Operation canceled"
    print GO?
    halt
]
print GO? 
halt

10.11 Request-file

This is function to pop up the appropriate file requestor window for the host operating system. The REBOL documentation shows a number of options, but some of those don't seem to work as expected. But, the things most commonly done do work, and here they are.

Normally one would set a word to the result of the function, as shown in the examples. That is because when you want to request a file name, you want to get your hands on it. If the operator cancels the request, the returned result is "none" and the word would be set to that value.

A plain "request-file" returns a block containing all the file names selected. The refinement of "path" returns a block, but the first item is the folder and the other items are the file names in a relative form.

If you want just one file, use the /only refinement.

If you want the request window to limit the choices only to certain file types, use the "filter" refinement.

Examples:

FILE-ID-1: request-file
print ["FILE-ID-1 is a " type? FILE-ID-1 " value is " FILE-ID-1]
FILE-ID-2: request-file/only 
print ["FILE-ID-2 is a " type? FILE-ID-2 " value is " FILE-ID-2] 
FILE-ID-3: request-file/path
print ["FILE-ID-3 is " FILE-ID-3]
FILE-ID-4: request-file/only/filter ["*.txt"]
print ["FILE-ID-4 is " FILE-ID-4]
halt

As hinted above, if the operator cancels the request, you have to take appropriate action because you won't have a file name to work with. A common approach would be to check the result of the function for "none" and then quit the program, or, if you are inside a function, exit the function, as shown below:

FILE-ID: request-file/only
if not FILE-ID [
    alert "No file requested"
    quit ;; or "exit" if inside a function 
]

10.12 Request-dir

Similar to request-file is the request-dir function to select a folder. The result is either a folder name or "none" if the request is canceled.

FOLDER-ID: request-dir
either FOLDER-ID [
    print ["Selected folder is " FOLDER-ID]
    halt
] [
    alert "No folder selected"
    quit
]

10.13 Request-color

The "request-color" function pops up a device with sliders so you can select a color, visually, and then, when the function exits, it returns a color tuple for the color you selected.

The function has refinements to control the placement of the device, and a default color, as shown in the example. Put this example under a REBOL header.

REQUESTED-COLOR: request-color
print REQUESTED-COLOR 
REQUESTED-COLOR: request-color/offset 50x50
print REQUESTED-COLOR
REQUESTED-COLOR: request-color/color brick 
print REQUESTED-COLOR
REQUESTED-COLOR: request-color/color/offset yellow 200x200 
print REQUESTED-COLOR  
halt

10.14 Request-date

The "request-date" function pops up a little date requestor box like you probably have seen elsewhere. When you select a date, the funtion returns it as a return value. If you don' select a date, the function returns "none." A "offset" refinement lets you position the box somewhere other than the center of the physical screen. Try the example under a REBOL header:

REQUESTED-DATE: request-date/offset 200x200  
print REQUESTED-DATE 
halt

10.15 Request-text

The "request-text" function is for requesting a small amount of text from the operator. An "offset" refinement allows positioning of the window. A "title" refinement allows a title on the title bar. A "default" refinement allows pre-filled text in the field. If the operator enters nothing, the function returns "none." This example shows all the refinements at once:

REQUESTED-TEXT: request-text/offset/title/default
    200x200
    "Enter text here"
    "Default text"  
print REQUESTED-TEXT 
halt

10.16 Request-pass

The "request-pass" function pops up a window for entering a user ID and password, which are returned in a two-element block, as shown in the example. There is a "user" refinement to pre-fill the user ID. There is an "offset" refinement to position the window. There is a "title" refinement to load the title bar. THere is an "only" refinement to get a password only in which case the function returns a string instead of a block. If the operator enters nothing, "none" is returned.

CREDENTIALS: request-pass
print ["CREDENTIALS is a " type? CREDENTIALS]
print ["User ID is " CREDENTIALS/1]
print ["Password is "CREDENTIALS/2]
CREDENTIALS: request-pass/user "defaultuser" 
print ["CREDENTIALS is a " type? CREDENTIALS]
print ["User ID is " CREDENTIALS/1]
print ["Password is "CREDENTIALS/2]
CREDENTIALS: request-pass/offset/title/only 200x200 "Password for defaultuser" 
print ["CREDENTIALS is a " type? CREDENTIALS]
print ["User ID is " CREDENTIALS]
halt

The examples above are written in sort of a plodding manner, where the result of a function is assigned as the value of a word, and then something is done with that value. Because of REBOL's structure, where you have the right-to-left evaluation and functions return values which go into other functions, these examples, and other code like it, can be condensed. If, for example, you want to get a password for a known user ID, store it, check to see if it was entered, and then take some other actions, you could code a lot of that in one line:

either PASSWORD: request-pass/title/only "Password for defaultuser" [
    alert rejoin [
        PASSWORD
        " is correct"
    ] 
] [
    alert "No password entered"
]

10.17 Request-list

The "request-list" function is for picking one item from a list of items. The list of items is provided in a block. There is an "offset" refinement to control positioning of the window. A title for the selection window is required:

SELECTED-ITEM: request-list/offset 200x200 "Pick an item" [
    "Item 01-01"
    "Item 01-02"
    "Item 01-03"
    "Item 01-04"
    "Item 01-05"
    "Item 01-06"
    "Item 01-07"
    "Item 01-08"
    "Item 01-09"
    "Item 01-10"
    "Item 01-11"
    "Item 01-12"
    "Item 01-13"
    "Item 01-14"
    "Item 01-15"
    "Item 01-16"
    "Item 01-17"
    "Item 01-18"
    "Item 01-19"
    "Item 01-20"
]  
print SELECTED-ITEM
halt

10.18 Request-download

The "request-download" function reads a file on the internet, as specified by a URL. With no refinements, the function will return the files as a binary data item. With the "to" refinement and a file name, the function will store the downloaded file on disk.

DOWNLOAD-PAGE: request-download http://www.rebol.com/what-rebol.html 
print ["DOWNLOAD-PAGE is " type? DOWNLOAD-PAGE]
request-download/to http://www.rebol.com/what-rebol.html %tempsave.html 
print "Check to see if tempsave.html exists" 
halt

10.19 Request

The "request" function brings up various forms of request boxes with buttons, and whatever the buttons are, the results are the same, which is, that a "true," "false," or "none" value is returned, and thus can be checked with an "if" or "either" function.

The function has an "offset" refinement to control positioning, and then other refinements that control the number of buttons and the appearance of an icon on the window. The function takes, as an argument, the text of a message for the request window. Running through the example is the best way to see what the results look like. Notice that for the "type" refinement, a REBOL "word" is expected. In other words, it needs that apostrophe in the front, so that it is not evaluated as a function or replaced with a value.

ANSWER: request "Question 1"
print ["The answer is " ANSWER] 
ANSWER: request/offset "Question 2" 200x200
print ["The answer is " ANSWER] 
ANSWER: request/ok "Question 3"
print ["The answer is " ANSWER] 
ANSWER: request/only "Question 4" 
print ["The answer is " ANSWER] 
ANSWER: request/confirm "Question 5" 
print ["The answer is " ANSWER] 
ANSWER: request/type "Question 6" 'alert
print ["The answer is " ANSWER] 
ANSWER: request/type "Question 7" 'help 
print ["The answer is " ANSWER] 
ANSWER: request/type "Question 8" 'info 
print ["The answer is " ANSWER] 
ANSWER: request/type "Question 9" 'stop 
print ["The answer is " ANSWER] 
halt

10.20 Flash

The "flash" function is for putting up a message to indicate that something is happending. It is the job of the program to use the "unview" function to close the flash window at the appropriate time. The "flash" function returns the flash window, so that the program can flash more than one thing, and then unview them one at a time by name.

flash "Basic flash window; wait three seconds."
wait 3
unview
request/ok "Done with basic flash demo." 
view layout [ 
    button 200  "Start demo" [
        FLASH-1: flash "Flash 1; drag off center."
        FLASH-2: flash "Flash 2; drag off center"
    ] 
    button 200 "Unview flash 1" [unview FLASH-1]
    button 200 "Unview flash 2" [unview FLASH-2]
    button 200 "Quit" [quit] 
]

10.21 Inform, hide-popup

The "inform" function pops up a dialog window of your own creation (with the layout function) and will not let you do anything else until you have used the "hide-popup" function to close the window. The window you show with "inform" is created with the "layout" function and can be as involved as you like. This is in contrast to some of the built-in functions for requesting small amounts of data, where you are restricted to small amounts of data. Put the following example under a REBOL header:

MODAL-TEXT: ""
MODAL-WINDOW: layout [
    MODAL-FIELD: field 500
    button "Close" [
        MODAL-TEXT: copy get-face MODAL-FIELD
        hide-popup
    ]
]
view layout [
    button "Get text" [
        inform MODAL-WINDOW
        print MODAL-TEXT
    ]
    button "Quit" [quit] 
]

10.22 Load-image

This function appears to be used for bringing into memory one copy of an image file, so it can be used multiple times without multiple copies in memory.

REBOL-LOGO: load-image %reb-logo.gif
view MAIN-WINDOW: layout [
    label "Copy 1 of the image"
    image REBOL-LOGO
    label "Copy 2 of the image"
    image REBOL-LOGO
    button "Close" [quit]
]

10.23 Focus, unfocus

These functions are used for putting the "focus" on a text-entry field, so that when you start typing, text appears there. You can focus a specified interface object, but the "unfocus" is general, in that it removes the focus from whatever currently has it. Put this under a REBOL header:

view center-face layout [
    across
    label "FIELD-1"
    FIELD-1: field 100
    return
    label "FIELD-2"
    FIELD-2: field 100
    return
    label "FIELD-3"
    FIELD-3: field 100
    return
    button 150 "Focus FIELD-1" [focus FIELD-1]
    return
    button 150 "Focus FIELD-2" [focus FIELD-2]
    return
    button 150 "Focus FIELD-3" [focus FIELD-3]
    return
    button 150 "Unfocus current" [unfocus] 
    return
    button 150 "Quit" [quit]

]

10.24 Dump-face

This is a debugging function that provides information about an interface object. The argument to the function can be a whole window, or just some part of a window, as shown (Put under a REBOL header):

view MAIN-WINDOW: layout [
    BANNER-TEXT: banner "Test window"
    FIELD-1: field 200 "Default text"
    BUTTON-1: button beige 200 "Dummy button"
    button 200 "Dump MAIN-WINDOW" [print dump-face MAIN-WINDOW]
    button 200 "Dump BANNER-TEXT" [print dump-face BANNER-TEXT]
    button 200 "Dump FIELD-1" [print dump-face FIELD-1]
    button 200 "Dump BUTTON-1" [print dump-face BUTTON-1]
    button 200 "Quit" [quit]
]

10.25 In-window?

This is a function that can tell, at run time, if some sytle is located in some window. This might seem like a strange thing to do, but remember that because REBOL is an iterpreted language, it is possible for a REBOL program to generate windows at run time. It seems that this function can NOT tell if a a window contains a style, only if an existing style is in a window. In other words, if you make a window, put a bunch of named styles in it, and then use the "in-window?" function on a style that does not exist, you will get an error. The function only checks to see if an existing style is in a specified window, not if a style exists in the first place. Put this example under a REBOL header:

MAIN-WINDOW: layout [
    label "BOX-1"
    BOX-1: box 200x200 red "BOX-1" font [align: 'center]
    button 200 tan "View secondary" [view/new SECONDARY-WINDOW]
    button 200 "BOX-1 in MAIN?" [print in-window? MAIN-WINDOW BOX-1]
    button 200 "BOX-1 in SECONDARY?" [print in-window? SECONDARY-WINDOW BOX-1]
    button 200 "BOX-2 in MAIN?" [print in-window? MAIN-WINDOW BOX-2]
    button 200 "BOX-2 in SECONDARY?" [print in-window? SECONDARY-WINDOW BOX-2]
    button 200 "Hide BOX-1" [hide BOX-1]
    button 200 "Hide BOX-2" [hide BOX-2]
    button 200 "Show BOX-1" [show BOX-1]
    button 200 "Show BOX-2" [show BOX-2]
    button 200 "Quit" [quit]
]
SECONDARY-WINDOW: layout [
    label "BOX-2"
    BOX-2: box 200x200 green "BOX-2" font [align: 'center]
    button 200 "Unview me" [unview SECONDARY-WINDOW]
]
view center-face MAIN-WINDOW

10.26 Clear-fields

This is a function that often is used on data-entry windows to clear out all fields, either after obtaining all fields, or maybe in response to a button for clearing fields. After clearing fields, it will be necessary to "show" the window, or you could have a window with data in fields, but in reality NOT have data in the fields.

MAIN-WINDOW: layout [
    across
    banner "Data entry form"
    return
    label "FIELD-1"
    FIELD-1: field 400
    return
    label "FIELD-2"
    FIELD-2: field 400
    return
    label "FIELD-3"
    FIELD-3: field 400
    return
    button "Clear" [
        clear-fields MAIN-WINDOW 
        show MAIN-WINDOW
    ]
    button "Submit" [
        print copy get-face FIELD-1
        print copy get-face FIELD-2
        print copy get-face FIELD-3
    ]
    button "Quit" [quit]
]
view center-face MAIN-WINDOW

10.27 Size-text

This is a function for obtaining the size of text inside of some style that holds text, like a text field or an area. The function is used a lot when scrolling text, because one has to know the size of the text, as well as the size of the style holding the text, to adjust a scroller to make the text scroll properly.

TEST-TEXT: {
This is a function that often is used on data-entry windows to clear
out all fields, either after obtaining all fields, or maybe in 
response to a button for clearing fields.  After clearing fields, it 
will be necessary to "show" the window, or you could have a window
with data in fields, but in reality NOT have data in the fields.
}
MAIN-WINDOW: layout [
    TEXT-FIELD-1-VALUE: text 200x400 TEST-TEXT
    TEXT-FIELD-1-SIZE: text 100
    TEXT-FIELD-2-VALUE: text 400x200 TEST-TEXT
    TEXT-FIELD-2-SIZE: text 100
    button 200 "Show size 1" [
        set-face TEXT-FIELD-1-SIZE to-string size-text TEXT-FIELD-1-VALUE
    ]
    button 200 "Show size 2" [
        set-face TEXT-FIELD-2-SIZE to-string size-text TEXT-FIELD-2-VALUE 
    ]
    button 200 "Quit" [quit]
]
view center-face MAIN-WINDOW

10.28 Caret-to-offset

This is a specialized function for working with styles that contain text. It converts an index of a string (remember that a string is a series and can have an index) to an x-y offset into the style that holds the string. An example from the REBOL function dictionary follows.

Here is a bit of explanation. In the layout as coded, the box called "bx" is about the size of one character, and is positioned by default at the top of the layout window, above "tx" which will hold some text in a 100x100 area. But before the window is "viewed" by the last line, we want to move that box on top of the letter "a" in the word "example." How do we do that? The "at" function applied to the text value of "tx" (tx/text) with a value of 14 will return the index into the text string that points to the 14th character, namely, the letter "a" in "example." Now we want to convert that index into an x-y pair that will locate the letter "a" inside the "tx" style. Remember now that the offset is going to be an x-y pair in pixels, which is why we have to apply some conversion to the index of the text string. The "caret-to-offset" function provides that conversion, and returns an x-y pair that points to the letter "a" in the "tx" style that holds the text. So now, to position the box, we have to adjust its offset. We adjust it to the offset of "tx" PLUS the calculated offset of the letter "a." AFTER we have made that adjustment, THEN we view the window. (The documentation notes that you also may do this kind of thing after the window has been made visible.)

out: layout [
    bx: box 10x15 red
    tx: body 100x100
]
tx/text: {This is an example character string.}
xy: caret-to-offset tx at tx/text 14
bx/offset: tx/offset + xy
view out

10.29 Offset-to-caret

This is a reverse function for caret-to-offset. It uses the offset of a text value in some text style and converts that offset into an index into the text value, so one can perhaps work with that text value at that position. For lack of a better example at this time, here is one from the REBOL documentation that shows some of the things that one could do if one wanted to dig into the "draw" dialect.

Here is a bit of explanation. At the top of the window is a small area of text. We want to put the mouse on some character of that text string and obtain the series index into that text, so we could potentially do something with the text at that point. It appears that the offset-to-caret function returns not an index value of the text, but the text itself from the point of the index value to the end.

The text area ("body") has an activated "look and feel" by the presence of the "feel" facet and its "engage" function which is activated by a mouse click on the area. The function operates with three things, which are indicated by the function parameters of "face," "act," and "event." If the action is the word "down" which indicates push of the mouse button, the function takes action. It appears that the event itself, that is, the mouse click, has an "offset" facet, which must be the offset in the text area where the pointer was when the mouse was clicked. The offset-to-caret function, when applied to the style itself (referred to by "face") and the offset of the event (the location of the mouse pointer when the mouse was clicked), returns the text from that point to the end, and with the "copy" function we load it into the text facet of "bx" and then re-show bx.

view layout [
    body 80x50 "This is an example string."
        feel [
            engage: func [face act event] [
                if act = 'down [
                    bx/text: copy offset-to-caret
                        face event/offset
                    show bx
                ]
            ]
        ]
    bx: body 80x50 white black
]

10.30 scroll-para

This is a function that encapsulates all that must be done to scroll a text style using a scroller. One passes to it a text face and a scroller.

;;  -- Generate some demo text and load it into the window.
LOAD-TEXT-FIELD: does [
    DEMO-TEXT: ""
    DEMO-FILE-LIST: read %.
    foreach FILENAME DEMO-FILE-LIST [
        append DEMO-TEXT rejoin [
            to-string FILENAME
            newline
        ]
    ]
    SCROLL-TEXT-LOAD WINDOW-TEXT WINDOW-SCROLLER DEMO-TEXT
    show WINDOW-TEXT
    show WINDOW-SCROLLER
]
;;  -- Load the text face with text passed to us in TDATA.
SCROLL-TEXT-LOAD: func [TXT BAR TDATA] [
    TXT/text: TDATA
    TXT/para/scroll/y: 0
    TXT/line-list: none
    TXT/user-data: second size-text TXT
    BAR/data: 0
    BAR/redrag TXT/size/y / TXT/user-data
]
view layout [
    across
    WINDOW-TEXT: text 300x400 as-is
    WINDOW-SCROLLER: scroller 20x400 
        [scroll-para WINDOW-TEXT WINDOW-SCROLLER]
    return
    button "Load text" [LOAD-TEXT-FIELD]
]

10.31 Insert-event-func, remove-event-func

These are two functions that are used to create user-defined functions that respond to GUI events. The documentation is a little sparse. The following example shows how one might trap the event of clicking the "close" X in the upper right corner of a Windows window. The program creates a function that is invoked when an event happens, and this function checks to see if the event is the "close" event that indicates the X is clicked. If it is the "close" event, the program removes that function it created and lets the event take place, which then closes the window. If the event is not the "close" event, it just lets the event take place.

REBOL [
]

CLOSER: insert-event-func [ 
    either event/type = 'close [ 
        if true = request "OK to close?" [
            remove-event-func :CLOSER
        ] 
    ] [
        event
    ] 
] 

view layout [
    box 200x200 red "Click the corner X to demo"
]

Note in the above code a little point about REBOL. In the line to remove the event function, it removes the function by name, that is, by the name of CLOSER. That name must be preceded by a colon to indicate that one is referring to the name CLOSER. Without that colon, the interpreter would try to evaluate the word CLOSER which would mean to run the CLOSER function, which would not make sense because the CLOSER function is running already.

10.32 Editor

This is not technically a function of REBOL/View, as in something that you call and that returns a result, but it is a very handy part of REBOL that you can make use of.

REBOL has a built-in text editor. If you call it with an argument of a file name, it will open that file and display it in its editing window. If you call it with an argument of "none" it will pop up a blank editing window.

editor none

A very handy feature of the editor is that if the file you are editing is a REBOL program, you can press the F5 key to run the program.

10.33 Browse

Another function that is not really a "view" function but is really handy is "browse." This takes the argument of a URL or a file name (in a format that makes sense, like html), and runs the default web browser to view it. This makes it handy to use the web browser for reporting, since REBOL does not have any native printing capability. Format a report in html, pop up a browser as a "print preview," and then use the browser's printing function to print it.

browse http://www.rebol.com

You can "browse" unexpected things. If you "browse" a PDF file, as an example, and the default web browser is configured with the propert helper program to handle a PDF file, it will come up.

10.34 Launch

This is not officially a "view" function, but has uses in a GUI program. If you have a GUI with, for example, a button that you want to use to open another window, you have a couple choices. You can use the "view" function to view a new window, and the new window will replace the old. You can use "view/new" which will make a second window. You could use the "call" function to run the interpreter with arguments to run another script. OR, you could use "launch" followed by the name of a REBOL script to run that other script.

11. Hacking around

If you read some of the VID documentation you get the impression that it is not totally complete. There are things that can be done, but how does one discover what those might be if they are not documented? A certain amount of self-help is needed when working with VID. For example, documentation on the drop-down does not mention how to modify a drop-down at run time. One might strongly suspect that it could be done. What is the approach to discovering if it can?

One way is to use the REBOL help to probe around and see what there is to be seen. In the example below, we make a layout that has a drop-down on it, and gives that drop-down a name. We use "dd" because it is short. In addition to the drop-down, we have a button that will execute the "halt" function to bring us to a command prompt, so we can look around.

REBOL []
view layout [
    dd: drop-down 200 data ["aaa" "bbb" "ccc"]
    button "Debug" [halt]
]

Run the script and click the button and you get a command prompt.

Use the command "help dd" or "? dd" and you will get the following:

>> ? dd
DD is an object of value:
   type            word!     face
   offset          pair!     20x20
   size            pair!     200x24
   span            none!     none
   pane            object!   [type offset size span pane text color image effec...
   text            none!     none
   color           tuple!    255.255.255
   image           none!     none
   effect          none!     none
   data            none!     none
   edge            object!   [color image effect size]
   font            object!   [name style size color offset space align valign s...
   para            object!   [origin margin indent tabs wrap? scroll]
   feel            object!   [redraw detect over engage]
   saved-area      none!     none
   rate            none!     none
   show?           logic!    true
   options         none!     none
   parent-face     object!   [type offset size span pane text color image effec...
   old-offset      pair!     20x20
   old-size        pair!     200x24
   line-list       none!     none
   changes         none!     none
   face-flags      integer!  0
   action          none!     none
   state           logic!    false
   access          object!   [set-face* get-face* clear-face* reset-face*]
   style           word!     drop-down
   alt-action      none!     none
   facets          none!     none
   related         none!     none
   words           none!     none
   colors          block!    length: 2
   texts           none!     none
   images          none!     none
   file            none!     none
   var             word!     dd
   keycode         none!     none
   reset           function! []
   styles          none!     none
   init            block!    length: 0
   multi           object!   [text size file image color block]
   blinker         none!     none
   pane-size       pair!     240x96
   dirty?          none!     none
   help            none!     none
   user-data       none!     none
   flags           block!    length: 2
   doc             object!   [info string image logic integer pair tuple file u...
   xy              none!     none
   list-lay        none!     none
   show-arrow?     logic!    true
   rows            integer!  4
   list-data       block!    length: 3
   arrow-button    object!   [type offset size span pane text color image effec...
   show-dropdown   function! [/local tl picked]
   resize          function! [new-size [pair! none!]]

What would you do with the above information? You would use your experience with other REBOL functions, your imagination, and some sample scripts you would write, and you would discover things.

For example, you might spot the item called "list-data" and see that it has a lengh of 3. "list-data" is a very suggestive name, and the length of 3 is the same as the size of the list in your script. So you might do this:

>> ? dd/list-data
DD/LIST-DATA is a block of value: ["aaa" "bbb" "ccc"]
>>

This shows where the values are, and so you might then write a sample script to modify list-data and see what happens. Or try it at the command line:

>> dd/list-data: "ddd"
== "ddd"

And then check the result:

>> ? dd/list-data
DD/LIST-DATA is a string of value: "ddd"
>>

You might try the above concept in a script, and you might discover that it is not quite working. Maybe you change the list-data but it doesn't seem to totally change. So then you might spot the "reset" function and wonder if that is relevant. You might try using the "reset" function before changing list-data values and discover that things finally work as desired.

A process like the one outlined above is something you might have to do when using VID because VID seems to be sort of frozen in time and that now is the only way to find out all it can do.

If you like to get your hands dirty so to speak, there is a keyword "with" that can be used to modify the various items in a face. What you can modify safely, and what will break, is something you would have to discover on your own. The "with" keyword will let you modify things as you create layouts, but those changes might or might not be overwritten when the layout is generated, depending on just how a layout is generated. The following example gives the idea. Thanks to Chris on rebolforum for the sample.

REBOL []
view layout [ 
     box with [color: red size: 200x100] 
     box green 50x100 with [color: red size: 200x100] 
     box with [color: red] blue 
]

Another thing you can do that could turn up useful information is capture the source code for styles and examine it. The script below will capture the source in text file for all styles and put those files in a folder of our choosing. You then can examine each with any text editor.

REBOL [
    Title: "Extract code for all VID styles"
]
;; [---------------------------------------------------------------------------]
;; [ This is a little utility program for extracting the code behind all the   ]
;; [ VID styles and writing the code for each style into a text file named     ]
;; [ <style-name>.txt.  These files then can be examined with a text editor.   ]
;; [ First make a folder for your output.                                      ]
;; [---------------------------------------------------------------------------]
CODE-FILENAME: none  ;; will generate name based on style-dot-txt
CODE-DIR: request-dir
if not CODE-DIR [
    alert "No folder selected for output"
    quit
]
change-dir CODE-DIR
foreach [STYLE-WORD STYLE-CODE] svv/vid-styles [
    CODE-FILENAME: copy ""
    CODE-FILENAME: to-file rejoin [
        to-string STYLE-WORD
        ".txt"
    ]
    write CODE-FILENAME STYLE-CODE
]
alert rejoin [
    "Code files created in " 
    CODE-DIR
]

12. Some common operations

This section shows some little things harvested from various places. They show some practical uses of VID, or maybe how to do something tricky, or maybe something you wouldn't immediately think of doing. But here is a question you should ask yourself.

VID provides default sizing and spacing and coloring for its various styles. All those can be changed. You have a lot of freedom to change how things look. But the question is, is it worth it?

Another very useful feature of VID is that it is very quick to whip up a window for some use, taking the default sizing and spacing and coloring. It is more valuable to you to be able to create a useful application quickly, or is it more valuable to fuss and tweak interminably to get the appearance just-so? If you look around on the internet, you might run into comments about REBOL that its interface looks "dated" and that it doesn't do menus, and other comments about its age. REBOL 2 is indeed frozen, it seems, but it still does what it does, and the ability to make a useful application quickly might be, for some people, a worthwhile trade-off for an appearance that some might call "better" only because it looks more like what is currently fashionable. "Different" is "better" only if it is better, not just because it is different.

12.1 Putting a clock on a window

Sometimes it is a nice touch to put a clock on a window. The code for that is a handful of lines and shows how to use the "rate" facet and the "feel" facet.

REBOL [
    Title: "VID test harness"
]

view layout [
    MAIN-TIME: h1 100 red black (to string! now/time) 
        rate 1                            
        feel [
            engage: [                     
                MAIN-TIME/text: now/time          
                show MAIN-TIME
            ]
        ]          
]

12.2 Basic data entry

A very common thing to do with a computer is to collect some data and do something with it. That could be one of the first things a person thinks of when learning a programming language. "OK, I understand that I can make a window with all these things in it, but now what do I actually DO to get something useful done?"

The example below shows one useful thing, namely, getting input from an operator and doing something with it. The example just feeds it back. Normally one would do more, but you can see in the example that the data from the window is available in some "variables" (WS-FIELD-1, etc.), so from that point you could do other stuff.

The example is laid out in one particular way, but that is not the "right" way or the only way. It just a "way" that is helpful to the author for keeping things organized. Notice for example that the field labels in the window have a standard prefix. That helps identify items when they are used elsewhere in a large program. Notice that the actions for the buttons are encapsulated in functions, and the action block for a button is just a function call. It would not have to be that way, that is, the code could all be in-line in the layout, but the function calls make things tidy.

Another thing that is not required is the pseudo-declarations of WS-FIELD-1 etc. You could just refer to MAIN-FIELD-1/text wherever you wanted to. Or, if you did want WS-FIELD-1, you still would not have to pseudo-declare it by setting an initial value. Doing so is just a personal preference. But, one thing it does accomplish is that by grabbing window data and putting it into WS-FIELD-1 etc., WS-FIELD-1 et al are global words that can be "probed" with the "probe" command at a command prompt if the program crashes, or at the command prompt that would become available if you clicked the "Halt" button.

In other words, the example is laid out in a rather plodding manner by design.

REBOL [
    Title: "VID test harness"
]

WS-FIELD-1: ""
WS-FIELD-2: ""
WS-FIELD-3: ""
WS-FIELD-4: ""
WS-FIELD-5: ""

GET-WINDOW-DATA: does [
    WS-FIELD-1: copy ""
    WS-FIELD-2: copy ""
    WS-FIELD-3: copy ""
    WS-FIELD-4: copy ""
    WS-FIELD-5: copy ""
    WS-FIELD-1: trim copy get-face MAIN-FIELD-1
;; or.. WS-FIELD-1: trim copy MAIN-FIELD-1/text
    WS-FIELD-2: trim copy get-face MAIN-FIELD-2
    WS-FIELD-3: trim copy get-face MAIN-FIELD-3
    WS-FIELD-4: trim copy get-face MAIN-FIELD-4
    WS-FIELD-5: trim copy get-face MAIN-FIELD-5
]

PROCESS-WINDOW-DATA: does [
    set-face MAIN-FEEDBACK-1 WS-FIELD-1
;; or.. MAIN-FEEDBACK-1/text: copy WS-FIELD-1
;; .... show MAIN-FEEDBACK-1
    set-face MAIN-FEEDBACK-2 WS-FIELD-2
    set-face MAIN-FEEDBACK-3 WS-FIELD-3
    set-face MAIN-FEEDBACK-4 WS-FIELD-4
    set-face MAIN-FEEDBACK-5 WS-FIELD-5
]

CLEAR-BUTTON: does [
    clear-fields MAIN-WINDOW
    show MAIN-WINDOW 
]

SUBMIT-BUTTON: does [
    GET-WINDOW-DATA
    PROCESS-WINDOW-DATA
]

MAIN-WINDOW: layout [
    across
    banner "Data entry window"
    return
    label "Field 1"
    tab
    MAIN-FIELD-1: field 200 
    MAIN-FEEDBACK-1: info 200
    return
    label "Field 2"
    tab
    MAIN-FIELD-2: field 200 
    MAIN-FEEDBACK-2: info 200
    return
    label "Field 3"
    tab
    MAIN-FIELD-3: field 200 
    MAIN-FEEDBACK-3: info 200
    return
    label "Field 4"
    tab
    MAIN-FIELD-4: field 200 
    MAIN-FEEDBACK-4: info 200
    return
    label "Field 5"
    tab
    MAIN-FIELD-5: field 200 
    MAIN-FEEDBACK-5: info 200
    return
    button "Submit" [SUBMIT-BUTTON]
    button "Clear" [CLEAR-BUTTON] 
    button "Quit" [quit]
    button "halt" [halt] ;; for debugging 
]

view center-face MAIN-WINDOW

12.3 Get a valid date in a field

A common field on a form is a date. If you let people enter dates as they like, you have many possible formats, and so you have to write code to make sense of the input and reformat it to some standard form, like a REBOL-compatible date or maybe YYYYMMDD. Here are some options for using the request-date function to make sure a field of date input is consistent.

Note that the date "field" is an "info" style so that direct input is not possible. The way to get a date is to left-click the info field which activates the request-date function and the fills in the field for you.

To test this script, copy the whole thing to a file on your computer and run it, since it includes the REBOL header.

Note also the code to request a date and put it into YYYYMMDD format. It uses the "year," "month," and "day" refinements to get the year, month, and day. But, REBOL will return those items as single digits if the value is less than ten. So to make sure we have two digits for the month and day, we reverse the number, add a zero to the end, reverse it again, and copy off the first two digits. That might be a clumsy way. Studying the REBOL documentation might turn up something better.

REBOL [
]

GET-YYYYMMDD: does [
    TEMP-DATE: request-date
    either TEMP-DATE [
        TEMP-YYYYMMDD: to-string rejoin [
            TEMP-DATE/year
            reverse copy/part reverse join 0 TEMP-DATE/month 2
            reverse copy/part reverse join 0 TEMP-DATE/day 2
        ]
    ] [
        TEMP-YYYYMMDD: "00000000"
    ]
    return TEMP-YYYYMMDD
]

GET-YYYYMMDD-DATE: does [
    set-face DATE-YYYYMMDD GET-YYYYMMDD 
]

GET-REBOL-DATE: does [
    set-face DATE-REBOL to-string request-date
] 

view layout [
    across
    label "Date in REBOL format" 
    DATE-REBOL: info 100 [GET-REBOL-DATE]
    return
    label "Date in YYYYMMDD format" 
    DATE-YYYYMMDD: info 100 [GET-YYYYMMDD-DATE]  
    return
    button "Quit" [quit]
    button "Debug" [halt] 
]

12.4 Scrolling a text field

Scrolling through things that don't fit in a window is a very common thing to do. Here is an example of scrolling a big text field. It would take very little work to modify this example for a general-purpose text viewer.

REBOL [
    Title: "Scrolling a text field"
]

TEXT-DATA: {SCROLLING A TEXT FIELD
This is a scroller demo from the REBOL cookbook, with annotations to      
describe some of the obscure points.
The key understanding is that TEXT-WINDOW it an interface object, and its text 
value can be envisioned as a rectangle of pixels, with the text "displayed" on   
it.
Only a part shows through the window. The para/scroll/y value shows the    
starting point from which text is displayed. This value starts at zero when 
the text is displayed at the top, and "increases" in a negative direction  
because the text area can be envisioned as a grid with the top left corner 
being 0x0--thus "down" the text would be in a negative y direction like    
the coordinates in algebra. The display window also is a rectangle of      
pixels, and displaying in it starts at 0x0.
The size/y value is the vertical size of the text window. The user-data     
value is the vertical size of the text. The (user-data minus size/y)       
expression is evaluated first. The result of that calculation represents   
a point in the text value somewhere back from the maximum value, that is,  
back from the end. That point, back from the end, is back by a distance    
equal to the size of the display window. In other words, it is the point   
in the text value where, if the text is displayed from that point forward, 
you will hit the end of the text when you hit the end of the window. In    
other words, it is the point where you start to display text when you are  
displaying the last page.
The para/scroll/y value is going to vary from zero (the top of the text)   
to the result of the above calculation (the last page), as you operate     
the scroller. That is why the (user-data minus size/y) result is           
multiplied by the data value of the scroller (which is a fraction in       
the range of zero to one). Somewhere in that range of zero through         
(user-data minus size/y) is where we want to start displaying a window     
of text.
The reason for the max function is that it could happen that the text      
is SMALLER than the window. In that case, (user-data minus size/y) will    
be negative (and will be negated later giving a positive value), and we    
don't want that. Instead, we want to display from the top all the time,    
and thus want para/scroll/y to be zero.
We negate the para/scroll/y value because we are going "down" the           
text in a negative y direction. 

In this example, we have a separate function to load the text into
the viewing window.  The reason for this is to show that this function
could be generalized and the viewing window could be reloaded with
a second batch of text, and to show what data items must be set up
to make the scrolling work.  There are a few things that must be done,
and they don't jump out of the regular VID documentation.

When we load a fresh batch of text, we set the para/scroll/y value
to zero so that when we do the first "show" of the text we are at
the top.

When we load a fresh batch of text, we set the "data" facet of the
scroller to zero to position it at the top.

When we load fresh text, the line-list must be set to none.

We store, in the user-data facet of the text area, the "y" size of
the text in the text area.  That is what the "size-text" function does,
it gets the size of the text that is in a text field.  We use the
"second" function because the size is a "pair" and the second part
of the pair is the "y" dimension.

The "TEXT-SCROLLER/redrag..." line sets the size of the little thing
that you grab and move in the scroller.  It must be sized appropriately
so it looks correct for the size of the text relative to the size of
the window.  The size/y item is the "y" size of the text window.
The user-data facet holds the "y" size of the whole chunk of text
in the text field.  Dividing the visible size by the total size gives
a result that is used to set the size of the scroll thing. 
(We are not exactly sure what is going on here.)

Another point to note about this example is how the TEXT-WINDOW and
TEXT-SCROLLER are objects in the layout, and they are passed as
arguments to the TEXT-SCROLL function.  You would not have to do it
that way, but it is interesting that you can.  That means that you 
could in theory write a general scrolling procedure for any text field.
---------------------------------------------------------------------------
}

TEXT-DISPLAY: center-face layout [
    across
    h3 "Scrolling a large text field" 
    return
    space 0
    TEXT-WINDOW: text 600x600 wrap green black font-name font-fixed 
    TEXT-SCROLLER: scroller 16x600 [TEXT-SCROLL TEXT-WINDOW TEXT-SCROLLER]
    return
    pad 0x5 
    space 5
    button "Close" [quit]                
]

TEXT-SCROLL: func [PASSED-TEXT PASSED-SCROLLER] [
    PASSED-TEXT/para/scroll/y: negate PASSED-SCROLLER/data *
        (max 0 PASSED-TEXT/user-data - PASSED-TEXT/size/y)
    show PASSED-TEXT
]

TEXT-LOAD: func [TEXT-TO-SHOW] [
    TEXT-WINDOW/text: TEXT-TO-SHOW 
    TEXT-WINDOW/para/scroll/y: 0
    TEXT-SCROLLER/data: 0
    TEXT-WINDOW/line-list: none
    TEXT-WINDOW/user-data: second size-text TEXT-WINDOW
    TEXT-SCROLLER/redrag TEXT-WINDOW/size/y / TEXT-WINDOW/user-data
]

TEXT-LOAD TEXT-DATA
view TEXT-DISPLAY

12.5 Scrolling a layout

Text is not the only thing that can be scrolled. With REBOL you can make sub-layouts, and they can be scrolled. This opens up interesting possibilities for windows that are too long to fit on a physical monitor. The following example was harvested from the internet, so the notes about how it works are comments in the code.

;; [---------------------------------------------------------------------------]
;; [ This script shows how one might make a scrolling panel of buttons and     ]
;; [ such.  This could be useful if one had an application that had a lot      ]
;; [ of buttons, and was run on a physical screen such that all those          ]
;; [ buttons could not show at one time.  One could put the buttons in a       ]
;; [ box and scroll through them.                                              ]
;; [                                                                           ]
;; [ The explanation below is a bit lengthy because at the time of writing     ]
;; [ I still am trying to get a firm understanding of the use of the scroller. ]
;; [ This was written after examining Carl's cookbook article number 36        ]
;; [ called "Scrolling a GUI panel."                                           ]
;; [                                                                           ]
;; [ Here are some concepts you probably know but must get firmly into your    ]
;; [ head so you don't continually have to remember them.                      ]
;; [                                                                           ]
;; [ When you display something, on a screen or in a window, that item has     ]
;; [ an "offset" which is a pair of numbers (x and y) that show where it       ]
;; [ is displayed starting from the top left corner of wherever you are        ]
;; [ displaying it.  The offset of the top left corner is 0x0.  As you move    ]
;; [ to the right, the first number (x) gets bigger; as you move down, the     ]
;; [ second number (y) gets bigger.  If you are displaying something on a      ]
;; [ screen, the offset refers to the position relative to the top left        ]
;; [ corner of the screen.  If you are displaying something in a box in a      ]
;; [ window, the offset refers to the position relative to the top left        ]
;; [ corner of that container inside which you are displaying it.              ]
;; [ You can refer to the x and y parts of the offset separately, as in        ]
;; [ offset/x and offset/y.  An offset can be negative, which seems to         ]
;; [ make no sense, but actually does, as will be shown below.                 ]
;; [                                                                           ]
;; [ A "face," or "interface object," (like a button, box, area, and so on)    ]
;; [ has an attribute called "pane" which is something that holds one or       ]
;; [ more interface objects inside the original face.                          ]
;; [ This is what allows you, in this example, to put a bunch of buttons       ]
;; [ inside a box, because the "pane" of the box holds all the buttons.        ]
;; [ The box is a "face" ("interface object") and the "pane" of the box        ]
;; [ can hold more "faces" ("interface objects").                              ]
;; [                                                                           ]
;; [ You can get your hands on the size (in pixels) of certain interface       ]
;; [ object ("faces") with the "size" property, and you can get the x and y    ]
;; [ sizes by referring to size/x and size/y, as shown below.                  ]
;; [                                                                           ]
;; [ When you activate a scroller, a property of the scroller called "data"    ]
;; [ changes from zero (when the scroller is at the low end) to one (when      ]
;; [ the scroller is at the high end.  In VID code, if you declare             ]
;; [ a scroller and put a block on it in which you have REBOL code (or a       ]
;; [ function call), that code or function will be executed every time you     ]
;; [ move that scroller.  In that code or function, you can access the         ]
;; [ "data" property to decide where the scroller is.                          ]
;; [                                                                           ]
;; [ The following item will show well only if you are displaying this         ]
;; [ code in a text editor with a fixed font.                                  ]
;; [                                                                           ]
;; [ If you have a box, and in the "pane" of that box you have more stuff      ]
;; [ than can show in the box, you have a situation that looks like this:      ]
;; [ (In this example, we are dealing only with an example of vertical         ]
;; [ scrolling.)                                                               ]
;; [                                                                           ]
;; [                                           +--------------+                ]
;; [                                           |1             |                ]
;; [                                           |2             |                ]
;; [                                           |3             |                ]
;; [                       Data when the       |4             |                ]
;; [                       scroller is at      |5             |                ]
;; [  Visible box          the top             |6             |                ]
;; [                                           |7             |                ]
;; [ +---------------+    +---------------+    |8             |                ]
;; [ |1              |    |1              |    |9             |                ]
;; [ |2              |    |2              |    |10            |                ]
;; [ |3              |    |3              |    |11            |                ]
;; [ |4              |    |4              |    |12            |                ]
;; [ |5              |    |5              |    |13            |                ]
;; [ |6              |    |6              |    |14            |                ]
;; [ |7              |    |7              |    |15            |                ]
;; [ |8              |    |8              |    |16            |                ]
;; [ |9              |    |9              |    |17            |                ]
;; [ |10             |    |10             |    |18            |                ]
;; [ |11             |    |11             |    |19            |                ]
;; [ |12             |    |12             |    |20            |                ]
;; [ +---------------+    |13             |    +--------------+                ]
;; [                      |14             |                                    ]
;; [                      |15             |     Data when the                  ]
;; [                      |16             |     scroller is at                 ]
;; [                      |17             |     the bottom                     ]
;; [                      |18             |                                    ]
;; [                      |19             |                                    ]
;; [                      |20             |                                    ]
;; [                      +---------------+                                    ]
;; [                                                                           ]
;; [ We will discuss this example in terms of lines rather than pixels for     ]
;; [ clarity.                                                                  ]
;; [                                                                           ]
;; [ On the left we have a box that shows 12 lines.  In the "pane" of that     ]
;; [ box we have 20 lines.  Not all lines can show at the same time.           ]
;; [ Somewhere we have a scroller that controls the display in that box.       ]
;; [ When the scroller is at the top, the data is displayed as shown in        ]
;; [ the middle area, where the first line is at the top of the box            ]
;; [ and lines 13-20 don't show.  When the scroller is at the bottom,          ]
;; [ the data is displayed as shown in the right area, where the last line     ]
;; [ is at the bottom of the box and lines 1-8 don't show.                     ]
;; [                                                                           ]
;; [ The question being answered by this script is, what do we do to make      ]
;; [ the contents of the pane scroll up and down properly inside the container ]
;; [ that contains that pane?                                                  ]
;; [                                                                           ]
;; [ What we do is conceptually very simple.  The "pane" is what contains      ]
;; [ the stuff we want to show.  We adjust the "offset" of that pane, the      ]
;; [ "y" (vertical) value only, and then redisplay (show) the container        ]
;; [ that contains that pane.                                                  ]
;; [                                                                           ]
;; [ To understand what to do, it helps to consider the boundaries.            ]
;; [ When the scroller is at the top, the offset/y of the pane will be zero.   ]
;; [ That means that the pane starts at the top of the container.              ]
;; [ What will the offset be when the scroller is at the end?                  ]
;; [ The answer is that the offset will be negative.  A negative number        ]
;; [ for the offset/y means that the display will start at some place          ]
;; [ above the box.  How far above the box?  Far enough so that the last       ]
;; [ line of the data will be at the bottom of the box.  How far is that?      ]
;; [ The answer is that it is an amount that is the difference between         ]
;; [ the size of the stuff you want to show and the space you have to show it. ]
;; [ In the above example, you have 20 lines you want to show, but only        ]
;; [ 12 lines to show it, so 20 minus 12 gives 8, which means that if you      ]
;; [ show the pane with an offset of negative 8, it will fall into the         ]
;; [ container such that line 20 of the data is at line 12 of the box.         ]
;; [                                                                           ]
;; [ The above is concept is very important.  When you scroll the box,         ]
;; [ the offset/y of the pane is going to vary from zero to a number that      ]
;; [ is the amount by which the data overflows the container.  If the data     ]
;; [ is smaller than the container, we want no scrolling to take place,        ]
;; [ so we will want to leave the offset/y at zero.                            ]
;; [                                                                           ]
;; [ So where does the scroller fit into this?  The scroller varies from       ]
;; [ zero to one.  It is a fraction.  It is the fractional amount of that      ]
;; [ total possible amount of scrolling.  In the above example, the total      ]
;; [ "travel" in that scroller is 8.  Eight is the amount that won't fit       ]
;; [ in the visible container.  Eight is the highest amount we will have       ]
;; [ to scroll, and a negative eight is the highest offset we will need        ]
;; [ to scroll to the bottom.  So what we do with the scroller is apply        ]
;; [ that fractional value to that maximimum possible offset to get the        ]
;; [ new offset represented by the scroller position.  When the scroller       ]
;; [ is at the half-way point, we multiply the maximum possible offset of      ]
;; [ eight by the scroller value of .5 to get a new offset of 4, or,           ]
;; [ actually, negative 4 because we are scrolling down and so want the        ]
;; [ data to display from a point four lines "higher" (a negative offset).     ]
;; [                                                                           ]
;; [ To put it all together into a tidy calculation, when we operate the       ]
;; [ scroller we want to do the following.                                     ]
;; [                                                                           ]
;; [ Subtract the size of the container from the size of the stuff we want     ]
;; [ to put in the container.  This gives us the maximum amount we possibly    ]
;; [ could have to scroll.  If the container is bigger that the stuff we       ]
;; [ want to show, use zero for that maximum amount because we don't want      ]
;; [ to do any scrolling.                                                      ]
;; [                                                                           ]
;; [ Multiply that maximum possible offset value by the fractional amount      ]
;; [ provided by the scroller.  That gives us the actual amount of offset      ]
;; [ we want to apply.                                                         ]
;; [                                                                           ]
;; [ Negate the amount we calculated, because if we are scrolling "down,"      ]
;; [ that means we have to start displaying the front of the data from         ]
;; [ some point "up," meaning the offset must be negative.                     ]
;; [                                                                           ]
;; [ When we calculate this new offset for the data inside the container       ]
;; [ (the "pane"), set that offset/y value of that pane and then               ]
;; [ redisplay the contiainer that contains the pane.                          ]
;; [                                                                           ]
;; [ The example below shows a screen with a bunch of buttons, so many         ]
;; [ buttons that we want to put them into a box and scroll the box with       ]
;; [ a scroller.                                                               ]
;; [---------------------------------------------------------------------------]

;; [---------------------------------------------------------------------------]
;; [ This is the function that is called when the operator moves the           ]
;; [ scroller so much as a pixel.                                              ]
;; [                                                                           ]
;; [ In REBOL examples on the internet, you usually see the scroller or        ]
;; [ its "data" property passed to such a procedure.  In this example,         ]
;; [ we just refer to the scroller based on its name in the layout.            ]
;; [ The reason for this is so that we don't have any local variables in       ]
;; [ this function.  And the reason for not having local variables is so       ]
;; [ that when the operator clicks the "Debug halt" button and the program     ]
;; [ halts, he then can examine the various words in this program.             ]
;; [ If those word were local, they would not be available.                    ]
;; [ Remember that this is a demo and not a "real" program.                    ]
;; [---------------------------------------------------------------------------]

SCROLL-BUTTON-LIST: does [

;;  -- Display the type of the pane inside the box.
    DEBUG-BUTTONBOX-TYPE/text: type? BUTTONBOX/pane
    show DEBUG-BUTTONBOX-TYPE

;;  -- Display the number from 0 to 1 produced by operating the scroller.
    DEBUG-SCROLLER-VALUE/text: to-string BUTTONSCROLLER/data
    show DEBUG-SCROLLER-VALUE

;;  -- Display the size of the box that holds the pane of buttons.
    DEBUG-BUTTONBOX-SIZE/text: to-string BUTTONBOX/size/y
    show DEBUG-BUTTONBOX-SIZE

;;  -- Display the size of the pane of buttons we put in the above box.
    DEBUG-BUTTONBOX-PANE-SIZE/text: to-string BUTTONBOX/pane/size/y
    show DEBUG-BUTTONBOX-PANE-SIZE

;;  -- Calculate the new button pane offset based on scroller input.
    NEW-OFFSET: negate BUTTONSCROLLER/data *
        (max 0 (BUTTONBOX/pane/size/y - BUTTONBOX/size/y))
    BUTTONBOX/pane/offset/y: NEW-OFFSET
    show BUTTONBOX

;;  -- Display the new offset for the button pane as we move the scroller
    DEBUG-BUTTONBOX-PANE-OFFSET/text: to-string NEW-OFFSET
    show DEBUG-BUTTONBOX-PANE-OFFSET

]

;; [---------------------------------------------------------------------------]
;; [ Below is a sub-layout, that is, a layout that we will put into a          ]
;; [ a box in the main window.  It is deliberately more buttons than will      ]
;; [ fit in the hard-coded size of the box.                                    ] 
;; [ The keyword "tight" causes this layout to be put into the box             ]
;; [ with no offset.                                                           ]
;; [---------------------------------------------------------------------------]
BUTTONLAYOUT: layout/tight [
    across
    button "button 01" [DEBUG-WHICH-BUTTON/text: "01" show DEBUG-WHICH-BUTTON]
    button "button 02" [DEBUG-WHICH-BUTTON/text: "02" show DEBUG-WHICH-BUTTON]
    button "button 03" [DEBUG-WHICH-BUTTON/text: "03" show DEBUG-WHICH-BUTTON]
    button "button 04" [DEBUG-WHICH-BUTTON/text: "04" show DEBUG-WHICH-BUTTON]
    button "button 05" [DEBUG-WHICH-BUTTON/text: "05" show DEBUG-WHICH-BUTTON]
    return
    button "button 06" [DEBUG-WHICH-BUTTON/text: "06" show DEBUG-WHICH-BUTTON]
    button "button 07" [DEBUG-WHICH-BUTTON/text: "07" show DEBUG-WHICH-BUTTON]
    button "button 08" [DEBUG-WHICH-BUTTON/text: "08" show DEBUG-WHICH-BUTTON]
    button "button 09" [DEBUG-WHICH-BUTTON/text: "09" show DEBUG-WHICH-BUTTON]
    button "button 10" [DEBUG-WHICH-BUTTON/text: "10" show DEBUG-WHICH-BUTTON]
    return
    button "button 11" [DEBUG-WHICH-BUTTON/text: "11" show DEBUG-WHICH-BUTTON]
    button "button 12" [DEBUG-WHICH-BUTTON/text: "12" show DEBUG-WHICH-BUTTON]
    button "button 13" [DEBUG-WHICH-BUTTON/text: "13" show DEBUG-WHICH-BUTTON]
    button "button 14" [DEBUG-WHICH-BUTTON/text: "14" show DEBUG-WHICH-BUTTON]
    button "button 15" [DEBUG-WHICH-BUTTON/text: "15" show DEBUG-WHICH-BUTTON]
    return
    button "button 16" [DEBUG-WHICH-BUTTON/text: "16" show DEBUG-WHICH-BUTTON]
    button "button 17" [DEBUG-WHICH-BUTTON/text: "17" show DEBUG-WHICH-BUTTON]
    button "button 18" [DEBUG-WHICH-BUTTON/text: "18" show DEBUG-WHICH-BUTTON]
    button "button 19" [DEBUG-WHICH-BUTTON/text: "19" show DEBUG-WHICH-BUTTON]
    button "button 20" [DEBUG-WHICH-BUTTON/text: "20" show DEBUG-WHICH-BUTTON]
    return
    button "button 21" [DEBUG-WHICH-BUTTON/text: "21" show DEBUG-WHICH-BUTTON]
    button "button 22" [DEBUG-WHICH-BUTTON/text: "22" show DEBUG-WHICH-BUTTON]
    button "button 23" [DEBUG-WHICH-BUTTON/text: "23" show DEBUG-WHICH-BUTTON]
    button "button 24" [DEBUG-WHICH-BUTTON/text: "24" show DEBUG-WHICH-BUTTON]
    button "button 25" [DEBUG-WHICH-BUTTON/text: "25" show DEBUG-WHICH-BUTTON]
    return
    button "button 26" [DEBUG-WHICH-BUTTON/text: "26" show DEBUG-WHICH-BUTTON]
    button "button 27" [DEBUG-WHICH-BUTTON/text: "27" show DEBUG-WHICH-BUTTON]
    button "button 28" [DEBUG-WHICH-BUTTON/text: "28" show DEBUG-WHICH-BUTTON]
    button "button 29" [DEBUG-WHICH-BUTTON/text: "29" show DEBUG-WHICH-BUTTON]
    button "button 30" [DEBUG-WHICH-BUTTON/text: "30" show DEBUG-WHICH-BUTTON]
    return
    button "button 31" [DEBUG-WHICH-BUTTON/text: "31" show DEBUG-WHICH-BUTTON]
    button "button 32" [DEBUG-WHICH-BUTTON/text: "32" show DEBUG-WHICH-BUTTON]
    button "button 33" [DEBUG-WHICH-BUTTON/text: "33" show DEBUG-WHICH-BUTTON]
    button "button 34" [DEBUG-WHICH-BUTTON/text: "34" show DEBUG-WHICH-BUTTON]
    button "button 35" [DEBUG-WHICH-BUTTON/text: "35" show DEBUG-WHICH-BUTTON]
    return
    button "button 36" [DEBUG-WHICH-BUTTON/text: "36" show DEBUG-WHICH-BUTTON]
    button "button 37" [DEBUG-WHICH-BUTTON/text: "37" show DEBUG-WHICH-BUTTON]
    button "button 38" [DEBUG-WHICH-BUTTON/text: "38" show DEBUG-WHICH-BUTTON]
    button "button 39" [DEBUG-WHICH-BUTTON/text: "39" show DEBUG-WHICH-BUTTON]
    button "button 40" [DEBUG-WHICH-BUTTON/text: "40" show DEBUG-WHICH-BUTTON]
    return
    button "button 41" [DEBUG-WHICH-BUTTON/text: "41" show DEBUG-WHICH-BUTTON]
    button "button 42" [DEBUG-WHICH-BUTTON/text: "42" show DEBUG-WHICH-BUTTON]
    button "button 43" [DEBUG-WHICH-BUTTON/text: "43" show DEBUG-WHICH-BUTTON]
    button "button 44" [DEBUG-WHICH-BUTTON/text: "44" show DEBUG-WHICH-BUTTON]
    button "button 45" [DEBUG-WHICH-BUTTON/text: "45" show DEBUG-WHICH-BUTTON]
    return
    button "button 46" [DEBUG-WHICH-BUTTON/text: "46" show DEBUG-WHICH-BUTTON]
    button "button 47" [DEBUG-WHICH-BUTTON/text: "47" show DEBUG-WHICH-BUTTON]
    button "button 48" [DEBUG-WHICH-BUTTON/text: "48" show DEBUG-WHICH-BUTTON]
    button "button 49" [DEBUG-WHICH-BUTTON/text: "49" show DEBUG-WHICH-BUTTON]
    button "button 50" [DEBUG-WHICH-BUTTON/text: "50" show DEBUG-WHICH-BUTTON]
] 

;; [---------------------------------------------------------------------------]
;; [ This is the main window.                                                  ]
;; [ It has some buttons, and places for displaying debugging information,     ]
;; [ and then it has a box of a defined size into which we will place the      ]
;; [ above sub-layout of buttons.                                              ]
;; [ The above sub-layout of buttons is too big for this box.                  ]
;; [---------------------------------------------------------------------------]

MAIN-WINDOW: layout [
    across
    vh1 "Scrolling button panel test"
    return
    button "Quit" [quit]
    button "Debug halt" [halt]
    return
    vh2 "Start of sub-layout box"
    return
;;  -- Sub-panel and scroller
    BUTTONBOX: box 550x200
    BUTTONSCROLLER: scroller 16x200 [SCROLL-BUTTON-LIST]
;;  --
    return
    vh2 "End of sub-layout box"
    return
;;  -- Debugging data
    label "Button pressed: "
    DEBUG-WHICH-BUTTON: text "Button pressed"
    return
    label "type? BUTTONBOX/pane "
    DEBUG-BUTTONBOX-TYPE: text "Pane type"
    return
    label "BUTTONSCROLLER/data "
    DEBUG-SCROLLER-VALUE: text "Scroller value"
    return
    label "BUTTONBOX/size/y "
    DEBUG-BUTTONBOX-SIZE: text "Box y"
    return
    label "BUTTONBOX/pane/size/y "
    DEBUG-BUTTONBOX-PANE-SIZE: text "Pane y"
    return
    label "BUTTONBOX/pane/offset/y "
    DEBUG-BUTTONBOX-PANE-OFFSET: text "Pane offset"
]

;; [---------------------------------------------------------------------------]
;; [ Before we display the main window, load the box with the sub-layout       ]
;; [ of buttons.  This sub-layout goes into the "pane" property.               ]
;; [---------------------------------------------------------------------------]

BUTTONBOX/pane: BUTTONLAYOUT 

;; [---------------------------------------------------------------------------]
;; [ Display the main window and wait for input.                               ]
;; [---------------------------------------------------------------------------]

view MAIN-WINDOW

12.6 Embedding an image

As indicated earlier, you can put an image in a window by using the keyword "image" to specify an image, followed by a file name to identify a file that contains the image. There is another way to put an image on a window, and it is handy for something like a logo that always is present, or for a demo where you want everyting in one file, or some other similar situation.

There are a couple ways you could approach this, but here is one way. First, make yourself a little toolbox of utilities, and include the following function. This function reads a specified image file and converts it to base 64 encoding. It puts the resulting string on the clipboard.

IMAGE-STRING: does [
    system/options/binary-base: 64
    IMAGESTRING-FILE: request-file/only
    if not IMAGESTRING-FILE [
        alert "No file specified"
        exit
    ]
    IMAGESTRING-STRING: read/binary IMAGESTRING-FILE
    save clipboard:// IMAGESTRING-STRING
    alert "Hex representation of image is on the clipboard"
]

Then, in some script you would write, execute the above function as follows, which will result in a hex representation of a graphic file put on the clipboard.

IMAGE-STRING

Now, in the program where you want the embedded image, pick a name for the image and put it on a line of code. This example uses the REBOL logo, so we will pick a name of REBOL-LOGO. Code it like this, and press the enter key after the "load."

REBOL-LOGO: load

Finally, copy the clipboard. In windows, press the CTRL-V key. The result will look like this:

REBOL-LOGO: load
64#{
R0lGODlhsAAsAOYAAAICAoGDe0hBPsTEwCYnIailnmBiW+Ph3DQ2M7m3sXNwaU1T
TJqWktTRzBYWFvLx746NhC8tKqupp2VmYjk+Ob65tFxaVQ8QDtbW1uzr6ElMR8zO
yXZ3b/7+/iIhH1ZbVrOxq5eXjoF+eKGhocvJxeXl49jX0m1vZomMhDs5NLi6t5KR
i3p8eaCfmB4gG0A+OlRUTlBMRgoKCigqJ6uqonJycPf28zEyLa6vp2tpZMK/uNzb
14eFfmZkXEBDP0dGQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAACwAAAAAsAAsAAAH/4AdgoOEhYaHiImKi4yNjo+QkZKTlJWW
l5iZmpucnZ6foKGio6SlpqeoqZk2KhMuMrCxsrO0tba3uLm6u7EAFz4gkxk8BDIA
vMizFy8rB4sZEggA09TV1tfY2drb3N3e1hEQOzaUDzoWxt/q2DkliiMw6/Lz9PXX
HivuljY6P/brDoIlQnDhn8GDCAF4CEEu04AXCblNUBSxosVuDiA01JQgxcVrCCh+
HPlRRo8Mngq4IDnNg8htF2bciECzZs0ZHgp6u3DjxUybNnvO4OYAqFEH6bil0LHI
xgESKkAk2FBiI6IMNbRdIPAzgoek6ma81EahgI4EaNOmBUEDggad2/98TK0gVW1a
HSR4ONDmQEGFs3YT0G1xYug2BwGsFnqwIYQBChEIzPAxocU4RSQ8YkPQ4myFCjxW
yhObqBsMfYt2cICbzYBiRDoiaIuQgJGNBBrAWvOxIZGJAASxOfjRLJENFKypLUDd
QYfhdaQRdePtqMQE3dY+ME8EQna2GwIZ6biRzcGKRCTicbtggESiDdKuacBACASB
edEPdaPgflCGDSqoMABKhFRAnjbaEZJBAww2aEIDKHgwGw2EPECCVBs8QIgNJ2AH
AAK9HdKAet7AsMNVE2AzX333jTZWNtQJwg8MN/QEAYGCNKDBNgkOokMPAsQgZAww
xBCBh9NEgAP/ISRYMMNkLWg4CHLXmCRlIQekqI4MKFy5IQTYrTiIffi9iE2MHdhA
A1y0EbKBPwgyR8Ne8ihZn2gAwGDCIA90eM0FIhxiQwt4UiPDDAgUSg0CAyBSAJ3V
iCkImS6Wxg2aNuBApwwv1DbImzwylwACDsxAk6kzQIqNnYMM4MMFF/R1oiAbaGbN
BRAcUkIO1zhggFkt5HZrYocMcGCk9I3ZInRmXoPpAAYgoIECIHjZXaiEHFDACjTg
4C0IEpygKjhL+ldAADy00EBDO+SQ3DQOtHDIBj5YI8MEewpCwo7WGIAjITssIF+y
ky4bVrO7hSjIAyYMQBWWPSA5TY8bGmLg/2zlDmLDA1bZAMG708ygQrG2ToPAyITQ
YDAAMRBMyK4Ds1impXEpnEgJOuQw7jUUY1YyubbRICxI/RUywM/tFGICBdYI0MAh
GSigm6QdUMoszdqgmaZiD7Rwg8TU9GzDDiRswOAGJuzQwnPXsCoj2SSQ4IyMDRjw
LgJFE6JDfNQkTUgDfE/jNNQKxKzszNJdqrANDTAAwkY2FOAdNz03cIIPPwipAQwG
vIrx3xz44MMLPTTa6s8AiFxs4B9WUEgL48IwN5YWGF4w4voprjEOBESA8sI0HBsn
ITgo6o3bHSRgsAI4ZmBAr/IaYgKJ08hgQL4duGrvCV4OggG/yBJvfP83+Rky3eKa
AmDB7GmuAHI1PRfw/jbIgyBh9SLg2KduFwRwyAM8SM4FLNACEISgXtZwAEPmxTRr
UI0GojEGLMiHsGpgikwOYEAhdkA9bPRsABZ4wQJgQEISfu1zg2gAB37wAxjw4Gn+
qZ29FPCaDpAAIvZyQQR2xjIYGqJ4trMhBwyQgxycIAAnmFw2yleI/SyOUj/woSBU
gi0+NYAEaTNBFlcwviRRSGMHeJAJumcsbCxHUCHg4RIfJygeqMhlTjmAHEvwgB3I
UBtMJIQTCaE8ePHASwe4owe3g4gEKBEc4XnGdbAxA08Z4gBS84YLFniIHYAvfIpw
HtjyOIhunLH/Vc9BgCMF8RBtGKB7sBGeNW7AFEaYgANqvAAHatiBHYjgfrNZASrH
NL5PJiIDPeAGJwXRDQ1kqAQZKEEBlmW9BjygBFXZwfOyYaIOJDMD2MwmNh/wgGVq
gwABiEoLWlCAcnqLBgwIAQQWMD8ALOWXNLAAAVgjAwfcYAIJ2OXCCoeNKG7NBgAN
KDmmJ8wKUsMFH8hBDxb6A9Y4AAYK7YECJqDKanjgBDzgwAk2ylGOcoADQ8OGDLgS
mSeZNAIzcIED1FgNWdIyTTsAAQo4oICNciAEKmDfISpwyINOAAUBEIFQhyoCHqAg
Byu7xjA74A0ZXEAW2HiqU8HmCwfA6qpYtL0qVSPCSkY8IJkHQKY+FRRMraz0rGhd
aTtbYlCWuHUdMlhfJ2yQRre6BGtvzSs9ZPkvTICgoheJgCJYqtfCHoYFfa2EDlD3
EQsoogY9Naxk+YJYTAxAAHm9wAgUUYIRRHayoG0pDEwnjBUk9SMXqOwiNsACUqX1
tbCNrWxnS9va2ra2sEqBBF76ywC4AFa3DS5aL+CBD0hgrKpIrnKXy9zmOve50I2u
dKdL3epa97rY3UQgAAA7
}

Now, when you make a layout, you can embed the REBOL logo with this line:

image REBOL-LOGO

12.7 Getting all file names of a particular type

Sometimes you might want to do something to all files of a particular type in a particular folder. Maybe you want to find all image files for viewing, or all text files for some sort of processing. Here is an example of how to do that. The procedure requests a folder name, then reads all the file names in that folder, resulting in a block, then goes through that block removing all file names that are not of the desired type.

The "print" at the end is just for demo purposes. Normally, one would create the list of files and do something with it besides just print it.

IMAGE-FILE?: func ["Returns true if file is an image" FILE-ID] [
    find [%.bmp %.jpg %.jpeg %.gif %.png] find/last FILE-ID "."
]
REQUESTED-FOLDER: request-dir
if not REQUESTED-FOLDER [
    quit     
]
FILE-LIST: read REQUESTED-FOLDER/.  
while [not tail? FILE-LIST] [
    either IMAGE-FILE? first FILE-LIST [ ;; always check the first one
        FILE-LIST: next FILE-LIST  ;; if an image, move on to the next one
    ] [
        remove FILE-LIST           ;; otherwise remove the non-image file
    ]
]
FILE-LIST: head FILE-LIST  ;; return the list at the head
if empty? FILE-LIST [
    inform layout [backdrop 140.0.0 text bold "No images found"]
    quit  
]
;; Show the results for demo purposes
print FILE-LIST
halt

12.8 Using the clipboard

REBOL seems to have limited access to the Windows clipboard. It appears that one can read and write only text to the clipboard. Here is a demo that shows how to reference the clipboard, and is a useful little program also. It was used in the preparation of this document to capture scripts and put them into this document with the indentation at the front of each line that marks them as code. The script would be run after loading the clipboard with lines of code, and the result of running the script would be that the clipboard is loaded with those same lines of code, but each line has four spaces in front. Adding the spaces is accomplished by replacing each line terminator with the line terminator plus four spaces (which would go on the next line since they are after the line terminator), and then, to take care of the first line which is not preceded by a line terminator, inserting four spaces at the front of the data. Inserting works because the stuff on the clipboard is a string, and a string is a variety of a series, and the insert function works on a series.

REBOL [
]
TEMP-LINES: read clipboard://
insert/dup TEMP-LINES " " 4
replace/all TEMP-LINES newline rejoin [newline "    "]
write clipboard:// TEMP-LINES
alert "Clipboard loaded"

12.9 Playing a sound and showing progress

This is a heavily-annotated script that shows a use of the progress bar to show how long a sound file has been playing. It is a pretty big program just to demo a progress bar, but it's a fun little demo that could be generalized.

rebol [
    Title: "Demo sound player"
    Author: "Rosemary de Dear annotated by SWW"
]
;;; thanks to Anton Rolls who helped me with slider
;;; also see Ch. 4 of Olivier and Peter's book.
;; [-----------------------------------------------------------------]
;; [ Because this is a demo, we have embedded a sound file into      ]
;; [ the code in base-64 encoding.  This item is "loaded" later      ]
;; [ in the program, in the same way it could be loaded from a       ]
;; [ file if one wanted to generalize this program and play any      ]
;; [ "wav" file loaded from disk.                                    ]
;; [ This embedded sound is short, because a long file would take    ]
;; [ huge number of lines and make the source file hard to work      ]
;; [ with.                                                           ]
;; [-----------------------------------------------------------------]
;WAVPLAYER-WAV-FILE: %incomingsig.wav
WAVPLAYER-WAV-FILE:
64#{
UklGRiaOAABXQVZFZm10IBAAAAABAAEAIlYAACJWAAABAAgAZGF0YQKOAACIiIeH
hoWEhISDg4OCgYGAgIB+fn19fHx8fHx7e3p5eXl5enp7e3t8e3t7e3t7fHx8fHx8
fHx8fHx8fHt7ent7fHx9fX5/f35+fn5+fn+Af4CAf39/f3+BgYGBgYKCg4OEhIWF
hYaGhoeHiImKi4yNjo6Oj4+QkI+Pjo6Ojo2NjIyLiomJiYmIiIeHhoaFhYSEg4KC
g4OEhIOCgYGBgIB/fn17enp5eHh3d3Z2dXV1dXV1dnZ3eHp7fHx8fX5/gICBgYGB
gYGCgoODg4ODgoKCgoGBgYCBgYGBgYGBgYGBgYKCg4OCgoGAf39/f4CAgICBgICA
gIGCgoKDgoODg4ODg4SEhYaGhoeIiImIiIeHh4aHh4WEhIOCgoGAf359fXx7enp5
eXl5eHh3eHh5eXp5eXl4eHZ0dXV0dHR0c3NzcnNzcnFxcHBvbm5ubm5tbm5ubm9v
b29vcHFxcnJzdHV1d3h5ent7fH1+fn5/f39/f39/fn5+fn19fX1+fn5+fn5+fn+A
gYOEhYaHh4mJiouLjI2Njo6Oj46Ojo6Ojo+Pj4+Pjo+Ojo6Pj5CRkZGRkpKSk5OT
k5OTkpKSkpKSk5SUlJWUlJSUk5OSkpGQj4+Pj46NjIyLiomIh4aEgoGAf318e3p5
eHd2dXV0dHV0dHNycXFwb25ubW1sbGtra2xsa2xsbW5ubm9wcXJyc3Nzc3NycnJz
c3N0dXZ2dnd3d3h5eXp7e3t7enp7fHx9fX1+fn19fXx8e3p6eXl4eHh3d3d4eHh4
eXl5eXl6ent7ent7fH19fX1+fX5/gYKDg4SEhISEhYWFhYWGhoaHh4iJiYqLjI2O
j4+QkJGRkpGRkZGRkI+Pjo6Ojo6Oj4+Pjo6Ojo6NjYyMi4qKiYiHh4eHhoWEhIOD
goGAf399fHt6enp6e3t8fX5/f39/gICBgYKDg4ODhISFhoeIh4mJh4eIiImJiYmK
iomJiIeGhYSCgoGAf358e3p5eXl4eHh4eXl4eXt8fX5/gYKDhISFhYaGhoWEhIOC
gYGBgH9/fn19fHt6eXl4d3Z2dnV0c3JxcG9vbm5ubm5ubWxsa2trbGxtbW5ucHFy
c3R2d3d4eHh4eXp6e3x8fHx8fHx8fHt7ent7enp6ent8fHx9fX6AgYGChIWGiImK
i4yNjo6Oj4+PkJOUjoeHjZGMhYWNko6IhIaIiIiHhoSAfn+Dg4B9fX5/f35+f4CC
g4OBgYKDhISEhIOCgoSGh4eGhoWGh4eHh4iHg4GDhpioo35UVYSyuZl3aWlvgJqx
tqeOg5OcgmFuob6oe1VARmyft6N9Z2JcX3eSmZKNh3dmYnCIqMC4kWhYXWuAmJt9
VkJCSFBaZGptbWhdUlFgfJaglHplaX+bsruwmYaCipScnpmOf25hXmJmaGZdTTwz
NUFRW1pQR0FDTmBxeXZrZmVwhZO21sFoFQxZyvjEclRkcn+dxdO1g2Fka1I0TpzI
pFQeGjVnrOHgrXZkbnyPr8fLuqCEbml7ocndzp1kPjpPb46ahlAeDiBFZHWAhXxo
VFNqjKi3uK2cjYygwN3o4Mu1qKiywcrFspd9amdyf35vXkw+Oj5JWmhoXVhWT0pV
bIeirqiUodnyrjoFRMn//ZpTUG2Hnb3TtmwzQHB9WzY/Zn91ShwLLoPGzKByZnmN
m66/vaaLhI6Vj4yasLCVcVNERVRmbmFDIQ8SJkFWX1xRS0xZboGNlZmVjImQo7nI
x72wpJ+nucbDsZZ+dXiBhoBuWkxFPjQuMT5OSz86OjtGM1PW/pUiBhmQ//+lNTFc
gbP7//+pVV2drG49ZrfaskkOCiaa9Py8Xio0WoaxzMuwj3+CiImVueDsy4pMKjJe
kq+eWxkLEkBzgX1wYFdaZnaIl6OtrqOTjJm21ujcupeHkq7ExKuIaVpeand6c2JM
QD1GUFlhXlFCQVVxgHdcPH3//4YWBDvd//95QEtJV6P//+dbDDWIkFIzZqu4dx8K
EGHR+diPWlJaYYXK9+CfcnaRm5en0O3Zml09QV1/mJyEUB0LHVeQrKF8WU9mh6W3
u7SmlYyUqb3L0cu5o5CLmbHAuZ9/aF1ganiAdFc5NEdcW0xHVmhoWEVGlfDYXhAG
TvD//69iT2CQ0///03A4VpOfdFFhjKCHTiAmY6bL0L2YbEtUkdLjvZGFkJqWl6m9
w7OWeFpHSFtsbVk4HRcrSWBqa2xxeoOGh4yVoKaimJOWn6ivs7GmmZGUnKGcjoBu
YV9jZF9aV1VOOyktUHh7XzQdOpXnwj8LCDTQ//+kSypBgM3//LZPHkOAjGNAR2yC
bDcSI2CcubemkHZZTm6r0cCPa2+Jm6Cnsrqym4FrXlxmdXtyWkI6RmF9jId5dIWh
uL61qKi1wsfDvbm7v8PHx72voqKusKKFaF9sg41+WTgtP2WEj4BfOilUyP+1OAkL
bf///6RjUmup7///w2pNcJeOY01kjJx7PxowecLn3bKBY2eGr8jEqpOJjpifo6er
rqmTaz0hJ0VjaVMoDgwZSXJ+c2FgcYygp6amqq6sqKWhoqy4v7acgXeAjpGHdF5M
Q0dTW1dQTElOTExTUVmq/9NLDgcqxf//rUQiMnHN///yahEvhZ9xRE5/mXs4Dg0/
mdXmy45MIStww+rNjWBfc36EmbS+sZl7UycQJ1+Jil4jDQ8waJOnnYRvcY2vw8fB
u7ixqKChrb3GwauNdG15h4uFaUo2N0xmbVpEP1ZsZ2FPN3j//XEVCRSc//+/TBsK
Jpf///+JDRBsvJFPS3+kjlMeFUSU0/Txx4ZMO3bh//+hW2CStLCuw9XKqIduVD9E
aZamgz0PEUiRvb2egn6TsMva29bNxsnMycG7vsvUxqN9coWhq5VuTT5AUWdya04w
LTxdclxYw/+jKAwFQu3//3IeDBNj1v//2zUCLJauZjhTi5doJgsRR5fK386ZTBMO
Xdz/8HYYE1SVq7PAwaBsTE5WVVVkfIFhLQ0ZUI6upIBhY4Kmv8XAuK2io7G8urCr
raygiHNufJKek3BIMj5hfoRrTDQ0U2Notf/BQA4HIsD//6Q8Ewwumf///30OFnSu
fkhTjK+TVSEXOXm54eS8fDwbNYzn/817REJrlqqppqCKb1hPUU9NVnSLgVw7OVuJ
q7OrnZKMkaCywcXBurazr7G2u7q0ppCAen6EhoJ0ZVlSVl5raWdeTV++9JomCwZN
9v/7hzURGGba///YNwJDtsZ+TWSZp4hfR0lfjMHp7L91OClarebkuopqXmN5oL/D
pX9pW05ERlZrdWhLNTVJYXR/hYqIgHt/iJOZmp6lp52KfYCPmpWEdG1wcW1vcG1f
S0VSYWVkWFNrwvCdKQsHTvL//6NGGxVPvf//+FcEKJjJmWVsmKaObFhYY4Cw4vbX
i0AmUqjn7smbeWlqe6DF0r2agnNcQD1fka2ecko7SGiQrresk3x2g5mrs7Grq66q
m5CSo7OxmXhmaHR5b2JPQjc2Vp3EchANBiu6/9VtGwsQSaz1/8dIBSyRuIE9OXSd
i15DSFZtk8Tgw3o2J1mgxLWPdWpjX2uJqa2Tcl9VQiQcPXSWh1YtKkRkg6C0sJd6
bXuWqK2vs7SqmYyQqMXSyLGXhn+EjJOThnRbSlaFuJ01Cggpo+fRlFQvKlKf6P/j
iUVYosy4hm2DpK2fi353eY212+W/e0dCca3JvZt6ZFlffqa6p39jXlxMNjFKbXtx
V0I3OUpqk6uniGVaaoagr7KsoZWQlqSwtLGonJOOiYJ6cWhkY26En5lTEAsMULLL
sXxHHhA1fsPbu3xPVneNin6AkZ+fkoR6c3SHpsXQu41eSVyHrLu0oYlzZ3KTs7mk
h3Vxb2RbX299f3t3cGRXVGWDmpuLdWhqdoqerbGqoJqan6SnoZuYmJaNf3NtcHqF
h3VTNSw8Vmt4eW1YR0JMYXaCgntxaGJiZmtyeXx+gIOHjI6LiIeJiYV/d3Jxc3mA
iIuKjJCYnJmOgn2BhIF7eXl4eHh8gYN+eXp/goF7dG9vdHmBipKYnJ6enqGnrrGv
qaCamJyhoJeHenJvdICMjIBvYVxhbHZ+f3dnWFJVYG12eHVydHyJl52clo+LjZCT
ko6Hf32Djpifn5mRiYN/fXp1bWReWlhZXF9hYV5cW1xeYF9bWFZVWGFteYOKjpGT
l52ipqWjnpuboKWkm42Be3p+ho+TjH1tYFteZ3J5d2tcT0hLVWRwdnd3eoSSnqWo
pp+amJqfo6Oel5WWnaaus7Orn5KJiImJhX92b21vd31/fnp2c3JycnFuaGFcXGBn
cXyFiouJiIiKjY+QkZKSkIh+dW1oZ2x1e3x1aVtQTVFZYGJcUEU8Oj9IUVVXWV5p
d4SNkI+KhYSIjpSYmJaTkpWboqqurqiflo6Ign15dnJwbW1wdHd4dnNxcnR4ent7
eXd4fIONlp2ipKSko6Ojpaqur6ujmY+HgYSOmZ+bkYV6c3N5gIN8b2JaV11la25w
cXN4hJGepqehmJCMj5afo6KfnZyfpq2xsayknZiUkI2Ig4B8eHl9hIeIhoF8enp6
e3p3cnBydn2EiImJi46SlJSSkI+PjoyHf3VsZWJmbnRzbGJYT0lIS05KQjgwLS41
PkZLTlBVXmx6hYuLhX56e3+FioyKh4aJkJmfoJyTioJ9eXd0cW1pZmVobXByc3Jv
bW5xdHV2dnZ4e3+FipCVl5eVlZianaGkpJ6WjoiEhIiPlZSPh4B5dXR2d3NpX1hU
VVpiaWxub3J5g4+Zn5+Zko2Ok5qfn5yYlpedpKiqp6GblZCMiYaDgHx5eHl8f4GC
g4GAgICBgoKBf4CEio+Tlpibnp+goKCio6Sjn5mTjoqHiI2RkImBeXFta2traWRd
V1FPU1tjZ2dmZ2xzfIWLi4Z/fH6DiYuKhoJ+fH6ChYWEgHt2cWtmYV1bWlpZWVlb
XmJlZ2hnZmdqbG5wcnV3eXyAg4WIi4yMioqNkZWVkImAeXV2eoGHiYV9dW9raWZj
XldRTk1PVV1gYWJkaXJ9iJCUk5COjo+SlZaWlJOUlpmbnJ2al5SRjIN6cWxrbW9w
cG9ub29zdnl8fHt8foGDhYmNkJOUlZmfpKWinpmXmJqalIyCenZ3fYSIh393cGxq
am1vbWhiXl9iaG90dnd4fYeSnKKinJSPj5KXmpycmZaUk5SXmJiWk5CNiISAfHl3
d3l7foCBgoGCg4SFh4mKiomJiYqJiYqMj5KUlZWTkIyJiYqLiYV/eXNvbm9ydHRx
bWdiX19gYF9cWVhYWl5iZ2lrbG5yd32DhYSBfn19f4GBgX98enl5enx9fX18fHx6
dnNwbm5ub29vbm5vcHJzc3N0dnh6enp6e3p6enx9f4CBgoKBgYGBgYKDhIWEgoF/
f4CChIaGhIB8ent9f4B/fXx7enyAhYiIiIiHiIqNkJSVlZSRkZCQkZCOioeFg4KC
goKCg4OEhIWHiIeGhYSEgX57eXp7fX+AgoSFhoaGiImJh4WDgoGDhomLioeEhIaJ
jI6OjIiFg4F9end0dHRycXBwcXJzdXV1dHJwbm1ubm1tbW9zd3p+gYODg4KBgYGB
gH99enp6ent8foKEhYOCgYCAf3+AgIGCgIB/f399fH6AgIB9fHt6d3Z3eHh4d3Z3
enx/gYKCgoKCgYKCgIB+e3t7e3x7e3t8fHx9fX5+f39+fHt6eXl5eXl6eXl6e32A
goSDgoOEhYaHiIqLioiIiIqLjY+PjoyKh4aFhYWFhYSDhISDg4SFhYOCgYCAgH5+
fXx6d3V2eHl6enp5d3d2d3h5enp5eHd4en1/f357d3Z3eXx+gICBg4aHh4aGhIGA
fn1+f35+f4CBgYGDhIWEgoGAf359fHx9foCCg4SEg4KCg4SDgH58enl5e3x8e3p6
fHx8e3p6enl3dnZ3eXp8fX5+fX6AgYB+fHp5eHh4eHZzcG9wcHFyc3RzcnBta2pq
amxtbGxsbW9wc3d7fn59e32AgoODg4KBf3x8fX9/fnx7e3p4eHh4eXd2dnd5eXp7
e3t7fYCEh4mJioyPkZKSkpKTk5WYnJ+goJ+foaGhn5yZl5SRkJGSkpSWmpycm5iV
k5KSkI6Lh4SCgYKDhYaGh4eHiIiIh4aFhYSDgoKChIWFhYeJiouLiISAfXx7eXh3
dnV0c3R3eHh1c3JycXBvb3BwcXBvcHJ0dXd5e3x7e31+fnx4dXRycXFvb25vb29u
bGppamxubm5tbG1tb3J0dXZ3eHp7e3t9fHx7e3t6enp7fH19fn59fX19f39/fn19
fX1+fn5/fn17enp6fH1+fn59fHx8fH5+fn19fn5/gICBgYB/f39/fn19fn18e3t8
fHx8fHx8e3t7e3t6eXp7fH+AgH9+fn+Bg4WGh4aGh4iJi42MjIyMjIuLi4yLioiH
hoaHh4aGhYWEg4ODgoKCgH99fH1+gIKDg4ODgoKCg4SEhIKBgIB/f39/gIB/fnx8
e3t8fH19fHp4eHl6e3t7e3t7fHx8e3t7fHx8e3t8foCChISEhISEhISFhYWFhYWF
hIWGh4mKiomIh4WEg4OCgYGAf39+fX1/gIGCg4KDhISFhIOCgoKDg4SFhoWEg4KB
gH9/f39+fHt6ent8fHx7e3t6eXl5eXp5eXh4eHh6enp6eXh3dXRzcnFxcXBwcG9v
b3BxcnN0dXV1dXZ3d3d4eXp6e3t8fH1/f39/f3+AgoSFhoaFhYSEhoiKi4uLjIyM
jIuLi4qJiIiHhoaFg4OCgYB/fn5/f4CAf39+fn58enl4eHh5enp6e31+f359fHt7
fH5+fn5+fn18fHt7fH1+f35+f3+AgYKBgYCBgYKDg4WGhoaGhoaGh4iJiouMjY2O
j5CQj46MioqKiomHhoWEhIODgoKAgIB/f3x7enp7e3t8fX5/gH9+fn5/gIKEhIOC
gH9+fX19fHt6enp5eXp7e3x9fXx8fX5+fn5+fn9/gICAgICAgYCAfnx6eHd1c3Fw
b25ubW1tbm5vb29ubWxsbW5wcnNzc3N0dXZ4eXl5eXp6fH19gHyBg36MkYx+dnuA
iZGUl5KKhn93cXB1e4WNk5WLjYR4enVwb3J4goyOi4eBfH+GiIeDf3h3gISJjIyO
i4eHi4yHho6SkpORjIN9f4iRnKenmo6Ee3V7h5KYlpSPiIF9f4OGiY2Qi4R/enh8
g42SkY2Ffnt5fYKEh4qHgXx5eHp+goKBfHh3eXp8fHhzcnV2d3l6eXp9g4N4bWlq
aW+BiYWHkpOAZEo9SmmPrbWqlHFOPDxLY3iOnZaCcWFVWGiDnqWYjXhdYXFybmtu
i7K0mG8/HilYkMDSwJhiNCcnPGmRrbuwloBmS1Fth6C8x7qeeF9YXG+NoZ+Tfmhh
ZXGFkIqAdWxpbHJ7fn+AdnJ5eWxcWWJ7nbK6rYpkSjpFb5qgiHRoYFtibnNzg5qd
kYBnUVVzmbS0oopqUldugo+dqK6zr6WWg3p+hImSmpyeoJmLemlian+Xq7i4rpd6
Y1pdanyOoKSbkoV1cHZ/j5+jn5WBb2hncYOTn6SbhnVpZm18iJOYmJGGe3VxbneJ
lZyclot6bWlveIKLjYd+dnBtbnN+homGfnRtbHBzdXV6fHh0cW9vcXZ8gHtzbGRj
ZmhpaWhpamhpbW9wb2tlYmFgY2t1eXZqYF9kbHR5eXl8fnt8g4iHgoCBiJCVl5WP
hn55e4WPk4+KiIeEg4KBgH16fIOHiIeEhIiNkpKMh4aHjZOVlJGLh4SBgIGCgH9/
hIyQkI2IhYGAh4qKhnt8jaGkknRaTEpcg6vBw7GWfW5sdoCGioFwY15gX1dSVWBv
gI+Ti3tqYWNziZmdmZCEfXyCiYuLjI6SlZOLfm5hWlZaZGtuamFaV1pjb3h9fn6A
g4iPk5eWkZCbtdPZvo9fQDlSgbTV3cqfdmRnbnZ+fXNhUlJYWVZMQUdigpefn5yX
lJ6wvsK/tq+qq6+vqaGYj42QlZSKeGNUS0pOVFldYWVmaG51fYaQnaessri6t66j
nKCjoaatsrOljXdgRzQuOU9icHh4dnFqXVJLRkNBRU9WVFRUVllaYG55h5Wfpamw
tLOwsbOzsKeXhHJnZWhqaWNYS0E5Mi4wNj5HUFxpc3uCipSgrr3Hzc/Kv7i4wcvL
vqSEZlZifJ24up5xPxoPECdSd5u2wr6xoY93XVJedI2kq6OLaU1CSWWMr8va2M3B
vL3DyszFuLCwsq+iiWlKOT1OZXd4Z0wyKC9CXXN/hYSGj56vur6+vL3AxszJvq+h
oKivp45nQC80UoCnspRQEwwODQ45f6/HyLaUb0stHiY5UmyAiX9jQikdKEh0qdn5
//DLpYZ2eImYoJ2Wj4d7bVY2Gg4RKU5rd3BcRzc1RWF/nbO+xMXHzNHOxK+Yj5mv
uK+Zg3t/g3xjQzQ0UorB0LNeEg0PDg5Uvv////LFl21FJBYZLlaEp7KdbjwgIj5v
s/f/////36t5VEdUc5SsuLeojmxFHw4PDR9MdY+Uh3VmYWyFp8jj9Pjz5tK4nIZ5
dnyGkZaUi4J9gYiMh3ZgT1aBtdHIdRoLEAsYd+n/////2p5mOyEWGCpLdJiron1N
Li1JfL7//////9KUXjYfGjBdh6KuqI5nNhMNDg4fOlJodnt7e4CLmKm+1OTq5dW+
oYJoVlFXYG57g4eKioyUoaSSc1Q9OVaIqqdlFwsPDRBi2f////zIjVkpDg4NDgsj
YZSpnXlSPEBck8/+///50aBwRyIQDh9LeZqtrpx8VjMbFiVAWWlycnF2hZ+6z97l
5uPc08awk3ZeUlZmfI+dpaWkoqCoucbJtpFoRURzp8WwUhAODw5Htf/////3zKF4
RhcMDgwSTZ3Q3cWab1lgg7fn///538SniGM0Eg0QMWeUtb6vkG5RQUBJWWJiYWZ0
kLHI0ceym4mAgoeFemlYUFFdcoSQl5yeoaWrtLisjWM2GBpEgKqocSUKDwsbacX/
////6sqkdTQNDA0LE1WgydbFp4p6gJOnt767trGtootnOhUNDyhSdI+epqmooJB6
ZlI8KyY2WYWuy9XPvaWMeGxnZmVlanSCk6Kpqaemp6mvs7WyppB0VEBEXHiDbDUO
DQ0RPo3Z/////+fBlmMnCw0NDBNMj7vPy7uml5Sbpa2xsre9wLyvlG9MNiwvQmKI
qLzCvq+ag2ZDIRAQJ1OLwOPw5s2pg2dYUVBWYnSLobS9u7Oll5CTnauzrJh8XU1U
bIF/XicMDw0mZa/w//////bYsH06DgwNDAw1eKjGzsi/uLKspJqNhISOnamspZV9
ZU4/PUphfJKhqKiil4NkQCERFjBZi7jW5OHQuZ+Gb1tOSVBheZKkr7Gso5uVkpCO
hnlnVU1TZ3t+ZDgUDQ4hUIjA6/////Tcu5FbHgoNDAwNMWaOrL7Hy8rEtqSMdWVg
ZXKDkZmYkIeAfn58dWpeVE1LTlJPSUI+Q1Nujqu/ysvGwLqzqZyLeWtjZG17ipad
oKGhoJ+bk4Z2aF9fZWtoWkY2MjxVd5y70Nvd2NDHu6qRcU0vHBwsRmN9kJ+qs7q9
u7Ggi3ZnYWRvfo6bpq62vL68s6SRfGdVSUE9PDo7P0hXaXuLlJmbmpiVko+Lh4OB
goiRmqKjn5eNhX56dnBoX1dQTU1RVFdXVVVZX2x6h5KYm5ydoKSoqKScj4J4cGxr
a2tqaWlqamtramZjYGJmb3yKmKGnqampqaejnJKGem9nYV9eX2JnbXZ/h42Qj4uG
gHt4d3d6foOJkZmgpKajn5mSi4R9d3Fubm9zeHyDhoiLj5Wanp+empWSj46NjIqG
f3lybW1vcnV3d3h5eXt7e3dzcnJ0eoKLk5meoaOlqKimopqRiYN+e3h3dnZ1d3p9
goWFg354cm9tbW5wdHh9goeLjo6Mh4J8dXBsaWdlZGJhYWJlaW93f4WKi4mGgn56
dXFsaGRgX2FkanB0eHl6e31+gIB/fXl2dnl/iJGZnqGjpKOjoZ2XkIiCfn6AgYKC
gICAgoSGhoN+enZzc3N0d3l7gIaMkZWVk46IgX15eHh4eHd1dHR1eHuAhYiJhoJ9
eHRwbWllYV5cXF9jaGxvb21sa2xub29wb29vcXR5foOHio6QkpOTkIuEfnt5eXp8
foCBg4SGhoSBfHdycHF0eX2Ag4SEhIWGiIqLi4uJh4eHiImHg397eHd6gIeOkpKO
iYWCgoKBfXhybWtrb3R5e3t4dnR0dXZ2dHBub3N6hI6Wm5ycmZiXlZOPi4iHh4qO
kpSWlpaXmJmZmJSOiISBgIGDhomNkpedoqWlo52XkY6Ok5mdnZqWkY6Nj5GVlpSP
iIJ/fHt4dG5pZmZpb3Z8fn56dG9sa2tqaWhmZmhsc3yEi5KXmZ2dmZSMg3t0cXBx
dHl9gYSGh4V/d2tgV1JQU1dbXmFjZWhscHNycnJvb3F1en5/fn59gIWNlZufn5qS
iYN/fXp2cWpkYmNob3d9gYB9eXVyb21pY19cXWNqc3uCiIyNjo6OjYuHhIOEhomM
jo6Oj4+Pjo6LhoB7eHh4eXl5eXl7f4OIi4uIgnx5e4CFiYqJhYKBhIuUnKCemJGJ
hIKAfHVuZ2JiZm11fH9/fHh1dXd4eHZzcXJ1eoCHjJCUl5mcnZ2blpCMi46SlpmZ
mJiYmJiVkImAd3BvcXZ8gYOFhoiKjY6NioWAf4SLk5mal5OPj5OaoaeppJuRiYWD
gX13cGlkZGdtc3Z1cWxoZ2hqbGtnZGRmbnd/hoqLi4iGhYSCfnp1dHZ6gISFg4F+
fHt6d3JqY1xZWl5la25vbm1vcnd7fXt4dXR4fYKEhIOCg4ePl5+joZqQh4KAgH54
cGhhXmBmbXJ0cmxmYWFjZmdmZGRpcHqFjZOVlpWUlJSUko6KiImMkJSWlZKPjo2M
ioaAenRwcXR5fX+Afn5/gYWHh4SAfX6Di5KXmJeVlJWYn6aopp+VjYiHiIaBenFr
aGludHl5dGthW1hZXV9fW1lZX2hyfIKFhoaGh4qNj4+Ni4mLkZWXlpKOi4iGhYJ/
enNubG1yeHx+fXp3eHl6end0cXF1e4CEh4iIiYuPlpudm5SLhIF/fnp1cGpnaGxy
eHt7d3BqZ2dqbW5saWdobHN6gIOEg4GAgIGCg4KAfn6Ch4yPj4yJhYF9endzb2tq
a21yeHx9fHp5enp6eHV0dXl+gYSHiIiJi5GZoaWknpaPi4mHhH95cm5ucXh+goJ9
dnBtb3N5fHx7enyCipKYnJ6dmpeWlpeXlpSTk5WanJ6dmpeTj4yKh4SBf36Ag4eM
jo6MioiIiYqLi42QkpKSk5SUlpmcoaeqqqafl5GNiIR/eXRvbm9zd3p6dm9lXVlY
W15gX15fYmhvdXp8fXx6eXl7fX59fHt8foGEhIJ+e3d0cW5raGZkZWZnam1ubm5t
bm9vb29vcHFycnJzdHZ6f4WMkpWUjoiBfHl1cm9raGdoa3B0dnVxa2ViY2VqbXBw
cHN3fIOJjpGRj42Mjo+Qj4yLiYqMjpCPjoqHhIF+e3l1cm9ub3J2enx8e3p6enp7
foCCg4KCg4eLkJacoaWnpqGbl5ORjYmFgHt4eXt+f39+enRuamlrbXByc3N0eoKJ
jpGUlpSSkZGRkZCOjIuLjpGSkY6KhoJ9eXVxbm1tbnF1en+Cg4OEhYaGh4mMjY6N
jY6Qk5icoaWoqaWfl5GLhoF7dW9qZ2dqb3J0dHFrZGBeXl9gYmNjZWpyeX6ChISE
g4KBgoKCgoB/gYSJi4mFgX56d3NxbWppa2xub3F1d3h3d3d3d3uCipKPg3hvbHJ/
jp6strq5saeckYZ6cGpnZ2xzeXt6c2tiWVRVWmJpcXd7f4OFhoF5cW5vdoSSnqWl
n5aKfXFnYFtYXGRveX58dWpgWlpgaXN9hIiIh4WCfXNweYibpp6KeW1teo6is77A
u6+imJGKf29gWltmdHp3bV1PRkJIWG2Ai5GSkIuHhYKBgYaRoK+8w8G2o5CBeXZ3
eXl4dHNycGtnZ2t0gpKirK6qopmTk5mhpKKWjZOlw8mod1JGUnakzeTjyqSAa2p3
hIV4bG92dGRCGwwODixchKCpmn1gVFttgZCWnKSoqKCQfXJvdH6IjYhxTSkVFiY9
UV5mbHF0dXN1gZCdqbO7u7GdhndrcpPE7N6YSBoWNW2s3fHer3xYUWN6gndnZXV+
a0IXDA4MJ2GTsLSed1dQaZKvubm4ta6jmZaWmZ6kqKqllHVGHxYqSWBpamdjX11i
cISZq7S1s7KtpJmQkpeQkaXK27VhHQwiX6ff+Oq6e0k6VIWsuKSDcGpdPhoODh9H
bImWj3peSlF0qdTcyq6Xi4eNnbTFy8W0opF9aVNAPU5mdGtTPDI3SmN+mKirppyU
k5aXnKSrs6eLgZW+ypxPGh5MisDi58mRVjZGfbHEs4VdT1BFLyAjNktXYm94dWRX
YYa10syulYuLjZCcssbIuKKQh39xX1RVXmNdSjYtNUZbcoeYoJqOi5Gcpqelp6eh
lXlibprHx4s6DhhDfK/R17RyMh9GiLS2lmdFPDgrHRwmNDg3QldkYE5GW4m3zcOn
kYV/f4mkyNzUtpaGhYZ+dnJxb2NOOzI3RFVpgJOcmImBipyuurq2tKubinNxksTj
zIQ7HzNhmczu6LVrNDZurs7Go3ldT0U+QU9bW1NQXW9yZl1pjLTPzrichnt8i6bJ
4ty7k36CkJmZlIt6YUc4N0BNW2h2gYWBenmEl6u4u7WqnIqBen+bx+jYlUcjOWyn
2ffyu2wvLWmy2tazgVM5MTZLZHFqUz08TFlcYnSUr7iwnYp/en2QqsHLu5h4anOL
nZ+Uflw7IyAxRVBTUlRWVVZda32Pm5+dloqAen6CgY2nwr6RUSs5Z5nC2tmxbjEk
VqDR1reFUzItP2B/iXdVMyg5VW+ElKCnoZmRjo+SlZ6rtrmwnImFkKOys6aPcVVF
RlZobWVZUlNaY3CCkZiXkZCQjo6NkZSNjJ64v6VzSk90nLzR07R7RTdjptHRr4JU
NC5EZ4WIaj4fGCxOboeTkYh8eICMl56dmpmZl5SSkJWcpKeilH9pWlVZYWZhVUpG
TFpnc3+Eg358gImOj42MjISDk6q3p4NmZoCYscXJtIdeVHipw8GrjmtLQlR2j4lp
RjEuOlFuipOLenB1g5CYnZyWkIyPlpydnZ+io56UiHtxamhoaWVdVVNZZHB6gYSD
fn2CjJKVk4+NhIGNorKsknhzgZKktsK5mXRkep+2tquaf15LUm2BfWRKOjI0Qlp0
gXtwa252fYOMkY+Hg4WOlZmbn6WnoZmSi4N8dXBuaWJdX2Vtc3h7fX16en2Cg4F9
enx5d36NnJ6RfnV8h5Geqq2cfWdof5ScnJWIb1hSXnF5b11NQjs+TmV5fnl0dHd7
gYmQkYqFhIiPlZqeo6alop6ZkoyGf3l1cW5ucXV5fIGEhoeJi42Ni4mHh4iGh5Cb
oZ+VjY2Rl6Gssq2djYaNm6aqqqKRfXBudHp4b2RYTUlPXW55fHx5d3d7goqOjIiF
goKHjpSYm5uZlI+KhoF6cmxnZGRmaGtucXR3enx/goOAfn5/gIGAho2TlpSQjYyM
kJmfn5aLg4GHjZOXlIl4amRiZGdlXlRJQUNMWWZucnFsaWpvd36Dg4F+fYKLk5ui
pqakoZ6cmpaQi4aDgYKEhoeIiImKi4yKh4J9enl5e3t8gYWJi4mGhYaGjJOWlIyE
gYKGjJKUkIV5b2ppampmXlVOTVJaZXB2eHd1dXl9g4iIhoSCg4iOlJmdnZyamZeT
joeAeXRydHd5enx+gIKEhoeEgH56eHl7e3p9gIWIiYeFhYSFjJGSj4mEhIeKkJWU
jYJ4cm5ucG9qYllUU1dfa3V3dHBwdHl8goeHhYODh4+XnqWnp6eop6GclpOMg4CB
hIaFhISGiIqMjIyMiYaCgYSHhYaLkJaYl5eWlpWboqajnpmTkZOWmpuWi350bWpq
amdhWVFOUFdgaG5vbmxrbXF1d3ZzcXF0eH6ChYeHh4aGg395cmtmZGRmaGprbW9w
c3Z5eXh3dXV1d3p7fYGHjZSWlZSTkpafpqmoo5+foKOqrq2mnJKLh4eHhH92bmpq
b3d/hIaFhISGioyOjYqJiYyQlZmbnJybm5yalpGJgHlzcXJzdHRzdXV1d3h3dHJv
bGpoaWlnanB1enx5dnRyc3uChoWAeXR0dnuBgn1zaWFaWVxcWlVOSElLUVphaGpr
bG9ydXd2dHN0eoCFi4+RkpWVl5iWk42HgX17foGDhIaIioyOkZKRkY+NjIyLjIuK
j5acoaGem5qanqivsa+po6Cgo6epqKWclIyFgH97dnFsaWpqbnJ0d3l7foGDhIN/
fHp8goiNkZKSkZGQkpKPi4R7dG9tbm9vcHFydHV3eXp6eXl3dnZ1dnV2fIGGiYeF
goGCiZKWl5KMh4KBg4eIhoF7dW9pZmJeWVVSVFdZXmFjZmhscnh7fHt6eXp9hIuQ
k5STkpGTk5KPi4V+eXRzc3N0dXd3eXt8fX59fXx9fX59fnx+ho+WmZWSj42OlqGo
qqeinJeVlZial5GMiIJ7dW9qZWBgYmRlZWZmaGpuc3d4eHVzcXJ3foSIioqKiouM
jo6KhX54dXR1dnd4d3d3eHp7fX+AgHx5d3Z2eX+Ei5CSkoyEfHt+h5Seo6CYj4eD
gYKHiYiEgHt1b2lkX15fYmhqa2poaGhrcnd6fHt5eXt/g4iJioyNj5KTkpGNiISC
gYGBgH9+fXx9fn9/f4CBg4WHiIeFhYaGiI6WmJSPjY2Pk5ykp6OclpGOjIuMi4eC
fnx6d3NuaWViYmRnamxtbnF0eHp6enl4e4GHi4uLiomLj5Wam5iTj4uHhIOCgX9+
f4CAgIB/f3+AgoKCg4J/fXt5fIKFhoaDf319g4ySk5GNiYaEg4OCfXdwbmxqaWhl
YFtXVldaXF5gYmVpamlnZWVpcHiAhIWEg4OGio6QkI2Kh4WDgn98eXh5e3x+gICA
f39/fn5+fn18fHt+g4eJiYiGh4mOl5+joZ2YlZKPj5GRj4yLi4uKiYaDfXl3dnh7
fX+AgoF/e3l5e36Fi5GSkI2Li4uNkZKSkI6MjIqHhIJ/foCDhoiIh4aFhIKAf3x7
fH17fH+EiIiFgn97eXh6gIWIiIaEgnx1cW9saWhqbG1raWdkX1pZW15jaG1xcG5s
aWpucnd+g4SEhIaIiouMjo2LioyNjYqIh4SAfXt5ent8f4OHh4J8eHh6fYCBgoaJ
i4yKh4SAfoKLk5eXlpSTkY6LiYeEgYCBg4SCgH58enp6ent9fX59e3p5enuAhIeJ
iYeFg4OFhoeHiImIiIWAfn+Af3x5eHRyc3l+fHx9d3FydXNxdnt7en2FiomIh4J+
e3yCiI+UlJGQj4yGgoCAfnx9gIKBfXdzcG5rbHF2eXl4eHh4eHt/g4aJioqLi4uK
iYeEg4SFhYaGhoJ9ent8eHd4eXl6eXh4enpxbHF6end6goF8e3x8foODf36ChYB7
fXx4d3x/fnx+f3x4dHBsaWpqaGpwc3FucHBubGpqbXJ2en6DhoR+fHt7e36Dh4mL
jIuOj4iEhYeEhImLioyJhIeKiIaEhYeHhIWOkY6NjY2OjoqHiJCVj4yQkZOUkIyN
j42Ig4OFhIGBhouKhYF+fn57enyAhYeKiYiLiYWFhYSHio6PjIyNjIyJiImGiImF
ho2Nh4aJioWChoF+goKHhIN/d3d3dnd3eXt+fn59eXl4dnZ6f3+EhIGDgX15fX94
dnl/fXV0c3Nsam9ua25zb2ltdXNucnRwbWtvb2xtcXJzeHp2dHd3cXF3enZ2e35+
eXh8fXh2d3Z2foZ9eX57eX97dXyBf4ODf4GDgH+BgIGDgYCDh4iJh4WCgomHfX6D
gHx+gn+AgIB/eHl+fXt7fn96d31+foB+fX1/f36FiYSDg4WGhYaJiIyRj4yKi4yL
j5WUk5KSlZCLiYuOkI+Njo6RlI+KiI+Qi4qNkZCMiIOFhn+DiIeLjoqCgIJ/fX6C
gYGFhYSBgH19fXl7f359fnx5e3x4end3fXZze3ZyeHt6eHl5e316e358ent5dXd5
enp3d4CBenx3cnV0dXZ6gIJ9eHx6dHNzdHZ4e3x+e3p8dnB1dnJycXR5d3Z4d3V3
eXl7fn2Agn5+gH+DioiEhoWDgYGEhYSHi4aChYN8gIJ/gYF8fYB7e355eX18eH2A
eXp6dHR5d3N6e3Z7fn18fn98f397foF/f4SDhYeDgoeGgYSFgYSEf4KCe36FhHx+
gnp9f3l+fXd9g4B8g4iBfH9+gYJ8g4SAgISGf4CJh4KDgH+Cfnp9e3d4en19foOD
f35/fHZ4fHV5f3p6f3x9g4KBgYOGhIWCgoaCg4eEg4WHhoWLj4yQjo2RjIyNiYaK
ioiJh4eJhoSMj4eGi4eEh4eEhoeEhYeDgYGEhIOEgoKAe3p8eXp6eXx9fXx5dXJz
eXp4dXd7eHp/e36DfoCFfn2Efn6Fg4SDg4SBgoSFioaChoKAhYKDg36BgH+Bfn5/
fXx9fXt8fXx6eX6Cfnx5d3x4d354eH13eXp1fXl0fnp8f3h7fXt3eH5+fH94dn56
dn17dnp8eHV6fn19eXp8d3qBfH2Be32EgYCHhoKDg4KAgYKCgn+BhH99hIWChoOC
hYGEiYaHhoOJiIaKhH+Eh4iGhYeHiIeEgoWBgoiDgYWIhoiIhIWFhoqMjY+MjIqH
jYuGiIWEhoSDhYWDgYOBfH56eH58ent6enx9e3h6dXh9c3qAdnp6dXp9e3t+fXl7
enh9gHt9f3+Bf39+goZ/goeDgoF+gIB9gYCBgnyAenZ+eHZ6d3Z0dnh2enh2eHp6
d3l6fHl6f32BhoF/fn1+f35+gXp4e3t9fH9/gH95e397fIF5eX94eHx7fIGFgoSI
gYaIen2EfH2CgoGAgYB9g36Ah4CGiIaIgYWHhIaJiIiHioyIjpGIjIiHkY2MiYSK
hYKJhoiLiIqHiYuIhYSGg4OFhIWHhoaBgoWDgISEfH+BfIGBe3l+eHN/gnp9gnl5
e3R4enh9gH97fHp2fXt9gnx4f3t7hX55gH55gH96fHx5fX15fX15dnZwcnl0cHl0
bHNxaXR2bnV3bXJzb3Z4foF9f398e4GFfIGMhYaIhIKEhoGFhoCGhH+CgIF/e3+F
fH2HgH6CgIKFhYF+hIOBhYJ/hoeIjoaFiYWJioyOiIqLiI6Nh42NiIuKhYOFhIOG
h4mMiYuLhIiHgIeHiIiIjYSIiYOPjYiOjoqLjIyPiYSFf4KGhISAiH97hHd2gXx0
fXhweXVyeHdzcnBtbHBybnJ2cXF0cXd5eH19fH9zdHpzdXl6f4eCe4SGgYGBfXuA
e3t9eHuAfX2AeHd6d3x8dHuAfX+DhYOEfH+CfX5+f3t+gnqAgXuEg4CHhYCChIKC
hYOGjIWAg4N/iIqEiYyFgoWCgIV8gYl9gYN7fHZ1dnWCg4SFd32Dc3h/dHd7eIGG
h4eCiYOFjX6Bin6FjYOKkYyLiYqIhYmIhoyIg4eChYuFgoSHgnx6eXh1eHpydHp4
dnh5dHZxbnFzdnR9fXR9dnF9d3N6dm99fnl/d3t9eIGAg4OCgX+GhIKEhoKDiYGK
jYOEhoSGkoaAi35/ioaDh4qBgYJ+foGAfX9+f4WIgISDen9+fH2AgYF/e357c4GE
eXt/goB+hISLjY+SjYeFh4GAiYyRkpCWjoiGgH+BgoKCfoCDfYF/gIF9gHh2enl7
f4CEgYGFf32BfoCAf4qGgoiAgoqIiYqGhIiHgIeGgoWEhIeLiYWDgHp7gHt/enN6
eHBye3Rwd3Rwdnl0dn13dnh1enx9enh9d3R5dnR4dXVzdHl3d3lvcXNnbXFvdHZx
cXN2c3J4dHp/e3t0c3h+gX6Fg4CGgoODgYSEg4aMi4uPi46Si4iKi42OkI+NjoiC
ho+KjZGMkZOTkIuHiIWCioqIiYWGi4qNjYyIhYmDg4yIh4yNi42KiYaBfoKEhouJ
hoSDhICAfn5+e3x+eXZzeHl5fHZ7eXZ9c2lvcW5ye3t2dm9naWxvdHR9gHp9e3l/
enVzdoGBfoJ+gYF4fHx4fXx6gYSEgHuAf318eXh/goKEiIuLi4qJiIeEho2MiIqD
gouLh4uLio6JipCOjo+RkpKQjoaEi4yPkpGOjYuIh4uLhYSFhIqNiIiEgYCChYSH
hICDhYmKiYuMhoCAg4SFg319gHl2enh7fHZ3eXd4eXVub3BweHx6enRxcXBxcnF1
fICBhIF7eXhzdX6Dg4SAfoKBe3t7d3h8foKBfXl1cnR4d3Z2dnZ2eHp5dnFxcnN5
enh6e32AgYSJi4qHhYSChISChIWFhISFg4GAfn19f4CBgoOCf35+f318foCChomK
i4uJh4aGiYqJiYmJh4qMjI6Oi4mKiomHhYSEhISFhoSEg4CAgYGCgH9+fHp7fX1+
gH99e3h4enl5enp6e3x8fn98enh4ent5eHh4eHZ1dnh3c3Jzdnh3d3h5eXh4fIKE
goCBg4SEg4KFhYWFh4mLiYaFhoeHh4eIiYqJiYuLiIJ+fHt6eXl7fX5+f4GDhIKC
hIeJi46QkpGPjYyKiIWEhoeJioyMiIR/e3h3eHl8f4SHiI6Zp6iZiHpuZmZyhZSf
pq65wMC3pZF8aVtVW2dvc3d+hoiFgHdsX1VTXGp3foOJkZaXk42FenFtc4CMkpCM
iIF3bGFWTEM/RFFhbnV6foGCgYGEhoSFiJOepKSgmY+DdnB3g4+PgWtWQjQuNURS
WmFreoeJfmtUPCccHSo+UF5ugpemq6ehm5eWm6e0wMjO1NbTyrmlkX9zcXV+hIWA
eXFlV0Y0Jx4cJzxXcIWXpK+2u729vsHEx87V1tLKwruzqJaCeoSapZRwSigTDRg/
bIydqLjIzL+ge1UvFRApVXiNmqm+y8a4qJqPh4qct9Hg39G9qZWDc2VZSj49TGJ1
enJeRS0YDg8PERcjPF6DorfCyMvM0NXZ19DGv7u2r6CMeWpdU1BBLTdeipFoMBAM
DQ0NQYmptMHY6ePDj1omDA8KIWqVm6Cwx8arkYJ4bml4ncbf4dLJx7qZbUs9ODM/
Y5CqppB5ZlU/JRMUIS5BZpvH29vV193h4eHk49fDs6+yrJV4YFFJREdUY2NgRj5x
u+XGZBMMDQ8JLaDu/P//////xmUYCw8MEWfFzbOruMWqdEs7MzFCd7/2/+vFrJqD
XjMeGx0uWpfH0reGVi8SDQ4NGztcisP2///crot8eYCVrLm5tbjCxLGKYEI0OEdh
f5CNgH2Cj5BuZpLKz3QYCw4ODxFq6P///////8hjEgwNDgoYe87MrqKvsYtTNjdF
W3uq3v7937qlopRsPi9EZIGevtLEkE4gExUUFipShKrE3/PvzZx2bXqMmqq7yc3G
vry2oH5gVFxtfomMiH1uY19ja2BVPSdQoNy6WxgMJCwlZd3///////7QdxsKDgsO
CTubwbSpqJ95QiMrQFyAps7x//vhwqmPbEcxMEFXbH6Ggm5JHAwODx8ySW+Yus7c
39K6n4yIlai1vsTGw7akkoFvXlBLTlZgZmVgWExBOjxMVFleTWGp8POsXDY8PzRX
vv/////n0rVxHwkODAwOCTGFr73DxLGIY11wkbzg9//////tyq2NXCgMFTlUX2ht
bmRQQ0JIUVZgfKfS7vn479/Is6SblY2Gg4iSlY17alxRS0lLUFdeZ3F5fn11bm95
iY6Rj3aDw/z/v2Q1LSQcQJ7v///q08WpZhkJDQsNDA5JmsPY6vryyJZ5cnydxODp
5+PUs5eGcEARCw0MH0NkeHx4dXRybW1ucHyVudvq6N3PvKqai35vYVtfbICLin9x
aGZlZmtucXR2e4GAenBnZWhydXZ4YGmp6Pi9WyAQDwwZbMfv8+XWyLKBMAgNCwsO
CTKHuNPp+PPNmXRcWHSbsre5wse5oYx1RxULDQsOLlpxfIiVmo9+b2FTTl57nrzP
2NjRxraegmZSSElUZXeEi42MioiBd21nanSBi46NiIWEhouQjo+KfJvf///Ze0Ak
Ew4ndMTq8vPt4c2lWxcLDQsNCjiSz/P///XPqI53bXyPkoyVu9zey7CNYzAODQwX
Pl9yg5isr56Fc2ZXT1Jkg6S7yMvIw7Wgh3NnXlNNUF9yf4J+d29lXFZWXWdub3By
d36BhYmQkZCLeYfA9v/GaCcPDQ0PT6jV4N/UyL6odi8MDQsOCSR/x+v179y+pZeB
a2x1dm51oNHi172ceFIwGxkoRV9qbXuSoZuIcl9NQ0RTcZW1ydLV2drTvqWOemla
U1lodXp1bGZgW1RPUlpiZ2lveYSPlZqempmPe47A7O2yYjEWDg0lbK/N1c/Bubas
gUccDQ4ME06bzufp3ciyp6CJdHF1dG14ncbZ1MGlh21XRjY0RVljaXWGkYx6ZU49
OUFTbYmkucTK0tvc0b2mk4N2cHBzdXFoW01DQEBBQ0hPVmBufYyapqijnY+OrNXp
0JJdPywlNGekyNDJtZ6Ph3ZRJw8NDg0oaqnW6+3fxa+ml35rZmlmZHCNqbvAt6B/
ZllOQj5JWF5fZXF7fHRlUDotLDdJX3uWp6+3ws3NxLipmIl/enZ0cW1iUEE5NDIv
LS4wMzxKW21+iZCQi5e109vAlG5UREJVfqnDysGtl4d6Z0clEQ4OECtbj73c6+rc
zsOxmoZ8e3dzdH2RqLrDwLOllH9oWFZfa3F2fYaJh393b2dgWlVVXnKKobfL3efn
5N7X0Ma6rZ6Qhn95dXFtZltPRD06PUVPWWBpcnuKnK+4tauglo6KjpaeoqGck4h/
eXFpYFhRS0pPWWZ2h5afpKaknpWKfnJoYl9cW2BocXh8gYaGgXt3dXV4fYKEhIJ9
dm9raWZhXFlYW19ncXqCiIyNjI2OkI+OjoyJh4WEg4J/enRuaGNgYGBiZWludXuC
iI2QkJCPjIqGf3lzbmtrbW9ydnh7fX+ChYiJioqLjI6QkZKUko+LhoB7dnNvb29u
b3Fzd3t9gIOGio6UmZyenp2al5ORjoqGhISFiIuPkpSUlZSTkpKTkpKSk5WWmJqb
m5mWk46JhYKAfnx7e32BhouOkZOVlZSSkI2Kh4SCgYKDhYWFhIOBf359fHp5d3Z2
dnd5fH5/f3x5dXBsaWZlZGRnam9zd3l6enp5eXl5enl5d3Vyb2pmYl5bWFdXVldX
V1dXV1ZXWFtfYmZqcHR4e3+BgIB+fXx6enp6eXl5eXp8f4KCgoGAgYGDhYeIiYmH
hYSCgX9+fHt5eXl7fYCBgoKCgoOEhYeIiYqKi4yNjY2NjIuKiYmIiIeHiImLjpGU
lpeXlpWTj4yIhYOBgICBgoODg4GAfn19fX1+foCBhIaJi4yNjIuIhYJ/fXt5eHd3
eHp8foCBgYGBgYOFh4mLjY6Pjo6MiYWAe3d0dHV4en2AgYKBgoKBf317e3p6fH6A
goKCgH17eXd2dHR1dnh7f4KEhYaHh4iJiYmHhIJ/fHl3dnV0dHV1dnd3eHh4d3d4
enx+gIGCg4J/fnx4dXFvbW1wcXN3enx9fX19fX5/gYOEhoaGhoWEgX98e3t8foGE
h4mKi4qLjI2NjYyMjYyLi4yNi4mGhIF+fXt6eXp7fX+AgYKBf358e3t7fH19fn5/
f39/fnx7enl5ent9gIKFh4mMjIyLioeFg4F/fXt5eHZ1dHNzc3V3d3d4eHl6fX+B
g4SEhYSEhISDgX9+fHx8fH1+f4CBg4SFhYSDgH58e3t8fn+BgoKBf317eXd2dXZ5
fICEh4mKi4qKiomJiYmJiYmJi4yMjIyLioiIh4iJiYmKjI6Pj5CQkI2LiYeGhIF/
fHl4d3Z2d3h3d3d3eHl6enp6enp6eXh4eHh2dnV0c3N0dXV2d3h4eXp5d3VzcXBw
cXFydHV2d3h4d3V0cnBwcHBxc3V2dnZ2dnV0c3JxcXJydHZ4ent7enl4dnV0dHR1
dnh6fH1/f35+fXt7enl4dnZ2dnZ4en1/gIKDhIaIiImKi4yMjY6Ojo6PkJCRkZGR
kI+Pjo2NjYyMjIuKh4WCgH9/f4GCg4SFh4iIh4WDgoGAgICCg4WHiImIh4eFhYWF
hISFhoeJiYmJiYiIhoaGh4iIiYqMjY6NjIyKh4WDg4OEhYWFhYWEg4OCgYB+fXx9
fn5/f359fHp5eHd3dnVzc3NycnFwcHBvb29ubm1ramloaGpsb3J1d3p7fH1+fX1+
f3+AgIKDg4KBgH58enh3dnZ1dHR0dXZ3eHd3dnV1dnh5en1/gIOFh4mIh4eGhoaH
h4eHh4eHh4iJiYmHhoSEg4KCgoKDg4OEhIWFhISEg4KBgYGChISEg4SCfn5/gH56
dnd8gYKCgYCChIJ+ent/goODg4OCgH9+fn16eHd4eXp7fH1/f3x5eXp9gIKDhISD
goKCgoKBgYGChYaFhISGhoSCgoGBgYGDhoiJiouLi4uLiomHhoiKjpGRj4uJiYmI
iouMi4iFhISFhoWCf35+f3x5d3l7e3p7fn14c3BzeHl2c3FzdnZydHx/fXZzeH+A
end6gIB/foCDgn55eYCHg3hxdHh4c3J1eXl3d3p7eXVwbm9zd3h3eHp7e3t+f398
eHd6enp+gX98e3t6dnR2eXt5d3l9fXp3dnh4eXh0cXR4d3Z2eHx8eXd8fnx+gYWD
enh9hIN8fIGGiISEhIWGhICCiYyHgYGGiYiEhoyLhHx7gYaHhISIi42LhoaLjo2J
iI2QjYiIj5STjYuNjYuJiYyNioeIiomIh4KBg4WGhoeKi4mJiIiJiYWDg4WFg4SF
hYJ/gYSAfoKCgYGEhoSDgX59e3p9f3p3dHd7eXh5eHt5cHB4e3hzc3l7dnV2c3F1
eXd1dnp8d3BzfH13d3p4d3h6e3h0dnl1b3B3eXRwdHl4dXV2d3h3eHl6foB+e32A
gHx6fX18fHx7fn58fHl4eHRzdnZ4eHR0en+AeXqBgHx8goR/foGCgH99foGAfoGE
goSIh4iHg4aJhoWGiY6Lh4eJhoOEiIiDhIiJiISEg4OFgoWGg4SIhoCBhoaDg4eJ
hoSHi4mFhoiHgH6Cg399gISCfoKHgoCEhISEhISFg317gYN/gYSGh4WFhoWGiYiH
i4uGh4WDg4WGgYSHg4KAfX19eHp+end4eXp4d3Z0dXd3eHd3dXJycnJ0cnN5dnV6
enZ5end5enp6end1dnV2d3l6eHl4dnVybm1vbmxwdnV1dnVycHBubnFwdndydXV0
dHZzbnh8eHh8gYGCgICCfX+EgoCAgoODf4GEf3p7gIB+fX2CgXp7goKChIWKiYiH
iIiEiImJjIyMioiJiouNjoqPkomKj46Iho2KjJGPjoyJjo2GgoeKhYaLioaIiIWH
h4eFg4WGiYiDfn6BenmDg3x/f3x+gH18f357e35+fHx7fHx7gIWCfX14dnt7ent6
fH59fX+AgH5+fn9/fn+AgoWGg4CBe3l9e3l+hIB8gH93cnJ1ent3eX59e3p9fHp9
e3Z3eX6Af36ChYF9fHt+gIGAgH59fX2BhYeBe3x9fYCDhIWFf36Af4KDfYCHgYGI
iIeHiYiFi42Fg4eKh4OFh4WAgIB/foGEgH5/gX96fHh5fnd3goB2dnl1c3l+fnt9
fX5/foKBeXd4eHl6enx9eoCCgYOAeXV2eHp/gYOFhIB+fX5/fn+Dgn19fXyBfXZ6
fnx7f4F9fH5+e3d5fHl1eX5/gIKEgHx+g4J/gIKDf3x9f4CBgYGBhIB/goGEiYmG
hoqMiYSHiYOFjYyLjo2JhoaGhomLiYuHgIGAgoWDg4WHhX19goWCf316eHl4eHx/
gX18e3yAgX56gIR6dXV1dHV6dXZ6dnR2d3d7d29zc3BwbnN2dXR3eXl3eHp1d397
fH5+iYV/goCDhH6CgX6ChYKDg4CFh4OEhIF+fX6AioqDh4aDgoWIhICFiIqEgYmE
fH+AfX+FhIR/fIF9e3uBhICJioaIhH6BiYmMkY2Ki4+OiYyJjJKMjZGPjIaKiYeN
jIeLioSGhYGEg4aGhIiHhYWFhIKAf4GBf359f397eHh4dXN1en97dXd3dHV4dXZ2
eHx3d3p9fX6BgH14dnZ5fHx8gIGAgYJ/fX9/fHx9fX6AgX5/gX19gX55dnZ3fH15
e311cHZ3dnh2dnp0c3p4c3J3e3Z2eXd0dnp5dnt/fn58fH5+f3x9gX1/gnt8gnp9
hH99gH98ent6fHt5f4V9fIJ8cnJ0dHd+goKDgICDfHd6fHh1e4CBf359en6Dg4J/
f316foGBgYKBfX6BgH6Ag3+BiYeGhYeEfYGHi46QkpOQi4iHiouHiIqJh4uOhYOH
hYiKhIqQhX2Ag4F6eXt4dnl8foKEg396eHp6dnV1eX5/gH9+fHh0dXuDhoSDhoiF
goGBg4OBfoCGiYWBgYGDhIKBhIaGhIGAg4WDgH5/gYWHh4eDg4iLiomKi4yKiouL
i4yNjImIiYyMiYaEhYiHg4GBgoF+fX1+gIB8ent+fnt4dnZ4eXl2d3l7end2dnp8
fHt5e3x8e3p5enx8e3t9f39/fn+Af39/fn1+gYF/fn+AgIGAgIKDgoGBgYGCgoGB
gYGBgYCAgICAf359fX17enp5eHd2dXZ2dXR0dXZ2d3d4eXp7fH1+gIGBgoKCgYGB
goKCg4ODg4ODg4OCgoOEg4OEhISEhYWEhISDg4GBgICAgH9+fn59fHt6enl5eHh4
eHh4eHl5eXp6e3x9fn+AgIGBgoKDg4SEhYaGhoaHh4aHh4eIiYqLjI2Oj4+Pj46O
jYyMi4uMi4qKiYmIh4aFhIKBgH9/f35+f39+f39/f35/f39/gICAgICAgH9/fn59
fX19fX19fHx8e3x8fHx8fHx8fX19fn59fX19fX1+fn9/gIB/f35+fn5+f3+Af3+A
gICBgYGBgYGBgYGBgYGAf35+fX19fHx8fH19fX5+f3+AgIGCg4SGh4iJioqKioqK
ioqKioqJiYmIiIeHhoaGhYWEhISEg4ODgoKBgYGBgYGBgYCAgH9+fX18fHt7e3t8
fH19fn5/f39/f39/f39/fn5+fX19fHx9fHp5eHh3dnZ1dXV1dHV1dnd3eHl6e3t7
e3t7e3t7e3x9fXx8fXx8e3l4d3Z1dHRzc3N0dXV2d3d4eHh4eXh5eXp6e3x9fn+A
gYKDg4SEhIWFhYWFhoeHiIiJiouMjY6Oj4+Pj4+Pjo2NjYyMjIuLi4uKiomJiYmK
iouLioqKioqKioqKiYmIh4eGhoWFhIODg4ODg4ODgoKCgYCAf359fXx8fH1+fn9/
f39+fXx8e3t6eXl4eHd3eHl5ent8fH19fX19fXx7enl4d3d3d3Z2dnV0dHNzc3Jy
cXFxcHFxcXBwcG9vb3BxcXJzdHV1dnZ2dnd3d3d3eHh5enp7e3x8fX5/gIKDhISE
hISFhYaGhoeGhoaGhoaHh4eHh4eGhoSDg4ODg4OEhISFhoeIiYqLi4yMjIyMi4uL
ioqKioqKioqKiouLi4yMjIyMjIyMjI2NjY6NjY2NjY2NjY2MjIuKiYiIh4eGhoSE
g4KCgYGBgICAf4CAgIB/f39+fXx8fHt7enp6e3p7e3t8fH19fX1+fn5+fn9/fn5+
fn5+fn5+fX19fX19fX19fHx8e3t8fHx9fn5/gICBgoODgoKBgoKCgYCAfn19fHx8
fHt8e3x7e3t7e3t7e3t7e3t7e3t6e319fXx8fHt7e3t7e3p5eHd3d3Z2dnd3eHl6
ent8fHx9fX5/f4CAgYGCg4SFhoaGhoaGh4eHiIiIiIiIiIeHhoaGhoaFhIOBgH9+
fHt5eHZ1c3JxcXBwcHBwcXFyc3N0dXZ3eXp7fX5/gIKDhIWGh4iJiYqKioqKioqK
ioqJiYiIh4aFhYSEg4ODgoKCgoKCgYGBgYGBgICAf39/f39/f35+fX18e3x8fHx9
fH19fX1+fn+AgYKDg4SFhoeIiImKi4yNjo6Ojo6Ojo2NjY2NjIyLi4uLiomIiIiH
hYSDg4ODg4OCgYGAgICAgIB/f39/f39/f4CAgIGBgYKCg4ODgoKBgYGAgIB/f35+
fn5+fX18fHt6e3p5eXl5eHd2dXV1dXR0dHR0dHNzc3Nzc3Rzc3Nzc3Nzc3R0dXV1
dXV2d3h4eHl5eXp6e3t8fHx8fH19f4CBgoODhISEhYWFhYWGhYWGhoeHh4aFhYSE
g4SEhISEg4ODg4ODg4OEhIWGh4eHh4iIiIiJioqLjIyMjI2NjYyMi4uMi4mJiIiI
iIiHh4eGhYSEhISDg4KCgYGBgYKCgoOCgYGBgX9/gICAgH+AgIGBgoKCg4ODg4OD
g4OEg4ODg4ODg4ODgoODgoKBgYCAgICBgYGAgIB/fn17enl5eHd3dnZ0dHNzc3R0
dHR0dHNzc3NzdHR0dHV1dnZ3eHh5eXp6ent7fH19fn5+f39/gIGBgYGBgYGBgYKB
gYB/fn5+fn5+fn19fHt6eXl4eHd4eHh5eXl6ent8fX19fX19fn+AgIGCg4SFhYWF
hYaGhoaHh4iJiIiHh4eHh4iIiYiIiIiIiYiIiYmJiomJiYmJiIeGhYSEhIOEg4OD
goGAf39+fX18fHx8fHx8fHx8fHx8fHx9fn5+f39/gIGBgoODg4ODg4ODg4SEhYWF
hISDg4ODgoGBgICAgYGCgoKCgoKBgYCAgICAf39+fn5+fn5+fn5+fn5+fn5+fn9/
f4CBgYOEhIWFhoaGhoaHh4iIiImJiYmKioqKiomIh4eGhYWEg4KBgYGBgICAf359
fHx8fHx8e3t6enp5enp6e3t6enl5eXh4eHh4d3d4d3yCfnRxd36BgH5+fX18e31/
f4B/f4GCgoGAgIGBgYGAgIB/f39+fn5/fn18fHx8fHx9f4B+fHh1eX1/goF/f359
fHx+gIB+ent/hIeFg4KDhIODhIWEg4ODgoB+fn6AhIeHhoSCgoKCgoF/fn1+f4CC
gYB/f4CBgYGBgIB/f318fX1/gICBgX9+fX19fn5+fn5+fX19fn9/f3+AgYKCg4OE
hISDg4SEhYeHh4iIiIiHhoaHh4eHh4eGhoWFhYSEg4OEhIWFhYSEg4ODg4ODg4SE
hISEg4KAgYGCgoKBgIB/f39+fn59fX1+fn18fn+Dh4B1bGViZGl1g42RjoZ9dW1o
Y2FkanF4foOEf3ZqYV1faHN/iI2PjIR8d3V1d3l9gYWIiomGfnRsZWNnb3Z7fXt1
bmdkZGZrcnqDi5KXmJaTkZKUmqKrsLCtpp2TjIaEgoKAenJmZHiZsqZ6SCcXGDRr
qdjn17aOdGNVSUlcfJutu8vTwI9TLClDcaXR7fPfsn9ZUV9sdYaiwdPSw6eEXz0m
JkNuk6CUfmJHLBwhNlFndYGNmp2RfWljboSfvtrp48qtloiFi5OdpKKXgWZRQjgx
LyopKBUdTIescxoLDw0PTrX////xqXJjZGRof6fO497W0Ld2JAwNF1eey9/Ws3Au
EQ4oWHiSrcnh48qmfVpCO02BvuXw1KBoLxAODzFnjJ+jnpWKd2FWWnGXv+P///TP
pYiBip63yM3GsI5rTjwzMjpLV1dNKxc5dp10HwkQCxdi0P////SQWlJpe4qiwdLP
tqKbjFQWDQwuerLQ1bqFPhENG0+Jqra+wbupkYByYFBQap3I1MacWh4MDg4xYXh2
ZFZTW2hyd36AiqG81OLdxKaRi5WpusS7o4NlVE5OT05LRkM+ODUqI0B9uLloGw4O
IGPE/////8eJc3yJlae+0dTDrp2DSxUNDjmDt9LQsHpDIiZFdavN2drVybmnlIqK
kqK4zdjOsYNRLR4oQ2J4fHFbRDxIYn2UpK+2ubzBwb22sLG1vMTEtZt+ZlhTVlxd
V0k5LikoKS4qLEqCwtmYMw0QDjST/////9B0SEVefZy1wsCtknhXIwsPCiZ0scvF
mlceDRlGhL7g49K9qpiKg4OIkJ+5z9G5iUsYDQ0hVHqLgV82Gho3Yo6zyM7Lw7y4
tbS2v8zZ4t7LqoJgT1BebXZzYEQoGBgkMkFJSl2Gu9ecORAQFEev/////8RlOT9p
mr/S0cCfdlQwEQ4MFFGYwcmtcjEQEjl4t+f25MGfi4WHkKCxvsXGwK+OYzkfIDla
doF3XDkeGjJci6/DyMK3r6yvt8PP2uHe0bqdgGlgZW95eWxVNRgODh03TFVVRjtN
gL/JfjIUECp34f///95zNzNjm77IvKaIaE89JhINF0uLtsOtfUgqMFqY0vb427WW
i4+brLu/ua6knJF4VTcjJjpTZGRSNBkSJ1B9oLO3tbGxuMLL09nf5OPazLach3t3
eXx3Z1A5JxwZIC07R09OS0U/VYzN6a1XJRcvd9v////yjEo3Womps6qZhGpONh0P
DRZLirK7onRGMTtkn9Xx79GpjYSJmam2urOmnJWKc1IzJS1EXGtrWkAqJTZagqO3
wcK/vsDGzdTd5Orn28evmYmCgYF+c2JPPC4nKDE9SVVcWVZMR2Si5+eWUTArUKH9
////tGI2RHuqvLWdhG5WPSgVDRY/d6KumGw+KDRipNvw4cKehYCNpLzLy7ylj351
bWBTT1FWV08/LB0aKkJedoSJiIuVpLTCzNHU1dLPxLWnnpiVkIV0Xkk7NTU2My4s
LTI7QERGSmSa1deTQxQWSaP/////uWU6Toq+0MOoi3BRLxgPFjRfiqOdeEYiHkSJ
zvXwzKODeIGcvtbf18Gjg2xjZ3F7gHlpUTIaFCNAXW92dG5qb4GduMzW19TRzsrF
wr69vLeplHpiUk5UXWFYQikdHy5HWmZmW15/vNKXVjAqTp/4////qVcvSY/L28OZ
c1c+JxseK0JffI2EYjcfJ1WY0+rZr4t4eI2v0Ofo0a+PfHuFkZ6jm4ZnRSsfKEFe
dHxyXU1MX4StzNvXyb26v8rX4ePdz76smYuDgIGDg3plSDAoMkpgaWhbTFR9tMaX
TBodVKn4///unVhAZqjV1bKGZFE/LicqM0BTZ29gPRsOIlaUvcKid1xZbI2xy9TL
s5V8cHB9kJ6gk3ZOJA8NHD9cZ1s/JBcjRXSetranlo6VpbrN2tvPvaiVioSEiIqH
fmtPMiMlNUtYWVNEO0t5qq57NhQqa7/////YlGhrndfw4LqVf3FhVFNXX2t5hIBo
RSstUIa2ybiRcGZzkbXS39rGr6KcmZqhr72+rYtjQjVBXXmIhGtIMjdTe6C3u6+f
l5upvdLh5t7Pvq2inZ+lp6KVg21XRTxBUGFoYE84LT9tobGIQBISQI/Z///WlmZd
grfV0beZgW9dT0pPWml3gHhbNhoZOGqWp5dxTT9KZYqoubmokn51eomdrrOpkXFR
PThCWnB4b1Y4JCE0WoGaoJB5aGd5l7XK0MazoJSTmaKpqqGQe2ZXTUpQWmBfU0Y3
MUNumZ9sJwsWUKPk//zQlWtvntn4786wm4x+dXyLlZqbloVnSDY/YY2qqoxjRkJY
faS6vrCbiX+BjqG1wsKzmHhbUFdth5WNckwuJjdYfJWYiG9bWWiEo7nDv7KhlpKW
oq60r6CMeWplZGducnBkTzspLVSQtZtDDQwUXrvz/9uUTzhjs/P916iLf3t3fpGd
npyXj3xcQDtVgqu1nG1BMEBolbW5pIZsZ3aMnqisraiZgGhbXmx+jZGDYz4pNFZ8
lZqOd2FZZYCds7ixpJiUlZmhqKyroZKCdGxrb3JzcGhZRTcwOmKYtpM2Cg0QXbrr
7rxxLx1Ppuv2y5FsYmNoeJSnpZeJeWZQQ0xtlrKuiVYyME99pbivlXVYTmGKscjF
rY9wW1lphZ2nnoVjRz1FX3+WnpZ/ZVhddJSrtK+gjYOEkKGutK6gkIaAgYeMjYmA
d3JoYFxUZZbAt2cWCw9QruX10oo7ETKL4//lnWVSW26GpsG6nIJ0cG9rbXuSpqiQ
aUo/TnGWrqqNalFIVHWfvr+jgGRcZnuSoqOWgGhYV2RyfoiLiH5xaWt5jJ2lpJmM
h4mToauspZiLhYSHiomDfXZxbmheWE1Se6ivaBUMCj6d1eXDey4JKYXg/+OXWUZW
c5OxxruTc2dqdHl+ipielXtcS0paepmro3xPOkZql7e9qIJgVmSAm6ijj3ZnY2Rr
dHt/f3t1b2psdYGNlZaQhH+DjpqhoJqSiIOGi42Lg3pzcHJxaWJSUneip2gaCw5G
m8vYtG4pDDSM3PXPh1JGWn6kw82xhGlqeouTmJ2gm4x6bGpxfpChpZJvV1x2lKap
oI13am6Al6WgjXpwcnR2e39+eXRydnl6e36Ch4yQkpKUmJudnZycnJqampiTjYaD
hIaDfXJkZH6Zl2gpCxpTjrK7nWcwHUSJwtGveE9GW3+iubmeeWVoeImSl5mWjYBy
bG50fIOEgHpsX1xicYGHf3FmYWNvfIeHfGxiZnR9gX50a2hrdX+Bfnp2dXqDjpOT
kpCPkZOVmJmZm5iRioWDg4SDfX2JlYhgNCdDcJKlooVaNzplmbeyk3BaVmaDobSw
mIF6go+Zn6Smo5qQiIOCh5Ogo5d/a2l1hZKWlIdzYWBwhZGSiXxwaGlzg46NhHp0
dnuAh46Pi4aFiI6TmJudnJmWk5SXmZyalY+Ef4eZoZBnQTdIZHyMi3RNLi9Pd4yH
cVpKRVBngI+KeWxrcnqAh46UlpSPioeGiI+Xm5aJfHd6g46UkYV1amludXl3cGVd
XGFnamhkYF9hZGltbm5tbXB2fIGFhYSEh4yRlZeVko2IjqK0sZZyXmR6lKmxo4BW
P05zlJqIbVVHR1dyiY+Aa19hanaCjJOTjoiFhYaKkpugn5aKgoSPnqmpnI2AfH6F
kJWQgnJpam51ent5c2xnanF1d3d4ent9gIaLjpGWnJ+gn56dm5ymuMG0lHdteo+k
srCce1pPXnyRkn9nUkhKV2p3enJoYF5jbHWAiZCSjYV8eoGOm6Kimo2AfISXpqqg
j4B1c3mEj5CGd2xoam1wcnR1b2poaGhpa29zdXRzc3V3fIKIiomFhoiIi5WkqqCJ
dHB6iZehoZF3YVlicnx8cmJVT1ReaGtpZ2hsbm5ucnmDi5CTko2GiJCcpKWgmJKQ
k5ufn5qTjIeFhoaGhH96eXl5d3Nwbm9xc3Z2dHBub3N4fH5+fX5/g4iLjIyLjIuK
jJSdnZF/cG11go6VkH9qXF1pd39+c2VYU1lmc3dzbWpscHV6fYCChYqPkI2KiYyS
mJqamJOPjpCSk5KPjYyLiYeDf3x8foGCgHt0cHBzeHx9e3VwbW5yeHt8e3p6foSJ
i4uLjIuKjZCTl5yemI6EfoCHkJiZj35wa292foF+eXBoZmtyd3h3eXp6enp9gISI
i4+Pi4WBgIOIjZCRjYaBgIKFiYyLhoB8enp6enx/gYB8dnFvcXV7gYJ/eHFucHR4
fHx6d3NxdHp9fXx8ent+fn18fHx9goeGgnx1c3d9goWEf3p1cnJ3fX98dXBubnF1
eHl5eXh5enp4eHp+hIyRkIl/en6GkJeYlI6Ig4KGj5aUkI+PjIeEhomLjZCOioaE
hYSFh4uLi46OiYWEiI6MkJuZin+Djo+NkZeThoKKh3x/iYqCgIWEfXh3eHZ4gISA
eXFxdXZ5fYB+eHJxdn19e3l5fX9+f315en6Dh4mJhoB9f4SLjY2KgXp4fIGBf399
eXV0cm1rbGtveX93aF9gZGZrcnZ6cmZeX297dWtwf4J3cnZ3dG5pcYGLiXRlcoB5
a3KGi4B2eYB+dXF0eX+EgoCCg392dIOQjYeHiIB2eoeNhoeOjo2Pj4mGipCOiJGb
lY2Oj4yNk5eVjYeIj5WRiYSAg4mPkJCRi4eKi4uLh4aIioyNjoqEg4F8hJOclouI
g3x7hIuJhoyRgG5veHt8h5SNgH99cWdyg4FycHx9cW93d3N4f3x3eHp3bG15gHhs
bXl8eHR3fnhwcXh/gHlxcXd4d3d3gYWAeXmAhHt5go+Rh4OGiYqGhIiFf4SKiIaG
goJ/foF5en98eXR6gn13eHp3eXyBf32Afnl+g398dXB0e35/gHh1enZyd3l9gHly
dHp/fHVyd3x+fnx3eoGBg4WGhoB2dX6GhIOCenZ2dn19eoSCdnmAfnh4fn9/goaE
fXZ2foCDhn98hIeAd3Z8fHZzdn+Efnh7gIF7cneChoWIlJCDg4iFiJGZlImIjoV8
g4eCgImPioeBfHt9e3l8iZGDdXmGh4KDhIeKiYeIjIyJhX6GlI+Ij46CfHp6dnuD
gn6DhHh0dHZ6eoCGgHdydX59g4iDf4GGfXaIkYeJkouAgomFgYyRjouGhoWFjo2I
jpOIhot8doSJhIKDgXx7fH6GjIN8foJ/dXd9fHp+fnd0dn6Ae3t/fHt7d3h1dXyC
g3t7gnl0enZyc3R5enyCfHV4enx4dnx8f4J9enh1eH18foF/gIKHh357e32CgoSJ
hX15b2pzdnN4gYB4dG5lZm9wb3d8d25paGxzd3p+f3x1dXt7enx2cHZ9enl+fXh4
fn13dHRwcXuEg32Cg3lye4aKjIyLj46Mj4+IiJCNiYyOjouIi42Kg4CFhX6BhH9+
gYB8fYB8e3x6foF/f4KEgICAgIaIgYCGgnp/g4aMjYyNiIWGgYGIiYaLkIqGjYN+
jIuBhY+MhoeOiX54cnNzd396dn59dXt7d3t9fX2DhH+AfXl7gISFiIqGf4CFg4GI
hXl9g35/gHpye4R5eX92eoKBiImAfoJ/gomIgH2GjIyLjo6Lh4iHgoGEhIGFhX17
gIB6enx4eX13c3N1dXN7fnp5enh4enp3d3d4eXd6endwbnJwcXV4eHd3c29xb25y
dHh4d3l5fn96enp/gX6AgIeLhIaEg4mKgoWLhYWHgYOJg4GHiouGgoKChoF8gHx8
hIGChoKEg3+DhIGAe3yAfHt+gn+Ah4B+gn1/hYGDhXyAi4KAgoCEiIuKhYmDgIJ/
gomGg4uKgX+AgHx/hH1+hH+BgH+Gf3yCgYCDgoeHhIZ+gIaEhoN+fX6Bg314eXhz
dnt4dnZ2eXRyeXh1fH95eHt9en19eYOBfY6Fe4WBe4N/d358eX1/gHx4dXd4en1+
fn1+fHt7eYF5cX5+d4CCeHyAdnyCdHmKeHiCeHyBeXp+fHuFiH+DhHh9hX2DhnqB
hX2Cf3V+fnmFiYKFhnx+gH58h42FhomIiIeIjYmKkIqKjo2Di42BioqBhYqIhYWC
gIJ/gIaEfYB/dnt4eoB9f3+Cf3+Ee4CEfoSAfoJ7f4WChouHgIKJg4iVh4mOfoGI
ho+SiIePiIaNiH6DioCFiH+Gh36Gi3l4hXl7gHh6f4F+hIN0fn5we396f3pyentz
d3t5ent5fIF5fH52enx6fH59hIV9foJ5eoWBfoF7dnx/f319eX1+d3t+fXl4dHmB
dXeBenyCf3d6fXZ6eXiBfnp7enh1enp5gIF9gnlzenNye3t8fHt6e3p1eX14eHx5
e4B3c3x4eH10dXx4eIKCgIV+eH6BgH6AgYOFgoCHhYKJg32AfX1+e3+HiYWGh36A
gnp/fH+HhoeDg4eDgYSAhIeDgYR/fX6DgHuLhXl2c3J2e32Cfnh5enJ1e3R0d3V4
f318gYN7f4WCgn53eYF9fYR+fIOFhImIg4SCf4OHiYuKiYSDioeChoeJkI6Hi46F
gYN6e4WAgoV7f4F6fH9+gYSEg4CDgn2Ef3mGiouQioSIioaGiIqKkIuDh4aDh4eB
h4yHioqGhpCMg4aFhomIh4eJj4iFi4N/ioqIjpCMhYJ9fIJ8eYKBd4F+c358eH98
dn18cHd6dXZ2c3V1c3R4e3x+gHt9fXN2e3V4eHZ2dHZ3eXl0dHZ0dnl7eXd7e3h3
eXh5end2d3d3e3dub3FvdHd0d3Vxenp1eXl7enZ6dnJ1d3d5d3h8fXqAhoSBgH18
fnp7fXt7eXx8gIuHgoiCe4J+fYSBgYeBf4WEfoCCgYWEhIOAgn+Ai4iHh3+GhX6C
hoeDgH+Gi4iHi4iEh4uJhoyKh42GhIaChIuFg4CAhX98gn59gX6Bg32DgX2EhYiK
iIaEgoGBhIaIi4+PkI2IhoKDio2KiIqGgIKDfoSKgYOGf4OLhIGKgXyEgnyAf3x/
fn6Dg3x9gHl5gHp3eXp+fHt4e4N9e35zeIB4fIB6gIV9g4d+fYKDgISIg4WJhISH
g4qNiIyLi4yGhouHio6Hg4J7fn99fn19foB/e3d2dXN0cHBzcHZ9dnB0dnd7eXZ6
d3J4d3d+en1/fYB9f4GBhYJ/gIKDh4SBhoF+goCDhn6Ag3x+gH1/fn19eHh6eHt5
c3Zzc356en95gIF+gXp4end+gXh7e3Z6gXx6fHl2fHt1fn10e3x2fIB7fH17gIKF
iIWFh4uOhoeLiImIg4qNhYyKg4uOh4iMi4uKhoaJiYuPioeKioWKi4WHiYeIhH+B
g4GChYWBg4N7e396fX55fIJ/gIOCgIKEh46JiYmBhYKChH+ChIWCgYOCg4aCf4J/
fYB8fYF8foF7f4N9gX57f3+GhoOEfn2CgICBfX6Dgn6FgXh8fHuBfHV7fHh/fXV6
fXR3fHp/gnt2eHNyeHVyfXt3fHhyd3l5e3t9fX55eX1+fX1+eHh/f4GDgYKAgYJ8
fnt+g3+Egn14fXx4enl/goJ9e356fX55gYR9fHt6fYB+gH6AgoCCeX6EhIaDg397
fH9/gIOCgYCBfn97foWEgn99fH1+f4KCfYKEhIR+e3l5fIOFgICAgIF+gIeIh4uJ
iISFhoGGiISFhIKLjYWHhoCGiIWIiYqHhIN+fHl1d4CFhYWEg3+EhYKIh4KFgoWF
gYOEh4eLiomGhoqIjIuHh4F8fn+BhIaGgX18fHt2c3h+gYSEe3l5dnt9eoKEf398
fH16enp8goWEh4eDhYSBgX99fnuAgoCDg4SDgICCg4SBfn17foB+e3t3en6CgIGB
gIR/fXt6eXV0e3p8g357d3Jyc3R8fHl7dnV1b3Bxcnd3e3lydXBtdXZ0e3l2d3Z2
eHp7e358eH2Df4OFfYCDfoODgH55ent/gX6BfHl5dnl8gH2Agn+CgICCfHx5d3yA
hoyJh4iMjY2Si42LhYyKioyJi4qRjYyTjpKRkI6LjImPko6Vko6NiY2Pj5CQk5GR
k5GUko2MiIaFiYuJkI2OlI2OiYWEg4ODgoeDhIaBh4KBhYWFhoaEgYN9e3p+g4KC
fXl9eXx+eH95dXlxc3Rub3BzcXFucXZ0d3ZzdXV2dHN2dnN2cnN4c3V7en2AeHp5
dnl4d32BgIB8fnp5fHp7fXZ3fX2DgXuAgoF/f3p1eXl6f4GEhIOCg4SChYaEiIWF
hYWEhYeGiYqHhYOBf358eHx9e4B+e399fX99enZ6fYCHh4eIhISDgoKGiIiNjYyO
jIqMiYeGhIKChoSEh4WEgoGAgoKBhYN+gHt1dnV2eHp3eHl2enp1dnt6eXt7eX6B
f4KDfoGDgYOCgH+EhoWGhYWHhoSBfn19e3Z6fX59e3l3d3Z5eXl+fX2Agn6Ag4OF
goGFhoqJiIN+hIGCh4aKhoCBgoOFg4J/f4SChouFhYN+g4aIi4uLiYWFg4aMhoSE
hYyMi4mFhoSDh4qJiIaEiImHhYSFg398fH6Cg39/gIKAeHh8gIF8en58dnNydXd0
c3V7f3x6enl7dW9xdHl6d3h7eXV1eoKGgn6AgX14dXl+fnx9gIOBfnx7fX19fn5+
e3Z3d3d3cW9xc3h5eXt9f39+fXp1d3l+hIWCfXl7fXp5e3x+fn+AfXp1c3d7fn57
e3x3c3V1dXd3ent6fHt9fn1+fn+EhIOFiIqJioqJi4yLiYeKi4qLjo6PjpCUkpCO
i42OjIuHioqGhIOHioiIiImOjIeHhoeFhIeKjo2KjpGTlJGPkZGPjo6QkI+MiYmK
hoeHh4qHhIODg4B9fn+CgHx8e3t7e3x9fn16eXl6e3t6fHx8fHp5eHh4eXl6e3t6
eXl5d3Z2dXZ2d3h5eHd1dXZ1dXV1d3d3d3Z2d3Z3eXt9f3+Af358e3t9f39/f35+
fX1+f4CAgYGCgoKBgICBgYGBgoGAgoWHiYiIhoSDgoOFhoiIh4eGh4aFhISFhoaG
hYSEhYSCfnt3dXV2e4KIioqIhYF7dnNxcnV5fYKDf3l0cXBxdHmAhIaHh4aDf3p5
fIGGiYuLiYaDgoGBf35/goWGhH95cmxrb3R5enh4cm5sZnKJoaeSdmJWT1l2mLS9
saepqJh8YlFPWWqFpLSqiGJPTVFWYXiNlpmfqKSIZVBRZ4WguMfEspqMi5GQh3+E
k6Gkm4pzWD01RFxwdG9sbWxoYl5dYGh6l7XDvayemZ2lrrvFx8G3sq+lk4V7e3p2
clxbdI2SYRsKDg0LKnm61cKahIWDZUQ7Un+myO3/761fPU10l67H4uTNr6GbhVky
Lkx7oLGzp4xbKhgnQ1ddZXuPi3RWQDIjGypTfZKPgXl3cmlodY6jsL/R3Na9oZSW
nqivtrWlh2tfXV1PPTkqOGubqmEQDA4NDlO8///ln3yGkG9BMlWa1ff//+J7HQoc
Z67H0dzVtYxxaFg2HShjte310ZJSJBAoYZm0qpOOlJJ6VjcrLkRtmrexh1M3Pl19
laazurq9wsO4oY6PpsXZ1sGjgF9LTF52fXVpVUcqDzN7pXMbCg8MLXLF///8n3CM
vbqCWmyo2ufl3b9uGwkZbsDNtaCXhWVOUl9cTERlquTuxoJJMzJHe7fc16t8aGhh
STM1TWZ5iZGIZjUaLF+XusG7trCrqqyzuLWyucvYzKl+YFVZZHB5dGJKOC0kHhQL
Hmi1vGIRDQ4PP6P////3m4OYpYpmYoi72+PbxIUnCw0TbL7ItJp7UzUuQVVZXXKd
z+rfrmgxHS5mq9/z3altPiYiKThRan+OkoJfNh0hQnm23+rbvqmgnaOxws/X2dXL
sYxoU1JgcoKIgGtSOy0nKjU0R3zK9LFDDw4WRJn/////zIJ8lJ+Og5rJ7/Xcsnwx
DA0RZ8vq1KRzTTc0R2SBnK23xM7LrXlLP1mKvN3r3KtkJQ0TLk9oeX96bVQyHB0z
WYWx0tjCoIeDjJ20y9ze0ryig2hXUVpsfoV5WjQYDg4WMUlVVkM6Wp7EhikMDRVd
v/////59NDV0rby1sLa6q4hfPBkOCyN+y923bSoOFDFhl8DMuZeCiZmYgmtujbbW
49y4dy8OEzlsi5SGak43KSk5VnmWrLzAtJqEfYqpy+fz7Na4moV5e4WPlZWMe2BB
KSEmOFBqfHVeOxwyfsnKeSQKHFmr+P///6FTTYbF3MqvoZ6XiHRiUjYfLWKixLN7
Px8nSHKev8eyjW9yj6uwpJmcqbnIzb6XZkM/VXWOlYdqSjUzQFVrfYiKiYiFgYKJ
l6u/zdHIuKWWjIqPmZyVh3VkWE1HRklPWGBhXEo3KhwwccHcmTYNDSZ20f///7td
N1me1OPWxLKbf2ldXFZJUHGbt7GESB0WN26ixsuvgVdKX4aourmuoqCjpJ2IcWJd
ZXaFiHlaOSYoPVhwfn9yY1laZ3mMnKWnpqWhnZqYmJueoaCYintxbnF0dHBoX1hW
VllXUkk8Rnazw4krDAwshtz///+pSR9Dl+D/9tareE5CV3+cnJGKiIiDc1tLTWaO
rbizmXZaUGSPudDPuJqGgomUmpqXjnxuaW12d29nZGNma3B1eXt4d3qBjZWWlpWW
mZygoqKdl5GLiYyPkY6KhHtya2ltdHh3cGNUTUpQaZKxoWAdChxbp+H/9bdlKiVb
pt3r1KdwPik7b6K3qotsV1JZZXF7hI6Sin50b2xrdYylsq+gjoF6e4aZqayehGlb
X2+CkJSKd2NYXm6Ai4yDdm1tdX+Kk5aTi4WEh4mKiouNjo+NiIJ8eHd5fH59d29l
X15eX2BhZG58g3hbPjVKcZy7xbaOYEVPeanHybGJYUZGZJGzvKqIZ1FQYn2Yp6OR
eWVgaXmEi42LhX57fH6Afn+ChoeCe3RwcXiCio2He25naneIlJeOgXZwcn2KlpuX
j4V/f4WNlZqZlI6KiYuPkZKRjomFg4SFhoSEhISFgoCBgYKFh4mIg316en6FjpaZ
koV6d3+KlJuclop+eH6LmJuZk4qDfoCIkZeUin5zbm50foWIg3pwampwe4SJh4N8
dnR2e4KHiIeFgoB+f4CDhYWDgHx4dHV4fH58d3Bram1yeX19enVxcHJ2e35/fXt3
dnh6fH18e3l2dXR0dXRzcW9tbGxsbnBzdHNwbm5wc3Z5e3x6d3d4en+ChIOBgH+A
gYSHiImHhYODhIWHioqLioiHhoSDg4KDg4SDg4SEg4KBgYGBgoOEhYWFhoaGhoaG
h4iKi4uKiYiHh4eIiouKh4WDgoKEh4mKiomIh4aGh4eHh4iIiIiIh4WCgYGEhoeI
h4SBf3x7e3t7e3t7e3t6eXh4eHh4enx9fn5+fX19fX5+f4CAgYKCgYB/f3+AgICB
goKCgIB/f3+AgoSFhoSCgYGBg4SFhoaGhoaHh4eHhoaFhISDg4KCgYGBgYGAfn18
e3p6e3t8fH19fn59fHt7e32Ag4SDgX99fHx9fX5+fX19fHt6eXh5e31/goKCgYGB
goSGh4iIh4eHh4eFhIKCgoOEg4F/fHt7fH1+fn5+fX1/gIGCg4aGh4iJioqKioqK
i4yLiomJiIeHh4iIiIiIh4WEg4KDhIeJiouKi4qJiYmIiYmKioqKiomIh4aFhYWG
hYWDgoGBgYGCgoKCgoOEhYWEhISDg4ODgoKAf359fXx8e3t6eXl4d3d2dnZ2dnd2
dnV0dHV2d3l5eHd2d3d5e3x7end1dHV1dnd3dnZ1dXV2dnZ1dHNzdHV1dXZ2dnZ3
eXt8fX59fXx8fH19fn9/gYGAf319fHt7e3t6enp6eXl5eXp6e3x+f4GBgYGCg4WH
iYyNjY2MjY6Ojo6PkJCQj42Mi4uLi4yMi4mHhYWGhoeGhYSCgoKDg4KAfnx8fH1/
gH9+fHt6e3x9fn5+fn5+f4CBgoOEhISEg4SEhISEg4ODg4OCgYB+fXx8e3x6eXh3
d3h4eXl5eHd2dXZ3eHl5eXp6ent7enp5eHh3dnd2dXVzc3NzdHR2eHl6e3t7fH1+
gIKEhoeJioqKiouMjY+QkZGRkJCRkI2GgX+EjpaYk4yDfHp6foKFh4mKiIWBfXt8
f4OFhYOBgH59fX1+gIKCg4SDgoGAgYGCg4SEhIOCgoKCg4SFhoWDg4KAgIGCgoOF
g4KBf35+gIGCg4SEhIOCgoKBgYGBgYKBgH9/f39/fn5+fnx8fHx7enp6ent7e3p6
ent8fHt5eXp7e3p5eHh4eXl6enl4d3d3dnZ2d3h6enp6enp6e31+f4CBgYKDhISF
hYWFhYaGh4eGhYSEhISEhIWFhISDg4KDg4ODg4SEhISDgoKCgoODhIODg4ODhIWF
hYSEhISEg4KBgYGCg4OCgH58e3p6e3t7enl4d3d3eHd3dnZ3eHl5ent7fHx9fn9+
f4CBgoODhISEg4OEhYWEg4KBgH9/f359fHx7e3p5d3d3d3h4d3d3d3d4eXp6e3t8
fX5/gYGBgYKDhIWGh4eGhoaHiYqLiomIhoWFhIOCgYCAf39/fn18e3t6enp7e3p5
eXl5enp7fH1+f4CAgICAgIGBg4SEhIODhISEhYWFhISDg4OCgoKCg4SEhIODgoOE
hYWFhISDg4ODg4ODhIODgoKBgH9+fXt5eXl5eHd2dnZ1dXZ3eHl6ent7e3t7enp5
eXp7fHx9fX5+fX5/f35+fXx9fX19fX5/gIGBgoKCgYGBgYGBgoKCgYGAgH9+fX19
foCBgoODgoOBgICAf39/f39/f4GDhIaIiouMi4qIhoaEgX9/f4CBgYGCgoOChIWE
hIOBgICAgICBgoKCg4SFhoaHh4aFhISDgoGBgYKDg4ODg4KCgYGBgYGBgIGBgYGB
gYGCg4OEhISCgH59fX19fX18enh2dHR0dHR0c3JycnN0dHR1dXZ4ent6enp5eXl4
eXl5eXl4eHh3d3Z2dnZ2dnh4eXp6ent7e3x8fX5/f39+fn9/gYSFhoeHiIiIh4eH
h4aFhIKAgICAgIGCgoODg4OEhIOCgYGBgICAgH9+fn5/gYGCgoKDhISEhYaHh4iI
iYmJiYmJiYmJiYmJiIeHhoaGhoaFhIODgoKCgoGAf359fX5+fnx6eXl5eXl5eXl5
eHh4eXp6eXh4eXp8fX+Af39/f39/f35+fn19fn9/fn5+gIGCg4SEg4KChIWFhoeH
h4aEg4KDg4OCgoB/fXp3dHJwbm1tbm5ta2pqamttcHN0c3N0dnl9gYOFhYWGiIqM
jY2LiYeFhYaHiImJh4WDgoGBgYKCgYGAf39/gIGDg4WFhYWGhYSCgH9+fn17enl5
ent9f4GCgYGAgICAgYKCgYGDgoKDg4OCgYGAgYGAgH58enl5enx9f39+fn+AgoOE
hISFhoSFhoaHh4iJiIaFg4B+fn5+fX18fHx8fH5/gIGCgoKDg4SEhIWFhYaHiYqL
i4mIhoaHh4iHhYJ+fHp6fH+BgoKBf359fX+AgYGBf359foCCgoF/f3+BhIeKioiG
g4KBgYKBgH99fX6AgoSDgX99e3t7e3p5eHZ1dnh5eXh2dHR1d3l7fHt6enp8fn+A
gICBgoOEhYWFg4GAgIGDhIOBf319fXx9fn59fHx8fX18e3l4eXl6enp5eHh3d3h4
eXp6eXd2dXV2dnh4eHd2dXV2dnd3d3d2dnd4eHl3d3Z3eXp5d3Vzc3R4fH+BgH17
e36BhISDgH5+f4KEhIJ+fHx/hImLioeCgICChISCf3x8fYGFiYuJhoOCg4WHiIeE
goCBg4WFhIB9e3t8fn59e3h3d3l8f39/f3+BhYmNkJCPjY2OkJKTko+Ni4uMjIyL
ioeEg4OEg4F9eXZ0dHR0dHNycXFyc3V1dXV1dXV2d3d4eHh4eHh5enp7fHx9fn+A
gYKChIaHh4SBf35/goaJjIqFgoCBhIaHhoWBfn6Ag4aFgn16fH+DiIqKiYWDhIeJ
ioeEgYCChYmMjIqHhIODhoiHhYF+fX6ChYWEgHx6e32Ag4OCgH59f4KEhYOCgYGE
h4mLi4qHhoaIiYmHhYSDg4SFhYWEgoGAgIGAf358enl4d3d2dXRzc3R0dXV1dXV0
dXV1dnV2d3d3d3d4eHh5eHh5eXl4eHh5eHh4d3h6fH59enZ0dHR4foOFg316eXt+
gIGBfnt5eHp+gH97dnR1eHx/f357eHZ4e35+e3ZycXJ2e3+Af359foCDhIOBfn19
gISIiYaDgH+AgoSFhYSDgYGEh4qKiIaGh4qNkZSVlZSSk5aZmpqXlZORkZKTk5KQ
jImHh4eGhYKAfn5+f39/fnx8fHx+gIGCgYGBgYKEhIODgoKBgIB/f39+fHt8fHx6
eXh4eHZ1dXZ3eHh4eHp8end0dHZ5fICDhIN/fHt8foB/fXp4d3h6fH18eHNwb3By
c3NycXBwc3V3dnJubG1vcnZ6fX18fH6AgoKAfHp5ent8fn9+fHl4eHp7enh2dXZ5
e32AgoKAfn6ChomLjI2Oj5CRkZGQjYqHhYaIiYqKiIaDgYOJi4R5cG50fIGDhYaG
hYF/f4CBf36AhIaGhYWGhoaGiIuOkI+SlJOQjYyLiYeFhYaHhoeIiIeFhIOEhISG
ioyFd2hjZ3F8h5KbnpmRioiIhX1ybnB2fYOLkI+GeW9scXZ5fH+DhoeIiomFfHJr
am93gIiOjoyIg354cGliX2BlbniAg4B6dXFwcXR5foOIjZKWmZiUjoeDgoWKkJOT
j4qFgHt2cm9rZmJiZGltbGlmY2Nmam90dnZ1c3N1d3h3d3d5fICEh4eHhIB9enl5
ent8fX5/fnx5eHd4en2Ch4uNjo+RkY+MiYmLjpKTkpGNjI+Wm493YFFRXXSOpre7
r5yLf3huXk5FRlBfdImZm5B9bGRncHuFjZWdpausqaGTgXBnanaFkZWWkYl/dGdd
U0xHSVNme42Ym5mUkIyKio2Qk5aZnqSopp+ShXltZmNkaG1wcXBta2dhXFZQTUtO
VWFveX6AgIGDhYiLjIqGgoGBg4SDgX58fH+DiI2RkpCPjYyLioeEgH17ent8fX19
fXx9f4GFiIuLiYiJjpKVlpOOiIKAgIWNlI94Xk5PYX2dvNPb1MCnkH1sWkUxJy5C
XXuVp6+rno+Fho2Ump+lrri/xMK4qZV+bGFgZ3B2eHl3dnFpX1VNSUpTYXaNoa+3
urm3s62kmpGJhIKEiY2OioJ3bGFZVFJRUVNXXmdyfIOEfXRoX11haW5wcnd+hoyQ
kIuCdGZcWFpeYWVpbnR6foGDg4KBf4CDiIyNjImFgHx2cW1qamtucnd8fn17d3Ry
cHFydnt/g4J+eXd3dnd7ho6Jd2NYXHCOrsfV1sq0mH1nUj0lFA8TK090lK7AxsG2
rqmop6enqK65w8nHva+bg2tVR0NFS1NbZG55gIKBgICBhImRnaq2v8XJy8nAsZ+L
emxiXl9kbHN5e3t7enh0cG9vcHV7gIiOlJiVj4V6cWtpampqamhoa3F2enp4dHFw
cnZ7foB/fXt7fX+BgoF/fn59fn9/f318fHx8fXx5dnNwb29vcHJ1eHyAhIeLjo2K
hYB9fH6BhYmMjouDfX+JlZB7YVFPXXeVr8DFvKeKcWBTQy8gHCI3WX+jw9zo5NbF
tqickIFzaWhveYGIioR3ZVJCODc6QUtWZXeKmqatr6ylnZWNiYiJjI6SmJucmZKG
d2heVlNXXGZyfoqUnKGioJmOgnhxbGhnam90eX+EhYJ/enVydHl+goaNkJOcp6up
p6KemJGNjIqJiIN8dnR3fYWMk5ean6Snp6Win5mRiYOBf357d3NxcnZ6fYGDhYaF
hISFh4qMjI6PkJCNioaCfHd0cnFwc3d9hIuPkY+JgnlvZ2BZUUtJS09YZHB7hIyR
lJaYmJWOh352b2pmYmBfX15dXF1eYGJjZGdpbG9zeX6DiIyQk5WWlZKPjYqIhoOB
f358enh3eHh5ent9f4CBgoKDhIOAfn17e3t6eXdzcG5tb3N6gYaKjY+RlJaXl5aU
kY+RlJieoaOjoZ6alZCMiIWDg4eMk5uhpaalo56ZlI+Lh4N/e3h2dXZ2d3d5enp5
eXt7fYCDhoaEf3p4eXx/gH98enl6foSKkZeYlpGMiIN/eXJqYVpWVVheZ3F6hI2U
nKOoq6uppJyShntxZ15VTUlISEtOUFNWWVxgZGlweH6Fi5CWm52foJ+em5aQioR+
enZ0c3N1dnh6e3+BhIeJjI6OjYyLioiGhIOCgYF+fHhzcG1sbXB1en+EiIqLi4yN
jY6OjIeDfnp3dXV1dnt8fX5/gYSGiYuNkJKTk5OSj42JhYF/fXt7fH2Ag4aIiImK
i4yJiIaEgoGBgYKEhYWDgYB/gICAf35+fHp3dXV3enx+gYSFhYOBf35/fnx5dXJw
bWtrbXF3foWNlp+mqquopJyTiH1za2NdWFZXXGJqcnmAhYiJiYmJiIeGhomNkJSY
m52dnJqWko2HgHlzbmxsbnB0en+Eh4mKiomHhYJ/fn17enh4d3h5ent9gIGCgYGB
gYGBgYKEhISCgYKCgoKCg4OCgHx3c3Jyc3Z6f4SHiYqKiomHhYKBgYOGiYuPkZKS
kY+OjYmEfXdzcG9vcnV6foGDhYiKjo+OjYuKiIWBf35+fnx6dnJtaGRhYWRpcHiA
iI+WnaOorK6ro5iMf3VpX1ZPS0tPV2Nzg5Gco6msq6mknJKHfHBmXltcXmJlaW1x
dHV1dHJvamdlZGhtc3qCipOboqepqaehmpCFfHRtZ2NhY2drcHR6foKGiImKioqI
hYKAf39/f4CBg4WFhoeHiIeFg4KBgYGBgYGDhYiMj5KUlJKPjIqKioiFgoCAgIKF
iY2PkZGSk5OSjYeBfHl5e36ChYeIiImKiYiEgHt4dnV1eH2BhouOkZWXmJaRjIV9
d3NvbGpoZ2Znam51e3+DhYiKjY+RkpCMh4J+e3p5eHh3dXJwb3B0e4CEhYSCf3x5
c3BsZ2NfYGVsd4OOl6Cnq6yrqKKZj4J2amJcWVdYWl9lbHR8g4iLioeEf3t3dHJx
cXN1eH2BhoqMjYyJhoJ8dm9pZGFfYGJlam5yd3yAhYiKiouKiIWCgH59fn5/gIOG
iIqMjY2Ojo2NjY2Mi4mIiImLjpCRk5OSkY+OjIuKiIaGh4iIiImKjY+Sk5WWlpWS
j4yKiIaEgoCAf39+f35+fn18e3t7eXZ1dXV3enx+gYSFhoWFhIOBfnt2c3FubGtr
bG5xdHh8gISFhYaGhoaGhYSFhYOBf317enl2c3FwcHFzdnl7fX5+f4KGiIeEgHx8
f4WLkpaXlI6Jg313b2ZeV1NTWGBreISOl5+nrrO0saqhl42DenNuamZiYGJla3F2
eXt9fX5+fn9/gH9/gIOHi42PkI+QkI+NioaAeHBqZWFfXlxcXWBjZmpucnV3eXp8
f4OEhYaHiIqLjY+QkJCOi4mGhYOBf39+fn18fHx9f4KCg4aJjI2Njo2NjIuKiYiH
hYKAfn59e3l4d3Z2dXV1dnh5e31+g4aHh4eFhYSCgH9+fn17eXl6e31+gIKEhYWF
hISDgoGAf4GCgoKAf3+Bg4WHiYyNjY2NjY6NjIuKiomIiIeHh4eHhoWGh4iIh4aF
hYaHiImKi4uKiouLi4uKiYiHh4aEhIOCgX9/f4GCg4OCgYCAgH9/gIKDgoB+fHx+
gYWIi42MiYeGhIJ+eHFrZ2RiYmRobXJ2e4CHjI+Qj4yJhYB8eXZ1c3BubW9xdHd4
ent8fHp6enp6eXl5fICEh4uOkZSWmJqbnJuXk46JhIB8d3NwbWtqaGhpamxsbW9z
d3l6e31/gIGCg4SGhoSBgH9+fXt6eXp6eXl4enp7fHt8foCCgoKCg4OEg4ODg4OC
gH9+fXx7eXl6fHx8fHx8fHx7e3x9fnx6eHd2dnV1dXZ4eHh4eXx+f4CAgoWGhoWF
hISDgoGAgYKAf39+f39/f3+Bg4OCgoKChIWFhYaHiIiHh4eHh4WEhIWGhoSDg4SF
hYWFhoiIh4aFhYWFhIOBgoOCgYB/gIB/fn1+gIGCgYGCgoODgoKEhYWGhYWHiIqL
i42Pj4+NjY2Njo2Li4uKiIaDgYB/fn18fH19fHl6e319fX1+gIKCgoOEhYaHhoaG
h4aDgX5+fHp5d3h5eXh4d3h3d3Z0dXd5enl5eXh4dnRycW9rZ2RiYmNlZ2hrcHN1
eHt+gYODg4OEhIKBgH59fHt7e3t6eXh2dXR1dnZ2d3l6fH6BhIaJiouMjY6Ojo6O
jo2Mi4qLi4qJiIaFhISDg4GAfn19fn+BgoOEhISFhYaGhYWEhISEhISEhYWGiIiJ
iYqJiYmJiYmIh4aFhIODhISEhIODgoKDg4KBgH9/f39/f39+fXx8fHx+fn9+fn5+
f4CAgYGBgYGBg4SFhYWFhoaGhoaGhYSDhIODhISDgoGAgYOEhYWFhYWFhoeHh4aF
hIODg4ODgoF/fn59fXx8e3p5eHl6e3t7e3t7e3t8fX5+fX18e3t7enl5eHh3d3d4
d3Z2dXV2dnZ1dHR0dHV2dnZ2dnZ3eHh5enp6ent8fX5/gIGBgoKBgoOEhISEhISF
hoeHhoWFhYSEhISDgoKCgYGAgIB/f39/gYGCgoGBgYGCg4OEhYWGhoeJiYqKioqK
iYyKiYmHh4aFhYWEg4F/f35+fXx7enp5eHd2dnV2dnZ3d3h5eXh4e31/gICCg4SE
hISEhIWFhoaGhYSDg4OEhIODgoKCgoGAgH9/f39/gICBgoKDhIaHiImKi4yMjY2N
jo6OjYyKiYeGhIKBgH58e3p5eXp5eXh4eHd2dnZ2d3Z2dnV1dXZ2dnd4eHh3d3d2
dnZ2dnZ3eHh4eHl6fHx8fX5+fn18e3p6eXl6enp5eHh4eHl5enp7fHx9fX19fX5/
f4CBgoOCgoKDg4OEhYWFhoaGhoWFhYWEhIODgoGAf4CAgICBgYKCgoKCg4SEhIWG
h4iHh4eHiIiJiYqLjI2NjY2Ojo6NjYyLioiGhYSDg4KBgYKCgYGBgYGBgH9/f39+
fn5+f3+AgIGCg4SEhIODgoKCgoKCgoGBgYGBgoODgoKDgoGBgYGBgH99fX19fHp5
eHd2dnZ3d3h4eHh4enp7e3p7e3x8e3x9fn5/f3+AgYGBgICAf359e3l4d3Z0c3Jx
cXBwcHBwcHBxcXJycnNzdHZ4eXp8fX1+f3+AgYKCgoKBgYGBgYGBgYGCgoKBgYKC
goOCg4ODg4OEg4SEg4KCgoKCgYGBgoKCgoOEhIWGhoaGh4eIiYmJioqLi4uMjIuL
jIyMjIyMjYyMjIuKiYmJiYmJiYiHhoWFhYWEg4OCgYCAgIGBgICAgICAgIGAgICA
gIB/f39/f39/gICAgYGAf35+fXx8fHt7enl6eXl5eXl5enp6enp6enp7e3x8fHx7
e3x8fHx8fH19fX19fX1+fn9/f39/f39/f39/gIGBgoKDhISEhIOEg4ODgoKCgoKB
gYGBgoODg4SEhIOCgoGBgYCAf39/fn18fHt7e3p5eXl5eHZ2dXV1dXV2dnd3d3h4
eXp7e3x9fn5+fn9/gICBgYKDhIWFhYaGhoaFhYWFhYWEhIODgoKBgYKCgYGBgYGB
goKDhISEhYWFhoWFhoaHiIiIiImJiIiHh4aGhoaFhISCgYGAf39/f39+fn9/f39+
f3+AgIB/f39+fn5+fn9/f39+fX18fHt7e3t6eXl4eHh4eHl5eXp5eXh3d3d3d3d3
d3d2dXV1dXZ2d3h5eXp6e3x8fn+BgoOFhYaHh4iJiouLjIyMjIyMjIyMjIuKioqJ
iomIiIiIiIiIiIiIiIeHhoaGhoeGhISDgoGBgH9/fn5/fn5+fX5+fn5+fn+AgYGC
goOEhYWGh4aFh4aGhoWFhYSEhISDg4KBgYCAgIGCg4SEg4SEg4ODgoKCgoGBgYGA
gIGBgYKCg4ODg4SEhYaGh4iIiYmJiYmJiYiIiIiIh4aFg4KBgH99fHt6eHh3dnZ2
dnZ2dnZ1dHR0c3Nzc3Nzc3NzcnJycnJxcXFycXFwcHFxcnJzdHV3d3d3d3h5eHl5
eXp6enp7e3t7enl5eXl4eHd3d3d3d3d3d3d3d3d3d3d2dnZ1dXV1dHR0dHR0dHV1
dnd4eXl6e3t8fX6AgYKDhIWGh4eIiYqKioqKiomJiIeHhoaFhIODgoOCgoODgoOD
g4OEhISFhYWGhoeHh4eIiImKi4uMjI2Ojo+QkZKTlJWWl5eYmZmZmZqZmJiXlpWU
k5GQj46NjIuKiIeGhYWEg4ODg4ODg4OEhISEhIWEhISDgoGBgH9/fn19fHt6enl4
eHh4eXh4d3d3d3h4eXl6enp7e3t7e3t8e3t7enl5eHh3dnd2dnZ0dHNzc3Nzc3Nz
cnJxcXBwcHBwcXFwcHBxcXJzc3R1d3h4eHl6ent9fHx9fX19fX19fX19fX19fXx8
fHx8fHx8fX5+fn5+f4CAgX+BgoKCgoKCg4OEhISFhYWFhYWFhoeHhoeHiImJiYmK
ioqJiYqLi4uLi4uLjIyLi4uLi4qKiomKiYmJiYmJiYmJiYmIiIiIiIiIh4aGhoWF
hIODhISEg4KCgoKDg4ODhIODgoKCgYGCgoKCgoKCgoKCgoGAgH9/f359fHx8e3t6
ent6enl5eXl5eXl5ent7e3x8fX19fn5+f39/f39/fn9/f39/fn18e3p6eXh4d3d3
dnZ2dnZ2d3d3eHh4eXh5eXl5enp7e3x9fX1+fn5+fn5/f39/f35+fX18fHx8fX18
fHx8fX1+fn5/gIB/f39/gICAgYGCgoKCg4OEhISFhYaHh4eHhoaGhoWFhYaGhYSE
hISDg4KBgYB/fn19fXx8fHx8fX5+fn9/f4CAgIGCgoKCgoOEhIWFhYaGhoaGh4eG
hoaHh4iJiYiHh4eHh4iIiImJiYiIiIiIiIiIiYmJiIiIiYmJiYmJiYmIiIeHh4aG
hYWFhYWEhIODg4KCgYGBgICAgICBgYGBgICAgH+Af39/f39/f4GAf39+fn19fHt6
enp5eHh3eHh4eHh5eXh4eHh4eHl5enp7e3t6e3t6enp6eXl4eHd3dnZ1dXV0dHNz
c3JycXFxcnJycnJyc3N0dXV2dnd3d3d3eHh4eHh4eHh3d3d3d3d3eHl5enp7fHx8
fHx9fX5+f3+AgIGAgICAgICAgH+AgICBgYKCg4SEhYaGhoeHiImJiYqKiouKi4uL
i4uLi4uKioqKi4uLjY2Oj4+QkJGRkpOTk5SUlJSUlJWUlJOTk5OSkZCPjo6NjYyM
i4uKioqJiIiHh4aGhoWEg4KCgoKBgICAgICAf39/f39+fn5+fn59fn5+f3+AgICA
gIB/fn59fHt7enp6eXh3d3Z2dXV1dXV1dHNzc3N0c3N0dHRzcnJycXFwb29vbm1s
a2tqampqamtsbW1ub3Fyc3R1dnh5eXp7e3x8fX19foCAgICAgYKCgoKDhISEhISE
hISEhISFhYWFhYWFhYU=
}
;; [-----------------------------------------------------------------]
;; [ This function plays the sound file.                             ]
;; [                                                                 ]
;; [ The calculation seems to find the length of the sound in        ]
;; [ milliseconds, for compatibility with timer events.              ]
;; [ The length of the sound data is in bytes.                       ]
;; [ A sample of sound takes more than one byte.                     ]
;; [ The number of bits divided by 8 gives the number of bytes in    ]
;; [ a sample, BUT, that must be multiplied by the number of         ]
;; [ channels to give the total number of bytes used in a sample.    ]
;; [ Dividing the total number of bytes in the file by the number    ]
;; [ of bytes in a sample gives the number of samples in the file.   ]
;; [ Dividing the number of samples by the samples per second        ]
;; [ gives the number of seconds of sound in the file.               ]
;; [ Multiplying the number of seconds by 1000 gives the number      ]
;; [ of milliseconds that the sound will play.                       ]
;; [                                                                 ]
;; [ In this procedure we load the sound file from disk,             ]
;; [ calculate how long it will play (for the progress bar),         ]
;; [ set a flag to indicate that the playing is in progress,         ]
;; [ and launch the sound into the sound port.                       ]
;; [-----------------------------------------------------------------]
WAVPLAYER-PLAY: func [WAVPLAYER-WAV-FILE][
    WAVPLAYER-LOADED-WAV: load WAVPLAYER-WAV-FILE
    WAVPLAYER-PLAY-TIME: 1000 * (             ; milliseconds per second
        (length? WAVPLAYER-LOADED-WAV/data) / ; bytes in the file
        ((WAVPLAYER-LOADED-WAV/bits / 8) * WAVPLAYER-LOADED-WAV/channels) 
        / WAVPLAYER-LOADED-WAV/rate  ;; bytes per sample / samples per second
    )
    WAVPLAYER-PLAYING?: true
    insert WAVPLAYER-SOUND-PORT WAVPLAYER-LOADED-WAV
]
;; [-----------------------------------------------------------------]
;; [ This is the function behind the "Play" button.                  ]
;; [ Redisplay the progress bar with a value of zero so that it      ]
;; [ shows no progress.  Then call the function to actually play     ]
;; [ the sound file.                                                 ]
;; [-----------------------------------------------------------------]
WAVPLAYER-PLAY-BUTTON: does [
    set-face WAVPLAYER-PROGRESS-BAR 0
    WAVPLAYER-PLAY WAVPLAYER-WAV-FILE
]
;; [-----------------------------------------------------------------]
;; [ This is the function behind the "Stop" button.                  ]
;; [ Reset the indicator that says whether or not playing is in      ]
;; [ progress.  Reset the start time in case we play again.          ]
;; [ Empty out the sound port to make the sound stop playing.        ]
;; [-----------------------------------------------------------------]
WAVPLAYER-STOP-BUTTON: does [
    WAVPLAYER-PLAYING?: false
    WAVPLAYER-START-TIME: none
    clear WAVPLAYER-SOUND-PORT
]
;; [-----------------------------------------------------------------]
;; [ This is the window that is displayed when the script is run.    ]
;; [ It is a "play" button, a "stop" button, a progress bar that     ]
;; [ will change as the sound plays, and a decorative box.           ]
;; [                                                                 ]
;; [ The decorative box has a rate attached to it.                   ]
;; [ The rate of 1 will cause a timer event to occur every second.   ]
;; [ This event will be processed by the                             ]
;; [ WAVPLAYER-TIMER-EVENT function                                  ]
;; [ defined below.                                                  ]
;; [-----------------------------------------------------------------]
WAVPLAYER-MAIN-WINDOW: layout [
    button "play" [WAVPLAYER-PLAY-BUTTON]
    button "stop" [WAVPLAYER-STOP-BUTTON]
    WAVPLAYER-PROGRESS-BAR: progress
    box 200x50 pewter rate 1
]
;; [-----------------------------------------------------------------]
;; [ This defines a function that will respond to events             ]
;; [ produced by the "rate 1" declaration in the                     ]
;; [ "WAVPLAYER-MAIN-WINDOW" window.                                 ]
;; [ It gives the function a                                         ]
;; [ name so we can remove it later, and puts it where it must be    ]
;; [ (insert-event-func) so that it will be called when events       ]
;; [ take place.                                                     ]
;; [                                                                 ]
;; [ The purpose of this function is to catch timer interrupts so    ]
;; [ that we can update the progress bar.  We only update the        ]
;; [ progress bar if the sound is playing.  (We set a flag for       ]
;; [ that when we played the sound.)                                 ]
;; [                                                                 ]
;; [ We use the WAVPLAYER-START-TIME to tell us if this is the first ]
;; [ interrupt.  If the WAVPLAYER-START-TIME is not set              ]
;; [ (meaning this is the                                            ]
;; [ first interrupt), we will set it to the time of the             ]
;; [ interrupt.  For every subsequent interrupt, we will subtract    ]
;; [ the start time from the subsequent time to give the time that   ]
;; [ has WAVPLAYER-ELAPSED from the start time,                      ]
;; [ which also is the length of                                     ]
;; [ time the sound has been playing.                                ]
;; [                                                                 ]
;; [ When we divide the length of time the sound has been playing    ]
;; [ by the total length of the sound, we get a fraction             ]
;; [ (a number between zero and 1) showing how much of the sound     ]
;; [ has played.  That number can be used to update the progress     ]
;; [ bar.  A progress bar uses a number between zero and one to      ]
;; [ show no progress (0) to 100 percent progress (1).               ]
;; [                                                                 ]
;; [ If our calculation of the fraction that shows how much of the   ]
;; [ sound has played gives a result of 1, that means that the       ]
;; [ sound is done playing.  In that case, we can reset the          ]
;; [ indicator to show that the sound is done, and reset the         ]
;; [ start time in case we play again.                               ]
;; [-----------------------------------------------------------------]
WAVPLAYER-TIMER-EVENT: insert-event-func func [face event] [
    if event/type = 'time [
        if WAVPLAYER-PLAYING? [
            either none? WAVPLAYER-START-TIME [
                WAVPLAYER-START-TIME: event/time
            ] [
                WAVPLAYER-ELAPSED: event/time - WAVPLAYER-START-TIME
                WAVPLAYER-PCT-DONE: min 1.0 WAVPLAYER-ELAPSED / WAVPLAYER-PLAY-TIME
                if WAVPLAYER-PCT-DONE <= 1.0 [
                    set-face WAVPLAYER-PROGRESS-BAR WAVPLAYER-PCT-DONE
                ]
                if WAVPLAYER-PCT-DONE >= 1.0 [
                    WAVPLAYER-PLAYING?: false 
                    WAVPLAYER-START-TIME: none
                ]
            ]
        ]
    ] 
    event
]
;; [-----------------------------------------------------------------]
;; [ Start the program.                                              ]
;; [-----------------------------------------------------------------]
WAVPLAYER-PLAYING?: none                ; Show nothing playing
WAVPLAYER-START-TIME: none              ; Clear our start time indicator
WAVPLAYER-SOUND-PORT: open sound://     ; Necessary preparation to play
center-face WAVPLAYER-MAIN-WINDOW       ; Put the window in the center of screen
view WAVPLAYER-MAIN-WINDOW              ; Show the window
;; [-----------------------------------------------------------------]
;; [ Put the program in a state to respond to events (mouse clicks,  ]
;; [ button pushes, and, important here, timer interrupts).          ]
;; [ If an error happens, set the word "err" to the error object     ]
;; [ that is the result of an error.  Then, if we do have an error,  ]
;; [ "disarm" it to gain access to the values in it, "mold" it so    ]
;; [ that it looks like REBOL code, and then print it.               ]
;; [-----------------------------------------------------------------]
if error? set/any 'err try [do-events] [
    print mold disarm err
]
;; [-----------------------------------------------------------------]
;; [ When the "WAVPLAYER-MAIN-WINDOW" window is closed               ]
;; [ with the X in the corner,                                       ]
;; [ the program will resume running here.                           ]
;; [-----------------------------------------------------------------]
close WAVPLAYER-SOUND-PORT              ; Necessary cleanup
remove-event-func :WAVPLAYER-TIMER-EVENT () ; Inserted earlier, removed now
quit                          ; not quitting leaves rebol.exe in memory

12.10 Playing an alert sound

The highlight of the above example was the progress bar that accompanied the sound. Here is a demo of a program to play one sound. The program works on a Windows computer. It locates the folder of system sounds, provides a list, and lets you click on the different sounds to hear them. The script includes a function that is called for each sound, so you may copy out that one function and include it in another program. Then you could provide your own block of sound file names to play, and play an appropriate one at an appropriate time.

Note one thing about the example. If you try to play sounds too rapidly, the program will crash. It seems to have to wait for one sound to play before playing another. Click through the sounds slowly and it works. Click too quickly and it crashes. This would not be a problem in the expected use scenario, where you play a short sound in response to something like a button click. There is documentation about using sound on the REBOL web site in the section about the Software Development Kit. The sound capability used to be available only in the paid version of REBOL, but it was moved to the free version when development stopped.

REBOL [
    Title: "VID test harness"
]

IMAGE-FILE?: func ["Returns true if file is a wav file" FILE-ID] [
    find [%.wav] find/last FILE-ID "."
]
REQUESTED-FOLDER: request-dir/dir %/C/windows/Media
if not REQUESTED-FOLDER [
    alert "No folder requested" 
    quit     
]
change-dir REQUESTED-FOLDER
FILE-LIST: read %.  
while [not tail? FILE-LIST] [
    either IMAGE-FILE? first FILE-LIST [ ;; always check the first one
        FILE-LIST: next FILE-LIST  ;; if a wav, move on to the next one
    ] [
        remove FILE-LIST           ;; otherwise remove the non-wav file
    ]
]
FILE-LIST: head FILE-LIST  ;; return the list at the head
if empty? FILE-LIST [
    inform layout [backdrop 140.0.0 text bold "No images found"]
    quit  
]
;; FILE-LIST now is a block of wav file names. 

SOUND-PLAY: func [SOUND-FILE] [
    wait 0 ;; Must do; initializes event handler. 
    SOUND-PORT: open sound://
    SOUND-LOADED: load SOUND-FILE
    insert SOUND-PORT SOUND-LOADED
    wait SOUND-PORT ;; If you don't wait, you don't hear it. 
    close SOUND-PORT
]

MAIN-WINDOW: layout [
    text "Select a sound file to play it"
    MAIN-LIST: text-list 300x700 data FILE-LIST [
        SOUND-PLAY to-file MAIN-LIST/picked
    ]
    button "Quit" [quit] 
    button "Halt" [halt] 
]

view center-face MAIN-WINDOW

12.11 Playing a key click sound

This is another variation of the sound-playing demos. It is a function that plays a sound hard-coded into the function. The sound was recorded from a spring-operated keyboard, and the original purpose of this function was to provide audible feedback on a window full of buttonw. One would paste this module into a program, or, if it is saved as a separate file, "do" the module at the beginning of a program, and then, when one wanted a click sound, one would code:

attempt [CLICK]

The use of the "attempt" function allows the program to continue if the sound can't play for some reason.

The canned sound could be replaced by any sound of your choosing, by converting the sound file to base-64 as explained elsewhere.

REBOL [
    Title: "Click"
]
;; [---------------------------------------------------------------------------]
;; [ This is a function that will play a particular canned sound.              ]
;; [ It original use was to play a clicking sound when a button was clicked.   ]
;; [ The canned sound was produced on a GNU/Linux computer with a sound        ]
;; [ recording program that would save a sound as a "wav" file.                ]
;; [ The recording procdedure was to place a microphone right next to a        ]
;; [ key on a spring-operated IBM keyboard, then, as fast as possible,         ]
;; [ start recording, press the key, and quit recording.                       ]
;; [ The way to use this procedure is to code the following as part of the     ]
;; [ code for a button or whatever you want to produce a sound:                ]
;; [     attempt [CLICK]                                                       ]
;; [ The use of "attempt" will allow the program to continue running if        ]
;; [ no sound hardware is present and the sound can not play.                  ]
;; [---------------------------------------------------------------------------]
CLICK-DATA:
64#{
UklGRmQFAQBXQVZFZm10IBAAAAABAAIARKwAABCxAgAEABAAZGF0YUAFAQDhB0AG
WQnIBzoMrAppCg0J3w2cDLYNDgw8BMoCXAiYBtYSURGiCRcIOAC6/owNQAy2EkER
HQbEBEkF4AMuDswMIQ2cCy0H2gVlBdoD2wZMBRcLzgkhDMUKbAUsBA0DqgG2DQsM
QRDMDsQBngCLAVsAEhCjDvQKsgmn/XH87QWLBDQP9Q18BzMGTAPwAcgIUAe4CTAI
+gZyBYUFBgQjBKsCXAUWBFkJ2AebBjYFygFSADYIiAapDRQMfwXtA5gF0QNkELYO
2ApcCWIC8wCmDdUL7xAeDwYEpAKIB/EFoBT2EnANBwyeAxYCTQycCsMTVxIuDaUL
hQbhBPEIlQe5DTEMbQ7YDKgIEweYBQ0ETQ6/DCUTcREaBpgEWAEcAHES6RDZFNwT
WAL2ACIBuv9eEgsR6RJhEZgGfAU9BzkGVw7oDLkORw2yCzcKPQkKCPEJlQiNDxsO
vA5wDYUEIwOSBFIDYRHlD04QvA45BL4C3gdyBrkRLhCADC0LIwXnA9sHMwYkC6UJ
QwvICQQJggfdBIgD7geLBj4P/g3hCo8JwQIpAfQIiAc+D/4NfwYTBYsBTwCWCkYJ
CA1pC3IFCgTtBVkEUwu7CbsKYAlTCd4HhQgzB18G+gSfCBcHNwpNCUYF8wNZBf0D
xQySCxEKbwinAVUA1AdyBrwNJwwpBasDqwIvAf4LrArOCD0HQv/D/asGOQVED8IN
UAe0BXIC2gA9CtsI2AxdC7UHaQY5BuoE1AdiBtUJYwifChQJuwVyBPQEkQP7DcUM
CA6vDF8C8wCCBC8DRxHPDxcNqQu0AQ8AjAcNBpAPNA7qB1YGXwMQApwK9AjICz0K
QwbtBBoGvgS4CH8HiQkHCI8IWQd1BBADmAJbAf0HpQYRCZUHLALqADAFxwNKDdIL
0Qc2BrcBYgDICGMHNwvuCXIDFgKVAykC0Qh1B5IGSQU5Bg0FmQlGCH8FJgQGBPAC
2AuDCnMJPQgcAL3+TwUgBO4MfAuVA0ICHP/J/RoKnwjLClwJ1AE4AEIE5wJvCSAI
QwWoA2IE3QJvBwcG3QO+AgMEpALxCW8IzgYwBboBWACcCUAInAsaCkUBMgC6AzwC
wg5gDWYIywZY/gL9Rgb0BDcLywnBAkwB0AJ+Ac4JRghyBiwFkQL8ANQEIAMDBb4D
mwUGBCMGzgTtAJf/EgDA/owJxQfuCGwHJf7f/FgD4wGzDkENqwQ8A6b7O/pgCRoI
RA4eDeb+h/2X/hL9XQwXC10K+gjjAH7/sQRcAw4L2wlDCS0IygRrA1ICCQH9BeEE
+Au4CssGggXj/cb8PAbnBPIQgw/HBWUE1vtq+o8IfAdhEBEPNgIpAQz98vsHCPQG
7gq4CZsEbwMAAgkBCgTQAn8HVgY9CeoHugJSAcD+yf1cCEYHpQsdCvb+cf3y/K37
rAs3CnMM+woMAL3+VQEDAEkJ5AdMBxAGkgQTA5UENgOuA4ECZgYgBW8HKQYZAI7+
CQDs/lMLGgodCmYIwP22/AMCAAHVDHAL/QXHBJ3+tv2LBjwFdgj3BqQBTwCSBE8D
jAkgCJgFNgSFBUkEsgh1B0YEAAN1A08CpQqGCdsHiAYAAKT+EAa0BDQLyAmhApcB
mAOFAqYMZguhBWgEpP5L/egJsghTDBEL8/6X/QYB0/8nDd4LIweYBTL97/tPBe0D
WgwUC0kF2gMMAMr+aAQ5AyMI/Qb0BpgFEwLgACwAwP6MB1MGAQzbCuoBugCH/kX9
QAw0C8kOiQ1e/wb+7/3m/DQLMArYCXkIJf4i/Q8B1v8KCtQI6gfUBogCJgHBAjIB
TAXNA7gGVgWxBDkD1v6k/YsB7f9pCUMIHQXUA+D9p/wTBfcDBArRCBYCqgCE/1j+
9wWhBHUGxwS6ApcB6gLUAdACngFSA0ICYgYpBccEaANIAT8ARgUQBNEHuwZFARkA
JQAc/9EHngY5BvQEIv78/N0B4wCyCJgH7QTHA18BSwD6BOcDrgSOA5sCjgFcBFID
bwQ2A/ACxAF8BV8EPwUTBOYAwP8pBLoC6wlvCDMEzQIl/+/9uwdTBlkKzgjdAHv/
ngFCAAoK8QihBYIEe/9R/jwFygOcCEYHCgR4AuABhAADBIUCeQbqBFkGGQVYARYA
/P66/QMF7QNcB9QFGf90/Xf+L/3OCFYHiwZvBQv7zPkM/9D9jwlJCKsCLAF9+jf5
kQImAasHPAZuAfP/OP/j/Y4EOQMjBtQEAAOXAYQAA/+0AXsAdQXtA08EAwNr/+z9
LADN/rEGeAXhBagEfv4Y/b0BEgAzCOoGcgI/ASX9FfzHA2gC8QaoBRYB1v8///b9
YgI1ARAEygLRBJ4DiwMjAp4AP/8pA70BHQa7BHsCQgGk/17+kgQsA5IGJgXEAXsA
mwJbAcEHTwaVBRAEhQL2ANEDmALaAo4BWAIGARMFxAMjA/YB2v+n/tEDcgJJBgAF
IgHT//YAt/9cBRMEAAO9Afb+fv1bAvwAAAS6Atb/l/4pAQMACgW6A/ABtAD8/7D+
aATnAnIE7QKHAE7/HAIAAVUDGQIGAtoAXAMJAqcCygFe/0X+cgMZAmYIIAdVAT8A
h/yN+wMGpAS4CDMHevyE+2r7R/oUCLgG7QXqBG36HvnD/b38eQhjBzMG8AQJ/ar7
Nfzf+voDugJmBwAGP/8J/hX63/h7BD8DbQvICbT/KP4F+n34PQixBjQN2wsD/0X9
ivv/+eoHmwYECqsINQEpANb/bv6IBBMDaQftBS0GygQfAdP/ugBI/2YIUwfCCEYH
OP0l/GT+Uf3OClAJKgeVBS781vovARYAuAh1B74DaAK0ADv/aATjAj8DvQHgAVsA
cgQGAxMC2gCK/zX+zgSFAwcGtAQV/6T9WwEJAJUIIwccA9cBMv7p/DwFiwPHBZgE
8/6q/dQBtABTBlYFdQE1AHgAQv/xBYUE4AOnAoH/SP7zAtQBiwMvAun+sP0mAQAA
1wNbAkj/Nf5xAGX/Jgb0BJ4Amv/J/LD7kgViBJ4FZQRO+1T6wP+U/tgJjAikAzIC
ZPz1+hwDpwE6CKgGNgMGApcAZf9+A08CAwa3BDAG2gSEAUsA1v6a/Z4GWQX7Cc4I
SP7Q/F777/nOCZ8IXQokCR77Ffpb/Qj8mQlGCAoE0AJt+hv53QB+/8sGaQX9AZoA
Yf8V/lUBTwATAuAAngOBAsoCcQHJ/Xf8xAB+/54GQwWnAHv/EvzJ+jAF8APqBsQF
L/0V/C//+f1GByYGRQJPAYT9ivzaAn4BiwMJAvn+8/3qAG7/cgLtAHT/H/5JAhMB
DQSFAlv9Ufzj/cb8cgUNBO0AXv+5+p35ewImAT8FzQPp+6D6rfxR+9QFXwQZAq0A
6fy9+7ECUgGoA1UCoP50/V8BOAAjBPACH//J/VUA+f6VBWgEjgB+/5T+kf39BqsF
XAQjA4f6TvmhAHj/jAdZBlj+Tv3f+6D6fwV7BJsENgMY/LD60/5+/U8E/QJrAVIA
W/93/pH/iv6a/m794AEDAVIESQNB/Uv8SPwV+7EGggWFBCAD6Pjf90IA//49C9sJ
jgBS/7n3UPZMA+oBlQnxB9n+wP1x+3H6oQNfAuoFxwS6AFL/rf2E/BYAp/7tA6sC
XwIMAQv77/m9/JD7vgZ8BTwD7QEx+MX27/2U/OEHlQbw/8r+4viW980Aiv+bBFgD
Ff/J/Vv9xvuK/1v+4wHKADwDLAIAAOz+LvwC+0UBDwA5BvcEw/6B/an6cPkDBAkD
rgZ/BQL9w/th/fz7MAXkA+oBiwDG/Yr84wGBAAMC3QAM/9D9WAEJAKcBYgDN/Y38
XgAM/1UDAALQ/kv9GP0C/JsCewEDAqoAiv1x/FUB/P/6AgYCdP2t/ND/h/6LBWIE
5v/w/nr8W/tvAwMCkQNYAtn9tvwvAOD+WQQNAwwB8/+O/0j+/ADw/wAADP8WAvMA
5ASeA2j/Ev7m+8n6OQUzBP0GvgVk+0T6NfwS+yMIDQeOBDYDkPlU+Kr+ev2SB0wG
7QK9AR/86frG/aP8RgQWA8QFdQRO/gz9OPoo+Z4DUgL0CWwIfv4V/VH4DverBX8E
TQo6CXH8RPu8+aD4QAcWBqsHZgaN/F77jf0+/NoEtAN/BFIDrf9x/q39W/wiACX/
vgShA6QClAEb/Pj6yv6k/fQF4QSuAWUAC/vl+eMAwP+7BbcEBv/m/ZD8hPscA/YB
GQMfAhL/+f23AJr/dQFVAJH/d/7qANb/3QGRAEUA8/5VAj8BVQMvAs3+cf01AAz/
Awa0BMcBwAAy/C77ngJxAQ0G1wRe/v/8Nf78/EkFYgQ/AlUBHP0l/J4BawDkA7cC
hAAv/+0Aof+IAV4Akf7G/cQBmgBGBR0Ew/+U/vn91vy4BbsEqwSCAwj8AvtCANn+
8QerBgMCAAGn/H37jgKLAa4FrgR+AWIAuv+z/kwBIgC6An4BtAN+AuMArf/m/cz8
cgNSAi0GAwXG/bD8avxR+7EGWQVMBS8EsPqK+S/+2fxTBxoG8wHTAOn7mvpfAVIA
FgXtA/YAqv9F/wb+CQHW/wkC0wCrAnUBhwCB/83+0P2RA1ICmAWLBDv+4/yn/UH8
EwakBO0DvgKz+5r6iwCK/y0H2gX2/37+evw4+2UEIAN/BHgDOP4P/d3/uv7KAogB
xACU/80BvQAAA/ABzf+H/u0Ap/8NBQoEugBb/+D9lPz0BMEDSQXEA+z8oPvQ/+D+
1AeIBpQCYgEG/r38wQSuAxoG6gQDAMb+3QHdACkG9wRMAmIBSAESALcEcgNfAx8C
AALEAL4EoQOuAsoBAAAZ/84ElQNcBTwEPv4o/TgAhP98B5gGvgKUAUv9GPwWA+AB
3gXdBI4Agf8//0j+eAJYASkCUgFPAlsBiwFxANb9w/zqAOD/6gW3BK3+pP0e+Tf4
MwPmAa4HbwZ0+5D6G/lX+FIFUgTEBY4E6fr4+ZP7ffozBF8DygSOA//+1v3M/Ob7
AAEAAMEFeASIAXEAqfp9+fD/8P6JCIgH+QDm/+v38vYTAvMAeQpNCUX/dP5n+ZD4
WQRyA0YHQAYy/yv+rf6K/W8DbgLtA+MCfgKEAVIBLAD5/yX/7QPwAr4FAAVV/3v+
Vf5k/ZsGmwWuBbQEIv1n/KoAnf+4BnUFYgEsAMP+0P3aBDwEJgRcA+P+7P2kAs0B
qAWkBMAAlP/tAPb/tATHA/MB8wAZAEL/ZQNiAhYCQgFh/3H+ZQNSArQCGQKj/DX8
vQAfAEYGRgWX/gL+JftB+iYELwO0BO0DH/yH++n9+fxCBHgDpwGUAEX+SP0MAC//
GQBx/yIAaP/QAfMAiv6z/QL8GPtoApcBEARYAzH7WvoF/DH72gUmBb4C+QGA+Yr4
uv2t/CkFMwQcAVgAzPvJ+vz+Bv4zAzkC/QEGAbr9wPzT/Pz7lALBAdcF2gRC/mT9
Qfp6+eoDMwNGB38Gw/xe+737yfo2BmIFtwTgAy78dPu9//P+SQZyBTMDUgJe/y/+
twCq/28DmwJfBJgDsQLqASkAA/+kAsQB1wbUBW4CYgGX/pf9UgUjBOQG9AWa/rP9
D/9C/kkHIAYdBMECQf1B/HsCqgGLBkwF7QD2/8D/vf6YA08CgQK6AacA5v8jAuYA
bgFPANABtADUBL4DygHQAJf9gfzgAsQBNgY8BU7+Rf07/fn7Ewa+BDMEPAOQ/LD7
aAB4/2kFWQQ4AEv/ev2X/GIBewDKAdoAFgAZ/3gBPwCeAIf/lP9+/hkDCQIJAvMA
p/yg+6r/qv60BLQDsP/D/oH8YfsZAxYChQRVA//9xvz5/Qz98AIDAjwCTAHK/+D+
BgDN/m4Al/8DA+oBpANoAvz+7P13/pr9kgWYBBME3QKE+yj68P72/fQH5wYMAuoA
3PkF+QABGQCSBm8Fof+E/sP7s/oDAa3/CQPXAcD/t/7G/b383f7J/SMC/ABuAlgB
+fzW+zX93PvEA44CpAJ7Abz6v/nD/Zf8jgVZBEwBLwAF/OL6mwF+AKEEYgNO/0L+
iv5Y/eoBsQDEAZQAHAHp/6cBZQB4AE7/5gAAAFUDFgLKAKT/d/5+/VsCDAHdAq4B
e/4+/bcAh//qBKsDkQCU/wn+KP1lA4UCVQNrAvb9w/yqAKT/ZQVMBFsBIgCd/rD9
cgM5ApUDbgJ+AGv/KQHm/6EBmgCxAacA5wPjAmICUgEi/iL91wHwABMH6gXTAPP/
d/xX+2IDLALOBcEEuv5k/Q/+6fwzBNcCewMpArD/Pv6E/2v+pwB0/4gBRQBJAhYB
s/5k/V78OPspAwYCtAXHBD79OPz8+9z6dQVCBBkFygMF/BL7WP4f/UYG5AQ8BNoC
Tv41/cr+4P1iAykCVgWCBH4BrQAY/TL86gHdALIHwQbgAMD/evqG+WUDPwJmCEwH
uv3M/AL7xvmIBXUEkgWVBLr83Pt+/pH9GQQZAxMCCQFl/4H+WABF/7EAmv/gATUB
LAPQAYH/bv7D/wz/dQVoBKcClwHv/N/71wGeADkGMwWO/3v+SP4y/SMG5wRcBC8D
Cf3W+6QAkf+SBVIEvQCO/xL+7PxlAoQBugKXAeP/Iv9lAD//wP+q/oT/Xv4sAuYA
SABV/xj8//rEAJ3/ewSLAxj9Bfw++//5LwTaAvADpwJB+y767P3Z/JUEVQN7ATIA
2f2z/JEAWP94AW4ALwE/AF8COQF7ACz/kf9h/lUERQPRA34CCf3i+xkAmv6CBjYF
VQFSAIH8hPvUAqcBcgVcBLD/aP66/rD9VQI/AcoClwEcAgMBngFuAOb/0P66AqEB
QwUjBGH/SP6n/Ir7twTzAyYGJgU7/Ej7DP72/OEH4QYjA3gCtvq5+dMA4/8wBgMF
LAAs/8P9yfw5AgwBtwKEARYB0//gAM3/tP93/i8BNQC3A6ECnf+a/j78V/vKApsB
7QPXAor7cfrf/Nz75ATzA93/0P5h+Tf4ugBx/2wEZQPm/Bv8UfwS+3UCbgEZASUA
8/32/PP/2f5VAJH/1v/5/gAC0AApADL/l/3c/L4CvQEKBP0C3/v8+iL9RfxvBkMF
4wHKAKb5ufixAIf/1AWVBKD9Z/yg+4f6tANrAhYD/QFn/XT8e/97/q4BiwC6ALD/
sQF7AGsAKP/j/bD8ngGaAIsEiAPz/Qz9H/35+64FQgTgA+cCsPvy+nH/a/4dBvQE
DAHa/w/90PtoAS8AawMfAqoBoQAyAS8ADADw/jIASP9VBFwDAwL2AMn7wPqHAHv/
1Ab0BeD/5v5k+mT5fgJuAXgFcgSK/KP7jfuD+uYBzQC9AeAAGf4l/RL+SP1h/3T+
WwFlAFgBHwDG/MD7rf2U/DMEzQIcAtoAkPo++Uj/OP6uBqgF0P/5/qD6w/mrAn4B
1wTaAyL98vv//fL8iwOYApoAl/+w/fn8qgDW/4QA4/84/yX+4ADA/3v/lP7c/bb8
vQFrAP0B/ACq/If7Nf/5/dcEtAPm/7f+Ivz1+uADrgLnBL4DS/z8+mj+Uf1ZBm8F
WwJFAQz9UfwcAuYAqwR4A5cAvf+d/6T+RQFVAOoBwADqAu0BQgFVAMP90/yXAacA
PAYzBcf/t/44+2r6oQOkAgAGtASt/KP7V/yH+1kEewMgA0wC0Pzy+7D+hP39AQkB
gQFSAM3/wP7m/en8mv22/EICPwE/AlIBHvtX+qf8pvvUBLEDbgGtAMn5+Pjz/Sv9
iARvAzwALP8o/Av7WP81/tABoQCeAH7/hP6X/T79UfxeAG7/iAN7Atb+pP3J+uX5
oQHQAG8FXwRk/W78o/uH+v0D7QJyA24CFfwl+2H+VP1fBIIDmwHqADv+dP2BAMr/
AwJFAe0B4ABMAXEA9v/w/vYA0P8DBOcCkQHHAHT+l/3EAscB+gQsBKT+uv1Y/oH9
TAWVBCMDRQJ6/KP76gADAIsFqARVAIH/yf0C/RYCAwHgAQMBQv8f/i//O/5FAEL/
SAE/AIUCTAE1/9z9o/zA+7oB4ACxA5gC0/vi+rn7s/rnBPMD4AL2AX36ivl3/p39
eAU2BKEAYf8P/AX73f8D/9cC8wH8APP/WP+R/nv/bv5bAIH/5wLtAbcApP84/SX8
8ADT/54EYgPK/u/9D/wb+7QCpAEDBNQC5v3p/Pz9Bf3BAZcAGQFeAIr/nf6R/0j+
nf+g/mgBoQCbAfMA+f0Y/en97PxYA0UCWAJuASX8evvK/u/9VgUKBEUBZQCK/FT7
aAElAO0D2gI1/yj+Nf7m/N0A8//2ACUAlADA/53/sP4M/zX+hAGBAJgCfgF3/iv9
oP2d/McCDAI2AmgB9fv8+tP+uv3hBL4DGQA7/9/75voZAgwBEATaApf9cfzg/fz8
iwKBATIBEgC9/qf97f/z/jUBEgCIAaoAKQEsAOn+HP7d/h/+aAKLAYsBVQA7/Qj8
NQA4/08FeASeAHj/Nfwb+9QCvQH6BOoDmv2g/CL9Ffz2AtoBugLUASL/SP6d/6f+
JgLjAJECmwFYAGv/4/3j/EIA5v5yBC8D8wEDAY38k/tiAF7/CgYDBWgAgf+Q+3H6
HwI1AdoFxwSh/8P+Nf5r/ZECtAETA1UC1wADAPz+Mv7p/lX+YgI8Ab4D3QLG/vP9
yfzs+9QC9gHRBMQDfv26/C78S/vdA6cCRQNCAij8G/un/dz8MwNlAsoB7QB7/pr9
hP6q/S8ABv+BAZ4ATwCO/9b83Pv//hn+xwP2AtcAAwDM++/61v+3/m8EngNI/y/+
7PsS+8QCpwEzBC8DVf6U/eb+3P0NAyMCiwFeACz/HP66ALT/DAFFAF4AZf9rAGv/
AwD//qEAsP9rAbQA4P/T/l7+iv0MASkAHwJSAWv+WP3J/cP8QgNJAkICRQGQ/K37
Gf9O/o4EYgOEAG7/V/xB+yUA1v60A5gCygC3/7P8xvuz/tz9pwLNAXgBpACq/bD8
t/7j/a4C2gGbAqQBh/22/G78o/uxAqoBaAR1A639ZPxh/E773QO+AmUDdQIF/LD6
0/x9+5QCUgFbAlIBwP7N/W7+Uf0AAcr/CQEcAIH/jv7J/cz8s/7J/YUCcQEGAbD/
3/sI+8r+4P05BPACHABL/9z83PsWARYA9gD8///9Cf3D/53+WP+H/l7/H/4JA/AB
LwAy/yX76fkSAPn+hQRJA6D+kf3c+/L6rQDQ/z8CFgES/g/91v3Q/NoCDAJyAn4B
4/zJ+yL9S/zHAscB1ALKAa3+fv2w/mf9AAEvAGgBUgCt/rD9SP5h/Z4CiwGeA7EC
Tv5k/Tv9UfwNAyMC/QPUAnH9ffyQ/Mb7KQN+AngDXwJ6/MP7Xv+H/uEFOQVPAJf/
O/qd+T//aP7XAqEBlP+U/hX/+f1oAGj/SwA7//n/5v6B/qT91v4G/lsCTAFfAYQA
AvwV+077XvqLAIf/2gHaAJr9s/xr/YH8NgL5AMP/uv7i+Rj5H/0S/N0CxAEcARwA
1v2q/FH9dPzg/vz9kQGnAKT/rf5q/FT7TwBL/yMELAMo/hX9ffua+uABCQHkAxwD
wP66/W78Mfvd/7r+YgI/AXUAe/+z/ar8Xv9x/lsClAHqAMr/Yf1k/Hj/cf5JBGUD
EwEGAGH6Tvnm/ez8VgVJBLEC2gFe/Wf8LwBF/5IExwPAAMD/ivvJ+m7/SP7dBMcD
6gHdANb8/Psl//z9QgIyATkBFgA4/0j+Iv8S/vwAzf+9AYEAyf3A/PL80/szAyYC
FgPXAZT8nfug/rP9ZQMsAuP///6g/cz8gQB7/08ANf9k/pr99v///gAB8P8DACz/
/P8P/6r/e/57/kH9fv+d/vkAFgAJAOb+e/+K/uoA2v/8/73+4P2j/KEAXv8sAwAC
8P/Z/gb++fxCAC//ygB0/9r/3f5IADL/lABY/6cAjv+xAJH/qv5r/Qz+O/2bAcQA
HAIcARX+vfwf/sz8BgP9AeACqgGn/Yr8rf6t/YsDmAKXAZcAH/7y/ND//P5vA0kC
XwIpAV7+dP3z/dn8lwGLABkDygHQ/sP9Rf4Y/dcDxALUA8QC+fyt+//83/vaA74C
VQQZAxn+6fyk/aP8MwNCAq4CcQE1/Qz8O/44/aQDfgKnAoQB4/2n/P/91vzmAb0A
IAMMAgb/Cf6n/Mn7rgGnAMEE3QMy/yL+Qf0M/DwDSQJ4A2ICGP0F/JH9uvz6AhAC
aAIsAZ3+a/04/jj9lAB7/7QBewD2/8b+mv1x/Jf/aP6xA74CNQA1/3H6ZPn//hn+
lQVVBKEAhP8r+w76DwA7/3IDiAJS/yL+yfyd+73/jv7jAp4BmwFPAOz87Pvc/LD7
lAJVAQADlwFO/PL6lPwx+wAE1wJCAzICffth+r38yfvzA7EC+QH5ADL8Ivvv/cb8
HwL5AMoA4P+R/a38sP2a/MQAe/97AogBt/+n/kH8XvsDABX/iANiAtD+mv2q+3r6
RQE/AN0DwQL2/tD9Bv4J/QwCAwHBATwApP5L/W7/O/4ZAfD/ugDj/9MAyv9SADj/
/P4V/ikACf+bAY4Auv+9/or/oP5PAUsAfgAo/4H+VP20AKr/lAE/ACz/OP7m/wn/
3QGkAOP/vf47/0X+8AHTAO0Ap/+d/sD97QDa/7oCfgEGAOb+7P0S/bb9nfx0/Wf8
jv+K/vYBfgBl/0L+WwBu/28EfgPTAAAA/Pv4+iIABv8ZBFIDZP2j/KP5mfj8/yL/
UgNSAuMAwP9r/0v+vQF7AM0DtwIPAVIAkPvD+h/8BfvHApsBygKRAYD5YPhh+h75
zgWbBE8GMAU+/Dv7Ff0S/HUFYgSIAm4BcPl9+HH7dPpJA1gCXANrAmT8avvT+qD5
EAITAc4FbATK/qD9s/nG+AkBIgB8BWwE3PvD+tX23vVlAFj/xASuAwj8LvuT+NX3
twDH/9QDxAIy/lj9l/tk+pT+xv0mAU8AKP41/RX5J/gP/DX7aAN1Al4Aa/+5+KP3
6fzG+yAFPwQWARwAkPqW+af+0P0QAwwCJf0Y/CT5Ufi6/bP8IgEJAKr+s/3A+9/6
gf1U/DkCKQHaAt0BwPya+1f6Pvnt/+D+PwBO/7n6bfn2ABwAJRHvD60UdBNaEXcQ
0xWdFLcWaBXYCtgJawM/AusJAQlEEBEPXAkUCMP/p/5e/0v+VghAB7kPwg6GCVYI
ngOhAk8CUgG2/aP89fYR9p37tvpiA3UCsPmQ+CXpVegG6AnnnPHL8JD7rfpVBCYD
aASFAzT6Mflm8mbx0/qm+VwFLAS6A80CrPnC+PTxF/GT94n2Xwc5BmESahFkE4cS
URA3D8EGxwXc+rz5oQB4/wYXBhalG5UahQexBgv74vm+B5gGkhwsGy0hByAyFAIT
xAPXAkT7EvpB+ij5S/+U/icKOglHEDEPUgRvA4/zfPLl9wX37gvLClEQPg/H/+n+
I/Ig8bHtxOy18NHvEvo0+dcA6f96/Hr7JPR582Pzr/Jx+6P6pAHKACv+Pv3O8hry
/e1S7Rj3JPZlAU8AbAViBC0JTQg9CicJJQA//8n57/gKBiMFxhGzEFALLQoZAVUA
IwJIARoKKgmJDX0Mggd1BhYA8/5+AJT/cgRVA1IBLAAcARYApQowCYkLQwrp/g/+
ZPqj+ZgDxAIgBh0FBfxE++L1B/Wm+aP4cf5e/Y4BxwD2AhACWABx/1v8qvtU+Ib3
N/WG9Kz2/vVR+XD4SvWl9KvxvvDv+Q75AwXaAyAGEwV1A6QCdQKOAeP9Ff1N+I33
NPqQ+e0AXgAABQYEFgZcBU8FngSrBdcEeQu/Cj4ORw3RBP0D0/yE+xYAGf8cA08C
5gAPADYELANjC0YKfAlvCPoD6gLEA7QCngaeBVMHbAYmAjUBd/mW+BH2KvUV/tb8
vgOnAnH/nf6q/Kr7WP5k/aD6oPkH9UP0c/i/9y/+Qf0f/iv9bvyE+6f9vfzZ/fL8
Bv75/FT9gfxE+kH5QfoF+fAA2v9ABhMFVgViBH8FYgQNBf0DTwBr/639lPxoAIr/
IwMWAsED2gKSBJEDHQT6Ap4DwQKlB1MGXAlmCD8DLALv/fz8W/+H/lsBKQDEAN3/
9wPzAj0HRgZiBiYFaQVSBEMGXAUdBAADe/+a/jH7Tvq8+A74ufvA+vkBCQHaA7oC
TwBY/zIBNQAgA1IChP+O/sb8l/tr/mf9Iv4o/dP6JfoS/Nb6DAH5/1IDbgJ1Aq4B
7P4P/tz7z/p3/aP86f+6/nT9tvzZ++L69v4P/rEArf/m/hn+jgDt/z8EMwNPAmUB
O/5r/dAAzf+uBbQEMAcaBu0FEAUQA/YBfv+a/hX+Pv0J/gL9ev1q/IT+Tv0SAHv/
qv6U/Qb+1vzqAtQB4QTKA/b+K/5X+076xv3J/Gv+Nf1q/Gf7Bv8r/oUEzQOuBoUF
QwUDBHgEmAPRBFwDwQLEAcz8uft9+G33vfx0+54DiALXAwMDPwM5AiQKQAlqDzQO
WQdGBp38+fsc/fL7OQI/AWUAqv8f/DX75v4J/qEEmwMjBWgE+f44/pD8vfsDAgYB
4AMzA6T+hP1q/D77cgNCApUGTwVl/0v+UfuH+gn//P2a/qf9d/mQ+Df5IfgcABn/
iAJbAS//KP7m/v/9sQC6/xX+Av159nb1F/RA88/63/nD/8r+yv7J/Qn+DP0yAIf/
VQBh/xj7CPrS+dL4sP3W/DL+GP01/Dv73P3M/PcDIwMwB0AGwQWLBFwFfwTYBwAH
/gj0B64FrgRxAVsANf8G/rr/vf6BAqEBPAVZBEkHiwY9CG8HwQXKBKQDxwIvAwMC
xwEAARMBGQCh/4T+nf2z/N3/wP4NBfcDogmrCK8JqAgABCMD9vzT+0T6Ffk++0f6
Qfpw+e/5z/im+8P6Uf1I/N/86fsF/EH7qvuj+mT7vPph+Yb4Tvl6+Cv9PvwGAxYC
5wOxAlT9cfwF+R74w/qj+Q/9VPwc/k79hP+k/soA3f/XAPb/8AAPACYBUgB4AZEA
JgIMAeMA9v/M/PX7vfvP+q3+zf0cAkwBbgGOAIr/qv7g/9n+L/47/U7+Pv2bAtoB
qAPQAlj9V/zM97b2v/nv+Pb9Cf2K/pr9ZQCh/7QB4AAG/ij9evrD+TT6G/lB+HP3
C/dE9pn4oPcI+mH5uv3A/HIDWwLUA9AC4P6q/en9tvyH/4f+Yfxk+wX6EfnA/dz8
nf9o/p39Xvyd/WT8LABL/3UCTwFoA3UCiwIvARIA0/5Y/0v+awCR/1gAdP/XAZEA
hQWSBK4D2gIJAAn/RgRCA3MJaQhMA3ICd/mA+O/7z/rdA+cC9wX3BGwEQgO7BJ4D
YgZ1BZ4EwQPAALT/fv5L/fD/3f4yAjkB9v4c/o380/tC/4H+iv9u/nf7oPqA+tz5
gPqK+ZzzvvLR7gPuB/Nm8gv7PvpO/5T+6f8J/6T9xvx9+/X6OPym+yj8Xvta+Gf3
7/cL9+L7Ivu/+b/4ZvMw8h3zafLo91D3pvjf94P31fbi9wv3MfY99R30J/OW9bj0
Tvqw+dD+DP72ARwBPwNSAgAG6gRACxQKrAt5CvADQgMS/1X++QASALcAjv8f/+z9
JgNMAkkGSQUjAywCQgRCA18IcgcHBT8EW/5h/SX83Pqz/sb9DQPdATMHOQa/CxEL
URBaD9IN1QzD///+fPK18djx2/DZ+uX5NQCq/1sAbv/dAzMDBAfxBXgBpwCt+6n6
Wvhn9z3yTPGS877yngK0ASQOVA0qDB0L5ATHAyv6Hvmc8cHwF/Xl86T9dPxVAlIB
SQN+AnIDugLQ/9b+S/13/LoBoQCkBI4DDwAy//n8+fv//ub9SP5R/Qj8Jfut/cD8
0P/A/pH+pP38/zL/jgJoARYEEwPUBvcFmASCA+n7yfok9yH2c/g996/33/ac9MXz
jfiA9z8AXv9oAT8A1v7g/X36sPmM9c/0GvUt9Oz7yfp+AmsBaAOFAuAB8ABrAHH/
6gIZAjAHVgZJAlsBQPTe8wbuVe2P9b/0Rf6d/fwAWAA2A18CKQMvAlH+l/1B+iv5
Bfw1+7f/4/51AKH/zQHXALUG1wWDCkAJywu4CkMGXwVq+lr5hvap9U77Z/qg+x77
//4V/p8HwQbkBiYGpwHqAHIDgQL6B+4GkgjLBxMFEASR/4T+V/pO+X33dvZb/C77
rgbHBWAJMAhMB0kGHAIvAez43PdE+z76PwFLAD76Mflt96n2SAE8AJUFxAQZA0UC
zf7p/Zz3rPaJ9X/0g/r1+SYBHABmBkYF9AYABvMDMwOXAUgAsPyj+3r9ffzKAM3/
ivoI+vL3Ifdn/Y38W/01/Ir8hPuxAr0BYgJMARL+D/1u/WT8MfsL+i76Mfk1/wb+
hQOOAvcF2gQUCvoIGgzVCqwJeQhPAV4AuvzJ+179V/zS+Mz39fc991MGIAXuDOIL
XAN1Al78ffs4/07+AwYgBXUDmwJ6+Zn40vns+L0BugAHBRMEGgj6Br4GtAVO/GH7
+u4w7jXnfubq6kXqYPVa9PL6UfoP/BL7eABY/9EErgP6AhACffzD+6L00vPR7PDr
Nesv6g74+PalCrsJ2RAbEFkIYwfD/dz8TfgL91T4SvcjAh8BxQrCCU8DiAI09Dfz
9ugy6CPrVeqhAZcAkRmEGLcZWxg2BjAF9PQK9L7w9+/M9tL1LP8o/s4F3QRACwoK
bQwaC/0EGQSt/cz8VP1n/ND+yf2/+f/41fZB9oEAx/9sCGkHiAK3AaT/qv52CYwI
nAvFCoH+l/1L+mT52f35/Dr1hvRc76HuOQNiAtsdrhzkH/4eUA0tDKP70/qV8vHx
EulL6OnoNeh+/+z+0xTTE2oPgA5oAkIBCglDCI0TbhKCCIgHGPdd9mD2k/Xw/wz/
LAJFAdoEBgSpDdIMdQa7BZn05fNa+qP5cRIoEWUXSBa7Bd0En/a89Yzxy/Bm86Xy
qv3D/HAKkgmDDZwMPwJSAXDzafJs8lbx+f0J/UkFeATBAhYClALHAe4J9AigD7YO
Hg9wDp8H2wYB9FPzgOHY4LTqE+qrBecEixaOFTYaPxlgDnMNJPac9T/rx+on96/2
ywfbBjcKMAll/47+Dvg09z77jfrG/h/+AAIyAesKDgrhCQQJLvkn+JzysvFB+mH5
8vzf+yH4Svej+YP4IwQmA00JiQiRAd0Amfbe9RHyZvF/8Zjw/fA28OX3AfdvBGUD
SQNCAtfuEO4l6IHnR/ej9jIAS/+eAeoAVQJ4AX79l/zo9vX1k/ej9mUDdQKHEbwQ
Gw4UDTr0ZvOp4OLfdOWQ5EP0Q/OYBuQFFhwQGzQhRiDlDe4MVvSP8+Dp2ugz7Xjs
Yflw+AcIBwfSD8kOPhM7EhEPKw7w/vn9vu/t7jf0hvNVACz/QgE/ADAIIAfVDZ8M
3Pvs+iDuHO0E9hH1pQfOBiMa9hjHGMQXmv6t/Z3m/OW54+LiSfBG76IIxQdGIHYf
UB85HssHywZs8l/xQ+5s7a/2ovUY/RX8YgCE/3YIbwddEH0PIhMxErMPlg4dBDwD
9fUH9SbvPO4e+S74CBFBENca5xm+CMgHjPa19Rv5OvhrA5QCywXRBDv/Tv4L9yH2
3eov6rbl+eQB9TD0Rw1TDNAW0BWxAtQBW+bA5VXndOaZ+KD3YPht95P3gPakA7QC
tAEPAcj0DvSN+sb5XwZsBaH/3f5T8qXxN/Qz8zj+bv3G/cz8+PMq83Xs0OsT7qjt
8+tF6/nnKOc39FbzJPZK9RHgUN9C0qTRwdkA2ejiK+IT7HXrBPVK9M3qT+r024Xb
wdgA2A3bjNoz7WLsXQqlCaoSuRFfB3wGQwtTCh8TQRJ1Ba4ERvN28k/tguwm72Xu
ovP+8jPxcvDE8AfwBfsh+msCgQFa+cz4N/eQ9r4HBwen/xz/4+Vk5eboHOgX9ob1
xAQTBPAaBhrvEDsQG/c39hL/SP5uFZEUpR+MHssfJx/CDzEPaOq36XvV9tR64sLh
GvET8HD3svYS/lT9DP5h/WYHeQYDHPAaVRomGVIFewT+8uTx6OAx4MnmG+acCp8J
ZClXKHUbjhpSAUsApvYE9sUHEAeQ9+j2oTLEMURVO1Tmj3iPFfya+zVFH0QAgACA
OdjH1/9//3+P2dHYvOL+4cg2zjXQK/kqq9lP2euB64F4ALf/dXUNdHmwxa8AgACA
T+qa6QhotWbQKtwpAIAAgFQTbhL/f/9/GLmzuACAAIC/+dz4/3//f1NO20wAgACA
k4k+if9//39lL6QuAIAAgBgQkw//f/9/CN9N3gCAAIAKTd5L/3//f7qjkaMAgACA
zxE4Ef9//39rucm4AIAAgNdgq18ge7h5AIAAgACAAID/f/9//3//f4vYENgLns+d
/3//f8h7gnoAgACAAIAAgP9//3//f/9/ppsXmymnkab/f/9/QE/3TQCAAIAAgACA
HxZRFaJP0k5v2rvZH0HmP/9//38F9yr2AIAAgPgmAiYWSNpGFsCuv7PO5s3/f/9/
/3//f0gAUv8AgACAAIAAgJqPP4/rHi0eFlzwWvBc0FuGJX0kHrTFs02CQ4LHu3S7
D89xzmTjtuK3AgYC7LZUtuK0d7RsTEZLq2F8YA3vOe7hq1yrsekc6UMJXAiC8wHz
VjZGNVtbNVp297z2AIAAgOOPdY/IY39i5X6ifXCyRLIAgACAgbnfuL3++f0lQdw/
/3//fxck/iIAgACAAIAAgFoofSf/f/9//3//f83THNMQlG+T0ItRiwCAAIABhMKD
mVCWT/9//3//f/9//3//f/9//392I58iAIAAgACAAIAAgACA/3//f/9//3+6z+PO
AIAAgACAAIAAgACAAIAAgOc03jMu+3f6AIAAgACAAIAAgACAkb/9vv9//3//f/9/
pqFxoQCAAIAAgACA5fbY9f9//38hUxtSAIAAgACAAIAAgACAAIAAgP9//3//f/9/
SOqe6QCAAIAAgACAAIAAgACAAID/f/9//3//f596dnnPzTTNvgkKCT0iISEAgACA
AIAAgP9//38DdQ10/3//f/9//3//f/9/CFbDVACAAIBc25/aAIAAgACAAID/f/9/
/3//f/9//3//f/9//3//fwCAAIAAgACAAIAAgACAAIA39KXz/3//f/9//3//f/9/
AIAAgACAAIAAgACArJlmmf9//3//f/9//3//f7C4JbgAgACAXYdRhwCAAIDWiKmI
W44vjgCAAIAAgACA3XGKcAyMeosAgACAAIAAgMccDRwwYwFi/3//f9NakVlt+oP5
AIAAgACAAID/f/9//3//fz1RWlBkuu+5AIAAgACAAICy98/2sFlrWHMgqB/s4j7i
AIAAgACAAIAAgACAAIAAgE32j/UAgACAAIAAgPO6d7oAgACALQhsB+1g7V8AgACA
AIAAgACAAIDEwjPC/3//fxBix2AAgACACgRSA74FCgXmjpGOE9rO2ceSiJIAgACA
YMj1x/9//3//f/9/Wd2s3ACAAIDvjMOMLoj7hwKjo6L/f/9//3//f6f92fz/f/9/
ZOXi5ACAAIAlWBVXEWXCY3vU6tNLFDgTyyDFH1qxHrEPt522iXozeVx6Nnkv1ZfU
RsSuw+X5LvlfTGZL/3//f2XWrtUAgACA/3//f/9//38AgACAJPd99gOTq5LDoY2h
/3//f/9//393bXFs9wQjBIOFVIWsJsYl9hM7EwCAAIAAgACAeuHr4EnZqNgAgACA
AIAAgA2XbJaWtA60rgbRBbdZdFjUHfQcXqIJogCAAIAAgACAAIAAgACAAIAAgACA
Gaqeqf9//3+IYllhAIAAgACAAIBPSUZI/3//fwCAAIAAgACAAIAAgP9//3+i2TbZ
AIAAgP9//3//f/9/euQC5AR8mHqnWjJZAIAAgACAAICjPI07/3//f/9//381c/Zx
AIAAgACAAIAAgACA/3//f/9//38nrsutubJgsq+YOpgAgACAUdCaz8iraauKjBWM
AIAAgACAAIBZHIgb/3//f+5+qX17RHtDCyQeI5TSzdEAgACAAIAAgGwfgh5+kCmQ
AIAAgO+flp//f/9//3//f/9//39HfQd83LY7tgCAAID5AEUAFTyyOgCAAIAAgACA
rwq7Cf58c3v/f/9//3//fwCAAIAAgACAKoHxgLO1IbXsQcxA/3//f/9//3//f/9/
7vY99l3GAcbTFy8X0Ld0twCAAIBEEY0Qh21ObFZPIU7/f/9//3//f92PaI8AgACA
AIAAgACAAIDLT6VO/3//f/9//3//f/9/edvU2gCAAIAAgACAOe5v7awP4g4oPyE+
/3//f/9//3//f/9/0grLCQCAAIAAgACAAIAAgDoLbAr/f/9//3//fwJUo1IAgACA
AIAAgACAAIAAgACA0gzYC/9//39hQI0/wxWqFG0mWiXBYLRfdmcnZrs0yzPmLfks
JRJaEZ/xHfHpPfI8DRwZGwCAAIBl6afo/3+DfxxEFUNmew16p1iNVwCAAIAAgACA
juvm6nG3D7deF3QW/3//fw7ieuEAgACAEJLBkQCAAIA5kwaTqB/bHkBlF2T/f9h/
1F6nXaLEX8QAgACA3/xL/P9//3/HQ8BCij1qPP9//395NlM1KJ+Znm3fyN5vBmIF
7b+Cv8kSzxH/f/9//3//f2fNycwAgACAKLXotBDabNmolUmVrdAl0C48Hju4CfcI
YpBikFKQ4I8ZGwkanyCYH13M78v7ODQ4/3//f+g64jl6WHdX/3//f/9//3//f/9/
t0eURvwUHxSOF3gW1uQC5ACAAIDS3jre1mqmaXfR+dAAgACA2YydjACAAIAAgACA
YPS/8wIpCyjUCCoIaawHrACAAIAj7ULs/3//fyQ6FDm3qTypjLEtsXzGDsZHPTQ8
/3//f/9//38pXu1cU7HYsITRvdBpOXw4/3//f/9//3//f/9/nGNcYpOxOrG2tXS1
3elh6dXJo8lLFmQVAU70TKDlH+W55CXk7BXpFACAAIAAgACAqfgu+GH58vhMkT+R
SRm3GM1GzUXIrzevAIAAgAnnmuYeJEAj0dg52CITSBKgEgUSX6gWqPTuRu4dBl8F
rqxfrEwGwQUOf8x9I105XGsruipYE8YSbO8W71/Z19jLrFasRY3cjDHemd2E+236
0dgN2KVfmF7/f/9/JNx82wCAAICl2EzYd40/jYLACsD/f/9//3//f5XWLNY3ODM3
QTpgOUwYnhf/f/9//3//f/9//3//f/9/v2boZX0+tj3/f/9//3//f+QyEzJTTU1M
/3//f1l1A3QV6ITnq8RcxF/UytPm0ZHRH/6B/TRREVD/f/9/lUqhSW7q2ul6+sb5
3h8qH3Ierh2dQ6BC1iwGLG78W/sTG08aDa3UrACAAIBP1YHUrbsluwCAAIAAgACA
CoLugQCAAIAJ6G7n/3//f/9//3/SDPsLAqK5oQDtb+wbPhE9x8FywQCAAIBanjGe
/3//f/9//38zYU9g/3//f/9//3+chNKEAIAAgHqIbYhkQqdBIF4ZXf9//389OGY3
xNR11DkB2gCGmVCZAIAAgACAAIAePBE7/3//f/9//3//f/9//3//f/y3prcAgACA
AIAAgACAAIBHyuvJ0Fa8Vf9//3//f/9/J2cnZgCAAIAAgACAAIAAgACAAICuHgce
/3//f/9//3//f/9/2LJmsgCAAIAAgACAAIAAgNm5H7leLTss/3//f/9//39vMYsw
oq/urniUHZQAgACAAIAAgP9//3//f/9//3//f/9//3//f/9/PXr0eHbEDcQAgACA
AIAAgCqynLGl2yDb/3//f/9//3//f/9/HuOZ4gCAAIAAgACAYYhOiAH2c/VRPVQ8
ljjIN7k9gzwYQPg+8JKrks6tY63eNPozAIAAgOHFdsX/f/9/ZBF9EOsNUA3/f/9/
CUXpQxL8kPtPXxNeKt153FA5djhWY/dhl4tIi9k/0z7/f/9/L0Y1RRcJRghBP0s+
A9gw1wm+p72UK7YqDC8cLiMzJjL/f/9/thPvEiud5ZyiHNcbDNJC0QCAAID/f/9/
/3//f2nC4cH/f/9//3//f52LcYubYphh/3//fz/B18BZXz9e/3//f9GtbK32pKSk
fDOlMiRo22YNB0YG+f01/QdQ0k6SCeQIed/C3nkjvyLsQglCXVN2UqsHAAeMsT2x
wCvmKkdQNE9227va1kDGP/p1p3SfyTTJ8vsu+/9//3+kLXQs4cAzwHdXOFb/f/9/
ahKaEZBUo1P/f/9/jQ+mDhAGPAX/f/9/Avob+XEqwyn/f/9/On/1fTQ8/jqMZFZj
xfJD8mLWtNVK+HP36IeTh0bZi9j/f/9/rA0RDbnlNeX/f/9/TkFkQDWKw4lTCY8I
d0GaQD64JbjWJtwl/3//fzssOysm65fqB/RD8wCAAIAAgACAK+KQ4fTwPfApHWkc
10S3Q+oGSQZp87vycgR4A/70bfSIF7oWJyUnJM7z+/JdD2AOqkOKQuMY4xfoDxEP
CFHxT0A4IDe29+L22REoEYUcxxs27brsqfX+9O8QFRCp+cn4KvGf8HIHtQYF5zjm
8ZnhmTDcnNusxSTFAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACA
AIAAgACAAIAAgACAUaHvoGZ8BHv/f/9//3//f/9//38GFiUVR+Kc4Y8cqBtKUydS
/3//f/9//3//f/9//3//f2ZjUGIkDU0M6wvuCiojHiKGOM43Z2wba8V6RnmkLXEs
odIv0lWk06MAgACAAIAAgGeKQYr2puamvMlHyaoBIgEI9332Xd/l3mfOvM0Yy3rK
ENuu2iLpgeh588XyOiSfI+1GLEZANzo21TmvOLMQ6A9k0QLRh7oSul6hbqEaxILD
mfMn86gKywmzPKA72Du2OmkLpQpP76HupLsyu7iVTJVswtrBwADt/yQkFCMqNGIz
6RQSFLrnDOdpqyCrAIAAgJ6mgaY64LzfmfTY89ocAxwIPRg8bDc6NqpBjUBRV+ZV
EkLyQI85rzi9PwI/7kzUS9h6u3n/f/9/iF9yXlcmkCX56HToFLPFsh6b0pp3iZCJ
UYYehoaYKpj6lMGUd6ICokfMs8vCyz7LR8joxxnWkdVF0K3PCOXG5N0X9haxL54u
4TIgMkkwVS+nGJ4XUfua+pnzJPNS6gzqwt8U30Tlo+QE8YLwYPLF8f/jeuMr5oTl
lvTo8/7gROAdwrjBu8BVwBPDpcJuuxy7KMvJyonh++CM39veDNSO07XFU8XUwZ7B
2dCU0JDgOuAV/k79fSa5JYY2tTU1QF4/wFrQWdlp8miSZZVkUlx1W/BZ+VgqaCpn
ZXJVcaRvNW7edqF1JnUjdKRcl1t4RJ1DaTZjNXgxnjB0Lbcs6yTlIxQiZiExJjol
FyGPIAYVWxRfBccEzehe6FTO783WzW3NAd1v3IbeAd5P1frUrdI70i7M78scubC4
UqXspHmYFJhuoeygXbIbsqDMJcwyAX4APDBCL2k2jzWmJ7MmmxqkGSwsMiuNVy5W
E2IwYUpQN08dTwFOxEfHRpIeqB1M7n/tZNHD0BK6jbkipcOkjbUktSbude0LEiER
PfWl9IG+HL56nxufr5eSl/qrdauJ4PLf6hkvGWo6ZjmISIhHzVqUWSxz8HH/f/9/
LXlJeHdrcGokf+J9/3//f/9//3//f/9//3//f/9//3//f/9//3//f/9//39GePR2
OkwaS+Qa8xlW73XuWcSyw2WoCaiQoY2hCpgamMCJcYmilEyU5MJ1whzphOhV58nm
XeDP3/X3ffc2HRocqTuDOnRVRFQ+ai5pe3EMcJ1uVG0AeKh2/3//f/9//3//f/9/
/3//fyB27XTFZJJjGUc5RsIjsiK6Ay8Dqukp6a7YM9jTz27P9MWGxUS32bYtrRCt
ArXctInJQck33N7bNeqa6Sj5hvg+D98ORClaKCE+Aj03UCRPJl8pXoJkWWNHVOtS
3FbDVf9//38PWsZY69t22/rZ4dnTumi6XopUij3I4sdM8NHvPoYhhgCAAIAAgACA
AIAAgACAAIAAgACAGIwMjGba5NllwWXBUtbk1Wf92fwS54HmtAXdBLcsvSuXRc1E
NnY8df9//3//f/9/wHGdcMBysXGRcJRvLWRGYx5WMVXLTetMXEdlRtI9rzyBL3Eu
ZRiqFy75Ufizz2TP+b2Bve7DX8PMtk62xbE6sZ+wNLDMtV21hsXhxHPI5cdI0uDR
i9b21ZG/P7+gtRi1sNBR0DLmquVU+fX4tBYMFmYHfwZZ8sHx9PAt8JbjDuPu8Sfx
WhGAEOgj6yITMQMwCCQbIzQMPQv6AlICRed35vTbqNsjB3kGXSCrH48ipSERPBE7
nEx/S8w6uTkkORE4p0GQQLFGwUVaVUFUiF5oXQZw3G4JdOpytU2rTDo4LTfkMfcw
5zAcMMNCukEbPy4+nyTYIzojViIpHZUc0Og76HrMLswPveC8eI8fj8iCnIIhhu6F
AIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgN+yfbJZ2OHX/NF+0STh3+Bt3vjd
wvgu+Jcr0yqBLlgtFUD4PsVQyE/OM/cyWCyBK/lA/z96O5w6qzTkM+U9zzyBKr0p
oCizJ9BByUAOPh49IzEcMAMxHzCnL+AuvyPxIgIo/yb8Kh8q2x0NHd0bEBvaGAMY
6CEhITo2STUJQuZAiVGiUNRF3US8JQUluRIoEm8ImAdNC5YKcA7FDeX1IfXk1hnW
5MNMw4mtRq3To4ej8bGmscfAb8DrysLKQ8bCxXbGF8b615XXV+DV30vq4Ol6/Bj8
kgauBfgNMQ1eFY0UbhZ7Ff8RJRFMGI4XgSrGKTo3WTYJQQVAmEySSxla+VgaYApf
5F3KXHhfoV7rYxpjxWXrZE9daFy5UAtQT0quScdE00PYNvo1FyAXH2MNwgzBBQAF
GQQ/A1wEtwNd+Zn4euHY4AfHtcZ5sEOwsasmq7aycLIqrcusUaM4o1KkL6QZqQOp
07uHu4Pe3t3M90f3K/5b/Tf1jPQ27aTscfoC+loOvA0PFUgUSg+GDjIAWP/u8Enw
7vSD9GsC5gER93P22fz/+8wPAg9fCOcHvA8uD8Qz4TK5OvU5qi4TLmk5zzgNN0Y2
jSvjKqEsHyz/JlEmdTHBMKEtrSwTGFsXQx2CHIIc1BvbIiEi9ToeOhVBXkAkO0E6
CDv+ObY93zzvPfU88jruORIsNSuLGcQYBRJhEd8SCBJZG1kaIxyCG98OWg7xB0MH
Tv/K/kT3r/ZiAND/RwtKClkHpQZiAMf/o/sF+6TsBuxr6wPrnu487ifemd10zw/P
VsUNxSfJAclK4b/g5+xi7Gnw5+/8+zX7avxq+1H5YPhsCLgHcRVnFBchViDPOfg4
mEd4Ro9Pdk4JXtdcQ2XrYwVo+GYqZQpk11ykW7FdaFy7XpFdok+lTpM6jDkrK0Uq
DBgpF63//P7Q5mvmH9XH1HfOEs4+ygXKz8yNzKfVNtVi1v3VRdXK1LXaUNrS4Xrh
p+oc6s/4cPgTBMQDYwrRCRoMogufByAHjww3DNwUXhT4D5kP2RI1EmkhnyD/JrAm
zCQbJBoiRyGfI88iwiXvJHsY5hehARkBWfMX83vqJuqQ5ubl9O1G7U/snuuV3CTc
ntU/1c/eYN4w81zyNA1KDHwivyG9LdMs2jH3MIw4xTf9SANIIF4TXTdm62TQWrBZ
mEzYS7tI6kfkSwpLxETjQ68ltiQmAqQBq/EU8cfpRelR48/imd9E3z/T2tKXt1u3
c5uJm1+UEJQ7o/Oiz7Kvsn23O7eXuFu4Brydu+HEosQa2LTXf/C179EFMwVeE8YS
1xhYGHMgqx+xLuMtiTq8ORg/jT6vPLY7LTNGMiUpMSjlJtwlgjDtLz05czjgLwAv
TB6lHacV1hRIFYEU5hY7FjwXtBYcFXEUcArOCf/9Uf1Y//n+/g52DjYasRnXF14X
KBPAEiIVihRPHYIc8yoYKug85TsmRWJEWjufOlgsjSvTKB4o2iwfLLAp/CjwG0Mb
EQpJCf73ifdo6ODnk+AX4Frght/73UrdJtbX1ULR0NAQ18HWgOTs43LvI++l9CT0
qfnC+Jr+6f2YAt0BKgtZCiwbjho4J4YmPimEKCktQiz7Ngc2RDxtO9I6DjqWPaw8
PERlQ3pBp0DqNN4zYStLKhIpQShUJoAlfB5fHWESdxHkBRMF6fxB/P/7Z/u6AAwA
ygLgAZH90/yJ9a/0cPPb8rz6KPpVBJ4DKgeuBqoAHABz+Mn3lvb49fL6bfrEAOP/
//1Y/bvxF/Gw50vnoego6PfyXPJh+bn4svAw8KbhQeGf2wTbFOB236fmJeYm68Dq
wOhS6F3gJ+DM313fE+5o7WsC2gFEDmoNGxAxDzsRphAMGZcYGyl0KJ866DmqQ81C
4j8VP7w4xTc0OXw4QUCKP55EfkNtPkc9izC6LwsmPiXrIe4gZh+iHmwgZh9aIl0h
mxmnGLIJ/ghO/5f+fgCn/+oEEARS/73+AfNp8m7rtOr56WXpHOyI6yntx+z56nHq
xue95ofnCec56tbpEO1+7Fbu5O2u8ffwqfRA9FP1v/SS8grygu/R7iPwB+8k84/y
AfUq9Jz2z/U0+Zb4ufrf+Vv82fvOB/oGYhm0GF0hnyAdHGgbgRe6Fj0fgh4sMYIw
jUDcP+ND/EL1PA48EzNPMgYsFStVLFgrujDNL0wxPzAfKVooXB55HbQZ5xjKFtMV
oA/VDmkIiAdSA1IC8vwo/Nj2UPYR9m31jfe89tX1SvWY8uvx0vPr8h72lvUn9Xz0
2PX+9GT8jfu+A90CAAVZBKQBKQE/AG7/HwEJAC8ChAFJBH4DwQYgBjkGtAWX//z+
Avx0+9ABMgFQCIUHQwZ/BTIBYgBiAaoASQeiBjoOqQ1FE70SZBOEEiENnwwaCWYI
LhBNDzYeWR0hJ10mzCfvJmclmSSKJrwloyrAKecvLC/ONgQ2yDbhNd0rOCsHITAg
2x0HHdcaABoLDicN/P16/SH0dvOO6RbpidsU2x/TmtJx0fbQh8z/yxbClcEpvbq8
4cF8wS3G9MUOx7/GNMvcymHSHNId2ZXYg+IF4t7vM+/J+Tf52f4y/pgGtAV0EpMR
Rh18HMgjDiOaKMAnIi1bLOYu3S23LuYtPDB+L8ExADH2LfYsXSNzItobSRs8HEwb
+h4NHgofJh7tFzwXkgvSCrECBgKIAuMBfwiPBw4OZw2DDPULbwPnAub8o/xo//P+
XAfLBmQRmhAlFmQVHhJOEU0JnwjLBhAGvw4bDq0V7BS9Ei4SeQnxCGH/t/5w+Ov3
R/Tr8yPyifG+79ruwOhL6HPh8uDe3jTeluJB4sDpQukw7rTt5O1o7V/t5+z08Fnw
zPpE+rsH6gYbEHMPXhSqE8cXABcWG3sa9yAqIOMp8ihiMI4veDKeMccxJjEmMFsv
Ly5rLXguvS0GMFUvTy6ELTQnWiaIHQ0dcRanFR4SbRFBEKAPlg7VDasH9wb8+z77
wfFT8aTr8+qB6P/n2edk52vm9uVq4Bfg19eb14vWINaS3D3cc+H44B7fId8d3Bfc
dt/73hLlw+Qp7Lrrz/RQ9Nb5JPn49oz2BPSM8yH4hvdCAcAASguPCvgQYRAVD3AO
JwuvCtULSgsFE2QS2hw/HC0hZiDOHUMd+Rc/F8MTDBNuFpEVIx2LHLUeKh4TGkwZ
NROdEvsNFA3lDToN+w43DmkKywl+AuMBoP3Q/GH67/nv+Gr48fVa9ZXvGu8D6Z3o
K+TA47biPuK840Hjs+JB4u7dkt2S2knaldtZ233h2ODW5XHlSOUo5eLhfeEu4Zzg
BuiN593tTO397oXu0e+i76XvFu9c8f3whvgI+J4BDAGlBwoHfwb6BaEDsQK7BA0E
3gtjCyIUhxMsFsoVwxMbExITmhJrFXcUnhgWGHId/RxNINEf2x5GHq4cxxtpHHsb
bx3UHIUfAR/RHvodyhgpGI0RBREFD3oOsBAVEAEMgwvzAzwDbgDT//X7h/sE8ozx
5uhF6D7mzOXp5H3kAd6v3avXSdfK10/Xu9iV2NfTP9NUzuzND9Gz0IzaGto04P7f
Kt/C3tnhTeEA7JjrNPaZ9Qv7ZPrD/Sv94wIvAhcINgeJDI8LkRSqE2MemB3CIN4f
bBu7GrEYCRiJH9sezyj1J1cnrCbnHTkdtxf5Fs0VIhUSFV4UsBT5E9YSFRIHDHAL
sQHmAH377Pqt/DL8tvvA+rz1F/Vv8bjwEO1F7A/pRejK517n/OV65SThkOBm3Srd
YNzC2+vdfN3V3kfeUNyr287aKtpZ3RrdHuJn4RjliuQ75cPkw+V35f/ouuie7Bzs
QPK48Tf5iviQ+Pj3DfOJ8mP1r/QD/zj+5AZWBqgK9An4ClkKJAyiC4APoA44E3oS
ABlVGOocIxyuGeoYQhSjE4QTAhNxFdYUqhUVFRIVsxQSE3cSrw0eDRcIaQeuBQ0F
5AVGBTYDygLG/A/8mffo9oP2+/VQ9Z/0afIg8hbuju3558Dng+Ix4t/fgN9N4Lzf
++Gj4d/ho+Fg3+veEdyi21Da7tlm3C3cJODb3yviyeGX5PjjreZ35nHo/Oeu62Xr
HfC471D0wvMV+3f6PwOUAiAHXAYAB0YG5wgUCHYOzw0yFqcVohzkG0Aezh30HI8c
9BtZG54cExwaHm8dJx/kHvQfbx8XHYIchBbsFeIQPhC8DhgO8gxaDIIJ7ghJBccE
lP///kr5s/hH9NLzrvFD8UzwCvDd7YXtvehL6IPiROKT4WrheuQ75KDjGONR4bzg
+N+v36LfR9+c4FTgsONq43Hp4+jk7Ijskew27ELtDe1W8vTxTvtL+yYEtwOCBg0G
CgahBW8JwgjPDkoOFRKEESUUkBNMGsQZQCCVH+sekh4WG1IaZRr9GSAcdRsmGoUZ
4BZFFmEUURMhEaYQZw3YDLIHBAeLAxwDsQJfAnH/9v40+vL52PYX9lb01fN28u7x
y/FZ8QTyVvGh7j/upOoy6jzrquoQ7Xjsp+tb65TpP+na6Evox+h76DXo0+cJ6qfp
A+577dfuXO7N61vrnulL6eDpi+km7d3ssvEB8Xb03vNw9Q71bfTx83zyI/Kv9FP0
ffsI+4EBAAGhA34DXAWoBE0JjAhjDAEMTQ2ADPIQ/w/WFjgWvhkQGX4a7RkzHWkc
wh+uHnYerh2rGsEZ8BdSF5oX4xbcFDgUqRDSD/4MXQxNCZIIRgWCBAkAh/9d+ZD4
kvIR8mzt5+wZ65vqeOq36cPncee54W3h/tx/3Fbev91N4evgs+Fq4YbhCOEY42Hi
1uZu5ojqAOqo7QPt3vJj8sz4OvhU+sb5l/vp+vABWwGJCvEJfRDiD9MRVBFeE9AS
ihXZFF4VuhQ4FbMUbhanFU4VkRSjEtYR2RAlEEoPYw5wCxcLkgauBRYFVQTkBUwF
DQQgA0L/uv56/SX9OP6U/Uv8tvtq+hL6Avpq+XD5v/iA99j2KvWZ9Gb1+/S292P3
C/em9u7xWfEj7b7s4OuB6wDteOwT7qTtu+6V7hrve+7B7XLtWe3a7CDwuO8H9Y/0
JPlz+A/9lPxFApsBLASoA1wDvgJ1AwkDVgbLBX8I8QdjB7sGQwaLBRcIXwc6Cq8J
PQuDCoYM1QsODawMUAusCg0JeQjYCUMJagyyC8wMUwx2DMULHg59DZYPDg92DOUL
FAmCCHkHxAaeBhoGuwb3Ba4E7QORAtoBxAAyACX6o/mv8zPzafTb8zH3n/Yk91f2
M/Pe8gDvm+677Vzt1+xl7E/r1+o87KrrT+6Y7Qruoe207Bbs5+x77F/tCe1l7ODr
lOwQ7KjwcvC29iH25vo7+of9//wyAY4AYgPXAvADQgP6B2wHoA65DewRKxFRE8YS
URWqFFgXqhbdGE8YUhjEFyIWmhUfFr0VqhYGFgYVWxSgET4RCA6JDSQKkgmYBiYG
IwWYBN0ClAKH/Tv9xvlR+Yr6C/pR+vz5JPfF9nn0GvSZ8zrzTfLO8UnuKe7X7Ivs
5PB/8Hb09PPR8T3x3e1Z7bvwJvBk+Pv3Pv7Z/XH+/P3s+oP6Ffm5+OL5SvkP/0j+
8QU8BcgGZgbjAWgBGP2g/Bv7cfqE/RL9AARVA8gHIAeFBPcDev13/Jr7RPukATUB
QAi7B2kJ8QgNBosFBgRvA+EFXwVJCNsHcwnbCK8LFwumDSQNRwt/Cs4HNgeoCBcI
rAr0CToKqAmSB+cG/QNJA/wAWwCR/+D+9v+B//D+fv6q+z77gPjv9zH2yPWW9CH0
afMw87LyIPL08XLxjPAX8K7tYu3E63Xrvu5Z7rLz+/Jz9MjzAfSZ86X0N/Tb9YP1
evkb+UIAh/+YBAoEbATKA28DsQJcBPcDIwdvBkMLogpHEKwPjRLDEc8Q7A9tDq8N
9Q5dDt8QKxCEEgISahG8EAEMZgszCIUHqAn+CPcJjAmuBRAFUgHdAKf/KP9k/gn+
0/yK/Hr8+fvM/CX8KPua+gv4lvev9Vf13vRp9Kb1N/WA9hf2Kvav9Uf1v/Rp9Pvz
bPP78lbzpfKv9Tr1vPcx96P3Mfdt+Av4evko+Wf4Bfhq+Oj3RfwY/LD/Mv+H/yj/
fv8f/x8BhwB+A/oCLQaVBXYIuAdWCMgHEQljCGANnwy/DwIPiQ62DQsMiQsECUYI
uAdAB0MKpQnPC2kLGgqyCVMHvgYdBagEQgOLAk8CjgGxBSkFZgfEBscBHAH8/EX8
Jf+n/mICDAKhAfAAMv/G/gn9h/yH+//6tvxL/C//xv5F/u/9RPv/+k756Pip+A74
AvmZ+L/5ZPmm+CT4bfXr9MvyhvJd88jyf/P78nD1OvUI+cn4evkL+ST3vPbJ91r3
SPvG+sb8evyH/Rz9ugBPAE8FygTRCBQI9AhpCGkHCgc3CcsIvA5RDsMSSBL/EYAR
eg/rDusOJA4YD6AOoxAxEP8SfRKsECEQaQvSCvEImAgwCK4HUweeBsgHLQc2BrsF
6gBiANn6evpN+Pj35fmm+dX4Ufgd8/vyefE98eL0ifT19sz2UPaW9Yzy7vEQ8fHw
Y/Ye9qD5d/ms9lP2hvbl9Zr7NfvG/pH+eP8y/zwB4wB4AAAAIv+n/s0CpAJyCC0I
uApDCmkK2wnkB38HiAQjBLsGIAYRDI8LBQ5wDa8KGgqrAz8D8P97//cDbwOyCk0K
1Qp2Ch0FfwQ8AtQBiAPnAuoDjgN/BscFbAkNCa4FQwW2/Ej8KPuz+kwC7QH3BnIG
TwS6Ayj///4S+636s/pa+p3/Xv+IBeEEywVPBen+aP5q9gj2vPQw9KD7avunAhkC
xAAyAKD6S/r1+Hf4XvoF+r37kPvc/S/9Mv7j/aD6CPrS+GT4gf0J/UkD2gL3A34D
WP/Z/vz7wPug/l7+rgQDBHwJ2whNDAEMcAzxC/EHUAeRA08DQAbOBS4N1Qx9ELYP
mQ0ODd4KDgrkCU0JQwmVCN4JQAmcCiEKRgioB3UEDQSbAyADdQMDA4gBKQGd/yL/
pP04/TH5qfgB83byfPIN8iH3+Pa2+VT5cPfy9nP0+PM98wHz3vOS8zr10vTi+Jz4
lPxh/Nn7nfv193337/eZ9+P+aP6SBCAEEwTRA54CEAIpBccESQjLB5wKLQqWDTcN
Jw3iDDcKtQkaCLsHdgr+CQUPag4YEHMPLQyfC28H9AZ/BtoFRgiyB+gKfwqpDDoM
JwqCCSkEugPXACIAwQFfAeEFdQWIBhMG9gCaAP/6w/rv+bD5YfwI/Bz+l/3v/WH9
Ff2n/Jr8Jfxx+wj7Tvrf+X36KPpB+536o/s1+9n7nfvG/Rz9VP32/Bv7qfqQ+xL7
yfwo/AX8hPsC/Mb7Yf3s/Nb9VP1b/fn8aP7m/WIB9gBlAR8Bw/5o/jj+8/0MAW4A
+gNMA4gGMwaoCBoIMwnICNEHTAf0Bk8GFwioBwQLhgq/DRsNqQ9HD+8PkA/yDWoN
FwulCp8I9wfbBmwGMwbaBdQGPAbxCF8I4Ql5CTAHogb2AnUCQgHTAEwB0wCEADUA
Iv+H/un9Z/13/dn8ufpe+k33+/bI9m32GPey9lr2C/YO97b2w/p9+of8G/z1+YD5
nPc398P6FfrT/3j/LACt/6r9KP1o/gz+tAImAtsGAwayCScJWQq1CUAHwQYjBKQD
7QWbBbILQAuQEO8PzA9tDxoKmQnqBZsF/QZ5BsIKzgnbCwsLvgcgB64BKQFoAOP/
xAMpA6gF/QSkAkwCrf0l/QX7sPpL/Kr7D/87/gMCdQGYAtQBd/se+4z1GvXV9mD2
d/nc+CT5hvj1+4f7l/0r/Wf8yfslALf/oQLgAWIBrQBlArQB6gBIAFj+3P2nAhYC
qAX0BOcEeATuBl8G6gViBTkBrQDnBG8EOQebBqsELARTCdgIUwrbCVgBmgCrBPoD
uAvICmMHuwZ/CtsJiQ6yDf0BPwEo/Wf8ngTKAzYCZQFfB3wG8hI4EtEJ7gj5/Wv9
fgHHANb8//uN/Az8uwo9CjAIjwed+zH7ZQL5AagF8ASw/Bv8HP2n/A/7sPoU9H/z
O/qz+Xv+2f0u+436HP+n/oD6G/o57sftYPLk8bb7W/vD+iv67/2t/Uj/8/6v9VD1
NPXI9Jf/S/8zBMQDGQSkA4sB/ABF/db8AwK6AawKYApUDswNihAuEHAOPg6rCEMI
IAnCCGoMQAwLDcwMihAhEPUQVxCiCxcLDgqiCbIKHQqlB18HeQfxBo8IAQgDBXUE
ngHwALEAAADd/07/tABrAGX/2f5k+vz52PZg9h30yPPY9UD1S/zf+6T/Cf+K+wX7
GvVt9AHzb/Ll90T3Z/3m/If8Jfw++QL5Mfn/+OL5sPlF/cD8Uwa+BTAIjwcs/3v+
V/ri+dP8O/wyAJH/WQeVBjEOTQ15DKULhQZ1Ba0A/P8J/ZD8AAFuADMJbAhzC68K
LQmVCKsFEAXXACwAO/97/k8AwP/HANr/Jf1b/Nz4NPgL+3f6PAahBRsQHg9tDVAM
1ANMA536Hvrl9IP0avqj+a4GywVQCXwIiwPgAqQAsP9O/rD93P0S/eoBUgGxAR8B
Pv6E/Rn+Pv3j/Tv9H/6d/RMBjgDK/lH+6Pcx9zf3gPb4+nH6d/3m/AACSAE/BJ4D
uv81/wz8oPu6/Gf8K/7Q/b3+Cf4fASIAtAEpAZ4BQgFvBcQE4QlJCXMK0QlsB5gG
8AP9AhMBQgB4AZoAFgUvBPEHPQf9B2wH3QQ8BM0B+QBMAVsA3f5I/g/7h/o4+4r6
hP0S/db8RfzW+tz5Qfhg93P0NPTO83bzAfdE9pb45ffl93P3Dvh69zH4nPf1+mr6
AAAv/2sA0/84/MD7tvgC+AL6O/n5/oH+dQX0BKgIvgeFBcoEJgHqAGgDtAKiBx0H
zggXCDAIhQeYBfcEjgEPAcEDIwN8CcUIAQpjCaUGOQbHADwA0/t0+8b+W/4DBWwE
1ARJBFIAwP9r/q39Xv/s/rEBIgGRAr0BBgFlAJT9DP0++sz5rfsu+8oBJgFpBssF
LQaoBY4D7QLW/3j/s/wY/JD8JfwpAG7/IwJoAcQBPwG3ABYAiv+6/vb/Mv/XAGsA
mgADAMEBPwEvAZEAlvr4+d71N/XJ+i76lAEZAV8BygD/+5D79feQ9y740vfZ+2H7
kQD5/64CXwLQAUUBnf01/ZP7BfvW/kv+OQS+A/oGlQb0BHgERQKhAWsDCQO+B2kH
Jwu1CuILFAsECYwI1ARGBJsE/QOVCNEHJApvCSoHkgb9A5UD6gB4ABkAdP9PA9cC
bAXnBEUC1wHp/Y39k/vv+kT7w/qw/RX9sP5V/or7Ffuv9zT3evfl9gX6O/l6/O/7
CPzM+9z5Svk++cz4cfsl+xz/0/4DApQBtwBFAAX9h/zv/Q/9FgBY/+MASwCuAwAD
KQaSBWUFmwSrBEIE8ASCBIgE8wMHBY4EmAX3BJsDLAObAwkDQgPHAkgA4/+eABkA
jgP9AgYCiAGg/mT+oP0r/RL7qfoh+qD5Yf75/X4B6gBb/8P+dPvf+oP49fdL+6n6
AAFPACwDfgJSAZEAe/8M/0X/Uf7jASYBTAZ4BeEFBwW9ATkBFf8+/n7+2f0cAX4A
ngX3BP0EdQQyAIH/7/w4/GH8nfv8/WH98wA4AD8Ah/8y/KP77Psx+0j+l/3p/xX/
O/9e/iv8wPsS+k75EvxB+9P/+f5uAKT/xAAJAGgA3f+O/rP9zf4r/nsCGQLdA2sD
AwM5AlUDjgKSBP0D1wRVBFwDxAJPAsEBBgJ1AVgDqwK0BRAFfAa4BRMDTAJU/ND7
mfc996D6NPpPAMf/vQH5ABj8o/v09G306/Ij8g75g/hI/63+O/2w/B73ifYH9Inz
yPZQ9or92fxlApsB9gFPAWv9yfzp+m36bv7Z/dQELAQ9CI8HPAbeBeAAWAAv/pH9
WAP2AqwMHgxND+sOiQggCBYBhADmAFsAZgbEBQ4LmQqGCQoJHQRvA7T/Vf/m/kv+
awEJAa4FLAXhBmYGHAGhALz6Ifp3+vz5Ff93/ogBHAHT/zX/tvsL+1T6/Pm9/j7+
UgTdA0MGEAaCAxADqv4C/hL+lP2IARwBlQMgA+cCgQIWAqQBugB1AKT/Tv+n/yL/
OADN/6EAmgAJAI7/qv0y/cD9Tv3m/4f/h/8D/xX+fv1Y/eP8mvwy/NP7gPvQ/U79
6gBVAP0CdQI2A8EC3f9u/3r8/PuU/Aj8kf8J/yAFlQQwCnYJxQgNCKED9gIZAoQB
2gRJBAoIZgdJCcsIZgfEBosE7QMpBXUEzgX9BJUFAAVPBuQFjgQKBE7+pP3c+yL7
lwAvADwEQgMcAlgBwP9Y/9z8W/x9+N/3Qfha92H8pvss/07+oP3W/K37yfqm++L6
DPyd+9/6HvpU+bn4OPu8+jX/pP6hASIBiAHmAFgAw/+RAMr/vQBLAIQApP9FAIH/
9gEJAcoDAwNfBAAEkgT3A6QEMwTXA2IDHAKeATIA1v9lAAYAXAOkAhkEfgPXAGsA
bv0Y/Wf8H/wo/dD8Ev+k/h8AtP9e/cn8Ufrc+ar7SPtb/br8p/0y/V7+Cf6K/Ev8
+/hn+Dv5rPiq/TL9vQD8/8oAHAC9/xL/Qv7D/RL+kf3//lX+ewHmAMcDzQI8AnEB
SwB7/ykBpAA/AngB4AE8AXEA8/8S/3f+SP/8/ub/bv9I/cn8D/yE++D/jv9YA8oC
+QCnAL38PvxO+p35Evu8+l7/5v4QA5gCIwOrAk8A5v8C/of9Cf1x/L3+Mv7gAj8C
BgR1Ax8BhADm/n7+S/8G/z8BrQCkA+cCDQRlA08A8P/j/Jr8fv4i/tQBYgHzASYB
2v8l/wn9yfx9+S759fg6+Bv8ivuz/Sj90/tR+5b5CPmT+O/3CPiT95b5K/ln+9P6
R/qp+fL3XfdK+A74qvwr/LQB+QDnAkwCOADT/63+Ev5h/wz/wQIJArUGMAb3CH8I
XwiyB2IFuwSxAwkDPAalBdgJJwnbCJUI1wYzBlwGuAV4BbcEugP2AkIEqANDBaEE
YgP6AlgB7QDXAF4A8wG3AW8D+gIJAlUBEv53/cn7S/vc+5D7yfte+wL8evsS/nf9
sP4Z/pr8s/up+hX6DPxb+0v+4/2w/yj/tAA/AKoAJQDt/zL/4P84/+oC7QGIBPcD
5wI/Al4A4P9S/3H+sP/A/t0BVQGRAykDqwJYAk8Aof8C/m79kf3c/Pb/SP/gAp4C
iAHXAPn8Qfw0+uX5ufsi++3/Qv8JApEBVQDz/0H97/wu/Nb7pP7m/YsCFgLOBKEE
8wNVA3gBOQE1ALf/WAHNAOcETAQqCLIHQwjRB1wEsQPt/6T/8wB+ANcFlQXnBoIG
IwKbAYH/bv/D/1v/Uf7N/Y396fyt/y//JQB7/5D7Evuj+Ff4OPrD+YT8Jfxh/s39
gf4C/kH9Bf13/O/76fum+/b8jfya/xX/RQK9AYUCFgI8AW4ApwA/AK4CYgKRAwAD
hQJFAiMEXAPHBQcFvgRMBIUEEATtBU8FqwU5BcQDMwPNAUwB4AA1ALcA8//d/0v/
Pv7A/XH8/Pv8+z77Nfu8+lr6GPoS+qb54vmN+Qv6oPmN+hX6evoY+hX60vk4+uz5
5vt3+4f9HP0P/cn8MvzQ+9n9bv0ZALD/PAGXAAwCaAG0AjIC4AJPAsoCRQKLAv0B
cgMNA3wF3QTRBDkEcgK0AS8BgQAJAkwBFgN+AkUDiALXAjYCewHQAPz+Yf50/uP9
1wAsAFICtAHa/1L/mvwF/Dv80PuQ/Pn7nfwS/Ob+dP4fAaQAzf9x/zj+nf0c/6f+
VQEGAU8D7QIDAoEBa/4J/lj/jv76AlUCcgTBA5EDzQIWAlIBiv8M/9b9HP2H/un9
KP+O/jj+S/3f/If8d/u5+ij6cPkC+236avv1+p36z/kY+Zn4CPg994P3G/dO+tn5
sP0v/cP9Jf0r/F77Ev2H/JT/9v4lAHv/ngAAAKECEwLUAk8CkQEMAXICzQEdBaEE
Mwd/BlkH5AaCB+4GOQeSBu4GfAYgB4IG2whACKIJFwmuBi0GpwIyAksA2v+h/yj/
EgCE//AASwCHACUA3f6w/sn8Z/wV+4r6l/sb+2v9vfzc/W79yfxh/Ev9s/zA/UH9
Jf7g/Tv/1v6B//b+8P5+/lH+0P3D/hX+twASACkDvgIsA44C0wCHAD8AwP/tAKcA
JgGaAEICqgGbAxAD4wFFAe/9SP3y/Gr8nf47/vz/W/8iAJf///6d/jL+uv0F/aD8
Nfy5+4H9Ff0c/sD9vfw7/Hf8/Psv/rb9kf9F/4sAPwB7APD/9v94/8cAHwBJApEB
kQMDAwAFtwTkBWkFfwQQBMECawIZAoQBmwPXAhYFlQQsBMQDLAOBAjYDtAI2AqEB
Yf/p/un+wP7Q/6T/lP4P/nf94/zJ/VH9KP7m/cP8ffxU+/L6+fuj+5D8IvxO/Aj8
1vyd/IT99vyE/fn8HP7N/XsA2v9+Ae0ASAAGAPb/fv+nASYBewMzA6gDAAPHAUwB
of8s/1v/4P4cAZQAxwMsA4sE0QN7AqQB5v5F/h/9XvyR/tz9oQDQ/7QA/P9S/7P+
oPzi+z76yfko+4f6SP6g/Z3+Ev5n+xL7nPjr96n4Qfjm+4D7Xv+K/nT/4/4M/X38
Avua+oD7yfpR/tb9ugEyATMDkQL5/z//PvxR+6f9/PwDAz8CkgXUBNQDIAPXADIA
WP7J/dD+KP4JAngBggTtA6sCPAJV//n+5vx3/Jr9Mv1uAK3/MgGeACX/h/7W/DX8
4vt3+2v9yfzm/0L/RQG0AOb/fv9e/Mz7avrW+Rv8nftu/7f+OQF7AGUAe//W/iX+
Pv3D/MD8DPzp/UH9Zf/z/uP/dP8s/93+O/6K/QL+VP2z/vP9Cf9+/of///7w/yL/
SP6H/cb8Mvyt/RL9Ev9+/lj+tv3m/JD88vuA+xX6dPlE+tn5//2z/dcAhAAf/4T+
mvsx+9b7W/vj/ij+VQCh/7EAGQCBAfkAxwEiAbcAAADwAGsA2gIDArQD7QKuAvYB
0wApAJoAAwC6AhkCcgTEA4IDqwLnAgwCHAORAsEB8wAvAFj/5gB1AOYBSAGhAOb/
+f8o/3UAvf/z/x//D/9O/rD+zf0+/of9OP50/dz8cfyg/CL8fv3f/HH9D/0C/Ff7
bft0+hv8h/ua/Ob7qvwr/K39Jf3g/zX/QgGhADwAl//5/kj+5v4y/vP+a/5VAND/
hQLzAVUC5gEPAI7/lP8J/3gA0P/dAO3/vQAvAL3/6f4V/of90P4i/tcAMgA1AdMA
HAFxAE8A0/8+/tn90/wF/Bn/Qv7QAQYBKQGtAH7/Bv9I/3T+xv0M/Xf82fvD/hz+
8wFFAUgBmgA4/63+L/+B/vn/O/+nAN3/JgG3APMBYgGqAeAA8ABPAEwBZQC0AvYB
cgPnAqEB6gBO/5H+9v50/pQAAABfAaEAYgG9AH4BtADW/xz/rf0r/Zf9K/0f/qr9
Ev53/VH9s/zG/E78qvzy+3T9yfwV/5r+FgB4/17/qv7j/mT+fv7G/eb+Nf5VAZEA
8wNlAxwDkQL8/2j/x/9S/4QB4wDqAGsAAAGUAK4CEwIyAacAMv7D/S//wP5lAYsA
GQF1AC//t/7y/If8//uX+wL8evuN/eb8sP4G/mv95vzy+lT6JPnP+FT6AvrD/Dv8
Z/0M/Xf8/Psy/Kb7uftB+5f7KPvA/R/98P+U/0j/vf4V/X38KP7T/c0BZQF1AwAD
wQI2Al8C8wEJA1sC6gMsA7QEAASIBaEESQSOA2UBpADZ/iv+8P5b/vYAaAD5ADgA
jv7N/WH9p/wS/of9Xv22/Nb7GPtb/Nz7l/3M/FT8wPuz+z77iv01/Vj/uv5V/rb9
7Px6/Mn8KPy6/Uj96f5o/tP/Nf8MAFj/cQDm/4gBBgHmAT8BjgDW/3v/w/5L/+z+
0P5R/pH/vf7QAH4AKQBu/3H91vz8+2r73Pso+z795vz//oH+Rf6g/S77z/p6+tL5
Ufy5+3T+7/1r/un9jfzy+wX7S/oi/HH7LP/D/jIBiwDmAVIBOQGLABn/Xv4M/6D+
4AJPAssFIAUTBI4DhwAlAND/Iv8WAboAEANSArQCGQKkAeoAGf+K/mr8JfwC/VT8
Jf+X/pQACQC3/kv+OPu5+v/5gPl3/Mz7Pv6U/SX9sPw4+8b66fqK+pD7Ivun/S/9
QgCw/24A1v+R/Sv9oPs1+2H95vz8AHsA5wJCAvkBYgEDALT/pP8y//MAYgDgAk8C
6gMWAxYCtAHW/3T/0/90/+MBawFJA5QC7QFSAfP+mv4S/br8w/xu/ND9h/1h//z+
Jf/W/or9+fxb/fn8ZP4J/qD+O/4r/tP94/5b/or/HP/g/zj/p/8f/1X/3f4G/3T+
KP+g/sP+Mv4c/3H+9v9o/1IAwP93/hz+yfwM/A/+O/0PAGX/tP9F/8P9cf10/Q/9
Uf72/Q//s/4i/9n+mv4J/of9Tv3W/J38Ff5+/b3/Rf97APP/FgCt/2j/A/8J/5f+
Nf/w/pcAMgAMAX4A8P97//b+W/5e/83+dQAcAE8BAAGxALEAaP8P/6r+ZP4J/9P+
NQCk/wkBsQBiAbcAHACn/1v/Ev/g/zL/4ABVALEASwBx/wz/rf5V/g//dP5O/7D+
KP8P/w//t/6g/jv+H/6K/QL9gfzs/GT8DP5h/SX+qv1I/b38zf1B/VX+8/16/Rj9
mvte+3H7Avvy/Kf8kf5C/or+bv5r/ub93P01/WT96fyX/UX9w/4+/pf/yv63/zL/
EgCU/27/L/90/93+9v+q/7EAUgBiAPb/Xv/j/gkAXv9iAQMBTwLwATIC0AGuATwB
yv8//3v+K/7m/oT+ngASAMAAaABiAO3/bv/2/sb9ZP3c/Dj8CPyN+1v89fte/dn8
vf4+/or+Bv4r/Q/9bvz8+7P8OPwf/sP9uv5o/gn+zf0f/af8Xv0V/fP+d/4sAcoA
oQFlATUApP8J/n79Bv5e/YsAHwA5AvkB+QFIAdD+Nf4f/Mb7s/w1/Dj/vf51AC8A
4P5b/qD7KPs7+tz53PyN/F4ASACkAEsA5v3D/WH79fpX+hX6HP16/DUBjgCLAscB
of8y/y78xvtx+8z6yf1R/UIBpwA8AfYANf+O/kX+2f2X/07/EAKeAe0DbwMcA7QC
kf/p/nr8VPwl/tz9jgEMAVsBMgEG/4T+Mv3//I38Ffxe/MP7cf04/cD+Iv5F/cn8
CPt9+vz6gPpI/fL8Iv/Z/nT+HP4f/dD8Iv2X/PP9oP2h/wb/aAD5/xkBhAChATUB
RQHjABkBlwAWAZoAHwG0AJEBMgH6AsQCTAPdAtABTAFiAPn/8/9o/9D/a/+U/1L/
//53/rD9Ff3m/Dj8UfzT+zj82fvG/Bj8qvzv+4D62fkL+H33WvnV+D79yfxY/rb9
TvzA+1H7ffpk+6P6oPsb+8D9OP3zAFIAlwAyAD79vfz/+337dP4v/iYB1wC6ARwB
vQAfACwAuv9VAM3/wABSAF8BzQAfAZcAa/8f/+b8ZPzW+5f7uv1U/Wv/0P7z/hz+
OP2d/GH82fvp/Az84/2g/VX/dP41/27+cf62/T7+Yf1+/53+LwCH/3gA0/8mAYcA
WwHXAAABUgBiAccAfgEfAbEBLwFrAQwBLAHtAG4B4wD5AW4BSAHQAAP/hP5b/tb9
LP+a/uD+WP7m/VT9a/0S/br8Z/xO+w/73PpO+rD7VPv8+5f77/qK+k77w/pF/Jf7
7/uK+2r71voF+2f6HvuQ+qr8Qfz5/r3+l////i//mv57/9n+0/9e/yIAsP8DAcQA
ZQHgADwAjv/N/27/rQAlAFUBxwDwAEgArf8//1j+Bv6a/Xr9wP5F/vb/fv8DAJ3/
Uf7N/d/7nfuw+1v73P2E/aT/LP+K/gb+oPwY/HT80/tU/b38lP4V/nsA4P8mAbEA
e//w/nr9GP2E/gL+ugBCAHsB/ADmAEUAhP8S/9n+Av5r/6f+RQGkAEwBlAB7//n+
w/4l/iL/WP4yAN3/ngEiAR8BqgBI/tD9evvi+s/6WvrM+4T72fw7/ND9cf3z/Y39
XvwI/E776fpu/O/7xv0+/ez9iv3A/tz90P5x/jL+sP3g/hz+AACK/+P/of8s/47+
2f47/vb+p/6t/1j/bgDm/5QA4P9o/xL/jf1b/WT89fvf/EH8dP8G/x8A4P8+/dz8
w/pU+lf7Bfua/T79Cf+g/uz+hP5x/Qz9UfsF+4D7Ivvj/Zf9jgAPADUB6gDN/07/
cf0c/RL90Pzt/9r/PwIsAnEBJgEv/8D+vf5e/ub/Uv9iAeYASQIMAiYBygCX/g/+
tv1r/Yr/LP+9ATIBOQKnAbD/L/+H+yj7R/rp+cz8dPxl/+n+kf/s/mH+Av4V/dD8
ZPvM+qP7Ffuw/gn+WwDj/0v+H/5B+8P6w/pO+u/93P3mAGUASwDN/+z8qvzc+p36
W/vc+lH9HP3Q/2j/qgAWAGv+2f2a+iv6VPr/+Xr9K/20/1L/D/+g/sD8SPzs+lT6
Avug+p39d/3s/rr+2f16/fL8h/wo/en86f53/uYAiwB1AvMBmwFFAaT/Zf/s/j7+
Bv+R/hkAvf+IAVsBZQLEAbcAOAAM/6D+LACH/2IBrQCRAOP/Vf/G/v/9mv1+/f/8
zf1B/bD+Mv4l/7r+rf0o/fn7VPt9+yj7G/yT+6P8D/w4/fb8D/7D/fn9s/1L/br8
KPyw+1T8+fu9/Vj9SP/Q/rD/Ff+a/ij+WP0r/Vv9mvyX/k7+AwDD/7T/Rf9r/QL9
AvuK+tP6evpY/f/8MgCX/5T/1v7m+4T7xvhz+H35Ifmq/GH8WP/z/jX/s/7m/BL8
0/pn+jX83/sl//n+WwDT/3H/4/4+/e/8mvwi/Ej+wP1YAQABMwOkAl8B/AAC/o39
SP3G/H4A9v+xA1gDqAMQAxYAp//M/Fv8k/tE+7r9O/01AK3/XgC9/wL+fv34+lT6
oPo0+jj9/Pwl/63+W/75/Zf8Ivz4+rP6jfso+5r9Qf2B/yL/nf8y/1j9H/3f+537
nf1I/RwBWADUAYQBcQAiAGj/D/9l/0L/6f+a/4sAVQDHAEIAKQCa/6D+Vf4l/sb9
OP7p/VH+lP01/ZT83Pt3+8D7RPt9/Az8lP0S/cn9Uf0P/cD8G/z8+w/86fu2/Wf9
kf5L/qD9WP0r/Oz73Pt9+6397PyU//z+GQCw/7r/LP+E/+D+Rf/G/kL/w/6h/yj/
hP9L/93+mv5o/u/9w/5r/nUA/P+HACIAs/5o/ij+l/17/lX+1v57/uD+gf6U/0j/
kf9o/8P9rf07/bP8ZP72/Wv/H//W/lX+HP6n/cb+W/4JAEj/LACE/7r/SP+U/yL/
PADW/xkBeADXACkAPwDQ/wAAp/8y/+n+0P6H/tD/DP8ZAKr/Qv+B/un9SP3J/Sv9
qv75/XT//P54//z+oP1U/Qj8nfsi/K37s/1F/VH+0/38/Lb8vPpt+jv6nflq/Aj8
h/5R/qf+Rf5k/Rj9BfyA+177D/t0/Cj8OP8D//n/rf+N/QL9jfsi+8P8gfzZ/rP+
t/9l/wAAgf+9/2j/yv5h/vD+jv7aAF4AAALHASYC9gHdAGIAW//g/sD/Tv/BAXUB
UgIDAvkAsQCO/y//wP6R/nT+Iv6t/kX+sP9I/1IAzf9u/5T+Qv4P/h/+//3//ar9
w/1r/UL+6f1Y/g/+h/0v/en8w/xh/Tj9jv4r/qH/Qv/z/6f/uv9l//P+mv6O/l7+
bv/p/jUADAAZACUAK/7//Y38Z/y6/ZT9pP9h/17/Ev8c/tb9K/wF/KD6VPpk+wj7
4P2n/Rz/4/41/Rz9Z/qH+pn5evn/+u/6Xv1B/VX+L/4Y/db80/t0+wX8+fuB/U79
Vf8v/+MAkQBiAAAA0/29/Yf9rf1VAAMALALEAVsBBgHa/63//P66/qD+e/6K/17/
LwGxAFgB+QDT/5H/7P63/pr/O/8J/wz/Qv4c/vL8rfzM+4T7+fud+739Tv23/jX+
sP16/SL8ufsb+9/63P1u/QkBvQAAAH7/KP3G/KT9Iv0AAHj/ngAiAGsAMgDEAGgA
DP97/qT9cf2d/xX/wQFFAXUBIgHG/jX+cfz/+1T9DP08AMD/iAEyAUX/s/5E+xj7
d/ku+Xr6JfoC/af8P/+n/uD9cf1q+jT6Lvkb+aD7VPuU/jL+e/8l/07+//3i+5P7
h/oL+qP8YfzAAE8APAEGAY7+O/7D/GH8Ff7D/fAAmgBJA9QCrgJPAvz+d/41/ND7
s/xX/E7/2f5CAb0AxABCAOP9Yf2E+yj7GPzZ+0X/yv4WAJ3/l/5b/uP8VPyQ/BX8
OP4J/h8AGQDzAMQAfv8c/2T+Ev5h/xX/sQBiABMCoQGbAi8CbgH5AOP/mv9C/x//
SP8D/14Avf/HAWIBtAFfAe3/dP/A/mH+sP4P/vz9iv1F/q391v8f/93/L//v/XH9
JfzQ+6D8//v5/Ir8ev3m/Gv++f2E/Rj9PvvZ+rb6V/rT/H38mv4f/s3+WP62/UX9
wPxq/HT9GP0l/6r+aADz/3T/+f6k/TX9ZPwY/Cj9mvwP/53+/ACUAOD/of/2/Kr8
S/z/+2f9S/0G/2H+h/8Z/1X+w/04/LP70/pq+rD8ivz5/27/5gCkAFX/yv75/IH8
8vyK/Kr/Gf9FAtQBPwLQAY4ALwAc/73+0/41/iwAgf+uAW4BngHQAN3+pP6d/UX9
Bv5k/Xf+Bv5I/8D+Nf+6/hL+s/1L/ZD8Xv3f/Gj+9v0l/pT9wPwu/DL80/th/fn8
WP4C/vb9l/1O/Rz9//yq/H79H/2t/ij+7f8//+AAPwAJALD/0/04/QX9s/y6/mj+
BgDa//b+WP5L/bb8a/3v/DX+yf0v/8r+vf8v/5r/0/4P/of9hPzv+0H9DP3w/rf+
Tv+k/pf8cfyt+kv6h/si+5f9Nf2O/kj+Tv7T/aD9mv38/Lb8Uf0c/af/bv+qAXEB
4ABCAGv+5v16/TX9Qv/p/scBMgF+AsQBawAsACL+sP0f/vP98P+X/ykBBgGnAXUB
eADg//n9h/1Y/fL8Nf4Z/gz/wP7G/nT+Rf7m/TL9p/xF/Nz7vf32/LD/Rf9PAM3/
hP4S/s39Pv3z/tn+HAC6/xkAof+w/0X/6f9u/zj/0P4c/pT9pP4l/iIAuv9FAA8A
l/8y//D/Xv8ZAHj/gf8M/5r/Gf9V//b+ZP4o/lH9//z8/Hf8ZP32/MD9sP2n/Uj9
mvxI/L37Lvtq+w/7nftB+0j8tvtO/bb87/2g/db9+fw1/cb8O/32/FH+tv23/kX+
4P5V/g//cf7z/oH+8/5V/tP/Vf9PAfMAPwHmABkAp//H/17/jgAWAAkBngBlAc0A
AAJ7AYEBAwGt/zL/e/4P/kj/s/6EAG4Avf9e/63+K/47/uz9kf4S/vz+gf5l///+
kf9L/3T+Cf5B/Z385vxL/Nn9lP2B/1L/AwCt/8D/Xv/s/m7+xv5Y/mj/Ff9xADUA
9gDdAAABxwCxAG4Arf+t/83/cf9IAOn/cQAZAA//4/6U/U79h/xO/IT88vvZ/EX8
W/3f/HH95vzy+5r7ZPvp+lv7Avvi+437V/zf+5f8FfwS/Zf8Rf3J/Pb8ZPzc/J38
KP66/eb+aP4v/+D+CQB7/x8Ap//p/4f/DADH/4gB8wC6ASkB2gBPANb/cf+3AFsA
qgEvASkB3QADAKr/pP9b/83/Uv9b/7r+4P5k/s3/Yf8cAKH/gf4Z/hz98vwZ/q39
vf5O/h/+sP3z/aD9e/4C/lX+yf0i/o39Ev9o/o4AEgBoAPD/nf9L/2j/5v4WAMr/
LwGhAPABNQHBASYBygBeAOz+sP5h/tn90P9r/wABeAB+AOP/Cf6q/cn8//vZ/JD8
vf1b/Xf91vzf/Ev8bvwb/Jr78vqN+wX7s/wu/CX9qvzs/Fv81vxX/L38EvzJ/DX8
sP3s/BX+W/3v/R/9uv4P/s3/Iv+9/2X/4/9+/+D/hP+K/iX+DP6d/cr/Rf/zAHgA
DwCk/9D/9v4vAJr/+f6n/rb9h/2E/gn+Tv/5/rP+Ev7Z/UX9Tv72/cP+S/5V/un9
Pv6N/Vv+5v2B/g/+Uv9x/pr/H/8lANr/ZQDH/27/3f7A/jj+Rf/g/s3/O/9L/6r+
jv8M/wMBtABbAd0ArQBVAB8Aiv+6/1j/gf7A/YT9GP2q/lj+DwCh/17/Ev+w/Sv9
evzp++n7Yftn/DX8Rf0P/fb91v13/i/+6f2z/Qj8qvs1+yX7l/0+/Vv+Cf6U/WT9
5v16/d3+Rf4P/rP9Bv6k/UX/3f4V/xz/Ff7Q/fn9qv1u/wn/nf9+/5r+lP7s/UH9
6fyz/Dj93PxI/tn9vf81/wkAtP9u///+ZP4G/kj+4P1+/zj/hwAAADwAmv+H/xX/
qv8Z/4f/Bv/N/0X/8wBoACIBugCt/1X/Uv84/+ABpAEZA80CDwHaAL3+ZP4C/mf9
dP4+/hIAuv91AfwACQGRAP/+fv5F/CX88vuN+3v+Jf6HABIAkf9O/3v+Bv41/uz9
8/5u/k7/wP7A/1v/L//G/rb9l/1k/eb8e/5I/mgAKQC3ACwApP6K/sn8h/z8/Hf8
P//2/qoBgQHQAIQAuv1h/WH8w/vf+6P7Iv3A/N3+Uf72/37/Vf7s/d/7Tvvy+3f7
0/29/Vv/+f7w/oH+SP7s/XT9Yf3s/TL9P//A/q0A0P/N/1L/cf4G/vn9ZP2t/yz/
RQKqAZ4CVQKhAHUA0/6K/iL+5v2U/pT+6gCOAJgCJgIPAYcADP7J/dP8jfzj/WH9
rf5k/lX+yf2B/B/8gPtL+538SPwi/73+x/+O/yX+5v1b/Cv8SPz/+2H9L/0ZAEL/
ewE8AV4AIgDv/Y39O/wf/JH9Iv20/0j/8wCeAG4A6f8D/7r+h/47/kj/8/6k/zL/
kf53/rP9Xv3f/Hf8Bf2w/MD9nf0c/tP9W/32/Bv8l/tL+yX7dPtB+5r8Nfw+/ez8
9vyq/HT8Avy9/FH8Tv1F/TL+5v2z/qT+4P6R/or+Qv5R/jX+4/6B/qr/OP+3AHEA
mgBiAI4ASAD8AIEADwG0ABYA4/9o//D+h/8v/5H/HP+R/gb+6f1u/ZH+Vf7//nT+
qv1r/eb8d/wv/dz8/P3Q/dD+e/6X/0X/DwB4/27/Iv/p/pr+DP+X/ub/wP9xAeoA
kQH8AJQAZQD5/4r/LwDW/9cASABuAAwALwDK/9r/Vf8s/83+pP9F/1gA/P8WAHH/
4/2a/dD8ZPxr/dn81v1e/Yr+Gf6q/kX+lP0J/VH76fqt+n36qvx6/Dj+D/63/mH+
Mv0c/SL8Avwi/fb8l/5k/n7/Iv/Z/qf+p/2t/VT94/w1/tz91wCUAG4CHALjAKcA
Yf4P/q39VP0l/5r+iwBPAMcASwD2/qf+wPyQ/Cv80/vv/N/8h/4G/pf/aP+k/qD+
a/1U/cb9d/1h/0j/twCLAGgAGQA7//n+bv78/eb+Tv5FALr/+QFVAXUB8ADA/0X/
Gf9h/t3/Tv+3AC8A5gB4AC8Ajv90/hX+uvxe/Ej9Av2a/zL/0ABoAAMAnf8S/rD9
zPx9/On8oPzc/Xf9mv5Y/i//yv5u/wz/Xv4c/iX9zPxh/Qz9lP5L/uD+kf7G/Y39
iv0P/dD9Xv1u/k7+aP+6/m7/Gf97//D+Pv7g/Rz93Py9/Wf9yv9S/0sAw/9O//n+
hP7g/Qz9ivzp+4T7uvw4/Dj+8/0v/3v+oP2E/Zf8Tvxb/Q/9Xv44/lL/5v7K/7f/
0/+H//D+p/69/m7+RQDw/6cBSAHEANcAbv8y/yj/sP57/y//OADQ/0gAHABF/+b+
mv16/VT93PxY/vn95v+K/zwB5gAiAOb/K/3v/AX8qvth/Sv9jv87/z8AEgC9/3v/
Bv/A/uz9vf3z/Zf9Jf/Z/rcAewB7ADIAvf5R/hX+p/2a/kv+nf90/yUA8P/m/0v/
oP5L/qD9h/3s/aT9iv9u/70AcQCO/zL/KP0C/Vf89fvZ/I381v07/SX+7P10/kL+
6f2g/YT83/s1/Mz7p/13/f/+nf5b/vb9ZP3v/On8kPzs/YH92f5r/pH//P6H/0L/
pP84//z+bv4M/7D+SAAGAOAApwBYAOD/KP8G/8r+h/7G/tP+OP8M//z/4P+w/5T/
Qv4f/jL9Ff3//cD9Bv/z/o7/Zf+d/zj/7P6g/hX+7/2O/iv+of9b/5QATwBxACIA
of9I/5H+Pv53/hz+rf8o/0IAAwCH/3T/xv6H/oH+bv44/+z+1v+H/xwA0P9r/wz/
0P2g/Yr9rf2n/hL+4P6g/kL+wP0S/cb8KP2z/M39hP2U/hz+gf4M/mT9Rf3j/Hr8
ivwy/C/9qvw4/uD9/P2z/b38ffxe/PL7/P2N/YH/Iv9u//z+Tv7j/Xr97PxU/dP8
a/7W/UUAkf8iAL3/kf44/jX+wP13/h/+/P7W/jj//P4v/63+iv47/gz+7P3K/nf+
W//w/un/Vf/2/7f/t/5Y/oH9VP1R/un9CQCR/0sA3f9C/+b+8P53/tD+WP7Z/mT+
of8V/73/Yf///nH+bv7s/Tv+yf2t/jL+t/8//2X/H/+g/kL+Iv6n/X7+8/07/4T+
e//j/r3/fv+q/1X/qv5R/iX+yf1F/sn9Gf7p/R/+yf1o/gL+OP7p/br9KP3Z/W79
kf41/lL/Iv+X//b+zf4+/of9OP2k/Vv9Ff7//af+Uf7W/pf+Av7G/Z38W/wP/ND7
SP0l/TL/Gf9V/xn/6f3N/TL95vwC/e/8w/2q/XT/DP81AMP/Bv/G/qf9OP2t/Wv9
hP5V/jj/Ff9o/xz/w/6K/vP9hP0Z/ub94P97/8QAWAD8/1L/l/4M/s39h/1I/sP9
e//2/jwAmv9F/93+Ev7A/fP9S/23/lH+RQDH/0UBpABPAOn/wP5h/nf+//2E//D+
aADp/4sA9v9x/yj/lP4M/qD+Uf54/w//+f+E/+n/p/9S//n+jv4v/oH+D/5l/x//
WwDz/53/aP9F/hz+kf1u/cb9l/0v/rb9oP5I/kv+6f1+/QL9nfw+/IH8O/zA/WT9
gf4f/l7+Gf6a/YH9/Pzv/Gv9DP1o/vP9kf0o/bD8YfyH/dP8Pv6z/ZH+OP7z/mH+
0/5V/l79H/3s/If8ev32/EX+/P23/kL+Nf78/Vv9/Pz//Hr8cf0F/RX+jf3Q/jL+
7P5+/q3+Pv5V/uD99v5+/oH///5Y/9n+Bv+O/nT/5v6d/zj/fv8l/53/Qv97/6T+
sP7//Qz/a/6H/xX/L/+k/iz/s/6k/17/W//8/ub+l/5C/6r+hP8P/xL/pP5b/vn9
7/2K/Z39D/3W/FH88vyN/Kr9HP3D/VT9Tv7T/Wj+H/6t/W79Qf3M/OP9xv3s/dP9
a/1I/Yr9Xv2X/nf+D//A/lv+DP66/Wf9cf0S/YH9KP0r/p39Pv7//br+Mv7Z/m7+
OP7G/R/93Pz//Kr8K/6n/UL+vf2d/Tj9Av4C/pT+Iv6B/g/+WP7j/V7+Av5e/9n+
8P9C/8r/Rf/a/0v/IgDH/8D/kf8//+D+A/+9/rD/Zf9IAO3/mgBPAOYAqgATAboA
awC6/4T/DP/K/3H//P+q/xYAvf/j/73/qv9C/xn/vf5e/gn+Pv4M/ij+H/53/UH9
S/0r/eD9vf13/m7+lP4y/or+L/7//YT9gf0l/TX+pP3W/nH+fv4l/kL+Ff7s/cD9
4/1+/XH+9v2B/xn/bv84/1H+H/4J/cP8Tv3p/PP9jf1V/iX+Pv7p/WT93/y2/GH8
ivzf+9D8S/ya/Dj8Yfzi+2f8KPyz/Fv8K/0P/Yr9Rf2t/TX9W/07/Z39Mv10/UX9
rf1x/YH+8/0S/4H++f50/sb+fv5C/93+rf8M/6T/Tv9VAMr/hAApAPz/fv8o/5r+
O//w/pf/Gf94/wP/DP+d/pT+SP5u/un9Uf4V/pf+SP50///+aP9S/wz+uv19/Fv8
Yf3y/HH/vf7W/zv/t/5Y/tD9pP10/vn9aP4y/rr+9v04/7r+S/8S/7f+Ev6z/WH9
lP7v/bf/of/A/zj/Uf7W/Uj9yfwP/b381v1b/R/+mv3//XT9Tv3A/Ej86fvG+z77
RfyT+4f90/wP/oT9Ev19/C78rfsM/LD7d/xI/AX9zPxL/fb8Xv0c/YT91vxx/f/8
Tv7J/XT/6f50/wP/s/5Y/lX+//2R/i/+Uv/5/kIA0P8PAGX/1v5e/rb9Rf2H/SL9
xv47/lv/4P5x/93+s/4M/gz+3P0i/rD9wP44/mv/0/41/6r+Xv7g/VX+Ev7w/oH+
Zf/T/of/Mv/N/lj+9v2H/en9h/3A/hX+DP+t/hL/0/4M/9P+zf7A/lH+H/4+/hz+
zf5R/gb/kf7d/kj+s/5C/s3+Vf4G/lH9Qf3D/Fv9/Pzs/Vj93P1e/WH9K/3J/YH9
lP1O/Xr9D/1+/QX9nf04/ar9KP1O/Z38iv38/Az+iv1R/ub9Iv7N/TL+Ev5h/jj+
Iv7m/f/9nf2w/hz+LP+6/vD+6f5x/hn+Jf7Q/Vv+//0J/qr9fv75/Tj+2f0+/q39
SP72/Rn+zf07/tP97P6K/i//4P6U/jL+vf50/qT/KP/z/37/4P6X/rr+OP69/1v/
FgDK/x8Avf/5/4T/tP8v/2H/xv5S/5r+dP8G/93/cf/T/zj/Jf+n/r3+Gf4r/tb9
yf10/eb9L/2a/R/9Gf6z/VX+yf0C/kH9Yf3c/EX98vx3/QX9//2X/Sz/dP5I/4r+
OP6w/WH99vzc/HT8l/32/LD+aP63/oH+Ev6E/cP8d/yt/JD8Av6g/br+S/5O/tb9
lPyE/I37KPtb/Pn7cf01/Sv+sP1F/Rz9K/z/+zX7O/ua+x770/yg/On9kf2H/S/9
H/zi+178H/yq/SX9Pv7c/Wv+K/4c/q39Mv3W/Cv97Pxu/jj++f9Y/5T/OP9+/kL+
Bv6U/Uv+mv0y//P+gQDd/14A4P+U/0j/lP5R/tn9fv1x/iL+wP9r/4T/Cf/g/Wv9
Qf3D/Bn+h/0c/73+bv8V/7P+Nf5F/fz8ivwF/K38Nfzz/YH9A/+d/vz+nf5V/uz9
SP38/Hr9GP3z/Yf9Cf7D/Q/+pP3m/bP9Jf7J/RL+zf1h/jj+yf2X/a38Pvya/E78
l/1L/Q/+tv0G/kj99v1+/Yr99vxh/B/8kPz5+4H93/x+/Sv9Xv0S/SL94/zJ/Jr8
uvx9/If9L/3g/YT9Jf3m/I39H/1e/vP9gf4M/p3+Ff6B/hL+gf4G/tP+Jf5b/+b+
vf9F//n/bv+a/wb/l//8/lL/4/4//73+t/8Z/zv/lP5u/tb9hP4i/kj/7P4o/6f+
h/4f/mj+2f1r/gL+KP6k/VH+Cf4c/+P+h/84/xL/xv66/Wf9Rf3G/Az+l/35/mj+
a/41/pr9h/1r/Rj9Qf0C/cb9Yf01/tP9l/4c/kL+9v0C/l79Iv6R/YH+6f26/j7+
1v5o/nT+DP6N/QX9uv0V/Vv+7P2q/jj+Ff7c/X79Ff0P/Y38S/3p/CX+mv0y/gL+
bv0i/db8d/x3/Az8nfzs+0v93Px+/gn+DP9+/ij+4/1k/R/9Ev66/TL/yv7T/1v/
bgD8/2UAHABC//P+ZP7v/VH+Av6U/wb/JQCt/+3/bv8G/4T+sP5e/un+p/5h//z+
sP97/73/dP+U/m7+uv1u/W7+L/6H/27/vf9b/2j+yf07/af8WP3v/On9w/3W/k7+
4/5r/kX+yf2q/SX9lP0V/WH+9v2d/y//mv9r/xz+xv10/fn8iv4v/u3/W//g/1v/
aP+q/uD+WP4o/vP9Mv7N/TL/oP7d/2X/OP/p/kj+yf0+/en85vzM/Kr9Bf38/Yf9
tv01/XT9Cf22/Qz90/1u/Xv+OP7K/kL+0/5+/nH+HP72/W79h/04/dz9kf0G/6T+
eP8V///+qv5u/h/+SP4Z/oH+DP6U/iv+jv4v/sr+h/6X/07/5v+6/3j/2f7K/m7+
8P6B/uP+jv66/i/+8/6K/o7/W/+k/2v/s/5O/qD9Xv1L/dP8HP2j/EX9kPwy/oH9
xv4r/g/+oP1n/eP8jfwl/AL9ffwr/n79qv5V/ub+Mv6H/jL+4/2n/eD9Qf1u/h/+
Rf8S/yL/0P4y/ub9kf1O/Q/+oP2K/hL+nf6B/kX/0P72/or+//2B/W79zPzJ/Z39
HP7G/X79Mv1L/dz8WP0C/S/9xvxY/en89v2w/cP+mv7g/p3+Ff6a/U790Pxn/fb8
OP7G/R//oP4J/7P+Yf7//br9W/2K/Uj9Nf7Z/UX/Jf8MAKT/dP8c/6T+OP6g/kX+
Zf8f/zgA2v/Q/1X/w/5Y/hz+0/1O/uz9t/57/iX/w/4v/63+9v13/Rz9xvyB/RL9
5v6d/rT/lP/W/qr+Yf0M/aD8O/zJ/JD8Qv7s/eP/rf8MAOD/5v6E/qD9OP13/TX9
OP72/V7///7a/7r/S////kv+//1F/hL+wP6d/p3+a/6a/j7+Bv6U/Wv99vx0/S/9
cf4r/iz/8/47///+oP50/sP9cf2R/Y39kf5C/sb+mv5V/vz94P1+/bD9Iv2N/Uv9
dP1U/dz9h/13/vb9Mv7p/bP9bv2U/Uv9gf0M/db9dP0c/2j+LP/Q/vn+gf57/v/9
w/26/dP9ev3Q/or+LP/8/uP+kf4P/qr9yf1r/bD9Tv2t/lj+cf/w/qD+Mv72/YT9
l/0o/Vv+8/0o//P+pP8v//b+sP5L/QL9qvxn/HT+Mv5IAOn/JQCH/6D+WP5r/dz8
Ff3//OP9ZP2w/zX/SwDm///+hP6B/Tv9s/01/d3+lP69/17/0/9I/8r+SP75/ZH9
jv78/Uj/zf6B/yL/Gf+9/rP+OP7p/XH9Qv69/aH/L/8GANb/Jf/s/g/+7P0+/QL9
DP2K/Pb90/2t/zL/tP9L/zX+kf3y/FH8hPxB/OP8gfxe/hL+//6w/nv+HP5k/fz8
oPxk/CX93/yK/lH+0P9l/zj/Cf8y/pT9Ev6R/a3+Vf47/7D++f9S/47/Ff93/uP9
oP04/XT+9v2R/+n+3f9u/1v/xv5F/qD9ev35/Pz9p/0o/73+W/8f/7f+Xv7p/Wv9
cf1L/YH9W/1b/mH++f7N/pr+OP6g/V79bv0C/bP9SP32/sr+HwDN/7D/Uv+6/m7+
uv5V/or/Jf8vAN3/TwAiAL3/cf8M/+z+0P6X/kj/HP9VABIAmgAGAGH/3f5r/Tv9
9vxR/C/+qv3g/2H/+f+q/zX/4P4o/rb9Ev35/EX99vyO/h/+3f7T/lj+e/5u/kv+
7P6H/hn/nf7w/pr+3f5+/oH+Xv50/hn+LP+6/rr/P/9r//n+4P6q/nH+OP72/db9
kf41/rr/LP9l/zv/KP6z/ZT9W/1F/gn+A/9u/jL/hP6q/mv+h/47/tP9Qf3Z/X79
dP4y/gP/wP4c/9b+hP4V/sn9l/3p/bb9sP5L/mH///5C/7r+0P6w/un+sP5o/yL/
uv9h/5T/Qv+X/07/Xv8c/2v/Rf9b//n+D/+d/hL/nf7N/of+d/5u/pf+dP4//yX/
Ff+O/m7+/P3g/Zr9OP7N/Z3+SP4J/53+e/8J/w//zf5V/rP90/1k/Vv+3P1C/9n+
9v8//3H/8P4M/qD9oP07/fP9h/1x/ub9Ff+E/kj/7P7d/mj+/P1+/fb9l/2a/vP9
t/41/rr+Xv5O/v/92f1B/Uj++f1Y/wb/Vf/d/k7+sP3A/V793P1k/V7+//3g/oH+
aP/p/jv///50/ij+Ff7W/Zf+Gf6R/xL/8P+q/7D/OP8v/8P+vf5b/tn+d/5o//D+
Uv8f/3T+Qv5I/uD9DP6k/Uj+7/38/qD+gf/j/iz/xv7W/b39Pv3j/Gj+1v2O/0L/
6f+O/5H/L/+H/vP97/1+/Z3+dP4sABYAxwBxAAMAsP/W/qD+OP4C/kX+3P3s/mT+
BgBr/17/6f5+/SX9yfxx/K39Qf1o/vz9/P3T/V79Nf1b/QX9Yf3p/Nz9Pv07/gL+
2f2N/Uj9D/3A/Ir89vy6/C/+qv10/w//1v6B/nr9+fzv/Hr8Cf6U/Tj/7P4GAHj/
AABb/6H/O//W/uP+Uf4v/gP/zf7t/8f/3f94/4H/Cf9l/93+WP/z/jv/7P72/qf+
6f6n/r3+dP5b/j7+//3D/Yf+Xv7z/sP+w/5h/n7+H/6a/jX+Cf78/V7+aP6R/3v/
TwBrAB8A0/84/xL/nf6d/tn+rf7T/2j/cQASAF4A9v8o/wP/1v5k/ub+fv4v/9n+
Qv/s/gn/l/4Z/rP9ZP07/Vv+5v0o/5H+p/5e/gb+0P0v/Qz9vfyE/A/90/yE/jL+
Iv7m/eP8l/wu/Ob7h/wi/ND9WP1I/gn+1v6H/sD+d/7z/aT9Uf3f/CX+/P10//n+
w/+w/2j/Uv84/9P+0P6w/uz+zf7j/nv+l/5+/iL/0P72/sP+uv5o/qT+Vf53/kX+
//0M/sb9rf3W/a39jv5b/gn/pP57/m7+Uf41/mj+aP7p/qf+3f63/h//8P5e/0L/
tP9+/xn/SP9S/wz/hP/8/hn/9v4G/+P+Uv9O/8f/0P/H/1X/Nf8P/4r/Vf8pALD/
yv9u/xwAiv8cAOb/OP9O/7r+a/44/+b+qv97/wP/0P44/iL+D/7W/fn9wP1+/j7+
yv6R/tP+1v6E/lj+xv1+/dn9rf2E/lv+H//w/uz+2f5u/hz+OP4l/lX+Mv6O/pT+
w/6H/vD+e/7K/rf+l/4f/rr+lP6q/wz/Tv/s/nH+KP5Y/gL+//6n/m7///50/x//
SP8o/9P+oP6H/kX+yv6g/pH/DP8vAK3/vf9o/+n+qv6t/pH+Yf9F/+D/mv9S/yL/
4P6X/vb+s/6K/m7+d/41/t3+zf5I/wz/Iv8Z/wb/s/6w/5T/FgAGAB8AAADN/8P/
9v7T/uP+h/6h/3v/+f/Q/9D/w/9l/wb/Ev+3/vb+uv4y/7f+W//z/lL/D/9x/kv+
7/3c/Tv+H/6n/mT+//6a/lj+Ff5L/QL9mvwr/Dj9yfzG/YT9Av6X/Qb+l/3G/Uv9
Xv3//J39L/2X/v/9xv6E/mH+Ev6K/UH9Gf6d/V7+HP6z/lH+Bv/A/un+p/7d/pT+
4/6g/mj/yv4//8b+W/81/wz/p/4P/gz+W/4C/vD+S/6z/j7+Ff69/Zf9bv2R/Uj9
ev1x/RL+4P3A/jj+8P6n/vn+oP50/lv+7/22/bP+Nf5S/+n++f7W/uD+fv5+/xz/
AACk/0j/3f7Z/m7+eP/2/rT/Mv90/wP/2v9O/+3/e/8D/6f+nf47/rr+Jf69/mv+
jv4r/gb+w/1e/Rj9Rf3y/L39xv35/Yr9yf13/ZH9Rf2g/WT93P2R/Sv+oP1I/ij+
Pv7g/ar9bv2w/V79Ev75/YT+h/7m/sr+aP5u/tP9sP0V/ub9xv57/t3+p/7T/qr+
nf5O/nf+6f2H/oH+Iv/d/vz+uv5O/g/+2f2k/RX+xv38/pr+Tv8P/x//0/5R/tb9
6f1h/WH+Iv4S/7P+SP8D/0L/Bv8s/+P+3f6K/nH/1v5CAPb/hABCAHT/OP+X/nf+
KP/d/t3/e/8SACwAKQAZAIT/O//Q/pH+yv5o/mX/HP+U/2j/A/+z/sD9p/1Y/f/8
Yf5O/gAA8/8fAND/rf5Y/rb9W/3//Z39zf5e/t3/e//W/27/0P6n/qT9a/3s/af9
DP/g/u3/hP/p/4H/qv5r/q39h/0l/hL+Zf/z/pH/A/9Y/vz94P1n/cb9a/07/vP9
Bv+9/kX/8P4r/h/+fv0i/Wf9D/1F/hL+Ev/W/lX/6f5V/qf9p/2E/cD+lP7t/83/
PADH/8r/qv9Y/+b+uv6U/kX/Xv8DAb0AjgGqAbcAeAC6/0j/dP9V//b/zf9bADgA
WwAfAFX/Mv/K/nf+oP4+/tP+yv5O//b+/P6w/o7+Rf6t/VT9hP2U/Zr+W/4l/7f+
xv6E/rD+Yf4D/8b+O//5/tb+bv6B/jL+0/5I/mH/rf5b/+n+HP+a/hn/xv7w/rD+
jv5I/rf+OP7z/oT+3f6H/gb+sP3A/VT9//2k/dP9bv2a/W79W/0Y/e/8kPxX/Ej8
Ff3Q/D79Qf0c/eb8w/yg/Bj95vxU/SX9ev0v/Tv+//2a/k7+Iv6z/RX+nf3K/jj+
P/8S/5H/Nf/5/8P/0/+w/0j/KP/T/2H/OADp/3H/Tv+6/nH+w/5h/kj+OP5V/i/+
xv6q/kL+HP41/Sj9Ff3Z/DL9K/38/db9Uf4C/ij+6f3W/bD92f29/WH+Qv6O/or+
Zf/j/vz+p/6n/mv+1v7D/vD/eP8iAMP/p/8i/yL/gf4V/7P+Zf87/6f/mv+n/1j/
2f6z/rP9fv2K/VH9fv4C/vz+pP6w/lH+wP0l/fL8lPz2/J387P22/XH+Jf7G/ZH9
lP0S/S/93/yX/QX9SP7g/a3+fv6U/mv+p/1b/ZT9Jf1k/hn+cf8M/07/Ff9Y//z+
/P6t/mv+Vf6w/qD+nf97/8r/e/+9/mj+Bv66/e/99v1b/jX+oP5e/k7+Qv5C/gz+
DP7J/XT+Pv4G/7P+LP/s/jv/3f7D/nv+0/57/kj/9v6X/3H/H//8/rf+a/7W/k7+
S//Z/o7/L/8PAI7/vf90/yX/0/7w/rD+s/5b/rP+bv7m/nv+oP5+/uP+kf5b/+n+
P//g/mj+K/78/Z39+f2n/S/+8/1Y/vz9l/5k/rP+Tv4y/sP9SP72/fD+e/5h//n+
7P7W/tD9zf2K/Zf9WP4l/tP+l/4M/+z+0P7Q/lj+SP7v/cb9L/4i/t3+ZP7D/n7+
S/5F/sn9pP1k/UH9Pv4c/sP+lP5C/vn9bv1b/V79Rf3D/YT9WP4i/tD+1v5I//P+
cf5+/vP95v1L/gz+fv5b/un+1v7w/tn+Ev/W/g//1v5I/yj/OP8V/7f+cf5I/jX+
L/4v/oH+ZP69/un+HP/W/n7+a/4o/gn+6f3p/Sj+sP3Z/a39Gf7j/fP+S/5r/k7+
hP4c/sr+lP7p/qr+cf5F/pH+Pv63/1X/8P/t/5T/nf8V/73+4/6K/rr+Rf4M/73+
OP8f/4r/Xv8o/yz/t/6X/hn/sP5C/wb/Uv///hz+7/01/Qn9GP0S/YH9w/01/ij+
iv4+/g/+s/1O/R/9vfyz/L39rf0f//n+LP/p/kj+Bv4P/sP9Qv7z/fz+pP5+/yz/
Tv8P/4r+jv5F/gb+fv4+/hX/8P5b//D+8/66/ij+8/35/Xf9WP7N/af+O/6t/hz+
Nf69/aD9cf10/U798/2g/Sj+yf3s/cD9Z/0y/R/9GP1B/Q/9Cf6g/dn+3f50/mv+
KP7z/XH+Pv6z/or+4/6w/iL/0P57/1v/tP9O/9P/Mv+6/3j/W/9C/7r+fv5C/iv+
+f6a/nv/DP+H/x//zf50/lH9Qf1e/Qz9Nf75/ZH+Xv7c/ZT9Nf0l/cn9p/3K/oT+
Zf9L/37/KP8f/v/93/yg/Lr9Nf17/+n+pwBSAJQAQgA1/6D+d/3y/JT9D/3w/nT+
NQDW/3T/8/7Q/Zf9Rf38/Fj+4P2k/zL/Nf/T/gb+h/2q/Ff8V/wS/Jf9K/1F///+
SwDg/8D+cf50/CL8O/wV/Nb9Xv0D/8P+Xv+z/tD+d/44/hn+Xv4S/gYAlP+tAHUA
x/9o/wn+l/16/Qz9Xv41/p3/eP94AAwAW/81/839a/07/Vv9yf13/R/+yf2O/lv+
KP72/T790PzD/J38Gf4M/gn/KP8f/vn9W/35/HT9WP3z/ZT9l/4i/rr/W/8ZAAYA
h/+B//D+6f7N/pf+Tv/p/vD/zf/g/63/Ff+9/g//pP7w/p3+Vf4S/jL+zf2t/kL+
Gf7Z/WH99vxL/dn87/2X/ez9pP1r/Vj9mv1r/XH9VP1L/RX9l/1h/Sv+4/1C/ub9
Yf53/n7+H/5V/uP9S/4G/uD+l/4M/wP/bv9h/4r/W/+t/nf+d/4f/h//nf5o/wz/
5v6z/sb+rf4Z/wb/rf6B/uz94P0G/pf9mv0C/fn8kPyq/KD8S/0C/Yf9D/1h/fL8
Ev29/Kf8YfyX/If84P2N/cP+fv7j/l7+sP4v/sD+Yf63/oH+x/8V/2sA6f/8/63/
Ev/m/v/+HP/p/7T/0P+X/9n+0/5o/lX+D/7c/Sj+yf1r/lj+vf6H/iv+Jf78/Bz9
UfxL/MD8uvw+/iL+p/5+/lT9HP1L/DL82fxx/KD9dP1O/hz+LP/K/mX/+f4v/s39
s/1r/Zf+Xv5O/wn/bv/p/qD+t/5L/vn9a/4o/jL/6f6H/2H/8P6t/uP90/3s/Pz8
+fzA/Hr9Uf2R/l7+bv5O/uP8sPyz+8D7EvwY/H38YfyQ/Fv8H/3y/Hr9Ev29/K38
//y2/GH9Pv2R/Wv9Av5k/X7+Ff5R/gz+mv6K/tb+s/7N/pr+p/6B/uz+sP5x/zL/
sP6H/rr+a/6n/pT+4P6q/vn+iv4y/hn+Rf0o/Sj98vz2/db9w/5b/lH+Mv7D/X79
OP38/EX95vyz/Zr9sP6K/hz/5v5b/j7+Jf0P/TL9D/1k/hX+Ev/A/vP+xv4i/tP9
7P3Q/UL+Mv6R/nv+5v66/kX/DP+O/kj+ZP32/Kr9ev0D/8D+Iv/s/jv+3P2g/Vj9
HP3m/P/8s/yw/YH9l/47/k7+Av5B/ez8h/xI/PL8bvy2/Yf9vf41/or+KP62/Y39
jf1h/Rn+5v3G/of+Ff/8/qf+gf44/hX+SP7W/T7+4/3G/nv+Jf/8/sP+iv4G/rb9
w/2w/XH+HP4l/7f+Tv8P/zj/+f66/o7+Ff66/fb9yf35/o7+WP8f/yj/A//W/qf+
cf5I/iX+D/7j/qr+fv+E/9D/4/+E/zj/kf5R/hL+6f38/f/9mv44/vP+oP7g/nv+
Mv7p/Zr9kf2R/Wf9OP4P/qT+Vf5V/gz+Uf3y/ND8mvy9/YH9S/4C/qr+cf5F/gb+
Z/0+/QL91vyB/XT9nf5+/vb+h/47/j7+iv1u/YH9W/17/g/+bv/p/pH/9v6a/kj+
bv0o/eb8sPxx/SX9W/4S/vz9s/0P/cb8Bf3c/DL9GP3v/aT9l/4i/s3+Yf7z/cD9
s/yt/KD8VPzW/aD9s/5o/nv+K/5O/v/9Ev7J/Zr+Uf7s/rf+A//K/lL/Ev9O//b+
L/8//3v/SP9Y/0v/Ev/s/rr+gf6K/h/+xv5I/vz+qv66/lX+9v2k/Qb+hP01/vb9
wP2d/ZH9VP1u/Tv9gf0o/VH97PxR/Sv9vf2U/X79iv13/Xr9cf1L/Rz+0/0P/tz9
L/01/SL9w/yk/UH9sP5L/iz/8/4S/wn/hP4r/or9GP0S/fL80P3J/cb+lP6n/pf+
9v3Z/Uj9Av0i/e/8wP2U/Uj+Bv7J/br9O/26/H38SPzy/JT8//2k/ZH+cf5O/tz9
cf0C/XH9GP3T/Yf9+f6E/g//3f7D/tb+Tv7D/fb9nf2O/k7+D/+n/jX/wP7j/m7+
9v6X/kv/7P6k/0v/Gf+9/or+Ev7Z/Y39WP0+/fb91v3D/rD+yv5C/mv9Rf2q/If8
6fz5/Ab+mv2g/lH+hP47/r39ZP1I/Qn9dP0+/RX+7/2E/vz9DP7J/bP9a/0+/Rj9
xv2w/Zr+Vf4i/g/+//zG/Pn8hPzj/a39e/47/lH+Ff7G/XT9l/xq/Bj8tvv8/L38
cf4r/sr+bv7j/Yr90Pyn/LP8gfzm/XH9Nf9S/x//A/8S/v/9Rf0v/XT9L/2k/k7+
vf9e/3j/DP/8/Wv9iv0r/W79Qf1u/gb+Nf/Z/kj/+f63/mv+7P3c/SL+DP6n/qf+
s/53/nf+Vf4v/ub9h/04/TX+7/3Q/rP+wP63/qr+kf4o/8b+Vf/g/g//0/4l/+D+
a/8Z/wz//P6H/lj+s/5r/sb+fv47/jj+Iv5L/vD+s/6R/nT+0P16/VT9Mv29/YT9
Rf4V/mH+Yf4G/rD9+fyz/A/89ftx/EH8bv3v/F7+Ev78/e/9VPw4/GT7MftL/AX8
3P2w/WT+8/0l/sb9kf2U/cz8rfwl/R/9bv47/vz+wP4i/sP9+fzM/BL95vwi/hL+
xv6k/rr+wP69/dP90/yg/Nn8w/x+/V79Tv4i/tP+l/62/ZH9W/wi/CL96fzA/eD9
H/7c/fn9zf3J/Zf92f2R/dn9wP3N/pr+1v+a/6r/eP8G//n+rf5u/nT+cf4c/0X/
FgDj/83/t/9L/0j/w/7m/n7+d/5L/hn+dP4l/un+rf44/hX+a/1b/WT9S/07/Rj9
D/3Z/BL92fyd/UX9Jf3c/CL89ftU/HT85vzj/GT9nf2z/YT9s/2U/Vv9Mv04/dn8
qv1x/SX+Jf5k/kL+nf2H/ez8tvyw/Lb8W/1U/bb9WP1b/Vv9bv1L/V79Av3p/Kr8
+fzj/NP9oP3T/YT9jfxn/GT88vvy/MD8fv0S/Z39Iv04/fz8mvw7/AX9bvzW/VT9
Tv4P/nv+WP5u/jX+Av6K/af9bv2E/lj+vf+H/2X/SP+n/nH+l/6K/gb/8P7N/rf+
t/6R/qD+jv4l/w//Jf/z/iL/Iv8J/+z+h/5o/tP9/P0Z/sn9W/4o/uz+2f6z/oH+
zf2g/ZH9a/0M/sb9l/5C/ij/zf7D/qT+zf3Q/br9l/2R/qf+hP+H/0X/Cf8c/vb9
4/yU/MP8Z/yw/VH9uv57/pf+S/5O/RX9KPzW+0X8+fuR/Wv9Tv72/RL+tv2d/If8
FfzM+9P8nfzg/cD9Uf4v/lH9W/2K/Jr85vzj/GT+H/5+/6T/L/8i/7r9jf0+/SX9
vf1B/a3+WP66/5r/zf9l/yv+Mv72/AL9d/1b/W7+SP4y/+P+H//m/hL+7/2q/Uj9
4P2d/Xv+SP7W/nH+gf5Y/jX+Gf6w/ZT9Gf4l/o7+Yf6H/j7+HP7G/Wj+9v2k/yj/
LwD5/xkAFgBL//P+Ev7G/RX+9v0P/8P+LP/D/hX/lP66/lH+Ff6w/dP9d/0o/v/9
kf47/pf9Rf2E/GT8mvx0/EH9H/2U/WT9oP1O/Sv9wPxL/Cj8Pvw1/CL9L/3W/aD9
0/2w/Zf9l/2N/Vv9rf1r/Rn+7/23/ij+nf4y/jj+H/6X/jv+0P5x/uD+e/7N/mj+
aP41/gz+Cf4o/uD9p/44/uP+nf69/p3+Gf7J/UH9Av16/VH9Ev7J/Qb+4P0P/rr9
9v3D/bD9bv3T/Yf9dP4+/g//w/5r/9n+Cf/2/lv/SP+X/2H/uv+B/xkAyv+0/53/
e/9L/4H/Uv/2/7r/zf+6/73/qv8s/zX/aP4o/g/+3P3G/db9Ff7Z/X7+Qv4f/ub9
xv1u/UX99vyQ/Jr8s/yd/EH9Cf3D/aT97P1r/bP9dP1n/Sv9fv04/br9hP0S/pT9
6f3G/Tj+7P01/gz+OP4G/n7+Uf4M/9b+2f57/hL+vf3c/Y39Nf4c/sP+0/7G/pr+
WP5L/p39gf0S/db8fv1B/TX+Tv6q/lX+9v16/W79H/0J/QX9ZP1U/X7+Yf4y/y//
fv57/jL9Bf0l/B/8SPwV/KD9oP0+/iv+SwAGACkCHAIDAtABVQL2AeMAzQDs/dn9
yfy6/Ob8o/wV/tn9LAAMAPn/t/8f/uD9d/0y/U79Iv1b/i/+eP9F/0X/Ev87/uP9
4/3G/cn9lP3G/X79//3c/dP9dP38/cb9aP8P/6f/S//s/eb9lPy2/MD8bvwV/Z38
cf4C/hkB5gA/AiYCeAEWAW7+cf7G+qP6Qfl9+b37qvtr/TL9KQDz/+0DiAMpAtAB
9v2R/XT5K/kU9Qv1Y/UX9SX7+PquA7EDDgrkCRcIHQgs/yX/v/aT9v7y2/Ky9lf2
sP+K/xMHCgcaBw0HIwLtASX87Psr99v2WvgI+Gv9O/0pAi8CQgQjBCwCKQK9/1v/
7/3N/a38VPyz/FT8V/wV/CX87/uU/E78Mv3A/Jf+Yf4vAMf/cQAPACUA7f8JAOb/
lP5O/oH8RfwV+/z6sPpe+jv8LvyhAKoAjgRPBDYERgTgAL0Aqfqz+iH22/Uh9+v2
Xv2n/RAE8wNTBkkGawM2AwX97/xa+JP4bfiA+Bj7KPtY/Xf9rf13/SL+/P1+/3v/
PAH8ALEB1wH8/vD+zPmw+Y/1YPU39x73pP6R/nIFZQXqB+EHqwSkBCv9K/00+Bj4
Qfgn+Mb6mvrv/br9DAEZAdACxwIcAxYDawI/Aub+s/56+Ur5J/Yx9pn3UPcr/f/8
YgNMA9cFxwUjA8cCKP35/DH4NPic9kr2ffmG+YT/SP+OA1IDggRsBO0C2gL8/pf+
7PrW+oD5Svln+yL7Jf8Z//YA8ABSARMBxwDAANn+Ff/M/Lr8jfvA+0T7D/sF/ND7
Cf4V/qr/fv/N/6r/Uv///k79Jf0S+9P61vp9+uL7sPvJ/MP87/26/Qz+Cf7g/af9
iv1F/dz8yfyH/aD9uv5x/qr+bv6t/Zr9cf0r/Yf9Tv0V/gn+fv8//4H/Vf9Y/i/+
5vy9/KD7jftb/Aj8wP2d/c3+uv6t/07/Tv/Z/j7+yf0G/rb9Jf7Q/cD9lP1Y/Q/9
Tv3m/G79Pv0v/uz9mv5u/h//Gf8lAMD/L/87/0j+1v1V/uP9hP41/pf+Vf7W/4H/
x/+O/73+rf7m/p3+L/4f/vn9Cf7Z/q3+Jf/z/mj+Xv7m/br97/38/Yf+gf72/vz+
Zf84//z+s/4y/d/8Jf2z/FH+Pv75/uz+//7g/or+gf6k/dD9w/2t/fb9+f2U/h/+
W/5V/lT9DP1O/cn8Nf4P/t3+nf47/xz/0P7W/mH9K/1U/UH9h/5b/vn+s/69/qD+
SP5V/gL+tv0c/s39DP/m/sP/Xv9L/xX/Pv4l/gn9DP3G/F78h/4l/qQAeADqAJoA
eP8c/4r9cf1n/H38Uf0P/Q//kf6kAEgA/P/N/1X+Mv50/Sv94/yU/Ev9Ev3W/rP+
rf9x/47/gf/w/hX/Nf7Z/dz8dPwC/YH8DP7W/V7/a/8fAeMADwETAQn/1v4f/e/8
9fsV/Pb8sPyB/nT+dQAWAGUBQgEDAdoAIv/W/i/96fzv+8P7h/s7+8D8ivxO/wP/
1wCXAMoAqgB+/w//KP2X/Dj7qfob+7D6rfwP/Jf+Yf7t/53/gf8c/3H+Mv5k/Q/9
sPxR/Oz8o/zs/Yr9LP/A/gYA0/8sAO3/2v+H/wb/w/75/U797P2n/ar+Yf6O/n7+
qv6d/h//wP4c/93+l/5h/rf+Xv5O/v/9Iv66/Yr9K/2E/TX90/1R/Qz+uv1V/ub9
e/4i/oH+3P26/VH9W/0v/YH9DP2H/U79Rf7v/SL/uv5S/w//dP/Z/uz+rf53/hL+
W/72/UL+5v2X/jv+sP5k/uz+lP4l/+n+L//d/hz/A/9u/h/+vf1b/eP8oPz//On8
fv3//Nb9l/2g/jj+Cf+g/jL+//2g/SX9cf3//Dv97PyK/RL9ZP72/cP+Yf75/tD+
Xv8D/wP/0P6K/Uj9tv0v/Qn+rf0V/qr9Jf+3/l7/+f78/o7+zf5r/lX+sP01/gL+
hP41/lX+D/6H/nH+S/4J/pr+L/7A/mv+gf7p/Y39fv2n/Sj9Ff2z/Lr9a/0v/9b+
Zf8f/47/aP+H/z//Tv/j/mv/8/4V/7r+6f2X/db9WP2k/l7+FgDK/yYBzQBlAEsA
L/4i/nf8RfwS/Nn7hP0y/VX/5v4SAI7/3f+k/zX/wP4S/qT9l/2K/Wv9L/1k/Qz9
pP13/Sj/1v5uAAYAlwAfAAn/xv5Y/Vj9ivxF/Nn8h/wZ/sn9Vf8//73/jv+a/1j/
Ev+a/rD9WP0V/db82fyQ/JT8SPxh/RL9zf6X/m7/1v6w/mH+zf16/b38cfwr/BX8
mvxk/Jf9Jf1h/rD9uv5C/kX/6f4c/63+mv6H/p3+Pv7j/Y39kf1L/aT+bv5uAPP/
BgGaAHgA1v9Y/9n+4/2k/b39Qf0V/vb9hP5o/vP+xv66/mv+tv1h/YT9SP35/Qb+
qv5F/of+bv4y/tD9VP32/Fj9/PwG/n79wP5O/pr/Uv+O/17/qv5o/pT+WP6w/n7+
SP8y/8D/p//Q/3T/lP8y/zL/3f7A/3j/lAA/AAkAp//G/pH+wP1r/cP8Yfx3/VH9
Nf/m/lUADwAPAM3/qv6U/kv8TvxX+/X6BfwI/D79w/xR/j7+W/9C/07/8P6q/nH+
d/0J/S783Psb/NP7Jf3y/Fv/LP/wAPwAHAEPAZoAFgB0/ij+jfyX/EH8//s+/S/9
KP///vMAhwAiAdoA1v9V/5r9Pv3y+4T7Evya+179H/26/qD+iv+O/1j/Bv8C/tb9
/PzA/Nn8kPwS/eb8a/4v/tD/nf8GAKf/hP9b/9n+0P6z/XH9O/3v/Bn+6f1u/1L/
rQCHAEUB9gD5/7T/vf2d/ZT8Rfxk/EX87P2a/dP/bv/QAHEATwA1AJ3+SP72/Jr8
Nfzc+7b8SPy2/WH9dP47/rf+Pv5k/h/+zf2z/cD80/xI/AX8Rfwo/PL8tvxL/hL+
Jf/N/iz//P5h/mT+DP7//Yr9cf01/vb9d/5F/tb+oP4M/8r+0P53/pf+OP78/db9
rf3N/Qz+6f0l/+n+W/9S/47+ZP5r/U79Tv0l/ZH9fv0S/sP9ZP47/tz9oP1h/fn8
0P2B/XH/Jf8PAA8ARQAMAKH/Nf+d/jL+Ev/A/vn+xv7D/pr+fv+a/+D/hP/A/n7+
hP6E/vP/hP/QAJ4A1wCLAGj/cf8C/d/8EvsL+zj85vvz/mj+GQGUAAkBzQAD/8r+
Qf0M/QL+8/2EAA8AAwGtACz/t/53/N/7d/pB+qb7Ivsr/tn9QgC0//z/pP/A/pH+
aP78/T//xv7p/7D/zf6B/iL9wPwP/Mb7H/zJ+wn+vf1rAAYAMgDT/1X+Ev69/FH8
Yfwu/Hv+Ev4WAJ3/O//d/vL83PwI/Mn7bvxe/Jf9Ff1C/s39W/4l/vb9qv2O/gn+
tP94/2gA8/+a/wP/7P2q/YT9L/2H/g/+EgC3//kA3QDp/4H/SP3D/EH7wPpb+7n6
Iv2Q/Kr/Ev/W/3v/sP53/hz+vf2g/k7+D/9e/lv+Mv7s/Z398/2X/Zr+S/5+/0X/
UgAsAK3/SP+U/uz9Qv72/aD+Mv7W/oT+l/5e/tP9oP0F/cn87PzZ/HH+a/6h/0j/
h/9C/4r+a/4c/Q/9Ev2q/BL+pP3m/rr+jv5k/v/98/2w/YT9Tv0V/eP9tv1F/tb9
9vyw/MD7d/vc+6D7bv01/dr/mv8GAeAAKQCX/9D9cf0Y/OL7V/wY/HH9KP1k/jj+
zf6K/l7+K/7v/dz9bv4y/p3+l/4Z/j7+W/1h/a38o/zA/IH81v2k/br+bv5O/gL+
/PyH/MP8XvwV/e/8jf1L/Sj+7P26/lj+gf5I/k7+Pv7K/qD+A/+H/gb/nf6n/lX+
S/4V/mH9DP2K/UH9oP5e/lv/HP8V/+z+SP8c/2v/OP/s/t3+3P3Q/dP8uvwf/af8
l/1k/bf+OP5V/zL/lP8//7r+nf5F/W797/y6/CL9L/38/Z397P22/UX+2f2n/nT+
8/5x/i/+3P0V/fz8ffwu/Lr8p/wS/rP9L/+3/gP/t/6R/lH+Ff7c/UX9xvzv/Lr8
Mv0i/Qz93/wJ/bb80P1U/Qb+w/2n/VT9yfx3/Hf8O/yq/G78Pv0F/TL+0/1k/tn9
1v2E/WH9GP2R/Tj9dP4Z/m7/zf5h/+n+Nf4S/vP9S/3T/V792f10/Qn+p/0v/uz9
8/5h/kX/2f6U/zv/zf7d/kX+//2z/Yf9SP3//M39ev1b//z+ZQAvAHsAFgAy/9b+
Ff6q/aT9K/2X/T79H/7N/Tj/zf6w/4T/Jf8V/6D+aP4f/sP9H/0Y/R/91vx3/Sv9
Pv4f/mT+Gf50/jj+Bv6n/Tv94/y6/J38Yfw4/MP8O/xe/fL8Yf4C/i/+3P2w/Xf9
//zJ/E78JfyK/E78Mv0P/eD9jf1r/kj+h/5C/lv+Gf7T/Zf9GP0i/cP8vfxe/EH8
9vzQ/Fj+Iv5h/2v/l/9C/yv+Bv7p/PL8EvzJ+4D7gPuQ/D78//2d/dD+jv6H/mv+
Xv4C/lH9ev3s/NP83Pyj/Dv9Ev0c/tP9Jf/T/kL/8/7Q/oH+K/7g/dn9wP0y/vn9
8P7g/ub/iv+n/17/7P6H/of+a/4v/hn+Iv7z/eP+d/6a/k7+O/78/VH++f0G/rb9
sP1F/V79Iv2E/RX9L/3m/Bz93Pyk/Tv9zf10/WH9Bf3D/JD8vfxu/Jr8Z/yj/Dj8
H/2H/Pb9Xv0V/tn9Ff69/eP9a/1n/Rz9dP3v/K39ev0i/p39KP7J/ar9S/2k/Tj9
OP0C/Sv96fxu/Tj9fv1F/U79+fzT/H383Pyg/FH9Qf3W/Yf9OP3J/ND8Z/zM/K38
Ff2a/G799vzs/c39cf4S/k7+Iv4P/hL+Cf7z/UX+4/1r/uP9Yf44/ij+1v1b/uD9
1v5R/s3+dP6U/lj+rf6B/n7+Rf4P/qD90P2U/b39l/2t/XH9uv2H/Uj+rf1+/u/9
Cf7J/ar9Qf1b/RL9lPw1/LP8lPx+/SL9nf1O/eb9lP2N/Tj9OP2K/L38UfzD/CL8
KP3G/Hr9O/3W/Vv9/P3A/Qb+xv3p/YT9Tv3Q/IT8H/xq/Aj81vyX/Gv9Nf29/W79
lP01/Zr8hPzW+2T7oPuH+078FfzT/JD8gf0J/Wf9Nf1k/f/8s/x0/Gr8Ivy2/Ir8
xvyn/D792fzQ/W79O/7D/Qb+7P0i/s39uv16/YT9Pv3Q/Vv9HP6a/W7+/P04/rr9
Gf7N/TX+/P1V/tP9Gf7m/Vj+4P3Z/ZT9H/3D/JT9Ev3Z/Xr9D/7c/S/+0P0C/oH9
s/1B/bb9ZP3A/Uv9jf0S/Z39Nf2z/Zf95v2z/WT+Cf7g/nf+pP53/hn+6f16/SX9
L/3Z/Lr9gf1r/vb9gf5V/iX+6f2B/Rj9Jf3Z/Mz8Z/yH/Dj8w/xk/Bj9sPzG/I38
KPzi+078H/x9/Ev8nfwb/Nz8wPw7/QX9S/0C/Vv9Bf2E/Wf9rf2X/eb9p/3T/Wf9
qv0Y/UH9oPx0/TX9iv75/cr+Qv6w/jX+sP1O/dP8l/wJ/Zf8Yf0J/Sj++f3//dz9
S/04/Yf9Uf22/VH90P2E/Qn+rf3g/YT9Nf3s/Oz81vzc/aT9Xv7j/ar+aP6B/m7+
K/4J/nT+Yf6a/p3+7P7A/qf+mv6K/n7+ZP5R/s3+l/6E/2H/mv90/xX/9v7D/oT+
e/4+/jv+8/2E/Z39zf22/WH9bv1B/R/9Gf7g/UX+SP7s/br9Iv3v/PL8wPyj/Jr8
1vx3/E79GP0v/sb9w/2k/Rj9Pv0S/bP8H/0l/VH9Ev3p/Kr8Cf3A/D793Pyg/Yf9
K/4P/rr9w/01/SX9/Pyz/MP8lPwY/ZD8HP7m/cb+gf4Z/un9SP3s/Jf8UfzJ/D78
+fyH/Bz9o/wC/bD8Iv3G/HT9+fyB/Sj9Tv0v/XT9Xv04/d/8Yf3c/An+0P2z/pT+
zf6R/lH+5v2w/W79rf1h/Vv+/P38/sr+bv84/7P+s/6O/lH+bv5F/pH+W/63/nH+
l/4v/tz9pP3v/Yf9h/5F/qf+ZP7j/VT9S/32/FH9xvwy/dz8uv1R/Wj+HP5x/iX+
vf2K/T79Av13/RX9h/01/Yf9Pv13/W79mv0y/XT9Qf35/af9Jf7c/dz9sP2N/br9
O/3j/A/9jfxU/ez8Ev6q/UX+zf01/nT9p/1x/S/98vzc/LD8Iv3c/B/96fwF/en8
SP0c/YT9Xv1+/TL9hP0o/Zf9L/1r/Uv9l/0M/Yr9Qf1k/Wf91v1I/VX+sP1C/vb9
H/7j/fn9yf2E/kL+Yf7//T7+9v1u/lj+Pv4C/sP9W/3c/Z39S/7s/QL+qv0P/uP9
ZP4Z/lj+L/5u/g/+S/4M/lH+Qv6E/hn+sP6k/vn+wP7Z/pf+aP6B/rP+kf6H/j7+
0P16/XT9WP3N/b397P2N/b39Yf0G/rP9DP7p/Z39W/2U/U79zf2X/ar9jf3D/aT9
7P3A/c39iv3T/af9Ev66/db9mv04/dz8mv1R/dD90/35/cD9fv50/uD+gf5u/nf+
D/7p/fn92f3//cD9//2X/Vj+D/5I/uD9gf78/Vv+Gf6B/iL+/P3J/dz9jf3s/aT9
HP7c/VH+D/5x/hL+K/7p/dD9fv2d/TX90P1r/ZT9Nf22/YH9yf1+/W79KP2N/Uv9
zf2N/XT+Iv41/r39L/78/UL+9v1e/tD9Mv7p/VX+Gf6t/jv+a/4l/oH+D/6O/i/+
mv7//Wv++f3v/bP96f2E/TL+0P1o/hn+7/3N/X79OP1+/R/9S/3Z/O/8nfxr/Sj9
pP1r/V79Cf1k/f/8Yf0S/eD9ev0v/u/9L/7g/fP9hP3A/a39vf2H/e/9fv0c/sP9
Iv62/Tj+Gf5x/hX+a/4r/pH+aP4V/tz9h/1L/dn9mv0c/ub9Gf4C/gb+/P29/Yr9
ev0+/Vj9wPxn/e/8SP0Y/Tv9+fyt/Tv94P2t/Tv+w/1u/lH+5v5+/kv+Av6E/Yf9
uv1+/QL+sP1+/kL+5v6a/uP+t/4+/iL+zf3T/eP9l/3W/bP9DP7//Sv+Iv4V/sn9
s/2E/a39l/2g/Vj9Qf3c/DL95vzW/MP89vy9/H79bv3W/YH9iv1L/Sj9DP3j/J38
8vzy/FH9Yf0y/iL+lP5L/hX+9v3z/Y39Av7D/Tv+0P1u/ij+S/4l/mv+HP5C/hz+
Nf7s/SX+5v38/bP9//3W/Qz+1v3Q/eP96f3g/VX+Iv4S/sn94P2k/VH+Jf5e/jL+
Iv7m/VH+4P1x/jj+hP5x/q3+qv7w/t3+5v7K/s3+2f4M/wn/aP/m/j//6f7D/k7+
Tv7m/dD9bv0i/uP9s/53/pr+dP5b/hn+Tv4+/s39/P3z/cn9Av4C/uD9wP2n/Yf9
9v32/UL+8/1e/jX+Qv4C/tz9mv3s/Zf92f3s/f/9D/7G/qT+Jf+9/s3+kf6H/kv+
Mv4c/ub93P3p/ZH9Mv75/Sj+0P01/hX+jv4c/hn+6f2k/Uv9rf1n/ZH9Qf2N/V79
0P10/ez9iv1+/X79xv1U/eD9W/0C/sP9Pv72/Vj+Ev44/gn+SP72/VH+H/41/iX+
hP5b/uz+yv7p/tD+dP5Y/pf+SP6E/nf+cf44/n7+Pv7m/of+5v6H/rr+bv6a/o7+
l/6B/k7+D/4i/tz9HP6z/R/+uv1C/uP9Nf7m/S/+H/4y/sD97P16/db95v3m/bD9
Iv7G/Wj+Uf50/gn+ZP4J/tb+l/4G/83+0/6k/nT+bv6z/oH+Cf+q/sr+e/5e/k7+
ZP4V/qD+aP53/lH+mv5o/m7+L/7p/b39tv1u/Zr9S/3G/YH93P2z/aT9cf1U/WH9
sP2U/SX+oP3Z/aD9+f3Z/cb98/2R/V79/P2w/U7+/P07/kL+Rf4M/qr+qv7G/nT+
gf5O/n7+cf6a/mj+Vf5I/mj+SP5+/k7+kf5I/pf+SP6R/mT+e/47/lX+Cf5o/gz+
K/7Q/eb94/3A/ar9w/1x/cD9iv3Q/ar9Av7p/fP97P0f/iL+Jf7//fb9xv0M/tD9
hP4r/pf+h/75/r3+4P6w/uP+xv6B/k7+O/78/Yf+gf63/n7+gf5L/sP+l/7A/of+
Tv4+/k7+Jf4l/iv+Av6k/Zf9S/3p/cn9Rf72/cn9zf35/fb9ZP5V/hn+7/3g/cD9
Av7p/Sj+vf0l/g/+bv5Y/s3+p/6d/o7+gf4+/j7+7/1F/iv+Mv4r/rD+WP6K/m7+
S/5R/jL+Cf5L/j7+pP5I/sb+l/6K/lX+O/4i/kj+/P1Y/lj+cf5L/kX+DP4+/g/+
K/4+/un96f3N/Y39/P3p/UL+7/0G/h/+4/38/Rn+wP3Q/dP9Bv7z/SL+//0Z/sP9
OP4f/pT+fv5V/hz+Av75/V7+Jf50/kv+Tv4V/iX+Gf5F/kX++f2w/XT9iv3z/eP9
Jf7s/Qz+zf0S/qT97P2w/dP9sP0v/un9a/4G/iv++f04/gL+s/5b/qf+e/5F/un9
dP4c/rf+Iv4l/uP9L/75/br+W/6B/lv+SP4Z/kj+Av4c/hX+HP7v/Uj+Gf5x/h/+
D/4C/hz+Gf4c/vP9D/7Z/Vv+4P2g/k7+fv5b/mj+Qv5x/lj+e/4o/m7+K/5O/h/+
nf4y/rf+kf6w/or+4P6t/rr+S/57/vP9S/5F/kX+L/4i/u/9Ev4M/pf+t/6n/mH+
Vf4f/iL+Jf4o/gn+qv2N/b39dP0P/tn9Ff7c/en91v0P/s39kf2q/Wv9bv3N/aD9
//3A/e/9p/0V/vb9nf4J/gz+4P0V/hL+jv5k/or+hP5k/g/+Jf4f/gL+6f0y/tz9
Jf7Z/Qz+uv3g/br9Bv6U/RX+tv3c/aD97P1h/eD94/2X/aD9lP1I/Tv9//yE/U79
sP16/fb9hP0J/tb95v26/ar9VP3A/Z39Ev7A/Tj+5v2H/ij+uv5x/rD+bv57/jL+
bv4P/lH+8/0J/rr9SP4i/lX+Gf5L/un9OP7m/fb90P2d/ZT9rf2k/bb9p/0M/sn9
6f3G/fP9iv01/vP91v3c/RX+nf38/c39zf2E/Qz+pP1F/vb9W/4G/u/90P0c/vP9
KP4o/kv+cf4+/jv+lP5R/nH+Qv4l/gL+7P3T/aT94/32/db9dP44/kv+//0M/un9
Iv7T/Qn+2f2q/Yr9l/1F/cD9L/3G/c393P3Q/Q/+5v3G/eP9w/2t/Wf9ZP3A/WH9
rf2a/Rz+3P17/h/+W/7//U7+Iv6a/jj+4P53/jX+Iv44/hX+cf4f/lv+DP6w/jj+
l/5e/of+Qv5V/h/+gf5F/pH+K/6k/iv+W/7//Tv++f0v/oT9O/66/Zr+ZP7G/lj+
d/47/iX+1v2B/hz+Mv4S/rf+Iv6O/kj+e/5o/s3+sP7g/r3+wP6w/qr+hP6O/kv+
SP4c/mv+6f1h/kL+lP5C/jL+D/7p/c39K/4Z/mj+9v07/vz9Bv7//SX+5v1k/g/+
a/4f/mH++f17/j7+lP53/lH+//1Y/tb9dP5O/pH+KP5x/lj+WP4M/nT+H/7G/nv+
kf5e/lj+WP6O/of+Yf5O/mv+Xv6E/pH+fv4v/ij+9v0P/vz9H/4G/gL+8/1V/iL+
KP41/vP99v3Q/cP9jf2R/cb9mv0V/vz9Xv75/T7+Cf78/dP92f3A/UX+DP5r/kL+
O/4l/j7+Ff6z/lH++f6E/lj/Ev90///+0/6E/r3+Pv5R/uP9Tv72/Yf+Ev6E/i/+
s/47/m7+/P0P/tP93P2U/ZT9l/3j/cn9rf2k/db9jf3v/a39Ev7//S/+Jf4M/jX+
//0Z/uD92f0J/sb9bv5u/hz/4P4v/8r+4P7D/qD+gf6U/oT+aP5R/rr+sP7//tP+
7P7T/sD+e/4v/hL+Nf7j/VH+L/57/kv+K/4f/jj+7/04/gb+Nf7W/eb9//3Z/Rn+
0/2z/XH9Tv04/Qn9fv1F/f/9wP0G/hX+L/7//f/9vf0J/qr9Gf69/Qb+0/23/jv+
HP+k/un+rf7z/qD+A/+3/iz/6f7Q/qf+l/5L/oT+Qv6B/nf+Nf4f/kj+7P17/iL+
Vf4Z/jj+4/29/Xr9+f2E/Qn+iv04/tP9Tv7//dz9yf0+/s39cf4i/m7+dP5O/h/+
fv44/j7+Nf4r/uz9S/4l/n7+aP7T/or+vf6K/p3+WP5F/vb9K/7m/VX+Iv5L/v/9
S/4S/jv+O/5x/ij+Jf7g/TL+5v0Z/qf92f2n/SX+mv0i/tb9Iv7m/f/9Cf4G/rP9
8/2z/fP98/3v/c39Qv5I/gz+0/1b/jj+oP6n/n7+Mv5C/jj+d/5e/nv+Rf5R/i/+
Qv4v/pr+Xv6k/nf+sP6B/vn+oP5+/kL+Rf7v/ar+Yf7K/pf+l/5h/qf+bv7G/nf+
ZP4f/jv+/P1+/o7+qv5V/kv+2f2z/lv+8/6t/r3+t/6q/or+3f50/n7+WP50/l7+
0P6n/gz/p/4c/8D+1v6K/pf+aP5k/kX+wP6E/s3+Tv6B/kj+uv5x/t3+sP6n/sr+
l/6R/nf+Bv4f/sb9lP1e/ar9Xv1C/u/9/P3J/TL+mv0v/vb9Ff4P/v/9vf3J/Zf9
w/26/eD9wP38/dz9Nf7m/cn9sP0P/rb9Gf4i/rb9zf2w/Zr9oP2B/af9a/1k/R/9
bv38/H79Pv2k/WT9Yf1U/dn9rf26/cn9W/0S/a39bv3c/dP9Bv7c/fP9yf1O/u/9
Yf7//RL++f0r/g/+W/7Z/Q/+0/1x/g/+d/44/vz+SP7//q3+p/6U/l7+cf4v/hn+
iv5C/mj+O/4f/un9/P3m/VH+DP6R/hX+Jf4V/mT+KP5V/mT+S/4f/uz9tv0o/rr9
Vf5R/l7+Uf6O/mH+wP6k/uD+hP6t/m7+Yf5F/mH+O/5x/nf+p/5R/l7+L/7D/rP+
Nf/j/jj+cf4v/hL+a/4c/nf+H/4G/ub9S/7j/TX+sP3J/Wf9rf1U/Z39iv2n/aD9
rf2R/c39p/2d/Z39gf1x/fn90P01/uD9ZP7Z/R/+K/5V/hL+d/5I/kv+Ff5+/ij+
ZP7J/R/+7/10/k7+SP5C/jv+3P10/jX+aP4+/i/+1v38/eb9iv41/mv+//0y/gn+
cf4r/lH+Bv4v/rP9/P2n/SX+Bv4i/tP9w/3G/Rn+4/3W/X79vf2R/Qz+1v0y/tb9
Pv7m/V7+Iv6B/kj+Mv7m/Qn+0/01/tb9Uf7m/RL++f07/jX+Nf4S/kL+Ff53/g/+
a/4l/gb+p/2q/Vj9iv1b/Yr9WP2a/Yf93P2g/en91v3D/c394/3c/eb97P2z/bb9
qv3Q/en93P3m/dn9DP7j/SX+Ff5L/u/9DP62/TX+7P0i/rb96f2k/fP9vf0V/uP9
//3W/Tj+4/0r/kv+Mv5L/pT+W/5V/jL+O/4V/v/94/1x/lX+hP5b/lX+Pv44/g/+
Nf5I/kv+Jf4f/hn+oP5o/qD+e/5Y/j7+Rf4Z/lj+Vf57/nH+Vf4o/nf+cf44/k7+
//3p/Qb+3P0v/vz9Jf4v/nT+H/7m/dD9oP26/dD9tv3J/Yr9/P3W/eD9l/3Q/bD9
Bv7v/cn91v3D/en9//3j/TX+Av7//SL+Gf4v/g/+8/0+/un9Bv7W/RL+wP32/dz9
+f0C/lX+Vf4y/g/++f3j/TX+//1L/ij+0/0C/vn90/1e/vz9Uf4i/gb+0P0i/u/9
Nf4V/tP92f3G/RL+Qv7p/S/+4/0y/gL+S/5L/uD94/0v/vb9Jf4r/iL+Ff4Z/rb9
+f3D/Wv+Mv5x/iL+WP5Y/nv+Iv5I/jj+Vf4r/jX+6f0c/tP9Mv7T/X7+e/5r/iX+
/P3m/RL+0P3z/cP9wP3G/cD9kf2t/ZT90P2a/Yf9Pv2K/Yf9nf16/Y39rf2N/Vj9
WP04/Xf9Iv2d/ZH9pP2d/dn9jf3Z/af9uv3v/Vv9nf1k/Wf9uv2z/c392f2H/aD9
w/2k/bP9qv07/WH9d/10/WT9d/1n/VT9l/1Y/YH9l/2g/Y39Nf1I/aD9dP29/ZT9
qv1b/U79KP07/ez8Rf04/Y39lP0v/sD9//3s/ez9iv3//dP9uv26/bD9ev07/rb9
bv4J/jL+6f3g/dz9OP4M/lj+Nf4l/gn+7P3G/br90P38/dz94P3D/br9wP3//e/9
gf2E/XH9W/16/WT9SP0M/Wf9bv1h/T79cf0c/VT9H/1x/Rz9dP13/Yr9Xv2t/V79
lP1I/W79a/3N/ar96f22/en93P3m/cn9sP2N/Y39iv3g/eP9Qv44/gL+xv26/Z39
2f3j/fn93P2n/VT9p/1e/bb9lP1e/UX9ZP1R/dz9vf3g/cD94/1+/ar9fv2a/ar9
zf3T/eP90P3c/cn93P3//SL+HP4S/vb98/32/Sj+DP6R/nT+jv5C/hz+sP01/g/+
hP5r/nf+S/5k/j7+Pv4i/gb+0/2n/aT9vf2U/UX+7P0C/v/9KP7Q/dz9kf2R/VT9
4P04/Sv+mv0o/rr9yf3A/db9lP3v/ar9Ff7//TL+tv3W/af9Av6q/dP9a/2k/Vj9
3P1k/aT9a/2z/Tj9WP0Y/Qz93/yE/SX9jf2R/Yf9Nf0o/db8S/0J/Tv9Ff38/L38
DP3W/Ej9Av0P/fb8Rf0c/Yf9iv3W/ZT9lP2K/XH9dP3g/WT9ZP01/YT9ZP3D/VT9
zf2d/eP9fv1V/hX+bv4J/uz9uv3G/af9yf2K/fz9p/0C/rb94/0C/vP9Av4S/u/9
0/22/Zr9d/16/X793P2X/eD9a/1n/V792f2R/V7+Mv78/eP9sP29/bb9vf2K/X79
nf13/f/90P0l/vP9wP2k/fz97/1F/mT+KP4v/h/+/P0f/v/9vf2k/ez96f3g/eb9
DP4M/uD9oP3s/a394P2w/YT9jf2a/WT9nf1k/af9Qf13/UX9tv2H/VT9HP1F/VT9
sP22/Z39qv1Y/fn8rf1+/R/+7P3Q/bb9xv2B/UL+/P0o/jv+a/5e/nv+Bv7//ez9
HP7T/Yf+Pv6H/k7+Uf4l/nH+Nf4J/tb9Nf4i/j7+Cf4+/h/+d/5V/kv+KP4Z/ij+
aP4y/jX+Gf5R/vn9Vf5V/m7+Ff4Z/vP9KP7j/fz9//3z/c39Iv78/SL++f01/vz9
H/4c/iv+Nf41/iL+WP4c/of+dP4y/ij+Gf7A/Uv+zf10/jX+a/4y/jX+7P2E/j7+
d/4f/tP9VP3c/Vv90P16/dn90/3A/aT9oP1x/c39cf0C/qf9w/1h/Zf9ZP3T/aD9
8/3A/Rn+4/35/dP9Vf7//WT+Cf57/jL+bv5Y/p3+l/6q/or+aP7z/S/+2f0Z/tD9
8/0S/vz9//1O/hn+SP7T/fz9wP1k/hL+ZP4r/gL+Bv5Y/tP9OP7//e/9w/0o/uP9
O/47/i/+D/4o/v/9jv53/pr+dP6O/lv+h/6R/oH+Rf5C/gb+//3s/Wv+Mv5+/v/9
HP78/W7+Nf50/mv+HP4V/s39sP3j/fb9DP6z/R/+pP0f/tD9DP7Q/fz9yf32/eP9
uv10/V79Tv2t/W79/P3A/fz9yf3c/cn9K/7T/TL+K/4M/uD9Iv62/SX+Cf7T/bb9
7/3T/Vv+Iv5h/lj+H/4S/uz9vf2w/Yr9qv1h/cb9jf0c/ub9+f3N/SL+xv0i/gz+
+f22/fP9w/0r/jv+5v3g/cP9nf0S/sn9Nf66/Tv+Bv6z/mj+5v6X/qT+Yf63/nf+
1v6k/rP+d/6t/lH+pP6E/tb+e/5L/lH+a/5r/pH+Xv4r/kL+K/78/TX+1v07/v/9
O/7N/RX+3P0o/hX+Ff4V/gz+4P0P/g/+Av7z/fn9vf0l/gL+H/7g/Rn+9v2O/jv+
bv7//UL+8/1I/u/9Xv4f/mj+Rf5r/kj+oP6B/j7+8/07/ub9W/4C/j7+H/4l/rb9
OP7z/R/+2f1b/tD9DP7j/Vj+Bv4S/s39xv2N/db9kf2H/XT9hP1I/Zf9dP2N/af9
3P2t/aT9cf2q/ZT93P3A/en9dP0Z/tD9Vf7N/T7+//1k/vn9S/4C/g/+w/01/un9
e/5C/o7+Uf6t/kX+d/5h/lv+Cf6O/ij+d/5I/l7+Ff4Z/tn9K/5I/jj+5v07/vz9
HP4V/pf+ZP6B/lj+Iv7G/Qn+h/0l/uP9aP4f/kv++f2B/vz9p/5C/q3+Nf7A/mv+
0/5u/sD+nf6w/m7+t/5V/nT+Ff5+/mj+9v53/ub+pP6O/kL+nf47/kX+OP5b/gz+
Yf41/g/+w/0P/rb9D/7c/bb9Z/0C/m790P3W/en9vf0C/tn9mv2n/en9uv01/gn+
Cf7z/TX+xv3//a391v2K/a39W/3v/Xr9Nf7Q/QL+sP1k/uz9Jf7G/Vv9VP2w/Wf9
kf1B/XT9Rf16/XH95v2a/Qb+p/0C/pH99v3G/cP9uv3D/Yr9wP2N/eP9sP3g/bP9
OP78/SL+vf01/tP97/2n/fn9qv0+/ub9//3s/f/9oP3j/cn96f3Z/S/+8/3//fP9
S/7z/WT+//2K/j7+mv6g/rr+ZP69/or+pP57/o7+Uf5h/h/+e/5k/k7+Pv5L/ij+
4P6R/sr+kf6z/nf+bv4r/o7+DP53/kX+Rf5R/pT+bv6t/oH+uv6O/tn+pP7g/qD+
mv6z/lX+Iv5+/jj+dP5Y/nT+Cf5R/g/+cf4f/nf+Bv4+/hX+Cf7D/fz9pP3p/aT9
KP4J/vP90/3c/db9Cf7p/db9nf3N/b391v2a/b39ev3T/V79vf2z/UX+//17/jL+
Yf5h/kj+K/7G/cP90P2a/Uv+1v13/jj+ZP5O/l7+D/6R/iv+SP7j/db9qv0y/hz+
9v3J/eb90P3T/aD91v2k/e/9zf0+/iv+KP7//fP9xv3//en94/3g/fb99v3//Zf9
//0G/gb+Bv5+/k7+l/5R/uz+l/7d/pT+vf5r/qT+W/6R/nf+p/5u/un+kf7G/nT+
uv6R/s3+pP7m/nT+Uf5I/jL+4P0i/uP9Av7J/fz95v07/un9Vf7//fz95v2t/aD9
wP3N/a39fv2z/br9K/4M/lj+//1V/sb9jv72/VH+2f32/bb9Ev7m/RL+Bv4+/iX+
S/75/Tv+Cf5o/ij+ZP4J/kv+Jf44/vn9DP7N/eP9zf32/c39//2z/T7+Av5O/hn+
/P2t/Qz++f0v/gn+HP7Q/Tv+Cf4+/v/9Uf4J/l7+Iv6d/mv+qv6E/rP+Uf63/sr+
p/6k/qD+jv6R/kX+yv6n/uz+qv6R/m7+gf5x/uP+h/6a/l7+l/44/nf+O/6E/jL+
H/7z/WH+yf1R/h/+L/5C/jL+//0P/gb+Rf7J/Rz+2f17/jj+Iv4J/gn+zf0c/jj+
a/4v/tD9//0M/gn+kf5o/nH+Rf4i/hz+a/5o/nH+Qv5k/kX+cf5R/mH+Xv4l/qT9
O/6t/Tj++f0G/sn94/3W/UX+6f1L/hz+8/3W/Uv+DP4+/tn9Jf62/fz90P1k/uP9
e/4G/pr+Mv6k/k7+e/44/mj+Mv5Y/iX+O/4G/kL++f2B/jv+1v5I/sP+kf7D/pT+
6f6K/qf+oP6H/i/+bv4c/qT+Pv7K/lj+0/5u/p3+jv5k/kj+xv5O/tb+l/6O/k7+
bv5R/qf+kf72/t3+sP6n/uP+yv4M/7D+1v6R/rD+Uf7W/qT+0/6n/sD+t/7N/pr+
5v6d/mj+aP5e/lH+h/5R/pH+Xv5u/kL+a/5u/mH+e/4+/jv+Jf7//Rn+DP4S/uz9
nf04/cD9qv32/ZT9d/2z/bP9kf22/Xf9lP10/c39jf3Q/bD9mv16/c39sP0P/uP9
Uf4P/l7+/P1C/gb+Nf72/QL+5v3//f/9Uf4C/o7+W/5I/h/+Yf4y/lX+HP5C/v/9
WP4r/h/+Ff4V/tn9Nf4P/jL+Gf4+/gn+Tv44/n7+W/4l/iL+Ff7//VH+aP6z/mH+
nf5V/pT+fv7m/qT+xv6t/h//4P4o/zL///4J/wn/4/4v/8r+LP8c/xX/A/8l/wn/
Rf/Z/g//vf6z/nT+8/6K/sP+zf7T/pf+l/5e/qf+qv5u/vz9Jf7s/SL+Av4i/tb9
Jf4M/hX+K/4M/tn9L/6N/QL+3P0i/v/9Ff7//Tj+H/41/s39Ff7A/Uj+9v2O/i/+
uv5o/oT+DP6B/jX+iv41/nf+//07/kL+Tv4+/vn90/2w/XT9Mv4C/h/+4/0S/vP9
aP5o/oT+WP5u/gL+WP4C/n7+Nf4G/tn9KP7D/WH+Gf5F/lj+dP4S/rf+kf6X/pT+
e/4o/kj+K/5k/kL+Qv4l/kL+Tv5O/lj+e/57/rf+h/5+/n7+Xv4l/jL+KP50/qD+
1v6H/mH+d/6a/of+xv6q/sr+t/6n/l7+wP5e/qf+s/66/nv+jv6X/qr+l/6d/pT+
mv6O/kj+O/5b/lX+Xv5F/l7+Yf6q/nT+2f6k/r3+gf4f/9b+uv5k/oT+W/5r/lX+
Vf7//ar+S/6E/pH+xv53/r3+hP7G/or+qv57/iv+6f0J/uP9Uf75/Uj+L/4v/uz9
Xv5F/n7+ZP5r/k7+jv6O/sr+gf6O/jL+uv5V/un+yv4Z/+P+//69/ub+iv78/tD+
A/8f///+Ff9O/w//Ev/d/vP+l/7g/pf+yv6U/o7+ZP6d/pH+e/6H/qr+e/6g/mv+
pP5I/pH+S/5O/vn9SP4S/lX+Jf5L/vb9hP5e/qf+h/6O/nT+hP5Y/of+mv53/nv+
uv6d/rP+nf6t/pT+8P6t/tn+t/7Z/rD+0/6O/rP+lP7W/rr+kf4r/qD+Yf7G/sb+
rf6B/l7+K/6B/lj+SP44/iv+DP5L/gn+bv53/sD+jv7j/lj+w/6E/vn+zf7g/tn+
wP7A/g//vf4P/+b+LP8Z/3v/KP9r/xL/cf9F/37/Mv9Y/+D+//7p/ij/8/4D/wn/
L/8v/2H/Tv9V/y//Gf+6/qf+e/6O/sb+qv66/rr+qv4P/+D+S//j/gb/8/4v/3H/
KP8f/6f+8/69/s3+a/8y/x//Iv84/xz/eP+K/3v/hP8c/xn/5v7//hL/Qv8G/1X/
5v4Z///+/P63/n7+gf6R/pf+sP7s/qr+Ev+6/pr+kf47/lH+Tv44/jL+S/4+/gb+
9v3z/Q/+zf0l/u/9gf4P/lj+Qv6E/kv+Uf4r/hn+8/2H/jv+mv6X/sr+qv7Q/qD+
4P6d/hz/5v4v/93+Gf/2/ub+2f7g/tb+8/6n/tD+hP6d/kj+5v6K/tP+4P6O/q3+
lP6E/tP+t/6w/rD+dP5e/nf+gf6n/or+8P6a/tP+oP41/93+DP+U/gP/w/4c/+b+
yv7G/sb+w/7Z/tb+D////mj/Tv/g/un+//7p/g//3f7T/s3+Ev/d/un+8P6t/sb+
wP6H/qf+qv5C/iL+d/4l/mv+Xv5b/lj+Xv5L/pH+Pv6U/pH+bv57/p3+dP5h/j7+
HP5C/ij+L/6g/l7+d/5L/nv+a/6O/qD+e/4+/j7+4P04/gn+Uf5L/kL+Mv4o/jv+
SP5o/jv+OP7c/fb9Mv41/sb+p/6a/qT+nf50/qf+pP5r/mj+iv5e/tD+h/6z/nf+
pP5e/rr+l/4P/9n+Qv8D/0j/KP8i/+P+6f6k/r3+iv7d/rf+LP8D/0L/A/8P/yz/
//4l///+Cf///uP+8P69/s3+kf5e/pT+lP6q/sD+4/6w/rf+sP63/sb+2f72/rD+
0/6R/rf+lP7K/qf+0/7G/hX/zf4c/93+yv7D/gz/5v78/tb+t/6g/rr+lP66/pf+
6f6k/qf+e/7D/nT+uv6a/pH+a/6R/j7+iv57/lj+DP53/iv+Xv47/hz+K/4+/gn+
SP44/jv+Vf5F/lv+Nf5V/kj+H/5O/k7+OP4V/lv+Jf5u/kX+W/5u/uP+kf6z/nH+
d/5r/sP+oP6B/nH+ZP50/pf+jv4P/w//L//d/vP+qv7//hX/OP8f/xX/DP8P/wb/
A////v/+7P4V/9b+8P4D//P+5v5h/0X/Cf9I/7P+0/7s/sP+Rf9I/yX/2f4V/yX/
iv+H/07/O/8y/xL/8/75/lj///5I/yj/LP///gP/Cf8V/zX/9v7G/rf+l/50/qD+
cf4+/qT+jv6E/of+cf5b/pH+Yf57/kv+a/4y/mT+2f0l/kL+O/5k/mT+Mv4C/ub9
1v35/Sj+Nf4o/gz+Gf78/Q/+Bv7//fz9/P3Q/Rz+Av5b/jX+Vf5R/pH+Xv63/mH+
qv6E/lX+Vf6X/lX+SP4v/iv+Nf66/n7+Rf4f/lH+e/6k/qr+Vf72/Yf+L/6E/nT+
d/5r/oT+Pv7D/sD++f7D/pf+t/6H/o7+D//j/vD+2f75/v/+5v7p/gP/yv7Z/rP+
Cf/m/hL/P/9C/1L/8P4P/yX/9v72/hX/s/6K/un++f6k/t3+cf6E/qf+p/6O/p3+
e/53/mj+ZP6H/jv+cf5+/h/+Cf4y/sP9Mv4S/jX+Pv4+/jX+W/4v/lX+WP4P/gb+
S/7W/Tj+DP50/lj+dP5O/j7+L/4f/v/9Cf4C/mv+a/5+/jv+bv5C/k7+Ff5R/gn+
Nf5F/n7+SP4f/ij+O/7m/fz9+f0P/iX+bv47/kX+iv6X/pf+KP4S/gz+7/1C/iL+
SP4C/lX+Xv6g/rf+WP/5/vP+4/6a/qT+0/6n/tP+qv6d/or+vf6K/i//Ev8y/yX/
Qv9C/yz/5v6a/s3+uv7W/sP+nf5u/oH+yv5r/iz/wP4J/7P+sP6E/pH+O/5x/i/+
SP4V/oT+Uf53/lv+h/6U/nH+l/7j/rr+yv7A/nT+Yf6R/m7+zf7K/vz+w/7s/qr+
KP8//07/+f78/sP+uv7W/vz+8P7W/tb+3f63/tD+3f63/tb+zf6g/iL/zf4D/9D+
fv5O/lj+Uf5I/vz9HP7m/Wj+OP6k/kL+WP5O/iX+H/5Y/lv+WP44/pr+iv6g/mv+
h/5O/r3+jv7N/n7+zf6a/gz/p/7G/sb+qv5+/tb+h/6a/nv+s/6t/qr+l/66/qT+
l/5o/k7+dP53/i/+HP4J/gz+9v1F/hL+Rf4Z/pH+Tv4+/gL+Rf4f/nf+Bv5L/hn+
Iv4Z/kj+K/6B/n7+Pv47/nH+Ev5C/lX+iv6B/j7+7/0S/gL+W/5o/or+WP6U/n7+
fv5F/lv+L/4v/jv+KP4i/kv+Cf7Z/SX+ZP44/nv+ZP4i/jv+aP5o/l7+Xv5r/hn+
SP7z/U7+Av4y/vP97P29/Qn+wP1u/j7+gf5C/mv+H/5F/iL+S/4G/mH+K/5O/hz+
K/7j/S/+8/1C/jL+fv5k/mj+KP5R/ij+a/41/gz+Ev7c/eb9H/4J/j7+H/5e/lX+
nf6B/jL+Jf4J/sD9D/4J/uz9Cf4l/vb9Uf4r/nH+Tv6K/mT+Vf5o/pT+W/6a/nv+
hP5I/mH+/P2O/lX+fv4y/o7+KP6O/n7+oP53/or+aP6k/m7+fv4v/jj+Gf50/lv+
oP5k/qT+gf6B/jj+a/5F/iL+H/5L/ub9Xv5V/lH+D/4J/vz9H/7s/VH+Mv4y/hL+
W/4c/o7+Xv57/kL+Qv4J/of+Mv7g/p3+mv50/pT+Rf5b/mj+yv66/ub+Xv6K/jv+
pP5h/nH+SP4+/hn+Xv5V/rr+gf6d/mv+kf5b/qD+K/41/h/+aP5I/kL+H/4l/gn+
jv4i/qf+e/5+/jv+oP5R/mv+Iv5x/hn+Rf4y/mj+Tv5b/iv+d/5F/o7+cf7Z/p3+
gf5h/lv+HP4o/g/+7P2w/fz9KP5F/ij+S/7//XT+Rf5V/oH+WP5R/tD9tv3W/Zr9
+f3J/en91v0S/uP9Nf4r/j7+Bv7v/Qb+KP4C/jX+5v1Y/hL+Rf7//X7+K/6w/lX+
qv5r/kj+d/6E/hz+Nf4i/jv+K/4c/tb9S/4G/lX+L/5I/jv+Pv72/fP9zf0G/sn9
2f3v/eP9sP0V/gn+6f3s/cP94P04/vn9Vf4l/kL+HP5h/jj+SP4S/lj+6f07/jj+
OP44/lX+K/6B/kj+hP6K/oT+O/6t/of+nf6k/rf+p/6k/pr+Yf6B/nH+a/69/s3+
iv53/lH+Uf5I/mT+a/6K/k7+W/5r/pf+W/5I/jv+Av4v/g/+yf3T/cb97/0f/iL+
L/4i/hL+0P1C/vz9d/4i/kX+Rf5L/hL+S/75/Sv+Mv4y/iX+h/5o/qf+Yf5F/mj+
Mv4o/tn96f2t/eD9rf2R/dz9rf3m/br92f3Z/Tv+Ff4S/rb9xv2n/VH9Xv1F/SL9
jf1I/cP9mv1e/hL+aP47/hX+Gf7N/cD9vf16/a39jf22/Xr9Gf7//RX+7/01/vP9
Uf5b/or+Tv7D/bD9pP1x/eD9pP3g/a39Ev72/Vj+SP6O/lj+bv47/jX+Mv4P/tn9
Jf78/Sv+Vf5h/nf+WP4+/mH+KP6B/nH+fv4+/gz+D/5r/lj+mv5+/p3+a/6g/nT+
8/6H/vP+wP7s/t3+Mv8G/2X/Ff8M/8b++f6d/uP+4/7A/m7+Iv+k/m7//P5V///+
8P6z/tn+jv7N/oT+mv47/of+KP4y/h/+Xv5r/qf+cf5k/kX+oP5x/k7+S/5k/k7+
Vf5C/jX+Gf7T/v/+s/7j/pr+mv5x/lv+O/4i/gb+//3c/aT9Tv5I/kX+OP4c/gn+
Ff7Z/bD9l/1r/UX9h/1I/a39tv3A/br9uv2U/U7+Bv47/j7++f3//fz96f0v/kv+
Rf7z/UL+Gf5h/pf+s/6R/of+lP7K/tb+t/6R/nf+dP6E/kL+O/5e/iX+K/5O/kj+
lP5+/pf+cf63/qf+0P7Q/of+lP4Z/ij+W/5h/qD+Uf6H/qD+7P7g/jL/KP8P/wP/
8P7Q/tD+yv63/oT+ZP6a/l7+gf7D/qD+sP6a/qT+sP5e/rr+gf50/ij+7P3T/ez9
K/47/l7+WP7N/qT+fv6k/hL+Cf4f/kX+O/5u/i/+O/7v/dn9w/3T/Z390/3g/dn9
6f0C/tb92f16/b39hP1x/Yf9dP1x/Vj9l/2E/cn9wP3D/dP9w/29/db9yf2n/cP9
qv2z/a39pP3D/eD92f3Z/dD97P1V/kX+8/3z/dn9/P0r/kX+8/0P/gL+2f0i/uz9
KP4M/jX+W/4o/jj+Ev78/SL+L/7z/RX+Gf7z/UX+Nf41/jX+Iv4c/m7+KP4l/ij+
e/4o/mv+Vf4P/iL+D/47/oT+W/6H/tn+dP6k/or+WP5b/jj+Ev5R/un9HP44/k7+
d/57/nH+Yf6O/qD+l/6n/mj+Yf5h/kL+SP5o/v/9D/4i/hL+3P3N/Sj+1v1V/jX+
Xv50/ij+9v3m/cD9KP4M/gn+5v0v/tP9H/4G/gn+DP5F/jX+D/7j/Wj+Vf5V/k7+
HP4C/vP9//07/vP9KP4V/gb+Cf5O/iX+WP4Z/mv+SP4y/kv+O/44/of+OP5F/j7+
Xv5x/nf+Uf5k/lH+aP5+/lX+SP5b/i/+WP4P/jX+Iv6U/j7+kf53/o7+cf6a/pT+
a/5e/oH+Yf6U/p3+nf5u/tP+w/44//b+4P7N/kv//P4S/9D+qv7N/qT+nf6B/nT+
yv63/uP+0/7A/rr+qv7z/vb+6f7N/uD+wP7T/pH+w/7Z/rP+4P6k/pH+0P7G/vz+
4/4l/83+9v7D/tD+w/69/sr+rf5k/nT+dP6B/tP+1v72/rP+lP50/pT+d/6w/nv+
a/5O/qr+dP6t/n7+aP5x/n7+bv5b/j7+aP4M/nv+SP50/oT+jv5R/kj+L/5L/hX+
Xv57/pf+p/63/p3+w/6n/o7+mv6K/lH+cf5R/qr+t/72/qD+7P7w/g//2f7s/qf+
wP7d/vn+mv7z/qT+pP6X/rP+dP6k/oH+t/6X/t3+8P7A/sb+qv6U/sD+zf7D/r3+
rf6H/or+oP6q/s3+vf7s/oT+qv6z/rD+9v7W/t3+yv7K/r3+HP/D/gz/7P6n/nv+
p/5r/oT+jv5u/kv+cf5F/nH+Vf6H/nf+h/5u/nv+Rf5+/jL+KP44/j7+L/41/hz+
SP41/lX+Tv6R/mj+hP6H/k7+S/53/ij+s/5k/o7+Mv5+/s39O/7//TL+6f0r/hL+
a/5C/mv+bv6a/oT+hP5R/kX+WP50/j7+S/5C/lH+Ev6w/jv+d/5k/tP+dP69/nf+
4P5k/nT+Iv5L/iv+Tv4l/lH+Qv57/hz+lP5r/rD+d/6U/or+W/47/lj+WP6X/of+
Cf7z/Uv+Ff69/o7+zf6q/gn/0P7s/qr+4P6U/p3+bv5h/kX+W/5C/oH+iv63/pT+
sP5e/pH+oP6O/mT+d/5r/qD+Xv6B/kX+d/4l/pT+Mv6g/qD+wP57/hX/oP7A/pH+
ZP5o/nf+Pv5V/jj+Tv53/of+Gf5+/oH+Pv4S/mH+Nf53/hn+Iv7//dP96f3z/fb9
Bv78/R/+/P0v/vb9cf5O/lH+Iv53/mv+kf6H/of+Xv6B/pH+8/6t/vz+3f6R/mT+
rf6E/pH+aP6n/oT+OP4y/or+Pv72/qf+w/6t/rP+wP7w/uD+uv6O/tb+iv4D/+D+
8P7D/r3+wP7w/pH+Ev+n/gP/jv4V/7f+/P6a/tD+w/7D/pf++f6t/tP+5v7Q/qr+
0P66/r3+wP63/rP+oP6O/rf+ZP6O/n7+WP4o/j7+Ev4y/vb9h/4r/qf+Xv5o/ij+
Vf5F/iL+Rf5k/vn98/26/Tj+Jf5Y/mj+l/5V/qr+OP6d/o7+h/6O/or+e/7T/pr+
mv5R/rD+Vf6B/mv+lP6O/o7+Xv5Y/kj+W/50/mT+ZP5b/kj+dP5L/m7+W/5u/lv+
bv53/q3+zf7p/pT+0P6t/iX/6f41/9n+/P4G/yL/Ev8Z//b+Iv8D/w//1v4c/xz/
Nf8D/yX/9v75/hX/0/7j/sD+w/7W/qT+8/6d/qf+pP7G/nH+w/6w/iX///7Z/tP+
wP7G/tb+l/6k/of+t/6B/s3+lP6a/pH+nf6w/pr+bv6O/kv+bv4r/mj+Bv6q/kL+
xv57/rP+a/4G/8D+wP6X/pH+SP6U/ij+dP5F/tb+ZP72/o7+8/7D/uP+3f63/qr+
wP6a/rD+h/63/nv+l/6t/tP+sP7K/pf+6f7D/qD+zf6B/k7+hP5u/o7+WP7p/rr+
/P78/kj/8P41/7r+/P7d/vz+0/63/oH+2f6g/vb+rf47/93+5v6n/iX/8P4f//b+
0/6K/q3+h/6g/mv+pP5x/n7+jv7A/s3+4/6z/gz/qv7N/nv+t/5O/or+jv6k/mH+
bv5h/qD+bv6k/k7+qv5x/uz+pP6w/qr+Iv5L/gn+Av7v/fn94P2t/e/98/0M/vn9
Rf7m/Vj+WP6O/q3+Xv4+/mj+HP5I/l7+Tv75/WH+OP6H/kL+jv5C/nH+H/5V/kL+
Iv4+/hn+6f35/af97/38/Uv+H/5I/kj+KP7z/fb94/0Z/un9KP5Y/oH+uv63/qf+
Cf84///+4P6E/or+Tv5O/nT+h/4v/n7+S/5O/t3+8P66/r3+xv63/rP+xv6X/rD+
1v7N/rP+d/6g/pr+3f6R/pr+pP7T/qD++f7N/vD+3f7j/vD+Cf/d/t3+iv6n/mH+
6f66/s3+oP6U/lj+sP6a/sP+1v7m/sb+HP+w/vP+Iv/w/uP+mv5Y/r3+rf7W/nv+
0/7G/sD+0/4D/83+1v63/tD+mv7G/sb+s/6B/oH+e/6U/n7+jv5k/mj+aP53/mT+
xv63/p3+jv5L/kL+d/5C/n7+S/7G/sr+w/7A/sb+w/6g/o7+ZP5h/nT+cf66/pH+
mv6t/qf+mv6t/pT+qv57/i//2f7w/q3+4/69/vz+8/7z/tD+zf6z/gb/Ff8V/yL/
Nf/5/gP/yv4Z/wb/OP8//2v/W/+q/0X/e/90/37/Jf+O/w//iv9o/6r/lP9+/4H/
fv+X/5H/fv+q/2H/p/84/1v/OP8//zX/Ev8o/z//A//W/vD+OP/Q/jL/9v7w/vP+
5v6U/t3+p/6z/q3+iv6O/r3+iv7K/sb+5v7K/gb/0P7m/pf+8P7T/sr+jv78/sD+
0P6U/sb+rf6q/s3+LP8S/0j/Iv8P//P+vf7D/rP+S/5h/lj+h/47/or+a/7A/mH+
a/5e/lj+OP7m/fP9Iv7T/S/+KP7z/en9H/7W/VH+KP6R/lj+L/4M/m7+HP6B/or+
hP6O/or+dP7T/r3+A//Z/uP+nf7T/rD+6f7W/hX/2f7G/tP+zf4J/wP/2f4V//D+
6f7W/vP+nf4D/7P+wP6t/vz+yv4M/wn/4P7d/un+0/7K/rr+h/6R/g//oP4f/xn/
5v7z/vz+wP7s/s3+t/6X/s3+3f7A/tb+s/7D/vn+9v7p/uD+4/7//sr+7P7Z/tb+
vf7d/gP/2f7Z/tb+8/7s/vD+Bv/Q/vD+p/6a/qT+ZP6E/pH+nf6R/kj+aP6O/oH+
sP4J/6r+uv6B/o7+Nf5+/lv+Uf4v/oH+Vf5Y/p3+rf6n/un+0P6H/sr+t/6O/p3+
kf6K/of+t/7d/rf+5v7d/qf+zf7K/sP+2f66/kX+ZP6E/mj+pP6U/lj+h/6g/lj+
hP5+/pT+e/50/mj+cf53/mH+Vf5r/pr+rf7d/uD+zf7W/vb+yv7g/nT+fv6R/l7+
hP6a/uD+uv4v/wz/Ev///jL/L/9F/0v/LP/p/vn+3f4f/yL/1v7D/uD+8/4P/wb/
KP8G//b+Bv8c/+n+DP/j/gb/+f7A/sb+xv6q/qT+oP5R/nH+yv6w/hn/Cf8l/wP/
8/7z/gb/qv6R/r3+iv50/s3+0P6a/vn+5v4s//D+Ff8D/yj/L/8s/9P+vf4M/93+
hP6O/q3+l/4G/9b+6f7s/gP/Cf///vz+4P7D/n7+qv50/rr+rf66/rD+t/6X/p3+
rf6w/pT+p/7Q/n7+0P6g/tn+qv6d/mT+sP7A/qD+w/7K/vn+Bv/s/sr+s/7D/tn+
uv53/pr+mv6d/nT+xv66/sD+fv6w/qr+bv50/nv+O/7K/pH+cf6K/rf+l/63/rr+
0P7W/q3+t/6z/pH+2f7z/t3+sP6H/or+l/7s/uD+wP75/qf+Cf/W/lL/L/8i/wz/
L/8G/x//H/8G/9n+L//8/vz+D//z/vD+vf66/uz+rf7m/tn+//7Z/t3+s/7N/uP+
lP63/or+d/6O/rr+oP6n/m7+bv50/pf+hP5k/nT+kf6k/o7+xv6X/pf+cf5x/oH+
bv5R/oT+Uf6K/lv+wP6X/tb+mv63/sb+4/7d/uz+A/8D/7D+rf5+/rD+xv6n/sD+
kf5+/t3+t/6q/pr+aP5x/l7+d/5O/n7+W/6U/kX+Iv47/jj+e/5h/mj+a/6w/pr+
qv7A/qf+oP6t/pT+lP6U/mH+hP5o/nT+mv6t/pT+nf6E/or+0P4M/0v/Mv8i//D+
uv6z/sD+0P7Z/tb+7P4c/wz/2f4V/0v/HP8Z//P+Jf/2/vb+4/7s/iL/DP8D/9b+
wP6n/qD+Xv7j/s3+yv7Z/gb/A//p/sP+1v69/sb+oP63/vD+2f4i//z+D//j/sr+
8P4P/83+Ev8l/yj/O/9C//P+LP/Q/qr+sP6X/pr+pP6H/nv+nf6O/tn+0P6a/p3+
vf6X/pf+oP6q/oT+iv44/k7+W/6R/kL+WP4r/nH+aP5F/kL+kf5V/r3+iv6B/p3+
xv6O/qT+fv6H/oH+zf6n/rf+uv4i/7r+P/8J/w//Iv8c/wz/Jf8J/xL/6f7j/un+
wP6z/s3+rf7j/qf+8/7Q/lL/Jf8f//D+mv5+/q3+e/6k/pT+sP6R/s3+wP4M/xL/
Ff8M//z+Cf8V/yj/LP8f/wb/L/8v/yX/Uv9r/yz/Qv8y/2v/Nf9o/1v/hP9Y/4H/
Yf9h/yj/Uv/Z/un+HP8Z/1j/a//5/vz+6f78/gz/Mv/j/iz/+f4V/xn/L//8/vD+
8P4J/8r+LP/d/iX/7P4J/wn/P/8P/xX/4/4S/8P+Bv8M/wn/3f72/un+Ev8v/2H/
+f4M/zv/Nf/Z/hX/6f7z/vD+w/7W/sP+l/6k/nT+bv5r/rP+yv7g/tP+zf6X/oH+
lP6n/qf+d/4+/nv+hP5L/rr+pP7T/tD+zf66/g//D//w/gb/sP6d/of+jv7Q/sb+
2f7g/hL/Ff8Z//D+Gf8l/+D+/P6w/rP+DP/m/pf+rf7p/tb+Cf8M//P+yv7p/gn/
Ff8c/wz/DP90/o7+p/53/gn/w/4S/7P+O//j/vz+rf72/sD+Iv/2/jj/Ev/p/vP+
Bv/m/sb+9v4G/xL/3f7Z/hn//P5L/17/H//8/vP+Cf8f/xn/Cf/w/un+6f7j/tD+
pP6O/i//4/4G/+P+7P7N/nH+d/6K/oT+Xv5u/kj+Ff44/jL+Nf5b/lX+Cf5L/kj+
L/4c/kv+e/4r/hL+zf3T/db9w/32/e/9iv4Z/lH+Uf6q/nv+e/4P/mv+Mv5o/jj+
Yf5O/lX+lP57/m7+0P6a/qf+jv7N/m7+xv6U/qr+gf50/nf+lP6U/sP+jv6t/q3+
t/6g/rD+t/7g/tP+w/7D/uP+D/9Y/xn/vf7N/sP+7P7D/rr+p/6n/tD+p/4D/47+
rf6n/gz/oP7g/qD+w/6g/rP+jv7A/qT+zf6B/sP+l/7A/q3+uv6X/n7+fv6w/p3+
uv5x/nv+jv5b/k7+Uf5e/of+jv6a/mj+jv6X/oT+Yf4c/jv+Xv41/lv+7P0v/iL+
SP47/n7+jv6t/pH+WP5+/nH+Qv6a/mv+l/5I/rf+h/69/p3+qv6k/p3+h/7K/o7+
0P6U/sr+iv53/mv+mv6w/qf+h/7K/sD+A//W/un+iv63/p3+l/6w/q3+rf6E/nH+
nf6g/gz/Gf8Z/zL/+f5C/yX/Gf8J/yX/dP9O/3H/Rf8s//b+Mv9L/3H/Jf+n/1v/
kf+O/4H/e/9L/xz/uv7A/pT+wP6q/nH+sP7W/tP+A/81/yL///4D/8r+wP63/or+
wP6H/rr+dP6a/j7+0/6n/sP+rf6t/qD+rf6a/tn+DP+6/t3+s/69/rD+oP6k/s3+
yv7z/r3+Gf/Z/rD+pP6t/sD+2f7W/tb+jv4l/83+Jf/W/gn/4P6t/q3+w/7m/vb+
9v7Q/t3+sP7z/tD+D//s/i//DP9V/wn/OP9I/z//Gf8s/xn/9v7Z/ij/4P4D/8r+
LP8i/4H/Uv97/1v/aP9+/17/e/+E/5T/Zf9I/0L/Vf8o/9n+Qv8Z/yz/qv5O//z+
Ev8V/zj/A/8G//n+0P7g/sr+wP7K/r3++f7g/gP/LP8l//z+D//m/tb+9v7G/tD+
6f6K/vz+0P7K/vD+6f66/sr+t/7Q/qf+yv6n/rf+nf5Y/l7+Mv4i/mv+Nf5x/or+
Pv5L/iX+DP5k/mj+hP53/sD+lP57/nf+ZP53/nv+Qv53/ij+Iv47/ij+WP6R/q3+
lP5u/jX+S/5Y/mH+dP5x/mH+WP5Y/m7+cf5h/nv+a/5R/k7+O/5F/nv+Uf5e/k7+
dP5F/or+p/6a/of+pP6H/l7+fv50/qD+iv6U/s3+1v7d/pr+6f7W/tD+DP/K/sb+
yv6k/r3+nf7N/sP+xv7Z/sD+0P7N/qT+yv69/pH+fv6B/nf+l/6K/o7+dP6K/sP+
6f6t/iz/5v5b/0X/Rf9C/93+2f6t/t3+/P7T/vn+DP8y/xz/Bv8D/93+wP7d/uD+
sP6d/r3+nf7d/sD+8/7p/jL/P//W/vP+4P7d/jL/6f7K/uz+7P6w/hn/D/8D/1v/
4P4i/yz/S/9b/3j/Nf9F/+b+//7Z/vz+2f4M/73+xv7z/s3+Iv8o/1L/Iv9L/xX/
Nf8V//P+mv6z/nv++f78/s3+nf78/t3+Gf8S/1j/Qv8G/0j/e/9b/2H/gf/d/vz+
vf78/oT/Xv8v/07/5v4l/2X/O/+k/2X/Tv9Y/zX/P/8v/yX/Yf9h/2X/Tv8Z/xn/
L/9S/1L/KP9b/0L/Nf9h/+z+2f7Q/rf+Ff9L/y//Ff/m/v/+Mv8i/3H/LP8M//b+
8/4l//D+Bv/D/v/+sP4P///+4P7w/gb/kf66/tP+2f4o/w//6f6w/tn+s/7Q/uD+
1v6k/vD+t/4V/w//P/8y/0j/Gf8s/y//8P4S/+D+t/7G/rr+0P7A/qD+nf6R/tb+
3f4M/+n++f7T/t3+oP6k/hL/4/78/vP+9v4P/+b+yv7W/tD+w/7T/s3+1v7Q/vb+
yv6n/ub+4P7m/sb+6f6k/sr+2f7Q/vP+dP6R/mv+zf7Z/tb+0/7w/rr+4/6z/tn+
uv4c/73+/P7K/rf+zf63/gz/9v4S/xX/8/7p/tP+9v7D/s3+t/63/r3+uv7w/tP+
/P72/hn/wP7d/q3+4/66/sr+jv7Q/rf+jv53/nv+kf7N/rD+p/69/q3+fv6O/pf+
cf4+/t3+l/7K/rD+WP5I/kX+L/5R/iv+S/4r/uz9+f0S/vz9Jf4M/jj+2f1C/gz+
L/4r/iL+6f1r/j7+Jf4S/kv+ZP6q/mT+mv6O/oH+e/6n/nT+fv6k/tD+4/63/rP+
sP6k/tP+s/7//g//sP5o/gP/Bv8l/xX///4P/wP/zf75/sb+Ev///hL/HP8M/xL/
9v7s/gz/H/8v//b+Bv8M/zL/OP87/xX/P/8f/yz/Jf8G/xL/Gf/2/lj/L/87/1j/
Mv9I/z//Vf9C/17/Vf9b/2j/Tv9V/yj//P4c//D+4P5L/0v/Rf90/xz/OP87/yL/
8P4M/+P+Cf/5/iz/5v4c/9D+t/7w/sr+Gf/2/g//2f4V/x//O/8y/wn/5v7Q/sb+
vf7W/o7+kf7D/r3+A//z/sP+l/5L/or+cf6w/uD+/P7m/g//p/7K/oT+d/6H/pf+
ZP6t/qT++f7W/sb+8/7N/uz+wP7Q/vb+/P7m/vP++f4Z/xn//P69/sP+pP7Z/vb+
Gf8V/0L/HP9I/1v/h/+q/5T/uv+0/3j/dP+E/4H/aP97/3H/pP+d/8f/qv+E/3H/
h/97/2j/WP8v/wn/H/8i/yz/DP9e/0X/Mv9O/z//SP+R/1L/e/97/4f/Xv9Y/2v/
D/8J/93+Cf8S/2v/Ff9L/4T/bv81/1j/H/8D/wz/3f4f/9n+HP8D//P+2f7m/or+
yv6E/s3+uv6O/qD+5v78/sP+4P4G/wP/zf7p/iL/+f4V/+P+7P7Z/g//yv7m/rD+
DP/d/gb/9v4V/w//1v4l/73+oP4c/xX//P41//b+0/7z/hn/zf66/uz+s/7j/tD+
Ev8P/1L/Zf9x/5H/e/9h/17/S/97/6H/gf90/5H/lP+O/4T/e/+X/17/eP+E/3v/
x//d/37/aP8v/0X/cf9V/x//Nf94/3T/bv9Y/07/eP8o/1X/5v72/h//W/9o/3T/
Qv9V/yX/SP/w/mX/KP8S/3H/W/8Z/zL/W/9b/xn/Vf8Z/yL/Iv8o/z//LP9O/yz/
Xv9L/xz/HP8c/xX/Mv8G///+7P7//ub+Cf/m/i//Rf+w/iL/gf6d/pf+h/6X/m7+
ZP5r/rr+rf7w/uD+pP69/tn+xv4S/83+0P7A/tD+DP/w/tD+s/6a/v/+0/4f/yL/
H/8l/0L/Bv8f/yX/zf72/uz+Ev8i/xz/Cf8f/z//Jf9V/z//Yf9r/z//DP8v/xX/
Ff8P/9b+Iv8f/wP/WP9F/2X/pP9r/1v/O/9Y/4r/h/+K/2j/lP9b/5T/kf+0/6T/
AwDm/1IAFgAGAO3/9v/j//n/rf+w/6T/hP9o/0j/Xv9x/5H/Qv9b/2H/jv94/1X/
fv9x/3j/cf9Y/yL/Qv8l/xz/HP8S//b+Qv8J/2H/Qv97/37/kf9V/3v/Zf9O/w//
Tv8//1X/HP8o/wP/Ff8M/xX/D/8M//P+7P7G/sr+9v7W/hz/Cf8D//b++f7K/gP/
pP7K/qD+vf72/g//L/8y/93+7P7m/vz+4P7z/tD+7P6n/tb+Bv8s/1L/Jf8s/zX/
LP84/0j/Nf+O/5H/Mv+R/0v/mv+H/4T/l/9l/6f/kf94/4H/of+O/73/tP+t/8P/
nf+X/7T/mv9+/4H/S/9F/zj/Iv9L/1X/h/+k/73/vf8sANb/HADd/6r/sP+a/3H/
lP+U/3j/e/94/3T/kf+q/73/t/9L/6H/cf+B/0X/Gf8v/0L/Zf9O/yz/SP8c/+P+
Ev8v/yL/LP9V/0X/Xv9C/4f/a/8v/0j/4/7W/vz+5v4Z/yz/0/4J/z//O/8v//P+
Bv/z/iL/wP7w/vb+wP7N/pr+jv7A/qT+8P6t/hL/4/7p/hL/Bv8G/xn/DP9O/0L/
H/8o/x//HP8//yj/iv9e/7T/qv+R/4f/dP+R/8P/jv+K/37/eP+R/5H/hP8v/3H/
L/84/1L/KP9b/2H/SP8//0j/P/9r/17/Nf8S/yL/1v4M/w//jv9r/6H/WP+d/3T/
rf+H/3j/hP90/6T/t//D//P/uv8pABkAHwD2/wMA7f/z/7r/3f+6/9b/0P+O/3j/
Tv9l/2v/aP9V/zj/WP9V/07/Nf9L/3v/HP8S/0v/HP8s/wb/Gf/s/l7/Cf81/+P+
aP/5/l7/8P5C//z+dP9O/zj/a/9e/yj/Nf8s//z+2f5r/y//P/8P/3H/Ff9l/27/
p/+H/5H/of9C/3j/S/+E/zj/P/9O/27/OP8Z/+z+KP9r/0v/e/8i/17/kf90/6H/
bv9x/2H/a/9I/xL/Qv9r/5T/fv+a/4T/zf8SANP/4/+6/63/lP+a/27/e/+K/7f/
qv/g/47/zf/D/47/tP/K/6r/sP+a/73/Yf+B/4H/e/90/3v/e/9+/37/qv84/2v/
O/84/4H/Tv8//wP/Cf87/w//LP84/0X/KP8l/wn/DP9V/0j/Zf+E/0j/Qv9V/yL/
Nf9r/0j/Uv84/wz/aP84/yz/Mv8c//P+cf9u/zj/Ev9F///+L/8c/1X/Yf9I/0X/
dP8s/2X/SP+B/yj/Xv8y/4r/O/+O/zv/a/9o/5r/cf+t/37/aP8v/xz/Mv9l/0X/
kf9L/5H/tP+6/6f/4P+X/wYA3f+n/9P/fv+a/7f/jv8cAMD/BgC9/+3/x/8vAN3/
GQDH/8P/nf+K/5H/dP94/4T/qv9o/5H/O/9S/1j/iv9L/2j/Ff8v/y//LP9r/27/
Iv87/8b+HP8D/0X/LP8f/07/Nf9Y/3j/hP+a/6r/p/+R/6H/cf9S/07/Qv8o/xL/
Rf8f/yj/Cf8o/xn/Ev8V/9D+2f4D/8b++f7Z/vz+0/7T/sD+xv4P/93+xv4Z//b+
Jf/p/gz/7P75/sb+6f7d/kL/DP8Z/yX/e/9+/4r/cf9x/z//Nf8M/zj/Bv9x/y//
Vf81/2X/Nf9r/zX/kf9S/0j/eP+h/6T/x/+t/zj/Uv+X/2X/l/9I/6T/dP+q/6r/
tP+k/5H/aP9e/0L/Gf9S/xX/a/+h/7D/SP9C/xz/L/9h/1v/Rf81/xL/Zf8D/xX/
Ev8G/wb/L/8V/x//Rf9C/z//Tv9o/1j/LP87/wz/A//8/mH/Uv9I/2H/Cf8//yL/
aP8P/07/Jf8P//z+Cf/g/iz/P/81/y//A//w/jL/8P41/xz/2f7G/s3+0P4P/yz/
DP8c/xn/Tv9r/0X/Yf9V/yL/Ff8l/zj/Uv8v/0L/Zf9C/4T/Qv90/5f/l//T/73/
of/t/8r/qv+X/4r/Zf81/5H/a//A/9D/4//N/8P/of/g/53/0//K/6f/iv94/2X/
Vf9O/37/kf90/4r/gf94/5r/nf/H/53/iv+E/2j/hP9e/2X/of9L/7D/dP+U/6f/
mv97/53/Vf+9/27/mv81/37/OP/D/37/of9x/2X/aP+6/5T/hP9u/0j/Xv+B/0j/
h/9e/3T/Tv+w/6H/pP+B/4r/SP+X/2v/w/9r/2v/Qv9r/2X/Yf84/4r/L/+0/2j/
kf9V/6r/KP8v/xn/Ev/G/v/++f5b/y//gf9e/3j/Zf9x/0L/Ev8S/1X/iv+h/63/
gf9F/6T/p//D/4f/wP+K/6T/sP+n/zL/pP+U/63/h/+O/27/Zf9e/9D/WP/H/5r/
1v9o/6H/Mv+n/1j/x/9x/5r/of/t/wwA4//H/7D/jv+O/5f/6f+q/zIA/P8sAAkA
yv/g//b/4P9IAOD/AAAZAJEARQCUAPz/w//a//z/of/Q/4r/tP/p/+n/4P8iAKH/
0P+h/+3/wP8lAOn/of+a/17/bv+q/1X/iv9h/5f/WP+n/4T/0/+k/9P/0//W/6T/
jv+H/37/a/+n/5H/e/9S/7r/gf+t/37/Yf87/17/OP9V/yL/eP8c/27/Qv87/zL/
e/8i/zj/8P4l/9n+Mv/p/i//5v4i/wb/KP8s/7D/e/97/3T/e/9h/3H/Qv90/xn/
h/9V/4r/iv+R/2v/p/9l/5f/nf/j/5f/8P+q/5f/Xv+q/3T/5v/K/+n/2v/A/6H/
GQDD/xwAIgASAAAA
}
CLICK-SOUND: load CLICK-DATA
CLICK: does [
    wait 0
    SOUND-PORT: open sound://
    insert SOUND-PORT CLICK-SOUND
    wait SOUND-PORT
    close SOUND-PORT
]

12.12 Changing languages

This somewhat lengthy demo shows one nice feature of an interpreted language, namely, the ability to modify itself.

There will be three files in this demo. One will be the demo script. This program will load, by means of the "do" function, a file that contains all the text for its window. Then, when the program makes its window with the "layout" function, it will obtain all text for the window from that loaded "language" file. Nothing spectacular there, BUT, the program has a button that will allow the operator to RELOAD a DIFFERENT language file, and remake the window with new text in a different language, all at run time. In other words, no restarting, no re-installing, no re-configuring. The three files follow. The language files have extensive comments.

Save this file under any name of your choosing.

REBOL [
    Title: "VID test harness"
]

do %LANGUAGE-EN.r

FIND-BUTTON: does [
    WS-IDNUMBER: copy ""
    WS-IDNUMBER: trim copy get-face MAIN-IDNUMBER
    if equal? WS-IDNUMBER "" [
        LM-ALERT "002"
        exit
    ]
    LM-ALERT "003"  ;; This is a demo, after all.
]

CLEAR-BUTTON: does [
    clear-fields MAIN-WINDOW
    show MAIN-WINDOW
]

SUBMIT-BUTTON: does [
    WS-IDNUMBER: copy ""
    WS-NAME: copy ""
    WS-ADDRESS: copy ""
    WS-CITY: copy ""
    WS-STATE: copy ""
    WS-POSTAL: copy ""

    WS-IDNUMBER: trim copy get-face MAIN-IDNUMBER
    WS-NAME: trim copy get-face MAIN-NAME
    WS-ADDRESS: trim copy get-face MAIN-ADDRESS
    WS-CITY: trim copy get-face MAIN-CITY
    WS-STATE: trim copy get-face MAIN-STATE
    WS-POSTAL: trim copy get-face MAIN-POSTAL

    if equal? WS-IDNUMBER "" [
        LM-ALERT "002"
        exit
    ]

    if equal? WS-NAME "" [
        LM-ALERT "004"
        exit
    ]

    if equal? WS-ADDRESS "" [
        LM-ALERT "005"
        exit
    ]

    if equal? WS-CITY "" [
        LM-ALERT "006"
        exit
    ]

    if equal? WS-STATE "" [
        LM-ALERT "007"
        exit
    ]

    if equal? WS-POSTAL "" [
        LM-ALERT "008"
        exit
    ]

    print ["ID: " WS-IDNUMBER]
    print ["Name: " WS-NAME]
    print ["Address: " WS-ADDRESS]
    print ["City: " WS-CITY]
    print ["State: " WS-STATE]
    print ["Postal: " WS-POSTAL]
    print "-------------------------------"
]

QUIT-BUTTON: does [
    quit
] 

LANGUAGE-BUTTON: does [
    LANGUAGE-FILE: copy ""
    LANGUAGE-FILE: request-list "Choose new language file" [
        "LANGUAGE-EN.r"
        "LANGUAGE-ES.r"
    ]
    if LANGUAGE-FILE [
        do to-file LANGUAGE-FILE
        MAIN-WINDOW: layout MAIN-WINDOW-CODE
        view center-face MAIN-WINDOW
    ]
]

MAIN-WINDOW-CODE: [
    across
    banner LMT-001
    return
    label LMT-002
    tab
    MAIN-IDNUMBER: field 100
    button 120 LMB-004 [FIND-BUTTON] [inform LMH-001]
    return
    label LMT-003
    tab
    MAIN-NAME: field 200
    return
    label LMT-004
    tab
    tab
    MAIN-ADDRESS: field 200
    return
    label LMT-005
    tab
    tab
    MAIN-CITY: field 200
    return
    label LMT-006
    tab
    tab
    MAIN-STATE: field 50
    return
    label LMT-007
    tab
    MAIN-POSTAL: field 100
    return
    button 200 LMB-005 [CLEAR-BUTTON] [inform LMH-002]
    button 200 LMB-006 [SUBMIT-BUTTON] [inform LMH-003]
    return
    button 200 LMB-007 [QUIT-BUTTON] [inform LMH-004]
    button 200 LMB-008 tan [LANGUAGE-BUTTON] [inform LMH-005]
]

MAIN-WINDOW: layout MAIN-WINDOW-CODE
view center-face MAIN-WINDOW

Save this file with the name of LANGUAGE-EN.r.

REBOL [
]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;              L A N G U A G E    M O D U L E
;              ==============================
;
; This module is loaded into another script with the "do"
; command somewhere near the beginning of the script.  It contains
; all screen text, button legends, messages, absolutely any text
; that appears anywhere in the application.  Each little piece of
; text is identified by a data name.
;
; The purpose of this module is to gather all text for an
; application into this one place.  With all the text in one
; place, the operation of porting the application to a different
; human language can be accomplished by translating this file,
; and only this file.
;
; The various kinds of text fragments are grouped together,
; just for ease of use.  The words that refer to the text
; fragments follow a naming convention, once again just for
; ease of use.  The words could be anything, but of course
; many other modules might refer to these names. 
;
; These are the text groupings:
;
;     Button text:    What is printed on buttons
;     Screen text:    Little text fragments that could appear
;                     anywhere in a script
;     Message text:   One-line messages to show in alert boxes
;     Message detail: Multi-line messages.
;     Help screens:   Larger screens that can be displayed as help.
;
; Each "message text" line is expected to have a matching "message
; detail" multi-line message.  The idea behind this is that
; if an operator gets a message in an alert box, he can ask
; for a more detailed message.
;
; The names of the text fragments have the following form.
;
;     XXX-999
;
; where XXX shows what kind of text it is:
;
;     LMB: Language Module Button text
;     LMT: Language Module Text fragment
;     LMM: Language Module Message
;     LMD: Language Module Detailed message
;     LMH: Language Module Help screen
;
; and 999 is a number.  Note again that each LMM piece of
; text is a one-line messsage, and each will have a matching
; LMD message.  By "matching" we mean that LMM-001 will have
; a corresponding detail message called LMD-001, and so on.
;
; *IN ADDITION* to the text strings and messages, this module
; contains an illustrative function that uses the text strings
; and messages so you can see how they work.  Calling the
; function LM-ALERT with a three digit number as a string,
; in this way:
;
;     LM-ALERT "nnn"
;
; will pop up an alert box with a message and two buttons.
; The message will be LMM-nnn, and the buttons will be one
; for OK and one for DETAILS.  Clicking OK will close the alert.
; Clicking DETAILS will pop up another alert with an expanded
; message, LMD-nnn.  Clicking OK on this second alert box
; will exit the function.
;
; Notice how the values of the buttons are data names, and
; the texts of the messages are pulled out of data items.
; This shows that if an application could be coded to get
; all text from this file, then the application could be
; moved to another language just by translating this file.
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;                    B U T T O N    L A B E L S
LMB-001:  "OK"
LMB-002:  "Details"
LMB-003:  "Close 'help' window" 
LMB-004:  "Find employee"
LMB-005:  "Clear all fields"
LMB-006:  "Update address"
LMB-007:  "Close the window"
LMB-008:  "Change language"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;                   T E X T    F R A G M E N T S
;
LMT-001:  "Employee Address Update"
LMT-002:  "Employee number"
LMT-003:  "Employee name"
LMT-004:  "Address"
LMT-005:  "City"
LMT-006:  "State"   
LMT-007:  "Postal code"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;                O N E - L I N E    M E S S A G E S
;                   each followed by a matching
;          M U L T I - L I N E    D E T A I L    M E S S A G E
LMM-001:  "An invalid message number was passed to LM-ALERT"
LMD-001:
{This is an internal programming error you never should see.
It means that the program tried to display a message box like
this one, BUT, when it called the function to do that, it 
passed the number of a message that does not exist in the program.
This is a program bug, and you should call the I-S department
to report it.}
LMM-002:  "Enter an employee ID number"
LMD-002:
{The 'Find employee' button is used to look up a person based
on the ID number you entered in the 'Employee number' field.
So the 'Employee number' field must not be blank.}
LMM-003:  "Employee not on file"
LMD-003: 
{There is no employee in the database with the ID number you
entered.}
LMM-004:  "Name must not be blank"
LMD-004:
{This window is used for adjusting the spelling of the name as
well as for the address.  The name may not be blank.  If you 
don't know the name, look up the person first with the
'Find employee' button.}
LMM-005:  "Address must not be blank"
LMD-005:
{All employees must have an address on file, even if it is a
post office box.  This is a policy requirement.}
LMM-006: "City must not be blank"
LMD-006:
{A full address must include the city, even if it is a local
address.}
LMM-007: "State must not be blank"
LMD-007:
{A full address must include a valid code for the state or
province.}
LMM-008: "Postal code must not be blank"
LMD-008:
{The postal code must be included for a complete mailing address,
for successful mailing of tax forms.}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;                H E L P    S C R E E N S
;
LMH-001: layout [
    vh1 "The 'Find employee' button"
    text 500X200
{This button uses the employee number you entered in the indicated
field and checks to see if it is in the database.  If the employee
is found, the employee's address is displayed in the window fields.}
    button 200x24 LMB-003 [hide-popup]
]
LMH-002: layout [
    vh1 "The 'Clear all fields' button"
    text 500X200
{This button will clear all the data entry fields.  It is a quick
way to clear the screen for entering fresh data.}
    button 200x24 LMB-003 [hide-popup]
]
LMH-003: layout [
    vh1 "The 'Update address' button"
    text 500X200
{This button will update the address for the selected employee
with the address information in the window.}
    button 200x24 LMB-003 [hide-popup]
]
LMH-004: layout [
    vh1 "The 'Close the window' button"
    text 500X200
{This button will close the window and end the program.  No updating
will take place.}
    button 200x24 LMB-003 [hide-popup]
]
LMH-005: layout [
    vh1 "The 'Change language' button"
    text 500X200
{This button will allow you to select a different language for the
program, and will re-display the window in the new language.}
    button 200x24 LMB-003 [hide-popup]
]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;                   L M - A L E R T
;                   ===============
;
; This function takes a message number and displays the message
; indicated by that number, in an alert box.  If a DETAILS button
; is clicked on the alert box, the function displays another
; alert with an expanded message.
LM-ALERT: func [
;
;   -- Function description and parameters
;
    "Display alert box based on message number"
    LM-MSG-NUMBER [string!] "Message number as three-byte string"
][
;   -- Function code
;
;   -- Use the passed message number to build the names of
;   -- the messages we will display.  Be sure to convert
;   -- the names we construct so that they are REBOL words.
;   -- If we don't re-initialize our message data names,
;   -- subsequent calls will just add LM-MSG-NUMBER to the
;   -- the ends of the values from the previous calls.  
;
    LM-SHORT-ID: copy "" 
    LM-LONG-ID:  copy "" 
    LM-SHORT-ID: to-word join "LMM-" LM-MSG-NUMBER
    LM-LONG-ID:  to-word join "LMD-" LM-MSG-NUMBER
;
;   -- pop up the first alert box.  The short message ID will
;   -- identify the message text.
;
    LM-RESULT: alert [ get LM-SHORT-ID LMB-001 LMB-002 ]
;
;   -- If the first button is clicked, the alert function
;   -- returns "true."  The second button returns "false."
;
    either LM-RESULT [
;       -- The first buttons is OK, and causes us to do nothing
    ][
;       -- The second (false) causes us to pop up another alert
        alert [ get LM-LONG-ID LMB-001 ]
    ]
]
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

This next file is the same as above, but with the messages in Spanish. Save it as LANGUAGE-ES.r. The Spanish, by the way, is courtesy of Professor Google, so don't expect it to be correct. This is a demo.

REBOL [
]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;              L A N G U A G E    M O D U L E
;              ==============================
;
; This module is loaded into another script with the "do"
; command somewhere near the beginning of the script.  It contains
; all screen text, button legends, messages, absolutely any text
; that appears anywhere in the application.  Each little piece of
; text is identified by a data name.
;
; The purpose of this module is to gather all text for an
; application into this one place.  With all the text in one
; place, the operation of porting the application to a different
; human language can be accomplished by translating this file,
; and only this file.
;
; The various kinds of text fragments are grouped together,
; just for ease of use.  The words that refer to the text
; fragments follow a naming convention, once again just for
; ease of use.  The words could be anything, but of course
; many other modules might refer to these names. 
;
; These are the text groupings:
;
;     Button text:    What is printed on buttons
;     Screen text:    Little text fragments that could appear
;                     anywhere in a script
;     Message text:   One-line messages to show in alert boxes
;     Message detail: Multi-line messages.
;     Help screens:   Larger screens that can be displayed as help.
;
; Each "message text" line is expected to have a matching "message
; detail" multi-line message.  The idea behind this is that
; if an operator gets a message in an alert box, he can ask
; for a more detailed message.
;
; The names of the text fragments have the following form.
;
;     XXX-999
;
; where XXX shows what kind of text it is:
;
;     LMB: Language Module Button text
;     LMT: Language Module Text fragment
;     LMM: Language Module Message
;     LMD: Language Module Detailed message
;     LMH: Language Module Help screen
;
; and 999 is a number.  Note again that each LMM piece of
; text is a one-line messsage, and each will have a matching
; LMD message.  By "matching" we mean that LMM-001 will have
; a corresponding detail message called LMD-001, and so on.
;
; *IN ADDITION* to the text strings and messages, this module
; contains an illustrative function that uses the text strings
; and messages so you can see how they work.  Calling the
; function LM-ALERT with a three digit number as a string,
; in this way:
;
;     LM-ALERT "nnn"
;
; will pop up an alert box with a message and two buttons.
; The message will be LMM-nnn, and the buttons will be one
; for OK and one for DETAILS.  Clicking OK will close the alert.
; Clicking DETAILS will pop up another alert with an expanded
; message, LMD-nnn.  Clicking OK on this second alert box
; will exit the function.
;
; Notice how the values of the buttons are data names, and
; the texts of the messages are pulled out of data items.
; This shows that if an application could be coded to get
; all text from this file, then the application could be
; moved to another language just by translating this file.
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;                    B U T T O N    L A B E L S
LMB-001:  "OK"
LMB-002:  "Detalles"
LMB-003:  "Cerrar 'ayuda' ventana"
LMB-004:  "Buscar empleado"
LMB-005:  "Borrar todos los campos"
LMB-006:  "Actualizar la dirección"
LMB-007:  "Cerrar la ventana"
LMB-008:  "Cambiar la lengua"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;                   T E X T    F R A G M E N T S
;
LMT-001:  "Actualizar la dirección del empleado"
LMT-002:  "Número del empleado"
LMT-003:  "Nombre del empleado"
LMT-004:  "Dirección"
LMT-005:  "Ciudad"
LMT-006:  "Estado"    
LMT-007:  "Código postal"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;                O N E - L I N E    M E S S A G E S
;                   each followed by a matching
;          M U L T I - L I N E    D E T A I L    M E S S A G E
LMM-001:  "Un número de mensaje no válido fue enviado a LM-ALERT"
LMD-001:
{Se trata de un error de programación interno nunca se debe ver.
Esto significa que el programa trató de mostrar un cuadro de mensaje como
éste, pero, cuando se llama a la función de hacer eso,
pasado el número de un mensaje que no existe en el programa.
Esto es un error de programa, y usted debe llamar al departamento de SI
reportarlo.}
LMM-002:  "Introducir un número de identificación del empleado"
LMD-002:
{El botón 'Encontrar empleado se utiliza para buscar una persona basándose
en el número de identificación que ha introducido en el campo "Número de empleado '.
Así que el campo "Número de empleado 'no debe estar en blanco.}
LMM-003:  "No hay un archivo del empleado"
LMD-003: 
{No hay trabajadores en la base de datos con el número de identificación que
entró.}
LMM-004:  "Nombre no debe estar vacío"
LMD-004:
{Esta ventana se utiliza para ajustar la ortografía del nombre como
así como para la dirección. El nombre no puede estar en blanco. si tu
no sé el nombre, buscar la persona primero con el
Botón 'Encontrar empleado.}
LMM-005: "Dirección no debe estar vacío"
LMD-005:
{Todos los empleados deben tener una dirección en archivo, incluso si se trata de un
apartado de correos. Este es un requisito política.}
LMM-006: "Ciudad no debe estar vacío"
LMD-006:
{Una dirección completa debe incluir la ciudad, incluso si se trata de un local de
dirección.}
LMM-007: "Estado no debe estar vacío"
LMD-007:
{Una dirección completa debe incluir un código válido para el Estado o
provincia.}
LMM-008: "Código postal no debe estar vacío"
LMD-008:
{El código postal debe incluir una dirección postal completa,
para el envío exitoso de formularios de impuestos.}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;                H E L P    S C R E E N S
;
LMH-001: layout [
    vh1 "El botón 'Encontrar empleado'"
    text 500X200
{Este botón utiliza el número de empleados que ha introducido en el indicado
campo y comprueba para ver si está en la base de datos. Si el empleado
se encuentra, la dirección del empleado se muestra en los campos de la ventana.}
    button 200x24 LMB-003 [hide-popup]
]
LMH-002: layout [
    vh1 "El botón 'Borrar todos los campos'"
    text 500X200
{Este botón borrará todos los campos de entrada de datos. Es una rápida
manera de borrar la pantalla para introducir nuevos datos.}
    button 200x24 LMB-003 [hide-popup]
]
LMH-003: layout [
    vh1 "El botón 'dirección de actualización'"
    text 500X200
{Este botón se actualizará la dirección para el empleado seleccionado
con la información de dirección en la ventana.}
    button 200x24 LMB-003 [hide-popup]
]
LMH-004: layout [
    vh1 "El botón 'Cierre la ventana'"
    text 500X200
{Este botón se cerrará la ventana y finalizar el programa. No se actualizan
tendrá lugar.}
    button 200x24 LMB-003 [hide-popup]
]
LMH-005: layout [
    vh1 "El botón 'Cambiar idioma'"
    text 500X200
{Este botón le permitirá seleccionar un idioma diferente para el
programa, y se volverá a mostrar la ventana en el nuevo idioma.}
    button 200x24 LMB-003 [hide-popup]
]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;                   L M - A L E R T
;                   ===============
;
; This function takes a message number and displays the message
; indicated by that number, in an alert box.  If a DETAILS button
; is clicked on the alert box, the function displays another
; alert with an expanded message.
LM-ALERT: func [
;
;   -- Function description and parameters
;
    "Display alert box based on message number"
    LM-MSG-NUMBER [string!] "Message number as three-byte string"
][
;   -- Function code
;
;   -- Use the passed message number to build the names of
;   -- the messages we will display.  Be sure to convert
;   -- the names we construct so that they are REBOL words.
;   -- If we don't re-initialize our message data names,
;   -- subsequent calls will just add LM-MSG-NUMBER to the
;   -- the ends of the values from the previous calls.  
;
    LM-SHORT-ID: copy "" 
    LM-LONG-ID:  copy "" 
    LM-SHORT-ID: to-word join "LMM-" LM-MSG-NUMBER
    LM-LONG-ID:  to-word join "LMD-" LM-MSG-NUMBER
;
;   -- pop up the first alert box.  The short message ID will
;   -- identify the message text.
;
    LM-RESULT: alert [ get LM-SHORT-ID LMB-001 LMB-002 ]
;
;   -- If the first button is clicked, the alert function
;   -- returns "true."  The second button returns "false."
;
    either LM-RESULT [
;       -- The first buttons is OK, and causes us to do nothing
    ][
;       -- The second (false) causes us to pop up another alert
        alert [ get LM-LONG-ID LMB-001 ]
    ]
]
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

12.13 Saving the window position

Lots of programs that show windows will show its window in the location on the screen where the window was when the program last quit. REBOL can do that by accessing the "offset" of a window and saving it in a file, and then loading that file at BOJ and using the saved offset in the "layout" function. The example below shows that. By the way, if you have a double monitor setup and drag the window to the second monitor before quitting, the window will be deformed when you run the program again. You could fix that by making sure that the location you save does not start outside the screen boundaries, and resetting the last location to some default value if it is. The screen size seems to be in the system object in system/view/screen-face/size.

REBOL [
    Title: "VID test harness"
]

LAST-LOC-FILE: %last-location.txt 
LAST-LOC: 20X20  ;; Default offset in case this is the first run.

WHERE-AM-I: does [
    print ["I am at " MAIN-WINDOW/offset] 
] 

QUIT-BUTTON: does [
    LAST-LOC: MAIN-WINDOW/offset
    save LAST-LOC-FILE LAST-LOC 
    quit
] 

;; If this is the first run, the saved location file will not exist.
if exists? LAST-LOC-FILE [
    LAST-LOC: load LAST-LOC-FILE
]

MAIN-WINDOW: layout/offset [
    banner "Find my location"
    button 200 "Where am I" [WHERE-AM-I]
    button 200 "Quit" [QUIT-BUTTON]
    button 200 "Debug" [halt] 
] LAST-LOC

view MAIN-WINDOW

12.14 Generating VID

One of the neat features of an interpreted langage is that a program can generate parts of itself. In this example, we have a function that takes a block of data and then generates its own VID code to display that data in a grid of "info" fields.

This is based on an idea in Nick Antonaccio's document for creating business applications at: http://business-programming.com/business_programming.html The goal is to create a function that could be fed the results of an SQL query and poof!...up would pop a grid containing the data items from the query. The result of an SQL query is a block of blocks, and each sub-block contains the data items from one row of the query. The way this works is to generate VID code where each item of the input data has its own field on a VID layout. Note the double loop. For each sub-block of input, we generate a row of data fields. For each item in the sub-block, we generate one info field on that row. This was designed for quick-and-dirty viewing of small queries. It appears that the "info" style has a certain default size, and a query that produces many columns could waste a lot of horizontal space if every column got the default size. To "fix" that the function takes a second block which is a list of column widths in pixels for each column of a data sub-block. It is the job of the caller to make sure this block of columns sizes has the same number of items as the data sub-blocks, and the column widths are big enough. This module really should be an object, but we had a bit of trouble when we had it as an object and used a second similar module for a second similar layout. The scroll bars were not scrolling their intended grids. That problem seemed to get solved when every word in the function was unique and not in conflict with any other word in the second module. That is why all the words below have the GLO prefix.

GLO-BOXHEIGHT: 500 
GLO-BOXWIDTH: 0
GLO-BOXSIZE: none 

GLO-LAYOUT: func [
    GLOBLOCK
    GLOWIDTHS
    /local GLOGRID GLODISP GLOCOL
] [
    GLO-BOXWIDTH: 0
    foreach WIDTH GLOWIDTHS [
        GLO-BOXWIDTH: GLO-BOXWIDTH + WIDTH
    ]
    GLO-BOXSIZE: to-pair reduce [GLO-BOXWIDTH GLO-BOXHEIGHT] 
    GLOGRID: copy [across space 0]
    foreach BLK GLOBLOCK [
        GLOCOL: 0 
        foreach COL BLK [
            GLOCOL: GLOCOL + 1
            append GLOGRID compose [
                info (pick GLOWIDTHS GLOCOL) (form COL)
            ]
         ]
         append GLOGRID compose [return]
    ]
    GLODISP: layout/tight [
        across
        GLOBOX: box GLO-BOXSIZE with [ ;; "with" lets us get at internals
            pane: layout/tight GLOGRID pane/offset: 0x0
        ]
        scroller to-pair reduce [20 second GLO-BOXSIZE] [
            GLOBOX/pane/offset/y: GLOBOX/size/y - GLOBOX/pane/size/y * value
            show GLOBOX
        ]
    ]
    return GLODISP
]

13. Appetizers

REBOL/View is the version of REBOL that has the GUI capability. VID, the Video Interface Dialect, is a mini-language that makes is easy to make windows. VID is part of REBOL/VIew. Also part of REBOL/View is all the functions that help work with windows created with VID. All the functions of REBOL/Core also are part of REBOL/View, so you can use the REBOL/Core functions to work with data obtained from VID windows. All these parts make it easy to use REBOL/View for making programs for getting data from windows, doing stuff with it, storing it on disk, and so one.

But there's more. The information in this document is limited enough that one might read it and get a limited idea of what REBOL can do. To try to offset that, we present below links to some interesting REBOL programs, modules, demos, and such that will hint at capabilities that are not obvious from just the above lists of styles and functions. This is not any sort of complete list of anything. It is little appetizers. It is things that might make you think, "That's interesting; I didn't know REBOL could do THAT."

13.1 List-view: enhanced list style

This is a module that you could incorporate into your own program that does what the "list" style does, but more. It is interesting because it is freely available and you may use it, and because it shows a REBOL style written in REBOL itself. In fact, a lot of REBOL is written in REBOL itself. I think that was one of its design goals, to have a minimum amount of native functions and then build the rest of REBOL on top of those for the sake of portability.

list-view.r

13.2 Area-scroll-style: enhanced area style

This is a module, with a built-in demo, that provides a new and improved "area" style with vertical and horizontal scrollers. This is another example of a style created in REBOL itself.

area-scroll-style.r

13.3 Layout-1.8.r: GUI layout builder

This is a demo of a VID program for making VID layouts. It is interesting because it shows that one can do that, but also because of the look of the operating window, which show that one can get nice results with a little bit of work. This script was written by the author of REBOL, so it shows the language as she should be spoken.

layout-1.8.r

13.4 Gui-crud-app-builder.r: GUI program generator

This is another idea for using a View program to generate another VIEW program.

gui-crud-app-builder

13.5 Toolt4vid.r: Tool tips

This is a demo of how one can make the "tool tips" which are those annoying help boxes that pop up when you move the mouse over something. This is interesting because it uses the "feel" facet to put some more life into a window, showing that such things can be done.

toolt4vid.r

13.6 Easy-vid.r: VID documenting itself

This is a script by the creator of REBOL that shows a window of VID documentation. It is interesting for that reason alone, but also for how it shows example code, and that example code can be clicked to make it run. How cool is that. Also, because it was written by the Creator himself, is another example of proper REBOL style.

easy-vid.r

13.7 Rebolusers.r: More than just data entry

This is a demo that shows how REBOL can do more than just make data entry forms with blue buttons. If you run this demo, it will download a bunch of pictures and a file of music, and then play the music while displaying the pictures.

rebolusers.r

The point being made is...

The point of the above links is to show a contrast with the documentation that came before. The documentation that came before showed the graphical elements that can be put together to make a graphical interface window. If you stop there, you might think that graphical windows full of styles is ALL that REBOL/View can do, and you might not look to REBOL to solve other kinds of problems. When you run into other kinds of problems, you should not automatically assume that REBOL can't handle them. The handful of examples above are meant to show that there is more to REBOL.

14. Source code for styles

This chapter shows the source code of the styles. Since the official documentation maybe is not as complete as it could be, sometimes just looking through the source can show you undocumented things that you might be able to take advantage of.

The source code that follows was extracted with the following program that, which is based on a trick we found on the internet.

REBOL [
    Title: "Style code makedoc"
    Purpose: {A documentation aid that combines the source code of the VID
    styles into one file, with makedoc headers between the code blocks.}
]

;; [---------------------------------------------------------------------------]
;; [ If you run the following code:                                            ]
;; [                                                                           ]
;; [ foreach [STYLE-WORD STYLE-CODE] svv/vid-styles [                          ]
;; [     CODE-FILENAME: copy ""                                                ]
;; [     CODE-FILENAME: to-file rejoin [                                       ]
;; [         to-string STYLE-WORD                                              ]
;; [         ".txt"                                                            ]
;; [     ]                                                                     ]
;; [     write CODE-FILENAME STYLE-CODE                                        ]
;; [ ]                                                                         ]
;; [                                                                           ]
;; [ you will extract the code for all the VID styles, and, for each style,    ]
;; [ write the code into a text file.  The name of the file will be the        ]
;; [ style name with the dot-txt extension.                                    ]
;; [                                                                           ]
;; [ This program is based on that idea but instead of writing the code        ]
;; [ for each style into its own file, the program writes it all into one      ]
;; [ file with a makedoc "---" header for each.  The output of this program    ]
;; [ would be suitable for pasting into a makedoc document.                    ]
;; [---------------------------------------------------------------------------]

MAKEDOC-FILE-ID: %StyleCode.txt
MAKEDOC-FILE: ""

foreach [STYLE-WORD STYLE-CODE] svv/vid-styles [
    append MAKEDOC-FILE rejoin [
        "---"
        STYLE-WORD
        newline
        newline
    ]
    STR: copy ""
    STR: to-string STYLE-CODE 
    insert/dup STR " " 4
    replace/all STR newline rejoin [newline "    "]
    append MAKEDOC-FILE STR
    append MAKEDOC-FILE newline
]
write MAKEDOC-FILE-ID MAKEDOC-FILE

alert "Done."

14.1 face

type: face
offset: 0x0
size: none
span: none
pane: none
text: none
color: 200.200.200
image: none
effect: none
data: none
edge: make object! [
    color: 200.200.200
    image: none
    effect: none
    size: 0x0
]
font: make object! [
    name: "arial"
    style: none
    size: 12
    color: 255.255.255
    offset: 2x2
    space: 0x0
    align: 'left
    valign: 'top
    shadow: 1x1
    colors: [255.255.255 255.180.75]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: make object! [
    redraw: none
    detect: none
    over: none
    engage: none
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][face/data: value]
    get-face*: func [face][face/data]
    clear-face*: func [face][face/data: false]
    reset-face*: func [face][face/data: false]
]
style: none
alt-action: none
facets: none
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: none
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: []
doc: make object! [
    info: "base face style"
    string: none
    image: none
    logic: none
    integer: none
    pair: none
    tuple: none
    file: none
    url: none
    decimal: none
    time: none
    block: none
    keywords: none
]

14.2 blank-face

type: face
offset: 0x0
size: none
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: none
font: none
para: none
feel: none
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: none
style: none
alt-action: none
facets: none
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: none
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: []
doc: make object! [
    info: "empty style (transparent, minimized)"
    string: none
    image: none
    logic: none
    integer: none
    pair: none
    tuple: none
    file: none
    url: none
    decimal: none
    time: none
    block: none
    keywords: none
]

14.3 IMAGE

type: face
offset: 0x0
size: none
span: none
pane: none
text: none
color: none
image: none
effect: [fit]
data: none
edge: make object! [
    color: 0.0.0
    image: none
    effect: none
    size: 0x0
]
font: make object! [
    name: "arial"
    style: 'bold
    size: 16
    color: 255.255.255
    offset: 2x2
    space: 0x0
    align: 'center
    valign: 'middle
    shadow: 2x2
    colors: [255.255.255 255.180.75]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: make object! [
    redraw: none
    detect: none
    over: none
    engage: func [face action event][
        switch action [
            time [if not face/state [face/blinker: not face/blinker]] 
            down [face/state: on] 
            alt-down [face/state: on] 
            up [if face/state [do-face face face/text] face/state: off] 
            alt-up [if face/state [do-face-alt face face/text] face/state: off] 
            over [face/state: on] 
            away [face/state: off]
        ] 
        cue face action 
        show face
    ]
    cue: none
    blink: none
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        if any [image? value none? value] [
            face/image: value
        ]
    ]
    get-face*: func [face][face/image]
    clear-face*: func [face][face/image: none]
]
style: FACE
alt-action: none
facets: [with [
        size: color: image: none 
        feel: svvf/sensor 
        access: ctx-access/image 
        effect: [fit] 
        edge: [size: 0x0 color: black] 
        font: [size: 16 align: 'center valign: 'middle style: 'bold shadow: 2x2] 
        doc: [
            info: "base style for images" 
            image: "loaded image data" 
            string: "text on top of image" 
            pair: "width and height of text area" 
            tuple: "colorize the image" 
            file: "load as image data" 
            url: "load as image data" 
            block: ["execute when clicked" "execute when alt-clicked"]
        ] 
        init: [
            if image? image [
                if none? size [size: image/size] 
                if size/y < 0 [size/y: size/x * image/size/y / image/size/x effect: insert copy effect 'fit] 
                if color [effect: join effect ['colorize color]]
            ] 
            if none? size [size: 100x100]
        ]
    ]]
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if image? image [
        if none? size [size: image/size] 
        if size/y < 0 [size/y: size/x * image/size/y / image/size/x effect: insert copy effect 'fit] 
        if color [effect: join effect ['colorize color]]
    ] 
    if none? size [size: 100x100]
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: []
doc: make object! [
    info: "base style for images"
    string: "text on top of image"
    image: "loaded image data"
    logic: none
    integer: none
    pair: "width and height of text area"
    tuple: "colorize the image"
    file: "load as image data"
    url: "load as image data"
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]

14.4 BACKDROP

type: face
offset: 0x0
size: none
span: none
pane: none
text: none
color: none
image: none
effect: [fit]
data: none
edge: make object! [
    color: 0.0.0
    image: none
    effect: none
    size: 0x0
]
font: make object! [
    name: "arial"
    style: 'bold
    size: 16
    color: 255.255.255
    offset: 2x2
    space: 0x0
    align: 'center
    valign: 'middle
    shadow: 2x2
    colors: [255.255.255 255.180.75]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: make object! [
    redraw: none
    detect: none
    over: none
    engage: func [face action event][
        switch action [
            time [if not face/state [face/blinker: not face/blinker]] 
            down [face/state: on] 
            alt-down [face/state: on] 
            up [if face/state [do-face face face/text] face/state: off] 
            alt-up [if face/state [do-face-alt face face/text] face/state: off] 
            over [face/state: on] 
            away [face/state: off]
        ] 
        cue face action 
        show face
    ]
    cue: none
    blink: none
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        if any [image? value none? value] [
            face/image: value
        ]
    ]
    get-face*: func [face][face/image]
    clear-face*: func [face][face/image: none]
]
style: IMAGE
alt-action: none
facets: [with [
        flags: [fixed drop] 
        doc: [info: "image scaled to fill pane" pair: block: none] 
        init: append copy init [size: pane-size]
    ]]
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if image? image [
        if none? size [size: image/size] 
        if size/y < 0 [size/y: size/x * image/size/y / image/size/x effect: insert copy effect 'fit] 
        if color [effect: join effect ['colorize color]]
    ] 
    if none? size [size: 100x100] size: pane-size
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [fixed drop]
doc: make object! [
    info: "image scaled to fill pane"
    string: "text on top of image"
    image: "loaded image data"
    logic: none
    integer: none
    pair: none
    tuple: "colorize the image"
    file: "load as image data"
    url: "load as image data"
    decimal: none
    time: none
    block: none
    keywords: none
]

14.5 BACKTILE

type: face
offset: 0x0
size: none
span: none
pane: none
text: none
color: none
image: none
effect: [tile-view]
data: none
edge: make object! [
    color: 0.0.0
    image: none
    effect: none
    size: 0x0
]
font: make object! [
    name: "arial"
    style: 'bold
    size: 16
    color: 255.255.255
    offset: 2x2
    space: 0x0
    align: 'center
    valign: 'middle
    shadow: 2x2
    colors: [255.255.255 255.180.75]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: make object! [
    redraw: none
    detect: none
    over: none
    engage: func [face action event][
        switch action [
            time [if not face/state [face/blinker: not face/blinker]] 
            down [face/state: on] 
            alt-down [face/state: on] 
            up [if face/state [do-face face face/text] face/state: off] 
            alt-up [if face/state [do-face-alt face face/text] face/state: off] 
            over [face/state: on] 
            away [face/state: off]
        ] 
        cue face action 
        show face
    ]
    cue: none
    blink: none
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        if any [image? value none? value] [
            face/image: value
        ]
    ]
    get-face*: func [face][face/image]
    clear-face*: func [face][face/image: none]
]
style: BACKDROP
alt-action: none
facets: [
    doc [info: "image tiled to fill pane"] 
    effect [tile-view]
]
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if image? image [
        if none? size [size: image/size] 
        if size/y < 0 [size/y: size/x * image/size/y / image/size/x effect: insert copy effect 'fit] 
        if color [effect: join effect ['colorize color]]
    ] 
    if none? size [size: 100x100] size: pane-size
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [fixed drop]
doc: make object! [
    info: "image tiled to fill pane"
    string: "text on top of image"
    image: "loaded image data"
    logic: none
    integer: none
    pair: none
    tuple: "colorize the image"
    file: "load as image data"
    url: "load as image data"
    decimal: none
    time: none
    block: none
    keywords: none
]

14.6 BOX

type: face
offset: 0x0
size: none
span: none
pane: none
text: none
color: none
image: none
effect: [fit]
data: none
edge: make object! [
    color: 0.0.0
    image: none
    effect: none
    size: 0x0
]
font: make object! [
    name: "arial"
    style: 'bold
    size: 16
    color: 255.255.255
    offset: 2x2
    space: 0x0
    align: 'center
    valign: 'middle
    shadow: 2x2
    colors: [255.255.255 255.180.75]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: make object! [
    redraw: none
    detect: none
    over: none
    engage: func [face action event][
        switch action [
            time [if not face/state [face/blinker: not face/blinker]] 
            down [face/state: on] 
            alt-down [face/state: on] 
            up [if face/state [do-face face face/text] face/state: off] 
            alt-up [if face/state [do-face-alt face face/text] face/state: off] 
            over [face/state: on] 
            away [face/state: off]
        ] 
        cue face action 
        show face
    ]
    cue: none
    blink: none
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        if any [image? value none? value] [
            face/image: value
        ]
    ]
    get-face*: func [face][face/image]
    clear-face*: func [face][face/image: none]
]
style: IMAGE
alt-action: none
facets: [doc [info: "shortcut for image"]]
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if image? image [
        if none? size [size: image/size] 
        if size/y < 0 [size/y: size/x * image/size/y / image/size/x effect: insert copy effect 'fit] 
        if color [effect: join effect ['colorize color]]
    ] 
    if none? size [size: 100x100]
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: []
doc: make object! [
    info: "shortcut for image"
    string: "text on top of image"
    image: "loaded image data"
    logic: none
    integer: none
    pair: "width and height of text area"
    tuple: "colorize the image"
    file: "load as image data"
    url: "load as image data"
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]

14.7 BAR

type: face
offset: 0x0
size: -1x3
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: make object! [
    color: 200.200.200
    image: none
    effect: 'bevel
    size: 1x1
]
font: none
para: none
feel: none
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: none
style: BLANK-FACE
alt-action: none
facets: [-1x3 with [
        edge: [size: 1x1 effect: 'bevel] 
        doc: [
            info: "horizontal separator" 
            integer: "width of bar" 
            pair: "size of bar" 
            tuple: "color of the bar"
        ] 
        init: [
            if data: color [edge: make edge [color: data + 20]] 
            if negative? size/x [size/x: 200]
        ]
    ]]
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if data: color [edge: make edge [color: data + 20]] 
    if negative? size/x [size/x: 200]
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: []
doc: make object! [
    info: "horizontal separator"
    string: none
    image: none
    logic: none
    integer: "width of bar"
    pair: "size of bar"
    tuple: "color of the bar"
    file: none
    url: none
    decimal: none
    time: none
    block: none
    keywords: none
]

14.8 SENSOR

type: face
offset: 0x0
size: none
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: none
font: none
para: none
feel: make object! [
    redraw: none
    detect: none
    over: none
    engage: func [face action event][
        switch action [
            time [if not face/state [face/blinker: not face/blinker]] 
            down [face/state: on] 
            alt-down [face/state: on] 
            up [if face/state [do-face face face/text] face/state: off] 
            alt-up [if face/state [do-face-alt face face/text] face/state: off] 
            over [face/state: on] 
            away [face/state: off]
        ] 
        cue face action 
        show face
    ]
    cue: none
    blink: none
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: none
style: BLANK-FACE
alt-action: none
facets: [with [
        feel: svvf/sensor 
        doc: [
            info: "transparent sensor area" 
            pair: "size of sensor"
        ] 
        init: [if none? size [size: 100x100]]
    ]]
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [if none? size [size: 100x100]]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: []
doc: make object! [
    info: "transparent sensor area"
    string: none
    image: none
    logic: none
    integer: none
    pair: "size of sensor"
    tuple: none
    file: none
    url: none
    decimal: none
    time: none
    block: none
    keywords: none
]

14.9 KEY

type: face
offset: 0x0
size: 0x0
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: none
font: none
para: none
feel: make object! [
    redraw: none
    detect: none
    over: none
    engage: func [face action event][
        switch action [
            time [if not face/state [face/blinker: not face/blinker]] 
            down [face/state: on] 
            alt-down [face/state: on] 
            up [if face/state [do-face face face/text] face/state: off] 
            alt-up [if face/state [do-face-alt face face/text] face/state: off] 
            over [face/state: on] 
            away [face/state: off]
        ] 
        cue face action 
        show face
    ]
    cue: none
    blink: none
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: none
style: SENSOR
alt-action: none
facets: [0x0 doc [info: "keyboard action" pair: none]]
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [if none? size [size: 100x100]]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: []
doc: make object! [
    info: "keyboard action"
    string: none
    image: none
    logic: none
    integer: none
    pair: none
    tuple: none
    file: none
    url: none
    decimal: none
    time: none
    block: none
    keywords: none
]

14.10 BASE-TEXT

type: face
offset: 0x0
size: none
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: none
font: make object! [
    name: "arial"
    style: none
    size: 12
    color: 0.0.0
    offset: 2x2
    space: 0x0
    align: 'left
    valign: 'top
    shadow: none
    colors: [0.0.0 40.40.40]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: make object! [
    redraw: none
    detect: none
    over: none
    engage: none
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        face/text: value 
        face/line-list: none
    ]
    get-face*: func [face][face/text]
    clear-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        if string? face/text [clear face/text] 
        face/line-list: none
    ]
    reset-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        face/text: copy "" 
        face/line-list: none
    ]
]
style: FACE
alt-action: none
facets: [with [
        size: image: color: none 
        access: ctx-access/text 
        edge: none 
        flags: [text] 
        font: [color: black shadow: none colors: [0.0.0 40.40.40]] 
        xy: none 
        doc: [
            info: "base text style" 
            string: "text contents" 
            integer: "width of text area" 
            pair: "width and height of text area" 
            tuple: ["text color" "background color"] 
            block: ["execute when clicked" "execute when alt-clicked"]
        ] 
        init: [
            if all [not flag-face? self as-is string? text] [trim/lines text] 
            if none? text [text: copy ""] 
            change font/colors font/color 
            if none? size [size: -1x-1] 
            xy: size 
            if any [size/x < 0 size/y < 0] [
                state: max 1x1 pane-size * 9 / 10 - offset 
                if size/x < 0 [size/x: state/x] 
                if size/y < 0 [size/y: state/y] 
                size: (size-text self) + (edge-size? self) 
                + (to-pair all [para (to-pair para/margin) + to-pair para/origin])
            ] 
            if xy/x > 0 [size/x: xy/x] 
            if xy/y > 0 [size/y: xy/y]
        ]
    ]]
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if all [not flag-face? self as-is string? text] [trim/lines text] 
    if none? text [text: copy ""] 
    change font/colors font/color 
    if none? size [size: -1x-1] 
    xy: size 
    if any [size/x < 0 size/y < 0] [
        state: max 1x1 pane-size * 9 / 10 - offset 
        if size/x < 0 [size/x: state/x] 
        if size/y < 0 [size/y: state/y] 
        size: (size-text self) + (edge-size? self) 
        + (to-pair all [para (to-pair para/margin) + to-pair para/origin])
    ] 
    if xy/x > 0 [size/x: xy/x] 
    if xy/y > 0 [size/y: xy/y]
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [text]
doc: make object! [
    info: "base text style"
    string: "text contents"
    image: none
    logic: none
    integer: "width of text area"
    pair: "width and height of text area"
    tuple: ["text color" "background color"]
    file: none
    url: none
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]
xy: none

14.11 VTEXT

type: face
offset: 0x0
size: none
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: none
font: make object! [
    name: "arial"
    style: none
    size: 12
    color: 255.255.255
    offset: 2x2
    space: 0x0
    align: 'left
    valign: 'top
    shadow: 1x1
    colors: [255.255.255 255.180.75]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: make object! [
    redraw: none
    detect: none
    over: none
    engage: func [face act event][
        switch act [
            down [
                either equal? face focal-face [unlight-text] [focus/no-show face] 
                caret: offset-to-caret face event/offset 
                show face 
                face/action face face/text
            ] 
            up [
                if highlight-start = highlight-end [unfocus]
            ] 
            over [
                if not-equal? caret offset-to-caret face event/offset [
                    if not highlight-start [highlight-start: caret] 
                    highlight-end: caret: offset-to-caret face event/offset 
                    show face
                ]
            ] 
            key [
                if 'copy-text = select keymap event/key [
                    copy-text face unlight-text
                ]
            ]
        ]
    ]
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        face/text: value 
        face/line-list: none
    ]
    get-face*: func [face][face/text]
    clear-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        if string? face/text [clear face/text] 
        face/line-list: none
    ]
    reset-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        face/text: copy "" 
        face/line-list: none
    ]
]
style: BASE-TEXT
alt-action: none
facets: [with [
        feel: ctx-text/swipe 
        font: [color: white shadow: 1x1 colors: [255.255.255 255.180.75]] 
        doc: [info: "video text (light on dark)"] 
        insert init [
            if :action [feel: svvf/hot saved-area: true]
        ]
    ]]
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if :action [feel: svvf/hot saved-area: true] 
    if all [not flag-face? self as-is string? text] [trim/lines text] 
    if none? text [text: copy ""] 
    change font/colors font/color 
    if none? size [size: -1x-1] 
    xy: size 
    if any [size/x < 0 size/y < 0] [
        state: max 1x1 pane-size * 9 / 10 - offset 
        if size/x < 0 [size/x: state/x] 
        if size/y < 0 [size/y: state/y] 
        size: (size-text self) + (edge-size? self) 
        + (to-pair all [para (to-pair para/margin) + to-pair para/origin])
    ] 
    if xy/x > 0 [size/x: xy/x] 
    if xy/y > 0 [size/y: xy/y]
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [text]
doc: make object! [
    info: "video text (light on dark)"
    string: "text contents"
    image: none
    logic: none
    integer: "width of text area"
    pair: "width and height of text area"
    tuple: ["text color" "background color"]
    file: none
    url: none
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]
xy: none

14.12 TEXT

type: face
offset: 0x0
size: none
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: none
font: make object! [
    name: "arial"
    style: none
    size: 12
    color: 0.0.0
    offset: 2x2
    space: 0x0
    align: 'left
    valign: 'top
    shadow: none
    colors: [0.0.0 255.180.75]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: make object! [
    redraw: none
    detect: none
    over: none
    engage: func [face act event][
        switch act [
            down [
                either equal? face focal-face [unlight-text] [focus/no-show face] 
                caret: offset-to-caret face event/offset 
                show face 
                face/action face face/text
            ] 
            up [
                if highlight-start = highlight-end [unfocus]
            ] 
            over [
                if not-equal? caret offset-to-caret face event/offset [
                    if not highlight-start [highlight-start: caret] 
                    highlight-end: caret: offset-to-caret face event/offset 
                    show face
                ]
            ] 
            key [
                if 'copy-text = select keymap event/key [
                    copy-text face unlight-text
                ]
            ]
        ]
    ]
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        face/text: value 
        face/line-list: none
    ]
    get-face*: func [face][face/text]
    clear-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        if string? face/text [clear face/text] 
        face/line-list: none
    ]
    reset-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        face/text: copy "" 
        face/line-list: none
    ]
]
style: VTEXT
alt-action: none
facets: [0.0.0 shadow none doc [info: "document text"]]
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if :action [feel: svvf/hot saved-area: true] 
    if all [not flag-face? self as-is string? text] [trim/lines text] 
    if none? text [text: copy ""] 
    change font/colors font/color 
    if none? size [size: -1x-1] 
    xy: size 
    if any [size/x < 0 size/y < 0] [
        state: max 1x1 pane-size * 9 / 10 - offset 
        if size/x < 0 [size/x: state/x] 
        if size/y < 0 [size/y: state/y] 
        size: (size-text self) + (edge-size? self) 
        + (to-pair all [para (to-pair para/margin) + to-pair para/origin])
    ] 
    if xy/x > 0 [size/x: xy/x] 
    if xy/y > 0 [size/y: xy/y]
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [flags text font]
doc: make object! [
    info: "document text"
    string: "text contents"
    image: none
    logic: none
    integer: "width of text area"
    pair: "width and height of text area"
    tuple: ["text color" "background color"]
    file: none
    url: none
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]
xy: none

14.13 BODY

type: face
offset: 0x0
size: none
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: none
font: make object! [
    name: "arial"
    style: none
    size: 12
    color: 0.0.0
    offset: 2x2
    space: 0x0
    align: 'left
    valign: 'top
    shadow: none
    colors: [0.0.0 255.180.75]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: make object! [
    redraw: none
    detect: none
    over: none
    engage: func [face act event][
        switch act [
            down [
                either equal? face focal-face [unlight-text] [focus/no-show face] 
                caret: offset-to-caret face event/offset 
                show face 
                face/action face face/text
            ] 
            up [
                if highlight-start = highlight-end [unfocus]
            ] 
            over [
                if not-equal? caret offset-to-caret face event/offset [
                    if not highlight-start [highlight-start: caret] 
                    highlight-end: caret: offset-to-caret face event/offset 
                    show face
                ]
            ] 
            key [
                if 'copy-text = select keymap event/key [
                    copy-text face unlight-text
                ]
            ]
        ]
    ]
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        face/text: value 
        face/line-list: none
    ]
    get-face*: func [face][face/text]
    clear-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        if string? face/text [clear face/text] 
        face/line-list: none
    ]
    reset-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        face/text: copy "" 
        face/line-list: none
    ]
]
style: TEXT
alt-action: none
facets: []
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if :action [feel: svvf/hot saved-area: true] 
    if all [not flag-face? self as-is string? text] [trim/lines text] 
    if none? text [text: copy ""] 
    change font/colors font/color 
    if none? size [size: -1x-1] 
    xy: size 
    if any [size/x < 0 size/y < 0] [
        state: max 1x1 pane-size * 9 / 10 - offset 
        if size/x < 0 [size/x: state/x] 
        if size/y < 0 [size/y: state/y] 
        size: (size-text self) + (edge-size? self) 
        + (to-pair all [para (to-pair para/margin) + to-pair para/origin])
    ] 
    if xy/x > 0 [size/x: xy/x] 
    if xy/y > 0 [size/y: xy/y]
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [flags text]
doc: make object! [
    info: "document text"
    string: "text contents"
    image: none
    logic: none
    integer: "width of text area"
    pair: "width and height of text area"
    tuple: ["text color" "background color"]
    file: none
    url: none
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]
xy: none

14.14 TXT

type: face
offset: 0x0
size: none
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: none
font: make object! [
    name: "arial"
    style: none
    size: 12
    color: 0.0.0
    offset: 2x2
    space: 0x0
    align: 'left
    valign: 'top
    shadow: none
    colors: [0.0.0 255.180.75]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: make object! [
    redraw: none
    detect: none
    over: none
    engage: func [face act event][
        switch act [
            down [
                either equal? face focal-face [unlight-text] [focus/no-show face] 
                caret: offset-to-caret face event/offset 
                show face 
                face/action face face/text
            ] 
            up [
                if highlight-start = highlight-end [unfocus]
            ] 
            over [
                if not-equal? caret offset-to-caret face event/offset [
                    if not highlight-start [highlight-start: caret] 
                    highlight-end: caret: offset-to-caret face event/offset 
                    show face
                ]
            ] 
            key [
                if 'copy-text = select keymap event/key [
                    copy-text face unlight-text
                ]
            ]
        ]
    ]
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        face/text: value 
        face/line-list: none
    ]
    get-face*: func [face][face/text]
    clear-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        if string? face/text [clear face/text] 
        face/line-list: none
    ]
    reset-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        face/text: copy "" 
        face/line-list: none
    ]
]
style: TEXT
alt-action: none
facets: []
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if :action [feel: svvf/hot saved-area: true] 
    if all [not flag-face? self as-is string? text] [trim/lines text] 
    if none? text [text: copy ""] 
    change font/colors font/color 
    if none? size [size: -1x-1] 
    xy: size 
    if any [size/x < 0 size/y < 0] [
        state: max 1x1 pane-size * 9 / 10 - offset 
        if size/x < 0 [size/x: state/x] 
        if size/y < 0 [size/y: state/y] 
        size: (size-text self) + (edge-size? self) 
        + (to-pair all [para (to-pair para/margin) + to-pair para/origin])
    ] 
    if xy/x > 0 [size/x: xy/x] 
    if xy/y > 0 [size/y: xy/y]
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [flags text]
doc: make object! [
    info: "document text"
    string: "text contents"
    image: none
    logic: none
    integer: "width of text area"
    pair: "width and height of text area"
    tuple: ["text color" "background color"]
    file: none
    url: none
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]
xy: none

14.15 BANNER

type: face
offset: 0x0
size: none
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: none
font: make object! [
    name: "arial"
    style: [bold]
    size: 24
    color: 250.215.0
    offset: 2x2
    space: 0x0
    align: 'center
    valign: 'middle
    shadow: 3x3
    colors: [255.255.255 255.180.75]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: make object! [
    redraw: none
    detect: none
    over: none
    engage: func [face act event][
        switch act [
            down [
                either equal? face focal-face [unlight-text] [focus/no-show face] 
                caret: offset-to-caret face event/offset 
                show face 
                face/action face face/text
            ] 
            up [
                if highlight-start = highlight-end [unfocus]
            ] 
            over [
                if not-equal? caret offset-to-caret face event/offset [
                    if not highlight-start [highlight-start: caret] 
                    highlight-end: caret: offset-to-caret face event/offset 
                    show face
                ]
            ] 
            key [
                if 'copy-text = select keymap event/key [
                    copy-text face unlight-text
                ]
            ]
        ]
    ]
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        face/text: value 
        face/line-list: none
    ]
    get-face*: func [face][face/text]
    clear-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        if string? face/text [clear face/text] 
        face/line-list: none
    ]
    reset-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        face/text: copy "" 
        face/line-list: none
    ]
]
style: VTEXT
alt-action: none
facets: [250.215.0 bold font-size 24 center middle shadow 3x3 
    doc [info: "video text title"]
]
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if :action [feel: svvf/hot saved-area: true] 
    if all [not flag-face? self as-is string? text] [trim/lines text] 
    if none? text [text: copy ""] 
    change font/colors font/color 
    if none? size [size: -1x-1] 
    xy: size 
    if any [size/x < 0 size/y < 0] [
        state: max 1x1 pane-size * 9 / 10 - offset 
        if size/x < 0 [size/x: state/x] 
        if size/y < 0 [size/y: state/y] 
        size: (size-text self) + (edge-size? self) 
        + (to-pair all [para (to-pair para/margin) + to-pair para/origin])
    ] 
    if xy/x > 0 [size/x: xy/x] 
    if xy/y > 0 [size/y: xy/y]
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [flags text font]
doc: make object! [
    info: "video text title"
    string: "text contents"
    image: none
    logic: none
    integer: "width of text area"
    pair: "width and height of text area"
    tuple: ["text color" "background color"]
    file: none
    url: none
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]
xy: none

14.16 VH1

type: face
offset: 0x0
size: none
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: none
font: make object! [
    name: "arial"
    style: [bold]
    size: 20
    color: 255.255.255
    offset: 2x2
    space: 0x0
    align: 'center
    valign: 'middle
    shadow: 3x3
    colors: [255.255.255 255.180.75]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: make object! [
    redraw: none
    detect: none
    over: none
    engage: func [face act event][
        switch act [
            down [
                either equal? face focal-face [unlight-text] [focus/no-show face] 
                caret: offset-to-caret face event/offset 
                show face 
                face/action face face/text
            ] 
            up [
                if highlight-start = highlight-end [unfocus]
            ] 
            over [
                if not-equal? caret offset-to-caret face event/offset [
                    if not highlight-start [highlight-start: caret] 
                    highlight-end: caret: offset-to-caret face event/offset 
                    show face
                ]
            ] 
            key [
                if 'copy-text = select keymap event/key [
                    copy-text face unlight-text
                ]
            ]
        ]
    ]
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        face/text: value 
        face/line-list: none
    ]
    get-face*: func [face][face/text]
    clear-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        if string? face/text [clear face/text] 
        face/line-list: none
    ]
    reset-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        face/text: copy "" 
        face/line-list: none
    ]
]
style: BANNER
alt-action: none
facets: [255.255.255 font-size 20 doc [info: "video text heading"]]
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if :action [feel: svvf/hot saved-area: true] 
    if all [not flag-face? self as-is string? text] [trim/lines text] 
    if none? text [text: copy ""] 
    change font/colors font/color 
    if none? size [size: -1x-1] 
    xy: size 
    if any [size/x < 0 size/y < 0] [
        state: max 1x1 pane-size * 9 / 10 - offset 
        if size/x < 0 [size/x: state/x] 
        if size/y < 0 [size/y: state/y] 
        size: (size-text self) + (edge-size? self) 
        + (to-pair all [para (to-pair para/margin) + to-pair para/origin])
    ] 
    if xy/x > 0 [size/x: xy/x] 
    if xy/y > 0 [size/y: xy/y]
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [flags text font]
doc: make object! [
    info: "video text heading"
    string: "text contents"
    image: none
    logic: none
    integer: "width of text area"
    pair: "width and height of text area"
    tuple: ["text color" "background color"]
    file: none
    url: none
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]
xy: none

14.17 VH2

type: face
offset: 0x0
size: none
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: none
font: make object! [
    name: "arial"
    style: [bold]
    size: 16
    color: 255.255.255
    offset: 2x2
    space: 0x0
    align: 'center
    valign: 'middle
    shadow: 2x2
    colors: [255.255.255 255.180.75]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: make object! [
    redraw: none
    detect: none
    over: none
    engage: func [face act event][
        switch act [
            down [
                either equal? face focal-face [unlight-text] [focus/no-show face] 
                caret: offset-to-caret face event/offset 
                show face 
                face/action face face/text
            ] 
            up [
                if highlight-start = highlight-end [unfocus]
            ] 
            over [
                if not-equal? caret offset-to-caret face event/offset [
                    if not highlight-start [highlight-start: caret] 
                    highlight-end: caret: offset-to-caret face event/offset 
                    show face
                ]
            ] 
            key [
                if 'copy-text = select keymap event/key [
                    copy-text face unlight-text
                ]
            ]
        ]
    ]
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        face/text: value 
        face/line-list: none
    ]
    get-face*: func [face][face/text]
    clear-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        if string? face/text [clear face/text] 
        face/line-list: none
    ]
    reset-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        face/text: copy "" 
        face/line-list: none
    ]
]
style: VH1
alt-action: none
facets: [font-size 16 shadow 2x2]
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if :action [feel: svvf/hot saved-area: true] 
    if all [not flag-face? self as-is string? text] [trim/lines text] 
    if none? text [text: copy ""] 
    change font/colors font/color 
    if none? size [size: -1x-1] 
    xy: size 
    if any [size/x < 0 size/y < 0] [
        state: max 1x1 pane-size * 9 / 10 - offset 
        if size/x < 0 [size/x: state/x] 
        if size/y < 0 [size/y: state/y] 
        size: (size-text self) + (edge-size? self) 
        + (to-pair all [para (to-pair para/margin) + to-pair para/origin])
    ] 
    if xy/x > 0 [size/x: xy/x] 
    if xy/y > 0 [size/y: xy/y]
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [flags text font]
doc: make object! [
    info: "video text heading"
    string: "text contents"
    image: none
    logic: none
    integer: "width of text area"
    pair: "width and height of text area"
    tuple: ["text color" "background color"]
    file: none
    url: none
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]
xy: none

14.18 VH3

type: face
offset: 0x0
size: none
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: none
font: make object! [
    name: "arial"
    style: [bold italic]
    size: 16
    color: 255.255.255
    offset: 2x2
    space: 0x0
    align: 'center
    valign: 'middle
    shadow: 2x2
    colors: [255.255.255 255.180.75]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: make object! [
    redraw: none
    detect: none
    over: none
    engage: func [face act event][
        switch act [
            down [
                either equal? face focal-face [unlight-text] [focus/no-show face] 
                caret: offset-to-caret face event/offset 
                show face 
                face/action face face/text
            ] 
            up [
                if highlight-start = highlight-end [unfocus]
            ] 
            over [
                if not-equal? caret offset-to-caret face event/offset [
                    if not highlight-start [highlight-start: caret] 
                    highlight-end: caret: offset-to-caret face event/offset 
                    show face
                ]
            ] 
            key [
                if 'copy-text = select keymap event/key [
                    copy-text face unlight-text
                ]
            ]
        ]
    ]
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        face/text: value 
        face/line-list: none
    ]
    get-face*: func [face][face/text]
    clear-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        if string? face/text [clear face/text] 
        face/line-list: none
    ]
    reset-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        face/text: copy "" 
        face/line-list: none
    ]
]
style: VH2
alt-action: none
facets: [font [style: [bold italic]]]
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if :action [feel: svvf/hot saved-area: true] 
    if all [not flag-face? self as-is string? text] [trim/lines text] 
    if none? text [text: copy ""] 
    change font/colors font/color 
    if none? size [size: -1x-1] 
    xy: size 
    if any [size/x < 0 size/y < 0] [
        state: max 1x1 pane-size * 9 / 10 - offset 
        if size/x < 0 [size/x: state/x] 
        if size/y < 0 [size/y: state/y] 
        size: (size-text self) + (edge-size? self) 
        + (to-pair all [para (to-pair para/margin) + to-pair para/origin])
    ] 
    if xy/x > 0 [size/x: xy/x] 
    if xy/y > 0 [size/y: xy/y]
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [flags text]
doc: make object! [
    info: "video text heading"
    string: "text contents"
    image: none
    logic: none
    integer: "width of text area"
    pair: "width and height of text area"
    tuple: ["text color" "background color"]
    file: none
    url: none
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]
xy: none

14.19 VH4

type: face
offset: 0x0
size: none
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: none
font: make object! [
    name: "arial"
    style: [bold]
    size: 14
    color: 255.255.255
    offset: 2x2
    space: 0x0
    align: 'center
    valign: 'middle
    shadow: 2x2
    colors: [255.255.255 255.180.75]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: make object! [
    redraw: none
    detect: none
    over: none
    engage: func [face act event][
        switch act [
            down [
                either equal? face focal-face [unlight-text] [focus/no-show face] 
                caret: offset-to-caret face event/offset 
                show face 
                face/action face face/text
            ] 
            up [
                if highlight-start = highlight-end [unfocus]
            ] 
            over [
                if not-equal? caret offset-to-caret face event/offset [
                    if not highlight-start [highlight-start: caret] 
                    highlight-end: caret: offset-to-caret face event/offset 
                    show face
                ]
            ] 
            key [
                if 'copy-text = select keymap event/key [
                    copy-text face unlight-text
                ]
            ]
        ]
    ]
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        face/text: value 
        face/line-list: none
    ]
    get-face*: func [face][face/text]
    clear-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        if string? face/text [clear face/text] 
        face/line-list: none
    ]
    reset-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        face/text: copy "" 
        face/line-list: none
    ]
]
style: VH2
alt-action: none
facets: [font-size 14]
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if :action [feel: svvf/hot saved-area: true] 
    if all [not flag-face? self as-is string? text] [trim/lines text] 
    if none? text [text: copy ""] 
    change font/colors font/color 
    if none? size [size: -1x-1] 
    xy: size 
    if any [size/x < 0 size/y < 0] [
        state: max 1x1 pane-size * 9 / 10 - offset 
        if size/x < 0 [size/x: state/x] 
        if size/y < 0 [size/y: state/y] 
        size: (size-text self) + (edge-size? self) 
        + (to-pair all [para (to-pair para/margin) + to-pair para/origin])
    ] 
    if xy/x > 0 [size/x: xy/x] 
    if xy/y > 0 [size/y: xy/y]
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [flags text font]
doc: make object! [
    info: "video text heading"
    string: "text contents"
    image: none
    logic: none
    integer: "width of text area"
    pair: "width and height of text area"
    tuple: ["text color" "background color"]
    file: none
    url: none
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]
xy: none

14.20 LABEL

type: face
offset: 0x0
size: none
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: none
font: make object! [
    name: "arial"
    style: [bold]
    size: 12
    color: 255.255.255
    offset: 2x2
    space: 0x0
    align: 'left
    valign: 'middle
    shadow: 1x1
    colors: [255.255.255 255.180.75]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: none
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        face/text: value 
        face/line-list: none
    ]
    get-face*: func [face][face/text]
    clear-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        if string? face/text [clear face/text] 
        face/line-list: none
    ]
    reset-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        face/text: copy "" 
        face/line-list: none
    ]
]
style: VTEXT
alt-action: none
facets: [middle bold feel none doc [info: "label for dark background"]]
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if :action [feel: svvf/hot saved-area: true] 
    if all [not flag-face? self as-is string? text] [trim/lines text] 
    if none? text [text: copy ""] 
    change font/colors font/color 
    if none? size [size: -1x-1] 
    xy: size 
    if any [size/x < 0 size/y < 0] [
        state: max 1x1 pane-size * 9 / 10 - offset 
        if size/x < 0 [size/x: state/x] 
        if size/y < 0 [size/y: state/y] 
        size: (size-text self) + (edge-size? self) 
        + (to-pair all [para (to-pair para/margin) + to-pair para/origin])
    ] 
    if xy/x > 0 [size/x: xy/x] 
    if xy/y > 0 [size/y: xy/y]
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [flags text font]
doc: make object! [
    info: "label for dark background"
    string: "text contents"
    image: none
    logic: none
    integer: "width of text area"
    pair: "width and height of text area"
    tuple: ["text color" "background color"]
    file: none
    url: none
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]
xy: none

14.21 VLAB

type: face
offset: 0x0
size: 72x24
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: none
font: make object! [
    name: "arial"
    style: [bold]
    size: 12
    color: 255.255.255
    offset: 2x2
    space: 0x0
    align: 'right
    valign: 'middle
    shadow: 1x1
    colors: [255.255.255 255.180.75]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: none
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        face/text: value 
        face/line-list: none
    ]
    get-face*: func [face][face/text]
    clear-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        if string? face/text [clear face/text] 
        face/line-list: none
    ]
    reset-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        face/text: copy "" 
        face/line-list: none
    ]
]
style: LABEL
alt-action: none
facets: [72x24 right doc [info: "label for dark forms, right aligned"]]
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if :action [feel: svvf/hot saved-area: true] 
    if all [not flag-face? self as-is string? text] [trim/lines text] 
    if none? text [text: copy ""] 
    change font/colors font/color 
    if none? size [size: -1x-1] 
    xy: size 
    if any [size/x < 0 size/y < 0] [
        state: max 1x1 pane-size * 9 / 10 - offset 
        if size/x < 0 [size/x: state/x] 
        if size/y < 0 [size/y: state/y] 
        size: (size-text self) + (edge-size? self) 
        + (to-pair all [para (to-pair para/margin) + to-pair para/origin])
    ] 
    if xy/x > 0 [size/x: xy/x] 
    if xy/y > 0 [size/y: xy/y]
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [flags text font]
doc: make object! [
    info: "label for dark forms, right aligned"
    string: "text contents"
    image: none
    logic: none
    integer: "width of text area"
    pair: "width and height of text area"
    tuple: ["text color" "background color"]
    file: none
    url: none
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]
xy: none

14.22 LBL

type: face
offset: 0x0
size: none
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: none
font: make object! [
    name: "arial"
    style: [bold]
    size: 12
    color: 0.0.0
    offset: 2x2
    space: 0x0
    align: 'left
    valign: 'middle
    shadow: none
    colors: [255.255.255 255.180.75]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: none
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        face/text: value 
        face/line-list: none
    ]
    get-face*: func [face][face/text]
    clear-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        if string? face/text [clear face/text] 
        face/line-list: none
    ]
    reset-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        face/text: copy "" 
        face/line-list: none
    ]
]
style: TEXT
alt-action: none
facets: [bold middle feel none doc [info: "label for light background"]]
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if :action [feel: svvf/hot saved-area: true] 
    if all [not flag-face? self as-is string? text] [trim/lines text] 
    if none? text [text: copy ""] 
    change font/colors font/color 
    if none? size [size: -1x-1] 
    xy: size 
    if any [size/x < 0 size/y < 0] [
        state: max 1x1 pane-size * 9 / 10 - offset 
        if size/x < 0 [size/x: state/x] 
        if size/y < 0 [size/y: state/y] 
        size: (size-text self) + (edge-size? self) 
        + (to-pair all [para (to-pair para/margin) + to-pair para/origin])
    ] 
    if xy/x > 0 [size/x: xy/x] 
    if xy/y > 0 [size/y: xy/y]
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [flags text font]
doc: make object! [
    info: "label for light background"
    string: "text contents"
    image: none
    logic: none
    integer: "width of text area"
    pair: "width and height of text area"
    tuple: ["text color" "background color"]
    file: none
    url: none
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]
xy: none

14.23 LAB

type: face
offset: 0x0
size: 72x24
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: none
font: make object! [
    name: "arial"
    style: [bold]
    size: 12
    color: 0.0.0
    offset: 2x2
    space: 0x0
    align: 'right
    valign: 'middle
    shadow: none
    colors: [255.255.255 255.180.75]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: none
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        face/text: value 
        face/line-list: none
    ]
    get-face*: func [face][face/text]
    clear-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        if string? face/text [clear face/text] 
        face/line-list: none
    ]
    reset-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        face/text: copy "" 
        face/line-list: none
    ]
]
style: LBL
alt-action: none
facets: [72x24 right doc [info: "label for light forms, right aligned"]]
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if :action [feel: svvf/hot saved-area: true] 
    if all [not flag-face? self as-is string? text] [trim/lines text] 
    if none? text [text: copy ""] 
    change font/colors font/color 
    if none? size [size: -1x-1] 
    xy: size 
    if any [size/x < 0 size/y < 0] [
        state: max 1x1 pane-size * 9 / 10 - offset 
        if size/x < 0 [size/x: state/x] 
        if size/y < 0 [size/y: state/y] 
        size: (size-text self) + (edge-size? self) 
        + (to-pair all [para (to-pair para/margin) + to-pair para/origin])
    ] 
    if xy/x > 0 [size/x: xy/x] 
    if xy/y > 0 [size/y: xy/y]
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [flags text font]
doc: make object! [
    info: "label for light forms, right aligned"
    string: "text contents"
    image: none
    logic: none
    integer: "width of text area"
    pair: "width and height of text area"
    tuple: ["text color" "background color"]
    file: none
    url: none
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]
xy: none

14.24 TITLE

type: face
offset: 0x0
size: none
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: none
font: make object! [
    name: "arial"
    style: [bold]
    size: 24
    color: 0.0.0
    offset: 2x2
    space: 0x0
    align: 'center
    valign: 'middle
    shadow: none
    colors: [255.255.255 255.180.75]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: make object! [
    redraw: none
    detect: none
    over: none
    engage: func [face act event][
        switch act [
            down [
                either equal? face focal-face [unlight-text] [focus/no-show face] 
                caret: offset-to-caret face event/offset 
                show face 
                face/action face face/text
            ] 
            up [
                if highlight-start = highlight-end [unfocus]
            ] 
            over [
                if not-equal? caret offset-to-caret face event/offset [
                    if not highlight-start [highlight-start: caret] 
                    highlight-end: caret: offset-to-caret face event/offset 
                    show face
                ]
            ] 
            key [
                if 'copy-text = select keymap event/key [
                    copy-text face unlight-text
                ]
            ]
        ]
    ]
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        face/text: value 
        face/line-list: none
    ]
    get-face*: func [face][face/text]
    clear-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        if string? face/text [clear face/text] 
        face/line-list: none
    ]
    reset-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        face/text: copy "" 
        face/line-list: none
    ]
]
style: BODY
alt-action: none
facets: [bold font-size 24 center middle doc [info: "document title"]]
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if :action [feel: svvf/hot saved-area: true] 
    if all [not flag-face? self as-is string? text] [trim/lines text] 
    if none? text [text: copy ""] 
    change font/colors font/color 
    if none? size [size: -1x-1] 
    xy: size 
    if any [size/x < 0 size/y < 0] [
        state: max 1x1 pane-size * 9 / 10 - offset 
        if size/x < 0 [size/x: state/x] 
        if size/y < 0 [size/y: state/y] 
        size: (size-text self) + (edge-size? self) 
        + (to-pair all [para (to-pair para/margin) + to-pair para/origin])
    ] 
    if xy/x > 0 [size/x: xy/x] 
    if xy/y > 0 [size/y: xy/y]
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [flags text font]
doc: make object! [
    info: "document title"
    string: "text contents"
    image: none
    logic: none
    integer: "width of text area"
    pair: "width and height of text area"
    tuple: ["text color" "background color"]
    file: none
    url: none
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]
xy: none

14.25 H1

type: face
offset: 0x0
size: none
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: none
font: make object! [
    name: "arial"
    style: [bold]
    size: 20
    color: 0.0.0
    offset: 2x2
    space: 0x0
    align: 'left
    valign: 'top
    shadow: none
    colors: [255.255.255 255.180.75]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: make object! [
    redraw: none
    detect: none
    over: none
    engage: func [face act event][
        switch act [
            down [
                either equal? face focal-face [unlight-text] [focus/no-show face] 
                caret: offset-to-caret face event/offset 
                show face 
                face/action face face/text
            ] 
            up [
                if highlight-start = highlight-end [unfocus]
            ] 
            over [
                if not-equal? caret offset-to-caret face event/offset [
                    if not highlight-start [highlight-start: caret] 
                    highlight-end: caret: offset-to-caret face event/offset 
                    show face
                ]
            ] 
            key [
                if 'copy-text = select keymap event/key [
                    copy-text face unlight-text
                ]
            ]
        ]
    ]
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        face/text: value 
        face/line-list: none
    ]
    get-face*: func [face][face/text]
    clear-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        if string? face/text [clear face/text] 
        face/line-list: none
    ]
    reset-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        face/text: copy "" 
        face/line-list: none
    ]
]
style: BODY
alt-action: none
facets: [bold font-size 20 doc [info: "document heading"]]
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if :action [feel: svvf/hot saved-area: true] 
    if all [not flag-face? self as-is string? text] [trim/lines text] 
    if none? text [text: copy ""] 
    change font/colors font/color 
    if none? size [size: -1x-1] 
    xy: size 
    if any [size/x < 0 size/y < 0] [
        state: max 1x1 pane-size * 9 / 10 - offset 
        if size/x < 0 [size/x: state/x] 
        if size/y < 0 [size/y: state/y] 
        size: (size-text self) + (edge-size? self) 
        + (to-pair all [para (to-pair para/margin) + to-pair para/origin])
    ] 
    if xy/x > 0 [size/x: xy/x] 
    if xy/y > 0 [size/y: xy/y]
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [flags text font]
doc: make object! [
    info: "document heading"
    string: "text contents"
    image: none
    logic: none
    integer: "width of text area"
    pair: "width and height of text area"
    tuple: ["text color" "background color"]
    file: none
    url: none
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]
xy: none

14.26 H2

type: face
offset: 0x0
size: none
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: none
font: make object! [
    name: "arial"
    style: [bold]
    size: 16
    color: 0.0.0
    offset: 2x2
    space: 0x0
    align: 'left
    valign: 'top
    shadow: none
    colors: [255.255.255 255.180.75]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: make object! [
    redraw: none
    detect: none
    over: none
    engage: func [face act event][
        switch act [
            down [
                either equal? face focal-face [unlight-text] [focus/no-show face] 
                caret: offset-to-caret face event/offset 
                show face 
                face/action face face/text
            ] 
            up [
                if highlight-start = highlight-end [unfocus]
            ] 
            over [
                if not-equal? caret offset-to-caret face event/offset [
                    if not highlight-start [highlight-start: caret] 
                    highlight-end: caret: offset-to-caret face event/offset 
                    show face
                ]
            ] 
            key [
                if 'copy-text = select keymap event/key [
                    copy-text face unlight-text
                ]
            ]
        ]
    ]
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        face/text: value 
        face/line-list: none
    ]
    get-face*: func [face][face/text]
    clear-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        if string? face/text [clear face/text] 
        face/line-list: none
    ]
    reset-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        face/text: copy "" 
        face/line-list: none
    ]
]
style: H1
alt-action: none
facets: [font-size 16]
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if :action [feel: svvf/hot saved-area: true] 
    if all [not flag-face? self as-is string? text] [trim/lines text] 
    if none? text [text: copy ""] 
    change font/colors font/color 
    if none? size [size: -1x-1] 
    xy: size 
    if any [size/x < 0 size/y < 0] [
        state: max 1x1 pane-size * 9 / 10 - offset 
        if size/x < 0 [size/x: state/x] 
        if size/y < 0 [size/y: state/y] 
        size: (size-text self) + (edge-size? self) 
        + (to-pair all [para (to-pair para/margin) + to-pair para/origin])
    ] 
    if xy/x > 0 [size/x: xy/x] 
    if xy/y > 0 [size/y: xy/y]
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [flags text font]
doc: make object! [
    info: "document heading"
    string: "text contents"
    image: none
    logic: none
    integer: "width of text area"
    pair: "width and height of text area"
    tuple: ["text color" "background color"]
    file: none
    url: none
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]
xy: none

14.27 H3

type: face
offset: 0x0
size: none
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: none
font: make object! [
    name: "arial"
    style: [bold]
    size: 14
    color: 0.0.0
    offset: 2x2
    space: 0x0
    align: 'left
    valign: 'top
    shadow: none
    colors: [255.255.255 255.180.75]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: make object! [
    redraw: none
    detect: none
    over: none
    engage: func [face act event][
        switch act [
            down [
                either equal? face focal-face [unlight-text] [focus/no-show face] 
                caret: offset-to-caret face event/offset 
                show face 
                face/action face face/text
            ] 
            up [
                if highlight-start = highlight-end [unfocus]
            ] 
            over [
                if not-equal? caret offset-to-caret face event/offset [
                    if not highlight-start [highlight-start: caret] 
                    highlight-end: caret: offset-to-caret face event/offset 
                    show face
                ]
            ] 
            key [
                if 'copy-text = select keymap event/key [
                    copy-text face unlight-text
                ]
            ]
        ]
    ]
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        face/text: value 
        face/line-list: none
    ]
    get-face*: func [face][face/text]
    clear-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        if string? face/text [clear face/text] 
        face/line-list: none
    ]
    reset-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        face/text: copy "" 
        face/line-list: none
    ]
]
style: H2
alt-action: none
facets: [font-size 14]
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if :action [feel: svvf/hot saved-area: true] 
    if all [not flag-face? self as-is string? text] [trim/lines text] 
    if none? text [text: copy ""] 
    change font/colors font/color 
    if none? size [size: -1x-1] 
    xy: size 
    if any [size/x < 0 size/y < 0] [
        state: max 1x1 pane-size * 9 / 10 - offset 
        if size/x < 0 [size/x: state/x] 
        if size/y < 0 [size/y: state/y] 
        size: (size-text self) + (edge-size? self) 
        + (to-pair all [para (to-pair para/margin) + to-pair para/origin])
    ] 
    if xy/x > 0 [size/x: xy/x] 
    if xy/y > 0 [size/y: xy/y]
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [flags text font]
doc: make object! [
    info: "document heading"
    string: "text contents"
    image: none
    logic: none
    integer: "width of text area"
    pair: "width and height of text area"
    tuple: ["text color" "background color"]
    file: none
    url: none
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]
xy: none

14.28 H4

type: face
offset: 0x0
size: none
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: none
font: make object! [
    name: "arial"
    style: [bold]
    size: 12
    color: 0.0.0
    offset: 2x2
    space: 0x0
    align: 'left
    valign: 'top
    shadow: none
    colors: [255.255.255 255.180.75]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: make object! [
    redraw: none
    detect: none
    over: none
    engage: func [face act event][
        switch act [
            down [
                either equal? face focal-face [unlight-text] [focus/no-show face] 
                caret: offset-to-caret face event/offset 
                show face 
                face/action face face/text
            ] 
            up [
                if highlight-start = highlight-end [unfocus]
            ] 
            over [
                if not-equal? caret offset-to-caret face event/offset [
                    if not highlight-start [highlight-start: caret] 
                    highlight-end: caret: offset-to-caret face event/offset 
                    show face
                ]
            ] 
            key [
                if 'copy-text = select keymap event/key [
                    copy-text face unlight-text
                ]
            ]
        ]
    ]
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        face/text: value 
        face/line-list: none
    ]
    get-face*: func [face][face/text]
    clear-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        if string? face/text [clear face/text] 
        face/line-list: none
    ]
    reset-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        face/text: copy "" 
        face/line-list: none
    ]
]
style: H3
alt-action: none
facets: [font-size 12]
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if :action [feel: svvf/hot saved-area: true] 
    if all [not flag-face? self as-is string? text] [trim/lines text] 
    if none? text [text: copy ""] 
    change font/colors font/color 
    if none? size [size: -1x-1] 
    xy: size 
    if any [size/x < 0 size/y < 0] [
        state: max 1x1 pane-size * 9 / 10 - offset 
        if size/x < 0 [size/x: state/x] 
        if size/y < 0 [size/y: state/y] 
        size: (size-text self) + (edge-size? self) 
        + (to-pair all [para (to-pair para/margin) + to-pair para/origin])
    ] 
    if xy/x > 0 [size/x: xy/x] 
    if xy/y > 0 [size/y: xy/y]
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [flags text font]
doc: make object! [
    info: "document heading"
    string: "text contents"
    image: none
    logic: none
    integer: "width of text area"
    pair: "width and height of text area"
    tuple: ["text color" "background color"]
    file: none
    url: none
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]
xy: none

14.29 H5

type: face
offset: 0x0
size: none
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: none
font: make object! [
    name: "arial"
    style: [bold italic]
    size: 12
    color: 0.0.0
    offset: 2x2
    space: 0x0
    align: 'left
    valign: 'top
    shadow: none
    colors: [255.255.255 255.180.75]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: make object! [
    redraw: none
    detect: none
    over: none
    engage: func [face act event][
        switch act [
            down [
                either equal? face focal-face [unlight-text] [focus/no-show face] 
                caret: offset-to-caret face event/offset 
                show face 
                face/action face face/text
            ] 
            up [
                if highlight-start = highlight-end [unfocus]
            ] 
            over [
                if not-equal? caret offset-to-caret face event/offset [
                    if not highlight-start [highlight-start: caret] 
                    highlight-end: caret: offset-to-caret face event/offset 
                    show face
                ]
            ] 
            key [
                if 'copy-text = select keymap event/key [
                    copy-text face unlight-text
                ]
            ]
        ]
    ]
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        face/text: value 
        face/line-list: none
    ]
    get-face*: func [face][face/text]
    clear-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        if string? face/text [clear face/text] 
        face/line-list: none
    ]
    reset-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        face/text: copy "" 
        face/line-list: none
    ]
]
style: H4
alt-action: none
facets: [font [style: [bold italic]]]
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if :action [feel: svvf/hot saved-area: true] 
    if all [not flag-face? self as-is string? text] [trim/lines text] 
    if none? text [text: copy ""] 
    change font/colors font/color 
    if none? size [size: -1x-1] 
    xy: size 
    if any [size/x < 0 size/y < 0] [
        state: max 1x1 pane-size * 9 / 10 - offset 
        if size/x < 0 [size/x: state/x] 
        if size/y < 0 [size/y: state/y] 
        size: (size-text self) + (edge-size? self) 
        + (to-pair all [para (to-pair para/margin) + to-pair para/origin])
    ] 
    if xy/x > 0 [size/x: xy/x] 
    if xy/y > 0 [size/y: xy/y]
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [flags text]
doc: make object! [
    info: "document heading"
    string: "text contents"
    image: none
    logic: none
    integer: "width of text area"
    pair: "width and height of text area"
    tuple: ["text color" "background color"]
    file: none
    url: none
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]
xy: none

14.30 TT

type: face
offset: 0x0
size: none
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: none
font: make object! [
    name: "courier new"
    style: none
    size: 12
    color: 0.0.0
    offset: 2x2
    space: 0x0
    align: 'left
    valign: 'top
    shadow: none
    colors: [255.255.255 255.180.75]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: make object! [
    redraw: none
    detect: none
    over: none
    engage: func [face act event][
        switch act [
            down [
                either equal? face focal-face [unlight-text] [focus/no-show face] 
                caret: offset-to-caret face event/offset 
                show face 
                face/action face face/text
            ] 
            up [
                if highlight-start = highlight-end [unfocus]
            ] 
            over [
                if not-equal? caret offset-to-caret face event/offset [
                    if not highlight-start [highlight-start: caret] 
                    highlight-end: caret: offset-to-caret face event/offset 
                    show face
                ]
            ] 
            key [
                if 'copy-text = select keymap event/key [
                    copy-text face unlight-text
                ]
            ]
        ]
    ]
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        face/text: value 
        face/line-list: none
    ]
    get-face*: func [face][face/text]
    clear-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        if string? face/text [clear face/text] 
        face/line-list: none
    ]
    reset-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        face/text: copy "" 
        face/line-list: none
    ]
]
style: TXT
alt-action: none
facets: [font-name "courier new" doc [info: "typewriter text (monospaced)"]]
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if :action [feel: svvf/hot saved-area: true] 
    if all [not flag-face? self as-is string? text] [trim/lines text] 
    if none? text [text: copy ""] 
    change font/colors font/color 
    if none? size [size: -1x-1] 
    xy: size 
    if any [size/x < 0 size/y < 0] [
        state: max 1x1 pane-size * 9 / 10 - offset 
        if size/x < 0 [size/x: state/x] 
        if size/y < 0 [size/y: state/y] 
        size: (size-text self) + (edge-size? self) 
        + (to-pair all [para (to-pair para/margin) + to-pair para/origin])
    ] 
    if xy/x > 0 [size/x: xy/x] 
    if xy/y > 0 [size/y: xy/y]
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [flags text font]
doc: make object! [
    info: "typewriter text (monospaced)"
    string: "text contents"
    image: none
    logic: none
    integer: "width of text area"
    pair: "width and height of text area"
    tuple: ["text color" "background color"]
    file: none
    url: none
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]
xy: none

14.31 CODE

type: face
offset: 0x0
size: none
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: none
font: make object! [
    name: "courier new"
    style: [bold]
    size: 12
    color: 0.0.0
    offset: 2x2
    space: 0x0
    align: 'left
    valign: 'top
    shadow: none
    colors: [255.255.255 255.180.75]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: make object! [
    redraw: none
    detect: none
    over: none
    engage: func [face act event][
        switch act [
            down [
                either equal? face focal-face [unlight-text] [focus/no-show face] 
                caret: offset-to-caret face event/offset 
                show face 
                face/action face face/text
            ] 
            up [
                if highlight-start = highlight-end [unfocus]
            ] 
            over [
                if not-equal? caret offset-to-caret face event/offset [
                    if not highlight-start [highlight-start: caret] 
                    highlight-end: caret: offset-to-caret face event/offset 
                    show face
                ]
            ] 
            key [
                if 'copy-text = select keymap event/key [
                    copy-text face unlight-text
                ]
            ]
        ]
    ]
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        face/text: value 
        face/line-list: none
    ]
    get-face*: func [face][face/text]
    clear-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        if string? face/text [clear face/text] 
        face/line-list: none
    ]
    reset-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        face/text: copy "" 
        face/line-list: none
    ]
]
style: TT
alt-action: none
facets: [bold doc [info: "source code text (monospaced)"]]
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if :action [feel: svvf/hot saved-area: true] 
    if all [not flag-face? self as-is string? text] [trim/lines text] 
    if none? text [text: copy ""] 
    change font/colors font/color 
    if none? size [size: -1x-1] 
    xy: size 
    if any [size/x < 0 size/y < 0] [
        state: max 1x1 pane-size * 9 / 10 - offset 
        if size/x < 0 [size/x: state/x] 
        if size/y < 0 [size/y: state/y] 
        size: (size-text self) + (edge-size? self) 
        + (to-pair all [para (to-pair para/margin) + to-pair para/origin])
    ] 
    if xy/x > 0 [size/x: xy/x] 
    if xy/y > 0 [size/y: xy/y]
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [flags text font]
doc: make object! [
    info: "source code text (monospaced)"
    string: "text contents"
    image: none
    logic: none
    integer: "width of text area"
    pair: "width and height of text area"
    tuple: ["text color" "background color"]
    file: none
    url: none
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]
xy: none

14.32 BUTTON

type: face
offset: 0x0
size: 100x24
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: make object! [
    color: 110.120.130
    image: none
    effect: 'bevel
    size: 2x2
]
font: make object! [
    name: "arial"
    style: 'bold
    size: 12
    color: 255.255.255
    offset: 2x2
    space: 0x0
    align: 'center
    valign: 'middle
    shadow: 1x1
    colors: [255.255.255 255.180.75]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: make object! [
    redraw: func [face act pos /local state][
        if all [face/texts face/texts/2] [
            face/text: either face/state [face/texts/2] [face/texts/1]
        ] 
        either face/images [
            face/image: either face/state [face/images/2] [face/images/1] 
            if all [face/colors face/effect find face/effect 'colorize] [
                change next find face/effect 'colorize pick face/colors not face/state
            ]
        ] [
            if face/edge [face/edge/effect: pick [ibevel bevel] face/state] 
            state: either not face/state [face/blinker] [true] 
            if face/colors [face/color: pick face/colors not state] 
            if face/effects [face/effect: pick face/effects not state]
        ]
    ]
    detect: none
    over: func [face action event][
        if all [face/font face/font/colors] [
            face/font/color: pick face/font/colors not action 
            show face 
            face/font/color: first face/font/colors
        ]
    ]
    engage: func [face action event][
        switch action [
            time [if not face/state [face/blinker: not face/blinker]] 
            down [face/state: on] 
            alt-down [face/state: on] 
            up [if face/state [do-face face face/text] face/state: off] 
            alt-up [if face/state [do-face-alt face face/text] face/state: off] 
            over [face/state: on] 
            away [face/state: off]
        ] 
        cue face action 
        show face
    ]
    cue: none
    blink: none
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][face/data: value]
    get-face*: func [face][face/data]
    clear-face*: func [face][face/data: false]
    reset-face*: func [face][face/data: false]
]
style: FACE
alt-action: none
facets: [100x24 with [
        color: image: none 
        font: [align: 'center valign: 'middle style: 'bold] 
        edge: [size: 2x2 effect: 'bevel color: svvc/bevel] 
        feel: svvf/button 
        effects: none 
        depth: 128 
        doc: [
            info: "rectangular, rendered buttons" 
            string: ["button label" "button down label"] 
            integer: "width of button" 
            pair: "width and height of button" 
            tuple: ["button color" "button down color"] 
            block: ["execute when clicked" "execute when alt-clicked"] 
            image: ["button background" "background when button down"]
        ] 
        init: [
            edge: make edge [] 
            font/color: first font/colors 
            either image [
                if not effect [
                    effect: copy [fit] 
                    if color [append effect reduce ['colorize color depth]] 
                    if all [colors greater? length? colors 1 not effects] [
                        effects: compose/deep [
                            [fit colorize (first colors) (depth)] 
                            [fit colorize (second colors) (depth)]
                        ]
                    ]
                ]
            ] [
                if not any [effect effects] [
                    either color [
                        effects: reduce [
                            reduce ['gradient 0x1 color + 32 color - 32] 
                            either all [block? colors colors/2] [
                                reduce ['gradient 0x-1 colors/2 + 32 color/2 - 32]
                            ] [
                                reduce ['gradient 0x-1 color + 32 color - 32]
                            ]
                        ]
                    ] [
                        effects: [
                            [gradient 0x1 66.120.192 44.80.132] 
                            [gradient 0x-1 66.120.192 44.80.132]
                        ]
                    ]
                ]
            ] 
            if not color [color: svvc/button]
        ]
    ]]
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    edge: make edge [] 
    font/color: first font/colors 
    either image [
        if not effect [
            effect: copy [fit] 
            if color [append effect reduce ['colorize color depth]] 
            if all [colors greater? length? colors 1 not effects] [
                effects: compose/deep [
                    [fit colorize (first colors) (depth)] 
                    [fit colorize (second colors) (depth)]
                ]
            ]
        ]
    ] [
        if not any [effect effects] [
            either color [
                effects: reduce [
                    reduce ['gradient 0x1 color + 32 color - 32] 
                    either all [block? colors colors/2] [
                        reduce ['gradient 0x-1 colors/2 + 32 color/2 - 32]
                    ] [
                        reduce ['gradient 0x-1 color + 32 color - 32]
                    ]
                ]
            ] [
                effects: [
                    [gradient 0x1 66.120.192 44.80.132] 
                    [gradient 0x-1 66.120.192 44.80.132]
                ]
            ]
        ]
    ] 
    if not color [color: svvc/button]
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: []
doc: make object! [
    info: "rectangular, rendered buttons"
    string: ["button label" "button down label"]
    image: ["button background" "background when button down"]
    logic: none
    integer: "width of button"
    pair: "width and height of button"
    tuple: ["button color" "button down color"]
    file: none
    url: none
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]
effects: none
depth: 128

14.33 CHECK

type: face
offset: 0x0
size: 16x16
span: none
pane: none
text: none
color: 240.240.240
image: none
effect: none
data: none
edge: make object! [
    color: 110.120.130
    image: none
    effect: 'ibevel
    size: 2x2
]
font: none
para: none
feel: make object! [
    redraw: func [face act pos][
        remove find face/effect 'cross 
        if face/data [insert face/effect 'cross] 
        if face/colors [face/color: pick face/colors not face/data] 
        if face/effects [face/effect: pick face/effects not face/data]
    ]
    detect: none
    over: none
    engage: func [face action event][
        if action = 'down [
            reset-related-faces face 
            do-face face face/data: not face/data 
            show face
        ]
    ]
    cue: none
    blink: none
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][face/data: value]
    get-face*: func [face][face/data]
    clear-face*: func [face][face/data: false]
    reset-face*: func [face][face/data: false]
]
style: BUTTON
alt-action: none
facets: [240.240.240 16x16 with [
        set [font para] none 
        feel: svvf/check 
        edge: [effect: 'ibevel] 
        init: [effect: copy []] 
        flags: [check input]
    ]]
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [effect: copy []]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [check input]
doc: make object! [
    info: "rectangular, rendered buttons"
    string: ["button label" "button down label"]
    image: ["button background" "background when button down"]
    logic: none
    integer: "width of button"
    pair: "width and height of button"
    tuple: ["button color" "button down color"]
    file: none
    url: none
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]
effects: none
depth: 128

14.34 CHECK-MARK

type: face
offset: 0x0
size: 13x13
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: none
font: none
para: none
feel: make object! [
    redraw: func [face act pos][
        act: pick face/images (to integer! face/data) + either face/hover [5] [1 + (2 * to integer! face/state)] 
        either face/pane [face/pane/image: act] [face/image: act]
    ]
    detect: none
    over: func [face over offset][
        face/hover: over 
        show face 
        face/hover: off
    ]
    engage: func [face action event][
        switch action [
            down [face/state: on] 
            alt-down [face/state: on] 
            up [
                if face/state [
                    face/state: off 
                    reset-related-faces face 
                    do-face face face/data: not face/data
                ]
            ] 
            alt-up [if face/state [do-face-alt face face/text] face/state: off] 
            over [face/state: on] 
            away [face/state: off]
        ] 
        show face
    ]
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][face/data: value]
    get-face*: func [face][face/data]
    clear-face*: func [face][face/data: false]
    reset-face*: func [face][face/data: false]
]
style: SENSOR
alt-action: none
facets: [with [
        set [font edge para] none 
        feel: svvf/check-radio 
        access: ctx-access/data 
        images: load-stock-block [check check-on check-down check-down-on check-hover check-hover-on] 
        size: images/1/size 
        hover: off 
        flags: [check input] 
        append init [text: none state: off]
    ]]
related: none
words: none
colors: none
texts: none
images: [make image! [13x13 #{
1C51801C51801C51801C51801C51801C51801C51801C51801C51801C5180
1C51801C51801C51801C5180E4E2D9E4E2D9E4E2D9E4E2D9E4E2D9E4E2D9
E9E8E1E9E8E1F0F0EAF0F0EAF4F4F01C51801C5180E4E2D9E4E2D9E4E2D9
E4E2D9E4E2D9E9E8E1E9E8E1F0F0EAF0F0EAF4F4F0F4F4F01C51801C5180
E4E2D9E4E2D9E4E2D9E4E2D9E9E8E1E9E8E1F0F0EAF0F0EAF4F4F0F4F4F0
F4F4F01C51801C5180E4E2D9E4E2D9E4E2D9E9E8E1E9E8E1F0F0EAF0F0EA
F4F4F0F4F4F0F4F4F0FAFAF81C51801C5180E4E2D9E4E2D9E9E8E1E9E8E1
F0F0EAF0F0EAF4F4F0F4F4F0F4F4F0FAFAF8FAFAF81C51801C5180E4E2D9
E9E8E1E9E8E1F0F0EAF0F0EAF4F4F0F4F4F0F4F4F0FAFAF8FAFAF8FAFAF8
1C51801C5180E9E8E1E9E8E1F0F0EAF0F0EAF4F4F0F4F4F0F4F4F0FAFAF8
FAFAF8FAFAF8FAFAF81C51801C5180E9E8E1F0F0EAF0F0EAF4F4F0F4F4F0
F4F4F0FAFAF8FAFAF8FAFAF8FAFAF8FAFAF81C51801C5180F0F0EAF0F0EA
F4F4F0F4F4F0F4F4F0FAFAF8FAFAF8FAFAF8FAFAF8FAFAF8FAFAF81C5180
1C5180F0F0EAF4F4F0F4F4F0F4F4F0FAFAF8FAFAF8FAFAF8FAFAF8FAFAF8
FAFAF8FAFAF81C51801C5180F4F4F0F4F4F0F4F4F0FAFAF8FAFAF8FAFAF8
FAFAF8FAFAF8FAFAF8FAFAF8FAFAF81C51801C51801C51801C51801C5180
1C51801C51801C51801C51801C51801C51801C51801C51801C5180
}] make image! [13x13 #{
1C51801C51801C51801C51801C51801C51801C51801C51801C51801C5180
1C51801C51801C51801C5180E4E2D9E4E2D9E4E2D9E4E2D9E4E2D9E4E2D9
E9E8E1E9E8E1F0F0EAF0F0EAF4F4F01C51801C5180E4E2D9E4E2D9E4E2D9
E4E2D9E4E2D9E9E8E1E9E8E1F0F0EAF0F0EAF4F4F0F4F4F01C51801C5180
E4E2D9E4E2D9E4E2D9E4E2D9E9E8E1E9E8E1F0F0EAF0F0EA009900F4F4F0
F4F4F01C51801C5180E4E2D9E4E2D9E4E2D9E9E8E1E9E8E1F0F0EAF0F0EA
009900009900F4F4F0FAFAF81C51801C5180E4E2D9E4E2D9009900E9E8E1
F0F0EAF0F0EA009900009900009900FAFAF8FAFAF81C51801C5180E4E2D9
E9E8E1009900009900F0F0EA009900009900009900FAFAF8FAFAF8FAFAF8
1C51801C5180E9E8E1E9E8E1009900009900009900009900009900FAFAF8
FAFAF8FAFAF8FAFAF81C51801C5180E9E8E1F0F0EAF0F0EA009900009900
009900FAFAF8FAFAF8FAFAF8FAFAF8FAFAF81C51801C5180F0F0EAF0F0EA
F4F4F0F4F4F0009900FAFAF8FAFAF8FAFAF8FAFAF8FAFAF8FAFAF81C5180
1C5180F0F0EAF4F4F0F4F4F0F4F4F0FAFAF8FAFAF8FAFAF8FAFAF8FAFAF8
FAFAF8FAFAF81C51801C5180F4F4F0F4F4F0F4F4F0FAFAF8FAFAF8FAFAF8
FAFAF8FAFAF8FAFAF8FAFAF8FAFAF81C51801C51801C51801C51801C5180
1C51801C51801C51801C51801C51801C51801C51801C51801C5180
}] make image! [13x13 #{
1C51801C51801C51801C51801C51801C51801C51801C51801C51801C5180
1C51801C51801C51801C5180C7C5B2C7C5B2C7C5B2C7C5B2C7C5B2C7C5B2
C7C5B2C9C7BAC9C7BAD7D4CAD7D4CA1C51801C5180C7C5B2C7C5B2C7C5B2
C7C5B2C7C5B2C7C5B2C9C7BAC9C7BAD7D4CAD7D4CAD7D4CA1C51801C5180
C7C5B2C7C5B2C7C5B2C7C5B2C7C5B2C9C7BAC9C7BAD7D4CAD7D4CAD7D4CA
D7D4CA1C51801C5180C7C5B2C7C5B2C7C5B2C7C5B2C9C7BAC9C7BAD7D4CA
D7D4CAD7D4CAD7D4CAE4E2D91C51801C5180C7C5B2C7C5B2C7C5B2C9C7BA
C9C7BAD7D4CAD7D4CAD7D4CAE4E2D9E4E2D9E4E2D91C51801C5180C7C5B2
C7C5B2C9C7BAC9C7BAD7D4CAD7D4CAD7D4CAE4E2D9E4E2D9E4E2D9E4E2D9
1C51801C5180C7C5B2C9C7BAC9C7BAD7D4CAD7D4CAD7D4CAE4E2D9E4E2D9
E4E2D9E9E8E1E4E2D91C51801C5180C9C7BAC9C7BAD7D4CAD7D4CAD7D4CA
E4E2D9E4E2D9E4E2D9E9E8E1E9E8E1E9E8E11C51801C5180C9C7BAD7D4CA
D7D4CAD7D4CAE4E2D9E4E2D9E4E2D9E9E8E1E9E8E1E9E8E1E9E8E11C5180
1C5180D7D4CAD7D4CAD7D4CAD7D4CAE4E2D9E4E2D9E9E8E1E9E8E1E9E8E1
E9E8E1E9E8E11C51801C5180D7D4CAD7D4CAD7D4CAE4E2D9E4E2D9E4E2D9
E9E8E1E9E8E1E9E8E1E9E8E1E9E8E11C51801C51801C51801C51801C5180
1C51801C51801C51801C51801C51801C51801C51801C51801C5180
}] make image! [13x13 #{
1C51801C51801C51801C51801C51801C51801C51801C51801C51801C5180
1C51801C51801C51801C5180C7C5B2C7C5B2C7C5B2C7C5B2C7C5B2C7C5B2
C7C5B2C9C7BAC9C7BAD7D4CAD7D4CA1C51801C5180C7C5B2C7C5B2C7C5B2
C7C5B2C7C5B2C7C5B2C9C7BAC9C7BAD7D4CAD7D4CAD7D4CA1C51801C5180
C7C5B2C7C5B2C7C5B2C7C5B2C7C5B2C9C7BAC9C7BAD7D4CA267C08D7D4CA
D7D4CA1C51801C5180C7C5B2C7C5B2C7C5B2C7C5B2C9C7BAC9C7BAD7D4CA
267C08267C08D7D4CAE4E2D91C51801C5180C7C5B2C7C5B2267C08C9C7BA
C9C7BAD7D4CA267C08267C08267C08E4E2D9E4E2D91C51801C5180C7C5B2
C7C5B2267C08267C08D7D4CA267C08267C08267C08E4E2D9E4E2D9E4E2D9
1C51801C5180C7C5B2C9C7BA267C08267C08267C08267C08267C08E4E2D9
E4E2D9E9E8E1E4E2D91C51801C5180C9C7BAC9C7BAD7D4CA267C08267C08
267C08E4E2D9E4E2D9E9E8E1E9E8E1E9E8E11C51801C5180C9C7BAD7D4CA
D7D4CAD7D4CA267C08E4E2D9E4E2D9E9E8E1E9E8E1E9E8E1E9E8E11C5180
1C5180D7D4CAD7D4CAD7D4CAD7D4CAE4E2D9E4E2D9E9E8E1E9E8E1E9E8E1
E9E8E1E9E8E11C51801C5180D7D4CAD7D4CAD7D4CAE4E2D9E4E2D9E4E2D9
E9E8E1E9E8E1E9E8E1E9E8E1E9E8E11C51801C51801C51801C51801C5180
1C51801C51801C51801C51801C51801C51801C51801C51801C5180
}] make image! [13x13 #{
1C51801C51801C51801C51801C51801C51801C51801C51801C51801C5180
1C51801C51801C51801C5180FEDF9AFEDF9AFCD27AFCD27AFCD27AFCD27A
FAC761FCD27AFCD27AFAC761F9BE4B1C51801C5180FEDF9AFCD27AFCD27A
FCD27AFCD27AFAC761FCD27AFCD27AFCD27AFCD27AFAC7611C51801C5180
FEDF9AFEDF9AE4E2D9E4E2D9E9E8E1E9E8E1F0F0EAF0F0EAF4F4F0FCD27A
FAC7611C51801C5180FEDF9AFEDF9AE4E2D9E9E8E1E9E8E1F0F0EAF0F0EA
F4F4F0F4F4F0FCD27AFAC7611C51801C5180FCD27AFEDF9AE9E8E1E9E8E1
F0F0EAF0F0EAF4F4F0F4F4F0F4F4F0FCD27AFAC7611C51801C5180FCD27A
FEDF9AE9E8E1F0F0EAF0F0EAF4F4F0F4F4F0F4F4F0FAFAF8FCD27AF9BE4B
1C51801C5180FCD27AFEDF9AF0F0EAF0F0EAF4F4F0F4F4F0F4F4F0FAFAF8
FAFAF8F9BE4BF8B4351C51801C5180FCD27AFCD27AF0F0EAF4F4F0F4F4F0
F4F4F0FAFAF8FAFAF8FAFAF8F8B435F8B4351C51801C5180FAC761FAC761
F4F4F0F4F4F0F4F4F0FAFAF8FAFAF8FAFAF8FAFAF8F8B435E597001C5180
1C5180F9BE4BF9BE4BFAC761FCD27AFCD27AFCD27AF9BE4BF8B435F8B435
F8B435E597001C51801C5180F9BE4BF9BE4BF9BE4BFAC761FAC761F9BE4B
F8B435F8B435E59700E59700F8B4351C51801C51801C51801C51801C5180
1C51801C51801C51801C51801C51801C51801C51801C51801C5180
}] make image! [13x13 #{
1C51801C51801C51801C51801C51801C51801C51801C51801C51801C5180
1C51801C51801C51801C5180FEDF9AFEDF9AFCD27AFCD27AFCD27AFCD27A
FAC761FCD27AFCD27AFAC761F9BE4B1C51801C5180FEDF9AFCD27AFCD27A
FCD27AFCD27AFAC761FCD27AFCD27AFCD27AFCD27AFAC7611C51801C5180
FEDF9AFEDF9AE4E2D9E4E2D9E9E8E1E9E8E1F0F0EAF0F0EA009900FCD27A
FAC7611C51801C5180FEDF9AFEDF9AE4E2D9E9E8E1E9E8E1F0F0EAF0F0EA
009900009900FCD27AFAC7611C51801C5180FCD27AFEDF9A009900E9E8E1
F0F0EAF0F0EA009900009900009900FCD27AFAC7611C51801C5180FCD27A
FEDF9A009900009900F0F0EA009900009900009900FAFAF8FCD27AF9BE4B
1C51801C5180FCD27AFEDF9A009900009900009900009900009900FAFAF8
FAFAF8F9BE4BF8B4351C51801C5180FCD27AFCD27AF0F0EA009900009900
009900FAFAF8FAFAF8FAFAF8F8B435F8B4351C51801C5180FAC761FAC761
F4F4F0F4F4F0009900FAFAF8FAFAF8FAFAF8FAFAF8F8B435E597001C5180
1C5180F9BE4BF9BE4BFAC761FCD27AFCD27AFCD27AF9BE4BF8B435F8B435
F8B435E597001C51801C5180F9BE4BF9BE4BF9BE4BFAC761FAC761F9BE4B
F8B435F8B435E59700E59700F8B4351C51801C51801C51801C51801C5180
1C51801C51801C51801C51801C51801C51801C51801C51801C5180
}]]
file: none
var: none
keycode: none
reset: none
styles: none
init: [if none? size [size: 100x100] text: none state: off]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [check input]
doc: make object! [
    info: "transparent sensor area"
    string: none
    image: none
    logic: none
    integer: none
    pair: "size of sensor"
    tuple: none
    file: none
    url: none
    decimal: none
    time: none
    block: none
    keywords: none
]
hover: false

14.35 RADIO

type: face
offset: 0x0
size: 13x13
span: none
pane: none
text: none
color: none
image: none
effect: [anti-alias]
data: none
edge: none
font: none
para: none
feel: make object! [
    redraw: func [face act pos][
        act: pick face/images (to integer! face/data) + either face/hover [5] [1 + (2 * to integer! face/state)] 
        either face/pane [face/pane/image: act] [face/image: act]
    ]
    detect: none
    over: func [face over offset][
        face/hover: over 
        show face 
        face/hover: off
    ]
    engage: func [face action event][
        switch action [
            down [face/state: on] 
            alt-down [face/state: on] 
            up [
                if face/state [
                    face/state: off 
                    reset-related-faces face 
                    do-face face face/data: not face/data
                ]
            ] 
            alt-up [if face/state [do-face-alt face face/text] face/state: off] 
            over [face/state: on] 
            away [face/state: off]
        ] 
        show face
    ]
]
saved-area: true
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][face/data: value]
    get-face*: func [face][face/data]
    clear-face*: func [face][face/data: false]
    reset-face*: func [face][face/data: false]
]
style: CHECK-MARK
alt-action: none
facets: [with [
        images: load-stock-block [radio radio-on radio-down radio-down-on radio-hover radio-hover-on] 
        size: images/1/size 
        effect: [anti-alias] 
        related: 'default 
        saved-area: true 
        flags: [radio input]
    ]]
related: default
words: none
colors: none
texts: none
images: [make image! [13x13 #{
000000000000000000000000000000003366003366003366000000000000
0000000000000000000000000000000000000033660033668BA9E58BA9E5
8BA9E50033660033660000000000000000000000000000000033668BA9E5
E4E2D9E4E2D9E9E8E1E9E8E1F0F0EA8BA9E5003366000000000000000000
0033668BA9E5E4E2D9E4E2D9E9E8E1E9E8E1F0F0EAF0F0EAF4F4F08BA9E5
003366000000000000003366E4E2D9E4E2D9E9E8E1E9E8E1F0F0EAF0F0EA
F4F4F0F4F4F0F4F4F00033660000000033668BA9E5E4E2D9E9E8E1E9E8E1
F0F0EAF0F0EAF4F4F0F4F4F0F4F4F0FAFAF88BA9E50033660033668BA9E5
E9E8E1E9E8E1F0F0EAF0F0EAF4F4F0F4F4F0F4F4F0FAFAF8FAFAF88BA9E5
0033660033668BA9E5E9E8E1F0F0EAF0F0EAF4F4F0F4F4F0F4F4F0FAFAF8
FAFAF8FAFAF88BA9E5003366000000003366F0F0EAF0F0EAF4F4F0F4F4F0
F4F4F0FAFAF8FAFAF8FAFAF8FAFAF80033660000000000000033668BA9E5
F4F4F0F4F4F0F4F4F0FAFAF8FAFAF8FAFAF8FAFAF88BA9E5003366000000
0000000000000033668BA9E5F4F4F0FAFAF8FAFAF8FAFAF8FAFAF88BA9E5
0033660000000000000000000000000000000033660033668BA9E58BA9E5
8BA9E5003366003366000000000000000000000000000000000000000000
000000003366003366003366000000000000000000000000000000
} #{
FFFFFFFFFF000000FFFF
FFFFFFFFFFFF00000000
000000FFFFFFFFFF0000
00000000000000FFFFFF
00000000000000000000
00FFFF00000000000000
00000000FF0000000000
00000000000000000000
00000000000000000000
00000000000000000000
00000000FF0000000000
000000000000FFFF0000
000000000000000000FF
FFFF0000000000000000
00FFFFFFFFFF00000000
000000FFFFFFFFFFFFFF
FF000000FFFFFFFFFF
}] make image! [13x13 #{
000000000000000000000000000000003366003366003366000000000000
0000000000000000000000000000000000000033660033668BA9E58BA9E5
8BA9E50033660033660000000000000000000000000000000033668BA9E5
E4E2D9E4E2D9E9E8E1E9E8E1F0F0EA8BA9E5003366000000000000000000
0033668BA9E5E4E2D9E4E2D9E9E8E1E9E8E1F0F0EAF0F0EAF4F4F08BA9E5
003366000000000000003366E4E2D9E4E2D9E9E8E122C02022C02022C020
F4F4F0F4F4F0F4F4F00033660000000033668BA9E5E4E2D9E9E8E122C020
22C020009900009900267C08F4F4F0FAFAF88BA9E50033660033668BA9E5
E9E8E1E9E8E122C020009900009900009900267C08FAFAF8FAFAF88BA9E5
0033660033668BA9E5E9E8E1F0F0EA22C020009900009900267C08267C08
FAFAF8FAFAF88BA9E5003366000000003366F0F0EAF0F0EAF4F4F0267C08
267C08267C08FAFAF8FAFAF8FAFAF80033660000000000000033668BA9E5
F4F4F0F4F4F0F4F4F0FAFAF8FAFAF8FAFAF8FAFAF88BA9E5003366000000
0000000000000033668BA9E5F4F4F0FAFAF8FAFAF8FAFAF8FAFAF88BA9E5
0033660000000000000000000000000000000033660033668BA9E58BA9E5
8BA9E5003366003366000000000000000000000000000000000000000000
000000003366003366003366000000000000000000000000000000
} #{
FFFFFFFFFF000000FFFF
FFFFFFFFFFFF00000000
000000FFFFFFFFFF0000
00000000000000FFFFFF
00000000000000000000
00FFFF00000000000000
00000000FF0000000000
00000000000000000000
00000000000000000000
00000000000000000000
00000000FF0000000000
000000000000FFFF0000
000000000000000000FF
FFFF0000000000000000
00FFFFFFFFFF00000000
000000FFFFFFFFFFFFFF
FF000000FFFFFFFFFF
}] make image! [13x13 #{
000000000000000000000000000000003366003366003366000000000000
0000000000000000000000000000000000000033660033666487DC6487DC
6487DC0033660033660000000000000000000000000000000033666487DC
C7C5B2C7C5B2C7C5B2C9C7BAC9C7BA6487DC003366000000000000000000
0033666487DCC7C5B2C7C5B2C7C5B2C9C7BAC9C7BAD7D4CAD7D4CA6487DC
003366000000000000003366C7C5B2C7C5B2C7C5B2C9C7BAC9C7BAD7D4CA
D7D4CAD7D4CAD7D4CA0033660000000033666487DCC7C5B2C7C5B2C9C7BA
C9C7BAD7D4CAD7D4CAD7D4CAE4E2D9E4E2D96487DC0033660033666487DC
C7C5B2C9C7BAC9C7BAD7D4CAD7D4CAD7D4CAE4E2D9E4E2D9E4E2D96487DC
0033660033666487DCC9C7BAC9C7BAD7D4CAD7D4CAD7D4CAE4E2D9E4E2D9
E4E2D9E9E8E16487DC003366000000003366C9C7BAD7D4CAD7D4CAD7D4CA
E4E2D9E4E2D9E4E2D9E9E8E1E9E8E10033660000000000000033666487DC
D7D4CAD7D4CAE4E2D9E4E2D9E4E2D9E9E8E1E9E8E16487DC003366000000
0000000000000033666487DCD7D4CAE4E2D9E4E2D9E9E8E1E9E8E16487DC
0033660000000000000000000000000000000033660033666487DC6487DC
6487DC003366003366000000000000000000000000000000000000000000
000000003366003366003366000000000000000000000000000000
} #{
FFFFFFFFFF000000FFFF
FFFFFFFFFFFF00000000
000000FFFFFFFFFF0000
00000000000000FFFFFF
00000000000000000000
00FFFF00000000000000
00000000FF0000000000
00000000000000000000
00000000000000000000
00000000000000000000
00000000FF0000000000
000000000000FFFF0000
000000000000000000FF
FFFF0000000000000000
00FFFFFFFFFF00000000
000000FFFFFFFFFFFFFF
FF000000FFFFFFFFFF
}] make image! [13x13 #{
000000000000000000000000000000003366003366003366000000000000
0000000000000000000000000000000000000033660033666487DC6487DC
6487DC0033660033660000000000000000000000000000000033666487DC
C7C5B2C7C5B2C7C5B2C9C7BAC9C7BA6487DC003366000000000000000000
0033666487DCC7C5B2C7C5B2C7C5B2C9C7BAC9C7BAD7D4CAD7D4CA6487DC
003366000000000000003366C7C5B2C7C5B2C7C5B222C02022C02022C020
D7D4CAD7D4CAD7D4CA0033660000000033666487DCC7C5B2C7C5B222C020
22C020009900009900267C08E4E2D9E4E2D96487DC0033660033666487DC
C7C5B2C9C7BA22C020009900009900009900267C08E4E2D9E4E2D96487DC
0033660033666487DCC9C7BAC9C7BA22C020009900009900267C08267C08
E4E2D9E9E8E16487DC003366000000003366C9C7BAD7D4CAD7D4CA267C08
267C08267C08E4E2D9E9E8E1E9E8E10033660000000000000033666487DC
D7D4CAD7D4CAE4E2D9E4E2D9E4E2D9E9E8E1E9E8E16487DC003366000000
0000000000000033666487DCD7D4CAE4E2D9E4E2D9E9E8E1E9E8E16487DC
0033660000000000000000000000000000000033660033666487DC6487DC
6487DC003366003366000000000000000000000000000000000000000000
000000003366003366003366000000000000000000000000000000
} #{
FFFFFFFFFF000000FFFF
FFFFFFFFFFFF00000000
000000FFFFFFFFFF0000
00000000000000FFFFFF
00000000000000000000
00FFFF00000000000000
00000000FF0000000000
00000000000000000000
00000000000000000000
00000000000000000000
00000000FF0000000000
000000000000FFFF0000
000000000000000000FF
FFFF0000000000000000
00FFFFFFFFFF00000000
000000FFFFFFFFFFFFFF
FF000000FFFFFFFFFF
}] make image! [13x13 #{
000000000000000000000000000000003366003366003366000000000000
000000000000000000000000000000000000003366003366BB9955B9B5A9
BB9955003366003366000000000000000000000000000000003366BB9955
E9E8E1FEDF9AFCD27AFEDF9AFCD27ABB9955003366000000000000000000
003366BB9955E9E8E1FEDF9AF8B435E9E8E1F8B435F9BE4BFAC761BB9955
003366000000000000003366FAFAF8FEDF9AE9E8E1E9E8E1F0F0EAF0F0EA
F4F4F0FAC761F9BE4B003366000000003366BB9955FEDF9AF8B435E9E8E1
F0F0EAF0F0EAF4F4F0F4F4F0F8B435F9BE4BBB9955003366003366B9B5A9
FCD27AE9E8E1F0F0EAF0F0EAF4F4F0F4F4F0F4F4F0FAFAF8F8B435BB9955
003366003366BB9955FEDF9AF8B435F0F0EAF4F4F0F4F4F0F4F4F0FAFAF8
F8B435F9BE4BBB9955003366000000003366FCD27AF9BE4BF4F4F0F4F4F0
F4F4F0FAFAF8FAFAF8F8B435F8B435003366000000000000003366BB9955
FAC761FAC761F8B435FAFAF8F8B435F8B435F8B435BB9955003366000000
000000000000003366BB9955F9BE4BF9BE4BF8B435F9BE4BF8B435BB9955
003366000000000000000000000000000000003366003366BB9955BB9955
BB9955003366003366000000000000000000000000000000000000000000
000000003366003366003366000000000000000000000000000000
} #{
FFFFFFFFFF000000FFFF
FFFFFFFFFFFF00000000
000000FFFFFFFFFF0000
00000000000000FFFFFF
00000000000000000000
00FFFF00000000000000
00000000FF0000000000
00000000000000000000
00000000000000000000
00000000000000000000
00000000FF0000000000
000000000000FFFF0000
000000000000000000FF
FFFF0000000000000000
00FFFFFFFFFF00000000
000000FFFFFFFFFFFFFF
FF000000FFFFFFFFFF
}] make image! [13x13 #{
000000000000000000000000000000003366003366003366000000000000
000000000000000000000000000000000000003366003366C7C5B2B9B5A9
C7C5B2003366003366000000000000000000000000000000003366C7C5B2
E9E8E1FEDF9AFCD27AFEDF9AFCD27ABB9955003366000000000000000000
003366C7C5B2E9E8E1FEDF9AFEDF9AFFFFFFFEDF9AF9BE4BFAC761BB9955
003366000000000000003366FAFAF8FEDF9AFFFFFF22C02022C02022C020
F4F4F0FAC761F9BE4B003366000000003366C7C5B2FEDF9AFEDF9A22C020
22C020009900009900267C08FEDF9AF9BE4BBB9955003366003366B9B5A9
FCD27AFFFFFF22C020009900009900009900267C08FAFAF8F8B435BB9955
003366003366C7C5B2FEDF9AFEDF9A22C020009900009900267C08267C08
FEDF9AF9BE4BBB9955003366000000003366FCD27AF9BE4BF4F4F0267C08
267C08267C08FAFAF8F9BE4BF8B435003366000000000000003366BB9955
FAC761FAC761FEDF9AFAFAF8FEDF9AF9BE4BF8B435BB9955003366000000
000000000000003366BB9955F9BE4BF9BE4BF8B435F9BE4BF8B435BB9955
003366000000000000000000000000000000003366003366BB9955BB9955
BB9955003366003366000000000000000000000000000000000000000000
000000003366003366003366000000000000000000000000000000
} #{
FFFFFFFFFF000000FFFF
FFFFFFFFFFFF00000000
000000FFFFFFFFFF0000
00000000000000FFFFFF
00000000000000000000
00FFFF00000000000000
00000000FF0000000000
00000000000000000000
00000000000000000000
00000000000000000000
00000000FF0000000000
000000000000FFFF0000
000000000000000000FF
FFFF0000000000000000
00FFFFFFFFFF00000000
000000FFFFFFFFFFFFFF
FF000000FFFFFFFFFF
}]]
file: none
var: none
keycode: none
reset: none
styles: none
init: [if none? size [size: 100x100] text: none state: off]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [radio input]
doc: make object! [
    info: "transparent sensor area"
    string: none
    image: none
    logic: none
    integer: none
    pair: "size of sensor"
    tuple: none
    file: none
    url: none
    decimal: none
    time: none
    block: none
    keywords: none
]
hover: false

14.36 CHECK-LINE

type: face
offset: 0x0
size: none
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: none
font: make object! [
    name: "arial"
    style: none
    size: 12
    color: 0.0.0
    offset: 2x2
    space: 0x0
    align: 'left
    valign: 'middle
    shadow: none
    colors: [0.0.0 40.40.40]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: make object! [
    redraw: func [face act pos][
        act: pick face/images (to integer! face/data) + either face/hover [5] [1 + (2 * to integer! face/state)] 
        either face/pane [face/pane/image: act] [face/image: act]
    ]
    detect: none
    over: func [face over offset][
        face/hover: over 
        show face 
        face/hover: off
    ]
    engage: func [face action event][
        switch action [
            down [face/state: on] 
            alt-down [face/state: on] 
            up [
                if face/state [
                    face/state: off 
                    reset-related-faces face 
                    do-face face face/data: not face/data
                ]
            ] 
            alt-up [if face/state [do-face-alt face face/text] face/state: off] 
            over [face/state: on] 
            away [face/state: off]
        ] 
        show face
    ]
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][face/data: value]
    get-face*: func [face][face/data]
    clear-face*: func [face][face/data: false]
    reset-face*: func [face][face/data: false]
]
style: BASE-TEXT
alt-action: none
facets: [middle with [
        images: load-stock-block [check check-on check-down check-down-on check-hover check-hover-on] 
        feel: svvf/check-radio 
        access: ctx-access/data 
        edge-size: none 
        hover: false 
        pad: 5 
        flags: [check input] 
        insert init [
            pane: make-face/spec 'check compose [
                size: (images/1/size) 
                offset: 2x2 
                feel: edge: color: none
            ] 
            para: make para [] 
            either font/align = 'right [
                para/margin/x: pane/size/x + pad
            ] [
                para/origin/x: pane/size/x + pad
            ]
        ] 
        append init [
            state: off 
            edge-size: edge-size? self 
            pane/offset/y: size/y - edge-size/y + 1 - pane/size/y / 2 
            all [font/align = 'right pane/offset/x: size/x - edge-size/x - 2 - pane/size/x]
        ]
    ]]
related: none
words: none
colors: none
texts: none
images: [make image! [13x13 #{
1C51801C51801C51801C51801C51801C51801C51801C51801C51801C5180
1C51801C51801C51801C5180E4E2D9E4E2D9E4E2D9E4E2D9E4E2D9E4E2D9
E9E8E1E9E8E1F0F0EAF0F0EAF4F4F01C51801C5180E4E2D9E4E2D9E4E2D9
E4E2D9E4E2D9E9E8E1E9E8E1F0F0EAF0F0EAF4F4F0F4F4F01C51801C5180
E4E2D9E4E2D9E4E2D9E4E2D9E9E8E1E9E8E1F0F0EAF0F0EAF4F4F0F4F4F0
F4F4F01C51801C5180E4E2D9E4E2D9E4E2D9E9E8E1E9E8E1F0F0EAF0F0EA
F4F4F0F4F4F0F4F4F0FAFAF81C51801C5180E4E2D9E4E2D9E9E8E1E9E8E1
F0F0EAF0F0EAF4F4F0F4F4F0F4F4F0FAFAF8FAFAF81C51801C5180E4E2D9
E9E8E1E9E8E1F0F0EAF0F0EAF4F4F0F4F4F0F4F4F0FAFAF8FAFAF8FAFAF8
1C51801C5180E9E8E1E9E8E1F0F0EAF0F0EAF4F4F0F4F4F0F4F4F0FAFAF8
FAFAF8FAFAF8FAFAF81C51801C5180E9E8E1F0F0EAF0F0EAF4F4F0F4F4F0
F4F4F0FAFAF8FAFAF8FAFAF8FAFAF8FAFAF81C51801C5180F0F0EAF0F0EA
F4F4F0F4F4F0F4F4F0FAFAF8FAFAF8FAFAF8FAFAF8FAFAF8FAFAF81C5180
1C5180F0F0EAF4F4F0F4F4F0F4F4F0FAFAF8FAFAF8FAFAF8FAFAF8FAFAF8
FAFAF8FAFAF81C51801C5180F4F4F0F4F4F0F4F4F0FAFAF8FAFAF8FAFAF8
FAFAF8FAFAF8FAFAF8FAFAF8FAFAF81C51801C51801C51801C51801C5180
1C51801C51801C51801C51801C51801C51801C51801C51801C5180
}] make image! [13x13 #{
1C51801C51801C51801C51801C51801C51801C51801C51801C51801C5180
1C51801C51801C51801C5180E4E2D9E4E2D9E4E2D9E4E2D9E4E2D9E4E2D9
E9E8E1E9E8E1F0F0EAF0F0EAF4F4F01C51801C5180E4E2D9E4E2D9E4E2D9
E4E2D9E4E2D9E9E8E1E9E8E1F0F0EAF0F0EAF4F4F0F4F4F01C51801C5180
E4E2D9E4E2D9E4E2D9E4E2D9E9E8E1E9E8E1F0F0EAF0F0EA009900F4F4F0
F4F4F01C51801C5180E4E2D9E4E2D9E4E2D9E9E8E1E9E8E1F0F0EAF0F0EA
009900009900F4F4F0FAFAF81C51801C5180E4E2D9E4E2D9009900E9E8E1
F0F0EAF0F0EA009900009900009900FAFAF8FAFAF81C51801C5180E4E2D9
E9E8E1009900009900F0F0EA009900009900009900FAFAF8FAFAF8FAFAF8
1C51801C5180E9E8E1E9E8E1009900009900009900009900009900FAFAF8
FAFAF8FAFAF8FAFAF81C51801C5180E9E8E1F0F0EAF0F0EA009900009900
009900FAFAF8FAFAF8FAFAF8FAFAF8FAFAF81C51801C5180F0F0EAF0F0EA
F4F4F0F4F4F0009900FAFAF8FAFAF8FAFAF8FAFAF8FAFAF8FAFAF81C5180
1C5180F0F0EAF4F4F0F4F4F0F4F4F0FAFAF8FAFAF8FAFAF8FAFAF8FAFAF8
FAFAF8FAFAF81C51801C5180F4F4F0F4F4F0F4F4F0FAFAF8FAFAF8FAFAF8
FAFAF8FAFAF8FAFAF8FAFAF8FAFAF81C51801C51801C51801C51801C5180
1C51801C51801C51801C51801C51801C51801C51801C51801C5180
}] make image! [13x13 #{
1C51801C51801C51801C51801C51801C51801C51801C51801C51801C5180
1C51801C51801C51801C5180C7C5B2C7C5B2C7C5B2C7C5B2C7C5B2C7C5B2
C7C5B2C9C7BAC9C7BAD7D4CAD7D4CA1C51801C5180C7C5B2C7C5B2C7C5B2
C7C5B2C7C5B2C7C5B2C9C7BAC9C7BAD7D4CAD7D4CAD7D4CA1C51801C5180
C7C5B2C7C5B2C7C5B2C7C5B2C7C5B2C9C7BAC9C7BAD7D4CAD7D4CAD7D4CA
D7D4CA1C51801C5180C7C5B2C7C5B2C7C5B2C7C5B2C9C7BAC9C7BAD7D4CA
D7D4CAD7D4CAD7D4CAE4E2D91C51801C5180C7C5B2C7C5B2C7C5B2C9C7BA
C9C7BAD7D4CAD7D4CAD7D4CAE4E2D9E4E2D9E4E2D91C51801C5180C7C5B2
C7C5B2C9C7BAC9C7BAD7D4CAD7D4CAD7D4CAE4E2D9E4E2D9E4E2D9E4E2D9
1C51801C5180C7C5B2C9C7BAC9C7BAD7D4CAD7D4CAD7D4CAE4E2D9E4E2D9
E4E2D9E9E8E1E4E2D91C51801C5180C9C7BAC9C7BAD7D4CAD7D4CAD7D4CA
E4E2D9E4E2D9E4E2D9E9E8E1E9E8E1E9E8E11C51801C5180C9C7BAD7D4CA
D7D4CAD7D4CAE4E2D9E4E2D9E4E2D9E9E8E1E9E8E1E9E8E1E9E8E11C5180
1C5180D7D4CAD7D4CAD7D4CAD7D4CAE4E2D9E4E2D9E9E8E1E9E8E1E9E8E1
E9E8E1E9E8E11C51801C5180D7D4CAD7D4CAD7D4CAE4E2D9E4E2D9E4E2D9
E9E8E1E9E8E1E9E8E1E9E8E1E9E8E11C51801C51801C51801C51801C5180
1C51801C51801C51801C51801C51801C51801C51801C51801C5180
}] make image! [13x13 #{
1C51801C51801C51801C51801C51801C51801C51801C51801C51801C5180
1C51801C51801C51801C5180C7C5B2C7C5B2C7C5B2C7C5B2C7C5B2C7C5B2
C7C5B2C9C7BAC9C7BAD7D4CAD7D4CA1C51801C5180C7C5B2C7C5B2C7C5B2
C7C5B2C7C5B2C7C5B2C9C7BAC9C7BAD7D4CAD7D4CAD7D4CA1C51801C5180
C7C5B2C7C5B2C7C5B2C7C5B2C7C5B2C9C7BAC9C7BAD7D4CA267C08D7D4CA
D7D4CA1C51801C5180C7C5B2C7C5B2C7C5B2C7C5B2C9C7BAC9C7BAD7D4CA
267C08267C08D7D4CAE4E2D91C51801C5180C7C5B2C7C5B2267C08C9C7BA
C9C7BAD7D4CA267C08267C08267C08E4E2D9E4E2D91C51801C5180C7C5B2
C7C5B2267C08267C08D7D4CA267C08267C08267C08E4E2D9E4E2D9E4E2D9
1C51801C5180C7C5B2C9C7BA267C08267C08267C08267C08267C08E4E2D9
E4E2D9E9E8E1E4E2D91C51801C5180C9C7BAC9C7BAD7D4CA267C08267C08
267C08E4E2D9E4E2D9E9E8E1E9E8E1E9E8E11C51801C5180C9C7BAD7D4CA
D7D4CAD7D4CA267C08E4E2D9E4E2D9E9E8E1E9E8E1E9E8E1E9E8E11C5180
1C5180D7D4CAD7D4CAD7D4CAD7D4CAE4E2D9E4E2D9E9E8E1E9E8E1E9E8E1
E9E8E1E9E8E11C51801C5180D7D4CAD7D4CAD7D4CAE4E2D9E4E2D9E4E2D9
E9E8E1E9E8E1E9E8E1E9E8E1E9E8E11C51801C51801C51801C51801C5180
1C51801C51801C51801C51801C51801C51801C51801C51801C5180
}] make image! [13x13 #{
1C51801C51801C51801C51801C51801C51801C51801C51801C51801C5180
1C51801C51801C51801C5180FEDF9AFEDF9AFCD27AFCD27AFCD27AFCD27A
FAC761FCD27AFCD27AFAC761F9BE4B1C51801C5180FEDF9AFCD27AFCD27A
FCD27AFCD27AFAC761FCD27AFCD27AFCD27AFCD27AFAC7611C51801C5180
FEDF9AFEDF9AE4E2D9E4E2D9E9E8E1E9E8E1F0F0EAF0F0EAF4F4F0FCD27A
FAC7611C51801C5180FEDF9AFEDF9AE4E2D9E9E8E1E9E8E1F0F0EAF0F0EA
F4F4F0F4F4F0FCD27AFAC7611C51801C5180FCD27AFEDF9AE9E8E1E9E8E1
F0F0EAF0F0EAF4F4F0F4F4F0F4F4F0FCD27AFAC7611C51801C5180FCD27A
FEDF9AE9E8E1F0F0EAF0F0EAF4F4F0F4F4F0F4F4F0FAFAF8FCD27AF9BE4B
1C51801C5180FCD27AFEDF9AF0F0EAF0F0EAF4F4F0F4F4F0F4F4F0FAFAF8
FAFAF8F9BE4BF8B4351C51801C5180FCD27AFCD27AF0F0EAF4F4F0F4F4F0
F4F4F0FAFAF8FAFAF8FAFAF8F8B435F8B4351C51801C5180FAC761FAC761
F4F4F0F4F4F0F4F4F0FAFAF8FAFAF8FAFAF8FAFAF8F8B435E597001C5180
1C5180F9BE4BF9BE4BFAC761FCD27AFCD27AFCD27AF9BE4BF8B435F8B435
F8B435E597001C51801C5180F9BE4BF9BE4BF9BE4BFAC761FAC761F9BE4B
F8B435F8B435E59700E59700F8B4351C51801C51801C51801C51801C5180
1C51801C51801C51801C51801C51801C51801C51801C51801C5180
}] make image! [13x13 #{
1C51801C51801C51801C51801C51801C51801C51801C51801C51801C5180
1C51801C51801C51801C5180FEDF9AFEDF9AFCD27AFCD27AFCD27AFCD27A
FAC761FCD27AFCD27AFAC761F9BE4B1C51801C5180FEDF9AFCD27AFCD27A
FCD27AFCD27AFAC761FCD27AFCD27AFCD27AFCD27AFAC7611C51801C5180
FEDF9AFEDF9AE4E2D9E4E2D9E9E8E1E9E8E1F0F0EAF0F0EA009900FCD27A
FAC7611C51801C5180FEDF9AFEDF9AE4E2D9E9E8E1E9E8E1F0F0EAF0F0EA
009900009900FCD27AFAC7611C51801C5180FCD27AFEDF9A009900E9E8E1
F0F0EAF0F0EA009900009900009900FCD27AFAC7611C51801C5180FCD27A
FEDF9A009900009900F0F0EA009900009900009900FAFAF8FCD27AF9BE4B
1C51801C5180FCD27AFEDF9A009900009900009900009900009900FAFAF8
FAFAF8F9BE4BF8B4351C51801C5180FCD27AFCD27AF0F0EA009900009900
009900FAFAF8FAFAF8FAFAF8F8B435F8B4351C51801C5180FAC761FAC761
F4F4F0F4F4F0009900FAFAF8FAFAF8FAFAF8FAFAF8F8B435E597001C5180
1C5180F9BE4BF9BE4BFAC761FCD27AFCD27AFCD27AF9BE4BF8B435F8B435
F8B435E597001C51801C5180F9BE4BF9BE4BF9BE4BFAC761FAC761F9BE4B
F8B435F8B435E59700E59700F8B4351C51801C51801C51801C51801C5180
1C51801C51801C51801C51801C51801C51801C51801C51801C5180
}]]
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    pane: make-face/spec 'check compose [
        size: (images/1/size) 
        offset: 2x2 
        feel: edge: color: none
    ] 
    para: make para [] 
    either font/align = 'right [
        para/margin/x: pane/size/x + pad
    ] [
        para/origin/x: pane/size/x + pad
    ] 
    if all [not flag-face? self as-is string? text] [trim/lines text] 
    if none? text [text: copy ""] 
    change font/colors font/color 
    if none? size [size: -1x-1] 
    xy: size 
    if any [size/x < 0 size/y < 0] [
        state: max 1x1 pane-size * 9 / 10 - offset 
        if size/x < 0 [size/x: state/x] 
        if size/y < 0 [size/y: state/y] 
        size: (size-text self) + (edge-size? self) 
        + (to-pair all [para (to-pair para/margin) + to-pair para/origin])
    ] 
    if xy/x > 0 [size/x: xy/x] 
    if xy/y > 0 [size/y: xy/y] 
    state: off 
    edge-size: edge-size? self 
    pane/offset/y: size/y - edge-size/y + 1 - pane/size/y / 2 
    all [font/align = 'right pane/offset/x: size/x - edge-size/x - 2 - pane/size/x]
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [flags check input font]
doc: make object! [
    info: "base text style"
    string: "text contents"
    image: none
    logic: none
    integer: "width of text area"
    pair: "width and height of text area"
    tuple: ["text color" "background color"]
    file: none
    url: none
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]
xy: none
edge-size: none
hover: false
pad: 5

14.37 RADIO-LINE

type: face
offset: 0x0
size: none
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: none
font: make object! [
    name: "arial"
    style: none
    size: 12
    color: 0.0.0
    offset: 2x2
    space: 0x0
    align: 'left
    valign: 'middle
    shadow: none
    colors: [0.0.0 40.40.40]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: make object! [
    redraw: func [face act pos][
        act: pick face/images (to integer! face/data) + either face/hover [5] [1 + (2 * to integer! face/state)] 
        either face/pane [face/pane/image: act] [face/image: act]
    ]
    detect: none
    over: func [face over offset][
        face/hover: over 
        show face 
        face/hover: off
    ]
    engage: func [face action event][
        switch action [
            down [face/state: on] 
            alt-down [face/state: on] 
            up [
                if face/state [
                    face/state: off 
                    reset-related-faces face 
                    do-face face face/data: not face/data
                ]
            ] 
            alt-up [if face/state [do-face-alt face face/text] face/state: off] 
            over [face/state: on] 
            away [face/state: off]
        ] 
        show face
    ]
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][face/data: value]
    get-face*: func [face][face/data]
    clear-face*: func [face][face/data: false]
    reset-face*: func [face][face/data: false]
]
style: CHECK-LINE
alt-action: none
facets: [with [
        images: load-stock-block [radio radio-on radio-down radio-down-on radio-hover radio-hover-on] 
        related: 'default 
        append init [
            pane/effect: [anti-alias] 
            pane/saved-area: true
        ]
    ]]
related: default
words: none
colors: none
texts: none
images: [make image! [13x13 #{
000000000000000000000000000000003366003366003366000000000000
0000000000000000000000000000000000000033660033668BA9E58BA9E5
8BA9E50033660033660000000000000000000000000000000033668BA9E5
E4E2D9E4E2D9E9E8E1E9E8E1F0F0EA8BA9E5003366000000000000000000
0033668BA9E5E4E2D9E4E2D9E9E8E1E9E8E1F0F0EAF0F0EAF4F4F08BA9E5
003366000000000000003366E4E2D9E4E2D9E9E8E1E9E8E1F0F0EAF0F0EA
F4F4F0F4F4F0F4F4F00033660000000033668BA9E5E4E2D9E9E8E1E9E8E1
F0F0EAF0F0EAF4F4F0F4F4F0F4F4F0FAFAF88BA9E50033660033668BA9E5
E9E8E1E9E8E1F0F0EAF0F0EAF4F4F0F4F4F0F4F4F0FAFAF8FAFAF88BA9E5
0033660033668BA9E5E9E8E1F0F0EAF0F0EAF4F4F0F4F4F0F4F4F0FAFAF8
FAFAF8FAFAF88BA9E5003366000000003366F0F0EAF0F0EAF4F4F0F4F4F0
F4F4F0FAFAF8FAFAF8FAFAF8FAFAF80033660000000000000033668BA9E5
F4F4F0F4F4F0F4F4F0FAFAF8FAFAF8FAFAF8FAFAF88BA9E5003366000000
0000000000000033668BA9E5F4F4F0FAFAF8FAFAF8FAFAF8FAFAF88BA9E5
0033660000000000000000000000000000000033660033668BA9E58BA9E5
8BA9E5003366003366000000000000000000000000000000000000000000
000000003366003366003366000000000000000000000000000000
} #{
FFFFFFFFFF000000FFFF
FFFFFFFFFFFF00000000
000000FFFFFFFFFF0000
00000000000000FFFFFF
00000000000000000000
00FFFF00000000000000
00000000FF0000000000
00000000000000000000
00000000000000000000
00000000000000000000
00000000FF0000000000
000000000000FFFF0000
000000000000000000FF
FFFF0000000000000000
00FFFFFFFFFF00000000
000000FFFFFFFFFFFFFF
FF000000FFFFFFFFFF
}] make image! [13x13 #{
000000000000000000000000000000003366003366003366000000000000
0000000000000000000000000000000000000033660033668BA9E58BA9E5
8BA9E50033660033660000000000000000000000000000000033668BA9E5
E4E2D9E4E2D9E9E8E1E9E8E1F0F0EA8BA9E5003366000000000000000000
0033668BA9E5E4E2D9E4E2D9E9E8E1E9E8E1F0F0EAF0F0EAF4F4F08BA9E5
003366000000000000003366E4E2D9E4E2D9E9E8E122C02022C02022C020
F4F4F0F4F4F0F4F4F00033660000000033668BA9E5E4E2D9E9E8E122C020
22C020009900009900267C08F4F4F0FAFAF88BA9E50033660033668BA9E5
E9E8E1E9E8E122C020009900009900009900267C08FAFAF8FAFAF88BA9E5
0033660033668BA9E5E9E8E1F0F0EA22C020009900009900267C08267C08
FAFAF8FAFAF88BA9E5003366000000003366F0F0EAF0F0EAF4F4F0267C08
267C08267C08FAFAF8FAFAF8FAFAF80033660000000000000033668BA9E5
F4F4F0F4F4F0F4F4F0FAFAF8FAFAF8FAFAF8FAFAF88BA9E5003366000000
0000000000000033668BA9E5F4F4F0FAFAF8FAFAF8FAFAF8FAFAF88BA9E5
0033660000000000000000000000000000000033660033668BA9E58BA9E5
8BA9E5003366003366000000000000000000000000000000000000000000
000000003366003366003366000000000000000000000000000000
} #{
FFFFFFFFFF000000FFFF
FFFFFFFFFFFF00000000
000000FFFFFFFFFF0000
00000000000000FFFFFF
00000000000000000000
00FFFF00000000000000
00000000FF0000000000
00000000000000000000
00000000000000000000
00000000000000000000
00000000FF0000000000
000000000000FFFF0000
000000000000000000FF
FFFF0000000000000000
00FFFFFFFFFF00000000
000000FFFFFFFFFFFFFF
FF000000FFFFFFFFFF
}] make image! [13x13 #{
000000000000000000000000000000003366003366003366000000000000
0000000000000000000000000000000000000033660033666487DC6487DC
6487DC0033660033660000000000000000000000000000000033666487DC
C7C5B2C7C5B2C7C5B2C9C7BAC9C7BA6487DC003366000000000000000000
0033666487DCC7C5B2C7C5B2C7C5B2C9C7BAC9C7BAD7D4CAD7D4CA6487DC
003366000000000000003366C7C5B2C7C5B2C7C5B2C9C7BAC9C7BAD7D4CA
D7D4CAD7D4CAD7D4CA0033660000000033666487DCC7C5B2C7C5B2C9C7BA
C9C7BAD7D4CAD7D4CAD7D4CAE4E2D9E4E2D96487DC0033660033666487DC
C7C5B2C9C7BAC9C7BAD7D4CAD7D4CAD7D4CAE4E2D9E4E2D9E4E2D96487DC
0033660033666487DCC9C7BAC9C7BAD7D4CAD7D4CAD7D4CAE4E2D9E4E2D9
E4E2D9E9E8E16487DC003366000000003366C9C7BAD7D4CAD7D4CAD7D4CA
E4E2D9E4E2D9E4E2D9E9E8E1E9E8E10033660000000000000033666487DC
D7D4CAD7D4CAE4E2D9E4E2D9E4E2D9E9E8E1E9E8E16487DC003366000000
0000000000000033666487DCD7D4CAE4E2D9E4E2D9E9E8E1E9E8E16487DC
0033660000000000000000000000000000000033660033666487DC6487DC
6487DC003366003366000000000000000000000000000000000000000000
000000003366003366003366000000000000000000000000000000
} #{
FFFFFFFFFF000000FFFF
FFFFFFFFFFFF00000000
000000FFFFFFFFFF0000
00000000000000FFFFFF
00000000000000000000
00FFFF00000000000000
00000000FF0000000000
00000000000000000000
00000000000000000000
00000000000000000000
00000000FF0000000000
000000000000FFFF0000
000000000000000000FF
FFFF0000000000000000
00FFFFFFFFFF00000000
000000FFFFFFFFFFFFFF
FF000000FFFFFFFFFF
}] make image! [13x13 #{
000000000000000000000000000000003366003366003366000000000000
0000000000000000000000000000000000000033660033666487DC6487DC
6487DC0033660033660000000000000000000000000000000033666487DC
C7C5B2C7C5B2C7C5B2C9C7BAC9C7BA6487DC003366000000000000000000
0033666487DCC7C5B2C7C5B2C7C5B2C9C7BAC9C7BAD7D4CAD7D4CA6487DC
003366000000000000003366C7C5B2C7C5B2C7C5B222C02022C02022C020
D7D4CAD7D4CAD7D4CA0033660000000033666487DCC7C5B2C7C5B222C020
22C020009900009900267C08E4E2D9E4E2D96487DC0033660033666487DC
C7C5B2C9C7BA22C020009900009900009900267C08E4E2D9E4E2D96487DC
0033660033666487DCC9C7BAC9C7BA22C020009900009900267C08267C08
E4E2D9E9E8E16487DC003366000000003366C9C7BAD7D4CAD7D4CA267C08
267C08267C08E4E2D9E9E8E1E9E8E10033660000000000000033666487DC
D7D4CAD7D4CAE4E2D9E4E2D9E4E2D9E9E8E1E9E8E16487DC003366000000
0000000000000033666487DCD7D4CAE4E2D9E4E2D9E9E8E1E9E8E16487DC
0033660000000000000000000000000000000033660033666487DC6487DC
6487DC003366003366000000000000000000000000000000000000000000
000000003366003366003366000000000000000000000000000000
} #{
FFFFFFFFFF000000FFFF
FFFFFFFFFFFF00000000
000000FFFFFFFFFF0000
00000000000000FFFFFF
00000000000000000000
00FFFF00000000000000
00000000FF0000000000
00000000000000000000
00000000000000000000
00000000000000000000
00000000FF0000000000
000000000000FFFF0000
000000000000000000FF
FFFF0000000000000000
00FFFFFFFFFF00000000
000000FFFFFFFFFFFFFF
FF000000FFFFFFFFFF
}] make image! [13x13 #{
000000000000000000000000000000003366003366003366000000000000
000000000000000000000000000000000000003366003366BB9955B9B5A9
BB9955003366003366000000000000000000000000000000003366BB9955
E9E8E1FEDF9AFCD27AFEDF9AFCD27ABB9955003366000000000000000000
003366BB9955E9E8E1FEDF9AF8B435E9E8E1F8B435F9BE4BFAC761BB9955
003366000000000000003366FAFAF8FEDF9AE9E8E1E9E8E1F0F0EAF0F0EA
F4F4F0FAC761F9BE4B003366000000003366BB9955FEDF9AF8B435E9E8E1
F0F0EAF0F0EAF4F4F0F4F4F0F8B435F9BE4BBB9955003366003366B9B5A9
FCD27AE9E8E1F0F0EAF0F0EAF4F4F0F4F4F0F4F4F0FAFAF8F8B435BB9955
003366003366BB9955FEDF9AF8B435F0F0EAF4F4F0F4F4F0F4F4F0FAFAF8
F8B435F9BE4BBB9955003366000000003366FCD27AF9BE4BF4F4F0F4F4F0
F4F4F0FAFAF8FAFAF8F8B435F8B435003366000000000000003366BB9955
FAC761FAC761F8B435FAFAF8F8B435F8B435F8B435BB9955003366000000
000000000000003366BB9955F9BE4BF9BE4BF8B435F9BE4BF8B435BB9955
003366000000000000000000000000000000003366003366BB9955BB9955
BB9955003366003366000000000000000000000000000000000000000000
000000003366003366003366000000000000000000000000000000
} #{
FFFFFFFFFF000000FFFF
FFFFFFFFFFFF00000000
000000FFFFFFFFFF0000
00000000000000FFFFFF
00000000000000000000
00FFFF00000000000000
00000000FF0000000000
00000000000000000000
00000000000000000000
00000000000000000000
00000000FF0000000000
000000000000FFFF0000
000000000000000000FF
FFFF0000000000000000
00FFFFFFFFFF00000000
000000FFFFFFFFFFFFFF
FF000000FFFFFFFFFF
}] make image! [13x13 #{
000000000000000000000000000000003366003366003366000000000000
000000000000000000000000000000000000003366003366C7C5B2B9B5A9
C7C5B2003366003366000000000000000000000000000000003366C7C5B2
E9E8E1FEDF9AFCD27AFEDF9AFCD27ABB9955003366000000000000000000
003366C7C5B2E9E8E1FEDF9AFEDF9AFFFFFFFEDF9AF9BE4BFAC761BB9955
003366000000000000003366FAFAF8FEDF9AFFFFFF22C02022C02022C020
F4F4F0FAC761F9BE4B003366000000003366C7C5B2FEDF9AFEDF9A22C020
22C020009900009900267C08FEDF9AF9BE4BBB9955003366003366B9B5A9
FCD27AFFFFFF22C020009900009900009900267C08FAFAF8F8B435BB9955
003366003366C7C5B2FEDF9AFEDF9A22C020009900009900267C08267C08
FEDF9AF9BE4BBB9955003366000000003366FCD27AF9BE4BF4F4F0267C08
267C08267C08FAFAF8F9BE4BF8B435003366000000000000003366BB9955
FAC761FAC761FEDF9AFAFAF8FEDF9AF9BE4BF8B435BB9955003366000000
000000000000003366BB9955F9BE4BF9BE4BF8B435F9BE4BF8B435BB9955
003366000000000000000000000000000000003366003366BB9955BB9955
BB9955003366003366000000000000000000000000000000000000000000
000000003366003366003366000000000000000000000000000000
} #{
FFFFFFFFFF000000FFFF
FFFFFFFFFFFF00000000
000000FFFFFFFFFF0000
00000000000000FFFFFF
00000000000000000000
00FFFF00000000000000
00000000FF0000000000
00000000000000000000
00000000000000000000
00000000000000000000
00000000FF0000000000
000000000000FFFF0000
000000000000000000FF
FFFF0000000000000000
00FFFFFFFFFF00000000
000000FFFFFFFFFFFFFF
FF000000FFFFFFFFFF
}]]
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    pane: make-face/spec 'check compose [
        size: (images/1/size) 
        offset: 2x2 
        feel: edge: color: none
    ] 
    para: make para [] 
    either font/align = 'right [
        para/margin/x: pane/size/x + pad
    ] [
        para/origin/x: pane/size/x + pad
    ] 
    if all [not flag-face? self as-is string? text] [trim/lines text] 
    if none? text [text: copy ""] 
    change font/colors font/color 
    if none? size [size: -1x-1] 
    xy: size 
    if any [size/x < 0 size/y < 0] [
        state: max 1x1 pane-size * 9 / 10 - offset 
        if size/x < 0 [size/x: state/x] 
        if size/y < 0 [size/y: state/y] 
        size: (size-text self) + (edge-size? self) 
        + (to-pair all [para (to-pair para/margin) + to-pair para/origin])
    ] 
    if xy/x > 0 [size/x: xy/x] 
    if xy/y > 0 [size/y: xy/y] 
    state: off 
    edge-size: edge-size? self 
    pane/offset/y: size/y - edge-size/y + 1 - pane/size/y / 2 
    all [font/align = 'right pane/offset/x: size/x - edge-size/x - 2 - pane/size/x] 
    pane/effect: [anti-alias] 
    pane/saved-area: true
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [flags check input]
doc: make object! [
    info: "base text style"
    string: "text contents"
    image: none
    logic: none
    integer: "width of text area"
    pair: "width and height of text area"
    tuple: ["text color" "background color"]
    file: none
    url: none
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]
xy: none
edge-size: none
hover: false
pad: 5

14.38 LED

type: face
offset: 0x0
size: 12x12
span: none
pane: none
text: none
color: 240.240.240
image: none
effect: none
data: none
edge: make object! [
    color: 110.120.130
    image: none
    effect: 'ibevel
    size: 2x2
]
font: none
para: none
feel: make object! [
    redraw: func [face act pos][face/color: either face/data [face/colors/1] [face/colors/2]]
    detect: none
    over: none
    engage: func [face action event][
        if any [action = 'time all [action = 'down get in face 'action]] [do-face face face/data: not face/data] 
        show face
    ]
    cue: none
    blink: none
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][face/data: value]
    get-face*: func [face][face/data]
    clear-face*: func [face][face/data: false]
    reset-face*: func [face][face/data: false]
]
style: CHECK
alt-action: none
facets: [12x12 with [
        feel: svvf/led 
        set [font para] none 
        colors: reduce [green red] 
        flags: [input]
    ]]
related: none
words: none
colors: [0.255.0 255.0.0]
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [effect: copy []]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [input]
doc: make object! [
    info: "rectangular, rendered buttons"
    string: ["button label" "button down label"]
    image: ["button background" "background when button down"]
    logic: none
    integer: "width of button"
    pair: "width and height of button"
    tuple: ["button color" "button down color"]
    file: none
    url: none
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]
effects: none
depth: 128

14.39 ARROW

type: face
offset: 0x0
size: 20x20
span: none
pane: none
text: none
color: 240.240.240
image: none
effect: none
data: none
edge: make object! [
    color: 110.120.130
    image: none
    effect: 'bevel
    size: 1x1
]
font: none
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: make object! [
    redraw: func [face act pos /local state][
        if all [face/texts face/texts/2] [
            face/text: either face/state [face/texts/2] [face/texts/1]
        ] 
        either face/images [
            face/image: either face/state [face/images/2] [face/images/1] 
            if all [face/colors face/effect find face/effect 'colorize] [
                change next find face/effect 'colorize pick face/colors not face/state
            ]
        ] [
            if face/edge [face/edge/effect: pick [ibevel bevel] face/state] 
            state: either not face/state [face/blinker] [true] 
            if face/colors [face/color: pick face/colors not state] 
            if face/effects [face/effect: pick face/effects not state]
        ]
    ]
    detect: none
    over: func [face action event][
        if all [face/font face/font/colors] [
            face/font/color: pick face/font/colors not action 
            show face 
            face/font/color: first face/font/colors
        ]
    ]
    engage: func [face action event][
        switch action [
            time [if not face/state [face/blinker: not face/blinker]] 
            down [face/state: on] 
            alt-down [face/state: on] 
            up [if face/state [do-face face face/text] face/state: off] 
            alt-up [if face/state [do-face-alt face face/text] face/state: off] 
            over [face/state: on] 
            away [face/state: off]
        ] 
        cue face action 
        show face
    ]
    cue: none
    blink: none
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][face/data: value]
    get-face*: func [face][face/data]
    clear-face*: func [face][face/data: false]
    reset-face*: func [face][face/data: false]
]
style: BUTTON
alt-action: none
facets: [240.240.240 20x20 with [
        font: none 
        edge: [size: 1x1] 
        init: [
            if not effect [
                state: either all [colors state: pick colors 2] [state] [black] 
                effect: compose [fit arrow (state) 0.7 rotate (
                        select [up 0 right 90 down 180 left 270] data
                    )] 
                state: off
            ]
        ] 
        words: [up right down left func [new args][new/data: first args args]]
    ]]
related: none
words: [up right down left func [new args][new/data: first args args]]
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if not effect [
        state: either all [colors state: pick colors 2] [state] [black] 
        effect: compose [fit arrow (state) 0.7 rotate (
                select [up 0 right 90 down 180 left 270] data
            )] 
        state: off
    ]
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: []
doc: make object! [
    info: "rectangular, rendered buttons"
    string: ["button label" "button down label"]
    image: ["button background" "background when button down"]
    logic: none
    integer: "width of button"
    pair: "width and height of button"
    tuple: ["button color" "button down color"]
    file: none
    url: none
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]
effects: none
depth: 128

14.40 TOGGLE

type: face
offset: 0x0
size: 100x24
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: make object! [
    color: 110.120.130
    image: none
    effect: 'bevel
    size: 2x2
]
font: make object! [
    name: "arial"
    style: 'bold
    size: 12
    color: 255.255.255
    offset: 2x2
    space: 0x0
    align: 'center
    valign: 'middle
    shadow: 1x1
    colors: [255.255.255 255.180.75]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: make object! [
    redraw: func [face act pos /local state][
        if all [face/texts face/texts/2] [
            face/text: either face/state [face/texts/2] [face/texts/1]
        ] 
        either face/images [
            face/image: either face/state [face/images/2] [face/images/1] 
            if all [face/colors face/effect find face/effect 'colorize] [
                change next find face/effect 'colorize pick face/colors not face/state
            ]
        ] [
            if face/edge [face/edge/effect: pick [ibevel bevel] face/state] 
            state: either not face/state [face/blinker] [true] 
            if face/colors [face/color: pick face/colors not state] 
            if face/effects [face/effect: pick face/effects not state]
        ]
    ]
    detect: none
    over: func [face action event][
        if all [face/font face/font/colors] [
            face/font/color: pick face/font/colors not action 
            show face 
            face/font/color: first face/font/colors
        ]
    ]
    engage: func [face action event][
        if find [down alt-down] action [
            if face/related [
                foreach item face/parent-face/pane [
                    if all [flag-face? item toggle item/related item/related = face/related item/data] [item/data: item/state: false show item]
                ]
            ] 
            face/data: face/state: not face/state 
            either action = 'down [do-face face face/data] [do-face-alt face face/data] 
            show face
        ]
    ]
    cue: none
    blink: none
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][face/data: face/state: value]
    get-face*: func [face][face/data]
    clear-face*: func [face][face/data: face/state: false]
    reset-face*: func [face][face/data: face/state: false]
]
style: BUTTON
alt-action: none
facets: [with [
        feel: svvf/toggle 
        access: ctx-access/data-state 
        flags: [toggle input]
    ]]
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    edge: make edge [] 
    font/color: first font/colors 
    either image [
        if not effect [
            effect: copy [fit] 
            if color [append effect reduce ['colorize color depth]] 
            if all [colors greater? length? colors 1 not effects] [
                effects: compose/deep [
                    [fit colorize (first colors) (depth)] 
                    [fit colorize (second colors) (depth)]
                ]
            ]
        ]
    ] [
        if not any [effect effects] [
            either color [
                effects: reduce [
                    reduce ['gradient 0x1 color + 32 color - 32] 
                    either all [block? colors colors/2] [
                        reduce ['gradient 0x-1 colors/2 + 32 color/2 - 32]
                    ] [
                        reduce ['gradient 0x-1 color + 32 color - 32]
                    ]
                ]
            ] [
                effects: [
                    [gradient 0x1 66.120.192 44.80.132] 
                    [gradient 0x-1 66.120.192 44.80.132]
                ]
            ]
        ]
    ] 
    if not color [color: svvc/button]
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [toggle input]
doc: make object! [
    info: "rectangular, rendered buttons"
    string: ["button label" "button down label"]
    image: ["button background" "background when button down"]
    logic: none
    integer: "width of button"
    pair: "width and height of button"
    tuple: ["button color" "button down color"]
    file: none
    url: none
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]
effects: none
depth: 128

14.41 ROTARY

type: face
offset: 0x0
size: 100x24
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: make object! [
    color: 110.120.130
    image: none
    effect: 'bezel
    size: 4x2
]
font: make object! [
    name: "arial"
    style: 'bold
    size: 12
    color: 255.255.255
    offset: 2x2
    space: 0x0
    align: 'center
    valign: 'middle
    shadow: 1x1
    colors: [255.255.255 255.180.75]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: make object! [
    redraw: func [face act pos][
        face/text: face/data/1 
        if face/edge [face/edge/effect: pick [ibezel bezel] face/state] 
        if face/colors [face/color: any [pick face/colors index? face/data face/color]] 
        if face/effects [face/effect: pick face/effects not face/state]
    ]
    detect: none
    over: func [face action event][
        if all [face/font face/font/colors] [
            face/font/color: pick face/font/colors not action 
            show face 
            face/font/color: first face/font/colors
        ]
    ]
    engage: func [face action event][
        switch action [
            down over [if not face/state [next-face face] face/state: on] 
            up alt-up [if face/state [do-face face face/data/1] face/state: off] 
            alt-down [if not face/state [back-face face] face/state: on] 
            away [if face/state [back-face face] face/state: off]
        ] 
        show face
    ]
    cue: none
    blink: none
    next-face: func [face][
        face/data: either tail? next face/data [head face/data] [next face/data]
    ]
    back-face: func [face][
        face/data: either head? face/data [back tail face/data] [back face/data]
    ]
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        all [series? face/data value: find head face/data value face/data: value]
    ]
    get-face*: func [face][all [series? face/data face/data/1]]
    clear-face*: func [face][all [series? face/data face/data: head face/data]]
    reset-face*: func [face][all [series? face/data face/data: head face/data]]
]
style: BUTTON
alt-action: none
facets: [with [
        edge: [size: 4x2 effect: 'bezel] 
        feel: svvf/rotary 
        access: ctx-access/data-find 
        insert init [if texts [data: texts]] 
        flags: [input] 
        words: [data func [new args][
                if all [block? args new/texts: args/2 not empty? new/texts] [new/text: first new/texts] 
                next args
            ]]
    ]]
related: none
words: [data func [new args][
        if all [block? args new/texts: args/2 not empty? new/texts] [new/text: first new/texts] 
        next args
    ]]
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [if texts [data: texts] 
    edge: make edge [] 
    font/color: first font/colors 
    either image [
        if not effect [
            effect: copy [fit] 
            if color [append effect reduce ['colorize color depth]] 
            if all [colors greater? length? colors 1 not effects] [
                effects: compose/deep [
                    [fit colorize (first colors) (depth)] 
                    [fit colorize (second colors) (depth)]
                ]
            ]
        ]
    ] [
        if not any [effect effects] [
            either color [
                effects: reduce [
                    reduce ['gradient 0x1 color + 32 color - 32] 
                    either all [block? colors colors/2] [
                        reduce ['gradient 0x-1 colors/2 + 32 color/2 - 32]
                    ] [
                        reduce ['gradient 0x-1 color + 32 color - 32]
                    ]
                ]
            ] [
                effects: [
                    [gradient 0x1 66.120.192 44.80.132] 
                    [gradient 0x-1 66.120.192 44.80.132]
                ]
            ]
        ]
    ] 
    if not color [color: svvc/button]
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [input]
doc: make object! [
    info: "rectangular, rendered buttons"
    string: ["button label" "button down label"]
    image: ["button background" "background when button down"]
    logic: none
    integer: "width of button"
    pair: "width and height of button"
    tuple: ["button color" "button down color"]
    file: none
    url: none
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]
effects: none
depth: 128

14.42 CHOICE

type: face
offset: 0x0
size: 100x24
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: make object! [
    color: 110.120.130
    image: none
    effect: 'bezel
    size: 4x2
]
font: make object! [
    name: "arial"
    style: 'bold
    size: 12
    color: 255.255.255
    offset: 2x2
    space: 0x0
    align: 'center
    valign: 'middle
    shadow: 1x1
    colors: [255.255.255 255.180.75]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: make object! [
    redraw: none
    detect: none
    over: func [face action event][
        if all [face/font face/font/colors] [
            face/font/color: pick face/font/colors not action 
            show face 
            face/font/color: first face/font/colors
        ]
    ]
    engage: func [face action event][
        if action = 'down [
            choose/style/window face/texts func [face parent] [
                parent/data: find parent/texts face/text 
                do-face parent parent/text: face/text
            ] face face/parent-face
        ] 
        show face
    ]
    cue: none
    blink: none
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        all [series? face/data value: find head face/data value face/data: value]
    ]
    get-face*: func [face][all [series? face/data face/data/1]]
    clear-face*: func [face][all [series? face/data face/data: head face/data]]
    reset-face*: func [face][all [series? face/data face/data: head face/data]]
]
style: ROTARY
alt-action: none
facets: [with [
        colors: svvc/body 
        feel: svvf/choice
    ]]
related: none
words: [data func [new args][
        if all [block? args new/texts: args/2 not empty? new/texts] [new/text: first new/texts] 
        next args
    ]]
colors: [40.100.130 255.180.55]
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [if texts [data: texts] 
    edge: make edge [] 
    font/color: first font/colors 
    either image [
        if not effect [
            effect: copy [fit] 
            if color [append effect reduce ['colorize color depth]] 
            if all [colors greater? length? colors 1 not effects] [
                effects: compose/deep [
                    [fit colorize (first colors) (depth)] 
                    [fit colorize (second colors) (depth)]
                ]
            ]
        ]
    ] [
        if not any [effect effects] [
            either color [
                effects: reduce [
                    reduce ['gradient 0x1 color + 32 color - 32] 
                    either all [block? colors colors/2] [
                        reduce ['gradient 0x-1 colors/2 + 32 color/2 - 32]
                    ] [
                        reduce ['gradient 0x-1 color + 32 color - 32]
                    ]
                ]
            ] [
                effects: [
                    [gradient 0x1 66.120.192 44.80.132] 
                    [gradient 0x-1 66.120.192 44.80.132]
                ]
            ]
        ]
    ] 
    if not color [color: svvc/button]
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [input]
doc: make object! [
    info: "rectangular, rendered buttons"
    string: ["button label" "button down label"]
    image: ["button background" "background when button down"]
    logic: none
    integer: "width of button"
    pair: "width and height of button"
    tuple: ["button color" "button down color"]
    file: none
    url: none
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]
effects: none
depth: 128

14.43 DROP-DOWN

type: face
offset: 0x0
size: 100x24
span: none
pane: none
text: none
color: 255.255.255
image: none
effect: none
data: none
edge: make object! [
    color: 110.120.130
    image: none
    effect: 'ibevel
    size: 2x2
]
font: make object! [
    name: "arial"
    style: none
    size: 12
    color: 0.0.0
    offset: 2x2
    space: 0x0
    align: 'left
    valign: 'top
    shadow: none
    colors: [255.255.255 255.180.75]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: make object! [
    redraw: none
    detect: none
    over: none
    engage: func [face action event][
        switch action [
            down [face/state: on] 
            up [if face/state [face/show-dropdown] face/state: off] 
            over [face/state: on] 
            away [face/state: off]
        ] 
        show face
    ]
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        face/text: value 
        face/line-list: none
    ]
    get-face*: func [face][face/text]
    clear-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        if string? face/text [clear face/text] 
        face/line-list: none
    ]
    reset-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        face/text: copy "" 
        face/line-list: none
    ]
]
style: TEXT
alt-action: none
facets: [0.0.0 255.255.255 100x24 with [
        edge: [color: 110.120.130 size: 2x2 effect: 'ibevel] 
        feel: svvf/dropdown 
        action: none 
        list-lay: none 
        show-arrow?: true 
        rows: 4 
        list-data: copy [] 
        arrow-button: does [
            layout [
                origin 0x0 arrow down [show-dropdown] effect [arrow 0.0.0 0.75 rotate 180] 
                edge [color: 110.120.130 size: 1x1 effect: 'ibevel] 128.128.128 14x20
            ]
        ] 
        show-dropdown: has [tl picked] [
            if not list-lay [
                list-lay: layout [
                    origin 0x0 at 0x0 
                    tl: text-list data list-data to-pair reduce [size/x rows * 15 + 4] 
                    font/color color 
                    [
                        data: text: value 
                        wait 0:00:00.06 
                        hide-popup 
                        show self
                    ] 
                    do [if picked: find list-data text [append clear tl/picked first picked]]
                ] 
                list-lay/offset: to-pair reduce [offset/x offset/y + size/y]
            ] 
            show-popup/window/away list-lay self/parent-face 
            do-events 
            do-face self data
        ] 
        reset: does [list-lay: none] 
        resize: func [new-size [pair! none!]] [
            reset 
            if new-size [size: new-size] 
            size: max size 32x24 
            either show-arrow? [
                pane: arrow-button 
                pane/offset: 0x0 
                pane/offset/x: self/size/x - arrow-button/size/x - 4 
                arrow-button/size/y: self/size/y
            ] [pane: none]
        ] 
        pane: none 
        words: [
            data func [new args][new/list-data: second args next args] 
            rows func [new args][new/rows: second args next args]
        ] 
        init: [
            if texts [list-data: texts] 
            arrow-button: arrow-button 
            resize none
        ]
    ]]
related: none
words: [
    data func [new args][new/list-data: second args next args] 
    rows func [new args][new/rows: second args next args]
]
colors: [0.0.0 255.255.255]
texts: none
images: none
file: none
var: none
keycode: none
reset: func [][list-lay: none]
styles: none
init: [
    if texts [list-data: texts] 
    arrow-button: arrow-button 
    resize none
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [flags text font]
doc: make object! [
    info: "document text"
    string: "text contents"
    image: none
    logic: none
    integer: "width of text area"
    pair: "width and height of text area"
    tuple: ["text color" "background color"]
    file: none
    url: none
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]
xy: none
list-lay: none
show-arrow?: true
rows: 4
list-data: []
arrow-button: func [][
    layout [
        origin 0x0 arrow down [show-dropdown] effect [arrow 0.0.0 0.75 rotate 180] 
        edge [color: 110.120.130 size: 1x1 effect: 'ibevel] 128.128.128 14x20
    ]
]
show-dropdown: func [/local tl picked][
    if not list-lay [
        list-lay: layout [
            origin 0x0 at 0x0 
            tl: text-list data list-data to-pair reduce [size/x rows * 15 + 4] 
            font/color color 
            [
                data: text: value 
                wait 0:00:00.06 
                hide-popup 
                show self
            ] 
            do [if picked: find list-data text [append clear tl/picked first picked]]
        ] 
        list-lay/offset: to-pair reduce [offset/x offset/y + size/y]
    ] 
    show-popup/window/away list-lay self/parent-face 
    do-events 
    do-face self data
]
resize: func [new-size [pair! none!]][
    reset 
    if new-size [size: new-size] 
    size: max size 32x24 
    either show-arrow? [
        pane: arrow-button 
        pane/offset: 0x0 
        pane/offset/x: self/size/x - arrow-button/size/x - 4 
        arrow-button/size/y: self/size/y
    ] [pane: none]
]

14.44 ICON

type: face
offset: 0x0
size: 64x64
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: make object! [
    color: 200.200.200
    image: none
    effect: none
    size: 0x0
]
font: make object! [
    name: "arial"
    style: none
    size: 11
    color: 255.255.255
    offset: 2x2
    space: 0x0
    align: 'center
    valign: 'bottom
    shadow: 1x1
    colors: [255.255.255 255.180.75]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: false
    scroll: 0x0
]
feel: make object! [
    redraw: func [face act pos /local state][
        if face/pane/edge [face/pane/edge/effect: pick [ibevel bevel] face/state]
    ]
    detect: none
    over: func [face action event][
        if all [face/font face/font/colors] [
            face/font/color: pick face/font/colors not action 
            show face 
            face/font/color: first face/font/colors
        ]
    ]
    engage: func [face action event][
        switch action [
            time [if not face/state [face/blinker: not face/blinker]] 
            down [face/state: on] 
            alt-down [face/state: on] 
            up [if face/state [do-face face face/text] face/state: off] 
            alt-up [if face/state [do-face-alt face face/text] face/state: off] 
            over [face/state: on] 
            away [face/state: off]
        ] 
        cue face action 
        show face
    ]
    cue: none
    blink: none
]
saved-area: true
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][face/data: value]
    get-face*: func [face][face/data]
    clear-face*: func [face][face/data: false]
    reset-face*: func [face][face/data: false]
]
style: FACE
alt-action: none
facets: [64x64 with [
        font: [size: 11 align: 'center valign: 'bottom] 
        para: [wrap?: off] 
        feel: svvf/icon 
        saved-area: true 
        hold: none 
        color: none 
        ps: none 
        init: [
            if none? text [text: file] 
            if none? image [image: svv/icon-image] 
            hold: reduce [image file] 
            image: file: none 
            ps: size - 0x16 
            pane: make svv/vid-face [
                edge: make edge [size: 2x2 effect: 'bevel color: 128.128.128] 
                es: edge/size * 2 
                feel: svvf/subicon 
                image: first hold 
                file: second hold 
                size: ps - 4x0 
                if image [either outside? size image/size + es [effect: 'fit] [size: image/size + es]] 
                offset: ps - size / 2
            ]
        ]
    ]]
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if none? text [text: file] 
    if none? image [image: svv/icon-image] 
    hold: reduce [image file] 
    image: file: none 
    ps: size - 0x16 
    pane: make svv/vid-face [
        edge: make edge [size: 2x2 effect: 'bevel color: 128.128.128] 
        es: edge/size * 2 
        feel: svvf/subicon 
        image: first hold 
        file: second hold 
        size: ps - 4x0 
        if image [either outside? size image/size + es [effect: 'fit] [size: image/size + es]] 
        offset: ps - size / 2
    ]
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: []
doc: make object! [
    info: "base face style"
    string: none
    image: none
    logic: none
    integer: none
    pair: none
    tuple: none
    file: none
    url: none
    decimal: none
    time: none
    block: none
    keywords: none
]
hold: none
ps: none

14.45 FIELD

type: face
offset: 0x0
size: 200x24
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: make object! [
    color: 110.120.130
    image: none
    effect: 'ibevel
    size: 2x2
]
font: make object! [
    name: "arial"
    style: none
    size: 12
    color: 0.0.0
    offset: 2x2
    space: 0x0
    align: 'left
    valign: 'top
    shadow: none
    colors: none
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: false
    scroll: 0x0
]
feel: make object! [
    redraw: func [face act pos][
        if all [in face 'colors block? face/colors] [
            face/color: pick face/colors face <> focal-face
        ]
    ]
    detect: none
    over: none
    engage: func [face act event][
        switch act [
            down [
                either equal? face focal-face [unlight-text] [focus/no-show face] 
                caret: offset-to-caret face event/offset 
                show face
            ] 
            over [
                if not-equal? caret offset-to-caret face event/offset [
                    if not highlight-start [highlight-start: caret] 
                    highlight-end: caret: offset-to-caret face event/offset 
                    show face
                ]
            ] 
            key [edit-text face event get in face 'action]
        ]
    ]
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        if face/para [face/para/scroll: 0x0] 
        face/text: form value 
        face/line-list: none
    ]
    get-face*: func [face][face/text]
    clear-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        if string? face/text [clear face/text] 
        if flag-face? face 'hide [clear face/data] 
        face/line-list: none
    ]
    reset-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        face/text: copy "" 
        face/line-list: none
    ]
]
style: FACE
alt-action: none
facets: [200x24 with [
        color: none 
        colors: reduce [svvc/field svvc/field-select] 
        edge: [size: 2x2 color: svvc/bevel effect: 'ibevel] 
        font: [color: svvc/field-font style: colors: shadow: none] 
        para: [wrap?: off] 
        feel: ctx-text/edit 
        access: ctx-access/field 
        init: [
            if color [colors: reduce [color colors/2]] 
            if not string? text [text: either text [form text] [copy ""]] 
            if not flag-face? self hide [data: text]
        ] 
        flags: [field return tabbed on-unfocus input] 
        words: [hide func [new args][new/data: copy "" flag-face new hide args]]
    ]]
related: none
words: [hide func [new args][new/data: copy "" flag-face new hide args]]
colors: [240.240.240 255.240.120]
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if color [colors: reduce [color colors/2]] 
    if not string? text [text: either text [form text] [copy ""]] 
    if not flag-face? self hide [data: text]
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [field return tabbed on-unfocus input]
doc: make object! [
    info: "base face style"
    string: none
    image: none
    logic: none
    integer: none
    pair: none
    tuple: none
    file: none
    url: none
    decimal: none
    time: none
    block: none
    keywords: none
]

14.46 INFO

type: face
offset: 0x0
size: 200x24
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: make object! [
    color: 110.120.130
    image: none
    effect: 'ibevel
    size: 2x2
]
font: make object! [
    name: "arial"
    style: none
    size: 12
    color: 0.0.0
    offset: 2x2
    space: 0x0
    align: 'left
    valign: 'top
    shadow: none
    colors: none
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: false
    scroll: 0x0
]
feel: make object! [
    redraw: none
    detect: none
    over: none
    engage: func [face act event][
        switch act [
            down [
                either equal? face focal-face [unlight-text] [focus/no-show face] 
                caret: offset-to-caret face event/offset 
                show face 
                face/action face face/text
            ] 
            up [
                if highlight-start = highlight-end [unfocus]
            ] 
            over [
                if not-equal? caret offset-to-caret face event/offset [
                    if not highlight-start [highlight-start: caret] 
                    highlight-end: caret: offset-to-caret face event/offset 
                    show face
                ]
            ] 
            key [
                if 'copy-text = select keymap event/key [
                    copy-text face unlight-text
                ]
            ]
        ]
    ]
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        if face/para [face/para/scroll: 0x0] 
        face/text: form value 
        face/line-list: none
    ]
    get-face*: func [face][face/text]
    clear-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        if string? face/text [clear face/text] 
        if flag-face? face 'hide [clear face/data] 
        face/line-list: none
    ]
    reset-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        face/text: copy "" 
        face/line-list: none
    ]
]
style: FIELD
alt-action: none
facets: [with [
        colors: 180.180.180 
        flags: [field] 
        feel: ctx-text/swipe
    ]]
related: none
words: [hide func [new args][new/data: copy "" flag-face new hide args]]
colors: 180.180.180
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if color [colors: reduce [color colors/2]] 
    if not string? text [text: either text [form text] [copy ""]] 
    if not flag-face? self hide [data: text]
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [field]
doc: make object! [
    info: "base face style"
    string: none
    image: none
    logic: none
    integer: none
    pair: none
    tuple: none
    file: none
    url: none
    decimal: none
    time: none
    block: none
    keywords: none
]

14.47 AREA

type: face
offset: 0x0
size: 400x150
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: make object! [
    color: 110.120.130
    image: none
    effect: 'ibevel
    size: 2x2
]
font: make object! [
    name: "arial"
    style: none
    size: 12
    color: 0.0.0
    offset: 2x2
    space: 0x0
    align: 'left
    valign: 'top
    shadow: none
    colors: none
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: false
    scroll: 0x0
]
feel: make object! [
    redraw: func [face act pos][
        if all [in face 'colors block? face/colors] [
            face/color: pick face/colors face <> focal-face
        ]
    ]
    detect: none
    over: none
    engage: func [face act event][
        switch act [
            down [
                either equal? face focal-face [unlight-text] [focus/no-show face] 
                caret: offset-to-caret face event/offset 
                show face
            ] 
            over [
                if not-equal? caret offset-to-caret face event/offset [
                    if not highlight-start [highlight-start: caret] 
                    highlight-end: caret: offset-to-caret face event/offset 
                    show face
                ]
            ] 
            key [edit-text face event get in face 'action]
        ]
    ]
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        if face/para [face/para/scroll: 0x0] 
        face/text: form value 
        face/line-list: none
    ]
    get-face*: func [face][face/text]
    clear-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        if string? face/text [clear face/text] 
        if flag-face? face 'hide [clear face/data] 
        face/line-list: none
    ]
    reset-face*: func [face][
        if face/para [face/para/scroll: 0x0] 
        face/text: copy "" 
        face/line-list: none
    ]
]
style: FIELD
alt-action: none
facets: [400x150 with [
        flags: [tabbed on-unfocus input] 
        init: append copy init [para: make para []]
    ]]
related: none
words: [hide func [new args][new/data: copy "" flag-face new hide args]]
colors: [240.240.240 255.240.120]
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if color [colors: reduce [color colors/2]] 
    if not string? text [text: either text [form text] [copy ""]] 
    if not flag-face? self hide [data: text] para: make para []
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [tabbed on-unfocus input]
doc: make object! [
    info: "base face style"
    string: none
    image: none
    logic: none
    integer: none
    pair: none
    tuple: none
    file: none
    url: none
    decimal: none
    time: none
    block: none
    keywords: none
]

14.48 SLIDER

type: face
offset: 0x0
size: 16x200
span: none
pane: none
text: none
color: 100.100.100
image: none
effect: none
data: 0
edge: make object! [
    color: 128.128.128
    image: none
    effect: 'ibevel
    size: 2x2
]
font: none
para: none
feel: make object! [
    redraw: func [face act pos][
        face/data: max 0 min 1 face/data 
        if face/data <> face/state [
            pos: face/size - face/pane/1/size - (2 * face/edge/size) - (2 * face/clip) 
            either face/size/x > face/size/y [face/pane/1/offset/x: face/data * pos/x + face/clip/x] [
                face/pane/1/offset/y: face/data * pos/y + face/clip/y
            ] 
            face/state: face/data 
            if act = 'draw [show face/pane/1]
        ]
    ]
    detect: none
    over: none
    engage: func [face action event][
        if action = 'down [
            drag-off face face/pane/1 event/offset - (face/pane/1/size / 2) 
            show face
        ]
    ]
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        if not number? value [
            make error! reform [face/style "must be set to a number"]
        ] 
        face/data: value
    ]
    get-face*: func [face][face/data]
    clear-face*: func [face][face/data: 0]
    reset-face*: func [face][face/data: 0]
]
style: FACE
alt-action: none
facets: [100.100.100 16x200 with [
        feel: svvf/slide 
        font: none 
        para: none 
        step: 2E-2 
        ratio: 
        page: 
        axis: none 
        data: 0 
        clip: 0x0 
        edge: [size: 2x2 effect: 'ibevel color: 128.128.128] 
        access: ctx-access/data-number 
        flags: [input] 
        dragger: make face [
            offset: 0x0 
            color: 128.128.128 
            feel: svvf/drag 
            text: font: para: none 
            edge: make edge [size: 1x1 effect: 'bevel color: 128.128.128]
        ] 
        init: [
            pane: reduce [make dragger [edge: make edge []]] 
            if colors [color: first colors pane/1/color: second colors] 
            axis: pick [y x] size/y >= size/x 
            redrag 0.1
        ] 
        redrag: func [val /local tmp] [
            state: none 
            ratio: min 1 max 0 val 
            page: any [all [ratio = 1 0] ratio / (1 - ratio)] 
            pane/1/size: val: size - (2 * edge/size) - (2 * clip * pick [0x1 1x0] axis = 'y) 
            tmp: val/:axis * ratio 
            if tmp < 10 [page: either val/:axis = tmp: 10 [1] [tmp / (val/:axis - tmp)]] 
            either axis = 'y [pane/1/size/y: tmp] [pane/1/size/x: tmp]
        ]
    ]]
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    pane: reduce [make dragger [edge: make edge []]] 
    if colors [color: first colors pane/1/color: second colors] 
    axis: pick [y x] size/y >= size/x 
    redrag 0.1
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [input]
doc: make object! [
    info: "base face style"
    string: none
    image: none
    logic: none
    integer: none
    pair: none
    tuple: none
    file: none
    url: none
    decimal: none
    time: none
    block: none
    keywords: none
]
step: 2E-2
ratio: none
page: none
axis: none
clip: 0x0
dragger: make object! [
    type: 'face
    offset: 0x0
    size: 100x100
    span: none
    pane: none
    text: none
    color: 128.128.128
    image: none
    effect: none
    data: none
    edge: make object! [
        color: 128.128.128
        image: none
        effect: 'bevel
        size: 1x1
    ]
    font: none
    para: none
    feel: make object! [
        redraw: none
        detect: none
        over: none
        engage: func [face action event][
            if find [over away] action [
                drag-off face/parent-face face face/offset + event/offset - face/data 
                show face
            ] 
            if find [down alt-down] action [face/data: event/offset]
        ]
    ]
    saved-area: none
    rate: none
    show?: true
    options: none
    parent-face: none
    old-offset: none
    old-size: none
    line-list: none
    changes: none
    face-flags: 0
    action: none
]
redrag: func [val /local tmp][
    state: none 
    ratio: min 1 max 0 val 
    page: any [all [ratio = 1 0] ratio / (1 - ratio)] 
    pane/1/size: val: size - (2 * edge/size) - (2 * clip * pick [0x1 1x0] axis = 'y) 
    tmp: val/:axis * ratio 
    if tmp < 10 [page: either val/:axis = tmp: 10 [1] [tmp / (val/:axis - tmp)]] 
    either axis = 'y [pane/1/size/y: tmp] [pane/1/size/x: tmp]
]

14.49 SCROLLER

type: face
offset: 0x0
size: 16x200
span: none
pane: none
text: none
color: 100.100.100
image: none
effect: none
data: 0
edge: make object! [
    color: 128.128.128
    image: none
    effect: 'ibevel
    size: 0x0
]
font: none
para: none
feel: make object! [
    redraw: func [face act pos][
        face/data: max 0 min 1 face/data 
        if face/data <> face/state [
            pos: face/size - face/pane/1/size - (2 * face/edge/size) - (2 * face/clip) 
            either face/size/x > face/size/y [face/pane/1/offset/x: face/data * pos/x + face/clip/x] [
                face/pane/1/offset/y: face/data * pos/y + face/clip/y
            ] 
            face/state: face/data 
            if act = 'draw [show face/pane/1]
        ]
    ]
    detect: none
    over: none
    engage: func [f act evt /local tmp][
        if act = 'down [
            tmp: f/axis 
            do-face pick reduce [f/pane/3 f/pane/2] evt/offset/:tmp > f/pane/1/offset/:tmp f/page
        ]
    ]
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        if not number? value [
            make error! reform [face/style "must be set to a number"]
        ] 
        face/data: value
    ]
    get-face*: func [face][face/data]
    clear-face*: func [face][face/data: 0]
    reset-face*: func [face][face/data: 0]
]
style: SLIDER
alt-action: none
facets: [with [
        speed: 20 
        edge: [size: 0x0] 
        feel: svvf/scroll 
        reset: does [data: 0] 
        resize: func [new /x /y /local tmp] [
            either any [x y] [
                if x [size/x: new] 
                if y [size/y: new]
            ] [
                size: any [new size]
            ] 
            tmp: pick [y x] axis = 'x 
            clip: pane/2/size: pane/3/size: size/:tmp - (2 * edge/size/:tmp) * 1x1 
            pane/3/offset: size/:axis - pane/3/size/:axis - (2 * edge/size/:axis) * 0x1 
            if tmp: axis = 'x [pane/3/offset: reverse pane/3/offset] 
            pane/2/data: pick [left up] tmp 
            pane/3/data: pick [right down] tmp 
            state: pane/2/effect: pane/3/effect: none 
            do pane/2/init do pane/3/init 
            pane/1/offset: 0x0 
            redrag any [ratio 0.1]
        ] 
        init: [
            pane: reduce [
                make dragger [edge: make edge []] 
                axis: make svv/vid-styles/arrow [dir: -1 edge: make edge [] 
                    color: first colors: [128.128.128 200.200.200] 
                    action: get in svvf 'move-drag 
                    feel: make svvf/scroll-button []
                ] 
                make axis [dir: 1 edge: make edge []]
            ] 
            if colors [
                color: first colors pane/1/color: second colors 
                pane/2/colors: pane/3/colors: append copy at colors 2 pane/2/colors/2
            ] 
            axis: pick [y x] size/y >= size/x 
            resize size
        ]
    ]]
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: func [][data: 0]
styles: none
init: [
    pane: reduce [
        make dragger [edge: make edge []] 
        axis: make svv/vid-styles/arrow [dir: -1 edge: make edge [] 
            color: first colors: [128.128.128 200.200.200] 
            action: get in svvf 'move-drag 
            feel: make svvf/scroll-button []
        ] 
        make axis [dir: 1 edge: make edge []]
    ] 
    if colors [
        color: first colors pane/1/color: second colors 
        pane/2/colors: pane/3/colors: append copy at colors 2 pane/2/colors/2
    ] 
    axis: pick [y x] size/y >= size/x 
    resize size
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [input]
doc: make object! [
    info: "base face style"
    string: none
    image: none
    logic: none
    integer: none
    pair: none
    tuple: none
    file: none
    url: none
    decimal: none
    time: none
    block: none
    keywords: none
]
step: 2E-2
ratio: none
page: none
axis: none
clip: 0x0
dragger: make object! [
    type: 'face
    offset: 0x0
    size: 100x100
    span: none
    pane: none
    text: none
    color: 128.128.128
    image: none
    effect: none
    data: none
    edge: make object! [
        color: 128.128.128
        image: none
        effect: 'bevel
        size: 1x1
    ]
    font: none
    para: none
    feel: make object! [
        redraw: none
        detect: none
        over: none
        engage: func [face action event][
            if find [over away] action [
                drag-off face/parent-face face face/offset + event/offset - face/data 
                show face
            ] 
            if find [down alt-down] action [face/data: event/offset]
        ]
    ]
    saved-area: none
    rate: none
    show?: true
    options: none
    parent-face: none
    old-offset: none
    old-size: none
    line-list: none
    changes: none
    face-flags: 0
    action: none
]
redrag: func [val /local tmp][
    state: none 
    ratio: min 1 max 0 val 
    page: any [all [ratio = 1 0] ratio / (1 - ratio)] 
    pane/1/size: val: size - (2 * edge/size) - (2 * clip * pick [0x1 1x0] axis = 'y) 
    tmp: val/:axis * ratio 
    if tmp < 10 [page: either val/:axis = tmp: 10 [1] [tmp / (val/:axis - tmp)]] 
    either axis = 'y [pane/1/size/y: tmp] [pane/1/size/x: tmp]
]
speed: 20
resize: func [new /x /y /local tmp][
    either any [x y] [
        if x [size/x: new] 
        if y [size/y: new]
    ] [
        size: any [new size]
    ] 
    tmp: pick [y x] axis = 'x 
    clip: pane/2/size: pane/3/size: size/:tmp - (2 * edge/size/:tmp) * 1x1 
    pane/3/offset: size/:axis - pane/3/size/:axis - (2 * edge/size/:axis) * 0x1 
    if tmp: axis = 'x [pane/3/offset: reverse pane/3/offset] 
    pane/2/data: pick [left up] tmp 
    pane/3/data: pick [right down] tmp 
    state: pane/2/effect: pane/3/effect: none 
    do pane/2/init do pane/3/init 
    pane/1/offset: 0x0 
    redrag any [ratio 0.1]
]

14.50 PROGRESS

type: face
offset: 0x0
size: 200x16
span: none
pane: none
text: none
color: 100.100.100
image: none
effect: [fit]
data: 0
edge: make object! [
    color: 128.128.128
    image: none
    effect: 'ibevel
    size: 2x2
]
font: none
para: none
feel: make object! [
    redraw: func [face act pos][
        face/data: max 0 min 1 face/data 
        if face/data <> face/state [
            either face/size/x > face/size/y [
                face/pane/size/x: max 1 face/data * face/size/x
            ] [
                face/pane/size/y: max 1 face/data * face/size/y 
                face/pane/offset: face/size - face/pane/size
            ] 
            face/state: face/data 
            if act = 'draw [show face/pane]
        ]
    ]
    detect: none
    over: none
    engage: none
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        if not number? value [
            make error! reform [face/style "must be set to a number"]
        ] 
        face/data: value
    ]
    get-face*: func [face][face/data]
    clear-face*: func [face][face/data: 0]
    reset-face*: func [face][face/data: 0]
]
style: IMAGE
alt-action: none
facets: [100.100.100 200x16 with [
        feel: svvf/progress 
        access: ctx-access/data-number 
        font: none 
        para: none 
        data: 0 
        edge: [size: 2x2 effect: 'ibevel color: 128.128.128] 
        flags: [input] 
        bar: make face [
            offset: 0x0 
            color: 0.80.200 
            edge: font: para: none
        ] 
        append init [
            pane: make bar [] 
            pane/size: size 
            either size/x > size/y [pane/size/x: 1] [pane/size/y: 1] 
            if colors [color: first colors pane/color: second colors]
        ]
    ]]
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if image? image [
        if none? size [size: image/size] 
        if size/y < 0 [size/y: size/x * image/size/y / image/size/x effect: insert copy effect 'fit] 
        if color [effect: join effect ['colorize color]]
    ] 
    if none? size [size: 100x100] 
    pane: make bar [] 
    pane/size: size 
    either size/x > size/y [pane/size/x: 1] [pane/size/y: 1] 
    if colors [color: first colors pane/color: second colors]
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [input]
doc: make object! [
    info: "base style for images"
    string: "text on top of image"
    image: "loaded image data"
    logic: none
    integer: none
    pair: "width and height of text area"
    tuple: "colorize the image"
    file: "load as image data"
    url: "load as image data"
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]
bar: make object! [
    type: 'face
    offset: 0x0
    size: 100x100
    span: none
    pane: none
    text: none
    color: 0.80.200
    image: none
    effect: none
    data: none
    edge: none
    font: none
    para: none
    feel: make object! [
        redraw: none
        detect: none
        over: none
        engage: none
    ]
    saved-area: none
    rate: none
    show?: true
    options: none
    parent-face: none
    old-offset: none
    old-size: none
    line-list: none
    changes: none
    face-flags: 0
    action: none
]

14.51 PANEL

type: face
offset: 0x0
size: -1x-1
span: none
pane: none
text: none
color: none
image: none
effect: [fit]
data: none
edge: make object! [
    color: 0.0.0
    image: none
    effect: none
    size: 0x0
]
font: make object! [
    name: "arial"
    style: 'bold
    size: 16
    color: 255.255.255
    offset: 2x2
    space: 0x0
    align: 'center
    valign: 'middle
    shadow: 2x2
    colors: [255.255.255 255.180.75]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: none
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-find-var: func [pane var value][
        foreach f pane [
            if all [
                find f/flags 'input 
                f/var = var 
                set-face f value
            ] [return true]
        ] 
        false
    ]
    set-face*: func [face value /local val][
        if all [block? face/pane block? value] [
            value: reduce value 
            foreach f face/pane [
                if any [find f/flags 'input find f/flags 'panel] [
                    if not empty? value [
                        val: value/1 
                        either word? val [
                            val: to-word val 
                            either f/var = val [set-face f value/2] [
                                if not set-find-var face/pane val value/2 [
                                    set-face/no-show f value/2
                                ]
                            ] 
                            value: skip value 2
                        ] [
                            set-face f val 
                            value: next value
                        ]
                    ]
                ]
            ]
        ]
    ]
    get-face*: func [face /local blk synth var][
        if block? face/pane [
            synth: copy [] 
            blk: make block! 6 
            foreach f face/pane [
                if any [find f/flags 'input find f/flags 'panel] [
                    if not word? var: f/var [
                        either var: find synth f/style [
                            change next var n: var/2 + 1
                        ] [
                            repend synth [f/style n: 1]
                        ] 
                        var: to-word rejoin [f/style #"-" n]
                    ] 
                    repend blk [to-set-word var get-face f]
                ]
            ]
        ] 
        blk
    ]
    clear-face*: func [face][
        if block? face/pane [
            foreach f face/pane [
                if any [find f/flags 'input find f/flags 'panel] [
                    clear-face/no-show f
                ]
            ]
        ]
    ]
    reset-face*: func [face][
        if block? face/pane [
            foreach f face/pane [
                if any [find f/flags 'input find f/flags 'panel] [
                    reset-face/no-show f
                ]
            ]
        ]
    ]
]
style: IMAGE
alt-action: none
facets: [with [
        feel: none 
        access: ctx-access/panel 
        size: -1x-1 
        flags: [panel] 
        append init [
            pane: layout/styles/tight/parent second :action copy self/styles compose [color: (color)] 
            pane/state: edge-size? self 
            if size/x < 0 [size/x: pane/size/x + pane/state/x] 
            if size/y < 0 [size/y: pane/size/y + pane/state/y] 
            color: pane/color 
            pane: pane/pane
        ]
    ]]
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if image? image [
        if none? size [size: image/size] 
        if size/y < 0 [size/y: size/x * image/size/y / image/size/x effect: insert copy effect 'fit] 
        if color [effect: join effect ['colorize color]]
    ] 
    if none? size [size: 100x100] 
    pane: layout/styles/tight/parent second :action copy self/styles compose [color: (color)] 
    pane/state: edge-size? self 
    if size/x < 0 [size/x: pane/size/x + pane/state/x] 
    if size/y < 0 [size/y: pane/size/y + pane/state/y] 
    color: pane/color 
    pane: pane/pane
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [panel]
doc: make object! [
    info: "base style for images"
    string: "text on top of image"
    image: "loaded image data"
    logic: none
    integer: none
    pair: "width and height of text area"
    tuple: "colorize the image"
    file: "load as image data"
    url: "load as image data"
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]

14.52 LIST

type: face
offset: 0x0
size: none
span: none
pane: none
text: none
color: 240.240.240
image: none
effect: [fit]
data: none
edge: make object! [
    color: 128.128.128
    image: none
    effect: 'ibevel
    size: 2x2
]
font: make object! [
    name: "arial"
    style: 'bold
    size: 16
    color: 255.255.255
    offset: 2x2
    space: 0x0
    align: 'center
    valign: 'middle
    shadow: 2x2
    colors: [255.255.255 255.180.75]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: none
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        if any [image? value none? value] [
            face/image: value
        ]
    ]
    get-face*: func [face][face/image]
    clear-face*: func [face][face/image: none]
]
style: IMAGE
alt-action: none
facets: [240.240.240 with [
        feel: none 
        subface: none 
        subfunc: none 
        edge: [size: 2x2 color: 128.128.128 effect: 'ibevel] 
        append init [
            subface: layout/parent/origin/styles second :action blank-face 0x0 copy self/styles 
            pane: func [face id /local count spane] [
                if pair? id [return 1 + second id / subface/size] 
                subface/offset: subface/old-offset: id - 1 * subface/size * 0x1 
                if subface/offset/y + subface/size/y > size/y [return none] 
                count: 0 
                foreach item subface/pane [
                    if object? item [
                        subfunc item id count: count + 1
                    ]
                ] 
                subface
            ]
        ] 
        set-it: func [face stuff index count /item] [
            item: stuff/:count/:index either file? item [face/image: load-image item] [face/text: any [item ""]]
        ] 
        words: [supply func [new args][new/subfunc: func [face count index] second args next args] 
            map func [new args][set-it: func [face stuff index count /map item] compose/deep [
                    map: [(second args)] 
                    item: stuff/:count/:index 
                    all ['text = map/:index none? item item: ""] 
                    either all ['image = map/:index any [file? item url? item]] [face/image: load-image item] [
                        all [map/:index set in face map/:index item]
                    ]
                ] 
                next args
            ] 
            data func [new args][new/subfunc: func [face count index /item /stuff] compose/deep [
                    stuff: [(second args)] 
                    either count > length? stuff [face/text: "" face/image: none] [
                        set-it face stuff index count
                    ]
                ] 
                next args
            ]
        ]
    ]]
related: none
words: [supply func [new args][new/subfunc: func [face count index] second args next args] 
    map func [new args][set-it: func [face stuff index count /map item] compose/deep [
            map: [(second args)] 
            item: stuff/:count/:index 
            all ['text = map/:index none? item item: ""] 
            either all ['image = map/:index any [file? item url? item]] [face/image: load-image item] [
                all [map/:index set in face map/:index item]
            ]
        ] 
        next args
    ] 
    data func [new args][new/subfunc: func [face count index /item /stuff] compose/deep [
            stuff: [(second args)] 
            either count > length? stuff [face/text: "" face/image: none] [
                set-it face stuff index count
            ]
        ] 
        next args
    ]
]
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if image? image [
        if none? size [size: image/size] 
        if size/y < 0 [size/y: size/x * image/size/y / image/size/x effect: insert copy effect 'fit] 
        if color [effect: join effect ['colorize color]]
    ] 
    if none? size [size: 100x100] 
    subface: layout/parent/origin/styles second :action blank-face 0x0 copy self/styles 
    pane: func [face id /local count spane] [
        if pair? id [return 1 + second id / subface/size] 
        subface/offset: subface/old-offset: id - 1 * subface/size * 0x1 
        if subface/offset/y + subface/size/y > size/y [return none] 
        count: 0 
        foreach item subface/pane [
            if object? item [
                subfunc item id count: count + 1
            ]
        ] 
        subface
    ]
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: []
doc: make object! [
    info: "base style for images"
    string: "text on top of image"
    image: "loaded image data"
    logic: none
    integer: none
    pair: "width and height of text area"
    tuple: "colorize the image"
    file: "load as image data"
    url: "load as image data"
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]
subface: none
subfunc: none
set-it: func [face stuff index count /item][
    item: stuff/:count/:index either file? item [face/image: load-image item] [face/text: any [item ""]]
]

14.53 TEXT-LIST

type: face
offset: 0x0
size: 200x200
span: none
pane: none
text: none
color: 240.240.240
image: none
effect: none
data: none
edge: none
font: make object! [
    name: "arial"
    style: none
    size: 12
    color: 0.0.0
    offset: 2x2
    space: 0x0
    align: 'left
    valign: 'top
    shadow: none
    colors: [0.0.0 255.180.75]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: none
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        all [in face 'picked insert clear head face/picked value]
    ]
    get-face*: func [face][get in face 'picked]
    clear-face*: func [face][all [in face 'picked clear face/picked]]
    reset-face*: func [face][all [in face 'picked clear face/picked]]
]
style: txt
alt-action: none
facets: [200x200 with [
        feel: none 
        access: ctx-access/data-pick 
        color: snow 
        colors: reduce [snow snow - 32] 
        sz: 
        iter: 
        sub-area: 
        sld: 
        sn: 
        lc: 
        picked: 
        cnt: 
        act: 
        slf: 
        lines: 
        none 
        append flags [as-is input] 
        text-pane: func [face id] [
            if pair? id [return 1 + second id / iter/size] 
            iter/offset: iter/old-offset: id - 1 * iter/size * 0x1 
            if iter/offset/y + iter/size/y > size/y [return none] 
            cnt: id: id + sn 
            if iter/text: pick data id [
                lines: at data id 
                iter
            ]
        ] 
        update: has [item value] [
            sld/redrag lc / max 1 length? data 
            if item: find data picked/1 [
                sld/data: min 1 (index? item) / (max 1 lc) 
                sn: max 0 to-integer sld/data * ((1 + length? data) - lc)
            ] [
                sld/value: 0.0 
                pane/offset: 0x0
            ] 
            self
        ] 
        resize: func [new /x /y /local tmp] [
            either any [x y] [
                if x [size/x: new] 
                if y [size/y: new]
            ] [
                size: any [new size]
            ] 
            pane/size: sz: size 
            sld/offset/x: first sub-area/size: size - 16x0 
            sld/resize/y: size/y 
            iter/size/x: first sub-area/size - sub-area/edge/size 
            lc: to-integer sz/y / iter/size/y 
            self
        ] 
        append init [
            sz: size 
            sn: 0 
            slf: :self 
            act: :action 
            if none? data [data: any [texts copy []]] 
            lines: data 
            picked: copy [] 
            iter: make-face/size 'txt sz * 1x0 + -16x20 
            iter/para: make self/para [origin: 2x0] 
            iter/font: make self/font [] 
            lc: to-integer sz/y / iter/size/y: second size-text iter 
            iter/feel: make iter/feel [
                redraw: func [f a i] [
                    iter/color: color 
                    if flag-face? slf striped [iter/color: pick next colors odd? cnt] 
                    if find picked iter/text [iter/color: svvc/field-select]
                ] 
                engage: func [f a e] [
                    if a = 'down [
                        if cnt > length? slf/data [exit] 
                        if not e/control [f/state: cnt clear picked] 
                        alter picked f/text 
                        do :act slf f/text
                    ] 
                    if a = 'up [f/state: none] 
                    show pane
                ]
            ] 
            pane: layout/size [
                origin 0 space 0 
                sub-area: box slf/color sz - 16x0 ibevel with [pane: :text-pane] 
                at sz * 1x0 - 16x0 
                sld: scroller sz * 0x1 + 16x0 [
                    if sn = value: max 0 to-integer value * ((1 + length? slf/data) - lc) [exit] 
                    sn: value 
                    show sub-area
                ]
            ] size 
            pane/offset: 0x0 
            sld/redrag lc / max 1 length? data
        ] 
        words: [
            data func [new args][new/text: pick new/texts: second args 1 next args]
        ]
    ]]
related: none
words: [
    data func [new args][new/text: pick new/texts: second args 1 next args]
]
colors: [240.240.240 208.208.208]
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if :action [feel: svvf/hot saved-area: true] 
    if all [not flag-face? self as-is string? text] [trim/lines text] 
    if none? text [text: copy ""] 
    change font/colors font/color 
    if none? size [size: -1x-1] 
    xy: size 
    if any [size/x < 0 size/y < 0] [
        state: max 1x1 pane-size * 9 / 10 - offset 
        if size/x < 0 [size/x: state/x] 
        if size/y < 0 [size/y: state/y] 
        size: (size-text self) + (edge-size? self) 
        + (to-pair all [para (to-pair para/margin) + to-pair para/origin])
    ] 
    if xy/x > 0 [size/x: xy/x] 
    if xy/y > 0 [size/y: xy/y] 
    sz: size 
    sn: 0 
    slf: :self 
    act: :action 
    if none? data [data: any [texts copy []]] 
    lines: data 
    picked: copy [] 
    iter: make-face/size 'txt sz * 1x0 + -16x20 
    iter/para: make self/para [origin: 2x0] 
    iter/font: make self/font [] 
    lc: to-integer sz/y / iter/size/y: second size-text iter 
    iter/feel: make iter/feel [
        redraw: func [f a i] [
            iter/color: color 
            if flag-face? slf striped [iter/color: pick next colors odd? cnt] 
            if find picked iter/text [iter/color: svvc/field-select]
        ] 
        engage: func [f a e] [
            if a = 'down [
                if cnt > length? slf/data [exit] 
                if not e/control [f/state: cnt clear picked] 
                alter picked f/text 
                do :act slf f/text
            ] 
            if a = 'up [f/state: none] 
            show pane
        ]
    ] 
    pane: layout/size [
        origin 0 space 0 
        sub-area: box slf/color sz - 16x0 ibevel with [pane: :text-pane] 
        at sz * 1x0 - 16x0 
        sld: scroller sz * 0x1 + 16x0 [
            if sn = value: max 0 to-integer value * ((1 + length? slf/data) - lc) [exit] 
            sn: value 
            show sub-area
        ]
    ] size 
    pane/offset: 0x0 
    sld/redrag lc / max 1 length? data
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [flags text as-is input]
doc: make object! [
    info: "document text"
    string: "text contents"
    image: none
    logic: none
    integer: "width of text area"
    pair: "width and height of text area"
    tuple: ["text color" "background color"]
    file: none
    url: none
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]
xy: none
sz: none
iter: none
sub-area: none
sld: none
sn: none
lc: none
picked: none
cnt: none
act: none
slf: none
lines: none
text-pane: func [face id][
    if pair? id [return 1 + second id / iter/size] 
    iter/offset: iter/old-offset: id - 1 * iter/size * 0x1 
    if iter/offset/y + iter/size/y > size/y [return none] 
    cnt: id: id + sn 
    if iter/text: pick data id [
        lines: at data id 
        iter
    ]
]
update: func [/local item value][
    sld/redrag lc / max 1 length? data 
    if item: find data picked/1 [
        sld/data: min 1 (index? item) / (max 1 lc) 
        sn: max 0 to-integer sld/data * ((1 + length? data) - lc)
    ] [
        sld/value: 0.0 
        pane/offset: 0x0
    ] 
    self
]
resize: func [new /x /y /local tmp][
    either any [x y] [
        if x [size/x: new] 
        if y [size/y: new]
    ] [
        size: any [new size]
    ] 
    pane/size: sz: size 
    sld/offset/x: first sub-area/size: size - 16x0 
    sld/resize/y: size/y 
    iter/size/x: first sub-area/size - sub-area/edge/size 
    lc: to-integer sz/y / iter/size/y 
    self
]

14.54 ANIM

type: face
offset: 0x0
size: none
span: none
pane: none
text: none
color: none
image: none
effect: [fit]
data: none
edge: make object! [
    color: 0.0.0
    image: none
    effect: none
    size: 0x0
]
font: make object! [
    name: "arial"
    style: 'bold
    size: 16
    color: 255.255.255
    offset: 2x2
    space: 0x0
    align: 'center
    valign: 'middle
    shadow: 2x2
    colors: [255.255.255 255.180.75]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: make object! [
    redraw: none
    detect: none
    over: none
    engage: func [face action event][
        if action = 'time [
            face/image: first face/frames 
            if tail? face/frames: next face/frames [
                face/frames: head face/frames
            ] 
            show face
        ]
    ]
    cue: none
    blink: none
]
saved-area: none
rate: 1
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        if any [image? value none? value] [
            face/image: value
        ]
    ]
    get-face*: func [face][face/image]
    clear-face*: func [face][face/image: none]
]
style: IMAGE
alt-action: none
facets: [with [
        frames: copy [] 
        rate: 1 
        feel: make feel [
            engage: func [face action event] [
                if action = 'time [
                    face/image: first face/frames 
                    if tail? face/frames: next face/frames [
                        face/frames: head face/frames
                    ] 
                    show face
                ]
            ]
        ] 
        words: [
            frames func [new args][append new/frames second args next args] 
            rate func [new args][new/rate: second args next args]
        ] 
        init: append copy init [
            forall frames [change frames load-image first frames] 
            frames: head frames 
            image: first frames
        ]
    ]]
related: none
words: [
    frames func [new args][append new/frames second args next args] 
    rate func [new args][new/rate: second args next args]
]
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if image? image [
        if none? size [size: image/size] 
        if size/y < 0 [size/y: size/x * image/size/y / image/size/x effect: insert copy effect 'fit] 
        if color [effect: join effect ['colorize color]]
    ] 
    if none? size [size: 100x100] 
    forall frames [change frames load-image first frames] 
    frames: head frames 
    image: first frames
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: []
doc: make object! [
    info: "base style for images"
    string: "text on top of image"
    image: "loaded image data"
    logic: none
    integer: none
    pair: "width and height of text area"
    tuple: "colorize the image"
    file: "load as image data"
    url: "load as image data"
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]
frames: []

14.55 BTN

type: face
offset: 0x0
size: -1x22
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: none
font: make object! [
    name: "arial"
    style: none
    size: 11
    color: 0.0.0
    offset: 14x0
    space: 0x0
    align: 'center
    valign: 'middle
    shadow: none
    colors: none
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: make object! [
    redraw: func [face act pos /local state][
        if all [face/texts face/texts/2] [
            face/text: either face/state [face/texts/2] [face/texts/1]
        ] 
        either face/images [
            face/image: either face/state [face/images/2] [face/images/1] 
            if all [face/colors face/effect find face/effect 'colorize] [
                change next find face/effect 'colorize pick face/colors not face/state
            ]
        ] [
            if face/edge [face/edge/effect: pick [ibevel bevel] face/state] 
            state: either not face/state [face/blinker] [true] 
            if face/colors [face/color: pick face/colors not state] 
            if face/effects [face/effect: pick face/effects not state]
        ]
    ]
    detect: none
    over: func [face act evt][
        remove/part find face/effect 'mix 2 
        if act [
            evt: any [find face/effect 'extend tail face/effect] 
            insert evt reduce ['mix face/images/3]
        ] 
        show face
    ]
    engage: func [face action event][
        remove/part find face/effect 'mix 2 
        switch action [
            down [face/state: on] 
            alt-down [face/state: on] 
            up [if face/state [do-face face face/text] face/state: off] 
            alt-up [if face/state [do-face-alt face face/text] face/state: off] 
            over [face/state: on] 
            away [face/state: off]
        ] 
        cue face action 
        show face
    ]
    cue: none
    blink: none
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][face/data: value]
    get-face*: func [face][face/data]
    clear-face*: func [face][face/data: false]
    reset-face*: func [face][face/data: false]
]
style: FACE
alt-action: none
facets: [-1x22 with [
        color: image: none 
        font: [color: black colors: none style: none size: 11 shadow: none align: 'center valign: 'middle offset: 14x0] 
        edge: none 
        effects: none 
        feel: svvf/btn 
        colors: color: none 
        depth: 128 
        init: [
            if size/x = -1 [
                either text [
                    use [tmp] [
                        size/x: 1000 
                        tmp: size-text self 
                        size/x: either tmp [tmp/x + font/offset/x] [50]
                    ]
                ] [
                    size/x: 50
                ]
            ] 
            if font/colors [font/color: first font/colors] 
            if not images [
                images: reduce [btn-up.png btn-dn.png load-stock 'btn-hover]
            ] 
            if images [image: images/1] 
            if colors [color: colors/1] 
            if all [image not effect] [
                effect: copy [] 
                if color [repend effect ['colorize color depth]] 
                repend effect ['extend image/size/2]
            ] 
            color: none
        ]
    ]]
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if size/x = -1 [
        either text [
            use [tmp] [
                size/x: 1000 
                tmp: size-text self 
                size/x: either tmp [tmp/x + font/offset/x] [50]
            ]
        ] [
            size/x: 50
        ]
    ] 
    if font/colors [font/color: first font/colors] 
    if not images [
        images: reduce [btn-up.png btn-dn.png load-stock 'btn-hover]
    ] 
    if images [image: images/1] 
    if colors [color: colors/1] 
    if all [image not effect] [
        effect: copy [] 
        if color [repend effect ['colorize color depth]] 
        repend effect ['extend image/size/2]
    ] 
    color: none
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: []
doc: make object! [
    info: "base face style"
    string: none
    image: none
    logic: none
    integer: none
    pair: none
    tuple: none
    file: none
    url: none
    decimal: none
    time: none
    block: none
    keywords: none
]
effects: none
depth: 128

14.56 BTN-ENTER

type: face
offset: 0x0
size: -1x22
span: none
pane: none
text: "Enter"
color: 255.190.80
image: none
effect: none
data: none
edge: none
font: make object! [
    name: "arial"
    style: none
    size: 11
    color: 0.0.0
    offset: 14x0
    space: 0x0
    align: 'center
    valign: 'middle
    shadow: none
    colors: none
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: make object! [
    redraw: func [face act pos /local state][
        if all [face/texts face/texts/2] [
            face/text: either face/state [face/texts/2] [face/texts/1]
        ] 
        either face/images [
            face/image: either face/state [face/images/2] [face/images/1] 
            if all [face/colors face/effect find face/effect 'colorize] [
                change next find face/effect 'colorize pick face/colors not face/state
            ]
        ] [
            if face/edge [face/edge/effect: pick [ibevel bevel] face/state] 
            state: either not face/state [face/blinker] [true] 
            if face/colors [face/color: pick face/colors not state] 
            if face/effects [face/effect: pick face/effects not state]
        ]
    ]
    detect: none
    over: func [face act evt][
        remove/part find face/effect 'mix 2 
        if act [
            evt: any [find face/effect 'extend tail face/effect] 
            insert evt reduce ['mix face/images/3]
        ] 
        show face
    ]
    engage: func [face action event][
        remove/part find face/effect 'mix 2 
        switch action [
            down [face/state: on] 
            alt-down [face/state: on] 
            up [if face/state [do-face face face/text] face/state: off] 
            alt-up [if face/state [do-face-alt face face/text] face/state: off] 
            over [face/state: on] 
            away [face/state: off]
        ] 
        cue face action 
        show face
    ]
    cue: none
    blink: none
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][face/data: value]
    get-face*: func [face][face/data]
    clear-face*: func [face][face/data: false]
    reset-face*: func [face][face/data: false]
]
style: btn
alt-action: none
facets: ["Enter" 255.190.80]
related: none
words: none
colors: none
texts: ["Enter"]
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if size/x = -1 [
        either text [
            use [tmp] [
                size/x: 1000 
                tmp: size-text self 
                size/x: either tmp [tmp/x + font/offset/x] [50]
            ]
        ] [
            size/x: 50
        ]
    ] 
    if font/colors [font/color: first font/colors] 
    if not images [
        images: reduce [btn-up.png btn-dn.png load-stock 'btn-hover]
    ] 
    if images [image: images/1] 
    if colors [color: colors/1] 
    if all [image not effect] [
        effect: copy [] 
        if color [repend effect ['colorize color depth]] 
        repend effect ['extend image/size/2]
    ] 
    color: none
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: []
doc: make object! [
    info: "base face style"
    string: none
    image: none
    logic: none
    integer: none
    pair: none
    tuple: none
    file: none
    url: none
    decimal: none
    time: none
    block: none
    keywords: none
]
effects: none
depth: 128

14.57 BTN-CANCEL

type: face
offset: 0x0
size: -1x22
span: none
pane: none
text: "Cancel"
color: 144.174.240
image: none
effect: none
data: none
edge: none
font: make object! [
    name: "arial"
    style: none
    size: 11
    color: 0.0.0
    offset: 14x0
    space: 0x0
    align: 'center
    valign: 'middle
    shadow: none
    colors: none
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: make object! [
    redraw: func [face act pos /local state][
        if all [face/texts face/texts/2] [
            face/text: either face/state [face/texts/2] [face/texts/1]
        ] 
        either face/images [
            face/image: either face/state [face/images/2] [face/images/1] 
            if all [face/colors face/effect find face/effect 'colorize] [
                change next find face/effect 'colorize pick face/colors not face/state
            ]
        ] [
            if face/edge [face/edge/effect: pick [ibevel bevel] face/state] 
            state: either not face/state [face/blinker] [true] 
            if face/colors [face/color: pick face/colors not state] 
            if face/effects [face/effect: pick face/effects not state]
        ]
    ]
    detect: none
    over: func [face act evt][
        remove/part find face/effect 'mix 2 
        if act [
            evt: any [find face/effect 'extend tail face/effect] 
            insert evt reduce ['mix face/images/3]
        ] 
        show face
    ]
    engage: func [face action event][
        remove/part find face/effect 'mix 2 
        switch action [
            down [face/state: on] 
            alt-down [face/state: on] 
            up [if face/state [do-face face face/text] face/state: off] 
            alt-up [if face/state [do-face-alt face face/text] face/state: off] 
            over [face/state: on] 
            away [face/state: off]
        ] 
        cue face action 
        show face
    ]
    cue: none
    blink: none
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][face/data: value]
    get-face*: func [face][face/data]
    clear-face*: func [face][face/data: false]
    reset-face*: func [face][face/data: false]
]
style: btn
alt-action: none
facets: ["Cancel" 144.174.240]
related: none
words: none
colors: none
texts: ["Cancel"]
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if size/x = -1 [
        either text [
            use [tmp] [
                size/x: 1000 
                tmp: size-text self 
                size/x: either tmp [tmp/x + font/offset/x] [50]
            ]
        ] [
            size/x: 50
        ]
    ] 
    if font/colors [font/color: first font/colors] 
    if not images [
        images: reduce [btn-up.png btn-dn.png load-stock 'btn-hover]
    ] 
    if images [image: images/1] 
    if colors [color: colors/1] 
    if all [image not effect] [
        effect: copy [] 
        if color [repend effect ['colorize color depth]] 
        repend effect ['extend image/size/2]
    ] 
    color: none
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: []
doc: make object! [
    info: "base face style"
    string: none
    image: none
    logic: none
    integer: none
    pair: none
    tuple: none
    file: none
    url: none
    decimal: none
    time: none
    block: none
    keywords: none
]
effects: none
depth: 128

14.58 BTN-HELP

type: face
offset: 0x0
size: 22x22
span: none
pane: none
text: "?"
color: 190.50.50
image: none
effect: none
data: none
edge: none
font: make object! [
    name: "arial"
    style: [bold]
    size: 11
    color: 255.255.255
    offset: 14x0
    space: 0x0
    align: 'center
    valign: 'middle
    shadow: none
    colors: none
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: make object! [
    redraw: func [face act pos /local state][
        if all [face/texts face/texts/2] [
            face/text: either face/state [face/texts/2] [face/texts/1]
        ] 
        either face/images [
            face/image: either face/state [face/images/2] [face/images/1] 
            if all [face/colors face/effect find face/effect 'colorize] [
                change next find face/effect 'colorize pick face/colors not face/state
            ]
        ] [
            if face/edge [face/edge/effect: pick [ibevel bevel] face/state] 
            state: either not face/state [face/blinker] [true] 
            if face/colors [face/color: pick face/colors not state] 
            if face/effects [face/effect: pick face/effects not state]
        ]
    ]
    detect: none
    over: func [face act evt][
        remove/part find face/effect 'mix 2 
        if act [
            evt: any [find face/effect 'extend tail face/effect] 
            insert evt reduce ['mix face/images/3]
        ] 
        show face
    ]
    engage: func [face action event][
        remove/part find face/effect 'mix 2 
        switch action [
            down [face/state: on] 
            alt-down [face/state: on] 
            up [if face/state [do-face face face/text] face/state: off] 
            alt-up [if face/state [do-face-alt face face/text] face/state: off] 
            over [face/state: on] 
            away [face/state: off]
        ] 
        cue face action 
        show face
    ]
    cue: none
    blink: none
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: func [face value][notify "Help is not available."]
state: false
access: make object! [
    set-face*: func [face value][face/data: value]
    get-face*: func [face][face/data]
    clear-face*: func [face][face/data: false]
    reset-face*: func [face][face/data: false]
]
style: btn
alt-action: none
facets: [bold "?" 22x22 190.50.50 font-color 255.255.255 with [keycode: 'f1] [notify "Help is not available."]]
related: none
words: none
colors: none
texts: ["?"]
images: none
file: none
var: none
keycode: f1
reset: none
styles: none
init: [
    if size/x = -1 [
        either text [
            use [tmp] [
                size/x: 1000 
                tmp: size-text self 
                size/x: either tmp [tmp/x + font/offset/x] [50]
            ]
        ] [
            size/x: 50
        ]
    ] 
    if font/colors [font/color: first font/colors] 
    if not images [
        images: reduce [btn-up.png btn-dn.png load-stock 'btn-hover]
    ] 
    if images [image: images/1] 
    if colors [color: colors/1] 
    if all [image not effect] [
        effect: copy [] 
        if color [repend effect ['colorize color depth]] 
        repend effect ['extend image/size/2]
    ] 
    color: none
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [flags font]
doc: make object! [
    info: "base face style"
    string: none
    image: none
    logic: none
    integer: none
    pair: none
    tuple: none
    file: none
    url: none
    decimal: none
    time: none
    block: none
    keywords: none
]
effects: none
depth: 128

14.59 LOGO-BAR

type: face
offset: 0x0
size: none
span: none
pane: none
text: none
color: none
image: none
effect: [fit]
data: none
edge: make object! [
    color: 0.0.0
    image: none
    effect: none
    size: 0x0
]
font: make object! [
    name: "arial"
    style: 'bold
    size: 16
    color: 255.255.255
    offset: 2x2
    space: 0x0
    align: 'center
    valign: 'middle
    shadow: 2x2
    colors: [255.255.255 255.180.75]
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: make object! [
    redraw: none
    detect: none
    over: none
    engage: func [face action event][
        switch action [
            time [if not face/state [face/blinker: not face/blinker]] 
            down [face/state: on] 
            alt-down [face/state: on] 
            up [if face/state [do-face face face/text] face/state: off] 
            alt-up [if face/state [do-face-alt face face/text] face/state: off] 
            over [face/state: on] 
            away [face/state: off]
        ] 
        cue face action 
        show face
    ]
    cue: none
    blink: none
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][
        if any [image? value none? value] [
            face/image: value
        ]
    ]
    get-face*: func [face][face/image]
    clear-face*: func [face][face/image: none]
]
style: IMAGE
alt-action: none
facets: [with [
        update: does [
            self/pane/1/offset/y: self/size/y - 100 
            self/pane/2/size/y: self/size/y - 99 
            self
        ] 
        resize: func [siz /x /y] [
            either any [x y] [
                if x [size/x: siz] 
                if y [size/y: siz]
            ] [size: siz] 
            update
        ] 
        logo-vert: [
            size 24x100 origin 0x0 
            image logo.gif 100x100 effect [rotate 270]
        ] 
        init: [
            pane: reduce [
                make face [offset: 0x199 image: to-image layout logo-vert size: 24x100 edge: none] 
                make face [size: 24x200 effect: [gradient 0x1 50.70.140 0.0.0] edge: none]
            ] 
            if none? size [size: 24x300] 
            update self
        ]
    ]]
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    pane: reduce [
        make face [offset: 0x199 image: to-image layout logo-vert size: 24x100 edge: none] 
        make face [size: 24x200 effect: [gradient 0x1 50.70.140 0.0.0] edge: none]
    ] 
    if none? size [size: 24x300] 
    update self
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: []
doc: make object! [
    info: "base style for images"
    string: "text on top of image"
    image: "loaded image data"
    logic: none
    integer: none
    pair: "width and height of text area"
    tuple: "colorize the image"
    file: "load as image data"
    url: "load as image data"
    decimal: none
    time: none
    block: ["execute when clicked" "execute when alt-clicked"]
    keywords: none
]
update: func [][
    self/pane/1/offset/y: self/size/y - 100 
    self/pane/2/size/y: self/size/y - 99 
    self
]
resize: func [siz /x /y][
    either any [x y] [
        if x [size/x: siz] 
        if y [size/y: siz]
    ] [size: siz] 
    update
]
logo-vert: [
    size 24x100 origin 0x0 
    image logo.gif 100x100 effect [rotate 270]
]

14.60 TOG

type: face
offset: 0x0
size: -1x22
span: none
pane: none
text: none
color: none
image: none
effect: none
data: none
edge: none
font: make object! [
    name: "arial"
    style: none
    size: 11
    color: 0.0.0
    offset: 14x0
    space: 0x0
    align: 'center
    valign: 'middle
    shadow: none
    colors: none
]
para: make object! [
    origin: 2x2
    margin: 2x2
    indent: 0x0
    tabs: 40
    wrap?: true
    scroll: 0x0
]
feel: make object! [
    redraw: func [face act pos /local state][
        if all [face/texts face/texts/2] [
            face/text: either face/state [face/texts/2] [face/texts/1]
        ] 
        either face/images [
            face/image: either face/state [face/images/2] [face/images/1] 
            if all [face/colors face/effect find face/effect 'colorize] [
                change next find face/effect 'colorize pick face/colors not face/state
            ]
        ] [
            if face/edge [face/edge/effect: pick [ibevel bevel] face/state] 
            state: either not face/state [face/blinker] [true] 
            if face/colors [face/color: pick face/colors not state] 
            if face/effects [face/effect: pick face/effects not state]
        ]
    ]
    detect: none
    over: func [face act evt][
        remove/part find face/effect 'mix 2 
        if act [
            evt: any [find face/effect 'extend tail face/effect] 
            insert evt reduce ['mix face/images/3]
        ] 
        show face
    ]
    engage: func [face action event][
        if find [down alt-down] action [
            if face/related [
                foreach item face/parent-face/pane [
                    if all [flag-face? item toggle item/related item/related = face/related item/data] [item/data: item/state: false show item]
                ]
            ] 
            face/data: face/state: not face/state 
            either action = 'down [do-face face face/data] [do-face-alt face face/data] 
            show face
        ]
    ]
    cue: none
    blink: none
]
saved-area: none
rate: none
show?: true
options: none
parent-face: none
old-offset: none
old-size: none
line-list: none
changes: none
face-flags: 0
action: none
state: false
access: make object! [
    set-face*: func [face value][face/data: face/state: value]
    get-face*: func [face][face/data]
    clear-face*: func [face][face/data: face/state: false]
    reset-face*: func [face][face/data: face/state: false]
]
style: BTN
alt-action: none
facets: [with [
        feel: svvf/tog 
        access: ctx-access/data-state 
        flags: [toggle input]
    ]]
related: none
words: none
colors: none
texts: none
images: none
file: none
var: none
keycode: none
reset: none
styles: none
init: [
    if size/x = -1 [
        either text [
            use [tmp] [
                size/x: 1000 
                tmp: size-text self 
                size/x: either tmp [tmp/x + font/offset/x] [50]
            ]
        ] [
            size/x: 50
        ]
    ] 
    if font/colors [font/color: first font/colors] 
    if not images [
        images: reduce [btn-up.png btn-dn.png load-stock 'btn-hover]
    ] 
    if images [image: images/1] 
    if colors [color: colors/1] 
    if all [image not effect] [
        effect: copy [] 
        if color [repend effect ['colorize color depth]] 
        repend effect ['extend image/size/2]
    ] 
    color: none
]
multi: make object! [
    text: func [face blk][
        if pick blk 1 [
            face/text: first blk 
            face/texts: copy blk
        ]
    ]
    size: func [face blk][
        if pick blk 1 [
            if pair? first blk [face/size: first blk] 
            if integer? first blk [
                if none? face/size [face/size: -1x-1] 
                face/size/x: first blk
            ]
        ]
    ]
    file: func [face blk][
        if pick blk 1 [
            face/image: load-image face/file: first blk 
            if pick blk 2 [
                face/colors: reduce [face/image] 
                foreach i next blk [
                    append face/colors load-image i
                ]
            ]
        ]
    ]
    image: func [face blk][
        if pick blk 1 [
            face/image: first blk 
            if pick blk 2 [face/images: copy blk]
        ]
    ]
    color: func [face blk][
        if pick blk 1 [
            either flag-face? face text [
                set-font face color first blk 
                if pick blk 2 [face/color: second blk]
            ] [
                face/color: first blk
            ] 
            if pick blk 2 [face/colors: copy blk]
        ]
    ]
    block: func [face blk][
        if pick blk 1 [
            face/action: func [face value] pick blk 1 
            if pick blk 2 [face/alt-action: func [face value] pick blk 2]
        ]
    ]
]
blinker: none
pane-size: none
dirty?: none
help: none
user-data: none
flags: [toggle input]
doc: make object! [
    info: "base face style"
    string: none
    image: none
    logic: none
    integer: none
    pair: none
    tuple: none
    file: none
    url: none
    decimal: none
    time: none
    block: none
    keywords: none
]
effects: none
depth: 128