/* CLASS: PrjInfo
    Contains global information of a debug session.  
    It's a global data object of the PowerTool.  The following instance variables
    are defined as:
    currentLoadFile = active loadfile of the debug session.
    sourcePathsCollection = [path, path...]
    loadFilesCollection = [ #(loadFileNameStr, loadSpace, loadFlags),...]
    dirtyPrj = true/nil
    loadFlags = symbol | code | status | warning
    loadOnDemand = 1 | 0

    NOTES: To open the PrjInfo object. (should be saved to a global variable)
        TheProjectInfoObj := init(new(prjInfo));

    - Use the loadFilesCollection to create menu item of the previous opened
    loadfiles.
*/!!

inherit(Object, #PrjInfo, #(pathCvnDict /* paths conversion Dict */
sourcePathsCollection /* a fixed size collection */
loadFilesCollection  /* fixed size collection of opened Loadfiles */
currentLoadFile /* active LoadFile */
dirtyPrj /* boolean indicate project changed */
loadFlags /* a long = symbol | code | status | warning | asm | ondemand */
), 2, nil)!!

now(class(PrjInfo))!!

now(PrjInfo)!!

/* 7/8/1992 11:58 - PUBLIC
  Get the previous used load information, i.e.,
  path name (e.g. "D:\TEST\*.ext"), load space and loadFlags.
  Return #("c:\test\*.abs", SPACE_SD, 0x003L) or nil
*/
Def prevLoadInfo(self | item, tmpParts)
{ 
  /* Get the path of the LRU loadfile */
  if (size(loadFilesCollection) > 0) cand (item := first(loadFilesCollection))
    cand (tmpParts := pathParts(item[0])) then
    ^tuple(tmpParts[0]+"*."+tmpParts[2], item[1], item[2]);
  endif;     
  ^nil;
}
!!

/* 6/10/1993 15:07  - PRIVATE
  Search for the fileSpec from the source paths collection.
*/
Def searchFileSpec(self, moduleInfoObj, fileSpec | index, tmpStr, lfPath)
{ 
  if (size(sourcePathsCollection) > 0) then
    /* Iterate over the collection */
    index := 0;
    do (sourcePathsCollection,
      {using(element)
        tmpStr := makePathString(asString(element), fileSpec);
        if exists(File, tmpStr, 0) then
          /* Reset the alias reference for the moduleInfoObj */  
          setAliasPathRef(moduleInfoObj, index);
          ^tmpStr;
        endif;
        index := index + 1;  
      });
  endif;
  /* Nothing found from the collection - So let try the loadpath */     
  if (size(loadFilesCollection) > 0) cand
     (lfPath := first(loadFilesCollection)[0]) cand (size(lfPath) > 0) then
    tmpStr := pathParts(lfPath)[0];
    lfPath :=  makePathString(tmpStr, fileSpec);
    if exists(File, lfPath, 0) then
       /* Reset the alias reference for the moduleInfoObj - add it to the list */  
       setAliasPathRef(moduleInfoObj, addAliasPath(self, tmpStr));
       ^lfPath;
    endif;
  endif;
  ^nil;   
}!!

/* 06/10/93 10:50 - PUBLIC 
  Add the new alias path to the sourcePathsCollection.
  Return the index of the newly added path string. 
*/
Def addAliasPath(self, defPath| index)
{ 
  /* <Judy 7/2/96> */
  defPath := asUpperCase(defPath);
  index := 0;
  do (sourcePathsCollection,
    {using(element)
      if (asString(element) = asString(defPath))
        remove(sourcePathsCollection, index);
      endif;  
      index := index + 1;
    });
  dirtyPrj := #true;
  /* ^addToEnd(sourcePathsCollection, defPath); */
  insert(sourcePathsCollection, defPath, 0);
  saveProjectProfile(self);
  ^0;
}
!!

