Subject: Pop window for 4gl modules
Newsgroups: comp.databases.informix

From: [email-masked] (Omer OZTAN)
Date: 18 Apr 1995 10:33:04 -0400

  A few weeks ago, my partner, A.Ergul, posted a mail about the pop window
code that we use in our modules. Here is the code of this function which may
be useful for your codes. An explanation for the use of this function is given
as a remark lines ...

{
-------------------------------------------------------------------------------
    WE HEREBY PUT THIS CODE IN PUBLIC DOMAIN. YOU CAN DO WHATEVER YOU LIKE
   WITH IT. HOWEVER, WE WOULD BE GLAD IF YOU MENTION MIDDLE EAST TECHNICAL
   UNIVERSITY (METU) , O.OZTAN & A.ERGUL AS THE ORIGINATORS OF THIS CODE .

   QUESTIONS TO : [email-masked]
-------------------------------------------------------------------------------

            EXPLANATIONS FOR THE USE OF FUNCTION L_POP??(.....)

1.  First of all , an array named 'PopUpArray' must be defined in a global file,
  or in your module (if you put this code in your module directly).

   DEFINE  PopUpArray Array[150] of char(60)
           --Used by the corresponding L_Pop..() functions.

   (size of PopUpArray can be changed by the programmer)

2.  In your 4gl module, fetch the rows from the related table via cursor to the
   programme array (in the example the array used is 'P_PopTranscript').
    Then assign the values of P_PopTranscript THAT IS DESIRED TO DISPLAY
   ON THE POPUP WINDOW to the P_PopUpArray. Since the type of P_PopTranscript is
   character, one can use any extra character during assignment. After calling a
   function 'L_Pop20(.....)', the index of 'P_PopTranscript' is stored to the
   variable 'choice'.

    After this, do whatever you like ....

SAMPLE CODE SHOWING THE USE OF FUNCTION L_POP() :
---------------------------------------------------------------------------
DEFINE icount,choice SMALLINT
DEFINE splSql CHAR(100)
DEFINE  P_PopTranscript
                ARRAY[100] OF RECORD
                                orderNo LIKE Transcript.orderNo,
                                student LIKE Transcript.student
                              END RECORD,

LET splSql = "EXECUTE PROCEDURE GetOrders('",
              P_Transcript.whom CLIPPED ,
             "')" CLIPPED
PREPARE getOrdersStm FROM splSql
DECLARE getOrdersCur CURSOR FOR getOrdersStm

FOREACH getOrdersCur INTO P_PopTranscript[icount].*
                LET PopUpArray[icount]= P_PopTranscript[icount].orderNo
                                          USING "######", "    ",
                                          P_PopTranscript[icount].student
                                          USING "#######"
                LET icount = icount + 1
        END FOREACH
        CALL SET_COUNT(icount-1)
        IF icount = 1 THEN
                ERROR "  No Records Found "
                RETURN
        END IF
        CALL L_Pop20(5,5,1,"OrderNo StudentId") RETURNING choice

	DISPLAY "The id number selected is ",  P_PopTranscript[choice].student
	AT 5,5

---------------------------------------------------------------------------

2. Functions L_Pop20(..),L_Pop40(..), and L_Pop60(..) call the function
   L_Pop(..). The only differences of these 3 functions are the size of
   the pop-up window to be displayed. You can go up and down with the cursor-up,
   cursor-down keys and control-key combinations (look at the help window to see
   the key combinations). You can also press any key (except RETURN) which
   matches with the first letter of the element of the array of PopUpArray.

}
DEFINE  PopUpArray Array[150] of char(60)
MAIN
END MAIN

#-----------------------------------------------------------------------------#
# Function L_Pop20() Calls the function L_Pop with a column width of 20       #
#                                                                             #
# Parameters : irow,icolumn : Corner coordinates of the window                #
#              choice       : Index of the array to be displayed to the       #
#                             first line of the pop window                    #
#              msgString    : Header of the pop window                        #
#                                                                             #
# Returns    : returnValue                                                    #
#                                                                             #
#-----------------------------------------------------------------------------#
FUNCTION L_Pop20(irow,icolumn,choice,msgStr)
DEFINE irow,icolumn,choice,columnWidth,returnValue SMALLINT
DEFINE msgStr CHAR(20)
LET returnValue =  L_Pop(irow,icolumn,choice,msgStr,20)
RETURN returnValue
END FUNCTION -- L_Pop20()

