COMPILE FUNCTION Comm_Prod_Spec_SI(Instruction, Parm1,Parm2)
/*
	Commuter module for PROD_SPEC_SI (Product Specification SI) window
	
	01/16/2009 - John C. Henry, J.C. Henry & Co., Inc.
*/
DECLARE SUBROUTINE Set_Property, End_Dialog, Send_Event, Set_Status
DECLARE SUBROUTINE ErrMsg, Send_Message, Set_Property, Send_Event,  obj_AppWindow
DECLARE FUNCTION Get_Property, Get_Status, Dialog_Box, Utility, Popup, Collect.Ixvals
DECLARE FUNCTION Send_Message, obj_PR_Spec, Msg, Security_Check, Start_Window
$INSERT MSG_EQUATES
$INSERT APPCOLORS
$INSERT LSL_USERS_EQU
$INSERT PROD_SPEC_EQU
$INSERT QUOTE_SPEC_EQU
$INSERT RECIPE_EQU
$INSERT RECIPE_LAYER_INFO_EQU	;* Another *($&@^! rathole!
$INSERT POPUP_EQUATES
EQU CRLF$	TO \0D0A\
EQU COL$LS_ID			TO 1
EQU COL$REC_NO			TO 2
EQU COL$REC_DESC		TO 3
EQU COL$THK_MIN			TO 4
EQU COL$THK_MAX			TO 5
EQU COL$THK_UNITS		TO 6
EQU COL$RES_MIN			TO 7
EQU COL$RES_MAX			TO 8
EQU COL$RES_UNITS		TO 9
EQU COL$CON_MIN			TO 10
EQU COL$CON_MAX			TO 11
EQU COL$CON_UNITS		TO 12
EQU COL$CRES_MIN		TO 13
EQU COL$CRES_MAX		TO 14
EQU COL$CRES_UNITS		TO 15
EQU COL$CRES_PHASE_MIN	TO 16
EQU COL$DOPANT			TO 2
EQU COL$THK_MEASURE		TO 3
EQU COL$RES_MEASURE		TO 4
EQU COL$CON_MEASURE		TO 5
EQU COL$CRES_MEASURE	TO 6
ErrTitle = 'Error in Comm_Prod_Spec_SI'
ErrorMsg = ''
Result = ''
BEGIN CASE
	CASE Instruction = 'Create'						; GOSUB Create
	CASE Instruction = 'LSATableDC'					; GOSUB LSATableDC
	CASE Instruction = 'LSTableDC'					; GOSUB LSTableDC
	CASE Instruction = 'LSTableDel'					; GOSUB LSTableDel
	CASE Instruction = 'LSATableDel'				; GOSUB LSATableDel
	CASE Instruction = 'Save'						; GOSUB Save
	CASE Instruction = 'LSAPC'						; GOSUB LSAPC
	CASE Instruction = 'LSPC'						; GOSUB LSPC
	
	CASE 1
		ErrorMsg = 'Unknown Instruction passed to routine.'
		ErrMsg(ErrorMsg)
END CASE
RETURN Result
* * * * * *
Create:
* * * * * *
SaveCheckControls = ''
obj_AppWindow('Create')
Set_Property(@WINDOW:'.LS_TABLE','VISIBLE',1)
Set_Property(@WINDOW:'.LSA_TABLE','VISIBLE',1)
ColStyle = Send_Message(@WINDOW:'.LS_TABLE', 'COLSTYLE', COL$REC_NO) 
ColStyle = bitor(ColStyle, 262144)
ColStyle = Send_Message(@WINDOW:'.LS_TABLE', 'COLSTYLE', COL$REC_NO, ColStyle)
ColStyle = Send_Message(@WINDOW:'.LS_TABLE', 'COLSTYLE', COL$THK_UNITS) 
ColStyle = bitor(ColStyle, 262144)
ColStyle = Send_Message(@WINDOW:'.LS_TABLE', 'COLSTYLE', COL$THK_UNITS, ColStyle)
ColStyle = Send_Message(@WINDOW:'.LS_TABLE', 'COLSTYLE', COL$RES_UNITS) 
ColStyle = bitor(ColStyle, 262144)
ColStyle = Send_Message(@WINDOW:'.LS_TABLE', 'COLSTYLE', COL$RES_UNITS, ColStyle)
ColStyle = Send_Message(@WINDOW:'.LS_TABLE', 'COLSTYLE', COL$CON_UNITS) 
ColStyle = bitor(ColStyle, 262144)
ColStyle = Send_Message(@WINDOW:'.LS_TABLE', 'COLSTYLE', COL$CON_UNITS, ColStyle)
ColStyle = Send_Message(@WINDOW:'.LS_TABLE', 'COLSTYLE', COL$CRES_UNITS) 
ColStyle = bitor(ColStyle, 262144)
ColStyle = Send_Message(@WINDOW:'.LS_TABLE', 'COLSTYLE', COL$CRES_UNITS, ColStyle)
Set_Property(@WINDOW:'.LS_TABLE','HEADERHEIGHT',30)
HeaderText = Get_Property(@WINDOW:'.LS_TABLE','LABEL')
HeaderText
 = HeaderText:CHAR(13):''
HeaderText = HeaderText:CHAR(13):''
HeaderText = HeaderText:CHAR(13):''
HeaderText = HeaderText:CHAR(13):''
HeaderText = HeaderText:CHAR(13):''
Set_Property(@WINDOW:'.LS_TABLE','LABEL',HeaderText)
SubstrateInfo	= Parm1[1,CHAR(244)]
EpiInfo			= Parm1[COL2()+1,CHAR(244)]
AddlInfo		= Parm1[COL2()+1,CHAR(244)]
NDInfo			= Parm1[COL2()+1,CHAR(244)]
PPInfo			= Parm1[COL2()+1,CHAR(244)]
CONVERT @SVM TO '' IN EpiInfo
LSCnt = COUNT(EpiInfo,Char(248)) + (EpiInfo NE '')
LSList = ''
LSAList	= ''
FOR I = 1 TO LSCnt
	BEGIN CASE
		CASE I = 1
			Layer = 'L1'
		
		CASE I = 2 
			IF LSCnt = 3 THEN
				Layer = 'L2'
			END ELSE
				Layer = '2'
			END
			
		CASE I = 3 ; Layer = '2'
		CASE 1 ; Layer = I-1
	END CASE
	
	EpiLayer = FIELD(EpiInfo,CHAR(248),I)
	
	LSList			    = Layer
	LSList		    = EpiLayer<1,QSEpiRecipe$>
	LSList		    = EpiLayer<1,QSEpiRecipeName$>
	LSList		    = OCONV(EpiLayer<1,QSEpiMinThick$>,'MD3')
	LSList		    = OCONV(EpiLayer<1,QSEpiMaxThick$>,'MD3')
	LSList		    = EpiLayer<1,QSEpiThickUnits$>
	LSList		    = OCONV(EpiLayer<1,QSEpiResMinThick$>,'MD3')
	LSList		    = OCONV(EpiLayer<1,QSEpiResMaxThick$>,'MD3')
	LSList		    = EpiLayer<1,QSEpiResUnits$>
	LSList		    = OCONV(EpiLayer<1,QSEpiConcMinThick$>,'MS21')
	LSList		    = OCONV(EpiLayer<1,QSEpiConcMaxThick$>,'MS21')
	LSList		    = EpiLayer<1,QSEpiConcUnits$>
	LSList		    = OCONV(EpiLayer<1,QSEpiCresMin$>,'MD3')
	LSList		    = OCONV(EpiLayer<1,QSEpiCresMax$>,'MD3')
	LSList	    = EpiLayer<1,QSEpiCresUnits$>
	LSList	= EpiLayer<1,QSEpiCresPhaseMin$>
	
	LSAList		    = Layer
	LSAList		    = EpiLayer<1,QSEpiDopant$>
	LSAList	    = EpiLayer<1,QSEpiThickMeasure$>
	LSAList	    = EpiLayer<1,QSEpiResMeasure$>
	LSAList	    = EpiLayer<1,QSEpiConcMeasure$>
	LSAList	    = EpiLayer<1,QSEpiCresMeasure$>
NEXT I
IF LSCnt = 0 THEN
	LSList = STR(@VM,16)
	LSAList = STR(@VM,5)
END
Set_Property(@WINDOW:'.LSA_TABLE','LIST',LSAList)
Set_Property(@WINDOW:'.LS_TABLE','LIST',LSList)
RETURN
* * * * * * *
LSTableDC:
* * * * * * *
RowData = Get_Property(@WINDOW:'.LS_TABLE','ROWDATA')
CONVERT @FM TO @VM IN RowData
CurrPos = Get_Property(@WINDOW:'.LS_TABLE','SELPOS')
CurrCol = CurrPos<1>
CurrRow = CurrPos<2>
MDataCurr = RowData<1,CurrCol>
BEGIN CASE
	CASE CurrCol = COL$REC_NO
		RecID = ''
	
		Option = Msg(@WINDOW,'','RECIPE_OPTIONS')						; * Select, Create New or Cancel
		BEGIN CASE
			CASE Option = 1
				RecID = Popup(@WINDOW,'','CHOOSE_RECIPE')					;* Select List
			CASE Option = 2
				IF MDataCurr = '' THEN
					Void = Start_Window( 'RECIPE', @WINDOW, '*Choosing', '', '' )
				END ELSE
					Void = Start_Window( 'RECIPE', @WINDOW, MDataCurr:'*CENTER', '', '' )
				END
			CASE 1
				RETURN
		END CASE
		
		
		IF RecID NE '' THEN
			oaParms = RecID:@RM:@WINDOW:'.LS_TABLE':@RM:COL$REC_NO:@FM:CurrRow
			obj_Appwindow('LUValReturn',oaParms)
		END
		
		
	CASE CurrCol = COL$THK_UNITS
		TypeOver = ''
		TypeOver	= 'Thickness Units of Measurement'
		TypeOver = 'THICK':@SVM:'Thickness':@SVM:'Micron':@SVM:'æm':@VM
		TypeOver = TypeOver:'THICK':@SVM:'Thickness':@SVM:'Angstrom':@SVM:''
		
		Units = Popup(@WINDOW,TypeOver,'METROLOGY_UNITS')
		
		IF Units NE '' THEN
			oaParms = Units:@RM:@WINDOW:'.LS_TABLE':@RM:COL$THK_UNITS:@FM:CurrRow
			obj_Appwindow('LUValReturn',oaParms)
		END
		
	
	CASE CurrCol = COL$RES_UNITS
		TypeOver = ''
		TypeOver	= 'Resistance Units of Measurement'
		TypeOver = 'RES':@SVM:'Resistivity':@SVM:'Ohms.Cm':@SVM:'ê-cm':@VM
		TypeOver = TypeOver:'RES':@SVM:'Resistivity':@SVM:'Ohms/Sq':@SVM:'ê/Ü'
		
		Units = Popup(@WINDOW,TypeOver,'METROLOGY_UNITS')
		IF Units NE '' THEN
			oaParms = Units:@RM:@WINDOW:'.LS_TABLE':@RM:COL$RES_UNITS:@FM:CurrRow
			obj_Appwindow('LUValReturn',oaParms)
		END
	
	
	CASE CurrCol = COL$CON_UNITS
		TypeOver = ''
		TypeOver	= 'Concentration -  Units of Measurement'
		TypeOver = 'CONC':@SVM:'Concentration':@SVM:'Carriers.Cubic Centimeter':@SVM:'cm-3'
		
		
		TypeOver = 1
		Units = Popup(@WINDOW,TypeOver,'METROLOGY_UNITS')
		IF Units NE '' THEN
			oaParms = Units:@RM:@WINDOW:'.LS_TABLE':@RM:COL$CON_UNITS:@FM:CurrRow
			obj_Appwindow('LUValReturn',oaParms)
		END
	
	
	CASE CurrCol = COL$CRES_UNITS
		TypeOver = ''
		TypeOver	= 'Mercury Probe -  Units of Measurement'
		TypeOver = 'CRES':@SVM:'HgCvResistivity':@SVM:'Ohms.Cm':@SVM:'ê-cm'
		
		TypeOver = 1
		Units = Popup(@WINDOW,TypeOver,'METROLOGY_UNITS')
		IF Units NE '' THEN
			oaParms = Units:@RM:@WINDOW:'.LS_TABLE':@RM:COL$CRES_UNITS:@FM:CurrRow
			obj_Appwindow('LUValReturn',oaParms)
		END
		
		
END CASE
RETURN
* * * * * * *
LSATableDC:
* * * * * * *
RowData = Get_Property(@WINDOW:'.LSA_TABLE','ROWDATA')
CONVERT @FM TO @VM IN RowData
CurrPos = Get_Property(@WINDOW:'.LSA_TABLE','SELPOS')
CurrCol = CurrPos<1>
CurrRow = CurrPos<2>
MDataCurr = RowData<1,CurrCol>
BEGIN CASE
	CASE CurrCol = COL$THK_MEASURE
		
		MType = 'THICK'
		MDesc = 'Thickness'
		
		MDataNew = Dialog_Box( 'PROD_SPEC_SI4', @WINDOW, MDataCurr:CHAR(245):MType:CHAR(245):' ':MDesc:CHAR(245):'CENTER' )
		IF MDataNew NE '' AND MDataNew NE MDataCurr THEN
			Set_Property(@WINDOW:'.LSA_TABLE','CELLPOS',MDataNew,COL$THK_MEASURE:@FM:CurrRow)
		END
	CASE CurrCol = COL$RES_MEASURE
	
		MType = 'RES'
		MDesc = 'Resistivity'
		
		MDataNew = Dialog_Box( 'PROD_SPEC_SI4', @WINDOW, MDataCurr:CHAR(245):MType:CHAR(245):' ':MDesc:CHAR(245):'CENTER' )
		IF MDataNew NE '' AND MDataNew NE MDataCurr THEN
			Set_Property(@WINDOW:'.LSA_TABLE','CELLPOS',MDataNew,COL$RES_MEASURE:@FM:CurrRow)
		END
	CASE CurrCol = COL$CON_MEASURE
		
		MType = 'CON'
		MDesc = 'Concentration'
		
		MDataNew = Dialog_Box( 'PROD_SPEC_SI4', @WINDOW, MDataCurr:CHAR(245):MType:CHAR(245):' ':MDesc:CHAR(245):'CENTER' )
		IF MDataNew NE '' AND MDataNew NE MDataCurr THEN
			Set_Property(@WINDOW:'.LSA_TABLE','CELLPOS',MDataNew,COL$CON_MEASURE:@FM:CurrRow)
		END
	
	CASE CurrCol = COL$CRES_MEASURE
	
		MType = 'RCON'
		MDesc = 'Concentration Resistance'
		
		MDataNew = Dialog_Box( 'PROD_SPEC_SI4', @WINDOW, MDataCurr:CHAR(245):MType:CHAR(245):' ':MDesc:CHAR(245):'CENTER' )
		IF MDataNew NE '' AND MDataNew NE MDataCurr THEN
			Set_Property(@WINDOW:'.LSA_TABLE','CELLPOS',MDataNew,COL$CRES_MEASURE:@FM:CurrRow)
		END
	
END CASE
RETURN
* * * * * * *
LSAPC:
* * * * * * *
CtrlEntID = 'PROD_SPEC_SI.LSA_TABLE'
LSAList		= Get_Property(CtrlEntID,'LIST')
LSAInArray	= Get_Property(CtrlEntID,'INVALUE')
LSList		= Get_Property('PROD_SPEC_SI.LS_TABLE','LIST')
PrevSelPos	= Get_Property(CtrlEntId,"PREVSELPOS")
PrevCol 	= PrevSelPos<1>
PrevRow 	= PrevSelPos<2>
CurrPos 	= Get_Property(CtrlEntId,'SELPOS')
CurrCol		= CurrPos<1>
CurrRow		= CurrPos<2>
* LostFocus checks 
LSIds = LSAInArray
* This section maintains the Layer Set ID column
GoodLines = 0
LineCnt = COUNT(LSAList,@FM) + (LSAList NE '')
LOOP
	TestLine = LSAList[-1,'B':@FM]
	TestLine = FIELD(TestLine,@VM,2,14)
UNTIL TestLine NE STR(@VM,13) 
	LSAList = DELETE(LSAList,LineCnt,0,0)
	Set_Property(CtrlEntID,'INVALUE','',COL$LS_ID:@FM:LineCnt)
	LineCnt -= 1
REPEAT
LSArray = ''
FOR I = 1 TO LineCnt
	BEGIN CASE
		CASE I = 1
			Layer = 'L1'
		
		CASE I = 2 
			IF LineCnt = 3 THEN
				Layer = 'L2'
			END ELSE
				Layer = '2'
			END
			
		CASE I = 3 ; Layer = '2'
		CASE 1 ; Layer = I-1
	END CASE
	
	IF LSAInArray NE Layer THEN
		Set_Property(CtrlEntID,'INVALUE',Layer,COL$LS_ID:@FM:I)
	END
	
NEXT I	
IF LSAList NE '' THEN
	
	BEGIN CASE
	
		CASE PrevCol = COL$DOPANT
		
			SpecDopant = LSAList
			RecipeID = LSList
			
			IF SpecDopant NE '' AND RecipeID NE '' THEN
				IF PrevRow = 1 THEN
					RecipeDopant = XLATE( 'RECIPE', RecipeID, RECIPE_EPI_DOPANT$, 'X' )
				END ELSE
					RecLayInfo = XLATE( 'RECIPE', RecipeID, RECIPE_LAYER_INFO$, 'X' )	;* Retrives rathole data for layers > 1
					RecipeDopant = RecLayInfo      
				END
				
				IF SpecDopant NE RecipeDopant THEN
					ErrMsg('Dopant entered ':Quote(SpecDopant):' does not match the dopant on the recipe ':QUOTE(RecipeDopant):'.')
					Set_Property(CtrlEntID,"SELPOS",PrevSelPos)
					Set_Property(CtrlEntID,'INVALUE','',PrevSelPos)			;* Clear entered field
				END
			END
			
	END CASE	
END
		
		
* Gotfocus checks
			
IF CurrCol = COL$LS_ID THEN
	Set_Property(CtrlEntId,'SELPOS',CurrCol + 1:@FM:CurrRow)
END	
			
RETURN
* * * * * * *
LSPC:
* * * * * * *
CtrlEntID = 'PROD_SPEC_SI.LS_TABLE'
LSList		= Get_Property(CtrlEntID,'LIST')
LSInArray	= Get_Property(CtrlEntID,'INVALUE')
LSAList		= Get_Property('PROD_SPEC_SI.LSA_TABLE','LIST')
PrevSelPos	= Get_Property(CtrlEntId,"PREVSELPOS")
PrevCol 	= PrevSelPos<1>
PrevRow 	= PrevSelPos<2>
CurrPos 	= Get_Property(CtrlEntId,'SELPOS')
CurrCol		= CurrPos<1>
CurrRow		= CurrPos<2>
* LostFocus checks 
LSIds = LSInArray
* This section maintains the Layer Set ID column
GoodLines = 0
LineCnt = COUNT(LSList,@FM) + (LSList NE '')
LOOP
	TestLine = LSList[-1,'B':@FM]
	TestLine = FIELD(TestLine,@VM,2,14)
UNTIL TestLine NE STR(@VM,13) 
	LSList = DELETE(LSList,LineCnt,0,0)
	Set_Property(CtrlEntID,'INVALUE','',COL$LS_ID:@FM:LineCnt)
	LineCnt -= 1
REPEAT
LSArray = ''
FOR I = 1 TO LineCnt
	BEGIN CASE
		CASE I = 1
			Layer = 'L1'
		
		CASE I = 2 
			IF LineCnt = 3 THEN
				Layer = 'L2'
			END ELSE
				Layer = '2'
			END
			
		CASE I = 3 ; Layer = '2'
		CASE 1 ; Layer = I-1
	END CASE
	
	IF LSInArray NE Layer THEN
		Set_Property(CtrlEntID,'INVALUE',Layer,COL$LS_ID:@FM:I)
	END
	
NEXT I	
	
BEGIN CASE
	CASE PrevCol = COL$REC_NO
	
		SpecDopant	= LSAList
		RecipeID	= LSList
		RecipeName	= LSList
		
		IF SpecDopant NE '' AND RecipeID NE '' THEN
			IF PrevRow = 1 THEN
				RecipeDopant = XLATE( 'RECIPE', RecipeID, RECIPE_EPI_DOPANT$, 'X' )
			END ELSE
				RecLayInfo = XLATE( 'RECIPE', RecipeID, RECIPE_LAYER_INFO$, 'X' )	;* Retrives rathole data for layers > 1
				RecipeDopant = RecLayInfo      
			END
			
			IF SpecDopant NE RecipeDopant THEN
				ErrMsg('Dopant entered ':Quote(SpecDopant):' does not match the dopant on the recipe ':QUOTE(RecipeDopant):'.')
				Set_Property(CtrlEntID,"SELPOS",PrevSelPos)
				Set_Property(CtrlEntID,'INVALUE','',PrevSelPos)						;* Clear entered field
			END
		END
		
		IF SpecDopant = '' AND RecipeID NE '' THEN
			IF PrevRow = 1 THEN
				RecipeDopant = XLATE( 'RECIPE', RecipeID, RECIPE_EPI_DOPANT$, 'X' )
			END ELSE
				RecLayInfo = XLATE( 'RECIPE', RecipeID, RECIPE_LAYER_INFO$, 'X' )	;* Retrives rathole data for layers > 1
				RecipeDopant = RecLayInfo      
			END
			
			Set_Property('PROD_SPEC_SI.LSA_TABLE','INVALUE',RecipeDopant,COL$DOPANT:@FM:PrevRow)	;* Sets null default for Dopant
			
			
		END
		
		IF RecipeID NE '' THEN
			RecipeName = XLATE( 'RECIPE', RecipeId, RECIPE_RECIPE_NAME$, 'X' )
		END ELSE
			RecipeName = ''
		END
 			
 		Set_Property(CtrlEntID,"SELPOS",COL$REC_DESC:@FM:PrevRow)
		Set_Property(CtrlEntID,'INVALUE',RecipeName,COL$REC_DESC:@FM:PrevRow)
			
		
		
		
	CASE PrevCol = COL$THK_MIN OR PrevCol = COL$THK_MAX
		ThickMin = LSInArray
		ThickMax = LSInArray
		
		IF ThickMin NE '' AND ThickMax NE '' THEN
			IF ThickMin > ThickMax THEN 
				ErrMsg('Thickness Minimum is greater than the Thickness Maximum in ':LSInArray:'.')
				Set_Property(CtrlEntID,'SELPOS',PrevPos)
			END
		END
		
	CASE PrevCol = COL$RES_MIN OR PrevCOl = COL$RES_MAX
		ResMin	= LSInArray
		ResMax	= LSInArray
		
		IF ResMin NE '' AND ResMax NE '' THEN
			IF ResMin > ResMax THEN 
				ErrMsg('Resistance Minimum is greater than the Resistance Maximum in ':LSInArray:'.')
				Set_Property(CtrlEntID,'SELPOS',PrevPos)
			END
		END
		
	CASE PrevCol = COL$CON_MIN OR PrevCol = COL$CON_MAX
		NULL
		
	CASE PrevCol = COL$CRES_MIN OR PrevCol = COL$CRES_MAX
		CResMin	= LSInArray
		CResMax	= LSInArray
		
		IF CResMin NE '' AND CResMax NE '' THEN
			IF CResMin > CResMax THEN 
				ErrMsg('CResistance Minimum is greater than the CResistance Maximum in ':LSInArray:'.')
				Set_Property(CtrlEntID,'SELPOS',PrevPos)
			END
		END
		
END CASE	
		
IF CurrCol = COL$LS_ID THEN
	Set_Property(CtrlEntId,'SELPOS',CurrCol + 1:@FM:CurrRow)
END	
RETURN
* * * * * * *
LSTableDel:
* * * * * * *
CtrlEntID = 'PROD_SPEC_SI.LS_TABLE'
LSList		= Get_Property(CtrlEntID,'LIST')
LSInArray	= Get_Property(CtrlEntID,'INVALUE')
LSAList		= Get_Property('PROD_SPEC_SI.LSA_TABLE','LIST')
PrevSelPos	= Get_Property(CtrlEntId,"PREVSELPOS")
PrevCol 	= PrevSelPos<1>
PrevRow 	= PrevSelPos<2>
CurrPos 	= Get_Property(CtrlEntId,'SELPOS')
CurrCol		= CurrPos<1>
CurrRow		= CurrPos<2>
LSIds = LSInArray
* This section maintains the Layer Set ID column
GoodLines = 0
LineCnt = COUNT(LSList,@FM) + (LSList NE '')
LOOP
	TestLine = LSList[-1,'B':@FM]
	TestLine = FIELD(TestLine,@VM,2,14)
UNTIL TestLine NE STR(@VM,13) 
	LSList = DELETE(LSList,LineCnt,0,0)
	Set_Property(CtrlEntID,'INVALUE','',COL$LS_ID:@FM:LineCnt)
	LineCnt -= 1
REPEAT
RETURN
* * * * * * *
LSATableDel:
* * * * * * *
CtrlEntID = 'PROD_SPEC_SI.LSA_TABLE'
LSList		= Get_Property(CtrlEntID,'LIST')
LSInArray	= Get_Property(CtrlEntID,'INVALUE')
LSAList		= Get_Property('PROD_SPEC_SI.LSA_TABLE','LIST')
PrevSelPos	= Get_Property(CtrlEntId,"PREVSELPOS")
PrevCol 	= PrevSelPos<1>
PrevRow 	= PrevSelPos<2>
CurrPos 	= Get_Property(CtrlEntId,'SELPOS')
CurrCol		= CurrPos<1>
CurrRow		= CurrPos<2>
LSIds = LSInArray
* This section maintains the Layer Set ID column
GoodLines = 0
LineCnt = COUNT(LSList,@FM) + (LSList NE '')
LOOP
	TestLine = LSList[-1,'B':@FM]
	TestLine = FIELD(TestLine,@VM,2,14)
UNTIL TestLine NE STR(@VM,13) 
	LSList = DELETE(LSList,LineCnt,0,0)
	Set_Property(CtrlEntID,'INVALUE','',COL$LS_ID:@FM:LineCnt)
	LineCnt -= 1
REPEAT
RETURN
* * * * * * *
Save:
* * * * * * *
* New completeness check added on 20 JAN 2011 by JCH
LSList = Get_Property(@WINDOW:'.LS_TABLE','LIST')
LineCnt = COUNT(LSList,@FM) + (LSList NE '')
FOR I = 1 TO LineCnt
	IF LSList NE '' THEN
	
		ThickMin = LSList	;	ThickMax = LSList	;	ThickUnits = LSList
		
		IF ThickMin NE '' OR ThickMax NE '' THEN
			 IF ThickMin = '' OR ThickMax = '' OR ThickUnits = '' THEN
				ErrMsg('Incomplete Thickness Specification on Layer Set ':LSList:'...')
				RETURN
			END
		END
		
		ResMin = LSList	;	ResMax = LSList	;	ResUnits = LSList
		IF ResMin NE '' OR ResMax NE '' THEN
			 IF ResMin = '' OR ResMax = '' OR ResUnits = '' THEN
				ErrMsg('Incomplete Resistivity Specification on Layer Set ':LSList:'...')
				RETURN
			 END
		END
		
		ConMin = LSList	;	ConMax = LSList	;	ConUnits = LSList
		
		IF ConMin NE '' OR ConMax NE '' THEN
			 IF ConMin = '' OR ConMax = '' OR ConUnits = '' THEN
				ErrMsg('Incomplete Concentration Specification on Layer Set ':LSList:'...')
				RETURN
			 END
		END
		
		CResMin = LSList	;	CResMax = LSList	;	CResUnits = LSList
		
		IF CResMin NE '' OR CResMax  NE '' THEN
			 IF CResMin = '' OR CResMax  = '' OR CResUnits = '' THEN
				ErrMsg('Incomplete CResistivity Specification on Layer Set ':LSList:'...')
				RETURN
			END
		END
	END	;* End of check for Layer Set ID
NEXT I
* This needs to end up setting @EpiInfo on the window
LSAArray	= Get_Property(@WINDOW:'.LSA_TABLE','INVALUE')
LSArray		= Get_Property(@WINDOW:'.LS_TABLE','INVALUE')
Product		= Get_Property(@WINDOW:'.SUB_PRODUCTS','TEXT')
IF Product NE '' THEN
	CurProducts = xlate( 'LISTBOX_CONFIG', 'PRODUCTS', '', 'X' )
	LOCATE Product IN CurProducts USING @VM SETTING Ppos ELSE
		MsgInfo = ''
		ErrMsg('Product ':QUOTE(Product):' is not valid.')
		
		RETURN
	END
END ELSE
	ErrMsg('You must select a product.')
	
	RETURN
END
L1RecipeID = LSArray
IF L1RecipeID NE '' THEN
	RecipePSNs	= XLATE( 'RECIPE', L1RecipeID, RECIPE_PROD_SPEC_IDS$, 'X' )
	CurPSN		= Get_Property( 'PROD_SPEC.PROD_SPEC_ID', 'TEXT' )
	LOCATE CurPSN IN RecipePSNs USING @VM SETTING FPos ELSE
		MsgInfo = ''
		MText   = 'This PSN ':quote(CurPSN):' is not set up in recipe ':quote(L1RecipeID)
		MText  := " with it's own recipe limits.  If this PSN is activated and goes through the"
		MText  := ' system without these limits, the system will use the top row limits in the'
		MText  := ' recipe.  Please notify an engineer to handle this issue.'
		MsgInfo = MText       
		MsgInfo = '!'
		Msg( '', MsgInfo )
	END
END
SubPreClean = Get_Property( @WINDOW:'.SUB_PRE_CLEAN', 'TEXT' )
IF INDEX( SubPreClean,'Akrion', 1 ) THEN
 	PreAkrionRecipe = Get_Property( @WINDOW:'.PRECLEAN_AKRIONRECIPES', 'TEXT' )
	IF PreAkrionRecipe = '' THEN
		MsgInfo = ''
		ErrMsg('You must select a pre clean akrion recipe...')
		
		RETURN
	END
END
SubPostClean = Get_Property( @WINDOW:'.SUB_POST_CLEAN', 'TEXT' )
IF INDEX( SubPostClean, 'Akrion', 1 ) THEN
	PostAkrionRecipe = Get_Property( @WINDOW:'.POSTCLEAN_AKRIONRECIPES', 'TEXT' )
	IF PostAkrionRecipe = '' THEN
		ErrMsg('You must select a post clean akrion recipe...')
		
		RETURN
	END
END
Result = 1
SaveEpiInfo = ''
LSIDs = ''
FOR I = 1 TO 9
	LSID = LSArray
UNTIL LSID = ''
	SaveEpiInfo			= LSArray
	SaveEpiInfo		= LSArray
	SaveEpiInfo	= LSArray
	SaveEpiInfo	= LSArray
	SaveEpiInfo		= LSArray
	SaveEpiInfo 	= LSArray
	SaveEpiInfo 	= LSArray
	SaveEpiInfo		= LSArray
	SaveEpiInfo		= LSArray
	SaveEpiInfo		= LSArray
	SaveEpiInfo 	= LSArray
	SaveEpiInfo		= LSArray
	SaveEpiInfo		= LSArray
	SaveEpiInfo		= LSArray
	SaveEpiInfo   = LSArray
	SaveEpiInfo			= LSAArray
	SaveEpiInfo	= LSAArray
	SaveEpiInfo		= LSAArray
	SaveEpiInfo	= LSAArray	
	SaveEpiInfo	= LSAArray	
	
NEXT I
CONVERT @FM TO CHAR(248) IN SaveEpiInfo
Set_Property(@WINDOW,'@EpiInfoTest',SaveEpiInfo)
Controls		= Get_Property( @WINDOW, '@SubControls' )
SubstrateInfo	= Get_Property( Controls, 'INVALUE' )
CONVERT @RM TO @VM IN SubstrateInfo
SWAP @TM WITH CRLF$ IN SubstrateInfo
Controls = Get_Property( @WINDOW, '@AddlControls' )
AddlInfo = Get_Property( Controls, 'INVALUE' )
CONVERT @RM TO @VM IN AddlInfo
SWAP @TM WITH CRLF$ IN AddlInfo
Controls	= Get_Property( @WINDOW, '@NDControls' )
NDInfo		= Get_Property( Controls, 'INVALUE' )
CONVERT @RM TO @VM IN NDInfo
Controls	= Get_Property( @WINDOW, '@PPControls' )
PPInfo		= Get_Property( Controls, 'INVALUE' )
CONVERT @RM TO @VM IN PPInfo
ReturnData = SubstrateInfo:CHAR(244):SaveEpiInfo:CHAR(244):AddlInfo:CHAR(244):NDInfo:CHAR(244):PPInfo
Set_Property(@WINDOW,'@ReturnData', ReturnData)
Result = ReturnData
RETURN