REM     The Standart GNU Personal Text Editor.
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 OutText ()
DECLARE SUB DeleteBackSymbol ()
DECLARE SUB EnterLine ()
DECLARE SUB ControlCoordinates ()
DECLARE SUB CursorRight ()
DECLARE SUB CursorUp ()
DECLARE SUB CursorDown ()
DECLARE SUB PageUp ()
DECLARE SUB PageDown ()
DECLARE SUB CursorHome ()
DECLARE SUB CursorEnd ()
DECLARE SUB CursorLeft ()
DECLARE SUB DeleteSymbol ()
DECLARE FUNCTION CalendarBox% (Title$, Message$, DayValue%, MonthValue%, YearValue%)
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 TextLines% = 100
DIM SHARED MenuItems$(13)
DIM SHARED Text$(TextLines%)
DIM SHARED TextColumn%
DIM SHARED TextRow%
DIM SHARED TextPosition%
DIM SHARED LinePosition%
DIM SHARED TextName$
DIM SHARED StatusText$
DIM Index%
DIM PrinterName$
DIM LinesPerPage%
DIM WorkIndex%
DIM WorkKey$
DIM OldSecond%
DIM WorkLine$
DIM Work$
DIM WorkYear%
DIM WorkMonth%
DIM WorkDay%
DIM OutIndex%
DIM Value%
DIM Days%(37)
TextName$ = "Text.txt"
PrinterName$ = "Prn"
LinesPerPage% = 55
TextColumn% = 1
TextRow% = 1
TextPosition% = 1
LinePosition% = 1
OldSecond% = NOT VAL(MID$(TIME$, 7, 2))
StatusText$ = CurrentDateTime$
SCREEN 0, 1, 0, 0
CALL ScratchScreen
CALL OutText
DO
 WorkKey$ = ""
 WHILE WorkKey$ = ""
  IF OldSecond% <> VAL(MID$(TIME$, 7, 2)) THEN
   OldSecond% = VAL(MID$(TIME$, 7, 2))
   StatusText$ = CurrentDateTime$
   CALL OutText
  END IF
  WorkKey$ = INKEY$
 WEND
 SELECT CASE LEN(WorkKey$)
 CASE 1
   SELECT CASE WorkKey$
   CASE CHR$(8)
     CALL DeleteBackSymbol
   CASE CHR$(13)
     CALL EnterLine
   CASE CHR$(27)
     StatusText$ = "Main menu."
     CALL OutText
     MenuItems$(1) = "Save text."
     MenuItems$(2) = "Save text with other name."
     MenuItems$(3) = "Load text."
     MenuItems$(4) = "Merge in text."
     MenuItems$(5) = "Change printer name (" + PrinterName$ + ".)."
     MenuItems$(6) = "Change count of lines per page (" + LTRIM$(STR$(LinesPerPage%)) + ".)."
     MenuItems$(7) = "Print text."
     MenuItems$(8) = "Find line."
     MenuItems$(9) = "Replace line."
     MenuItems$(10) = "Replace all occurences."
     MenuItems$(11) = "Insert calendar."
     MenuItems$(12) = "Insert current date and time."
     MenuItems$(13) = "Quit."
     SELECT CASE MenuBox%(13)
     CASE 1
       StatusText$ = "Save text."
       CALL ScratchScreen
       CALL OutText
       ON ERROR GOTO CannotOpenFileForSave
       OPEN TextName$ FOR OUTPUT AS #1
       ON ERROR GOTO 0
       FOR Index% = TextLines% TO 1 STEP -1
        IF Text$(Index%) <> "" THEN EXIT FOR
       NEXT Index%
       FOR Index% = 1 TO Index%
        ON ERROR GOTO CannotWriteToFileForSave
        PRINT #1, Text$(Index%)
        ON ERROR GOTO 0
       NEXT Index%
       CLOSE #1
     CASE 2
       StatusText$ = "Save text as other name."
       CALL ScratchScreen
       CALL OutText
       WorkLine$ = ""
       IF InputBox%("Text editor.", "Please enter new file name.", WorkLine$) THEN
        CALL ScratchScreen
        CALL OutText
        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 OutBox("Text editor.", "You input the invalid file name.")
        ELSE
         ON ERROR GOTO CannotOpenFileForSaveAs
         OPEN WorkLine$ FOR OUTPUT AS #1
         ON ERROR GOTO 0
         FOR Index% = TextLines% TO 1 STEP -1
          IF Text$(Index%) <> "" THEN EXIT FOR
         NEXT Index%
         FOR Index% = 1 TO Index%
          ON ERROR GOTO CannotWriteToFileForSaveAs
          PRINT #1, Text$(Index%)
          ON ERROR GOTO 0
         NEXT Index%
         CLOSE #1
         TextName$ = WorkLine$
        END IF
       END IF
     CASE 3
       StatusText$ = "Load text."
       CALL ScratchScreen
       CALL OutText
       WorkLine$ = ""
       IF InputBox%("Text editor.", "Please enter text exist file name for load.", WorkLine$) THEN
        CALL ScratchScreen
        CALL OutText
        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 OutBox("Text editor.", "You input the invalid file name.")
        ELSE
         IF MessageBox%("Text editor.", "Save current text before load new?") THEN
          StatusText$ = "Save text."
          CALL ScratchScreen
          CALL OutText
          ON ERROR GOTO CannotOpenFileForSave
          OPEN TextName$ FOR OUTPUT AS #1
          ON ERROR GOTO 0
          FOR Index% = TextLines% TO 1 STEP -1
           IF Text$(Index%) <> "" THEN EXIT FOR
          NEXT Index%
          FOR Index% = 1 TO Index%
           ON ERROR GOTO CannotWriteToFileForSave
           PRINT #1, Text$(Index%)
           ON ERROR GOTO 0
          NEXT Index%
          CLOSE #1
         END IF
         StatusText$ = "Load text."
         CALL ScratchScreen
         CALL OutText
         FOR Index% = 1 TO TextLines%
          Text$(Index%) = ""
         NEXT Index%
         TextColumn% = 1
         TextRow% = 1
         TextPosition% = 1
         LinePosition% = 1
         ON ERROR GOTO CannotOpenFileForLoad
         OPEN WorkLine$ FOR INPUT AS #1
         ON ERROR GOTO 0
         Index% = 1
         DO WHILE NOT EOF(1)
          ON ERROR GOTO CannotReadFromFileForLoad
          LINE INPUT #1, Work$
          ON ERROR GOTO 0
          Work$ = LEFT$(Work$, 256)
          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%
          Text$(Index%) = Work$
          Index% = Index% + 1
          IF Index% = TextLines% + 1 THEN
           CALL OutBox("Text editor.", "Input file is too lagre. Loaded first " + LTRIM$(STR$(TextLines%)) + " lines.")
           EXIT DO
          END IF
         LOOP
         CLOSE #1
         TextName$ = WorkLine$
        END IF
       END IF
     CASE 4
       StatusText$ = "Merge in text."
       CALL ScratchScreen
       CALL OutText
       IF (TextRow% + 1) > TextLines% - 1 THEN
        CALL OutBox("Text editor.", "Nothing room to merge in.")
       ELSE
        WorkLine$ = ""
        IF InputBox%("Text editor.", "Please enter text exist file name for merge in.", WorkLine$) THEN
         CALL ScratchScreen
         CALL OutText
         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 OutBox("Text editor.", "You input the invalid file name.")
         ELSE
          IF MessageBox%("Text editor.", "Save current text before merging?") THEN
           StatusText$ = "Save text."
           CALL ScratchScreen
           CALL OutText
           ON ERROR GOTO CannotOpenFileForSave
           OPEN TextName$ FOR OUTPUT AS #1
           ON ERROR GOTO 0
           FOR Index% = TextLines% TO 1 STEP -1
            IF Text$(Index%) <> "" THEN EXIT FOR
           NEXT Index%
           FOR Index% = 1 TO Index%
            ON ERROR GOTO CannotWriteToFileForSave
            PRINT #1, Text$(Index%)
            ON ERROR GOTO 0
           NEXT Index%
           CLOSE #1
          END IF
          StatusText$ = "Merge in text."
          CALL ScratchScreen
          CALL OutText
          FOR Index% = TextRow% + 1 TO TextLines%
           Text$(Index%) = ""
          NEXT Index%
          ON ERROR GOTO CannotOpenFileForMerge
          OPEN WorkLine$ FOR INPUT AS #1
          ON ERROR GOTO 0
          Index% = TextRow% + 1
          DO WHILE NOT EOF(1)
           ON ERROR GOTO CannotReadFromFileForMerge
           LINE INPUT #1, Work$
           ON ERROR GOTO 0
           Work$ = LEFT$(Work$, 256)
           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%
           Text$(Index%) = Work$
           Index% = Index% + 1
           IF Index% = TextLines% + 1 THEN EXIT DO
          LOOP
          CLOSE #1
         END IF
        END IF
       END IF
     CASE 5
       StatusText$ = "Changing printer name."
       CALL ScratchScreen
       CALL OutText
       WorkLine$ = ""
       IF InputBox%("Text editor.", "Please enter new printer name.", WorkLine$) THEN
        CALL ScratchScreen
        CALL OutText
        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 OutBox("Text editor.", "You input the invalid printer name.")
        ELSE
         PrinterName$ = WorkLine$
        END IF
       END IF
     CASE 6
       StatusText$ = "Changing count of lines per page."
       CALL ScratchScreen
       CALL OutText
       WorkLine$ = ""
       IF InputBox%("Text editor.", "Please enter new count of lines per page (from 1 to 256.).", WorkLine$) THEN
        CALL ScratchScreen
        CALL OutText
        WorkLine$ = LTRIM$(RTRIM$(WorkLine$))
        IF (VAL(WorkLine$) < 1) OR (VAL(WorkLine$) > 256) THEN
         CALL OutBox("Text editor.", "You input the invalid count of lines per page.")
        ELSE
         LinesPerPage% = VAL(WorkLine$)
        END IF
       END IF
     CASE 7
       StatusText$ = "Print text."
       CALL ScratchScreen
       CALL OutText
       ON ERROR GOTO CannotOpenPrinter
       OPEN PrinterName$ FOR OUTPUT AS #1
       ON ERROR GOTO 0
       FOR Index% = TextLines% TO 1 STEP -1
        IF Text$(Index%) <> "" THEN EXIT FOR
       NEXT Index%
       WorkIndex% = 0
       FOR Index% = 1 TO Index%
        ON ERROR GOTO CannotWriteToPrinter
        PRINT #1, Text$(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("Text editor.", "Please insert new paper on printer.")
         CALL ScratchScreen
         CALL OutText
         WorkIndex% = 0
        END IF
       NEXT Index%
       ON ERROR GOTO CannotWriteToPrinter
       PRINT #1, CHR$(26);
       ON ERROR GOTO 0
       CLOSE #1
     CASE 8
       StatusText$ = "Find text."
       CALL ScratchScreen
       CALL OutText
       WorkLine$ = ""
       IF InputBox%("Text editor.", "Please enter text to find.", WorkLine$) THEN
        CALL ScratchScreen
        CALL OutText
        FOR Index% = TextRow% TO TextLines% + 1
         IF Index% = TextLines% + 1 THEN
          CALL OutBox("Text editor.", "Text is not found.")
          EXIT FOR
         END IF
         IF INSTR(UCASE$(Text$(Index%)), UCASE$(WorkLine$)) > 0 THEN EXIT FOR
        NEXT Index%
        IF Index% < TextLines% + 1 THEN
         TextRow% = Index%
         TextPosition% = TextRow%
         TextColumn% = INSTR(UCASE$(Text$(Index%)), UCASE$(WorkLine$))
         LinePosition% = TextColumn%
         CALL ControlCoordinates
        END IF
       END IF
     CASE 9
       StatusText$ = "Replace text."
       CALL ScratchScreen
       CALL OutText
       WorkLine$ = ""
       IF InputBox%("Text editor.", "Please enter text to find.", WorkLine$) THEN
        CALL ScratchScreen
        CALL OutText
        Work$ = ""
        IF InputBox%("Text editor.", "Please enter text to replace it.", Work$) THEN
         CALL ScratchScreen
         CALL OutText
         FOR Index% = TextRow% TO TextLines% + 1
          IF Index% = TextLines% + 1 THEN
           CALL OutBox("Text editor.", "Replacing is end.")
           EXIT FOR
          END IF
          WorkIndex% = 1
          WHILE INSTR(UCASE$(MID$(Text$(Index%), WorkIndex%)), UCASE$(WorkLine$)) > 0
           TextRow% = Index%
           TextPosition% = TextRow%
           TextColumn% = INSTR(UCASE$(Text$(Index%)), UCASE$(WorkLine$))
           LinePosition% = TextColumn%
           CALL ControlCoordinates
           WorkIndex% = TextColumn%
           IF MessageBox%("Text editor.", "Replace this occurence?") THEN
            Text$(Index%) = LEFT$(MID$(Text$(Index%), 1, INSTR(UCASE$(Text$(Index%)), UCASE$(WorkLine$)) - 1) + Work$ + MID$(Text$(Index%), (INSTR(UCASE$(Text$(Index%)), UCASE$(WorkLine$)) + LEN(WorkLine$))), 256)
           ELSE
            EXIT FOR
           END IF
           CALL ScratchScreen
           CALL OutText
          WEND
         NEXT Index%
        END IF
       END IF
     CASE 10
       StatusText$ = "Replace all occurences."
       CALL ScratchScreen
       CALL OutText
       WorkLine$ = ""
       IF InputBox%("Text editor.", "Please enter text to find.", WorkLine$) THEN
        CALL ScratchScreen
        CALL OutText
        Work$ = ""
        IF InputBox%("Text editor.", "Please enter text to replace it.", Work$) THEN
         CALL ScratchScreen
         CALL OutText
         FOR Index% = TextRow% TO TextLines% + 1
          IF Index% = TextLines% + 1 THEN
           CALL OutBox("Text editor.", "Replacing is end.")
           EXIT FOR
          END IF
          WHILE INSTR(UCASE$(Text$(Index%)), UCASE$(WorkLine$)) > 0
           Text$(Index%) = LEFT$(MID$(Text$(Index%), 1, INSTR(UCASE$(Text$(Index%)), UCASE$(WorkLine$)) - 1) + Work$ + MID$(Text$(Index%), (INSTR(UCASE$(Text$(Index%)), UCASE$(WorkLine$)) + LEN(WorkLine$))), 256)
          WEND
         NEXT Index%
        END IF
       END IF
     CASE 11
       StatusText$ = "Insert calendar."
       CALL ScratchScreen
       CALL OutText
       IF TextRow% > TextLines% - 8 THEN
        CALL OutBox("Text editor.", "Current line number is too large for insert calendar. Before insert calendar, current row must be less than " + LTRIM$(STR$(TextLines% - 7)) + ".")
       ELSE
        WorkDay% = VAL(MID$(DATE$, 4, 2))
        WorkMonth% = VAL(MID$(DATE$, 1, 2))
        WorkYear% = VAL(MID$(DATE$, 7, 4))
        IF CalendarBox%("Text editor.", "Please select date for including calendar.", WorkDay%, WorkMonth%, WorkYear%) THEN
         Text$(TextRow%) = LEFT$(MID$(Text$(TextRow%), 1, TextColumn% - 1) + MonthName$(WorkMonth%) + ", " + LTRIM$(STR$(WorkYear%)) + " year." + SPACE$(21 - LEN(MonthName$(WorkMonth%) + ", " + LTRIM$(STR$(WorkYear%)) + " year.")) + MID$(Text$(TextRow%), TextColumn%), 256)
         Text$(TextRow% + 1) = LEFT$(MID$(Text$(TextRow% + 1), 1, TextColumn% - 1) + " Mo Tu We Th Fr Sa Su" + MID$(Text$(TextRow% + 1), TextColumn%), 256)
         FOR OutIndex% = 1 TO 37
          Days%(OutIndex%) = 0
         NEXT OutIndex%
         Value% = 1
         FOR OutIndex% = DayOfWeek%(1, WorkMonth%, WorkYear%) TO 37
          Days%(OutIndex%) = Value%
          Value% = Value% + 1
          IF Value% = MonthDays%(WorkMonth%, WorkYear%) + 1 THEN EXIT FOR
         NEXT OutIndex%
         WorkLine$ = ""
         WorkIndex% = 2
         FOR OutIndex% = 1 TO 37
          IF Days%(OutIndex%) > 0 THEN
           IF Days%(OutIndex%) = WorkDay% THEN
            WorkLine$ = WorkLine$ + "*" + SPACE$(2 - LEN(LTRIM$(STR$(Days%(OutIndex%))))) + LTRIM$(STR$(Days%(OutIndex%)))
           ELSE
            WorkLine$ = WorkLine$ + SPACE$(3 - LEN(LTRIM$(STR$(Days%(OutIndex%))))) + LTRIM$(STR$(Days%(OutIndex%)))
           END IF
          ELSE
           WorkLine$ = WorkLine$ + SPACE$(3)
          END IF
          IF LEN(WorkLine$) = 21 THEN
           IF LEN(Text$(TextRow% + WorkIndex%)) < TextColumn% - 1 THEN Text$(TextRow% + WorkIndex%) = SPACE$(TextColumn% - 1)
           Text$(TextRow% + WorkIndex%) = LEFT$(MID$(Text$(TextRow% + WorkIndex%), 1, TextColumn% - 1) + WorkLine$ + MID$(Text$(TextRow% + WorkIndex%), TextColumn%), 256)
           WorkLine$ = ""
           WorkIndex% = WorkIndex% + 1
          END IF
         NEXT OutIndex%
         IF WorkLine$ <> "" THEN
          IF LEN(Text$(TextRow% + WorkIndex%)) < TextColumn% - 1 THEN Text$(TextRow% + WorkIndex%) = SPACE$(TextColumn% - 1)
          Text$(TextRow% + WorkIndex%) = LEFT$(MID$(Text$(TextRow% + WorkIndex%), 1, TextColumn% - 1) + WorkLine$ + SPACE$(21 - LEN(WorkLine$)) + MID$(Text$(TextRow% + WorkIndex%), TextColumn%), 256)
          WorkLine$ = ""
         END IF
        END IF
       END IF
     CASE 12
       Text$(TextRow%) = LEFT$(MID$(Text$(TextRow%), 1, TextColumn% - 1) + CurrentDateTime$ + MID$(Text$(TextRow%), TextColumn%), 256)
     CASE 13
       StatusText$ = "Quit."
       CALL ScratchScreen
       CALL OutText
       IF MessageBox%("Text editor.", "Save text before quit?") THEN
        StatusText$ = "Save text."
        CALL ScratchScreen
        CALL OutText
        ON ERROR GOTO CannotOpenFileForSave
        OPEN TextName$ FOR OUTPUT AS #1
        ON ERROR GOTO 0
        FOR Index% = TextLines% TO 1 STEP -1
         IF Text$(Index%) <> "" THEN EXIT FOR
        NEXT Index%
        FOR Index% = 1 TO Index%
         ON ERROR GOTO CannotWriteToFileForSave
         PRINT #1, Text$(Index%)
         ON ERROR GOTO 0
        NEXT Index%
        CLOSE #1
       END IF
       EXIT DO
     END SELECT
     StatusText$ = CurrentDateTime$
     CALL ScratchScreen
     CALL OutText
   CASE ELSE
     IF ASC(WorkKey$) > (ASC(SPACE$(1)) - 1) THEN
      IF TextColumn% = 257 THEN
       IF TextRow% < TextLines% THEN
        TextRow% = TextRow% + 1
        TextPosition% = TextPosition% + 1
        TextColumn% = 1
        LinePosition% = 1
        Text$(TextRow%) = MID$(Text$(TextRow%), 1, TextColumn% - 1) + WorkKey$ + MID$(Text$(TextRow%), TextColumn%)
        CALL OutText
       END IF
      ELSE
       Text$(TextRow%) = MID$(Text$(TextRow%), 1, TextColumn% - 1) + WorkKey$ + MID$(Text$(TextRow%), TextColumn%)
       CALL CursorRight
      END IF
     END IF
   END SELECT
 CASE 2
   WorkKey$ = MID$(WorkKey$, 2)
   SELECT CASE WorkKey$
   CASE CHR$(72)
     CALL CursorUp
   CASE CHR$(80)
     CALL CursorDown
   CASE CHR$(73)
     CALL PageUp
   CASE CHR$(81)
     CALL PageDown
   CASE CHR$(71)
     CALL CursorHome
   CASE CHR$(79)
     CALL CursorEnd
   CASE CHR$(75)
     CALL CursorLeft
   CASE CHR$(77)
     CALL CursorRight
   CASE CHR$(83)
     CALL DeleteSymbol
   END SELECT
 END SELECT