#-----------------------------------------------------------------------------#
# Function L_Pop40() Calls the functiion L_Pop with a columnwidth of 40       #
#                                                                             #
# Parameters : irow,icolumn : Corner coordinates of the window                #
#              choice       : Index of the array to be displayed to the       #
#                             first line of the pop window                    #
#              msgString    : Header of the pop window                        #
#                                                                             #
# Returns    : returnValue                                                    #
#                                                                             #
#-----------------------------------------------------------------------------#
FUNCTION L_Pop40(irow,icolumn,choice,msgStr)
DEFINE irow,icolumn,choice,columnWidth,returnValue  SMALLINT
DEFINE msgStr CHAR(40)
LET returnValue =  L_Pop(irow,icolumn,choice,msgStr,40)
RETURN returnValue
END FUNCTION -- L_Pop40()

#-----------------------------------------------------------------------------#
# Function L_Pop60() Calls the functiion L_Pop with a columnwidth of 60       #
#                                                                             #
# Parameters : irow,icolumn : Corner coordinates of the window                #
#              choice       : Index of the array to be displayed to the       #
#                             first line of the pop window                    #
#              msgString    : Header of the pop window                        #
#                                                                             #
# Returns    : returnValue                                                    #
#                                                                             #
#-----------------------------------------------------------------------------#
FUNCTION L_Pop60(irow,icolumn,choice,msgStr)
DEFINE irow,icolumn,choice,columnWidth,returnValue  SMALLINT
DEFINE msgStr CHAR(60)
LET returnValue =  L_Pop(irow,icolumn,choice,msgStr,60)
RETURN returnValue
END FUNCTION -- L_Pop60()

#-----------------------------------------------------------------------------#
# Function L_Pop() Displays a pop window & returns the selected row           #
#                                                                             #
# Parameters : irow,icolumn : Corner coordinates of the window                #
#              choice       : Index of the array to be displayed to the       #
#                             first line of the pop window                    #
#              msgString    : Header of the pop window                        #
#              columnWidth  : Width of the pop window                         #
#                                                                             #
# Returns    : choice                                                         #
#                                                                             #
#                                                                             #
#   The logic of the character matching part of the function is taken from    #
#  Jorge Torralba's drop-down menu code posted to c.d.i. on March 12nd,1995   #
#                                                                             #
#-----------------------------------------------------------------------------#
FUNCTION L_Pop(irow,icolumn,choice,msgStr,columnWidth)
DEFINE 	CurrentLine,ScreenLine,
	irow,icolumn, choice,i,
	rowSize,columnWidth	SMALLINT
DEFINE msgStr, tmpStr 		CHAR(60)
DEFINE searchedPattern		CHAR(2)

DEFINE firstLine,lastLine,rowPos,searchStart	SMALLINT
DEFINE icount,arrayShift,arrayLoc,arraySize	SMALLINT
DEFINE c_any_key  CHAR(2)

IF ARR_COUNT()  =   0 	THEN 	RETURN 0 		END IF
IF choice      <=   0 	THEN 	LET choice = 1   	END IF
IF choice      >= 140 	THEN 	LET choice = 140 	END IF

FOR i = ARR_COUNT() +1 TO 150     -- 150 is the array size of 'PopUpArray'
        LET PopUpArray[i] = NULL  -- in case of any modification of the size
                                  -- of 'PopUpArray' defined in the global file
                                  -- this statament must also be modified
END FOR

LET searchStart = 1
LET currentLine = choice
LET arraySize = ARR_COUNT()
LET firstLine = 3   -- this value can be changed according to programmer's wish
LET lastLine  = 10  -- this value can be changed according to programmer's wish
LET rowSize   = lastLine - firstline + 5

LET rowPos = firstLine

OPEN WINDOW PopWindow AT irow,icolumn
WITH rowSize ROWS,columnWidth COLUMNS
ATTRIBUTE(BORDER,FORM LINE 1,PROMPT LINE LAST)

