' Simple Line Editor — cursor movement, insert/delete via INKEY$
#COMPILE EXE
#DIM ALL

SUB ShowBuffer(buf AS STRING, cursorPos AS LONG)
    PRINT "> " & LEFT$(buf, cursorPos) & "|" & MID$(buf, cursorPos + 1)
    PRINT "  " & STRING$(LEN(LEFT$(buf, cursorPos)) + 2, 32) & "^"
    PRINT "  Cursor: " & STR$(cursorPos) & "  Len: " & STR$(LEN(buf))
END SUB

SUB CursorLeft(cpos AS LONG, BYREF result AS LONG)
    IF cpos > 0 THEN
        result = cpos - 1
    ELSE
        result = 0
    END IF
END SUB

SUB CursorRight(buf AS STRING, cpos AS LONG, BYREF result AS LONG)
    IF cpos < LEN(buf) THEN
        result = cpos + 1
    ELSE
        result = LEN(buf)
    END IF
END SUB

SUB InsertChar(buf AS STRING, cpos AS LONG, ch AS STRING, BYREF result AS STRING)
    result = LEFT$(buf, cpos) & ch & MID$(buf, cpos + 1)
END SUB

SUB DeleteChar(buf AS STRING, cpos AS LONG, BYREF result AS STRING)
    LOCAL lenBuf AS LONG
    lenBuf = LEN(buf)
    IF lenBuf = 0 OR cpos >= lenBuf THEN
        result = buf
        EXIT SUB
    END IF
    result = LEFT$(buf, cpos) & MID$(buf, cpos + 2)
END SUB

SUB BackspaceChar(buf AS STRING, cpos AS LONG, BYREF result AS STRING)
    IF cpos = 0 THEN
        result = buf
        EXIT SUB
    END IF
    result = LEFT$(buf, cpos - 1) & MID$(buf, cpos + 1)
END SUB

SUB ClearLine()
    PRINT STRING$(80, CHR$(8))
    PRINT STRING$(80, " ")
    PRINT STRING$(80, CHR$(8))
END SUB

SUB TestEditBuffer()
    LOCAL buf AS STRING
    LOCAL cursorPos AS LONG
    LOCAL k AS STRING
    LOCAL done AS LONG
    LOCAL newBuf AS STRING
    LOCAL temp AS LONG
    buf = "Hello, World!"
    cursorPos = LEN(buf)
    done = 0
    PRINT "=== LINE EDITOR DEMO ==="
    PRINT "Editor commands:"
    PRINT "  Left/Right arrows = move cursor"
    PRINT "  Home = start, End = end"
    PRINT "  Delete = delete char, Backspace = backspace"
    PRINT "  Esc = exit editor"
    PRINT
    CALL ShowBuffer(buf, cursorPos)
    DO
        k = INKEY$
        IF k <> "" THEN
            IF k = CHR$(27) THEN
                done = 1
            ELSEIF LEN(k) = 2 AND ASC(k, 1) = 0 THEN
                IF ASC(k, 2) = 75 THEN
                    CALL CursorLeft(cursorPos, cursorPos)
                ELSEIF ASC(k, 2) = 77 THEN
                    CALL CursorRight(buf, cursorPos, cursorPos)
                ELSEIF ASC(k, 2) = 71 THEN
                    cursorPos = 0
                ELSEIF ASC(k, 2) = 79 THEN
                    cursorPos = LEN(buf)
                ELSEIF ASC(k, 2) = 83 THEN
                    CALL DeleteChar(buf, cursorPos, newBuf)
                    IF LEN(newBuf) < LEN(buf) AND cursorPos > 0 THEN
                        CALL CursorLeft(cursorPos, cursorPos)
                    END IF
                    buf = newBuf
                END IF
            ELSEIF k = CHR$(8) THEN
                CALL CursorLeft(cursorPos, cursorPos)
                CALL BackspaceChar(buf, cursorPos, buf)
            ELSEIF ASC(k) >= 32 AND ASC(k) <= 126 THEN
                CALL InsertChar(buf, cursorPos, k, newBuf)
                buf = newBuf
                CALL CursorRight(buf, cursorPos, cursorPos)
            END IF
            CALL ClearLine()
            CALL ShowBuffer(buf, cursorPos)
        END IF
        SLEEP 30
    LOOP UNTIL done
    PRINT
    PRINT "Final text: " & buf
    PRINT "Editor demo complete."
    PRINT
