 {$K-,C-,B-,D+}
PROGRAM MAKEKEY; { prepares an encrypting key file }

 {MAKEKEY   Myfile.KEY}

 {Version 2.0 1987 February 2 by Roedy Green}

 {Please direct comments for improvement of this public domain program to:}
 {Roedy Green}
 {Canadian Mind Products}
 {#11 - 2856 Sunset Street}
 {Burnaby, BC}
 {CANADA  V5G 1T3}
 {telephone (604) 435-2957}
 {Envoy/Bix id: ROEDY}

 TYPE charint = -1..255;
         {-1 indicates end of file}

 VAR KeyFile : TEXT [ 8192 {blocksize} ];
        {output file contain no ctrl-z}
     c : charint;
        { current char from Before file }
     lastc : charint; { used to detect using repeat key }
     totcap : integer; { total random chars captured }

PROCEDURE Beep;
     BEGIN {Beep}
     Sound(400);
     Delay(500);
     NoSound
     END; {Beep}

PROCEDURE Die;
     BEGIN {Die}
     Beep;
     {$I-}
     Close (KeyFile);
     {$I+}
     HALT(1)
     END; {Die}

 FUNCTION GetIt: charint; {get 1 random number 0..255}
    VAR
    achar : char;
    i,j : 0 .. 257;
  BEGIN {GetIt}
      REPEAT {until get different than last time}
        WHILE KeyPressed Do  {get rid of backed up characters}
            BEGIN
            Read(Kbd,achar);
            IF ord(achar) = 26 {^Z} THEN
               BEGIN
               GetIt := -1;
               EXIT
               END
             END; {WHILE}
        i := 0;
        WHILE NOT KeyPressed Do
            BEGIN
            i := i + 1; {wheel of fortune stops when hit a key}
            IF i > 255 THEN i := 0 ELSE j := 0
            {The code j := 0 is simply to waste an equal amount of time}
            {as the i := 0 case.}
            {This makes the wheel almost perfectly fair.}
            {All numbers 0..255 are equally likely}
            END;
      UNTIL i <> Lastc; {must be different timing}
        {Purists will note that the insistence on different timing}
        {means the file is not perfectly random.  But it avoids the}
        {greater evil of strings of identical numbers resulting}
        {from holding down a key.}
        Sound(800); {click when capture a number}
        Lastc := i;
        i := i XOR ord(achar);
        {a little extra scrambling just in case}
        {there is some regularity in timing}
        { Note we do not avoid Ctrl-Z }
        totcap := totcap + 1;
        GOTOXY (1,5);
        Write(totcap:5,i:4);
        GetIt := i;
        NoSound
  END {GetIt};

PROCEDURE PutIt(c:charint) {emit 1 character to Keyfile};
  BEGIN {PutIt}
        write(KeyFile, char(c));
  END {PutIt};

BEGIN {MAKEKEY}
    if ParamCount <> 1 THEN
        BEGIN
        writeln('Oops! usage:   MAKEKEY   Myfile.KEY');
        Die
        END;
    Assign (KeyFile, ParamStr(1));
    {$I-} {ensure no crash on cantopen}
    ReWrite(KeyFile);
    IF IORESULT <> 0 THEN
       BEGIN
       Writeln('Oops! Cannot create file ',Paramstr(1),
       ' -- probably no such subdirectory');
       Die
       END;
    {$I+}
    ClrScr;
    Writeln('MakeKey 2.0 creating file ',Paramstr(1));
    Writeln('Hit Random keys with Random times between keystrokes.');
    Writeln('Do not use auto-repeat!');
    Writeln('Hit Ctrl-Z when done.');
    Writeln;    Writeln;    Writeln;
    Writeln('count random');
       lastc := 0;
       totcap := 0;
       c := GetIt;
          WHILE c >= 0 Do
            BEGIN
            PutIt(c);
            c:=GetIt
            END; {WHILE}
   GOTOXY(1,10);
   Close (Keyfile);

END {MAKEKEY}.