LET i=(columnWidth-LENGTH(msgStr))/2
LET msgStr=tmpStr[1,i], msgStr CLIPPED
DISPLAY msgStr at 1,1
DISPLAY "_______________________________________________________________" AT 2,1
LET rowSize = rowSize - 1
DISPLAY "_______________________________________________________________"
AT rowSize,1

LET arrayShift = choice - firstLine
LET arrayLoc   = choice
LET icount     = 0
FOR i = firstLine TO lastLine
	LET icount = icount + 1
	IF icount <= arraySize THEN
		DISPLAY PopUpArray[arrayShift+i] AT i,1
	END IF
END FOR
DISPLAY PopUpArray[choice] AT firstLine,1 ATTRIBUTE(REVERSE)

# first thing to do is to take the key value and
# assign it to the variable c_any_key
WHILE TRUE
PROMPT " ctrl-Y: help " FOR CHAR c_any_key
        ON KEY(DOWN)      LET c_any_key = "+1"  -- 1 row forward
        ON KEY(CONTROL-F) LET c_any_key = "+2"  -- 1 page forward
        ON KEY(UP)        LET c_any_key = "+3"  -- 1 row backward
        ON KEY(CONTROL-B) LET c_any_key = "+4"  -- 1 page backward
        ON KEY(CONTROL-G) LET c_any_key = "+5"  -- bottom of array
        ON KEY(CONTROL-E) LET c_any_key = "+6"  -- top of array
        ON KEY(CONTROL-Y) LET c_any_key = "+7"  -- info about keys
END PROMPT

LET c_any_key = UPSHIFT(c_any_key)
IF fgl_lastkey() = fgl_keyval("RETURN") THEN EXIT WHILE END IF
IF int_flag OR quit_flag 		THEN EXIT WHILE END IF

IF c_any_key >= "+1" AND c_any_key <= "+7" THEN

IF c_any_key = "+1" THEN    -- 1 row forward
	IF rowPos < lastLine AND arrayLoc < ARR_COUNT() THEN
		DISPLAY PopUpArray[arrayLoc] AT rowPos,1
		LET arrayLoc = arrayLoc + 1
		LET rowPos   = rowPos + 1
		DISPLAY PopUpArray[arrayLoc] AT rowPos,1 ATTRIBUTE(REVERSE)
		LET currentLine = arrayLoc
	ELSE
		LET arrayShift = arrayLoc - firstLine
		FOR i = firstLine TO lastLine
			DISPLAY PopUpArray[arrayShift+i] AT i,1
			IF arrayShift+i > ARR_COUNT() THEN
				DISPLAY "                    ",
					"                    ",
					"                    " AT i,1
			END IF
		END FOR
		DISPLAY PopUpArray[arrayShift+firstLine] AT firstLine,1
		ATTRIBUTE(REVERSE)
		LET rowPos = firstLine
	END IF
	CONTINUE WHILE
END IF

IF c_any_key = "+2" THEN    --1 page forward
	IF ARR_COUNT()  > lastLine - firstLine + 1 THEN
		IF arrayLoc + lastLine - firstLine < ARR_COUNT() THEN
			LET arrayLoc = arrayLoc + lastLine - firstLine
			LET arrayShift = arrayLoc - firstLine
			FOR i = firstLine TO lastLine
			DISPLAY PopUpArray[arrayShift+i] AT i,1
				IF arrayShift+i > ARR_COUNT() THEN
					DISPLAY "                    ",
					"                    ",
					"                    " AT i,1
	
				END IF
			END FOR
			DISPLAY PopUpArray[arrayLoc] AT firstLine,1
			ATTRIBUTE(REVERSE)
			LET rowPos = firstLine
			LET currentLine = arrayLoc
		ELSE
			LET arrayLoc = ARR_COUNT() -(lastLine - firstLine)
			LET arrayShift = arrayLoc - firstLine
			FOR i = firstLine TO lastLine
				DISPLAY PopUpArray[arrayShift+i] AT i,1
				IF arrayShift+i > ARR_COUNT() THEN
					DISPLAY "                    ",
					"                    ",
					"                    " AT i,1

				END IF
			END FOR
			DISPLAY PopUpArray[arrayLoc] AT firstLine,1
			ATTRIBUTE(REVERSE)
			LET rowPos = firstLine
			LET currentLine = arrayLoc
		END IF
	END IF
	CONTINUE WHILE
