ͻ
 Text based GUI Toolkit                                       Version 0.6a 
     (c) David Cuny                                                        
     July 30, 1997                                                         
     Internet:  dcuny@lanset.com                                           
ͼ


ͻ
 WHAT'S NEW                                                                
ͼ

I've added a "close" button to the dialogs, and made a number of cosmetic
fixes to the graphical user interfaces. Additionally, I've added a new
UI, called PLAIN.EX, which is the default UI.

While I'm no longer on the Euphoria discussion group, I encourage you to send
me e-mail if you have any questions, or ideas!


ͻ
 BACKGROUND                                                                
ͼ

The initial reason I wrote the toolkit was to create an editor for Euphoria
that was more akin to the MS-DOS editor that I've grown used to, with a few
improvements - namely, the "correct" keys for editing: ^X, ^V, etc.

I've taken the pieces and worked them into an integrated toolkit. I've tried
to come up with a design that are a good balance between being flexible, and
easy to use. I think I've done that.

The goals of the toolkit are:

    - Standard look-and-feel
       
      Applications written using this toolkit will have the same "look and
      feel" that users will immediately be familiar with.
                                      
    - Modular code
       
      It should be easy to add other types of controls to the toolkit. This
      is hard for me to judge, since code that is "easy" for me may be 
      something else for any other programmer.
              
    - "Plug and Play"
       
      At the most basic level, you can simply load up the data structure
      and call the dialog functions without having to add your own code.

To get a feel for what can be done with the toolkit, run EE.EX. It's
modeled after the DOS-based text editor that comes with Win95. README.TXT
presents some of the features in the demo.

Even if you can't use the tools, take a look at KEYS.E and INTENSE.E. You
just might find something useful after all.

ͻ
 WHAT'S IN THE TOOLKIT                                                     
ͼ

The controls all have the same "look and feel" as the MS-DOS editor. Features
include:

        - Drop-down menus have: Hot Keys
                                Help text
                                Checked items
                                Dimmed Items
                                Shadows

        - Multi-line Edit:      Standard edit key functions
                                Horizontal and vertical scrolling
                                Multi-line text section
                                Scroll bars

        - Dialog boxes have:    Shadows
                                Automatic Centering

        - All controls have:    Titles with Accelerator Keys
                                A Dim Option
                                User-definable colors

        - Single line edits:    Horizontal scrolling
                                Select, Cut and Paste

        - Scrolling list boxes  "Hot" Keys
                                Scroll bars

        - Control Buttons       Cancel
                                Default

        - Radio Buttons

        - Check boxes

ͻ
 FREEWARE                                                                  
ͼ

Yes, this package is freeware. Please use it if you find it valuable, but
give me *some* credit. If you don't find it useful, let me know what can
be done to fix it for you.


ͻ
 QUICK OVERVIEW                                                            
ͼ

There are two parts to the toolkit: the dialogs, and the menus. Although
they share code, they are independant - you can choose to use only one of
them in your application.

Menus
 
    Using menus is fairly easy. Just call the run_menu() routine, passing it
    your menu and the last key pressed. The function handles the display,
    selection, and cleanup of the drop-down menu system.

    The value returned from the function is a single number indicating which 
    menu item was selected:

        1000 + ( 100 * menu bar ) + menu item.

    For example, "1205" would be the menu bar #2, item #5. If the user makes 
    no selection, a "0" is returned.

    Menus automatically display a "help text" on the bottom line of the 
    screen explaining what each menu item selection is.

Dialog Boxes
 
    Dialogs are implemented through a control array. Once you define
    the controls, you can run the dialog with a single call:
    
        run_dialog()

    It's easy to add your own functionality to the dialog, by evaluating the
    keys that the user presses and adding your own actions.

ͻ
 EXAMPLES                                                                  
ͼ
    I've include the following example files. The first three are variations
    on a theme, and covered in the tutorial of this text.

        EXAMPLE1.EX     - Simple 3 button dialog, using default key loop
        EXAMPLE2.EX     - Example 1, manual key loop
        EXAMPLE3.EX     - Example 2, with "Help" button and help dialog
        EXAMPLE4.EX     - Single line edit
        EXAMPLE5.EX     - List
        EXAMPLE6.EX     - Multi-line edit
        EXAMPLE7.EX     - Menu
        EXAMPLE8.EX     - Radio buttons
        EXAMPLE9.EX     - Check boxes