TextWork:
LOOP
COLOR 7, 0
CLS
LOCATE 1, 1, 1, 7, 8
END
CannotOpenFileForSave:
 IF MessageBox%("Text editor.", "Cannot open file for save. Retry opening?") THEN
  CALL ScratchScreen
  CALL OutText
  RESUME
 ELSE
  StatusText$ = CurrentDateTime$
  CALL ScratchScreen
  CALL OutText
  RESUME TextWork
 END IF
CannotWriteToFileForSave:
 IF MessageBox%("Text editor.", "Cannot write to file for save. Retry writing?") THEN
  CALL ScratchScreen
  CALL OutText
  RESUME
 ELSE
  CLOSE #1
  KILL TextName$
  StatusText$ = CurrentDateTime$
  CALL ScratchScreen
  CALL OutText
  RESUME TextWork
 END IF
CannotOpenFileForSaveAs:
 IF MessageBox%("Text editor.", "Cannot open file for save as other name. Retry opening?") THEN
  CALL ScratchScreen
  CALL OutText
  RESUME
 ELSE
  StatusText$ = CurrentDateTime$
  CALL ScratchScreen
  CALL OutText
  RESUME TextWork
 END IF
CannotWriteToFileForSaveAs:
 IF MessageBox%("Text editor.", "Cannot write to file for save as other name. Retry writing?") THEN
  CALL ScratchScreen
  CALL OutText
  RESUME
 ELSE
  CLOSE #1
  KILL WorkLine$
  StatusText$ = CurrentDateTime$
  CALL ScratchScreen
  CALL OutText
  RESUME TextWork
 END IF
