From: Dennis Pimple <[email-masked]>
Date: Thu, 26 May 94 18:42:53 PDT

There are three files: the .per for the array, the .per for the wordwrap,
and the 4gl code.

I hope it's of use.

============================================================
Dennis J. Pimple         Informix Software Inc
Senior Consultant        Denver Colorado USA
[email-masked]     Voice:303-850-0210 Fax:303-779-4025
------------------------ CUT HERE --------------------------------------
{*
   warray.per; screen for the INPUT ARRAY. When the user enters field f003,
   the window in ww.per will pop to allow array input
*}
DATABASE FORMONLY

SCREEN
{
[f001    |f002|f003                                                        |n  ]
[f001    |f002|f003                                                        |n  ]
[f001    |f002|f003                                                        |n  ]
[f001    |f002|f003                                                        |n  ]
[f001    |f002|f003                                                        |n  ]
[f001    |f002|f003                                                        |n  ]
[f001    |f002|f003                                                        |n  ]
[f001    |f002|f003                                                        |n  ]
[f001    |f002|f003                                                        |n  ]
[f001    |f002|f003                                                        |n  ]
[f001    |f002|f003                                                        |n  ]
[f001    |f002|f003                                                        |n  ]
[f001    |f002|f003                                                        |n  ]
[f001    |f002|f003                                                        |n  ]
[f001    |f002|f003                                                        |n  ]
[f001    |f002|f003                                                        |n  ]
[f001    |f002|f003                                                        |n  ]
[f001    |f002|f003                                                        |n  ]
[f001    |f002|f003                                                        |n  ]
[f001    |f002|f003                                                        |n  ]
 ==============================================================================

}

ATTRIBUTES
f001 = FORMONLY.sdate TYPE DATE, FORMAT = "mm/dd/yy", COMMENTS =
    "Date of status entry";
f002 =  FORMONLY.catid TYPE CHAR, UPSHIFT, COMMENTS =
    "Category ID";
f003 = FORMONLY.sdetl TYPE CHAR;
n    = FORMONLY.ne TYPE CHAR, NOENTRY;

INSTRUCTIONS

DELIMITERS "  "

SCREEN RECORD s_warray[20] (FORMONLY.sdate, FORMONLY.catid, FORMONLY.sdetl,
                            FORMONLY.ne)

END
------------------------ CUT HERE --------------------------------------
{*
  ww.per; Window to INPUT in WORDWRAP mode
*}
DATABASE FORMONLY

SCREEN
{
 [f003                                                        ]
 [f003                                                        ]
 [f003                                                        ]
 [f003                                                        ]
 [f003                                                        ]
}

ATTRIBUTES
f003 = FORMONLY.sdetl TYPE CHAR, WORDWRAP COMPRESS, COMMENTS =
    "Full Status description";

INSTRUCTIONS

DELIMITERS "  "

END
------------------------ CUT HERE --------------------------------------
###########     #   INFORMIX PROFESSIONAL SERVICES
#######     #  ##   Denver, Colorado
######     #  ###   ==================================================
#####     #  ####   File: %M%  SCCS: %I% %P%
####     #  #####   Program: ww.4gi
###     #  ######   Client: Internal
##     #  #######   Author: Dennis J. Pimple
#     ###########   Date: %G% %U%
# Demo of using INPUT ARRAY and a WORDWRAP screen until that feature is
# provided for real. If it looks kludgey, it's better than nothing.

DEFINE ma_warray  ARRAY[60] OF RECORD    # Input array
        sdate       DATE,
        catid       CHAR(4),
        sdetl       CHAR(60),           # 1st 60 of 300 chars in sdetl
        ne          CHAR(3)             # NOENTRY ("..." for wrapping)
END RECORD
DEFINE ma_ww    ARRAY[60] OF RECORD     # hold entire detail record
        sdetl       CHAR(300)
END RECORD
DEFINE sdetl_l     SMALLINT                # length ma_warray.sdetl
DEFINE mstat_x     SMALLINT                # max array count
DEFINE mstat_s     SMALLINT                # screen record size
DEFINE mstat_t     SMALLINT                # tot array filled

