Compile function WO_MAT_GAN_EVENTS(CtrlEntId, Event, @PARAMS)
/***********************************************************************************************************************

    Name        :   WO_Mat_Gan_Events

    Description :   Commuter module for the WO_MAT_GAN form.

    Notes       :   Application errors should be logged using the Error Services module. There are a few methodological
                    assumptions built into way errors are managed which are important to understand in order to properly
                    work with Error Services:

                    - The term 'top' refers to the originating procedure of a call stack and the term 'bottom' refers to
                      the last routine (or the current routine) within a call stack. Within the OpenInsight Debugger
                      this will appear backwards since the originating procedure always appears at the bottom of the
                      list and the current routine appears at the top of the list. We are using this orientation because
                      it is common to refer to the process of calling other procedures as 'drilling down'.

                    - The reason for defining the orientation of the call stack is because Error_Services allows for
                      multiple error conditions to be appended to an original error. In most cases this will happen when
                      a procedure at the bottom of the stack generates an error condition and then returns to its
                      calling procedure. This higher level procedure can optionally add more information relevant to
                      itself. This continues as the call stack 'bubbles' its way back to the top to where the
                      originating procedure is waiting.

                    - Native OpenInsight commands that handle errors (e.g., Set_Status, Set_FSError, Set_EventStatus)
                      preserve their error state until explicitly cleared. This can hinder the normal execution of code
                      since subsequent procedures (usually SSPs) will fail if a pre-existing error condition exists.
                      Our philosophy is that error conditions should automatically be cleared before a new procedure
                      is executed to avoid this problem. However, the nature of Basic+ does not make this easy to
                      automate for any given stored procedure. Therefore, if a stored procedure wants to conform to our
                      philosophy then it should include a call into the 'Clear' service request at the top of the
                      program. Alternatively this can be done through a common insert (see SERVICE_SETUP for example.)

                    - Service modules will use the SERVICE_SETUP insert and therefore automatically clear out any
                      error conditions that were set before.

    Parameters  :
        Service         [in] -- Name of the service being requested
        Param1-10   [in/out] -- Additional request parameter holders
        Response       [out] -- Response to be sent back to the Controller (MCP) or requesting procedure

    Metadata    :

    History     :   (Date, Initials, Notes)
        08/05/19    djs     Coverted old commuter module, WO_MAT_GAN, to WO_MAT_GAN_EVENTS.
                            Updated the form to allow users to reorder wafers in the cassette via arrow buttons.

***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
#window WO_MAT_GAN

DECLARE SUBROUTINE Set_Property, Set_Status,obj_WO_Wfr, obj_React_Run, Print_GaN_Out_Labels, obj_WO_Mat
DECLARE SUBROUTINE ErrMsg, Send_Message, Set_Property, Send_Event, obj_AppWindow, Security_Err_Msg, Forward_Event
DECLARE SUBROUTINE End_Window,obj_React_Reads, obj_WO_Mat_Log, obj_WO_Mat, obj_Appwindow,obj_Run_Stage
DECLARE SUBROUTINE Database_Services, Gan_Services, Error_Services, Dialog_Box, Btree.Extract, Print_Manifest
DECLARE SUBROUTINE Material_Services, Print_Gan_Scribe_Labels

DECLARE FUNCTION Get_Property, Get_Status, Dialog_Box, Utility, Popup, Collect.Ixvals, obj_Appwindow, Database_Services
DECLARE FUNCTION Send_Message, Msg, Security_Check, obj_WO_Log, Set_Property, Create_Dialog, obj_wo_Mat_GaN, SRP_Array
DECLARE FUNCTION Error_Services, GaN_Services, Datetime, RGB, Form_Services

$INSERT REACT_RUN_EQUATES
$INSERT RUN_STAGE_EQUATES
$INSERT WO_MAT_EQUATES
$INSERT WO_MAT_WFR_EQUATES
$INSERT WO_WFR_EQUATES
$INSERT LSL_USERS_EQUATES
$INSERT POPUP_EQUATES
$INSERT TOOL_CLASS_EQUATES
$INSERT RTI_STYLE_EQUATES
$INSERT MSG_EQUATES
$INSERT APPCOLORS
$INSERT SECURITY_RIGHTS_EQU
$INSERT RUN_STAGE_WFR_EQUATES
$INSERT WO_LOG_EQUATES

EQU COL$OUT_SLOT			TO 1
EQU COL$OUT_WFR_ID			TO 2
EQU COL$OUT_CARR_SLOT_ID	TO 3
EQU COL$OUT_GAN_WFR_ID		TO 4
EQU COL$OUT_SCRIBE			TO 5
EQU COL$OUT_GRADE			TO 6

EQU COL$POP_WFR_ID			TO 1
EQU COL$POP_CARR_SLOT_ID	TO 2

Equ COL$LOG_FILE        to 1
Equ COL$LOG_DTM         to 2
Equ COL$ACTION          to 3
Equ COL$WH_CD           to 4
Equ COL$LOC_CD          to 5
Equ COL$WO_NOS          to 6
Equ COL$CASS_NOS        to 7
Equ COL$USER_ID         to 8
Equ COL$TAGS            to 9
Equ COL$TOOL_ID         to 10

// In Cass OLE Edit Table
EQU COL$CASS_SLOT		    TO 1
EQU COL$CASS_WFR_ID  		TO 2
EQU COL$CASS_CARR_SLOT_ID	TO 3
EQU COL$CASS_GAN_WFR_ID		TO 4
EQU COL$CASS_SCRIBE		    TO 5
EQU COL$CASS_GRADE	        TO 6
EQU COL$CASS_WMO_NCR	    TO 7

// NCR OLE Edit Table
EQU COL$NCR_NO			 TO 1
EQU COL$NCR_STATUS		 TO 2
EQU COL$NCR_REJ_QTY		 TO 3
EQU COL$NCR_RESP		 TO 4
EQU COL$NCR_STAGE		 TO 5
EQU COL$NCR_LOSS_DESC	 TO 6
EQU COL$NCR_LOSS_COMM	 TO 7
EQU COL$NCR_FIN_SIG		 TO 8
EQU COL$NCR_FIN_SIG_DTM	 TO 9

EQU CRLF$	    TO \0D0A\
EQU TAB$	    TO \09\
EQU TOP$ROW     TO 1
EQU BOTTOM$ROW  TO 25

SubclassInfo    = Form_Services('FindSubclassControl')
Subclass        = SubclassInfo<1>

If Assigned(Param8) else Param8 = ''
// Update the arguments so that the OpenInsight OLE event will treate the ActiveX event as a native event handler.
If Event EQ 'OLE' then
	Transfer Event to OIEvent
	Transfer Param1 to Event
	Transfer Param2 to Param1
	Transfer Param3 to Param2
	Transfer Param4 to Param3
	Transfer Param5 to Param4
	Transfer Param6 to Param5
	Transfer Param7 to Param6
	Transfer Param8 to Param7
end

GoToEvent Event for CtrlEntId else
	// Event not implemented
end

Return EventFlow or 1

//-----------------------------------------------------------------------------
// EVENT HANDLERS
//-----------------------------------------------------------------------------

Event WINDOW.CREATE(CreateParam)
	
	obj_Appwindow('Create',@WINDOW)
	
End Event


Event WINDOW.READ()
	
	Set_Property(@Window, 'REDRAW', False$)
	Set_Property(@Window:'.OLE_EDT_IN_CASS', 'OLE.Redraw', False$)
	Set_Property(@Window:'.OLE_EDT_NCR', 'OLE.Redraw', False$)
	WONo	= Get_Property(@WINDOW:'.WO_NO','DEFPROP')
	CassNo	= Get_Property(@WINDOW:'.CASS_NO','DEFPROP')
	
	IF RowExists('WO_MAT',WONo:'*':CassNo) THEN
		IF NOT(Security_Check('RDS',READ$)) THEN
			Send_Event(@WINDOW,'CLEAR')
			Security_Err_Msg('Work Order Mat',READ$)
			RETURN
		END
		
		IF NOT(Security_Check('RDS',EDIT$)) THEN
			obj_Appwindow('ReadOnly',@WINDOW)					;*Set to Read Only
		END
		
	END ELSE
		ErrMsg('Work Order Mat entries are only created by the program.')
		Send_Event(@WINDOW,'CLEAR')
		RETURN
	END
	
	GoSub SetupOLEControls
	GoSub FillForm
	GoSub EnableArrowButtons
	GoSub EnableAddButton
	GoSub EnableRemoveButton
	GoSub EnableSignButton
	GoSub StyleSymbolics
	CassList = Get_Property(@Window:'.OLE_EDT_IN_CASS', 'OLE.LIST')
	Set_Property(@Window, '@ORIGCASSLIST', CassList)
	Set_Property(@Window, 'REDRAW', True$)
	Set_Property(@Window:'.OLE_EDT_IN_CASS', 'OLE.Redraw', True$)
	Set_Property(@Window:'.OLE_EDT_NCR', 'OLE.Redraw', True$)
	
end event


Event WINDOW.CLOSE(CancelFlag)
	
	obj_Appwindow('DetailReturn')
	
end event


Event WINDOW.CLEAR(bSaveKey, bSuppressWarning, bMaintainFocus, CtrlIDFocus)
	
	GoSub StyleSymbolics
	
end event


Event WINDOW.WRITE()
	
	IOOptions = Get_Property(@Window, 'IOOPTIONS')
	IOOptions<6> = True$
	Set_Property(@Window, 'IOOPTIONS', IOOptions)         
	CassEDTCtrl = @Window:'.OLE_EDT_IN_CASS'
	CassList    = Get_Property(CassEDTCtrl, 'OLE.ARRAY')
	OutSlots    = CassList<1>
	InWfrIDs    = CassList<2>
	CarrSlotIDs = CassList<3>
	WONo        = Get_Property(@Window:'.WO_NO', 'TEXT')
	CassNo      = Get_Property(@Window:'.CASS_NO', 'TEXT')
	// Update WO_MAT_WFR record
	WOMatWfrKey = WONo:'*':CassNo
	WOMatWfrRec = Database_Services('ReadDataRow', 'WO_MAT_WFR', WOMatWfrKey)
	WOMatWfrRec<WO_MAT_WFR_OUT_WFR_ID$> = InWfrIDs
	Database_Services('WriteDataRow', 'WO_MAT_WFR', WOMatWfrKey, WOMatWfrRec, True$, False$, True$)
	// Update REACT_RUN and WO_WFR records
	For each InWfrID in InWfrIDs using @VM setting wPos
		OutSlotID    = WONo:'*':CassNo:'*':OutSlots<0, wPos>
		RDSNo        = Xlate('WO_WFR', InWfrID, 'RDS_NO', 'X')
		// Update REACT_RUN record
		ReactRunRec  = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo)
		RRInWfrIDs   = ReactRunRec<REACT_RUN_IN_WFR_ID$>
		RROutSlotIDs = ReactRunRec<REACT_RUN_OUT_SLOT_ID$>
		Locate InWfrID in RRInWfrIDs using @VM setting vPos then
			RROutSlotIDs<0, vPos> = OutSlotID
		end
		ReactRunRec<REACT_RUN_OUT_SLOT_ID$> = RROutSlotIDs
		Database_Services('WriteDataRow', 'REACT_RUN', RDSNo, ReactRunRec, True$, False$, True$) 
		// Update WO_WFR record
		WOWfrRec  = Database_Services('ReadDataRow', 'WO_WFR', InWfrID)
		EventDTMs = WOWfrRec<WO_WFR_LOC_DTM$>
		NumEvents = DCount(EventDTMs, @VM)
		SlotIDs   = WOWfrRec<WO_WFR_SLOT_ID$>
		SlotIDs<0, NumEvents> = OutSlotID
		WOWfrRec<WO_WFR_SLOT_ID$> = SlotIDs
		Database_Services('WriteDataRow', 'WO_WFR', InWfrID, WOWfrRec, True$, False$, True$)
	Next InWfrID      
	Forward_Event()
	Send_Event(@Window, 'READ')
	
end event


Event PUB_ADD_WAFERS.CLICK()    
	
	WONo        = Get_Property(@WINDOW:'.WO_NO','DEFPROP')
	CassNo      = Get_Property(@WINDOW:'.CASS_NO','DEFPROP')
	CurrLoad    = Get_Property(@WINDOW:'.OLE_EDT_IN_CASS', 'OLE.ARRAY')
	CurrSlotNos = CurrLoad<COL$OUT_SLOT>
	CurrWfrIDs	= CurrLoad<COL$OUT_WFR_ID>
	OutCassID   = WONo:'*':CassNo
	WfrData     = obj_WO_Mat_GaN('GetManifestWfrs', WONo)
	IF Not( Get_Status(errCode) ) THEN
		IF WfrData NE '' THEN       
			CONVERT @VM:@FM TO @SVM:@VM IN WfrData
			TypeOver = ''
			TypeOver<PDISPLAY$> = WfrData
			SelWfrs  = Popup(@WINDOW, TypeOver, 'WO_WFRS')
			swCnt    = DCount(SelWfrs, @FM)   
			WfrArray = SRP_Array('Rotate', SelWfrs, @FM, @VM)
			WaferIDs = WfrArray<1>
			Error_Services('Clear')
			Gan_Services('AddWfrsToOutCass', OutCassID, WaferIDs)        
			If Error_Services('NoError') then
				Send_Event(@Window, 'READ')
				GoSub EnableAddButton
				GoSub EnableRemoveButton
			end else
				ErrorMessage = Error_Services('GetMessage')
				ErrMsg(ErrorMessage)
			end
		end else
			Msg(@WINDOW,'','NO_SHIPPABLE')       
		end
	end else
		ErrMsg(errCode) 
	end
	
end event


Event PUB_REM_WAFERS.CLICK()
	WONo	        = Get_Property(@WINDOW:'.WO_NO','DEFPROP')
	CassNo	        = Get_Property(@WINDOW:'.CASS_NO','DEFPROP')
	SlotSelection	= Get_Property(@WINDOW:'.OLE_EDT_IN_CASS', 'OLE.SelPos')
	SelectedRows	= SlotSelection<2>
	WfrIDs          = ''
	WfrArray        = Get_Property(@WINDOW:'.OLE_EDT_IN_CASS', 'OLE.ARRAY')
	InWfrIDs        = WfrArray<2>
	For each SelRow in SelectedRows using @VM setting vPos
		WfrIDs<0, -1> = InWfrIDs<0, SelRow>
	Next SelRow
	OutCassID = WONo:'*':CassNo
	Error_Services('Clear')
	Gan_Services('RemoveWfrsFromOutCass', OutCassID, WfrIDs)
	If Error_Services('NoError') then
		Send_Event(@Window, 'READ')
		GoSub EnableAddButton
		GoSub EnableRemoveButton
	end else
		ErrorMessage = Error_Services('GetMessage')
		ErrMsg(ErrorMessage)
	end
	
end event


Event PUB_SIGN_FQA.CLICK()
	
	WONo	= Get_Property(@WINDOW:'.WO_NO','DEFPROP')
	CassNo	= Get_Property(@WINDOW:'.CASS_NO','DEFPROP')
	
	Valid = Dialog_Box('NDW_VERIFY_USER', @Window, @User4)
    Valid = Valid<1>
	
	IF NOT(Valid) THEN
		RETURN 0
	END
	
	SigDTM = OCONV( Date(), 'D4/' ):' ':OCONV( Time(), 'MTS' )
	
	Set_Property(@WINDOW:'.CASS_FINAL_SIG','DEFPROP',@USER4)
	Set_Property(@WINDOW:'.CASS_FINAL_SIG_DTM','DEFPROP',SigDTM)
	
	Send_Event(@WINDOW,'WRITE')
	
	ScanUser	= @USER4
	ScanDTM		= SigDTM
	WOStep		= '1' 			;* GaN is a single step process
	StatusStage = 'G_FQA'
	WhCd 		= 'CR'
	LocCd		= 'QA'
	Tags		= ''
	ToolID		= ''
	
	owmParms = WONo:@RM:CassNo:@RM:WOStep:@RM:StatusStage:@RM:ScanUser:@RM:ScanDTM:@RM:ToolID:@RM:WHCd:@RM:LocCD:@RM:Tags
	
	If Get_Status(errCode) then
		ErrMsg(errCode)
	end	else
		EventParms                  = ''
		EventParms<COL$LOG_FILE>    = 'WO_MAT'
		EventParms<COL$LOG_DTM>     = SigDTM
		EventParms<COL$ACTION>      = WOStep:'QA'
		EventParms<COL$WH_CD>       = 'CR'
		EventParms<COL$LOC_CD>      = 'QA'
		EventParms<COL$WO_NOS>      = WONo
		EventParms<COL$CASS_NOS>    = CassNo
		EventParms<COL$USER_ID>     = @USER4
		EventParms<COL$TAGS>        = ''
		EventParms<COL$TOOL_ID>     = ''
		
		CONVERT @FM TO @RM IN EventParms
		
		obj_WO_Mat_Log('Create',EventParms)
		
		If Get_Status(errCode) Then
			ErrMsg(errCode)
		End
		
		// Move wafers out of G_PACK location queue
		CurrDTM       = Datetime()
		EDTList       = Get_Property(@Window:'.OLE_EDT_IN_CASS', 'OLE.LIST')
		*        WOLogRec      = Database_Services('ReadDataRow', 'WO_LOG', WONo)
		*        AvailSlotList = WOLogRec<WO_LOG_AVAIL_OUT_SLOTS$>
		For each Row in EDTList using @FM setting RowIndex
			WfrID     = Row<0, COL$OUT_WFR_ID>
			RDSNo     = Field(Row<0, COL$OUT_CARR_SLOT_ID>, '.', 1)
			CurrStage = GaN_Services('GetCurrStage', WfrID)
			CurrQ     = GaN_Services('GetWfrQueue', WfrID)
			Gan_Services('RemoveWfrFromWIP', WfrID)
			// Mark current stage complete
			Convert '*' to '.' in WfrID
			RunStageWfrKey = RDSNo:'*':CurrStage:'*':WfrID
			RunStageWfrRec = Database_Services('ReadDataRow', 'RUN_STAGE_WFR', RunStageWfrKey)
			StageStatus    = RunStageWfrRec<RUN_STAGE_WFR_STATUS$>
			If StageStatus _EQC 'INIT' then
				// Mark DISP stage as complete
				RunStageWfrRec<RUN_STAGE_WFR_COMP_BY$>  = @USER4
				RunStageWfrRec<RUN_STAGE_WFR_COMP_DTM$> = CurrDTM
				RunStageWfrRec<RUN_STAGE_WFR_STATUS$>   = 'COMP'
				Database_Services('WriteDataRow', 'RUN_STAGE_WFR', RunStageWfrKey, RunStageWfrRec, True$, False$, True$)
			end
			// Ensure all slots are marked as unavailable in the WO_LOG record
			Convert '.' to '*' in WfrID
			SlotNo  = RowIndex
			SlotKey = CassNo:'*':SlotNo
			*            Locate SlotKey in AvailSlotList using @VM setting vPos then
			*                AvailSlotList<0, vPos> = 0            
			*            end
		Next Row
		*        WOLogRec<WO_LOG_AVAIL_OUT_SLOTS$> = AvailSlotList
		*        Database_Services('WriteDataRow', 'WO_LOG', WONo, WOLogRec, True$, False$, True$)
	end
	
	obj_AppWindow('LoadFormKeys',@WINDOW:@RM:WONo:'*':CassNo)
	
end event


Event PUB_PRINT_CASS_LABEL.CLICK()
	
	WONo   = Get_Property(@WINDOW:'.WO_NO','DEFPROP')
	CassNo = Get_Property(@WINDOW:'.CASS_NO','DEFPROP')
	Print_Gan_Out_Labels(WONo,CassNo)
	
end event


Event PUB_PRINT_MANIFEST.CLICK()
	
	WONo   = Get_Property(@WINDOW:'.WO_NO','DEFPROP')
	CassNo = Get_Property(@WINDOW:'.CASS_NO','DEFPROP') 
	Print_Manifest(WONo, CassNo)
	
end event


Event PUB_UPDATE_DB.CLICK()
	
	Response = Msg(@Window, '', 'YESNO', '', 'Verification':@FM:'Have you verified the wafer List accuracy?')
	If Response EQ Yes$ then
		WONo   = Get_Property(@Window:'.WO_NO', 'TEXT')
		CassNo = Get_Property(@Window:'.CASS_NO', 'TEXT')
		WMOKey = WONo:'*1*':CassNo
		Material_Services('UpdateWaferLocation', WMOKey)
		Msg(@Window, '', 'OK', '', 'Success':@FM:'Data updated successfully!')
	end
	
end event


Event PUB_TOP_ARROW.CLICK()
	
	CassEDTCtrl = @Window:'.OLE_EDT_IN_CASS'
	CassList    = Get_Property(CassEDTCtrl, 'OLE.LIST')
	SelList     = Get_Property(CassEDTCtrl, 'OLE.SelPos')
	SelRowIndex = SelList<2, 1>
	SelRow      = CassList<SelRowIndex>
	CassList    = Delete(CassList, SelRowIndex, 0 ,0)
	CassList    = Insert(CassList, TOP$ROW, 0, 0, SelRow)
	Set_Property(CassEDTCtrl, 'LIST', CassList)
	GoSub UpdateSlotNos
	GoSub SetSavewarn
	Set_Property(CassEDTCtrl, 'SELPOS', 0:@FM:TOP$ROW)
	GoSub EnableArrowButtons
	
end event


Event PUB_UP_ARROW.CLICK()
	
	CassEDTCtrl = @Window:'.OLE_EDT_IN_CASS'
	CassList    = Get_Property(CassEDTCtrl, 'OLE.LIST')
	SelList     = Get_Property(CassEDTCtrl, 'OLE.SelPos')
	SelRowIndex = SelList<2, 1>    
	SelRow      = CassList<SelRowIndex>
	CassList    = Delete(CassList, SelRowIndex, 0 ,0)
	NewRowIndex = SelRowIndex - 1
	CassList    = Insert(CassList, NewRowIndex, 0, 0, SelRow)
	Set_Property(CassEDTCtrl, 'LIST', CassList)
	GoSub UpdateSlotNos
	GoSub SetSavewarn
	Set_Property(CassEDTCtrl, 'SELPOS', 0:@FM:NewRowIndex)
	GoSub EnableArrowButtons
	
end event


Event PUB_DOWN_ARROW.CLICK()
	
	CassEDTCtrl = @Window:'.OLE_EDT_IN_CASS'
	CassList    = Get_Property(CassEDTCtrl, 'OLE.LIST')
	SelList     = Get_Property(CassEDTCtrl, 'OLE.SelPos')
	SelRowIndex = SelList<2, 1>
	SelRow      = CassList<SelRowIndex>
	CassList    = Delete(CassList, SelRowIndex, 0 ,0)
	NewRowIndex = SelRowIndex + 1
	CassList    = Insert(CassList, NewRowIndex, 0, 0, SelRow)
	Set_Property(CassEDTCtrl, 'LIST', CassList)
	GoSub UpdateSlotNos
	GoSub SetSavewarn
	Set_Property(CassEDTCtrl, 'SELPOS', 0:@FM:NewRowIndex)
	GoSub EnableArrowButtons
	
end event


Event PUB_BOTTOM_ARROW.CLICK()
	
	CassEDTCtrl = @Window:'.OLE_EDT_IN_CASS'
	CassList    = Get_Property(CassEDTCtrl, 'OLE.LIST')
	SelList     = Get_Property(CassEDTCtrl, 'OLE.SelPos')
	SelRowIndex = SelList<2, 1>
	SelRow      = CassList<SelRowIndex>
	CassList    = Delete(CassList, SelRowIndex, 0 ,0)
	CassList    = Insert(CassList, BOTTOM$ROW, 0, 0, SelRow)
	Set_Property(CassEDTCtrl, 'LIST', CassList)
	GoSub UpdateSlotNos   
	GoSub SetSavewarn
	// Return focus to the new row index.
	Set_Property(CassEDTCtrl, 'SELPOS', 0:@FM:BOTTOM$ROW)
	GoSub EnableArrowButtons
	
end event


Event PUB_CREATE_NCR.CLICK()
	
	! To do
	
end event


Event OLE_EDT_IN_CASS.OnClick(Cell, Point, Button, Shift, Ctrl)
	
	GoSub EnableArrowButtons
	GoSub EnableRemoveButton
	
end event


Event OLE_EDT_IN_CASS.OnCheckChanged(Cell, OldValue, NewValue)
	
	Col = Field(Cell, ';', 1, 1)
	Row = Field(Cell, ';', 2, 1)
	NCRButton = ''
	Begin Case    
		
		Case Col EQ COL$CASS_WMO_NCR
			// The checkbox is only used for creating NCRs. We don't need to save anything at this time.
			// Check (no pun intended) if any of the checkboxes in this column are True$. If so, then enable
			// the "Create NCR" button, otherwise disable it.
			GoSub EnableNCRButton
			
	End Case
	
end event


Event OLE_EDT_NCR.OnDblClick(Cell, Point, Button, Shift, Ctrl)
	
	Row   = Field(Cell, ';', 2, 1)
	NCRNo = Get_Property(CtrlEntID, "OLE.CellText[":COL$NCR_NO:";":Row:"]")
	If RowExists('NCR', NCRNo) then
		PreNCRRec  = Database_Services('ReadDataRow', 'NCR', NCRNo)
		Dialog_Box('NCR', @Window, NCRNo)
		PostNCRRec = Database_Services('ReadDataRow', 'NCR', NCRNo)
		If PreNCRRec NE PostNCRRec then GoSub FillNCREditTable          
	end
	
end event


Event PUB_PRINT_SCRIBE.CLICK()
	
	WONo   = Get_Property(@WINDOW:'.WO_NO','DEFPROP')
	CassNo = Get_Property(@WINDOW:'.CASS_NO','DEFPROP')
	If ( (WONo NE '') and (CassNo NE '') ) then
		Response  = Dialog_Box('NDW_REC_SEND', @Window)
		If Response then
			Recipient = Response<1>
			Sender    = Response<2>
			If ( (Sender NE '') and (Recipient NE '') ) then
				Print_Gan_Scribe_Labels(WONo, CassNo, Recipient, Sender)
			end
		end
	end
	
end event


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Internal GoSubs
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


StyleSymbolics:
	
	* Turn edit table symbolic column backgrounds to green
	
	ETSymbolics = Get_Property('WO_MAT_WFR','@ET_SYMBOLICS')		;* Loaded during 'Create' in obj_Appwindow
	
	ETCtrls	= ETSymbolics<1>
	ETCols	= ETSymbolics<2>
	
	FOR I = 1 TO COUNT(ETCtrls,@VM) + (ETCtrls NE '')
		ETCtrl	= ETCtrls<1,I>
		IF ETCtrl NE 'WO_MAT_WFR.SLOT_NO' THEN
			ETList = Get_Property(ETCtrl,'LIST')
			FOR Line = 1 TO COUNT(ETList,@FM) + (ETList NE '')
				IF ETList<Line,1> NE '' THEN
					FOR N = 1 TO COUNT(ETCols<1,I>,@SVM) + (ETCols<1,I> NE '')
						stat = Send_Message(ETCtrl,'COLOR_BY_POS',ETCols<1,I,N>,Line,GREEN$)
					NEXT N
				END
			NEXT Line
		END
	NEXT I
	
return


EnableArrowButtons:
	
	WONo        = Get_Property(@Window:'.WO_NO', 'TEXT')
	PSNo        = Xlate('WO_LOG', WONo, 'PS_NO', 'X')
	TechType    = Xlate('PROD_SPEC', PSNo, 'TECH_TYPE', 'X')
	CassEDTCtrl = @Window:'.OLE_EDT_IN_CASS'
	TopArrow    = @Window:'.PUB_TOP_ARROW'
	UpArrow     = @Window:'.PUB_UP_ARROW'
	DownArrow   = @Window:'.PUB_DOWN_ARROW'
	BottomArrow = @Window:'.PUB_BOTTOM_ARROW'
	CassList    = Get_Property(CassEDTCtrl, 'OLE.ARRAY')
	SelRow      = ''
	SelWfrID    = ''
	WfrList     = CassList<2>
	NumWfrs     = 0
	For each Row in WfrList using @VM setting fPos
		If Row NE '' then NumWfrs += 1
	Next Row
	SelList     = Get_Property(CassEDTCtrl, 'OLE.SelPos')
	SelRows     = SelList<2>
	NumSelRows  = DCount(SelRows, @VM)
	If NumSelRows EQ 1 then
		SelRow   = SelRows<0, 1>
		SelWfrID = WfrList<0, SelRow>
	end
	CassList = Delete(CassList, 1, 0, 0)
	Convert @FM to '' in CassList
	Convert @VM to '' in CassList
	Convert @FM to '' in SelList
	Convert @VM to '' in SelList
	Begin Case
		
		Case TechType EQ 'P'
			
			Set_Property(TopArrow,      'ENABLED', False$)
			Set_Property(UpArrow ,      'ENABLED', False$)
			Set_Property(DownArrow,     'ENABLED', False$)
			Set_Property(BottomArrow,   'ENABLED', False$) 
			
		Case (CassList NE '') and (SelList NE '') and (NumSelRows EQ 1) and (SelWfrID NE '')                               
			
			Begin Case
				Case SelRow EQ TOP$ROW
					Set_Property(TopArrow,      'ENABLED', False$)
					Set_Property(UpArrow ,      'ENABLED', False$)
					Set_Property(DownArrow,     'ENABLED', True$)
					Set_Property(BottomArrow,   'ENABLED', True$)               
				Case (SelRow EQ BOTTOM$ROW)
					Set_Property(TopArrow,      'ENABLED', True$)
					Set_Property(UpArrow ,      'ENABLED', True$)
					Set_Property(DownArrow,     'ENABLED', False$)
					Set_Property(BottomArrow,   'ENABLED', False$)
				Case Otherwise$
					Set_Property(TopArrow,      'ENABLED', True$)
					Set_Property(UpArrow ,      'ENABLED', True$)
					Set_Property(DownArrow,     'ENABLED', True$)
					Set_Property(BottomArrow,   'ENABLED', True$)                                        
			End Case
			
		Case Otherwise$
			
			Set_Property(TopArrow,      'ENABLED', False$)
			Set_Property(UpArrow ,      'ENABLED', False$)
			Set_Property(DownArrow,     'ENABLED', False$)
			Set_Property(BottomArrow,   'ENABLED', False$)               
			
	End Case
	
return


UpdateSlotNos:
	
	CassEDTCtrl = @Window:'.OLE_EDT_IN_CASS'
	CassList    = Get_Property(CassEDTCtrl, 'OLE.ARRAY')
	SlotList    = ''
	SlotNo      = ''
	For SlotNo = 1 to 25
		SlotList<0, -1> = SlotNo
	Next SlotNo
	CassList<1> = SlotList
	Set_Property(CassEDTCtrl, 'OLE.ARRAY', CassList)
	
return


SetSavewarn:
	
	CurrCassList = Get_Property(@Window:'.OLE_EDT_IN_CASS', 'OLE.LIST')
	OrigCassList = Get_Property(@Window, '@ORIGCASSLIST')
	If CurrCassList NE OrigCassList then
		Set_Property(@Window, 'SAVEWARN', True$)
	end else
		Set_Property(@Window, 'SAVEWARN', False$)
	end
	
return


EnableRemoveButton:
	
	WONo          = Get_Property(@Window:'.WO_NO', 'TEXT')
	PSNo          = Xlate('WO_LOG', WONo, 'PS_NO', 'X')
	TechType      = Xlate('PROD_SPEC', PSNo, 'TECH_TYPE', 'X')
	CassArray     = Get_Property(@Window:'.OLE_EDT_IN_CASS', 'OLE.ARRAY')
	SlotSelection = Get_Property(@Window:'.OLE_EDT_IN_CASS', 'OLE.SelPos')
	WfrSelected   = False$
	WfrCol        = CassArray<2>
	SelectedRows  = SlotSelection<2>
	SelCnt		  = DCount(SelectedRows, @VM)
	If SelCnt GT 0 then
		For each RowIndex in SelectedRows using @VM setting vPos
			// Does at least one row selected have a wafer ID in it?
			WfrID = WfrCol<0, RowIndex>
			If WfrID NE '' then WfrSelected = True$
		Until WfrSelected EQ True$
		Next RowIndex
	end
	Begin Case
		Case TechType EQ 'P'
			
			Set_Property(@Window:'.PUB_REM_WAFERS', 'ENABLED', False$)
			
		Case ( (SelCnt GT 0) and (WfrSelected EQ True$) )
			
			Set_Property(@Window:'.PUB_REM_WAFERS', 'ENABLED', True$)
			
		Case Otherwise$
			
			Set_Property(@Window:'.PUB_REM_WAFERS', 'ENABLED', False$)
			
	End Case
	
return


EnableAddButton:
	
	WONo          = Get_Property(@Window:'.WO_NO', 'TEXT')
	PSNo          = Xlate('WO_LOG', WONo, 'PS_NO', 'X')
	CurrPartNo    = Xlate('PROD_SPEC', PSNo, 'CURR_PART_NO', 'X')
	TechType      = Xlate('PROD_SPEC', PSNo, 'TECH_TYPE', 'X')
	CassArray     = Get_Property(@Window:'.OLE_EDT_IN_CASS', 'OLE.ARRAY')
	WfrCol        = CassArray<2>
	SlotAvailable = False$
	
	For each WfrID in WfrCol using @VM setting WfrIndex
		// Is at least one row empty?
		If WfrID EQ '' then SlotAvailable = True$
	Until SlotAvailable EQ True$
	Next WfrID
	
	Begin Case
		Case TechType EQ 'P' ; // and CurrPartNo NE 'U314'
			
			Set_Property(@Window:'.PUB_ADD_WAFERS', 'ENABLED', False$)
			
		Case SlotAvailable EQ True$
			
			Set_Property(@Window:'.PUB_ADD_WAFERS', 'ENABLED', True$)
			
		Case Otherwise$
			
			Set_Property(@Window:'.PUB_ADD_WAFERS', 'ENABLED', False$)
			
	End Case
	
return


SetupOLEControls:
	
	GoSub SetupCassEditTable                
	GoSub SetupNCREditTable
	
return


SetupCassEditTable:
	
	NumCassCols = 7
	NumCassRows = 25
	CassCtrl    = @Window:'.OLE_EDT_IN_CASS'
	
	HeaderFontArray   = 'Segoe UI':@SVM:8:@SVM:700
	CassDimArray      = NumCassCols :@FM: NumCassRows
	
	Set_Property(CassCtrl, "OLE.CellFont[All; All]", 'Segoe UI':@SVM:8)
	Set_Property(CassCtrl, "OLE.Dimension", CassDimArray)
	Set_Property(CassCtrl, "OLE.HeaderFont[All; 1]", HeaderFontArray)
	Set_Property(CassCtrl, "OLE.HeaderFont[1; All]", HeaderFontArray)
	
	CassHeaderTitles = 'Slot':@VM:'Inbound':@VM:'Carrier':@VM:'GaN Wfr ID':@VM:'Scribe':@VM:'Grade':@VM:'WMO NCR'
	Set_Property(CassCtrl, "OLE.TitleList", CassHeaderTitles)
	Set_Property(CassCtrl, "OLE.HeaderAlignment[All; 1]", 'C':@FM:'C':@FM:'L')
	Set_Property(CassCtrl, "OLE.CellAlignment[1; All]", 'C':@FM:'C':@FM:'L')
	Set_Property(CassCtrl, "OLE.CellAlignment[2-":NumCassCols-1:"; All]", 'C':@FM:'L':@FM:'L')
	Set_Property(CassCtrl, "OLE.CellAlignment[":COL$CASS_WMO_NCR:"; All]", 'C':@FM:'C':@FM:'L')
	Set_Property(CassCtrl, "OLE.AllowDeletions", False$)
	Set_Property(CassCtrl, "OLE.AllowInserts", False$)
	HeaderColArray    = ''
	HeaderColArray<2> = False$
	Set_Property(CassCtrl, "OLE.HeaderColumn[1]", HeaderColArray)
	
	// Set default header colors
	HeaderColorArray    = ''
	HeaderColorArray<1> = 'Auto'
	HeaderColorArray<2> = 'None'
	HeaderColorArray<3> = 'None'
	HeaderColorArray<4> = OI_HOT_BLUE$
	HeaderColorARray<5> = False$
	Set_Property(CassCtrl, "OLE.HeaderColors[All; All]", HeaderColorArray)
	
	// Qualify OLE events that we want to intercept
	Qualifier = ''
	Qualifier<1> = 1
	Qualifier<4> = 0 ; * process synchronously (i.e. immediately)
	Send_Message(CassCtrl, 'QUALIFY_EVENT', 'OLE.OnCheckChanged', Qualifier)
	Send_Message(CassCtrl, 'QUALIFY_EVENT', 'OLE.OnClick', Qualifier)
	
	// Disable resizing of the header row and header column
	// Resize header column to fit contents
	HeaderRowArray = Get_Property(CassCtrl, "OLE.HeaderRow[1]")
	HeaderRowArray<3> = False$
	Set_Property(CassCtrl, "OLE.HeaderRow[1]", HeaderRowArray)
	// Disable resizing of columns as there is no need for this on this form
	ColSize = Get_Property(CassCtrl, "OLE.DataColumn[1]")
	ColSize<3> = False$
	Set_Property(CassCtrl, "OLE.DataColumn[All]", ColSize)
	// Manually set column widths
	ColSize<1> = 45
	Set_Property(CassCtrl, "OLE.DataColumn[":COL$CASS_SLOT:"]", ColSize)
	ColSize<1> = 80
	Set_Property(CassCtrl, "OLE.DataColumn[":COL$CASS_WFR_ID:"]", ColSize)
	ColSize<1> = 76
	Set_Property(CassCtrl, "OLE.DataColumn[":COL$CASS_CARR_SLOT_ID:"]", ColSize)
	ColSize<1> = 100
	Set_Property(CassCtrl, "OLE.DataColumn[":COL$CASS_GAN_WFR_ID:"]", ColSize)
	ColSize<1> = 76
	Set_Property(CassCtrl, "OLE.DataColumn[":COL$CASS_SCRIBE:"]", ColSize)
	ColSize<1> = 50
	Set_Property(CassCtrl, "OLE.DataColumn[":COL$CASS_GRADE:"]", ColSize)
	ColSize<1> = 70
	Set_Property(CassCtrl, "OLE.DataColumn[":COL$CASS_WMO_NCR:"]", ColSize)
	// Disable scroll bars
	Set_Property(CassCtrl, "OLE.ScrollBarsVisible", 'N':@FM:'N')    
	// Disable resizing of rows as there is no need for this on this form
	RowSizeProps = Get_Property(CassCtrl, "OLE.DataRow[1]")
	RowSizeProps<3> = False$
	Set_Property(CassCtrl, "OLE.DataRow[All]", RowSizeProps)   
	Set_Property(CassCtrl, "OLE.CellProtection[All; All]", 'SEL')    
	// Color headers
	HeaderColorArray    = ''
	HeaderColorArray<2> = "{200, 200, 200}"
	HeaderColorArray<4> = "{200, 200, 200}"
	Set_Property(CassCtrl, "OLE.HeaderColors[All; 1]", HeaderColorArray)   
	// Color cells
	Set_Property(CassCtrl, "OLE.CellColors[All; All]", 'None':@FM:RGB(192,220,192))
	// Cell selection style setup
	Set_Property(CassCtrl, "OLE.ResetSelPos", False$) ;// Prevent cell selection reset upon lost focus event
	
	CassSelStyleArray      = Get_Property(CassCtrl, "OLE.SelectionStyle")
	CassSelStyleArray<2,2> = OI_HOT_BLUE$
	CassSelStyleArray<3,2> = 'None'
	CassSelStyleArray<4>   = 'None'
	CassSelStyleArray<6>   = 'None'
	CassSelStyleArray<7>   = 'None'
	CassSelStyleArray<8>   = True$                              ;// Keep cell highlighted when table loses focus
	Set_Property(CassCtrl,  'OLE.SelectionStyle', CassSelStyleArray)   
	
return


SetupNCREditTable:
	
	NumNCRCols  = 9
	NumNCRRows  = 5
	NCRCtrl     = @Window:'.OLE_EDT_NCR'
	
	HeaderFontArray   = 'Segoe UI':@SVM:8:@SVM:700
	NCRDimArray       = NumNCRCols :@FM: NumNCRRows
	
	Set_Property(NCRCtrl, "OLE.CellFont[All; All]", 'Segoe UI':@SVM:8)
	Set_Property(NCRCtrl, "OLE.Dimension", NCRDimArray)
	Set_Property(NCRCtrl, "OLE.HeaderFont[All; 1]", HeaderFontArray)
	Set_Property(NCRCtrl, "OLE.HeaderFont[1; All]", HeaderFontArray)
	
	NCRHeaderTitles  = 'NCR':@VM:'Status':@VM:'Qty':@VM:'Responsible':@VM:'Stage':@VM:'Loss Desc':@VM
	NCRHeaderTitles := 'Loss Comments':@VM:'Signature':@VM:'Date & Time'
	Set_Property(NCRCtrl, "OLE.TitleList", NCRHeaderTitles)
	Set_Property(NCRCtrl, "OLE.HeaderAlignment[All; 1]", 'C':@FM:'C':@FM:'L')
	Set_Property(NCRCtrl, "OLE.CellAlignment[All; All]", 'C':@FM:'C':@FM:'L')
	Set_Property(NCRCtrl, "OLE.AllowDeletions", False$)
	Set_Property(NCRCtrl, "OLE.AllowInserts", False$)
	HeaderColArray    = ''
	HeaderColArray<2> = False$
	Set_Property(NCRCtrl, "OLE.HeaderColumn[1]", HeaderColArray)
	
	// Set default header colors
	HeaderColorArray    = ''
	HeaderColorArray<1> = 'Auto'
	HeaderColorArray<2> = 'None'
	HeaderColorArray<3> = 'None'
	HeaderColorArray<4> = OI_HOT_BLUE$
	HeaderColorARray<5> = False$
	Set_Property(NCRCtrl, "OLE.HeaderColors[All; All]", HeaderColorArray)
	
	// Qualify OLE events that we want to intercept
	Qualifier = ''
	Qualifier<1> = 1
	Qualifier<4> = 0 ; * process synchronously (i.e. immediately)
	Send_Message(NCRCtrl, 'QUALIFY_EVENT', 'OLE.OnDblClick', Qualifier)    
	
	// Disable resizing of the header row and header column
	// Resize header column to fit contents
	HeaderRowArray = Get_Property(NCRCtrl, "OLE.HeaderRow[1]")
	HeaderRowArray<3> = False$
	Set_Property(NCRCtrl, "OLE.HeaderRow[1]", HeaderRowArray)
	// Disable resizing of columns as there is no need for this on this form
	ColSize = Get_Property(NCRCtrl, "OLE.DataColumn[1]")
	ColSize<3> = False$
	ColSize<1> = 56
	Set_Property(NCRCtrl, "OLE.DataColumn[":COL$NCR_NO:"]", ColSize)
	ColSize<1> = 45
	Set_Property(NCRCtrl, "OLE.DataColumn[":COL$NCR_STATUS:"]", ColSize)
	ColSize<1> = 35
	Set_Property(NCRCtrl, "OLE.DataColumn[":COL$NCR_REJ_QTY:"]", ColSize)
	ColSize<1> = 90
	Set_Property(NCRCtrl, "OLE.DataColumn[":COL$NCR_RESP:"]", ColSize)
	ColSize<1> = 58
	Set_Property(NCRCtrl, "OLE.DataColumn[":COL$NCR_STAGE:"]", ColSize)
	ColSize<1> = 100
	Set_Property(NCRCtrl, "OLE.DataColumn[":COL$NCR_LOSS_DESC:"]", ColSize)
	ColSize<1> = 100
	Set_Property(NCRCtrl, "OLE.DataColumn[":COL$NCR_LOSS_COMM:"]", ColSize)
	ColSize<1> = 100
	Set_Property(NCRCtrl, "OLE.DataColumn[":COL$NCR_FIN_SIG:"]", ColSize)
	ColSize<1> = 100
	Set_Property(NCRCtrl, "OLE.DataColumn[":COL$NCR_FIN_SIG_DTM:"]", ColSize)
	
	// Disable resizing of rows as there is no need for this on this form
	RowSizeProps = Get_Property(NCRCtrl, "OLE.DataRow[1]")
	RowSizeProps<3> = False$
	Set_Property(NCRCtrl, "OLE.DataRow[All]", RowSizeProps)   
	Set_Property(NCRCtrl, "OLE.CellProtection[":COL$NCR_NO:"-":COL$NCR_FIN_SIG_DTM:"; All]", 'SEL')   
	// Color headers
	Set_Property(NCRCtrl, "OLE.HeaderColors[All; 1]", @FM:"{200, 200, 200}")   
	// Color cells
	Set_Property(NCRCtrl, "OLE.CellColors[All; All]", 'None':@FM:RGB(192,220,192))
	// Set Loss Comments column to autosized so that the table resizes when scrollbars are necessary
	ColArray = Get_Property(NCRCtrl, "OLE.DataColumn[":COL$NCR_LOSS_COMM:"]")
	ColArray<4> = True$
	Set_Property(NCRCtrl, "OLE.DataColumn[":COL$NCR_LOSS_COMM:"]", ColArray)
	
return


FillForm:
	
	WONo         = Get_Property(@Window:'.WO_NO', 'TEXT')
	CassNo       = Get_Property(@Window:'.CASS_NO', 'TEXT')
	If ( (WONo NE '') and (CassNo NE '') ) then
		GoSub FillCassEditTable
		GoSub FillNCREditTable
	end
	
return


FillCassEditTable:
	
	CassCtrl     = @Window:'.OLE_EDT_IN_CASS'
	WONo         = Get_Property(@Window:'.WO_NO', 'TEXT')
	CassNo       = Get_Property(@Window:'.CASS_NO', 'TEXT')
	
	If ( (WONo NE '') and (CassNo NE '') ) then
		// Suppress redraw until all properties are set
		Set_Property(CassCtrl, "OLE.Redraw", False$)
		
		WOMatKey     = WONo:'*':CassNo
		Database_Services('ActivateRecord', 'WO_MAT', WOMatKey)
		CassCtrlArray = ''
		CassCtrlArray<COL$CASS_SLOT>         = {OUT_SLOT_NO}
		CassCtrlArray<COL$CASS_WFR_ID>       = {OUT_WFR_ID}
		CassCtrlArray<COL$CASS_CARR_SLOT_ID> = {OUT_CARR_SLOT_ID}
		CassCtrlArray<COL$CASS_GAN_WFR_ID>   = {OUT_GAN_WFR_ID}
		CassCtrlArray<COL$CASS_SCRIBE>       = {OUT_SCRIBE}
		CassCtrlArray<COL$CASS_GRADE>        = {OUT_GRADE}
		CassCtrlArray<COL$CASS_WMO_NCR>      = {OUT_NCR}
		
		For RowIndex = 1 to 25
			NCRNo = CassCtrlArray<COL$CASS_WMO_NCR, RowIndex>
			WfrID = CassCtrlArray<COL$CASS_WFR_ID,  RowIndex>
			If ( (NCRNo EQ '') and (WfrID NE '') ) then
				// This inbound wafer is eligible to be NCR'd
				// Convert NCR cell for this row into a check box
				Set_Property(CassCtrl, "OLE.CellText[":COL$CASS_WMO_NCR:";":RowIndex:"]", '')
				CheckBoxArray      = 'Check Box'
				CheckBoxArray<2,1> = True$
				Set_Property(CassCtrl, "OLE.CellType[":COL$CASS_WMO_NCR:";":RowIndex:"]", CheckBoxArray)
				Set_Property(CassCtrl, "OLE.CellCheckEnabled[":COL$CASS_WMO_NCR:";":RowIndex:"]", True$)
			end else
				Set_Property(CassCtrl, "OLE.CellType[":COL$CASS_WMO_NCR:";":RowIndex:"]", 'Text')
			end
		Next RowIndex
		
		Set_Property(CassCtrl, 'OLE.ARRAY', CassCtrlArray)
		// Re-enable redraw now that all properties are set
		Set_Property(CassCtrl, "OLE.Redraw", True$)
	end
	
return


FillNCREditTable:
	
	WONo              = Get_Property(@Window:'.WO_NO', 'TEXT')
	CassNo            = Get_Property(@Window:'.CASS_NO', 'TEXT')
	CassCtrl          = @Window:".OLE_EDT_IN_CASS"
	NCRCtrl           = @Window:'.OLE_EDT_NCR'
	SearchTable       = 'NCR'
	SearchString      = 'WO_NO' : @VM : WONo : @FM
	SearchString     := 'OUT_CASS_NO' : @VM : CassNo : @FM
	hDictSearchTable  = Database_Services('GetTableHandle', 'DICT.' : SearchTable)
	NCRNos            = ''
	If Error_Services('NoError') then
		rv              = Set_Status(0)
		MakeupBoxes     = ''
		Flag            = ''
		StatusCode      = ''
		Btree.Extract(SearchString, SearchTable, hDictSearchTable, NCRNos, '', Flag)
	end
	NCRCtrlArray = ''
	Set_Property(NCRCtrl, "OLE.Redraw", False$)
	If ( (NCRNos NE 0) and (NCRNos NE '') ) then           
		NCRCtrl = @Window:'.OLE_EDT_NCR'
		For each NCRNo in NCRNos using @VM setting nPos
			If ( (RowExists('NCR', NCRNo)) and (NCRNo NE 0) ) then
				Database_Services('ActivateRecord', 'NCR', NCRNo)
				NCRCtrlArray<COL$NCR_NO, nPos>          =  NCRNo
				NCRCtrlArray<COL$NCR_STATUS, nPos>      = {STATUS}
				NCRCtrlArray<COL$NCR_REJ_QTY, nPos>     = {REJ_CNT}
				NCRCtrlArray<COL$NCR_RESP, nPos>        = {LOSS_BY}
				NCRCtrlArray<COL$NCR_STAGE, nPos>       = {LOSS_STAGE}
				NCRCtrlArray<COL$NCR_LOSS_DESC, nPos>   = {LOSS_DESC}
				NCRCtrlArray<COL$NCR_LOSS_COMM, nPos>   = {LOSS_COMMENTS}
				NCRCtrlArray<COL$NCR_FIN_SIG, nPos>     = OConv({AUTH_SHIP_SIG}, '[XLATE_CONV,LSL_USERS*FIRST_LAST]')
				NCRCtrlArray<COL$NCR_FIN_SIG_DTM, nPos> = OConv({AUTH_SHIP_SIG_DTM}, 'DT')
			end
		Next NCR
	end else
		// No NCRs associated with this inbound cassette, so clear the NCR table.
		For nPos = 1 to 5
			NCRCtrlArray<COL$NCR_NO, nPos>          = ''
			NCRCtrlArray<COL$NCR_STATUS, nPos>      = ''
			NCRCtrlArray<COL$NCR_REJ_QTY, nPos>     = ''
			NCRCtrlArray<COL$NCR_RESP, nPos>        = ''
			NCRCtrlArray<COL$NCR_STAGE, nPos>       = ''
			NCRCtrlArray<COL$NCR_LOSS_DESC, nPos>   = ''
			NCRCtrlArray<COL$NCR_LOSS_COMM, nPos>   = ''
			NCRCtrlArray<COL$NCR_FIN_SIG, nPos>     = ''
			NCRCtrlArray<COL$NCR_FIN_SIG_DTM, nPos> = ''
		Next nPos
	end
	Set_Property(NCRCtrl, "OLE.ARRAY", NCRCtrlArray)
	Set_Property(NCRCtrl, "OLE.Redraw", True$)
	
return


EnableNCRButton:
	
	CassCtrl = @Window:'.OLE_EDT_IN_CASS'
	Checkmarks = Get_Property(CassCtrl, "OLE.CellCheck[":COL$CASS_WMO_NCR:"; All]")
	Checksum   = Sum(Checkmarks)
	ButtonEnabled = False$
	If ( Checksum GT 0 ) then ButtonEnabled = True$ 
	*    Set_Property(@Window:'.PUB_CREATE_NCR', 'ENABLED', ButtonEnabled)
	
return


EnableSignButton:
	
	FQASig   = Get_Property(@Window:'.CASS_FINAL_SIG', 'TEXT')
	CassCtrl = @Window:'.OLE_EDT_IN_CASS'
	WfrIDs   = Get_Property(CassCtrl, "OLE.ColumnData[":COL$OUT_WFR_ID:"]")
	WfrIDs   = SRP_Array('Clean', WfrIDs, 'Trim', @VM)
	If ( (WfrIDs NE '') and (FQASig EQ '') ) then
		ButtonEnabled = True$ 
	end else
		ButtonEnabled = False$
	end
	Set_Property(@Window:'.PUB_SIGN_FQA', 'ENABLED', ButtonEnabled)
	
return