CannotOpenFileForLoad:
 IF MessageBox%("Text editor.", "Cannot open file for load. Retry opening?") THEN
  CALL ScratchScreen
  CALL OutText
  RESUME
 ELSE
  StatusText$ = CurrentDateTime$
  CALL ScratchScreen
  CALL OutText
  RESUME TextWork
 END IF
CannotReadFromFileForLoad:
 IF MessageBox%("Text editor.", "Cannot read from file for load. Retry reading?") THEN
  CALL ScratchScreen
  CALL OutText
  RESUME
 ELSE
  CLOSE #1
  StatusText$ = CurrentDateTime$
  CALL ScratchScreen
  CALL OutText
  RESUME TextWork
 END IF
CannotOpenFileForMerge:
 IF MessageBox%("Text editor.", "Cannot open file for merge in text. Retry opening?") THEN
  CALL ScratchScreen
  CALL OutText
  RESUME
 ELSE
  StatusText$ = CurrentDateTime$
  CALL ScratchScreen
  CALL OutText
  RESUME TextWork
 END IF
CannotReadFromFileForMerge:
 IF MessageBox%("Text editor.", "Cannot read from file for merge in text. Retry reading?") THEN
  CALL ScratchScreen
  CALL OutText
  RESUME
 ELSE
  CLOSE #1
  StatusText$ = CurrentDateTime$
  CALL ScratchScreen
  CALL OutText
  RESUME TextWork
 END IF