END IF

IF c_any_key = "+3" THEN   -- 1 row backward
	IF rowPos > firstLine THEN -- AND arrayLoc > 0 THEN
		DISPLAY PopUpArray[arrayLoc] AT rowPos,1
		LET arrayLoc = arrayLoc - 1
		LET rowPos   = rowPos   - 1
		DISPLAY PopUpArray[arrayLoc] AT rowPos,1 ATTRIBUTE(REVERSE)
		LET currentLine = arrayLoc
	ELSE
		IF arrayLoc < lastLine - firstLine + 1 THEN
			LET arrayShift = 1 - firstLine
			FOR i = firstLine TO lastLine
        			DISPLAY PopUpArray[arrayShift+i] AT i,1
			END FOR
			LET arrayLoc = arrayShift + firstLine
			DISPLAY PopUpArray[arrayLoc] AT firstLine,1
			ATTRIBUTE(REVERSE)
			LET currentLine = arrayLoc
		ELSE
			LET rowPos = lastLine
			LET arrayShift = arrayLoc - lastLine
			FOR i = firstLine TO lastLine
				IF arrayShift+i > 0 THEN
					DISPLAY PopUpArray[arrayShift+i]
					AT i,1
				END IF
			END FOR
			IF arrayShift+firstLine > 0 THEN
				DISPLAY PopUpArray[arrayLoc] AT lastLine,1
				ATTRIBUTE(REVERSE)
			END IF
			LET rowPos = lastLine
		END IF
	END IF
	CONTINUE WHILE
END IF

IF c_any_key = "+4" THEN    --  1 page backward
	IF arrayLoc - (lastLine - firstLine) > 0 THEN
		LET arrayLoc = arrayLoc - lastLine + firstLine
		LET arrayShift = arrayLoc - firstLine
		FOR i = firstLine TO lastLine
			DISPLAY PopUpArray[arrayShift+i] AT i,1
		END FOR
		LET arrayLoc = arrayShift + firstLine
		DISPLAY PopUpArray[arrayLoc] AT firstLine,1 ATTRIBUTE(REVERSE)
		LET rowPos = firstLine
		LET currentLine = arrayLoc
	ELSE
		LET arrayShift =  -firstLine + 1
		FOR i = firstLine TO lastLine
			IF arrayShift+i > ARR_COUNT() THEN
				DISPLAY "                    ",
				"                    ",
				"                    " AT i,1
			ELSE
				DISPLAY PopUpArray[arrayShift+i] AT i,1
			END IF
		END FOR
		LET arrayLoc = 1
		DISPLAY PopUpArray[arrayLoc] AT firstLine,1 ATTRIBUTE(REVERSE)
		LET rowPos = firstLine
		LET currentLine = arrayLoc
	END IF
	CONTINUE WHILE
END IF

IF c_any_key ="+5" THEN -- bottom of array
	IF ARR_COUNT()  > lastLine - firstLine + 1 THEN
		LET arrayLoc = ARR_COUNT() -(lastLine - firstLine)
		LET arrayShift = ARR_COUNT() -lastLine
		FOR i = firstLine TO lastLine
			IF arrayShift+i > ARR_COUNT() THEN
				DISPLAY "                    ",
				"                    ",
				"                    " AT i,1
			ELSE
				DISPLAY PopUpArray[arrayShift+i] AT i,1
			END IF
		END FOR
		DISPLAY PopUpArray[arrayLoc] AT firstLine,1 ATTRIBUTE(REVERSE)
		LET rowPos = firstLine
		LET currentLine = arrayLoc
	END IF
END IF

IF c_any_key = "+6" THEN -- top of array
	LET arrayShift = -firstLine  + 1
	FOR i = firstLine TO lastLine
		DISPLAY PopUpArray[arrayShift+i] AT i,1
	END FOR
	LET arrayLoc = 1
	DISPLAY PopUpArray[arrayLoc] AT firstLine,1 ATTRIBUTE(REVERSE)
	LET rowPos = firstLine
	LET currentLine = arrayLoc
	CONTINUE WHILE
END IF

IF c_any_key = "+7" THEN  -- info about keys
	CALL L_KeyHelpWindow()
	CONTINUE WHILE
