 
------------------------------------------------------------------------------
-- Program Name: TruckInOut
-- The 1280 Truck In/Out application is included with the 1280 standard firmware 
-- and is loaded by importing the application from the Configuration menu
-- “Import Files”.  
------------------------------------------------------------------------------

program TruckInOut; 
 
#include TruckInOut.iri 

  -- Constants and aliases definitions 
  g_csProgName          : constant string  := "TruckInOut"; --Program Name 
  g_csVersion           : constant string  := "1.00"; --Program Version   
  g_ciDigSlot           : constant integer := 0;  
  g_ciPrinter           : constant integer := 0;
  g_ciDigInOn           : constant integer := 0; --Digital Input is On 
  g_ciDigInOff          : constant integer := 1; --Digital Input is Off
  g_ciDigOutOn          : constant integer := 1; --Digital Output is On
  g_ciDigOutOff         : constant integer := 0; --Digital Output is Off 
  g_ciBackDoorPassword  : constant string  := "1234";  --Backdoor Password 
  g_ciInt32_Max         : constant integer := 2147483647;  
  g_ciStopnGoRemote                : constant integer := 2;    
  g_ciStopnGoRemoteRedLight        : constant string  := "|00DO3!";
  g_ciStopnGoRemoteGreenLight      : constant string  := "|00DO2!";
  
  -- Screens
  g_ciMain    : constant integer := 1;
  g_ciSetup   : constant integer := 9; 
  g_ciDList   : constant integer := 2; 
  
  -- Outputs
  g_ciGreenLight   : constant integer := 1;
  g_ciRedLight     : constant integer := 2;
     
  -- Operation Modes
  LockMode                : constant integer := 0;
  NoMode                  : constant integer := 100;
  WeighMode               : constant integer := 110;
  EnterTruckID_WeighIn    : constant integer := 111; 
  EnterTruckID_WeighOut   : constant integer := 112; 
  CapturingInboundWeight  : constant integer := 113; 
  CapturingOutboundWeight : constant integer := 114; 
  CapturingKeyTareWeight  : constant integer := 115; 
	ExitScale								: constant integer := 116;
	  
  SetupEnterTPasswordMode : constant integer := 120; 
  SelectInboundDB         : constant integer := 121;  
  YNClearALLInbounds      : constant integer := 122;
  YNClearOneInbound       : constant integer := 123;

  -- Setup Modes
  SetupEnterSPasswordMode  : constant integer := 999;
  Setup1Mode               : constant integer := 1000; 
    SetupChangeSPasswordMode  : constant integer := 1100;
      SetupVerifySPasswordMode  : constant integer := 1101;   
    SetupChangeTPasswordMode  : constant integer := 1200;
      SetupVerifyTPasswordMode  : constant integer := 1201;      
    SetupStoredTaresMode     : constant integer :=  1300;
    SetupValueSwappingMode   : constant integer :=  1400;
  Setup2Mode               : constant integer :=  2000;  
    SetupThresholdWeightMode : constant integer :=  2200;   
  Setup3Mode               : constant integer := 3000; 
    
  EntryMode : integer;      
  LastEntryMode : integer;

  g_ciMaxPerScreen          : constant integer := 8; 
  g_ciMaxRecords            : constant integer := 104;  

  Blank : constant string := "";      

  -- Global/Types variables definitions 
  g_sSetupPassword : stored string;   
  g_sTruckPassword : stored string;
  g_iDownload : stored integer;
  g_sTmpPassword : string; 
  g_rCountby : real;    
  g_iDecimal : integer;
  g_uUnits : Units; 
  g_iWaitSSScale : integer;  
  g_sysResult1 : SysCode;
	g_sysResult2 : SysCode;
  g_iDebug : integer;
  g_iStoredTares : stored integer;
  g_iValueSwapping : stored integer;
  g_iPage : integer;
  g_iWidgetNum : integer;  
  g_sLightStatus : string;    
  g_rThresholdWeight : stored real;

  type boolean is (False,True); 
  
  type DisplayRecord is
    record 
      sID : string; 
      sName : string;
			sInDT : string;
    end record;     

 type DisplayArrays is array [g_ciMaxRecords] of DisplayRecord;
  g_arDisplay : DisplayArrays; 

  InboundDB : Inbounddatabase; 
  
  -- Functions and procedures definitions   
      

  -- Sets all 5 sofktey text  
  procedure WriteKeys(sKey1 : string; sKey2 : string; sKey3 : string; sKey4 : string; sKey5 : string);
  begin  
  
    SetSoftkeyText(1, sKey1);
    SetSoftkeyText(2, sKey2);
    SetSoftkeyText(3, sKey3);
    SetSoftkeyText(4, sKey4);
    SetSoftkeyText(5, sKey5);  
       
  end;

  procedure BlankKeys;  -- Sets 5 softkeys to [] - [] - [] - [] - [] 
  begin
    
    Writekeys(Blank, Blank, Blank, Blank, Blank);
  
  end;   

  procedure SetKeys;
  begin
    if EntryMode = NoMode then
      WriteKeys(Blank, Blank, "Inbound Trucks", "Toggle Lights","Setup Menu");
    elsif EntryMode = Setup1Mode then
      WriteKeys("Setup Password", "Inbound Password", "Stored Tares", "Value Swapping", "More=>");  
    elsif EntryMode = Setup2Mode then
      WriteKeys("<=Back", "Threshold Weight", Blank, Blank, "Exit");      
    elsif EntryMode = SelectInboundDB then 
      WriteKeys("Page Up", "Page Down", "Delete", "Delete ALL", "Exit");  
    elsif EntryMode = YNClearALLInbounds or EntryMode = YNClearOneInbound then
      WriteKeys("Yes", Blank, Blank, Blank,"No");           
    elsif EntryMode = WeighMode then   
      WriteKeys("Weigh In", "Weigh Out", "Inbound Trucks", "Toggle Lights",Blank);
	  elsif EntryMode = CapturingInboundWeight or EntryMode = CapturingOutboundWeight or EntryMode = CapturingKeyTareWeight or EntryMode = ExitScale then
    	Writekeys(Blank, Blank, Blank, Blank, Blank);  
    end if;    
  end;   

  procedure SetupStartTimer(iTimer : integer; iDuration : integer; itmMode : TimerMode);  -- Setup a Timer and Start                                
  begin
  
    SetTimer(iTimer, iDuration);
    SetTimerMode(iTimer, itmMode);
    StartTimer(iTimer);
    
  end;    

  procedure WaitSS(iScale : integer);
  begin
    
    g_iWaitSSScale := iScale;
    SetupStartTimer(25, 10, TimerContinuous);
  
  end;  

  procedure TurnOnGreenLight;  
  begin 
     
    WriteLn(g_ciStopnGoRemote, g_ciStopnGoRemoteGreenLight); 
    WriteLn(g_ciStopnGoRemote, g_ciStopnGoRemoteGreenLight);
    WriteLn(g_ciStopnGoRemote, g_ciStopnGoRemoteGreenLight);
    WriteLn(g_ciStopnGoRemote, g_ciStopnGoRemoteGreenLight);
    WriteLn(g_ciStopnGoRemote, g_ciStopnGoRemoteGreenLight);
    SetDigout(g_ciDigSlot, g_ciRedLight, g_ciDigOutOff);
    SetDigout(g_ciDigSlot, g_ciGreenLight, g_ciDigOutOn); 
    g_sLightStatus := "GREEN";
    SetLabelText(lbLight, g_sLightStatus);  
		SetBargraphLevel(lbLight, 100);
		SetWidgetColor(lbLight, "Green"); 		

  end;

 procedure TurnOnRedLight; 
 begin
        
    WriteLn(g_ciStopnGoRemote, g_ciStopnGoRemoteRedLight); 
    WriteLn(g_ciStopnGoRemote, g_ciStopnGoRemoteRedLight);
    WriteLn(g_ciStopnGoRemote, g_ciStopnGoRemoteRedLight);
    WriteLn(g_ciStopnGoRemote, g_ciStopnGoRemoteRedLight);
    WriteLn(g_ciStopnGoRemote, g_ciStopnGoRemoteRedLight);            
    SetDigout(g_ciDigSlot, g_ciGreenLight, g_ciDigOutOff);
    SetDigout(g_ciDigSlot, g_ciRedLight, g_ciDigOutOn);   
    g_sLightStatus := "RED";   
    SetLabelText(lbLight, g_sLightStatus);
		SetBargraphLevel(lbLight, 100);
    SetWidgetColor(lbLight, "Red"); 
		
 end;      

  procedure DisableDisplayListHandlers;  -- Disables NumericKey, NavUp, NavDown and Enter Key Handlers
  begin

    DisableHandler(NumericKeyPressed);
    DisableHandler(NavUpKeyPressed);   
    DisableHandler(NavDownKeyPressed); 
    DisableHandler(EnterKeyPressed);  
  
  end;    

  procedure EnableDisplayListHandlers;  -- Enables NumericKey, NavUp, NavDown and Enter Key Handlers
  begin

    EnableHandler(NumericKeyPressed);
    EnableHandler(NavUpKeyPressed);   
    EnableHandler(NavDownKeyPressed); 
    EnableHandler(EnterKeyPressed);  
  
  end;  

  procedure LockMajorKeys;  -- Locks ZERO, GROSS/NET, TARE, UNITS and PRINT key
  begin
  
    LockKey(GrossNetKey);
    LockKey(UnitsKey);
    LockKey(PrintKey);
    
  end; 

  procedure UnLockMajorKeys;  -- UnLocks ZERO, GROSS/NET, TARE, UNITS and PRINT key
  begin
  
    UnlockKey(GrossNetKey);
    UnlockKey(TareKey);
    UnlockKey(UnitsKey);
    UnlockKey(PrintKey);
    
  end;   

  procedure LockAllKeys; -- Lock All Keys
  begin
  
    LockMajorKeys;
    DisableDisplayListHandlers;
  
  end;   

  procedure PromptForEntry(sPrompt : string;  iMode : integer; sDefault : string);  -- Prompts operator for data
  begin
    
    DisableHandler(NumericKeyPressed);
    DisableHandler(EnterKeyPressed);
    DisableHandler(NavUpKeyPressed);
    DisableHandler(NavDownKeyPressed);   
    
    LockMajorKeys;
     
		SetEntry(sDefault);   
    PromptUser(sPrompt);
    EntryMode := iMode;
    
  end;  

  function IsDigits(sNumeric : string) : boolean;  -- Makes ure user entry is numeric       
    i : integer;
    sTemp : string;
    bResult : boolean := True;
    bDecimal : boolean := False;
  begin
  
    if sNumeric = "." or StringToInteger(sNumeric) >= g_ciInt32_Max then   
      bResult := False;
      return bResult;
    end if;  

    for i := 1 to Len(sNumeric)
    loop                              
    
      sTemp := Mid$(sNumeric, i, 1); 
      
      -- ignore first decimal point
      if sTemp = "." then  
        if bDecimal = True then   
          bResult := False;
          exit;   
        end if;     
        bDecimal := True;  
      end if; 
      
      -- ignore negative if first character
      if i <> 1 and sTemp = "-" then
        bResult := False;
        exit;
      end if;
      
      if (sTemp < "0" or sTemp > "9") and sTemp <> "." and sTemp <> "-" then        
        bResult := False;
        exit;
      end if; 
      
    end loop;
        
    return bResult; 
    
  end;   

  function IsValid(sTemp : string; sValidFor : string; iLength : integer) : boolean;  -- Validates a String, Integer and Real
    bResult : boolean := True; 
    sMessage : string;
  begin 
    
    sValidFor := UCase$(sValidFor);
    
    if sValidFor = "S" then
    
      if Len(sTemp) = 0 or (Len(sTemp) > iLength and iLength <> 0) then  
        bResult := False;
        sMessage := "Required Entry - Try Again";  
      end if;      
        
    elsif sValidFor = "I" then
      
      if isDigits(sTemp) = False then
        bResult := False;  
        sMessage := "Invalid Number - Try Again";        
      elsif (Len(sTemp) = 0 or StringToInteger(sTemp) < 1) and iLength = 0 then   -- iLength to 1 will allow zero for an entry
        bResult := False;  
        sMessage := "Invalid Number (0) - Try Again";
      end if;      
    
    elsif sValidFor = "R" then
    
      if isDigits(sTemp) = False or StringToReal(sTemp) < 0 then     
        bResult := False;    
        sMessage := "Invalid Number - Try Again";
      elsif (Len(sTemp) = 0 or StringToReal(sTemp) = 0) and iLength = 0 then  -- iLength to 1 will allow zero for an entry
        bResult := False;    
        sMessage := "Invalid Number (0) - Try Again";              
      end if;  

    elsif sValidFor = "P" then
    
      if isDigits(sTemp) = False or StringToReal(sTemp) < 0 or StringToReal(sTemp) > 100 then 
        bResult := False; 
        sMessage := "Invalid Number (0-100) - Try Again";
      end if; 
                
    else
      
      DisplayStatus("Validation Error");
      bResult := False;
      
    end if;

    if bResult = False then
      PromptForEntry(sMessage, EntryMode, Blank);
    end if;
    
    return bResult;

  end;   
  
  procedure ClearDisplayListArray;  -- Clear Display List Array
    i : integer;
  begin 
  
    for i := 1 to g_ciMaxRecords 
    loop
      g_arDisplay[i].sID := Blank;
      g_arDisplay[i].sName := Blank; 
			g_arDisplay[i].sInDT := Blank;
    end loop;
         
  end;

  procedure ClearWidgetsData;  -- Clear Display  List Screen text boxes
    i : integer;
  begin  
  
    for i := MinLabel to maxLabel
    loop
      SetLabelText(i, Chr$(08));
    end loop;
    
    for i := minArrow to maxArrow
    loop   
      SetSymbolState(i, 2);  
    end loop;   
    
    SetLabelText(lbSelR, Blank);
    
  end;  

  procedure DisplayInboundDB;  -- Display the Selected Database 
    i : integer;
    j : integer;
  begin 

    -- Clear Text Boxes & Widgets
    ClearWidgetsData;
    
    -- Clear Array
    ClearDisplayListArray; 
    
    -- Sort DB or Get Based of Criteria                                       
    InboundDB.Sort(1);                                    
    i := 1; 
    
    -- FillArray
    if InboundDB.GetFirst = SysOk then  

      g_arDisplay[i].sID := InboundDB.ID;  
      g_arDisplay[i].sName := RealToString(InboundDB.InWgt,0,g_iDecimal);  
			g_arDisplay[i].sInDT := Time$(InboundDB.DT) + " " + Date$(InboundDB.DT);
      i := 2;            
 
      while InboundDB.GetNext = SysOk  
      loop   
             
        if i <= g_ciMaxRecords then             
          g_arDisplay[i].sID := InboundDB.ID;  
      		g_arDisplay[i].sName := RealToString(InboundDB.InWgt,0,g_iDecimal);  
					g_arDisplay[i].sInDT :=Time$(InboundDB.DT) + " " + Date$(InboundDB.DT);                                                      
          i := i + 1;                          
          
        end if;       
      end loop; 
      
    end if; 
    
    -- Select Screen, Enable Handlers, Clear Screen and initialize variables
    SelectScreen(g_ciDList);      
    EnableDisplayListHandlers;                                     
    i := minLabel;  
    g_iWidgetNum := minArrow; 
    SetSymbolState(g_iWidgetNum, 1);
    g_iPage := 1;          
    j := 1;   
    
    -- Populate Screen
    while g_arDisplay[j].sID <> Blank and j <= g_ciMaxPerScreen   
    loop    

      if j = 1 then
        SetLabelText(lbSelR, "***" + g_arDisplay[j].sID + "***");
      end if;  
      
      SetLabelText(i, g_arDisplay[j].sID);
      SetLabelText(i + 1, g_arDisplay[j].sName); 
			SetLabelText(i + 2, g_arDisplay[j].sInDT); 
      i := i + 3;
      j := j + 1;   
    end loop;                            

  end;       

  procedure PageUporDownList(tmpPage : integer);  -- Page Up/Page Down the Display List 
    a : integer;
    i : integer;
    j : integer;
    b : integer;
  begin 
    
    -- Clear display
    for i := minLabel to maxLabel
    loop
      SetLabelText(i, Blank);
    end loop;
    
    -- Find out where we are in the array
    if tmpPage = 1 then
      i := 1;                          -- g_ciMaxRecords MUST BE MULTIPLE OF 8
    elsif tmpPage >= 2 and tmpPage <= (g_ciMaxRecords/g_ciMaxPerScreen) then
      i := (tmpPage * g_ciMaxPerScreen) - 7;      
    else
      i := 1;
      g_iPage := 1;              
    end if;

    b := minLabel;
    j := i + 7; 
    
    -- Display the top of the list if we have reach the end 
    if g_arDisplay[i].sID = Blank then -- and EntryMode <> SetupSelectTruck then
 
      DisplayInboundDB;  

    else  
      
      -- Populate display with new data
      for a := i to j
      loop  
        if a > 0 and a <= g_ciMaxRecords and g_arDisplay[a].sID <> Blank then

          if b = minLabel then
            SetLabelText(lbSelR, "***" + g_arDisplay[a].sID +  "***");
          end if;  
   
          SetLabelText(b, g_arDisplay[a].sID);
          SetLabelText(b + 1, g_arDisplay[a].sName);  
					SetLabelText(b + 2, g_arDisplay[a].sInDT);
          b := b + 3; 
          
        end if; 
      end loop;
       
    end if;

  end; 

  function GetSelection : integer;  -- Returns the current selected record in the display list    
    i : integer;    
  begin  
   
    i := (g_iPage - 1) * g_ciMaxPerScreen + g_iWidgetNum - maxLabel;  
    return i;  
      
  end;       

  function CalcDecimal(rCountBy : real) : integer;  -- Calculates the amount of decimal positions  
    iDecimal : integer := 0;    
  begin   
         
    while rCountBy < 1.0
    loop    
      iDecimal := iDecimal + 1;
      rCountBy := rCountBy * 10.0;  
     end loop;

     return iDecimal; 
     
  end; 

  function GetCurrentUnitsString(s : integer) : string;  -- Gets current units string (lb/kg/etc). 
    sUnit : Units;
    sUnitString : string;  
  begin          
    
    if GetUnits(s, sUnit) = SysOk then
      GetUnitsString(s, sUnit, sUnitString);    
    else
      sUnitString := Blank;
    end if; 
    
    return sUnitString; 
    
  end;

  procedure DisplayVersion;    -- Displays Version Number and program name on startup or exiting config   
  begin   
  
    DisplayStatus(g_csProgName + " " + g_csVersion); 
    SetLabelText(lbProg, "Program: " + g_csProgName + " " + g_csVersion);  
    
  end; 
  
  procedure RefreshSetupDisplay;  -- Update display screen in setup menu 
  begin             
    
    if g_iStoredTares = 1 then
      SetLabelText(lbSet1, "Stored Tares: ON");   
    else
      SetLabelText(lbSet1, "Stored Tares: OFF");  
    end if;
    
    if g_iValueSwapping = 1 then
      SetLabelText(lbSet2, "Value Swapping: ON");   
    else
      SetLabelText(lbSet2, "Value Swapping: OFF");  
    end if;    
    
    SetLabelText(lbSet3, "Threshold Weight: " + RealToString(g_rThresholdWeight,0,g_iDecimal) + " " + GetCurrentUnitsString(1));
                                                                                                     
  end;
  
  procedure GoIntoSetupMenu;  -- Enters Setup Menu
  begin
		
		DisableSP(1);
		DisableSP(2);
    DisplayStatus("Setup Menu");
    EntryMode := Setup1Mode;  
    SetKeys;      
    SelectScreen(g_ciSetup);     
    RefreshSetupDisplay;     
  
  end; 

  procedure ReadytoProcessTruck(iTime : integer);  -- Removes Display Status Message
  begin 
  
    SetupStartTimer(29, iTime, TimerOneShot);
    
  end;    

  procedure ProcessPromptCancel;   -- Performs Cancel operation when cancelling a prompt
  begin 
  
    ClosePrompt;  
    UnLockMajorKeys;
    
    if EntryMode >= Setup1Mode and EntryMode < Setup2Mode then      
      EntryMode := Setup1Mode;   
    elsif EntryMode >= Setup2Mode and EntryMode < Setup3Mode then  
      EntryMode := Setup2Mode;
    elsif Entrymode = EnterTruckID_WeighIn or EntryMode = EnterTruckID_WeighOut then  
      SetLabelText(lbSts1, "Press [Weigh In] or [Weigh Out]"); 
      EntryMode := WeighMode;
    else   
      DisplayStatus(Blank); 
      SetLabelText(lbSts1, Blank);  
      EntryMode := NoMode; 
      SetKeys;     
    end if;
    
  end;    
 
  procedure ProcessDataEntry(sTemp : string);  -- Processing the entered data    
    rTareWgt : real;
  begin 
    
    ClosePrompt;   
    UnLockMajorKeys;
    
    if EntryMode = SetupChangeSPasswordMode then
     
      if IsDigits(sTemp) then 
        g_sTmpPassword := sTemp;
        PromptForEntry("Re-enter Password to Verify", SetupVerifySPasswordMode, Blank);    
      else      
        PromptForEntry("Error: Numeric Only", SetupChangeSPasswordMode, Blank);  
      end if;      
     
    elsif EntryMode = SetupVerifySPasswordMode then 
    
      if sTemp = g_sTmpPassword then    
        g_sSetupPassword := sTemp;
        EntryMode := Setup1Mode;
        DisplayStatus("Password Changed");      
      else 
        DisplayStatus("Error: Passwords don't Match");
        EntryMode := Setup1Mode;  
      end if;     

    elsif EntryMode = SetupChangeTPasswordMode then
     
      if IsDigits(sTemp) then 
        g_sTmpPassword := sTemp;
        PromptForEntry("Re-enter Password to Verify", SetupVerifyTPasswordMode, Blank);    
      else      
        PromptForEntry("Error: Numeric Only", SetupChangeTPasswordMode, Blank);  
      end if;      
     
    elsif EntryMode = SetupVerifyTPasswordMode then 
    
      if sTemp = g_sTmpPassword then    
        g_sTruckPassword := sTemp;
        EntryMode := Setup1Mode;
        DisplayStatus("Password Changed");      
      else 
        DisplayStatus("Error: Passwords don't Match");
        EntryMode := Setup1Mode;  
      end if;       

    elsif EntryMode = SetupThresholdWeightMode then

      if isValid(sTemp, "r", 0) then 
				g_rThresholdWeight  :=  StringToReal(sTemp);
        SetSPValue(1, g_rThresholdWeight);
        SetSPValue(2, g_rThresholdWeight);
        EntryMode := Setup2Mode;
        SetKeys;
      end if;         

    elsif EntryMode = EnterTruckID_WeighIn then 
      
      if IsValid(sTemp, "S", 15) then
    
        InboundDB.ID := sTemp;
        g_sysResult1 := InboundDB.FindFirst(Inbound_Id);    
        
        if g_sysResult1 <> SysOk then
          EntryMode := CapturingInboundWeight;   
          SetKeys;
          WaitSS(1);          
        else     
          SetLabelText(lbSts1, "Truck Already Weighed In"); 
          BlankKeys;
          ReadytoProcessTruck(100); 
        end if;             
      else     
        SetLabelText(lbSts1, "Error: Invalid Truck Id"); 
        BlankKeys;
        ReadytoProcessTruck(100); 
      end if;   

    elsif EntryMode = EnterTruckID_WeighOut then 
      
      if IsValid(sTemp, "S", 15) then
    
        InboundDB.ID := sTemp;
        g_sysResult1 := InboundDB.FindFirst(Inbound_Id);   
        
        if g_sysResult1 = SysOk then
          EntryMode := CapturingOutboundWeight;   
          SetKeys;
          WaitSS(1);         
        else
          
          -- Check Keyed Tare Option
          GetTare(1, g_uUnits, rTareWgt); 

          if rTareWgt = 0.0 then           
            SetLabelText(lbSts1, "Truck Not Weighed In");
            BlankKeys;
            ReadytoProcessTruck(100); 
          else
            EntryMode := CapturingKeyTareWeight;   
            SetKeys;
            WaitSS(1);               
          end if;
          
        end if;             
      else     
        SetLabelText(lbSts1, "Error: Invalid Truck Id"); 
        BlankKeys;
        ReadytoProcessTruck(100); 
      end if; 
      
    elsif EntryMode = YNClearALLInbounds then
      
      if sTemp = "Y" then
      
        g_sysResult1 := InboundDB.Clear;
        if g_sysResult1 = SysOk then
          EntryMode := SelectInboundDB;
          DisplayStatus("Loading Inbounds...");
          DisplayInboundDB; 
          SetKeys; 
          DisplayStatus("All Trucks Deleted");  
        else    
          EntryMode := SelectInboundDB;
          DisplayStatus("Loading Inbounds...");
          DisplayInboundDB; 
          SetKeys;         
          DisplayStatus("Database Error: " + SysCodeToString(g_sysResult1));
        end if; 
        
      else
        EntryMode := SelectInboundDB;
        DisplayStatus("Loading Inbounds...");
        DisplayInboundDB; 
        SetKeys;         
        DisplayStatus("Inbounds NOT Cleared");      
      end if;                

    elsif EntryMode = YNClearOneInbound then
      
      if sTemp = "Y" then
      
        g_sysResult1 := InboundDB.Delete;
        if g_sysResult1 = SysOk then
          EntryMode := SelectInboundDB;
          DisplayStatus("Loading Inbounds...");
          DisplayInboundDB; 
          SetKeys; 
          DisplayStatus("Truck Deleted");  
        else    
          EntryMode := SelectInboundDB;
          DisplayStatus("Loading Inbounds...");
          DisplayInboundDB; 
          SetKeys;         
          DisplayStatus("Database Error: " + SysCodeToString(g_sysResult1));
        end if;             

      else
        EntryMode := SelectInboundDB;
        DisplayStatus("Loading Inbounds...");
        DisplayInboundDB; 
        SetKeys;         
        DisplayStatus("Truck NOT Cleared");      
      end if;
        
    end if; 

    if EntryMode >=  Setup1Mode then
      RefreshSetupDisplay;
    end if; 
          
  end; 

  procedure Ready;  -- Initialization procedure
  begin
 
    UnLockMajorKeys;
    DisableDisplayListHandlers; 
    
    SetLabelText(lbSts1, Blank);    
    
    if GetUnits(1, g_uUnits) = SysOk then
      if GetCountBy(1, g_uUnits, g_rCountby) = SysOk then
        g_iDecimal := CalcDecimal(g_rCountby); 
      end if;
    end if;   

    SetSPValue(1, g_rThresholdWeight);
    SetSPValue(2, g_rThresholdWeight);

    EnableSP(1);  
    SetupStartTimer(1, 500, TimerOneShot);
        
    SelectScreen(g_ciMain); 
    EntryMode := NoMode;
    SetKeys;  
  
  end;    

  procedure PrintInboundTicket;  -- Print Weigh In Ticket
  begin

    SetPrintText(1, InboundDB.Id);  
    SetPrintText(2, RealToString(InboundDB.InWgt,6,g_idecimal) + " " + GetCurrentUnitsString(1));
    SetPrintText(3, Time$(InboundDB.DT));
    SetPrintText(4, Date$(InboundDB.DT));   
    ProgramDelay(10); 
    Print(AuxFmt1);    
  
  end;     

  procedure PrintOutboundTicket(rGrossWgt : real; rTareWgt : real; rNetWgt : real);  -- Print Weigh Out Ticket
    dtTemp : datetime;
  begin
    
    dtTemp := SystemTime;

    SetPrintText(1, InboundDB.Id);
    SetPrintText(2, RealToString(rGrossWgt, 6, g_iDecimal) + " " + GetCurrentUnitsString(1));
    SetPrintText(4, RealToString(rTareWgt, 6, g_iDecimal) + " " + GetCurrentUnitsString(1));
    SetPrintText(6, RealToString(rNetWgt, 6, g_iDecimal) + " " + GetCurrentUnitsString(1));
    SetPrintText(7, Time$(dtTemp));
    SetPrintText(8, Date$(dtTemp));  
    ProgramDelay(10);
    Print(AuxFmt2);
          
  end;      
  
  handler EnterKeyPressed;  -- Enter Key Pressed Handler
  begin 
  
    if EntryMode = SetupEnterSPasswordMode then 
      
      -- Password validation including backdoor password
      if g_sTmpPassword = g_sSetupPassword or g_sTmpPassword = g_ciBackDoorPassword then 
        GoIntoSetupMenu;          
      else      
        DisplayStatus("Error: Invalid Password");   
        g_sTmpPassword := Blank;        
        EntryMode := NoMode;                      
        SetKeys;        
      end if;      
      
    elsif EntryMode = SetupEnterTPasswordMode then  

      -- Password validation including backdoor password
      if g_sTmpPassword = g_sTruckPassword then 
        EntryMode := SelectInboundDB;
        DisplayStatus("Loading Inbounds...");
        DisplayInboundDB; 
        SetKeys; 
        DisplayStatus("Select a Inbound");         
      else      
        DisplayStatus("Error: Invalid Password");   
        g_sTmpPassword := Blank;        
        EntryMode := LastEntryMode;                      
        SetKeys;        
      end if;  
          
      
      DisableHandler(NumericKeyPressed); 
      DisableHandler(EnterKeyPressed);  
    
    end if;  
      
  end;  

  handler NumericKeyPressed;  -- Numeric Key Pressed Handler
    sMask : string;
    sCh : Keys;
    sTemp : string;
  begin

    sCh := EventKey;

    if sCh = N0KEY then
      sTemp := "0";
    elsif sCh = N1KEY then
      sTemp := "1";
    elsif sCh = N2KEY then
      sTemp := "2";
    elsif sCh = N3KEY then
      sTemp := "3";
    elsif sCh = N4KEY then
      sTemp := "4";
    elsif sCh = N5KEY then
      sTemp := "5";
    elsif sCh = N6KEY then
      sTemp := "6";
    elsif sCh = N7KEY then
      sTemp :=  "7";
    elsif sCh = N8KEY then
      sTemp :=  "8";
    elsif sCh = N9KEY then
      sTemp :=  "9";
    elsif sCh = DecpntKey then
      sTemp :=  ".";
    end if;       
    
    -- Process Entry  
    if EntryMode = SetupEnterSPasswordMode then  
      
      if EventKey <> ClearKey then
        g_sTmpPassword := g_sTmpPassword + sTemp;
      else
        g_sTmpPassword := Left$(g_sTmpPassword, Len(g_sTmpPassword) - 1); 
      end if;  
      
      if Len(g_sTmpPassword) = 0 then
        sMask := "";
      else  
        sMask := Left$("*-*-*-*-*-*-*-*-*-*-*",Len(g_sTmpPassword));
        EnableHandler(EnterKeyPressed);
      end if;                          

      if Len(g_sTmpPassword) = Len(g_sSetupPassword) and g_sTmpPassword = g_sSetupPassword then   
        GoIntoSetupMenu;
      else
        DisplayStatus(sMask);       
      end if;  
      
    elsif EntryMode = SetupEnterTPasswordMode then

      if EventKey <> ClearKey then
        g_sTmpPassword := g_sTmpPassword + sTemp;
      else
        g_sTmpPassword := Left$(g_sTmpPassword, Len(g_sTmpPassword) - 1); 
      end if;  
      
      if Len(g_sTmpPassword) = 0 then
        sMask := "";
      else  
        sMask := Left$("*-*-*-*-*-*-*-*-*-*-*",Len(g_sTmpPassword));
        EnableHandler(EnterKeyPressed);
      end if;                          

      if Len(g_sTmpPassword) = Len(g_sTruckPassword) and g_sTmpPassword = g_sTruckPassword then   
        -- Password validation including backdoor password
        if g_sTmpPassword = g_sTruckPassword then 
          EntryMode := SelectInboundDB;
          DisplayStatus("Loading Inbounds...");
          DisplayInboundDB; 
          SetKeys; 
          DisplayStatus("Select a Inbound");         
        else      
          DisplayStatus("Error: Invalid Password");   
          g_sTmpPassword := Blank;        
          EntryMode := LastEntryMode;                      
          SetKeys;        
        end if;    
      else
        DisplayStatus(sMask);       
      end if;  

    end if; 
  
  end;

  handler User1KeyPressed;  -- User 1/F1 Softkey
  begin 
		
    if EntryMode = WeighMode then 
      
      PromptForEntry("Enter Truck ID", EnterTruckID_WeighIn, Blank);
			SetLabelText(lbSts1, Blank); 
      
    elsif EntryMode = SelectInboundDB then     
    
      g_iPage := g_iPage - 1;   
      SetSymbolState(g_iWidgetNum, 2); 
      SetSymbolState(minArrow, 1);    
      g_iWidgetNum := minArrow;       
      PageUporDownList(g_iPage);   
      
    elsif EntryMode = Setup1Mode then 
    
			PromptForEntry("Enter New Password", SetupChangeSPasswordMode, Blank); 
			
	  elsif EntryMode = Setup2Mode then
	    
	    EntryMode := Setup1Mode;
	    SetKeys;    
      
    elsif EntryMode = YNClearALLInbounds or EntryMode = YNClearOneInbound then
      
      ProcessDataEntry("Y");
      
    end if;                
    
  end;

  handler User2KeyPressed;  -- User 2/F2 Softkey  
  begin   
    
    if EntryMode = WeighMode then 
    
      PromptForEntry("Enter Truck ID", EnterTruckID_WeighOut, Blank); 
			SetLabelText(lbSts1, Blank); 

    elsif EntryMode = SelectInboundDB then     
    
      g_iPage := g_iPage + 1;   
      SetSymbolState(g_iWidgetNum, 2); 
      SetSymbolState(minArrow, 1);    
      g_iWidgetNum := minArrow;       
      PageUporDownList(g_iPage);  

		elsif EntryMode = Setup1Mode then 
    
			PromptForEntry("Enter New Password", SetupChangeTPasswordMode, Blank); 
			
		elsif EntryMode = Setup2Mode then

      PromptForEntry("Enter Threshold Weight", SetupThresholdWeightMode, RealToString(g_rThresholdWeight, 0, g_iDecimal));			

    end if;  
    
  end;  

  handler User3KeyPressed;  -- User 3/F3 Softkey  
  begin   
 
     if EntryMode = WeighMode or EntryMode = NoMode then 

      LastEntryMode := EntryMode;
           
      -- Bypassing password entry if zero or blank
      if g_sTruckPassword = "0" or g_sTruckPassword = Blank then
        EntryMode := SelectInboundDB;
        DisplayStatus("Loading Inbounds...");
        DisplayInboundDB; 
        SetKeys; 
        DisplayStatus("Select a Inbound");          
      else       
        DisplayStatus("Enter Password");
        EntryMode := SetupEnterTPasswordMode;
        EnableHandler(NumericKeyPressed);  
        EnableHandler(EnterKeyPressed);
        g_sTmpPassword := Blank; 
        WriteKeys(Blank, Blank, Blank, Blank,"Exit"); 
      end if; 

		elsif EntryMode = Setup1Mode then 
		
      if g_iStoredTares = 1 then
        g_iStoredTares := 0;
      else
        g_iStoredTares := 1;
      end if;
      RefreshSetupDisplay; 

    elsif EntryMode = SelectInboundDB then
      
      InboundDB.ID := g_arDisplay[GetSelection].sID;
  
      if InboundDB.FindFirst(1) = SysOk then        
        DisableDisplayListHandlers;          
        DisplayStatus("Are You Sure?");
        EntryMode := YNClearOneInbound;
        SetKeys;       
      else 
        DisplayStatus("Error: Invalid ID");
      end if;
            
    end if;
    
  end;

  handler User4KeyPressed;  -- User 4/F4 Softkey  
  begin   
    
    if EntryMode = NoMode or EntryMode = WeighMode then
      
      if g_sLightStatus = "RED" then 
        TurnOnGreenLight;
      else
        TurnOnRedLight;
      end if;

    elsif EntryMode = Setup1Mode then   

		  if g_iValueSwapping = 1 then
        g_iValueSwapping := 0;
      else
        g_iValueSwapping := 1;
      end if;
      RefreshSetupDisplay; 		


    elsif EntryMode = SelectInboundDB then
      
      DisplayStatus("Are You Sure?");
      EntryMode := YNClearALLInbounds;
      SetKeys;

    end if;
    
  end;

  handler User5KeyPressed;  -- User 5/F5 Softkey  
  begin   
  
    if EntryMode = noMode then   
      
      -- Bypassing password entry if zero or blank
      if g_sSetupPassword = "0" or g_sSetupPassword = Blank then
        GoIntoSetupMenu;           
      else       
        DisplayStatus("Enter Password");
        EntryMode := SetupEnterSPasswordMode;
        EnableHandler(NumericKeyPressed);  
        EnableHandler(EnterKeyPressed);
        g_sTmpPassword := Blank; 
        WriteKeys(Blank, Blank, Blank, Blank,"Exit"); 
      end if; 
    
    elsif EntryMode = SetupEnterSPasswordMode then 
  
      DisableHandler(NumericKeyPressed);  
      DisableHandler(EnterKeyPressed); 
      Ready; 
      
    elsif EntryMode =  SetupEnterTPasswordMode then
      
      DisableHandler(NumericKeyPressed);  
      DisableHandler(EnterKeyPressed);  
      EntryMode := LastEntryMode;
      SetKeys;    
			
		elsif EntryMode = Setup1Mode then
			
			EntryMode := Setup2Mode;
			SetKeys;

    elsif EntryMode = Setup2Mode then
      
			DisplayStatus(Blank);
      SelectScreen(g_ciMain);
      EntryMode := NoMode;
      SetKeys;   
			EnableSP(1);
                       
    elsif EntryMode = SelectInboundDB then
			
			DisplayStatus(Blank);
      DisableDisplayListHandlers;
      EntryMode := LastEntryMode;
      SelectScreen(g_ciMain);
      SetKeys;  

    elsif EntryMode = YNClearALLInbounds or EntryMode = YNClearOneInbound then
      
      ProcessDataEntry("N");        

    end if;  
     
  end; 

  handler NavDownKeyPressed;  -- Go to the next record    
    i : integer;
  begin  
    
    if EntryMode = SelectInboundDB then   
                   
        i := GetSelection;  -- Get Current selected record

        if i < g_ciMaxRecords then
         
          if g_arDisplay[i + 1].sID <> Blank then
          
            SetSymbolState(g_iWidgetNum, 2);  
            g_iWidgetNum := g_iWidgetNum + 1;
            
            if g_iWidgetNum < minArrow then
              g_iWidgetNum := maxArrow; 
            elsif g_iWidgetNum > maxArrow then
              g_iWidgetNum := minArrow; 
              g_iPage := g_iPage + 1;
              PageUporDownList(g_iPage);
            end if;   

            SetLabelText(lbSelR, "***" + g_arDisplay[i + 1].sID + "***");

          end if; 
          
        end if;
        
        SetSymbolState(g_iWidgetNum, 1); 

    end if;
      
  end;

  handler NavUpKeyPressed;  -- Go to the previous record   
    i : integer;
  begin
  
    if EntryMode = SelectInboundDB then 
          
      if g_iWidgetNum <> minArrow then
       
        SetSymbolState(g_iWidgetNum, 2);   
        g_iWidgetNum := g_iWidgetNum - 1;
          
        if g_iWidgetNum < minArrow then
          g_iWidgetNum := maxArrow; 
        elsif g_iWidgetNum > maxArrow then
          g_iWidgetNum := minArrow; 
        end if;  
        
        i := GetSelection;
        SetLabelText(lbSelR, "***" + g_arDisplay[i].sID +  "***");
        
      else
      
        g_iPage := g_iPage - 1;  
        PageUporDownList(g_iPage); 
  
      end if; 
         
      SetSymbolState(g_iWidgetNum, 1);   
     
    end if;
    
  end;  

  handler Timer1Trip;
  begin
  
    TurnOnGreenLight;
  
  end;      

  handler Timer25Trip;  -- Wait for Standstill check
    iMotion : integer;   
    rGrossWgt : real;
    rTareWgt : real;
    rNetWgt : real;
		iInRange : integer;
  begin
    
    InMotion(1, iMotion);
    
    if iMotion = 0 then  
    
      StopTimer(25);
      DisplayStatus(Blank);  
      SetLabelText(lbSts1,  Blank); 
      
      GetUnits(1, g_uUnits);
      g_sysResult1 := GetGross(1, g_uUnits, rGrossWgt); 
			g_sysResult2 := InRange(1, iInRange);
      GetTare(1, g_uUnits, rTareWgt);
      
			-- Get Gross Command
      if g_sysResult1 <> SysOk then
        SetLabelText(lbSts1, "Scale Error: " + SysCodeToString(g_sysResult1));  
        BlankKeys;
        ReadytoProcessTruck(200);
			  return;
      end if;
			
			-- Check In Range
      if g_sysResult2 <> SysOk then
        SetLabelText(lbSts1, "Scale Error: " + SysCodeToString(g_sysResult2));  
        BlankKeys;
        ReadytoProcessTruck(200);  
			  return;
      end if;			
			
		 -- Validate InRage
		 if iInRange = 0 then  
        SetLabelText(lbSts1, "Scale NOT In Range");  
        BlankKeys;
        ReadytoProcessTruck(200); 
				return;
		 end if;
		 
     if EntryMode = CapturingInboundWeight then  -- Weigh In
        
        InboundDB.DT := SystemTime; 
        InboundDB.InWgt := rGrossWgt;
        g_sysResult1 := InboundDB.Add;
        
        if g_sysResult1 = SysOk then      
          PrintInboundTicket;  -- Print Inbound Ticket
          SetLabelText(lbSts1, "Weigh In Complete - Exit Scale");
					ClearTare(1);
					EntryMode := ExitScale;
					SetKeys;  					
        else 
          SetLabelText(lbSts1, "Database Error: " + SysCodeToString(g_sysResult1));
        	BlankKeys;
        	ReadytoProcessTruck(200);  					
        end if;  

      elsif EntryMode = CapturingKeyTareWeight then
        
        rGrossWgt := rGrossWgt;
        rTareWgt := rTareWgt; 
        rNetWgt := (rGrossWgt - rTareWgt);         
        SetPrintText(3, Blank);
        SetPrintText(5, "KEYED"); 
                   
        PrintOutboundTicket(rGrossWgt, rTareWgt, rNetWgt);  
        SetLabelText(lbSts1, "Weigh Out Complete - Exit Scale");   
        
        ClearTare(1);  
				EntryMode := ExitScale;
				SetKeys;   
                  
      elsif EntryMode = CapturingOutboundWeight then  -- Weigh Out

        if g_iValueSwapping = 1 then   -- Value Swapping  
        
          if rGrossWgt > InboundDB.InWgt then  
            rGrossWgt := rGrossWgt;             
            rTareWgt := InboundDB.InWgt;
            rNetWgt := (rGrossWgt- rTareWgt); 
            SetPrintText(5, "RECALLED");
            SetPrintText(3, Blank); 
          else
            rTareWgt := rGrossWgt;
            rGrossWgt := InboundDB.InWgt; 
            rNetWgt := (rGrossWgt - rTareWgt);    
            SetPrintText(3, "RECALLED");
            SetPrintText(5, Blank);                                               
          end if;   

        else 

          rGrossWgt := rGrossWgt;
          rTareWgt := InboundDB.InWgt; 
          rNetWgt := (rGrossWgt - rTareWgt);         
          SetPrintText(5, "RECALLED");
          SetPrintText(3, Blank);   
                  
        end if;   

        PrintOutboundTicket(rGrossWgt, rTareWgt, rNetWgt);  
        SetLabelText(lbSts1, "Weigh Out Complete - Exit Scale");
        
        if g_iStoredTares = 0 then
          g_sysResult1 := InboundDB.Delete;
          if g_sysResult1 <> SysOk then
            DisplayStatus("Database Error: " + SysCodeToString(g_sysResult1));
          end if; 
        end if;    
        
        ClearTare(1);   
				EntryMode := ExitScale;
				SetKeys;  
        
      end if;  
      
    else
      SetLabelText(lbSts1, "...In Motion...");
    end if;

  end;   

	handler Timer29Trip;
	begin
	
    EntryMode := WeighMode;  
    SetKeys;   
    SetLabelText(lbSts1, "Press [Weigh In] or [Weigh Out]"); 

	end;  

  handler UserEntry;  -- Processing a data entry method
    sTemp : string;  
  begin   
  
    sTemp := GetEntry; 
    
    if EventKey = EnterKey then     --Enter key pressed
      ProcessDataEntry(sTemp); 
    else                            --Cancel key pressed    
      ProcessPromptCancel;    
    end if;

  end;  

  handler SP1Trip;
  begin   
    
    DisableSP(1);  
    StopTimer(1);  
		DisplayStatus(Blank);
    DisableDisplayListHandlers;
    SelectScreen(g_ciMain);	
    LockMajorKeys;
    TurnOnRedLight;
    EntryMode := WeighMode;  
    SetKeys;   
    SetLabelText(lbSts1, "Press [Weigh In] or [Weigh Out]"); 
    EnableSP(2);
		
  end;  

  handler SP2Trip;
  begin    
     
    DisableSP(2); 
    TurnOnGreenLight;
    UnlockMajorKeys; 
    EntryMode := NoMode;   
    SetKeys;
    SetLabelText(lbSts1, Blank);
    DisplayStatus(Blank); 
    StopTimer(25);   
    EnableSP(1);
		
  end;      

begin
  
  DisableSP(1);
  DisableSP(2);
  DisplayVersion;  
  
  if g_iDownload = 0 then
    g_iDownload := 1;
    g_sSetupPassword := Blank;    
    g_sTruckPassword := Blank;
    g_iStoredTares := 1;
    g_iValueSwapping := 1;    
    g_rThresholdWeight := 5000;
  end if;    
  
  Ready;       

end TruckInOut; 
