-- XFileIOImpl.mesa
-- Created by Jeff Weinstein on  6-May-87 23:10:07

DIRECTORY
  CString,
  Heap,
  MFile,
  MStream,
  Stream,
  String,
  XFileIO;
  
XFileIOImpl:PROGRAM IMPORTS CString, Heap, MFile, MStream, Stream, String EXPORTS XFileIO =
  BEGIN
  
  z:UNCOUNTED ZONE ← Heap.systemZone;
  
  FiOpenForRead:PUBLIC PROCEDURE[name:CString.CString] RETURNS [fid:Stream.Handle] =
    BEGIN
    string:LONG STRING ← CString.CStringToLongString[name,z];
    fid ← MStream.ReadOnly[string,[NIL,NIL] ! MStream.Error => { fid ← NIL; CONTINUE;}];
    String.FreeString[z, string];
    END;
    
  FiClose:PUBLIC PROCEDURE[fid:Stream.Handle] =
    BEGIN
    Stream.Delete[fid];
    END;
  
  FiRead:PUBLIC PROCEDURE[buf:LONG POINTER, itemsize:CARDINAL, nitem:CARDINAL, fid:Stream.Handle] RETURNS[itemsRead:CARDINAL] =
    BEGIN
    why:Stream.CompletionCode;
    bytes:CARDINAL;
    [bytesTransferred:bytes,why:why] ← Stream.GetBlock[fid,[buf,0,nitem*itemsize]];
    itemsRead ← bytes / itemsize;
    END;
    
  SetDefaultFontPath:PUBLIC PROCEDURE[name:CString.CString] =
    BEGIN
    string:LONG STRING ← CString.CStringToLongString[name,z];
    path:MFile.SearchPath ← z.NEW[MFile.SearchPathObject[1]];
    path.length ← 1;
    path.directories[0] ← string;
    [] ← MFile.SetSearchPath[path];
    String.FreeString[z,string];
    z.FREE[@path];
    END;
    
  SetFontPath:PUBLIC PROCEDURE[path:XFileIO.FontPath] =
    BEGIN
    sPath:MFile.SearchPath ← z.NEW[MFile.SearchPathObject[path.npaths]];
    sPath.length ← path.npaths;
    FOR i:INTEGER IN [0..path.npaths) DO
      sPath.directories[i] ← CString.CStringToLongString[path.paths[i],z];
      ENDLOOP;
    [] ← MFile.SetSearchPath[sPath];
    FOR i:INTEGER IN [0..path.npaths) DO
      String.FreeString[z,sPath.directories[i]];
      ENDLOOP;
    z.FREE[@sPath];
    END;
    
  ExpandFontName:PUBLIC PROCEDURE[name:CString.CString, pathName:LONG POINTER TO CString.CString, zone:UNCOUNTED ZONE] RETURNS[nameLen:CARDINAL] =
    BEGIN
    numNames:CARDINAL;
    names:LONG POINTER TO ARRAY [0..0) OF LONG STRING;
    pattern:LONG STRING ← CString.CStringToLongString[name,z];
    [names,numNames] ← LookupFiles[pattern, 1];
    IF numNames # 1 THEN
      BEGIN
      nameLen ← 0;
      pathName↑ ← LOOPHOLE[LONG[0]];
      END
    ELSE
      BEGIN
      nameLen ← names[0].length;
      pathName↑ ← CString.LongStringToCString[names[0],zone];
      END;
    FreeNames[names,numNames];
    String.FreeString[z,pattern];
    END;
  
  ExpandFontNamePattern:PUBLIC PROCEDURE[pattern:CString.CString, maxNames:CARDINAL, zone:UNCOUNTED ZONE] RETURNS [paths:XFileIO.FontPath] =
    BEGIN
    names:LONG POINTER TO ARRAY [0..0) OF LONG STRING;
    numNames:CARDINAL;
    string:LONG STRING ← CString.CStringToLongString[pattern,z];
    paths ← zone.NEW[XFileIO.FontPathRec];
    [names, numNames] ← LookupFiles[string,maxNames];
    IF numNames > 0 THEN
      BEGIN
      paths.npaths ← numNames;
--      paths.length ← zone.NEW[ARRAY[0..numNames) OF INTEGER];
--      paths.paths ← zone.NEW[ARRAY[0..numNames) OF CString.CString];
      paths.length ← Heap.MakeNode[z:zone, n:SIZE[INTEGER]*numNames];
      paths.paths ← Heap.MakeNode[z:zone, n:SIZE[CString.CString]*numNames];
      FOR i:CARDINAL IN [0..numNames) DO
        paths.length[i] ← names[i].length;
	paths.paths[i] ← CString.LongStringToCString[names[i],zone];
	ENDLOOP;
      END
    ELSE
      paths↑ ← [0,NIL,NIL];
    FreeNames[names,numNames];
    String.FreeString[z,string];
    END;
    
  LookupFiles:PROCEDURE[pattern:LONG STRING, maxNames:CARDINAL] RETURNS [names:LONG POINTER TO ARRAY [0..0) OF LONG STRING, numNames:CARDINAL] =
    BEGIN
    
    EnumProc:MFile.EnumerateProc =
      BEGIN
      names[numNames] ← String.CopyToNewString[fullName,z];
      numNames ← numNames + 1;
      IF numNames >= maxNames THEN
        done ← TRUE;
      END;
     
    numNames ← 0; 
--    names ← z.NEW[ARRAY[0..maxNames) OF LONG STRING];
    names ← Heap.MakeNode[z:z, n:SIZE[LONG STRING]*maxNames];
    MFile.EnumerateDirectory[name:pattern, proc:EnumProc, which:filesOnly];
    END;
    
  FreeNames:PROCEDURE[names:LONG POINTER TO ARRAY [0..0) OF LONG STRING, numNames:CARDINAL] =
    BEGIN
    FOR i:CARDINAL IN [0..numNames) DO
      String.FreeString[z,names[i]];
      ENDLOOP;
    z.FREE[@names];
    END;
    
  END...