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. ===The target audience and references The target audience for this document is someone in one of the following groups. *Those who know REBOL already and want to know what GUI capabilities are available. Note that important point, that you know REBOL already and are interested in branching out of the basics into GUI programming. *Those who like a more "reference manual" style of documentation instead of a more "tutorial" style. 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 ===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. ===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: ---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. ---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. ---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. ===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. ---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. ---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. ---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. ---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. ===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: ---Keyword The words like "above" and "below" explained previously, used to control positioning on the layout, are called "keywords." ---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. ---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. ---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." ---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." ---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." ===Overview of all styles (the things you put on windows) \note 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. /note 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). \note 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. /note 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" ] ] ===Facets: The attributes of styles \note 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. /note 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. ---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 ---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. ---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. ---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. ---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. ---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"] ---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. ---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] ---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 ] ] ---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. ---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 ---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. ---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 ] ---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"] ] ===Positioning items (styles), and other attributes \note 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. /note 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. ---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. ---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" ---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" ---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. ---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 ---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. ---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" ---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" ---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" ---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. ---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" ---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" ---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" ===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. \note 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. /note 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: *All the "facets" that can reasonably apply to that style, referencing the previous chapter that explains all the possible facets. As noted previously, because all styles come from a master interface object, one could potentially apply all facets to any style. Because the number of combinations would be too vast to list, this document shows the ones that would be most likely to be used. Remember that facets are keywords and values that follow the sytle word. *An explanation of how to use that style. For example, if the style is a button, you will want to know how to make the button do something. If the style is a field, you will want to know how to get whatever is typed into the field. If the style is text on the window, you will want to know how to refresh it. *A decent set of examples. It will not be possible to give examples of everything. We want to provide enough examples so you can start using the style right away. 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. \note 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. /note 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 ] ;; [ .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. ---Banner The banner style is generally used for some big text like a window heading. Commonly-used facets: *text: This is the text of the banner. *font: This controls the text attributes. *action: This allows a banner to be clickable. *color: Alters default color *size: Specified the amount of window space used. 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 ---Title The title style is another option for window text. Commonly-used facets: *text: The text of the title *font: The appearance of the title *action: Make the title clickable *color: Alters default color *size: Specified the amount of window space used. title "Default title text" title "Titles can be made small" font [size: 12] title "And clickable" [print "left-clicked"] [print "right-clicked"] ---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: *text: The text of the heading. *font: Controls the appearance. *action: Make a heading clickable. *color: Alters default color *size: Specified the amount of window space used. 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 ---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: *text: The text of the heading. *font: Controls the appearance. *action: Make a heading clickable. *color: Alters default color *size: Specified the amount of window space used. 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 ---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: *text: The text of the label. *font: Controls the appearance. *action: Make a label clickable. *color: Alters default color *size: Specified the amount of window space used. 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 ---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: The text of the label. *font: Controls the appearance. *action: Make a label clickable. *color: Alters default color *size: Specified the amount of window space used. 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" ---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: *text: The text of the label. *font: Controls the appearance. *action: Make a label clickable, but only with the left button. *color: Alters default color of the background, not the text. *size: Specified the amount of window space used. 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"] ---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: The name of an image file *action: An image can be clickable. *size: This specifies the size of the area to be filled with the image. *text: You may put test on top of the image. *font: Controls the appearance of the text facet if it is present. *color: This will overlay the picture with a color. *effect: Apply visual effects, as explained in the section on effect. image 100x100 http://www.rebol.com/graphics/reb-logo.gif red "test" font [color: blue] [print "left-clicked"] [print "right-clicked"] \note 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 /note ---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: *image: The name of an image file to be put in the box *action: An box can be clickable *size: This specifies the size of the box. *text: You may put test in the box. *font: Controls the appearance of the text facet if it is present. *color: This will overlay the picture with a color. *effect: Apply visual effects, as explained in the section on effect. *rate: Apply a timer event. \note 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. /note 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]] ---Button The button style is a clickable button. Commonly-used facets: *size: This is a pair that sets the size of the button. *text: This is a text string that will be printed on the button. *color: This is a tuple or word to set the button color. *image: This can be used to put a picture on a button. *action: This is a block of code after the button. *character: A button can have a shortcut key. *font: This controls the font of the text facet. 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"] ---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: *size: You can specify the size, but might not want to bother since these are somewhat-predefined buttons. *text: This is text for the btn style. The other buttons have pre-assigned text. *action: This is the block of code after the button. 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? ---Bar This is a basic horizontal bar, for window decoration. Commonly-used facets: *size: This controls the length. I also can control thickness, if you must. *color: This controls the color of the bar. Examples: bar bar 300 bar 200x30 bar red ---Icon This style displays a specified image file as a standard-size icon with a caption. Commonly-used-facets: *image: This identifies the image file to be turned into an icon. *size: This controls the size if you don't want the standard size. *font: This controls some attributes of the caption, but it appears that not all attributes work. *action: These are left-click and right-click blocks of code that are executed when you click the icon. 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. ---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 ---Led This is a little indicator button. It has a color of either red or green that toggles when left-clicked. Commonly-used facets: *size: Size can be specifiedd, if you don't like the default which seems readonable for an LED. *action: This is an action block that will be executed on left-click. Right-click does not work. What happens when you click the LED is that the procedure is executed and the color toggles between red and green. It would be up to your code to keep track of when things are "on" or "off." Examples: led [print "Left click small"] led 50x50 [print "Left click big"] ---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: *action: Only the left-click action works, and it specifies what to do when the arrow is clicked. Examples: arrow arrow 50x50 arrow 50x50 left arrow 50x50 down arrow 50x50 right arrow 60x60 red [print "Left click"] [print "Right click"] ---Progress This is a progress bar like you are used to seeing on many applications. Commonly-used facets: *size: There is a default size, but any size can be specified. *color: You can specify a background color for the bar plus a color for the moving part of the bar. *data: This facet is set to a fractional number between zero and one, which indicates what fraction of the bar is filled. 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] ] ---Field \note 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. /note This is the commonly-used sytle for entering short data items. Commonly-used facets: *size: You might want to make bigger fields to hold bigger text. *color: This controls the background color. A second color facet indicates the color to show when the field is being filled, or when it "has the focus" as they say in the lingo. *text: This refers to the text that has been entered into the field, and also to any text you might specify in the layout that "pre-fills" the field. 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 ] ---Area \note As noted under "field," there is a more thorough document on the REBOL web site about text styles. /note This is a style used for entry of larger amounts of text, like paragraphs of it. Commonly-used facets: *size: There is a default area size, but you may specify your own with a pair representing width by height. *color: One or two color words set the background and text colors. *text: This is the text in the area. *font: A font block can be used to specify the various font attributes. 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 ] ] ---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: *size: There is a default size, and you can alter the size. *color: One or two color words set the text and background colors. *data: This is a block of items that are put into the list. *font: This controls the font of the data items. 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] ] ---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. ---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 ---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 ] ---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 ] ---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" ---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] ---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] ] ---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] ---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 ] ] ---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. ===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. \note 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. /note 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. ---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. ---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 ---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 ---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 ---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 ---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 ---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. ---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] ---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 ---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 ---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 ] ---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 ] ---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 ---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 ---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 ---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 \note 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: /note either PASSWORD: request-pass/title/only "Password for defaultuser" [ alert rejoin [ PASSWORD " is correct" ] ] [ alert "No password entered" ] ---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 ---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 ---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 ---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] ] ---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] ] ---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] ] ---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] ] ---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] ] ---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 ---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 ---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 ---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 ---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 ] ---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] ] ---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. ---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. ---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. ---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. ===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 ] ;; [ .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 ] ===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. ---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 ] ] ] ---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 ---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] ] ---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 ---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 ---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 ---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 ---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" ---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 ---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 ---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 ] ---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 ] ] ] ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ---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 ---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 ] ===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." ---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 ---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 ---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 ---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 ---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 ---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 ---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 \note 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. /note ===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." ---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 ] ---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 ] ---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 ] ---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 ] ---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 ] ---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 ] ---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 ] ---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 ] ---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 ] ---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 ---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 ---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 ---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 ---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 ---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 ---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 ---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 ---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 ---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 ---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 ---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 ---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 ---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 ---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 ---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 ---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 ---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 ---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 ---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 ---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 ---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 ---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 ---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 ---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 ---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 ---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 ---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 ---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 ---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 ---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 ---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 ---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 ---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] ] ---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 ---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 ] ---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 ] ---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 ] ---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] ] ---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] ] ---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 ] ---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 ] ---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 ""]] ] ---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 ] ---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: [] ---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 ---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 ---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 ---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 ---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] ] ---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 ###