-- ppkint.mesa
--  keyboard interrupt routines for silicon (pretty picture) program
-- last edited by McCreight, December 16, 1982  12:00 PM

DIRECTORY
  ProcessDefs,
  FrameDefs,
  ppddefs,
ppdddefs,
  ppdefs,
  multiGraphicsDefs,
  InlineDefs,
  SystemDefs;
ppkint: MONITOR
  IMPORTS ProcessDefs, FrameDefs, InlineDefs, multiGraphicsDefs, ppdddefs,ppdefs, ppddefs
  EXPORTS ppddefs,ppdefs =
  BEGIN OPEN InlineDefs, ppdddefs,ppdefs, ppddefs, multiGraphicsDefs;

  curx, cury: PUBLIC INTEGER;
  localx, localy: INTEGER;
  gridCol, gridBW: PUBLIC CARDINAL;
  savedCx, savedCy: INTEGER;

  tickCnt: CARDINAL ← 0;
  tickLimit: CARDINAL = 14;

  lev: ProcessDefs.InterruptLevel = 11;
  Keywakeup: CONDITION;
  aKey: CONDITION;

  kb: ARRAY [0..3] OF POINTER TO CARDINAL = [
    LOOPHOLE[177034B], LOOPHOLE[177035B], LOOPHOLE[177036B], LOOPHOLE[177037B]];
  oldkb, akb, akmb, kbd: ARRAY [0..3] OF CARDINAL;
  kbm: ARRAY [0..3] OF CARDINAL = [177777B, 177777B, 153676B, 177564B];

  MouseX: POINTER TO INTEGER = LOOPHOLE[424B];
  MouseY: POINTER TO INTEGER = LOOPHOLE[425B];
  curse: POINTER TO ARRAY [0..15] OF CARDINAL = LOOPHOLE[431B];
  CursX: POINTER TO INTEGER = LOOPHOLE[426B];
  CursY: POINTER TO INTEGER = LOOPHOLE[427B];

  mButs: POINTER TO CARDINAL = LOOPHOLE[177030B];
  amb, mb, oldmb: CARDINAL ← 0;
  mbmask: CARDINAL = 7;
  mbArray1: ARRAY [0..7] OF CARDINAL = [0, 1, 2, 2, 4, 4, 4, 4];
  --none,yel,blue,yb,red,yr,br,ybr
  mbArray2: ARRAY [0..4] OF CARDINAL = [0, 2, 3, 3, 1];

  kesMax: CARDINAL = 127;
  takek, kesi: CARDINAL;
  kes: ARRAY [0..kesMax] OF keyEvent;

  -- THE KEYS !:  BS,<bl-top>,xx,xx, LF,<bl-mid>,DEL,xx,
  -- \,],↑,<bl-bot>,  /,',RET,<sh-rt>,  P,COMMA,;,=,  -,L,.,[,
  -- K,O,<sh-lft>,SPC,  0,X,Z,LOCK,  V,I,B,M,  U,9,J,N,
  -- D,A,C,8,  7,S,CTRL,H,  E,Q,F,Y,
  -- 6,W,TAB,G,  4,2,ESC,T,  5,3,1,R

  kCode: PACKED ARRAY [0..63] OF [0..255] = [
    62B, 56B, 0, 0, 61B, 66B, 63B, 0, 54B, 55B, 57B, 67B, 51B, 52B, 60B, 0, 31B, 46B,
    44B, 45B, 47B, 25B, 50B, 53B, 24B, 30B, 0, 64B, 0B, 41B, 43B, 0, 37B, 22B,
    13B, 26B, 36B, 11B, 23B, 27B, 15B, 12B, 14B, 10B, 7B, 34B, 0, 21B, 16B, 32B,
    17B, 42B, 6B, 40B, 0, 20B, 4B, 2B, 65B, 35B, 5B, 3B, 1B, 33B];

  bwCursPnt: POINTER TO ARRAY [0..15] OF CARDINAL;
  cursorOnBW: PUBLIC BOOLEAN;

  initkbd: PUBLIC PROCEDURE [
    bp: POINTER TO ARRAY [0..15] OF CARDINAL, cp: POINTER TO Bitmap] =
    BEGIN
    i: CARDINAL;
    gridCol ← 8;
    gridBW ← 1;
    bwCursPnt ← bp;
    initCcurse[cp.nLines, cp];
    curx ← cury ← localx ← localy ← 200;
    drawColorCurs[200, 200];
    savedCx ← savedCy ← 200;
    cursorOnBW ← FALSE;
    FOR i IN [0..3] DO oldkb[i] ← 0; ENDLOOP;
    oldmb ← 0;
    FrameDefs.MakeCodeResident[FrameDefs.GlobalFrame[keybreak]];
    FrameDefs.MakeCodeResident[FrameDefs.GlobalFrame[doTemps]];
    FrameDefs.MakeCodeResident[FrameDefs.GlobalFrame[reDrawRect]];
    FrameDefs.MakeCodeResident[FrameDefs.GlobalFrame[SetupColorAreaBLT]];
    FrameDefs.MakeCodeResident[FrameDefs.GlobalFrame[cannonRect]];
    FrameDefs.MakeCodeResident[FrameDefs.GlobalFrame[deScaledCursor]];
    ProcessDefs.DisableTimeout[@Keywakeup];
    ProcessDefs.CV[lev] ← @Keywakeup;
    ProcessDefs.DIW↑ ← BITOR[ProcessDefs.DIW↑, BITSHIFT[1, lev]];
    ProcessDefs.Detach[FORK keybreak[]];
    END;
  keybreak: ENTRY PROCEDURE =
    BEGIN
    bitthing, i, b: CARDINAL;
    ke: keyEvent;
    ctrl: [0..255];
    c, n: [0..127];
    lockState, oldLockState: BOOLEAN ← FALSE;
    takek ← kesi ← 0;
    MouseX↑ ← MouseY↑ ← 0;
    ProcessDefs.SetPriority[ProcessDefs.DefaultPriority + 1];
    DO
      WAIT Keywakeup;

      lockState ← BITAND[kb[3]↑, 200B] = 0;

      n ← 4;
      FOR i IN [0..3] DO
        kbd[i] ← BITNOT[kb[i]↑];
        akmb[i] ← BITAND[kbd[i], kbm[i]];
        akb[i] ← BITAND[akmb[i], BITNOT[oldkb[i]]];
        IF akb[i] # 0 THEN n ← i;
        oldkb[i] ← BITAND[oldkb[i], kbd[i]];
        ENDLOOP;
      mb ← BITNOT[mButs↑];
      mb ← BITAND[mb, mbmask];
      amb ← BITXOR[mb, oldmb];
      IF MouseX↑ # 0 OR MouseY↑ # 0 THEN
        BEGIN
        localx ← localx + MouseX↑;
        localy ← localy + MouseY↑;
        IF localx < 0 THEN localx ← 0;
        IF localx > colWidth + 606 THEN localx ← colWidth + 606;
        IF localy < 0 THEN localy ← 0;
        IF localy > 808 THEN localy ← 808;
        MouseX↑ ← MouseY↑ ← 0;
        IF localx <= colWidth THEN
          BEGIN
          IF cursorOnBW THEN localy ← (localy*3)/5;
          IF localy > colHeight THEN localy ← colHeight;
          curx ← localx - (localx MOD gridCol);
          cury ← localy - (localy MOD gridCol);
          IF curx # savedCx OR cury # savedCy THEN
            BEGIN drawColorCurs[curx, cury]; savedCx ← curx; savedCy ← cury; END;
          IF cursorOnBW THEN
            BEGIN
            FOR i IN [0..15] DO curse↑[i] ← 0; ENDLOOP;
            cursorOnBW ← FALSE;
            END;
          END
        ELSE
          BEGIN
          IF NOT cursorOnBW THEN localy ← (localy*5)/3;
          IF localy > 808 THEN localy ← 808;
          IF localy < bwBottom THEN
            BEGIN
            curx ← localx - ((localx-colWidth) MOD gridBW);
            cury ← localy - (localy MOD gridBW);
            IF curx < colWidth THEN curx ← colWidth;
            END
          ELSE BEGIN curx ← localx; cury ← localy; END;
          IF NOT cursorOnBW THEN
            BEGIN
            undrawColorCurs[];
            FOR i IN [0..15] DO curse↑[i] ← bwCursPnt↑[i]; ENDLOOP;
            cursorOnBW ← TRUE;
            END;
          CursX↑ ← curx - colWidth;
          CursY↑ ← cury;
          END;
        END;
      ke.mx ← curx;
      ke.my ← cury;
      ctrl ← 0;
      IF BITAND[100B, kbd[2]] # 0 OR BITAND[10B, kbd[3]] # 0 THEN
        ctrl ← ctrl + 16;  --shift
      IF BITAND[4000B, kbd[2]] # 0 THEN ctrl ← ctrl + 4;  -- CTRL
      IF BITAND[20000B, kbd[2]] # 0 THEN ctrl ← ctrl + 8;  -- TAB
      ke.ctl ← ctrl;
      IF amb # 0 THEN
        BEGIN
        bitthing ← mbArray1[amb];
        oldmb ← BITXOR[oldmb, bitthing];
        IF BITAND[mb, bitthing] = 0 THEN  --if button up
          BEGIN
          ke.k ← 71B + mbArray2[bitthing];
          kesi ← kesi + 1;
          IF kesi > kesMax THEN kesi ← 0;
          kes[kesi] ← ke;
          BROADCAST aKey;
          END
        ELSE
          BEGIN
          ke.ctl ← BITOR[ctrl, mbArray2[bitthing]];
          ke.k ← 77B;
          FOR i IN [0..3] DO
            IF akmb[i] # 0 THEN
              BEGIN
              b ← akmb[i];
              c ← i;
              UNTIL BITAND[b, 1] # 0 DO c ← c + 4; b ← BITSHIFT[b, -1]; ENDLOOP;
              ke.k ← kCode[c];
              EXIT;
              END;
            ENDLOOP;
          kesi ← kesi + 1;
          IF kesi > kesMax THEN kesi ← 0;
          kes[kesi] ← ke;
          BROADCAST aKey;
          ke.ctl ← ctrl;
          END;
        END;
      IF n # 4 THEN
        BEGIN
        FOR i IN [0..3] DO
          IF akb[i] # 0 THEN
            BEGIN
            bitthing ← b ← akb[i];
            c ← i;
            UNTIL BITAND[b, 1] # 0 DO c ← c + 4; b ← BITSHIFT[b, -1]; ENDLOOP;
            ke.k ← kCode[c];
            EXIT;
            END;
          ENDLOOP;
        oldkb[n] ← BITOR[oldkb[n], bitthing];
        kesi ← kesi + 1;
        IF kesi > kesMax THEN kesi ← 0;
        kes[kesi] ← ke;
        BROADCAST aKey;
        END;
      tickCnt ← tickCnt + 1;
      IF tickCnt > tickLimit THEN
        BEGIN tickCnt ← 0; IF NOT cursorOnBW THEN doTemps[]; END;
      ENDLOOP;
    END;
  getKchr: PUBLIC ENTRY PROCEDURE RETURNS [ke: keyEvent] =
    BEGIN
    UNTIL takek # kesi DO WAIT aKey; ENDLOOP;
    takek ← takek + 1;
    IF takek > kesMax THEN takek ← 0;
    ke ← kes[takek];
    RETURN;
    END;
  anyKavail: PUBLIC ENTRY PROCEDURE RETURNS [BOOLEAN] =
    BEGIN RETURN[takek # kesi]; END;


  END.