MODULE editor;

(* based on the kilo editor building course*)

(* Step 9 *)

IMPORT FIO, SYSTEM, termios, STextIO, NumberIO;
IMPORT CharClass, STextIO, libc;

VAR 
    c           : CHAR;
    p           : POINTER TO CHAR;
    thetermios  : termios.TERMIOS;
    raw         : termios.TERMIOS;
    result      : INTEGER;

    PROCEDURE disableRawMode(): INTEGER;
        VAR
            TCSAFLUSH : INTEGER;
            result    : INTEGER; 
        
    BEGIN
        TCSAFLUSH := termios.tcsflush ();
        result := termios.tcsetattr(FIO.StdIn, TCSAFLUSH, thetermios);
        RETURN result;
    END disableRawMode;

    PROCEDURE enableRawMode;

        VAR
            TCSAFLUSH   : INTEGER;
            result      : INTEGER;
            bresult     : BOOLEAN;
    BEGIN
        TCSAFLUSH := termios.tcsflush (); 
        libc.atexit(disableRawMode);
        bresult := termios.SetFlag(raw,termios.lecho, FALSE);
        bresult := termios.SetFlag(raw,termios.licanon, FALSE);
        bresult := termios.SetFlag(raw,termios.lisig, FALSE);
        result := termios.tcsetattr(FIO.StdIn, TCSAFLUSH, raw);
    END enableRawMode;

BEGIN
    thetermios := termios.InitTermios();
    raw := termios.InitTermios();
    result := termios.tcgetattr(FIO.StdIn, thetermios);
    result := termios.tcgetattr(FIO.StdIn, raw);

    enableRawMode;
    p := SYSTEM.ADR(c);
    WHILE (FIO.ReadNBytes(FIO.StdIn,1,p) = 1) AND (c <> "q") DO
        IF CharClass.IsControl(c) THEN
            NumberIO.WriteCard(ORD(c),5);
            STextIO.WriteLn;
        ELSE
            NumberIO.WriteCard(ORD(c),5);
            STextIO.WriteString(" ('");
            STextIO.WriteChar(c);
            STextIO.WriteString(" ')");
            STextIO.WriteLn;
        END;
    END;
END editor.