-- IconConvert.mesa; Edited by McGregor on June 7, 1982 3:32 pm

DIRECTORY
Directory USING [Error, Lookup],
IOStream USING [Close, CreateFileStream, Handle, UnsafePutBlock],
File USING [Capability, GetSize, PageCount],
Runtime USING [CallDebugger],
Space USING [Create, Delete, Handle, LongPointer, Map, PageCount, virtualMemory];

IconConvert: PROGRAM

IMPORTS Directory, File, IOStream, Runtime, Space =

BEGIN

iconH, iconW: INTEGER = 64;

OldIconRep: TYPE = ARRAY [0..iconH*iconW/16) OF UNSPECIFIED;
OldIconRef: TYPE = REF OldIconRep;
oldIcons: ARRAY OldIconFlavor OF OldIconRef;

OldIconFlavor: TYPE = MACHINE DEPENDENT {
 document(0),
 filecabinet(1),
 inoutbasket(2),
 inoutletter(3),
 formspad(4),
 printer(5),
 calendar(6),
 help(7),
 folder(8),
 records(9),
 calculator(10),
 proofreader(11),
 magnifier(12),
 recorder(13),
 telephone(14),
 teleconference(15),
 floppy(16),
 typescript(17),
 private(18) -- will cause call of viewer paintProc to paint icon
 };

NewIconFlavor: TYPE = MACHINE DEPENDENT { -- pre-defined icons
 document(0),
 dirtyDocument(1),
 fileCabinet(2),
 tool(3),
 typescript(4),
 private(177776B), -- will cause call of viewer paintProc to paint icon
 unInit(177777B)  -- private flag for unitialised icon type
 };

NewIcon: TYPE = REF NewIconFileFormat;
NewIconFileFormat: TYPE = MACHINE DEPENDENT RECORD [
 bits: ARRAY [0..iconH*iconW/16) OF UNSPECIFIEDALL[0],
 label: BOOLFALSE,
 filler: [0..32768) ← 0,
 lx, ly, lw, lh: INTEGER ← 0,
 empty: ARRAY [0..251) OF UNSPECIFIEDALL[0]
 ];

LoadOldIcons: PROC = BEGIN
ENABLE Directory.Error => GOTO Punt;
 iconBase: LONG POINTER TO OldIconRep;
 file: File.Capability ← Directory.Lookup[fileName: "Old.icons"L];
 pages: File.PageCount ← File.GetSize[file];
 size: Space.PageCount ← IF pages<30 THEN pages ELSE ERROR;
 space: Space.Handle ← Space.Create[size: size, parent: Space.virtualMemory];
 Space.Map[space: space, window: [file: file, base: 1]]; -- first page is 1!
 iconBase ← Space.LongPointer[space];
FOR f: OldIconFlavor IN [document..typescript] DO
  oldIcons[f] ← NEW[OldIconRep ← iconBase^];
  iconBase ← iconBase+SIZE[OldIconRep];
  ENDLOOP;
 Space.Delete[space];
EXITS Punt => Runtime.CallDebugger["Needs Old.icons to run!"L];
END;

WriteNewIcons: PROC = BEGIN OPEN IOStream;
 newFile: Handle ← CreateFileStream["New.icons"];
 newIcon: NewIcon ← NEW[NewIconFileFormat];

WriteIcon: PROC = BEGIN
  UnsafePutBlock[newFile, [LOOPHOLE[newIcon], 0, SIZE[NewIconFileFormat]*2]];
  newIcon.label ← FALSE;
  newIcon.lx ← newIcon.ly ← newIcon.lw ← newIcon.lh ← 0;
  END;

-- document
 newIcon.bits ← oldIcons[document]^;
 newIcon.label ← TRUE;
 newIcon.lx ← 1;
 newIcon.ly ← 2;
 newIcon.lw ← 49;
 newIcon.lh ← 50;
 WriteIcon[];
  
-- dirtyDocument
 newIcon.bits ← oldIcons[document]^;
FOR i: INTEGER IN [0..iconH) DO-- hack a diagonal line to distinguish from document
  index: INTEGER = (4*i) + (i/16);
  newIcon.bits[index] ← newIcon.bits[index] + (SELECT i MOD 16 FROM
   0   => 100000B,
   1   => 040000B,
   2   => 020000B,
   3   => 010000B,
   4   => 004000B,
   5   => 002000B,
   6   => 001000B,
   7   => 000400B,
   8   => 000200B,
   9   => 000100B,
   10   => 000040B,
   11   => 000020B,
   12   => 000010B,
   13   => 000004B,
   14   => 000002B,
   ENDCASE => 000001B);
  ENDLOOP;
 newIcon.label ← TRUE;
 newIcon.lx ← 1;
 newIcon.ly ← 2;
 newIcon.lw ← 49;
 newIcon.lh ← 50;
 WriteIcon[];

-- fileCabinet
 newIcon.bits ← oldIcons[filecabinet]^;
 WriteIcon[];

-- tool
 newIcon.bits ← oldIcons[records]^;
 newIcon.label ← TRUE;
 newIcon.lx ← 6;
 newIcon.ly ← 27;
 newIcon.lw ← 41;
 newIcon.lh ← 25;
 WriteIcon[];

-- typescript
 newIcon.bits ← oldIcons[typescript]^;
 newIcon.label ← TRUE;
 newIcon.lx ← 11;
 newIcon.ly ← 17;
 newIcon.lw ← 44;
 newIcon.lh ← 30;
 WriteIcon[];

 Close[newFile];
END;

LoadOldIcons[];
WriteNewIcons[];

END.