ͻ
 Using Graphic Mode Support                                                
ͼ
        
    The Graphics Mode allows you to use the GUI to generate programs with a
    look and feel similar to Windows or Mac programs. It is designed to be
    100% compatible with text mode. This means that if you design a screen
    in text mode, you will not have to make any changes to the screen to get
    it to display in graphics mode.

    There is only one bug that I know of remaining in Graphic mode: printing
    a character in the lower right hand corner caused the screen to scroll.
    I've got a patch to take care of it, but a side effect of the patch is
    that only the color, and not the text, will be printed in that one
    position.

    Selecting Graphics Mode
    

    To select graphic mode, change the constant RESOLUTION in SCREEN.E from:

        RESOLUTION = 0  -- text mode GUI

    to:

        RESOLUTION = 1  -- graphic mode 18 GUI


    Selecting a User Interface
    
    There are several files provided that will give you a different look and
    feel:

        WIN31.E         Windows 3.1
        WIN95.E         Windows 95
        BORLAND.E       Windows 95 with Borland's radio buttons & check boxes
        MAC.E           "Classic" monochrome Macintosh
        COPLAND.E       Macintosh Copland experience
        MOTIF.E         X-Windows, "Motif" look

    The file is loaded in the last line of GUI.E. Just comment out the
    old interface, and un-comment the one that you want.

    The UI files merely describe how to display the elements of the user
    interface:

            graphic_button()
            graphic_check()
            graphic_frame()
            graphic_menu()
            graphic_radio()
            graphic_scroll_bar()
            graphic_thumb()
            graphic_window()

ͻ
 THE MENU                                                                  
ͼ

    Displaying the Menu
     
    The menu makes the assumption that it has ownership of two pieces of
    the screen: the top and bottom line.

    The top line is where the menu bar is placed. You need make a call at
    the beginning of your program to draw_menu_bar() to initially draw the
    menu:
        
        draw_menu_bar( menu )

    After that point, you do not need to redraw the menu bar, unless you 
    write over the menu bar.

    The bottom line of the screen is used to display the long text of the
    menu bar function. This is optional. If you do not want a status line in
    your program, leave the help text on the menus blank.

    Building the Menu
     
    The easiest way to think about a menu is as a collection of drop-down
    menus placed into a menu bar. The data structure for a menu bar is:
        
        TITLE       Text displayed in menu bar
        HOT         Position of "hot" key in title
        COL         Position of text in menu bar
        ITEMS       Collection of dropdown items

    The data structure for a dropdown item looks like this:

        TITLE       Text displayed in the menu
        HOT         Position of "hot" key in title
        DIM         Flag indicating if menu item is dimmed
        HELP_TEXT   Help text to display in status bar

    The width of the text in TITLE should be identical for each item in 
    the dropdown. 

    Rather than struggle with the data structure, use these procedures:

        m_bar( index, title, column )
        m_item( menubar, item, text, help_text )

    They populate the global sequence MAIN_MENU.

    Here is a menu bar for an editor. Items must be declared in order:
     
        

        m_bar( 1, "&File",     4  )
        m_bar( 2, "&Edit",     10 )
        m_bar( 3, "&Search",   16 )
        m_bar( 4, "&Options",  24 )
        m_bar( 5, "&Help",     33 )


    Here is the first drop-down menu in the prior menu bar. Note that all
    the menu items are the same width. Like the menu bar, items must be
    declared in order. Also note that the help text can be left blank:
    
       
        m_item( 1, 1, "&New            ", "Creates a new file" )
        m_item( 1, 2, "&Open           ", "Loads an existing file from disk" ) )
        m_item( 1, 3, "&Save           ", "Saves current file" )
        m_item( 1, 4, "Save &As...     ", "Saves current file with new name" )
        m_item( 1, 5, "&Close          ", "Closes current file"  )
        m_item( 1, 6, "-", "" )
        m_item( 1, 7, "&Print...       ", "Prints currently loaded file to printer" )
        m_item( 1, 8, "-", "" )
        m_item( 1, 9, "E&xit           ", "Exits the editor" )


    Calling the Menu
     
    It is up to you to pass events to the menu. This is done by calling the
    run_menu() function with the value of the last key pressed:

        menu_picked = run_menu( MAIN_MENU, key_pressed )

    If the menu becomes activated, it will run until the user chooses an
    option, or cancels. The function either returns a zero (no action, or
    the user cancelled), or a number indicating which menu was selected,
    based on the formula:

        1000 + ( 100 * menu bar ) + menu item

    The menu takes no action; it is up to you to decide what to do about a
    menu item being selected.


    Dimming the Menu
     
    Before passing a key to the menu, you may want to alter the settings
    of the menu (dim items, etc.) You can do this by altering their
    attributes:

        -- dim Paste if clipboard is empty
        if length( CLIPBOARD ) = 0 then
            MAIN_MENU[2][3][DIM] = 1        -- dim Edit | Paste
        else
            MAIN_MENU[2][3][DIM] = 0        -- un-dim Edit | Paste
        end if

    However, it is expensive to make these sorts of tests on each keystroke.
    There are only two events that will activate the menu:

        - Pressing the Alt key
        - Clicking the mouse on the top line

    You can write your code to take advantage of this:

        -- was menu activated?
        if ( MOUSE_CLICK and MOUSE_ROW = 1 )    -- click on menu bar
        or ( keyPress = ALT_PRESSED ) then      -- or Alt key pressed

            -- dim/activate menu
            <CODE GOES HERE>

            -- pass event to menu
            menu_picked = run_menu( MAIN_MENU, key_pressed )

            if menu_picked != 0 then

                -- handle menu selection
                <CODE GOES HERE>

            end if

        end if