CannotOpenPrinter:
 IF MessageBox%("Text editor.", "Cannot open printer. Retry opening?") THEN
  CALL ScratchScreen
  CALL OutText
  RESUME
 ELSE
  StatusText$ = CurrentDateTime$
  CALL ScratchScreen
  CALL OutText
  RESUME TextWork
 END IF
CannotWriteToPrinter:
 IF MessageBox%("Text editor.", "Cannot write to printer. Retry writing?") THEN
  CALL ScratchScreen
  CALL OutText
  RESUME
 ELSE
  CLOSE #1
  StatusText$ = CurrentDateTime$
  CALL ScratchScreen
  CALL OutText
  RESUME TextWork
 END IF

FUNCTION CalendarBox% (Title$, Message$, DayValue%, MonthValue%, YearValue%)
 DIM OutMessage$
 DIM OutIndex%
 DIM Value%
 DIM Days%(37)
 DIM CalendarLine$
 DIM WorkDay%
 DIM WorkMonth%
 DIM WorkYear%
 DIM WorkKey$
 IF LEN(Message$) < 256 THEN OutMessage$ = Message$ + SPACE$(256 - LEN(Message$)) ELSE OutMessage$ = LEFT$(Message$, 256)
 CALL MakeBox(7, 5, 64, 14)
 PRINT LEFT$(Title$, 64) + SPACE$(64 - LEN(LEFT$(Title$, 64)));
 COLOR 1, 7
 FOR OutIndex% = 1 TO 4
  LOCATE 6 + OutIndex%, 8, 0
  PRINT LEFT$(OutMessage$, 64);
  OutMessage$ = MID$(OutMessage$, 65)
 NEXT OutIndex%
 COLOR 14, 7
 LOCATE 19, 8, 0
 PRINT "Please press key is equalient to your answer: ENTER=Yes, ESC=No.";
 WorkDay% = DayValue%
 WorkMonth% = MonthValue%
 WorkYear% = YearValue%
 COLOR 15, 7
 LOCATE 11, 31, 0
 PRINT "Mo Tu We Th Fr Sa Su";
 GOSUB OutCalendar
 DO
  WorkKey$ = INKEY$
  SELECT CASE LEN(WorkKey$)
  CASE 1
    SELECT CASE WorkKey$
    CASE CHR$(13)
      DayValue% = WorkDay%
      MonthValue% = WorkMonth%
      YearValue% = WorkYear%
      EXIT DO
    CASE CHR$(27)
      EXIT DO
    END SELECT
  CASE 2
    WorkKey$ = MID$(WorkKey$, 2)
    SELECT CASE WorkKey$
    CASE CHR$(72)
      WorkDay% = WorkDay% - 1
      IF WorkDay% < 1 THEN
       WorkMonth% = WorkMonth% - 1
       IF WorkMonth% < 1 THEN
        IF WorkYear% = 1980 THEN
         WorkMonth% = 1
         WorkDay% = 1
        ELSE
         WorkYear% = WorkYear% - 1
         WorkMonth% = 12
         WorkDay% = 31
        END IF
       ELSE
        WorkDay% = MonthDays%(WorkMonth%, WorkYear%)
       END IF
      END IF
      GOSUB OutCalendar
    CASE CHR$(80)
      WorkDay% = WorkDay% + 1
      IF WorkDay% > MonthDays%(WorkMonth%, WorkYear%) THEN
       WorkMonth% = WorkMonth% + 1
       IF WorkMonth% > 12 THEN
        IF WorkYear% = 2010 THEN
         WorkMonth% = 12
         WorkDay% = 31
        ELSE
         WorkYear% = WorkYear% + 1
         WorkMonth% = 1
         WorkDay% = 1
        END IF
       ELSE
        WorkDay% = 1
       END IF
      END IF
      GOSUB OutCalendar
    CASE CHR$(75)
      WorkDay% = WorkDay% - 1
      IF WorkDay% < 1 THEN
       WorkMonth% = WorkMonth% - 1
       IF WorkMonth% < 1 THEN
        IF WorkYear% = 1980 THEN
         WorkMonth% = 1
         WorkDay% = 1
        ELSE
         WorkYear% = WorkYear% - 1
         WorkMonth% = 12
         WorkDay% = 31
        END IF
       ELSE
        WorkDay% = MonthDays%(WorkMonth%, WorkYear%)
       END IF
      END IF
      GOSUB OutCalendar
    CASE CHR$(77)
      WorkDay% = WorkDay% + 1
      IF WorkDay% > MonthDays%(WorkMonth%, WorkYear%) THEN
       WorkMonth% = WorkMonth% + 1
       IF WorkMonth% > 12 THEN
        IF WorkYear% = 2010 THEN
         WorkMonth% = 12
         WorkDay% = 31
        ELSE
         WorkYear% = WorkYear% + 1
         WorkMonth% = 1
         WorkDay% = 1
        END IF
       ELSE
        WorkDay% = 1
       END IF
      END IF
      GOSUB OutCalendar
    CASE CHR$(73)
      WorkMonth% = WorkMonth% - 1
      IF WorkMonth% < 1 THEN
       IF WorkYear% = 1980 THEN
        WorkMonth% = 1
       ELSE
        WorkYear% = WorkYear% - 1
        WorkMonth% = 12
       END IF
      END IF
      IF WorkDay% > MonthDays%(WorkMonth%, WorkYear%) THEN WorkDay% = MonthDays%(WorkMonth%, WorkYear%)
      GOSUB OutCalendar
    CASE CHR$(81)
      WorkMonth% = WorkMonth% + 1
      IF WorkMonth% > 12 THEN
       IF WorkYear% = 2010 THEN
        WorkMonth% = 12
       ELSE
        WorkYear% = WorkYear% + 1
        WorkMonth% = 1
       END IF
      END IF
      IF WorkDay% > MonthDays%(WorkMonth%, WorkYear%) THEN WorkDay% = MonthDays%(WorkMonth%, WorkYear%)
      GOSUB OutCalendar
    CASE CHR$(71)
      IF WorkYear% > 1980 THEN
       WorkYear% = WorkYear% - 1
       IF WorkDay% > MonthDays%(WorkMonth%, WorkYear%) THEN WorkDay% = MonthDays%(WorkMonth%, WorkYear%)
       GOSUB OutCalendar
      END IF
    CASE CHR$(79)
      IF WorkYear% < 2010 THEN
       WorkYear% = WorkYear% + 1
       IF WorkDay% > MonthDays%(WorkMonth%, WorkYear%) THEN WorkDay% = MonthDays%(WorkMonth%, WorkYear%)
       GOSUB OutCalendar
      END IF
    END SELECT
  END SELECT
 LOOP
 CalendarBox% = WorkKey$ = CHR$(13)
 EXIT FUNCTION
