--  ALECmd.mesa  
--    Edited by Sweet,  4-Feb-81 13:10:29

DIRECTORY
  ALEOps,
  Ascii,
  FrameDefs,
  ImageDefs,
  MiscOps,
  ProcessDefs,
  Window;

ALECmd: PROGRAM 
  IMPORTS 
    ALEOps, FrameDefs, ImageDefs, MiscOps, Window 
  EXPORTS ALEOps =
  BEGIN OPEN ALEOps;
  DrawSource: PROC  [place: Window.Place] =
    BEGIN
    IF ~sourceWindow.notInTree THEN Window.RemoveFromTree[sourceWindow];
    Window.Slide[sourceWindow, [x: place.x - 7, y: place.y - 4]];
    IF sourceWindow.notInTree THEN 
      BEGIN
      sourceWindow.sibling ← SELECT TRUE FROM
        ~destWindow.notInTree => destWindow,
        ~originWindow.notInTree => originWindow,
        ENDCASE => NIL;
      Window.InsertIntoTree[sourceWindow];
      END;
    Window.InvalidateBox[feedbackWindow, sourceValueBox];
    END;

  DrawDest: PROC [place: Window.Place] =
    BEGIN
    IF ~destWindow.notInTree THEN Window.RemoveFromTree[destWindow];
    Window.Slide[destWindow, [x: place.x, y: place.y - 4]];
    IF destWindow.notInTree THEN 
      BEGIN
      destWindow.sibling ← SELECT TRUE FROM
        ~sourceWindow.notInTree => sourceWindow,
        ~originWindow.notInTree => originWindow,
        ENDCASE => NIL;
      Window.InsertIntoTree[destWindow];
      END;
    Window.InvalidateBox[feedbackWindow, destValueBox];
    END;

  DrawUpper: PROC [place: Window.Place] =
    BEGIN
    IF ~upperWindow.notInTree THEN Window.RemoveFromTree[upperWindow];
    Window.Slide[upperWindow, place];
    IF upperWindow.notInTree THEN 
      BEGIN
      upperWindow.sibling ← SELECT TRUE FROM
        ~lowerWindow.notInTree => lowerWindow,
        ~destWindow.notInTree => destWindow,
        ~sourceWindow.notInTree => sourceWindow,
        ~originWindow.notInTree => originWindow,
        ENDCASE => NIL;
      Window.InsertIntoTree[upperWindow];
      END;
    END;

  DrawLower: PROC [place: Window.Place] =
    BEGIN
    IF ~lowerWindow.notInTree THEN Window.RemoveFromTree[lowerWindow];
    Window.Slide[lowerWindow, [x: place.x - 7, y: place.y - 7]];
    IF lowerWindow.notInTree THEN 
      BEGIN
      lowerWindow.sibling ← SELECT TRUE FROM
        ~upperWindow.notInTree => upperWindow,
        ~destWindow.notInTree => destWindow,
        ~sourceWindow.notInTree => sourceWindow,
        ~originWindow.notInTree => originWindow,
        ENDCASE => NIL;
      Window.InsertIntoTree[lowerWindow];
      END;
    END;

  Print: PROC [file: STRING] =
    BEGIN
    ENABLE UNWIND => GiveBackKeys[];
    box: ABox ← [x1: 0, y1: 0, x2: LAST[LONG INTEGER], y2: LAST[LONG INTEGER]];
    inches8: ADistance = (8*LONG[16*12*16])/LONG[state.sixteenthsPerFoot];
    inches10: ADistance = (10*LONG[16*12*16])/LONG[state.sixteenthsPerFoot];
    IF upperWindow.notInTree AND lowerWindow.notInTree THEN
      {PressPicture[file]; GO TO done};
    IF ~upperWindow.notInTree THEN
      BEGIN
      pos: APosition = APosForPlace[upperWindow.box.place];
      box.x1 ← pos.x; box.y1 ← pos.y;
      END;
    IF ~lowerWindow.notInTree THEN
      BEGIN
      place: Window.Place = lowerWindow.box.place;
      pos: APosition = APosForPlace[[x: place.x+7, y: place.y+7]];
      box.x2 ← pos.x; box.y2 ← pos.y;
      END;
    IF box.x2 < box.x1 OR box.y2 < box.y1 THEN
      {OutString[" invalid box"L]; RETURN};
    IF box.x2 - box.x1 ~IN [0..inches8] OR (box.y2-box.y1) ~IN [0..inches10] THEN
      BEGIN
      pos: APosition = [
	x: MIN[box.x2, box.x1 + inches8],
	y: MIN[box.y2, box.y1 + inches10]];
      DrawLower[PicturePlace[pos]];
      Window.ValidateTree[lowerWindow];
      OutString["box trimmed, ok?"L];
      IF ~Confirm[] THEN GO TO done;
      box.x2 ← pos.x; box.y2 ← pos.y;
      END
    ELSE
      BEGIN
      IF ~upperWindow.notInTree THEN Window.RemoveFromTree[upperWindow];
      IF ~lowerWindow.notInTree THEN Window.RemoveFromTree[lowerWindow];
      END;
    PressPictureInABox[file, box];
    GO TO done;
    EXITS
      done => {GiveBackKeys[]; RETURN};
    END;

  BitmapBox: PUBLIC Window.Box;
  state: PUBLIC State;

  SELECT TRUE FROM
    FrameDefs.IsBound[ImageDefs.MakeCheckPoint] =>
      [] ← ImageDefs.MakeCheckPoint["ALE.image"];
    FrameDefs.IsBound[ImageDefs.MakeImage] =>
      {ImageDefs.MakeImage["ALE.image"]; MiscOps.ReleaseDebuggerBitmap[]};
    ENDCASE;
  state ← [
    displayTicks: TRUE,
    showingLabels: TRUE,
    grain: 2,
    magnify: 1,
    minMagnify: 1,
    currentWidth: 1,
    currentTexture: solid,
    currentLabelMode: portrait,
    currentFont: small,
    sixteenthsPerFoot: 4,
    blowup: 1];

  InitLines[];
  BitmapBox ← [[x: 16, y: 32], [w: 576, h: 752]];
  StartDisplay[];
  StartMouseHandler[];
  DO
    op: Operation = GetCmd[];
    WITH op SELECT FROM
      drawSource => DrawSource[place];
      drawDest => DrawDest[place];
      drawUpper => DrawUpper[place];
      drawLower => DrawLower[place];
      setOrigin => ASetOriginPos[pos];
      showTicks =>
	IF state.displayTicks THEN
	  BEGIN
	  state.displayTicks ← FALSE;
	  DisplayBoxTicks[FALSE];
	  END
	ELSE
	  BEGIN
          MarksOut[];
	  state.displayTicks ← TRUE;
	  DisplayBoxTicks[TRUE];
          MarksIn[];
	  END;
      drawOrigin =>
        BEGIN
        MarksOut[];
	Window.Slide[originWindow, [x: place.x - 5, y: place.y - 5]];
	Window.InvalidateBox[feedbackWindow, 
	  [[0,0], FeedbackBox.dims]];
        MarksIn[];
        END;
      undrawSource => 
        IF ~sourceWindow.notInTree THEN Window.RemoveFromTree[sourceWindow];
      undrawDest => 
        IF ~destWindow.notInTree THEN Window.RemoveFromTree[destWindow];
      undrawUpper => 
        IF ~upperWindow.notInTree THEN Window.RemoveFromTree[upperWindow];
      undrawLower => 
        IF ~lowerWindow.notInTree THEN Window.RemoveFromTree[lowerWindow];
      draw => {DrawLine[from, to]; pictureChanged ← TRUE; ASetSourcePos[to]};
      drawRect =>
        BEGIN
	deltaY: LONG CARDINAL = ABS[to.y - from.y];
	deltaX: LONG CARDINAL = ABS[to.x - from.x];
        newDest: APosition ← to;
        IF deltaY < deltaX THEN newDest.y ← from.y
	ELSE newDest.x ← from.x;
	IF newDest # to THEN ASetDestPos[newDest];
	DrawLine[from, newDest]; pictureChanged ← TRUE;
        ASetSourcePos[newDest];
	END;
      repaint =>
	Window.InvalidateBox[pictureWindow, [PicturePlace[cornerPos], FrameBox.dims]];
      reset => 
	BEGIN
	ResetLines[];
	Window.InvalidateBox[pictureWindow, [PicturePlace[cornerPos], FrameBox.dims]];
	ClearText[]; pictureChanged ← FALSE;
	END;
      slide => SlideCorner[pos];
      zoomIn => ZoomDetail[p1, p2];
      zoomOut => ZoomGlobal[];
      redrawSelections => 
        {RedrawSelections[]; ClearText[]; pictureChanged ← TRUE};
      pressOut => Print[file];
      jamOut => JamPicture[file];
      collectLabel => {CollectLabel[c, pos]; pictureChanged ← TRUE};
      readIn => {ReadPicture[file]; ClearText[]; pictureChanged ← FALSE};
      writeOut => {WritePicture[file]; ClearText[]; pictureChanged ← FALSE};
      newSelection => {ClearSelections[]; AddSelection[pos]};
      addSelection => AddSelection[pos];
      subSelection => SubSelection[pos];
      delete => {DeleteSelections[]; pictureChanged ← TRUE};
      undelete => {UndeleteItems[]; pictureChanged ← TRUE};
      sourceToClose => SourceToClosePoint[pos];
      destToClose => DestToClosePoint[pos];
      boxSelection => SelectInBox[pos1, pos2];
      move => {MoveSelections[delta]; pictureChanged ← TRUE};
      xlateAndRotate => {MoveAndRotate[source, dest]; pictureChanged ← TRUE};
      dimensionSelection => {DimSelection[pos, feet]; pictureChanged ← TRUE};
      copy => {CopySelections[delta]; pictureChanged ← TRUE};
      ENDCASE;
    Window.ValidateTree[];
    ENDLOOP;
  END.