END SUB

SUB CountWords(text AS STRING)
    LOCAL i AS LONG
    LOCAL wc AS LONG
    LOCAL inWord AS LONG
    LOCAL ch AS STRING
    wc = 0
    inWord = 0
    FOR i = 1 TO LEN(text)
        ch = MID$(text, i, 1)
        IF ch <> " " THEN
            IF inWord = 0 THEN
                wc = wc + 1
                inWord = 1
            END IF
        ELSE
            inWord = 0
        END IF
    NEXT i
    PRINT "Word count: " & STR$(wc)
END SUB

SUB CharAnalysis(text AS STRING)
    LOCAL i AS LONG
    LOCAL ch AS STRING
    LOCAL letters AS LONG
    LOCAL digits AS LONG
    LOCAL spaces AS LONG
    LOCAL other AS LONG
    letters = 0
    digits = 0
    spaces = 0
    other = 0
    FOR i = 1 TO LEN(text)
        ch = MID$(text, i, 1)
        IF (ch >= "A" AND ch <= "Z") OR (ch >= "a" AND ch <= "z") THEN
            letters = letters + 1
        ELSEIF ch >= "0" AND ch <= "9" THEN
            digits = digits + 1
        ELSEIF ch = " " THEN
            spaces = spaces + 1
        ELSE
            other = other + 1
        END IF
    NEXT i
    PRINT "=== CHARACTER ANALYSIS ==="
    PRINT "Text: " & text
    PRINT "Letters: " & STR$(letters)
    PRINT "Digits: " & STR$(digits)
    PRINT "Spaces: " & STR$(spaces)
    PRINT "Other: " & STR$(other)
    PRINT "Total: " & STR$(LEN(text))
    PRINT
END SUB

SUB ReverseString(s AS STRING, BYREF result AS STRING)
    LOCAL i AS LONG
    LOCAL n AS LONG
    LOCAL rev AS STRING
    n = LEN(s)
    rev = ""
    FOR i = n TO 1 STEP -1
        rev = rev & MID$(s, i, 1)
    NEXT i
    result = rev
END SUB

SUB IsPalindrome(s AS STRING)
    LOCAL i AS LONG
    LOCAL n AS LONG
    LOCAL isPal AS LONG
    n = LEN(s)
    isPal = 1
    FOR i = 1 TO n / 2
        IF MID$(s, i, 1) <> MID$(s, n - i + 1, 1) THEN
            isPal = 0
            EXIT FOR
        END IF
    NEXT i
    IF isPal THEN
        PRINT "The string is a palindrome."
    ELSE
        PRINT "The string is NOT a palindrome."
    END IF
END SUB

FUNCTION PBMAIN() AS LONG
    LOCAL rev AS STRING
    PRINT "=========================="
    PRINT " Console Line Editor "
    PRINT "=========================="
    PRINT
    CALL TestEditBuffer()
    PRINT "=========== TEXT ANALYSIS ==========="
    CALL CountWords("The quick brown fox jumps over the lazy dog")
    CALL CharAnalysis("Hello World! 123 ABC def. x=5")
    CALL ReverseString("Hello World", rev)
    PRINT "Reversed: " & rev
    CALL IsPalindrome("racecar")
    CALL IsPalindrome("hello")
    PRINT
    PRINT "Press any key to exit..."
    WAITKEY$
    FUNCTION = 0
END FUNCTION