ͻ
 THE DIALOG                                                                
ͼ

    Building The Dialog
    

    The easiest way to set up the dialog is through the new_dialog()
    function:

        new_dialog( title, row, column, wide, deep, layout )

    Not all these values are required; in fact, some are mutually exclusive.
    If you do not specify the row or column, it is calculated for you. You
    must supply either wide and deep, or the layout.

    Here is an example of a dialog using wide and deep:

        new_dialog( "Print", 0, 0, 30, 12, {} )

    Here is an example of a dialog using layout (the extra space at the
    bottom is for the "OK" button). It is most useful for putting out lots of
    text without having to declare labels:

        new_dialog( "About", 0, 0, 0, 0, {
                "ͻ"
                " CD Organizer v2.3             "
                " (c) 1997 Fred Cheezebits      "
                "                               "
                "                               "
                "                               "
                "                               "
                "ͼ"} )


    Creating Controls
     

    Once you have created the dialog, you have to populate it with controls.
    The easiest way to do this is with the add_control() function:

        add_control( index, type, title, row, col, wide, deep, flags )

    Values that are not used for a particular control (for example, an SLE
    does not use DEEP) are passed a zero.

    The flags argument is a sequence of attributes to set to TRUE.

    For example:

        add_control( 1,             -- first control on dialog
                 BUTTON,            -- command button
                 "&OK",             -- Title is "OK", with "O" as accelerator key
                 4,                 -- place in row 4 of the dialog
                 6,                 -- place in column 4 of the dialog
                 8,                 -- 8 bytes wide
                 0,                 -- deep is not used
                 {FOCUS,            -- control button with intial focus
                  DEFAULT_BUTTON} ) -- DEFAULT_BUTTON is true

    Running the Dialog
     
    If there is no special action that needs to be added to the dialog, you
    can run it with the procedure:
    
        run_dialog()

ͻ
 CONTROL ATTRIBUTES                                                        
ͼ

There are a *lot* of attributes for the controls. However, not all controls 
share the same set of attributes, and most have a very small number of
attributes that are actually required.

Here is the list of controls supported by the toolkit:

    CONTROL         EXPLANATION
             
    MLE             Multiple line edit
    SLE             Single line edit
    LIST            Scrolling list
    BUTTON          Push button
    CHECK           Check box
    RADIO           Radio button
    LABEL           Text label
    MENU            Menu bar
    DROPDOWN        Menu dropdown
    DIALOG          Dialog

Here is the a list showing the minimum setup for any control:

    CONTROL     REQUIRED ELEMENTS
         
    SLE:        TYPE, ROW, COL, WIDE
    LIST:       TYPE, ROW, COL, ITEMS, WIDE, DEEP
    BUTTON:     TYPE, TITLE, ROW, COL, WIDE
    CHECK:      TYPE, TITLE, ROW, COL, WIDE
    RADIO:      TYPE, TITLE, ROW, COL, WIDE
    LABEL:      TYPE, TITLE, ROW, COL, WIDE
    MENU:       TYPE, TITLE, COL
    DROPDOWN:   TYPE, TITLE
    DIALOG:     TYPE, TITLE, ITEMS, WIDE, DEEP (see note 1)

