'===========================================================================
' Subject: LIST BOX                           Date: 01-11-97 (16:45)       
'  Author: Thomas Matysik                     Code: QB, QBasic, PDS        
'  Origin: FidoNet QUIK_BAS Echo            Packet: MENU.ABC
'===========================================================================
'* LISTBOX.BAS * '* By Thomas Matysik *

' **** PUBLIC DOMAIN ****

'* These routines display a 78-character-wide list box on the screen, in any
'  height required.  The length of the lines can be up to 76 characters.
'
'  The data is transferred to the ListBox routine in the string array
'  MyData(), which can have basically as many different elements as needed,
'  but the first element must be 1.
'
'  If the extended ascii characters in the PRINT statements in the Box sub
'  don't come out properly, they should be characters 201, 205, 178 for the
'  first PRINT statement, character 186 (twice) for the second PRINT, and
'  characters 200, 205 and 188 for the third PRINT.

'  To make a list box, call ListBox, with the data array, starting line on
'  the screen, ending line on the screen, and the variable to return the
'  selected option number in.

'  The Selected% variable returned will be either -1 (if the user pressed
'  <Esc>) or the array element number of the selected option. *

DECLARE SUB Box (x1%, y1%, x2%, y2%)
DECLARE SUB ListBox (MyData() AS STRING, StartLine%, EndLine%, Selected%)
DECLARE SUB DisplayListBox (MyData() AS STRING, CurrentDisplay%, CurrentSelection%, StartLine%, EndLine%)

COLOR 7, 1
CLS
OPEN "e:\bitcom\sw-index\selected.txt" FOR INPUT AS #1

DIM MyData(1 TO 100)  AS STRING

FOR i = 1 TO 100
  INPUT #1, MyData(i)
  MyData(i) = LEFT$(MyData(i), 76)
NEXT i

CLOSE

ListBox MyData(), 1, 25, a%

IF a% > 0 THEN
  PRINT : PRINT "You selected option"; a%
  PRINT MyData(a%)
ELSEIF a% = -1 THEN
  PRINT : PRINT "*Cancel*"
END IF

SLEEP dummy$ = INKEY$

SUB Box (x1%, y1%, x2%, y2%) '* Display top line (character 201, row of character 205, character 187) *
LOCATE y1%, x1%
PRINT "+"; STRING$(x2% - x1% - 1, "-"); "+";

'* Display side bars (character 186) *
FOR i = y1% + 1 TO y2% - 1
  LOCATE i, x1%
  PRINT "|";
  LOCATE i, x2%
  PRINT "|";
NEXT i

'* Display bottom line (200, row of 205, 188) *
LOCATE y2%, x1%
PRINT "+"; STRING$(x2% - x1% - 1, "-"); "+";

END SUB

SUB DisplayListBox (MyData() AS STRING, CurrentDisplay%, CurrentSelection%, StartLine%, EndLine%)
  COLOR 3, 0
  Box 2, StartLine%,79, EndLine%               'Draw a box around the list COLOR 7, 0

  FOR i = StartLine% + 1 TO EndLine% - 1

    '* Get string to display *
    CurrentString$ = MyData(CurrentDisplay% + i - StartLine% - 1)

    '* If the selection bar is on this line then change colour *
    IF i - StartLine% = CurrentSelection% THEN COLOR 15, 4

    LOCATE i, 3
    PRINT CurrentString$; SPACE$(76 - LEN(CurrentString$));

    '* If colour was changed for selection bar then change back *
    IF i - StartLine% = CurrentSelection% THEN COLOR 7, 0
  NEXT i

END SUB

