-- Scale.mesa
-- a program to run within Chipmonk

-- written by E. McCreight, February 8, 1983  12:20 PM

DIRECTORY
  ChipUserInt,
  InlineDefs,
  ppddefs,
  ppdefs;

Scale: PROGRAM
  IMPORTS ChipUserInt, InlineDefs,
    ppddefs, ppdefs =
  BEGIN OPEN ChipUserInt, ppddefs, ppdefs;

  scaleN, scaleD: INTEGER;

  UnmarkList: PROCEDURE[head: listPtr,
    selectedOnly: BOOLEAN ← FALSE] =
    BEGIN
    FOR lp: listPtr ← head, lp.nxt WHILE lp#NIL DO
      UnmarkObject[lp.ob];
      ENDLOOP;
    END;

  UnmarkObject: PROCEDURE[ob: obPtr] =
    BEGIN
    ob.marked ← FALSE;
    WITH dob: ob SELECT FROM
      cell => UnmarkList[dob.ptr];
      ENDCASE => NULL;
    END;

  RescaleList: PROCEDURE[head: listPtr,
    selectedOnly: BOOLEAN ← FALSE] =
    BEGIN
    FOR lp: listPtr ← head, lp.nxt WHILE lp#NIL DO
      lp.lx ← Rescale[lp.lx];
      lp.ly ← Rescale[lp.ly];
      IF NOT selectedOnly OR lp.selected THEN
        BEGIN
        RescaleObject[lp.ob];
        END;
      ENDLOOP;
    END;

  RescaleObject: PROCEDURE[ob: obPtr] =
    BEGIN
    IF NOT ob.marked THEN
      BEGIN
      ob.marked ← TRUE;
      ob.size[0] ← ob.size[2] ← Rescale[ob.size[0]];
      ob.size[1] ← Rescale[ob.size[1]];
      ob.surround ← Rescale[ob.surround];
      WITH dob: ob SELECT FROM
        xstr =>
          BEGIN
          dob.width ← Rescale[dob.width];
          dob.length ← Rescale[dob.length];
          dob.wExt ← Rescale[dob.wExt];
          dob.lExt ← Rescale[dob.lExt];
          END;
        cell => RescaleList[dob.ptr];
        cont =>
          BEGIN
          dob.magicN ← Rescale[dob.magicN];
          dob.m2Ext ← Rescale[dob.m2Ext];
          dob.c2Ext ← Rescale[dob.c2Ext];
          dob.lExt ← Rescale[dob.lExt];
          dob.wExt ← Rescale[dob.wExt];
          END;
        bus =>
          BEGIN
          dob.wspace ← Rescale[dob.wspace];
          dob.firstLength ← Rescale[dob.firstLength];
          dob.topIncr ← Rescale[dob.topIncr];
          dob.lenIncr ← Rescale[dob.lenIncr];
          dob.offsetFirst ← Rescale[dob.offsetFirst];
          dob.wwidth ← Rescale[dob.wwidth];
          END;
        ENDCASE => NULL;
      END;
    END;

  Rescale: PROC [x: locNum] RETURNS [locNum] =
    {RETURN[NarrowToInteger[(LONG[x]*scaleN)/scaleD]]};

  NarrowToInteger: PROC [x: LONG INTEGER] RETURNS [INTEGER] =
    BEGIN
    IF x IN [FIRST[INTEGER]..LAST[INTEGER]] THEN
      RETURN[InlineDefs.LowHalf[x]]
    ELSE ERROR;
    END;


  -- M a i n   P r o g r a m

  BEGIN ENABLE Punt => GOTO Exit;  -- for exits
  scaleN ← RequestInteger["Scale factor numerator"];
  scaleD ← RequestInteger["Scale factor denominator"];
  UnmarkList[masterList];
  FOR cl: cListPtr ← cellList, cl.nxt WHILE cl#NIL DO
    UnmarkObject[cl.ob];
    ENDLOOP;
  RescaleList[masterList];
  FOR cl: cListPtr ← cellList, cl.nxt WHILE cl#NIL DO
    RescaleObject[cl.ob];
    ENDLOOP;
  EXITS Exit => NULL;
  END;

  dChange ← TRUE;

  END. -- of Scale