END IF

ELSE
	LET searchedPattern = c_any_key CLIPPED ,"*"
	FOR i = searchStart TO ARR_COUNT()
		IF L_LeftTrim(PopUpArray[i])
		MATCHES searchedPattern CLIPPED THEN
			LET searchStart = i + 1
			IF searchStart > ARR_COUNT() THEN
				LET searchStart = 1
			END IF
			LET arrayLoc = i
			LET currentLine = arrayLoc
			LET rowPos = firstLine
			LET arrayShift = arrayLoc - firstLine
			FOR icount = firstLine TO lastLine
				IF arrayShift+icount <= ARR_COUNT() THEN
					DISPLAY PopUpArray[arrayShift+icount]
					AT icount,1
				ELSE
					DISPLAY "                    ",
					"                    ",
					"                    " AT i,1
				END IF
			END FOR
			DISPLAY PopUpArray[arrayLoc] AT firstLine,1
			ATTRIBUTE(REVERSE)
			EXIT FOR	
		ELSE
			LET searchStart = 1
		END IF
	END FOR
	
END IF

END WHILE

CLOSE WINDOW PopWindow
RETURN currentline

END FUNCTION -- L_Pop()

#-----------------------------------------------------------------------------#
# Function L_KeyHelpWindow() :Called by function L_Pop                        #
#                                                                             #
#                  This function displays a window which gives an             #
#                  information about the keys                                 #
#-----------------------------------------------------------------------------#
FUNCTION L_KeyHelpWindow()

DEFINE a CHAR(1)

OPEN WINDOW KeyHelpWindow AT 3,40
WITH 12 ROWS,29 COLUMNS
ATTRIBUTE(BORDER,PROMPT LINE LAST)

DISPLAY "KEYS"                            AT 1,12
DISPLAY "_____________________________"   AT 2,1
DISPLAY " cursor down: forward  / 1 row"  AT 3,1
DISPLAY " cursor up  : backward / 1 row"  AT 4,1
DISPLAY " ctrl-F     : forward  / 1 page" AT 5,1
DISPLAY " ctrl-B     : backward / 1 page" AT 6,1
DISPLAY " ctrl-G     : bottom"            AT 7,1
DISPLAY " ctrl-E     : top"               AT 8,1
DISPLAY "	ctrl-C : cancel"              AT 9,1
DISPLAY "	enter  : accept"              AT 10,1
DISPLAY "_____________________________"   AT 11,1

PROMPT "" FOR CHAR a
IF int_flag OR Quit_flag THEN
	LET int_flag = FALSE
	LET quit_flag= FALSE
END IF
CLOSE WINDOW KeyHelpWindow

END FUNCTION -- L_KeyHelpWindow()

#-----------------------------------------------------------------------------#
# FUNCTION : L_LeftTrim()                                                     #
#                                                                             #
# Purpose  :  IN ORDER TO trim the LEFT-sided blanks                          #
#                                                                             #
#            IN the character variables, use this FUNCTION                    #
#                                                                             #
#                                                                             #
# Usage    :  ...                                                             #
#             .                                                               #
#             LET P_Name.fname = L_LeftTrim(P_Name.fname)                     #
#                                                                             #
# Returns  :  LEFT trimmed character variable itself                          #
#                                                                             #
#-----------------------------------------------------------------------------#
FUNCTION L_LeftTrim(TrmChar)
DEFINE trmchar      CHAR(80),
       i,charpos,lt INTEGER

IF trmchar IS NULL THEN
	LET trmchar = " "
END IF

LET lt = LENGTH(trmchar)
IF trmchar <> " " THEN
	FOR i = 1 TO lt
		IF trmchar[i] <> " " THEN
			EXIT FOR
		ELSE
			LET charpos = i
		END IF
	END FOR
END IF

IF lt > 0 THEN
	LET trmchar = trmchar[charpos+1,lt]
ELSE
	LET trmchar = " "
END IF

RETURN trmchar CLIPPED

END FUNCTION -- L_LeftTrim()

====================================================================

          Omer OZTAN

        Research Assistant              e-mail
 Middle East Technical University      [email-masked]
        President's Office             [email-masked]
         Computer Center               [email-masked]
                                       [email-masked]
====================================================================