/* Overlay Map Dialog */!!

inherit(Dialog, #OverlayDialog, #(startA    /* starting offset to be/currently set */
startB
mapInfoA  /* map data to be/currently set */
mapInfoB
sizeBoxA  /* block size combo box instance */
sizeBoxB
charWidth /* text size params */
charHeight
), 2, nil)!!

now(class(OverlayDialog))!!

now(OverlayDialog)!!

/* 10/28/1993 10:57 */
Def disableOverlayControls(self, controlsList)
{ 
  if controlsList then
    do(controlsList,
      {using(controlId)
         disableItem(self, controlId);
      });
  endif;    
}
!!

/* 10/28/1993 10:57 */
Def enableOverlayControls(self, controlsList)
{ 
  if controlsList then
    do(controlsList,
      {using(controlId)
         enableItem(self, controlId);
      });
  endif;    
}
!!

/* 7/21/1992 11:13 */

/* return the current access rights */
Def accessRights(self, mapInfo)
{ 
  ^mapInfo[#accessRights];
}
!!

/* WINDOWS */
Def command(self, wP, lP | rc)
{
  select
   case (wP == 300) cand (high(lP) = 0) /* OK */
     if ((rc:=programMap(self)) = GOOD) then
       destroyMapAddress(self, mapInfoA);
       destroyMapAddress(self, mapInfoB); 
       end(self, 1); /* OK */
     else
       displayError(ErrorTextLibClass$Inst,rc,FORCE_POPUP);
       setFocus(self);
     endif;
   endCase
   
   case (wP == 400) cand (high(lP) = 0)
     getAllMapInfo(self);
     destroyMapAddress(self, mapInfoA);
     destroyMapAddress(self, mapInfoB); 
     end(self, 0); /* CANCEL */
   endCase
   
   case (wP = 102) cor (wP = 103) /* A's enable/disable */
     mapInfoA[#enabled] := wP - 102;
     Call CheckRadioButton(hWnd, 102, 103, wP );     
     if (mapInfoA[#enabled] <> 0) /* enable */
        Call CheckDlgButton(hWnd, (accessRights(self,mapInfoA)+501), 1);
        enableOverlayControls(self, tuple(104, 105, 106, 107, 500, 501, 502, 503, 504));
     else
        disableOverlayControls(self, tuple(104, 105, 106, 107, 500, 501, 502, 503, 504));
        Call CheckDlgButton(hWnd, (accessRights(self,mapInfoA)+501), 0);
     endif;   
   endCase
   
   case (wP = 202) cor (wP = 203) /* B's enable/disable */
     mapInfoB[#enabled] := wP - 202;
     Call CheckRadioButton(hWnd, 202, 203, wP ) ;
     if (mapInfoB[#enabled] <> 0) /* enable */
        Call CheckDlgButton(hWnd, (accessRights(self,mapInfoB)+601), 1);
        enableOverlayControls(self, tuple(204, 205, 206, 207, 600, 601, 602, 603, 604));
     else
        Call CheckDlgButton(hWnd, (accessRights(self,mapInfoB)+601), 0);
        disableOverlayControls(self, tuple(204, 205, 206, 207, 600, 601, 602, 603, 604));
     endif;   
   endCase

   case (wP >= 501) cand (wP <= 504) /* A's Access Rights */
     mapInfoA[#accessRights] := wP-501 ;
     Call CheckRadioButton(hWnd, 501, 504, wP ) ;
   endCase
   
   case (wP >= 601) cand (wP <= 604) /* B's Access Rights */
     mapInfoB[#accessRights] := wP-601 ;
     Call CheckRadioButton(hWnd, 601, 604, wP ) ;
   endCase

   case wP == IDHELP 
     is contextNumber(TheHelpObject, hWnd, HE_DLGR_OVERLAY);
   endCase

   default
     ^command( self:ancestor, wP, lP ) ;
    
  endSelect ;
  
  ^0     
}
!!

/* 7/21/1992 10:38 */

/* mapGet creates address descriptors.  This allocates memory that must 
   be freed.  The removal of these descriptors is an on demand process */
   
Def destroyMapAddress(self, mapInfo)
{ 
  if not(destroyAddress(AddressLibClass$Inst, mapInfo[#address])) then
    /* @@ return a real error code */
    ^0;
  endif;
}
!!

/* PUBLIC */
Def enableA?(self)
{ 
  /* if the map is not enabled (0) return the disable button value */
  if mapInfoA[#enabled] = 0 then 
    ^102;
  else
    ^103;
  endif;
}
!!

/* PUBLIC */
Def enableB?(self)
{ 
  /* if the map is not enabled (0) return the disable button value */
  if mapInfoB[#enabled] = 0 then 
    ^202;
  else
    ^203;
  endif;
}
!!

/* 7/21/1992 10:20 */
Def getAllMapInfo(self)
{ 
  if not(getMap(MapLibClass$Inst, mapInfoA) = 0) then
    /* @@ set a real error code */
    ^1;
  endif;

  if not(getMap(MapLibClass$Inst, mapInfoB) = 0) then
    /* @@ set a real error code */
    ^1;
  endif;
  
  startA := getOffset(AddressLibClass$Inst, mapInfoA[#address]);
  startB := getOffset(AddressLibClass$Inst, mapInfoB[#address]);
  
  if startA = nil then
    startA := 0;
  endif;
  
  if startB = nil then
    startB := 0;
  endif;
  
  ^nil;
  
}
!!

/* 7/30/1992 15:52 */

/* initializes the block size drop down box */
Def initBlockSize(self | loopVal gran blockSize rc i numEntries tmpVal
                         granStruct blockStruct addrRect tmpPnt addrPnt)
{ 
  /* gran and blockSize are both sent to dll's so they need to be structs */
  granStruct:=new(Struct,4);
  blockStruct:=new(Struct,4);
  
  /* assume there are never going to be map blocks < 1KB in granularity */
  /* getMapBlockXXX never return errors, so don't bother checking */
  if not(getMapBlockGran(MapLibClass$Inst, granStruct) = GOOD) then
    ^0;
  endif;
  if not(getMapBlockSize(MapLibClass$Inst, blockStruct) = GOOD) then
    ^0;
  endif;
  gran := longAt(granStruct,0);
  blockSize := longAt(blockStruct,0);
  loopVal := gran;
  
  if (gran = 0L) cor not(gran) then
    displayError(ErrorTextLibClass$Inst,ER_NO_MEMORY_PRESENT,FORCE_POPUP);
    ^0;
  else
    i:=0;
    tmpVal := loopVal;
    loop
    while tmpVal <= blockSize
      begin
      tmpVal := tmpVal * 2;   /* hard code map blocks to binary values. */
      i := i+1;
    endLoop;
    if( i > 6) then 
      numEntries := 6;
    else
      numEntries := i;
    endif;
  endif;
  
  /* calculate the position of the size boxes */
  addrRect := new(Rect);
  tmpPnt:=new(Point);
  /* 105 -> address box A */
  Call GetWindowRect(itemHandle(self, 105), addrRect);
  setX(tmpPnt,left(addrRect));
  setY(tmpPnt,top(addrRect));
  addrPnt:=screenToClient(self, tmpPnt);
  
  sizeBoxA := newDropDownList(ComboBox, 106, self, 
                  rect(x(addrPnt) + (right(addrRect) - left(addrRect) + charWidth),
                  y(addrPnt),
                  x(addrPnt) + (right(addrRect) - left(addrRect) + (charWidth * 12)),
                  y(addrPnt)+(charHeight * (numEntries+2))));

  Call GetWindowRect(itemHandle(self, 205), addrRect);
  setX(tmpPnt,left(addrRect));
  setY(tmpPnt,top(addrRect));
  addrPnt:=screenToClient(self, tmpPnt);
  
  sizeBoxB := newDropDownList(ComboBox, 206, self, 
                  rect(x(addrPnt) + (right(addrRect) - left(addrRect) + charWidth),
                  y(addrPnt),
                  x(addrPnt) + (right(addrRect) - left(addrRect) + (charWidth * 12)),
                  y(addrPnt)+(charHeight * (numEntries+2))));
  
  i:=0;
  loop
  while loopVal <= blockSize
  begin
    /* add values from min block size to max block size in KB */
    insertString(sizeBoxA, (asString(loopVal/1024) + "K"), i);
    insertString(sizeBoxB, (asString(loopVal/1024) + "K"), i);
    setCurSel(sizeBoxA, 0);
    setCurSel(sizeBoxB, 0);
    loopVal := loopVal * 2;   /* hard code map blocks to binary values. */
    i := i+1;
  endLoop;
  
  show(sizeBoxA,1);
  show(sizeBoxB,1);
  ^nil;

}
!!

/* initialize char width and height */
Def initCharDimensions(self | hdc, tm, oldFont)
{
  tm  := new( Struct, 32 ) ;
  Call GetTextMetrics(hdc := getContext(self), tm);
  charWidth  := asInt( wordAt(tm, 10) ) ;
  charHeight := asInt( wordAt(tm, 8) ) + asInt( wordAt(tm, 0) ) ;
  releaseContext( self, hdc ) ;
}
!!

/* By returning a 1 from the INITDIALOG message, we
  are telling MS-Windows to set the input focus to
  first tabstop item. (See MS-Windows Reference). */
Def initDialog(self, wP, lP | rc)
{ 
  requireWithPath( MapLib, "map.dll" ) ;
  showWaitCurs();
  
  initCharDimensions(self);
  
  /* create map structures */
  mapInfoA := newMapInfo(MapLibClass$Inst);
  mapInfoB := newMapInfo(MapLibClass$Inst);
  
  /* set the block numbers */
  mapInfoA[#blockNumber] := 0;
  mapInfoB[#blockNumber] := 1;

  /* get address descriptors */
  mapInfoA[#address] := createAddress(AddressLibClass$Inst);
  mapInfoB[#address] := createAddress(AddressLibClass$Inst);
  
  if (mapInfoA[#address] = nil) cor (mapInfoB[#address] = nil) then
    /* report error, come up with real error code */
    displayError(ErrorTextLibClass$Inst,ER_ADR_INVALID_DESCRIPTOR,FORCE_POPUP);
    if not(mapInfoA[#address]) then
      destroyAddress(AddressLibClass$Inst,mapInfoA[#address]);
    endif;
    if not(mapInfoB[#address]) then
      destroyAddress(AddressLibClass$Inst,mapInfoB[#address]);
    endif;
    showOldCurs();
    end(self,0);  /* cancel dialog */
  endif;

  if initBlockSize(self) then
    /* there is no overlay memory */
    /* the error has already been reported by initBlockSize */
    /* so just return */
    destroyMapAddress(self,mapInfoA);
    destroyMapAddress(self,mapInfoB);
    showOldCurs();
    end(self,0);  /* cancel dialog */
  endif;
  
  /* get the current shared data settings */
  if rc:=getAllMapInfo(self) then
    /* pop up error box then kill dialog */
    displayError(ErrorTextLibClass$Inst,rc,FORCE_POPUP);
    destroyMapAddress(self,mapInfoA);
    destroyMapAddress(self,mapInfoB);
    showOldCurs();
    end(self,0);  /* cancel dialog */
  endif;
  
  if (setDialogEntries(self, wP, lP) = 0 ) then
    destroyMapAddress(self,mapInfoA);
    destroyMapAddress(self,mapInfoB);
    showOldCurs();
    end(self,0);
  endif;
  
  registerF1Help(CLIULibraryClass$Inst, HI_DLGR_OVERLAY,
     getHWnd(self), HE_DLGR_OVERLAY);
  showOldCurs();
  ^1;
}!!

/* 7/21/1992 12:42 */
/* performs all of the necessary sanity checks before sending the 
   data to the map server */
Def programMap(self | inputTxt, rc status blockAString blockBString)
{ 
     /* Nghia 08/13/93 - Fixed PPR8832 - Symbolic Address Input for Map start address */
     if not(inputTxt := getItemText(self, 105)) cor 
        not(startA := getSymbolicOffsetNoError(AddressLibClass$Inst, inputTxt)) then
       ^ER_ADR_INVALID_ADDRESS_STR;  /* map syntax error */
     endif;
     if not(inputTxt := getItemText(self, 205)) cor 
        not(startB := getSymbolicOffsetNoError(AddressLibClass$Inst, inputTxt)) then
       ^ER_ADR_INVALID_ADDRESS_STR;
     endif;
     setOffset(AddressLibClass$Inst, mapInfoA[#address], startA);
     setOffset(AddressLibClass$Inst, mapInfoB[#address], startB);
     /* block size box holds values in # KB therefore mult. by 1024 */
     blockAString := getSelString(sizeBoxA);
     blockBString := getSelString(sizeBoxB);
     mapInfoA[#blockSize] := (string2int(
       subString(blockAString,0,upTo(blockAString,"K",0))) * 1024) - 1L;
     mapInfoB[#blockSize] := (string2int(
       subString(blockBString,0,upTo(blockBString,"K",0))) * 1024) - 1L;

     /* clear the map before reprogramming.  This solves the problem of */
     /* checking for multiple map block overlaps based upon what is already */
     /* programmed in the HW and what is about to be programmed.  It also */
     /* makes the windows interface capable of making arbitrary changes to */
     /* a previously mapped block */
     if not((rc := clearMap(MapLibClass$Inst)) = GOOD) then
       ^rc;
     endif;
     /* set the hw map logic */
     /* set map does a destroy address, so there is no need to explicitly
        call the destroyAddress routine before closing the dialog */
     rc := setMap(MapLibClass$Inst, mapInfoA);
     if not(rc=GOOD) then
       ^rc;
     endif;
     /* NOTES: Nghia- 10/28/93
     ** Program the overlay B anyway - server will keep the information
     */  
     status := new(Struct,4);
     rc := mapBlockOverlap(MapLibClass$Inst, mapInfoB, startB, status);
       
     select
       case (wordAt(status,0) = 0)  /* map entry was not found */
         if (mapInfoB[#enabled] = 1) then 
            rc := setMap(MapLibClass$Inst, mapInfoB);
            if not(rc=GOOD) then
              ^rc;
            endif;
         endif;   
       endCase
       case (wordAt(status,0) = 1) /* map block found, but diff. parms */
       is
         ^ER_BLOCK_ALREADY_MAPPED;
       endCase
       case (wordAt(status,0) = 2) /* block already mapped */
       is
         ^ER_BLOCK_ALREADY_MAPPED;
       endCase
       case (wordAt(status,0) = 3) /* blocks identical */
       is
         ^GOOD;
       endCase
       case (wordAt(status,0) = 4) /* no free blocks */
       is
         ^ER_NO_FREE_MAP_BLOCKS;  /* address range already mapped */
       endCase
     endSelect;
   ^GOOD;
}
!!

/* 7/21/1992 11:05 */
Def setDialogEntries(self, wP, lP | gran granStruct index i)
{ 
  granStruct := new(Struct,4);
  /* get the map granularity */
  if not(getMapBlockGran(MapLibClass$Inst, granStruct) = GOOD) then
    ^0;
  endif;

  gran := longAt(granStruct,0);
  
  if (gran = 0L) cor not(gran) then
    displayError(ErrorTextLibClass$Inst,ER_NO_MEMORY_PRESENT,FORCE_POPUP);
    ^0;
  endif;

  /* set the block A enable/disable button */
  sendDlgItemMessage( self, enableA?(self), BM_SETCHECK, wP, lP ) ;
  /* set the block B enable/disable button */
  sendDlgItemMessage( self, enableB?(self), BM_SETCHECK, wP, lP ) ;

  /* set the block A access rights */
  if (mapInfoA[#enabled] <> 0) /* enable */
    Call CheckDlgButton(hWnd, (accessRights(self,mapInfoA)+501), 1);
    enableOverlayControls(self, tuple(104, 105, 106, 107, 500, 501, 502, 503, 504));
  else
    Call CheckDlgButton(hWnd, (accessRights(self,mapInfoA)+501), 0);
    disableOverlayControls(self, tuple(104, 105, 106, 107, 500, 501, 502, 503, 504));
  endif;   

  /* set the block B access rights */
  if (mapInfoB[#enabled] <> 0) /* enable */
    Call CheckDlgButton(hWnd, (accessRights(self,mapInfoB)+601), 1);
    enableOverlayControls(self, tuple(204, 205, 206, 207, 600, 601, 602, 603, 604));
  else
    Call CheckDlgButton(hWnd, (accessRights(self,mapInfoB)+601), 0);
    disableOverlayControls(self, tuple(204, 205, 206, 207, 600, 601, 602, 603, 604));
  endif;   
  
  /* set the start address entries */
  setItemText(self, 105, 
              asciiz("0x" + asUnsignedStringRadix(asLong(startA),16)));
  setItemText(self, 205, 
              asciiz("0x" + asUnsignedStringRadix(asLong(startB),16)));

  /* set the block size entries */
  index := mapInfoA[#blockSize]/gran;
  
  /* index 0 is the smallest mappable block.  Therefore, if index is */
  /* zero the map block has not been initialized yet.  if index is 1 then */
  /* the minimum map block has been selected and the combo box selection */
  /* index is one less than the mathmatical index calculated above */
  if not(index = 0) then
    i := 0;
    loop
      while (index > 1) begin 
        index := index / 2;  /* shift right */
        i := i + 1;
    endLoop;
    index := i;
  endif;
  setCurSel(sizeBoxA, index);

  /* set the block size entries */
  index := mapInfoB[#blockSize]/gran;
  
  /* index 0 is the smallest mappable block.  Therefore, if index is */
  /* zero the map block has not been initialized yet.  if index is 1 then */
  /* the minimum map block has been selected and the combo box selection */
  /* index is one less than the mathmatical index calculated above */
  if not(index = 0) then
    i := 0;
    loop
      while (index > 1) begin 
        index := index / 2;  /* shift right */
        i := i + 1;
    endLoop;
    index := i;
  endif;
  setCurSel(sizeBoxB, index);
  
  ^1; /* good */
}
!!

/* PUBLIC */
Def startA(self)
{ ^startA }
!!

/* PUBLIC */
Def startB(self)
{ ^startB }
!!