/* 6/8/1993 15:18 - PUBLIC
  Return the path alias given the index location.  Return nil if index is
  invalid or the loadfile path if the sourcePathsCollection is empty.
  
*/
Def getAliasFilePath(self, moduleInfoObj, index | numItems, newStr)
{ 
  numItems := size(sourcePathsCollection);
  if index cand (numItems > 0) then
    /* Make sure that the index is not out of bound */
    if between(index, 0, numItems) then 
      ^sourcePathsCollection[index];
    else
      /* Reset the alias reference for the moduleInfoObj */  
      setAliasPathRef(moduleInfoObj, nil);      
    endif;
  endif;
  /* sourcePaths Collection is empty - try the loadfile path */
  if isLoaded(currentLoadFile) cand 
     (newStr := loadFilePath(currentLoadFile)) then
    addAliasPath(self, newStr);
    ^newStr;       
  endif;  
  ^nil;   
}
!!

/* 6/4/1993 17:16 - PUBLIC
  Replace the current sourcePathsCollection with the newColl.
*/
Def setSourcePathsCollection(self, newColl | modulesDict)
{ 
  sourcePathsCollection := deepCopy(newColl);
  /* Flush all source/mixed info that we have so far */
  if isLoaded(currentLoadFile) cand
     (modulesDict := modulesDict(currentLoadFile)) then
    do (modulesDict,
      {using(module)
        resetBrowsedInfo(module);
      });
  endif;
  saveProjectProfile(self);
}
!!

/* 6/4/1993 16:42 - PUBLIC
  return the current sourcePathsCollection
*/
Def sourcePathsCollection(self)
{ 
  ^sourcePathsCollection;
}
!!

/* 6/3/1993 13:43 - PUBLIC
  return the state of the PrjInfo object.
*/
Def isDirty(self)
{ 
  ^dirtyPrj;
}
!!