OutCalendar:
 COLOR 8, 7
 LOCATE 12, 31, 0
 PRINT MonthName$(WorkMonth%) + ", " + LTRIM$(STR$(WorkYear%)) + " year." + SPACE$(21 - LEN(MonthName$(WorkMonth%) + ", " + LTRIM$(STR$(WorkYear%)) + " year."));
 FOR OutIndex% = 1 TO 37
  Days%(OutIndex%) = 0
 NEXT OutIndex%
 Value% = 1
 FOR OutIndex% = DayOfWeek%(1, WorkMonth%, WorkYear%) TO 37
  Days%(OutIndex%) = Value%
  Value% = Value% + 1
  IF Value% = MonthDays%(WorkMonth%, WorkYear%) + 1 THEN EXIT FOR
 NEXT OutIndex%
 CalendarLine$ = ""
 Value% = 1
 FOR OutIndex% = 1 TO 37
  IF Days%(OutIndex%) > 0 THEN
   IF Days%(OutIndex%) = WorkDay% THEN
    CalendarLine$ = CalendarLine$ + "*" + SPACE$(2 - LEN(LTRIM$(STR$(Days%(OutIndex%))))) + LTRIM$(STR$(Days%(OutIndex%)))
   ELSE
    CalendarLine$ = CalendarLine$ + SPACE$(3 - LEN(LTRIM$(STR$(Days%(OutIndex%))))) + LTRIM$(STR$(Days%(OutIndex%)))
   END IF
  ELSE
   CalendarLine$ = CalendarLine$ + SPACE$(3)
  END IF
  IF LEN(CalendarLine$) = 21 THEN
   COLOR 6, 7
   LOCATE 12 + Value%, 30, 0
   WHILE CalendarLine$ <> ""
    SELECT CASE LEFT$(CalendarLine$, 1)
    CASE "*"
      COLOR 14, 6
      CalendarLine$ = MID$(CalendarLine$, 2)
      PRINT SPACE$(1) + LEFT$(CalendarLine$, 3);
      CalendarLine$ = MID$(CalendarLine$, 4)
      COLOR 6, 7
    CASE ELSE
      PRINT LEFT$(CalendarLine$, 1);
      CalendarLine$ = MID$(CalendarLine$, 2)
    END SELECT
   WEND
   Value% = Value% + 1
  END IF
 NEXT OutIndex%
 IF CalendarLine$ <> "" THEN
  COLOR 6, 7
  LOCATE 12 + Value%, 30, 0
  WHILE CalendarLine$ <> ""
   SELECT CASE LEFT$(CalendarLine$, 1)
   CASE "*"
     COLOR 14, 6
     CalendarLine$ = MID$(CalendarLine$, 2)
     PRINT SPACE$(1) + LEFT$(CalendarLine$, 3);
     CalendarLine$ = MID$(CalendarLine$, 4)
     COLOR 6, 7
   CASE ELSE
     PRINT LEFT$(CalendarLine$, 1);
     CalendarLine$ = MID$(CalendarLine$, 2)
   END SELECT
  WEND
 END IF
 RETURN