Here is the complete list of attributes, with a brief explanation of their
purpose. Attributes preceeded by an asterisk are maintained by the program,
and usually do not have to be set by you:

    ATTRIBUTE       EXPLANATION
             
    TYPE            The type of control. The options are:

    TITLE           Title that is displayed with the control
  * HOT             Which letter in the title may be activated with Alt- key.
    ROW             Control's row, relative to the dialog.
    COL             Control's column, relative to the dialog.
    DIM             If set, the control is displayed as dimmed.
    DATA            Dialog box background for DIALOGs; Text for SLEs
    ITEMS           List items in a LIST; Dropdown items in a MENU
    HELP_TEXT       Help text in a DROPDOWN.
    WIDE            Width of SLE, LIST, BUTTON, DROPDOWN or DIALOG
    FOCUS           Indicates if a BUTTON has current focus
    CHECKED         Indicates if a RADIO, CHECK or DROPDOWN is checked
  * FIRST_CHAR      The first byte of MLE or SLE text displayed
  * ITEM            The selected item on a LIST
  * CURSOR          The relative cursor position in an MLE or SLE
    DEFAULT_BUTTON  Indicates BUTTON is the default
  * ANCHOR_LINE     Marks line where text selection begins in an MLE or SLE
    ANCHOR_COL      Marks where text selection begins in an MLE or SLE
    CANCEL_BUTTON   Indicated a BUTTON is the cancel button
    DEEP            Depth (lines deep) of LIST or DIALOG
  * REDRAW          Indicates control and it's title need to be redrawn
    PERSIST         Indicates highlight on a LIST remains after focus leaves
  * EXIT_STATE      Exit state flag on a DIALOG
  * TOP_LINE        First line displayed in a LIST or MLE
  * ELEVATOR        Tracks position of scroll bar's "thumb" or MLE or LIST
  * KEY_PRESSED     Key processed by DIALOG.
  * CLEAN_SCREEN    Screen hidden behind DIALOG.
  * DIRTY           True if MLE text has been edited.
    READ_ONLY       If true, prevents XLE text from being edited.
  * CURSOR_POS      Position cursor was before DIALOG was displayed.
    COLOR_SYNTAX    True if MLE text uses sytax coloring.


ͻ
 SETTING UP A DIALOG: A SIMPLE EXAMPLE                                     
ͼ

To run a dialog, you do the following:

    1. Define a dialog.
    2. Define the controls that will go on the dialog.
    3. Run the dialog.
    4. Analyze the results.

As an example, we will set up a dialog that displays a message to the user,
and allows them to press one of three buttons: Yes, No or Cancel. Here's a
layout of the dialog:

    Yes or No?Ŀ
                                      
     Do you like pizza?               
                                      
     < Yes >   <  No  >   < Cancel >  
                                      
    


Here is the basic information about the dialog:

    Object          Attribute       Value
        
    Dialog Box      Title:          "Yes or No?"
                                    Wide:           34
                                    Deep:           6 (includes title)
                                    Controls:       4

    Control #1:     Type:           Label
                                    Text:           "Do you like pizza?"
                                    Row:            2
                                    Col:            2

    Control #2      Type:           Button
                                    Text:           "Yes"
                                    Wide:           7
                                    Row:            4
                                    Col:            2

    Control #3      Type:           Button
                                    Text:           "No"
                                    Wide:           8
                                    Row:            4
                                    Col:            12
                                            
    Control #4      Type:           Button
                                    Text:           "Cancel"
                                    Wide:           10
                                    Row:            4
                                    Col:            23
                                    Cancel:         Yes

The first thing to do is define a dialog:

    -- create the dialog
    new_dialog( "Yes or No?", 0, 0, 34, 6, {} )
    
This creates a new dialog. If there was a prior dialog running, it is placed
onto a stack. 

Next, define each control in the dialog:

    add_control( 1, LABEL,  "Do you like pizza?", 2, 2, 0, 0, {} )
    add_control( 2, BUTTON, "&Yes", 4, 2, 7, 0, {}  )
    add_control( 3, BUTTON, "&No", 4, 12, 8, 0, {}  )
    add_control( 4, BUTTON, "&Cancel", 4, 24, 10, 0, {CANCEL_BUTTON} )

