REM     The Standart GNU Personal Phone Book.
REM     Copyright (C) Sandul Yura Valentinovich.
REM     (R) Wednesday, 5 March 2003 year.
REM     This program is free software; you can redistribute it and/or modify
REM it under the terms of the GNU General Public License as published by the
REM Free Software Foundation; either version 2 of the License, or (at your
REM option) any later version.
REM     This program is distributed in the hope that it will be useful, but
REM WITHOUT ANY WARRANTY; without even the implied warranty of
REM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
REM Public License for more details.
REM     You should have received a copy of the GNU General Public License
REM along with this program; if not, write to the Free Software Foundation,
REM Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
REM
REM $DYNAMIC
DECLARE SUB ScratchScreen ()
DECLARE SUB OutBox (Title$, Message$)
DECLARE SUB MakeBox (BoxColumn%, BoxRow%, BoxWidth%, BoxHeight%)
DECLARE SUB OutPhones ()
DECLARE FUNCTION CurrentDateTime$ ()
DECLARE FUNCTION DayName$ (DayNumber%)
DECLARE FUNCTION DayOfWeek% (DayValue%, MonthValue%, YearValue%)
DECLARE FUNCTION DayOfWeekName$ (DayValue%, MonthValue%, YearValue%)
DECLARE FUNCTION DaysCount& (DayValue%, MonthValue%, YearValue%)
DECLARE FUNCTION InputBox% (Title$, Message$, InputTextLine$)
DECLARE FUNCTION IsLeapYear% (YearValue%)
DECLARE FUNCTION MenuBox% (ItemsCount%)
DECLARE FUNCTION MessageBox% (Title$, Message$)
DECLARE FUNCTION MonthDays% (MonthValue%, YearValue%)
DECLARE FUNCTION MonthDaysCount% (MonthValue%, YearValue%)
DECLARE FUNCTION MonthName$ (MonthNumber%)
OPTION BASE 1
CONST False% = 0
CONST True% = NOT False%
CONST PhonesCount% = 256
DIM SHARED MenuItems$(7)
DIM SHARED Phones$(PhonesCount%)
DIM SHARED PhonePosition%
DIM SHARED PhoneLine%
DIM SHARED StatusText$
DIM WorkKey$
DIM OldSecond%
DIM WorkLine$
DIM PhoneBookName$
DIM Index%
DIM PrinterName$
DIM Work$
DIM LinesPerPage%
DIM WorkIndex%
PhoneBookName$ = "Phone.pbk"
PrinterName$ = "Prn"
LinesPerPage% = 55
PhonePosition% = 1
PhoneLine% = 1
OldSecond% = NOT VAL(MID$(TIME$, 7, 2))
StatusText$ = CurrentDateTime$ + " " + LTRIM$(STR$(PhonePosition%)) + "/" + PhoneBookName$ + " ESC=Menu"
SCREEN 0, 1, 0, 0
CALL ScratchScreen
CALL OutPhones
DO
 IF OldSecond% <> VAL(MID$(TIME$, 7, 2)) THEN
  OldSecond% = VAL(MID$(TIME$, 7, 2))
  StatusText$ = CurrentDateTime$ + " " + LTRIM$(STR$(PhonePosition%)) + "/" + PhoneBookName$ + " ESC=Menu"
  CALL OutPhones
 END IF
 WorkKey$ = INKEY$
 SELECT CASE LEN(WorkKey$)
 CASE 1
   SELECT CASE WorkKey$
   CASE CHR$(13)
     StatusText$ = "Change phone field."
     CALL ScratchScreen
     CALL OutPhones
     MenuItems$(1) = "Change name field."
     MenuItems$(2) = "Change phone field."
     MenuItems$(3) = "Change comment field."
     MenuItems$(4) = "Cancel."
     SELECT CASE MenuBox%(4)
     CASE 1
       WorkLine$ = LEFT$(Phones$(PhonePosition%), 30)
       IF InputBox%("Phone book.", "Please change name field and press ENTER to save it.", WorkLine$) THEN
        WorkLine$ = LEFT$(LTRIM$(RTRIM$(WorkLine$)), 30)
        Phones$(PhonePosition%) = WorkLine$ + SPACE$(30 - LEN(WorkLine$)) + MID$(Phones$(PhonePosition%), 31)
       END IF
     CASE 2
       WorkLine$ = MID$(Phones$(PhonePosition%), 31, 15)
       IF InputBox%("Phone book.", "Please change phone field and press ENTER to save it.", WorkLine$) THEN
        WorkLine$ = LEFT$(LTRIM$(RTRIM$(WorkLine$)), 15)
        Phones$(PhonePosition%) = LEFT$(Phones$(PhonePosition%), 30) + WorkLine$ + SPACE$(15 - LEN(WorkLine$)) + MID$(Phones$(PhonePosition%), 46)
       END IF
     CASE 3
       WorkLine$ = MID$(Phones$(PhonePosition%), 46, 32)
       IF InputBox%("Phone book.", "Please change comment field and press ENTER to save it.", WorkLine$) THEN
        WorkLine$ = LEFT$(LTRIM$(RTRIM$(WorkLine$)), 32)
        Phones$(PhonePosition%) = LEFT$(Phones$(PhonePosition%), 45) + WorkLine$ + SPACE$(32 - LEN(WorkLine$))
       END IF
     END SELECT
   CASE CHR$(27)
     StatusText$ = "Main menu."
     CALL ScratchScreen
     CALL OutPhones
     MenuItems$(1) = "Save phone book."
     MenuItems$(2) = "Save phone book as other name."
     MenuItems$(3) = "Open phone book."
     MenuItems$(4) = "Change printer name (" + PrinterName$ + ".)."
     MenuItems$(5) = "Change count of lines per page (" + LTRIM$(STR$(LinesPerPage%)) + ".)."
     MenuItems$(6) = "Print phones."
     MenuItems$(7) = "Quit."
     SELECT CASE MenuBox%(7)
     CASE 1
       StatusText$ = "Saving phone book. Please waith..."
       CALL ScratchScreen
       CALL OutPhones
       ON ERROR GOTO CannotOpenPhoneBookForSave
       OPEN PhoneBookName$ FOR OUTPUT AS #1
       ON ERROR GOTO 0
       FOR Index% = 1 TO PhonesCount%
        ON ERROR GOTO CannotWriteToPhoneBookForSave
        PRINT #1, Phones$(Index%)
        ON ERROR GOTO 0
       NEXT Index%
       CLOSE #1
     CASE 2
       StatusText$ = "Saving phone book. Please waith..."
       CALL ScratchScreen
       CALL OutPhones
       WorkLine$ = ""
       IF InputBox%("Phone book.", "Please enter file name for save current phone book in new file.", WorkLine$) THEN
        WorkLine$ = UCASE$(LEFT$(LTRIM$(RTRIM$(WorkLine$)), 1)) + LCASE$(MID$(LTRIM$(RTRIM$(WorkLine$)), 2))
        IF (WorkLine$ = "") OR (LEN(WorkLine$) > 12) OR (INSTR(WorkLine$, ":") > 0) OR (INSTR(WorkLine$, "/") > 0) OR (INSTR(WorkLine$, "\") > 0) OR (INSTR(WorkLine$, "?") > 0) OR (INSTR(WorkLine$, "*") > 0) THEN
         CALL ScratchScreen
         CALL OutPhones
         CALL OutBox("Phone book.", "You input the invalid file name.")
        ELSE
         CALL ScratchScreen
         CALL OutPhones
         ON ERROR GOTO CannotOpenPhoneBookForSave
         OPEN WorkLine$ FOR OUTPUT AS #1
         ON ERROR GOTO 0
         FOR Index% = 1 TO PhonesCount%
          ON ERROR GOTO CannotWriteToPhoneBookForSave
          PRINT #1, Phones$(Index%)
          ON ERROR GOTO 0
         NEXT Index%
         CLOSE #1
         PhoneBookName$ = WorkLine$
        END IF
       END IF
     CASE 3
       StatusText$ = "Loading phone book. Please waith..."
       CALL ScratchScreen
       CALL OutPhones
       WorkLine$ = ""
       IF InputBox%("Phone book.", "Please enter file name for load phone book from it.", WorkLine$) THEN
        CALL ScratchScreen
        CALL OutPhones
        WorkLine$ = UCASE$(LEFT$(LTRIM$(RTRIM$(WorkLine$)), 1)) + LCASE$(MID$(LTRIM$(RTRIM$(WorkLine$)), 2))
        IF (WorkLine$ = "") OR (LEN(WorkLine$) > 12) OR (INSTR(WorkLine$, ":") > 0) OR (INSTR(WorkLine$, "/") > 0) OR (INSTR(WorkLine$, "\") > 0) OR (INSTR(WorkLine$, "?") > 0) OR (INSTR(WorkLine$, "*") > 0) THEN
         CALL ScratchScreen
         CALL OutPhones
         CALL OutBox("Phone book.", "You input the invalid file name.")
        ELSE
         IF MessageBox%("Phone book.", "Save current phone book before load new?") THEN
          StatusText$ = "Saving phone book. Please waith..."
          CALL ScratchScreen
          CALL OutPhones
          WorkLine$ = ""
          ON ERROR GOTO CannotOpenPhoneBookForSave
          OPEN WorkLine$ FOR OUTPUT AS #1
          ON ERROR GOTO 0
          FOR Index% = 1 TO PhonesCount%
           ON ERROR GOTO CannotWriteToPhoneBookForSave
           PRINT #1, Phones$(Index%)
           ON ERROR GOTO 0
          NEXT Index%
          CLOSE #1
         END IF
         StatusText$ = "Loading phone book. Please waith..."
         CALL ScratchScreen
         CALL OutPhones
         ON ERROR GOTO CannotOpenPhoneBookForLoad
         OPEN WorkLine$ FOR INPUT AS #1
         ON ERROR GOTO 0
         FOR Index% = 1 TO PhonesCount%
          Phones$(Index%) = ""
         NEXT Index%
         Index% = 1
         DO WHILE NOT EOF(1)
          ON ERROR GOTO CannotReadFromPhoneBookForLoad
          LINE INPUT #1, Work$
          ON ERROR GOTO 0
          Work$ = LEFT$(RTRIM$(Work$), 77)
          FOR WorkIndex% = 0 TO 31
           WHILE INSTR(Work$, CHR$(WorkIndex%)) > 0
            Work$ = MID$(Work$, 1, INSTR(Work$, CHR$(WorkIndex%)) - 1) + SPACE$(1) + MID$(Work$, INSTR(Work$, CHR$(WorkIndex%)) + 1)
           WEND
          NEXT WorkIndex%
          Phones$(Index%) = Work$ + SPACE$(77 - LEN(Work$))
          Index% = Index% + 1
          IF Index% = PhonesCount% + 1 THEN EXIT DO
         LOOP
         CLOSE #1
         PhonePosition% = 1
         PhoneLine% = 1
         PhoneBookName$ = WorkLine$
        END IF
       END IF
     CASE 4
       StatusText$ = "Change printer name."
       CALL ScratchScreen
       CALL OutPhones
       WorkLine$ = ""
       IF InputBox%("Phone book.", "Please enter new printer name.", WorkLine$) THEN
        WorkLine$ = UCASE$(LEFT$(LTRIM$(RTRIM$(WorkLine$)), 1)) + LCASE$(MID$(LTRIM$(RTRIM$(WorkLine$)), 2))
        IF (WorkLine$ = "") OR (LEN(WorkLine$) > 12) OR (INSTR(WorkLine$, ":") > 0) OR (INSTR(WorkLine$, "/") > 0) OR (INSTR(WorkLine$, "\") > 0) OR (INSTR(WorkLine$, "?") > 0) OR (INSTR(WorkLine$, "*") > 0) THEN
         CALL ScratchScreen
         CALL OutPhones
         CALL OutBox("Phone book.", "You input the invalid file name.")
        ELSE
         PrinterName$ = WorkLine$
        END IF
       END IF
     CASE 5
       StatusText$ = "Change count of lines per page."
       CALL ScratchScreen
       CALL OutPhones
       WorkLine$ = ""
       IF InputBox%("Phone book.", "Please enter new value for count of lines per page.", WorkLine$) THEN
        WorkLine$ = LTRIM$(RTRIM$(WorkLine$))
        IF (VAL(WorkLine$) < 1) OR (VAL(WorkLine$) > 256) THEN
         CALL ScratchScreen
         CALL OutPhones
         CALL OutBox("Phone book.", "Count of lines per page must be in range: 1 - 256.")
        ELSE
         LinesPerPage% = VAL(WorkLine$)
        END IF
       END IF
     CASE 6
       StatusText$ = "Printing phone book. Please waith..."
       CALL ScratchScreen
       CALL OutPhones
       FOR Index% = PhonesCount% TO 0 STEP -1
        IF Index% = 0 THEN EXIT FOR
        IF Phones$(Index%) <> "" THEN EXIT FOR
       NEXT Index%
       IF Index% <> 0 THEN
        ON ERROR GOTO CannotOpenPrinter
        OPEN PrinterName$ FOR OUTPUT AS #1
        ON ERROR GOTO 0
        WorkIndex% = 0
        FOR Index% = 1 TO Index%
         ON ERROR GOTO CannotWriteToPrinter
         PRINT #1, Phones$(Index%)
         ON ERROR GOTO 0
         WorkIndex% = WorkIndex% + 1
         IF WorkIndex% = LinesPerPage% THEN
          ON ERROR GOTO CannotWriteToPrinter
          PRINT #1, CHR$(12)
          ON ERROR GOTO 0
          CALL OutBox("Phone book.", "Please insert new paper on printer and press ENTER.")
          CALL ScratchScreen
          CALL OutPhones
          WorkIndex% = 0
         END IF
        NEXT Index%
        ON ERROR GOTO CannotWriteToPrinter
        PRINT #1, CHR$(26);
        ON ERROR GOTO 0
        CLOSE #1
       END IF
     CASE 7
       StatusText$ = "Quit."
       CALL ScratchScreen
       CALL OutPhones
       IF MessageBox%("Phone book.", "Save phone book before quit?") THEN
        StatusText$ = "Saving phone book. Please waith..."
        CALL ScratchScreen
        CALL OutPhones
        ON ERROR GOTO CannotOpenPhoneBookForSave
        OPEN PhoneBookName$ FOR OUTPUT AS #1
        ON ERROR GOTO 0
        FOR Index% = 1 TO PhonesCount%
         ON ERROR GOTO CannotWriteToPhoneBookForSave
         PRINT #1, Phones$(Index%)
         ON ERROR GOTO 0
        NEXT Index%
        CLOSE #1
       END IF
       EXIT DO
     END SELECT
   END SELECT
   StatusText$ = CurrentDateTime$ + " " + LTRIM$(STR$(PhonePosition%)) + "/" + PhoneBookName$ + " ESC=Menu"
   CALL ScratchScreen
   CALL OutPhones
 CASE 2
   WorkKey$ = MID$(WorkKey$, 2)
   SELECT CASE WorkKey$
   CASE CHR$(72)
     IF PhonePosition% > 1 THEN
      PhonePosition% = PhonePosition% - 1
      PhoneLine% = PhoneLine% - 1
      IF PhonePosition% < 1 THEN PhonePosition% = 1
      IF PhoneLine% < 1 THEN PhoneLine% = 1
      StatusText$ = CurrentDateTime$ + " " + LTRIM$(STR$(PhonePosition%)) + "/" + PhoneBookName$ + " ESC=Menu"
      CALL OutPhones
     END IF
   CASE CHR$(80)
     IF PhonePosition% < PhonesCount% THEN
      PhonePosition% = PhonePosition% + 1
      PhoneLine% = PhoneLine% + 1
      IF PhonePosition% > PhonesCount% THEN PhonePosition% = PhonesCount%
      IF PhoneLine% > 20 THEN PhoneLine% = 20
      StatusText$ = CurrentDateTime$ + " " + LTRIM$(STR$(PhonePosition%)) + "/" + PhoneBookName$ + " ESC=Menu"
      CALL OutPhones
     END IF
   CASE CHR$(73)
     IF PhonePosition% > 1 THEN
      PhonePosition% = PhonePosition% - 20
      PhoneLine% = PhoneLine% - 20
      IF PhonePosition% < 1 THEN PhonePosition% = 1
      IF PhoneLine% < 1 THEN PhoneLine% = 1
      StatusText$ = CurrentDateTime$ + " " + LTRIM$(STR$(PhonePosition%)) + "/" + PhoneBookName$ + " ESC=Menu"
      CALL OutPhones
     END IF
   CASE CHR$(81)
     IF PhonePosition% < PhonesCount% THEN
      PhonePosition% = PhonePosition% + 20
      PhoneLine% = PhoneLine% + 20
      IF PhonePosition% > PhonesCount% THEN PhonePosition% = PhonesCount%
      IF PhoneLine% > 20 THEN PhoneLine% = 20
      StatusText$ = CurrentDateTime$ + " " + LTRIM$(STR$(PhonePosition%)) + "/" + PhoneBookName$ + " ESC=Menu"
      CALL OutPhones
     END IF
   CASE CHR$(71)
     IF PhonePosition% <> 1 THEN
      PhonePosition% = 1
      PhoneLine% = 1
      StatusText$ = CurrentDateTime$ + " " + LTRIM$(STR$(PhonePosition%)) + "/" + PhoneBookName$ + " ESC=Menu"
      CALL OutPhones
     END IF
   CASE CHR$(79)
     IF PhonePosition% <> PhonesCount% THEN
      PhonePosition% = PhonesCount%
      PhoneLine% = 20
      StatusText$ = CurrentDateTime$ + " " + LTRIM$(STR$(PhonePosition%)) + "/" + PhoneBookName$ + " ESC=Menu"
      CALL OutPhones
     END IF
   END SELECT
 END SELECT
PhoneBookWork:
LOOP
COLOR 7, 0
CLS
LOCATE 1, 1, 1, 7, 8
END
CannotOpenPhoneBookForSave:
 IF MessageBox%("Phone book.", "Cannot open file for save it. Retry opening?") THEN
  CALL ScratchScreen
  CALL OutPhones
  RESUME
 ELSE
  StatusText$ = CurrentDateTime$ + " " + LTRIM$(STR$(PhonePosition%)) + "/" + PhoneBookName$ + " ESC=Menu"
  CALL ScratchScreen
  CALL OutPhones
  RESUME PhoneBookWork
 END IF
CannotWriteToPhoneBookForSave:
 IF MessageBox%("Phone book.", "Cannot write to file for save. Retry writing?") THEN
  CALL ScratchScreen
  CALL OutPhones
  RESUME
 ELSE
  CLOSE #1
  StatusText$ = CurrentDateTime$ + " " + LTRIM$(STR$(PhonePosition%)) + "/" + PhoneBookName$ + " ESC=Menu"
  CALL ScratchScreen
  CALL OutPhones
  RESUME PhoneBookWork
 END IF
CannotOpenPhoneBookForLoad:
 IF MessageBox%("Phone book.", "Cannot open file for load it. Retry opening?") THEN
  CALL ScratchScreen
  CALL OutPhones
  RESUME
 ELSE
  StatusText$ = CurrentDateTime$ + " " + LTRIM$(STR$(PhonePosition%)) + "/" + PhoneBookName$ + " ESC=Menu"
  CALL ScratchScreen
  CALL OutPhones
  RESUME PhoneBookWork
 END IF
CannotReadFromPhoneBookForLoad:
 IF MessageBox%("Phone book.", "Cannot read from file. Retry reading?") THEN
  CALL ScratchScreen
  CALL OutPhones
  RESUME
 ELSE
  CLOSE #1
  StatusText$ = CurrentDateTime$ + " " + LTRIM$(STR$(PhonePosition%)) + "/" + PhoneBookName$ + " ESC=Menu"
  CALL ScratchScreen
  CALL OutPhones
  RESUME PhoneBookWork
 END IF
CannotOpenPrinter:
 IF MessageBox%("Phone book.", "Cannot open printer. Retry opening?") THEN
  CALL ScratchScreen
  CALL OutPhones
  RESUME
 ELSE
  StatusText$ = CurrentDateTime$ + " " + LTRIM$(STR$(PhonePosition%)) + "/" + PhoneBookName$ + " ESC=Menu"
  CALL ScratchScreen
  CALL OutPhones
  RESUME PhoneBookWork
 END IF
CannotWriteToPrinter:
 IF MessageBox%("Phone book.", "Cannot write to printer. Retry writing?") THEN
  CALL ScratchScreen
  CALL OutPhones
  RESUME
 ELSE
  CLOSE #1
  StatusText$ = CurrentDateTime$ + " " + LTRIM$(STR$(PhonePosition%)) + "/" + PhoneBookName$ + " ESC=Menu"
  CALL ScratchScreen
  CALL OutPhones
  RESUME PhoneBookWork
 END IF

FUNCTION CurrentDateTime$
 CurrentDateTime$ = "Date: " + DayOfWeekName$(VAL(MID$(DATE$, 4, 2)), VAL(MID$(DATE$, 1, 2)), VAL(MID$(DATE$, 7, 4))) + ", " + LTRIM$(STR$(VAL(MID$(DATE$, 4, 2)))) + " " + MonthName$(VAL(MID$(DATE$, 1, 2))) + " " + LTRIM$(STR$(VAL(MID$(DATE$, 7, 4)))) + " year. Time: " + TIME$ + "."
END FUNCTION

FUNCTION DayName$ (DayNumber%)
 SELECT CASE DayNumber%
 CASE 1
   DayName$ = "Monday"
 CASE 2
   DayName$ = "Tuesday"
 CASE 3
   DayName$ = "Wednesday"
 CASE 4
   DayName$ = "Thursday"
 CASE 5
   DayName$ = "Friday"
 CASE 6
   DayName$ = "Saturday"
 CASE 7
   DayName$ = "Sunday"
 END SELECT
END FUNCTION

FUNCTION DayOfWeek% (DayValue%, MonthValue%, YearValue%)
 SELECT CASE DaysCount&(DayValue%, MonthValue%, YearValue%) - (INT(DaysCount&(DayValue%, MonthValue%, YearValue%) / 7) * 7)
 CASE 0
   DayOfWeek% = 6
 CASE 1
   DayOfWeek% = 7
 CASE 2
   DayOfWeek% = 1
 CASE 3
   DayOfWeek% = 2
 CASE 4
   DayOfWeek% = 3
 CASE 5
   DayOfWeek% = 4
 CASE 6
   DayOfWeek% = 5
 CASE 7
   DayOfWeek% = 6
 END SELECT
END FUNCTION

FUNCTION DayOfWeekName$ (DayValue%, MonthValue%, YearValue%)
 DayOfWeekName$ = DayName$(DayOfWeek%(DayValue%, MonthValue%, YearValue%))
END FUNCTION

FUNCTION DaysCount& (DayValue%, MonthValue%, YearValue%)
 DaysCount& = (YearValue% * 365#) + INT(YearValue% / 100) + INT(YearValue% / 4) + MonthDaysCount%(MonthValue%, YearValue%) + DayValue%
END FUNCTION

FUNCTION InputBox% (Title$, Message$, InputTextLine$)
 DIM OutMessage$
 DIM OutIndex%
 DIM WorkKey$
 DIM InputTextCursorColumn%
 DIM InputTextCursorPosition%
 DIM InputText$
 IF LEN(Message$) < 256 THEN OutMessage$ = Message$ + SPACE$(256 - LEN(Message$)) ELSE OutMessage$ = LEFT$(Message$, 256)
 CALL MakeBox(7, 8, 64, 7)
 PRINT LEFT$(Title$, 64) + SPACE$(64 - LEN(LEFT$(Title$, 64)));
 COLOR 1, 7
 FOR OutIndex% = 1 TO 4
  LOCATE 9 + OutIndex%, 8, 0
  PRINT LEFT$(OutMessage$, 64);
  OutMessage$ = MID$(OutMessage$, 65)
 NEXT OutIndex%
 COLOR 14, 7
 LOCATE 15, 8, 0
 PRINT "Please press key is equalient to your answer: ENTER=Yes, ESC=No.";
 InputTextCursorColumn% = 1
 InputTextCursorPosition% = 1
 InputText$ = InputTextLine$
 GOSUB OutInputLine
 DO
  WorkKey$ = INKEY$
  SELECT CASE LEN(WorkKey$)
  CASE 1
    SELECT CASE WorkKey$
    CASE CHR$(8)
      IF InputTextCursorColumn% > 1 THEN
       InputTextCursorColumn% = InputTextCursorColumn% - 1
       InputTextCursorPosition% = InputTextCursorPosition% - 1
       IF InputTextCursorColumn% < 1 THEN InputTextCursorColumn% = 1
       IF InputTextCursorPosition% < 1 THEN InputTextCursorPosition% = 1
       InputText$ = MID$(InputText$, 1, InputTextCursorColumn% - 1) + MID$(InputText$, InputTextCursorColumn% + 1)
       GOSUB OutInputLine
      END IF
    CASE CHR$(13)
      InputTextLine$ = InputText$
      EXIT DO
    CASE CHR$(27)
      EXIT DO
    CASE ELSE
      IF (LEN(InputText$) < 256) AND (ASC(WorkKey$) > (ASC(SPACE$(1)) - 1)) THEN
       InputText$ = MID$(InputText$, 1, InputTextCursorColumn% - 1) + WorkKey$ + MID$(InputText$, InputTextCursorColumn%)
       InputTextCursorColumn% = InputTextCursorColumn% + 1
       InputTextCursorPosition% = InputTextCursorPosition% + 1
       IF InputTextCursorColumn% > LEN(InputText$) + 1 THEN InputTextCursorColumn% = LEN(InputText$) + 1
       IF LEN(InputText$) > 63 THEN IF InputTextCursorPosition% > 64 THEN InputTextCursorPosition% = 64
       IF LEN(InputText$) < 65 THEN IF InputTextCursorPosition% > LEN(InputText$) + 1 THEN InputTextCursorPosition% = LEN(InputText$) + 1
       GOSUB OutInputLine
      END IF
    END SELECT
  CASE 2
    WorkKey$ = MID$(WorkKey$, 2)
    SELECT CASE WorkKey$
    CASE CHR$(75)
      IF InputTextCursorColumn% > 1 THEN
       InputTextCursorColumn% = InputTextCursorColumn% - 1
       InputTextCursorPosition% = InputTextCursorPosition% - 1
       IF InputTextCursorColumn% < 1 THEN InputTextCursorColumn% = 1
       IF InputTextCursorPosition% < 1 THEN InputTextCursorPosition% = 1
       GOSUB OutInputLine
      END IF
    CASE CHR$(77)
      IF InputTextCursorColumn% < LEN(InputText$) + 1 THEN
       InputTextCursorColumn% = InputTextCursorColumn% + 1
       InputTextCursorPosition% = InputTextCursorPosition% + 1
       IF InputTextCursorColumn% > LEN(InputText$) + 1 THEN InputTextCursorColumn% = LEN(InputText$) + 1
       IF LEN(InputText$) > 63 THEN IF InputTextCursorPosition% > 64 THEN InputTextCursorPosition% = 64
       IF LEN(InputText$) < 65 THEN IF InputTextCursorPosition% > LEN(InputText$) + 1 THEN InputTextCursorPosition% = LEN(InputText$) + 1
       GOSUB OutInputLine
      END IF
    CASE CHR$(71)
      IF InputTextCursorColumn% <> 1 THEN
       InputTextCursorColumn% = 1
       InputTextCursorPosition% = 1
       GOSUB OutInputLine
      END IF
    CASE CHR$(79)
      IF InputTextCursorColumn% <> LEN(InputText$) + 1 THEN
       InputTextCursorColumn% = LEN(InputText$) + 1
       InputTextCursorPosition% = LEN(InputText$) + 1
       IF LEN(InputText$) > 63 THEN IF InputTextCursorPosition% > 64 THEN InputTextCursorPosition% = 64
       IF LEN(InputText$) < 65 THEN IF InputTextCursorPosition% > LEN(InputText$) + 1 THEN InputTextCursorPosition% = LEN(InputText$) + 1
       GOSUB OutInputLine
      END IF
    CASE CHR$(83)
      IF InputText$ <> "" THEN
       InputText$ = MID$(InputText$, 1, InputTextCursorColumn% - 1) + MID$(InputText$, InputTextCursorColumn% + 1)
       GOSUB OutInputLine
      END IF
    END SELECT
  END SELECT
 LOOP
 LOCATE , , 0
 InputBox% = WorkKey$ = CHR$(13)
 EXIT FUNCTION
OutInputLine:
 COLOR 4, 7
 LOCATE 14, 8, 0
 PRINT MID$(InputText$, (InputTextCursorColumn% - InputTextCursorPosition%) + 1, 64) + SPACE$(64 - LEN(MID$(InputText$, (InputTextCursorColumn% - InputTextCursorPosition%) + 1, 64)));
 LOCATE 14, 7 + InputTextCursorPosition%, 1, 7, 8
 RETURN
END FUNCTION

FUNCTION IsLeapYear% (YearValue%)
 IsLeapYear% = ABS((INT(YearValue% / 4) * 4) = YearValue%)
END FUNCTION

SUB MakeBox (BoxColumn%, BoxRow%, BoxWidth%, BoxHeight%)
 DIM BoxWorkIndex%
 IF (BoxColumn% < 1) OR (BoxRow% < 1) OR (BoxWidth% < 1) OR (BoxHeight% < 1) OR (BoxWidth% > 77) OR (BoxHeight% > 22) OR (((BoxColumn% - 1) + BoxWidth%) > 77) OR (((BoxRow% - 1) + BoxHeight%) > 22) THEN EXIT SUB
 COLOR 0, 7
 LOCATE BoxRow%, BoxColumn%, 0
 PRINT CHR$(201) + STRING$(BoxWidth%, CHR$(205)) + CHR$(187);
 FOR BoxWorkIndex% = 1 TO BoxHeight% + 1
  LOCATE BoxRow% + BoxWorkIndex%, BoxColumn%, 0
  PRINT CHR$(186) + SPACE$(BoxWidth%) + CHR$(186);
  COLOR 0, 0
  PRINT SPACE$(1);
  COLOR 0, 7
 NEXT BoxWorkIndex%
 LOCATE BoxRow% + BoxHeight% + 1, BoxColumn%, 0
 PRINT CHR$(200) + STRING$(BoxWidth%, CHR$(205)) + CHR$(188);
 COLOR 0, 0
 LOCATE BoxRow% + BoxHeight% + 2, BoxColumn% + 1, 0
 PRINT SPACE$(BoxWidth% + 2);
 COLOR 15, 2
 LOCATE BoxRow% + 1, BoxColumn% + 1, 0
END SUB

FUNCTION MenuBox% (ItemsCount%)
 DIM MenuIndex%
 DIM MenuLineLength%
 DIM CurrentItem%
 DIM WorkKey$
 IF (ItemsCount% < 1) OR (ItemsCount% > UBOUND(MenuItems$)) OR (UBOUND(MenuItems$) > 20) THEN
  MenuBox% = 0
  EXIT FUNCTION
 END IF
 MenuLineLength% = 0
 FOR MenuIndex% = 1 TO ItemsCount%
  IF LEN(MenuItems$(MenuIndex%)) > MenuLineLength% THEN MenuLineLength% = LEN(MenuItems$(MenuIndex%))
 NEXT MenuIndex%
 IF MenuLineLength% < 56 THEN MenuLineLength% = 56
 IF MenuLineLength% > 75 THEN MenuLineLength% = 75
 CurrentItem% = 1
 GOSUB OutMenu
 DO
  WorkKey$ = UCASE$(INKEY$)
  SELECT CASE LEN(WorkKey$)
  CASE 1
    SELECT CASE WorkKey$
    CASE CHR$(13)
      MenuBox% = CurrentItem%
      EXIT DO
    CASE CHR$(27)
      MenuBox% = 0
      EXIT DO
    CASE ELSE
      IF (ASC(WorkKey$) > (ASC("A") - 1)) AND (ASC(WorkKey$) < (ASC("A") + ItemsCount%)) THEN
       CurrentItem% = (ASC(WorkKey$) - ASC("A")) + 1
       GOSUB OutMenu
      END IF
    END SELECT
  CASE 2
    WorkKey$ = MID$(WorkKey$, 2)
    SELECT CASE WorkKey$
    CASE CHR$(72)
      IF CurrentItem% > 1 THEN
       CurrentItem% = CurrentItem% - 1
       GOSUB OutMenu
      END IF
    CASE CHR$(80)
      IF CurrentItem% < ItemsCount% THEN
       CurrentItem% = CurrentItem% + 1
       GOSUB OutMenu
      END IF
    CASE CHR$(73)
      IF CurrentItem% <> 1 THEN
       CurrentItem% = 1
       GOSUB OutMenu
      END IF
    CASE CHR$(81)
      IF CurrentItem% <> ItemsCount% THEN
       CurrentItem% = ItemsCount%
       GOSUB OutMenu
      END IF
    CASE CHR$(71)
      IF CurrentItem% <> 1 THEN
       CurrentItem% = 1
       GOSUB OutMenu
      END IF
    CASE CHR$(79)
      IF CurrentItem% <> ItemsCount% THEN
       CurrentItem% = ItemsCount%
       GOSUB OutMenu
      END IF
    END SELECT
  END SELECT
 LOOP
 EXIT FUNCTION
OutMenu:
 CALL MakeBox(INT((80 - (MenuLineLength% + 5)) / 2) + 1, INT((25 - (ItemsCount% + 5)) / 2) + 1, MenuLineLength% + 2, ItemsCount% + 2)
 FOR MenuIndex% = 1 TO ItemsCount%
  COLOR 14, 7
  LOCATE INT((25 - (ItemsCount% + 5)) / 2) + (MenuIndex% + 1), INT((80 - (MenuLineLength% + 5)) / 2) + 2, 0
  PRINT CHR$(ASC("A") + (MenuIndex% - 1));
  COLOR 12, 7
  PRINT "=";
  IF MenuIndex% = CurrentItem% THEN COLOR 15, 6 ELSE COLOR 8, 7
  PRINT LEFT$(MenuItems$(MenuIndex%), MenuLineLength%) + SPACE$(MenuLineLength% - LEN(LEFT$(MenuItems$(MenuIndex%), MenuLineLength%)));
 NEXT MenuIndex%
 COLOR 0, 7
 LOCATE INT((25 - (ItemsCount% + 5)) / 2) + 2 + ItemsCount%, INT((80 - (MenuLineLength% + 5)) / 2) + 1, 0
 PRINT CHR$(204) + STRING$(MenuLineLength% + 2, CHR$(205)) + CHR$(185);
 COLOR 14, 7
 LOCATE INT((25 - (ItemsCount% + 5)) / 2) + 3 + ItemsCount%, INT((80 - (MenuLineLength% + 5)) / 2) + 2, 0
 PRINT SPACE$(INT((MenuLineLength% - 56) / 2) + 1) + "Please press ENTER to select menu item or ESC to cancel."
 RETURN
END FUNCTION

FUNCTION MessageBox% (Title$, Message$)
 DIM OutMessage$
 DIM OutIndex%
 DIM WorkKey$
 IF LEN(Message$) < 256 THEN OutMessage$ = Message$ + SPACE$(256 - LEN(Message$)) ELSE OutMessage$ = LEFT$(Message$, 256)
 CALL MakeBox(7, 9, 64, 6)
 PRINT LEFT$(Title$, 64) + SPACE$(64 - LEN(LEFT$(Title$, 64)));
 COLOR 1, 7
 FOR OutIndex% = 1 TO 4
  LOCATE 10 + OutIndex%, 8, 0
  PRINT LEFT$(OutMessage$, 64);
  OutMessage$ = MID$(OutMessage$, 65)
 NEXT OutIndex%
 COLOR 14, 7
 LOCATE 15, 8, 0
 PRINT "Please press key is equalient to your answer: ENTER=Yes, ESC=No.";
 WorkKey$ = ""
 WHILE (WorkKey$ <> CHR$(13)) AND (WorkKey$ <> CHR$(27))
  WorkKey$ = INKEY$
 WEND
 MessageBox% = WorkKey$ = CHR$(13)
END FUNCTION

FUNCTION MonthDays% (MonthValue%, YearValue%)
 SELECT CASE MonthValue%
 CASE 1
   MonthDays% = 31
 CASE 2
   MonthDays% = 28 + IsLeapYear%(YearValue%)
 CASE 3
   MonthDays% = 31
 CASE 4
   MonthDays% = 30
 CASE 5
   MonthDays% = 31
 CASE 6
   MonthDays% = 30
 CASE 7
   MonthDays% = 31
 CASE 8
   MonthDays% = 31
 CASE 9
   MonthDays% = 30
 CASE 10
   MonthDays% = 31
 CASE 11
   MonthDays% = 30
 CASE 12
   MonthDays% = 31
 END SELECT
END FUNCTION

FUNCTION MonthDaysCount% (MonthValue%, YearValue%)
 SELECT CASE MonthValue%
 CASE 1
   MonthDaysCount% = 0
 CASE 2
   MonthDaysCount% = 31
 CASE 3
   MonthDaysCount% = 59 + IsLeapYear%(YearValue%)
 CASE 4
   MonthDaysCount% = 90 + IsLeapYear%(YearValue%)
 CASE 5
   MonthDaysCount% = 120 + IsLeapYear%(YearValue%)
 CASE 6
   MonthDaysCount% = 151 + IsLeapYear%(YearValue%)
 CASE 7
   MonthDaysCount% = 181 + IsLeapYear%(YearValue%)
 CASE 8
   MonthDaysCount% = 212 + IsLeapYear%(YearValue%)
 CASE 9
   MonthDaysCount% = 243 + IsLeapYear%(YearValue%)
 CASE 10
   MonthDaysCount% = 273 + IsLeapYear%(YearValue%)
 CASE 11
   MonthDaysCount% = 304 + IsLeapYear%(YearValue%)
 CASE 12
   MonthDaysCount% = 334 + IsLeapYear%(YearValue%)
 END SELECT
END FUNCTION

FUNCTION MonthName$ (MonthNumber%)
 SELECT CASE MonthNumber%
 CASE 1
   MonthName$ = "January"
 CASE 2
   MonthName$ = "February"
 CASE 3
   MonthName$ = "March"
 CASE 4
   MonthName$ = "April"
 CASE 5
   MonthName$ = "May"
 CASE 6
   MonthName$ = "June"
 CASE 7
   MonthName$ = "July"
 CASE 8
   MonthName$ = "August"
 CASE 9
   MonthName$ = "September"
 CASE 10
   MonthName$ = "October"
 CASE 11
   MonthName$ = "November"
 CASE 12
   MonthName$ = "December"
 END SELECT
END FUNCTION

SUB OutBox (Title$, Message$)
 DIM OutMessage$
 DIM OutIndex%
 IF LEN(Message$) < 256 THEN OutMessage$ = Message$ + SPACE$(256 - LEN(Message$)) ELSE OutMessage$ = LEFT$(Message$, 256)
 CALL MakeBox(7, 9, 64, 6)
 PRINT LEFT$(Title$, 64) + SPACE$(64 - LEN(LEFT$(Title$, 64)));
 COLOR 1, 7
 FOR OutIndex% = 1 TO 4
  LOCATE 10 + OutIndex%, 8, 0
  PRINT LEFT$(OutMessage$, 64);
  OutMessage$ = MID$(OutMessage$, 65)
 NEXT OutIndex%
 COLOR 14, 7
 LOCATE 15, 8, 0
 PRINT "       Please press the ENTER key to quit from this box.";
 WHILE INKEY$ <> CHR$(13)
 WEND
END SUB

SUB OutPhones
 DIM Index%
 CALL MakeBox(1, 1, 77, 22)
 COLOR 2, 7
 LOCATE 2, 2, 0
 PRINT "Name.                         Phone.         Comment.";
 FOR Index% = 1 TO 20
  IF Index% + (PhonePosition% - PhoneLine%) = PhonePosition% THEN COLOR 14, 1 ELSE COLOR 1, 7
  LOCATE 2 + Index%, 2, 0
  PRINT Phones$(Index% + (PhonePosition% - PhoneLine%)) + SPACE$(77 - LEN(Phones$(Index% + (PhonePosition% - PhoneLine%))));
 NEXT Index%
 COLOR 4, 7
 LOCATE 23, 2, 0
 PRINT StatusText$;
END SUB

SUB ScratchScreen
 COLOR 0, 2
 CLS
 PRINT "********************************************************************************"
 PRINT "                      The Standart GNU Personal Phone Book."
 PRINT "                     Copyright (C) Sandul Yura Valentinovich."
 PRINT "                        (R) Wednesday, 5 March 2003 year."
 PRINT
 PRINT "    This program is free software; you can redistribute it and/or modify it"
 PRINT "under the terms of the GNU General Public License as published by the Free"
 PRINT "Software Foundation; either version 2 of the License, or (at your option) any"
 PRINT "later version."
 PRINT "    This program is distributed in the hope that it will be useful, but WITHOUT"
 PRINT "ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS"
 PRINT "FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details."
 PRINT "    You should have received a copy of the GNU General Public License along with"
 PRINT "this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave,"
 PRINT "Cambridge, MA 02139, USA."
END SUB