END FUNCTION

SUB ControlCoordinates
 IF TextRow% < 1 THEN TextRow% = 1
 IF TextPosition% < 1 THEN TextPosition% = 1
 IF TextRow% > TextLines% THEN TextRow% = TextLines%
 IF TextPosition% > 20 THEN TextPosition% = 20
 IF TextColumn% < 1 THEN TextColumn% = 1
 IF LinePosition% < 1 THEN LinePosition% = 1
 IF TextColumn% > LEN(Text$(TextRow%)) + 1 THEN TextColumn% = LEN(Text$(TextRow%)) + 1
 IF LEN(Text$(TextRow%)) > 76 THEN IF LinePosition% > 77 THEN LinePosition% = 77
 IF LEN(Text$(TextRow%)) < 77 THEN IF LinePosition% > LEN(Text$(TextRow%)) + 1 THEN LinePosition% = LEN(Text$(TextRow%)) + 1
 CALL OutText
END SUB

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

SUB CursorDown
 TextRow% = TextRow% + 1
 TextPosition% = TextPosition% + 1
 CALL ControlCoordinates
END SUB

SUB CursorEnd
 TextColumn% = LEN(Text$(TextRow%)) + 1
 LinePosition% = TextColumn%
 CALL ControlCoordinates
END SUB