Now, we can run the dialog:

    run_dialog()      -- set up and display the dialog

After the dialog has been run, you need to check the EXIT_STATE to see
how the dialog was exited. The user can exit a dialog by selecting:

    1. The Escape key.
    2. The Enter key.
    3. A control button.

You can look at the EXIT_STATE attribute of the dialog to determine if the
Dialog was cancelled. If it wasn't, check which control has the last focus.

The function get_dialog() returns attributes from the MAIN_DIALOG:

    if get_dialog( EXIT_STATE ) = CANCELLED then
        result = -1     -- Escape key or Cancel key
    elsif get_dialog( FOCUS ) = 2 then
        result = 1      -- Yes
    elsif get_dialog( FOCUS ) = 3 then
        result = 0      -- No
    end if

Notice that we don't have to check if the Cancel button was pressed, since
pressing the Cancel buttons sets the EXIT_STATE to CANCELLED.

Also note that we can't just return a value at this point, because the 
dialog has tob removed. And we can't remove the dialog until we get the
exit attribute.

Now that we have the values, we need to remove the dialog. If there was a 
prior dialog running, it is popped off the stack and made current.

    hide_dialog()

    Ŀ
    PLEASE NOTE: The hide_dialog() function not only hides the dialog, it 
                 also removes it from the stack. If you try to access any 
                 of the dialog attributes after a hide_dialog(), you will 
                 get the attributes of the dialog that was next under the 
                 stack, or an error if the stack is empty!                
                                                                          
                 Just make sure that this is the last function called     
                 prior to the return or exit.                             
    


Here is the complete code (see EXAMPLE1.EX):

    -- Example #1: Simple Dialog
    -- Ask the user if they like pizza
    
    include dialog.e
    
    function ask_pizza_1()
    
        integer result
        
        -- create the dialog
        new_dialog("Yes or No?", 0, 0, 36, 6, {} )
        
        -- define controls    
        add_control( 1, LABEL,  "Do you like pizza?", 2, 2, 0, 0, {} )
        add_control( 2, BUTTON, "&Yes", 4, 2, 7, 0, {} )
        add_control( 3, BUTTON, "&No", 4, 12, 8, 0, {} )
        add_control( 4, BUTTON, "&Cancel", 4, 23, 10, 0, {CANCEL_BUTTON} )
                
        -- initialize and run the dialog
        run_dialog()
    
        -- determine the exit state
        if get_dialog( EXIT_STATE ) = CANCELLED then
            result = -1     -- Escape key or Cancel key
        elsif get_dialog( FOCUS ) = 2 then
            result = 1      -- Yes
        elsif get_dialog( FOCUS ) = 3 then
            result = 0      -- No
        end if
                    
        -- remove the dialog
        hide_dialog()
    
        -- return result
        return result
    
    end function
                                                               
                                                               
ͻ
 SETTING UP A DIALOG: A MORE COMPLEX EXAMPLE                               
ͼ

If we need to augment the dialog, we will need to get inside of the key
processing loop in run_dialog. Rather than jump into a more complex example,
here is the prior example coded without the run_dialog() function.

Instead, we can use the procedure show_dialog() to display the dialog, and 
set up a key loop of our own. The procedure edit_dialog() waits for a single
key/mouse event, and processes it. 

The loop waits for the dialog flag EXIT_STATE to move from MORE to something
else (either CANCELLED or OKAYED):

    show_dialog()      -- set up and display the dialog    

    -- loop until exit state doesn't wait for keys
    while get_dialog( EXIT_STATE ) = MORE do    -- until the user exits
        edit_dialog()                      -- process keys
    end while

Here is the complete code (see EXAMPLE2.EX):

    -- Example #2: Simple Dialog
    -- Ask the user if they like pizza
    -- Uses loop test instead of run_dialog()
    
    include dialog.e    -- dialog tools
    
    function ask_pizza_2()
    
        integer result
        
        -- create the dialog
        new_dialog("Yes or No?", 0, 0, 36, 6, {} )
        
        -- define controls    
        add_control( 1, LABEL,  "Do you like pizza?", 2, 2, 0, 0, {} )
        add_control( 2, BUTTON, "&Yes", 4, 2, 7, 0, {} )
        add_control( 3, BUTTON, "&No", 4, 12, 8, 0, {} )
        add_control( 4, BUTTON, "&Cancel", 4, 23, 10, 0, {CANCEL_BUTTON} )
                
        show_dialog()      -- set up and display the dialog    
    
        -- loop until exit state changes
        while get_dialog( EXIT_STATE ) = MORE do    -- until the user exits
            edit_dialog()                           -- process keys
        end while
                
        -- determine result    
        if get_dialog( EXIT_STATE ) = CANCELLED then
            result = -1     -- pressed Esc or Cancel
        elsif get_dialog( FOCUS ) = 2 then
            result = 1      -- Yes
        else
            result = 0      -- No
        end if             
    
        -- remove dialog
        hide_dialog()
        
        -- return result
        return result
                    
    end function
        