#---------------------------------------------------------------------#
MAIN
# Arguments: N/A
# Purpose:   Display screen & menu
# Returns:   N/A
#---------------------------------------------------------------------#

DEFER INTERRUPT

# Set up options
OPTIONS INSERT KEY CONTROL-O
OPTIONS DELETE KEY CONTROL-Y
OPTIONS NEXT KEY CONTROL-F
OPTIONS PREVIOUS KEY CONTROL-U
OPTIONS INPUT NO WRAP

# initialize local variables
LET sdetl_l = 60
LET mstat_x = 60
LET mstat_s = 20

OPEN FORM warray FROM "warray"
DISPLAY FORM warray

# for starters, set ma_warray to null
CALL null_stat()

# call the function to do the input
CALL inp_stat()

END MAIN

#---------------------------------------------------------------------#
FUNCTION null_stat()
# Arguments: N/A
# Purpose:   Null ma_warray
# Returns:   N/A
#---------------------------------------------------------------------#
DEFINE arr      SMALLINT

FOR arr = 1 TO mstat_x
    INITIALIZE ma_warray[arr].* TO NULL
    INITIALIZE ma_ww[arr].* TO NULL
    IF arr <= mstat_s THEN
        CLEAR s_warray[arr].*
    END IF
END FOR
# mark that none are filled in
LET mstat_t = 0

END FUNCTION
# null_stat()

#---------------------------------------------------------------------#
FUNCTION inp_stat()
# Arguments: N/A
# Purpose:   Input records ma_warray.* and update database
# Returns:   N/A
#---------------------------------------------------------------------#
DEFINE arr,scr,act  SMALLINT
DEFINE arrg         SMALLINT
DEFINE x            SMALLINT

DISPLAY "INPUT: ESC accepts, DEL quits", "" AT 1,1
DISPLAY "^P Ditto ^O Ins ^Y Del ^F Nxt ^U Prv ^T Top ^B Bot", "" AT 2,1