SUB CursorHome
 TextColumn% = 1
 LinePosition% = 1
 CALL ControlCoordinates
END SUB

SUB CursorLeft
 IF TextColumn% = 1 THEN
  IF TextRow% > 1 THEN
   TextColumn% = LEN(Text$(TextRow% - 1)) + 1
   LinePosition% = TextColumn%
   CALL CursorUp
  END IF
 ELSE
  TextColumn% = TextColumn% - 1
  LinePosition% = LinePosition% - 1
  CALL ControlCoordinates
 END IF
END SUB

SUB CursorRight
 IF TextColumn% = LEN(Text$(TextRow%)) + 1 THEN
  IF TextRow% < TextLines% THEN
   TextColumn% = 1
   LinePosition% = 1
   CALL CursorDown
  END IF
 ELSE
  TextColumn% = TextColumn% + 1
  LinePosition% = LinePosition% + 1
  CALL ControlCoordinates
 END IF
END SUB

SUB CursorUp
 TextRow% = TextRow% - 1
 TextPosition% = TextPosition% - 1
 CALL ControlCoordinates
END SUB

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

SUB DeleteBackSymbol
 DIM Index%
 DIM LineLength%
 IF TextColumn% = 1 THEN
  IF TextRow% > 1 THEN
   IF LEN(Text$(TextRow% - 1)) < 256 THEN
    LineLength% = LEN(Text$(TextRow% - 1))
    Text$(TextRow% - 1) = Text$(TextRow% - 1) + LEFT$(Text$(TextRow%), 256 - LineLength%)
    Text$(TextRow%) = MID$(Text$(TextRow%), (256 - LineLength%) + 1)
    IF Text$(TextRow%) = "" THEN
     FOR Index% = TextRow% TO TextLines% - 1
      Text$(Index%) = Text$(Index% + 1)
      Text$(Index% + 1) = ""
     NEXT Index%
    END IF
    TextColumn% = LineLength% + 1
    LinePosition% = TextColumn%
    CALL CursorUp
   END IF
  END IF
 ELSE
  Text$(TextRow%) = MID$(Text$(TextRow%), 1, TextColumn% - 2) + MID$(Text$(TextRow%), TextColumn%)
  CALL CursorLeft
 END IF