ͻ
 EXTENDING THE EXAMPLE                                                     
ͼ


    Augmenting the Dialog
             
    In many cases you will need to augment the basic dialog functions, so we
    will explore the adding to the "bare bones" dialog.
    
    Let's add one complication: a Help button. The dialog is now:

        Yes or No?Ŀ
                                                    
         Do you like pizza?                         
                                                    
         < Yes >   <  No  >   < Cancel >   < Help > 
                                                    
        

    The logic here is a little bit different. Now, we may not want to exit the
    dialog when the EXIT_STATE is no longer MORE, because we may just want to
    show the help dialog. The following test is added into the edit loop:

    -- loop until exit state changes
    while get_dialog( EXIT_STATE ) = MORE do    -- until the user exits
        edit_dialog( dialog )                   -- process keys
                                        
        if  get_dialog( EXIT_STATE ) = OKAYED   -- if exited dialog
        and get_dialog( FOCUS ) = 5 then        -- by pressing help button
            show_help()                         -- then show help
            set_dialog( EXIT_STATE, MORE )      -- and reset flag
        end if
                                    
    end while

Here, if we are about to exit because the Help button (#5) was pressed, we
instead show the help message, and reset the EXIT_STATE flag, preventing
the loop from exiting. The complete code is (see EXAMPLE3.EX):
                                                              
    -- Example #3: Simple Dialog
    -- Ask the user if they like pizza
    -- Uses loop test instead of run_dialog()
    -- Includes "help"
    
    
    include dialog.e    -- dialog tools
    include d_msgbox.e  -- message box
    
    procedure show_help()
            
            -- help for the ask_pizza2() dialog
                    
            sequence helpText
                    
            helpText = {"Select 'Yes' if you like pizza.",
                        "Select 'No' is you don't like pizza.",
                        "Select 'Cancel' to exit." }
                                    
            message_box( "Help", helpText )
            
    end procedure
    
    function ask_pizza_3()
    
        integer result
        
        -- create the dialog
        new_dialog( "Yes or No?", 0, 0, 50, 6, {} )
    
        -- define controls
        add_control( 1, LABEL,  "Do you like pizza?", 2, 2, 0, 0, {} )
        add_control( 2, BUTTON, "&Yes", 4, 2, 8, 0, {} )
        add_control( 3, BUTTON, "&No", 4, 13, 8, 0, {} )
        add_control( 4, BUTTON, "&Cancel", 4, 24, 10, 0, {CANCEL_BUTTON} )
        add_control( 5, BUTTON, "&Help", 4, 37, 10, 0, {} )
                    
        -- initialize dialog    
        show_dialog()      -- set up and display the dialog
                    
        -- loop until exit state changes
        while get_dialog( EXIT_STATE ) = MORE do    -- until the user exits
            edit_dialog()                           -- process keys
                                            
            if  get_dialog( EXIT_STATE ) = OKAYED   -- if exited dialog
            and get_dialog( FOCUS ) = 5 then        -- by pressing help button
                show_help()                         -- then show help
                set_dialog( EXIT_STATE, MORE )      -- and reset flag
            end if
                                        
        end while
    
        -- determine result    
        if get_dialog( EXIT_STATE ) = CANCELLED then
            result = -1     -- pressed Esc or Cancel
        elsif get_dialog( FOCUS ) = 2 then
            result = 1      -- Yes
        else
            result = 0      -- No
        end if             
                            
        -- remove dialog
        hide_dialog()
        
        return result
    
    end function
                                                                                                                            

ͻ
 THE EDIT LOOP                                                             
ͼ

Calling the function edit_dialog() causes the dialog to wait for a key from
the user, and then processes the key. The key is then returned to the user
for further processing, if required. The control array is processed through 
the following routines:

    edit_dialog() --> give_dialog_key() --> edit_xxx()

    PROCESS             WHAT IT DOES
        
    edit_dialog()       1. Get a key from the user.
                        2. Pass it on to give_dialog_key() for processing.
                        3. Return the key pressed.

    give_dialog_key()   1. Pass the key to the control with focus for
                            processing by calling edit_xxx(), where
                            'xxx' is the type of control:

                                - edit_sle()
                                - edit_list()
                                - edit_button()
                                - edit_check()
                                - edit_radio()
                                - edit_label()

                        2. Process the key to navigate within the
                           dialog.

                        3. Set an internal return code to indicate if the
                           dialog can be closed.

    edit_xxx()          1. Process a key for the control appropriate control
                            type. Returns the updated version of the control.

The process of navigating from one dialog control is a bit convoluted, but
is fortunately hidden from sight. The following states are passed through:

    1. Move Left        Any of these three will activate the navigation 
       Move Right       process for the dialog. The program calculates
       Hot Key          the next control to become active, skipping any
                        dimmed controls or labels.

    2. Lose Focus       Next, the currently active control is given a chance
                        to "clean up" (remove highlight, etc.).

    3. Get Focus        Focus is then placed on the next control to be
                        activated.

    4. Done             This is the standard cleanup routine.


ͻ
 CONTROL FUNCTIONS                                                         
ͼ

To give action to the controls, each can may have one or more of the following
routines coded. The simpler the control, the less routines it needs. For
example, the Label only has a draw_label() procedure:

    draw_xxx        draw the control
    edit_xxx        process keys sent to the controls
    focus_on_xxx    set focus on item
    focus_off_xxx   remove focus from item


ͻ
 CAVEATS                                                                   
ͼ
        
    1. LACK OF ERROR CHECKING
     
    I don't have many checks to ensure that your data is correct. If you feed
    a routine a bad data structure, the program will often just crash. I do
    some basic checks (control array exists; control has been initialized),
    but not a lot beyond that.

    Think of it as an incentive to have the Full version of Euphoria ;).


    2. NON-STANDARD EUPHORIA TOOLS
     
    There are two places that I've diverged from using the standard set of
    Euphoria tools: key handling, and screen writing.

        KEYS.E: Extended Key Handling
        
        Pressing the ^C key while Euphoria is waiting for a key has the 
        unfortunate side effect of halting the program. This was especially 
        undesirable because this key combination is used in most word 
        processors to "copy" text. 
                            
        Pressing the "Alt" key in Euphoria is not trapped, only combinations
        of the Alt- and some other key. This is needed to activate the menus.

        The Shift+Arrow keys are also not trapped by Euphoria, but are needed
        for selecting text in Single Line Edits.
                            
        I've had to write my own key handler (KEYS.E) around the standard 
        Euphoria key handler. It traps ^C, and watches the Alt and Shift keys.

        SCREEN.E: Colored Text Handling
        
        I haven't been able to figure out how to get more than one background
        color with text at a time with Euphoria. If you use bk_color() to
        change the background color of your text, it redefined color 0
        (black), which has a number of nasty side effects.

        As a result, I've written my own set of display tools. They reside in
        SCREEN.E

    3. PROCESSED CODE
     
    I've used my preprocessor, PP, in prototyping the toolkit. As a result,
    not all of the generated code may be as readable as it could be (although 
    the source is). Since I don't want to force people to have to use PP and I
    intend this code for general distribution, I'm going back and re-coding 
    the pieces to be as understandable as possible.

ͻ
 HISTORY                                                                   
ͼ

v06a        Added a "close" button to the dialogs, and the PLAIN.E UI.
            Spiffed up some of the other UI code.

v0.6        Graphical code is completed.

v0.53       Corrected the examples of code. Added 3 example files.

v0.5        This version. Sorry, but I haven't had time to get this list
02-24-97    up to date.

v0.3        Lots of corrections!                   
02-03-97    

v0.2        Robert Craig found an error in demo with "Save As" page up/down 
01-28-97    on file list. Sloppy code in demo.ex. Fixed.

            Error on "File Open" and "Save As" with page up/down not updating
            file name. Bug in demo.ex. Fixed.

            Error when page down on any list smaller than length. TOP in list.ee
            was not being set to 1. Fixed.

v0.1        First "early alpha" release
01-27-96



