## FOXPRO FOR CLIPPERHEADS by Tom Rettig, page 61

Listing 1 -- Simple window example

01: * WINDOW.PRG
02: DEFINE WINDOW w1 FROM 0,0 TO 5,10
03: STORE 0 TO r, c  && starting row and column
04: CLEAR
05: @ 12,28 SAY "Press any key to stop."
06: ACTIVATE WINDOW w1    && automatically saves screen
07: DO WHILE INKEY() = 0
08:    DO CASE
09:       CASE c = 69 .AND. r < 19
10:          r = r+1
11:       CASE c = 69 .OR. (r = 19 .AND. c > 0)
12:          c = c-1
13:       CASE r = 19 .OR. (c = 0 .AND. r > 0)
14:          r = r-1
15:       OTHERWISE
16:          c = c+1
17:    ENDCASE
18:    MOVE WINDOW w1 TO r, c
19:    @ 1,4 SAY r PICTURE "99"  && relative coordinates
20:    @ 2,4 SAY c PICTURE "99"  && relative coordinates
21: ENDDO
22: DEACTIVATE WINDOW w1  && automatically restores screen
23: @ 12,28      && clear screen prompt
24: RETURN



Listing 2 -- @...MENU versus ACHOICE()

   * FoxPro.
   @ <row>, <col> MENU <array name>, <N elements in menu>
                       [, <N elements shown in window>]
                       [TITLE <expC>] [SHADOW]
   [<memvar> = <N starting element>]
   READ MENU TO <memvar> [SAVE]
    * Clipper.
   <memvar> = ACHOICE(<N row>, <N col>, <N row>, <N col>,
                      <array name>
                      [, <selectability array>
                       [, <C user-function name>
                        [, <N first choice>
                         [, <N window row>]]]])



Listing 3 -- Menu selection options

01: DECLARE choices[7]
02: choices[1] = "\<One"    && press O
03: choices[2] = "\<Two"    && press T
04: choices[3] = "T\<hree"  && press H
05: choices[4] = "\-"       && unselectable line
06: choices[5] = "\<Four"   && press F
07: choices[6] = "F\<ive"   && press I
08: choices[7] = "\Six"     && unselectable item
09: @ 5,5 MENU choices      && define menu position
10: select = 3              && start with element 3
11: READ MENU TO select     && activate menu



Listing 4 -- @...GET input example

01: * Prepare a pick-list of choices for WHEN UDF().
02: DECLARE picklist[5]
03: picklist[1] = "One"
04: picklist[2] = "Two"
05: picklist[3] = "Three"
06: picklist[4] = "Four"
07: picklist[5] = "Five"
08:
09: CLEAR
10: STORE SPACE(15) TO a, b, c, d, e
11: @ 5, 5 SAY "A:" GET a WHEN when_udf() VALID valid_udf()
12: @ 6, 5 SAY "B:" GET b WHEN when_udf() VALID valid_udf()
13: @ 7, 5 SAY "C:" GET c WHEN when_udf() VALID valid_udf()
14: @ 8, 5 SAY "D:" GET d WHEN when_udf() VALID valid_udf()
15: @ 9, 5 SAY "E:" GET e WHEN when_udf() VALID valid_udf()
16: READ NOMOUSE
17: RETURN
18: *******************************************************
19:
20: FUNCTION when_udf
21: * Brings up predeclared pick-list on entry into GET
22: *
23: PRIVATE var, ret, choice
24: var = VARREAD()
25: ret = .F.
26: @ 10,25 MENU picklist, 5 TITLE "GET: " + var
27: READ MENU TO choice
28: IF choice > 0
29:    &var = picklist[choice]   && place choice in GET
30:    ret = .T.
31: ENDIF
32: RETURN ret
33: ** when_udf() *****************************************
34:
35: FUNCTION valid_udf
36: PRIVATE var, temp
37: var = VARREAD()
38: IF EMPTY(&var)
39:    temp = SPACE(35)
40:    @ 11, 5 SAY "Field is empty" GET temp VALID v2_udf()
41:    READ  && nested one deep
42: ENDIF
43: @ 11, 5
44: RETURN .T.
45: ** valid_udf() ****************************************
46:
47: FUNCTION v2_udf
48: IF EMPTY(temp)
49:    temp2 = SPACE(35)
50:    @ 12, 5 SAY "What, again?" GET temp2 VALID v3_udf()
51:    READ  && nested two deep
52: ENDIF
53: @ 12, 5
54: RETURN .T.
55: ** v2_udf() *******************************************
56:
57: FUNCTION v3_udf
58: IF EMPTY(temp2)
59:    temp3 = SPACE(35)
60:    @ 13, 5 SAY "Third time!!!" GET temp3
61:    READ  && nested three deep
62: ENDIF
63: @ 13, 5
64: RETURN .T.
65: ** v3_udf() *******************************************

Listing 5 -- Specify next GET

STORE SPACE(15) TO a, b, c, d, e
@ 1, 1 GET a VALID v_udf()
@ 2, 2 GET b VALID v_udf()
@ 3, 3 GET c VALID v_udf()
@ 4, 4 GET d VALID v_udf()
@ 5, 5 GET e VALID v_udf()
READ
RETURN

FUNCTION v_udf
PRIVATE var, ret
var = VARREAD()
ret = 1       && next GET, same as logical true
DO CASE
   CASE var=="B" .AND. EMPTY(b)
      * Go to D, skipping C if B is blank.
      ret = 2
   CASE var=="E" .AND. EMPTY(a) .AND. !EMPTY(e)
      * Return to A if A is blank and E is not.
      ret = -4
   CASE var=="D" .AND. EMPTY(d)
      * Prevent D from being left blank.
      ret = 0          && same as logical false
ENDCASE
RETURN ret