SUB ListBox (MyData() AS STRING, StartLine%, EndLine%, Selected%)

  CurrentDisplay% = 1                   'Set first line displayed to 1
  GOSUB ListMenuDown                    'Set the selection bar to item 1

  ' Display the box
  DisplayListBox MyData(), CurrentDisplay%, CurrentSelection%, StartLine%, EndLine%

  DO

    DO
      xxx$ = INKEY$
    LOOP WHILE xxx$ = ""

    SELECT CASE xxx$

      CASE CHR$(0) + "H"                'Up arrow key
        GOSUB ListMenuUp

      CASE CHR$(0) + "P"                'Down arrow key
        GOSUB ListMenuDown

      CASE CHR$(0) + "I"                'Page Up key
        IF CurrentDisplay% > 1 THEN
          CurrentDisplay% = CurrentDisplay% - (EndLine% - StartLine% - 2)
          IF CurrentDisplay% < 1 THEN CurrentDisplay% = 1
          DisplayListBox MyData(), CurrentDisplay%, CurrentSelection%, StartLine%, EndLine%
        END IF

      CASE CHR$(0) + "Q"                'Page Down key
        IF CurrentDisplay% < UBOUND(MyData) - ((EndLine% - StartLine% - 2) * 2) THEN
          CurrentDisplay% = CurrentDisplay% + (EndLine% - StartLine% - 2)
        ELSE
          CurrentDisplay% = UBOUND(MyData) - (EndLine% - StartLine% - 2)
        END IF
        DisplayListBox MyData(), CurrentDisplay%, CurrentSelection%, StartLine%, EndLine%

      CASE CHR$(13)                     'Enter key (select)
        Selected% = CurrentDisplay% + CurrentSelection% - 1
        EXIT SUB

      CASE CHR$(27)                     'Esc key (cancel)
        Selected% = -1
        EXIT SUB
    END SELECT
  LOOP

  EXIT SUB

ListMenuDown:                        'GOSUB routine for down arrow key
 IF CurrentDisplay% + CurrentSelection% < UBOUND(MyData) THEN
    '* If selection bar is on the last item currently displayed scroll down *
    IF CurrentSelection% = EndLine% - StartLine% - 1 THEN
      IF CurrentDisplay% < (UBOUND(MyData) - (EndLine% - StartLine% - 2)) THEN
        CurrentDisplay% = CurrentDisplay% + 1
        DisplayListBox MyData(), CurrentDisplay%, CurrentSelection%, StartLine%, EndLine%
      END IF
    ELSE
      CurrentSelection% = CurrentSelection% + 1

      IF NOT CurrentSelection% < 2 THEN         'Remove old selection bar
        COLOR 7, 0
        LOCATE CurrentSelection% + StartLine% - 1, 3
        PRINT MyData(CurrentSelection% - 2 + CurrentDisplay%); SPACE$(76 - LEN(MyData(CurrentSelection% - 2 + CurrentDisplay%)));
      END IF

      COLOR 15, 4                               'Create new selection bar
      LOCATE CurrentSelection% + StartLine%, 3
      PRINT MyData(CurrentSelection% - 1 + CurrentDisplay%); SPACE$(76 - LEN(MyData(CurrentSelection% - 1 + CurrentDisplay%)));
    END IF
  END IF
RETURN



ListMenuUp:                                     'Gosub routine for up arrow
  IF CurrentDisplay% + CurrentSelection% > 2 THEN

    '* If currently selected item is first item displayed then scroll up *
    IF CurrentSelection% = 1 AND CurrentDisplay% > 1 THEN
      CurrentDisplay% = CurrentDisplay% - 1
      DisplayListBox MyData(), CurrentDisplay%, CurrentSelection%, StartLine%, EndLine%
    ELSE
      CurrentSelection% = CurrentSelection% - 1

      '* Remove old selection bar *
      IF NOT CurrentSelection% + StartLine% = EndLine% - 1 THEN
        COLOR 7, 0
        LOCATE CurrentSelection% + StartLine% + 1, 3
        PRINT MyData(CurrentSelection% + CurrentDisplay%); SPACE$(76 - LEN(MyData(CurrentSelection% + CurrentDisplay%)));
      END IF

      '* Create new selection bar *
      COLOR 15, 4
      LOCATE CurrentSelection% + StartLine%, 3
      PRINT MyData(CurrentSelection% - 1 + CurrentDisplay%); SPACE$(76 - LEN(MyData(CurrentSelection% - 1 + CurrentDisplay%)));
    END IF
  END IF
RETURN

END SUB