/* 5/21/1993 13:16 - PUBLIC 
  Added the new last loadfile item to loadFilesCollection.
  NOTES: loadFileItem = tuple("fileName", loadSpace, loadFlags)
  Return #true if the <loadFileStr> is added, else nil.
*/
Def setLastLoadFile(self, loadFileItem | idx)
{
  /* Search for the <loadFileStr> in the collection 
  ** If it is not the first item then add it in - else 
  ** remove the item then add the new item in.
  */
  idx := 0;
  do (loadFilesCollection,
    {using(element)
      if (asString(element[0]) = asString(loadFileItem[0]))
        if (idx = 0) ^nil; endif; 
        /* remove the element in list, except if it match the first one */
        remove(loadFilesCollection, idx);
      endif;
      idx := idx + 1;  
    });
  add(loadFilesCollection, loadFileItem);
  ^(dirtyPrj := #true);
}
!!

/* 5/21/1993 10:42 - PUBLIC
  return the last loadfiles collection.
*/
Def lastLoadFiles(self)
{ 
  /* Collection of [#("fileName", loadSpace, loadFlags),...] */ 
  ^loadFilesCollection;
}
!!

/* 8/7/1992 9:06 - PUBLIC
  Save the project Info profile control to SourceInfo of POWERVIEW.INI
*/
Def saveProjectProfile(self | appName, numAliasPath, i, val)
{ 
  appName := "SourceInfo";
  /* Save the LRU loadfiles - loadFileCollections is a fixed size queue */
  i := 0;
  if size(loadFilesCollection) > 0 then
    i := 0;
    do (loadFilesCollection, 
      {using(element)
        saveProfileEntry(TheProfileInfoObj, appName, 
            "LoadFile"+asString(i), 
            asString(element[0]+","+asString(element[1])+","+asHex(element[2])));
        i := i + 1;
      });
  endif;

  /* Save all source path alias (max 50) - sourcePathsCollection is a fixed size queue */
  numAliasPath := size(sourcePathsCollection);
  saveProfileEntry(TheProfileInfoObj, appName, "NumAliasPath", asString(numAliasPath));

  i := 0;
  if (numAliasPath > 0) then
    do (sourcePathsCollection,
      {using(element)
        saveProfileEntry(TheProfileInfoObj, appName, "SourcePathAlias"+asString(i), 
          asString(element));
        i := i + 1;  
      });
  endif;   
}
!!

/* 8/7/1992 9:06 - PUBLIC
  Get the project info profile control from SourceInfo of POWERVIEWS.INI
*/
Def getProjectProfile(self | appName, loadFileItem, iniStr, iniVal, i, lFlags, lSpace)
{ 
  appName := "SourceInfo";
  /* Get upto MAX_LRU_LOADFILES (4) loadfiles */
  i := 0;
  loop
  while (i < MAX_LRU_LOADFILES)
  begin
     if (loadFileItem := getProfileEntry(TheProfileInfoObj, appName, 
        "LoadFile"+asString(i), "," )) cand 
        (size(loadFileItem[0]) > 0) then
        /* Convert LoadFlags to number */
        if (loadFileItem[1]) then
          lSpace := asInt(loadFileItem[1], 10);
        else
          lSpace := ADDR_SPACE_DEFAULT;
        endif;    
        
        if (loadFileItem[2]) then
          lFlags := asInt(loadFileItem[2], 16);
        else
          lFlags := 0x0L 
        endif;    
        /* Added #("filename", spaceName, 0x0003L) to [collection] */
        addToEnd(loadFilesCollection, tuple(loadFileItem[0],  /* file name */
                                            lSpace,           /* loadSpace */
                                            lFlags));         /* loadFlags */
     endif;        
     i := i + 1;
  endLoop;
 
  /* Get all source path alias (max 50) */
  if (iniVal := getIniValueNum(TheProfileInfoObj, appName, "NumAliasPath")) 
        cand between(iniVal, 0, MAX_SRC_PATHS) then
    i := 0;
    loop
    while (i < iniVal)
    begin
       if (iniStr := getIniValueStr(TheProfileInfoObj, appName, 
        "SourcePathAlias"+asString(i))) cand (size(iniStr) > 0) then
        addToEnd(sourcePathsCollection, iniStr);
       endif;        
       i := i + 1;
    endLoop;
  endif;
}
!!

/* 5/5/1992 11:26 - PUBLIC
  Set the currentLoadFile of the ProjectInfo.
*/
Def setCurrentLoadFile(self, newLoadFile)
{ 
  dirtyPrj := #true;
  ^(currentLoadFile := newLoadFile);
}!!

/* 5/5/1992 12:47 - PUBLIC
  Return the current loadfile of self.
*/
Def currentLoadFile(self)
{ 
  ^currentLoadFile;
}
!!

/* 7/8/1992 11:58 - PUBLIC
  Return the previous used path name (e.g. "D:\TEST\*.ext").
*/
Def prevUsedPath(self | item, tmpParts)
{ 
  /* Get the path of the LRU loadfile */
  if (size(loadFilesCollection) > 0) cand (item := first(loadFilesCollection))
    cand (tmpParts := pathParts(item[0])) then
    ^tmpParts[0]+"*."+tmpParts[2];
  endif;     
  ^nil;
}
!!

/* 6/25/1992 10:50 - PUBLIC 
  Add the new alias path to pathCvnDict[] = systemPath->AliasPath.
*/
Def addDefinedPath(self, keyPath, defPath)
{ 
  dirtyPrj := #true;
  add(pathCvnDict, keyPath, defPath);
}
!!

/* 6/4/1992 10:42 - PUBLIC
  Return the path conversion dictionary.
*/
Def pathCvnDict(self)
{ 
  ^pathCvnDict; 
}
!!

/* 6/3/1992 11:25 - PUBLIC */
Def loadFlags(self)
{ ^loadFlags; }
!!

/* 06/20/92 - PUBLIC */
Def setLoadFlags(self, newLoadFlag)
{ 
  if newLoadFlag <> loadFlags then
    dirtyPrj := #true;
    ^(loadFlags := newLoadFlag) 
  endif;      
}!!

/* 6/3/1992 10:17 - PUBLIC
  Set the dirtyPrj flag
*/
Def setPrjDirty(self, flag)
{ 
  dirtyPrj := flag;
}
!!

/* 6/3/1992 9:40 - PUBLIC
  Initialize project information
*/
Def init(self)
{ 
  dirtyPrj := nil;
  currentLoadFile := init(new(LoadFileModule), nil, nil); /* Uninitialize */
  pathCvnDict := new(Dictionary, 2); /* paths to source dictionary */
  loadFilesCollection := new(FixedSizeQueue, MAX_LRU_LOADFILES); /* the last 4 loadfiles */
  sourcePathsCollection := new(FixedSizeQueue, MAX_SRC_PATHS);
  loadFlags := 0L;
  getProjectProfile(self);
}
!!
