Compile function DBW_GAN_RDS_PROD_EVENTS(CtrlEntId, Event, @PARAMS) /*********************************************************************************************************************** Name : DBW_GAN_RDS_PROD_EVENTS Description : Commuter module for the DBW_GAN_RDS_PROD 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) 01/11/19 djs Original programmer. 07/12/19 fr Updated FillDispEditTable subroutine to not allow "Internal" wafers to be NCR'd. 07/23/19 djs Updated the UpdateDispData routine to only look for 06/06/20 djs Cutover to CR-004 and CR-005 ***********************************************************************************************************************/ #pragma precomp SRP_PreCompiler #window DBW_GAN_RDS_PROD DECLARE SUBROUTINE Set_Property, End_Dialog, Send_Event, Set_Status, Center_Window, Post_Event, SRP_EditTable_Manager DECLARE SUBROUTINE ErrMsg, Send_Message, Set_Property, Send_Event, Btree.Extract, obj_AppWindow, SRP_Show_Window DECLARE SUBROUTINE obj_Notes, Security_Err_Msg, End_Window, Forward_Event, Start_Window, Create_Note, Excel_Services DECLARE SUBROUTINE obj_RDS_Test, Print_Control_Plan, Print_RDS_Instruction, Send_Info, Post_Event, Database_Services DECLARE SUBROUTINE obj_Run_Stage_Wfr, obj_WO_Wfr, obj_Run_Stage, GaN_Services, Utility, SRP_Stopwatch, COMM_NCR DECLARE SUBROUTINE Dialog_Box, Get_Status, Logging_Services, Unlock, Error_Services, Disposition_Services DECLARE SUBROUTINE Engineering_Services, Reactor_Services DECLARE FUNCTION Get_Property, Get_Status, Dialog_Box, Utility, Center_Window, Popup, Collect.Ixvals, Security_Services DECLARE FUNCTION Send_Message, Msg, Security_Check, RowExists, NextKey, obj_React_Esc, obj_React_Run, Form_Services DECLARE FUNCTION obj_RDS_Test, MemberOf, Create_Dialog, obj_Popup, obj_WO_Wfr, SRP_EditTable_Manager, Database_Services DECLARE FUNCTION Obj_Run_Stage, Obj_Run_Stage_Wfr, Gan_Services, SRP_Array, DateTime, Error_Services, Obj_NCR DECLARE FUNCTION Memory_Services, SRP_Get_Window_Rect, Excel_Services, Environment_Services, Logging_Services DECLARE FUNCTION SRP_Date $INSERT APPCOLORS $INSERT RTI_STYLE_EQUATES $INSERT EVENT_SETUP $INSERT MSG_EQUATES $INSERT LSL_USERS_EQU $INSERT SECURITY_RIGHTS_EQU $INSERT REACT_EVENT_EQUATES $INSERT REACT_RUN_EQUATES $INSERT WO_STEP_EQU $INSERT WO_MAT_EQUATES $INSERT WO_WFR_WIP_EQUATES $INSERT EPI_SUSCEPTOR_EQUATES $INSERT REACTOR_EQUATES $INSERT POPUP_EQUATES $INSERT TOOL_CLASS_EQUATES $INSERT RUN_STAGE_EQUATES $INSERT LOCATION_EQUATES $INSERT RUN_STAGE_WFR_EQUATES $INSERT WO_WFR_EQUATES $INSERT SRP_POPUP_EQUATES $INSERT WO_LOG_EQUATES $INSERT GAN_PARAMS_EQUATES $INSERT GAN_PARAM_CONFIG_EQUATES $INSERT NCR_EQUATES // Cassette / Wafer Action Combo Box Selections EQU COMBO_X$ TO 1 EQU COMBO_START$ TO 2 EQU COMBO_STOP$ TO 3 EQU COMBO_COMP$ TO 4 EQU COMBO_PART$ TO 5 EQU COL$CHAR_WFR_ID TO 1 EQU COL$SCRIBE TO 2 EQU COL$SPLIT_BY TO 3 EQU COL$SPLIT_DTM TO 4 EQU COL$CURR_STAGE TO 5 EQU COL$CHAR_DEST TO 6 EQU COL$CHAR_TW_NO TO 7 EQU COL$CHAR_WFR_STATUS TO 8 EQU COL$CARR_SLOG_NO TO 1 EQU COL$CARR_WFR_ID TO 2 EQU COL$CARR_SCRIBE TO 3 EQU COL$CARR_CHAR_FLAG TO 4 EQU COL$CARR_NCR TO 5 EQU COL$CARR_GRADE TO 6 EQU COL$SIG_PROF TO 1 EQU COL$SIGNATURE TO 2 EQU COL$SIG_DTM TO 3 EQU COL$STAGE_COMMENT TO 4 EQU COL$STAGE_STATUS TO 5 EQU COL$MET_STAGE TO 1 EQU COL$MET_TOOL_ID TO 2 // Disposition OLE Edit Table EQU COL$DISP_SLOT TO 1 EQU COL$DISP_WFR_ID TO 2 EQU COL$DISP_SCRIBE TO 3 EQU COL$DISP_GRADE TO 4 EQU COL$DISP_REASON TO 5 EQU COL$DISP_ROOT_CAUSE TO 6 EQU COL$DISP_RDS_NCR TO 7 EQU COL$DISP_WMO_NCR TO 8 EQU COL$DISP_SHIP_ID TO 9 EQU COL$DISP_RETAIN_BOX TO 10 EQU COL$DISP_RETAIN_SLOT TO 11 // 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 COL$SUSC_LOAD_WFR_ID TO 6 ;* SUSC_LOAD control EQU COL$SUSC_LOAD_WFR_SCRIBE TO 7 EQU EDITABLE$ TO 4 EQU PROTECTED$ TO 8 ;* Protected - Edittable COLSTYLE constants EQU MULTILINE_STYLE$ TO 512 ;* MultiLine Select EQU LOCKED$ TO 8192 EQU DROPDOWN_STYLE$ TO 131072 LogPath = Environment_Services('GetApplicationRootPath') : '\LogFiles\GaNWIP' LogDate = Oconv(Date(), 'D4/') LogTime = Oconv(Time(), 'MTS') LogFileName = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' GaN WIP Log.csv' Headers = 'Logging DTM' : @FM : 'RDS Key ID' : @FM : 'Username' : @FM : 'Notes' objLog = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, Comma$, Headers, '', False$, False$) LoggingDTM = LogDate : ' ' : LogTime ; // Logging DTM SubclassInfo = Form_Services('FindSubclassControl') Subclass = SubclassInfo<1> // 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) IOOptions = Get_Property(@Window, 'IOOPTIONS') IOOptions<2> = 2 ;// Do not lock the record Set_Property(@Window, 'IOOPTIONS', IOOptions) If CreateParam NE '' then RDSNo = CreateParam Set_Property(@Window:'.RDS_NO', 'TEXT', RDSNo) Post_Event(@Window, 'READ') end SRP_Show_Window(@Window, 'SYSTEM', 'C', 'C', 1, '', False$, False$, '', 1) End Event Event WINDOW.READ() RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') If RDSNo NE '' then WONo = Xlate('REACT_RUN', RDSNo, 'WO_NO', 'X') PSNo = Xlate('REACT_RUN', RDSNo, 'PS_NO', 'X') TechType = Xlate('PROD_SPEC', PSNo, 'TECH_TYPE', 'X') If ( (TechType EQ 'E') or (TechType EQ '') ) then ParentWindow = Get_Property(@Window, "PARENT") Start_Window('REACT_RUN', ParentWindow, RDSNo) GoTo Abort end Set_Property(@Window, '@RDSNO', RDSNo) Def = "" Def = "Loading..." Def = "G" Def = 100 ; // 100% Def = 400 Def = -2 ;* message h-pos in pixels, or -2 (center screen, the default), -1 (center parent) Def = -2 ;* message v-pos in pixels MsgUp = Msg(@Window, Def) Set_Property(@Window, 'REDRAW', False$) Set_Property(@Window:'.OLE_REACTOR_EDT' , "OLE.Redraw", False$) Set_Property(@Window:'.OLE_METROLOGY_EDT' , "OLE.Redraw", False$) Set_Property(@Window:'.OLE_DISP_EDT' , "OLE.Redraw", False$) Set_Property(@Window:'.OLE_DISP_STAGE_EDT' , "OLE.Redraw", False$) Set_Property(@Window:'.OLE_NCR_EDT' , "OLE.Redraw", False$) RunPriorities = '':@FM:'P1':@FM:'P2':@FM:'P3' Set_Property(@Window:'.COMBO_PRIORITY', 'LIST', RunPriorities) If RDSNo Not(Num(RDSNo)) then * update the gauge Msg(@Window, MsgUp, 10, MSGINSTUPDATE$) // Check if run info scribes have been updated ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) InWfrIDs = ReactRunRec RunPriority = ReactRunRec Set_Property(@Window:'.COMBO_PRIORITY', 'TEXT', RunPriority) GaNRunID = ReactRunRec GrowthKey = RDSNo:'*GROWTH' GrowthRec = Database_Services('ReadDataRow', 'RUN_STAGE', GrowthKey) InvActions = GrowthRec Locate 'LOAD' in InvActions using @VM setting vPos then LoadSig = GrowthRec If LoadSig NE '' then RRScribes = Xlate('REACT_RUN', RDSNo, 'WFR_SCRIBES', 'X') GaNRunInfo = Gan_Services('GetRunInfo', GaNRunID) If Error_Services('NoError') then RunScribes = GaNRunInfo<4> If ( (RRScribes NE RunScribes) and (RunScribes NE '') ) then // Scribes have been updated in wafer track database For each WfrID in InWfrIDs using @VM setting vPos WOWfrRec = Database_Services('ReadDataRow', 'WO_WFR', WfrID) WOWfrRec = RunScribes<0, vPos> Database_Services('WriteDataRow', 'WO_WFR', WfrID, WOWfrRec) Next WfrID end end end end * update the gauge Msg(@Window, MsgUp, 20, MSGINSTUPDATE$) WONo = Get_Property(@Window:'.WO_NO', 'TEXT') If WONo EQ '' then WONo = Xlate('RDS', RDSNo, 'WO', 'X') WOLogRec = Database_Services('ReadDataRow', 'WO_LOG', WONo) SPCWaferTrackPart = WOLogRec Set_Property(@Window:'.EDL_WAFER_TRACK_PART', 'TEXT', SPCWaferTrackPart) Reactor = ReactRunRec If Reactor EQ '' then Reactor = GaN_Services('GetReactor', WONo) Set_Property(@Window, '@REACTOR', Reactor) * update the gauge Msg(@Window, MsgUp, 30, MSGINSTUPDATE$) If GaNRunID EQ '' then AvailGaNRunIDs = Gan_Services('GetAvailableRunIDs', Reactor, WoNo) Msg(@Window, MsgUp, 40, MSGINSTUPDATE$) EpiPartNo = Get_Property(@Window:'.EPI_PART_NO', 'TEXT') NumRunIDs = DCount(AvailGaNRunIDs, @FM) FilteredList = '' Voltage = '' Voltage = Xlate('WO_LOG', WONo, 'GAN_COST_TYPE', 'X') Begin Case Case Voltage _EQC 'High Voltage' // Filter on hvfet For RunIndex = 1 to NumRunIDs RunID = AvailGaNRunIDs If Indexc(RunID, 'HV', 1) then FilteredList<-1> = RunID end Next RunIndex Case Voltage _EQC 'Mid Voltage' // Filter on mvfet - ( e.g. U014 is Medium Voltage (MV) ) For RunIndex = 1 to NumRunIDs RunID = AvailGaNRunIDs If Indexc(RunID, 'MV', 1) then FilteredList<-1> = RunID end Next RunIndex Case Otherwise$ ErrorMsg = 'Unrecognized GaN Cost Type (Voltage): "':Voltage:'" read from work order.':CRLF$ | : 'Unabled to filter GaN Run ID list.':CRLF$:' Verify GaN Cost Type in work order ' | : 'or contact FI team for assistance.' ErrMsg(ErrorMsg) FilteredList = AvailGaNRunIDs End Case Set_Property(@Window : '.CMB_GAN_RUN_ID', 'LIST', FilteredList) end else Convert @Upper.Case to @Lower.Case in GaNRunID Set_Property(@Window : '.CMB_GAN_RUN_ID', 'LIST', GaNRunID) Set_Property(@Window : '.CMB_GAN_RUN_ID', 'SELPOS', 1) end * update the gauge Msg(@Window, MsgUp, 50, MSGINSTUPDATE$) GaNEtchIDs = Xlate('REACT_RUN', RDSNo, 'GAN_ETCH_ID', 'X') Convert @VM to @FM in GaNEtchIDs If GaNEtchIDs NE '' then NumEtchIDs = DCount(GaNEtchIDs, @FM) Set_Property(@Window : '.CMB_GAN_ETCH_ID', 'LIST', GaNEtchIDs) // Select the last external etch ID to display by default Set_Property(@Window : '.CMB_GAN_ETCH_ID', 'SELPOS', NumEtchIDs) GaNEtchRecipes = Xlate('REACT_RUN', RDSNo, 'GAN_ETCH_RECIPE', 'X') LastEtchRecipe = GaNEtchRecipes<0, NumEtchIDs> Set_Property(@Window : '.ETCH_RECIPE', 'TEXT', LastEtchRecipe) EtchKey = RDSNo:'*ETCH' EtchStatus = Xlate('RUN_STAGE', EtchKey, 'STATUS', 'X') If EtchStatus EQ 'COMP' then // Verify the etch recipe hasn't changed. ExternalEtchID = Get_Property(@Window:'.CMB_GAN_ETCH_ID', 'TEXT') GaNEtchInfo = Gan_Services('GetRunInfo', ExternalEtchID) If GaNEtchInfo NE '' then WaferTrackEtchRecipe = GaNEtchInfo<1,1> If WaferTrackEtchRecipe NE LastEtchRecipe then ReactRunRec = WaferTrackEtchRecipe Database_Services('WriteDataRow', 'REACT_RUN', RDSNo, ReactRunRec, True$, False$, True$) Set_Property(@Window:'.ETCH_RECIPE', 'TEXT', WaferTrackEtchRecipe) end end end end else Set_Property(@Window : '.CMB_GAN_RUN_ID', 'ENABLED', False$) end GoSub Setup_OLE_Controls // Need to check if any wafers have made it to disposition. If so, then check the Disposition Report // for any updates. * update the gauge Msg(@Window, MsgUp, 60, MSGINSTUPDATE$) WfrIDs = ReactRunRec If WfrIDs NE '' then For each WfrID in WfrIDs using @VM setting vPos MetDone = GaN_Services('GetMetrologyStatus', WfrID) If MetDone EQ True$ then Set_Property(@Window:'.PUB_UPDATE_DISP', 'ENABLED', True$) end Until MetDone EQ True$ Next WfrID end GoSub VerifyRecipe * update the gauge Msg(@Window, MsgUp, 70, MSGINSTUPDATE$) GoSub FillDispEditTable * update the gauge Msg(@Window, MsgUp, 80, MSGINSTUPDATE$) GoSub FillNCREditTable * update the gauge Msg(@Window, MsgUp, 90, MSGINSTUPDATE$) GoSub FillCommentsTable end GoSub VerifyScribes GoSub EnableRunIDComboBox GoSub EnableCloseRDSButton GoSub UpdateRDSStatus GoSub EnableLotAbortButton GoSub EnableImportMetDataButton GoSub FillDispStageCtrl * update the gauge Msg(@Window, MsgUp, 100, MSGINSTUPDATE$) Msg(@Window, MsgUp) ;* take down the gauge Set_Property(@Window, 'REDRAW', True$) Set_Property(@Window:'.OLE_REACTOR_EDT' , "OLE.Redraw", True$) Set_Property(@Window:'.OLE_METROLOGY_EDT' , "OLE.Redraw", True$) Set_Property(@Window:'.OLE_DISP_EDT' , "OLE.Redraw", True$) Set_Property(@Window:'.OLE_DISP_STAGE_EDT' , "OLE.Redraw", True$) Set_Property(@Window:'.OLE_NCR_EDT' , "OLE.Redraw", True$) end end event Event WINDOW.CLEAR(bSaveKey, bSuppressWarning, bMaintainFocus, CtrlIDFocus) If Get_Property(@WINDOW,'@READONLY') then obj_AppWindow('ReadOnly',@RM:1) ;* Reenables data bound controls Set_Property(@WINDOW,'@READONLY',0) ;* Clear flag on window end end event Event WINDOW.CLOSE(CancelFlag) obj_Notes('Inbox',@USER4) ;* Checks for any new messages end event Event WINDOW.WRITE() prevControl = Get_Property("SYSTEM" , "PREVFOCUS") EventFlow = 1 end event Event WINDOW.PAGE(PageAction) Page = Get_Property(@WINDOW:'.TABCONTROL', 'VALUE') Set_Property(@WINDOW,'VPOSITION', Page) end event Event WINDOW.VSCROLL(Value) Set_Property(@WINDOW:'.TABCONTROL','VALUE', Value) end event Event WINDOW.OMNIEVENT(Message, Param1, Param2, Param3, Param4) Begin Case Case Message _EQC 'FillDispEditTable' GoSub FillDispEditTable Case Message _EQC 'FillNCREditTable' GoSub FillNCREditTable End Case end event Event CMB_GAN_RUN_ID.CHANGED(NewData) If NewData NE '' then GaNRunID = NewData ReactorNo = Get_Property(@Window, '@REACTOR') GaNRunInfo = Gan_Services('GetRunInfo', GaNRunID) Recipe = GaNRunInfo<1,1> SuscSerialNo = GaNRunInfo<2,1> SPCWaferTrackPart = GaNRunInfo<6,1> Set_Property(@Window:'.EDL_WAFER_TRACK_PART', 'TEXT', SPCWaferTrackPart) Set_Property(@Window:'.OLE_REACTOR_EDT', "OLE.HeaderText[1; 2]", 'Reactor ':ReactorNo) WOLogOpenInsightPart = Get_Property(@Window:'.EPI_PART_NO', 'TEXT') Convert @Lower.Case to @Upper.Case in GaNRunID SchedWaferTrackPart = Xlate('GAN_SCHEDULE', GaNRunID, 'WAFER_TRACK_PART', 'X') SchedOpenInsightPart = Xlate('GAN_SCHEDULE', GaNRunID, 'OPENINSIGHT_PART', 'X') // OpenInsightPart Verification If SchedOpenInsightPart NE WOLogOpenInsightPart then Set_Property(@Window:'.EPI_PART_NO', 'BACKCOLOR', RED$) end else Set_Property(@Window:'.EPI_PART_NO', 'BACKCOLOR', GREEN$) end // WaferTrackPart Verification If SchedWaferTrackPart NE SPCWaferTrackPart then Set_Property(@Window:'.EDL_WAFER_TRACK_PART', 'BACKCOLOR', RED$) end else Set_Property(@Window:'.EDL_WAFER_TRACK_PART', 'BACKCOLOR', GREEN$) end Set_Property(@Window, '@GANRUNINFO', GaNRunInfo) Set_Property(@Window : '.GAN_RECIPE', 'TEXT', Recipe) Set_Property(@Window : '.GAN_SUSC_SERIAL', 'TEXT', SuscSerialNo) GoSub VerifyRecipe end end event Event CMB_GAN_ETCH_ID.CHANGED(NewData) ExternalEtchID = NewData Begin Case Case (ExternalEtchID _EQC 'No Etch Required') Set_Property(@Window : '.ETCH_RECIPE', 'TEXT', 'Not Applicable') Case (ExternalEtchID NE '') and (ExternalEtchID _NEC 'No Etch Required') GaNEtchInfo = Gan_Services('GetRunInfo', ExternalEtchID) Recipe = GaNEtchInfo<1,1> Set_Property(@Window : '.ETCH_RECIPE', 'TEXT', Recipe) End Case end event Event CTRL_PLAN.CLICK() PSNo = Get_Property(@WINDOW:'.PS_NO','DEFPROP') IF PSNo NE '' THEN Print_Control_Plan(PSNo) END end event Event WONO_BUTTON.CLICK() WONo = Get_Property(@WINDOW:'.WO_NO','DEFPROP') IF WONo NE '' THEN NewForm = Xlate('APP_INFO', 'NEW_WO_FORM', '', 'X') If NewForm then Start_Window('NDW_WO_LOG', @Window, WONo) end else Start_Window('WO_LOG2',@WINDOW, WONo:'*CENTER', '', '' ) ;* Added (copied from ViewPSN) -dkk 10/23/14 end END end event Event RDS_NO.LOSTFOCUS(Flag, FocusID) ReactRunKey = Get_Property(CtrlEntID, 'TEXT') If ReactRunKey NE '' then RDSNo = Get_Property(@Window, '@RDSNO') If ReactRunKey NE RDSNo then ReactorType = Xlate('REACT_RUN', ReactRunKey, 'REACTOR_TYPE', 'X') If ReactorType _EQC 'GAN' then If RowExists('REACT_RUN', ReactRunKey) then Post_Event(@Window, 'READ') end else ErrMsg('REACT_RUN record ':ReactRunKey:' does not exist! Contact FI admin for assistance.') end end else ErrMsg('Incompatible reactor type ':ReactorType:'. Reactor type must be GAN.') end end end end event Event SEND_MSG.CLICK() CurrWindow = @WINDOW CurrKey = Get_Property(CurrWindow,'ID') IF CurrKey = '' THEN MsgInfo = '' MsgInfo = 'You must have a record present...' MsgInfo = 'H' Msg( '', MsgInfo ) RETURN END IF RowExists('REACT_RUN',CurrKey) THEN NoteID = NextKey('NOTES') obj_AppWindow('ViewRelated','NOTE_MESSAGE':@RM:NoteID:@RM:@WINDOW:@FM:CurrKey) END ELSE MsgInfo = '' MsgInfo = 'You must save this run data sheet first...' MsgInfo = 'H' Msg( '', MsgInfo ) END end event Event PSNO_BUTTON.CLICK() PSNo = Get_Property(@WINDOW:'.PS_NO','DEFPROP') IF PSNo NE '' THEN Start_Window('PROD_SPEC',@WINDOW, PSNo:'*CENTER', '', '' ) ;* Old style call to old style window END end event Event EDB_CASS_COMMENTS.CHANGED(NewData) NewComments = NewData OrigComments = Get_Property(@Window, '@COMMENTS') If NewComments NE OrigComments then Set_Property(@Window:'.PUB_SAVE_COMMENTS', 'ENABLED', True$) end else Set_Property(@Window:'.PUB_SAVE_COMMENTS', 'ENABLED', True$) end end event Event PUB_SAVE_COMMENTS.CLICK() RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') CassComments = Get_Property(@Window:'.EDB_CASS_COMMENTS', 'TEXT') ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) ReactRunRec = CassComments Database_Services('WriteDataRow', 'REACT_RUN', RDSNo, ReactRunRec, True$, False$, True$) Set_Property(CtrlEntID, 'ENABLED', False$) Set_Property(@Window, '@COMMENTS', CassComments) end event Event PUB_UPDATE_EA_DATA.CLICK() RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') Engineering_Services('UpdateAll', RDSNo) end event Event PUB_CLOSE_RDS.CLICK() RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') AllWfrsComp = GaN_Services('ReadyToClose', RDSNo) If AllWfrsComp EQ True$ then MsgText = 'Are you sure you want to close this RDS? Once closed an RDS cannot be re-opened.' MsgHead = 'Warning' Response = Msg(@WINDOW,'','YESNO','',MsgHead:@FM:MsgText) If Response EQ Yes$ then GaN_Services('CloseRDS', RDSNo) GoSub FillDispEditTable GoSub EnableCloseRDSButton GoSub UpdateRDSStatus // Refresh the WO_PROD_GAN form if it is open to reflect possible updates to outbound cassettes. GaNProdVis = Get_Property('WO_PROD_GAN', 'VISIBLE') If GaNProdVis EQ True$ then Send_Event('WO_PROD_GAN', 'READ') end end else Dialog_Box('NDW_WAFER_STATUS', @Window, RDSNo) end end event Event PUB_CREATE_NCR.CLICK() DispEDTCtrl = @Window:".OLE_DISP_EDT" CarrSlotList = Get_Property(DispEDTCtrl, 'OLE.List') SelectedRows = Get_Property(DispEDTCtrl, "OLE.ColumnData[":COL$DISP_RDS_NCR:"]") CONVERT @VM TO @FM in SelectedRows NumWfrs = DCount(SelectedRows, @FM) WONo = Get_Property(@Window:'.WO_NO', 'TEXT') RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') Reactor = Get_Property(@Window, '@REACTOR') RejWfrIDs = '' RejSlotIDs = '' GoodLines = 0 FOR WfrIndex = 1 TO NumWfrs RowSelected = SelectedRows If RowSelected EQ True$ then SlotNo = CarrSlotList IF CarrSlotList NE '' Then GoodLines += 1 RejWfrIDs<1,GoodLines> = CarrSlotList RejSlotIDs<1,GoodLines> = RDSNo:'*':SlotNo END end NEXT I ncrParms = WONo:@RM ncrParms := '1':@RM ncrParms := '':@RM ;* Place holder for WO_MAT_CASS_NO ncrParms := RDSNo:@RM ;* Single RDS field ncrParms := Reactor:@RM ;* Reactor No ncrParms := '':@RM ;* Loss Stage ncrParms := RejWfrIDs:@RM ;* WfrIDs ;* CarrWafer IDs ncrParms := RejSlotIDs:@RM ;* CarrSlotIDs ;* GaN PostEpi Carrier Slot ID -> GaN non-characterization wafers ncrParms := '':@RM ;* CassSlotIDs ;* WOMat Cassette Slot ID -> Rej from cassette ncrParms := '' ;* RunPocketZone ;* RPZ -> Rej from susceptor Set_Status(0) NCRNo = obj_NCR('CreateWfr',ncrParms) ;* Create new NCR for this wafer/group of wafers IF Get_Status(errCode) THEN ErrMsg(errCode) end else // Mark wafers as scrap ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) Grades = Xlate('REACT_RUN', RDSNo, 'WFR_GRADES', 'X') WfrIDs = ReactRunRec OutSlotIDs = ReactRunRec For each RejWfrID in RejWfrIDs using @VM setting vPos Locate RejWfrID in WfrIDs using @VM setting wPos then Grades<0, wPos> = 'Scrap' // Check if this wafer is in an outbound cassette. If so, // then remove it. Wafers cannot be shipped and scrapped at the same time. OutSlotID = OutSlotIDs<0, wPos> If OutSlotID NE '' then // Remove wafer from outbound cassette OutCass = Field(OutSlotID, '*', 1, 2) GaN_Services('RemoveWfrsFromOutCass', OutCass, RejWfrID) end end WOWfrRec = Database_Services('ReadDataRow', 'WO_WFR', RejWfrID) WOWfrRec = 'Scrap' WOWfrRec = NCRNo Database_Services('WriteDataRow', 'WO_WFR', RejWfrID, WOWfrRec, True$, False$, True$) Next RejWfrID Dialog_Box('NCR', @Window, NCRNo) PrevCursor = Set_Property('SYSTEM', 'CURSOR', 'H') Def = "" Def = "Loading..." Def = "G" Def = 100 ; // 100% Def = 400 Def = -2 ;* message h-pos in pixels, or -2 (center screen, the default), -1 (center parent) Def = -2 ;* message v-pos in pixels MsgUp = Msg(@Window, Def) Disposition_Services('AutoDispositionRun', RDSNo) Msg(@Window, MsgUp, 20, MSGINSTUPDATE$) GoSub FillMetEditTable Msg(@Window, MsgUp, 40, MSGINSTUPDATE$) GoSub FillDispEditTable Msg(@Window, MsgUp, 60, MSGINSTUPDATE$) GoSub FillNCREditTable Msg(@Window, MsgUp, 80, MSGINSTUPDATE$) GoSub EnableCloseRDSButton Msg(@Window, MsgUp, 100, MSGINSTUPDATE$) Msg(@Window, MsgUp) PrevCursor = Set_Property('SYSTEM', 'CURSOR', 'A') end GoSub EnableNCRButton end event Event PUB_LOT_ABORT.CLICK() RDSNo = Get_Property(@Window : '.RDS_NO', 'TEXT') WfrIDs = Xlate('REACT_RUN', RDSNo, 'IN_WFR_ID', 'X') For each WfrID in WfrIDs using @VM setting vPos FormattedWfrID = WfrID Convert '*' to '.' in FormattedWfrID CurrStage = Gan_Services('GetCurrStage', WfrID) Begin Case Case ( (CurrStage EQ 'UV') or (CurrStage EQ 'UV_PRE') or (CurrStage EQ 'UV_PST') or (CurrStage EQ 'WARP') or (CurrStage EQ 'CAN') or (CurrStage EQ 'CAN_PRE') or (CurrStage EQ 'CAN_PST') ) // Pre-SPLIT wafer // a) Skip any pre-SPLIT stages // b) Mark all wafers as "Disposition" at SPLIT stage Loop StageKey = RDSNo:'*':CurrStage:'*':FormattedWfrID StageStatus = Xlate('RUN_STAGE_WFR', StageKey, 'STATUS', 'X') Begin Case Case StageStatus _EQC 'INIT' // Skip stage - Moves wafer to next stage Gan_Services('SkipWaferStage', RDSNo, WfrID, CurrStage) Case StageStatus _EQC 'START' // Stop wafer - Moves wafer to next stage Gan_Services('StopWaferStage', RDSNo, WfrID, CurrStage) Case StageStatus _EQC 'COMP' Null Case Otherwise$ Null End Case CurrStage = Gan_Services('GetCurrStage', WfrID) Until CurrStage _EQC 'SPLIT' Repeat If CurrStage _EQC 'SPLIT' then Gan_Services('DispositionWfr', RDSNo, WfrID) Case CurrStage _EQC 'SPLIT' // SPLIT wafer - Simply disposition the wafer Gan_Services('DispositionWfr', RDSNo, WfrID) Case (CurrStage _EQC 'XRD') or (CurrStage _EQC 'AFM') | or (CurrStage _EQC 'RPM') or (CurrStage _EQC 'PR') or (CurrStage _EQC 'SCOPE') | or (CurrStage _EQC 'HALL') or (CurrStage _EQC 'EBEAM') or (CurrStage _EQC 'RTA_HALL') | or (CurrStage _EQC 'RTA') or (CurrStage _EQC 'HALL_PGAN') | or (CurrStage _EQC 'BV') or (CurrStage _EQC 'JV_XRD') // Post-SPLIT wafer // a) Currently running wafers will need to be stopped // b) All subsequent stages will need to be auto-skipped including unprescribed stages Loop CurrQ = Gan_Services('GetWfrQueue', WfrID) QType = Gan_Services('GetQueueType', CurrQ) Begin Case Case QType _EQC 'Location' // Wafer not running on a tool. Skip the stage. Gan_Services('SkipWaferStage', RDSNo, WfrID, CurrStage) Case QType _EQC 'Tool' // Wafer running on tool. Stop the stage. Gan_Services('StopWaferStage', RDSNo, WfrID, CurrStage) End Case CurrStage = Gan_Services('GetCurrStage', WfrID) Until CurrStage _EQC 'DISP' Repeat Case CurrStage _EQC 'DISP' // Wafer is where it needs to be. Nothing needed to do. Null Case Otherwise$ ErrorMsg = 'Error aborting wafer ':WfrID:'. Contact FI team for assistance.' ErrMsg(ErrorMsg) End Case Disposition_Services('AutoDispositionWfr', WfrID) Next WfrID GoSub FillMetEditTable GoSub FillDispEditTable end event Event OLE_METROLOGY_EDT.OnButtonClick(Cell, Point, Button, Shift, Ctrl) Row = Field(Cell, ';', 2) Col = Field(Cell, ';', 1) SelStage = Get_Property(CtrlEntID, "OLE.CellText[":Col:";":Row:"]") SelStageID = GaN_Services('GetStageID', SelStage) If ( (SelStageID EQ 'UV') or (SelStageID EQ 'UV_PRE') or (SelStageID EQ 'UV_PST') or (SelStageID EQ 'WARP') or (SelStageID EQ 'WET_CLEAN') or (SelStageID EQ 'CAN_PRE') or (SelStageID EQ 'CAN_PST') or (SelStageID EQ 'PLATO') ) then RDSNo = Get_Property(@Window : '.RDS_NO', 'TEXT') ToolID = Get_Property(@Window : '.OLE_METROLOGY_EDT', 'OLE.CellText[2; ':Row:']') IsSplit = Gan_Services('IsCassSplit', RDSNo) Menu = "" // Initialize menu options StartStatus = False$ StopStatus = False$ CompStatus = False$ SkipStatus = False$ UnskipStatus = False$ WfrIDs = Xlate('REACT_RUN', RDSNo, 'IN_WFR_ID', 'X') WfrStages = Xlate('REACT_RUN', RDSNo, 'WFR_STAGE', 'X') CanPreStartCnt = 0 CanPstStartCnt = 0 WetCleanStartCnt = 0 NumWfrs = Get_Property(@Window, '@NUMWFRS') // Check each wafer in the selected stage to determine which menu options should be enabled. For each WfrID in WfrIDs using @VM setting wPos Convert '*' to '.' in WfrID Begin Case Case SelStageID EQ 'UV_PRE' // Check if UV stage exists UVStageWfrKey = RDSNo:'*UV*':WfrID If RowExists('RUN_STAGE_WFR', UVStageWfrKey) then // Display this on the UV_PRE line RunStageWfrKey = UVStageWfrKey end else RunStageWfrKey = RDSNo:'*':SelStageID:'*':WfrID end Case SelStageID EQ 'CAN_PRE' // Check if CAN stage exists CanStageWfrKey = RDSNo:'*CAN*':WfrID If RowExists('RUN_STAGE_WFR', CanStageWfrKey) then // Display this on the CAN_PRE line RunStageWfrKey = CanStageWfrKey end else RunStageWfrKey = RDSNo:'*':SelStageID:'*':WfrID end Case Otherwise$ RunStageWfrKey = RDSNo:'*':SelStageID:'*':WfrID End Case WfrStatus = Xlate('RUN_STAGE_WFR', RunStageWfrKey, 'STATUS', 'X') Begin Case Case WfrStatus EQ 'INIT' and ToolID NE 'Select' StartStatus = True$ SkipStatus = True$ Case WfrStatus EQ 'INIT' SkipStatus = True$ Case WfrStatus EQ 'START' StopStatus = True$ Case WfrStatus EQ 'STOP' CompStatus = True$ Case WfrStatus EQ 'SKIP' If IsSplit EQ False$ then UnskipStatus = True$ End Case Next WfrID Menu<-1> = "START" :@VM:"Start" :@VM:StartStatus Menu<-1> = "STOP" :@VM:"Stop" :@VM:StopStatus Menu<-1> = "COMP" :@VM:"Complete" :@VM:CompStatus Menu<-1> = "SKIP" :@VM:"Skip" :@VM:SkipStatus Menu<-1> = "UNSKIP" :@VM:"Unskip" :@VM:UnskipStatus Send_Message(CtrlEntID, "OLE.ShowContextMenu", Point, Menu, Cell) end end event Event OLE_REACTOR_EDT.OnButtonClick(Cell, Point, Button, Shift, Ctrl) RecipeMismatch = Get_Property(@Window, '@RECIPEMISMATCH') RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') Row = Field(Cell, ';', 2) Col = Field(Cell, ';', 1) Stage = Get_Property(CtrlEntID, "OLE.CellText[":Col:";":Row:"]") StageID = Gan_Services('GetStageID', Stage) If StageID NE 'ETCH' then Menu = "" // Initialize all menu options to false until we deem they need to be turned on StartStatus = False$ StopStatus = False$ LoadStatus = False$ UnloadStatus = False$ CompStatus = False$ // Get inventory actions associated with this particular stage RDSNo = Get_Property(@Window : '.RDS_NO', 'TEXT') RunStageKey = RDSNo:'*':StageID InvActions = Xlate('RUN_STAGE', RunStageKey, 'SPEC_INV_ACTION', 'X') CurrStatus = Xlate('RUN_STAGE', RunStageKey, 'STATUS', 'X') Begin Case Case StageID EQ 'G_RDS' // Need to check if GaN Run ID has been selected and if the GaN Recipe is populated. GaNRunID = Get_Property(@Window:'.CMB_GAN_RUN_ID', 'TEXT') GaNRecipe = Get_Property(@Window:'.GAN_RECIPE', 'TEXT') EtchKey = RDSNo:'*ETCH' EtchStageComp = Xlate('RUN_STAGE', EtchKey, 'STATUS', 'X') If (GaNRunID NE '') and (GaNRecipe NE '') and (EtchStageComp _EQC 'COMP') and (CurrStatus NE 'COMP') then CompStatus = True$ end Case StageID EQ 'GROWTH' PrevStageKey = RDSNo:'*':'ETCH' PrevStageStatus = Xlate('RUN_STAGE', PrevStageKey, 'STATUS', 'X') If PrevStageStatus EQ 'COMP' then Begin Case Case CurrStatus EQ 'START' UnloadStatus = True$ Case CurrStatus EQ 'COMP' Null Case Otherwise$ LoadStatus = True$ End Case end Case StageID EQ 'G_RATE' PrevStageKey = RDSNo:'*':'GROWTH' PrevStageStatus = Xlate('RUN_STAGE', PrevStageKey, 'STATUS', 'X') If PrevStageStatus EQ 'COMP' and CurrStatus NE 'COMP' then CompStatus = True$ End Case For each Action in InvActions using @VM Begin Case Case Action EQ "START" Menu<-1> = "START" :@VM:"Start" :@VM:StartStatus Case Action EQ "STOP" Menu<-1> = "STOP" :@VM:"Stop" :@VM:StopStatus Case Action EQ "LOAD" Menu<-1> = "LOAD" :@VM:"Load" :@VM:LoadStatus Case Action EQ "UNLOAD" Menu<-1> = "UNLOAD" :@VM:"Unload" :@VM:UnloadStatus End Case Next Action If RecipeMismatch EQ True$ then CompStatus = False$ If StageID NE 'GROWTH' then Menu<-1> = "COMP" :@VM:"Complete" :@VM:CompStatus Send_Message(CtrlEntID, "OLE.ShowContextMenu", Point, Menu, Cell) end end event Event OLE_REACTOR_EDT.OnContextMenuClick(Item, UserData) Set_Property(@Window:'.OLE_METROLOGY_EDT' , "OLE.Redraw", False$) Set_Property(@Window:'.OLE_DISP_STAGE_EDT' , "OLE.Redraw", False$) CurrDTM = DateTime() SelCell = UserData Row = Field(SelCell, ';', 2) RowData = Get_Property(CtrlEntID, "OLE.RecordData[":Row:"]") ReactorStageCtrl = @Window:'.OLE_REACTOR_EDT' RDSNo = Get_Property(@Window : '.RDS_NO', 'TEXT') PSNo = Xlate('REACT_RUN', RDSNo, 'PS_NO', 'X') ANKO = Xlate('PROD_SPEC', PSNo, 'ANKO', 'X') ANKOMetPockets = Xlate('PROD_SPEC', PSNo, 'ANKO_MET_POCKETS', 'X') NumWfrs = DCount(InWfrIDs, @VM) StartCol = 3 EndCol = StartCol + (NumWfrs - 1) WfrActions = '' WfrStage = RowData<1, 1> For Col = StartCol to EndCol WfrActions<1, -1> = RowData<1, Col> Next Col StageName = Get_Property(CtrlEntID, 'OLE.CellText[1; ':Row:']') StageID = Gan_Services('GetStageID', StageName) PRSStageKey = PSNo :'*': StageID CurrAction = Item RunStageKey = RDSNo:'*':StageID RunStageRec = Database_Services('ReadDataRow', 'RUN_STAGE', RunStageKey) WONo = Get_Property(@Window:'.WO_NO', 'TEXT') CassNo = Get_Property(@Window:'.CASS_NO', 'TEXT') WOMatKey = WONo:'*':CassNo WOMatRec = Database_Services('ReadDataRow', 'WO_MAT', WOMatKey) ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) Begin Case Case CurrAction EQ 'UNLOAD' Begin Case Case StageID EQ 'GROWTH' GaN_Services('UnloadSusceptor', RDSNo) If Error_Services('NoError') then Set_Property(ReactorStageCtrl, "OLE.CellText[2; ":Row:"]", 'Complete') ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) CarrSlotIDs = ReactRunRec Scribes = Xlate('REACT_RUN', RDSNo, 'WFR_SCRIBES', 'X') Set_Property(@Window, '@CARRSLOTIDS', CarrSlotIDs) Set_Property(@Window, '@SCRIBES', Scribes) Engineering_Services('PostEARequest', RDSNo, 'GROWTH') GaN_Services('GetGaNMetrologyData', RDSNo, 'GROWTH') GaN_Services('GetGaNMetrologyData', RDSNo, 'TEMP') Reactor = Xlate('REACT_RUN', RDSNo, 'REACTOR', 'X') ToolID = 'R':Reactor Reactor_Services('IncrementCycleCount', ToolID) end else ErrorMessages = Error_Services('GetMessages') Convert @FM to CRLF$ in ErrorMessages ErrMsg(ErrorMesssages) end End Case Case CurrAction EQ 'LOAD' Begin Case Case StageID EQ 'GROWTH' RunStageKey = RDSNo:'*':StageID Reactor = Get_Property(@Window, '@REACTOR') // Need to sign 'LOAD' inventory action LoadComplete = Dialog_Box('DIALOG_LOAD_SUSCEPTOR', @WINDOW, RDSNo:@FM:StageName:@FM:Reactor) If LoadComplete EQ True$ then // Update the UI Set_Property(ReactorStageCtrl, "OLE.CellText[2; ":Row:"]", 'Load') Scribes = Xlate('REACT_RUN', RDSNo, 'WFR_SCRIBES', 'X') WfrIDs = Xlate('REACT_RUN', RDSNo, 'IN_WFR_ID', 'X') Set_Property(@Window, '@WFRIDS', WfrIDs) HeaderTitles = "Stage":@VM:"Tool ID":@VM:Scribes Set_Property(MetStageCtrl, "OLE.TitleList", HeaderTitles) GaNProdVis = Get_Property('WO_PROD_GAN', 'VISIBLE') If GaNProdVis EQ True$ then Send_Event('WO_PROD_GAN', 'READ') GoSub FillDispEditTable GoSub FillNCREditTable GoSub ReadCurrParams GoSub FillDispStageCtrl GoSub ColorTabs GoSub EnableTabs end End Case Case CurrAction EQ 'COMP' // 1. Save REACT_RUN record (Bind REACT_RUN (RDS) key id to GaN Run ID and to GaN Etch ID). Remove GaN Run ID and GaN Etch ID from their respective lists. // 2. Remove all wafers from previous Location/Tool ID queue if applicable // 3. Insert all wafers into Location/Tool ID queue (e.g. LOCATION*GCH*Q_ETCH/TOOL_WFR*R69) // 4. Add COMP_BY and COMP_DTM to RUN_STAGE record // 5. Update UI // 6. Refresh GaN Work Order status form Begin Case Case StageID EQ 'G_RDS' GaNRunID = Get_Property(@Window:'.CMB_GAN_RUN_ID', 'TEXT') GanSuscSerial = Get_Property(@Window:'.GAN_SUSC_SERIAL', 'TEXT') GaNRunRecipe = Get_Property(@Window:'.GAN_RECIPE', 'TEXT') SPCWaferTrackPart = Get_Property(@Window:'.EDL_WAFER_TRACK_PART', 'TEXT') ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) RunInfo = Gan_Services('GetRunInfo', GaNRunID) PocketNos = RunInfo<3> Scribes = RunInfo<4> SatSerialNos = RunInfo<5> // Save the Wafer Track Part from SPC into the WO_LOG record. WOLogRec = Database_Services('ReadDataRow', 'WO_LOG', WONo) WOLogRec = SPCWaferTrackPart Database_Services('WriteDataRow', 'WO_LOG', WONo, WOLogRec, True$, False$, True$) // Just get the first reator in the list InWfrIDs = ReactRunRec Reactor = Get_Property(@Window, '@REACTOR') ReactRunRec = GaNRunID ReactRunRec = GaNRunRecipe ReactRunRec = GanSuscSerial ReactRunRec = SatSerialNos ReactRunRec = Reactor GaN_Services('RemoveRunID', GaNRunID) Database_Services('WriteDataRow', 'REACT_RUN', RDSNo, ReactRunRec, True$, False$, True$) // 2 - N/A // 3 - Move cassette to GROWTH queue. GrowthQ = 'GCH*Q_GROWTH' GaN_Services('MoveCassToQueue', WOMatKey, GrowthQ) WOMatRec = Database_Services('ReadDataRow', 'WO_MAT', WOMatKey) WOMatRec = CurrDTM WOMatRec = @User4 WOMatRec = GrowthQ Database_Services('WriteDataRow', 'WO_MAT', WOMatKey, WOMatRec, True$, False$, True$) // 4 RunStageRec = @User4 RunStageRec = CurrDTM RunStageRec = 'COMP' Database_Services('WriteDataRow', 'RUN_STAGE', RunStageKey, RunStageRec, True$, False$, True$) // 5 Set_Property(ReactorStageCtrl, "OLE.CellText[2; ":Row:"]", 'Complete') // 6 GaNProdVis = Get_Property('WO_PROD_GAN', 'VISIBLE') If GaNProdVis EQ True$ then Send_Event('WO_PROD_GAN', 'READ') Case StageID EQ 'G_RATE' GaNRunID = Get_Property(@Window:'.CMB_GAN_RUN_ID', 'TEXT') RunInfo = Gan_Services('GetRunInfo', GaNRunID) PocketNos = RunInfo<3> Scribes = RunInfo<4> // 1. Remove all wafers from current Location queue // 2. Lookup next Location queue // 3. Insert all wafers into next Location queue CurrLocQID = 'GCH*Q_RATE' NextLocQID = 'GCH*UV_PRE_Q' InWfrIDs = ReactRunRec For each WOWfrID in InWfrIDs using @VM setting vPos If WOWfrID NE '' then ANKOMetPocket = ANKOMetPockets<0, vPos> GaN_Services('RemoveWfrFromWIP', WOWfrID) WOWfrRec = Database_Services('ReadDataRow', 'WO_WFR', WOWfrID) LocDTMs = WOWfrRec NextIndex = DCount(LocDTMs, @VM) + 1 WOWfrRec = CurrDTM WOWfrRec = @User4 WOWfrRec = NextLocQID WOWfrRec = 'COMP' WOWfrRec = PocketNos<0, vPos> WOWfrRec = Scribes<0, vPos> Database_Services('WriteDataRow', 'WO_WFR', WOWfrID, WOWfrRec, True$, False$, True$) Gan_Services('MoveWfrToQueue', WOWfrID, NextLocQID) If ( (ANKO EQ True$) and (ANKOMetPocket EQ True$) ) then GaN_Services('CreateRunStageWfr', RDSNo, 'XRD', WOWfrID) GaN_Services('CreateRunStageWfr', RDSNo, 'PR', WOWfrID) end end Next WOWfrID // 3. Add COMP_BY and COMP_DTM to RUN_STAGE record RunStageRec = @User4 RunStageRec = CurrDTM RunStageRec = 'COMP' Database_Services('WriteDataRow', 'RUN_STAGE', RunStageKey, RunStageRec, True$, False$, True$) // 4. Create prescribed RUN_STAGE_WFR records GaN_Services('CreateAllRunStageWfr', RDSNo, 'SPLIT') // 5. Update REACT_RUN form Set_Property(ReactorStageCtrl, "OLE.CellText[2; ":Row:"]", 'Complete') GoSub EnableRows GoSub FillMetEditTable GoSub FillMetHeader GoSub FillDispStageHeader // 6. Refresh GaN Work Order status form if it is open GaNProdVis = Get_Property('WO_PROD_GAN', 'VISIBLE') If GaNProdVis EQ True$ then Send_Event('WO_PROD_GAN', 'READ') End Case End Case Set_Property(@Window:'.OLE_METROLOGY_EDT' , "OLE.Redraw", True$) Set_Property(@Window:'.OLE_DISP_STAGE_EDT' , "OLE.Redraw", True$) end event Event OLE_METROLOGY_EDT.OnContextMenuClick(Item, UserData) PrevCursor = Set_Property('SYSTEM', 'CURSOR', 'H') // Suppress redraw until all properties are set Set_Property(@Window:'.OLE_METROLOGY_EDT', "OLE.Redraw", False$) Set_Property(@Window:'.OLE_DISP_STAGE_EDT', "OLE.Redraw", False$) Set_Property(@Window:'.OLE_DISP_EDT', "OLE.Redraw", False$) Set_Property(@Window:'.OLE_NCR_EDT', "OLE.Redraw", False$) SelCell = UserData Row = Field(SelCell, ';', 2) RowData = Get_Property(CtrlEntID, "OLE.RecordData[":Row:"]") RDSNo = Get_Property(@Window : '.RDS_NO', 'TEXT') ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) InWfrIDs = ReactRunRec CritStages = ReactRunRec PSNo = Xlate('REACT_RUN', RDSNo, 'PS_NO', 'X') NumWfrs = DCount(InWfrIDs, @VM) StartCol = 3 EndCol = StartCol + (NumWfrs - 1) WfrActions = '' WfrStage = RowData<1, 1> For Col = StartCol to EndCol WfrActions<1, -1> = RowData<1, Col> Next Col StageName = Get_Property(@Window : '.OLE_METROLOGY_EDT', 'OLE.CellText[1; ':Row:']') StageID = Gan_Services('GetStageID', StageName) ToolID = Get_Property(@Window : '.OLE_METROLOGY_EDT', 'OLE.CellText[2; ':Row:']') If ToolID EQ 'Select' then ToolID = '' PRSStageKey = PSNo :'*': StageName Action = Item SpecToolClass = Xlate('PRS_STAGE', PRSStageKey, 'PROC_TOOL_CLASS', 'X') ToolClassRec = Database_Services('ReadDataRow', 'TOOL_CLASS', SpecToolClass) CurrDTM = DateTime() NextStage = Gan_Services('GetNextRxStage', RDSNo, StageID) Begin Case Case Action _EQC 'START' For each WfrID in InWfrIDs using @VM setting WaferIndex FormattedWfrID = WfrID Swap '*' with '.' in FormattedWfrID RunStageWfrKey = RDSNo:'*':StageID:'*':FormattedWfrID StageStatus = Xlate('RUN_STAGE_WFR', RunStageWfrKey, 'STATUS', 'X') ReadyToStart = GaN_Services('ReadyToStart', RDSNo, WfrID) If ( (StageStatus EQ 'INIT') and (ReadyToStart EQ True$) ) then GaN_Services('StartWaferStage', RDSNo, WfrID, StageID, ToolID) Next WfrID Case Action _EQC 'STOP' Def = "" If StageID NE 'WET_CLEAN' then Def = "Stopping Stage and Retrieving SPC Data..." end else Def = "Stopping Stage..." end Def = "G" Def = 100 ; // 100% Def = 400 Def = -2 ;* message h-pos in pixels, or -2 (center screen, the default), -1 (center parent) Def = -2 ;* message v-pos in pixels MsgUp = Msg(@Window, Def) NumWfrs = Get_Property(@Window, '@NUMWFRS') Increment = Int(100 / NumWfrs) + 1 OkToComplete = True$ For each WfrID in InWfrIDs using @VM setting WaferIndex FormattedWfrID = WfrID Swap '*' with '.' in FormattedWfrID RunStageWfrKey = RDSNo:'*':StageID:'*':FormattedWfrID StageStatus = Xlate('RUN_STAGE_WFR', RunStageWfrKey, 'STATUS', 'X') If StageStatus EQ 'START' then GaN_Services('StopWaferStage', RDSNo, WfrID, StageID) Locate StageID in CritStages using @VM setting vPos then If StageID EQ 'PLATO' then GaN_Services('GetPlatoData', RDSNo, ToolID) end else GaN_Services('GetGaNMetrologyData', RDSNo, StageID, ToolID, WfrID) end end If Error_Services('HasError') then DataMissingFlags = ReactRunRec DataDisabledFlags = ReactRunRec For each MissingFlag in DataMissingFlags using @VM setting vPos DisabledFlag = DataDisabledFlags<0, vPos> If MissingFlag and Not(DisabledFlag) then OkToComplete = False$ Next MissingFlag end end * update the gauge Msg(@Window, MsgUp, (Increment * WaferIndex), MSGINSTUPDATE$) Next WfrID Msg(@Window, MsgUp, 90, MSGINSTUPDATE$) Msg(@Window, MsgUp, 100, MSGINSTUPDATE$) Msg(@Window, MsgUp) ;* take down the gauge If OkToComplete EQ True$ then Def = "" Def = "Auto-Completing Stage..." Def = "G" Def = 100 ; // 100% Def = 400 Def = -2 ;* message h-pos in pixels, or -2 (center screen, the default), -1 (center parent) Def = -2 ;* message v-pos in pixels MsgUp = Msg(@Window, Def) For each WfrID in InWfrIDs using @VM setting vPos FormattedWfrID = WfrID Swap '*' with '.' in FormattedWfrID RunStageWfrKey = RDSNo:'*':StageID:'*':FormattedWfrID StageStatus = Xlate('RUN_STAGE_WFR', RunStageWfrKey, 'STATUS', 'X') If StageStatus EQ 'STOP' then GaN_Services('CompleteWaferStage', RDSNo, WfrID, StageID) * update the gauge Msg(@Window, MsgUp, (Increment * vPos), MSGINSTUPDATE$) Next WfrID Msg(@Window, MsgUp, 90, MSGINSTUPDATE$) Engineering_Services('PostEARequest', RDSNo, StageID) If NextStage EQ 'SPLIT' then GaN_Services('SplitSelection', RDSNo) Msg(@Window, MsgUp, 100, MSGINSTUPDATE$) Msg(@Window, MsgUp) ;* take down the gauge end else ErrorMsg = 'Warning: Auto-complete failed. Unable to find ':StageID:' data in SPC.':CRLF$ ErrorMsg := 'Verify metrology data, then attempt to complete the stage again.' Error_Services('Add', ErrorMsg) ErrMsg(ErrorMsg) end If Error_Services('NoError') then Disposition_Services('AutoDispositionRun', RDSNo) GoSub ReadCurrParams GoSub FillDispStageCtrl GoSub ColorTabs GoSub FillDispEditTable Case Action _EQC 'COMP' NumWfrs = Get_Property(@Window, '@NUMWFRS') Increment = Int(100 / NumWfrs) + 1 OkToComplete = True$ If StageID NE 'WET_CLEAN' then Def = "" Def = "Retrieving SPC Data..." Def = "G" Def = 100 Def = 400 Def = -2 ;* message h-pos in pixels, or -2 (center screen, the default), -1 (center parent) Def = -2 ;* message v-pos in pixels MsgUp = Msg(@Window, Def) For each WfrID in InWfrIDs using @VM setting WaferIndex FormattedWfrID = WfrID Swap '*' with '.' in FormattedWfrID RunStageWfrKey = RDSNo:'*':StageID:'*':FormattedWfrID StageStatus = Xlate('RUN_STAGE_WFR', RunStageWfrKey, 'STATUS', 'X') If StageStatus EQ 'STOP' then Locate StageID in CritStages using @VM setting vPos then If StageID EQ 'PLATO' then GaN_Services('GetPlatoData', RDSNo, ToolID) end else GaN_Services('GetGaNMetrologyData', RDSNo, StageID, ToolID, WfrID) end end If Error_Services('HasError') then DataMissingFlags = ReactRunRec DataDisabledFlags = ReactRunRec For each MissingFlag in DataMissingFlags using @VM setting vPos DisabledFlag = DataDisabledFlags<0, vPos> If MissingFlag and Not(DisabledFlag) then OkToComplete = False$ Next MissingFlag end end * update the gauge Msg(@Window, MsgUp, (Increment * WaferIndex), MSGINSTUPDATE$) Next WfrID Msg(@Window, MsgUp, 100, MSGINSTUPDATE$) Msg(@Window, MsgUp) ;* take down the gauge end If OkToComplete EQ True$ then Def = "" Def = "Completing Stage..." Def = "G" Def = 100 ; // 100% Def = 400 Def = -2 ;* message h-pos in pixels, or -2 (center screen, the default), -1 (center parent) Def = -2 ;* message v-pos in pixels MsgUp = Msg(@Window, Def) For each WfrID in InWfrIDs using @VM setting vPos FormattedWfrID = WfrID Swap '*' with '.' in FormattedWfrID RunStageWfrKey = RDSNo:'*':StageID:'*':FormattedWfrID StageStatus = Xlate('RUN_STAGE_WFR', RunStageWfrKey, 'STATUS', 'X') If StageStatus EQ 'STOP' then GaN_Services('CompleteWaferStage', RDSNo, WfrID, StageID) * update the gauge Msg(@Window, MsgUp, (Increment * vPos), MSGINSTUPDATE$) Next WfrID If ( (NextStage EQ 'SPLIT') and (PSNo NE 5191) and (PSNo NE 5192) ) then GaN_Services('SplitSelection', RDSNo) Msg(@Window, MsgUp, 90, MSGINSTUPDATE$) If Error_Services('NoError') then Disposition_Services('AutoDispositionRun', RDSNo) GoSub ReadCurrParams GoSub FillDispStageCtrl GoSub ColorTabs GoSub FillDispEditTable end Engineering_Services('PostEARequest', RDSNo, StageID) Msg(@Window, MsgUp, 100, MSGINSTUPDATE$) Msg(@Window, MsgUp) ;* take down the gauge end else ErrorMsg = 'Warning: Complete stage failed. Unable to find ':StageID:' data in SPC.':CRLF$ ErrorMsg := 'Verify metrology data, then attempt to complete the stage again.' Error_Services('Add', ErrorMsg) ErrMsg(ErrorMsg) end Case Action _EQC 'SKIP' For each WfrID in InWfrIDs using @VM setting vPos FormattedWfrID = WfrID Swap '*' with '.' in FormattedWfrID RunStageWfrKey = RDSNo:'*':StageID:'*':FormattedWfrID StageStatus = Xlate('RUN_STAGE_WFR', RunStageWfrKey, 'STATUS', 'X') If StageStatus EQ 'INIT' then GaN_Services('SkipWaferStage', RDSNo, WfrID, StageID) Next WfrID If ( (NextStage EQ 'SPLIT') and (PSNo NE 5191) ) then Gan_Services('SplitSelection', RDSNo) If Error_Services('NoError') then Disposition_Services('AutoDispositionRun', RDSNo) GoSub ReadCurrParams GoSub FillDispStageCtrl GoSub ColorTabs GoSub FillDispEditTable end end Case Action _EQC 'UNSKIP' For each WfrID in InWfrIDs using @VM setting vPos FormattedWfrID = WfrID Swap '*' with '.' in FormattedWfrID RunStageWfrKey = RDSNo:'*':StageID:'*':FormattedWfrID StageStatus = Xlate('RUN_STAGE_WFR', RunStageWfrKey, 'STATUS', 'X') If StageStatus EQ 'SKIP' then GaN_Services('UnskipWaferStage', RDSNo, WfrID, StageID) Next WfrID End Case GoSub FillMetEditTable // Re-enable redraw now that all properties are set Set_Property(@Window:'.OLE_METROLOGY_EDT', "OLE.Redraw", True$) Set_Property(@Window:'.OLE_DISP_STAGE_EDT', "OLE.Redraw", True$) Set_Property(@Window:'.OLE_DISP_EDT', "OLE.Redraw", True$) Set_Property(@Window:'.OLE_NCR_EDT', "OLE.Redraw", True$) PrevCursor = Set_Property('SYSTEM', 'CURSOR', PrevCursor) end event Event OLE_METROLOGY_EDT.OnClick(Cell, Point, Button, Shift, Ctrl) If Button _EQC 'Right' then Column = Field(Cell, ';', 1, 1) Row = Field(Cell, ';', 2, 1) PopupCtrl = @Window : '.OLE_POPUP' AllowPopup = False$ PopupVisible = Get_Property(PopupCtrl, 'OLE.Visible') If PopupVisible EQ True$ then GoSub DismissPopup end GoSub DisplayPopup end end event Event OLE_METROLOGY_EDT.OnHeaderDblClick(Cell, Point, Button, Shift, Ctrl) Col = Field(Cell, ';', 1, 1) If Col GT 3 then RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') WfrIDs = Xlate('REACT_RUN', RDSNo, 'IN_WFR_ID', 'X') WfrIndex = Col - 3 WfrID = WfrIDs<0, WfrIndex> WfrComments = '' WfrComments = Xlate('WO_WFR', WfrID, 'COMMENTS', 'X') // Display wafer comments and allow user to edit/erase comments. Response = Dialog_Box('NDW_WFR_COMMENTS', @WINDOW, WfrComments) Save = Response<1> NewComments = Response<2> If Save EQ True$ then // Insert comments into WO_WFR record WOWfrRec = Database_Services('ReadDataRow', 'WO_WFR', WfrID) WOWfrRec = NewComments Database_Services('WriteDataRow', 'WO_WFR', WfrID, WOWfrRec, True$, False$, True$) ColNo = WfrIndex + 3 Set_Property(CtrlEntID, "OLE.HeaderToolTip[":ColNo:";1]", NewComments) HeaderColors = Get_Property(CtrlEntID, "OLE.HeaderColors[":ColNo:";1]") If NewComments NE '' then // Set header to cyan so the user knows there's a comment HeaderColors<2> = 'LightCyan' HeaderColors<4> = 'LightCyan' end else // Comment has been removed, so reset header colors back to default colors HeaderColors<2> = 'None' HeaderColors<4> = OI_HOT_BLUE$ end Set_Property(CtrlEntID, "OLE.HeaderColors[":ColNo:";1]", HeaderColors) end end end event Event OLE_REACTOR_EDT.OnClick(Cell, Point, Button, Shift, Ctrl) If Button _EQC 'Right' then Column = Field(Cell, ';', 1, 1) Row = Field(Cell, ';', 2, 1) PopupCtrl = @Window : '.OLE_POPUP' AllowPopup = False$ PopupVisible = Get_Property(PopupCtrl, 'OLE.Visible') If PopupVisible EQ True$ then GoSub DismissPopup end GoSub DisplayPopup end end event Event PUB_IMPORT_MET_DATA.CLICK() Def = "" Def = "Importing..." Def = "G" Def = 100 ; // 100% Def = 400 Def = -2 ;* message h-pos in pixels, or -2 (center screen, the default), -1 (center parent) Def = -2 ;* message v-pos in pixels MsgUp = Msg(@Window, Def) RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') GaN_Services('ClearScribeErrors', RDSNo) MetStageCtrl = @Window:'.OLE_METROLOGY_EDT' GaNParamKeys = Xlate('REACT_RUN', RDSNo, 'GAN_PARAM_KEYS', 'X') MetStageList = '' AllStageList = Database_Services('ReadDataRow', 'APP_INFO', 'GAN_MET_STAGES') For each GaNParamKey in GaNParamKeys using @VM Stage = Field(GaNParamKey, '*', 2, 1) MetStageList<0, -1> = Stage Next GaNParamKey InWfrIDs = Get_Property(@Window, '@WFRIDS') For each Stage in MetStageList using @VM If ( (Stage EQ 'GROWTH') or (Stage EQ 'TEMP') ) then Gan_Services('GetGaNMetrologyData', RDSNo, Stage) end else Locate Stage in AllStageList using @FM setting Row then Msg(@Window, MsgUp, (Row * 5), MSGINSTUPDATE$) ToolType = GaN_Services('GetStageID', Stage) Tool = Get_Property(@Window : '.OLE_METROLOGY_EDT', 'OLE.CellText[2; ':Row:']') WaferIndex = 1 ; // Just use the first wafer's status to determine if the stage is complete. StageStatus = Get_Property(@Window : '.OLE_METROLOGY_EDT', 'OLE.CellText[':(WaferIndex + 2):'; ':Row:']') If ( (Stage EQ 'CAN_PRE') or (Stage EQ 'CAN_PST') or (Stage EQ 'JV_XRD') ) then GaN_Services('VerifyWaferScribes', RDSNo, Tool) Begin Case Case ( ( (ToolType EQ 'UV') or (ToolType EQ 'UV_PRE') or (ToolType EQ 'UV_PST') or (ToolType EQ 'WARP') or (ToolType EQ 'CAN') or (ToolType EQ 'CAN_PRE') or (ToolType EQ 'CAN_PST') ) and (StageStatus EQ 'Complete') ) Gan_Services('GetGaNMetrologyData', RDSNo, ToolType, Tool) Case ( (ToolType EQ 'PLATO') and (StageStatus EQ 'Complete') ) // Plato has a unique service and query GaN_Services('GetPlatoData', RDSNo, Tool) Case StageStatus EQ 'Complete' // Default case for all other stages For each WfrID in InWfrIDs using @VM setting WaferIndex StageStatus = Get_Property(@Window : '.OLE_METROLOGY_EDT', 'OLE.CellText[':(WaferIndex + 2):'; ':Row:']') If StageStatus EQ 'Complete' then Gan_Services('GetGaNMetrologyData', RDSNo, ToolType, Tool, WfrID) Next WfrID End Case end end Next Stage Disposition_Services('AutoDispositionRun', RDSNo) Msg(@Window, MsgUp, 90, MSGINSTUPDATE$) GoSub ReadCurrParams GoSub FillDispStageCtrl Msg(@Window, MsgUp, 95, MSGINSTUPDATE$) GoSub ColorTabs GoSub FillDispEditTable GoSub VerifyScribes GoSub EnableCloseRDSButton Msg(@Window, MsgUp, 100, MSGINSTUPDATE$) Msg(@Window, MsgUp) ;* take down the gauge end event Event OLE_METROLOGY_EDT.OnComboClicked(Cell, SelPos, Value) PrevCursor = Set_Property('SYSTEM', 'CURSOR', 'H') Column = Field(Cell, ';', 1, 1) Row = Field(Cell, ';', 2, 1) MetStageCtrl = @Window:'.OLE_METROLOGY_EDT' MetStageList = Get_Property(MetStageCtrl, "OLE.ColumnData[1]") StageDesc = MetStageList<0, Row> StageID = GaN_Services('GetStageID', StageDesc) RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') PSNo = Xlate('REACT_RUN', RDSNo, 'PS_NO', 'X') WfrIDs = Xlate('REACT_RUN', RDSNo, 'IN_WFR_ID', 'X') MetRowsEnabled = Get_Property(@Window, '@METROWSENABLED') ColorArray = 'None':@FM:'None':@FM:'None':@FM:'None':@FM:'None' ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) WfrStages = ReactRunRec UnRxStages = ReactRunRec CritStages = ReactRunRec ToolID = Get_Property(@Window : '.OLE_METROLOGY_EDT', 'OLE.CellText[2; ':Row:']') CurrDTM = DateTime() WfrIndex = Column - 2 PartNo = Get_Property(@Window:'.EPI_PART_NO', 'TEXT') Reactor = Get_Property(@Window, '@REACTOR') RunID = Get_Property(@Window:'.CMB_GAN_RUN_ID', 'TEXT') SelStage = Get_Property(CtrlEntID, "OLE.CellText[":Column:";":Row:"]") ToolType = GaN_Services('GetStageID', SelStage) Tool = Get_Property(@Window : '.OLE_METROLOGY_EDT', 'OLE.CellText[2; ':Row:']') MetParameter = '' Abort = False$ NextStage = Gan_Services('GetNextRxStage', RDSNo, StageID) If Column EQ COL$MET_TOOL_ID then ToolID = Value // A tool ID has been selected. Need to check all RUN_STAGE_WFR statuses. Tool IDs can only be updated if the // status is 'INIT' or if the stage is CAN. For each WfrID in WfrIDs using @VM setting vPos If WfrID NE '' then WfrIDFormatted = WfrID Swap '*' with '.' in WfrIDFormatted RunStageWfrKey = RDSNo:'*':StageID:'*':WfrIDFormatted If RowExists('RUN_STAGE_WFR', RunStageWfrKey) then WfrStatus = Xlate('RUN_STAGE_WFR', RunStageWfrKey, 'STATUS', 'X') If ( (WfrStatus EQ 'INIT') or (StageID EQ 'CAN') or (StageID EQ 'CAN_PRE') or (StageID EQ 'CAN_PST') ) then Set_Property(MetStageCtrl, "OLE.CellProtection[":Column:";":Row:"]", "None") RunStageWfrRec = Database_Services('ReadDataRow', 'RUN_STAGE_WFR', RunStageWfrKey) RunStageWfrRec = ToolID Database_Services('WriteDataRow','RUN_STAGE_WFR',RunStageWfrKey,RunStageWfrRec,True$,False$,True$) end end end Next WfrID MetRowsEnabled = True$ Set_Property(@Window, '@METROWSENABLED', MetRowsEnabled) end else Action = Value WfrID = WfrIDs<0, WfrIndex> Begin Case Case Action _EQC 'START' Gan_Services('StartWaferStage', RDSNo, WfrID, StageID, ToolID) Case Action _EQC 'STOP' OkToComplete = True$ FormattedWfrID = WfrID Swap '*' with '.' in FormattedWfrID RunStageWfrKey = RDSNo:'*':StageID:'*':FormattedWfrID StageStatus = Xlate('RUN_STAGE_WFR', RunStageWfrKey, 'STATUS', 'X') If StageStatus EQ 'START' then GaN_Services('StopWaferStage', RDSNo, WfrID, StageID) Locate StageID in CritStages using @VM setting vPos then GaN_Services('GetGaNMetrologyData', RDSNo, StageID, ToolID, WfrID) end If Error_Services('HasError') then DataMissingFlags = ReactRunRec DataDisabledFlags = ReactRunRec For each MissingFlag in DataMissingFlags using @VM setting vPos DisabledFlag = DataDisabledFlags<0, vPos> If MissingFlag and Not(DisabledFlag) then OkToComplete = False$ Next MissingFlag end end If ( (StageID EQ 'CAN_PRE') or (StageID EQ 'CAN_PST') or (StageID EQ 'JV_XRD') or (StageID EQ 'PLATO') ) then GaN_Services('VerifyWaferScribes', RDSNo, ToolID) GoSub VerifyScribes end If OkToComplete EQ True$ then FormattedWfrID = WfrID Swap '*' with '.' in FormattedWfrID RunStageWfrKey = RDSNo:'*':StageID:'*':FormattedWfrID StageStatus = Xlate('RUN_STAGE_WFR', RunStageWfrKey, 'STATUS', 'X') If StageStatus EQ 'STOP' then GaN_Services('CompleteWaferStage', RDSNo, WfrID, StageID) Engineering_Services('PostEARequest', RDSNo, StageID) If NextStage EQ 'SPLIT' then GaN_Services('SplitSelection', RDSNo) end Case Action _EQC 'Complete' OkToComplete = True$ If StageID NE 'WET_CLEAN' then FormattedWfrID = WfrID Swap '*' with '.' in FormattedWfrID RunStageWfrKey = RDSNo:'*':StageID:'*':FormattedWfrID StageStatus = Xlate('RUN_STAGE_WFR', RunStageWfrKey, 'STATUS', 'X') If StageStatus EQ 'STOP' then Locate StageID in CritStages using @VM setting vPos then GaN_Services('GetGaNMetrologyData', RDSNo, StageID, ToolID, WfrID) end If Error_Services('HasError') then DataMissingFlags = ReactRunRec DataDisabledFlags = ReactRunRec For each MissingFlag in DataMissingFlags using @VM setting vPos DisabledFlag = DataDisabledFlags<0, vPos> If MissingFlag and Not(DisabledFlag) then OkToComplete = False$ Next MissingFlag end end end If ( (StageID EQ 'CAN_PRE') or (StageID EQ 'CAN_PST') or (StageID EQ 'JV_XRD') ) then GaN_Services('VerifyWaferScribes', RDSNo, ToolID) GoSub VerifyScribes end If OkToComplete EQ True$ then FormattedWfrID = WfrID Swap '*' with '.' in FormattedWfrID RunStageWfrKey = RDSNo:'*':StageID:'*':FormattedWfrID StageStatus = Xlate('RUN_STAGE_WFR', RunStageWfrKey, 'STATUS', 'X') If StageStatus EQ 'STOP' then GaN_Services('CompleteWaferStage', RDSNo, WfrID, StageID) Engineering_Services('PostEARequest', RDSNo, StageID) end else ErrorMsg = 'Warning: Complete stage failed. Unable to find ':StageID:' data in SPC.':CRLF$ ErrorMsg := 'Verify metrology data, then attempt to complete the stage again.' Error_Services('Add', ErrorMsg) ErrMsg(ErrorMsg) end Case Action _EQC 'SKIP' Gan_Services('SkipWaferStage', RDSNo, WfrID, StageID) Case Action _EQC 'UNSKIP' Gan_Services('UnskipWaferStage', RDSNo, WFrID, StageID) Case Action _EQC 'ADD' Gan_Services('AddWaferStage', RDSNo, WfrID, StageID, ToolID) Case Action _EQC 'REMOVE' Gan_Services('RemoveWaferStage', RDSNo, WfrID, StageID) Case Action _EQC 'CHARACTERIZE' If Not( Memberof(@User4, 'GAN_WIP_SUPERVISOR') ) then Response = Dialog_Box('NDW_VERIFY_USER', @Window, @User4 : @FM : 'GAN_WIP_SUPERVISOR') Valid = Response<1> end else Valid = True$ end If Valid EQ True$ then Gan_Services('CharacterizeWafer', RDSNo, WfrID) end else Abort = True$ end Case Action _EQC 'DISPOSITION' If Not( Memberof(@User4, 'GAN_WIP_SUPERVISOR') ) then Response = Dialog_Box('NDW_VERIFY_USER', @Window, @User4 : @FM : 'GAN_WIP_SUPERVISOR') Valid = Response<1> end else Valid = True$ end If Valid EQ True$ then Gan_Services('DispositionWfr', RDSNo, WfrID) end else Abort = True$ end Case Action _EQC 'WITHDRAW' If Not( Memberof(@User4, 'GAN_WIP_SUPERVISOR') ) then Response = Dialog_Box('NDW_VERIFY_USER', @Window, @User4 : @FM : 'GAN_WIP_SUPERVISOR') Valid = Response<1> end else Valid = True$ end If Valid EQ True$ then Gan_Services('WithdrawWfr', RDSNo, WfrID) end else Abort = True$ end Case Otherwise$ End Case end If Error_Services('HasError') then Errmsg(Error_Services('GetMessage')) end If Abort EQ False$ then CurrStage = Gan_Services('GetCurrStage', WfrID) If CurrStage _EQC 'DISP' then // Update the Disposition DTM for all wafers that have been through or are at disposition ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) InWfrIDs = ReactRunRec For each WOWfrID in InWfrIDs using @VM setting vPos ThisWOWfrRec = Database_Services('ReadDataRow', 'WO_WFR', WOWfrID) LocDTMs = ThisWOWfrRec LocQs = ThisWOWfrRec Locate 'GGR*Q_DISP' in LocQs using @VM setting vPos then // Wafer has been dispositioned at some point, so update the disposition DTM LocDTMs<0, vPos> = CurrDTM ThisWOWfrRec = LocDTMs Database_Services('WriteDataRow', 'WO_WFR', WOWfrID, ThisWOWfrRec, True$, False$, True$) end Next WOWfrID Set_Property(@Window:'.PUB_UPDATE_DISP', 'ENABLED', True$) end Disposition_Services('AutoDispositionRun', RDSNo) GoSub ReadCurrParams GoSub FillDispEditTable GoSub FillMetEditTable GoSub ColorTabs GoSub EnableCloseRDSButton end PrevCursor = Set_Property('SYSTEM', 'CURSOR', 'A') end event Event OLE_DISP_EDT.OnCheckChanged(Cell, OldValue, NewValue) Col = Field(Cell, ';', 1, 1) Row = Field(Cell, ';', 2, 1) NCRButton = '' Begin Case Case Col EQ COL$DISP_RDS_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 COMBO_PRIORITY.CHANGED(NewData) Priority = NewData RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) ReactRunRec = Priority Database_Services('WriteDataRow', 'REACT_RUN', RDSNo, ReactRunRec, True$, False$, True$) end event Event CMB_GAN_ETCH_ID.DROPDOWN(EditLineText) /* If ETCH stage complete, then display dropdown of all external etch IDs bound to this RDS. If ETCH stage is not complete, then provide a popup of all available etch IDs and allow the user to select multiple external etch IDs to bind to the RDS */ RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') LogData = '' LogData<1> = OConv(Datetime(), 'DT') LogData<2> = RDSNo LogData<3> = @User4 LogData<4> = 'Begin dropdown event.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) EtchStageKey = RDSNo:'*ETCH' EtchStageStatus = Xlate('RUN_STAGE', EtchStageKey, 'STATUS', 'X') LogData<4> = 'Etch Stage Status: ':EtchStageStatus Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) If EtchStageStatus _NEC 'COMP' then // Open the External Etch Manager so that users can select one or more internal and external etch ID(s) to // bind to this RDS (REACT_RUN) record. Reactor = Get_Property(@Window, '@REACTOR') LogData<4> = 'Reactor: ':Reactor Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) If (Reactor NE '') then SelEtchIDs = '' SelEtchIDs = Dialog_Box('NDW_EXTERNAL_ETCH_MANAGER', @Window, Reactor) LogEtchIDs = SelEtchIDs Convert @FM to ',' in LogEtchIDs LogData<4> = 'Selected etch IDs: ':LogEtchIDs Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) // If SelEtchIDs is equal to False$ (0) then the user canceled the external etch selection process. If SelEtchIDs NE False$ then SelIntEtchIDs = SelEtchIDs<1> SelExtEtchIDs = SelEtchIDs<2> // Update RUN_STAGE record RunStageKey = RDSNo:'*ETCH' RunStageRec = Database_Services('ReadDataRow', 'RUN_STAGE', RunStageKey) If Error_Services('NoError') then CurrDTM = DateTime() RunStageRec = @User4 RunStageRec = CurrDTM RunStageRec = 'COMP' RunStageRec = SelIntEtchIDs Database_Services('WriteDataRow', 'RUN_STAGE', RunStageKey, RunStageRec, True$, False$, True$) If Error_Services('NoError') then // Update REACT_RUN record NumExtEtchIDs = DCount(SelExtEtchIDs, @VM) LastExtEtchID = SelExtEtchIDs<0, NumExtEtchIDs> ExtEtchRecipes = '' Set_Property(@Window:'.CMB_GAN_ETCH_ID', 'LIST', SelExtEtchIDs) Set_Property(@Window:'.CMB_GAN_ETCH_ID', 'SELPOS', -1) Set_Property(@Window:'.CMB_GAN_RUN_ID', 'ENABLED', True$) For each ExtEtchID in SelExtEtchIDs using @VM setting vPos If ExtEtchID _NEC 'No Etch Required' then LogData<4> = 'Calling Gan_Services("GetRunInfo", ':ExtEtchID:').' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) GaNEtchInfo = Gan_Services('GetRunInfo', ExtEtchID) If Error_Services('NoError') then LogData<4> = 'Call to Gan_Services("GetRunInfo", ':ExtEtchID:') was successful.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) end else LogData<4> = 'Error Calling Gan_Services("GetRunInfo", ':ExtEtchID:').' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) end ExtEtchRecipes<0, -1> = GaNEtchInfo<1,1> LogData<4> = 'Calling Gan_Services("ConsumeExtEtchID", ':ExtEtchID:').' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) GaN_Services('ConsumeExtEtchID', ExtEtchID) If Error_Services('NoError') then LogData<4> = 'Call to Gan_Services("ConsumeExtEtchID", ':ExtEtchID:') was successful.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) end else ErrorMessage = Error_Services('GetMessage') LogData<4> = 'Error Calling Gan_Services("ConsumeExtEtchID", ':ExtEtchID:'). Error message: ':ErrorMessage Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) end end else ExtEtchRecipes = 'Not Applicable' end Next ExtEtchID LastExtEtchRecipe = ExtEtchRecipes<0, NumExtEtchIDs> Set_Property(@Window:'.ETCH_RECIPE', 'TEXT', LastExtEtchRecipe) ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) If Error_Services('NoError') then ReactRunRec = SelExtEtchIDs ReactRunRec = ExtEtchRecipes Database_Services('WriteDataRow', 'REACT_RUN', RDSNo, ReactRunRec, True$, False$, True$) If Error_Services('NoError') then For each IntEtchID in SelIntEtchIDs using @VM setting vPos LogData<4> = 'Calling Gan_Services("ConsumeIntEtchID", ':IntEtchID:').' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) GaN_Services('ConsumeIntEtchID', IntEtchID) If Error_Services('NoError') then LogData<4> = 'Call to Gan_Services("ConsumeIntEtchID", ':IntEtchID:') was successful.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) end else ErrorMessage = Error_Services('GetMessage') LogData<4> = 'Error Calling Gan_Services("ConsumeIntEtchID", ':IntEtchID:'). Error message: ':ErrorMessage Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) end Next IntEtchID // Update the UI Row = 1 ; // Etch Configuration Row Set_Property(@Window:'.OLE_REACTOR_EDT', "OLE.CellText[2; ":Row:"]", 'Complete') Set_Property(@Window:'.CMB_GAN_RUN_ID', 'ENABLED', True$) end else ErrorMessage = Error_Services('GetMessage') LogData<4> = 'Error writing REACT_RUN record: ':RDSNo:'. Error message: ':ErrorMessage:'.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) end end else ErrorMessage = Error_Services('GetMessage') LogData<4> = 'Error reading REACT_RUN record: ':RDSNo:'. Error message: ':ErrorMessage:'.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) end end else ErrorMessage = Error_Services('GetMessage') LogData<4> = 'Error writing RUN_STAGE record: ':RunStageKey:'. Error message: ':ErrorMessage:'.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) end end else ErrorMessage = Error_Services('GetMessage') LogData<4> = 'Error reading RUN_STAGE record: ':RunStageKey:'. Error message: ':ErrorMessage:'.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) end end end else ErrorMsg = 'Reactor number is missing. Unable to complete ETCH stage.' ErrMsg(ErrorMsg) end end If Error_Services('NoError') then LogData<4> = 'Dropdown event successful.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) end else LogData<4> = 'Error in dropdown event.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) end LogData<4> = 'End dropdown event.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, True$) end event Event OLE_TAB.SelChanged(Index, PrevIndex) GoSub FillDispStageCtrl end event //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Internal GoSubs //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Setup_OLE_Controls: NumReactorCols = 2 NumReactorRows = 4 NumMetCols = 10 NumMetRows = 21 NumDispCols = 11 NumDispRows = 8 NumNCRCols = 9 NumNCRRows = 5 ReactorCtrlList = '' MetCtrlList = '' DispCtrlList = '' DispParamCtrlList = 'LSL':@FM:'USL' ReactorToolIDArray = '' MetToolIDArray = '' RDSNo = Get_Property(@Window : '.RDS_NO', 'DEFPROP') PSNo = Xlate('RDS', RDSNo, 'PROD_SPEC_ID', 'X') ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) DefaultGaNStageArray = Database_Services('ReadDataRow', 'APP_INFO', 'GAN_STAGES') GaNStageArray = '' MetStageOrder = ReactRunRec If MetStageOrder NE '' then For each StageID in MetStageOrder using @VM Done = False$ For each Row in DefaultGaNStageArray using @FM ThisRowStage = Row<0, 1> If ThisRowStage EQ StageID then GaNStageArray<-1> = Row Done = True$ end Until Done EQ True$ Next Row Next StageID end else GaNStageArray = DefaultGaNStageArray end Set_Property(@Window, '@GAN_STAGES', GaNStageArray) ReactorStageIndex = 1 MetStageIndex = 1 For each Row in GaNStageArray using @FM setting fPos StageDesc = Row<0,2> ToolClassIDs = Row<0,3> RunType = Row<0,5> Begin Case Case RunType EQ 'Reactor' ReactorCtrlList = StageDesc ReactorStageIndex += 1 Case RunType EQ 'Metrology' MetCtrlList = StageDesc TempArray = '' MetCtrlList = 'Select' For each ToolClassID in ToolClassIDs using @SVM setting svPos ToolIDs = Xlate('TOOL_CLASS', ToolClassID, 'TOOL', 'X') ProdTools = '' For each ToolID in ToolIDs using @VM setting vPos CurrMode = Xlate('TOOL', ToolID, 'CURR_MODE', 'X') If CurrMode EQ 'PROD' then ProdTools<0, -1> = ToolID Next ToolID Convert @VM to @STM in ProdTools TempArray = SRP_Array('Join', TempArray, ProdTools, 'OR', @STM) Next ToolClassID If TempArray[-1, 1] EQ @STM then TempArray[-1, 1] = '' MetToolIDArray = TempArray MetStageIndex += 1 End Case Next Row WfrIDs = ReactRunRec Scribes = Xlate('REACT_RUN', RDSNo, 'WFR_SCRIBES', 'X') CarrSlotIDs = ReactRunRec Slots = ReactRunRec NumWfrs = DCount(Scribes, @VM) Set_Property(@Window, '@SCRIBES', Scribes) Set_Property(@Window, '@CARRSLOTIDS', CarrSlotIDs) Set_Property(@Window, '@NUMWFRS', NumWfrs) Set_Property(@Window, '@WFRIDS', WfrIDs) Set_Property(@Window, '@SLOTS', Slots) NumDummyWfrs = 0 DummyPockets = '' NumEmptyWfrs = 0 EmptyPockets = '' For each Scribe in Scribes using @VM setting vPos DummyID = GanRunID[1,7]:'D' EmptyID = GaNRunID[1,7]:'E' If Scribe[1,8] EQ DummyID then NumDummyWfrs += 1 DummyPockets<1, vPos> = True$ end If Scribe[1,8] EQ EmptyID then NumEmptyWfrs += 1 EmptyPockets<1, vPos> = True$ end Next Scribe Set_Property(@Window, '@DUMMYPOCKETS', DummyPockets) Set_Property(@Window, '@EMPTYPOCKETS', EmptyPockets) SuscUnloaded = False$ If NumWfrs GT 0 then // Wafers have not yet been unloaded from the susceptor. We will use this flag to // deactivate various control elements. SuscUnloaded = True$ end ReactorStageCtrl = @Window:'.OLE_REACTOR_EDT' MetStageCtrl = @Window:'.OLE_METROLOGY_EDT' DispCtrl = @Window:'.OLE_DISP_EDT' NCRCtrl = @Window:'.OLE_NCR_EDT' DispParamCtrl = @Window:'.OLE_DISP_PARAM_EDT' HeaderFontArray = 'Segoe UI':@SVM:8:@SVM:700 ReactorDimArray = NumReactorCols :@FM: NumReactorRows MetDimArray = NumMetCols :@FM: NumMetRows DispDimArray = NumDispCols :@FM: NumDispRows NCRDimArray = NumNCRCols :@FM: NumNCRRows Set_Property(@Window, '@METDIMARRAY', MetDimArray) Set_Property(@Window, '@DISPDIMARRAY', DispDimArray) Set_Property(@Window, '@NCRDIMARRAY', NCRDimArray) Set_Property(ReactorStageCtrl, "OLE.CellFont[All; All]", 'Segoe UI':@SVM:8) Set_Property(ReactorStageCtrl, "OLE.Dimension", ReactorDimArray) Set_Property(ReactorStageCtrl, "OLE.CellFont[1;All]", HeaderFontArray) Set_Property(ReactorStageCtrl, "OLE.LIST", ReactorCtrlList) Set_Property(ReactorStageCtrl, "OLE.HeaderFont[All; 1]", HeaderFontArray) Set_Property(ReactorStageCtrl, "OLE.HeaderFont[1; All]", HeaderFontArray) Set_Property(MetStageCtrl, "OLE.CellFont[All; All]", 'Segoe UI':@SVM:8) Set_Property(MetStageCtrl, "OLE.Dimension", MetDimArray) Set_Property(MetStageCtrl, "OLE.CellFont[1;All]", HeaderFontArray) Set_Property(MetStageCtrl, "OLE.LIST", MetCtrlList) Set_Property(MetStageCtrl, "OLE.HeaderFont[All; 1]", HeaderFontArray) Set_Property(MetStageCtrl, "OLE.HeaderFont[1; All]", HeaderFontArray) Set_Property(DispCtrl, "OLE.CellFont[All; All]", 'Segoe UI':@SVM:8) Set_Property(DispCtrl, "OLE.Dimension", DispDimArray) Set_Property(DispCtrl, "OLE.HeaderFont[All; 1]", HeaderFontArray) Set_Property(DispCtrl, "OLE.HeaderFont[1; All]", HeaderFontArray) 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) ScribesCopy = Scribes Convert @VM to '' in ScribesCopy HeaderTitles = "Stage":@VM:"Tool ID" ScribeHeaderTitles = '' If ScribesCopy NE '' then For each Scribe in Scribes using @VM setting vPos SlotID = Field(CarrSlotIDs<0, vPos>, '.', 2, 1) ScribeHeaderTitles<0, -1> = Scribe:' (':SlotID:')' Next Scribe HeaderTitles<0, -1> = ScribeHeaderTitles Set_Property(@Window, '@SCRIBE_HEADER_TITLES', ScribeHeaderTitles) end else DefWfrTitles = '' For WfrIndex = 1 to NumWfrs DefWfrTitles<1, -1> = 'Wafer ':WfrIndex Next WfrIndex HeaderTitles = "Stage":@VM:"Tool ID":@VM:DefWfrTitles end ReactorNo = Get_Property(@Window, '@REACTOR') ReactorHeaderTitles = "Stage":@VM:"Status" Set_Property(ReactorStageCtrl, "OLE.TitleList", ReactorHeaderTitles) Set_Property(ReactorStageCtrl, "OLE.HeaderMerge[1; 2]", 1:@FM:NumReactorRows) Set_Property(ReactorStageCtrl, "OLE.HeaderText[1; 2]", 'Reactor ':ReactorNo) Set_Property(ReactorStageCtrl, "OLE.HeaderAlignment[All; 1]", 'C':@FM:'C':@FM:'L') Set_Property(ReactorStageCtrl, "OLE.CellAlignment[All; All]", 'C':@FM:'C':@FM:'L') Set_Property(ReactorStageCtrl, "OLE.CellAlignment[1; All]", 'C':@FM:'L':@FM:'L') Set_Property(ReactorStageCtrl, "OLE.AllowDeletions", False$) Set_Property(ReactorStageCtrl, "OLE.AllowInserts", False$) Set_Property(MetStageCtrl, "OLE.TitleList", HeaderTitles) Set_Property(MetStageCtrl, "OLE.HeaderMerge[1; 2]", 1:@FM:NumMetRows) Set_Property(MetStageCtrl, "OLE.HeaderText[1; 2]", 'Metrology') Set_Property(MetStageCtrl, "OLE.HeaderAlignment[All; 1]", 'C':@FM:'C':@FM:'L') Set_Property(MetStageCtrl, "OLE.CellAlignment[All; All]", 'C':@FM:'C':@FM:'L') Set_Property(MetStageCtrl, "OLE.CellAlignment[1; All]", 'C':@FM:'L':@FM:'L') Set_Property(MetStageCtrl, "OLE.AllowDeletions", False$) Set_Property(MetStageCtrl, "OLE.AllowInserts", False$) DispHeaderTitles = 'Slot':@VM:'Inbound':@VM:'Scribe':@VM:'Grade':@VM:'Reason':@VM:'Root Cause':@VM:'RDS NCR':@VM:'WMO NCR':@VM DispHeaderTitles := 'Outbound':@VM:'Retain Box':@VM:'Retain Slot' Set_Property(DispCtrl, "OLE.TitleList", DispHeaderTitles) Set_Property(DispCtrl, "OLE.HeaderText[1; 2]", 'Disposition') Set_Property(DispCtrl, "OLE.HeaderAlignment[All; 1]", 'C':@FM:'C':@FM:'L') Set_Property(DispCtrl, "OLE.CellAlignment[":COL$DISP_SLOT:"-":COL$DISP_GRADE:"; All]", 'C':@FM:'C':@FM:'L') Set_Property(DispCtrl, "OLE.CellAlignment[":COL$DISP_REASON:"-":COL$DISP_ROOT_CAUSE:"; All]", 'C':@FM:'L':@FM:'L') Set_Property(DispCtrl, "OLE.CellAlignment[":COL$DISP_RDS_NCR:"-":COL$DISP_RETAIN_SLOT:"; All]", 'C':@FM:'C':@FM:'L') Set_Property(DispCtrl, "OLE.AllowDeletions", False$) Set_Property(DispCtrl, "OLE.AllowInserts", False$) NCRHeaderTitles = 'NCR':@VM:'Status':@VM:'Qty':@VM:'Responsible':@VM:'Stage':@VM:'Loss Desc':@VM:'Loss Comments' | :@VM:'Signature':@VM:'Date & Time' Set_Property(NCRCtrl, "OLE.TitleList", NCRHeaderTitles) Set_Property(NCRCtrl, "OLE.HeaderMerge[1; 2]", 1:@FM:NumNCRRows) Set_Property(NCRCtrl, "OLE.HeaderText[1; 2]", 'Scrap') 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$) // Set default header colors HeaderColorArray = '' HeaderColorArray<1> = 'Auto' HeaderColorArray<2> = 'None' HeaderColorArray<3> = 'None' HeaderColorArray<4> = OI_HOT_BLUE$ HeaderColorArray<5> = False$ Set_Property(ReactorStageCtrl, "OLE.HeaderColors[All; All]", HeaderColorArray) Set_Property(MetStageCtrl, "OLE.HeaderColors[All; All]", HeaderColorArray) Set_Property(DispCtrl, "OLE.HeaderColors[All; All]", HeaderColorArray) Set_Property(NCRCtrl, "OLE.HeaderColors[All; All]", HeaderColorArray) Set_Property(DispParamCtrl, "OLE.HeaderColors[All; All]", HeaderColorArray) // Set header tooltips (wafer comments) For each WfrID in WfrIDs using @VM setting WfrIndex WfrComments = '' WfrComments = Xlate('WO_WFR', WfrID, 'COMMENTS', 'X') ColNo = WfrIndex + 3 If WfrComments NE '' then Set_Property(MetStageCtrl, "OLE.HeaderToolTip[":ColNo:";1]", WfrComments) // Set header to light cyan so the user knows there's a comment HeaderColors = Get_Property(MetStageCtrl, "OLE.HeaderColors[":ColNo:";1]") HeaderColors<2> = 'LightCyan' HeaderColors<4> = 'LightCyan' Set_Property(MetStageCtrl, "OLE.HeaderColors[":ColNo:";1]", HeaderColors) end Next WfrID // Qualify OLE events that we want to intercept Qualifier = '' Qualifier<1> = 1 Qualifier<4> = 0 ; * process synchronously (i.e. immediately) Send_Message(ReactorStageCtrl, 'QUALIFY_EVENT', 'OLE.OnClick', Qualifier) Send_Message(ReactorStageCtrl, 'QUALIFY_EVENT', 'OLE.OnButtonClick', Qualifier) Send_Message(ReactorStageCtrl, 'QUALIFY_EVENT', 'OLE.OnContextMenuClick', Qualifier) Send_Message(MetStageCtrl, 'QUALIFY_EVENT', 'OLE.OnClick', Qualifier) Send_Message(MetStageCtrl, 'QUALIFY_EVENT', 'OLE.PosChanged', Qualifier) Send_Message(MetStageCtrl, 'QUALIFY_EVENT', 'OLE.OnButtonClick', Qualifier) Send_Message(MetStageCtrl, 'QUALIFY_EVENT', 'OLE.OnComboClicked', Qualifier) Send_Message(MetStageCtrl, 'QUALIFY_EVENT', 'OLE.OnContextMenuClick', Qualifier) Send_Message(MetStageCtrl, 'QUALIFY_EVENT', 'OLE.OnHeaderDblClick', Qualifier) Send_Message(DispCtrl, 'QUALIFY_EVENT', 'OLE.OnCheckChanged', Qualifier) Send_Message(DispCtrl, 'QUALIFY_EVENT', 'OLE.OnClick', Qualifier) Send_Message(DispCtrl, 'QUALIFY_EVENT', 'OLE.OnContextMenuClick', Qualifier) Send_Message(DispCtrl, 'QUALIFY_EVENT', 'OLE.OnComboClicked', Qualifier) Send_Message(NCRCtrl, 'QUALIFY_EVENT', 'OLE.OnDblClick', Qualifier) // Process BeforeUpdate event synchronously Qualifier<4> = 1 Send_Message(DispCtrl, 'QUALIFY_EVENT', 'OLE.BeforeUpdate', Qualifier) // Setup Tool ID and Wafer status/action combo boxes CellTypeArray = "" CellTypeArray<1> = "Combo" CellTypeArray<2, 1> = "" CellTypeArray<2, 2> = "L" CellTypeArray<2, 3> = '' CellTypeArray<2, 4> = 1 ;// Column 1 contains the values we care about CellTypeArray<2, 5> = 1 ;// Auto fill on CellTypeArray<2, 6> = 0 ;// Case sensitive on CellTypeArray<2, 7> = 10 ;// 10 visible rows max CellTypeArray<2, 8> = 0 ;// Don't fire the OnOptionClick CellTypeArray<2, 9> = 1 ;// Reduce the list to partial matches CellTypeArray<2, 10> = 0 ;// Only show the drop down when the user types CellTypeArray<2, 11> = 0 ;// Do not use LIST Format CellTypeArray<2, 12> = 1 ;// Autofill on Tool ID name CellTypeArray<2, 13> = 1 ;// Hide dropdown when user clears cell CellTypeArray<2, 14> = 0 ;// Let navigation keys show the drop down CellTypeArray<2, 15> = 0 ;// Show the drop down regardless of the cell's contents CellTypeArray<2, 16> = 0 ;// Show the drop down during autofill CellTypeArray<2, 17> = 1 ;// Remove selection when user backspaces/deletes CellTypeArray<2, 18> = 0 ;// Show Popup while in read only mode CellTypeArray<2, 19> = 1 ;// Show Popup When Navigating CellTypeArray<2, 20> = 1 ;// Always Tab Out on Enter CellTypeArray<2, 21> = -1 ;// Always show the dropdown above when close to the screen bottom CellTypeArray<2, 23> = 1 ;// Limit possible values to those in dropdown // Store this for later use elsewhere Set_Property(@Window, '@COMBOBOX', CellTypeArray) For RowIndex = 1 to NumMetRows ThisComboArray = CellTypeArray ThisComboArray<2, 3> = MetToolIDArray Set_Property(MetStageCtrl, "OLE.CellType[2; ":RowIndex:"]", ThisComboArray) Next RowIndex // Cell selection style setup Set_Property(ReactorStageCtrl, "OLE.ResetSelPos", False$) ;// Prevent cell selection from being reset upon lost focus event Set_Property(MetStageCtrl, "OLE.ResetSelPos", False$) Set_Property(DispCtrl, "OLE.ResetSelPos", False$) Set_Property(NCRCtrl, "OLE.ResetSelPos", False$) ReactorSelStyleArray = Get_Property(ReactorStageCtrl, "OLE.SelectionStyle") ReactorSelStyleArray<8> = True$ MetSelStyleArray = Get_Property(MetStageCtrl, "OLE.SelectionStyle") MetSelStyleArray<8> = True$ ;// Keep cell highlighted when table loses focus DispSelStyleArray = Get_Property(DispCtrl, "OLE.SelectionStyle") DispSelStyleArray<8> = True$ ;// Keep cell highlighted when table loses focus NCRSelStyleArray = Get_Property(NCRCtrl, "OLE.SelectionStyle") NCRSelStyleArray<8> = True$ ;// Keep cell highlighted when table loses focus Set_Property(ReactorStageCtrl, 'OLE.SelectionStyle', ReactorSelStyleArray) Set_Property(MetStageCtrl, 'OLE.SelectionStyle', MetSelStyleArray) Set_Property(DispCtrl, 'OLE.SelectionStyle', DispSelStyleArray) Set_Property(NCRCtrl, 'OLE.SelectionStyle', MCRSelStyleArray) CellSelStyleArray = '' CellSelStyleArray<1> = 'White' ;// Selected cell foreground color CellSelStyleArray<2> = OI_BLUE$ ;// Selected cell background color CellSelStyleArray<3> = 'None' ;// Selected record (row) foreground color - none = default CellSelStyleArray<4> = OI_HOT_BLUE$ ;// Selected record (row) background color CellSelStyleArray<5> = 'None' ;// Selected field (column) foreground color - none = default CellSelStyleArray<6> = OI_HOT_BLUE$ ;// Selected field (column) background color Set_Property(ReactorStageCtrl, 'OLE.CellSelColors[2; All]', CellSelStyleArray) Set_Property(MetStageCtrl, 'OLE.CellSelColors[2-':NumDummyWfrs+2:'; All]', CellSelStyleArray) Set_Property(NCRCtrl, 'OLE.CellSelColors[All; All]', CellSelStyleArray) // Stage cell button style setup ButtonTypeArray = '' ButtonTypeArray<1> = 'Push Button' ButtonTypeArray<2> = '' ButtonTypeArray<2, 1> = False$ ButtonTypeArray<2, 2> = True$ ButtonTypeArray<2, 3> = True$ ButtonTypeArray<3> = 'None' ButtonTypeArray<4> = "Vertical(Gradient(":OI_HOT_BLUE$:", ":OI_HOT_BLUE$:"), Border(":OI_BLUE$:"))" ButtonTypeArray<5> = "Vertical(Gradient(":OI_CLICK_BLUE$:", ":OI_CLICK_BLUE$:"), Border(":OI_BLUE$:"))" ButtonTypeArray<6> = 'OD' ButtonTypeArray<7> = 'None' Set_Property(ReactorStageCtrl, "OLE.CellType[1; All]", ButtonTypeArray) Set_Property(MetStageCtrl, "OLE.CellType[1; All]", ButtonTypeArray) MetRowsEnabled = '' For RowIndex = 1 to NumMetRows MetRowsEnabled = False$ Next RowIndex // Get associated run stage keys and check them for assigned Tool IDs. If Tool ID is // set, then set the Tool ID combo box selection accordingly. ReactorStageList = Get_Property(ReactorStageCtrl, "OLE.ColumnData[1]") MetStageList = Get_Property(MetStageCtrl, "OLE.ColumnData[1]") ReactorStageIDList = '' MetStageIDList = '' For each StageDesc in ReactorStageList using @VM setting vPos ReactorStageIDList<1, vPos> = Gan_Services('GetStageID', StageDesc) Next StageDesc For each StageDesc in MetStageList using @VM setting vPos MetStageIDList<1, vPos> = Gan_Services('GetStageID', StageDesc) Next StageDesc Set_Property(@Window, '@METSTAGEIDLIST', MetStageIDList) RunStageKeys = ReactRunRec MetStages = ReactRunRec Set_Property(@Window, '@METTOOLIDARRAY', MetToolIDArray) // Protect and color dummy and empty wafer columns ColorArray = @FM:'OD' CellColorArray = 'None':@FM:'None':@FM:'None':@FM:'None':@FM:'None' For each Pocket in DummyPockets using @VM setting vPos If Pocket EQ True$ then ColNo = vPos + 2 Set_Property(MetStageCtrl,"OLE.CellProtection[":ColNo:"; All]", "Full") Set_Property(MetStageCtrl,"OLE.CellColors[":ColNo:"; All]", ColorArray) Set_Property(MetStageCtrl,"OLE.ColumnData[":ColNo:"]", '') Set_Property(MetStageCtrl,"OLE.HeaderColors[":ColNo+1:"; 1]", ColorArray) end Next Pocket For each Pocket in EmptyPockets using @VM setting vPos If Pocket EQ True$ then ColNo = vPos + 2 Set_Property(MetStageCtrl,"OLE.CellProtection[":ColNo:"; All]", "Full") Set_Property(MetStageCtrl,"OLE.CellColors[":ColNo:"; All]", ColorArray) Set_Property(MetStageCtrl,"OLE.ColumnData[":ColNo:"]", '') Set_Property(MetStageCtrl,"OLE.HeaderColors[":ColNo+1:"; 1]", ColorArray) end Next Pocket // Protect and color N/A wafer columns If NumWfrs LT 8 then ; // 8 wafers make a full cassette in GaN StartCol = NumWfrs + 3 ; // Must add the three columns before the wafer columns Set_Property(MetStageCtrl,"OLE.CellProtection[":StartCol:"-":NumMetCols:"; All]", "Full") Set_Property(MetStageCtrl,"OLE.CellColors[":StartCol:"-":NumMetCols:"; All]", ColorArray) Set_Property(MetStageCtrl,"OLE.ColumnData[":StartCol:"-":NumMetCols:"]", '') Set_Property(MetStageCtrl,"OLE.HeaderColors[":StartCol+1:"-":NumMetCols+1:"; 1]", ColorArray) end else StartCol = 3 Set_Property(MetStageCtrl,"OLE.CellProtection[":StartCol:"-":NumMetCols:"; All]", "None") Set_Property(MetStageCtrl,"OLE.CellColors[":StartCol:"-":NumMetCols:"; All]", CellColorArray) Set_Property(MetStageCtrl,"OLE.ColumnData[":StartCol:"-":NumMetCols:"]", '') Set_Property(MetStageCtrl,"OLE.HeaderColors[":StartCol+1:"-":NumMetCols+1:"; 1]", CellColorArray) end // Get and set each cassette's current status for each reactor stage // Cassette level (RUN_STAGE) For each Stage in ReactorStageIDList using @VM setting StageIndex RunStageKey = RDSNo:'*':Stage If RowExists('RUN_STAGE', RunStageKey) then CurrStatus = Xlate('RUN_STAGE', RunStageKey, 'STATUS', 'X') DispStatus = '' Begin Case Case CurrStatus _EQC 'COMP' DispStatus = 'Complete' Case CurrStatus _EQC 'STOP' Begin Case Case Stage _EQC 'GROWTH' DispStatus = 'Unload' Case Otherwise$ DispStatus = 'Stop' End Case Case CurrStatus _EQC 'START' If Stage EQ 'GROWTH' then DispStatus = 'Load' end else DispStatus = 'Start' end Case CurrStatus _EQC 'SKIP' DispStatus = 'Skip' Case Otherwise$ DispStatus = 'X' End Case Set_Property(ReactorStageCtrl, "OLE.CellText[2; ":StageIndex:"]", DispStatus) Set_Property(ReactorStageCtrl, "OLE.CellProtection[2; ":StageIndex:"]", "RO") end Next Stage // Get and set each wafer's current status for each stage within the Metrology and Disposition edit tables. GoSub FillMetEditTable GoSub SetupDispEDT GoSub SetupTabCtrl GoSub SetupDispStageCtrl GoSub ReadCurrParams GoSub FillDispStageCtrl GoSub ColorTabs GoSub EnableTabs //////////////////////////////////// Code below here only runs once ////////////////////////////////////////// FirstPassComp = Get_Property(@Window, '@FIRSTPASS') If FirstPassComp EQ '' or FirstPassComp EQ False$ then // Color headers Set_Property(MetStageCtrl, "OLE.HeaderColors[All; 1]", @FM:"{200, 200, 200}") Set_Property(@Window, '@FIRSTPASS', True$) // Disable resizing of the header row and header column // Resize header column to fit contents HeaderRowArray = Get_Property(MetStageCtrl, "OLE.HeaderRow[1]") HeaderColArray = Get_Property(MetStageCtrl, "OLE.HeaderColumn[1]") HeaderRowArray<3> = False$ HeaderColArray<1> = 80 HeaderColArray<3> = False$ Set_Property(MetStageCtrl, "OLE.HeaderColumn[1]", HeaderColArray) Set_Property(MetStageCtrl, "OLE.HeaderRow[1]", HeaderRowArray) // Disable resizing of columns as there is no need for this on this form StageColSize = Get_Property(MetStageCtrl, "OLE.DataColumn[1]") StageColSize<3> = False$ Set_Property(MetStageCtrl, "OLE.DataColumn[All]", StageColSize) // Resize the stage column to fit stage descriptions StageColSize<1> = 186 Set_Property(MetStageCtrl, "OLE.DataColumn[1]", StageColSize) WfrColSize = Get_Property(MetStageCtrl, "OLE.DataColumn[3]") WfrColSize<1> = 96 Set_Property(MetStageCtrl, "OLE.DataColumn[3-10]", WfrColSize) // Disable resizing of rows as there is no need for this on this form RowSizeProps = Get_Property(MetStageCtrl, "OLE.DataRow[1]") RowSizeProps<3> = False$ Set_Property(MetStageCtrl, "OLE.DataRow[All]", RowSizeProps) // Disable resizing of the header row and header column // Resize header column to fit contents HeaderRowArray = Get_Property(ReactorStageCtrl, "OLE.HeaderRow[1]") HeaderColArray = Get_Property(ReactorStageCtrl, "OLE.HeaderColumn[1]") HeaderRowArray<3> = False$ HeaderColArray<1> = 80 HeaderColArray<3> = False$ Set_Property(ReactorStageCtrl, "OLE.HeaderColumn[1]", HeaderColArray) Set_Property(ReactorStageCtrl, "OLE.HeaderRow[1]", HeaderRowArray) // Disable resizing of columns as there is no need for this on this form StageColSize = Get_Property(ReactorStageCtrl, "OLE.DataColumn[1]") StageColSize<3> = False$ Set_Property(ReactorStageCtrl, "OLE.DataColumn[All]", StageColSize) // Resize the stage column to fit stage descriptions StageColSize<1> = 186 Set_Property(ReactorStageCtrl, "OLE.DataColumn[1]", StageColSize) // Disable resizing of rows as there is no need for this on this form RowSizeProps = Get_Property(ReactorStageCtrl, "OLE.DataRow[1]") RowSizeProps<3> = False$ Set_Property(ReactorStageCtrl, "OLE.DataRow[All]", RowSizeProps) // Color headers Set_Property(ReactorStageCtrl, "OLE.HeaderColors[All; 1]", @FM:"{200, 200, 200}") //////////////////////////////////// Setup NCR OLE Edit Table ////////////////////////////////////////////// // Disable resizing of the header row and header column // Resize header column to fit contents HeaderRowArray = Get_Property(NCRCtrl, "OLE.HeaderRow[1]") HeaderColArray = Get_Property(NCRCtrl, "OLE.HeaderColumn[1]") HeaderRowArray<3> = False$ HeaderColArray<1> = 80 HeaderColArray<3> = False$ Set_Property(NCRCtrl, "OLE.HeaderColumn[1]", HeaderColArray) 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> = 140 Set_Property(NCRCtrl, "OLE.DataColumn[":COL$NCR_LOSS_DESC:"]", ColSize) ColSize<1> = 173 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> = 120 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}") // 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) end return FillMetEditTable: RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') WfrIDs = Get_Property(@Window, '@WFRIDS') NumWfrs = Get_Property(@Window, '@NUMWFRS') MetStageIDList = Get_Property(@Window, '@METSTAGEIDLIST') If WfrIDs EQ '' then WfrIDs = Xlate('REACT_RUN', RDSNo, 'IN_WFR_ID', 'X') Set_Property(@Window, '@WFRIDS', WfrIDs) end If NumWfrs EQ '' then NumWfrs = DCount(WfrIDs, @VM) Set_Property(@Window, '@NUMWFRS') end GoSub AutoSelectToolID MetStageCtrl = @Window:'.OLE_METROLOGY_EDT' MetRowsEnabled = Get_Property(@Window, '@METROWSENABLED') CellTypeArray = Get_Property(@Window, '@COMBOBOX') ColorArray = @FM:'OD' CellColorArray = 'None':@FM:'None':@FM:'None':@FM:'None':@FM:'None' EnabledColorArray = CellColorArray // Get and set each wafer's current status for each stage within the Metrology edit table. EndCol = NumWfrs + 2 For each Stage in MetStageIDList using @VM setting StageIndex For each WfrID in WfrIDs using @VM setting WfrIndex BackgroundColor = 'None' CurrWfrRow = StageIndex CurrWfrCol = WfrIndex + 2 If WfrID NE '' then Convert '*' to '.' in WfrID Begin Case Case Stage EQ 'UV_PRE' // Check if UV stage exists UVStageWfrKey = RDSNo:'*UV*':WfrID If RowExists('RUN_STAGE_WFR', UVStageWfrKey) then // Display this on the UV_PRE line RunStageWfrKey = UVStageWfrKey end else RunStageWfrKey = RDSNo:'*':Stage:'*':WfrID end Case Stage EQ 'CAN_PRE' // Check if CAN stage exists CanStageWfrKey = RDSNo:'*CAN*':WfrID If RowExists('RUN_STAGE_WFR', CanStageWfrKey) then // Display this on the CAN_PRE line RunStageWfrKey = CanStageWfrKey end else RunStageWfrKey = RDSNo:'*':Stage:'*':WfrID end Case Otherwise$ RunStageWfrKey = RDSNo:'*':Stage:'*':WfrID End Case SplitKey = RDSNo:'*SPLIT*':WfrID SplitStatus = (Xlate('RUN_STAGE_WFR', SplitKey, 'STATUS', 'X') _EQC 'CHAR') If SplitStatus EQ True$ then MetRowsEnabled = True$ Convert '.' to '*' in WfrID ReadyToSplit = Gan_Services('ReadyToSplit', WfrID) If (Stage _EQC 'SPLIT') and (ReadyToSplit EQ True$) then Set_Property(MetStageCtrl,"OLE.CellProtection[":CurrWfrCol:";":CurrWfrRow:"]", "None") Set_Property(MetStageCtrl,"OLE.CellColors[":CurrWfrCol:";":CurrWfrRow:"]", EnabledColorArray) Set_Property(MetStageCtrl,"OLE.CellColors[":COL$MET_STAGE:'-':COL$MET_TOOL_ID:";":CurrWfrRow:"]", EnabledColorArray) Set_Property(MetStageCtrl,"OLE.CellProtection[":COL$MET_STAGE:'-':COL$MET_TOOL_ID:";":CurrWfrRow:"]", "None") end ThisComboArray = CellTypeArray If RowExists('RUN_STAGE_WFR', RunStageWfrKey) then UnRxStage = Gan_Services('GetUnRxStatus', RDSNo, Stage) If UnRxStage EQ True$ then BackgroundColor = YELLOW$ CurrStatus = Xlate('RUN_STAGE_WFR', RunStageWfrKey, 'STATUS', 'X') ToolID = Xlate('RUN_STAGE_WFR', RunStageWfrKey, 'TOOL_ID', 'X') // Has another stage has already begun for this wafer? ReadyToStart = Gan_Services('ReadyToStart', RDSNo, WfrID) DispStatus = '' Begin Case Case CurrStatus _EQC 'COMP' DispStatus = 'Complete' MetActionArray = 'Complete' If ( ( (Stage _EQC 'CAN_PST') or (Stage _EQC 'WET_CLEAN') or (Stage _EQC 'CAN_PRE') ) and (ReadyToStart EQ True$) and ( (ToolID NE '') or (ToolID NE 'Select') ) ) then MetActionArray<2> = 'Start' Case CurrStatus _EQC 'START' DispStatus = 'Start' MetActionArray = 'Stop' Case CurrStatus _EQC 'STOP' DispStatus = 'Stop' MetActionArray = 'Complete' Case CurrStatus _EQC 'SKIP' DispStatus = 'Skip' MetActionArray = 'Unskip' Case CurrStatus _EQC 'CHAR' DispStatus = 'Characterize' MetActionArray = '' // If any metrology stages after split have been started and/or completed, then withdraw // will not be an option. CanWithdraw = Gan_Services('EligibleToWithdrawWfr', RDSNo, WfrID) If CanWithdraw EQ True$ then MetActionArray = 'Withdraw' Case CurrStatus _EQC 'DISP' DispStatus = 'Disposition' MetActionArray = '' // If G_PACK or RETAIN have been completed, then withdraw will not be an option. CanWithdraw = Gan_Services('EligibleToWithdrawWfr', RDSNo, WfrID) If CanWithdraw EQ True$ then MetActionArray = 'Withdraw' Case CurrStatus _EQC 'INIT' DispStatus = 'X' If Stage _NEC 'SPLIT' then // Need to check if stage is prescribed or not. If UnRxStage EQ True$ then MetActionArray = 'Remove' end else MetActionArray = 'Skip' end If ( (ReadyToStart EQ True$) and (ToolID NE '') and (ToolID NE 'Select') ) then Temp = MetActionArray MetActionArray = 'Start' MetActionArray<2> = Temp end end else MetActionArray = 'Characterize' MetActionArray<2> = 'Disposition' If ReadyToSplit EQ False$ then ColorArray = 'None':@FM:BackgroundColor:@FM:'White':@FM:OI_BLUE$:@FM:'None' Set_Property(MetStageCtrl,"OLE.CellProtection[":CurrWfrCol:";":CurrWfrRow:"]", "FUL") Set_Property(MetStageCtrl,"OLE.CellColors[":CurrWfrCol:";":CurrWfrRow:"]", ColorArray) Set_Property(MetStageCtrl,"OLE.CellColors[":COL$MET_TOOL_ID:";":CurrWfrRow:"]", ColorArray) Set_Property(MetStageCtrl,"OLE.CellProtection[":COL$MET_TOOL_ID:";":CurrWfrRow:"]", "FUL") end end End Case Convert @FM to @STM in MetActionArray ThisComboArray<2, 3> = MetActionArray Set_Property(MetStageCtrl, "OLE.CellType[":CurrWfrCol:";":CurrWfrRow:"]", ThisComboArray) // Cassette/Wafer status/action combo boxes // Need to check current status and set the dropdown options accordingly // Combo box selection options should be context aware. (e.g. "Skip" should not be an option if a // wafer has already started on a tool.) If (Stage _EQC 'XRD') or (Stage _EQC 'AFM') or (Stage _EQC 'RPM') | or (Stage _EQC 'PR') or (Stage _EQC 'SCOPE') or (Stage _EQC 'RTA') | or (Stage _EQC 'HALL') or (Stage _EQC 'EBEAM') or (Stage _EQC 'RTA_HALL') | or (Stage _EQC 'HALL_PGAN') or (Stage _EQC 'BV') or (Stage _EQC 'JV_XRD' ) | or (Stage _EQC 'BV100%') then If ReadyToSplit EQ False$ then Set_Property(MetStageCtrl, "OLE.CellProtection[":CurrWfrCol:";":CurrWfrRow:"]", "FUL") end else Set_Property(MetStageCtrl, "OLE.CellProtection[":CurrWfrCol:";":CurrWfrRow:"]", "None") end Destructive = Gan_Services('IsDestStage', Stage) RowEnabled = MetRowsEnabled If (Destructive EQ True$) then // Set row text color to red If (RowEnabled EQ True$) then DestEditArray = 'Red':@FM:BackgroundColor:@FM:'White':@FM:OI_BLUE$:@FM:'None' Set_Property(MetStageCtrl,"OLE.CellProtection[":CurrWfrCol:";":CurrWfrRow:"]", "None") Set_Property(MetStageCtrl,"OLE.CellColors[":CurrWfrCol:";":CurrWfrRow:"]", DestEditArray) Set_Property(MetStageCtrl,"OLE.CellProtection[":COL$MET_STAGE:'-':COL$MET_TOOL_ID:";":CurrWfrRow:"]", "None") Set_Property(MetStageCtrl,"OLE.CellColors[":COL$MET_STAGE:'-':COL$MET_TOOL_ID:";":CurrWfrRow:"]", DestEditArray) end else DestEditArray = 'Red':@FM:'OD':@FM:'None':@FM:'None':@FM:'None' Set_Property(MetStageCtrl,"OLE.CellProtection[":CurrWfrCol:";":CurrWfrRow:"]", "None") Set_Property(MetStageCtrl,"OLE.CellColors[":CurrWfrCol:";":CurrWfrRow:"]", DestEditArray) Set_Property(MetStageCtrl,"OLE.CellProtection[":COL$MET_STAGE:'-':COL$MET_TOOL_ID:";":CurrWfrRow:"]", "None") Set_Property(MetStageCtrl,"OLE.CellColors[":COL$MET_STAGE:'-':COL$MET_TOOL_ID:";":CurrWfrRow:"]", DestEditArray) end end else // Set row text color to default (i.e. 'None') If (RowEnabled EQ True$) then ColorArray = 'None':@FM:BackgroundColor:@FM:'White':@FM:OI_BLUE$:@FM:'None' Set_Property(MetStageCtrl,"OLE.CellProtection[":CurrWfrCol:";":CurrWfrRow:"]", "None") Set_Property(MetStageCtrl,"OLE.CellColors[":CurrWfrCol:";":CurrWfrRow:"]", ColorArray) Set_Property(MetStageCtrl,"OLE.CellProtection[":COL$MET_STAGE:'-':COL$MET_TOOL_ID:";":CurrWfrRow:"]", "None") Set_Property(MetStageCtrl,"OLE.CellColors[":COL$MET_STAGE:'-':COL$MET_TOOL_ID:";":CurrWfrRow:"]", ColorArray) end else ColorArray = 'None':@FM:'OD':@FM:'None':@FM:'None':@FM:'None' Set_Property(MetStageCtrl,"OLE.CellProtection[":CurrWfrCol:";":CurrWfrRow:"]", "None") Set_Property(MetStageCtrl,"OLE.CellColors[":CurrWfrCol:";":CurrWfrRow:"]", ColorArray) Set_Property(MetStageCtrl,"OLE.CellProtection[":COL$MET_STAGE:'-':COL$MET_TOOL_ID:";":CurrWfrRow:"]", "None") Set_Property(MetStageCtrl,"OLE.CellColors[":COL$MET_STAGE:'-':COL$MET_TOOL_ID:";":CurrWfrRow:"]", ColorArray) end end end Set_Property(MetStageCtrl, "OLE.CellText[":CurrWfrCol:"; ":CurrWfrRow:"]", DispStatus) If ( ( (CurrStatus EQ 'COMP') and (Stage NE 'CAN') and (Stage NE 'WET_CLEAN') and (Stage NE 'CAN_PRE') and (Stage NE 'CAN_PST') ) or (Stage EQ 'UV') or (Stage EQ 'UV_PRE') or (Stage EQ 'UV_PST') or (Stage EQ 'WARP') ) then Set_Property(MetStageCtrl, "OLE.CellText[":CurrWfrCol:"; ":CurrWfrRow:"]", DispStatus) Set_Property(MetStageCtrl, "OLE.CellProtection[":CurrWfrCol:"; ":CurrWfrRow:"]", "FUL") end If ( (Stage _EQC 'CAN') or (Stage _EQC 'CAN_PRE') or (Stage _EQC 'CAN_PST') or (Stage _EQC 'WET_CLEAN') ) and (CurrStatus _EQC 'START') then Set_Property(MetStageCtrl, "OLE.CellProtection[":CurrWfrCol:"; ":CurrWfrRow:"]", "FUL") end end else // RunStageWfr record for this stage is unprescribed. Add option for users to add the stage. MetActionArray = 'Add' Convert @FM to @STM in MetActionArray ThisComboArray = CellTypeArray ThisComboArray<2, 3> = MetActionArray Set_Property(MetStageCtrl, "OLE.CellType[":CurrWfrCol:";":CurrWfrRow:"]", ThisComboArray) Set_Property(MetStageCtrl, "OLE.CellText[":CurrWfrCol:"; ":CurrWfrRow:"]", '') If (Stage _EQC 'CAN_PST') or (Stage _EQC 'CAN_PRE') or (Stage _EQC 'XRD') | or (Stage _EQC 'AFM') or (Stage _EQC 'RPM') or (Stage _EQC 'PR') or (Stage _EQC 'SCOPE') | or (Stage _EQC 'RTA') or (Stage _EQC 'HALL') or (Stage _EQC 'EBEAM') | or (Stage _EQC 'RTA_HALL') or (Stage _EQC 'HALL_PGAN') or (Stage _EQC 'BV') | or (Stage _EQC 'JV_XRD' ) or (Stage EQ 'BV100%') then Destructive = Gan_Services('IsDestStage', Stage) RowEnabled = MetRowsEnabled If ( (StageIndex LE 7) or (SplitStatus EQ True$) ) then If Destructive EQ True$ then DestEditArray = 'Red':@FM:'None':@FM:'White':@FM:OI_BLUE$:@FM:'None' EnabledColorArray = DestEditArray end else EnabledColorArray = 'None':@FM:'None':@FM:'None':@FM:'None':@FM:'None' end Set_Property(MetStageCtrl,"OLE.CellProtection[":CurrWfrCol:";":CurrWfrRow:"]", "None") Set_Property(MetStageCtrl,"OLE.CellColors[":CurrWfrCol:";":CurrWfrRow:"]", EnabledColorArray) Set_Property(MetStageCtrl,"OLE.CellColors[":COL$MET_STAGE:'-':COL$MET_TOOL_ID:";":CurrWfrRow:"]", EnabledColorArray) Set_Property(MetStageCtrl,"OLE.CellProtection[":COL$MET_STAGE:'-':COL$MET_TOOL_ID:";":CurrWfrRow:"]", "None") end else If Destructive EQ True$ then DisabledColorArray = 'Red':@FM:'OD':@FM:'None':@FM:'None':@FM:'None' end else DisabledColorArray = 'None':@FM:'OD':@FM:'None':@FM:'None':@FM:'None' end Set_Property(MetStageCtrl,"OLE.CellProtection[":CurrWfrCol:";":CurrWfrRow:"]", "FUL") Set_Property(MetStageCtrl,"OLE.CellColors[":CurrWfrCol:";":CurrWfrRow:"]", DisabledColorArray) end end end end Next WfrID Destructive = Gan_Services('IsDestStage', Stage) RowEnabled = MetRowsEnabled DisabledColorArray = 'None':@FM:'OD':@FM:'None':@FM:'None':@FM:'None' EnabledColorArray = 'None':@FM:'None':@FM:'None':@FM:'None':@FM:'None' If RowEnabled EQ False$ then If Destructive EQ True$ then DestEditArray = 'Red':@FM:'OD':@FM:'None':@FM:'None':@FM:'None' DisabledColorArray = DestEditArray end Set_Property(MetStageCtrl,"OLE.CellProtection[":COL$MET_STAGE:'-':COL$MET_TOOL_ID:";":StageIndex:"]", "FUL") Set_Property(MetStageCtrl,"OLE.CellColors[":COL$MET_STAGE:'-':COL$MET_TOOL_ID:";":StageIndex:"]", DisabledColorArray) end else If Destructive EQ True$ then DestEditArray = 'Red':@FM:'None':@FM:'White':@FM:OI_BLUE$:@FM:'None' EnabledColorArray = DestEditArray end Set_Property(MetStageCtrl,"OLE.CellProtection[":COL$MET_STAGE:'-':COL$MET_TOOL_ID:";":StageIndex:"]", "None") Set_Property(MetStageCtrl,"OLE.CellColors[":COL$MET_STAGE:'-':COL$MET_TOOL_ID:";":StageIndex:"]", EnabledColorArray) end Next Stage Set_Property(@Window, '@METROWSENABLED', MetRowsEnabled) return AutoSelectToolID: EnabledColorArray = 'None':@FM:'None':@FM:'None':@FM:'None':@FM:'None' MetStageIDList = Get_Property(@Window, '@METSTAGEIDLIST') WfrIDs = Get_Property(@Window, '@WFRIDS') MetStageCtrl = @Window:'.OLE_METROLOGY_EDT' MetRowsEnabled = Get_Property(@Window, '@METROWSENABLED') MetToolIDArray = Get_Property(@Window, '@METTOOLIDARRAY') For each MetStage in MetStageIDList using @VM setting mPos If MetStage _NEC 'SPLIT' then RunStageWfrKey = '' For each WfrID in WfrIDs using @VM setting wPos If WfrID NE '' then CurrWfrCol = wPos + 2 Convert '*' to '.' in WfrID Begin Case Case MetStage EQ 'UV_PRE' // Check if UV stage exists UVStageWfrKey = RDSNo:'*UV*':WfrID If RowExists('RUN_STAGE_WFR', UVStageWfrKey) then // Display this on the UV_PRE line RunStageWfrKey = UVStageWfrKey end else RunStageWfrKey = RDSNo:'*':MetStage:'*':WfrID end Case MetStage EQ 'CAN_PRE' // Check if CAN stage exists CanStageWfrKey = RDSNo:'*CAN*':WfrID If RowExists('RUN_STAGE_WFR', CanStageWfrKey) then // Display this on the CAN_PRE line RunStageWfrKey = CanStageWfrKey end else RunStageWfrKey = RDSNo:'*':MetStage:'*':WfrID end Case Otherwise$ RunStageWfrKey = RDSNo:'*':MetStage:'*':WfrID End Case KeyFound = RowExists('RUN_STAGE_WFR', RunStageWfrKey) If KeyFound EQ True$ then RunStageWfrRec = Database_Services('ReadDataRow', 'RUN_STAGE_WFR', RunStageWfrKey) ToolID = RunStageWfrRec If ToolID EQ '' then // Check to see how many tools exist for the current stage. If only one exists, then // auto-select it for convenience. ToolIDs = Gan_Services('GetToolIDs', MetStage, 'PROD') NumTools = DCount(ToolIDs, @VM) If NumTools EQ 1 then ToolID = ToolIDs<0, 1> RunStageWfrRec = ToolID Database_Services('WriteDataRow', 'RUN_STAGE_WFR', RunStageWfrKey, RunStageWfrRec, True$, False$, True$) end end If ToolID NE '' then Locate MetStage in MetStageIDList using @VM setting RowIndex then ThisComboArray = MetToolIDArray Convert @STM to @VM in ThisComboArray Locate ToolID in ThisComboArray using @VM setting vPos then Set_Property(MetStageCtrl, "OLE.CellComboSelPos[2; ":RowIndex:"]", vPos) end else Set_Property(MetStageCtrl, "OLE.CellText[2;":RowIndex:"]", ToolID) end // Tool ID is set, so enable wafer action dropdown menus. If ( (MetStage NE 'UV') and (MetStage NE 'UV_PRE') and (MetStage NE 'UV_PST') and (MetStage NE 'WARP') and (MetStage NE 'CAN') and (MetStage NE 'CAN_PRE') and (MetStage NE 'CAN_PST') and (MetStage NE 'WET_CLEAN') ) then Set_Property(MetStageCtrl,"OLE.CellProtection[":CurrWfrCol:"; ":RowIndex:"]","None") end MetRowsEnabled = True$ end end end end Next WfrID end Next MetStage Set_Property(@Window, '@METROWSENABLED', MetRowsEnabled) return FillDispStageHeader: DispStageCtrl = @Window:'.OLE_DISP_STAGE_EDT' ScribeHeaderTitles = Get_Property(@Window, '@SCRIBE_HEADER_TITLES') HeaderRowTitles = 'LSL':@VM:'Target':@VM:'USL':@VM:ScribeHeaderTitles Set_Property(DispStageCtrl, "OLE.TitleList", HeaderRowTitles) Set_Property(DispStageCtrl, "OLE.HeaderColors[All; 1]", @FM:"{200, 200, 200}") return FillMetHeader: Scribes = Xlate('REACT_RUN', RDSNo, 'WFR_SCRIBES', 'X') CarrSlotIDs = Xlate('REACT_RUN', RDSNo, 'CARR_SLOT_NO', 'X') Set_Property(@Window, '@SCRIBES', Scribes) Set_Property(@Window, '@CARRSLOTIDS', CarrSlotIDs) MetStageCtrl = @Window:'.OLE_METROLOGY_EDT' ScribesCopy = Scribes Convert @VM to '' in ScribesCopy HeaderTitles = "Stage":@VM:"Tool ID" ScribeHeaderTitles = '' If ScribesCopy NE '' then For each Scribe in Scribes using @VM setting vPos SlotID = CarrSlotIDs<0, vPos> ScribeHeaderTitles<0, -1> = Scribe:' (':SlotID:')' Next Scribe HeaderTitles<0, -1> = ScribeHeaderTitles Set_Property(@Window, '@SCRIBE_HEADER_TITLES', ScribeHeaderTitles) end else DefWfrTitles = '' For WfrIndex = 1 to NumWfrs DefWfrTitles<1, -1> = 'Wafer ':WfrIndex Next WfrIndex HeaderTitles = "Stage":@VM:"Tool ID":@VM:DefWfrTitles end Set_Property(MetStageCtrl, "OLE.TitleList", HeaderTitles) Set_Property(MetStageCtrl, "OLE.HeaderColors[All; 1]", @FM:"{200, 200, 200}") return EnableRows: // Enable rows and columns now that RUN_STAGE_WFR records have been created GaNRunID = Get_Property(@Window:'.CMB_GAN_RUN_ID', 'TEXT') RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') MetStageCtrl = @Window:'.OLE_METROLOGY_EDT' Scribes = Xlate('REACT_RUN', RDSNo, 'PKT_SAT_ID', 'X') DummyPockets = '' NumDummyWfrs = 0 For each Scribe in Scribes using @VM setting vPos DummyID = GanRunID[1,7]:'D' If Scribe[1,8] EQ DummyID then NumDummyWfrs += 1 DummyPockets<1, vPos> = True$ end else DummyPockets<1, vPos> = False$ end Next Scribe NumWfrs = DCount(Scribes, @VM) Set_Property(@Window, '@DUMMYPOCKETS', DummyPockets) Set_Property(@Window, '@NUMWFRS', NumWfrs) MetDimArray = Get_Property(@Window, '@METDIMARRAY') NumMetCols = MetDimArray<1> DispDimArray = Get_Property(@Window, '@DISPDIMARRAY') NumDispCols = DispDimArray<1> EnabledColorArray = 'None':@FM:'None':@FM:'None':@FM:'None':@FM:'None' For each Pocket in DummyPockets using @VM setting vPos If Pocket EQ True$ then ColNo = vPos + 2 Set_Property(MetStageCtrl,"OLE.CellProtection[":ColNo:"; All]", "None") Set_Property(MetStageCtrl,"OLE.CellColors[":ColNo:"; All]", EnabledColorArray) Set_Property(MetStageCtrl,"OLE.ColumnData[":ColNo:"]", '') Set_Property(MetStageCtrl,"OLE.HeaderColors[":ColNo+1:"; 1]", EnabledColorArray) end Next Pocket // Protect and color empty wafer columns If NumWfrs GT 0 then ColOffset = 3 StartCol = ColOffset EndCol = NumWfrs + ColOffset Set_Property(MetStageCtrl,"OLE.CellProtection[":StartCol:"-":EndCol:"; 1-6]", "None") Set_Property(MetStageCtrl,"OLE.CellColors[":StartCol:"-":EndCol:"; 1-6]", EnabledColorArray) Set_Property(MetStageCtrl,"OLE.ColumnData[":StartCol:"-":EndCol:"]", '') Set_Property(MetStageCtrl,"OLE.HeaderColors[":StartCol+1:"-":EndCol+1:"; 1]", EnabledColorArray) end return FillDispEditTable: RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') DispCtrl = @Window:'.OLE_DISP_EDT' DispDimArray = Get_Property(@Window, '@DISPDIMARRAY') NumDispRows = DispDimArray<2> Set_Property(DispCtrl, "OLE.HeaderMerge[1; 2]", 1:@FM:NumDispRows) ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) DispCtrlArray = '' ComboBoxArray = Get_Property(@Window, '@COMBOBOX') InWfrIDs = ReactRunRec NumWfrs = DCount(InWfrIDs, @VM) RDSClosed = ReactRunRec ScribeErrors = ReactRunRec PSNo = Xlate('REACT_RUN', RDSNo, 'PS_NO', 'X') ANKO = Xlate('PROD_SPEC', PSNo, 'ANKO', 'X') For WfrIndex = 1 to NumWfrs ScribeError = ScribeErrors<0, WfrIndex> Row = WfrIndex WfrID = InWfrIDs<0, WfrIndex> WOWfrRec = Database_Services('ReadDataRow', 'WO_WFR', WfrID) RDSNCRNo = WOWfrRec WMONCRNo = WOWfrRec NCRReq = ReactRunRec DispReady = ReactRunRec Grade = WOWfrRec Scribe = WOWfrRec Reason = ReactRunRec WfrChar = ReactRunRec RetainBox = WOWfrRec RetainSlot = WOWfrRec DispCtrlArray = ReactRunRec DispCtrlArray = ReactRunRec DispCtrlArray = Scribe DispCtrlArray = RDSNCRNo DispCtrlArray = WMONCRNo DispCtrlArray = ReactRunRec DispCtrlArray = Grade If RDSNCRNo NE '' then // Display the reason from the NCR record LossCode = Xlate('NCR', RDSNCRNo, 'LOSS_CODE', 'X') DispCtrlArray = Xlate('NCR', RDSNCRNo, 'LOSS_DESC', 'X') DispCtrlArray = Xlate('NCR', RDSNCRNo, 'AC_DESC', 'X') end else // Display the reason from the REACT_RUN record LossCode = '' DispCtrlArray = ReactRunRec DispCtrlArray = '' end DispCtrlArray = RetainSlot DispCtrlArray = RetainBox MetComp = GaN_Services('GetMetrologyStatus', WfrID) DispComp = GaN_Services('GetDispStatus', WfrID) CharType = Gan_Services('GetCharType', WfrID) If ( ( (WfrChar NE True$) or (CharType EQ 'Light') ) and (RDSClosed NE True$) and (RDSNCRNo EQ '') ) then // Reset cell back to a text cell in case it was previously set to a check box Set_Property(DispCtrl, "OLE.CellType[":COL$DISP_RDS_NCR:";":WfrIndex:"]", 'Text') Set_Property(DispCtrl, "OLE.CellText[":COL$DISP_RDS_NCR:";":WfrIndex:"]", '') // Convert NCR cell for this row into a check box CheckBoxArray = 'Check Box' CheckBoxArray<2,1> = True$ Set_Property(DispCtrl, "OLE.CellType[":COL$DISP_RDS_NCR:";":WfrIndex:"]", CheckBoxArray) end else // Reset cell back to a text cell in case it was previously set to a check box Set_Property(DispCtrl, "OLE.CellType[":COL$DISP_RDS_NCR:";":WfrIndex:"]", 'Text') Set_Property(DispCtrl, "OLE.CellText[":COL$DISP_RDS_NCR:";":WfrIndex:"]", RDSNCRNo) end Begin Case Case ScribeError EQ True$ ColorArray = 'None':@FM:ORANGE$ Case Grade _EQC 'Scrap' ColorArray = 'None':@FM:RED$ Case DispReady EQ True$ // Color scribe cell green to indicate that the wafer is ready to be placed in an outbound cassette. // Color scribe cell within disposition edit table green ColorArray = 'None':@FM:BGREEN$ Case Otherwise$ ColorArray = 'None':@FM:'None' End Case Set_Property(DispCtrl, 'OLE.CellColors[':COL$DISP_SCRIBE:';':WfrIndex:']', ColorArray) If RDSClosed NE True$ then // Enable editing of the cell Set_Property(DispCtrl, 'OLE.CellProtection[':COL$DISP_REASON:';':WfrIndex:']', 'None') end Next WfrIndex Set_Property(DispCtrl, "OLE.ARRAY", DispCtrlArray) GoSub EnableNCRButton return Event OLE_NCR_EDT.OnDblClick(Cell, Point, Button, Shift, Ctrl) DispCtrlArray = Get_Property(@Window:'.OLE_DISP_EDT', "OLE.ARRAY") Row = Field(Cell, ';', 2, 1) RDSNCRNos = DispCtrlArray WMONCRNos = DispCtrlArray NCRNos = SRP_Array('Join', RDSNCRNos, WMONCRNos, 'OR', @VM) NCRNo = Get_Property(CtrlEntID, "OLE.CellText[":COL$NCR_NO:";":Row:"]") If RowExists('NCR', NCRNo) then PreNCRRec = Database_Services('ReadDataRow', 'NCR', NCRNo) PostNCRRec = '' Dialog_Box('NCR', @Window, NCRNo) If RowExists('NCR', NCRNo) then PostNCRRec = Database_Services('ReadDataRow', 'NCR', NCRNo) If PreNCRRec NE PostNCRRec then RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') PrevCursor = Set_Property('SYSTEM', 'CURSOR', 'H') Def = "" Def = "Loading..." Def = "G" Def = 100 ; // 100% Def = 400 Def = -2 ;* message h-pos in pixels, or -2 (center screen, the default), -1 (center parent) Def = -2 ;* message v-pos in pixels MsgUp = Msg(@Window, Def) Disposition_Services('AutoDispositionRun', RDSNo) Msg(@Window, MsgUp, 20, MSGINSTUPDATE$) Msg(@Window, MsgUp, 40, MSGINSTUPDATE$) GoSub FillDispEditTable Msg(@Window, MsgUp, 60, MSGINSTUPDATE$) GoSub FillNCREditTable Msg(@Window, MsgUp, 80, MSGINSTUPDATE$) GoSub EnableCloseRDSButton Msg(@Window, MsgUp, 100, MSGINSTUPDATE$) GoSub EnableNCRButton Msg(@Window, MsgUp) PrevCursor = Set_Property('SYSTEM', 'CURSOR', 'A') end end end event Event OLE_DISP_STAGE_EDT.OnClick(Cell, Point, Button, Shift, Ctrl) If Button EQ 'Right' then Col = Field(Cell, ';', 1, 1) Row = Field(Cell, ';', 2, 1) CellColorArray = Get_Property(@Window, '@COLOR_ARRAY') SelTabIndex = Get_Property(@Window:".OLE_TAB", "OLE.SelectedTab") CaptionList = Get_Property(@Window:".OLE_TAB", "OLE.CaptionList") StageID = Field(CaptionList, ',', SelTabIndex, 1) BackColor = CellColorArray CellText = Get_Property(CtrlEntID, "OLE.CellText[":Col:";":Row:"]") Begin Case Case CellText EQ 'Multi' PopupCtrl = @Window : '.OLE_POPUP' PopupVisible = Get_Property(PopupCtrl, 'OLE.Visible') If PopupVisible EQ True$ then GoSub DismissPopup end GoSub DisplayMetPopup Case BackColor EQ 'Yellow' PopupCtrl = @Window : '.OLE_POPUP' PopupVisible = Get_Property(PopupCtrl, 'OLE.Visible') If PopupVisible EQ True$ then GoSub DismissPopup end GoSub DisplayStageDisPopup End Case end end event Event OLE_DISP_STAGE_EDT.OnHeaderClick(Cell, Point, Button, Shift, Ctrl) If Button EQ 'Right' then Col = Field(Cell, ';', 1, 1) Row = Field(Cell, ';', 2, 1) Scribe = Get_Property(CtrlEntID, "OLE.HeaderText[":Col:";":Row:"]") Scribe = Scribe[1, 'F '] RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') Scribes = Get_Property(@Window, '@SCRIBES') RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') RDSClosed = Xlate('REACT_RUN', RDSNo, 'DISP_COMPLETE', 'X') Locate Scribe in Scribes using @VM setting WfrIndex then ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) DataValidationDisabled = ReactRunRec DataIsMissing = ReactRunRec DataOutOfSpec = ReactRunRec If RDSClosed EQ True$ then Enabled = False$ end else Enabled = True$ end Menu = '' Begin Case Case DataValidationDisabled EQ True$ Menu<-1> = 'ENABLE' :@VM: 'Enable Data Validation' :@VM: Enabled Case ( ( (DataValidationDisabled NE True$) and (DataIsMissing EQ True$) ) or (DataOutOfSpec EQ True$) ) Menu<-1> = 'DISABLE' :@VM: 'Disable Data Validation' :@VM: Enabled Case Otherwise$ Menu<-1> = 'DISABLE' :@VM: 'Disable Data Validation' :@VM: False$ End Case // Note you must pass all variables when calling Send_Message otherwise the call will fail User = '' Locate Scribe in Scribes using @VM setting WfrIndex then User = WfrIndex end Send_Message(CtrlEntID, "OLE.ShowContextMenu", Point, Menu, User) end end end event Event OLE_DISP_STAGE_EDT.OnContextMenuClick(Item, UserData) Abort = False$ If Not( Memberof(@User4, 'GAN_WIP_SUPERVISOR') ) then MsgText = 'A member of the "GAN_WIP_SUPERVISOR" group must override.' Response = Msg(@Window, '', 'OVERRIDE', '', MsgText) If Response EQ Yes$ then // Verify credentials Response = Dialog_Box('NDW_VERIFY_USER', @WINDOW, @USER4:@FM:'GAN_WIP_SUPERVISOR') Valid = Response<1> If Valid NE True$ then Abort = True$ end else Abort = True$ end end If Abort EQ False$ then RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) WfrIDs = ReactRunRec Action = Item WfrIndex = UserData WfrID = WfrIDs<0, WfrIndex> TabCount = Get_Property(@Window:'.OLE_TAB', 'OLE.TabCount') CellColorArray = Get_Property(@Window, '@COLOR_ARRAY') Begin Case Case Action EQ 'DISABLE' ReactRunRec = True$ ReactRunRec = @User4 ReactRunRec = Datetime() Case Action EQ 'ENABLE' ReactRunRec = False$ ReactRunRec = '' ReactRunRec = '' End Case For TabIndex = 1 to TabCount ThisTabCellColorArray = CellColorArray Convert @VM to @FM in ThisTabCellColorArray Convert @SVM to @VM in ThisTabCellColorArray ThisTabCellColorArray = SRP_Array('Rotate', ThisTabCellColorArray, @FM, @VM) ThisWaferCellColorArray = ThisTabCellColorArray Stage = Get_Property(@Window:'.OLE_TAB', "OLE.TabCaption[":TabIndex:"]") Swap ' ' with '_' in Stage Swap '*' with '.' in WfrID RunStageWfrKey = RDSNo:'*':Stage:'*':WfrID ParamOutOfSpec = Xlate('RUN_STAGE_WFR', RunStageWfrKey, RUN_STAGE_WFR_PARAM_OUT_OF_SPEC$, 'X') DataOutOfSpec = False$ DataMissing = False$ For each Value in ParamOutOfSpec using @VM If Value EQ 1 then DataOutOfSpec = True$ If Value EQ -1 then DataMissing = True$ Next Value Begin Case Case Action EQ 'DISABLE' Begin Case Case DataOutOfSpec EQ True$ Swap 'Red' with 'SlateBlue L=75' in ThisWaferCellColorArray Case DataMissing EQ True$ Swap 'Yellow' with 'SlateBlue L=75' in ThisWaferCellColorArray End Case Case Action EQ 'ENABLE' Begin Case Case DataOutOfSpec EQ True$ Swap 'SlateBlue L=75' with 'Red' in ThisWaferCellColorArray Case DataMissing EQ True$ Swap 'SlateBlue L=75' with 'Yellow' in ThisWaferCellColorArray End Case End Case ThisTabCellColorArray = ThisWaferCellColorArray ThisTabCellColorArray = SRP_Array('Rotate', ThisTabCellColorArray, @FM, @VM) Convert @VM to @SVM in ThisTabCellColorArray Convert @FM to @VM in ThisTabCellColorArray CellColorArray = ThisTabCellColorArray Next TabIndex Set_Property(@Window, '@COLOR_ARRAY', CellColorArray) Database_Services('WriteDataRow', 'REACT_RUN', RDSNo, ReactRunRec, True$, False$, True$) Disposition_Services('AutoDispositionRun', RDSNo) GoSub ColorCells GoSub ColorTabs GoSub FillDispEditTable GoSub EnableCloseRDSButton end end event Event OLE_DISP_EDT.OnClick(Cell, Point, Button, Shift, Ctrl) Col = Field(Cell, ';', 1, 1) Row = Field(Cell, ';', 2, 1) Begin Case Case Col EQ COL$DISP_WFR_ID If Button _EQC 'Right' then RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') WfrID = Get_Property(CtrlEntID, "OLE.CellText[":COL$DISP_WFR_ID:";":Row:"]") Menu = '' MenuEnabled = False$ If RowExists('WO_WFR', WfrID) then MenuEnabled = True$ Menu<-1> = "CharStages" :@VM:"View Char Stages" :@VM:MenuEnabled Menu<-1> = "WaferTrace" :@VM:"View Wafer Trace" :@VM:MenuEnabled Send_Message(CtrlEntID, "OLE.ShowContextMenu", Point, Menu, WfrID) end End Case If Col EQ COL$DISP_WFR_ID then If Button _EQC 'Right' then RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') WfrID = Get_Property(CtrlEntID, "OLE.CellText[":COL$DISP_WFR_ID:";":Row:"]") Menu = '' MenuEnabled = False$ If RowExists('WO_WFR', WfrID) then MenuEnabled = True$ Menu<-1> = "CharStages" :@VM:"View Char Stages" :@VM:MenuEnabled Menu<-1> = "WaferTrace" :@VM:"View Wafer Trace" :@VM:MenuEnabled Send_Message(CtrlEntID, "OLE.ShowContextMenu", Point, Menu, WfrID) end end end event Event OLE_DISP_EDT.OnContextMenuClick(Item, UserData) RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') Action = Item WfrID = UserData Begin Case Case Action _EQC 'CharStages' WfrSigProfile = obj_React_Run('GetWfrSigKeys', RDSNo:@RM:WfrID) TypeOver = '' TypeOver = WfrSigProfile Dummy = Popup(@Window, TypeOver, 'CHAR_WFR_STAGES') Case Action _EQC 'WaferTrace' TraceData = obj_WO_Wfr('TraceData', WfrID:@RM:'') TypeOver = '' TypeOver = TraceData Dummy = Popup(@Window, TypeOver, 'WAFER_TRACE') End Case end event EnableNCRButton: Checkmarks = Get_Property(@Window:".OLE_DISP_EDT", "OLE.CellCheck[":COL$DISP_RDS_NCR:"; All]") Checksum = Sum(Checkmarks) If ( Checksum GT 0 ) then NCRButton = True$ end else NCRButton = False$ end Set_Property(@Window:'.PUB_CREATE_NCR', 'ENABLED', NCRButton) return FillNCREditTable: RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') NCRCtrl = @Window:'.OLE_NCR_EDT' InWfrIDs = Get_Property(@Window, '@WFRIDS') NCRCtrlArray = '' NCRNos = '' RDSNCRs = Xlate('WO_WFR', InWfrIDs, 'RDS_NCR_NO', 'X') WMONCRs = Xlate('WO_WFR', InWfrIDs, 'WMO_NCR_NO', 'X') NCRNos = SRP_Array('Join', RDSNCRs, WMONCRs, 'OR', @VM) NCRNos = SRP_Array('Clean', NCRNos, 'Trim', @VM) If NCRNos NE '' then For each NCRNo in NCRNos using @VM setting nPos Database_Services('ActivateRecord', 'NCR', NCRNo) If Error_Services('NoError') then NCRCtrlArray = NCRNo NCRCtrlArray = {STATUS} NCRCtrlArray = {REJ_CNT} NCRCtrlArray = {LOSS_BY} NCRCtrlArray = {LOSS_STAGE} NCRCtrlArray = {LOSS_DESC} NCRCtrlArray = {LOSS_COMMENTS} NCRCtrlArray = OConv({AUTH_SHIP_SIG}, '[XLATE_CONV,LSL_USERS*FIRST_LAST]') NCRCtrlArray = OConv({AUTH_SHIP_SIG_DTM}, 'DT') end else NCRCtrlArray = NCRNo NCRCtrlArray = 'Error' NCRCtrlArray = 'Error' NCRCtrlArray = 'Error' NCRCtrlArray = 'Error' NCRCtrlArray = 'Error' NCRCtrlArray = 'Error' NCRCtrlArray = 'Error' NCRCtrlArray = 'Error' end Next NCRNo end else // No NCRs associated with this inbound cassette, so clear the NCR table. NCRDimArray = Get_Property(@Window, '@NCRDIMARRAY') NumRows = NCRDimArray<2> For nPos = 1 to NumRows NCRCtrlArray = '' NCRCtrlArray = '' NCRCtrlArray = '' NCRCtrlArray = '' NCRCtrlArray = '' NCRCtrlArray = '' NCRCtrlArray = '' NCRCtrlArray = '' NCRCtrlArray = '' Next nPos end Set_Property(NCRCtrl, "OLE.ARRAY", NCRCtrlArray) return DismissPopup: PopupCtrl = @Window : '.OLE_POPUP' PopupVisible = Get_Property(PopupCtrl, 'OLE.Visible') If PopupVisible EQ True$ then Send_Message(PopupCtrl, 'OLE.Close') end return DisplayPopup: Set_Property('SYSTEM', 'CURSOR', 'H') BackColor = Get_Property(@Window, 'BACKCOLOR') ForeColor = Get_Property(@Window, 'FORECOLOR') CursorXPos = Field(Point, ',', 1, 1) CursorYPos = Field(Point, ',', 2, 1) FormSize = SRP_Get_Window_Rect(@Window) FormXPos = FormSize<1> FormYPos = FormSize<2> CtrlSize = Get_Property(CtrlEntID, 'SIZE') CtrlXPos = CtrlSize<1> CtrlYPos = CtrlSize<2> PopupWidth = 160 PopupHeight = 60 XPadding = 10 YPadding = 10 XOffset = 10 YOffset = 55 PopupXPos = FormXPos + CtrlXPos + CursorXPos + XOffset PopupYPos = FormYPos + CtrlYPos + CursorYPos + YOffset StatusBy = '' StatusDTM = '' RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) StageDesc = Get_Property(CtrlEntID, 'OLE.CellText[1; ':Row:']') StageID = Gan_Services('GetStageID', StageDesc) Begin Case Case CtrlEntID _EQC @Window:'.OLE_REACTOR_EDT' // Cassette Level RunStageKey = RDSNo:'*':StageID RunStageRec = Database_Services('ReadDataRow', 'RUN_STAGE', RunStageKey) StageStatus = RunStageRec Begin Case Case StageStatus _EQC 'COMP' or StageStatus _EQC 'SKIP' StatusBy = RunStageRec StatusDTM = RunStageRec Case StageStatus _EQC 'START' InvActions = RunStageRec Locate 'START' in InvActions using @VM setting vPos then StatusBy = RunStageRec StatusDTM = RunStageRec end End Case Case CtrlEntID _EQC @Window:'.OLE_METROLOGY_EDT' // Wafer level ScribeHeader = Get_Property(CtrlEntID, 'OLE.HeaderText[':Column+1:'; 1]') Scribe = ScribeHeader[1, 'F '] Scribes = Xlate('REACT_RUN', RDSNo, 'WFR_SCRIBES', 'X') WfrIDs = ReactRunRec WfrID = '' Locate Scribe in Scribes using @VM setting vPos then WfrID = WfrIDs<0, vPos> end Convert '*' to '.' in WfrID RunStageWfrKey = RDSNo:'*':StageID:'*':WfrID If RowExists('RUN_STAGE_WFR', RunStageWfrKey) then RunStageWfrRec = Database_Services('ReadDataRow', 'RUN_STAGE_WFR', RunStageWfrKey) end else // This may be an old run that has a CAN stage instead of a CAN_PRE stage If StageID EQ 'CAN_PRE' then RunStageWfrKey = RDSNo:'*CAN*':WfrID If RowExists('RUN_STAGE_WFR', RunStageWfrKey) then RunStageWfrRec = Database_Services('ReadDataRow', 'RUN_STAGE_WFR', RunStageWfrKey) end end end StageStatus = RunStageWfrRec Begin Case Case StageStatus _EQC 'COMP' or StageStatus _EQC 'SKIP' or StageStatus _EQC 'CHAR' or StageStatus _EQC 'DISP' StatusBy = RunStageWfrRec StatusDTM = RunStageWfrRec Case StageStatus _EQC 'START' InvActions = RunStageWfrRec Locate 'START' in InvActions using @VM setting vPos then StatusBy = RunStageWfrRec StatusDTM = RunStageWfrRec end End Case End Case If (StatusBy NE '') and (StatusDTM NE '') then HoverData = '' HoverData := OConv(StatusBy, '[XLATE_CONV,LSL_USERS*FIRST_LAST]') : @FM HoverData := OConv(StatusDTM, 'DT') NumLines = DCount(HoverData, @FM) ItemList = '' If HoverData NE '' then For Each Item in HoverData using @FM setting ItemCount ItemList = XPadding ; // X Position of item ItemList = (20 * (ItemCount - 1) ) ; // Y Position of item ItemList = PopupWidth - (2 * XPadding) ; // Width ItemList = PopupHeight - (2 * YPadding) ; // Height ItemList = Item ItemList = Forecolor ItemList = '' : @SVM : '' : @SVM : '700' : @SVM : '0' : @SVM : '0' ItemList = 'Left' : @SVM : 'Center' Next Item end Set_Property(PopupCtrl, 'OLE.Theme', 'Custom') Set_Property(PopupCtrl, 'OLE.Opacity', 255) Set_Property(PopupCtrl, 'OLE.Animation', 'N') Set_Property(PopupCtrl, 'OLE.Background', 'Vertical(Gradient(' : Backcolor : ', ' : Backcolor : '), Border(' : Backcolor : ' L=20))' : @FM : 'None' : @FM : 'None') Set_Property(PopupCtrl, 'OLE.ItemList', ItemList) Set_Property(PopupCtrl, 'OLE.ShowDelay', 1000) Set_Property(PopupCtrl, 'OLE.Size', 0 : @FM : 0 : @FM : PopupWidth : @FM : PopupHeight) Send_Message(PopupCtrl, 'OLE.ShowAt', PopupXPos, PopupYPos) end Set_Property('SYSTEM', 'CURSOR', 'A') return DisplayMetPopup: Set_Property('SYSTEM', 'CURSOR', 'H') BackColor = Get_Property(@Window, 'BACKCOLOR') ForeColor = Get_Property(@Window, 'FORECOLOR') CursorXPos = Field(Point, ',', 1, 1) CursorYPos = Field(Point, ',', 2, 1) FormSize = SRP_Get_Window_Rect(@Window) FormXPos = FormSize<1> FormYPos = FormSize<2> CtrlSize = Get_Property(CtrlEntID, 'SIZE') CtrlXPos = CtrlSize<1> CtrlYPos = CtrlSize<2> PopupWidth = 130 XPadding = 10 YPadding = 10 XOffset = 10 YOffset = 55 PopupXPos = FormXPos + CtrlXPos + CursorXPos + XOffset PopupYPos = FormYPos + CtrlYPos + CursorYPos + YOffset StatusBy = '' StatusDTM = '' RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) TabIndex = Get_Property(@Window:'.OLE_TAB', 'OLE.SelectedTab') Stage = Get_Property(@Window:'.OLE_TAB', 'OLE.TabCaption[':TabIndex:']') WfrIndex = Col - 3 InWfrIDs = Get_Property(@Window, '@WFRIDS') WfrID = InWfrIDs<0, WfrIndex> Convert '*' to '.' in WfrID RunStageWfrKey = RDSNo:'*':Stage:'*':WfrID RunStageWfrRec = Database_Services('ReadDataRow', 'RUN_STAGE_WFR', RunStageWfrKey) ParamValues = RunStageWfrRec OutOfSpec = RunStageWfrRec RowParamValues = ParamValues<0, Row> RowOutOfSpec = OutOfSpec<0, Row> ColorArray = '' Convert @SVM to @FM in RowParamValues HoverData = 'Index | Value' For each Value in RowParamValues setting Index HoverData := @FM:Index:' | ':Value If RowOutOfSpec<0, 0, Index> EQ True$ then ColorArray = 'Red' end else ColorArray = 'None' end Next Value NumLines = DCount(HoverData, @FM) PopupHeight = (25 * (NumLines) ) ItemList = '' If HoverData NE '' then For Each Item in HoverData using @FM setting ItemCount ItemList = XPadding ; // X Position of item ItemList = ( 25 * (ItemCount - 1) ) ; // Y Position of item ItemList = PopupWidth - (2 * XPadding) ; // Width ItemList = 25 ; // Height ItemList = Item ItemList = ColorArray ItemList = '' : @SVM : '' : @SVM : '700' : @SVM : '0' : @SVM : '0' ItemList = 'Left' : @SVM : 'Center' Next Item end Set_Property(PopupCtrl, 'OLE.Theme', 'Custom') Set_Property(PopupCtrl, 'OLE.Opacity', 255) Set_Property(PopupCtrl, 'OLE.Animation', 'N') Set_Property(PopupCtrl, 'OLE.Background', 'Vertical(Gradient(' : Backcolor : ', ' : Backcolor : '), Border(' : Backcolor : ' L=20))' : @FM : 'None' : @FM : 'None') Set_Property(PopupCtrl, 'OLE.ItemList', ItemList) Set_Property(PopupCtrl, 'OLE.ShowDelay', 1000) Set_Property(PopupCtrl, 'OLE.Size', 0 : @FM : 0 : @FM : PopupWidth : @FM : PopupHeight) Send_Message(PopupCtrl, 'OLE.ShowAt', PopupXPos, PopupYPos) Set_Property('SYSTEM', 'CURSOR', 'A') return DisplayStageDisPopup: Set_Property('SYSTEM', 'CURSOR', 'H') BackColor = Get_Property(@Window, 'BACKCOLOR') ForeColor = Get_Property(@Window, 'FORECOLOR') CursorXPos = Field(Point, ',', 1, 1) CursorYPos = Field(Point, ',', 2, 1) FormSize = SRP_Get_Window_Rect(@Window) FormXPos = FormSize<1> FormYPos = FormSize<2> CtrlSize = Get_Property(CtrlEntID, 'SIZE') CtrlXPos = CtrlSize<1> CtrlYPos = CtrlSize<2> PopupWidth = 160 PopupHeight = 60 XPadding = 10 YPadding = 10 XOffset = 10 YOffset = 55 PopupXPos = FormXPos + CtrlXPos + CursorXPos + XOffset PopupYPos = FormYPos + CtrlYPos + CursorYPos + YOffset StatusBy = '' StatusDTM = '' RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) WfrStages = ReactRunRec Locate StageID in WfrStages using @VM setting StageIndex then DisabledBy = ReactRunRec DisabledDTM = ReactRunRec If (DisabledBy NE '') and (DisabledDTM NE '') then HoverData = '' HoverData := OConv(DisabledBy, '[XLATE_CONV,LSL_USERS*FIRST_LAST]') : @FM HoverData := OConv(DisabledDTM, 'DT') NumLines = DCount(HoverData, @FM) ItemList = '' If HoverData NE '' then For Each Item in HoverData using @FM setting ItemCount ItemList = XPadding ; // X Position of item ItemList = (20 * (ItemCount - 1) ) ; // Y Position of item ItemList = PopupWidth - (2 * XPadding) ; // Width ItemList = PopupHeight - (2 * YPadding) ; // Height ItemList = Item ItemList = Forecolor ItemList = '' : @SVM : '' : @SVM : '700' : @SVM : '0' : @SVM : '0' ItemList = 'Left' : @SVM : 'Center' Next Item end Set_Property(PopupCtrl, 'OLE.Theme', 'Custom') Set_Property(PopupCtrl, 'OLE.Opacity', 255) Set_Property(PopupCtrl, 'OLE.Animation', 'N') Set_Property(PopupCtrl, 'OLE.Background', 'Vertical(Gradient(' : Backcolor : ', ' : Backcolor : '), Border(' : Backcolor : ' L=20))' : @FM : 'None' : @FM : 'None') Set_Property(PopupCtrl, 'OLE.ItemList', ItemList) Set_Property(PopupCtrl, 'OLE.ShowDelay', 1000) Set_Property(PopupCtrl, 'OLE.Size', 0 : @FM : 0 : @FM : PopupWidth : @FM : PopupHeight) Send_Message(PopupCtrl, 'OLE.ShowAt', PopupXPos, PopupYPos) end end Set_Property('SYSTEM', 'CURSOR', 'A') return VerifyRecipe: GaNRunID = Get_Property(@Window:'.CMB_GAN_RUN_ID', 'TEXT') If GaNRunID NE '' then GaNRecipe = Get_Property(@Window:'.GAN_RECIPE', 'TEXT') Convert @Lower_Case to @Upper_Case in GaNRunID SchedRecipe = Xlate('GAN_SCHEDULE', GaNRunID, 'RECIPE', 'X') If GaNRecipe NE '' then If SchedRecipe _EQC GaNRecipe then // If the recipes match, then color the recipe ID bright green, otherwise // color it bright red and block the Run Configuration "Complete" event. Set_Property(@Window:'.GAN_RECIPE', 'BACKCOLOR', BGREEN$) Set_Property(@Window, '@RECIPEMISMATCH', False$) end else Set_Property(@Window:'.GAN_RECIPE', 'BACKCOLOR', BRED$) Set_Property(@Window, '@RECIPEMISMATCH', True$) end end end return EnableRunIDComboBox: RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') EtchKey = RDSNo:'*ETCH' EtchStatus = Xlate('RUN_STAGE', EtchKey, 'STATUS', 'X') If EtchStatus _EQC 'COMP' then Set_Property(@Window:'.CMB_GAN_RUN_ID', 'ENABLED', True$) end else Set_Property(@Window:'.CMB_GAN_RUN_ID', 'ENABLED', False$) end return FillCommentsTable: RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') CassComments = Xlate('REACT_RUN', RDSNo, 'CASS_COMMENTS', 'X') Set_Property(@Window:'.EDB_CASS_COMMENTS', 'TEXT', CassComments) Set_Property(@Window, '@COMMENTS', CassComments) return EnableCloseRDSButton: RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) ScribeError = Sum(ReactRunRec) DispComp = ReactRunRec DispCtrl = @Window:'.PUB_CLOSE_RDS' If ( (DispComp NE True$) and ( Not(ScribeError) ) ) then Set_Property(DispCtrl, 'ENABLED', True$) end else Set_Property(DispCtrl, 'ENABLED', False$) end return UpdateRDSStatus: RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) DispComp = ReactRunRec If DispComp EQ True$ then Set_Property(@Window:'.LBL_RDS_STATUS', 'TEXT', 'CLOSED') Set_Property(@Window:'.LBL_RDS_STATUS', 'FORECOLOR', BRED$) end else Set_Property(@Window:'.LBL_RDS_STATUS', 'TEXT', 'OPEN') Set_Property(@Window:'.LBL_RDS_STATUS', 'FORECOLOR', BGREEN$) end return EnableLotAbortButton: RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') GrowthKey = RDSNo:'*GROWTH' GrowthStatus = Xlate('RUN_STAGE', GrowthKey, 'STATUS', 'X') // Need to check each wafer's current stage. If all wafers are at disposition, then // there is no need to enable the "Lot Abort" button. LotAbortAllowed = False$ WfrIDs = Xlate('REACT_RUN', RDSNo, 'IN_WFR_ID', 'X') For each WfrID in WfrIDs using @VM setting vPos CurrStage = Gan_Services('GetCurrStage', WfrID) If (CurrStage _NEC 'DISP') and (CurrStage _NEC 'G_PACK') and (CurrStage _NEC 'RETAIN') then LotAbortAllowed = True$ end Next WfrID If (GrowthStatus _EQC 'COMP') and (LotAbortAllowed EQ True$) then Set_Property(@Window:'.PUB_LOT_ABORT', 'ENABLED', True$) end else Set_Property(@Window:'.PUB_LOT_ABORT', 'ENABLED', False$) end return EnableImportMetDataButton: RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') UserAuthorized = Memberof(@User4, 'GAN_WIP_SUPERVISOR') RDSClosed = Xlate('REACT_RUN', RDSNo, 'DISP_COMPLETE', 'X') Enabled = ( (RDSClosed NE True$) and (UserAuthorized EQ True$) ) Set_Property(@Window:'.PUB_IMPORT_MET_DATA', 'ENABLED', Enabled) return ResetColorArrays: PSNo = Get_Property('PROD_SPEC.PROD_SPEC_ID', 'TEXT') PartNo = Get_Property(@Window, '@CURR_PART_NO') GaNParamStages = Get_Property(@Window, '@GAN_PARAM_STAGES') CellColorArray = '' For each Stage in GaNParamStages using @VM setting TabIndex GaNParamConfigKey = PSNo:'*':PartNo:'*':Stage GaNParamConfigRec = Database_Services('ReadDataRow', 'GAN_PARAM_CONFIG', GaNParamConfigKey) ParamNames = GaNParamConfigRec For each ParamName in ParamNames using @VM setting RowPos CellColorArray = 'None' CellColorArray = 'None' CellColorArray = 'None' CellColorArray = 'None' CellColorArray = 'None' Next ParamName Next Stage Set_Property(@Window, '@COLOR_ARRAY', CellColorArray) return SetupTabCtrl: RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') PSNo = Xlate('REACT_RUN', RDSNo, 'PS_NO', 'X') Set_Property(@Window, '@PS_NO', PSNo) PartNos = Xlate('PROD_SPEC', PSNo, 'PROD_VER_EPI_PART_NO', 'X') NumPartNos = DCount(PartNos, @VM) CurrPartNo = Field(PartNos, @VM, NumPartNos) Set_Property(@Window, '@CURR_PART_NO', CurrPartNo) GaNParamStages = Xlate('APP_INFO', 'GAN_PARAM_STAGES', '', 'X') TabCtrl = @Window:'.OLE_TAB' NumTabs = DCount(GaNParamStages, @VM) Set_Property(TabCtrl, "OLE.TabCount", NumTabs) Convert @VM to ',' in GaNParamStages Convert '_' to ' ' in GaNParamStages Set_Property(TabCtrl, "OLE.CaptionList", GaNParamStages) FontArray = 'Segoe UI':@SVM:9:@SVM:700 Set_Property(TabCtrl, "OLE.Font", FontArray) Set_Property(TabCtrl, "OLE.SelectFont", FontArray) // Qualify OLE events that we want to intercept Qualifier = '' Qualifier<1> = 1 Qualifier<4> = 0 ; * process synchronously Send_Message(TabCtrl, 'QUALIFY_EVENT', 'OLE.SelChanged', Qualifier) return SetupDispStageCtrl: DispStageCtrl = @Window:'.OLE_DISP_STAGE_EDT' ScribeHeaderTitles = Get_Property(@Window, '@SCRIBE_HEADER_TITLES') HeaderRowTitles = 'LSL':@VM:'Target':@VM:'USL':@VM:ScribeHeaderTitles DispStageDimArray = 12:@FM:1 Set_Property(DispStageCtrl, "OLE.Dimension", DispStageDimArray) Set_Property(DispStageCtrl, "OLE.TitleList", HeaderRowTitles) HeaderFontArray = 'Segoe UI':@SVM:8:@SVM:700 Set_Property(DispStageCtrl, "OLE.HeaderFont[All; All]", HeaderFontArray) HeaderColArray = 181:@FM:True$:@FM:False$:@FM:False$ Set_Property(DispStageCtrl, "OLE.HeaderColumn[1]", HeaderColArray) Set_Property(DispStageCtrl, "OLE.HeaderText[1; 1]", "Metrology Limits") // Disable resizing of columns as there is no need for this on this form StageColSize = Get_Property(DispStageCtrl, "OLE.DataColumn[1]") StageColSize<1> = 55 StageColSize<3> = False$ Set_Property(DispStageCtrl, "OLE.DataColumn[1-3]", StageColSize) StageColSize<1> = 96 Set_Property(DispStageCtrl, "OLE.DataColumn[4-11]", StageColSize) Set_Property(DispStageCtrl, "OLE.CellProtection[All; All]", 'Read Only') // Qualify OLE events that we want to intercept Qualifier = '' Qualifier<1> = 1 Qualifier<4> = 0 ; * process synchronously (i.e. immediately) Send_Message(DispStageCtrl, 'QUALIFY_EVENT', 'OLE.OnClick', Qualifier) Send_Message(DispStageCtrl, 'QUALIFY_EVENT', 'OLE.OnHeaderClick', Qualifier) Send_Message(DispStageCtrl, 'QUALIFY_EVENT', 'OLE.OnContextMenuClick', Qualifier) return ReadCurrParams: RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) ValidationDisFlags = ReactRunRec MetStageCtrl = @Window:'.OLE_METROLOGY_EDT' MetStageList = Get_Property(MetStageCtrl, "OLE.ColumnData[1]") Reactor = 'R':Get_Property(@Window, '@REACTOR') RunNo = Get_Property(@Window:'.CMB_GAN_RUN_ID', 'TEXT') Scribes = Get_Property(@Window, '@SCRIBES') InWfrIDs = Get_Property(@Window, '@WFRIDS') PSNo = Get_Property(@Window, '@PS_NO') If PSNo NE '' then GaNParamStages = Xlate('APP_INFO', 'GAN_PARAM_STAGES', '', 'X') GaNParamKeys = Xlate('REACT_RUN', RDSNo, 'GAN_PARAM_KEYS', 'X') ParameterList = '' ParamNameList = '' MetNameList = '' CellColorArray = '' ParamOutOfSpec = '' GaNParamKeysPrime = SRP_Array('Rotate', GaNParamKeys, @VM, '*') ConfigGaNParamStages = GaNParamKeysPrime<0, 2> Set_Property(@Window, '@GAN_PARAM_STAGES', GaNParamStages) Convert '*' to @VM in ConfigGaNParamStages For each GaNParamKey in GaNParamKeys using @VM MetType = Field(GaNParamKey, '*', 2) Locate MetType in GaNParamStages using @VM setting TabPos then StageID = MetType StageDesc = GaN_Services('GetStageDesc', MetType) ToolType = MetType GaNParamRec = Database_Services('ReadDataRow', 'GAN_PARAMS', GaNParamKey) PartNo = Field(GaNParamKey, '*', 1) ParamNames = GaNParamRec MetNames = GaNParamRec Locate StageDesc in MetStageList using @VM setting StageRowPos then Tool = Get_Property(@Window : '.OLE_METROLOGY_EDT', 'OLE.CellText[2; ':StageRowPos:']') end MetParameter = '' ParamValues = '' MetData = '' For each WfrID in InWfrIDs using @VM setting WaferIndex Convert '*' to '.' in WfrID Begin Case Case StageID EQ 'UV_PRE' // Check if UV stage exists UVStageWfrKey = RDSNo:'*UV*':WfrID If RowExists('RUN_STAGE_WFR', UVStageWfrKey) then // Display this on the UV_PRE line RunStageWfrKey = UVStageWfrKey end else RunStageWfrKey = RDSNo:'*':StageID:'*':WfrID end Case StageID EQ 'CAN_PRE' // Check if CAN stage exists CanStageWfrKey = RDSNo:'*CAN*':WfrID If RowExists('RUN_STAGE_WFR', CanStageWfrKey) then // Display this on the CAN_PRE line RunStageWfrKey = CanStageWfrKey end else RunStageWfrKey = RDSNo:'*':StageID:'*':WfrID end Case Otherwise$ RunStageWfrKey = RDSNo:'*':StageID:'*':WfrID End Case If RowExists('RUN_STAGE_WFR', RunStageWfrKey) then RunStageWfrRec = Database_Services('ReadDataRow', 'RUN_STAGE_WFR', RunStageWfrKey) TheseParamValues = RunStageWfrRec TheseOutOfSpecValues = RunStageWfrRec If Index(TheseParamValues, @SVM, 1) GT 0 then For each FlagSet in TheseOutOfSpecValues using @VM setting ParamIndex ValueSet = TheseParamValues<0, ParamIndex> NumVals = DCount(ValueSet, @SVM) If NumVals GT 1 then ParamValues = 'Multi' OutOfSpec = ( Sum(TheseOutOfSpecValues<1, ParamIndex>) > 0 ) end else ParamValues = ValueSet OutOfSpec = TheseOutOfSpecValues<1, ParamIndex> end ParamOutOfSpec = OutOfSpec Next FlagSet end else ParamValues = TheseParamValues ParamOutOfSpec = TheseOutOfSpecValues end end else ParamValues = '' ParamOutOfSpec = '' end Next WfrID ParamValues = SRP_Array('Rotate', ParamValues, @FM, @VM) ParamOutOfSpec = SRP_Array('Rotate', ParamOutOfSpec, @FM, @VM) Convert @VM to @SVM in ParamValues Convert @VM to @SVM in ParamOutOfSpec Convert @FM to @VM in ParamOutOfSpec ParamOutOfSpec = SRP_Array('Rotate', ParamOutOfSpec, @VM, @SVM) For each WfrID in InWfrIDs using @VM setting WaferIndex ValidDisabled = ValidationDisFlags<0, WaferIndex> WfrParamOutOfSpec = ParamOutOfSpec<0, WaferIndex> If ValidDisabled EQ True$ then Swap '-1' with 'SlateBlue L=75' in WfrParamOutOfSpec Swap 1 with 'SlateBlue L=75' in WfrParamOutOfSpec end else Swap '-1' with 'Yellow' in WfrParamOutOfSpec end ParamOutOfSpec<0, WaferIndex> = WfrParamOutOfSpec Next WfrID ParamOutOfSpec = SRP_Array('Rotate', ParamOutOfSpec, @VM, @SVM) Swap 1 with 'Red' in ParamOutOfSpec Swap 0 with 'None' in ParamOutOfSpec CellColorArray = ParamOutOfSpec For each ParamName in ParamNames using @VM setting RowPos MetName = MetNames<0, RowPos> MetNameList = ParamName ParamNameList = MetName ParameterList = GaNParamRec ParameterList = GaNParamRec ParameterList = GaNParamRec If ParamValues NE '' then ParameterList = ParamValues Next ParamName end Next GaNParamKey Set_Property(@Window, '@NAME_LIST', ParamNameList) Set_Property(@Window, '@VALUE_LIST', ParameterList) Set_Property(@Window, '@ORIG_VALUE_LIST', ParameterList) Set_Property(@Window, '@ORIG_MET_LIST', MetNameList) Set_Property(@Window, '@COLOR_ARRAY', CellColorArray) end return FillDispStageCtrl: DispStageCtrl = @Window:'.OLE_DISP_STAGE_EDT' TabCtrl = @Window:'.OLE_TAB' TabIndex = Get_Property(TabCtrl, 'OLE.SelectedTab') HeaderTitles = Get_Property(@Window, '@NAME_LIST') ParameterList = Get_Property(@Window, '@VALUE_LIST') NumCols = 11 NumRows = DCount(ParameterList, @VM) DispStageDimArray = NumCols:@FM:NumRows Set_Property(DispStageCtrl, "OLE.Dimension", DispStageDimArray) Convert @VM to @FM in ParameterList Convert @SVM to @VM in ParameterList Set_Property(@Window:'.OLE_DISP_STAGE_EDT', 'OLE.LIST', ParameterList) Convert @VM to @FM in HeaderTitles Convert @SVM to @VM in HeaderTitles For each HeaderTitle in HeaderTitles using @FM setting RowIndex Set_Property(DispStageCtrl, "OLE.HeaderText[1; ":RowIndex + 1:"]", HeaderTitle) Next HeaderTitle Set_Property(DispStageCtrl, "OLE.HeaderAlignment[1; 2-":NumRows + 1:"]", 'C':@FM:'L':@FM:'L') Set_Property(DispStageCtrl, "OLE.CellAlignment[All; All]", 'C':@FM:'R':@FM:'L') Set_Property(DispStageCtrl, "OLE.HeaderAlignment[All; 1]", 'C':@FM:'C':@FM:'L') // Color headers Set_Property(DispStageCtrl, "OLE.HeaderColors[All; 1]", @FM:"{200, 200, 200}") // Color limit columns Set_Property(DispStageCtrl, "OLE.CellColors[1-3; All]", @FM:"{240, 240, 240}") // Bold limit text BoldFontArray = 'Segoe UI':@SVM:8:@SVM:700 Set_Property(DispStageCtrl, "OLE.CellFont[1-3; All]", BoldFontArray) GoSub ColorCells return ColorCells: TabIndex = Get_Property(@Window:'.OLE_TAB', 'OLE.SelectedTab') CellColorArray = Get_Property(@Window, '@COLOR_ARRAY') DispStageCtrl = @Window:'.OLE_DISP_STAGE_EDT' DimArray = Get_Property(DispStageCtrl, "OLE.Dimension") NumCols = DimArray<1> NumRows = DimArray<2> For Row = 1 to NumRows For Col = 1 to NumCols CellColor = CellColorArray<0, Row, Col> If CellColor EQ '' then CellColor = 'None' Set_Property(DispStageCtrl, 'OLE.CellColors[':Col+3:';':Row:']', @FM:CellColor) Next Col Next Row return ColorTabs: TabCtrl = @Window:'.OLE_TAB' RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) GaNParamStages = Get_Property(@Window, '@GAN_PARAM_STAGES') CellColorArray = Get_Property(@Window, '@COLOR_ARRAY') WfrStages = ReactRunRec For each Stage in GaNParamStages using @VM setting TabIndex ThisCellColorArray = CellColorArray GoSub ColorTab Next Stage return EnableTabs: SelTabIndex = Get_Property(@Window:".OLE_TAB", "OLE.SelectedTab") GaNParamStages = Get_Property(@Window, '@GAN_PARAM_STAGES') NameArray = Get_Property(@Window, '@NAME_LIST') For each Stage in GaNParamStages using @VM setting TabIndex ThisNameArray = NameArray GoSub EnableTab Next Stage SelTabVisible = Get_Property(@Window:'.OLE_TAB', 'OLE.TabVisible[':SelTabIndex:']') If SelTabVisible EQ False$ then For TabIndex = 1 to 12 TabVisible = Get_Property(@Window:'.OLE_TAB', 'OLE.TabVisible[':TabIndex:']') Until TabVisible EQ True$ Next TabIndex If TabVisible EQ True$ then Set_Property(@Window:".OLE_TAB", "OLE.SelectedTab", TabIndex) end return EnableTab: If ThisNameArray EQ '' then Set_Property(@Window:'.OLE_TAB', 'OLE.TabVisible[':TabIndex:']', False$) end else Set_Property(@Window:'.OLE_TAB', 'OLE.TabVisible[':TabIndex:']', True$) end return ColorTab: GaNMetStages = Database_Services('ReadDataRow', 'APP_INFO', 'GAN_MET_STAGES') Locate Stage in GaNMetStages using @FM setting sPos then PostSplit = (sPos GT 6) end else PostSplit = False$ end WfrChar = (Sum(ReactRunRec) GT 0) NumRows = DCount(ThisCellColorArray, @VM) NumCols = DCount(ThisCellColorArray, @SVM) MetFailed = False$ MetMissing = False$ ValidDisabled = False$ For Row = 1 to NumRows For Col = 1 to NumCols CellColor = ThisCellColorArray<0, Row, Col> If CellColor EQ 'Red' then MetFailed = True$ end If CellColor EQ 'Yellow' then MetMissing = True$ end If CellColor EQ 'SlateBlue L=75' then ValidDisabled = True$ end Until MetFailed EQ True$ Next Col Until MetFailed EQ True$ Next Row Begin Case Case MetFailed EQ True$ Colors = "" Colors<1, 2> = "Vertical(Gradient(Red L=80, Red L=90), Border(Red))" Colors<2, 2> = "Vertical(Gradient(Red L=90, Red L=95), Border(Red))" Colors<3, 2> = "Vertical(Gradient(Red L=85, Red L=95), Border(Red))" Colors<4, 1> = "Gray" Colors<4, 2> = "Vertical(Gradient(Gray L=80, Gray L=90), Border(Gray))" Colors<5> = "Vertical(Gradient(Red L=95, Red L=80), Border(Red))" Set_Property(TabCtrl, "OLE.TabColors[":TabIndex:"]", Colors) Case MetMissing EQ True$ Colors = "" Colors<1, 2> = "Vertical(Gradient(Yellow L=80, Yellow L=90), Border(Yellow))" Colors<2, 2> = "Vertical(Gradient(Yellow L=90, Yellow L=95), Border(Yellow))" Colors<3, 2> = "Vertical(Gradient(Yellow L=85, Yellow L=95), Border(Yellow))" Colors<4, 1> = "Gray" Colors<4, 2> = "Vertical(Gradient(Gray L=80, Gray L=90), Border(Gray))" Colors<5> = "Vertical(Gradient(Yellow L=95, Yellow L=80), Border(Yellow))" Set_Property(TabCtrl, "OLE.TabColors[":TabIndex:"]", Colors) Case ValidDisabled EQ True$ Colors = "" Colors<1, 2> = "Vertical(Gradient(Blue L=80, Blue L=90), Border(Blue))" Colors<2, 2> = "Vertical(Gradient(Blue L=90, Blue L=95), Border(Blue))" Colors<3, 2> = "Vertical(Gradient(Blue L=85, Blue L=95), Border(Blue))" Colors<4, 1> = "Gray" Colors<4, 2> = "Vertical(Gradient(Gray L=80, Gray L=90), Border(Gray))" Colors<5> = "Vertical(Gradient(Blue L=95, Blue L=80), Border(Blue))" Set_Property(TabCtrl, "OLE.TabColors[":TabIndex:"]", Colors) Case ( ( (PostSplit EQ True$) and (WfrChar EQ False$) ) or (NumRows EQ 0) ) Null Case Otherwise$ Colors = "" Colors<1, 2> = "Vertical(Gradient(Green L=80, Green L=90), Border(Green))" Colors<2, 2> = "Vertical(Gradient(Green L=90, Green L=95), Border(Green))" Colors<3, 2> = "Vertical(Gradient(Green L=85, Green L=95), Border(Green))" Colors<4, 1> = "Gray" Colors<4, 2> = "Vertical(Gradient(Gray L=80, Gray L=90), Border(Gray))" Colors<5> = "Vertical(Gradient(Green L=95, Green L=80), Border(Green))" Set_Property(TabCtrl, "OLE.TabColors[":TabIndex:"]", Colors) End Case return SetupDispEDT: DispCtrl = @Window:'.OLE_DISP_EDT' // Disable resizing of the header row and header column // Resize header column to fit contents HeaderRowArray = Get_Property(DispCtrl, "OLE.HeaderRow[1]") HeaderColArray = Get_Property(DispCtrl, "OLE.HeaderColumn[1]") HeaderRowArray<3> = False$ HeaderColArray<1> = 80 HeaderColArray<3> = False$ Set_Property(DispCtrl, "OLE.HeaderColumn[1]", HeaderColArray) Set_Property(DispCtrl, "OLE.HeaderRow[1]", HeaderRowArray) // Disable resizing of columns as there is no need for this on this form StageColSize = Get_Property(DispCtrl, "OLE.DataColumn[1]") StageColSize<3> = False$ Set_Property(DispCtrl, "OLE.DataColumn[All]", StageColSize) WfrColSize = Get_Property(DispCtrl, "OLE.DataColumn[1]") // Set column widths WfrColSize<1> = 30 Set_Property(DispCtrl, "OLE.DataColumn[":COL$DISP_SLOT:"]", WfrColSize) WfrColSize<1> = 79 Set_Property(DispCtrl, "OLE.DataColumn[":COL$DISP_WFR_ID:"-":COL$DISP_SCRIBE:"]", WfrColSize) WfrColSize<1> = 50 Set_Property(DispCtrl, "OLE.DataColumn[":COL$DISP_GRADE:"]", WfrColSize) WfrColSize<1> = 244 Set_Property(DispCtrl, "OLE.DataColumn[":COL$DISP_REASON:"]", WfrColSize) WfrColSize<1> = 69 Set_Property(DispCtrl, "OLE.DataColumn[":COL$DISP_RDS_NCR:"-":COL$DISP_WMO_NCR:"]", WfrColSize) WfrColSize<1> = 81 Set_Property(DispCtrl, "OLE.DataColumn[":COL$DISP_SHIP_ID:"]", WfrColSize) WfrColSize<1> = 70 Set_Property(DispCtrl, "OLE.DataColumn[":COL$DISP_RETAIN_BOX:"-":COL$DISP_RETAIN_SLOT:"]", WfrColSize) WfrColSize<4> = True$ ; // Set this column autosize property to true Set_Property(DispCtrl, "OLE.DataColumn[":COL$DISP_ROOT_CAUSE:"]", WfrColSize) // Disable resizing of rows as there is no need for this on this form RowSizeProps = Get_Property(DispCtrl, "OLE.DataRow[1]") RowSizeProps<3> = False$ Set_Property(DispCtrl, "OLE.DataRow[All]", RowSizeProps) // Disable scrollbars Set_Property(DispCtrl, "OLE.ScrollBarsVisible", 'N':@FM:'N') // Color headers Set_Property(DispCtrl, "OLE.HeaderColors[All; 1]", @FM:"{200, 200, 200}") // Set edit mode of cells if and when we enable them EditArray = 'E' EditArray<2> = 'O' Set_Property(DispCtrl, "OLE.CellEditMode[All; All]", EditArray) // Disable editing of all cells Set_Property(DispCtrl, "OLE.CellProtection[All; All]", 'Full') // Do not allow scrolling past the bottom right cell. // This prevents scrolling when tabbing out of the bottom right cell. Set_Property(DispCtrl, "OLE.FreezePos", COL$DISP_RETAIN_SLOT:@FM:8) return Abort: Utility('DESTROY', @Window) return VerifyScribes: RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT') If RDSNo NE '' then DispCtrl = @Window:'.OLE_DISP_EDT' ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) InWfrIDs = ReactRunRec ScribeErrors = ReactRunRec DispReadyFlags = ReactRunRec NumWfrs = DCount(InWfrIDs, @VM) For WfrIndex = 1 to NumWfrs WfrKey = InWfrIDs<0, WfrIndex> ScribeError = ScribeErrors<0, WfrIndex> DispReady = DispReadyFlags<0, WfrIndex> Grade = Xlate('WO_WFR', WfrKey, 'GRADE', 'X') Begin Case Case ScribeError EQ True$ ColorArray = 'None':@FM:ORANGE$ Case Grade _EQC 'Scrap' ColorArray = 'None':@FM:RED$ Case DispReady EQ True$ // Color scribe cell green to indicate that the wafer is ready to be placed in an outbound cassette. // Color scribe cell within disposition edit table green ColorArray = 'None':@FM:BGREEN$ Case Otherwise$ ColorArray = 'None':@FM:'None' End Case Set_Property(DispCtrl, 'OLE.CellColors[':COL$DISP_SCRIBE:';':WfrIndex:']', ColorArray) Next WfrIndex end return