# a lot of this stuff is for NEXT ROW jumping and such. Look at the
# BEFORE INSERT, AFTER DELETE, and BEFORE FIELD sdetl control blocks
# for the stuff that implements the WORDWRAP
LET act = mstat_t
LET arrg = 1
WHILE arrg > 0
    CALL set_count(act)
    INPUT ARRAY ma_warray WITHOUT DEFAULTS FROM s_warray.*
        ON KEY (CONTROL-P)
            # ditto key
            IF arr = 1 THEN
                ERROR ""
            ELSE
                CASE
                WHEN INFIELD(sdate)
                    LET ma_warray[arr].sdate = ma_warray[arr-1].sdate
                WHEN INFIELD(catid)
                    LET ma_warray[arr].catid = ma_warray[arr-1].catid
                WHEN INFIELD(sdetl)
                    LET ma_warray[arr].sdetl = ma_warray[arr-1].sdetl
                    # keep the wordwrap array up to date as well
                    LET ma_ww[arr].sdetl = ma_ww[arr-1].sdetl
                    IF LENGTH(ma_ww[arr].sdetl) > sdetl_l THEN
                        # show that there is more to detail to see
                        LET ma_warray[arr].ne = "..."
                    ELSE
                        LET ma_warray[arr].ne = ""
                    END IF
                END CASE
                DISPLAY ma_warray[arr].* TO s_warray[scr].*
                    ATTRIBUTE(REVERSE)
            END IF
        ON KEY (CONTROL-T)
            # home
            LET arrg = 1
            EXIT INPUT
        ON KEY (CONTROL-B)
            # bottom
            LET arrg = act
            EXIT INPUT
        BEFORE ROW
            LET arr = arr_curr()
            LET scr = scr_line()
            LET act = arr_count()
            IF arrg > arr THEN
                # jump to next row
                NEXT FIELD ne
            END IF
            IF arr > 1 AND arr >= act THEN
                IF ma_warray[arr-1].sdate IS NULL THEN
                    # on moving down from an empty row, go to top
                    LET arrg = 1
                    EXIT INPUT
                END IF
            END IF
            LET arrg = 0
            NEXT FIELD sdate
        BEFORE INSERT
            # open up ma_ww
            IF arr <= act THEN
                FOR x = act TO arr STEP -1
                    IF x <= mstat_x THEN
                        LET ma_ww[x+1].* = ma_ww[x].*
                    END IF
                END FOR
                INITIALIZE ma_ww[arr].* TO NULL
            END IF
        AFTER DELETE
            # bring ma_ww up to date
            IF arr < act THEN
                FOR arr = arr+1 TO act
                    LET ma_ww[arr-1].* = ma_ww[arr].*
                END FOR
            END IF
            INITIALIZE ma_warray[act].* TO NULL
            INITIALIZE ma_ww[act].* TO NULL
        BEFORE FIELD sdate
            IF ma_warray[arr].sdate IS NULL THEN
                IF arr = 1 THEN
                    # default to TODAY
                    LET ma_warray[arr].sdate = TODAY
                ELSE
                    # default to day after the one above
                    LET ma_warray[arr].sdate = ma_warray[arr-1].sdate + 1
                END IF
            END IF
            DISPLAY ma_warray[arr].* TO s_warray[scr].* ATTRIBUTE(REVERSE)
        BEFORE FIELD catid
            IF ma_warray[arr].sdate IS NULL THEN
                ERROR "Required"
                NEXT FIELD sdate
            END IF
        AFTER FIELD catid
            IF ma_warray[arr].catid IS NULL THEN
                ERROR "Required"
                NEXT FIELD catid
            END IF
        BEFORE FIELD sdetl
            # jump into the wordwarp input
            LET ma_ww[arr].sdetl[1,sdetl_l] = ma_warray[arr].sdetl
            DISPLAY ma_warray[arr].* TO s_warray[scr].*
            # call the function that does the wordwrap input
            CALL inp_sdetl(arr)
            # back to the input array
            CURRENT WINDOW IS SCREEN
            DISPLAY ma_warray[arr].* TO s_warray[scr].*
                ATTRIBUTE(REVERSE)
            # jump to next row
            NEXT FIELD ne
        AFTER ROW
            IF ma_warray[arr].sdate IS NULL
            OR ma_warray[arr].catid IS NULL THEN
                INITIALIZE ma_warray[arr].* TO NULL
            END IF
            DISPLAY ma_warray[arr].* TO s_warray[scr].*
    END INPUT
    IF ma_warray[arr].sdate IS NULL
    OR ma_warray[arr].catid IS NULL THEN
        INITIALIZE ma_warray[arr].* TO NULL
    END IF
    DISPLAY ma_warray[arr].* TO s_warray[scr].*
    IF int_flag THEN
        LET arrg = 0
    END IF
    LET act = arr_count()
END WHILE   # arrg > 0

DISPLAY "" AT 1,1
DISPLAY "" AT 2,1

IF int_flag THEN
    ERROR ""
    LET int_flag = FALSE
    CLEAR FORM
    RETURN
END IF

# HERE is where you'd update the table, using ma_ww[#].sdetl to
# populate the sdetl column

END FUNCTION
# inp_stat()

#---------------------------------------------------------------------#
FUNCTION inp_sdetl(arr)
# Arguments: Array value to do input to
# Purpose:   Input ma_ww[arr].sdetl in WORDWRAP mode
# Returns:   N/A
#---------------------------------------------------------------------#
DEFINE arr      SMALLINT

OPEN WINDOW ww AT 2,15 WITH FORM "ww"
    ATTRIBUTE(BORDER,COMMENT LINE LAST,MESSAGE LINE LAST)

DISPLAY "INPUT: RETURN accepts, DEL quits", "" AT 1,1
DISPLAY "Enter up to 5 lines for description", "" AT 2,1

INPUT BY NAME ma_ww[arr].sdetl WITHOUT DEFAULTS

CLOSE WINDOW ww

IF NOT int_flag THEN
    LET ma_warray[arr].sdetl = ma_ww[arr].sdetl CLIPPED
    IF LENGTH(ma_ww[arr].sdetl) > sdetl_l THEN
        # show that there is more to detail to see
        LET ma_warray[arr].ne = "..."
    ELSE
        LET ma_warray[arr].ne = ""
    END IF
ELSE
    LET int_flag = FALSE
END IF

END FUNCTION
# inp_sdetl(arr)