(*-------------------------------------------------------------------------*)
(*                                                                         *)
(*                    This handles PrintIt!'s Display                      *)
(*                                                                         *)
(*-------------------------------------------------------------------------*)

IMPLEMENTATION MODULE PrintItDisplay;

(*-------------------------  IMPORTs:  ------------------------------------*)

(*------  SYSTEM:  ------*)
FROM SYSTEM    IMPORT ADR, ADDRESS, SHIFT, BITSET, LONGSET, CAST;
FROM Arts      IMPORT TermProcedure;

(*------  Libraries:  ------*)
FROM Intuition IMPORT Gadget, GadgetFlags, GadgetFlagSet, boolGadget,
                      ActivationFlags, ActivationFlagSet, WindowPtr,
                      NewWindow, WindowFlags, WindowFlagSet, ScreenFlags,
                      ScreenFlagSet, IDCMPFlags, IDCMPFlagSet, OpenWindow,
                      CloseWindow, RefreshGadgets, strGadget, StringInfo,
                      IntuiMessagePtr, GadgetPtr, MakeScreen, ScreenToFront,
                      WBenchToFront;
FROM Graphics  IMPORT SetAPen, SetBPen, SetDrMd, RastPortPtr, RectFill,
                      Move, Draw, Text, jam1, jam2, ViewModes, ViewModeSet,
                      BltClear, SetRGB4, ReadPixel, WritePixel;
FROM Exec      IMPORT WaitPort, GetMsg, ReplyMsg;

(*------  Standard:  ------*)
FROM Strings   IMPORT Length;

(*-------------------  Variables from Definition:  --------------------------

TYPE
  Gadgets = (hori1ID,hori2ID,hori3ID,hori4ID,hori5ID,hori6ID,hori7ID,hori8ID,
             vert1ID,vert2ID,vert3ID,vert4ID,vert5ID,vert6ID,vert7ID,vert8ID,
             PrintNormalID,PrintDoubleID,DpiH60ID,DpiH72ID,DpiH80ID,DpiH90ID,
             DpiH120ID,DpiH144ID,DpiH240ID,DpiV72ID,DpiV144ID,DpiV216ID,
             PositiveID,RepHorID,RepVerID,PrintItID,LoadPicID,ResetID);
  TextType = ARRAY[0..79] OF CHAR;

VAR
  Window: WindowPtr;
  Gadgs: ARRAY Gadgets OF Gadget;
  StrInfo: ARRAY[RepHorID..RepVerID] OF StringInfo;
  Buffers: ARRAY[RepHorID..RepVerID] OF ARRAY[0..9] OF CHAR;
  RP: RastPortPtr;
  PixName: TextType;                    (* Pic's Name                 *)
  StretchX: CARDINAL;                   (* horizontal Stretch-Value   *)
  StretchY: CARDINAL;                   (* vertical Stretch-Value     *)
  DoublePrint: BOOLEAN;                 (* Print it Twice ?           *)
  Positive: BOOLEAN;                    (* Reverse or not ?           *)
  xRes: Gadgets;                        (* horizontal DPI (DpiHxxID)  *)
  yRes: Gadgets;                        (* vertical DPI (DpiVxxID)    *)
  Screen: ScreenPtr;                    (* Screen containing Picture  *)
  Shade: CARDINAL;                      (* For Color -> BW conversion *)

-----------------------  Internal needed Variables:  ----------------------*)

VAR
  IDCount: Gadgets;
  NuWindow: NewWindow;
  i,j,k: CARDINAL;
  ii: LONGCARD;
  NameWindow, ConvertWindow: WindowPtr;
  TextGadg,OKGadg: Gadget;
  TextInfo: StringInfo;
  ShadeGadget: ARRAY[0..15] OF Gadget;
  UsePlaneGadget, ConvertGadget: Gadget;
  gadget: GadgetPtr;
  PlaneString: ARRAY[0..1] OF CHAR;
  Msg: IntuiMessagePtr;
  map: ADDRESS;
  LightColors: LONGSET;
  WordPtr: POINTER TO BITSET;
  Color: CARDINAL;
  li: LONGINT;
  PlanePtrs: ARRAY[0..7] OF POINTER TO BITSET;
  Words: ARRAY[0..7] OF BITSET;
  Word: BITSET;

(*----------------------  Internal Procedures:  ---------------------------*)

(*------  Set a Bool-Gadget:  ------*)

PROCEDURE SetBool(VAR Gadg: Gadget; x,y,w,h: INTEGER);

BEGIN
  WITH Gadg DO
    nextGadget := NIL;
    leftEdge := x;  topEdge := y;
    width    := w;  height  := h;
    flags    := GadgetFlagSet{};
    activation   := ActivationFlagSet{gadgImmediate,toggleSelect};
    gadgetType   := boolGadget;
    gadgetRender := NIL;
    selectRender := NIL;
    gadgetText   := NIL;
    mutualExclude:= LONGSET{};
    specialInfo  := NIL;
    gadgetID := 0;
    userData := NIL;
  END;
END SetBool;

(*------  Draw A Box:  ------*)

PROCEDURE Box(rp: RastPortPtr; x,y,X,Y: INTEGER);

BEGIN
  Move(rp,x,y); Draw(rp,X,y); Draw(rp,X,Y); Draw(rp,x,Y); Draw(rp,x,y);
END Box;

(*------  Type Text:  ------*)

TYPE
  TypeTextType = POINTER TO ARRAY[0..999] OF CHAR;

PROCEDURE Type(rp: RastPortPtr; x,y: INTEGER; text:TypeTextType);

BEGIN
  Move(rp,x,y); Text(rp,text,Length(text^));
END Type;

(*-------------------------------------------------------------------------*)
(*                                                                         *)
(*                          Open the Screen:                               *)
(*                                                                         *)
(*-------------------------------------------------------------------------*)

PROCEDURE OpenPrintIt();

BEGIN

(*------  Gadgets:  ------*)

  FOR IDCount := hori1ID TO hori8ID DO
    SetBool(Gadgs[IDCount],129+16*ORD(IDCount),27,15,11);
  END;
  FOR IDCount := vert1ID TO vert8ID DO
    SetBool(Gadgs[IDCount],1+16*ORD(IDCount),43,15,11);
  END;
  SetBool(Gadgs[PrintNormalID], 77, 59, 79,11);
  SetBool(Gadgs[PrintDoubleID],157, 59, 79,11);
  FOR IDCount := DpiH60ID TO DpiH90ID DO
    SetBool(Gadgs[IDCount],65+24*(ORD(IDCount)-ORD(DpiH60ID)),75,23,11);
  END;
  FOR IDCount := DpiH120ID TO DpiH240ID DO
    SetBool(Gadgs[IDCount],161+32*(ORD(IDCount)-ORD(DpiH120ID)),75,31,11);
  END;
  SetBool(Gadgs[DpiV72ID  ], 65, 91, 63,11);
  SetBool(Gadgs[DpiV144ID ],129, 91, 63,11);
  SetBool(Gadgs[DpiV216ID ],193, 91, 63,11);
  SetBool(Gadgs[PositiveID],  9, 43, 64,11);
  FOR IDCount := RepHorID TO RepVerID DO
    SetBool(Gadgs[IDCount  ],116+96*(ORD(IDCount)-ORD(RepHorID)),108,40,8);
    WITH Gadgs[IDCount] DO
      activation  := ActivationFlagSet{relVerify,stringCenter,longint};
      gadgetType  := strGadget;
      specialInfo := ADR(StrInfo[IDCount]);
    END;
    WITH StrInfo[IDCount] DO
      buffer := ADR(Buffers[IDCount]);
      undoBuffer := NIL;
      bufferPos := 0;
      maxChars := 6;
      dispPos := 0;
      numChars := 2;
      longInt := 1;
    END;
    Buffers[IDCount] := "1";
  END;
  SetBool(Gadgs[PrintItID ],  9,123,111,11);
  SetBool(Gadgs[LoadPicID ],  9,135,111,11);
  SetBool(Gadgs[ResetID   ],  9,147,111,11);

(*------  Link Gadgets:  ------*)

  FOR IDCount := hori1ID TO LoadPicID DO
    WITH Gadgs[IDCount] DO
      nextGadget := ADR(Gadgs[Gadgets(ORD(IDCount)+1)]);
      gadgetID := ORD(IDCount);
    END;
  END;
  WITH Gadgs[ResetID] DO
    nextGadget := NIL;
    gadgetID := ORD(ResetID)
  END;

(*------  Window:  ------*)

  WITH NuWindow DO
    leftEdge   := 188;  topEdge   := 47;
    width      := 264;  height    := 162;
    detailPen  := 0;    blockPen  := 1;
    idcmpFlags := IDCMPFlagSet{gadgetDown,closeWindow};
    flags      := WindowFlagSet{windowDrag,windowDepth,windowClose,activate,
                                noCareRefresh};
    firstGadget:= ADR(Gadgs);
    checkMark  := NIL;
    title      := ADR("Print It !");
    screen     := NIL;
    bitMap     := NIL;
    type       := ScreenFlagSet{wbenchScreen};
  END;

  Window := OpenWindow(NuWindow);
  RP := Window^.rPort;

(*------  Draw into Window:  ------*)

  SetAPen(RP,2); SetDrMd(RP,jam1);
  FOR i:= 128 TO 240 BY 16 DO
    Box(RP,i,26,i+16,38);
    Box(RP,i,42,i+16,54);
  END;
  Box(RP, 76, 58,236, 70); Move(RP,156,58); Draw(RP,156,70);
  Box(RP,  8, 42, 73, 54);
  FOR i:=64 TO 144 BY 24 DO
    Box(RP,i,74,i+24,86);
  END;
  FOR i:= 160 TO 224 BY 32 DO
    Box(RP,i,74,i+32,86);
  END;
  FOR i:= 64 TO 192 BY 64 DO
    Box(RP,i,90,i+64,102);
  END;
  Box(RP,112,106,160,118); Box(RP,208,106,256,118);
  FOR i:= 122 TO 146 BY 12 DO
    Box(RP,8,i,120,i+12);
  END;
  Box(RP,136,124,248,156);

(*------  Type Text into Window:  -------*)

  SetAPen(RP,1);
  Type(RP,  8, 23,ADR("Pic:"));
  Type(RP,  8, 35,ADR("Stretch:"));
  Type(RP, 80, 35,ADR("hori:"));
  Type(RP, 80, 51,ADR("vert:"));
  Type(RP,132, 35,ADR("1 2 3 4 5 6 7 8"));
  Type(RP,132, 51,ADR("1 2 3 4 5 6 7 8"));
  Type(RP,  8, 67,ADR("Print:"));
  Type(RP, 92, 67,ADR("Single    Double"));
  Type(RP,  8, 92,ADR("Dpi:"));
  Type(RP, 32, 83,ADR("hor:"));
  Type(RP, 32, 99,ADR("ver:   72"));
  Type(RP, 68, 83,ADR("60 72 80 90 120 144 240"));
  Type(RP,148, 99,ADR("144     216"));
  Type(RP,  8,115,ADR("Repeat: hor:        ver:"));
  Type(RP, 24,131,ADR("Print It !"));
  Type(RP, 32,143,ADR("Load Pic"));
  Type(RP, 44,155,ADR("Reset"));

END OpenPrintIt;

(*-------------------------------------------------------------------------*)
(*                                                                         *)
(*                          Get Picture's Name                             *)
(*                                                                         *)
(*-------------------------------------------------------------------------*)

PROCEDURE GetName();

BEGIN

(*------  Gadgets:  ------*)

  SetBool(OKGadg  ,184, 30, 47,11);
  SetBool(TextGadg, 12, 16,216, 8);
  WITH TextGadg DO
    nextGadget  := ADR(OKGadg);
    activation  := ActivationFlagSet{relVerify,stringCenter};
    gadgetType  := strGadget;
    specialInfo := ADR(TextInfo);
  END;
  WITH TextInfo DO
    buffer := ADR(PixName);
    undoBuffer := NIL;
    bufferPos := 0;
    maxChars := 80;
    dispPos := 0;
    numChars := Length(PixName);
  END;

(*------  Window:  ------*)

  WITH NuWindow DO
    leftEdge   := 200;  topEdge   := 105;
    width      := 240;  height    := 46;
    detailPen  := 0;    blockPen  := 1;
    idcmpFlags := IDCMPFlagSet{gadgetDown,gadgetUp};
    flags      := WindowFlagSet{windowDrag,activate,noCareRefresh};
    firstGadget:= ADR(TextGadg);
    checkMark  := NIL;
    title      := ADR("Print It ! Picture's Name:");
    screen     := NIL;
    bitMap     := NIL;
    type       := ScreenFlagSet{wbenchScreen};
  END;
  NameWindow := OpenWindow(NuWindow);

(*------  Draw into Window:  ------*)

  WITH NameWindow^ DO
    SetAPen(rPort,2); SetDrMd(rPort,jam1);
    Move(rPort,  8, 14); Draw(rPort,232, 14); Draw(rPort,232, 26);
    Draw(rPort,  8, 26); Draw(rPort,  8, 14);
    Move(rPort,184, 30); Draw(rPort,232, 30); Draw(rPort,232, 42);
    Draw(rPort,184, 42); Draw(rPort,184, 30);
    SetAPen(rPort,1);
    Type(rPort,200, 39,ADR("OK"));
  END;

(*------  Wait for Input:  ------*)

  WaitPort(NameWindow^.userPort);

  CloseWindow(NameWindow);
  NameWindow := NIL;

END GetName;

(*-------------------------------------------------------------------------*)
(*                                                                         *)
(*                    Set Gadgets to their values:                         *)
(*                                                                         *)
(*-------------------------------------------------------------------------*)

PROCEDURE InitPrintIt();

VAR
  ax,ay: LONGINT; (* to draw Aspect *)

BEGIN

  RefreshGadgets(ADR(Gadgs),Window,NIL);

(*------  Set Gadgets to their values:  ------*)

  FOR IDCount := hori1ID TO ResetID DO
    WITH Gadgs[IDCount] DO
      flags := flags - GadgetFlagSet{selected};
    END;
  END;
  INCL(Gadgs[Gadgets(StretchX-1)].flags,selected);
  INCL(Gadgs[Gadgets(StretchY+7)].flags,selected);
  IF DoublePrint THEN
    INCL(Gadgs[PrintDoubleID].flags,selected);
  ELSE
    INCL(Gadgs[PrintNormalID].flags,selected);
  END;
  SetDrMd(RP,jam2); SetAPen(RP,1); SetBPen(RP,0);
  IF Positive THEN
    Type(RP,9,51,ADR("Positive"));
  ELSE
    Type(RP,9,51,ADR("Negative"));
  END;
  INCL(Gadgs[xRes].flags,selected);
  INCL(Gadgs[yRes].flags,selected);

(*------  Type Pic's Name:  ------*)

  SetAPen(RP,0); SetDrMd(RP,jam1);
  RectFill(RP,48,16,256,24);
  SetAPen(RP,1);
  Type(RP,48,23,ADR(PixName));

(*------  Refresh:  ------*)

  RefreshGadgets(ADR(Gadgs),Window,NIL);

(*------  Aspect:  ------*)

  SetAPen(RP,0); SetDrMd(RP,jam1);
  RectFill(RP,137,125,247,155);
  WITH Screen^ DO
    ax := LONGINT(Screen^.width ) * LONGINT(StretchX) * 2;
    ay := LONGINT(Screen^.height) * LONGINT(StretchY);
  END;
  CASE xRes OF
    DpiH60ID:  ay := ay *  60; |
    DpiH72ID:  ay := ay *  72; |
    DpiH80ID:  ay := ay *  80; |
    DpiH90ID:  ay := ay *  90; |
    DpiH120ID: ay := ay * 120; |
    DpiH144ID: ay := ay * 144; |
    DpiH240ID: ay := ay * 216; |
  END;
  CASE yRes OF
    DpiV72ID:  ax := ax *  72; |
    DpiV144ID: ax := ax * 144; |
    DpiV216ID: ax := ax * 216; |
  END;
  IF (ax * 28 DIV ay) > 108 THEN
    ay := ay * 54 DIV ax;
    ax := 54;
  ELSE
    ax := ax * 14 DIV ay;
    ay := 14;
  END;
  SetAPen(RP,2);
  RectFill(RP,192-ax,140-ay,192+ax,140+ay);
  SetAPen(RP,1);
  Type(RP,168,143,ADR("Aspect"));

END InitPrintIt;

(*-------------------------------------------------------------------------*)
(*                                                                         *)
(*               Ask to Convert Colors and do it after that:               *)
(*                                                                         *)
(*-------------------------------------------------------------------------*)

PROCEDURE Convert();

BEGIN

(*------  Gadgets:  ------*)

  FOR i:=0 TO 15 DO
    SetBool(ShadeGadget[i],9+i*24,25,23,11);
    ShadeGadget[i].gadgetID := i;
  END;
  SetBool(UsePlaneGadget,  9,45,127,11);
  SetBool(ConvertGadget ,265,45,127,11);
  FOR i:=0 TO 14 DO
    ShadeGadget[i].nextGadget := ADR(ShadeGadget[i+1]);
  END;
  ShadeGadget[15].nextGadget := ADR(UsePlaneGadget);
  UsePlaneGadget.nextGadget := ADR(ConvertGadget);

(*------  Window:  ------*)

  WITH NuWindow DO
    leftEdge   := 120;  topEdge   := 98;
    width      := 400;  height    := 60;
    detailPen  := 0;    blockPen  := 1;
    idcmpFlags := IDCMPFlagSet{gadgetDown,gadgetUp};
    flags      := WindowFlagSet{windowDrag,activate,noCareRefresh};
    firstGadget:= ADR(ShadeGadget);
    checkMark  := NIL;
    title      := ADR("Print It !");
    screen     := NIL;
    bitMap     := NIL;
    type       := ScreenFlagSet{wbenchScreen};
  END;
  ConvertWindow := OpenWindow(NuWindow);

(*------  Draw into Window:  ------*)

  WITH ConvertWindow^ DO
    SetAPen(rPort,1); SetDrMd(rPort,jam1);
    Type(rPort,  8,19,ADR("That's a Color Picture !"));
    Type(rPort, 16,33,ADR("0  1  2  3  4  5  6  7  8  9"));
    Type(rPort,252,33,ADR("10 11 12 13 14 15"));
    Type(rPort, 16,53,ADR("Use Plane #                      Convert Pic."));
    SetAPen(rPort,2);
    FOR i:=8 TO 368 BY 24 DO
      Box(rPort,i,24,i+24,36);
    END;
    Box(rPort,  8,44,136,56);
    Box(rPort,264,44,392,56);
    IF Shade < Screen^.bitMap.depth THEN
      PlaneString[0] := CHAR(Shade+ORD("0"));
    ELSE
      PlaneString[0] := "0";
    END;
    PlaneString[1] := CHAR(0);
    WITH ConvertWindow^ DO
      SetDrMd(rPort,jam2); SetAPen(rPort,1); SetBPen(rPort,0);
      Type(rPort,112,53,ADR(PlaneString));
    END;
  END;
  INCL(ShadeGadget[Shade].flags,selected);
  RefreshGadgets(ADR(ShadeGadget),ConvertWindow,NIL);

(*------  Wait for Input:  ------*)

  LOOP
    WaitPort(ConvertWindow^.userPort);
    Msg := GetMsg(ConvertWindow^.userPort);
    gadget := Msg^.iAddress;
    ReplyMsg(Msg);
    IF    (gadget=ADR(UsePlaneGadget)) OR (gadget=ADR(ConvertGadget)) THEN
      EXIT
    ELSE
      gadget^.flags := gadget^.flags / GadgetFlagSet{selected};
      RefreshGadgets(ADR(ShadeGadget),ConvertWindow,NIL);
      INCL(gadget^.flags,selected);
      WITH ShadeGadget[Shade] DO
        flags := flags - GadgetFlagSet{selected};
      END;
      Shade := gadget^.gadgetID;
      IF Shade < Screen^.bitMap.depth THEN
        PlaneString[0] := CHAR(Shade+ORD("0"));
      ELSE
        PlaneString[0] := "0";
      END;
      PlaneString[1] := CHAR(0);
      WITH ConvertWindow^ DO
        SetDrMd(rPort,jam2); SetAPen(rPort,1); SetBPen(rPort,0);
        Type(rPort,112,53,ADR(PlaneString));
      END;
    END;
  END;

  ScreenToFront(Screen);

  WITH Screen^ DO
    IF gadget=ADR(ConvertGadget) THEN
(*------  Convert Pic:  ------*)
      WordPtr := viewPort.colorMap^.colorTable;
      LightColors := LONGSET{};
      FOR i:=0 TO viewPort.colorMap^.count-1 DO
        Color :=   SHIFT(CAST(CARDINAL,WordPtr^ * {8..11}),-8)
                 + SHIFT(CAST(CARDINAL,WordPtr^ * {4..7} ),-4)
                 + CAST(CARDINAL,WordPtr^ * {0..3});
        Color := Color DIV 3;
        IF Color>=Shade THEN
          INCL(LightColors,i);
        END;
        INC(WordPtr,2);
      END;
      SetRGB4(ADR(viewPort),0,15,15,15); (* white *)
      SetRGB4(ADR(viewPort),1, 0, 0, 0); (* black *)
      FOR i:=0 TO bitMap.depth-1 DO
        PlanePtrs[i] := bitMap.planes[i];
      END;
      FOR ii:=0 TO bitMap.bytesPerRow * bitMap.rows - 2 BY 2 DO
        FOR j:=0 TO bitMap.depth-1 DO
          Words[j] := PlanePtrs[j]^;
        END;
        FOR j:=0 TO 15 DO
          Color := 0;
          k:=bitMap.depth;
          WHILE k>0 DO
            DEC(k);
            Color := SHIFT(Color,1);
            IF j IN Words[k] THEN
              INC(Color);
            END;
          END;
          IF Color IN LightColors THEN
            Word := Word - {j};
          ELSE
            INCL(Word,j);
          END;
        END;
        PlanePtrs[0]^ := Word;
        INC(PlanePtrs[0],2);
        j := 1;
        WHILE j < bitMap.depth DO
          PlanePtrs[j]^ := {};
          INC(PlanePtrs[j],2);
          INC(j);
        END;
      END;
    ELSE
(*------  Delete unwanted Planes:  ------*)
      SetRGB4(ADR(viewPort),0,15,15,15); (* white *)
      SetRGB4(ADR(viewPort),1, 0, 0, 0); (* black *)
      IF (Shade<bitMap.depth) AND (Shade#0) THEN
        map := bitMap.planes[Shade];
        bitMap.planes[Shade] := bitMap.planes[0];
        bitMap.planes[0] := map;
      END;
      i := 1;
      WHILE i<bitMap.depth DO
        BltClear(bitMap.planes[i],bitMap.bytesPerRow * bitMap.rows,0);
        INC(i);
      END;
    END;
  END;
  MakeScreen(Screen);

  IF WBenchToFront() THEN END;
  CloseWindow(ConvertWindow);
  ConvertWindow := NIL;

END Convert;

(*------------------------------  CleanUp:  -------------------------------*)

PROCEDURE CleanUp();

BEGIN
  IF NameWindow#NIL THEN CloseWindow(NameWindow) END;
  IF ConvertWindow#NIL THEN CloseWindow(ConvertWindow) END;
END CleanUp;

(*---------------------------  Initialization:  ---------------------------*)

BEGIN
  StretchX := 1; StretchY := 1;
  DoublePrint := FALSE;
  xRes := DpiH240ID;
  yRes := DpiV216ID;
  Positive := TRUE;
  NameWindow := NIL;
  ConvertWindow := NIL;
  PixName := "Name.iff";
  Shade := 8;
  TermProcedure(CleanUp);
END PrintItDisplay.
