

                             CDD 1.03 TUTORIAL

                     Copyright 1993 Phoenix Systems, Inc.


     (This document does not contain imbedded form feeds.  You may wish
      to print this file using your text editor or a print utility.)

     This tutorial will take you step-by-step through the process of
     building your first CDD application.  The application that you will
     construct is a very simple phone book / call tracking program
     consisting of four data files, menus, browse screens, edit screens,
     a lookup, a memo edit, and file maintenance utilities.  This
     tutorial is intended to illustrate the basic features of CDD and
     will require from four to eight hours to complete.

     At the end of this tutorial there is a discussion about a few
     advanced features of CDD.EXE and various programming shortcuts.

     The data dictionary maintenance program, CDD.EXE, is the main
     program that you will be using throughout this tutorial.  CDD.EXE
     is first used to create an empty set of data dictionary files, and
     then used to create and modify application data files, indexes,
     menus, browses, screens, etc.


     1.0 CREATING THE APPLICATION AND DATA DICTIONARY
     ------------------------------------------------

        1.1   Install CDD.EXE by copying it to your \CLIPPER\BIN
              directory or to another directory on your path.

        1.2   Install CDDLIB.LIB by copying it to your \CLIPPER\LIB
              directory or to your library directory.

        1.3   Create the directory \CDDTUTOR to hold the tutorial
              program and files.  Go to the \CDDTUTOR directory.

        1.4   Create the tutorial program PRG file, TUTOR.PRG, in the
              \CDDTUTOR directory:

                 *************************************

                 // TUTOR.EXE main module
                 v_init("tutor")

                 // install alternate error handler
                 procedure errorsys
                    errorblock({|e| v_e_alt(e)} )
                 return

                 *************************************

        1.5   Compile TUTOR.PRG, by typing "CLIPPER TUTOR".

        1.6   Create the link file, named TUTOR.LNK:

                 *************************************

                 output tutor.exe

                 # main module
                 file tutor.obj

                 overlay code
                 begin
                    # your other program modules below

                    # overlayable libs
                    library extend
                 end
                 library clipper, cddlib

                 *************************************

        1.7   Link the tutorial by typing "RTLINK @TUTOR" or if you are
              using the Blinker linker type "BLINKER @TUTOR".  The
              executable file TUTOR.EXE should exist at this point.
              TUTOR.EXE is not ready to run because the data dictionary
              has not yet been created by CDD.EXE.

        1.8   While in the \CDDTUTOR directory, run CDD.EXE by typing
              "CDD" and pressing <Enter>.

        1.9   CDD will prompt you to enter the system name.  Type
              "TUTOR" and press <Enter>.  Since the TUTOR data
              dictionary files do not currently exist, you will be
              prompted to create them.  Select the "Create" option.  The
              CDD data dictionary files for the TUTOR application will
              now be created and indexed.

              NOTE: Later, you can start CDD with a system name
                    parameter.  E.g. Type "CDD TUTOR" to automatically
                    load the TUTOR data dictionary files.


     2.0 DATA DICTIONARY SETUP
     -------------------------

        2.1   At the CDD main menu, choose "7. Startup and
              Configuration".  The startup and configuration screen will
              now be displayed.

        2.2   Using the arrow keys, move the "floating" cursor arrow
              down to the "Backdrop line 1 title" field.  Press <Enter>
              to begin editing this field.  Input the string "CDD 1.03
              TUTORIAL" (no quotes) in this field.  This will be the
              title for your tutorial program.

                 Path to data files......:
                 Path to index files.....:
                 Start function ID.......:    MAINMENU
                 Start function type.....:    M
                 Show backdrop?..........:    Y
                 Backdrop line 1 title...:    CDD 1.03 TUTORIAL
                 Backdrop line 2 title...:
                 Backdrop fill char......:    
                 Browse box string.......:   *Ŀ
                 Browse column separator.:    
                 Browse header separator.:    
                 Menu box string.........:   *ͻȺ
                 Screen box string.......:   *ͻȺ
                 Key list box string.....:   *
                 Key list title..........:    ~ AVAILABLE COMMAND KEYS ~
                 Prompt for exit?........:    N
                 Lock record on edit?....:    Y
                 Color defaults..........:    [Screen]
                 Sound, other defaults...:    [Screen]

              Please note that a newly created CDD data dictionary
              already has fields filled in with system-wide default
              values.  In most cases, these values will remain as is.

              The fields "Start function ID" and "Start function type"
              designate the very first CDD definition (or function) to
              be called.  In this case, the startup call will be to a
              CDD menu named "MAINMENU".  In a later section, you will
              create the menu "MAINMENU".  CDD uses a unique ID's (up to
              ten characters) to identify each definition of the menus,
              browses, screens, etc.  You supply the ID for each
              definition.  For each type of definition, the ID must be
              unique.  I.e. No two browse definitions may be identically
              named, but a browse and a screen can have (and often do
              have) the same name ID.

        2.3   Press <Esc> to exit this screen.  At the accept prompt,
              choose "Accept" to save your changes.


     3.0 DEFINING A DATA FILE AND ITS INDEXES
     ----------------------------------------

        3.1   At the CDD main menu, choose "6. DBFs, NTXs, and Fields".
              Since no data files have previously been defined, the add
              screen for a data file will be automatically loaded.  Fill
              in the following data file information:

                 Alias................:    PHONE
                 Filename.............:    PHONE
                 Description..........:    Phone number file
                 Alternate Path.......:
                 Open at startup?.....:    Y
                 Show in V_REINDEX()?.:    Y

                 Fields...............:    [Browse]
                 Indexes..............:    [Browse]

                 Create DBF now?......:    Process
                 Index now?...........:    Process

        3.2   Once the data file information screen is completed, the
              data field add screen will automatically load.  Fill in
              the following information:

                 Pos.........:  10
                 Fieldname...: LASTNAME
                 Type........: C
                 Length......:    20
                 Decimals....:  0
                 Description.: last name

              After accepting (saving) this new record, the browse for
              the data fields will be displayed.

        3.3   Add another data field record by pressing the <Ins> key.
              Fill in the following information:

                 Pos.........:  20
                 Fieldname...: FIRSTNAME
                 Type........: C
                 Length......:    20
                 Decimals....:  0
                 Description.: first name

        3.4   Add another data field record with the following
              information:

                 Pos.........:  30
                 Fieldname...: PHONE_NO
                 Type........: C
                 Length......:    20
                 Decimals....:  0
                 Description.: phone

        3.5   Add another data field record with the following
              information:

                 Pos.........:  40
                 Fieldname...: FAX_NO
                 Type........: C
                 Length......:    20
                 Decimals....:  0
                 Description.: fax

        3.6   Add another data field record with the following
              information:

                 Pos.........:  50
                 Fieldname...: REC_TYPE
                 Type........: C
                 Length......:    1
                 Decimals....:  0
                 Description.: type of record

        3.7   Add another data field record with the following
              information:

                 Pos.........:  60
                 Fieldname...: CREATED
                 Type........: D
                 Length......:     8
                 Decimals....:  0
                 Description.: date record added

        3.8   Add another data field record with the following
              information:

                 Pos.........: 100
                 Fieldname...: MEMO
                 Type........: M
                 Length......:    10
                 Decimals....:  0
                 Description.: memo field

              NOTE: Please recheck the spelling of ALL fields!
                    Misspelling of the fieldnames has been a common
                    problem experienced by users of this tutorial.

        3.9   Once all of the fields have been entered, press <Esc> to
              exit the data field browse and then you will be
              automatically taken to an index definition add screen.
              Fill in the following information:

                 Index Alias....: PHONE1
                 Index Name.....: PHONE1
                 Key Expression.: upper(lastname)+upper(firstname)
                 Unique Index?..: N
                 Description....: by name
                 Alternate Path.:

        3.10  At the index file browse, add another index record by
              pressing the <Ins> key.  Fill in the following
              information:

                 Index Alias....: PHONE2
                 Index Name.....: PHONE2
                 Key Expression.: dtos(created)
                 Unique Index?..: N
                 Description....: by date
                 Alternate Path.:

        3.11  Press <Esc> to exit the index file browse.  You will be
              taken back to the browse of the data files.

        3.12  To create the actual data file and index it, press <Enter>
              on the PHONE record of the data file browse, and from the
              data file information screen choose the "Create DBF now?"
              and then the "Index Now?" processes.  A process is chosen
              by moving the floating arrow to the desired selection and
              pressing <Enter>.  Once the data file and indexes have
              been created, press <Esc> twice to return to the CDD main
              menu.


     4.0 DEFINING THE MAIN MENU
     --------------------------

        4.1   At the CDD main menu, choose "3. Menu Definitions". An
              empty browse list for the menus definitions will flash by
              and then the add screen for a new menu definition will be
              loaded.  In the next few steps, you will define the main
              menu for your program.

        4.2   Fill in the following menu definition fields:

                 Menu Function ID......:    MAINMENU
                 Title.................:    [ Main Menu ]
                 Coordinates (t,l).....:     5     5
                 Condition for access..:
                 Condition for exit....:
                 Post process..........:
                 Auto. execute on key?.:    Y
                 Save Scrn/Area/Ord/Rec:    Y    Y    N    N
                 Center menu prompts?..:    Y
                 Alt. menu colors......:
                 Alt. menu fade color..:
                 Alt. menu box chars...:   *

              At the accept prompt, choose "Accept" to save this record.

              NOTE 1: Since the contents of the "Title" menu field is
                      trimmed at run time, you can use the tilde "~"
                      character to preserve leading and trailing spaces
                      in your menu title.  E.g. ~My Title~ will cause a
                      space to display on either side of the title.

              NOTE 2: Like most Clipper edit screens, you can press
                      <PgDn> to terminate the edit without having to
                      pass through all of the remaining fields.

        4.3   Once the menu definition record is saved, you will be
              automatically taken to the menu item definition add
              screen.  Menu items provide the programmer with branch
              points to call other CDD definitions such as browses or
              screens, or to call external functions.  Fill in the
              following information:

                 Menu item position....:      10
                 Description...........:     1. Phone File

                 Call Function ID......:     PHONE
                  "       "    Type....:     B
                  "       "    Param...:
                  "       "    Extern..:

                 Cond. for item select.:
                 Condition for access..:
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade Menu?............:     Y

                 Line 23 message.......:     Maintain PHONE.DBF records
                 Line 24 message.......:

              Upon saving this menu item definition record, you will be
              returned to a browse list of all menu items for this menu.

        4.4   Add another menu item definition by pressing the <Ins>
              key.  Fill in the following information:

                 Menu item position....:      20
                 Description...........:     2. Reindex the Data Dictionary

                 Call Function ID......:
                  "       "    Type....:     U
                  "       "    Param...:
                  "       "    Extern..:     v_reindex("CDD")

                 Cond. for item select.:
                 Condition for access..:   v_alert("Reindex?",{"Yes","No"})==1
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade Menu?............:     Y

                 Line 23 message.......:     Reindex the data dictionary
                 Line 24 message.......:

              NOTE 1: Please observe that the "Call Function Type" for
                      this menu item is "U".  This is the method by
                      which an external function is called by a CDD menu
                      item, browse key, or screen key.  The call
                      function type is "U" and the function to call is
                      entered in the "Call function extern" field.

              NOTE 2: The CDDLIB.LIB function v_reindex() is a
                      reindexing utility for CDD data dictionary files
                      and applications data files.

        4.5   Add another menu item definition by pressing the <Ins>
              key.  Fill in the following information:

                 Menu item position....:      30
                 Description...........:     3. Reindex Data Files

                 Call Function ID......:
                  "       "    Type....:     U
                  "       "    Param...:
                  "       "    Extern..:     v_reindex()

                 Cond. for item select.:
                 Condition for access..:
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade Menu?............:     Y

                 Line 23 message.......:     Reindex Data Files
                 Line 24 message.......:

        4.6   To exit the menu item browse, press <Esc>.  You will be
              returned to the menu definition screen.  If you need to go
              back to the menu item browse for this menu, move the
              floating arrow to the "Menu Item Definitions  [Browse]"
              field, and press <Enter>.

        4.7   Press <Esc> until you are back at the CDD main menu.


     5.0 DEFINING A BROWSE
     ---------------------

        5.1   At the CDD main menu, choose "2. Browse Definitions".
              Since no browse definitions currently exist, the browse
              definition add screen will be displayed.  Fill in the
              following browse definition:

                 Browse Function ID...:    PHONE
                 Datafile Alias.......:   *PHONE
                 Init. Index Alias....:   *PHONE1  .......
                 Index Filter Expr....:
                 Title................:    Phone List
                 Coordinates (t,l,b,r):     5     4    21    75
                 Condition for access.:
                 Condition for exit...:
                 Post process.........:
                 Post keystroke proc..:
                 Frozen columns.......:     0
                 Save Scr/Area/Ord/Rec:    Y    Y    N    N
                 Initial GOTOP?.......:    Y
                 Use std. nav. keys?..:    Y

                 Browse Def. Pg. 2....:    [Screen]

                 Column Definitions...:    [Browse]
                 Key Definitions......:    [Browse]


              NOTE: Every CDD data dictionary field annotated with an
                    asterisk "*" has a lookup available -  press <Enter>
                    on an empty field to popup the lookup table.

              The second screen of the browse definition will be
              automatically loaded after the first screen is completed.

                 Line 23 message.........:     Press F10 for commands
                 Line 24 message.........:
                 Center status lines?....:     N
                 Full width hilite bar...:     Y
                 Alt. browse colors......:
                 Alt. browse fade color..:
                 Alt. browse box chars...:    *
                 Alt. browse column sep..:
                 Alt browse header sep...:
                 F-Key for keylist.......:     F10 (F2 - F10)
                 Alt. keylist colors.....:
                 Alt. keylist box chars..:    *
                 Alt. keylist title......:


                 Help Text...............:     Memo


        5.2   Once the browse definition is finished and saved, the add
              screen for the browse column definitions will be loaded.
              Fill in the following browse column definition:

                 Column position.......:      10
                 Field/Memvar/Expr.....:    *LASTNAME
                 Column header.........:     Last Name
                 Picture clause........:
                 Condition to show?....:
                 Alt. column separator.:
                 Alt header separator..:

        5.3   Use the <Ins> key to add the remaining browse columns:

                 Column position.......:      20
                 Field/Memvar/Expr.....:    *FIRSTNAME
                 Column header.........:     First Name


                 Column position.......:      30
                 Field/Memvar/Expr.....:    *PHONE_NO
                 Column header.........:     Phone


                 Column position.......:      40
                 Field/Memvar/Expr.....:    *FAX_NO
                 Column header.........:     Fax


                 Column position.......:      50
                 Field/Memvar/Expr.....:    *CREATED
                 Column header.........:     Created


                 Column position.......:      60
                 Field/Memvar/Expr.....:    *padr(memo,20)
                 Column header.........:     Memo

                 NOTE:  The last column (60) is a call to a function.  A
                        column expression can be ANY function or memvar
                        that returns a fixed length value.

        5.4   Once the browse columns are defined, press the <Esc> key
              to exit the browse column definitions.  Now the add screen
              for the browse key definitions will be loaded.  Browse
              keys are similar to menu items - they provide branches to
              other CDD definitions or to external functions.  Fill in
              the following browse key definitions:

                 Key list position.....:      10
                 Char. or "K"+Inkey....:     A
                 Description...........:     A - Add

                 Call Function ID......:     PHONE
                  "       "    Type....:     S
                  "       "    Param...:     A
                  "       "    Extern..:

                 Cond. for key select..:
                 Condition for access..:
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade browse?..........:     Y
                 RefreshAll after key?.:     Y
                 RefreshCurrent after?.:     N


                 Key list position.....:      20
                 Char. or "K"+Inkey....:     D
                 Description...........:     D - Delete

                 Call Function ID......:
                  "       "    Type....:     U
                  "       "    Param...:
                  "       "    Extern..:     v_delrec()

                 Cond. for key select..:     !phone->(eof())
                 Condition for access..:     v_is_delete()
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade browse?..........:     N
                 RefreshAll after key?.:     Y
                 RefreshCurrent after?.:     N


                 Key list position.....:      30
                 Char. or "K"+Inkey....:     E
                 Description...........:     E - Edit

                 Call Function ID......:     PHONE
                  "       "    Type....:     S
                  "       "    Param...:     E
                  "       "    Extern..:

                 Cond. for key select..:     !phone->(eof())
                 Condition for access..:
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade browse?..........:     Y
                 RefreshAll after key?.:     Y
                 RefreshCurrent after?.:     N


                 Key list position.....:      40
                 Char. or "K"+Inkey....:     F
                 Description...........:     F - Find

                 Call Function ID......:     PHONE
                  "       "    Type....:     F
                  "       "    Param...:
                  "       "    Extern..:

                 Cond. for key select..:     !phone->(eof())
                 Condition for access..:
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade browse?..........:     Y
                 RefreshAll after key?.:     Y
                 RefreshCurrent after?.:     N


                 Key list position.....:      50
                 Char. or "K"+Inkey....:     O
                 Description...........:     O - Order (Sort)

                 Call Function ID......:     O_PHONE
                  "       "    Type....:     M
                  "       "    Param...:
                  "       "    Extern..:

                 Cond. for key select..:     !phone->(eof())
                 Condition for access..:
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade browse?..........:     Y
                 RefreshAll after key?.:     Y
                 RefreshCurrent after?.:     N


                 Key list position.....:      60
                 Char. or "K"+Inkey....:     M
                 Description...........:     M - Memoedit

                 Call Function ID......:
                  "       "    Type....:     U
                  "       "    Param...:
                  "       "    Extern..:     v_memo_f("memo","[ MEMOEDIT ]")

                 Cond. for key select..:     !phone->(eof())
                 Condition for access..:
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade browse?..........:     Y
                 RefreshAll after key?.:     Y
                 RefreshCurrent after?.:     N


                 Key list position.....:      70
                 Char. or "K"+Inkey....:     K13
                 Description...........:     <Enter> - View Phone Record

                 Call Function ID......:     PHONE
                  "       "    Type....:     S
                  "       "    Param...:
                  "       "    Extern..:

                 Cond. for key select..:     !phone->(eof())
                 Condition for access..:
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade browse?..........:     Y
                 RefreshAll after key?.:     Y
                 RefreshCurrent after?.:     N


                 Key list position.....:      80
                 Char. or "K"+Inkey....:     K28
                 Description...........:     <F1> - Help

                 Call Function ID......:
                  "       "    Type....:     U
                  "       "    Param...:
                  "       "    Extern..:     v_help()

                 Cond. for key select..:
                 Condition for access..:
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade browse?..........:     N
                 RefreshAll after key?.:     N
                 RefreshCurrent after?.:     N


                 Key list position.....:     500
                 Char. or "K"+Inkey....:     K27
                 Description...........:     <Esc> - Exit to Main Menu

                 Call Function ID......:
                  "       "    Type....:     U
                  "       "    Param...:
                  "       "    Extern..:     v_exit()

                 Cond. for key select..:
                 Condition for access..:
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade browse?..........:     N
                 RefreshAll after key?.:     N
                 RefreshCurrent after?.:     N


                 NOTE 1: The call function parameter field is currently
                         only used for "S" type (screen) functions. The
                         call function parameter field is NOT used to
                         provide parameters to external function calls
                         ("U" type functions).

                 NOTE 2: This is a good time to point out the difference
                         between the "Condition for key select" and
                         "Condition for access" fields.  Each CDD
                         browse and screen has an F10 popup achoice()
                         menu that lists the defined command keys.  The
                         "Condition for key select" is evaluated for
                         each key to determine whether the key is
                         unavailable (grayed-out) when the F10 menu is
                         displayed.

                         The "Condition for access" determines whether
                         the specified branch or function will be
                         executed.  The "Condition for access" is also
                         commonly used to open and initialize secondary
                         or lookup datafiles.

                         In other words, the former means "Can I pick
                         it?" and the latter means "I picked it, am I
                         able to do it?".

                 NOTE 3: The CDDLIB.LIB function v_delrec() locks and
                         deletes the current record.  The function
                         v_is_delete() is a user prompt asking the user
                         to confirm the delete request.  The function
                         v_help() calls the CDD help screen.  The
                         function v_exit() sets a global flag that
                         forces the current menu, browse, or screen to
                         terminate.


        5.5   Press <Esc> until you return to the CDD main menu.


     6.0 DEFINING A SCREEN
     ---------------------

        6.1   At the CDD main menu, choose "1. Screen Definitions".
              Since no screen definitions currently exist, the screen
              definition add screen will be displayed.  Fill in the
              following screen definition:

                 Screen Function ID...:    PHONE
                 Datafile Alias.......:   *PHONE
                 Init. Index Alias....:   *
                 Index Filter Expr....:
                 Condition for access.:
                 Condition for exit...:
                 Post process.........:
                 Post keystroke proc..:
                 Save Scr/Area/Ord/Rec:    Y    Y    N    N
                 Initial GOTOP?.......:    N
                 Use std. nav. keys?..:    Y
                 Exit screen if eof?..:    Y

                 Screen def. page 2...:    [Screen]
                 Screen def. page 3...:    [Screen]

                 Field/Get definitions:    [Browse]
                 Key definitions......:    [Browse]
                 Screen designer......:    Process

                 *** Screen Def. Page 2 ***
                 Cond. for Add/Edit.........:
                 Cond. for Add/Edit Exit....:
                 Before Add/Edit Update proc:
                 After Add/Edit Update proc.:
                 Post Add/Edit proc.........:
                 Set CONFIRM ON?............:     N
                 Prompt for accept?.........:     Y
                 Accept Prompt if Esc?......:     Y

                 *** Screen Def. Page 3 ***
                 Line 23 message.........:     Press F10 for commands
                 Line 24 message.........:
                 Center status lines?....:     Y
                 Alt. screen colors......:
                 Alt. screen fade color..:
                 Alt screen box chars....:    *
                 F-Key for keylist.......:     F10 (F2 - F10)
                 Alt. keylist colors.....:
                 Alt. keylist box chars..:    *
                 Alt. keylist title......:

              NOTE: Although the "Datafile Alias" field is optional, it
                    is a good habit to always enter the appropriate
                    alias.  It may occur later that you will call a
                    screen directly, without going through a browse
                    first.  The "Init Index Alias" field is rarely
                    filled because most often a preceding browse has
                    already set the desired index order.

        6.2   Once the screen definition is finished and saved, the add
              screen for the screen field/get definitions will be
              loaded.  Fill in the following screen field/get
              definitions:

              Position (Get sequence):     10
              DBF alias->field.......:   *PHONE     ->   *LASTNAME
              Int. variable name.....:    mlastname
              Int. var. declaration..:    P
              Get prompt (line 23)...:    Enter last name
               "  type/length/dec....:    C       20     0
               "  PICTURE............:
               "  init. expression...:
               "  VALID (cond).......: v_getljust() .and. v_getempty("Last")
               "  WHEN (is editable?):

              Full screen valid cond.:    !empty(mlastname)
              Full screen valid msg..:    Last name cannot be blank

              Alt. colors (2 colors).:    W+/R,W+/R
              Alt. color operation...:    N


              Position (Get sequence):     20
              DBF alias->field.......:   *PHONE     ->   *FIRSTNAME
              Int. variable name.....:    mfirstname
              Int. var. declaration..:    P
              Get prompt (line 23)...:    Enter the first name
               "  type/length/dec....:    C       20     0
               "  PICTURE............:
               "  init. expression...:
               "  VALID (cond).......:    v_getljust()
               "  WHEN (is editable?):

              Full screen valid cond.:
              Full screen valid msg..:

              Alt. colors (2 colors).:
              Alt. color operation...:    N


              Position (Get sequence):     30
              DBF alias->field.......:   *PHONE     ->   *PHONE_NO
              Int. variable name.....:    mphone_no
              Int. var. declaration..:    P
              Get prompt (line 23)...:    Enter the phone number
               "  type/length/dec....:    C       20     0
               "  PICTURE............:    @!
               "  init. expression...:
               "  VALID (cond).......: v_getljust() .and. v_getempty("Phone")
               "  WHEN (is editable?):

              Full screen valid cond.:    !empty(mphone_no)
              Full screen valid msg..:    Phone cannot be blank

              Alt. colors (2 colors).:    W+/R, W+/R
              Alt. color operation...:    N


              Position (Get sequence):     40
              DBF alias->field.......:   *PHONE     ->   *FAX_NO
              Int. variable name.....:    mfax_no
              Int. var. declaration..:    P
              Get prompt (line 23)...:    Enter the fax number
               "  type/length/dec....:    C       20     0
               "  PICTURE............:    @!
               "  init. expression...:
               "  VALID (cond).......:    v_getljust()
               "  WHEN (is editable?):

              Full screen valid cond.:
              Full screen valid msg..:

              Alt. colors (2 colors).:
              Alt. color operation...:    N


              Position (Get sequence):     50
              DBF alias->field.......:   *PHONE     ->   *REC_TYPE
              Int. variable name.....:    mrec_type
              Int. var. declaration..:    P
              Get prompt (line 23)...:    Enter the record type
               "  type/length/dec....:    C        1     0
               "  PICTURE............:    @!
               "  init. expression...:
               "  VALID (cond).......:
               "  WHEN (is editable?):

              Full screen valid cond.:
              Full screen valid msg..:

              Alt. colors (2 colors).:
              Alt. color operation...:    N


              Position (Get sequence):     60
              DBF alias->field.......:   *PHONE     ->   *CREATED
              Int. variable name.....:    mcreated
              Int. var. declaration..:    P
              Get prompt (line 23)...:
               "  type/length/dec....:    D        8     0
               "  PICTURE............:
               "  init. expression...:    date()
               "  VALID (cond).......:
               "  WHEN (is editable?):    .f.

              Full screen valid cond.:
              Full screen valid msg..:

              Alt. colors (2 colors).:
              Alt. color operation...:    N

              NOTE 1: The WHEN clause for mcreated is .f. so that no
                      editing of this field will be allowed.

              NOTE 2: The CDDLIB.LIB function v_getljust() left
                      justifies the current screen get memvar.  The
                      function v_getempty() checks that the current
                      screen get memvar is not empty and displays a
                      error message if needed.

              NOTE 3: The value of the "Position (Get sequence)" field
                      determine the order by which the screen gets are
                      activated.

              NOTE 4: CDD does not edit the database fields directly -
                      the screen memvars are edited, then saved to the
                      record.  If a screen memvar does not have both a
                      DBF alias and DBF field associated with it, then
                      it is treated as just another memvar - editable,
                      but not saved to a record.  Memvar-only fields
                      should have an initialization expression.

        6.3   Once the screen fields are defined, press the <Esc> key to
              exit the screen field definitions browse.  Now the add
              screen for the screen key definitions will be loaded.
              Screen keys are similar to browse keys - they provide
              branches to other CDD definitions or to external
              functions.  Fill in the following screen key definitions:

                 Key list position.....:      10
                 Char. or "K"+Inkey....:     A
                 Description...........:     A - Add

                 Call Function ID......:
                  "       "    Type....:     U
                  "       "    Param...:
                  "       "    Extern..:     s_add()

                 Cond. for key select..:
                 Condition for access..:
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade screen?..........:     N
                 Reload after key?.....:     N
                 Redisplay after key?..:     N


                 Key list position.....:      20
                 Char. or "K"+Inkey....:     D
                 Description...........:     D - Delete

                 Call Function ID......:
                  "       "    Type....:     U
                  "       "    Param...:
                  "       "    Extern..:     v_delrec()

                 Cond. for key select..:     
                 Condition for access..:     v_is_delete()
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade screen?..........:     N
                 Reload after key?.....:     Y
                 Redisplay after key?..:     Y


                 Key list position.....:      30
                 Char. or "K"+Inkey....:     E
                 Description...........:     E - Edit

                 Call Function ID......:
                  "       "    Type....:     U
                  "       "    Param...:
                  "       "    Extern..:     s_edit()

                 Cond. for key select..:
                 Condition for access..:
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade screen?..........:     N
                 Reload after key?.....:     N
                 Redisplay after key?..:     N


                 Key list position.....:      40
                 Char. or "K"+Inkey....:     F
                 Description...........:     F - Find

                 Call Function ID......:     PHONE
                  "       "    Type....:     F
                  "       "    Param...:
                  "       "    Extern..:

                 Cond. for key select..:
                 Condition for access..:
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade screen?..........:     Y
                 Reload after key?.....:     Y
                 Redisplay after key?..:     Y


                 Key list position.....:      50
                 Char. or "K"+Inkey....:     O
                 Description...........:     O - Order (Sort)

                 Call Function ID......:     O_PHONE
                  "       "    Type....:     M
                  "       "    Param...:
                  "       "    Extern..:

                 Cond. for key select..:
                 Condition for access..:
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade screen?..........:     Y
                 Reload after key?.....:     Y
                 Redisplay after key?..:     Y


                 Key list position.....:      60
                 Char. or "K"+Inkey....:     M
                 Description...........:     M - Memoedit

                 Call Function ID......:
                  "       "    Type....:     U
                  "       "    Param...:
                  "       "    Extern..:     v_memo_f("memo","[ MEMOEDIT ]")

                 Cond. for key select..:
                 Condition for access..:
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade screen?..........:     Y
                 Reload after key?.....:     N
                 Redisplay after key?..:     N


                 Key list position.....:      80
                 Char. or "K"+Inkey....:     K28
                 Description...........:     <F1> - Help

                 Call Function ID......:
                  "       "    Type....:     U
                  "       "    Param...:
                  "       "    Extern..:     v_help()

                 Cond. for key select..:
                 Condition for access..:
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade screen?..........:     N
                 Reload after key?.....:     N
                 Redisplay after key?..:     N


                 Key list position.....:     500
                 Char. or "K"+Inkey....:     K27
                 Description...........:     <Esc> - Exit to browse

                 Call Function ID......:
                  "       "    Type....:     U
                  "       "    Param...:
                  "       "    Extern..:     v_exit()

                 Cond. for key select..:
                 Condition for access..:
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade screen?..........:     N
                 Reload after key?.....:     N
                 Redisplay after key?..:     N

        6.4   Once the screen keys are defined, you will need to return
              to the screen definition for PHONE.  Move the floating arrow
              to the "Screen designer" process and press <Enter>.

              The screen designer allows you to move and size the screen
              window, and add text, lines, fields, etc. to the screen.

              <F1> provides help for all of the key commands within the
              screen designer.  Before you begin to design your screen,
              please quickly familiarize yourself with all of the
              submenu items.

              Resize the window (using the F10 key) and add the
              following text:

                 ͻ
                              Phone Record              
                 ĺ
                                                        
                   Last Name...:                        
                   First Name..:                        
                   Phone.......:                        
                   Fax.........:                        
                   Record type.: *                      
                                                        
                   Created.....:                        
                                                        
                 ͼ

              NOTE: The asterisk beside the "Record Type" text is often
                    used as a visual indicator for a field with a lookup
                    table associated.  The lookup table will be added
                    later in this tutorial.

        6.5   Once the screen is laid out, add the screen fields to the
              screen via the F4 key.  To add a field:

                 1. Pre-position the cursor where you want the field to
                    be dropped.

                 2. Press F4, then "A" to popup the screen memvars pick
                    list.

                 3. Select the desired field from the list by pressing
                    <Enter>.  The field is now dropped at the previous
                    cursor position.  Please insure that the right side
                    of the window box does not truncate the right end of
                    a screen field.

                 ͻ
                              Phone Record              
                 ĺ
                                                        
                   Last Name...: MLASTNAME              
                   First Name..: MFIRSTNAME             
                   Phone.......: MPHONE_NO              
                   Fax.........: MFAX_NO                
                   Record type.: M                      
                                                        
                   Created.....: MCREATED               
                                                        
                 ͼ


        6.6   When you are finished designing your screen, press <Esc> to
              exit.  If the screen has been altered (it has now), you
              will be prompted to save or to discard your changes -
              choose the "Save and Exit" selection.

        6.7   STOP HERE.  Press <Esc> until you are back at DOS.
              Although not all of the browse and screen keys have been
              defined, this is a good place to stop and examine your
              work.  The tutorial program now has a working menu,
              browse, edit screen, and some utilities.  You can now
              view, add, edit, and delete PHONE.DBF records.  To run the
              tutorial program, type "TUTOR" at the DOS prompt.

              Remember, when running the TUTOR program, press F10 to
              view a list of the available key commands when you are in
              the browse or screen.

        NOTE: If you get a DOS Error = 4  (Insufficient file handles)
              when running TUTOR, you must increase the number of files
              that your computer and the program are allowed to open.

              Since a CDD application is mostly data-driven, the data
              dictionary is open at all times during operation.  As a
              result, the number of file handles in your CONFIG.SYS and
              network config file (SHELL.CFG for Novell) should be set
              to 65 or higher.  Reboot your computer for changes to
              CONFIG.SYS to take effect.  The actual CDD data dictionary
              requires 36 file handles at run time, 21 dbf/dbts and 15
              indexes.

              Also remember to either SET CLIPPER=F65 or burn in the max
              file handles setting into your EXE file via the linker.

     ************************************************************************


     7.0 DEFINING THE "O" - ORDER MENU
     ---------------------------------

        7.1   Restart CDD.EXE by typing "CDD TUTOR".

        7.2   At the CDD main menu, choose "3. Menu Definitions". The
              browse list for the existing menus definitions will be
              displayed.  Press <Ins> to add a new menu definition:

                 Menu Function ID......:    O_PHONE
                 Title.................:    [ Select Viewing Order ]
                 Coordinates (t,l).....:    14    40
                 Condition for access..:
                 Condition for exit....:
                 Post process..........:
                 Auto. execute on key?.:    Y
                 Save Scrn/Area/Ord/Rec:    Y    Y    N    N
                 Center menu prompts?..:    Y
                 Alt. menu colors......:
                 Alt. menu fade color..:
                 Alt. menu box chars...:   *


        7.3   Add the following menu items:

                 Menu item position....:      10
                 Description...........:     1. Last Name

                 Call Function ID......:
                  "       "    Type....:     U
                  "       "    Param...:
                  "       "    Extern..:     v_vieword("phone",phone1)

                 Cond. for item select.:
                 Condition for access..:
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade Menu?............:     N


                 Menu item position....:      20
                 Description...........:     2. Create Date

                 Call Function ID......:
                  "       "    Type....:     U
                  "       "    Param...:
                  "       "    Extern..:     v_vieword("phone",phone2)

                 Cond. for item select.:
                 Condition for access..:
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade Menu?............:     N

              NOTE: The CDDLIB.LIB function v_vieword() is specifically
                    designed to be called as a menu item.  V_vieword()
                    changes the index order and then forces the menu to
                    terminate.  If you need to change index orders from
                    within your own code, use the v_order() function
                    which can accept an index alias variable as its
                    parameter.


     8.0 DEFINING THE "F" - FIND
     ---------------------------

        8.1   At the CDD main menu, choose "4. Find Definitions".  Since
              no finds have previously been defined, the add screen for
              the find will be loaded automatically.  Fill in the
              following find information:

                 Find function ID.......:    PHONE
                 Data alias.............:   *PHONE

        8.2   When the find definition is completed, the add screen for
              the find items will be loaded.  Fill in the following find
              items:

                 DBF alias..............:   *PHONE
                 Index alias............:   *PHONE1  upper(lastname)+...
                 Get title..............:    Last Name
                  "  type/length/dec....:    C       20     0
                  "  picture............:    @!
                  "  init. expression...:
                  "  cond. for valid....:
                  "  cleanup expression.:    alltrim(v_findget)
                  Append expression.....:
                  Set confirm ON?.......:    N
                  Softseek ON?..........:    N


                  DBF alias..............:   *PHONE
                  Index alias............:   *PHONE2  dtos(created)
                  Get title..............:    Create Date
                   "  type/length/dec....:    D        8     0
                   "  picture............:
                   "  init. expression...:
                   "  cond. for valid....:
                   "  cleanup expression.:    dtos(v_findget)
                   Append expression.....:
                   Set confirm ON?.......:    N
                   Softseek ON?..........:    N

        8.3   STOP HERE.  Run the tutorial and test the find and order
              keys in the browse and screen.  Note that for each
              available index order, there is a corresponding find.

     ************************************************************************


     9.0 ADDING A LINK FIELD FOR A CALLS (CHILD) DATABASE
     ----------------------------------------------------

        9.1  During the next few steps you will be adding another field
             to PHONE.DBF.  This new field will be used as a link field
             to a child database.  The contents of the link field will
             be system generated by incrementing a counter field from a
             single record database.  The child database will be named
             CALLS.DBF and will contain call tracking records.

        9.2  Add the following field to PHONE.DBF:

                Pos.........:  70
                Fieldname...: LINK
                Type........: C
                Length......:     8
                Decimals....:  0
                Description.: link field

        9.3  Recreate PHONE.DBF by choosing "Create DBF Now?" and
             overwriting the current PHONE.DBF.  Any existing PHONE
             records will be lost.

        9.4  Reindex PHONE.DBF by choosing "Index Now?".

        9.5  In order to call the child database browse from within the
             PHONE browse, add the following key to the PHONE browse:

                Key list position.....:      65
                Char. or "K"+Inkey....:     C
                Description...........:     C - Calls (Calls file)

                Call Function ID......:     CALLS
                 "       "    Type....:     B
                 "       "    Param...:
                 "       "    Extern..:

                Cond. for key select..:     !phone->(eof())
                Condition for access..:
                Post execution proc...:
                Post key proc.........:
                Condition to show.....:
                Fade browse?..........:     Y
                RefreshAll after key?.:     N
                RefreshCurrent after?.:     N

        9.6  In order to call the child database browse from within the
             PHONE screen, add the following key to the PHONE screen:

                Key list position.....:      65
                Char. or "K"+Inkey....:     C
                Description...........:     C - Calls (Calls file)

                Call Function ID......:     CALLS
                 "       "    Type....:     B
                 "       "    Param...:
                 "       "    Extern..:

                Cond. for key select..:
                Condition for access..:
                Post execution proc...:
                Post key proc.........:
                Condition to show.....:
                Fade screen?..........:     Y
                Reload after key?.....:     N
                Redisplay after key?..:     N


        9.7  Add the link field to the PHONE screen field/get
             definitions:

                Position (Get sequence):     70
                DBF alias->field.......:   *PHONE     ->   *LINK
                Int. variable name.....:    mlink
                Int. var. declaration..:    P
                Get prompt (line 23)...:
                 "  type/length/dec....:    C        8     0
                 "  PICTURE............:
                 "  init. expression...:
                 "  VALID (cond).......:
                 "  WHEN (is editable?):    .f.

                Full screen valid cond.:
                Full screen valid msg..:

                Alt. colors (2 colors).:
                Alt. color operation...:    N


             NOTE: The mlink field is NOT editable and is NOT
                   added to the screen window.

        9.8  In the PHONE screen definition page 2,  change the contents
             of the "Before Add/Edit Update proc" field to:

                 if(s_mode=="A", v_assign("mlink",
                 strzero(v_inc("system","counter"),8)), .t.)

             NOTE 1: The preceding two lines are actually ONE line of
                     code!  This expression will increment a numeric
                     counter, convert the count to a zero-padded string,
                     and store the string to the link field memvar
                     MLINK.

             NOTE 2: The CDDLIB.LIB variable S_MODE is an indicator of the
                     current screen mode ("A"=Add, "E"=Edit, "V"=View).
                     The function v_assign() is a function that permits
                     a value to be assigned to a memvar.  The function
                     v_inc() returns an numeric counter field value and
                     then increments the field value.

     10.0 ADDING THE SYSTEM FILE
     ---------------------------

        10.1  Add the following data file into your tutorial program:

                 Alias................:    SYSTEM
                 Filename.............:    SYSTEM
                 Description..........:    System file
                 Alternate Path.......:
                 Open at startup?.....:    Y
                 Show in V_REINDEX()?.:    N

        10.2  Add the following field to SYSTEM.DBF:

                 Pos.........:  10
                 Fieldname...: COUNTER
                 Type........: N
                 Length......:     8
                 Decimals....:  0
                 Description.: phone->link counter

        10.3  Create SYSTEM.DBF.  There are no indexes.  The starting
              record in SYSTEM.DBF will be created the first time
              that a PHONE record is added (when v_inc() is called).


     11.0 ADDING THE CALLS DATABASE
     ------------------------------

        11.1  Add the CALLS.DBF data file into your tutorial program:

                 Alias................:    CALLS
                 Filename.............:    CALLS
                 Description..........:    Calls file
                 Alternate Path.......:
                 Open at startup?.....:    Y
                 Show in V_REINDEX()?.:    Y

        11.2  Add the following fields to CALLS.DBF:

                 Pos.........:  10
                 Fieldname...: LINK
                 Type........: C
                 Length......:     8
                 Decimals....:  0
                 Description.: phone-call link fld


                 Pos.........:  20
                 Fieldname...: TEXT
                 Type........: C
                 Length......:    40
                 Decimals....:  0
                 Description.: Text line


                 Pos.........:  30
                 Fieldname...: CALL_DATE
                 Type........: D
                 Length......:     8
                 Decimals....:  0
                 Description.: date of call

        11.3  Add the following indexes to CALLS.DBF:

                 Index Alias....: CALLS1
                 Index Name.....: CALLS1
                 Key Expression.: link+upper(text)
                 Unique Index?..: N
                 Description....: text index
                 Alternate Path.:


                 Index Alias....: CALLS2
                 Index Name.....: CALLS2
                 Key Expression.: link+dtos(call_date)
                 Unique Index?..: N
                 Description....: date index
                 Alternate Path.:

        11.4  Create CALLS.DBF and its indexes.


     12.0 DEFINING THE CALLS BROWSE
     ------------------------------

        12.1  The CALLS browse will be called from the PHONE browse and
              from the PHONE screen.  First create the CALLS browse
              definition:

                 Browse Function ID...:    CALLS
                 Datafile Alias.......:   *CALLS
                 Init. Index Alias....:   *CALLS2   link+dtos(call_date)
                 Index Filter Expr....:    phone->link
                 Title................:    Calls
                 Coordinates (t,l,b,r):     9    22    19    77
                 Condition for access.:
                 Condition for exit...:
                 Post process.........:
                 Post keystroke proc..:
                 Frozen columns.......:     0
                 Save Scr/Area/Ord/Rec:    Y    Y    N    N
                 Initial GOTOP?.......:    Y
                 Use std. nav. keys?..:    Y

                 *** Page 2 ***
                 Line 23 message.........:     Press F10 for commands
                 Line 24 message.........:
                 Center status lines?....:     Y
                 Full width hilite bar...:     Y
                 Alt. browse colors......:
                 Alt. browse fade color..:
                 Alt. browse box chars...:    *
                 Alt. browse column sep..:
                 Alt browse header sep...:
                 F-Key for keylist.......:     F10 (F2 - F10)
                 Alt. keylist colors.....:
                 Alt. keylist box chars..:    *
                 Alt. keylist title......:

              NOTE: The browse index filter is phone->link so that only
                    those CALLS records belonging to the current PHONE
                    record will be displayed.

        12.2  Add the CALLS browse columns:

                 Column position.......:      10
                 Field/Memvar/Expr.....:    *TEXT
                 Column header.........:                   Text Message
                 Picture clause........:
                 Condition to show?....:
                 Alt. column separator.:
                 Alt header separator..:


                 Column position.......:      20
                 Field/Memvar/Expr.....:    *CALL_DATE
                 Column header.........:     Call Date
                 Picture clause........:
                 Condition to show?....:
                 Alt. column separator.:
                 Alt header separator..:

        12.3  Add the CALLS browse keys:

                 Key list position.....:      10
                 Char. or "K"+Inkey....:     A
                 Description...........:     A - Add

                 Call Function ID......:     CALLS
                  "       "    Type....:     S
                  "       "    Param...:     A
                  "       "    Extern..:

                 Cond. for key select..:
                 Condition for access..:
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade browse?..........:     Y
                 RefreshAll after key?.:     Y
                 RefreshCurrent after?.:     N


                 Key list position.....:      20
                 Char. or "K"+Inkey....:     D
                 Description...........:     D - Delete

                 Call Function ID......:
                  "       "    Type....:     U
                  "       "    Param...:
                  "       "    Extern..:     v_delrec()

                 Cond. for key select..:     !calls->(eof())
                 Condition for access..:     v_is_delete()
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade browse?..........:     N
                 RefreshAll after key?.:     Y
                 RefreshCurrent after?.:     N


                 Key list position.....:      30
                 Char. or "K"+Inkey....:     E
                 Description...........:     E - Edit

                 Call Function ID......:     CALLS
                  "       "    Type....:     S
                  "       "    Param...:     E
                  "       "    Extern..:

                 Cond. for key select..:     !calls->(eof())
                 Condition for access..:
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade browse?..........:     Y
                 RefreshAll after key?.:     Y
                 RefreshCurrent after?.:     N


                 Key list position.....:      40
                 Char. or "K"+Inkey....:     F
                 Description...........:     F - Find

                 Call Function ID......:     CALLS
                  "       "    Type....:     F
                  "       "    Param...:
                  "       "    Extern..:

                 Cond. for key select..:     !calls->(eof())
                 Condition for access..:
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade browse?..........:     Y
                 RefreshAll after key?.:     Y
                 RefreshCurrent after?.:     N


                 Key list position.....:      50
                 Char. or "K"+Inkey....:     O
                 Description...........:     O - Order (Sort)

                 Call Function ID......:     O_CALLS
                  "       "    Type....:     M
                  "       "    Param...:
                  "       "    Extern..:

                 Cond. for key select..:     !calls->(eof())
                 Condition for access..:
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade browse?..........:     Y
                 RefreshAll after key?.:     Y
                 RefreshCurrent after?.:     N


                 Key list position.....:      80
                 Char. or "K"+Inkey....:     K28
                 Description...........:     <F1> - Help

                 Call Function ID......:
                  "       "    Type....:     U
                  "       "    Param...:
                  "       "    Extern..:     v_help()

                 Cond. for key select..:
                 Condition for access..:
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade browse?..........:     N
                 RefreshAll after key?.:     N
                 RefreshCurrent after?.:     N


                 Key list position.....:     500
                 Char. or "K"+Inkey....:     K27
                 Description...........:     <Esc> - Exit

                 Call Function ID......:
                  "       "    Type....:     U
                  "       "    Param...:
                  "       "    Extern..:     v_exit()

                 Cond. for key select..:
                 Condition for access..:
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade browse?..........:     N
                 RefreshAll after key?.:     N
                 RefreshCurrent after?.:     N

              NOTE: An <F5> hotkey copy utility is available from the
                    browse definition screen.  Using this utility, a
                    range of browse columns and browse keys may be
                    copied from an existing browse.  If you use this
                    copy utility, be sure to check every copied item for
                    the correct calls to CDD function IDs, database
                    aliases, etc.


     13.0 DEFINING THE CALLS SCREEN
     ------------------------------

        13.1  The CALLS screen will be called only from the CALLS
              browse.  Now create the CALLS screen definition:

                 Screen Function ID...:    CALLS
                 Datafile Alias.......:   *CALLS
                 Init. Index Alias....:   *
                 Index Filter Expr....:    phone->link
                 Condition for access.:
                 Condition for exit...:
                 Post process.........:
                 Post keystroke proc..:
                 Save Scr/Area/Ord/Rec:    Y    Y    N    N
                 Initial GOTOP?.......:    N
                 Use std. nav. keys?..:    Y
                 Exit screen if eof?..:    Y

                 *** page 3 ***
                 Line 23 message.........:     Press F10 for commands
                 Line 24 message.........:
                 Center status lines?....:     Y
                 Alt. screen colors......:
                 Alt. screen fade color..:
                 Alt screen box chars....:    *
                 F-Key for keylist.......:     F10 (F2 - F10)
                 Alt. keylist colors.....:
                 Alt. keylist box chars..:    *
                 Alt. keylist title......:

              NOTE: Like the CALLS browse, the index filter for the
                    CALLS screen is also phone->link!

        13.2  Add the CALLS screen fields/gets:

                 Position (Get sequence):     10
                 DBF alias->field.......:   *CALLS     ->   *LINK
                 Int. variable name.....:    mlink
                 Int. var. declaration..:    P
                 Get prompt (line 23)...:
                  "  type/length/dec....:    C        8     0
                  "  PICTURE............:
                  "  init. expression...:    phone->link
                  "  VALID (cond).......:
                  "  WHEN (is editable?):    .f.

                 Full screen valid cond.:
                 Full screen valid msg..:

                 Alt. colors (2 colors).:
                 Alt. color operation...:    N


                 Position (Get sequence):     20
                 DBF alias->field.......:   *CALLS     ->   *TEXT
                 Int. variable name.....:    mtext
                 Int. var. declaration..:    P
                 Get prompt (line 23)...:    Enter a brief message
                  "  type/length/dec....:    C       40     0
                  "  PICTURE............:
                  "  init. expression...:
                  "  VALID (cond).......: v_getljust() .and. v_getempty("Text")
                  "  WHEN (is editable?):

                 Full screen valid cond.:    !empty(mtext)
                 Full screen valid msg..:    Text cannot be empty

                 Alt. colors (2 colors).:    W+/R,W+/R
                 Alt. color operation...:    N


                 Position (Get sequence):     30
                 DBF alias->field.......:   *CALLS     ->   *CALL_DATE
                 Int. variable name.....:    mcall_date
                 Int. var. declaration..:    P
                 Get prompt (line 23)...:    Edit the call date
                  "  type/length/dec....:    D        8     0
                  "  PICTURE............:
                  "  init. expression...:    date()
                  "  VALID (cond).......:
                  "  WHEN (is editable?):

                 Full screen valid cond.:
                 Full screen valid msg..:

                 Alt. colors (2 colors).:
                 Alt. color operation...:    N

        13.3  Add the CALLS screen keys:

                 Key list position.....:      10
                 Char. or "K"+Inkey....:     A
                 Description...........:     A - Add

                 Call Function ID......:
                  "       "    Type....:     U
                  "       "    Param...:
                  "       "    Extern..:     s_add()

                 Cond. for key select..:
                 Condition for access..:
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade screen?..........:     N
                 Reload after key?.....:     N
                 Redisplay after key?..:     N


                 Key list position.....:      20
                 Char. or "K"+Inkey....:     D
                 Description...........:     D - Delete

                 Call Function ID......:
                  "       "    Type....:     U
                  "       "    Param...:
                  "       "    Extern..:     v_delrec()

                 Cond. for key select..:
                 Condition for access..:     v_is_delete()
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade screen?..........:     N
                 Reload after key?.....:     Y
                 Redisplay after key?..:     Y


                 Key list position.....:      30
                 Char. or "K"+Inkey....:     E
                 Description...........:     E - Edit

                 Call Function ID......:
                  "       "    Type....:     U
                  "       "    Param...:
                  "       "    Extern..:     s_edit()

                 Cond. for key select..:
                 Condition for access..:
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade screen?..........:     N
                 Reload after key?.....:     N
                 Redisplay after key?..:     N


                 Key list position.....:      40
                 Char. or "K"+Inkey....:     F
                 Description...........:     F - Find

                 Call Function ID......:     CALLS
                  "       "    Type....:     F
                  "       "    Param...:
                  "       "    Extern..:

                 Cond. for key select..:
                 Condition for access..:
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade screen?..........:     Y
                 Reload after key?.....:     Y
                 Redisplay after key?..:     Y


                 Key list position.....:      50
                 Char. or "K"+Inkey....:     O
                 Description...........:     O - Order (Sort)

                 Call Function ID......:     O_CALLS
                  "       "    Type....:     M
                  "       "    Param...:
                  "       "    Extern..:

                 Cond. for key select..:
                 Condition for access..:
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade screen?..........:     Y
                 Reload after key?.....:     Y
                 Redisplay after key?..:     Y


                 Key list position.....:      70
                 Char. or "K"+Inkey....:     K28
                 Description...........:     <F1> - Help

                 Call Function ID......:
                  "       "    Type....:     U
                  "       "    Param...:
                  "       "    Extern..:     v_help()

                 Cond. for key select..:
                 Condition for access..:
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade screen?..........:     N
                 Reload after key?.....:     N
                 Redisplay after key?..:     N


                 Key list position.....:     500
                 Char. or "K"+Inkey....:     K27
                 Description...........:     <Esc> - Exit to browse

                 Call Function ID......:
                  "       "    Type....:     U
                  "       "    Param...:
                  "       "    Extern..:     v_exit()

                 Cond. for key select..:
                 Condition for access..:
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade screen?..........:     N
                 Reload after key?.....:     N
                 Redisplay after key?..:     N

              NOTE: An <F5> hotkey copy utility is available from the
                    screen definition screen.  Using this utility, a
                    range of screen fields and screen keys may be copied
                    from an existing screen.  If you use this copy
                    utility, be sure to check every copied item for the
                    correct calls to CDD function IDs, database aliases,
                    etc.

        13.4  Design the CALLS screen window:

                 ͻ
                                       Call Record                      
                 ĺ
                                                                        
                  Message...:  MTEXT                                    
                  Call Date.:  MCALL_DA                                 
                                                                        
                                                                        
                 ͼ


     14.0 DEFINING FIND AND ORDER FOR THE CALLS BROWSE AND SCREEN
     -----------------------------------------------------------

        14.1  Create the O_CALLS order selection menu and its menu
              items:

                 Menu Function ID......:    O_CALLS
                 Title.................:    [ Select Viewing Order ]
                 Coordinates (t,l).....:    14    40
                 Condition for access..:
                 Condition for exit....:
                 Post process..........:
                 Auto. execute on key?.:    Y
                 Save Scrn/Area/Ord/Rec:    Y    Y    N    N
                 Center menu prompts?..:    Y
                 Alt. menu colors......:
                 Alt. menu fade color..:
                 Alt. menu box chars...:   *


                 Menu item position....:      10
                 Description...........:     1. Text

                 Call Function ID......:
                  "       "    Type....:     U
                  "       "    Param...:
                  "       "    Extern..:     v_vieword("calls",calls1)


                  Menu item position....:      20
                  Description...........:     2. Call Date

                  Call Function ID......:
                   "       "    Type....:     U
                   "       "    Param...:
                   "       "    Extern..:     v_vieword("calls",calls2)


        14.2  Create the CALLS find definition and its find items:

                 Find function ID.......:    CALLS
                 Data alias.............:   *CALLS


                 DBF alias..............:   *CALLS
                 Index alias............:   *CALLS1  link+upper(text)
                 Get title..............:    Text
                  "  type/length/dec....:    C       20     0
                  "  picture............:    @!
                  "  init. expression...:
                  "  cond. for valid....:
                  "  cleanup expression.:    alltrim(v_findget)
                  Append expression.....:    phone->link
                  Set confirm ON?.......:    N
                  Softseek ON?..........:    N


                  DBF alias..............:   *CALLS
                  Index alias............:   *CALLS2  link+dtos(call_date)
                  Get title..............:    Call Date
                   "  type/length/dec....:    D        8     0
                   "  picture............:
                   "  init. expression...:
                   "  cond. for valid....:
                   "  cleanup expression.:    dtos(v_findget)
                   Append expression.....:    phone->link
                   Set confirm ON?.......:    N
                   Softseek ON?..........:    N

        14.3  STOP HERE.  Run TUTOR.EXE and examine how the CALLS
              browse, screens, and finds work via an index filter
              expression.  Please note that the index filter expression
              may be ANY expression, dbf field, or memvar that evaluates
              to a fixed length string.  The index filter expression
              must always match the first portion of any available index
              for a browse or screen.  Do not allow the user to select
              an index that is incompatible with the index filter
              expression!

     ************************************************************************


     15.0 ADD A DATAFILE USED AS A LOOKUP TABLE
     ------------------------------------------

        15.1  Define and create a file named TABLE.DBF with an alias of
              TABLE.  The fields are:

                 code C 1
                 desc C 25

        15.2  Define and create an index named TABLE1 with an index alias of
              TABLE1.  The key is:

                 upper(code)

        15.3  Define and create an index named TABLE2 with an index alias of
              TABLE2.  The key is:

                 upper(desc)

        15.4  Define a full set of maintenance routines for TABLE.DBF. A
              full set of maintenance routines for TABLE.DBF should
              include a TABLE browse, a TABLE edit screen, a TABLE find
              and an O_TABLE order menu.  Call the TABLE browse from the
              main menu.

              The data format and validation requirements for the TABLE
              edit screen are:

                 1. A code is required to be filled in
                 2. A code is capitalized (via the PICTURE clause)
                 3. A desc is required to be filled in
                 4. A desc is left justified

        15.5  STOP HERE.  Test your table maintenance routines.  Add a few
              TABLE.DBF records for use later in the tutorial.


     16.0 DEFINE A LOOKUP BROWSE
     ---------------------------

        16.1  A lookup browse is called from a screen field/get VALID by
              the CDDLIB.LIB function v_look1().  A browse used by the
              lookup validation function v_look() is a regular browse,
              except that it usually only has four browse keys - find,
              order, <Enter>, and <Esc>.   Define following lookup table
              browse:

                 Browse Function ID...:    L_TABLE
                 Datafile Alias.......:   *TABLE
                 Init. Index Alias....:   *TABLE1   upper(code)
                 Index Filter Expr....:
                 Title................:    TABLE.DBF Lookup
                 Coordinates (t,l,b,r):     4    40    15    78
                 Condition for access.:
                 Condition for exit...:
                 Post process.........:
                 Post keystroke proc..:
                 Frozen columns.......:     0
                 Save Scr/Area/Ord/Rec:    Y    Y    N    N
                 Initial GOTOP?.......:    N
                 Use std. nav. keys?..:    Y

                 *** page 2 ***
                 Line 23 message.........:     Press F10 for commands
                 Line 24 message.........:
                 Center status lines?....:     Y
                 Full width hilite bar...:     Y
                 Alt. browse colors......:     W+/BG,N/W,,,N/W
                 Alt. browse fade color..:     BG+/BG
                 Alt. browse box chars...:    *
                 Alt. browse column sep..:
                 Alt browse header sep...:
                 F-Key for keylist.......:     F10 (F2 - F10)
                 Alt. keylist colors.....:     W+/BG,N/W,,,N/W
                 Alt. keylist box chars..:    *
                 Alt. keylist title......:

              NOTE: The "Initial GOTOP?" field is set to NO!

        16.2  Define the following browse columns:

                 Column position.......:      10
                 Field/Memvar/Expr.....:    *CODE
                 Column header.........:     Code
                 Picture clause........:
                 Condition to show?....:
                 Alt. column separator.:
                 Alt header separator..:


                 Column position.......:      20
                 Field/Memvar/Expr.....:    *DESC
                 Column header.........:     Description
                 Picture clause........:
                 Condition to show?....:
                 Alt. column separator.:
                 Alt header separator..:

        16.3  Define the following browse keys:

                 Key list position.....:      40
                 Char. or "K"+Inkey....:     F
                 Description...........:     F - Find

                 Call Function ID......:     TABLE
                  "       "    Type....:     F
                  "       "    Param...:
                  "       "    Extern..:

                 Cond. for key select..:
                 Condition for access..:
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade browse?..........:     Y
                 RefreshAll after key?.:     Y
                 RefreshCurrent after?.:     N


                 Key list position.....:      50
                 Char. or "K"+Inkey....:     O
                 Description...........:     O - Order (Sort)

                 Call Function ID......:     O_TABLE
                  "       "    Type....:     M
                  "       "    Param...:
                  "       "    Extern..:

                 Cond. for key select..:
                 Condition for access..:
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade browse?..........:     Y
                 RefreshAll after key?.:     Y
                 RefreshCurrent after?.:     N


                 Key list position.....:      70
                 Char. or "K"+Inkey....:     K13
                 Description...........:     <Enter> - Select a Code

                 Call Function ID......:
                  "       "    Type....:     U
                  "       "    Param...:
                  "       "    Extern..:     v_exit()

                 Cond. for key select..:
                 Condition for access..:
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade browse?..........:     N
                 RefreshAll after key?.:     N
                 RefreshCurrent after?.:     N


                 Key list position.....:     500
                 Char. or "K"+Inkey....:     K27
                 Description...........:     <Esc> - Exit (no selection)

                 Call Function ID......:
                  "       "    Type....:     U
                  "       "    Param...:
                  "       "    Extern..:     v_exit()

                 Cond. for key select..:
                 Condition for access..:
                 Post execution proc...:
                 Post key proc.........:
                 Condition to show.....:
                 Fade browse?..........:     N
                 RefreshAll after key?.:     N
                 RefreshCurrent after?.:     N

        16.4  Add the validation function v_look1() in the VALID for
              the mrec_type memvar in the screen PHONE:

                 Position (Get sequence):     50
                 DBF alias->field.......:   *PHONE     ->   *REC_TYPE
                 Int. variable name.....:    mrec_type
                 Int. var. declaration..:    P
                 Get prompt (line 23)...:    Enter the record type
                  "  type/length/dec....:    C        1     0
                  "  PICTURE............:    @!
                  "  init. expression...:
                  "  VALID (cond).......:

                  v_look1("O","l_table","table",table1,mrec_type,"code")

                  "  WHEN (is editable?):

                 Full screen valid cond.:
                 Full screen valid msg..:

                 Alt. colors (2 colors).:
                 Alt. color operation...:    N

              NOTE 1: The v_look1() function is added to the VALID.  The
                      CDD Programmer's Guide fully explains the various
                      v_look1() options.  The function v_look1() is a
                      generic lookup with a range of capabilities.  If
                      you need a custom tailored lookup - copy, rename,
                      and adapt v_look1() to meet your requirements.

              NOTE 2: On many occasions, a lookup code field is paired
                      with a description field that must be updated and
                      redisplayed when the code is changed.  To do
                      simultaneous updates and redisplays, include the
                      additional v_look1() parameters to load lookup
                      table values into screen or other memvars.

                      E.g. To simultaneously reload and repaint a
                           description screen memvar for a REQUIRED
                           field lookup:

                      v_look1("R","l_table","table",table1,mrec_type,
                         "code", , "desc", "mdesc")
                         .and. s_refresh("mdesc")

                      Where: desc is the lookup table fieldname.
                             mdesc is a description screen memvar paired
                                with mrec_type.
                             s_refresh() forces a redisplay.


                      E.g. To simultaneously reload and repaint a
                           description screen memvar for an OPTIONAL
                           field lookup:

                      v_look1("O","l_table","table",table1,mrec_type,
                         "code", , "desc", "mdesc") .and.
                         if(empty(mrec_type), v_assign("mdesc",space(20)), .t. )
                         .and. s_refresh("mdesc")

                      Where: desc is the lookup table fieldname.
                             mdesc is a description screen memvar paired
                                with mrec_type.
                             s_refresh() forces a redisplay.
                             Note that since mrec_type can be empty
                             the mdesc memvar must be blanked.

        16.5  STOP HERE.  Examine how the L_TABLE lookup works from the
              PHONE edit screen.  In this example, the lookup is
              configured to be optional - I.e. blank is permitted but a
              non-blank code must be valid.

     ************************************************************************


     17.0 RELATIONAL DATA INTEGRITY
     ------------------------------

        17.1  Maintaining data integrity is always a concern when
              developing relational database programs.  CDDLIB.LIB
              functions such as v_is_dup(), v_sweep_i(), and v_sweep_l()
              are often used to maintain data integrity in your program.

              For example, use v_is_dup() via the mcode VALID to prevent
              entry of duplicate records in your TABLE screen :

                 Position (Get sequence):     10
                 DBF alias->field.......:   *TABLE     ->   *CODE
                 Int. variable name.....:    mcode
                 Int. var. declaration..:    P
                 Get prompt (line 23)...:    Edit the code
                  "  type/length/dec....:    C        1     0
                  "  PICTURE............:    @!
                  "  init. expression...:
                  "  VALID (cond).......:

                     v_getempty("Code") .and. !v_is_dup("table",table1,
                     mcode,s_mode,"This Code")

                  "  WHEN (is editable?):

                 Full screen valid cond.:
                 Full screen valid msg..:

                 Alt. colors (2 colors).:    W+/R,W+/R
                 Alt. color operation...:    N

              NOTE: Although the VALID condition is shown on multiple
                    lines, it is ONE line!  MCODE is the screen memvar
                    and S_MODE is a CDD private variable indicating the
                    current screen mode ("A"=Add, "E"=Edit, "V"=View).

        17.2  Maintaining relational integrity is another concern.  If a
              code is changed in TABLE.DBF, then every field that uses
              that code must be updated.  To insure that changes to the
              TABLE->CODE field are reflected in PHONE->REC_TYPE field,
              add a call to v_sweep_l() to the "After Add/Edit Update
              proc" field in the TABLE screen:

                 Cond. for Add/Edit.........:
                 Cond. for Add/Edit Exit....:
                 Before Add/Edit Update proc:
                 After Add/Edit Update proc.:

                    if(s_mode=="E",v_sweep_l("phone",
                    "rec_type==s_origval('mcode')","rec_type",mcode), .t.)

                 Post Add/Edit proc.........:
                 Set CONFIRM ON?............:     N
                 Prompt for accept?.........:     Y
                 Accept Prompt if Esc?......:     Y

              NOTE: The "After Add/Edit Update proc" is ONE line.  The
                    call to v_sweep_l() is only made when a TABLE.DBF
                    record is edited, NOT during an add.  The function
                    s_origval(), is a CDDLIB.LIB screen function that
                    returns the original value of a screen memvar.
                    Please note that single quotes are needed in this
                    occurrence of s_origval('mcode') for proper nesting
                    of quotes.

        17.3  The global update function v_sweep_l() does not use an
              index.  As an experiment, you may wish to add a third
              index to PHONE.DBF with the key "upper(rec_type)" and use
              v_sweep_i() instead.  The function v_sweep_i() is much
              faster because it uses an index to seek the records for
              updating.

        17.4  Another relational integrity issue is the prevention of
              orphans.  For example, orphan records can be created when
              a parent record is deleted but child records still exist.
              To avoid creating orphan CALLS.DBF records when PHONE.DBF
              records are deleted, you can use the CDDLIB.LIB function
              v_match().  V_match() is used as part of the "condition
              for access" for both the PHONE browse delete key and the
              PHONE screen delete key:

                 if(v_match("calls",calls1,phone->link),
                 v_msg("A child still exists"),.t.) .and.
                 v_is_delete()

              NOTE 1: The above expression is on one line.  V_msg()
                      is an error display function that returns false.

              NOTE 2: In some situations you may wish to automatically
                      delete all child records if a parent record is
                      deleted.  In that case you will write a chain
                      delete function that is called after v_is_delete().
                      E.g. v_is_delete() .and. delete_all()

        17.5  STOP HERE.  Examine how the relational integrity functions
              operate.  Try changing a TABLE->CODE and checking to insure
              that any corresponding PHONE->REC_TYPE codes are updated.
              Also attempt to delete a PHONE.DBF record that still has
              CALLS.DBF records associated with it.

     ************************************************************************


     18.0 SEQUENCES
     --------------

        18.1  The sequencer provides the programmer with the means of
              executing a list of functions in a sequential manner.
              Sequence definitions are stored in the CDD data dictionary
              and are often used for simple initialization or cleanup
              routines.  Another good use for sequences is for complex
              relational integrity routines such as multiple file
              updates.

              Sequences are defined via the CDD main menu selection "5.
              Sequence Definitions" and are executed by calling the
              CDDLIB.LIB function v_sequence().  Below is an example of
              a sequence (named INIT) that creates a public variable and
              loads it with a value from a DOS environment variable:

                 * begin INIT sequence

                 v_make_pub("p_user", getenv("USER") )
                 if( empty(p_user), v_msg("WARNING - USER is not set!"), .t.)

                 * end INIT sequence

              NOTE:  See the CDD Programmer's Guide for information
                     about writing and calling sequences.

        18.2  The above sequence, INIT, can be called in the "condition
              for access" for the MAINMENU menu definition:

                 Menu Function ID......:    MAINMENU
                 Title.................:    [ Main Menu ]
                 Coordinates (t,l).....:     5     5
                 Condition for access..:    v_sequence("INIT")
                 Condition for exit....:
                 Post process..........:
                 Auto. execute on key?.:    Y
                 Save Scrn/Area/Ord/Rec:    Y    Y    N    N
                 Center menu prompts?..:    Y
                 Alt. menu colors......:
                 Alt. menu fade color..:
                 Alt. menu box chars...:   *

              NOTE: V_sequence() returns true by default.  See the CDD
                    Programmer's Guide for information about changing
                    the v_sequence() return value.


     19.0 ADVANCED CDD.EXE FEATURES AND SHORTCUTS
     --------------------------------------------

        19.1  CDD.EXE has several features that dramatically speed up
              the development process.  A few of these features are:

                 1. Reusability of existing code.

                 2. Cloning of existing menus, browses, screens, finds,
                    and sequences.

                 3. Copying of browse and screen key definitions.

                 4. Copying of screen field/get definitions.

                 5. Copy and paste for screen field/get VALID and
                    initialization expressions.

                 6. Importing of any definition from another CDD data
                    dictionary.

        19.2  The reusability of existing code within CDD is similar to
              normal Clipper coding practices where the same function is
              called from several different places in the code.  For
              example, if the lookup browse L_TABLE needs the capability
              for adding a new TABLE.DBF record, simply define an add
              browse key for the L_TABLE browse.  The add browse key
              will call the table maintenance screen TABLE.

        19.3  Menus, browses, screens, finds, and sequences can be
              cloned via the CDD main menu selection "8. Utilities" -
              "3. Clone Definitions".  A clone of a definition will copy
              and rename all associated child definitions.  Carefully
              examine each cloned record and field to identify where
              data aliases and other expressions must be altered.

        19.4  While in the browse or screen definition screen, the <F5>
              hotkey may be used to copy a range of key definitions from
              a another definition.

              While in the browse or screen definition screen, the <F5>
              hotkey may also be used to copy a range of browse column
              or screen field definitions from a another definition.

        19.5  Copy and paste hotkeys are available while in a screen
              field/get definition.  The <Alt-L> key will load either
              the "VALID" or the "Init. expression" into a buffer.

              The <Alt-K> key will dump the buffer contents into the
              keyboard buffer (stuff the keyboard).  Use the <Alt-K>
              key ONLY while in an active get for the field.

              The copy and paste keys are most useful when copying
              complicated VALID expressions, such as v_look1(), from one
              screen memvar to another.

        19.6  Importing from other CDD data dictionaries is done via the
              CDD main menu selection "8. Utilities" - "4. Import
              Definitions".  Reuse of code across applications is
              possible with this feature.

              If the application development is a team effort, the
              import feature allows individual programmers to work with
              separate copies of the data dictionary and then merge
              their changes back into a master data dictionary.  CDD
              data dictionary comparison and reporting utilities are
              available to licensed CDD users.

        19.7  Please see the file ORDER.TXT for information about
              ordering CDD.

        19.8  That's all, Folks!  I hope that you will enjoy using CDD.



     CDD 1.03 Tutorial
     Written by Vick Perry
     Copyright 1993 Phoenix Systems, Inc.

     Phoenix Systems, Inc.
     1700 N. Moore Street
     Arlington, VA 22209

     Phone: 703-522-0820 (Orders and information only)