END SUB

SUB DeleteSymbol
 DIM Index%
 DIM LineLength%
 IF TextColumn% = LEN(Text$(TextRow%)) + 1 THEN
  IF (LEN(Text$(TextRow%)) < 256) AND (TextRow% < TextLines%) THEN
   LineLength% = LEN(Text$(TextRow%))
   Text$(TextRow%) = Text$(TextRow%) + LEFT$(Text$(TextRow% + 1), 256 - LineLength%)
   Text$(TextRow% + 1) = MID$(Text$(TextRow% + 1), (256 - LineLength%) + 1)
   IF Text$(TextRow% + 1) = "" THEN
    FOR Index% = TextRow% + 1 TO TextLines% - 1
     Text$(Index%) = Text$(Index% + 1)
     Text$(Index% + 1) = ""
    NEXT Index%
   END IF
  END IF
 ELSE
  Text$(TextRow%) = MID$(Text$(TextRow%), 1, TextColumn% - 1) + MID$(Text$(TextRow%), TextColumn% + 1)
 END IF
 CALL OutText
END SUB

SUB EnterLine
 DIM Index%
 IF (TextRow% > (TextLines% - 1)) OR (Text$(TextLines%) <> "") THEN EXIT SUB
 FOR Index% = TextLines% - 1 TO TextRow% + 1 STEP -1
  Text$(Index% + 1) = Text$(Index%)
  Text$(Index%) = ""
 NEXT Index%
 Text$(TextRow% + 1) = MID$(Text$(TextRow%), TextColumn%)
 Text$(TextRow%) = MID$(Text$(TextRow%), 1, TextColumn% - 1)
 TextColumn% = 1
 LinePosition% = 1
 CALL CursorDown
END SUB

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 OutText
 DIM Index%
 CALL MakeBox(1, 1, 77, 22)
 COLOR 1, 7
 FOR Index% = 1 TO 20
  LOCATE Index% + 1, 2, 0
  PRINT SPACE$(77);
  LOCATE Index% + 1, 2, 0
  PRINT MID$(Text$((TextRow% - TextPosition%) + Index%), (TextColumn% - LinePosition%) + 1, 77);
 NEXT Index%
 COLOR 2, 7
 LOCATE 22, 2, 0
 PRINT SPACE$(77);
 LOCATE 22, 2, 0
 PRINT "Column=" + LTRIM$(STR$(TextColumn%)) + ". Row=" + LTRIM$(STR$(TextRow%)) + ". File=" + TextName$ + ". ESC=Menu.";
 COLOR 4, 7
 LOCATE 23, 2, 0
 PRINT SPACE$(77);
 LOCATE 23, 2, 0
 PRINT StatusText$;
 COLOR 1, 7
 LOCATE TextPosition% + 1, LinePosition% + 1, 1, 7, 8
END SUB

SUB PageDown
 TextRow% = TextRow% + 20
 TextPosition% = TextPosition% + 20
 CALL ControlCoordinates
END SUB

SUB PageUp
 TextRow% = TextRow% - 20
 TextPosition% = TextPosition% - 20
 CALL ControlCoordinates
END SUB

SUB ScratchScreen
 COLOR 0, 2
 CLS
 PRINT "********************************************************************************"
 PRINT "                      The Standart GNU Personal Text Editor."
 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

